diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..3d280eed2c --- /dev/null +++ b/.clang-format @@ -0,0 +1,24 @@ +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignTrailingComments: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: WithoutElse +BasedOnStyle: Microsoft +BreakBeforeBraces: Allman +ColumnLimit: 130 +Cpp11BracedListStyle: true +FixNamespaceComments: true +IncludeBlocks: Regroup +IndentPPDirectives: BeforeHash +IndentWidth: 4 +Language: Cpp +NamespaceIndentation: All +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesInParentheses: false +Standard: Cpp11 +UseTab: Never \ No newline at end of file diff --git a/source/main/Application.cpp b/source/main/Application.cpp index 2cf4cdd9fe..24db3aa5dc 100644 --- a/source/main/Application.cpp +++ b/source/main/Application.cpp @@ -17,21 +17,19 @@ along with Rigs of Rods. If not, see . */ - /// @file Application.cpp /// @author Petr Ohlidal /// @date 05/2014 - #include "Application.h" #include "CacheSystem.h" #include "ContentManager.h" #include "GUIManager.h" #include "InputEngine.h" +#include "MumbleIntegration.h" #include "OgreSubsystem.h" #include "OverlayWrapper.h" -#include "MumbleIntegration.h" /* -------------------- Research of debug options (only_a_ptr, 06/2017) ---------------------- @@ -40,452 +38,490 @@ ["Debug Truck Mass"] | GVar: diag_truck_mass --- extra logging on runtime - mass recalculation. ["Debug Collisions"] | GVar: diag_collisions --- visual debug of static map collisions. Only effective on map load. ["EnvMapDebug"] | GVar: diag_envmap --- effective on terrain load (envmap init). -["VideoCameraDebug"] | GVar: diag_videocameras--- creates debug mesh showing videocamera direction. Effective on vehicle spawn. +["VideoCameraDebug"] | GVar: diag_videocameras--- creates debug mesh showing videocamera direction. Effective on vehicle +spawn. -["Enable Ingame Console"] | + --- Equivalent to "\log" console command, echoes all RoR.log output to console. Reported to cause massive slowdown on startup. +["Enable Ingame Console"] | + --- Equivalent to "\log" console command, echoes all RoR.log output to +console. Reported to cause massive slowdown on startup. ["Beam Break Debug"] | + --- Use before spawn, lasts entire vehicle lifetime. ["Beam Deform Debug"] | + --- Use before spawn, lasts entire vehicle lifetime. ["Trigger Debug"] | + --- Use before spawn, lasts entire vehicle lifetime. ["Advanced Logging"] | ~ no gvar ~ --- DEAD, used in removed 'ScopeLog' feature of old spawner. -["DebugBeams"] --- Pre configured debug overlay mode --- DEAD since debug overlay has been remade with different modes +["DebugBeams"] --- Pre configured debug overlay mode --- DEAD since debug overlay has been +remade with different modes */ -namespace RoR { -namespace App { - -// ================================================================================ -// Global variables -// ================================================================================ - - -// Object instances -static OgreSubsystem* g_ogre_subsystem; -static ContentManager g_content_manager; -static OverlayWrapper* g_overlay_wrapper; -static GUIManager* g_gui_manager; -static Console* g_console; -static InputEngine* g_input_engine; -static CacheSystem* g_cache_system; -static MainMenu* g_main_menu; -static SimController* g_sim_controller; -static MumbleIntegration* g_mumble; -static TerrainManager* g_sim_terrain; - -// App - GVarEnum_AP app_state ("app_state", nullptr, AppState::BOOTSTRAP, AppState::MAIN_MENU); - GVarStr_A<50> app_language ("app_language", "Language", "en"); - GVarStr_A<50> app_country ("app_country", "Country", "us"); - GVarPod_A app_skip_main_menu ("app_skip_main_menu", "SkipMainMenu", false); - GVarPod_APS app_async_physics ("app_async_physics", "AsyncPhysics", true, - true, true); - GVarPod_APS app_num_workers ("app_num_workers", "NumWorkerThreads", 0, - 0, 0); - GVarStr_AP<50> app_screenshot_format ("app_screenshot_format", "Screenshot Format", "png", "png"); - GVarStr_A<100> app_rendersys_override ("app_rendersys_override", "Render system", ""); - GVarStr_A<300> app_extra_mod_path ("app_extra_mod_path", "Extra mod path", ""); - GVarPod_A app_force_cache_purge ("app_force_cache_purge", nullptr, false); - GVarPod_A app_force_cache_udpate ("app_force_cache_udpate", nullptr, false); - GVarPod_A app_disable_online_api ("app_disable_online_api", "Disable Online API", false); - - -// Simulation - GVarEnum_AP sim_state ("sim_state", nullptr, SimState::OFF, SimState::OFF); - GVarStr_AP<200> sim_terrain_name ("sim_terrain_name", nullptr, "", ""); - GVarStr_AP<300> sim_terrain_gui_name ("sim_terrain_gui_name", nullptr, "", ""); - GVarStr_A<100> sim_savegame ("sim_savegame", nullptr, ""); - GVarPod_A sim_load_savegame ("sim_load_savegame", nullptr, false); - GVarPod_A sim_spawn_running ("sim_spawn_running", "Engines spawn running", true); - GVarPod_A sim_replay_enabled ("sim_replay_enabled", "Replay mode", false); - GVarPod_A sim_replay_length ("sim_replay_length", "Replay length", 200); - GVarPod_A sim_replay_stepping ("sim_replay_stepping", "Replay Steps per second", 1000); - GVarPod_A sim_realistic_commands ("sim_realistic_commands", "Realistic forward commands",false); - GVarPod_A sim_races_enabled ("sim_races_enabled", "Races", true); - GVarPod_A sim_no_collisions ("sim_no_collisions", "DisableCollisions", false); - GVarPod_A sim_no_self_collisions ("sim_no_self_collisions", "DisableSelfCollisions", false); - GVarEnum_AP sim_gearbox_mode ("sim_gearbox_mode", "GearboxMode", SimGearboxMode::AUTO, SimGearboxMode::AUTO); - -// Multiplayer - GVarEnum_AP mp_state ("mp_state", nullptr, MpState::DISABLED, MpState::DISABLED); - GVarPod_APS mp_join_on_startup ("mp_join_on_startup", "Auto connect", false, false, false); - GVarPod_A mp_chat_auto_hide ("mp_chat_auto_hide", "Auto hide chat", true); - GVarPod_A mp_hide_net_labels ("mp_hide_net_labels", "Hide net labels", false); - GVarPod_A mp_hide_own_net_label ("mp_hide_own_net_label", "Hide own net label", true); - GVarPod_A mp_pseudo_collisions ("mp_pseudo_collisions", "Multiplayer collisions", false); - GVarStr_AP<200> mp_server_host ("mp_server_host", "Server name", "", ""); - GVarPod_A mp_server_port ("mp_server_port", "Server port", 0); - GVarStr_APS<100> mp_server_password ("mp_server_password", "Server password", "", "", ""); - GVarStr_AP<100> mp_player_name ("mp_player_name", "Nickname", "Player", "Player"); - GVarStr_AP<100> mp_player_token ("mp_player_token", "User Token", "", ""); - GVarStr_A<100> mp_api_url ("mp_api_url", "Online API URL", "http://api.rigsofrods.org"); - -// Diagnostic - GVarPod_A diag_auto_spawner_report("diag_auto_spawner_report","AutoActorSpawnerReport", false); - GVarPod_A diag_camera ("diag_camera", "Camera Debug", false); - GVarPod_A diag_trace_globals ("diag_trace_globals", nullptr, false); // Don't init to 'true', logger is not ready at startup - GVarPod_A diag_rig_log_node_import("diag_rig_log_node_import","RigImporter_Debug_TraverseAndLogAllNodes", false); - GVarPod_A diag_rig_log_node_stats ("diag_rig_log_node_stats", "RigImporter_PrintNodeStatsToLog", false); - GVarPod_A diag_rig_log_messages ("diag_rig_log_messages", "RigImporter_PrintMessagesToLog", false); - GVarPod_A diag_collisions ("diag_collisions", "Debug Collisions", false); - GVarPod_A diag_truck_mass ("diag_truck_mass", "Debug Truck Mass", false); - GVarPod_A diag_envmap ("diag_envmap", "EnvMapDebug", false); - GVarPod_A diag_videocameras ("diag_videocameras", "VideoCameraDebug", false); - GVarStr_APS<100> diag_preset_terrain ("diag_preset_terrain", "Preselected Terrain", "", "", ""); - GVarStr_A<100> diag_preset_spawn_pos ("diag_spawn_position", nullptr, ""); - GVarStr_A<100> diag_preset_spawn_rot ("diag_spawn_rotation", nullptr, ""); - GVarStr_APS<100> diag_preset_vehicle ("diag_preset_vehicle", "Preselected Truck", "", "", ""); - GVarStr_A<100> diag_preset_veh_config ("diag_preset_veh_config", "Preselected TruckConfig", ""); - GVarPod_APS diag_preset_veh_enter ("diag_preset_veh_enter", "Enter Preselected Truck", false, false, false); - GVarPod_A diag_log_console_echo ("diag_log_console_echo", "Enable Ingame Console", false); - GVarPod_A diag_log_beam_break ("diag_log_beam_break", "Beam Break Debug", false); - GVarPod_A diag_log_beam_deform ("diag_log_beam_deform", "Beam Deform Debug", false); - GVarPod_A diag_log_beam_trigger ("diag_log_beam_trigger", "Trigger Debug", false); - GVarPod_A diag_simple_materials ("diag_simple_materials", "SimpleMaterials", false); - GVarPod_A diag_warning_texture ("diag_warning_texture", "Warning texture", false); - GVarPod_A diag_hide_broken_beams ("diag_hide_broken_beams", "Hide broken beams", false); - GVarPod_A diag_hide_beam_stress ("diag_hide_beam_stress", "Hide beam stress", true); - GVarPod_A diag_hide_wheel_info ("diag_hide_wheel_info", "Hide wheel info", true); - GVarPod_A diag_hide_wheels ("diag_hide_wheels", "Hide wheels", false); - GVarPod_A diag_hide_nodes ("diag_hide_nodes", "Hide nodes", false); - GVarPod_A diag_physics_dt ("diag_physics_dt", "PhysicsTimeStep", 0.0005f); - -// System (all paths are without ending slash!) - GVarStr_A<300> sys_process_dir ("sys_process_dir", nullptr, ""); - GVarStr_A<300> sys_user_dir ("sys_user_dir", nullptr, ""); - GVarStr_A<300> sys_config_dir ("sys_config_dir", "Config Root", ""); - GVarStr_A<300> sys_cache_dir ("sys_cache_dir", "Cache Path", ""); - GVarStr_A<300> sys_logs_dir ("sys_logs_dir", "Log Path", ""); - GVarStr_A<300> sys_resources_dir ("sys_resources_dir", "Resources Path", ""); - GVarStr_A<300> sys_profiler_dir ("sys_profiler_dir", "Profiler output dir", ""); - GVarStr_A<300> sys_savegames_dir ("sys_savegames_dir", nullptr, ""); - GVarStr_A<300> sys_screenshot_dir ("sys_screenshot_dir", nullptr, ""); - -// Input - Output - GVarPod_A io_analog_smoothing ("io_analog_smoothing", "Analog Input Smoothing", 1.f); - GVarPod_A io_analog_sensitivity ("io_analog_sensitivity", "Analog Input Sensitivity", 1.f); - GVarPod_A io_ffb_enabled ("io_ffb_enabled", "Force Feedback", false); - GVarPod_A io_ffb_camera_gain ("io_ffb_camera_gain", "Force Feedback Camera", 0.f); - GVarPod_A io_ffb_center_gain ("io_ffb_center_gain", "Force Feedback Centering", 0.f); - GVarPod_A io_ffb_master_gain ("io_ffb_master_gain", "Force Feedback Gain", 0.f); - GVarPod_A io_ffb_stress_gain ("io_ffb_stress_gain", "Force Feedback Stress", 0.f); - GVarEnum_AP io_input_grab_mode ("io_input_grab_mode", "Input Grab", IoInputGrabMode::ALL, IoInputGrabMode::ALL); - GVarPod_A io_arcade_controls ("io_arcade_controls", "ArcadeControls", false); - GVarPod_A io_outgauge_mode ("io_outgauge_mode", "OutGauge Mode", 0); // 0 = disabled, 1 = enabled - GVarStr_A<50> io_outgauge_ip ("io_outgauge_ip", "OutGauge IP", "192.168.1.100"); - GVarPod_A io_outgauge_port ("io_outgauge_port", "OutGauge Port", 1337); - GVarPod_A io_outgauge_delay ("io_outgauge_delay", "OutGauge Delay", 10.f); - GVarPod_A io_outgauge_id ("io_outgauge_id", "OutGauge ID", 0); - GVarPod_A io_discord_rpc ("io_discord_rpc", "Discord Rich Presence", true); - -// Audio - GVarPod_A audio_master_volume ("audio_master_volume", "Sound Volume", 1); - GVarPod_A audio_enable_creak ("audio_enable_creak", "Creak Sound", false); - GVarStr_AP<100> audio_device_name ("audio_device_name", "AudioDevice", "", ""); - GVarPod_A audio_menu_music ("audio_menu_music", "MainMenuMusic", false); - -// Graphics - GVarEnum_AP gfx_flares_mode ("gfx_flares_mode", "Lights", GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS, GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS); - GVarEnum_AP gfx_shadow_type ("gfx_shadow_type", "Shadow technique", GfxShadowType::PSSM, GfxShadowType::PSSM); - GVarEnum_AP gfx_extcam_mode ("gfx_extcam_mode", "External Camera Mode", GfxExtCamMode::PITCHING, GfxExtCamMode::PITCHING); - GVarEnum_AP gfx_sky_mode ("gfx_sky_mode", "Sky effects", GfxSkyMode::CAELUM, GfxSkyMode::CAELUM); - GVarEnum_AP gfx_texture_filter ("gfx_texture_filter", "Texture Filtering", GfxTexFilter::ANISOTROPIC, GfxTexFilter::ANISOTROPIC); - GVarEnum_AP gfx_vegetation_mode ("gfx_vegetation_mode", "Vegetation", GfxVegetation::FULL, GfxVegetation::FULL); - GVarEnum_AP gfx_water_mode ("gfx_water_mode", "Water effects", GfxWaterMode::FULL_FAST, GfxWaterMode::FULL_FAST); - GVarPod_A gfx_anisotropy ("gfx_anisotropy", "Anisotropy", 4); - GVarPod_A gfx_water_waves ("gfx_water_waves", "Waves", false); - GVarPod_A gfx_particles_mode ("gfx_particles_mode", "Particles", 0); - GVarPod_A gfx_enable_videocams ("gfx_enable_videocams", "gfx_enable_videocams", false); - GVarPod_A gfx_window_videocams ("gfx_window_videocams", "UseVideocameraWindows", false); - GVarPod_APS gfx_surveymap_icons ("gfx_surveymap_icons", "Overview map icons", true, true, true); - GVarPod_A gfx_declutter_map ("gfx_declutter_map", "Declutter overview map", true); - GVarPod_A gfx_envmap_enabled ("gfx_envmap_enabled", "Reflections", true); - GVarPod_A gfx_envmap_rate ("gfx_envmap_rate", "ReflectionUpdateRate", 1); - GVarPod_A gfx_shadow_quality ("gfx_shadow_quality", "Shadows Quality", 2); - GVarPod_A gfx_skidmarks_mode ("gfx_skidmarks_mode", "Skidmarks", 0); - GVarPod_A gfx_sight_range ("gfx_sight_range", "SightRange", 5000); // Previously either 2000 or 4500 (inconsistent) - GVarPod_A gfx_camera_height ("gfx_camera_height", "Static camera height", 5); - GVarPod_APS gfx_fov_external ("gfx_fov_external", "FOV External", 60, 60, 60); - GVarPod_APS gfx_fov_internal ("gfx_fov_internal", "FOV Internal", 75, 75, 75); - GVarPod_A gfx_static_cam_fov_exp ("gfx_static_cam_fov_exp", nullptr, 1.f); - GVarPod_A gfx_fixed_cam_tracking ("gfx_fixed_cam_tracking", nullptr, false); - GVarPod_A gfx_fps_limit ("gfx_fps_limit", "FPS-Limiter", 0); // 0 = unlimited - GVarPod_A gfx_speedo_digital ("gfx_speedo_digital", "DigitalSpeedo", true); - GVarPod_A gfx_speedo_imperial ("gfx_speedo_imperial", "gfx_speedo_imperial", false); - GVarPod_A gfx_flexbody_lods ("gfx_flexbody_lods", "Flexbody_EnableLODs", false); - GVarPod_A gfx_flexbody_cache ("gfx_flexbody_cache", "Flexbody_UseCache", false); - GVarPod_A gfx_reduce_shadows ("gfx_reduce_shadows", "Shadow optimizations", true); - GVarPod_A gfx_enable_rtshaders ("gfx_enable_rtshaders", "Use RTShader System", false); - -// Instance management -void SetMainMenu (MainMenu* obj) { g_main_menu = obj; } -void SetSimController (SimController* obj) { g_sim_controller = obj;} -void SetSimTerrain (TerrainManager* obj) { g_sim_terrain = obj;} -void SetCacheSystem (CacheSystem* obj) { g_cache_system = obj; } - -// Instance access -OgreSubsystem* GetOgreSubsystem () { return g_ogre_subsystem; }; -ContentManager* GetContentManager () { return &g_content_manager;} -OverlayWrapper* GetOverlayWrapper () { return g_overlay_wrapper;} -GUIManager* GetGuiManager () { return g_gui_manager;} -Console* GetConsole () { return g_gui_manager->GetConsole();} -InputEngine* GetInputEngine () { return g_input_engine;} -CacheSystem* GetCacheSystem () { return g_cache_system;} -MainMenu* GetMainMenu () { return g_main_menu;} -SimController* GetSimController () { return g_sim_controller; } -MumbleIntegration* GetMumble () { return g_mumble; } -TerrainManager* GetSimTerrain () { return g_sim_terrain; } - -void StartOgreSubsystem() +namespace RoR { - g_ogre_subsystem = new OgreSubsystem(); - if (g_ogre_subsystem == nullptr) + namespace App { - throw std::runtime_error("[RoR] Failed to create OgreSubsystem"); - } - if (! g_ogre_subsystem->StartOgre("", "")) - { - throw std::runtime_error("[RoR] Failed to start up OGRE 3D engine"); - } -} + // ================================================================================ + // Global variables + // ================================================================================ + + // Object instances + static OgreSubsystem * g_ogre_subsystem; + static ContentManager g_content_manager; + static OverlayWrapper * g_overlay_wrapper; + static GUIManager * g_gui_manager; + static Console * g_console; + static InputEngine * g_input_engine; + static CacheSystem * g_cache_system; + static MainMenu * g_main_menu; + static SimController * g_sim_controller; + static MumbleIntegration *g_mumble; + static TerrainManager * g_sim_terrain; + + // App + GVarEnum_AP app_state("app_state", nullptr, AppState::BOOTSTRAP, AppState::MAIN_MENU); + GVarStr_A<50> app_language("app_language", "Language", "en"); + GVarStr_A<50> app_country("app_country", "Country", "us"); + GVarPod_A app_skip_main_menu("app_skip_main_menu", "SkipMainMenu", false); + GVarPod_APS app_async_physics("app_async_physics", "AsyncPhysics", true, true, true); + GVarPod_APS app_num_workers("app_num_workers", "NumWorkerThreads", 0, 0, 0); + GVarStr_AP<50> app_screenshot_format("app_screenshot_format", "Screenshot Format", "png", "png"); + GVarStr_A<100> app_rendersys_override("app_rendersys_override", "Render system", ""); + GVarStr_A<300> app_extra_mod_path("app_extra_mod_path", "Extra mod path", ""); + GVarPod_A app_force_cache_purge("app_force_cache_purge", nullptr, false); + GVarPod_A app_force_cache_udpate("app_force_cache_udpate", nullptr, false); + GVarPod_A app_disable_online_api("app_disable_online_api", "Disable Online API", false); + + // Simulation + GVarEnum_AP sim_state("sim_state", nullptr, SimState::OFF, SimState::OFF); + GVarStr_AP<200> sim_terrain_name("sim_terrain_name", nullptr, "", ""); + GVarStr_AP<300> sim_terrain_gui_name("sim_terrain_gui_name", nullptr, "", ""); + GVarStr_A<100> sim_savegame("sim_savegame", nullptr, ""); + GVarPod_A sim_load_savegame("sim_load_savegame", nullptr, false); + GVarPod_A sim_spawn_running("sim_spawn_running", "Engines spawn running", true); + GVarPod_A sim_replay_enabled("sim_replay_enabled", "Replay mode", false); + GVarPod_A sim_replay_length("sim_replay_length", "Replay length", 200); + GVarPod_A sim_replay_stepping("sim_replay_stepping", "Replay Steps per second", 1000); + GVarPod_A sim_realistic_commands("sim_realistic_commands", "Realistic forward commands", false); + GVarPod_A sim_races_enabled("sim_races_enabled", "Races", true); + GVarPod_A sim_no_collisions("sim_no_collisions", "DisableCollisions", false); + GVarPod_A sim_no_self_collisions("sim_no_self_collisions", "DisableSelfCollisions", false); + GVarEnum_AP sim_gearbox_mode("sim_gearbox_mode", "GearboxMode", SimGearboxMode::AUTO, + SimGearboxMode::AUTO); + + // Multiplayer + GVarEnum_AP mp_state("mp_state", nullptr, MpState::DISABLED, MpState::DISABLED); + GVarPod_APS mp_join_on_startup("mp_join_on_startup", "Auto connect", false, false, false); + GVarPod_A mp_chat_auto_hide("mp_chat_auto_hide", "Auto hide chat", true); + GVarPod_A mp_hide_net_labels("mp_hide_net_labels", "Hide net labels", false); + GVarPod_A mp_hide_own_net_label("mp_hide_own_net_label", "Hide own net label", true); + GVarPod_A mp_pseudo_collisions("mp_pseudo_collisions", "Multiplayer collisions", false); + GVarStr_AP<200> mp_server_host("mp_server_host", "Server name", "", ""); + GVarPod_A mp_server_port("mp_server_port", "Server port", 0); + GVarStr_APS<100> mp_server_password("mp_server_password", "Server password", "", "", ""); + GVarStr_AP<100> mp_player_name("mp_player_name", "Nickname", "Player", "Player"); + GVarStr_AP<100> mp_player_token("mp_player_token", "User Token", "", ""); + GVarStr_A<100> mp_api_url("mp_api_url", "Online API URL", "http://api.rigsofrods.org"); + + // Diagnostic + GVarPod_A diag_auto_spawner_report("diag_auto_spawner_report", "AutoActorSpawnerReport", false); + GVarPod_A diag_camera("diag_camera", "Camera Debug", false); + GVarPod_A diag_trace_globals("diag_trace_globals", nullptr, + false); // Don't init to 'true', logger is not ready at startup + GVarPod_A diag_rig_log_node_import("diag_rig_log_node_import", "RigImporter_Debug_TraverseAndLogAllNodes", false); + GVarPod_A diag_rig_log_node_stats("diag_rig_log_node_stats", "RigImporter_PrintNodeStatsToLog", false); + GVarPod_A diag_rig_log_messages("diag_rig_log_messages", "RigImporter_PrintMessagesToLog", false); + GVarPod_A diag_collisions("diag_collisions", "Debug Collisions", false); + GVarPod_A diag_truck_mass("diag_truck_mass", "Debug Truck Mass", false); + GVarPod_A diag_envmap("diag_envmap", "EnvMapDebug", false); + GVarPod_A diag_videocameras("diag_videocameras", "VideoCameraDebug", false); + GVarStr_APS<100> diag_preset_terrain("diag_preset_terrain", "Preselected Terrain", "", "", ""); + GVarStr_A<100> diag_preset_spawn_pos("diag_spawn_position", nullptr, ""); + GVarStr_A<100> diag_preset_spawn_rot("diag_spawn_rotation", nullptr, ""); + GVarStr_APS<100> diag_preset_vehicle("diag_preset_vehicle", "Preselected Truck", "", "", ""); + GVarStr_A<100> diag_preset_veh_config("diag_preset_veh_config", "Preselected TruckConfig", ""); + GVarPod_APS diag_preset_veh_enter("diag_preset_veh_enter", "Enter Preselected Truck", false, false, false); + GVarPod_A diag_log_console_echo("diag_log_console_echo", "Enable Ingame Console", false); + GVarPod_A diag_log_beam_break("diag_log_beam_break", "Beam Break Debug", false); + GVarPod_A diag_log_beam_deform("diag_log_beam_deform", "Beam Deform Debug", false); + GVarPod_A diag_log_beam_trigger("diag_log_beam_trigger", "Trigger Debug", false); + GVarPod_A diag_simple_materials("diag_simple_materials", "SimpleMaterials", false); + GVarPod_A diag_warning_texture("diag_warning_texture", "Warning texture", false); + GVarPod_A diag_hide_broken_beams("diag_hide_broken_beams", "Hide broken beams", false); + GVarPod_A diag_hide_beam_stress("diag_hide_beam_stress", "Hide beam stress", true); + GVarPod_A diag_hide_wheel_info("diag_hide_wheel_info", "Hide wheel info", true); + GVarPod_A diag_hide_wheels("diag_hide_wheels", "Hide wheels", false); + GVarPod_A diag_hide_nodes("diag_hide_nodes", "Hide nodes", false); + GVarPod_A diag_physics_dt("diag_physics_dt", "PhysicsTimeStep", 0.0005f); + + // System (all paths are without ending slash!) + GVarStr_A<300> sys_process_dir("sys_process_dir", nullptr, ""); + GVarStr_A<300> sys_user_dir("sys_user_dir", nullptr, ""); + GVarStr_A<300> sys_config_dir("sys_config_dir", "Config Root", ""); + GVarStr_A<300> sys_cache_dir("sys_cache_dir", "Cache Path", ""); + GVarStr_A<300> sys_logs_dir("sys_logs_dir", "Log Path", ""); + GVarStr_A<300> sys_resources_dir("sys_resources_dir", "Resources Path", ""); + GVarStr_A<300> sys_profiler_dir("sys_profiler_dir", "Profiler output dir", ""); + GVarStr_A<300> sys_savegames_dir("sys_savegames_dir", nullptr, ""); + GVarStr_A<300> sys_screenshot_dir("sys_screenshot_dir", nullptr, ""); + + // Input - Output + GVarPod_A io_analog_smoothing("io_analog_smoothing", "Analog Input Smoothing", 1.f); + GVarPod_A io_analog_sensitivity("io_analog_sensitivity", "Analog Input Sensitivity", 1.f); + GVarPod_A io_ffb_enabled("io_ffb_enabled", "Force Feedback", false); + GVarPod_A io_ffb_camera_gain("io_ffb_camera_gain", "Force Feedback Camera", 0.f); + GVarPod_A io_ffb_center_gain("io_ffb_center_gain", "Force Feedback Centering", 0.f); + GVarPod_A io_ffb_master_gain("io_ffb_master_gain", "Force Feedback Gain", 0.f); + GVarPod_A io_ffb_stress_gain("io_ffb_stress_gain", "Force Feedback Stress", 0.f); + GVarEnum_AP io_input_grab_mode("io_input_grab_mode", "Input Grab", IoInputGrabMode::ALL, + IoInputGrabMode::ALL); + GVarPod_A io_arcade_controls("io_arcade_controls", "ArcadeControls", false); + GVarPod_A io_outgauge_mode("io_outgauge_mode", "OutGauge Mode", 0); // 0 = disabled, 1 = enabled + GVarStr_A<50> io_outgauge_ip("io_outgauge_ip", "OutGauge IP", "192.168.1.100"); + GVarPod_A io_outgauge_port("io_outgauge_port", "OutGauge Port", 1337); + GVarPod_A io_outgauge_delay("io_outgauge_delay", "OutGauge Delay", 10.f); + GVarPod_A io_outgauge_id("io_outgauge_id", "OutGauge ID", 0); + GVarPod_A io_discord_rpc("io_discord_rpc", "Discord Rich Presence", true); + + // Audio + GVarPod_A audio_master_volume("audio_master_volume", "Sound Volume", 1); + GVarPod_A audio_enable_creak("audio_enable_creak", "Creak Sound", false); + GVarStr_AP<100> audio_device_name("audio_device_name", "AudioDevice", "", ""); + GVarPod_A audio_menu_music("audio_menu_music", "MainMenuMusic", false); + + // Graphics + GVarEnum_AP gfx_flares_mode("gfx_flares_mode", "Lights", GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS, + GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS); + GVarEnum_AP gfx_shadow_type("gfx_shadow_type", "Shadow technique", GfxShadowType::PSSM, + GfxShadowType::PSSM); + GVarEnum_AP gfx_extcam_mode("gfx_extcam_mode", "External Camera Mode", GfxExtCamMode::PITCHING, + GfxExtCamMode::PITCHING); + GVarEnum_AP gfx_sky_mode("gfx_sky_mode", "Sky effects", GfxSkyMode::CAELUM, GfxSkyMode::CAELUM); + GVarEnum_AP gfx_texture_filter("gfx_texture_filter", "Texture Filtering", GfxTexFilter::ANISOTROPIC, + GfxTexFilter::ANISOTROPIC); + GVarEnum_AP gfx_vegetation_mode("gfx_vegetation_mode", "Vegetation", GfxVegetation::FULL, + GfxVegetation::FULL); + GVarEnum_AP gfx_water_mode("gfx_water_mode", "Water effects", GfxWaterMode::FULL_FAST, + GfxWaterMode::FULL_FAST); + GVarPod_A gfx_anisotropy("gfx_anisotropy", "Anisotropy", 4); + GVarPod_A gfx_water_waves("gfx_water_waves", "Waves", false); + GVarPod_A gfx_particles_mode("gfx_particles_mode", "Particles", 0); + GVarPod_A gfx_enable_videocams("gfx_enable_videocams", "gfx_enable_videocams", false); + GVarPod_A gfx_window_videocams("gfx_window_videocams", "UseVideocameraWindows", false); + GVarPod_APS gfx_surveymap_icons("gfx_surveymap_icons", "Overview map icons", true, true, true); + GVarPod_A gfx_declutter_map("gfx_declutter_map", "Declutter overview map", true); + GVarPod_A gfx_envmap_enabled("gfx_envmap_enabled", "Reflections", true); + GVarPod_A gfx_envmap_rate("gfx_envmap_rate", "ReflectionUpdateRate", 1); + GVarPod_A gfx_shadow_quality("gfx_shadow_quality", "Shadows Quality", 2); + GVarPod_A gfx_skidmarks_mode("gfx_skidmarks_mode", "Skidmarks", 0); + GVarPod_A gfx_sight_range("gfx_sight_range", "SightRange", 5000); // Previously either 2000 or 4500 (inconsistent) + GVarPod_A gfx_camera_height("gfx_camera_height", "Static camera height", 5); + GVarPod_APS gfx_fov_external("gfx_fov_external", "FOV External", 60, 60, 60); + GVarPod_APS gfx_fov_internal("gfx_fov_internal", "FOV Internal", 75, 75, 75); + GVarPod_A gfx_static_cam_fov_exp("gfx_static_cam_fov_exp", nullptr, 1.f); + GVarPod_A gfx_fixed_cam_tracking("gfx_fixed_cam_tracking", nullptr, false); + GVarPod_A gfx_fps_limit("gfx_fps_limit", "FPS-Limiter", 0); // 0 = unlimited + GVarPod_A gfx_speedo_digital("gfx_speedo_digital", "DigitalSpeedo", true); + GVarPod_A gfx_speedo_imperial("gfx_speedo_imperial", "gfx_speedo_imperial", false); + GVarPod_A gfx_flexbody_lods("gfx_flexbody_lods", "Flexbody_EnableLODs", false); + GVarPod_A gfx_flexbody_cache("gfx_flexbody_cache", "Flexbody_UseCache", false); + GVarPod_A gfx_reduce_shadows("gfx_reduce_shadows", "Shadow optimizations", true); + GVarPod_A gfx_enable_rtshaders("gfx_enable_rtshaders", "Use RTShader System", false); + + // Instance management + void SetMainMenu(MainMenu *obj) + { + g_main_menu = obj; + } + void SetSimController(SimController *obj) + { + g_sim_controller = obj; + } + void SetSimTerrain(TerrainManager *obj) + { + g_sim_terrain = obj; + } + void SetCacheSystem(CacheSystem *obj) + { + g_cache_system = obj; + } + + // Instance access + OgreSubsystem *GetOgreSubsystem() + { + return g_ogre_subsystem; + }; + ContentManager *GetContentManager() + { + return &g_content_manager; + } + OverlayWrapper *GetOverlayWrapper() + { + return g_overlay_wrapper; + } + GUIManager *GetGuiManager() + { + return g_gui_manager; + } + Console *GetConsole() + { + return g_gui_manager->GetConsole(); + } + InputEngine *GetInputEngine() + { + return g_input_engine; + } + CacheSystem *GetCacheSystem() + { + return g_cache_system; + } + MainMenu *GetMainMenu() + { + return g_main_menu; + } + SimController *GetSimController() + { + return g_sim_controller; + } + MumbleIntegration *GetMumble() + { + return g_mumble; + } + TerrainManager *GetSimTerrain() + { + return g_sim_terrain; + } + + void StartOgreSubsystem() + { + g_ogre_subsystem = new OgreSubsystem(); + if (g_ogre_subsystem == nullptr) { throw std::runtime_error("[RoR] Failed to create OgreSubsystem"); } + + if (!g_ogre_subsystem->StartOgre("", "")) { throw std::runtime_error("[RoR] Failed to start up OGRE 3D engine"); } + } + + void ShutdownOgreSubsystem() + { + assert(g_ogre_subsystem != nullptr && "ShutdownOgreSubsystem(): Ogre subsystem was not started"); + delete g_ogre_subsystem; + g_ogre_subsystem = nullptr; + } + + void CreateOverlayWrapper() + { + g_overlay_wrapper = new OverlayWrapper(); + if (g_overlay_wrapper == nullptr) { throw std::runtime_error("[RoR] Failed to create OverlayWrapper"); } + } + + void DestroyOverlayWrapper() + { + delete g_overlay_wrapper; // deleting nullptr does nothing + g_overlay_wrapper = nullptr; + } + + void CreateGuiManagerIfNotExists() + { + if (g_gui_manager == nullptr) { g_gui_manager = new GUIManager(); } + } + + void DeleteGuiManagerIfExists() + { + if (g_gui_manager != nullptr) + { + delete g_gui_manager; + g_gui_manager = nullptr; + } + } + + void CreateInputEngine() + { + assert(g_input_engine == nullptr); + g_input_engine = new InputEngine(); + } + + void CheckAndCreateMumble() + { +#ifdef USE_MUMBLE // The class is always forward-declared but only defined if USE_MUMBLE is defined + if (g_mumble == nullptr) g_mumble = new MumbleIntegration(); +#endif // USE_MUMBLE + } -void ShutdownOgreSubsystem() -{ - assert(g_ogre_subsystem != nullptr && "ShutdownOgreSubsystem(): Ogre subsystem was not started"); - delete g_ogre_subsystem; - g_ogre_subsystem = nullptr; -} + } // namespace App -void CreateOverlayWrapper() -{ - g_overlay_wrapper = new OverlayWrapper(); - if (g_overlay_wrapper == nullptr) + const char *EnumToStr(AppState v) { - throw std::runtime_error("[RoR] Failed to create OverlayWrapper"); + switch (v) + { + case AppState::BOOTSTRAP: return "BOOTSTRAP"; + case AppState::MAIN_MENU: return "MAIN_MENU"; + case AppState::PRINT_HELP_EXIT: return "PRINT_HELP_EXIT"; + case AppState::PRINT_VERSION_EXIT: return "PRINT_VERSION_EXIT"; + case AppState::SHUTDOWN: return "SHUTDOWN"; + case AppState::SIMULATION: return "SIMULATION"; + default: return "~invalid~"; + } } -} - -void DestroyOverlayWrapper() -{ - delete g_overlay_wrapper; // deleting nullptr does nothing - g_overlay_wrapper = nullptr; -} -void CreateGuiManagerIfNotExists() -{ - if (g_gui_manager == nullptr) + const char *EnumToStr(MpState v) { - g_gui_manager = new GUIManager(); + switch (v) + { + case MpState::DISABLED: return "DISABLED"; + case MpState::CONNECTED: return "CONNECTED"; + default: return "~invalid~"; + } } -} -void DeleteGuiManagerIfExists() -{ - if (g_gui_manager != nullptr) + const char *EnumToStr(SimState v) { - delete g_gui_manager; - g_gui_manager = nullptr; + switch (v) + { + case SimState::OFF: return "OFF"; + case SimState::RUNNING: return "RUNNING"; + case SimState::PAUSED: return "PAUSED"; + case SimState::SELECTING: return "SELECTING"; + case SimState::EDITOR_MODE: return "EDITOR_MODE"; + default: return "~invalid~"; + } } -} - -void CreateInputEngine() -{ - assert(g_input_engine == nullptr); - g_input_engine = new InputEngine(); -} - -void CheckAndCreateMumble() -{ -#ifdef USE_MUMBLE // The class is always forward-declared but only defined if USE_MUMBLE is defined - if (g_mumble == nullptr) - g_mumble = new MumbleIntegration(); -#endif // USE_MUMBLE -} - -} // namespace App - -const char* EnumToStr(AppState v) -{ - switch (v) + const char *EnumToStr(SimGearboxMode v) { - case AppState::BOOTSTRAP: return "BOOTSTRAP"; - case AppState::MAIN_MENU: return "MAIN_MENU"; - case AppState::PRINT_HELP_EXIT: return "PRINT_HELP_EXIT"; - case AppState::PRINT_VERSION_EXIT: return "PRINT_VERSION_EXIT"; - case AppState::SHUTDOWN: return "SHUTDOWN"; - case AppState::SIMULATION: return "SIMULATION"; - default: return "~invalid~"; + switch (v) + { + case SimGearboxMode::AUTO: return "AUTO"; + case SimGearboxMode::SEMI_AUTO: return "SEMI_AUTO"; + case SimGearboxMode::MANUAL: return "MANUAL"; + case SimGearboxMode::MANUAL_STICK: return "MANUAL_STICK"; + case SimGearboxMode::MANUAL_RANGES: return "MANUAL_RANGES"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(MpState v) -{ - switch (v) + const char *EnumToStr(GfxFlaresMode v) { - case MpState::DISABLED: return "DISABLED"; - case MpState::CONNECTED: return "CONNECTED"; - default: return "~invalid~"; + switch (v) + { + case GfxFlaresMode::NONE: return "NONE"; + case GfxFlaresMode::NO_LIGHTSOURCES: return "NO_LIGHTSOURCES"; + case GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY: return "CURR_VEHICLE_HEAD_ONLY"; + case GfxFlaresMode::ALL_VEHICLES_HEAD_ONLY: return "ALL_VEHICLES_HEAD_ONLY"; + case GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS: return "ALL_VEHICLES_ALL_LIGHTS"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(SimState v) -{ - switch (v) + const char *EnumToStr(GfxVegetation v) { - case SimState::OFF : return "OFF"; - case SimState::RUNNING : return "RUNNING"; - case SimState::PAUSED : return "PAUSED"; - case SimState::SELECTING : return "SELECTING"; - case SimState::EDITOR_MODE: return "EDITOR_MODE"; - default : return "~invalid~"; + switch (v) + { + case GfxVegetation::NONE: return "NONE"; + case GfxVegetation::x20PERC: return "20%"; + case GfxVegetation::x50PERC: return "50%"; + case GfxVegetation::FULL: return "FULL"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(SimGearboxMode v) -{ - switch (v) + const char *EnumToStr(GfxWaterMode v) { - case SimGearboxMode::AUTO : return "AUTO"; - case SimGearboxMode::SEMI_AUTO : return "SEMI_AUTO"; - case SimGearboxMode::MANUAL : return "MANUAL"; - case SimGearboxMode::MANUAL_STICK : return "MANUAL_STICK"; - case SimGearboxMode::MANUAL_RANGES: return "MANUAL_RANGES"; - default : return "~invalid~"; + switch (v) + { + case GfxWaterMode::NONE: return "NONE"; + case GfxWaterMode::BASIC: return "BASIC"; + case GfxWaterMode::REFLECT: return "REFLECT"; + case GfxWaterMode::FULL_FAST: return "FULL_FAST"; + case GfxWaterMode::FULL_HQ: return "FULL_HQ"; + case GfxWaterMode::HYDRAX: return "HYDRAX"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(GfxFlaresMode v) -{ - switch (v) + const char *EnumToStr(GfxSkyMode v) { - case GfxFlaresMode::NONE : return "NONE"; - case GfxFlaresMode::NO_LIGHTSOURCES : return "NO_LIGHTSOURCES"; - case GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY : return "CURR_VEHICLE_HEAD_ONLY"; - case GfxFlaresMode::ALL_VEHICLES_HEAD_ONLY : return "ALL_VEHICLES_HEAD_ONLY"; - case GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS: return "ALL_VEHICLES_ALL_LIGHTS"; - default : return "~invalid~"; + switch (v) + { + case GfxSkyMode::SANDSTORM: return "SANDSTORM"; + case GfxSkyMode::CAELUM: return "CAELUM"; + case GfxSkyMode::SKYX: return "SKYX"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(GfxVegetation v) -{ - switch(v) + const char *EnumToStr(IoInputGrabMode v) { - case GfxVegetation::NONE : return "NONE"; - case GfxVegetation::x20PERC : return "20%"; - case GfxVegetation::x50PERC : return "50%"; - case GfxVegetation::FULL : return "FULL"; - default : return "~invalid~"; + switch (v) + { + case IoInputGrabMode::NONE: return "NONE"; + case IoInputGrabMode::ALL: return "ALL"; + case IoInputGrabMode::DYNAMIC: return "DYNAMIC"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(GfxWaterMode v) -{ - switch(v) + const char *EnumToStr(GfxShadowType v) { - case GfxWaterMode::NONE : return "NONE"; - case GfxWaterMode::BASIC : return "BASIC"; - case GfxWaterMode::REFLECT : return "REFLECT"; - case GfxWaterMode::FULL_FAST : return "FULL_FAST"; - case GfxWaterMode::FULL_HQ : return "FULL_HQ"; - case GfxWaterMode::HYDRAX : return "HYDRAX"; - default : return "~invalid~"; + switch (v) + { + case GfxShadowType::NONE: return "NONE"; + case GfxShadowType::PSSM: return "PSSM"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(GfxSkyMode v) -{ - switch(v) + const char *EnumToStr(GfxTexFilter v) { - case GfxSkyMode::SANDSTORM: return "SANDSTORM"; - case GfxSkyMode::CAELUM : return "CAELUM"; - case GfxSkyMode::SKYX : return "SKYX"; - default : return "~invalid~"; + switch (v) + { + case GfxTexFilter::NONE: return "NONE"; + case GfxTexFilter::BILINEAR: return "BILINEAR"; + case GfxTexFilter::TRILINEAR: return "TRILINEAR"; + case GfxTexFilter::ANISOTROPIC: return "ANISOTROPIC"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(IoInputGrabMode v) -{ - switch (v) + const char *EnumToStr(GfxExtCamMode v) { - case IoInputGrabMode::NONE : return "NONE"; - case IoInputGrabMode::ALL : return "ALL"; - case IoInputGrabMode::DYNAMIC: return "DYNAMIC"; - default : return "~invalid~"; + switch (v) + { + case GfxExtCamMode::NONE: return "NONE"; + case GfxExtCamMode::STATIC: return "STATIC"; + case GfxExtCamMode::PITCHING: return "PITCHING"; + default: return "~invalid~"; + } } -} -const char* EnumToStr(GfxShadowType v) -{ - switch(v) + void Log(const char *msg) { - case GfxShadowType::NONE : return "NONE"; - case GfxShadowType::PSSM : return "PSSM"; - default : return "~invalid~"; + Ogre::LogManager::getSingleton().logMessage(msg); } -} -const char* EnumToStr(GfxTexFilter v) -{ - switch (v) + void LogFormat(const char *format, ...) { - case GfxTexFilter::NONE : return "NONE"; - case GfxTexFilter::BILINEAR : return "BILINEAR"; - case GfxTexFilter::TRILINEAR : return "TRILINEAR"; - case GfxTexFilter::ANISOTROPIC: return "ANISOTROPIC"; - default : return "~invalid~"; - } -} + char buffer[2000] = {}; -const char* EnumToStr(GfxExtCamMode v) -{ - switch (v) - { - case GfxExtCamMode::NONE: return "NONE"; - case GfxExtCamMode::STATIC: return "STATIC"; - case GfxExtCamMode::PITCHING: return "PITCHING"; - default: return "~invalid~"; - } -} - -void Log(const char* msg) -{ - Ogre::LogManager::getSingleton().logMessage(msg); -} - -void LogFormat(const char* format, ...) -{ - char buffer[2000] = {}; - - va_list args; - va_start(args, format); + va_list args; + va_start(args, format); vsprintf(buffer, format, args); - va_end(args); + va_end(args); - RoR::Log(buffer); -} + RoR::Log(buffer); + } -const char* GVarBase::LOG_FMT_S = "[RoR|GVar] %20s: %s(), new: \"%s\", old: \"%s\""; -const char* GVarBase::LOG_FMT_D = "[RoR|GVar] %20s: %s(), new: \"%d\", old: \"%d\""; -const char* GVarBase::LOG_FMT_F = "[RoR|GVar] %20s: %s(), new: \"%f\", old: \"%f\""; + const char *GVarBase::LOG_FMT_S = "[RoR|GVar] %20s: %s(), new: \"%s\", old: \"%s\""; + const char *GVarBase::LOG_FMT_D = "[RoR|GVar] %20s: %s(), new: \"%d\", old: \"%d\""; + const char *GVarBase::LOG_FMT_F = "[RoR|GVar] %20s: %s(), new: \"%f\", old: \"%f\""; -void GVarBase::LogFormat(const char* format, ...) const -{ - if (! App::diag_trace_globals.GetActive()) + void GVarBase::LogFormat(const char *format, ...) const { - return; - } + if (!App::diag_trace_globals.GetActive()) { return; } - char buffer[2000] = {}; + char buffer[2000] = {}; - va_list args; - va_start(args, format); + va_list args; + va_start(args, format); vsprintf(buffer, format, args); - va_end(args); + va_end(args); - RoR::Log(buffer); -} + RoR::Log(buffer); + } } // namespace RoR diff --git a/source/main/Application.h b/source/main/Application.h index 079b2c6d1a..104f681b10 100644 --- a/source/main/Application.h +++ b/source/main/Application.h @@ -17,7 +17,6 @@ along with Rigs of Rods. If not, see . */ - /// @file Application.h /// @author Petr Ohlidal /// @date 05/2014 @@ -31,803 +30,969 @@ #include #include -namespace RoR { - - -// ------------------------------------------------------------------------------------------------ -// Global definitions and enumerations -// ------------------------------------------------------------------------------------------------ - - -enum class AppState +namespace RoR { - BOOTSTRAP, ///< Initial state - MAIN_MENU, - SIMULATION, - SHUTDOWN, - PRINT_HELP_EXIT, - PRINT_VERSION_EXIT, -}; -const char* EnumToStr(AppState v); - -enum class MpState -{ - DISABLED, ///< Not connected for whatever reason. - CONNECTING, - CONNECTED, -}; -const char* EnumToStr(MpState v); -enum class SimState -{ - OFF, - RUNNING, - PAUSED, - SELECTING, ///< The selector GUI window is displayed. - EDITOR_MODE ///< Hacky, but whatever... added by Ulteq, 2016 -}; -const char* EnumToStr(SimState v); - -enum class SimGearboxMode -{ - AUTO, ///< Automatic shift - SEMI_AUTO, ///< Manual shift - Auto clutch - MANUAL, ///< Fully Manual: sequential shift - MANUAL_STICK, ///< Fully manual: stick shift - MANUAL_RANGES, ///< Fully Manual: stick shift with ranges -}; -const char* EnumToStr(SimGearboxMode v); - -enum class GfxShadowType -{ - NONE, - PSSM -}; -const char* EnumToStr(GfxShadowType v); - -enum class GfxExtCamMode -{ - NONE, - STATIC, - PITCHING, -}; -const char* EnumToStr(GfxExtCamMode v); - -enum class GfxTexFilter -{ - NONE, - BILINEAR, - TRILINEAR, - ANISOTROPIC, -}; -const char* EnumToStr(GfxTexFilter v); - -enum class GfxVegetation -{ - NONE, - x20PERC, - x50PERC, - FULL, -}; -const char* EnumToStr(GfxVegetation v); - -enum class GfxFlaresMode -{ - NONE, ///< None (fastest) - NO_LIGHTSOURCES, ///< No light sources - CURR_VEHICLE_HEAD_ONLY, ///< Only current vehicle, main lights - ALL_VEHICLES_HEAD_ONLY, ///< All vehicles, main lights - ALL_VEHICLES_ALL_LIGHTS, ///< All vehicles, all lights -}; -const char* EnumToStr(GfxFlaresMode v); - -enum class GfxWaterMode -{ - NONE, ///< None - BASIC, ///< Basic (fastest) - REFLECT, ///< Reflection - FULL_FAST, ///< Reflection + refraction (speed optimized) - FULL_HQ, ///< Reflection + refraction (quality optimized) - HYDRAX, ///< HydraX -}; -const char* EnumToStr(GfxWaterMode v); - -enum class GfxSkyMode -{ - SANDSTORM, ///< Sandstorm (fastest) - CAELUM, ///< Caelum (best looking, slower) - SKYX, ///< SkyX (best looking, slower) -}; -const char* EnumToStr(GfxSkyMode v); + // ------------------------------------------------------------------------------------------------ + // Global definitions and enumerations + // ------------------------------------------------------------------------------------------------ -enum class IoInputGrabMode -{ - NONE, - ALL, - DYNAMIC, -}; -const char* EnumToStr(IoInputGrabMode v); + enum class AppState + { + BOOTSTRAP, ///< Initial state + MAIN_MENU, + SIMULATION, + SHUTDOWN, + PRINT_HELP_EXIT, + PRINT_VERSION_EXIT, + }; + const char *EnumToStr(AppState v); + + enum class MpState + { + DISABLED, ///< Not connected for whatever reason. + CONNECTING, + CONNECTED, + }; + const char *EnumToStr(MpState v); + enum class SimState + { + OFF, + RUNNING, + PAUSED, + SELECTING, ///< The selector GUI window is displayed. + EDITOR_MODE ///< Hacky, but whatever... added by Ulteq, 2016 + }; + const char *EnumToStr(SimState v); + + enum class SimGearboxMode + { + AUTO, ///< Automatic shift + SEMI_AUTO, ///< Manual shift - Auto clutch + MANUAL, ///< Fully Manual: sequential shift + MANUAL_STICK, ///< Fully manual: stick shift + MANUAL_RANGES, ///< Fully Manual: stick shift with ranges + }; + const char *EnumToStr(SimGearboxMode v); + + enum class GfxShadowType + { + NONE, + PSSM + }; + const char *EnumToStr(GfxShadowType v); -// ------------------------------------------------------------------------------------------------ -// Generic utilities -// ------------------------------------------------------------------------------------------------ + enum class GfxExtCamMode + { + NONE, + STATIC, + PITCHING, + }; + const char *EnumToStr(GfxExtCamMode v); + enum class GfxTexFilter + { + NONE, + BILINEAR, + TRILINEAR, + ANISOTROPIC, + }; + const char *EnumToStr(GfxTexFilter v); + + enum class GfxVegetation + { + NONE, + x20PERC, + x50PERC, + FULL, + }; + const char *EnumToStr(GfxVegetation v); + + enum class GfxFlaresMode + { + NONE, ///< None (fastest) + NO_LIGHTSOURCES, ///< No light sources + CURR_VEHICLE_HEAD_ONLY, ///< Only current vehicle, main lights + ALL_VEHICLES_HEAD_ONLY, ///< All vehicles, main lights + ALL_VEHICLES_ALL_LIGHTS, ///< All vehicles, all lights + }; + const char *EnumToStr(GfxFlaresMode v); + + enum class GfxWaterMode + { + NONE, ///< None + BASIC, ///< Basic (fastest) + REFLECT, ///< Reflection + FULL_FAST, ///< Reflection + refraction (speed optimized) + FULL_HQ, ///< Reflection + refraction (quality optimized) + HYDRAX, ///< HydraX + }; + const char *EnumToStr(GfxWaterMode v); + + enum class GfxSkyMode + { + SANDSTORM, ///< Sandstorm (fastest) + CAELUM, ///< Caelum (best looking, slower) + SKYX, ///< SkyX (best looking, slower) + }; + const char *EnumToStr(GfxSkyMode v); -/// Wrapper for classic c-string (local buffer) -/// Refresher: `strlen()` excludes '\0' terminator; `strncat()` Appends '\0' terminator -/// @author Petr Ohlidal, 2017 -template class Str -{ -public: - // Constructors - inline Str() { this->Clear(); } - inline Str(Str const & src) { this->Assign(src); } - inline Str(const char* src) { this->Assign(src); } - - // Reading - inline const char* ToCStr() const { return m_buffer; } - inline bool IsEmpty() const { return m_buffer[0] == '\0'; } - inline char* GetBuffer() { return m_buffer; } - inline size_t GetCapacity() const { return m_capacity; } - inline int Compare(const char* str) const { return std::strncmp(m_buffer, str, L); } - inline size_t GetLength() const { return std::strlen(m_buffer); } - - // Writing - inline Str& Clear() { std::memset(m_buffer, 0, L); return *this; } - inline Str& Assign(const char* src) { this->Clear(); this->Append(src); return *this; } - inline Str& Append(const char* src) { std::strncat(m_buffer, src, (L - (this->GetLength() + 1))); return *this; } - inline Str& Append(float f) { char buf[50]; std::snprintf(buf, 50, "%f", f); this->Append(buf); return *this; } - inline Str& Append(int i) { char buf[50]; std::snprintf(buf, 50, "%d", i); this->Append(buf); return *this; } - inline Str& Append(size_t z) { char buf[50]; std::snprintf(buf, 50, "%lu", static_cast(z)); this->Append(buf); return *this; } - inline Str& Append(char c) { char buf[2] = {}; buf[0] = c; this->Append(buf); return *this; } - - // Operators - inline operator const char*() const { return this->ToCStr(); } - inline Str& operator= (const char* src) { return this->Assign(src); } - inline Str& operator= (std::string const& str) { return this->Assign(str.c_str()); } - inline Str& operator<< (const char* src) { return this->Append(src); } - inline Str& operator<< (std::string const& str) { return this->Append(str.c_str()); } - inline Str& operator<< (float f) { return this->Append(f); } - inline Str& operator<< (int i) { return this->Append(i); } - inline Str& operator<< (size_t z) { return this->Append(z); } - inline Str& operator<< (char c) { return this->Append(c); } - inline bool operator== (const char* other) const { return (this->Compare(other) == 0); } - -private: - char m_buffer[L]; - const size_t m_capacity = L; -}; - - -void Log(const char* msg); ///< The ultimate, application-wide logging function. Adds a line (any length) in 'RoR.log' file. -void LogFormat(const char* format, ...); ///< Improved logging utility. Uses fixed 2Kb buffer. -inline const char* BoolToStr(bool b) { return (b) ? "true" : "false"; } - - -// ------------------------------------------------------------------------------------------------ -// Global variables -// ------------------------------------------------------------------------------------------------ - - -/// A global variable - only for use in 'Application.(h/cpp)' -/// -/// Concept: A GVar may contain 1-3 values: -/// * [A] Active value = the value currently in effect. Each GVar has an active value. -/// * [P] Pending value = the value to be set as active on earliest occasion (occasion may be anything from next frame to game restart) -/// When no change is requested, value of Pending equals value of Active. -/// Currently all GVars contain a pending value, but this design may be changed in the future. -/// * [S] Stored value = The user-defined value to be persisted in config file. -/// - When not present, Active is taken as Stored. -/// - When present, it's unaffected by Active and only changes when user wants. -/// GVar classes are named _A, _AP or _APS depending on which values they contain. NOTE this concept is not fully implemented yet. -/// -/// API usage: -/// SetPending(): new pending value, active stands. GVars without pending value don't have this function. -/// SetActive(): direct update of active (+pending, if present) value -/// ApplyPending(): updates active from pending. GVars without pending value don't have this function. -/// ResetPending(): updates pending from active. GVars without pending value don't have this function. -/// GetStored(): gets stored value, if present, or active value if not. -/// SetStored(): direct update of stored value. GVars without stored value don't have this function. -/// -/// Usage guidelines: -/// * There are no definite rules how to use and update a GVar. Each one is specific. -/// * Each GVar should have an Owner - a piece of code which checks for 'pending' values and Apply()-ies them. -/// This may be any thread and any code location, but there should be just 1 per GVar. -/// -/// Implementation notes: -/// GVars use virtual functions (-> overhead: vtable per class, vptr per instance, function-ptr calls). -/// The choice was 1) duplicate code in A/AP/APS classes 2) virtual inheritance. Rationale: -/// * Call overhead is not considered a problem because virtuals only do non-frequent tasks: -/// setting value (user action) and retrieving 'Stored' value (user console action/saving config on game exit). -/// * Vtable pointer is not considered a problem because sane number of GVars is not more than ~250 (RoR has ~100 now). -struct GVarBase -{ -public: - GVarBase(const char* name, const char* conf_name): - name(name), conf_name(conf_name) - {} + enum class IoInputGrabMode + { + NONE, + ALL, + DYNAMIC, + }; + const char *EnumToStr(IoInputGrabMode v); + + // ------------------------------------------------------------------------------------------------ + // Generic utilities + // ------------------------------------------------------------------------------------------------ + + /// Wrapper for classic c-string (local buffer) + /// Refresher: `strlen()` excludes '\0' terminator; `strncat()` Appends '\0' terminator + /// @author Petr Ohlidal, 2017 + template class Str + { + public: + // Constructors + inline Str() + { + this->Clear(); + } + inline Str(Str const &src) + { + this->Assign(src); + } + inline Str(const char *src) + { + this->Assign(src); + } - const char* const name; - const char* const conf_name; + // Reading + inline const char *ToCStr() const + { + return m_buffer; + } + inline bool IsEmpty() const + { + return m_buffer[0] == '\0'; + } + inline char *GetBuffer() + { + return m_buffer; + } + inline size_t GetCapacity() const + { + return m_capacity; + } + inline int Compare(const char *str) const + { + return std::strncmp(m_buffer, str, L); + } + inline size_t GetLength() const + { + return std::strlen(m_buffer); + } -protected: + // Writing + inline Str &Clear() + { + std::memset(m_buffer, 0, L); + return *this; + } + inline Str &Assign(const char *src) + { + this->Clear(); + this->Append(src); + return *this; + } + inline Str &Append(const char *src) + { + std::strncat(m_buffer, src, (L - (this->GetLength() + 1))); + return *this; + } + inline Str &Append(float f) + { + char buf[50]; + std::snprintf(buf, 50, "%f", f); + this->Append(buf); + return *this; + } + inline Str &Append(int i) + { + char buf[50]; + std::snprintf(buf, 50, "%d", i); + this->Append(buf); + return *this; + } + inline Str &Append(size_t z) + { + char buf[50]; + std::snprintf(buf, 50, "%lu", static_cast(z)); + this->Append(buf); + return *this; + } + inline Str &Append(char c) + { + char buf[2] = {}; + buf[0] = c; + this->Append(buf); + return *this; + } - static const char* LOG_FMT_S; - static const char* LOG_FMT_D; - static const char* LOG_FMT_F; + // Operators + inline operator const char *() const + { + return this->ToCStr(); + } + inline Str &operator=(const char *src) + { + return this->Assign(src); + } + inline Str &operator=(std::string const &str) + { + return this->Assign(str.c_str()); + } + inline Str &operator<<(const char *src) + { + return this->Append(src); + } + inline Str &operator<<(std::string const &str) + { + return this->Append(str.c_str()); + } + inline Str &operator<<(float f) + { + return this->Append(f); + } + inline Str &operator<<(int i) + { + return this->Append(i); + } + inline Str &operator<<(size_t z) + { + return this->Append(z); + } + inline Str &operator<<(char c) + { + return this->Append(c); + } + inline bool operator==(const char *other) const + { + return (this->Compare(other) == 0); + } - void LogFormat(const char* format, ...) const; + private: + char m_buffer[L]; + const size_t m_capacity = L; + }; - // arg = the new value, cur = the old value - inline void LogSetPending(const char* arg, const char* cur) const { this->LogFormat(LOG_FMT_S, name, "SetPending", arg, cur); } - inline void LogSetPending(int arg, int cur) const { this->LogFormat(LOG_FMT_D, name, "SetPending", arg, cur); } - inline void LogSetPending(float arg, float cur) const { this->LogFormat(LOG_FMT_F, name, "SetPending", arg, cur); } - inline void LogSetPending(bool arg, bool cur) const { this->LogSetPending(BoolToStr(arg), BoolToStr(cur)); } + void Log(const char *msg); ///< The ultimate, application-wide logging function. Adds a line (any length) in 'RoR.log' file. + void LogFormat(const char *format, ...); ///< Improved logging utility. Uses fixed 2Kb buffer. + inline const char *BoolToStr(bool b) + { + return (b) ? "true" : "false"; + } - inline void LogSetActive(const char* arg, const char* cur) const { this->LogFormat(LOG_FMT_S, name, "SetActive", arg, cur); } - inline void LogSetActive(int arg, int cur) const { this->LogFormat(LOG_FMT_D, name, "SetActive", arg, cur); } - inline void LogSetActive(float arg, float cur) const { this->LogFormat(LOG_FMT_F, name, "SetActive", arg, cur); } - inline void LogSetActive(bool arg, bool cur) const { this->LogSetActive(BoolToStr(arg), BoolToStr(cur)); } + // ------------------------------------------------------------------------------------------------ + // Global variables + // ------------------------------------------------------------------------------------------------ + + /// A global variable - only for use in 'Application.(h/cpp)' + /// + /// Concept: A GVar may contain 1-3 values: + /// * [A] Active value = the value currently in effect. Each GVar has an active value. + /// * [P] Pending value = the value to be set as active on earliest occasion (occasion may be anything from next frame to + /// game restart) + /// When no change is requested, value of Pending equals value of Active. + /// Currently all GVars contain a pending value, but this design may be changed in the future. + /// * [S] Stored value = The user-defined value to be persisted in config file. + /// - When not present, Active is taken as Stored. + /// - When present, it's unaffected by Active and only changes when user wants. + /// GVar classes are named _A, _AP or _APS depending on which values they contain. NOTE this concept is not fully implemented + /// yet. + /// + /// API usage: + /// SetPending(): new pending value, active stands. GVars without pending value don't have this function. + /// SetActive(): direct update of active (+pending, if present) value + /// ApplyPending(): updates active from pending. GVars without pending value don't have this function. + /// ResetPending(): updates pending from active. GVars without pending value don't have this function. + /// GetStored(): gets stored value, if present, or active value if not. + /// SetStored(): direct update of stored value. GVars without stored value don't have this function. + /// + /// Usage guidelines: + /// * There are no definite rules how to use and update a GVar. Each one is specific. + /// * Each GVar should have an Owner - a piece of code which checks for 'pending' values and Apply()-ies them. + /// This may be any thread and any code location, but there should be just 1 per GVar. + /// + /// Implementation notes: + /// GVars use virtual functions (-> overhead: vtable per class, vptr per instance, function-ptr calls). + /// The choice was 1) duplicate code in A/AP/APS classes 2) virtual inheritance. Rationale: + /// * Call overhead is not considered a problem because virtuals only do non-frequent tasks: + /// setting value (user action) and retrieving 'Stored' value (user console action/saving config on game exit). + /// * Vtable pointer is not considered a problem because sane number of GVars is not more than ~250 (RoR has ~100 now). + struct GVarBase + { + public: + GVarBase(const char *name, const char *conf_name) : name(name), conf_name(conf_name) + { + } - inline void LogSetStored(const char* arg, const char* cur) const { this->LogFormat(LOG_FMT_S, name, "SetStored", arg, cur); } - inline void LogSetStored(int arg, int cur) const { this->LogFormat(LOG_FMT_D, name, "SetStored", arg, cur); } - inline void LogSetStored(float arg, float cur) const { this->LogFormat(LOG_FMT_F, name, "SetStored", arg, cur); } - inline void LogSetStored(bool arg, bool cur) const { this->LogSetStored(BoolToStr(arg), BoolToStr(cur)); } + const char *const name; + const char *const conf_name; - // p = 'Pending' value, a = 'Active' value - inline void LogApplyPending(const char* p, const char* a) const { this->LogFormat(LOG_FMT_S, name, "ApplyPending", p, a); } - inline void LogApplyPending(int p, int a) const { this->LogFormat(LOG_FMT_D, name, "ApplyPending", p, a); } - inline void LogApplyPending(float p, float a) const { this->LogFormat(LOG_FMT_F, name, "ApplyPending", p, a); } - inline void LogApplyPending(bool p, bool a) const { this->LogApplyPending(BoolToStr(p), BoolToStr(a)); } + protected: + static const char *LOG_FMT_S; + static const char *LOG_FMT_D; + static const char *LOG_FMT_F; - inline void LogResetPending(const char* p, const char* a) const { this->LogFormat(LOG_FMT_S, name, "ResetPending", a, p); } - inline void LogResetPending(int p, int a) const { this->LogFormat(LOG_FMT_D, name, "ResetPending", a, p); } - inline void LogResetPending(float p, float a) const { this->LogFormat(LOG_FMT_F, name, "ResetPending", a, p); } - inline void LogResetPending(bool p, bool a) const { this->LogResetPending(BoolToStr(p), BoolToStr(a)); } -}; + void LogFormat(const char *format, ...) const; + // arg = the new value, cur = the old value + inline void LogSetPending(const char *arg, const char *cur) const + { + this->LogFormat(LOG_FMT_S, name, "SetPending", arg, cur); + } + inline void LogSetPending(int arg, int cur) const + { + this->LogFormat(LOG_FMT_D, name, "SetPending", arg, cur); + } + inline void LogSetPending(float arg, float cur) const + { + this->LogFormat(LOG_FMT_F, name, "SetPending", arg, cur); + } + inline void LogSetPending(bool arg, bool cur) const + { + this->LogSetPending(BoolToStr(arg), BoolToStr(cur)); + } -/// POD = Plain old data (C++ concept); _A = Has only 'Active' field -template class GVarPod_A: public GVarBase -{ -public: - GVarPod_A(const char* name, const char* conf, T active_val): - GVarBase(name, conf), m_value_active(active_val) - {} + inline void LogSetActive(const char *arg, const char *cur) const + { + this->LogFormat(LOG_FMT_S, name, "SetActive", arg, cur); + } + inline void LogSetActive(int arg, int cur) const + { + this->LogFormat(LOG_FMT_D, name, "SetActive", arg, cur); + } + inline void LogSetActive(float arg, float cur) const + { + this->LogFormat(LOG_FMT_F, name, "SetActive", arg, cur); + } + inline void LogSetActive(bool arg, bool cur) const + { + this->LogSetActive(BoolToStr(arg), BoolToStr(cur)); + } - virtual ~GVarPod_A() {} + inline void LogSetStored(const char *arg, const char *cur) const + { + this->LogFormat(LOG_FMT_S, name, "SetStored", arg, cur); + } + inline void LogSetStored(int arg, int cur) const + { + this->LogFormat(LOG_FMT_D, name, "SetStored", arg, cur); + } + inline void LogSetStored(float arg, float cur) const + { + this->LogFormat(LOG_FMT_F, name, "SetStored", arg, cur); + } + inline void LogSetStored(bool arg, bool cur) const + { + this->LogSetStored(BoolToStr(arg), BoolToStr(cur)); + } - inline T GetActive() const - { - return m_value_active; - } + // p = 'Pending' value, a = 'Active' value + inline void LogApplyPending(const char *p, const char *a) const + { + this->LogFormat(LOG_FMT_S, name, "ApplyPending", p, a); + } + inline void LogApplyPending(int p, int a) const + { + this->LogFormat(LOG_FMT_D, name, "ApplyPending", p, a); + } + inline void LogApplyPending(float p, float a) const + { + this->LogFormat(LOG_FMT_F, name, "ApplyPending", p, a); + } + inline void LogApplyPending(bool p, bool a) const + { + this->LogApplyPending(BoolToStr(p), BoolToStr(a)); + } - virtual T GetStored() const - { - return m_value_active; - } + inline void LogResetPending(const char *p, const char *a) const + { + this->LogFormat(LOG_FMT_S, name, "ResetPending", a, p); + } + inline void LogResetPending(int p, int a) const + { + this->LogFormat(LOG_FMT_D, name, "ResetPending", a, p); + } + inline void LogResetPending(float p, float a) const + { + this->LogFormat(LOG_FMT_F, name, "ResetPending", a, p); + } + inline void LogResetPending(bool p, bool a) const + { + this->LogResetPending(BoolToStr(p), BoolToStr(a)); + } + }; - virtual void SetActive(T val) + /// POD = Plain old data (C++ concept); _A = Has only 'Active' field + template class GVarPod_A : public GVarBase { - if (val != m_value_active) + public: + GVarPod_A(const char *name, const char *conf, T active_val) : GVarBase(name, conf), m_value_active(active_val) { - GVarBase::LogSetActive(val, m_value_active); - m_value_active = val; } - } -protected: - T m_value_active; -}; + virtual ~GVarPod_A() + { + } + inline T GetActive() const + { + return m_value_active; + } -/// POD = Plain old data (C++ concept); _AP = Has 'Active' and 'Pending' fields -template class GVarPod_AP: public GVarPod_A -{ -public: - GVarPod_AP(const char* name, const char* conf, T active_val, T pending_val): - GVarPod_A(name, conf, active_val), m_value_pending(pending_val) - {} + virtual T GetStored() const + { + return m_value_active; + } - virtual ~GVarPod_AP() {} + virtual void SetActive(T val) + { + if (val != m_value_active) + { + GVarBase::LogSetActive(val, m_value_active); + m_value_active = val; + } + } - inline T GetPending() const - { - return m_value_pending; - } + protected: + T m_value_active; + }; - void SetPending(T val) + /// POD = Plain old data (C++ concept); _AP = Has 'Active' and 'Pending' fields + template class GVarPod_AP : public GVarPod_A { - if (val != m_value_pending) + public: + GVarPod_AP(const char *name, const char *conf, T active_val, T pending_val) + : GVarPod_A(name, conf, active_val), m_value_pending(pending_val) { - GVarBase::LogSetPending(val, m_value_pending); - m_value_pending = val; } - } - virtual void SetActive(T val) override - { - if ((val != GVarPod_A::m_value_active) || (val != m_value_pending)) + virtual ~GVarPod_AP() { - GVarBase::LogSetActive(val, GVarPod_A::m_value_active); - GVarPod_A::m_value_active = val; - m_value_pending = val; } - } - void ApplyPending() - { - if (GVarPod_A::m_value_active != m_value_pending) + inline T GetPending() const { - GVarBase::LogApplyPending(m_value_pending, GVarPod_A::m_value_active); - GVarPod_A::m_value_active = m_value_pending; + return m_value_pending; } - } - void ResetPending() - { - if (GVarPod_A::m_value_active != m_value_pending) + void SetPending(T val) { - GVarBase::LogResetPending(m_value_pending, GVarPod_A::m_value_active); - m_value_pending = GVarPod_A::m_value_active; + if (val != m_value_pending) + { + GVarBase::LogSetPending(val, m_value_pending); + m_value_pending = val; + } } - } - -protected: - T m_value_pending; -}; + virtual void SetActive(T val) override + { + if ((val != GVarPod_A::m_value_active) || (val != m_value_pending)) + { + GVarBase::LogSetActive(val, GVarPod_A::m_value_active); + GVarPod_A::m_value_active = val; + m_value_pending = val; + } + } -/// POD = Plain old data (C++ concept); _APS = Has 'Active, Pending, Stored' fields -template class GVarPod_APS: public GVarPod_AP -{ -public: - GVarPod_APS(const char* name, const char* conf, T active_val, T pending_val, T stored_val): - GVarPod_AP(name, conf, active_val, pending_val), m_value_stored(stored_val) - {} + void ApplyPending() + { + if (GVarPod_A::m_value_active != m_value_pending) + { + GVarBase::LogApplyPending(m_value_pending, GVarPod_A::m_value_active); + GVarPod_A::m_value_active = m_value_pending; + } + } - virtual ~GVarPod_APS() {} + void ResetPending() + { + if (GVarPod_A::m_value_active != m_value_pending) + { + GVarBase::LogResetPending(m_value_pending, GVarPod_A::m_value_active); + m_value_pending = GVarPod_A::m_value_active; + } + } - virtual T GetStored() const override - { - return m_value_stored; - } + protected: + T m_value_pending; + }; - void SetStored(T val) + /// POD = Plain old data (C++ concept); _APS = Has 'Active, Pending, Stored' fields + template class GVarPod_APS : public GVarPod_AP { - if (val != m_value_stored) + public: + GVarPod_APS(const char *name, const char *conf, T active_val, T pending_val, T stored_val) + : GVarPod_AP(name, conf, active_val, pending_val), m_value_stored(stored_val) { - GVarBase::LogSetStored(val, m_value_stored); - m_value_stored = val; } - } -protected: - T m_value_stored; -}; + virtual ~GVarPod_APS() + { + } + virtual T GetStored() const override + { + return m_value_stored; + } -/// _A = Has only 'Active' field -template class GVarEnum_A: public GVarBase -{ -public: - GVarEnum_A(const char* name, const char* conf, E active_val): - GVarBase(name, conf), m_value_active(active_val) - {} + void SetStored(T val) + { + if (val != m_value_stored) + { + GVarBase::LogSetStored(val, m_value_stored); + m_value_stored = val; + } + } - virtual ~GVarEnum_A() {}; + protected: + T m_value_stored; + }; - inline E GetActive() const + /// _A = Has only 'Active' field + template class GVarEnum_A : public GVarBase { - return m_value_active; - } - - virtual void SetActive(E val) - { - if (val != m_value_active) + public: + GVarEnum_A(const char *name, const char *conf, E active_val) : GVarBase(name, conf), m_value_active(active_val) { - GVarBase::LogSetActive(EnumToStr(val), EnumToStr(m_value_active)); // Conversion needed - m_value_active = val; } - } - -protected: - E m_value_active; -}; + virtual ~GVarEnum_A(){}; -/// _AP = Has 'Active' and 'Pending' fields -template class GVarEnum_AP: public GVarEnum_A -{ -public: - GVarEnum_AP(const char* name, const char* conf, E active_val, E pending_val): - GVarEnum_A(name, conf, active_val), m_value_pending(pending_val) - {} + inline E GetActive() const + { + return m_value_active; + } - virtual ~GVarEnum_AP() {} + virtual void SetActive(E val) + { + if (val != m_value_active) + { + GVarBase::LogSetActive(EnumToStr(val), EnumToStr(m_value_active)); // Conversion needed + m_value_active = val; + } + } - inline E GetPending() - { - return m_value_pending; - } + protected: + E m_value_active; + }; - void SetPending(E val) + /// _AP = Has 'Active' and 'Pending' fields + template class GVarEnum_AP : public GVarEnum_A { - if (val != m_value_pending) + public: + GVarEnum_AP(const char *name, const char *conf, E active_val, E pending_val) + : GVarEnum_A(name, conf, active_val), m_value_pending(pending_val) { - GVarBase::LogSetPending(EnumToStr(val), EnumToStr(m_value_pending)); - m_value_pending = val; } - } - virtual void SetActive(E val) override - { - if ((val != GVarEnum_A::m_value_active) || (val != m_value_pending)) + virtual ~GVarEnum_AP() { - GVarBase::LogSetPending(EnumToStr(val), EnumToStr(GVarEnum_A::m_value_active)); - GVarEnum_A::m_value_active = val; - m_value_pending = val; } - } - void ApplyPending() - { - if (GVarEnum_A::m_value_active != m_value_pending) + inline E GetPending() { - GVarBase::LogApplyPending(EnumToStr(m_value_pending), EnumToStr(GVarEnum_A::m_value_active)); - GVarEnum_A::m_value_active = m_value_pending; + return m_value_pending; } - } - void ResetPending() - { - if (GVarEnum_A::m_value_active != m_value_pending) + void SetPending(E val) { - GVarBase::LogResetPending(EnumToStr(m_value_pending), EnumToStr(GVarEnum_A::m_value_active)); - m_value_pending = GVarEnum_A::m_value_active; + if (val != m_value_pending) + { + GVarBase::LogSetPending(EnumToStr(val), EnumToStr(m_value_pending)); + m_value_pending = val; + } } - } -protected: - E m_value_pending; -}; + virtual void SetActive(E val) override + { + if ((val != GVarEnum_A::m_value_active) || (val != m_value_pending)) + { + GVarBase::LogSetPending(EnumToStr(val), EnumToStr(GVarEnum_A::m_value_active)); + GVarEnum_A::m_value_active = val; + m_value_pending = val; + } + } + void ApplyPending() + { + if (GVarEnum_A::m_value_active != m_value_pending) + { + GVarBase::LogApplyPending(EnumToStr(m_value_pending), EnumToStr(GVarEnum_A::m_value_active)); + GVarEnum_A::m_value_active = m_value_pending; + } + } -/// _APS = Has 'Active, Pending, Stored' fields -template class GVarEnum_APS: public GVarEnum_AP -{ -public: - GVarEnum_APS(const char* name, const char* conf, E active_val, E pending_val, E stored_val): - GVarEnum_AP(name, conf, active_val, pending_val), m_value_stored(stored_val) - {} + void ResetPending() + { + if (GVarEnum_A::m_value_active != m_value_pending) + { + GVarBase::LogResetPending(EnumToStr(m_value_pending), EnumToStr(GVarEnum_A::m_value_active)); + m_value_pending = GVarEnum_A::m_value_active; + } + } - virtual ~GVarEnum_APS() {} + protected: + E m_value_pending; + }; - void SetStored(E val) + /// _APS = Has 'Active, Pending, Stored' fields + template class GVarEnum_APS : public GVarEnum_AP { - if (val != m_value_stored) + public: + GVarEnum_APS(const char *name, const char *conf, E active_val, E pending_val, E stored_val) + : GVarEnum_AP(name, conf, active_val, pending_val), m_value_stored(stored_val) { - GVarBase::LogSetStored(EnumToStr(val), EnumToStr(m_value_stored)); - m_value_stored = val; } - } - -protected: - E m_value_stored; -}; + virtual ~GVarEnum_APS() + { + } -template class GVarStr_A: public GVarBase -{ -public: - GVarStr_A(const char* name, const char* conf, const char* active_val): - GVarBase(name, conf), m_value_active(active_val) - {} - - virtual ~GVarStr_A() {} - - inline const char* GetActive() const - { - return m_value_active; - } + void SetStored(E val) + { + if (val != m_value_stored) + { + GVarBase::LogSetStored(EnumToStr(val), EnumToStr(m_value_stored)); + m_value_stored = val; + } + } - virtual const char* GetStored() const - { - return m_value_active; - } + protected: + E m_value_stored; + }; - virtual void SetActive(const char* val) + template class GVarStr_A : public GVarBase { - if (val != m_value_active) + public: + GVarStr_A(const char *name, const char *conf, const char *active_val) : GVarBase(name, conf), m_value_active(active_val) { - GVarBase::LogSetActive(val, m_value_active); - m_value_active = val; } - } - inline bool IsActiveEmpty() const - { - return m_value_active.IsEmpty(); - } + virtual ~GVarStr_A() + { + } -protected: - Str m_value_active; -}; + inline const char *GetActive() const + { + return m_value_active; + } + virtual const char *GetStored() const + { + return m_value_active; + } -/// _AP = Has 'Active' and 'Pending' fields -template class GVarStr_AP: public GVarStr_A -{ -public: - GVarStr_AP(const char* name, const char* conf, const char* active_val, const char* pending_val): - GVarStr_A(name, conf, active_val), m_value_pending(pending_val) - {} + virtual void SetActive(const char *val) + { + if (val != m_value_active) + { + GVarBase::LogSetActive(val, m_value_active); + m_value_active = val; + } + } - virtual ~GVarStr_AP() {} + inline bool IsActiveEmpty() const + { + return m_value_active.IsEmpty(); + } - inline const char* GetPending() const - { - return m_value_pending; - } + protected: + Str m_value_active; + }; - inline bool IsPendingEmpty() const + /// _AP = Has 'Active' and 'Pending' fields + template class GVarStr_AP : public GVarStr_A { - return m_value_pending.IsEmpty(); - } + public: + GVarStr_AP(const char *name, const char *conf, const char *active_val, const char *pending_val) + : GVarStr_A(name, conf, active_val), m_value_pending(pending_val) + { + } - void SetPending(const char* val) - { - if (val != m_value_pending) + virtual ~GVarStr_AP() { - if(GVarStr_A::name != "mp_player_token") - GVarBase::LogSetPending(val, m_value_pending); - m_value_pending = val; } - } - virtual void SetActive(const char* val) override - { - if ((val != GVarStr_A::m_value_active) || (val != m_value_pending)) + inline const char *GetPending() const { - if(GVarStr_A::name != "mp_player_token") - GVarBase::LogSetActive(val, GVarStr_A::m_value_active); - GVarStr_A::m_value_active = val; - m_value_pending = val; + return m_value_pending; } - } - void ApplyPending() - { - if (GVarStr_A::m_value_active != m_value_pending) + inline bool IsPendingEmpty() const { - if(GVarStr_A::name != "mp_player_token") - GVarBase::LogApplyPending(m_value_pending, GVarStr_A::m_value_active); - GVarStr_A::m_value_active.Assign(m_value_pending); + return m_value_pending.IsEmpty(); } - } - void ResetPending() - { - if (GVarStr_A::m_value_active != m_value_pending) + void SetPending(const char *val) { - if(GVarStr_A::name != "mp_player_token") - GVarBase::LogResetPending(m_value_pending, GVarStr_A::m_value_active); - m_value_pending.Assign(GVarStr_A::m_value_active); + if (val != m_value_pending) + { + if (GVarStr_A::name != "mp_player_token") GVarBase::LogSetPending(val, m_value_pending); + m_value_pending = val; + } } - } -protected: - Str m_value_pending; -}; + virtual void SetActive(const char *val) override + { + if ((val != GVarStr_A::m_value_active) || (val != m_value_pending)) + { + if (GVarStr_A::name != "mp_player_token") GVarBase::LogSetActive(val, GVarStr_A::m_value_active); + GVarStr_A::m_value_active = val; + m_value_pending = val; + } + } + void ApplyPending() + { + if (GVarStr_A::m_value_active != m_value_pending) + { + if (GVarStr_A::name != "mp_player_token") + GVarBase::LogApplyPending(m_value_pending, GVarStr_A::m_value_active); + GVarStr_A::m_value_active.Assign(m_value_pending); + } + } -/// _APS = Has 'Active, Pending, Stored' fields -template class GVarStr_APS: public GVarStr_AP -{ -public: - GVarStr_APS(const char* name, const char* conf, const char* active_val, const char* pending_val, const char* stored_val): - GVarStr_AP(name, conf, active_val, pending_val), m_value_stored(stored_val) - {} + void ResetPending() + { + if (GVarStr_A::m_value_active != m_value_pending) + { + if (GVarStr_A::name != "mp_player_token") + GVarBase::LogResetPending(m_value_pending, GVarStr_A::m_value_active); + m_value_pending.Assign(GVarStr_A::m_value_active); + } + } - virtual ~GVarStr_APS() {} + protected: + Str m_value_pending; + }; - virtual const char* GetStored() const override + /// _APS = Has 'Active, Pending, Stored' fields + template class GVarStr_APS : public GVarStr_AP { - return m_value_stored; - } + public: + GVarStr_APS(const char *name, const char *conf, const char *active_val, const char *pending_val, const char *stored_val) + : GVarStr_AP(name, conf, active_val, pending_val), m_value_stored(stored_val) + { + } - void SetStored(const char* val) - { - if (val != m_value_stored) + virtual ~GVarStr_APS() { - GVarBase::LogSetStored(val, m_value_stored); - m_value_stored = val; } - } -protected: - Str m_value_stored; -}; - - -namespace App { - - -// App -extern GVarEnum_AP app_state; -extern GVarStr_A<50> app_language; -extern GVarStr_A<50> app_country; -extern GVarPod_A app_skip_main_menu; -extern GVarPod_APS app_async_physics; -extern GVarPod_APS app_num_workers; -extern GVarStr_AP<50> app_screenshot_format; -extern GVarStr_A<100> app_rendersys_override; -extern GVarStr_A<300> app_extra_mod_path; -extern GVarPod_A app_force_cache_purge; -extern GVarPod_A app_force_cache_udpate; -extern GVarPod_A app_disable_online_api; - -// Simulation -extern GVarEnum_AP sim_state; -extern GVarStr_AP<200> sim_terrain_name; -extern GVarStr_AP<300> sim_terrain_gui_name; -extern GVarStr_A<100> sim_savegame; -extern GVarPod_A sim_load_savegame; -extern GVarPod_A sim_spawn_running; -extern GVarPod_A sim_replay_enabled; -extern GVarPod_A sim_replay_length; -extern GVarPod_A sim_replay_stepping; -extern GVarPod_A sim_realistic_commands; -extern GVarPod_A sim_races_enabled; -extern GVarPod_A sim_no_collisions; -extern GVarPod_A sim_no_self_collisions; -extern GVarEnum_AP sim_gearbox_mode; - -// Multiplayer -extern GVarEnum_AP mp_state; -extern GVarPod_APS mp_join_on_startup; -extern GVarPod_A mp_chat_auto_hide; -extern GVarPod_A mp_hide_net_labels; -extern GVarPod_A mp_hide_own_net_label; -extern GVarPod_A mp_pseudo_collisions; -extern GVarStr_AP<200> mp_server_host; -extern GVarPod_A mp_server_port; -extern GVarStr_APS<100> mp_server_password; -extern GVarStr_AP<100> mp_player_name; -extern GVarStr_AP<100> mp_player_token; -extern GVarStr_A<100> mp_api_url; - -// Diagnostic -extern GVarPod_A diag_auto_spawner_report; -extern GVarPod_A diag_camera; -extern GVarPod_A diag_trace_globals; -extern GVarPod_A diag_rig_log_node_import; -extern GVarPod_A diag_rig_log_node_stats; -extern GVarPod_A diag_rig_log_messages; -extern GVarPod_A diag_collisions; -extern GVarPod_A diag_truck_mass; -extern GVarPod_A diag_envmap; -extern GVarPod_A diag_videocameras; -extern GVarStr_APS<100> diag_preset_terrain; -extern GVarStr_A<100> diag_preset_spawn_pos; -extern GVarStr_A<100> diag_preset_spawn_rot; -extern GVarStr_APS<100> diag_preset_vehicle; -extern GVarStr_A<100> diag_preset_veh_config; -extern GVarPod_APS diag_preset_veh_enter; -extern GVarPod_A diag_log_console_echo; -extern GVarPod_A diag_log_beam_break; -extern GVarPod_A diag_log_beam_deform; -extern GVarPod_A diag_log_beam_trigger; -extern GVarPod_A diag_simple_materials; -extern GVarPod_A diag_warning_texture; -extern GVarPod_A diag_hide_broken_beams; -extern GVarPod_A diag_hide_beam_stress; -extern GVarPod_A diag_hide_wheel_info; -extern GVarPod_A diag_hide_wheels; -extern GVarPod_A diag_hide_nodes; -extern GVarPod_A diag_physics_dt; - -// System -extern GVarStr_A<300> sys_process_dir; -extern GVarStr_A<300> sys_user_dir; -extern GVarStr_A<300> sys_config_dir; -extern GVarStr_A<300> sys_cache_dir; -extern GVarStr_A<300> sys_logs_dir; -extern GVarStr_A<300> sys_resources_dir; -extern GVarStr_A<300> sys_profiler_dir; -extern GVarStr_A<300> sys_savegames_dir; -extern GVarStr_A<300> sys_screenshot_dir; - -// Input - Output -extern GVarPod_A io_analog_smoothing; -extern GVarPod_A io_analog_sensitivity; -extern GVarPod_A io_ffb_enabled; -extern GVarPod_A io_ffb_camera_gain; -extern GVarPod_A io_ffb_center_gain; -extern GVarPod_A io_ffb_master_gain; -extern GVarPod_A io_ffb_stress_gain; -extern GVarEnum_AP io_input_grab_mode; -extern GVarPod_A io_arcade_controls; -extern GVarPod_A io_outgauge_mode; -extern GVarStr_A<50> io_outgauge_ip; -extern GVarPod_A io_outgauge_port; -extern GVarPod_A io_outgauge_delay; -extern GVarPod_A io_outgauge_id; -extern GVarPod_A io_discord_rpc; - -// Audio -extern GVarPod_A audio_master_volume; -extern GVarPod_A audio_enable_creak; -extern GVarStr_AP<100> audio_device_name; -extern GVarPod_A audio_menu_music; - -// Graphics -extern GVarEnum_AP gfx_flares_mode; -extern GVarEnum_AP gfx_shadow_type; -extern GVarEnum_AP gfx_extcam_mode; -extern GVarEnum_AP gfx_sky_mode; -extern GVarEnum_AP gfx_texture_filter; -extern GVarEnum_AP gfx_vegetation_mode; -extern GVarEnum_AP gfx_water_mode; -extern GVarPod_A gfx_anisotropy; -extern GVarPod_A gfx_water_waves; -extern GVarPod_A gfx_particles_mode; -extern GVarPod_A gfx_enable_videocams; -extern GVarPod_A gfx_window_videocams; -extern GVarPod_APS gfx_surveymap_icons; -extern GVarPod_A gfx_declutter_map; -extern GVarPod_A gfx_envmap_enabled; -extern GVarPod_A gfx_envmap_rate; -extern GVarPod_A gfx_shadow_quality; -extern GVarPod_A gfx_skidmarks_mode; -extern GVarPod_A gfx_sight_range; -extern GVarPod_A gfx_camera_height; -extern GVarPod_APS gfx_fov_external; -extern GVarPod_APS gfx_fov_internal; -extern GVarPod_A gfx_static_cam_fov_exp; -extern GVarPod_A gfx_fixed_cam_tracking; -extern GVarPod_A gfx_fps_limit; -extern GVarPod_A gfx_speedo_digital; -extern GVarPod_A gfx_speedo_imperial; -extern GVarPod_A gfx_flexbody_lods; -extern GVarPod_A gfx_flexbody_cache; -extern GVarPod_A gfx_reduce_shadows; -extern GVarPod_A gfx_enable_rtshaders; - -// Getters -OgreSubsystem* GetOgreSubsystem(); -ContentManager* GetContentManager(); -OverlayWrapper* GetOverlayWrapper(); -GUIManager* GetGuiManager(); -Console* GetConsole(); -InputEngine* GetInputEngine(); -CacheSystem* GetCacheSystem(); -MainMenu* GetMainMenu(); -SimController* GetSimController(); -MumbleIntegration* GetMumble(); -TerrainManager* GetSimTerrain(); - -// Factories -void StartOgreSubsystem(); -void ShutdownOgreSubsystem(); -void CreateOverlayWrapper(); -void DestroyOverlayWrapper(); -void CreateGuiManagerIfNotExists(); -void DeleteGuiManagerIfExists(); -void CreateInputEngine(); -void CheckAndCreateMumble(); - -// Setters -void SetMainMenu (MainMenu* obj); -void SetSimController (SimController* obj); -void SetSimTerrain (TerrainManager* obj); -void SetCacheSystem (CacheSystem* obj); - - -} // namespace App -} // namespace RoR + virtual const char *GetStored() const override + { + return m_value_stored; + } + + void SetStored(const char *val) + { + if (val != m_value_stored) + { + GVarBase::LogSetStored(val, m_value_stored); + m_value_stored = val; + } + } + + protected: + Str m_value_stored; + }; + + namespace App + { -inline void LOG(const char* msg) { RoR::Log(msg); } ///< Legacy alias - formerly a macro -inline void LOG(std::string const & msg) { RoR::Log(msg.c_str()); } ///< Legacy alias - formerly a macro + // App + extern GVarEnum_AP app_state; + extern GVarStr_A<50> app_language; + extern GVarStr_A<50> app_country; + extern GVarPod_A app_skip_main_menu; + extern GVarPod_APS app_async_physics; + extern GVarPod_APS app_num_workers; + extern GVarStr_AP<50> app_screenshot_format; + extern GVarStr_A<100> app_rendersys_override; + extern GVarStr_A<300> app_extra_mod_path; + extern GVarPod_A app_force_cache_purge; + extern GVarPod_A app_force_cache_udpate; + extern GVarPod_A app_disable_online_api; + + // Simulation + extern GVarEnum_AP sim_state; + extern GVarStr_AP<200> sim_terrain_name; + extern GVarStr_AP<300> sim_terrain_gui_name; + extern GVarStr_A<100> sim_savegame; + extern GVarPod_A sim_load_savegame; + extern GVarPod_A sim_spawn_running; + extern GVarPod_A sim_replay_enabled; + extern GVarPod_A sim_replay_length; + extern GVarPod_A sim_replay_stepping; + extern GVarPod_A sim_realistic_commands; + extern GVarPod_A sim_races_enabled; + extern GVarPod_A sim_no_collisions; + extern GVarPod_A sim_no_self_collisions; + extern GVarEnum_AP sim_gearbox_mode; + + // Multiplayer + extern GVarEnum_AP mp_state; + extern GVarPod_APS mp_join_on_startup; + extern GVarPod_A mp_chat_auto_hide; + extern GVarPod_A mp_hide_net_labels; + extern GVarPod_A mp_hide_own_net_label; + extern GVarPod_A mp_pseudo_collisions; + extern GVarStr_AP<200> mp_server_host; + extern GVarPod_A mp_server_port; + extern GVarStr_APS<100> mp_server_password; + extern GVarStr_AP<100> mp_player_name; + extern GVarStr_AP<100> mp_player_token; + extern GVarStr_A<100> mp_api_url; + + // Diagnostic + extern GVarPod_A diag_auto_spawner_report; + extern GVarPod_A diag_camera; + extern GVarPod_A diag_trace_globals; + extern GVarPod_A diag_rig_log_node_import; + extern GVarPod_A diag_rig_log_node_stats; + extern GVarPod_A diag_rig_log_messages; + extern GVarPod_A diag_collisions; + extern GVarPod_A diag_truck_mass; + extern GVarPod_A diag_envmap; + extern GVarPod_A diag_videocameras; + extern GVarStr_APS<100> diag_preset_terrain; + extern GVarStr_A<100> diag_preset_spawn_pos; + extern GVarStr_A<100> diag_preset_spawn_rot; + extern GVarStr_APS<100> diag_preset_vehicle; + extern GVarStr_A<100> diag_preset_veh_config; + extern GVarPod_APS diag_preset_veh_enter; + extern GVarPod_A diag_log_console_echo; + extern GVarPod_A diag_log_beam_break; + extern GVarPod_A diag_log_beam_deform; + extern GVarPod_A diag_log_beam_trigger; + extern GVarPod_A diag_simple_materials; + extern GVarPod_A diag_warning_texture; + extern GVarPod_A diag_hide_broken_beams; + extern GVarPod_A diag_hide_beam_stress; + extern GVarPod_A diag_hide_wheel_info; + extern GVarPod_A diag_hide_wheels; + extern GVarPod_A diag_hide_nodes; + extern GVarPod_A diag_physics_dt; + + // System + extern GVarStr_A<300> sys_process_dir; + extern GVarStr_A<300> sys_user_dir; + extern GVarStr_A<300> sys_config_dir; + extern GVarStr_A<300> sys_cache_dir; + extern GVarStr_A<300> sys_logs_dir; + extern GVarStr_A<300> sys_resources_dir; + extern GVarStr_A<300> sys_profiler_dir; + extern GVarStr_A<300> sys_savegames_dir; + extern GVarStr_A<300> sys_screenshot_dir; + + // Input - Output + extern GVarPod_A io_analog_smoothing; + extern GVarPod_A io_analog_sensitivity; + extern GVarPod_A io_ffb_enabled; + extern GVarPod_A io_ffb_camera_gain; + extern GVarPod_A io_ffb_center_gain; + extern GVarPod_A io_ffb_master_gain; + extern GVarPod_A io_ffb_stress_gain; + extern GVarEnum_AP io_input_grab_mode; + extern GVarPod_A io_arcade_controls; + extern GVarPod_A io_outgauge_mode; + extern GVarStr_A<50> io_outgauge_ip; + extern GVarPod_A io_outgauge_port; + extern GVarPod_A io_outgauge_delay; + extern GVarPod_A io_outgauge_id; + extern GVarPod_A io_discord_rpc; + + // Audio + extern GVarPod_A audio_master_volume; + extern GVarPod_A audio_enable_creak; + extern GVarStr_AP<100> audio_device_name; + extern GVarPod_A audio_menu_music; + + // Graphics + extern GVarEnum_AP gfx_flares_mode; + extern GVarEnum_AP gfx_shadow_type; + extern GVarEnum_AP gfx_extcam_mode; + extern GVarEnum_AP gfx_sky_mode; + extern GVarEnum_AP gfx_texture_filter; + extern GVarEnum_AP gfx_vegetation_mode; + extern GVarEnum_AP gfx_water_mode; + extern GVarPod_A gfx_anisotropy; + extern GVarPod_A gfx_water_waves; + extern GVarPod_A gfx_particles_mode; + extern GVarPod_A gfx_enable_videocams; + extern GVarPod_A gfx_window_videocams; + extern GVarPod_APS gfx_surveymap_icons; + extern GVarPod_A gfx_declutter_map; + extern GVarPod_A gfx_envmap_enabled; + extern GVarPod_A gfx_envmap_rate; + extern GVarPod_A gfx_shadow_quality; + extern GVarPod_A gfx_skidmarks_mode; + extern GVarPod_A gfx_sight_range; + extern GVarPod_A gfx_camera_height; + extern GVarPod_APS gfx_fov_external; + extern GVarPod_APS gfx_fov_internal; + extern GVarPod_A gfx_static_cam_fov_exp; + extern GVarPod_A gfx_fixed_cam_tracking; + extern GVarPod_A gfx_fps_limit; + extern GVarPod_A gfx_speedo_digital; + extern GVarPod_A gfx_speedo_imperial; + extern GVarPod_A gfx_flexbody_lods; + extern GVarPod_A gfx_flexbody_cache; + extern GVarPod_A gfx_reduce_shadows; + extern GVarPod_A gfx_enable_rtshaders; + + // Getters + OgreSubsystem * GetOgreSubsystem(); + ContentManager * GetContentManager(); + OverlayWrapper * GetOverlayWrapper(); + GUIManager * GetGuiManager(); + Console * GetConsole(); + InputEngine * GetInputEngine(); + CacheSystem * GetCacheSystem(); + MainMenu * GetMainMenu(); + SimController * GetSimController(); + MumbleIntegration *GetMumble(); + TerrainManager * GetSimTerrain(); + + // Factories + void StartOgreSubsystem(); + void ShutdownOgreSubsystem(); + void CreateOverlayWrapper(); + void DestroyOverlayWrapper(); + void CreateGuiManagerIfNotExists(); + void DeleteGuiManagerIfExists(); + void CreateInputEngine(); + void CheckAndCreateMumble(); + + // Setters + void SetMainMenu(MainMenu *obj); + void SetSimController(SimController *obj); + void SetSimTerrain(TerrainManager *obj); + void SetCacheSystem(CacheSystem *obj); + + } // namespace App +} // namespace RoR +inline void LOG(const char *msg) +{ + RoR::Log(msg); +} ///< Legacy alias - formerly a macro +inline void LOG(std::string const &msg) +{ + RoR::Log(msg.c_str()); +} ///< Legacy alias - formerly a macro diff --git a/source/main/CMakeLists.txt b/source/main/CMakeLists.txt index 2bced2749d..9706b0e8a9 100644 --- a/source/main/CMakeLists.txt +++ b/source/main/CMakeLists.txt @@ -448,10 +448,10 @@ if (USE_PACKAGE_MANAGER) ) if (UNIX) - set(CFG_OGRE_PLUGIN_CAELUM "Plugin=libCaelum.so") + set(CFG_OGRE_PLUGIN_CAELUM "Plugin=libCaelum.so") set(CFG_OGRE_PLUGIN_CAELUM_D "Plugin=libCaelum_d.so") else () - set(CFG_OGRE_PLUGIN_CAELUM "Plugin=Caelum") + set(CFG_OGRE_PLUGIN_CAELUM "Plugin=Caelum") set(CFG_OGRE_PLUGIN_CAELUM_D "Plugin=Caelum_d") endif () @@ -510,7 +510,7 @@ else (USE_PACKAGE_MANAGER) endif () if (TARGET Caelum::Caelum) - set(CFG_OGRE_PLUGIN_CAELUM "Plugin=../libCaelum.so") + set(CFG_OGRE_PLUGIN_CAELUM "Plugin=../libCaelum.so") set(CFG_OGRE_PLUGIN_CAELUM_D "Plugin=../libCaelum_d.so") target_link_libraries(${BINNAME} PRIVATE Caelum::Caelum) target_compile_definitions(${BINNAME} PRIVATE USE_CAELUM) @@ -542,7 +542,7 @@ else () set(PLUGINS_FOLDER ${OGRE_PLUGIN_DIR}) endif () -configure_file(plugins.cfg.in ${RUNTIME_OUTPUT_DIRECTORY}/plugins.cfg) +configure_file(plugins.cfg.in ${RUNTIME_OUTPUT_DIRECTORY}/plugins.cfg) configure_file(plugins_d.cfg.in ${RUNTIME_OUTPUT_DIRECTORY}/plugins_d.cfg) diff --git a/source/main/ForwardDeclarations.h b/source/main/ForwardDeclarations.h index 62671ba5d1..d140335a8e 100644 --- a/source/main/ForwardDeclarations.h +++ b/source/main/ForwardDeclarations.h @@ -19,65 +19,63 @@ along with Rigs of Rods. If not, see . */ - /// @file ForwardDeclarations.h /// @brief Global forward declarations. /// @author Petr Ohlidal /// @date 12/2013 - #pragma once namespace RoR { - class ActorManager; - class CameraManager; - class ConfigFile; - class Console; - class ContentManager; - class FlexBodyFileIO; + class ActorManager; + class CameraManager; + class ConfigFile; + class Console; + class ContentManager; + class FlexBodyFileIO; struct FlexBodyCacheData; - class FlexFactory; - class GfxActor; + class FlexFactory; + class GfxActor; struct GfxCharacter; - class GfxScene; - class GUIManager; + class GfxScene; + class GUIManager; struct GuiManagerImpl; - class GuiManagerInterface; - class MainMenu; - class OgreSubsystem; + class GuiManagerInterface; + class MainMenu; + class OgreSubsystem; struct PlatformUtils; - class Renderdash; - class RigLoadingProfiler; - class SceneMouse; - class Skidmark; - class SkidmarkConfig; + class Renderdash; + class RigLoadingProfiler; + class SceneMouse; + class Skidmark; + class SkidmarkConfig; struct SkinDef; - class SkinManager; + class SkinManager; struct Terrn2Author; struct Terrn2Def; - class Terrn2Parser; + class Terrn2Parser; struct Terrn2Telepoint; namespace GUI { - class Dialog; - class FrictionSettings; - class GameMainMenu; - class GamePauseMenu; - class LoadingWindow; - class MainSelector; - class MpClientList; - class MultiplayerSelector; - class OpenSaveFileDialog; - class SimUtils; - class TopMenubar; - } + class Dialog; + class FrictionSettings; + class GameMainMenu; + class GamePauseMenu; + class LoadingWindow; + class MainSelector; + class MpClientList; + class MultiplayerSelector; + class OpenSaveFileDialog; + class SimUtils; + class TopMenubar; + } // namespace GUI } // namespace RoR namespace MyGUI { - class OgrePlatform; + class OgrePlatform; } namespace RoRnet @@ -88,7 +86,7 @@ namespace RoRnet struct ActorStreamRegister; struct ServerInfo; struct VehicleState; -} +} // namespace RoRnet struct node_t; struct beam_t; @@ -127,7 +125,7 @@ namespace Ogre class Overlay; class RenderTarget; class TerrainGroup; -} +} // namespace Ogre class Actor; class ActorSpawner; diff --git a/source/main/GlobalEnvironment.h b/source/main/GlobalEnvironment.h index 7d105f7b6a..21871aaf98 100644 --- a/source/main/GlobalEnvironment.h +++ b/source/main/GlobalEnvironment.h @@ -25,23 +25,16 @@ class GlobalEnvironment { -public: - - GlobalEnvironment() : - collisions(0) - , mainCamera(0) - , player(0) - , sceneManager(0) - , SkyX(0) - , threadPool(0) - , mrTime(0.f) - {} - - Ogre::Camera* mainCamera; - Ogre::SceneManager* sceneManager; - Character* player; - Collisions* collisions; - SkyXManager* SkyX; - ThreadPool* threadPool; + public: + GlobalEnvironment() : collisions(0), mainCamera(0), player(0), sceneManager(0), SkyX(0), threadPool(0), mrTime(0.f) + { + } + + Ogre::Camera * mainCamera; + Ogre::SceneManager *sceneManager; + Character * player; + Collisions * collisions; + SkyXManager * SkyX; + ThreadPool * threadPool; float mrTime; }; diff --git a/source/main/MainMenu.cpp b/source/main/MainMenu.cpp index 4ea8d66814..6611caa5f4 100644 --- a/source/main/MainMenu.cpp +++ b/source/main/MainMenu.cpp @@ -19,12 +19,10 @@ along with Rigs of Rods. If not, see . */ - /// @file /// @author Petr Ohlidal /// @date 05/2014 - #include "MainMenu.h" #include "ChatSystem.h" @@ -36,338 +34,291 @@ #include "GUI_MultiplayerSelector.h" #include "InputEngine.h" #include "Language.h" - #include "OgreSubsystem.h" #include "OverlayWrapper.h" #ifdef USE_ANGELSCRIPT -# include "ScriptEngine.h" + #include "ScriptEngine.h" #endif #include -namespace RoR { - -MainMenu::MainMenu() +namespace RoR { - RoR::App::SetMainMenu(this); -} -void MainMenu::EnterMainMenuLoop() -{ - OgreBites::WindowEventUtilities::addWindowEventListener(App::GetOgreSubsystem()->GetRenderWindow(), this); - - App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(this); - - auto start_time = std::chrono::high_resolution_clock::now(); + MainMenu::MainMenu() + { + RoR::App::SetMainMenu(this); + } - while (App::app_state.GetPending() == AppState::MAIN_MENU) + void MainMenu::EnterMainMenuLoop() { - // Check FPS limit - if (App::gfx_fps_limit.GetActive() > 0) + OgreBites::WindowEventUtilities::addWindowEventListener(App::GetOgreSubsystem()->GetRenderWindow(), this); + + App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(this); + + auto start_time = std::chrono::high_resolution_clock::now(); + + while (App::app_state.GetPending() == AppState::MAIN_MENU) { - const float min_frame_time = 1.0f / Ogre::Math::Clamp(App::gfx_fps_limit.GetActive(), 60, 240); - float dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); - while (dt < min_frame_time) + // Check FPS limit + if (App::gfx_fps_limit.GetActive() > 0) { - int ms = static_cast((min_frame_time - dt) * 1000.0f); - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); + const float min_frame_time = 1.0f / Ogre::Math::Clamp(App::gfx_fps_limit.GetActive(), 60, 240); + float dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); + while (dt < min_frame_time) + { + int ms = static_cast((min_frame_time - dt) * 1000.0f); + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); + } } - } - const auto now = std::chrono::high_resolution_clock::now(); - const float dt_sec = std::chrono::duration(now - start_time).count(); - start_time = now; + const auto now = std::chrono::high_resolution_clock::now(); + const float dt_sec = std::chrono::duration(now - start_time).count(); + start_time = now; - this->MainMenuLoopUpdate(dt_sec); + this->MainMenuLoopUpdate(dt_sec); - if (RoR::App::GetGuiManager()->GetMainSelector()->IsFinishedSelecting()) - { - if (RoR::App::GetGuiManager()->GetMainSelector()->GetSelectedEntry() != nullptr) + if (RoR::App::GetGuiManager()->GetMainSelector()->IsFinishedSelecting()) { - App::app_state.SetPending(AppState::SIMULATION); - App::sim_terrain_name.SetPending(""); + if (RoR::App::GetGuiManager()->GetMainSelector()->GetSelectedEntry() != nullptr) + { + App::app_state.SetPending(AppState::SIMULATION); + App::sim_terrain_name.SetPending(""); + } } - } #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_LINUX - OgreBites::WindowEventUtilities::messagePump(); + OgreBites::WindowEventUtilities::messagePump(); #endif - Ogre::RenderWindow* rw = RoR::App::GetOgreSubsystem()->GetRenderWindow(); - if (rw->isClosed()) - { - App::app_state.SetPending(AppState::SHUTDOWN); - continue; - } + Ogre::RenderWindow *rw = RoR::App::GetOgreSubsystem()->GetRenderWindow(); + if (rw->isClosed()) + { + App::app_state.SetPending(AppState::SHUTDOWN); + continue; + } - App::GetGuiManager()->NewImGuiFrame(dt_sec); - App::GetGuiManager()->DrawMainMenuGui(); + App::GetGuiManager()->NewImGuiFrame(dt_sec); + App::GetGuiManager()->DrawMainMenuGui(); - App::GetOgreSubsystem()->GetOgreRoot()->renderOneFrame(); + App::GetOgreSubsystem()->GetOgreRoot()->renderOneFrame(); - if (!rw->isActive() && rw->isVisible()) - rw->update(); // update even when in background ! + if (!rw->isActive() && rw->isVisible()) rw->update(); // update even when in background ! + } + OgreBites::WindowEventUtilities::removeWindowEventListener(App::GetOgreSubsystem()->GetRenderWindow(), this); + App::GetOgreSubsystem()->GetOgreRoot()->removeFrameListener(this); } - OgreBites::WindowEventUtilities::removeWindowEventListener(App::GetOgreSubsystem()->GetRenderWindow(), this); - App::GetOgreSubsystem()->GetOgreRoot()->removeFrameListener(this); -} -void MainMenu::MainMenuLoopUpdate(float seconds_since_last_frame) -{ - if (RoR::App::GetOgreSubsystem()->GetRenderWindow()->isClosed()) + void MainMenu::MainMenuLoopUpdate(float seconds_since_last_frame) { - App::app_state.SetPending(AppState::SHUTDOWN); - return; - } + if (RoR::App::GetOgreSubsystem()->GetRenderWindow()->isClosed()) + { + App::app_state.SetPending(AppState::SHUTDOWN); + return; + } #ifdef USE_SOCKETW - if (App::mp_state.GetPending() == MpState::CONNECTED && - App::mp_state.GetActive() == MpState::DISABLED) - { - Networking::StartConnecting(); - } + if (App::mp_state.GetPending() == MpState::CONNECTED && App::mp_state.GetActive() == MpState::DISABLED) + { Networking::StartConnecting(); } - Networking::NetEventQueue events = Networking::CheckEvents(); - while (!events.empty()) - { - switch (events.front().type) + Networking::NetEventQueue events = Networking::CheckEvents(); + while (!events.empty()) { - case Networking::NetEvent::Type::SERVER_KICK: - this->LeaveMultiplayerServer(); - App::GetGuiManager()->ShowMessageBox( - _LC("Network", "Network disconnected"), events.front().message.c_str()); - break; - - case Networking::NetEvent::Type::RECV_ERROR: - this->LeaveMultiplayerServer(); - App::GetGuiManager()->ShowMessageBox( - _L("Network fatal error: "), events.front().message.c_str()); - break; - - case Networking::NetEvent::Type::CONNECT_STARTED: - App::GetGuiManager()->SetMpConnectingStatusMsg(events.front().message.c_str()); - App::GetGuiManager()->SetVisible_GameMainMenu(false); - App::GetGuiManager()->SetVisible_MultiplayerSelector(false); - break; - - case Networking::NetEvent::Type::CONNECT_PROGRESS: - App::GetGuiManager()->SetMpConnectingStatusMsg(events.front().message.c_str()); - break; - - case Networking::NetEvent::Type::CONNECT_SUCCESS: - App::mp_state.SetActive(RoR::MpState::CONNECTED); - App::GetGuiManager()->SetVisible_MpClientList(true); - App::GetGuiManager()->GetMpClientList()->update(); - ChatSystem::SendStreamSetup(); - App::CheckAndCreateMumble(); - if (Networking::GetTerrainName() != "any") - { - App::sim_terrain_name.SetPending(Networking::GetTerrainName().c_str()); - App::app_state.SetPending(AppState::SIMULATION); - } - else + switch (events.front().type) { - // Connected -> go directly to map selector - if (App::diag_preset_terrain.IsActiveEmpty()) + case Networking::NetEvent::Type::SERVER_KICK: + this->LeaveMultiplayerServer(); + App::GetGuiManager()->ShowMessageBox(_LC("Network", "Network disconnected"), events.front().message.c_str()); + break; + + case Networking::NetEvent::Type::RECV_ERROR: + this->LeaveMultiplayerServer(); + App::GetGuiManager()->ShowMessageBox(_L("Network fatal error: "), events.front().message.c_str()); + break; + + case Networking::NetEvent::Type::CONNECT_STARTED: + App::GetGuiManager()->SetMpConnectingStatusMsg(events.front().message.c_str()); + App::GetGuiManager()->SetVisible_GameMainMenu(false); + App::GetGuiManager()->SetVisible_MultiplayerSelector(false); + break; + + case Networking::NetEvent::Type::CONNECT_PROGRESS: + App::GetGuiManager()->SetMpConnectingStatusMsg(events.front().message.c_str()); + break; + + case Networking::NetEvent::Type::CONNECT_SUCCESS: + App::mp_state.SetActive(RoR::MpState::CONNECTED); + App::GetGuiManager()->SetVisible_MpClientList(true); + App::GetGuiManager()->GetMpClientList()->update(); + ChatSystem::SendStreamSetup(); + App::CheckAndCreateMumble(); + if (Networking::GetTerrainName() != "any") { - App::GetGuiManager()->GetMainSelector()->Reset(); - App::GetGuiManager()->GetMainSelector()->Show(LT_Terrain); + App::sim_terrain_name.SetPending(Networking::GetTerrainName().c_str()); + App::app_state.SetPending(AppState::SIMULATION); } else { - App::app_state.SetPending(AppState::SIMULATION); + // Connected -> go directly to map selector + if (App::diag_preset_terrain.IsActiveEmpty()) + { + App::GetGuiManager()->GetMainSelector()->Reset(); + App::GetGuiManager()->GetMainSelector()->Show(LT_Terrain); + } + else + { + App::app_state.SetPending(AppState::SIMULATION); + } } - } - break; + break; - case Networking::NetEvent::Type::CONNECT_FAILURE: - App::mp_state.SetActive(RoR::MpState::DISABLED); - App::GetGuiManager()->ShowMessageBox( - _LC("Network", "Multiplayer: connection failed"), events.front().message.c_str()); - App::GetGuiManager()->ReflectGameState(); - break; + case Networking::NetEvent::Type::CONNECT_FAILURE: + App::mp_state.SetActive(RoR::MpState::DISABLED); + App::GetGuiManager()->ShowMessageBox(_LC("Network", "Multiplayer: connection failed"), + events.front().message.c_str()); + App::GetGuiManager()->ReflectGameState(); + break; - - default:; + default:; + } + events.pop(); } - events.pop(); - } - if (App::mp_state.GetActive() == MpState::CONNECTED) - { - App::GetGuiManager()->GetMpClientList()->update(); - } + if (App::mp_state.GetActive() == MpState::CONNECTED) { App::GetGuiManager()->GetMpClientList()->update(); } - if (App::GetGuiManager()->GetMpSelector()->IsRefreshThreadRunning()) - { - App::GetGuiManager()->GetMpSelector()->CheckAndProcessRefreshResult(); - } + if (App::GetGuiManager()->GetMpSelector()->IsRefreshThreadRunning()) + { App::GetGuiManager()->GetMpSelector()->CheckAndProcessRefreshResult(); } #endif // USE_SOCKETW - if (App::app_force_cache_udpate.GetActive() || App::app_force_cache_purge.GetActive()) - { - if (App::GetGuiManager()->IsVisible_GameSettings()) + if (App::app_force_cache_udpate.GetActive() || App::app_force_cache_purge.GetActive()) { - App::GetGuiManager()->SetVisible_GameSettings(false); - App::GetGuiManager()->SetMouseCursorVisibility(GUIManager::MouseCursorVisibility::HIDDEN); - } - else - { - App::GetContentManager()->InitModCache(); - App::GetGuiManager()->SetVisible_GameMainMenu(true); + if (App::GetGuiManager()->IsVisible_GameSettings()) + { + App::GetGuiManager()->SetVisible_GameSettings(false); + App::GetGuiManager()->SetMouseCursorVisibility(GUIManager::MouseCursorVisibility::HIDDEN); + } + else + { + App::GetContentManager()->InitModCache(); + App::GetGuiManager()->SetVisible_GameMainMenu(true); + } } - } - RoR::App::GetInputEngine()->Capture(); + RoR::App::GetInputEngine()->Capture(); - MainMenuLoopUpdateEvents(seconds_since_last_frame); + MainMenuLoopUpdateEvents(seconds_since_last_frame); #ifdef USE_ANGELSCRIPT - ScriptEngine::getSingleton().framestep(seconds_since_last_frame); + ScriptEngine::getSingleton().framestep(seconds_since_last_frame); #endif -} - -void MainMenu::MainMenuLoopUpdateEvents(float seconds_since_last_frame) -{ - RoR::App::GetInputEngine()->updateKeyBounces(seconds_since_last_frame); - - if (! RoR::App::GetInputEngine()->getInputsChanged()) - { - return; } - if (RoR::App::GetOverlayWrapper() != nullptr) + void MainMenu::MainMenuLoopUpdateEvents(float seconds_since_last_frame) { - RoR::App::GetOverlayWrapper()->update(seconds_since_last_frame); // TODO: What's the meaning of this? It only updates some internal timer. ~ only_a_ptr - } + RoR::App::GetInputEngine()->updateKeyBounces(seconds_since_last_frame); - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUIT_GAME)) // TODO: EV_COMMON_QUIT_GAME should really be EV_COMMON_ESCAPE ~ only_a_ptr, 12/2017 - { - if (App::GetGuiManager()->IsVisible_GameAbout()) - { - App::GetGuiManager()->SetVisible_GameAbout(false); - App::GetGuiManager()->SetVisible_GameMainMenu(true); - } - else if (App::GetGuiManager()->IsVisible_MainSelector()) - { - App::GetGuiManager()->GetMainSelector()->Cancel(); - App::GetGuiManager()->SetVisible_GameMainMenu(true); - } - else if (App::GetGuiManager()->IsVisible_GameSettings()) - { - App::GetGuiManager()->SetVisible_GameSettings(false); - App::GetGuiManager()->SetVisible_GameMainMenu(true); - } - else if (App::GetGuiManager()->IsVisible_MultiplayerSelector()) + if (!RoR::App::GetInputEngine()->getInputsChanged()) { return; } + + if (RoR::App::GetOverlayWrapper() != nullptr) { - App::GetGuiManager()->SetVisible_MultiplayerSelector(false); - App::GetGuiManager()->SetVisible_GameMainMenu(true); + RoR::App::GetOverlayWrapper()->update( + seconds_since_last_frame); // TODO: What's the meaning of this? It only updates some internal timer. ~ only_a_ptr } - else + + if (RoR::App::GetInputEngine()->getEventBoolValueBounce( + EV_COMMON_QUIT_GAME)) // TODO: EV_COMMON_QUIT_GAME should really be EV_COMMON_ESCAPE ~ only_a_ptr, 12/2017 { - App::app_state.SetPending(AppState::SHUTDOWN); + if (App::GetGuiManager()->IsVisible_GameAbout()) + { + App::GetGuiManager()->SetVisible_GameAbout(false); + App::GetGuiManager()->SetVisible_GameMainMenu(true); + } + else if (App::GetGuiManager()->IsVisible_MainSelector()) + { + App::GetGuiManager()->GetMainSelector()->Cancel(); + App::GetGuiManager()->SetVisible_GameMainMenu(true); + } + else if (App::GetGuiManager()->IsVisible_GameSettings()) + { + App::GetGuiManager()->SetVisible_GameSettings(false); + App::GetGuiManager()->SetVisible_GameMainMenu(true); + } + else if (App::GetGuiManager()->IsVisible_MultiplayerSelector()) + { + App::GetGuiManager()->SetVisible_MultiplayerSelector(false); + App::GetGuiManager()->SetVisible_GameMainMenu(true); + } + else + { + App::app_state.SetPending(AppState::SHUTDOWN); + } + return; } - return; - } - - this->HandleSavegameShortcuts(); - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_CONSOLE_TOGGLE, 5.f)) - { - App::GetGuiManager()->SetVisible_Console(!App::GetGuiManager()->IsVisible_Console()); - } + this->HandleSavegameShortcuts(); - // TODO: screenshot + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_CONSOLE_TOGGLE, 5.f)) + { App::GetGuiManager()->SetVisible_Console(!App::GetGuiManager()->IsVisible_Console()); } - // FOV settings disabled in menu + // TODO: screenshot - // FIXME: full screen/windowed screen switching - //if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_FULLSCREEN_TOGGLE, 2.0f)) {} -} + // FOV settings disabled in menu -void MainMenu::HandleSavegameShortcuts() -{ - int slot = -1; - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_01, 1.0f)) - { - slot = 1; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_02, 1.0f)) - { - slot = 2; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_03, 1.0f)) - { - slot = 3; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_04, 1.0f)) - { - slot = 4; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_05, 1.0f)) - { - slot = 5; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_06, 1.0f)) - { - slot = 6; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_07, 1.0f)) - { - slot = 7; + // FIXME: full screen/windowed screen switching + // if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_FULLSCREEN_TOGGLE, 2.0f)) {} } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_08, 1.0f)) + + void MainMenu::HandleSavegameShortcuts() { - slot = 8; + int slot = -1; + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_01, 1.0f)) { slot = 1; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_02, 1.0f)) { slot = 2; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_03, 1.0f)) { slot = 3; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_04, 1.0f)) { slot = 4; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_05, 1.0f)) { slot = 5; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_06, 1.0f)) { slot = 6; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_07, 1.0f)) { slot = 7; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_08, 1.0f)) { slot = 8; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_09, 1.0f)) { slot = 9; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_10, 1.0f)) { slot = 0; } + if (slot != -1) + { + Ogre::String filename = Ogre::StringUtil::format("quicksave-%d.sav", slot); + App::sim_savegame.SetActive(filename.c_str()); + App::sim_load_savegame.SetActive(true); + App::app_state.SetPending(AppState::SIMULATION); + } } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_09, 1.0f)) + + void MainMenu::LeaveMultiplayerServer() { - slot = 9; +#ifdef USE_SOCKETW + if (App::mp_state.GetActive() == MpState::CONNECTED) + { + RoR::Networking::Disconnect(); + App::GetGuiManager()->SetVisible_MpClientList(false); + App::GetGuiManager()->GetMainSelector()->Reset(); // We may get disconnected while still in map selection + App::GetGuiManager()->GetMainSelector()->Hide(/*smooth=*/false); + App::GetGuiManager()->SetVisible_GameMainMenu(true); + } +#endif // SOCKETW } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_10, 1.0f)) + + void MainMenu::windowResized(Ogre::RenderWindow *rw) { - slot = 0; + App::GetInputEngine()->windowResized(rw); // Update mouse area } - if (slot != -1) + + void MainMenu::windowFocusChange(Ogre::RenderWindow *rw) { - Ogre::String filename = Ogre::StringUtil::format("quicksave-%d.sav", slot); - App::sim_savegame.SetActive(filename.c_str()); - App::sim_load_savegame.SetActive(true); - App::app_state.SetPending(AppState::SIMULATION); + App::GetInputEngine()->resetKeys(); } -} -void MainMenu::LeaveMultiplayerServer() -{ -#ifdef USE_SOCKETW - if (App::mp_state.GetActive() == MpState::CONNECTED) + bool MainMenu::frameRenderingQueued(const Ogre::FrameEvent &evt) { - RoR::Networking::Disconnect(); - App::GetGuiManager()->SetVisible_MpClientList(false); - App::GetGuiManager()->GetMainSelector()->Reset(); // We may get disconnected while still in map selection - App::GetGuiManager()->GetMainSelector()->Hide(/*smooth=*/false); - App::GetGuiManager()->SetVisible_GameMainMenu(true); + App::GetGuiManager()->GetImGui().Render(); + return true; } -#endif //SOCKETW -} - -void MainMenu::windowResized(Ogre::RenderWindow* rw) -{ - App::GetInputEngine()->windowResized(rw); // Update mouse area -} - -void MainMenu::windowFocusChange(Ogre::RenderWindow* rw) -{ - App::GetInputEngine()->resetKeys(); -} - -bool MainMenu::frameRenderingQueued(const Ogre::FrameEvent & evt) -{ - App::GetGuiManager()->GetImGui().Render(); - return true; -} } // namespace RoR - - diff --git a/source/main/MainMenu.h b/source/main/MainMenu.h index 1a1ea37127..a0b0d9c4aa 100644 --- a/source/main/MainMenu.h +++ b/source/main/MainMenu.h @@ -19,8 +19,8 @@ along with Rigs of Rods. If not, see . */ -/** - +/** + @author Petr Ohlidal @date 05/2014 @brief Main menu logic. Also helps with multiplayer setup. @@ -32,32 +32,31 @@ #include -namespace RoR { - -class MainMenu: public Ogre::WindowEventListener, public Ogre::FrameListener +namespace RoR { -public: - - MainMenu(); - void LeaveMultiplayerServer(); + class MainMenu : public Ogre::WindowEventListener, public Ogre::FrameListener + { + public: + MainMenu(); - void EnterMainMenuLoop(); + void LeaveMultiplayerServer(); -private: + void EnterMainMenuLoop(); - void MainMenuLoopUpdate(float seconds_since_last_frame); + private: + void MainMenuLoopUpdate(float seconds_since_last_frame); - void MainMenuLoopUpdateEvents(float seconds_since_last_frame); + void MainMenuLoopUpdateEvents(float seconds_since_last_frame); - void HandleSavegameShortcuts(); + void HandleSavegameShortcuts(); - // From Ogre::FrameListener - bool frameRenderingQueued(const Ogre::FrameEvent & evt) override; + // From Ogre::FrameListener + bool frameRenderingQueued(const Ogre::FrameEvent &evt) override; - // Ogre::WindowEventListener - void windowResized (Ogre::RenderWindow* rw) override; - void windowFocusChange(Ogre::RenderWindow* rw) override; -}; + // Ogre::WindowEventListener + void windowResized(Ogre::RenderWindow *rw) override; + void windowFocusChange(Ogre::RenderWindow *rw) override; + }; } // namespace RoR diff --git a/source/main/PagedGeometryConfig.h b/source/main/PagedGeometryConfig.h index 480d0be9a6..c9fe8dabe7 100644 --- a/source/main/PagedGeometryConfig.h +++ b/source/main/PagedGeometryConfig.h @@ -5,7 +5,7 @@ #define PAGEDGEOMETRY_VERSION_MAJOR 1 #define PAGEDGEOMETRY_VERSION_MINOR 2 #define PAGEDGEOMETRY_VERSION_PATCH 1 -#define PAGEDGEOMETRY_VERSION "1.2.1" +#define PAGEDGEOMETRY_VERSION "1.2.1" /* Define if we use the alternate coordsystem */ /* #undef PAGEDGEOMETRY_ALTERNATE_COORDSYSTEM */ @@ -16,8 +16,7 @@ /* Define if we support user data */ /* #undef PAGEDGEOMETRY_USER_DATA */ - /* some helpful OIS macro */ /* #undef OIS_USING_DIR */ -#endif //PagedGeometryConfig_h__ +#endif // PagedGeometryConfig_h__ diff --git a/source/main/RoRPrerequisites.h b/source/main/RoRPrerequisites.h index 29c09b5c37..dedeba2ac9 100644 --- a/source/main/RoRPrerequisites.h +++ b/source/main/RoRPrerequisites.h @@ -21,34 +21,33 @@ along with Rigs of Rods. If not, see . #pragma once +#include // Forward declarations #include #include - -#include // Forward declarations #if MYGUI_VERSION >= 0x030201 -# define MYGUI_GET_SCANCODE(KEY) (KEY.getValue()) + #define MYGUI_GET_SCANCODE(KEY) (KEY.getValue()) #else -# define MYGUI_GET_SCANCODE(KEY) (KEY.toValue()) + #define MYGUI_GET_SCANCODE(KEY) (KEY.toValue()) #endif +#include "BitFlags.h" #include "ForwardDeclarations.h" #include "GlobalEnvironment.h" #include "ZeroedMemoryAllocator.h" // this is used quite a lot, so we include it here already -#include "BitFlags.h" // some config for angelscript, doesnt matter if we compile with angelscript or not as its just a definition #ifdef USE_ANGELSCRIPT -#ifndef AS_USE_NAMESPACE -#define AS_USE_NAMESPACE -#endif //AS_USE_NAMESPACE -#endif // USE_ANGELSCRIPT + #ifndef AS_USE_NAMESPACE + #define AS_USE_NAMESPACE + #endif // AS_USE_NAMESPACE +#endif // USE_ANGELSCRIPT // version information now residing in RoRVersion.h // some shortcuts for us -#define TOSTRING(x) Ogre::StringConverter::toString(x) -#define TOUTFSTRING(x) ANSI_TO_UTF(Ogre::StringConverter::toString(x)) -#define PARSEINT(x) Ogre::StringConverter::parseInt(x) +#define TOSTRING(x) Ogre::StringConverter::toString(x) +#define TOUTFSTRING(x) ANSI_TO_UTF(Ogre::StringConverter::toString(x)) +#define PARSEINT(x) Ogre::StringConverter::parseInt(x) #define PARSEREAL(x) Ogre::StringConverter::parseReal(x) #define HydraxLOG(msg) Ogre::LogManager::getSingleton().logMessage("[Hydrax] " + Ogre::String(msg)); @@ -56,40 +55,50 @@ along with Rigs of Rods. If not, see . // #define FEAT_DEBUG_ASSERT #ifdef FEAT_DEBUG_ASSERT -# ifdef _WIN32 -// __debugbreak will break into the debugger in visual studio -# define MYASSERT(x) do { if (x) { } else { LOGSAFE("***ASSERT FAILED: "+OGREFUNCTIONSTRING); __debugbreak(); }; } while(0) -# endif // _WIN32 -#else //!FEAT_DEBUG_ASSERT -# define MYASSERT(x) assert(x) -#endif //FEAT_DEBUG_ASSERT + #ifdef _WIN32 + // __debugbreak will break into the debugger in visual studio + #define MYASSERT(x) \ + do \ + { \ + if (x) {} \ + else \ + { \ + LOGSAFE("***ASSERT FAILED: " + OGREFUNCTIONSTRING); \ + __debugbreak(); \ + }; \ + } while (0) + #endif // _WIN32 +#else //! FEAT_DEBUG_ASSERT + #define MYASSERT(x) assert(x) +#endif // FEAT_DEBUG_ASSERT #define CHARACTER_ANIM_NAME_LEN 10 // Restricted for networking -enum VisibilityMasks { - DEPTHMAP_ENABLED = BITMASK(1), - DEPTHMAP_DISABLED = BITMASK(2), - HIDE_MIRROR = BITMASK(3), +enum VisibilityMasks +{ + DEPTHMAP_ENABLED = BITMASK(1), + DEPTHMAP_DISABLED = BITMASK(2), + HIDE_MIRROR = BITMASK(3), }; extern GlobalEnvironment *gEnv; -enum LoaderType -{ - LT_None, - LT_Terrain, - LT_Vehicle, - LT_Truck, - LT_Car, - LT_Boat, - LT_Airplane, - LT_Trailer, - LT_Train, - LT_Load, - LT_Extension, - LT_Network, - LT_NetworkWithBoat, - LT_Heli, - LT_Skin, - LT_AllBeam +enum LoaderType +{ + LT_None, + LT_Terrain, + LT_Vehicle, + LT_Truck, + LT_Car, + LT_Boat, + LT_Airplane, + LT_Trailer, + LT_Train, + LT_Load, + LT_Extension, + LT_Network, + LT_NetworkWithBoat, + LT_Heli, + LT_Skin, + LT_AllBeam }; diff --git a/source/main/audio/MumbleIntegration.cpp b/source/main/audio/MumbleIntegration.cpp index 359ef0434f..18ae0dbcda 100644 --- a/source/main/audio/MumbleIntegration.cpp +++ b/source/main/audio/MumbleIntegration.cpp @@ -25,12 +25,12 @@ #ifdef USE_MUMBLE -#include "MumbleIntegration.h" + #include "MumbleIntegration.h" -#include "Application.h" + #include "Application.h" -#include -#include + #include + #include using namespace Ogre; @@ -41,63 +41,52 @@ MumbleIntegration::MumbleIntegration() : lm(NULL) MumbleIntegration::~MumbleIntegration() { - if (lm != nullptr) - delete lm; + if (lm != nullptr) delete lm; } void MumbleIntegration::initMumble() { -#ifdef _WIN32 + #ifdef _WIN32 HANDLE hMapObject = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink"); - if (hMapObject == NULL) - return; + if (hMapObject == NULL) return; - lm = (LinkedMem *) MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkedMem)); + lm = (LinkedMem *)MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkedMem)); if (lm == NULL) { CloseHandle(hMapObject); hMapObject = NULL; return; } -#else + #else char memname[256]; snprintf(memname, 256, "/MumbleLink.%d", getuid()); int shmfd = shm_open(memname, O_RDWR, S_IRUSR | S_IWUSR); - if (shmfd < 0) - { - return; - } + if (shmfd < 0) { return; } - lm = (LinkedMem *)(mmap(NULL, sizeof(struct LinkedMem), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd,0)); + lm = (LinkedMem *)(mmap(NULL, sizeof(struct LinkedMem), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)); if (lm == (void *)(-1)) { lm = NULL; return; } -#endif // _WIN32 + #endif // _WIN32 } void MumbleIntegration::SetNonPositionalAudio() { - if (! lm) - return; + if (!lm) return; - this->update( - Ogre::Vector3::ZERO, - Ogre::Vector3(0.0f, 0.0f, 1.0f), - Ogre::Vector3(0.0f, 1.0f, 0.0f), - Ogre::Vector3::ZERO, - Ogre::Vector3(0.0f, 0.0f, 1.0f), - Ogre::Vector3(0.0f, 1.0f, 0.0f)); + this->update(Ogre::Vector3::ZERO, Ogre::Vector3(0.0f, 0.0f, 1.0f), Ogre::Vector3(0.0f, 1.0f, 0.0f), Ogre::Vector3::ZERO, + Ogre::Vector3(0.0f, 0.0f, 1.0f), Ogre::Vector3(0.0f, 1.0f, 0.0f)); } -void MumbleIntegration::update(Ogre::Vector3 cameraPos, Ogre::Vector3 cameraDir, Ogre::Vector3 cameraUp, Ogre::Vector3 avatarPos, Ogre::Vector3 avatarDir, Ogre::Vector3 avatarUp) +void MumbleIntegration::update(Ogre::Vector3 cameraPos, Ogre::Vector3 cameraDir, Ogre::Vector3 cameraUp, Ogre::Vector3 avatarPos, + Ogre::Vector3 avatarDir, Ogre::Vector3 avatarUp) { - if (! lm) - return; + if (!lm) return; if (lm->uiVersion != 2) { @@ -114,10 +103,9 @@ void MumbleIntegration::update(Ogre::Vector3 cameraPos, Ogre::Vector3 cameraDir, // // 1 unit = 1 meter - // OGRE uses right-handed coordinate system ( http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Basic+Tutorial+1&structure=Tutorials ) - // X positive towards "right". - // Y positive towards "up". - // Z positive towards "back". => conversion necessary! + // OGRE uses right-handed coordinate system ( + // http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Basic+Tutorial+1&structure=Tutorials ) X positive towards "right". Y + // positive towards "up". Z positive towards "back". => conversion necessary! // // 1 unit = 1 meter (in RoR) @@ -169,8 +157,8 @@ void MumbleIntegration::update(Ogre::Vector3 cameraPos, Ogre::Vector3 cameraDir, // so we should take that into account as well int teamID = 0; // RoR currently doesn't have any kind of team-based gameplay - int port = RoR::App::mp_server_port.GetActive(); - port = (port != 0) ? port : 1337; + int port = RoR::App::mp_server_port.GetActive(); + port = (port != 0) ? port : 1337; sprintf((char *)lm->context, "%s:%s|%d", RoR::App::mp_server_host.GetActive(), TOSTRING(port).c_str(), teamID); lm->context_len = (int)strnlen((char *)lm->context, 256); } diff --git a/source/main/audio/MumbleIntegration.h b/source/main/audio/MumbleIntegration.h index efd74f3cad..cecf187354 100644 --- a/source/main/audio/MumbleIntegration.h +++ b/source/main/audio/MumbleIntegration.h @@ -27,54 +27,55 @@ #ifdef USE_MUMBLE -#include "RoRPrerequisites.h" + #include "RoRPrerequisites.h" -#ifdef _WIN32 -#include -#else - #include - #include /* For O_* constants */ -#endif // _WIN32 + #ifdef _WIN32 + #include + #else + #include /* For O_* constants */ + #include + #endif // _WIN32 class MumbleIntegration : public ZeroedMemoryAllocator { -public: + public: MumbleIntegration(); - void update(Ogre::Vector3 cameraPos, Ogre::Vector3 cameraDir, Ogre::Vector3 cameraUp, Ogre::Vector3 avatarPos, Ogre::Vector3 avatarDir, Ogre::Vector3 avatarUp); + void update(Ogre::Vector3 cameraPos, Ogre::Vector3 cameraDir, Ogre::Vector3 cameraUp, Ogre::Vector3 avatarPos, + Ogre::Vector3 avatarDir, Ogre::Vector3 avatarUp); void SetNonPositionalAudio(); // for main menu -protected: + protected: ~MumbleIntegration(); void initMumble(); struct LinkedMem { -#ifdef _WIN32 + #ifdef _WIN32 UINT32 uiVersion; - DWORD uiTick; -#else + DWORD uiTick; + #else uint32_t uiVersion; uint32_t uiTick; -#endif // _WIN32 - float fAvatarPosition[3]; - float fAvatarFront[3]; - float fAvatarTop[3]; + #endif // _WIN32 + float fAvatarPosition[3]; + float fAvatarFront[3]; + float fAvatarTop[3]; wchar_t name[256]; - float fCameraPosition[3]; - float fCameraFront[3]; - float fCameraTop[3]; + float fCameraPosition[3]; + float fCameraFront[3]; + float fCameraTop[3]; wchar_t identity[256]; -#ifdef _WIN32 + #ifdef _WIN32 UINT32 context_len; -#else + #else uint32_t context_len; -#endif // _WIN32 + #endif // _WIN32 unsigned char context[256]; - wchar_t description[2048]; + wchar_t description[2048]; }; - LinkedMem* lm; + LinkedMem *lm; }; -#endif //USE_MUMBLE +#endif // USE_MUMBLE diff --git a/source/main/audio/Sound.cpp b/source/main/audio/Sound.cpp index 038712481a..554f7f1201 100644 --- a/source/main/audio/Sound.cpp +++ b/source/main/audio/Sound.cpp @@ -20,24 +20,15 @@ #ifdef USE_OPENAL -#include "Sound.h" -#include "SoundManager.h" + #include "Sound.h" + + #include "SoundManager.h" using namespace Ogre; -Sound::Sound(ALuint buffer, SoundManager* soundManager, int sourceIndex) : - buffer(buffer) - , sound_manager(soundManager) - , source_index(sourceIndex) - , audibility(0.0f) - , gain(0.0f) - , pitch(1.0f) - , position(Vector3::ZERO) - , velocity(Vector3::ZERO) - , enabled(true) - , loop(false) - , should_play(false) - , hardware_index(-1) +Sound::Sound(ALuint buffer, SoundManager *soundManager, int sourceIndex) + : buffer(buffer), sound_manager(soundManager), source_index(sourceIndex), audibility(0.0f), gain(0.0f), pitch(1.0f), + position(Vector3::ZERO), velocity(Vector3::ZERO), enabled(true), loop(false), should_play(false), hardware_index(-1) { } @@ -55,10 +46,7 @@ void Sound::computeAudibility(Vector3 pos) { int value = 0; alGetSourcei((ALuint)sound_manager->getHardwareSource(hardware_index), AL_SOURCE_STATE, &value); - if (value != AL_PLAYING) - { - should_play = false; - } + if (value != AL_PLAYING) { should_play = false; } } // should it play at all? @@ -70,17 +58,16 @@ void Sound::computeAudibility(Vector3 pos) float distance = (pos - position).length(); - if (distance > sound_manager->MAX_DISTANCE) - { - audibility = 0.0f; - } + if (distance > sound_manager->MAX_DISTANCE) { audibility = 0.0f; } else if (distance < sound_manager->REFERENCE_DISTANCE) { audibility = gain; } else { - audibility = gain * (sound_manager->REFERENCE_DISTANCE / (sound_manager->REFERENCE_DISTANCE + (sound_manager->ROLLOFF_FACTOR * (distance - sound_manager->REFERENCE_DISTANCE)))); + audibility = gain * (sound_manager->REFERENCE_DISTANCE / + (sound_manager->REFERENCE_DISTANCE + + (sound_manager->ROLLOFF_FACTOR * (distance - sound_manager->REFERENCE_DISTANCE)))); } } @@ -97,8 +84,7 @@ bool Sound::isPlaying() void Sound::setEnabled(bool e) { - if (e == this->enabled) - return; + if (e == this->enabled) return; this->enabled = e; sound_manager->recomputeSource(source_index, REASON_PLAY, 0.0f, NULL); @@ -123,8 +109,7 @@ void Sound::stop() void Sound::setGain(float gain) { - if (gain == this->gain) - return; + if (gain == this->gain) return; this->gain = gain; sound_manager->recomputeSource(source_index, REASON_GAIN, gain, NULL); @@ -132,8 +117,7 @@ void Sound::setGain(float gain) void Sound::setLoop(bool loop) { - if (loop == this->loop) - return; + if (loop == this->loop) return; this->loop = loop; sound_manager->recomputeSource(source_index, REASON_LOOP, (loop) ? 1.0f : 0.0f, NULL); @@ -141,8 +125,7 @@ void Sound::setLoop(bool loop) void Sound::setPitch(float pitch) { - if (pitch == this->pitch) - return; + if (pitch == this->pitch) return; this->pitch = pitch; sound_manager->recomputeSource(source_index, REASON_PTCH, pitch, NULL); @@ -150,8 +133,7 @@ void Sound::setPitch(float pitch) void Sound::setPosition(Ogre::Vector3 pos) { - if (pos == this->position) - return; + if (pos == this->position) return; this->position = pos; sound_manager->recomputeSource(source_index, REASON_POSN, 0.0f, &pos); @@ -159,8 +141,7 @@ void Sound::setPosition(Ogre::Vector3 pos) void Sound::setVelocity(Ogre::Vector3 vel) { - if (vel == this->velocity) - return; + if (vel == this->velocity) return; this->velocity = vel; sound_manager->recomputeSource(source_index, REASON_VLCT, 0.0f, &vel); diff --git a/source/main/audio/Sound.h b/source/main/audio/Sound.h index 5c92a43804..d26ce03b39 100644 --- a/source/main/audio/Sound.h +++ b/source/main/audio/Sound.h @@ -20,22 +20,22 @@ #ifdef USE_OPENAL -#pragma once + #pragma once -#include "RoRPrerequisites.h" + #include "RoRPrerequisites.h" -#ifdef __APPLE__ - #include -#else -#include -#endif // __APPLE__ + #ifdef __APPLE__ + #include + #else + #include + #endif // __APPLE__ class Sound : public ZeroedMemoryAllocator { friend class SoundManager; -public: - Sound(ALuint buffer, SoundManager* soundManager, int sourceIndex); + public: + Sound(ALuint buffer, SoundManager *soundManager, int sourceIndex); void setPitch(float pitch); void setGain(float gain); @@ -60,24 +60,24 @@ class Sound : public ZeroedMemoryAllocator REASON_VLCT }; -private: + private: void computeAudibility(Ogre::Vector3 pos); float audibility; float gain; float pitch; - bool loop; - bool enabled; - bool should_play; + bool loop; + bool enabled; + bool should_play; // this value is changed dynamically, depending on whether the input is played or not. - int hardware_index; + int hardware_index; ALuint buffer; Ogre::Vector3 position; Ogre::Vector3 velocity; - SoundManager* sound_manager; + SoundManager *sound_manager; // must not be changed during the lifetime of this object int source_index; }; diff --git a/source/main/audio/SoundManager.cpp b/source/main/audio/SoundManager.cpp index d95800f08d..2b406a81fc 100644 --- a/source/main/audio/SoundManager.cpp +++ b/source/main/audio/SoundManager.cpp @@ -21,16 +21,16 @@ #ifdef USE_OPENAL -#include "SoundManager.h" + #include "SoundManager.h" -#include "Application.h" -#include "Sound.h" + #include "Application.h" + #include "Sound.h" -#include + #include -#define LOGSTREAM Ogre::LogManager::getSingleton().stream() << "[RoR|Audio] " + #define LOGSTREAM Ogre::LogManager::getSingleton().stream() << "[RoR|Audio] " -bool _checkALErrors(const char* filename, int linenum) +bool _checkALErrors(const char *filename, int linenum) { int err = alGetError(); if (err != AL_NO_ERROR) @@ -43,21 +43,18 @@ bool _checkALErrors(const char* filename, int linenum) return false; } -#define hasALErrors() _checkALErrors(__FILE__, __LINE__) + #define hasALErrors() _checkALErrors(__FILE__, __LINE__) using namespace RoR; using namespace Ogre; -const float SoundManager::MAX_DISTANCE = 500.0f; -const float SoundManager::ROLLOFF_FACTOR = 1.0f; +const float SoundManager::MAX_DISTANCE = 500.0f; +const float SoundManager::ROLLOFF_FACTOR = 1.0f; const float SoundManager::REFERENCE_DISTANCE = 7.5f; -SoundManager::SoundManager() : - audio_buffers_in_use_count(0) - , hardware_sources_in_use_count(0) - , hardware_sources_num(0) - , sound_context(NULL) - , audio_device(NULL) +SoundManager::SoundManager() + : audio_buffers_in_use_count(0), hardware_sources_in_use_count(0), hardware_sources_num(0), sound_context(NULL), + audio_device(NULL) { if (App::audio_device_name.IsActiveEmpty()) { @@ -69,7 +66,8 @@ SoundManager::SoundManager() : audio_device = alcOpenDevice(App::audio_device_name.GetActive()); if (!audio_device) { - LOGSTREAM << "Failed to open configured audio device \"" << App::audio_device_name.GetActive() << "\", opening default."; + LOGSTREAM << "Failed to open configured audio device \"" << App::audio_device_name.GetActive() + << "\", opening default."; App::audio_device_name.SetActive(""); audio_device = alcOpenDevice(nullptr); } @@ -98,16 +96,17 @@ SoundManager::SoundManager() : if (alGetString(AL_VERSION)) LOG("SoundManager: OpenAL version is: " + String(alGetString(AL_VERSION))); if (alGetString(AL_RENDERER)) LOG("SoundManager: OpenAL renderer is: " + String(alGetString(AL_RENDERER))); if (alGetString(AL_EXTENSIONS)) LOG("SoundManager: OpenAL extensions are: " + String(alGetString(AL_EXTENSIONS))); - if (alcGetString(audio_device, ALC_DEVICE_SPECIFIER)) LOG("SoundManager: OpenAL device is: " + String(alcGetString(audio_device, ALC_DEVICE_SPECIFIER))); - if (alcGetString(audio_device, ALC_EXTENSIONS)) LOG("SoundManager: OpenAL ALC extensions are: " + String(alcGetString(audio_device, ALC_EXTENSIONS))); + if (alcGetString(audio_device, ALC_DEVICE_SPECIFIER)) + LOG("SoundManager: OpenAL device is: " + String(alcGetString(audio_device, ALC_DEVICE_SPECIFIER))); + if (alcGetString(audio_device, ALC_EXTENSIONS)) + LOG("SoundManager: OpenAL ALC extensions are: " + String(alcGetString(audio_device, ALC_EXTENSIONS))); // generate the AL sources for (hardware_sources_num = 0; hardware_sources_num < MAX_HARDWARE_SOURCES; hardware_sources_num++) { alGetError(); alGenSources(1, &hardware_sources[hardware_sources_num]); - if (alGetError() != AL_NO_ERROR) - break; + if (alGetError() != AL_NO_ERROR) break; alSourcef(hardware_sources[hardware_sources_num], AL_REFERENCE_DISTANCE, REFERENCE_DISTANCE); alSourcef(hardware_sources[hardware_sources_num], AL_ROLLOFF_FACTOR, ROLLOFF_FACTOR); alSourcef(hardware_sources[hardware_sources_num], AL_MAX_DISTANCE, MAX_DISTANCE); @@ -130,20 +129,16 @@ SoundManager::~SoundManager() // destroy the sound context and device sound_context = alcGetCurrentContext(); - audio_device = alcGetContextsDevice(sound_context); + audio_device = alcGetContextsDevice(sound_context); alcMakeContextCurrent(NULL); alcDestroyContext(sound_context); - if (audio_device) - { - alcCloseDevice(audio_device); - } + if (audio_device) { alcCloseDevice(audio_device); } LOG("SoundManager destroyed."); } void SoundManager::setCamera(Ogre::Vector3 position, Ogre::Vector3 direction, Ogre::Vector3 up, Ogre::Vector3 velocity) { - if (!audio_device) - return; + if (!audio_device) return; camera_position = position; recomputeAllSources(); @@ -171,7 +166,7 @@ bool compareByAudibility(std::pair a, std::pair b) void SoundManager::recomputeAllSources() { // Creates this issue: https://github.com/RigsOfRods/rigs-of-rods/issues/1054 -#if 0 + #if 0 if (!audio_device) return; for (int i=0; i < audio_buffers_in_use_count; i++) @@ -207,13 +202,12 @@ void SoundManager::recomputeAllSources() } } } -#endif + #endif } -void SoundManager::recomputeSource(int source_index, int reason, float vfl, Vector3* vvec) +void SoundManager::recomputeSource(int source_index, int reason, float vfl, Vector3 *vvec) { - if (!audio_device) - return; + if (!audio_device) return; audio_sources[source_index]->computeAudibility(camera_position); if (audio_sources[source_index]->audibility == 0.0f) @@ -234,20 +228,13 @@ void SoundManager::recomputeSource(int source_index, int reason, float vfl, Vect // update the AL settings switch (reason) { - case Sound::REASON_PLAY: alSourcePlay(hw_source); - break; - case Sound::REASON_STOP: alSourceStop(hw_source); - break; - case Sound::REASON_GAIN: alSourcef(hw_source, AL_GAIN, vfl * App::audio_master_volume.GetActive()); - break; - case Sound::REASON_LOOP: alSourcei(hw_source, AL_LOOPING, (vfl > 0.5) ? AL_TRUE : AL_FALSE); - break; - case Sound::REASON_PTCH: alSourcef(hw_source, AL_PITCH, vfl); - break; - case Sound::REASON_POSN: alSource3f(hw_source, AL_POSITION, vvec->x, vvec->y, vvec->z); - break; - case Sound::REASON_VLCT: alSource3f(hw_source, AL_VELOCITY, vvec->x, vvec->y, vvec->z); - break; + case Sound::REASON_PLAY: alSourcePlay(hw_source); break; + case Sound::REASON_STOP: alSourceStop(hw_source); break; + case Sound::REASON_GAIN: alSourcef(hw_source, AL_GAIN, vfl * App::audio_master_volume.GetActive()); break; + case Sound::REASON_LOOP: alSourcei(hw_source, AL_LOOPING, (vfl > 0.5) ? AL_TRUE : AL_FALSE); break; + case Sound::REASON_PTCH: alSourcef(hw_source, AL_PITCH, vfl); break; + case Sound::REASON_POSN: alSource3f(hw_source, AL_POSITION, vvec->x, vvec->y, vvec->z); break; + case Sound::REASON_VLCT: alSource3f(hw_source, AL_VELOCITY, vvec->x, vvec->y, vvec->z); break; default: break; } } @@ -270,13 +257,13 @@ void SoundManager::recomputeSource(int source_index, int reason, float vfl, Vect { // now, compute who is the faintest // note: we know the table m_hardware_sources_map is full! - float fv = 1.0f; - int al_faintest = 0; + float fv = 1.0f; + int al_faintest = 0; for (int i = 0; i < hardware_sources_num; i++) { if (hardware_sources_map[i] >= 0 && audio_sources[hardware_sources_map[i]]->audibility < fv) { - fv = audio_sources[hardware_sources_map[i]]->audibility; + fv = audio_sources[hardware_sources_map[i]]->audibility; al_faintest = i; } } @@ -295,13 +282,12 @@ void SoundManager::recomputeSource(int source_index, int reason, float vfl, Vect void SoundManager::assign(int source_index, int hardware_index) { - if (!audio_device) - return; + if (!audio_device) return; audio_sources[source_index]->hardware_index = hardware_index; - hardware_sources_map[hardware_index] = source_index; + hardware_sources_map[hardware_index] = source_index; - ALuint hw_source = hardware_sources[hardware_index]; - Sound* audio_source = audio_sources[source_index]; + ALuint hw_source = hardware_sources[hardware_index]; + Sound *audio_source = audio_sources[source_index]; // the hardware source is supposed to be stopped! alSourcei(hw_source, AL_BUFFER, audio_source->buffer); @@ -311,55 +297,46 @@ void SoundManager::assign(int source_index, int hardware_index) alSource3f(hw_source, AL_POSITION, audio_source->position.x, audio_source->position.y, audio_source->position.z); alSource3f(hw_source, AL_VELOCITY, audio_source->velocity.x, audio_source->velocity.y, audio_source->velocity.z); - if (audio_source->should_play) - { - alSourcePlay(hw_source); - } + if (audio_source->should_play) { alSourcePlay(hw_source); } hardware_sources_in_use_count++; } void SoundManager::retire(int source_index) { - if (!audio_device) - return; - if (audio_sources[source_index]->hardware_index == -1) - return; + if (!audio_device) return; + if (audio_sources[source_index]->hardware_index == -1) return; alSourceStop(hardware_sources[audio_sources[source_index]->hardware_index]); hardware_sources_map[audio_sources[source_index]->hardware_index] = -1; - audio_sources[source_index]->hardware_index = -1; + audio_sources[source_index]->hardware_index = -1; hardware_sources_in_use_count--; } void SoundManager::pauseAllSounds() { - if (!audio_device) - return; + if (!audio_device) return; // no mutex needed alListenerf(AL_GAIN, 0.0f); } void SoundManager::resumeAllSounds() { - if (!audio_device) - return; + if (!audio_device) return; // no mutex needed alListenerf(AL_GAIN, App::audio_master_volume.GetActive()); } void SoundManager::setMasterVolume(float v) { - if (!audio_device) - return; + if (!audio_device) return; // no mutex needed App::audio_master_volume.SetActive(v); // TODO: Use 'pending' mechanism and set externally, only 'apply' here. alListenerf(AL_GAIN, v); } -Sound* SoundManager::createSound(String filename) +Sound *SoundManager::createSound(String filename) { - if (!audio_device) - return NULL; + if (!audio_device) return NULL; if (audio_buffers_in_use_count >= MAX_AUDIO_BUFFERS) { @@ -390,7 +367,7 @@ Sound* SoundManager::createSound(String filename) audio_buffer_file_name[audio_buffers_in_use_count] = ""; return NULL; } - buffer = audio_buffers[audio_buffers_in_use_count]; + buffer = audio_buffers[audio_buffers_in_use_count]; audio_buffer_file_name[audio_buffers_in_use_count] = filename; } @@ -401,30 +378,29 @@ Sound* SoundManager::createSound(String filename) bool SoundManager::loadWAVFile(String filename, ALuint buffer) { - if (!audio_device) - return true; - LOG("Loading WAV file "+filename); + if (!audio_device) return true; + LOG("Loading WAV file " + filename); // create the Stream - ResourceGroupManager* rgm = ResourceGroupManager::getSingletonPtr(); - String group = rgm->findGroupContainingResource(filename); - DataStreamPtr stream = rgm->openResource(filename, group); + ResourceGroupManager *rgm = ResourceGroupManager::getSingletonPtr(); + String group = rgm->findGroupContainingResource(filename); + DataStreamPtr stream = rgm->openResource(filename, group); // load RIFF/WAVE char magic[5]; magic[4] = 0; - unsigned int lbuf; // uint32_t + unsigned int lbuf; // uint32_t unsigned short sbuf; // uint16_t // check magic if (stream->read(magic, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } if (String(magic) != String("RIFF")) { - LOG("Invalid WAV file (no RIFF): "+filename); + LOG("Invalid WAV file (no RIFF): " + filename); return true; } // skip 4 bytes (magic) @@ -432,60 +408,60 @@ bool SoundManager::loadWAVFile(String filename, ALuint buffer) // check file format if (stream->read(magic, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } if (String(magic) != String("WAVE")) { - LOG("Invalid WAV file (no WAVE): "+filename); + LOG("Invalid WAV file (no WAVE): " + filename); return true; } // check 'fmt ' sub chunk (1) if (stream->read(magic, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } if (String(magic) != String("fmt ")) { - LOG("Invalid WAV file (no fmt): "+filename); + LOG("Invalid WAV file (no fmt): " + filename); return true; } // read (1)'s size if (stream->read(&lbuf, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } unsigned long subChunk1Size = lbuf; if (subChunk1Size < 16) { - LOG("Invalid WAV file (invalid subChunk1Size): "+filename); + LOG("Invalid WAV file (invalid subChunk1Size): " + filename); return true; } // check PCM audio format if (stream->read(&sbuf, 2) != 2) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } unsigned short audioFormat = sbuf; if (audioFormat != 1) { - LOG("Invalid WAV file (invalid audioformat "+TOSTRING(audioFormat)+"): "+filename); + LOG("Invalid WAV file (invalid audioformat " + TOSTRING(audioFormat) + "): " + filename); return true; } // read number of channels if (stream->read(&sbuf, 2) != 2) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } unsigned short channels = sbuf; // read frequency (sample rate) if (stream->read(&lbuf, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } unsigned long freq = lbuf; @@ -494,19 +470,19 @@ bool SoundManager::loadWAVFile(String filename, ALuint buffer) // read bits per sample if (stream->read(&sbuf, 2) != 2) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } unsigned short bps = sbuf; // check 'data' sub chunk (2) if (stream->read(magic, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } if (String(magic) != String("data") && String(magic) != String("fact")) { - LOG("Invalid WAV file (no data/fact): "+filename); + LOG("Invalid WAV file (no data/fact): " + filename); return true; } // fact is an option section we don't need to worry about @@ -516,24 +492,24 @@ bool SoundManager::loadWAVFile(String filename, ALuint buffer) // now we should hit the data chunk if (stream->read(magic, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } if (String(magic) != String("data")) { - LOG("Invalid WAV file (no data): "+filename); + LOG("Invalid WAV file (no data): " + filename); return true; } } // the next four bytes are the remaining size of the file if (stream->read(&lbuf, 4) != 4) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); return true; } unsigned long dataSize = lbuf; - int format = 0; + int format = 0; if (channels == 1 && bps == 8) format = AL_FORMAT_MONO8; @@ -545,27 +521,27 @@ bool SoundManager::loadWAVFile(String filename, ALuint buffer) format = AL_FORMAT_STEREO16; else { - LOG("Invalid WAV file (wrong channels/bps): "+filename); + LOG("Invalid WAV file (wrong channels/bps): " + filename); return true; } if (channels != 1) LOG("Invalid WAV file: the file needs to be mono, and nothing else. Will try to continue anyways ..."); // ok, creating buffer - void* bdata = malloc(dataSize); + void *bdata = malloc(dataSize); if (!bdata) { - LOG("Memory error reading file "+filename); + LOG("Memory error reading file " + filename); return true; } if (stream->read(bdata, dataSize) != dataSize) { - LOG("Could not read file "+filename); + LOG("Could not read file " + filename); free(bdata); return true; } - //LOG("alBufferData: format "+TOSTRING(format)+" size "+TOSTRING(dataSize)+" freq "+TOSTRING(freq)); + // LOG("alBufferData: format "+TOSTRING(format)+" size "+TOSTRING(dataSize)+" freq "+TOSTRING(freq)); alGetError(); // Reset errors ALint error; alBufferData(buffer, format, bdata, dataSize, freq); @@ -576,7 +552,7 @@ bool SoundManager::loadWAVFile(String filename, ALuint buffer) if (error != AL_NO_ERROR) { - LOG("OpenAL error while loading buffer for "+filename+" : "+TOSTRING(error)); + LOG("OpenAL error while loading buffer for " + filename + " : " + TOSTRING(error)); return true; } diff --git a/source/main/audio/SoundManager.h b/source/main/audio/SoundManager.h index f841519735..5d50b792be 100644 --- a/source/main/audio/SoundManager.h +++ b/source/main/audio/SoundManager.h @@ -21,50 +21,59 @@ #ifdef USE_OPENAL -#pragma once + #pragma once -#include "RoRPrerequisites.h" + #include "RoRPrerequisites.h" -#include -#include + #include + #include -#ifdef __APPLE__ - #include - #include -#else - #include - #include -#endif // __APPLE__ + #ifdef __APPLE__ + #include + #include + #else + #include + #include + #endif // __APPLE__ class SoundManager : public ZeroedMemoryAllocator { friend class Sound; -public: + public: SoundManager(); ~SoundManager(); - Sound* createSound(Ogre::String filename); + Sound *createSound(Ogre::String filename); void setCamera(Ogre::Vector3 position, Ogre::Vector3 direction, Ogre::Vector3 up, Ogre::Vector3 velocity); void pauseAllSounds(); void resumeAllSounds(); void setMasterVolume(float v); - bool isDisabled() { return audio_device == 0; } + bool isDisabled() + { + return audio_device == 0; + } - int getNumHardwareSources() { return hardware_sources_num; } + int getNumHardwareSources() + { + return hardware_sources_num; + } - static const float MAX_DISTANCE; - static const float ROLLOFF_FACTOR; - static const float REFERENCE_DISTANCE; + static const float MAX_DISTANCE; + static const float ROLLOFF_FACTOR; + static const float REFERENCE_DISTANCE; static const unsigned int MAX_HARDWARE_SOURCES = 32; - static const unsigned int MAX_AUDIO_BUFFERS = 8192; + static const unsigned int MAX_AUDIO_BUFFERS = 8192; -private: - void recomputeAllSources(); - void recomputeSource(int source_index, int reason, float vfl, Ogre::Vector3 *vvec); - ALuint getHardwareSource(int hardware_index) { return hardware_sources[hardware_index]; }; + private: + void recomputeAllSources(); + void recomputeSource(int source_index, int reason, float vfl, Ogre::Vector3 *vvec); + ALuint getHardwareSource(int hardware_index) + { + return hardware_sources[hardware_index]; + }; void assign(int source_index, int hardware_index); void retire(int source_index); @@ -72,24 +81,24 @@ class SoundManager : public ZeroedMemoryAllocator bool loadWAVFile(Ogre::String filename, ALuint buffer); // active audio sources (hardware sources) - int hardware_sources_num; // total number of available hardware sources < MAX_HARDWARE_SOURCES + int hardware_sources_num; // total number of available hardware sources < MAX_HARDWARE_SOURCES int hardware_sources_in_use_count; int hardware_sources_map[MAX_HARDWARE_SOURCES]; // stores the hardware index for each source. -1 = unmapped ALuint hardware_sources[MAX_HARDWARE_SOURCES]; // this buffer contains valid AL handles up to m_hardware_sources_num // audio sources - Sound* audio_sources[MAX_AUDIO_BUFFERS]; + Sound *audio_sources[MAX_AUDIO_BUFFERS]; // helper for calculating the most audible sources std::pair audio_sources_most_audible[MAX_AUDIO_BUFFERS]; - + // audio buffers: Array of AL buffers and filenames int audio_buffers_in_use_count; ALuint audio_buffers[MAX_AUDIO_BUFFERS]; Ogre::String audio_buffer_file_name[MAX_AUDIO_BUFFERS]; Ogre::Vector3 camera_position; - ALCdevice* audio_device; - ALCcontext* sound_context; + ALCdevice * audio_device; + ALCcontext * sound_context; }; #endif // USE_OPENAL diff --git a/source/main/audio/SoundScriptManager.cpp b/source/main/audio/SoundScriptManager.cpp index 555bbc73a0..31d0efab31 100644 --- a/source/main/audio/SoundScriptManager.cpp +++ b/source/main/audio/SoundScriptManager.cpp @@ -20,29 +20,24 @@ #ifdef USE_OPENAL -#include "SoundScriptManager.h" + #include "SoundScriptManager.h" -#include "Beam.h" -#include "Sound.h" -#include "SoundManager.h" -#include "Utils.h" + #include "Beam.h" + #include "Sound.h" + #include "SoundManager.h" + #include "Utils.h" -#include + #include using namespace Ogre; using namespace RoR; -const float SoundScriptInstance::PITCHDOWN_FADE_FACTOR = 3.0f; +const float SoundScriptInstance::PITCHDOWN_FADE_FACTOR = 3.0f; const float SoundScriptInstance::PITCHDOWN_CUTOFF_FACTOR = 5.0f; -SoundScriptManager::SoundScriptManager() : - disabled(true) - , loading_base(false) - , instance_counter(0) - , max_distance(500.0f) - , rolloff_factor(1.0f) - , reference_distance(7.5f) - , sound_manager(nullptr) +SoundScriptManager::SoundScriptManager() + : disabled(true), loading_base(false), instance_counter(0), max_distance(500.0f), rolloff_factor(1.0f), + reference_distance(7.5f), sound_manager(nullptr) { for (int i = 0; i < SS_MAX_TRIG; i++) { @@ -52,7 +47,7 @@ SoundScriptManager::SoundScriptManager() : for (int i = 0; i < SS_MAX_MOD; i++) { free_pitches[i] = 0; - free_gains[i] = 0; + free_gains[i] = 0; } // TODO: there is a memory corruption going on here, need to fix @@ -64,7 +59,7 @@ SoundScriptManager::SoundScriptManager() : for (int i = 0; i < SS_MAX_MOD * MAX_INSTANCES_PER_GROUP; i++) { pitches[i] = 0; - gains[i] = 0; + gains[i] = 0; } // reset all states @@ -86,151 +81,114 @@ SoundScriptManager::SoundScriptManager() : return; } - LOG("SoundScriptManager: Sound Manager started with " + TOSTRING(sound_manager->getNumHardwareSources())+" sources"); + LOG("SoundScriptManager: Sound Manager started with " + TOSTRING(sound_manager->getNumHardwareSources()) + " sources"); script_patterns.push_back("*.soundscript"); ResourceGroupManager::getSingleton()._registerScriptLoader(this); } SoundScriptManager::~SoundScriptManager() { - if (sound_manager != nullptr) - delete sound_manager; + if (sound_manager != nullptr) delete sound_manager; } -void SoundScriptManager::trigOnce(Actor* actor, int trig, int linkType, int linkItemID) +void SoundScriptManager::trigOnce(Actor *actor, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (actor) - { - trigOnce(actor->ar_instance_id, trig, linkType, linkItemID); - } + if (actor) { trigOnce(actor->ar_instance_id, trig, linkType, linkItemID); } } void SoundScriptManager::trigOnce(int actor_id, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; for (int i = 0; i < free_trigs[trig]; i++) { // cycle through all instance groups - SoundScriptInstance* inst = trigs[trig + i * SS_MAX_TRIG]; + SoundScriptInstance *inst = trigs[trig + i * SS_MAX_TRIG]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) - { - inst->runOnce(); - } + { inst->runOnce(); } } } -void SoundScriptManager::trigStart(Actor* actor, int trig, int linkType, int linkItemID) +void SoundScriptManager::trigStart(Actor *actor, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (actor) - { - trigStart(actor->ar_instance_id, trig, linkType, linkItemID); - } + if (actor) { trigStart(actor->ar_instance_id, trig, linkType, linkItemID); } } void SoundScriptManager::trigStart(int actor_id, int trig, int linkType, int linkItemID) { - if (disabled) - return; - if (getTrigState(actor_id, trig, linkType, linkItemID)) - return; + if (disabled) return; + if (getTrigState(actor_id, trig, linkType, linkItemID)) return; state_map[linkType][linkItemID][actor_id][trig] = true; for (int i = 0; i < free_trigs[trig]; i++) { - SoundScriptInstance* inst = trigs[trig + i * SS_MAX_TRIG]; + SoundScriptInstance *inst = trigs[trig + i * SS_MAX_TRIG]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) - { - inst->start(); - } + { inst->start(); } } } -void SoundScriptManager::trigStop(Actor* actor, int trig, int linkType, int linkItemID) +void SoundScriptManager::trigStop(Actor *actor, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (actor) - { - trigStop(actor->ar_instance_id, trig, linkType, linkItemID); - } + if (actor) { trigStop(actor->ar_instance_id, trig, linkType, linkItemID); } } void SoundScriptManager::trigStop(int actor_id, int trig, int linkType, int linkItemID) { - if (disabled) - return; - if (!getTrigState(actor_id, trig, linkType, linkItemID)) - return; + if (disabled) return; + if (!getTrigState(actor_id, trig, linkType, linkItemID)) return; state_map[linkType][linkItemID][actor_id][trig] = false; for (int i = 0; i < free_trigs[trig]; i++) { - SoundScriptInstance* inst = trigs[trig + i * SS_MAX_TRIG]; + SoundScriptInstance *inst = trigs[trig + i * SS_MAX_TRIG]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) - { - inst->stop(); - } + { inst->stop(); } } } -void SoundScriptManager::trigKill(Actor* actor, int trig, int linkType, int linkItemID) +void SoundScriptManager::trigKill(Actor *actor, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (actor) - { - trigKill(actor->ar_instance_id, trig, linkType, linkItemID); - } + if (actor) { trigKill(actor->ar_instance_id, trig, linkType, linkItemID); } } void SoundScriptManager::trigKill(int actor_id, int trig, int linkType, int linkItemID) { - if (disabled) - return; - if (!getTrigState(actor_id, trig, linkType, linkItemID)) - return; + if (disabled) return; + if (!getTrigState(actor_id, trig, linkType, linkItemID)) return; state_map[linkType][linkItemID][actor_id][trig] = false; for (int i = 0; i < free_trigs[trig]; i++) { - SoundScriptInstance* inst = trigs[trig + i * SS_MAX_TRIG]; + SoundScriptInstance *inst = trigs[trig + i * SS_MAX_TRIG]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) - { - inst->kill(); - } + { inst->kill(); } } } -void SoundScriptManager::trigToggle(Actor* actor, int trig, int linkType, int linkItemID) +void SoundScriptManager::trigToggle(Actor *actor, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (actor) - { - trigToggle(actor->ar_instance_id, trig, linkType, linkItemID); - } + if (actor) { trigToggle(actor->ar_instance_id, trig, linkType, linkItemID); } } void SoundScriptManager::trigToggle(int actor_id, int trig, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; if (getTrigState(actor_id, trig, linkType, linkItemID)) trigStop(actor_id, trig, linkType, linkItemID); @@ -238,10 +196,9 @@ void SoundScriptManager::trigToggle(int actor_id, int trig, int linkType, int li trigStart(actor_id, trig, linkType, linkItemID); } -bool SoundScriptManager::getTrigState(Actor* actor, int trig, int linkType, int linkItemID) +bool SoundScriptManager::getTrigState(Actor *actor, int trig, int linkType, int linkItemID) { - if (disabled) - return false; + if (disabled) return false; if (actor) return getTrigState(actor->ar_instance_id, trig, linkType, linkItemID); @@ -251,38 +208,32 @@ bool SoundScriptManager::getTrigState(Actor* actor, int trig, int linkType, int bool SoundScriptManager::getTrigState(int actor_id, int trig, int linkType, int linkItemID) { - if (disabled) - return false; + if (disabled) return false; return state_map[linkType][linkItemID][actor_id][trig]; } -void SoundScriptManager::modulate(Actor* actor, int mod, float value, int linkType, int linkItemID) +void SoundScriptManager::modulate(Actor *actor, int mod, float value, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (actor) - { - modulate(actor->ar_instance_id, mod, value, linkType, linkItemID); - } + if (actor) { modulate(actor->ar_instance_id, mod, value, linkType, linkItemID); } } void SoundScriptManager::modulate(int actor_id, int mod, float value, int linkType, int linkItemID) { - if (disabled) - return; + if (disabled) return; - if (mod >= SS_MAX_MOD) - return; + if (mod >= SS_MAX_MOD) return; for (int i = 0; i < free_gains[mod]; i++) { - SoundScriptInstance* inst = gains[mod + i * SS_MAX_MOD]; + SoundScriptInstance *inst = gains[mod + i * SS_MAX_MOD]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { // this one requires modulation - float gain = value * value * inst->templ->gain_square + value * inst->templ->gain_multiplier + inst->templ->gain_offset; + float gain = + value * value * inst->templ->gain_square + value * inst->templ->gain_multiplier + inst->templ->gain_offset; gain = std::max(0.0f, gain); gain = std::min(gain, 1.0f); inst->setGain(gain); @@ -291,11 +242,12 @@ void SoundScriptManager::modulate(int actor_id, int mod, float value, int linkTy for (int i = 0; i < free_pitches[mod]; i++) { - SoundScriptInstance* inst = pitches[mod + i * SS_MAX_MOD]; + SoundScriptInstance *inst = pitches[mod + i * SS_MAX_MOD]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { // this one requires modulation - float pitch = value * value * inst->templ->pitch_square + value * inst->templ->pitch_multiplier + inst->templ->pitch_offset; + float pitch = + value * value * inst->templ->pitch_square + value * inst->templ->pitch_multiplier + inst->templ->pitch_offset; pitch = std::max(0.0f, pitch); inst->setPitch(pitch); } @@ -304,12 +256,11 @@ void SoundScriptManager::modulate(int actor_id, int mod, float value, int linkTy void SoundScriptManager::setCamera(Vector3 position, Vector3 direction, Vector3 up, Vector3 velocity) { - if (disabled) - return; + if (disabled) return; sound_manager->setCamera(position, direction, up, velocity); } -const StringVector& SoundScriptManager::getScriptPatterns(void) const +const StringVector &SoundScriptManager::getScriptPatterns(void) const { return script_patterns; } @@ -320,7 +271,7 @@ Real SoundScriptManager::getLoadingOrder(void) const return 1000.0f; } -SoundScriptTemplate* SoundScriptManager::createTemplate(String name, String groupname, String filename) +SoundScriptTemplate *SoundScriptManager::createTemplate(String name, String groupname, String filename) { // first, search if there is a template name collision if (templates.find(name) != templates.end()) @@ -329,15 +280,16 @@ SoundScriptTemplate* SoundScriptManager::createTemplate(String name, String grou return nullptr; } - SoundScriptTemplate* ssi = new SoundScriptTemplate(name, groupname, filename, loading_base); - templates[name] = ssi; + SoundScriptTemplate *ssi = new SoundScriptTemplate(name, groupname, filename, loading_base); + templates[name] = ssi; return ssi; } -SoundScriptInstance* SoundScriptManager::createInstance(Ogre::String templatename, int actor_id, Ogre::SceneNode* toAttach, int soundLinkType, int soundLinkItemId) +SoundScriptInstance *SoundScriptManager::createInstance(Ogre::String templatename, int actor_id, Ogre::SceneNode *toAttach, + int soundLinkType, int soundLinkItemId) { - //first, search template - SoundScriptTemplate* templ = NULL; + // first, search template + SoundScriptTemplate *templ = NULL; if (templates.find(templatename) == templates.end()) { @@ -351,15 +303,17 @@ SoundScriptInstance* SoundScriptManager::createInstance(Ogre::String templatenam return NULL; // invalid template! } - if (free_trigs[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP - || (free_gains[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP && templ->gain_source != SS_MOD_NONE) - || (free_pitches[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP && templ->pitch_source != SS_MOD_NONE)) + if (free_trigs[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP || + (free_gains[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP && templ->gain_source != SS_MOD_NONE) || + (free_pitches[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP && templ->pitch_source != SS_MOD_NONE)) { LOG("SoundScriptManager: Reached MAX_INSTANCES_PER_GROUP limit (" + TOSTRING(MAX_INSTANCES_PER_GROUP) + ")"); return NULL; // reached limit! } - SoundScriptInstance* inst = new SoundScriptInstance(actor_id, templ, sound_manager, templ->file_name + "-" + TOSTRING(actor_id) + "-" + TOSTRING(instance_counter), soundLinkType, soundLinkItemId); + SoundScriptInstance *inst = new SoundScriptInstance( + actor_id, templ, sound_manager, templ->file_name + "-" + TOSTRING(actor_id) + "-" + TOSTRING(instance_counter), + soundLinkType, soundLinkItemId); instance_counter++; // register to lookup tables @@ -378,21 +332,18 @@ SoundScriptInstance* SoundScriptManager::createInstance(Ogre::String templatenam } // SoundTrigger: SS_TRIG_ALWAYSON - if (templ->trigger_source == SS_TRIG_ALWAYSON) - { - inst->start(); - } + if (templ->trigger_source == SS_TRIG_ALWAYSON) { inst->start(); } return inst; } -void SoundScriptManager::parseScript(DataStreamPtr& stream, const String& groupName) +void SoundScriptManager::parseScript(DataStreamPtr &stream, const String &groupName) { - SoundScriptTemplate* sst = 0; - String line = ""; - std::vector vecparams; + SoundScriptTemplate *sst = 0; + String line = ""; + std::vector vecparams; - LOG("SoundScriptManager: Parsing script "+stream->getName()); + LOG("SoundScriptManager: Parsing script " + stream->getName()); while (!stream->eof()) { @@ -404,12 +355,12 @@ void SoundScriptManager::parseScript(DataStreamPtr& stream, const String& groupN { // no current SoundScript // so first valid data should be a SoundScript name - LOG("SoundScriptManager: creating template "+line); + LOG("SoundScriptManager: creating template " + line); sst = createTemplate(line, groupName, stream->getName()); if (!sst) { // there is a name collision for this Sound Script - LOG("SoundScriptManager: Error, this sound script is already defined: "+line); + LOG("SoundScriptManager: Error, this sound script is already defined: " + line); skipToNextOpenBrace(stream); skipToNextCloseBrace(stream); continue; @@ -432,16 +383,14 @@ void SoundScriptManager::parseScript(DataStreamPtr& stream, const String& groupN Ogre::StringVector veclineparams = StringUtil::split(line, "\t ", 0); if (!sst->setParameter(veclineparams)) - { - LOG("Bad SoundScript attribute line: '" + line + "' in " + stream->getName()); - } + { LOG("Bad SoundScript attribute line: '" + line + "' in " + stream->getName()); } } } } } } -void SoundScriptManager::skipToNextCloseBrace(DataStreamPtr& stream) +void SoundScriptManager::skipToNextCloseBrace(DataStreamPtr &stream) { String line = ""; @@ -451,7 +400,7 @@ void SoundScriptManager::skipToNextCloseBrace(DataStreamPtr& stream) } } -void SoundScriptManager::skipToNextOpenBrace(DataStreamPtr& stream) +void SoundScriptManager::skipToNextOpenBrace(DataStreamPtr &stream) { String line = ""; @@ -471,37 +420,21 @@ void SoundScriptManager::setEnabled(bool state) //===================================================================== -SoundScriptTemplate::SoundScriptTemplate(String name, String groupname, String filename, bool baseTemplate) : - base_template(baseTemplate) - , file_name(filename) - , free_sound(0) - , gain_multiplier(1.0f) - , gain_offset(0.0f) - , gain_source(SS_MOD_NONE) - , gain_square(0.0f) - , has_start_sound(false) - , has_stop_sound(false) - , name(name) - , pitch_multiplier(1.0f) - , pitch_offset(0.0f) - , pitch_source(SS_MOD_NONE) - , pitch_square(0.0f) - , start_sound_pitch(0.0f) - , stop_sound_pitch(0.0f) - , trigger_source(SS_TRIG_NONE) - , unpitchable(false) +SoundScriptTemplate::SoundScriptTemplate(String name, String groupname, String filename, bool baseTemplate) + : base_template(baseTemplate), file_name(filename), free_sound(0), gain_multiplier(1.0f), gain_offset(0.0f), + gain_source(SS_MOD_NONE), gain_square(0.0f), has_start_sound(false), has_stop_sound(false), name(name), + pitch_multiplier(1.0f), pitch_offset(0.0f), pitch_source(SS_MOD_NONE), pitch_square(0.0f), start_sound_pitch(0.0f), + stop_sound_pitch(0.0f), trigger_source(SS_TRIG_NONE), unpitchable(false) { } bool SoundScriptTemplate::setParameter(Ogre::StringVector vec) { - if (vec.empty()) - return false; + if (vec.empty()) return false; if (vec[0] == String("trigger_source")) { - if (vec.size() < 2) - return false; + if (vec.size() < 2) return false; if (vec[1] == String("engine")) { trigger_source = SS_TRIG_ENGINE; @@ -838,8 +771,7 @@ bool SoundScriptTemplate::setParameter(Ogre::StringVector vec) if (vec[0] == String("pitch_source")) { - if (vec.size() < 2) - return false; + if (vec.size() < 2) return false; int mod = parseModulation(vec[1]); if (mod >= 0) { @@ -851,21 +783,16 @@ bool SoundScriptTemplate::setParameter(Ogre::StringVector vec) if (vec[0] == String("pitch_factors")) { - if (vec.size() < 3) - return false; - pitch_offset = StringConverter::parseReal(vec[1]); + if (vec.size() < 3) return false; + pitch_offset = StringConverter::parseReal(vec[1]); pitch_multiplier = StringConverter::parseReal(vec[2]); - if (vec.size() == 4) - { - pitch_square = StringConverter::parseReal(vec[3]); - } + if (vec.size() == 4) { pitch_square = StringConverter::parseReal(vec[3]); } return true; } if (vec[0] == String("gain_source")) { - if (vec.size() < 2) - return false; + if (vec.size() < 2) return false; int mod = parseModulation(vec[1]); if (mod >= 0) { @@ -877,55 +804,42 @@ bool SoundScriptTemplate::setParameter(Ogre::StringVector vec) if (vec[0] == String("gain_factors")) { - if (vec.size() < 3) - return false; - gain_offset = StringConverter::parseReal(vec[1]); + if (vec.size() < 3) return false; + gain_offset = StringConverter::parseReal(vec[1]); gain_multiplier = StringConverter::parseReal(vec[2]); - if (vec.size() == 4) - { - gain_square = StringConverter::parseReal(vec[3]); - } + if (vec.size() == 4) { gain_square = StringConverter::parseReal(vec[3]); } return true; } if (vec[0] == String("start_sound")) { - if (vec.size() < 3) - return false; + if (vec.size() < 3) return false; start_sound_pitch = StringConverter::parseReal(vec[1]); // unparsable (e.g. "unpitched") will result in value 0.0 - start_sound_name = vec[2]; - has_start_sound = true; + start_sound_name = vec[2]; + has_start_sound = true; return true; } if (vec[0] == String("stop_sound")) { - if (vec.size() < 3) - return false; + if (vec.size() < 3) return false; stop_sound_pitch = StringConverter::parseReal(vec[1]); // unparsable (e.g. "unpitched") will result in value 0.0 - stop_sound_name = vec[2]; - has_stop_sound = true; + stop_sound_name = vec[2]; + has_stop_sound = true; return true; } if (vec[0] == String("sound")) { - if (vec.size() < 3) - return false; + if (vec.size() < 3) return false; if (free_sound >= MAX_SOUNDS_PER_SCRIPT) { LOG("SoundScriptManager: Reached MAX_SOUNDS_PER_SCRIPT limit (" + TOSTRING(MAX_SOUNDS_PER_SCRIPT) + ")"); return false; } sound_pitches[free_sound] = StringConverter::parseReal(vec[1]); // unparsable (e.g. "unpitched") will result in value 0.0 - if (sound_pitches[free_sound] == 0) - { - unpitchable = true; - } - if (free_sound > 0 && !unpitchable && sound_pitches[free_sound] <= sound_pitches[free_sound - 1]) - { - return false; - } + if (sound_pitches[free_sound] == 0) { unpitchable = true; } + if (free_sound > 0 && !unpitchable && sound_pitches[free_sound] <= sound_pitches[free_sound - 1]) { return false; } sound_names[free_sound] = vec[2]; free_sound++; return true; @@ -936,96 +850,53 @@ bool SoundScriptTemplate::setParameter(Ogre::StringVector vec) int SoundScriptTemplate::parseModulation(String str) { - if (str == String("none")) - return SS_MOD_NONE; - if (str == String("engine_rpm")) - return SS_MOD_ENGINE; - if (str == String("turbo_rpm")) - return SS_MOD_TURBO; - if (str == String("aeroengine1_rpm")) - return SS_MOD_AEROENGINE1; - if (str == String("aeroengine2_rpm")) - return SS_MOD_AEROENGINE2; - if (str == String("aeroengine3_rpm")) - return SS_MOD_AEROENGINE3; - if (str == String("aeroengine4_rpm")) - return SS_MOD_AEROENGINE4; - if (str == String("aeroengine5_rpm")) - return SS_MOD_AEROENGINE5; - if (str == String("aeroengine6_rpm")) - return SS_MOD_AEROENGINE6; - if (str == String("aeroengine7_rpm")) - return SS_MOD_AEROENGINE7; - if (str == String("aeroengine8_rpm")) - return SS_MOD_AEROENGINE8; - if (str == String("wheel_speed_kmph")) - return SS_MOD_WHEELSPEED; - if (str == String("injector_ratio")) - return SS_MOD_INJECTOR; - if (str == String("torque_nm")) - return SS_MOD_TORQUE; - if (str == String("gearbox_rpm")) - return SS_MOD_GEARBOX; - if (str == String("creak")) - return SS_MOD_CREAK; - if (str == String("break")) - return SS_MOD_BREAK; - if (str == String("screetch")) - return SS_MOD_SCREETCH; - if (str == String("pump_rpm")) - return SS_MOD_PUMP; - if (str == String("aeroengine1_throttle")) - return SS_MOD_THROTTLE1; - if (str == String("aeroengine2_throttle")) - return SS_MOD_THROTTLE2; - if (str == String("aeroengine3_throttle")) - return SS_MOD_THROTTLE3; - if (str == String("aeroengine4_throttle")) - return SS_MOD_THROTTLE4; - if (str == String("aeroengine5_throttle")) - return SS_MOD_THROTTLE5; - if (str == String("aeroengine6_throttle")) - return SS_MOD_THROTTLE6; - if (str == String("aeroengine7_throttle")) - return SS_MOD_THROTTLE7; - if (str == String("aeroengine8_throttle")) - return SS_MOD_THROTTLE8; - if (str == String("air_speed_knots")) - return SS_MOD_AIRSPEED; - if (str == String("angle_of_attack_degree")) - return SS_MOD_AOA; - if (str == String("linked_command_rate")) - return SS_MOD_LINKED_COMMANDRATE; - if (str == String("music_volume")) - return SS_MOD_MUSIC_VOLUME; + if (str == String("none")) return SS_MOD_NONE; + if (str == String("engine_rpm")) return SS_MOD_ENGINE; + if (str == String("turbo_rpm")) return SS_MOD_TURBO; + if (str == String("aeroengine1_rpm")) return SS_MOD_AEROENGINE1; + if (str == String("aeroengine2_rpm")) return SS_MOD_AEROENGINE2; + if (str == String("aeroengine3_rpm")) return SS_MOD_AEROENGINE3; + if (str == String("aeroengine4_rpm")) return SS_MOD_AEROENGINE4; + if (str == String("aeroengine5_rpm")) return SS_MOD_AEROENGINE5; + if (str == String("aeroengine6_rpm")) return SS_MOD_AEROENGINE6; + if (str == String("aeroengine7_rpm")) return SS_MOD_AEROENGINE7; + if (str == String("aeroengine8_rpm")) return SS_MOD_AEROENGINE8; + if (str == String("wheel_speed_kmph")) return SS_MOD_WHEELSPEED; + if (str == String("injector_ratio")) return SS_MOD_INJECTOR; + if (str == String("torque_nm")) return SS_MOD_TORQUE; + if (str == String("gearbox_rpm")) return SS_MOD_GEARBOX; + if (str == String("creak")) return SS_MOD_CREAK; + if (str == String("break")) return SS_MOD_BREAK; + if (str == String("screetch")) return SS_MOD_SCREETCH; + if (str == String("pump_rpm")) return SS_MOD_PUMP; + if (str == String("aeroengine1_throttle")) return SS_MOD_THROTTLE1; + if (str == String("aeroengine2_throttle")) return SS_MOD_THROTTLE2; + if (str == String("aeroengine3_throttle")) return SS_MOD_THROTTLE3; + if (str == String("aeroengine4_throttle")) return SS_MOD_THROTTLE4; + if (str == String("aeroengine5_throttle")) return SS_MOD_THROTTLE5; + if (str == String("aeroengine6_throttle")) return SS_MOD_THROTTLE6; + if (str == String("aeroengine7_throttle")) return SS_MOD_THROTTLE7; + if (str == String("aeroengine8_throttle")) return SS_MOD_THROTTLE8; + if (str == String("air_speed_knots")) return SS_MOD_AIRSPEED; + if (str == String("angle_of_attack_degree")) return SS_MOD_AOA; + if (str == String("linked_command_rate")) return SS_MOD_LINKED_COMMANDRATE; + if (str == String("music_volume")) return SS_MOD_MUSIC_VOLUME; return -1; } //==================================================================== -SoundScriptInstance::SoundScriptInstance(int actor_id, SoundScriptTemplate* templ, SoundManager* sound_manager, String instancename, int soundLinkType, int soundLinkItemId) : - actor_id(actor_id) - , templ(templ) - , sound_manager(sound_manager) - , sound_link_type(soundLinkType) - , sound_link_item_id(soundLinkItemId) - , start_sound(NULL) - , start_sound_pitchgain(0.0f) - , stop_sound(NULL) - , stop_sound_pitchgain(0.0f) - , lastgain(1.0f) +SoundScriptInstance::SoundScriptInstance(int actor_id, SoundScriptTemplate *templ, SoundManager *sound_manager, + String instancename, int soundLinkType, int soundLinkItemId) + : actor_id(actor_id), templ(templ), sound_manager(sound_manager), sound_link_type(soundLinkType), + sound_link_item_id(soundLinkItemId), start_sound(NULL), start_sound_pitchgain(0.0f), stop_sound(NULL), + stop_sound_pitchgain(0.0f), lastgain(1.0f) { // create sounds - if (templ->has_start_sound) - { - start_sound = sound_manager->createSound(templ->start_sound_name); - } + if (templ->has_start_sound) { start_sound = sound_manager->createSound(templ->start_sound_name); } - if (templ->has_stop_sound) - { - stop_sound = sound_manager->createSound(templ->stop_sound_name); - } + if (templ->has_stop_sound) { stop_sound = sound_manager->createSound(templ->stop_sound_name); } for (int i = 0; i < templ->free_sound; i++) { @@ -1035,7 +906,7 @@ SoundScriptInstance::SoundScriptInstance(int actor_id, SoundScriptTemplate* temp setPitch(0.0f); setGain(1.0f); - LOG("SoundScriptInstance: instance created: "+instancename); + LOG("SoundScriptInstance: instance created: " + instancename); } void SoundScriptInstance::setPitch(float value) @@ -1045,9 +916,7 @@ void SoundScriptInstance::setPitch(float value) start_sound_pitchgain = pitchgain_cutoff(templ->start_sound_pitch, value); if (start_sound_pitchgain != 0.0f && templ->start_sound_pitch != 0.0f) - { - start_sound->setPitch(value / templ->start_sound_pitch); - } + { start_sound->setPitch(value / templ->start_sound_pitch); } } if (templ->free_sound) @@ -1057,10 +926,7 @@ void SoundScriptInstance::setPitch(float value) for (up = 0; up < templ->free_sound; up++) { - if (templ->sound_pitches[up] > value) - { - break; - } + if (templ->sound_pitches[up] > value) { break; } } if (up == 0) @@ -1069,9 +935,7 @@ void SoundScriptInstance::setPitch(float value) sounds_pitchgain[0] = pitchgain_cutoff(templ->sound_pitches[0], value); if (sounds_pitchgain[0] != 0.0f && templ->sound_pitches[0] != 0.0f && sounds[0]) - { - sounds[0]->setPitch(value / templ->sound_pitches[0]); - } + { sounds[0]->setPitch(value / templ->sound_pitches[0]); } for (int i = 1; i < templ->free_sound; i++) { @@ -1105,9 +969,7 @@ void SoundScriptInstance::setPitch(float value) sounds_pitchgain[templ->free_sound - 1] = 1.0f; if (templ->sound_pitches[templ->free_sound - 1] != 0.0f && sounds[templ->free_sound - 1]) - { - sounds[templ->free_sound - 1]->setPitch(value / templ->sound_pitches[templ->free_sound - 1]); - } + { sounds[templ->free_sound - 1]->setPitch(value / templ->sound_pitches[templ->free_sound - 1]); } } else { @@ -1129,7 +991,8 @@ void SoundScriptInstance::setPitch(float value) if (templ->sound_pitches[low] != 0.0f && sounds[low]) { - sounds_pitchgain[low] = (templ->sound_pitches[up] - value) / (templ->sound_pitches[up] - templ->sound_pitches[low]); + sounds_pitchgain[low] = + (templ->sound_pitches[up] - value) / (templ->sound_pitches[up] - templ->sound_pitches[low]); sounds[low]->setPitch(value / templ->sound_pitches[low]); } else @@ -1139,7 +1002,8 @@ void SoundScriptInstance::setPitch(float value) if (templ->sound_pitches[up] != 0.0f && sounds[up]) { - sounds_pitchgain[up] = (value - templ->sound_pitches[low]) / (templ->sound_pitches[up] - templ->sound_pitches[low]); + sounds_pitchgain[up] = + (value - templ->sound_pitches[low]) / (templ->sound_pitches[up] - templ->sound_pitches[low]); sounds[up]->setPitch(value / templ->sound_pitches[up]); } else @@ -1167,9 +1031,7 @@ void SoundScriptInstance::setPitch(float value) stop_sound_pitchgain = pitchgain_cutoff(templ->stop_sound_pitch, value); if (stop_sound_pitchgain != 0.0f && templ->stop_sound_pitch != 0.0f) - { - stop_sound->setPitch(value / templ->stop_sound_pitch); - } + { stop_sound->setPitch(value / templ->stop_sound_pitch); } } // propagate new gains @@ -1194,28 +1056,20 @@ float SoundScriptInstance::pitchgain_cutoff(float sourcepitch, float targetpitch } // linear fading - return (targetpitch - sourcepitch / PITCHDOWN_CUTOFF_FACTOR) / (sourcepitch / PITCHDOWN_FADE_FACTOR - sourcepitch / PITCHDOWN_CUTOFF_FACTOR); + return (targetpitch - sourcepitch / PITCHDOWN_CUTOFF_FACTOR) / + (sourcepitch / PITCHDOWN_FADE_FACTOR - sourcepitch / PITCHDOWN_CUTOFF_FACTOR); } void SoundScriptInstance::setGain(float value) { - if (start_sound) - { - start_sound->setGain(value * start_sound_pitchgain); - } + if (start_sound) { start_sound->setGain(value * start_sound_pitchgain); } for (int i = 0; i < templ->free_sound; i++) { - if (sounds[i]) - { - sounds[i]->setGain(value * sounds_pitchgain[i]); - } + if (sounds[i]) { sounds[i]->setGain(value * sounds_pitchgain[i]); } } - if (stop_sound) - { - stop_sound->setGain(value * stop_sound_pitchgain); - } + if (stop_sound) { stop_sound->setGain(value * stop_sound_pitchgain); } lastgain = value; } @@ -1248,10 +1102,7 @@ void SoundScriptInstance::runOnce() { if (start_sound) { - if (start_sound->isPlaying()) - { - return; - } + if (start_sound->isPlaying()) { return; } start_sound->play(); } @@ -1259,10 +1110,7 @@ void SoundScriptInstance::runOnce() { if (sounds[i]) { - if (sounds[i]->isPlaying()) - { - continue; - } + if (sounds[i]->isPlaying()) { continue; } sounds[i]->setLoop(false); sounds[i]->play(); } @@ -1270,10 +1118,7 @@ void SoundScriptInstance::runOnce() if (stop_sound) { - if (stop_sound->isPlaying()) - { - return; - } + if (stop_sound->isPlaying()) { return; } stop_sound->play(); } } @@ -1283,7 +1128,7 @@ void SoundScriptInstance::start() if (start_sound) { start_sound->stop(); - //start_sound->setLoop(true); + // start_sound->setLoop(true); start_sound->play(); } @@ -1301,8 +1146,7 @@ void SoundScriptInstance::stop() { for (int i = 0; i < templ->free_sound; i++) { - if (sounds[i]) - sounds[i]->stop(); + if (sounds[i]) sounds[i]->stop(); } if (stop_sound) @@ -1316,12 +1160,10 @@ void SoundScriptInstance::kill() { for (int i = 0; i < templ->free_sound; i++) { - if (sounds[i]) - sounds[i]->stop(); + if (sounds[i]) sounds[i]->stop(); } - if (start_sound) - start_sound->stop(); + if (start_sound) start_sound->stop(); if (stop_sound) { @@ -1332,22 +1174,13 @@ void SoundScriptInstance::kill() void SoundScriptInstance::setEnabled(bool e) { - if (start_sound) - { - start_sound->setEnabled(e); - } + if (start_sound) { start_sound->setEnabled(e); } - if (stop_sound) - { - stop_sound->setEnabled(e); - } + if (stop_sound) { stop_sound->setEnabled(e); } for (int i = 0; i < templ->free_sound; i++) { - if (sounds[i]) - { - sounds[i]->setEnabled(e); - } + if (sounds[i]) { sounds[i]->setEnabled(e); } } } diff --git a/source/main/audio/SoundScriptManager.h b/source/main/audio/SoundScriptManager.h index 7fb70167b4..7db82e14e2 100644 --- a/source/main/audio/SoundScriptManager.h +++ b/source/main/audio/SoundScriptManager.h @@ -21,29 +21,30 @@ #ifdef USE_OPENAL -#pragma once + #pragma once -#include "RoRPrerequisites.h" + #include "RoRPrerequisites.h" + #include "Singleton.h" -#include "Singleton.h" + #include -#include + #define SOUND_PLAY_ONCE(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigOnce((_ACTOR_), (_TRIG_)) + #define SOUND_START(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigStart((_ACTOR_), (_TRIG_)) + #define SOUND_STOP(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigStop((_ACTOR_), (_TRIG_)) + #define SOUND_TOGGLE(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigToggle((_ACTOR_), (_TRIG_)) + #define SOUND_KILL(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigKill((_ACTOR_), (_TRIG_)) + #define SOUND_GET_STATE(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().getTrigState((_ACTOR_), (_TRIG_)) + #define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_) SoundScriptManager::getSingleton().modulate((_ACTOR_), (_MOD_), (_VALUE_)) -#define SOUND_PLAY_ONCE(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigOnce ( (_ACTOR_), (_TRIG_) ) -#define SOUND_START(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigStart ( (_ACTOR_), (_TRIG_) ) -#define SOUND_STOP(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigStop ( (_ACTOR_), (_TRIG_) ) -#define SOUND_TOGGLE(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigToggle ( (_ACTOR_), (_TRIG_) ) -#define SOUND_KILL(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().trigKill ( (_ACTOR_), (_TRIG_) ) -#define SOUND_GET_STATE(_ACTOR_, _TRIG_) SoundScriptManager::getSingleton().getTrigState( (_ACTOR_), (_TRIG_) ) -#define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_) SoundScriptManager::getSingleton().modulate ( (_ACTOR_), (_MOD_), (_VALUE_) ) - -enum { - MAX_SOUNDS_PER_SCRIPT = 16, +enum +{ + MAX_SOUNDS_PER_SCRIPT = 16, MAX_INSTANCES_PER_GROUP = 256 }; -enum SoundTriggers { - SS_TRIG_NONE = -1, +enum SoundTriggers +{ + SS_TRIG_NONE = -1, SS_TRIG_ENGINE = 0, SS_TRIG_AEROENGINE1, SS_TRIG_AEROENGINE2, @@ -113,7 +114,8 @@ enum SoundTriggers { SS_MAX_TRIG }; -enum ModulationSources { +enum ModulationSources +{ SS_MOD_NONE, SS_MOD_ENGINE, SS_MOD_TURBO, @@ -148,21 +150,22 @@ enum ModulationSources { SS_MAX_MOD }; -enum SoundLinkTypes { +enum SoundLinkTypes +{ SL_DEFAULT, - SL_COMMAND, - SL_HYDRO, - SL_COLLISION, - SL_SHOCKS, - SL_BRAKES, - SL_ROPES, - SL_TIES, - SL_PARTICLES, - SL_AXLES, - SL_FLARES, - SL_FLEXBODIES, - SL_EXHAUSTS, - SL_VIDEOCAMERA, + SL_COMMAND, + SL_HYDRO, + SL_COLLISION, + SL_SHOCKS, + SL_BRAKES, + SL_ROPES, + SL_TIES, + SL_PARTICLES, + SL_AXLES, + SL_FLARES, + SL_FLEXBODIES, + SL_EXHAUSTS, + SL_VIDEOCAMERA, SL_MAX }; @@ -175,32 +178,30 @@ class SoundScriptTemplate : public ZeroedMemoryAllocator friend class SoundScriptManager; friend class SoundScriptInstance; -public: - + public: SoundScriptTemplate(Ogre::String name, Ogre::String groupname, Ogre::String filename, bool baseTemplate); - -private: - int parseModulation(Ogre::String str); + private: + int parseModulation(Ogre::String str); bool setParameter(Ogre::StringVector vec); Ogre::String name; Ogre::String file_name; - bool base_template; - bool has_start_sound; - bool has_stop_sound; - bool unpitchable; + bool base_template; + bool has_start_sound; + bool has_stop_sound; + bool unpitchable; - float gain_multiplier; - float gain_offset; - float gain_square; - int gain_source; + float gain_multiplier; + float gain_offset; + float gain_square; + int gain_source; - float pitch_multiplier; - float pitch_offset; - float pitch_square; - int pitch_source; + float pitch_multiplier; + float pitch_offset; + float pitch_square; + int pitch_source; Ogre::String sound_names[MAX_SOUNDS_PER_SCRIPT]; float sound_pitches[MAX_SOUNDS_PER_SCRIPT]; @@ -209,8 +210,8 @@ class SoundScriptTemplate : public ZeroedMemoryAllocator Ogre::String stop_sound_name; float stop_sound_pitch; - int trigger_source; - int free_sound; + int trigger_source; + int free_sound; }; class SoundScriptInstance : public ZeroedMemoryAllocator @@ -218,9 +219,9 @@ class SoundScriptInstance : public ZeroedMemoryAllocator friend class SoundScriptManager; friend class RigInspector; -public: - - SoundScriptInstance(int actor_id, SoundScriptTemplate* templ, SoundManager* sm, Ogre::String instancename, int soundLinkType=SL_DEFAULT, int soundLinkItemId=-1); + public: + SoundScriptInstance(int actor_id, SoundScriptTemplate *templ, SoundManager *sm, Ogre::String instancename, + int soundLinkType = SL_DEFAULT, int soundLinkItemId = -1); void runOnce(); void setEnabled(bool e); void setGain(float value); @@ -233,19 +234,18 @@ class SoundScriptInstance : public ZeroedMemoryAllocator static const float PITCHDOWN_FADE_FACTOR; static const float PITCHDOWN_CUTOFF_FACTOR; -private: - + private: float pitchgain_cutoff(float sourcepitch, float targetpitch); - SoundScriptTemplate* templ; - SoundManager* sound_manager; - Sound *start_sound; - Sound *stop_sound; - Sound *sounds[MAX_SOUNDS_PER_SCRIPT]; - float start_sound_pitchgain; - float stop_sound_pitchgain; - float sounds_pitchgain[MAX_SOUNDS_PER_SCRIPT]; - float lastgain; + SoundScriptTemplate *templ; + SoundManager * sound_manager; + Sound * start_sound; + Sound * stop_sound; + Sound * sounds[MAX_SOUNDS_PER_SCRIPT]; + float start_sound_pitchgain; + float stop_sound_pitchgain; + float sounds_pitchgain[MAX_SOUNDS_PER_SCRIPT]; + float lastgain; int actor_id; // ID of the actor this sound belongs to. int sound_link_type; // holds the SL_ type this is bound to @@ -254,82 +254,87 @@ class SoundScriptInstance : public ZeroedMemoryAllocator class SoundScriptManager : public Ogre::ScriptLoader, public RoRSingleton, public ZeroedMemoryAllocator { -public: - + public: SoundScriptManager(); ~SoundScriptManager(); // ScriptLoader interface - const Ogre::StringVector& getScriptPatterns(void) const; - void parseScript(Ogre::DataStreamPtr& stream, const Ogre::String& groupName); - Ogre::Real getLoadingOrder(void) const; + const Ogre::StringVector &getScriptPatterns(void) const; + void parseScript(Ogre::DataStreamPtr &stream, const Ogre::String &groupName); + Ogre::Real getLoadingOrder(void) const; - SoundScriptInstance* createInstance(Ogre::String templatename, int actor_id, Ogre::SceneNode *toAttach=NULL, int soundLinkType=SL_DEFAULT, int soundLinkItemId=-1); + SoundScriptInstance *createInstance(Ogre::String templatename, int actor_id, Ogre::SceneNode *toAttach = NULL, + int soundLinkType = SL_DEFAULT, int soundLinkItemId = -1); // functions - void trigOnce (int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigOnce (Actor* actor, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigStart (int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigStart (Actor* actor, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigStop (int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigStop (Actor* actor, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigToggle (int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigToggle (Actor* actor, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void trigKill (int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); - void trigKill (Actor* actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); - bool getTrigState(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - bool getTrigState(Actor* actor, int trig, int linkType = SL_DEFAULT, int linkItemID=-1); - void modulate (int actor_id, int mod, float value, int linkType = SL_DEFAULT, int linkItemID=-1); - void modulate (Actor* actor, int mod, float value, int linkType = SL_DEFAULT, int linkItemID=-1); + void trigOnce(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigOnce(Actor *actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigStart(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigStart(Actor *actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigStop(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigStop(Actor *actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigToggle(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigToggle(Actor *actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigKill(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void trigKill(Actor *actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + bool getTrigState(int actor_id, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + bool getTrigState(Actor *actor, int trig, int linkType = SL_DEFAULT, int linkItemID = -1); + void modulate(int actor_id, int mod, float value, int linkType = SL_DEFAULT, int linkItemID = -1); + void modulate(Actor *actor, int mod, float value, int linkType = SL_DEFAULT, int linkItemID = -1); void setEnabled(bool state); void setCamera(Ogre::Vector3 position, Ogre::Vector3 direction, Ogre::Vector3 up, Ogre::Vector3 velocity); - void setLoadingBaseSounds(bool value) { loading_base = value; }; - - bool isDisabled() { return disabled; } - -private: - - SoundScriptTemplate* createTemplate(Ogre::String name, Ogre::String groupname, Ogre::String filename); - void skipToNextCloseBrace(Ogre::DataStreamPtr& chunk); - void skipToNextOpenBrace(Ogre::DataStreamPtr& chunk); - - bool disabled; - bool loading_base; - float max_distance; - float reference_distance; - float rolloff_factor; - int instance_counter; + void setLoadingBaseSounds(bool value) + { + loading_base = value; + }; + + bool isDisabled() + { + return disabled; + } + + private: + SoundScriptTemplate *createTemplate(Ogre::String name, Ogre::String groupname, Ogre::String filename); + void skipToNextCloseBrace(Ogre::DataStreamPtr &chunk); + void skipToNextOpenBrace(Ogre::DataStreamPtr &chunk); + + bool disabled; + bool loading_base; + float max_distance; + float reference_distance; + float rolloff_factor; + int instance_counter; Ogre::StringVector script_patterns; - std::map templates; + std::map templates; // instances lookup tables - int free_trigs[SS_MAX_TRIG]; + int free_trigs[SS_MAX_TRIG]; SoundScriptInstance *trigs[SS_MAX_TRIG * MAX_INSTANCES_PER_GROUP]; - int free_pitches[SS_MAX_MOD]; + int free_pitches[SS_MAX_MOD]; SoundScriptInstance *pitches[SS_MAX_MOD * MAX_INSTANCES_PER_GROUP]; - - int free_gains[SS_MAX_MOD]; + + int free_gains[SS_MAX_MOD]; SoundScriptInstance *gains[SS_MAX_MOD * MAX_INSTANCES_PER_GROUP]; // state map // soundLinks, soundItems, actor_ids, triggers - std::map > > > state_map; + std::map>>> state_map; - SoundManager* sound_manager; + SoundManager *sound_manager; }; #else // USE_OPENAL -#define SOUND_PLAY_ONCE(_ACTOR_, _TRIG_) -#define SOUND_START(_ACTOR_, _TRIG_) -#define SOUND_STOP(_ACTOR_, _TRIG_) -#define SOUND_TOGGLE(_ACTOR_, _TRIG_) -#define SOUND_KILL(_ACTOR_, _TRIG_) -#define SOUND_GET_STATE(_ACTOR_, _TRIG_) (false) -#define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_) + #define SOUND_PLAY_ONCE(_ACTOR_, _TRIG_) + #define SOUND_START(_ACTOR_, _TRIG_) + #define SOUND_STOP(_ACTOR_, _TRIG_) + #define SOUND_TOGGLE(_ACTOR_, _TRIG_) + #define SOUND_KILL(_ACTOR_, _TRIG_) + #define SOUND_GET_STATE(_ACTOR_, _TRIG_) (false) + #define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_) #endif // USE_OPENAL diff --git a/source/main/datatypes/beam_t.h b/source/main/datatypes/beam_t.h index 99f30284c0..a7c18547d7 100644 --- a/source/main/datatypes/beam_t.h +++ b/source/main/datatypes/beam_t.h @@ -24,10 +24,13 @@ /// Simulation: An edge in the softbody structure struct beam_t { - beam_t() { memset(this, 0, sizeof(beam_t)); } + beam_t() + { + memset(this, 0, sizeof(beam_t)); + } - node_t *p1; - node_t *p2; + node_t * p1; + node_t * p2; Ogre::Real k; //!< tensile spring Ogre::Real d; //!< damping factor Ogre::Real L; //!< length @@ -37,11 +40,11 @@ struct beam_t Ogre::Real strength; Ogre::Real stress; Ogre::Real plastic_coef; - int detacher_group; //!< Attribute: detacher group number (integer) - short bounded; //!< { SHOCK1=1, SHOCK2=2, SHOCK3=3, TRIGGER=4, SUPPORTBEAM=5, ROPE=6 } - short bm_type; //!< { BEAM_NORMAL, BEAM_HYDRO, BEAM_VIRTUAL } - bool bm_inter_actor; //!< in case p2 is on another actor - Actor* bm_locked_actor; //!< in case p2 is on another actor + int detacher_group; //!< Attribute: detacher group number (integer) + short bounded; //!< { SHOCK1=1, SHOCK2=2, SHOCK3=3, TRIGGER=4, SUPPORTBEAM=5, ROPE=6 } + short bm_type; //!< { BEAM_NORMAL, BEAM_HYDRO, BEAM_VIRTUAL } + bool bm_inter_actor; //!< in case p2 is on another actor + Actor * bm_locked_actor; //!< in case p2 is on another actor /// Multipurpose; excludes beam from physics, controls visibility (gfx) and indicates multiple other states (hooks/ties). /// Users: @@ -55,7 +58,8 @@ struct beam_t /// Actor::ReplayStep() -- WRITE: fills from replay buffer /// Actor::CalcBeams() -- READ excludes beam from physics /// -- WRITE: when SUPPORTBEAM breaks, it's set to 'disabled' + 'broken' - /// -- WRITE: when regular beam breaks, 'true' is set to it and all beams in it's detacher group. + /// -- WRITE: when regular beam breaks, 'true' is set to it and all beams in it's detacher + /// group. /// Actor::CalcBeamsInterActor() -- READ: excludes beam from physics /// -- WRITE: when beam breaks (special conditions), it's set to 'disabled' + 'broken' /// Actor::calcHooks() -- READ/WRITE: If disabled during locking, it's enabled @@ -82,12 +86,12 @@ struct beam_t Ogre::Real shortbound; Ogre::Real longbound; - Ogre::Real refL; //!< reference length + Ogre::Real refL; //!< reference length shock_t *shock; Ogre::Real initial_beam_strength; ///< for reset - Ogre::Real default_beam_deform; ///< for reset + Ogre::Real default_beam_deform; ///< for reset Ogre::Real debug_k; //< debug shock spring_rate Ogre::Real debug_d; //< debug shock damping diff --git a/source/main/datatypes/node_t.h b/source/main/datatypes/node_t.h index a8f78612f0..cf31e21b0a 100644 --- a/source/main/datatypes/node_t.h +++ b/source/main/datatypes/node_t.h @@ -27,11 +27,20 @@ struct node_t // REFACTOR IN PROGRESS: Currently nodes are adressed mostly by pointers or int32_t indices, // although there was always a hidden soft limit of 2^16 nodes (because of `short node_t::pos`). // Let's use `uint16_t` indices everywhere to be clear. ~ only_a_ptr, 04/2018 - static const uint16_t INVALID_IDX = std::numeric_limits::max(); + static const uint16_t INVALID_IDX = std::numeric_limits::max(); static const int8_t INVALID_BBOX = -1; - node_t() { memset(this, 0, sizeof(node_t)); nd_coll_bbox_id = INVALID_BBOX; } - node_t(size_t _pos) { memset(this, 0, sizeof(node_t)); nd_coll_bbox_id = INVALID_BBOX; pos = static_cast(_pos); } + node_t() + { + memset(this, 0, sizeof(node_t)); + nd_coll_bbox_id = INVALID_BBOX; + } + node_t(size_t _pos) + { + memset(this, 0, sizeof(node_t)); + nd_coll_bbox_id = INVALID_BBOX; + pos = static_cast(_pos); + } Ogre::Vector3 RelPosition; //!< relative to the local physics origin (one origin per actor) (shaky) Ogre::Vector3 AbsPosition; //!< absolute position in the world (shaky) @@ -46,27 +55,27 @@ struct node_t Ogre::Real surface_coef; Ogre::Real volume_coef; - int16_t pos; //!< This node's index in Actor::ar_nodes array. - int16_t nd_coll_bbox_id; //!< Optional attribute (-1 = none) - multiple collision bounding boxes defined in truckfile - int16_t nd_lockgroup; //!< Optional attribute (-1 = default, 9999 = deny lock) - used in the hook lock logic + int16_t pos; //!< This node's index in Actor::ar_nodes array. + int16_t nd_coll_bbox_id; //!< Optional attribute (-1 = none) - multiple collision bounding boxes defined in truckfile + int16_t nd_lockgroup; //!< Optional attribute (-1 = default, 9999 = deny lock) - used in the hook lock logic // Bit flags - bool nd_cab_node:1; //!< Attr; This node is part of collision triangle - bool nd_rim_node:1; //!< Attr; This node is part of a rim - bool nd_tyre_node:1; //!< Attr; This node is part of a tyre - bool nd_contacter:1; //!< Attr; User-defined - bool nd_contactable:1; //!< Attr; This node will be treated as contacter on inter truck collisions - bool nd_has_ground_contact:1; //!< Physics state - bool nd_has_mesh_contact:1; //!< Physics state - bool nd_immovable:1; //!< Attr; User-defined - bool nd_loaded_mass:1; //!< User defined attr; mass is calculated from 'globals/loaded-mass' rather than 'globals/dry-mass' - bool nd_no_ground_contact:1; //!< User-defined attr; node ignores contact with ground - bool nd_override_mass:1; //!< User defined attr; mass is user-specified rather than calculated (override the calculation) - bool nd_under_water:1; //!< State; GFX hint - bool nd_no_mouse_grab:1; //!< Attr; User-defined + bool nd_cab_node : 1; //!< Attr; This node is part of collision triangle + bool nd_rim_node : 1; //!< Attr; This node is part of a rim + bool nd_tyre_node : 1; //!< Attr; This node is part of a tyre + bool nd_contacter : 1; //!< Attr; User-defined + bool nd_contactable : 1; //!< Attr; This node will be treated as contacter on inter truck collisions + bool nd_has_ground_contact : 1; //!< Physics state + bool nd_has_mesh_contact : 1; //!< Physics state + bool nd_immovable : 1; //!< Attr; User-defined + bool nd_loaded_mass : 1; //!< User defined attr; mass is calculated from 'globals/loaded-mass' rather than 'globals/dry-mass' + bool nd_no_ground_contact : 1; //!< User-defined attr; node ignores contact with ground + bool nd_override_mass : 1; //!< User defined attr; mass is user-specified rather than calculated (override the calculation) + bool nd_under_water : 1; //!< State; GFX hint + bool nd_no_mouse_grab : 1; //!< Attr; User-defined Ogre::Real nd_avg_collision_slip; //!< Physics state; average slip velocity across the last few physics frames Ogre::Vector3 nd_last_collision_slip; //!< Physics state; last collision slip vector Ogre::Vector3 nd_last_collision_force; //!< Physics state; last collision force - ground_model_t* nd_last_collision_gm; //!< Physics state; last collision 'ground model' (surface definition) + ground_model_t *nd_last_collision_gm; //!< Physics state; last collision 'ground model' (surface definition) }; diff --git a/source/main/datatypes/shock_t.h b/source/main/datatypes/shock_t.h index c11833dfc0..28409a458b 100644 --- a/source/main/datatypes/shock_t.h +++ b/source/main/datatypes/shock_t.h @@ -22,39 +22,42 @@ #pragma once /** -* SIM-CORE; Shock. -*/ + * SIM-CORE; Shock. + */ struct shock_t { - shock_t() { memset(this, 0, sizeof(shock_t)); } + shock_t() + { + memset(this, 0, sizeof(shock_t)); + } int beamid; int flags; - bool trigger_enabled; //!< general trigger,switch and blocker state + bool trigger_enabled; //!< general trigger,switch and blocker state float trigger_switch_state; //!< needed to avoid doubleswitch, bool and timer in one float trigger_boundary_t; //!< optional value to tune trigger_switch_state autorelease - int trigger_cmdlong; //!< F-key for trigger injection longbound-check - int trigger_cmdshort; //!< F-key for trigger injection shortbound-check - int last_debug_state; //!< smart debug output + int trigger_cmdlong; //!< F-key for trigger injection longbound-check + int trigger_cmdshort; //!< F-key for trigger injection shortbound-check + int last_debug_state; //!< smart debug output float springin; //!< shocks2 & shocks3 float dampin; //!< shocks2 & shocks3 float springout; //!< shocks2 & shocks3 float dampout; //!< shocks2 & shocks3 - float sprogin; //!< shocks2 - float dprogin; //!< shocks2 - float sprogout; //!< shocks2 - float dprogout; //!< shocks2 + float sprogin; //!< shocks2 + float dprogin; //!< shocks2 + float sprogout; //!< shocks2 + float dprogout; //!< shocks2 - float splitin; //!< shocks3 - float dslowin; //!< shocks3 - float dfastin; //!< shocks3 - float splitout; //!< shocks3 - float dslowout; //!< shocks3 - float dfastout; //!< shocks3 + float splitin; //!< shocks3 + float dslowin; //!< shocks3 + float dfastin; //!< shocks3 + float splitout; //!< shocks3 + float dslowout; //!< shocks3 + float dfastout; //!< shocks3 - float sbd_spring; //!< set beam default for spring - float sbd_damp; //!< set beam default for damping + float sbd_spring; //!< set beam default for spring + float sbd_damp; //!< set beam default for damping }; diff --git a/source/main/datatypes/wheel_t.h b/source/main/datatypes/wheel_t.h index a1d43e846d..d39cef4b4e 100644 --- a/source/main/datatypes/wheel_t.h +++ b/source/main/datatypes/wheel_t.h @@ -24,50 +24,53 @@ #include "RoRPrerequisites.h" /** -* SIM-CORE; Wheel. -*/ + * SIM-CORE; Wheel. + */ struct wheel_t { - enum class BrakeCombo /// Wheels are braked by three mechanisms: A footbrake, a handbrake/parkingbrake, and directional brakes used for skidsteer steering. + enum class BrakeCombo /// Wheels are braked by three mechanisms: A footbrake, a handbrake/parkingbrake, and directional brakes + /// used for skidsteer steering. { NONE, /// - 0 = no footbrake, no handbrake, no direction control -- wheel is unbraked FOOT_HAND, /// - 1 = yes footbrake, yes handbrake, no direction control - FOOT_HAND_SKID_LEFT, /// - 2 = yes footbrake, yes handbrake, yes direction control (braked when vehicle steers to the left) - FOOT_HAND_SKID_RIGHT, /// - 3 = yes footbrake, yes handbrake, yes direction control (braked when vehicle steers to the right) - FOOT_ONLY /// - 4 = yes footbrake, no handbrake, no direction control -- footbrake only, such as with the front wheels of a passenger car + FOOT_HAND_SKID_LEFT, /// - 2 = yes footbrake, yes handbrake, yes direction control (braked when vehicle steers to the + /// left) + FOOT_HAND_SKID_RIGHT, /// - 3 = yes footbrake, yes handbrake, yes direction control (braked when vehicle steers to the + /// right) + FOOT_ONLY /// - 4 = yes footbrake, no handbrake, no direction control -- footbrake only, such as with the front wheels + /// of a passenger car }; - int wh_num_nodes; - node_t* wh_nodes[50]; // TODO: remove limit, make this dyn-allocated ~ only_a_ptr, 08/2017 - int wh_num_rim_nodes; - node_t* wh_rim_nodes[50]; // TODO: remove limit, make this dyn-allocated ~ only_a_ptr, 08/2017 - BrakeCombo wh_braking; - node_t* wh_arm_node; - node_t* wh_near_attach_node; - node_t* wh_axis_node_0; - node_t* wh_axis_node_1; - int wh_propulsed; // TODO: add enum ~ only_a_ptr, 08/2017 - Ogre::Real wh_radius; - Ogre::Real wh_rim_radius; - Ogre::Real wh_speed; // -#include - #include "AeroEngine.h" #include "Application.h" #include "AutoPilot.h" @@ -31,48 +28,42 @@ #include "BeamEngine.h" #include "InputEngine.h" +#include +#include + using namespace RoR; -void AircraftSimulation::UpdateInputEvents(Actor* vehicle, float seconds_since_last_frame) +void AircraftSimulation::UpdateInputEvents(Actor *vehicle, float seconds_since_last_frame) { - if (vehicle->isBeingReset() || vehicle->ar_physics_paused || vehicle->ar_replay_mode) - return; - //autopilot - if (vehicle->ar_autopilot && vehicle->ar_autopilot->wantsdisconnect) - { - vehicle->ar_autopilot->disconnect(); - } - //AIRPLANE KEYS + if (vehicle->isBeingReset() || vehicle->ar_physics_paused || vehicle->ar_replay_mode) return; + // autopilot + if (vehicle->ar_autopilot && vehicle->ar_autopilot->wantsdisconnect) { vehicle->ar_autopilot->disconnect(); } + // AIRPLANE KEYS float commandrate = 4.0; - float tmp_left = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_STEER_LEFT); - float tmp_right = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_STEER_RIGHT); - float sum_steer = -tmp_left + tmp_right; + float tmp_left = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_STEER_LEFT); + float tmp_right = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_STEER_RIGHT); + float sum_steer = -tmp_left + tmp_right; RoR::App::GetInputEngine()->smoothValue(vehicle->ar_aileron, sum_steer, seconds_since_last_frame * commandrate); - vehicle->ar_hydro_dir_command = vehicle->ar_aileron; - vehicle->ar_hydro_speed_coupling = !(RoR::App::GetInputEngine()->isEventAnalog(EV_AIRPLANE_STEER_LEFT) && RoR::App::GetInputEngine()->isEventAnalog(EV_AIRPLANE_STEER_RIGHT)); + vehicle->ar_hydro_dir_command = vehicle->ar_aileron; + vehicle->ar_hydro_speed_coupling = !(RoR::App::GetInputEngine()->isEventAnalog(EV_AIRPLANE_STEER_LEFT) && + RoR::App::GetInputEngine()->isEventAnalog(EV_AIRPLANE_STEER_RIGHT)); - //pitch - float tmp_pitch_up = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_ELEVATOR_UP); + // pitch + float tmp_pitch_up = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_ELEVATOR_UP); float tmp_pitch_down = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_ELEVATOR_DOWN); - float sum_pitch = tmp_pitch_down - tmp_pitch_up; + float sum_pitch = tmp_pitch_down - tmp_pitch_up; RoR::App::GetInputEngine()->smoothValue(vehicle->ar_elevator, sum_pitch, seconds_since_last_frame * commandrate); - //rudder - float tmp_rudder_left = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_RUDDER_LEFT); + // rudder + float tmp_rudder_left = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_RUDDER_LEFT); float tmp_rudder_right = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_RUDDER_RIGHT); - float sum_rudder = tmp_rudder_left - tmp_rudder_right; + float sum_rudder = tmp_rudder_left - tmp_rudder_right; RoR::App::GetInputEngine()->smoothValue(vehicle->ar_rudder, sum_rudder, seconds_since_last_frame * commandrate); - //brake - if (!vehicle->ar_parking_brake) - { - vehicle->ar_brake = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_BRAKE) * 0.66f; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_PARKING_BRAKE)) - { - vehicle->ToggleParkingBrake(); - } - //reverse + // brake + if (!vehicle->ar_parking_brake) { vehicle->ar_brake = RoR::App::GetInputEngine()->getEventValue(EV_AIRPLANE_BRAKE) * 0.66f; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_PARKING_BRAKE)) { vehicle->ToggleParkingBrake(); } + // reverse if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_REVERSE)) { for (int i = 0; i < vehicle->ar_num_aeroengines; i++) @@ -90,67 +81,43 @@ void AircraftSimulation::UpdateInputEvents(Actor* vehicle, float seconds_since_l } } - //flaps + // flaps if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_FLAPS_NONE)) { - if (vehicle->ar_aerial_flap > 0) - { - vehicle->ar_aerial_flap = 0; - } + if (vehicle->ar_aerial_flap > 0) { vehicle->ar_aerial_flap = 0; } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_FLAPS_FULL)) { - if (vehicle->ar_aerial_flap < 5) - { - vehicle->ar_aerial_flap = 5; - } + if (vehicle->ar_aerial_flap < 5) { vehicle->ar_aerial_flap = 5; } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_FLAPS_LESS)) { - if (vehicle->ar_aerial_flap > 0) - { - vehicle->ar_aerial_flap = (vehicle->ar_aerial_flap) - 1; - } + if (vehicle->ar_aerial_flap > 0) { vehicle->ar_aerial_flap = (vehicle->ar_aerial_flap) - 1; } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_FLAPS_MORE)) { - if (vehicle->ar_aerial_flap < 5) - { - vehicle->ar_aerial_flap = (vehicle->ar_aerial_flap) + 1; - } + if (vehicle->ar_aerial_flap < 5) { vehicle->ar_aerial_flap = (vehicle->ar_aerial_flap) + 1; } } - //airbrakes + // airbrakes if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_AIRBRAKES_NONE)) { - if (vehicle->ar_airbrake_intensity > 0) - { - vehicle->setAirbrakeIntensity(0); - } + if (vehicle->ar_airbrake_intensity > 0) { vehicle->setAirbrakeIntensity(0); } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_AIRBRAKES_FULL)) { - if (vehicle->ar_airbrake_intensity < 5) - { - vehicle->setAirbrakeIntensity(5); - } + if (vehicle->ar_airbrake_intensity < 5) { vehicle->setAirbrakeIntensity(5); } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_AIRBRAKES_LESS)) { - if (vehicle->ar_airbrake_intensity > 0) - { - vehicle->setAirbrakeIntensity((vehicle->ar_airbrake_intensity) - 1); - } + if (vehicle->ar_airbrake_intensity > 0) { vehicle->setAirbrakeIntensity((vehicle->ar_airbrake_intensity) - 1); } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_AIRBRAKES_MORE)) { - if (vehicle->ar_airbrake_intensity < 5) - { - vehicle->setAirbrakeIntensity((vehicle->ar_airbrake_intensity) + 1); - } + if (vehicle->ar_airbrake_intensity < 5) { vehicle->setAirbrakeIntensity((vehicle->ar_airbrake_intensity) + 1); } } - //throttle + // throttle float tmp_throttle = RoR::App::GetInputEngine()->getEventBoolValue(EV_AIRPLANE_THROTTLE); if (tmp_throttle > 0) { @@ -169,7 +136,7 @@ void AircraftSimulation::UpdateInputEvents(Actor* vehicle, float seconds_since_l } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_THROTTLE_DOWN, 0.1f)) { - //throttle down + // throttle down for (int i = 0; i < vehicle->ar_num_aeroengines; i++) { vehicle->ar_aeroengines[i]->setThrottle(vehicle->ar_aeroengines[i]->getThrottle() - 0.05); @@ -177,7 +144,7 @@ void AircraftSimulation::UpdateInputEvents(Actor* vehicle, float seconds_since_l } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_AIRPLANE_THROTTLE_UP, 0.1f)) { - //throttle up + // throttle up for (int i = 0; i < vehicle->ar_num_aeroengines; i++) { vehicle->ar_aeroengines[i]->setThrottle(vehicle->ar_aeroengines[i]->getThrottle() + 0.05); @@ -203,7 +170,8 @@ void AircraftSimulation::UpdateInputEvents(Actor* vehicle, float seconds_since_l { for (int i = 0; i < vehicle->ar_num_aeroengines; i++) { - vehicle->ar_aeroengines[i]->setThrottle(vehicle->ar_autopilot->getThrottle(vehicle->ar_aeroengines[i]->getThrottle(), seconds_since_last_frame)); + vehicle->ar_aeroengines[i]->setThrottle( + vehicle->ar_autopilot->getThrottle(vehicle->ar_aeroengines[i]->getThrottle(), seconds_since_last_frame)); } } } diff --git a/source/main/gameplay/AircraftSimulation.h b/source/main/gameplay/AircraftSimulation.h index 101d5d221c..6012309b61 100644 --- a/source/main/gameplay/AircraftSimulation.h +++ b/source/main/gameplay/AircraftSimulation.h @@ -26,17 +26,18 @@ #include "ForwardDeclarations.h" -namespace RoR { - -/** -* Stateless class which provides simulation logic. -*/ -struct AircraftSimulation +namespace RoR { + /** - * SIM-CORE: 1x per frame. Logic: input, GUI, vehicle state. - */ - static void UpdateInputEvents(Actor* vehicle, float seconds_since_last_frame); -}; + * Stateless class which provides simulation logic. + */ + struct AircraftSimulation + { + /** + * SIM-CORE: 1x per frame. Logic: input, GUI, vehicle state. + */ + static void UpdateInputEvents(Actor *vehicle, float seconds_since_last_frame); + }; } // namespace RoR diff --git a/source/main/gameplay/AutoPilot.cpp b/source/main/gameplay/AutoPilot.cpp index 08a3800b44..34e70d72a5 100644 --- a/source/main/gameplay/AutoPilot.cpp +++ b/source/main/gameplay/AutoPilot.cpp @@ -29,61 +29,57 @@ using namespace Ogre; using namespace RoR; -Autopilot::Autopilot(int actor_id): - m_actor_id(actor_id) +Autopilot::Autopilot(int actor_id) : m_actor_id(actor_id) { - ref_l = nullptr; - ref_r = nullptr; - ref_b = nullptr; - ref_c = nullptr; + ref_l = nullptr; + ref_r = nullptr; + ref_b = nullptr; + ref_c = nullptr; ref_span = 1.0f; reset(); } void Autopilot::reset() { - mode_heading = HEADING_NONE; - mode_alt = ALT_NONE; - mode_ias = false; - mode_gpws = true; - heading = 0; - alt = 1000; - vs = 0; - ias = 150; - last_elevator = 0; - last_rudder = 0; - last_aileron = 0; - last_gpws_height = 0; - last_pullup_height = 0; - m_ils_angle_vdev = -90; - m_ils_angle_hdev = -90; - m_ils_runway_heading = 0; + mode_heading = HEADING_NONE; + mode_alt = ALT_NONE; + mode_ias = false; + mode_gpws = true; + heading = 0; + alt = 1000; + vs = 0; + ias = 150; + last_elevator = 0; + last_rudder = 0; + last_aileron = 0; + last_gpws_height = 0; + last_pullup_height = 0; + m_ils_angle_vdev = -90; + m_ils_angle_hdev = -90; + m_ils_runway_heading = 0; m_ils_runway_distance = 0; - last_closest_hdist = 0; - wantsdisconnect = false; + last_closest_hdist = 0; + wantsdisconnect = false; - m_vertical_locator_available = false; + m_vertical_locator_available = false; m_horizontal_locator_available = false; } void Autopilot::disconnect() { - mode_heading = HEADING_NONE; - mode_alt = ALT_NONE; - mode_ias = false; + mode_heading = HEADING_NONE; + mode_alt = ALT_NONE; + mode_ias = false; wantsdisconnect = false; - if (mode_gpws) - { - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_APDISCONNECT); - } + if (mode_gpws) { SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_APDISCONNECT); } } -void Autopilot::setInertialReferences(node_t* refl, node_t* refr, node_t* refb, node_t* refc) +void Autopilot::setInertialReferences(node_t *refl, node_t *refr, node_t *refb, node_t *refc) { - ref_l = refl; - ref_r = refr; - ref_b = refb; - ref_c = refc; // ar_camera_node_pos(0) + ref_l = refl; + ref_r = refr; + ref_b = refb; + ref_c = refc; // ar_camera_node_pos(0) ref_span = (refl->RelPosition - refr->RelPosition).length(); } @@ -92,7 +88,7 @@ float Autopilot::getAilerons() float val = 0; if (ref_l && ref_r) { - float rat = (ref_r->RelPosition.y - ref_l->RelPosition.y) / ref_span; + float rat = (ref_r->RelPosition.y - ref_l->RelPosition.y) / ref_span; float bank = 90.0; if (rat >= 1.0) bank = 90.0; @@ -103,56 +99,41 @@ float Autopilot::getAilerons() if (mode_heading == HEADING_WLV) { val = bank / 100.0; - if (val > 0.5) - val = 0.5; - if (val < -0.5) - val = -0.5; + if (val > 0.5) val = 0.5; + if (val < -0.5) val = -0.5; } if (mode_heading == HEADING_FIXED) { - Vector3 vel = (ref_l->Velocity + ref_r->Velocity) / 2.0; - float curdir = atan2(vel.x, -vel.z) * 57.295779513082; - float want_bank = curdir - (float)heading; - if (want_bank < -180.0) - want_bank += 360.0; + Vector3 vel = (ref_l->Velocity + ref_r->Velocity) / 2.0; + float curdir = atan2(vel.x, -vel.z) * 57.295779513082; + float want_bank = curdir - (float)heading; + if (want_bank < -180.0) want_bank += 360.0; want_bank = want_bank * 2.0; - if (want_bank > 45.0) - want_bank = 45.0; - if (want_bank < -45.0) - want_bank = -45.0; + if (want_bank > 45.0) want_bank = 45.0; + if (want_bank < -45.0) want_bank = -45.0; val = (bank - want_bank) / 100.0; - if (val > 0.5) - val = 0.5; - if (val < -0.5) - val = -0.5; + if (val > 0.5) val = 0.5; + if (val < -0.5) val = -0.5; } if (mode_heading == HEADING_NAV) { - //compute intercept heading + // compute intercept heading float error_heading = m_ils_angle_hdev / 10.0; - if (error_heading > 1.0) - error_heading = 1.0; - if (error_heading < -1.0) - error_heading = -1.0; + if (error_heading > 1.0) error_heading = 1.0; + if (error_heading < -1.0) error_heading = -1.0; float offcourse_tolerance = m_ils_runway_distance / 30.0; - if (offcourse_tolerance > 60.0) - offcourse_tolerance = 60.0; - float intercept_heading = m_ils_runway_heading + error_heading * offcourse_tolerance; - Vector3 vel = (ref_l->Velocity + ref_r->Velocity) / 2.0; - float curdir = atan2(vel.x, -vel.z) * 57.295779513082; - float want_bank = curdir - intercept_heading; - if (want_bank < -180.0) - want_bank += 360.0; + if (offcourse_tolerance > 60.0) offcourse_tolerance = 60.0; + float intercept_heading = m_ils_runway_heading + error_heading * offcourse_tolerance; + Vector3 vel = (ref_l->Velocity + ref_r->Velocity) / 2.0; + float curdir = atan2(vel.x, -vel.z) * 57.295779513082; + float want_bank = curdir - intercept_heading; + if (want_bank < -180.0) want_bank += 360.0; want_bank = want_bank * 2.0; - if (want_bank > 45.0) - want_bank = 45.0; - if (want_bank < -45.0) - want_bank = -45.0; + if (want_bank > 45.0) want_bank = 45.0; + if (want_bank < -45.0) want_bank = -45.0; val = (bank - want_bank) / 100.0; - if (val > 0.5) - val = 0.5; - if (val < -0.5) - val = -0.5; + if (val > 0.5) val = 0.5; + if (val < -0.5) val = -0.5; } } last_aileron = (last_aileron + val) / 2.0; @@ -164,53 +145,42 @@ float Autopilot::getElevator() float val = 0; if (ref_l && ref_r && ref_b) { - float wanted_vs = (float)vs / 196.87; + float wanted_vs = (float)vs / 196.87; float current_vs = (ref_l->Velocity.y + ref_r->Velocity.y) / 2.0; - float pitch_var = current_vs - ref_b->Velocity.y; + float pitch_var = current_vs - ref_b->Velocity.y; if (mode_alt == ALT_VS) { if (mode_heading == HEADING_NAV) { - //this is cheating a bit - float ch = m_ils_runway_distance * sin((m_ils_angle_vdev + 4.0) / 57.295779513082); - float oh = m_ils_runway_distance * sin((4.0) / 57.295779513082); - wanted_vs = 5000.0 / 196.87; + // this is cheating a bit + float ch = m_ils_runway_distance * sin((m_ils_angle_vdev + 4.0) / 57.295779513082); + float oh = m_ils_runway_distance * sin((4.0) / 57.295779513082); + wanted_vs = 5000.0 / 196.87; float wanted_vs2 = (-ch + oh) / 5.0; - if (wanted_vs2 < -wanted_vs) - wanted_vs2 = -wanted_vs; - if (wanted_vs2 > wanted_vs) - wanted_vs2 = wanted_vs; + if (wanted_vs2 < -wanted_vs) wanted_vs2 = -wanted_vs; + if (wanted_vs2 > wanted_vs) wanted_vs2 = wanted_vs; val = (wanted_vs2 - current_vs) / 40.0 + pitch_var / 40.0; - if (val > 0.75) - val = 0.75; - if (val < -0.75) - val = -0.75; + if (val > 0.75) val = 0.75; + if (val < -0.75) val = -0.75; } else { val = (wanted_vs - current_vs) / 40.0 + pitch_var / 40.0; - if (val > 0.5) - val = 0.5; - if (val < -0.5) - val = -0.5; + if (val > 0.5) val = 0.5; + if (val < -0.5) val = -0.5; } } if (mode_alt == ALT_FIXED) { - float wanted_alt = (float)alt * 0.3048; + float wanted_alt = (float)alt * 0.3048; float current_alt = (ref_l->AbsPosition.y + ref_r->AbsPosition.y) / 2.0; - if (wanted_vs < 0) - wanted_vs = -wanted_vs; //absolute value + if (wanted_vs < 0) wanted_vs = -wanted_vs; // absolute value float wanted_vs2 = (wanted_alt - current_alt) / 8.0; - if (wanted_vs2 < -wanted_vs) - wanted_vs2 = -wanted_vs; - if (wanted_vs2 > wanted_vs) - wanted_vs2 = wanted_vs; + if (wanted_vs2 < -wanted_vs) wanted_vs2 = -wanted_vs; + if (wanted_vs2 > wanted_vs) wanted_vs2 = wanted_vs; val = (wanted_vs2 - current_vs) / 40.0 + pitch_var / 40.0; - if (val > 0.5) - val = 0.5; - if (val < -0.5) - val = -0.5; + if (val > 0.5) val = 0.5; + if (val < -0.5) val = -0.5; } } return val; @@ -228,26 +198,22 @@ float Autopilot::getThrottle(float thrtl, float dt) float val = thrtl; if (ref_l && ref_r) { - //tropospheric model valid up to 11.000m (33.000ft) + // tropospheric model valid up to 11.000m (33.000ft) float altitude = ref_l->AbsPosition.y; - //float sea_level_temperature=273.15+15.0; //in Kelvin - float sea_level_pressure = 101325; //in Pa - //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin - float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa - float airdensity = airpressure * 0.0000120896;//1.225 at sea level + // float sea_level_temperature=273.15+15.0; //in Kelvin + float sea_level_pressure = 101325; // in Pa + // float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin + float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896; // 1.225 at sea level float gspd = 1.94384449 * ((ref_l->Velocity + ref_r->Velocity) / 2.0).length(); - float spd = gspd * sqrt(airdensity / 1.225); //KIAS + float spd = gspd * sqrt(airdensity / 1.225); // KIAS - if (spd > (float)ias) - val = val - dt / 15.0; - if (spd < (float)ias) - val = val + dt / 15.0; - if (val > 1.0) - val = 1.0; - if (val < 0.02) - val = 0.02; + if (spd > (float)ias) val = val - dt / 15.0; + if (spd < (float)ias) val = val + dt / 15.0; + if (val > 1.0) val = 1.0; + if (val < 0.02) val = 0.02; } return val; } @@ -285,10 +251,8 @@ bool Autopilot::toggleGPWS() int Autopilot::adjHDG(int d) { heading += d; - if (heading < 0) - heading += 360; - if (heading > 359) - heading -= 360; + if (heading < 0) heading += 360; + if (heading > 359) heading -= 360; return heading; } @@ -301,49 +265,38 @@ int Autopilot::adjALT(int d) int Autopilot::adjVS(int d) { vs += d; - if (vs > 9900) - vs = 9900; - if (vs < -9900) - vs = -9900; + if (vs > 9900) vs = 9900; + if (vs < -9900) vs = -9900; return vs; } int Autopilot::adjIAS(int d) { ias += d; - if (ias < 0) - ias = 0; - if (ias > 350) - ias = 350; + if (ias < 0) ias = 0; + if (ias > 350) ias = 350; return ias; } void Autopilot::gpws_update(float spawnheight) { #ifdef USE_OPENAL - if (SoundScriptManager::getSingleton().isDisabled()) - return; + if (SoundScriptManager::getSingleton().isDisabled()) return; if (mode_gpws && ref_b) { float groundalt = App::GetSimTerrain()->GetHeightAt(ref_c->AbsPosition.x, ref_c->AbsPosition.z); if (App::GetSimTerrain()->getWater() && groundalt < App::GetSimTerrain()->getWater()->GetStaticWaterHeight()) groundalt = App::GetSimTerrain()->getWater()->GetStaticWaterHeight(); - float height = (ref_c->AbsPosition.y - groundalt - spawnheight) * 3.28083f; //in feet! - //skip height warning sounds when the plane is slower then ~10 knots + float height = (ref_c->AbsPosition.y - groundalt - spawnheight) * 3.28083f; // in feet! + // skip height warning sounds when the plane is slower then ~10 knots if ((ref_c->Velocity.length() * 1.9685f) > 10.0f) { - if (height < 10 && last_gpws_height > 10) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_10); - if (height < 20 && last_gpws_height > 20) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_20); - if (height < 30 && last_gpws_height > 30) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_30); - if (height < 40 && last_gpws_height > 40) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_40); - if (height < 50 && last_gpws_height > 50) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_50); - if (height < 100 && last_gpws_height > 100) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_100); + if (height < 10 && last_gpws_height > 10) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_10); + if (height < 20 && last_gpws_height > 20) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_20); + if (height < 30 && last_gpws_height > 30) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_30); + if (height < 40 && last_gpws_height > 40) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_40); + if (height < 50 && last_gpws_height > 50) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_50); + if (height < 100 && last_gpws_height > 100) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_100); } last_gpws_height = height; @@ -352,74 +305,69 @@ void Autopilot::gpws_update(float spawnheight) height *= 0.3048; // get the y-velocity in meters/s float yVel = ref_c->Velocity.y * 1.9685f; - // will trigger the pullup sound when vvi is high (avoid pullup warning when landing normal) and groundcontact will be in less then 10 seconds - if (yVel * 10.0f < -height && yVel < -10.0f) - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_PULLUP); + // will trigger the pullup sound when vvi is high (avoid pullup warning when landing normal) and groundcontact will be in + // less then 10 seconds + if (yVel * 10.0f < -height && yVel < -10.0f) SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_PULLUP); } -#endif //OPENAL +#endif // OPENAL } void Autopilot::UpdateIls(std::vector localizers) { - if (!ref_l || !ref_r) - return; - Vector3 position = (ref_l->AbsPosition + ref_r->AbsPosition) / 2.0; - float closest_hdist = -1; - float closest_hangle = -90; - float closest_vdist = -1; - float closest_vangle = -90; - m_ils_runway_heading = 0; + if (!ref_l || !ref_r) return; + Vector3 position = (ref_l->AbsPosition + ref_r->AbsPosition) / 2.0; + float closest_hdist = -1; + float closest_hangle = -90; + float closest_vdist = -1; + float closest_vangle = -90; + m_ils_runway_heading = 0; for (std::vector::size_type i = 0; i < localizers.size(); i++) { - Plane hplane = Plane(Vector3::UNIT_Y, 0); - Vector3 plocd = hplane.projectVector(localizers[i].rotation * Vector3::UNIT_Z); - float loc = atan2(plocd.z, plocd.x); - Vector3 posd = hplane.projectVector(position - localizers[i].position); - float dir = atan2(posd.z, posd.x); - float diff = (dir - loc) * 57.295779513082; - if (diff > 180.0) - diff -= 360.0; - if (diff < -180.0) - diff += 360.0; + Plane hplane = Plane(Vector3::UNIT_Y, 0); + Vector3 plocd = hplane.projectVector(localizers[i].rotation * Vector3::UNIT_Z); + float loc = atan2(plocd.z, plocd.x); + Vector3 posd = hplane.projectVector(position - localizers[i].position); + float dir = atan2(posd.z, posd.x); + float diff = (dir - loc) * 57.295779513082; + if (diff > 180.0) diff -= 360.0; + if (diff < -180.0) diff += 360.0; if (diff < 80 && diff > -80) { - //we are in the visibility cone, we search the closest + // we are in the visibility cone, we search the closest float dist = (localizers[i].position - position).length(); - //horizontal + // horizontal if (localizers[i].type == Autopilot::LOCALIZER_HORIZONTAL) { if (closest_hdist < 0 || closest_hdist > dist) { - closest_hdist = dist; - closest_hangle = diff; - m_ils_runway_heading = loc * 57.295779513082 - 90.0; //dont ask me why - if (m_ils_runway_heading < 0.0) - m_ils_runway_heading += 360.0; + closest_hdist = dist; + closest_hangle = diff; + m_ils_runway_heading = loc * 57.295779513082 - 90.0; // dont ask me why + if (m_ils_runway_heading < 0.0) m_ils_runway_heading += 360.0; m_ils_runway_distance = dist; } } - //vertical + // vertical if (localizers[i].type == Autopilot::LOCALIZER_VERTICAL) { if (closest_vdist < 0 || closest_vdist > dist) { - Vector3 normv = (localizers[i].rotation * Vector3::UNIT_Z).crossProduct(Vector3::UNIT_Y); - Plane vplane = Plane(normv, 0); - float glideslope = 4; //4 degree is the norm - Vector3 posd2 = vplane.projectVector(position - localizers[i].position); - float d = posd2.length(); - if (d < 0.01) - d = 0.01; + Vector3 normv = (localizers[i].rotation * Vector3::UNIT_Z).crossProduct(Vector3::UNIT_Y); + Plane vplane = Plane(normv, 0); + float glideslope = 4; // 4 degree is the norm + Vector3 posd2 = vplane.projectVector(position - localizers[i].position); + float d = posd2.length(); + if (d < 0.01) d = 0.01; float dir2 = 90.0; - d = posd2.y / d; + d = posd2.y / d; if (d >= 1.0) dir2 = 90.0; else if (d <= -1.0) dir2 = -90.0; else dir2 = asin(d) * 57.295779513082; - float diff2 = dir2 - glideslope; - closest_vdist = dist; + float diff2 = dir2 - glideslope; + closest_vdist = dist; closest_vangle = diff2; } } @@ -429,21 +377,17 @@ void Autopilot::UpdateIls(std::vector localiz m_ils_angle_vdev = closest_vangle; m_horizontal_locator_available = (closest_hdist != -1); - m_vertical_locator_available = (closest_vdist != -1); + m_vertical_locator_available = (closest_vdist != -1); - if (mode_heading == HEADING_NAV && mode_gpws && closest_hdist > 10.0 && closest_hdist < 350.0 && last_closest_hdist > 10.0 && last_closest_hdist > 350.0) - { - SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_MINIMUMS); - } + if (mode_heading == HEADING_NAV && mode_gpws && closest_hdist > 10.0 && closest_hdist < 350.0 && last_closest_hdist > 10.0 && + last_closest_hdist > 350.0) + { SOUND_PLAY_ONCE(m_actor_id, SS_TRIG_GPWS_MINIMUMS); } last_closest_hdist = closest_hdist; if (mode_heading == HEADING_NAV) { // disconnect if close to runway or no locators are available - if (closest_hdist < 20.0 || closest_vdist < 20.0) - wantsdisconnect = true; - if (!this->IsIlsAvailable()) - wantsdisconnect = true; + if (closest_hdist < 20.0 || closest_vdist < 20.0) wantsdisconnect = true; + if (!this->IsIlsAvailable()) wantsdisconnect = true; } - } diff --git a/source/main/gameplay/AutoPilot.h b/source/main/gameplay/AutoPilot.h index cd366f3abe..92485365e1 100644 --- a/source/main/gameplay/AutoPilot.h +++ b/source/main/gameplay/AutoPilot.h @@ -25,8 +25,7 @@ class Autopilot : public ZeroedMemoryAllocator { -public: - + public: enum { HEADING_NONE, @@ -50,21 +49,21 @@ class Autopilot : public ZeroedMemoryAllocator LOCALIZER_VOR }; - int heading; + int heading; bool wantsdisconnect; Autopilot(int actor_id); void reset(); void disconnect(); - void setInertialReferences(node_t* refl, node_t* refr, node_t* refb, node_t* refc); - int toggleHeading(int mode); - int toggleAlt(int mode); + void setInertialReferences(node_t *refl, node_t *refr, node_t *refb, node_t *refc); + int toggleHeading(int mode); + int toggleAlt(int mode); bool toggleIAS(); bool toggleGPWS(); - int adjHDG(int d); - int adjALT(int d); - int adjVS(int d); - int adjIAS(int d); + int adjHDG(int d); + int adjALT(int d); + int adjVS(int d); + int adjIAS(int d); float getAilerons(); float getElevator(); @@ -73,39 +72,69 @@ class Autopilot : public ZeroedMemoryAllocator void gpws_update(float spawnheight); - void UpdateIls(std::vector localizers); - float GetVerticalApproachDeviation() { return m_ils_angle_vdev; } - float GetHorizontalApproachDeviation() { return m_ils_angle_hdev; } - bool IsIlsAvailable() { return m_horizontal_locator_available && m_vertical_locator_available; } - int GetHeadingMode() const { return mode_heading; } - int GetAltMode() const { return mode_alt; } - int GetAltValue() const { return alt; } - bool GetIasMode() const { return mode_ias; } - int GetIasValue() const { return ias; } - bool GetGpwsMode() const { return mode_gpws; } - int GetVsValue() const { return vs; } -private: - - int mode_heading; - int mode_alt; - bool mode_ias; - bool mode_gpws; - int alt; - int vs; - int ias; - node_t* ref_l; - node_t* ref_r; - node_t* ref_b; - node_t* ref_c; - float ref_span; - float last_elevator; - float last_aileron; - float last_rudder; - float last_gpws_height; - float last_pullup_height; - - bool m_vertical_locator_available; - bool m_horizontal_locator_available; + void UpdateIls(std::vector localizers); + float GetVerticalApproachDeviation() + { + return m_ils_angle_vdev; + } + float GetHorizontalApproachDeviation() + { + return m_ils_angle_hdev; + } + bool IsIlsAvailable() + { + return m_horizontal_locator_available && m_vertical_locator_available; + } + int GetHeadingMode() const + { + return mode_heading; + } + int GetAltMode() const + { + return mode_alt; + } + int GetAltValue() const + { + return alt; + } + bool GetIasMode() const + { + return mode_ias; + } + int GetIasValue() const + { + return ias; + } + bool GetGpwsMode() const + { + return mode_gpws; + } + int GetVsValue() const + { + return vs; + } + + private: + int mode_heading; + int mode_alt; + bool mode_ias; + bool mode_gpws; + int alt; + int vs; + int ias; + node_t *ref_l; + node_t *ref_r; + node_t *ref_b; + node_t *ref_c; + float ref_span; + float last_elevator; + float last_aileron; + float last_rudder; + float last_gpws_height; + float last_pullup_height; + + bool m_vertical_locator_available; + bool m_horizontal_locator_available; float m_ils_angle_vdev; float m_ils_angle_hdev; float m_ils_runway_heading; diff --git a/source/main/gameplay/BeamEngine.cpp b/source/main/gameplay/BeamEngine.cpp index c5dd24e1cd..65ea9718c6 100644 --- a/source/main/gameplay/BeamEngine.cpp +++ b/source/main/gameplay/BeamEngine.cpp @@ -30,77 +30,27 @@ using namespace Ogre; -EngineSim::EngineSim(float _min_rpm, float _max_rpm, float torque, std::vector gears, float dratio, Actor* actor) : - m_air_pressure(0.0f) - , m_auto_cur_acc(0.0f) - , m_auto_mode(AUTOMATIC) - , m_autoselect(DRIVE) - , m_braking_torque(-torque / 5.0f) - , m_clutch_force(10000.0f) - , m_clutch_time(0.2f) - , m_starter_has_contact(false) - , m_cur_acc(0.0f) - , m_cur_clutch(0.0f) - , m_cur_clutch_torque(0.0f) - , m_cur_engine_rpm(0.0f) - , m_cur_engine_torque(0.0f) - , m_cur_gear(0) - , m_cur_gear_range(0) - , m_cur_wheel_revolutions(0.0f) - , m_ref_wheel_revolutions(0.0f) - , m_diff_ratio(dratio) - , m_tcase_ratio(1.0f) - , m_engine_torque(torque) - , m_gear_ratios(gears) - , m_engine_has_air(true) - , m_engine_has_turbo(true) - , m_hydropump_state(0.0f) - , m_engine_idle_rpm(std::min(std::abs(_min_rpm), 800.0f)) - , m_engine_inertia(10.0f) - , m_kickdown_delay_counter(0) - , m_max_idle_mixture(0.1f) - , m_engine_max_rpm(std::abs(_max_rpm)) - , m_min_idle_mixture(0.0f) - , m_engine_min_rpm(std::abs(_min_rpm)) - , m_num_gears((int)gears.size() - 2) - , m_post_shift_time(0.2f) - , m_post_shift_clock(0.0f) - , m_post_shifting(0) - , m_engine_is_priming(false) - , m_engine_is_running(false) - , m_shift_behaviour(0.0f) - , m_shift_time(0.5f) - , m_shift_clock(0.0f) - , m_shifting(0) - , m_shift_val(0) - , m_engine_stall_rpm(300.0f) - , m_starter(0) - , m_torque_curve(new TorqueCurve()) - , m_actor(actor) - , m_engine_turbo_mode(OLD) - , m_engine_type('t') - , m_upshift_delay_counter(0) - , m_engine_is_electric(false) - , m_turbo_inertia_factor(1) - , m_num_turbos(1) - , m_max_turbo_rpm(200000.0f) - , m_turbo_engine_rpm_operation(0.0f) - , m_turbo_ver(1) - , m_min_bov_psi(11) - , m_min_wastegate_psi(20) - , m_turbo_has_wastegate(false) - , m_turbo_has_bov(false) - , m_turbo_flutters(false) - , m_turbo_wg_threshold_p(0) - , m_turbo_wg_threshold_n(0) - , m_turbo_has_antilag(false) - , m_antilag_rand_chance(0.9975) - , m_antilag_min_rpm(3000) - , m_antilag_power_factor(170) +EngineSim::EngineSim(float _min_rpm, float _max_rpm, float torque, std::vector gears, float dratio, Actor *actor) + : m_air_pressure(0.0f), m_auto_cur_acc(0.0f), m_auto_mode(AUTOMATIC), m_autoselect(DRIVE), m_braking_torque(-torque / 5.0f), + m_clutch_force(10000.0f), m_clutch_time(0.2f), m_starter_has_contact(false), m_cur_acc(0.0f), m_cur_clutch(0.0f), + m_cur_clutch_torque(0.0f), m_cur_engine_rpm(0.0f), m_cur_engine_torque(0.0f), m_cur_gear(0), m_cur_gear_range(0), + m_cur_wheel_revolutions(0.0f), m_ref_wheel_revolutions(0.0f), m_diff_ratio(dratio), m_tcase_ratio(1.0f), + m_engine_torque(torque), m_gear_ratios(gears), m_engine_has_air(true), m_engine_has_turbo(true), m_hydropump_state(0.0f), + m_engine_idle_rpm(std::min(std::abs(_min_rpm), 800.0f)), m_engine_inertia(10.0f), m_kickdown_delay_counter(0), + m_max_idle_mixture(0.1f), m_engine_max_rpm(std::abs(_max_rpm)), m_min_idle_mixture(0.0f), + m_engine_min_rpm(std::abs(_min_rpm)), m_num_gears((int)gears.size() - 2), m_post_shift_time(0.2f), m_post_shift_clock(0.0f), + m_post_shifting(0), m_engine_is_priming(false), m_engine_is_running(false), m_shift_behaviour(0.0f), m_shift_time(0.5f), + m_shift_clock(0.0f), m_shifting(0), m_shift_val(0), m_engine_stall_rpm(300.0f), m_starter(0), + m_torque_curve(new TorqueCurve()), m_actor(actor), m_engine_turbo_mode(OLD), m_engine_type('t'), m_upshift_delay_counter(0), + m_engine_is_electric(false), m_turbo_inertia_factor(1), m_num_turbos(1), m_max_turbo_rpm(200000.0f), + m_turbo_engine_rpm_operation(0.0f), m_turbo_ver(1), m_min_bov_psi(11), m_min_wastegate_psi(20), + m_turbo_has_wastegate(false), m_turbo_has_bov(false), m_turbo_flutters(false), m_turbo_wg_threshold_p(0), + m_turbo_wg_threshold_n(0), m_turbo_has_antilag(false), m_antilag_rand_chance(0.9975), m_antilag_min_rpm(3000), + m_antilag_power_factor(170) { - m_full_rpm_range = (m_engine_max_rpm - m_engine_min_rpm); + m_full_rpm_range = (m_engine_max_rpm - m_engine_min_rpm); m_one_third_rpm_range = m_full_rpm_range / 3.0f; - m_half_rpm_range = m_full_rpm_range / 2.0f; + m_half_rpm_range = m_full_rpm_range / 2.0f; m_gear_ratios[0] = -m_gear_ratios[0]; for (std::vector::iterator it = m_gear_ratios.begin(); it != m_gear_ratios.end(); ++it) @@ -111,7 +61,7 @@ EngineSim::EngineSim(float _min_rpm, float _max_rpm, float torque, std::vector MAXTURBO) { m_num_turbos = 4; - LOG("Turbo: No more than 4 turbos allowed"); //TODO: move this under RigParser + LOG("Turbo: No more than 4 turbos allowed"); // TODO: move this under RigParser } else m_num_turbos = nturbos; - m_turbo_ver = type; + m_turbo_ver = type; m_turbo_inertia_factor = tinertiaFactor; - if (param2 != 9999) - m_turbo_engine_rpm_operation = param2; + if (param2 != 9999) m_turbo_engine_rpm_operation = param2; if (m_turbo_ver == 1) { for (int i = 0; i < m_num_turbos; i++) - m_engine_addi_torque[i] = param1 / m_num_turbos; //Additional torque + m_engine_addi_torque[i] = param1 / m_num_turbos; // Additional torque } else { - float turbo_max_psi = param1; //maxPSI - m_max_turbo_rpm = turbo_max_psi * 10000; + float turbo_max_psi = param1; // maxPSI + m_max_turbo_rpm = turbo_max_psi * 10000; - //Duh + // Duh if (param3 == 1) m_turbo_has_bov = true; else m_turbo_has_bov = false; - if (param3 != 9999) - m_min_bov_psi = param4; + if (param3 != 9999) m_min_bov_psi = param4; if (param5 == 1) m_turbo_has_wastegate = true; else m_turbo_has_wastegate = false; - if (param6 != 9999) - m_min_wastegate_psi = param6 * 10000; + if (param6 != 9999) m_min_wastegate_psi = param6 * 10000; if (param7 != 9999) { @@ -179,76 +128,57 @@ void EngineSim::SetTurboOptions(int type, float tinertiaFactor, int nturbos, flo else m_turbo_has_antilag = false; - if (param9 != 9999) - m_antilag_rand_chance = param9; + if (param9 != 9999) m_antilag_rand_chance = param9; - if (param10 != 9999) - m_antilag_min_rpm = param10; + if (param10 != 9999) m_antilag_min_rpm = param10; - if (param11 != 9999) - m_antilag_power_factor = param11; + if (param11 != 9999) m_antilag_power_factor = param11; } } -void EngineSim::SetEngineOptions(float einertia, char etype, float eclutch, float ctime, float stime, float pstime, float irpm, float srpm, float maximix, float minimix, float ebraking) +void EngineSim::SetEngineOptions(float einertia, char etype, float eclutch, float ctime, float stime, float pstime, float irpm, + float srpm, float maximix, float minimix, float ebraking) { m_engine_inertia = einertia; - m_engine_type = etype; - m_clutch_force = eclutch; - - if (ctime > 0) - m_clutch_time = ctime; - if (stime > 0) - m_shift_time = stime; - if (pstime > 0) - m_post_shift_time = pstime; - if (irpm > 0) - m_engine_idle_rpm = irpm; - if (srpm > 0) - m_engine_stall_rpm = srpm; - if (maximix > 0) - m_max_idle_mixture = maximix; - if (minimix > 0) - m_min_idle_mixture = minimix; - if (ebraking > 0) - m_braking_torque = -ebraking; - - m_shift_time = std::max(0.0f, m_shift_time); + m_engine_type = etype; + m_clutch_force = eclutch; + + if (ctime > 0) m_clutch_time = ctime; + if (stime > 0) m_shift_time = stime; + if (pstime > 0) m_post_shift_time = pstime; + if (irpm > 0) m_engine_idle_rpm = irpm; + if (srpm > 0) m_engine_stall_rpm = srpm; + if (maximix > 0) m_max_idle_mixture = maximix; + if (minimix > 0) m_min_idle_mixture = minimix; + if (ebraking > 0) m_braking_torque = -ebraking; + + m_shift_time = std::max(0.0f, m_shift_time); m_post_shift_time = std::max(0.0f, m_post_shift_time); - m_clutch_time = Math::Clamp(m_clutch_time, 0.0f, 0.9f * m_shift_time); + m_clutch_time = Math::Clamp(m_clutch_time, 0.0f, 0.9f * m_shift_time); m_engine_stall_rpm = Math::Clamp(m_engine_stall_rpm, 0.0f, 0.9f * m_engine_idle_rpm); if (etype == 'c') { // it's a car! - m_engine_has_air = false; - m_engine_has_turbo = false; + m_engine_has_air = false; + m_engine_has_turbo = false; m_engine_is_electric = false; // set default clutch force - if (m_clutch_force < 0.0f) - { - m_clutch_force = 5000.0f; - } + if (m_clutch_force < 0.0f) { m_clutch_force = 5000.0f; } } - else if (etype == 'e') //electric + else if (etype == 'e') // electric { m_engine_is_electric = true; - m_engine_has_air = false; - m_engine_has_turbo = false; - if (m_clutch_force < 0.0f) - { - m_clutch_force = 5000.0f; - } + m_engine_has_air = false; + m_engine_has_turbo = false; + if (m_clutch_force < 0.0f) { m_clutch_force = 5000.0f; } } else { m_engine_is_electric = false; // it's a truck - if (m_clutch_force < 0.0f) - { - m_clutch_force = 10000.0f; - } + if (m_clutch_force < 0.0f) { m_clutch_force = 10000.0f; } } } @@ -259,10 +189,7 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) acc = std::max(getIdleMixture(), acc); acc = std::max(getPrimeMixture(), acc); - if (doUpdate) - { - SOUND_MODULATE(m_actor, SS_MOD_INJECTOR, acc); - } + if (doUpdate) { SOUND_MODULATE(m_actor, SS_MOD_INJECTOR, acc); } if (m_engine_has_air) { @@ -280,7 +207,7 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) if (m_engine_turbo_mode == OLD) { // update turbo speed (lag) - float turbotorque = 0.0f; + float turbotorque = 0.0f; float turboInertia = 0.000003f; // braking (compression) @@ -288,9 +215,7 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) // powering (exhaust) with limiter if (m_cur_turbo_rpm[0] < 200000.0f && m_engine_is_running && m_cur_acc > 0.06f) - { - turbotorque += 1.5f * m_cur_acc * (m_cur_engine_rpm / m_engine_max_rpm); - } + { turbotorque += 1.5f * m_cur_acc * (m_cur_engine_rpm / m_engine_max_rpm); } else { turbotorque += 0.1f * (m_cur_engine_rpm / m_engine_max_rpm); @@ -305,7 +230,7 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) { // update turbo speed (lag) // reset each of the values for each turbo - float turbotorque = 0.0f; + float turbotorque = 0.0f; float turboBOVtorque = 0.0f; float turboInertia = 0.000003f * m_turbo_inertia_factor; @@ -323,7 +248,9 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) { if (m_cur_turbo_rpm[i] < m_min_wastegate_psi * m_turbo_wg_threshold_p && !m_turbo_flutters) { - turbotorque += 1.5f * acc * (((m_cur_engine_rpm - m_turbo_engine_rpm_operation) / (m_engine_max_rpm - m_turbo_engine_rpm_operation))); + turbotorque += 1.5f * acc * + (((m_cur_engine_rpm - m_turbo_engine_rpm_operation) / + (m_engine_max_rpm - m_turbo_engine_rpm_operation))); } else { @@ -342,30 +269,30 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) } } else - turbotorque += 1.5f * acc * (((m_cur_engine_rpm - m_turbo_engine_rpm_operation) / (m_engine_max_rpm - m_turbo_engine_rpm_operation))); + turbotorque += 1.5f * acc * + (((m_cur_engine_rpm - m_turbo_engine_rpm_operation) / + (m_engine_max_rpm - m_turbo_engine_rpm_operation))); } else { - turbotorque += 0.1f * (((m_cur_engine_rpm - m_turbo_engine_rpm_operation) / (m_engine_max_rpm - m_turbo_engine_rpm_operation))); + turbotorque += 0.1f * (((m_cur_engine_rpm - m_turbo_engine_rpm_operation) / + (m_engine_max_rpm - m_turbo_engine_rpm_operation))); } - //Update waste gate, it's like a BOV on the exhaust part of the turbo, acts as a limiter + // Update waste gate, it's like a BOV on the exhaust part of the turbo, acts as a limiter if (m_turbo_has_wastegate) { if (m_cur_turbo_rpm[i] > m_min_wastegate_psi * 0.95) - turboInertia = turboInertia * 0.7; //Kill inertia so it flutters + turboInertia = turboInertia * 0.7; // Kill inertia so it flutters else - turboInertia = turboInertia * 1.3; //back to normal inertia + turboInertia = turboInertia * 1.3; // back to normal inertia } } - //simulate compressor surge + // simulate compressor surge if (!m_turbo_has_bov) { - if (m_cur_turbo_rpm[i] > 13 * 10000 && m_cur_acc < 0.06f) - { - turbotorque += (turbotorque * 2.5); - } + if (m_cur_turbo_rpm[i] > 13 * 10000 && m_cur_acc < 0.06f) { turbotorque += (turbotorque * 2.5); } } // anti lag @@ -389,10 +316,10 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) // update main turbo rpm m_cur_turbo_rpm[i] += dt * turbotorque / turboInertia; - //Update BOV - //It's basicly an other turbo which is limmited to the main one's rpm, but it doesn't affect its rpm. It only affects the power going into the engine. - //This one is used to simulate the pressure between the engine and the compressor. - //I should make the whole turbo code work this way. -Max98 + // Update BOV + // It's basicly an other turbo which is limmited to the main one's rpm, but it doesn't affect its rpm. It only + // affects the power going into the engine. This one is used to simulate the pressure between the engine and the + // compressor. I should make the whole turbo code work this way. -Max98 if (m_turbo_has_bov) { if (m_turbo_bov_rpm[i] < m_cur_turbo_rpm[i]) @@ -423,19 +350,14 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) // engine braking if (m_engine_is_running && m_starter_has_contact) - { - totaltorque += m_braking_torque * m_cur_engine_rpm / m_engine_max_rpm * (1.0f - m_cur_acc); - } + { totaltorque += m_braking_torque * m_cur_engine_rpm / m_engine_max_rpm * (1.0f - m_cur_acc); } else if (!m_starter_has_contact || !m_starter) { totaltorque += m_braking_torque; } // braking by m_hydropump_state - if (m_cur_engine_rpm > 100.0f) - { - totaltorque -= 8.0f * m_hydropump_state / (m_cur_engine_rpm * 0.105f * dt); - } + if (m_cur_engine_rpm > 100.0f) { totaltorque -= 8.0f * m_hydropump_state / (m_cur_engine_rpm * 0.105f * dt); } if (m_engine_is_running && m_starter_has_contact && m_cur_engine_rpm < (m_engine_max_rpm * 1.25f)) { @@ -445,19 +367,14 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) if (!m_engine_is_electric) { - if (m_engine_is_running && m_cur_engine_rpm < m_engine_stall_rpm) - { - this->StopEngine(); - } + if (m_engine_is_running && m_cur_engine_rpm < m_engine_stall_rpm) { this->StopEngine(); } if (m_starter_has_contact && !m_engine_is_running) { if (m_cur_engine_rpm < m_engine_idle_rpm) { if (m_starter) - { - totaltorque += m_engine_torque * exp(-2.7f * m_cur_engine_rpm / m_engine_idle_rpm) - m_braking_torque; - } + { totaltorque += m_engine_torque * exp(-2.7f * m_cur_engine_rpm / m_engine_idle_rpm) - m_braking_torque; } } else { @@ -468,10 +385,7 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) } // clutch - if (m_cur_gear) - { - totaltorque -= m_cur_clutch_torque / m_gear_ratios[m_cur_gear + 1]; - } + if (m_cur_gear) { totaltorque -= m_cur_clutch_torque / m_gear_ratios[m_cur_gear + 1]; } // integration m_cur_engine_rpm += dt * totaltorque / m_engine_inertia; @@ -480,9 +394,9 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) if (m_cur_gear) { float force_threshold = 1.5f * std::max(m_engine_torque, getEnginePower()) * std::abs(m_gear_ratios[2]); - float gearboxspinner = m_cur_engine_rpm / m_gear_ratios[m_cur_gear + 1]; - m_cur_clutch_torque = (gearboxspinner - m_cur_wheel_revolutions) * m_cur_clutch * m_clutch_force; - m_cur_clutch_torque = Math::Clamp(m_cur_clutch_torque, -force_threshold, +force_threshold); + float gearboxspinner = m_cur_engine_rpm / m_gear_ratios[m_cur_gear + 1]; + m_cur_clutch_torque = (gearboxspinner - m_cur_wheel_revolutions) * m_cur_clutch * m_clutch_force; + m_cur_clutch_torque = Math::Clamp(m_cur_clutch_torque, -force_threshold, +force_threshold); m_cur_clutch_torque *= 1.0f - approx_exp(-std::abs(gearboxspinner - m_cur_wheel_revolutions)); } else @@ -504,10 +418,10 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) float declutchTime = std::min(m_shift_time - m_clutch_time, m_clutch_time); if (m_shift_clock <= declutchTime) { - // depress the clutch - float ratio = pow(1.0f - (m_shift_clock / declutchTime), 2); + // depress the clutch + float ratio = pow(1.0f - (m_shift_clock / declutchTime), 2); m_cur_clutch = std::min(ratio, m_cur_clutch); - m_cur_acc = std::min(ratio, m_auto_cur_acc); + m_cur_acc = std::min(ratio, m_auto_cur_acc); } else { @@ -528,8 +442,8 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) // we're done m_shifting SOUND_STOP(m_actor, SS_TRIG_SHIFT); SetAcceleration(m_auto_cur_acc); - m_shifting = 0; - m_post_shifting = 1; + m_shifting = 0; + m_post_shifting = 1; m_post_shift_clock = 0.0f; } else if (!m_shift_val && m_cur_gear && m_shift_clock >= (m_shift_time - m_clutch_time)) @@ -537,28 +451,25 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) // release the clutch <-- Done below float timer = m_shift_clock - (m_shift_time - m_clutch_time); float ratio = sqrt(timer / m_clutch_time); - m_cur_acc = (m_auto_cur_acc / 2.0f) * ratio; + m_cur_acc = (m_auto_cur_acc / 2.0f) * ratio; } } if (m_post_shifting) { m_post_shift_clock += dt; - if (m_post_shift_clock > m_post_shift_time) - { - m_post_shifting = 0; - } + if (m_post_shift_clock > m_post_shift_time) { m_post_shifting = 0; } else if (m_auto_cur_acc > 0.0f) { float ratio = m_post_shift_clock / m_post_shift_time; - m_cur_acc = (m_auto_cur_acc / 2.0f) + (m_auto_cur_acc / 2.0f) * ratio; + m_cur_acc = (m_auto_cur_acc / 2.0f) + (m_auto_cur_acc / 2.0f) * ratio; } else if (m_cur_gear) { float gearboxspinner = m_cur_engine_rpm / m_gear_ratios[m_cur_gear + 1]; if (m_cur_wheel_revolutions > gearboxspinner) { - float ratio = sqrt(m_post_shift_clock / m_post_shift_time); + float ratio = sqrt(m_post_shift_clock / m_post_shift_time); m_cur_clutch = std::max(m_cur_clutch, ratio); } } @@ -566,10 +477,7 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) // auto clutch float declutchRPM = m_engine_min_rpm * 0.75f + m_engine_stall_rpm * 0.25f; - if (m_cur_gear == 0 || m_cur_engine_rpm < declutchRPM) - { - m_cur_clutch = 0.0f; - } + if (m_cur_gear == 0 || m_cur_engine_rpm < declutchRPM) { m_cur_clutch = 0.0f; } else if (m_cur_engine_rpm < m_engine_min_rpm && m_engine_min_rpm > declutchRPM) { float clutch = (m_cur_engine_rpm - declutchRPM) / (m_engine_min_rpm - declutchRPM); @@ -577,18 +485,18 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) } else if (!m_shift_val && m_cur_engine_rpm > m_engine_min_rpm && m_cur_clutch < 1.0f) { - float threshold = 1.5f * getEnginePower(m_cur_engine_rpm) * std::abs(m_gear_ratios[2]); + float threshold = 1.5f * getEnginePower(m_cur_engine_rpm) * std::abs(m_gear_ratios[2]); float gearboxspinner = m_cur_engine_rpm / m_gear_ratios[m_cur_gear + 1]; - float clutchTorque = (gearboxspinner - m_cur_wheel_revolutions) * m_clutch_force; - float reTorque = Math::Clamp(clutchTorque, -threshold, +threshold) / m_gear_ratios[m_cur_gear + 1]; + float clutchTorque = (gearboxspinner - m_cur_wheel_revolutions) * m_clutch_force; + float reTorque = Math::Clamp(clutchTorque, -threshold, +threshold) / m_gear_ratios[m_cur_gear + 1]; - float range = (m_engine_max_rpm - m_engine_min_rpm) * 0.4f * sqrt(std::max(0.2f, acc)); - float powerRatio = std::min((m_cur_engine_rpm - m_engine_min_rpm) / range, 1.0f); + float range = (m_engine_max_rpm - m_engine_min_rpm) * 0.4f * sqrt(std::max(0.2f, acc)); + float powerRatio = std::min((m_cur_engine_rpm - m_engine_min_rpm) / range, 1.0f); float engineTorque = getEnginePower() * std::min(m_cur_acc, 0.9f) * powerRatio; float torqueDiff = std::min(engineTorque, std::abs(reTorque)); - float clutch = torqueDiff / reTorque; - m_cur_clutch = std::max(m_cur_clutch, clutch); + float clutch = torqueDiff / reTorque; + m_cur_clutch = std::max(m_cur_clutch, clutch); } m_cur_clutch = std::max(0.0f, m_cur_clutch); @@ -601,28 +509,28 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) float velocity = m_actor->ar_nodes[0].Velocity.length(); Vector3 hdir = m_actor->GetCameraDir(); - if (hdir != Vector3::ZERO) - { - velocity = hdir.dotProduct(m_actor->ar_nodes[0].Velocity); - } + if (hdir != Vector3::ZERO) { velocity = hdir.dotProduct(m_actor->ar_nodes[0].Velocity); } if (m_actor->ar_wheels[0].wh_radius != 0) - { - m_ref_wheel_revolutions = velocity / m_actor->ar_wheels[0].wh_radius * RAD_PER_SEC_TO_RPM; - } + { m_ref_wheel_revolutions = velocity / m_actor->ar_wheels[0].wh_radius * RAD_PER_SEC_TO_RPM; } if (!m_engine_is_electric && m_auto_mode == AUTOMATIC && (m_autoselect == DRIVE || m_autoselect == TWO) && m_cur_gear > 0) { - if ((m_cur_engine_rpm > m_engine_max_rpm - 100.0f && m_cur_gear > 1) || m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1] > m_engine_max_rpm - 100.0f) + if ((m_cur_engine_rpm > m_engine_max_rpm - 100.0f && m_cur_gear > 1) || + m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1] > m_engine_max_rpm - 100.0f) { - if ((m_autoselect == DRIVE && m_cur_gear < m_num_gears && m_cur_clutch > 0.99f) || (m_autoselect == TWO && m_cur_gear < std::min(2, m_num_gears))) + if ((m_autoselect == DRIVE && m_cur_gear < m_num_gears && m_cur_clutch > 0.99f) || + (m_autoselect == TWO && m_cur_gear < std::min(2, m_num_gears))) { m_kickdown_delay_counter = 100; shift(1); } } - else if (m_cur_gear > 1 && m_ref_wheel_revolutions * m_gear_ratios[m_cur_gear] < m_engine_max_rpm && (m_cur_engine_rpm < m_engine_min_rpm || (m_cur_engine_rpm < m_engine_min_rpm + m_shift_behaviour * m_half_rpm_range / 2.0f && - getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear]) > getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1])))) + else if (m_cur_gear > 1 && m_ref_wheel_revolutions * m_gear_ratios[m_cur_gear] < m_engine_max_rpm && + (m_cur_engine_rpm < m_engine_min_rpm || + (m_cur_engine_rpm < m_engine_min_rpm + m_shift_behaviour * m_half_rpm_range / 2.0f && + getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear]) > + getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1])))) { shift(-1); } @@ -633,11 +541,11 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) m_accs.push_front(acc); m_brakes.push_front(m_actor->ar_brake); - float avgRPM50 = 0.0f; - float avgRPM200 = 0.0f; - float avgAcc50 = 0.0f; - float avgAcc200 = 0.0f; - float avgBrake50 = 0.0f; + float avgRPM50 = 0.0f; + float avgRPM200 = 0.0f; + float avgAcc50 = 0.0f; + float avgAcc200 = 0.0f; + float avgBrake50 = 0.0f; float avgBrake200 = 0.0f; for (unsigned int i = 0; i < m_accs.size(); i++) @@ -663,73 +571,64 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) avgBrake200 /= m_brakes.size(); if (avgAcc50 > 0.8f || avgAcc200 > 0.8f || avgBrake50 > 0.8f || avgBrake200 > 0.8f) - { - m_shift_behaviour = std::min(m_shift_behaviour + 0.01f, 1.0f); - } - else if (acc < 0.5f && avgAcc50 < 0.5f && avgAcc200 < 0.5f && m_actor->ar_brake < 0.5f && avgBrake50 < 0.5f && avgBrake200 < 0.5) + { m_shift_behaviour = std::min(m_shift_behaviour + 0.01f, 1.0f); } + else if (acc < 0.5f && avgAcc50 < 0.5f && avgAcc200 < 0.5f && m_actor->ar_brake < 0.5f && avgBrake50 < 0.5f && + avgBrake200 < 0.5) { m_shift_behaviour /= 1.01; } if (avgAcc50 > 0.8f && m_cur_engine_rpm < m_engine_max_rpm - m_one_third_rpm_range) { - while (newGear > 1 && m_cur_wheel_revolutions * m_gear_ratios[newGear] < m_engine_max_rpm - m_one_third_rpm_range && - getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear]) * m_gear_ratios[newGear] > - getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear + 1]) * m_gear_ratios[newGear + 1]) + while (newGear > 1 && + m_cur_wheel_revolutions * m_gear_ratios[newGear] < m_engine_max_rpm - m_one_third_rpm_range && + getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear]) * m_gear_ratios[newGear] > + getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear + 1]) * m_gear_ratios[newGear + 1]) { newGear--; } } - else if (avgAcc50 > 0.6f && acc < 0.8f && acc > avgAcc50 + 0.1f && m_cur_engine_rpm < m_engine_min_rpm + m_half_rpm_range) + else if (avgAcc50 > 0.6f && acc < 0.8f && acc > avgAcc50 + 0.1f && + m_cur_engine_rpm < m_engine_min_rpm + m_half_rpm_range) { if (newGear > 1 && m_cur_wheel_revolutions * m_gear_ratios[newGear] < m_engine_min_rpm + m_half_rpm_range && getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear]) * m_gear_ratios[newGear] > - getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear + 1]) * m_gear_ratios[newGear + 1]) - { - newGear--; - } + getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear + 1]) * m_gear_ratios[newGear + 1]) + { newGear--; } } - else if (avgAcc50 > 0.4f && acc < 0.8f && acc > avgAcc50 + 0.1f && m_cur_engine_rpm < m_engine_min_rpm + m_half_rpm_range) + else if (avgAcc50 > 0.4f && acc < 0.8f && acc > avgAcc50 + 0.1f && + m_cur_engine_rpm < m_engine_min_rpm + m_half_rpm_range) { if (newGear > 1 && m_cur_wheel_revolutions * m_gear_ratios[newGear] < m_engine_min_rpm + m_one_third_rpm_range && getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear]) * m_gear_ratios[newGear] > - getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear + 1]) * m_gear_ratios[newGear + 1]) - { - newGear--; - } + getEnginePower(m_cur_wheel_revolutions * m_gear_ratios[newGear + 1]) * m_gear_ratios[newGear + 1]) + { newGear--; } } - else if (m_cur_gear < (m_autoselect == TWO ? std::min(2, m_num_gears) : m_num_gears) && - avgBrake200 < 0.2f && acc < std::min(avgAcc200 + 0.1f, 1.0f) && m_cur_engine_rpm > avgRPM200 - m_full_rpm_range / 20.0f) + else if (m_cur_gear < (m_autoselect == TWO ? std::min(2, m_num_gears) : m_num_gears) && avgBrake200 < 0.2f && + acc < std::min(avgAcc200 + 0.1f, 1.0f) && m_cur_engine_rpm > avgRPM200 - m_full_rpm_range / 20.0f) { - if (avgAcc200 < 0.6f && avgAcc200 > 0.4f && m_cur_engine_rpm > m_engine_min_rpm + m_one_third_rpm_range && m_cur_engine_rpm < m_engine_max_rpm - m_one_third_rpm_range) + if (avgAcc200 < 0.6f && avgAcc200 > 0.4f && m_cur_engine_rpm > m_engine_min_rpm + m_one_third_rpm_range && + m_cur_engine_rpm < m_engine_max_rpm - m_one_third_rpm_range) { if (m_cur_wheel_revolutions * m_gear_ratios[newGear + 2] > m_engine_min_rpm + m_one_third_rpm_range) - { - newGear++; - } + { newGear++; } } else if (avgAcc200 < 0.4f && avgAcc200 > 0.2f && m_cur_engine_rpm > m_engine_min_rpm + m_one_third_rpm_range) { if (m_cur_wheel_revolutions * m_gear_ratios[newGear + 2] > m_engine_min_rpm + m_one_third_rpm_range / 2.0f) - { - newGear++; - } + { newGear++; } } - else if (avgAcc200 < 0.2f && m_cur_engine_rpm > m_engine_min_rpm + m_one_third_rpm_range / 2.0f && m_cur_engine_rpm < m_engine_min_rpm + m_half_rpm_range) + else if (avgAcc200 < 0.2f && m_cur_engine_rpm > m_engine_min_rpm + m_one_third_rpm_range / 2.0f && + m_cur_engine_rpm < m_engine_min_rpm + m_half_rpm_range) { if (m_cur_wheel_revolutions * m_gear_ratios[newGear + 2] > m_engine_min_rpm + m_one_third_rpm_range / 2.0f) - { - newGear++; - } + { newGear++; } } if (newGear > m_cur_gear) { m_upshift_delay_counter++; - if (m_upshift_delay_counter <= 100 * m_shift_behaviour) - { - newGear = m_cur_gear; - } + if (m_upshift_delay_counter <= 100 * m_shift_behaviour) { newGear = m_cur_gear; } } else { @@ -737,17 +636,17 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) } } - if (newGear < m_cur_gear && m_kickdown_delay_counter > 0) - { - newGear = m_cur_gear; - } + if (newGear < m_cur_gear && m_kickdown_delay_counter > 0) { newGear = m_cur_gear; } m_kickdown_delay_counter = std::max(0, m_kickdown_delay_counter - 1); - if (newGear < m_cur_gear && std::abs(m_cur_wheel_revolutions * (m_gear_ratios[newGear + 1] - m_gear_ratios[m_cur_gear + 1])) > m_one_third_rpm_range / 6.0f || - newGear > m_cur_gear && std::abs(m_cur_wheel_revolutions * (m_gear_ratios[newGear + 1] - m_gear_ratios[m_cur_gear + 1])) > m_one_third_rpm_range / 3.0f) + if (newGear < m_cur_gear && + std::abs(m_cur_wheel_revolutions * (m_gear_ratios[newGear + 1] - m_gear_ratios[m_cur_gear + 1])) > + m_one_third_rpm_range / 6.0f || + newGear > m_cur_gear && + std::abs(m_cur_wheel_revolutions * (m_gear_ratios[newGear + 1] - m_gear_ratios[m_cur_gear + 1])) > + m_one_third_rpm_range / 3.0f) { - if (std::abs(m_actor->GetGForcesCur().y) < 0.25f) - shiftTo(newGear); + if (std::abs(m_actor->GetGForcesCur().y) < 0.25f) shiftTo(newGear); } if (m_accs.size() > 200) @@ -761,7 +660,9 @@ void EngineSim::UpdateEngineSim(float dt, int doUpdate) { if (std::abs(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1]) > m_engine_max_rpm * 1.25f) { - float clutch = 0.0f + 1.0f / (1.0f + std::abs(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1] - m_engine_max_rpm * 1.25f) / 2.0f); + float clutch = 0.0f + 1.0f / (1.0f + std::abs(m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1] - + m_engine_max_rpm * 1.25f) / + 2.0f); m_cur_clutch = std::min(clutch, m_cur_clutch); } if (m_cur_gear * m_cur_wheel_revolutions < -10.0f) @@ -790,10 +691,7 @@ void EngineSim::UpdateEngineAudio() SOUND_MODULATE(m_actor, SS_MOD_GEARBOX, m_cur_wheel_revolutions); // reverse gear beep - if (m_cur_gear == -1 && m_engine_is_running) - { - SOUND_START(m_actor, SS_TRIG_REVERSE_GEAR); - } + if (m_cur_gear == -1 && m_engine_is_running) { SOUND_START(m_actor, SS_TRIG_REVERSE_GEAR); } else { SOUND_STOP(m_actor, SS_TRIG_REVERSE_GEAR); @@ -807,22 +705,16 @@ void EngineSim::ToggleAutoShiftMode() if (m_auto_mode == AUTOMATIC) { - if (m_cur_gear > 0) - m_autoselect = DRIVE; - if (m_cur_gear < 0) - m_autoselect = REAR; - if (m_cur_gear == 0) - m_autoselect = NEUTRAL; + if (m_cur_gear > 0) m_autoselect = DRIVE; + if (m_cur_gear < 0) m_autoselect = REAR; + if (m_cur_gear == 0) m_autoselect = NEUTRAL; } else { m_autoselect = MANUALMODE; } - if (m_auto_mode == MANUAL_RANGES) - { - m_cur_gear_range = 0; - } + if (m_auto_mode == MANUAL_RANGES) { m_cur_gear_range = 0; } } RoR::SimGearboxMode EngineSim::GetAutoShiftMode() @@ -842,10 +734,7 @@ void EngineSim::SetAcceleration(float val) float EngineSim::GetTurboPsi() { - if (m_engine_turbo_mode == OLD) - { - return m_cur_turbo_rpm[0] / 10000.0f; - } + if (m_engine_turbo_mode == OLD) { return m_cur_turbo_rpm[0] / 10000.0f; } float turboPSI = 0; @@ -868,29 +757,24 @@ float EngineSim::GetAcceleration() return m_cur_acc; } -void EngineSim::PushNetworkState(float rpm, float acc, float clutch, int gear, bool running, bool contact, char automode, char autoselect) +void EngineSim::PushNetworkState(float rpm, float acc, float clutch, int gear, bool running, bool contact, char automode, + char autoselect) { - m_cur_engine_rpm = rpm; - m_cur_acc = acc; - m_cur_clutch = clutch; - m_cur_gear = gear; - m_engine_is_running = running; + m_cur_engine_rpm = rpm; + m_cur_acc = acc; + m_cur_clutch = clutch; + m_cur_gear = gear; + m_engine_is_running = running; m_starter_has_contact = contact; - if (automode != -1) - { - m_auto_mode = automode; - } - if (autoselect != -1) - { - m_autoselect = (autoswitch)autoselect; - } + if (automode != -1) { m_auto_mode = automode; } + if (autoselect != -1) { m_autoselect = (autoswitch)autoselect; } } float EngineSim::GetSmoke() { if (m_engine_is_running) { - return m_cur_acc * (1.0f - m_cur_turbo_rpm[0] /* doesn't matter */ / m_max_turbo_rpm);// * m_engine_torque / 5000.0f; + return m_cur_acc * (1.0f - m_cur_turbo_rpm[0] /* doesn't matter */ / m_max_turbo_rpm); // * m_engine_torque / 5000.0f; } return -1; @@ -923,8 +807,7 @@ void EngineSim::SetWheelSpin(float rpm) void EngineSim::SetTCaseRatio(float ratio) { - if (ratio < 1.0f) - return; + if (ratio < 1.0f) return; for (std::vector::iterator it = m_gear_ratios.begin(); it != m_gear_ratios.end(); ++it) { @@ -945,8 +828,8 @@ float EngineSim::GetCrankFactor() float minWorkingRPM = m_engine_idle_rpm * 1.1f; // minWorkingRPM > m_engine_idle_rpm avoids commands deadlocking the engine float rpmRatio = (m_cur_engine_rpm - minWorkingRPM) / (m_engine_max_rpm - minWorkingRPM); - rpmRatio = std::max(0.0f, rpmRatio); // Avoids a negative rpmRatio when m_cur_engine_rpm < minWorkingRPM - rpmRatio = std::min(rpmRatio, 1.0f); // Avoids a rpmRatio > 1.0f when m_cur_engine_rpm > m_engine_max_rpm + rpmRatio = std::max(0.0f, rpmRatio); // Avoids a negative rpmRatio when m_cur_engine_rpm < minWorkingRPM + rpmRatio = std::min(rpmRatio, 1.0f); // Avoids a rpmRatio > 1.0f when m_cur_engine_rpm > m_engine_max_rpm float crankfactor = 5.0f * rpmRatio; @@ -971,10 +854,7 @@ float EngineSim::GetClutchForce() void EngineSim::ToggleStarterContact() { m_starter_has_contact = !m_starter_has_contact; - if (m_starter_has_contact) - { - SOUND_START(m_actor, SS_TRIG_IGNITION); - } + if (m_starter_has_contact) { SOUND_START(m_actor, SS_TRIG_IGNITION); } else { SOUND_STOP(m_actor, SS_TRIG_IGNITION); @@ -985,38 +865,29 @@ void EngineSim::StartEngine() { this->OffStart(); m_starter_has_contact = true; - m_cur_engine_rpm = m_engine_idle_rpm; - m_engine_is_running = true; - if (m_auto_mode <= SEMIAUTO) - { - m_cur_gear = 1; - } - if (m_auto_mode == AUTOMATIC) - { - m_autoselect = DRIVE; - } + m_cur_engine_rpm = m_engine_idle_rpm; + m_engine_is_running = true; + if (m_auto_mode <= SEMIAUTO) { m_cur_gear = 1; } + if (m_auto_mode == AUTOMATIC) { m_autoselect = DRIVE; } SOUND_START(m_actor, SS_TRIG_IGNITION); SOUND_START(m_actor, SS_TRIG_ENGINE); } void EngineSim::OffStart() { - m_air_pressure = 0.0f; - m_autoselect = MANUALMODE; + m_air_pressure = 0.0f; + m_autoselect = MANUALMODE; m_starter_has_contact = false; - m_cur_acc = 0.0f; - m_cur_clutch = 0.0f; - m_cur_clutch_torque = 0.0f; - m_cur_engine_rpm = 0.0f; - m_cur_gear = 0; - m_post_shifting = 0; - m_engine_is_running = false; - m_shifting = 0; - m_shift_val = 0; - if (m_auto_mode == AUTOMATIC) - { - m_autoselect = NEUTRAL; - } + m_cur_acc = 0.0f; + m_cur_clutch = 0.0f; + m_cur_clutch_torque = 0.0f; + m_cur_engine_rpm = 0.0f; + m_cur_gear = 0; + m_post_shifting = 0; + m_engine_is_running = false; + m_shifting = 0; + m_shift_val = 0; + if (m_auto_mode == AUTOMATIC) { m_autoselect = NEUTRAL; } for (int i = 0; i < m_num_turbos; i++) { m_cur_turbo_rpm[i] = 0.0f; @@ -1052,8 +923,7 @@ void EngineSim::SetGearRange(int v) void EngineSim::StopEngine() { - if (!m_engine_is_running) - return; + if (!m_engine_is_running) return; m_engine_is_running = false; TRIGGER_EVENT(SE_TRUCK_ENGINE_DIED, m_actor->ar_instance_id); @@ -1069,28 +939,21 @@ float EngineSim::GetAccToHoldRPM() void EngineSim::autoSetAcc(float val) { m_auto_cur_acc = val; - if (!m_shifting) - { - SetAcceleration(val); - } + if (!m_shifting) { SetAcceleration(val); } } void EngineSim::shift(int val) { - if (!val || m_cur_gear + val < -1 || m_cur_gear + val > getNumGears()) - return; + if (!val || m_cur_gear + val < -1 || m_cur_gear + val > getNumGears()) return; if (m_auto_mode < MANUAL) { - m_shift_val = val; - m_shifting = 1; + m_shift_val = val; + m_shifting = 1; m_shift_clock = 0.0f; } else { - if (m_cur_clutch > 0.25f) - { - SOUND_PLAY_ONCE(m_actor, SS_TRIG_GEARSLIDE); - } + if (m_cur_clutch > 0.25f) { SOUND_PLAY_ONCE(m_actor, SS_TRIG_GEARSLIDE); } else { SOUND_PLAY_ONCE(m_actor, SS_TRIG_SHIFT); @@ -1106,17 +969,12 @@ void EngineSim::shiftTo(int newGear) void EngineSim::updateShifts() { - if (m_engine_is_electric) - return; - if (m_autoselect == MANUALMODE) - return; + if (m_engine_is_electric) return; + if (m_autoselect == MANUALMODE) return; SOUND_PLAY_ONCE(m_actor, SS_TRIG_SHIFT); - if (m_autoselect == REAR) - { - m_cur_gear = -1; - } + if (m_autoselect == REAR) { m_cur_gear = -1; } else if (m_autoselect == NEUTRAL) { m_cur_gear = 0; @@ -1130,17 +988,15 @@ void EngineSim::updateShifts() // search for an appropriate gear int newGear = 1; - while (newGear < m_num_gears && m_cur_wheel_revolutions > 0.0f && m_cur_wheel_revolutions * m_gear_ratios[newGear + 1] > m_engine_max_rpm - 100.0f) + while (newGear < m_num_gears && m_cur_wheel_revolutions > 0.0f && + m_cur_wheel_revolutions * m_gear_ratios[newGear + 1] > m_engine_max_rpm - 100.0f) { newGear++; } m_cur_gear = newGear; - if (m_autoselect == TWO) - { - m_cur_gear = std::min(m_cur_gear, 2); - } + if (m_autoselect == TWO) { m_cur_gear = std::min(m_cur_gear, 2); } } } @@ -1177,17 +1033,15 @@ void EngineSim::setManualClutch(float val) { if (m_auto_mode >= MANUAL) { - val = std::max(0.0f, val); + val = std::max(0.0f, val); m_cur_clutch = 1.0 - val; } } float EngineSim::getTurboPower() { - if (!m_engine_has_turbo) - return 0.0f; - if (m_engine_turbo_mode != NEW) - return 0.0f; + if (!m_engine_has_turbo) return 0.0f; + if (m_engine_turbo_mode != NEW) return 0.0f; float atValue = 0.0f; // torque (turbo integreation) @@ -1200,7 +1054,7 @@ float EngineSim::getTurboPower() } else { - atValue = (((GetTurboPsi() * 6.8) * m_engine_torque) / 100); //1psi = 6% more power + atValue = (((GetTurboPsi() * 6.8) * m_engine_torque) / 100); // 1psi = 6% more power } return atValue; @@ -1211,18 +1065,14 @@ float EngineSim::getEnginePower(float rpm) // engine power with limiter float tqValue = 1.0f; // ratio (0-1) - if (m_torque_curve) - { - tqValue = m_torque_curve->getEngineTorque(rpm); - } + if (m_torque_curve) { tqValue = m_torque_curve->getEngineTorque(rpm); } return (m_engine_torque * tqValue) + getTurboPower(); } float EngineSim::getIdleMixture() { - if (m_cur_engine_rpm <= m_engine_idle_rpm) - return m_max_idle_mixture; + if (m_cur_engine_rpm <= m_engine_idle_rpm) return m_max_idle_mixture; return m_min_idle_mixture; } diff --git a/source/main/gameplay/BeamEngine.h b/source/main/gameplay/BeamEngine.h index db98754cc8..bb08adf5bb 100644 --- a/source/main/gameplay/BeamEngine.h +++ b/source/main/gameplay/BeamEngine.h @@ -24,21 +24,20 @@ #include "Application.h" #include "RoRPrerequisites.h" - /// A land vehicle engine + transmission /// NOTE: Formerly named 'BeamEngine' because 'Actor' was 'Beam' class EngineSim : public ZeroedMemoryAllocator { friend class ActorSpawner; -public: - - EngineSim(float min_rpm, float max_rpm, float torque, std::vector gears, float dratio, Actor* actor); + public: + EngineSim(float min_rpm, float max_rpm, float torque, std::vector gears, float dratio, Actor *actor); ~EngineSim(); /// Sets current engine state; /// @param gear Current gear {-1 = reverse, 0 = neutral, 1...21 = forward} - void PushNetworkState(float engine_rpm, float acc, float clutch, int gear, bool running, bool contact, char auto_mode, char auto_select=-1); + void PushNetworkState(float engine_rpm, float acc, float clutch, int gear, bool running, bool contact, char auto_mode, + char auto_select = -1); /// Sets engine options. /// @param einertia Engine inertia @@ -51,73 +50,126 @@ class EngineSim : public ZeroedMemoryAllocator /// @param srpm Stall RPM /// @param maximix Max. idle mixture /// @param minimix Min. idle mixture - void SetEngineOptions(float einertia, char etype, float eclutch, float ctime, float stime, float pstime, float irpm, float srpm, float maximix, float minimix, float ebraking); + void SetEngineOptions(float einertia, char etype, float eclutch, float ctime, float stime, float pstime, float irpm, + float srpm, float maximix, float minimix, float ebraking); /// Sets turbo options. /// @param tinertiatinertiaFactor Turbo inertia factor /// @param nturbos Number of turbos /// @param additionalTorque Torque that will be added to the engine at max turbo rpm - void SetTurboOptions(int type, float tinertiaFactor, int nturbos, float param1, float param2, float param3, float param4, float param5, float param6, float param7, float param8, float param9, float param10, float param11); - - void SetAcceleration(float val); - void SetAutoMode(RoR::SimGearboxMode mode); - void SetClutch(float clutch); - float GetAcceleration(); - float GetClutch(); - float GetClutchForce(); - float GetCrankFactor(); - float GetSmoke(); - float GetTorque(); - float GetTurboPsi(); + void SetTurboOptions(int type, float tinertiaFactor, int nturbos, float param1, float param2, float param3, float param4, + float param5, float param6, float param7, float param8, float param9, float param10, float param11); + + void SetAcceleration(float val); + void SetAutoMode(RoR::SimGearboxMode mode); + void SetClutch(float clutch); + float GetAcceleration(); + float GetClutch(); + float GetClutchForce(); + float GetCrankFactor(); + float GetSmoke(); + float GetTorque(); + float GetTurboPsi(); RoR::SimGearboxMode GetAutoShiftMode(); - void SetEngineRpm(float rpm); //!< Set current engine RPM. - void SetEnginePriming(bool p); //!< Set current engine prime. - void SetHydroPumpWork(float work); //!< Set current hydro pump work. - void SetWheelSpin(float rpm); //!< Set current wheel spinning speed. - void SetTCaseRatio(float ratio); //!< Set current transfer case gear (reduction) ratio - void ToggleAutoShiftMode(); - void ToggleStarterContact(); - void OffStart(); //!< Quick start of vehicle engine. - void SetStarter(bool v); //!< Controls vehicle m_starter. No side effects. - void StartEngine(); //!< Quick engine start. Plays sounds. - int GetGear(); //!< low level gear changing - int GetGearRange(); //!< low level gear changing - void SetGear(int v); //!< low level gear changing - void SetGearRange(int v); //!< low level gear changing - void StopEngine(); //!< stall engine - float GetAccToHoldRPM(); //!< estimate required throttle input to hold the current rpm - bool HasStarterContact() const{ return m_starter_has_contact; }; - bool HasTurbo() const { return m_engine_has_turbo; }; - bool IsRunning() const { return m_engine_is_running; }; - int GetAutoMode() const { return static_cast(m_auto_mode); }; - char GetEngineType() const { return m_engine_type; }; - float getIdleRPM() const { return m_engine_idle_rpm; }; - float getMaxRPM() const { return m_engine_max_rpm; }; - float getMinRPM() const { return m_engine_min_rpm; }; - int getNumGears() const { return static_cast(m_gear_ratios.size() - 2); }; - int getNumGearsRanges() const{ return getNumGears() / 6 + 1; }; - TorqueCurve* getTorqueCurve() { return m_torque_curve; }; - float GetEngineRpm() const { return m_cur_engine_rpm; } - float GetEngineTorque() const { return m_cur_engine_torque; } - float GetInputShaftRpm() { return m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1]; }; - float GetDriveRatio() { return m_gear_ratios[m_cur_gear + 1]; }; - float GetEngineInertia() { return m_engine_inertia; }; - float getEnginePower() { return getEnginePower(m_cur_engine_rpm); }; - float getEnginePower(float rpm); - float getTurboPower(); - float getIdleMixture(); - float getPrimeMixture(); - int getAutoShift(); - void autoSetAcc(float val); - void autoShiftDown(); - void autoShiftSet(int mode); - void autoShiftUp(); - void setManualClutch(float val); - void shift(int val); //!< Changes gear by a relative offset. Plays sounds. - void shiftTo(int val); //!< Changes gear to given value. Plays sounds. - void updateShifts(); //!< Changes gears. Plays sounds. - void UpdateEngineSim(float dt, int doUpdate); - void UpdateEngineAudio(); + void SetEngineRpm(float rpm); //!< Set current engine RPM. + void SetEnginePriming(bool p); //!< Set current engine prime. + void SetHydroPumpWork(float work); //!< Set current hydro pump work. + void SetWheelSpin(float rpm); //!< Set current wheel spinning speed. + void SetTCaseRatio(float ratio); //!< Set current transfer case gear (reduction) ratio + void ToggleAutoShiftMode(); + void ToggleStarterContact(); + void OffStart(); //!< Quick start of vehicle engine. + void SetStarter(bool v); //!< Controls vehicle m_starter. No side effects. + void StartEngine(); //!< Quick engine start. Plays sounds. + int GetGear(); //!< low level gear changing + int GetGearRange(); //!< low level gear changing + void SetGear(int v); //!< low level gear changing + void SetGearRange(int v); //!< low level gear changing + void StopEngine(); //!< stall engine + float GetAccToHoldRPM(); //!< estimate required throttle input to hold the current rpm + bool HasStarterContact() const + { + return m_starter_has_contact; + }; + bool HasTurbo() const + { + return m_engine_has_turbo; + }; + bool IsRunning() const + { + return m_engine_is_running; + }; + int GetAutoMode() const + { + return static_cast(m_auto_mode); + }; + char GetEngineType() const + { + return m_engine_type; + }; + float getIdleRPM() const + { + return m_engine_idle_rpm; + }; + float getMaxRPM() const + { + return m_engine_max_rpm; + }; + float getMinRPM() const + { + return m_engine_min_rpm; + }; + int getNumGears() const + { + return static_cast(m_gear_ratios.size() - 2); + }; + int getNumGearsRanges() const + { + return getNumGears() / 6 + 1; + }; + TorqueCurve *getTorqueCurve() + { + return m_torque_curve; + }; + float GetEngineRpm() const + { + return m_cur_engine_rpm; + } + float GetEngineTorque() const + { + return m_cur_engine_torque; + } + float GetInputShaftRpm() + { + return m_cur_wheel_revolutions * m_gear_ratios[m_cur_gear + 1]; + }; + float GetDriveRatio() + { + return m_gear_ratios[m_cur_gear + 1]; + }; + float GetEngineInertia() + { + return m_engine_inertia; + }; + float getEnginePower() + { + return getEnginePower(m_cur_engine_rpm); + }; + float getEnginePower(float rpm); + float getTurboPower(); + float getIdleMixture(); + float getPrimeMixture(); + int getAutoShift(); + void autoSetAcc(float val); + void autoShiftDown(); + void autoShiftSet(int mode); + void autoShiftUp(); + void setManualClutch(float val); + void shift(int val); //!< Changes gear by a relative offset. Plays sounds. + void shiftTo(int val); //!< Changes gear to given value. Plays sounds. + void updateShifts(); //!< Changes gears. Plays sounds. + void UpdateEngineSim(float dt, int doUpdate); + void UpdateEngineAudio(); enum autoswitch { @@ -135,8 +187,7 @@ class EngineSim : public ZeroedMemoryAllocator NEW }; -private: - + private: enum shiftmodes { AUTOMATIC, @@ -147,92 +198,92 @@ class EngineSim : public ZeroedMemoryAllocator }; // Vehicle - Actor* m_actor; + Actor *m_actor; // Gearbox - float m_ref_wheel_revolutions; //!< Gears; estimated wheel revolutions based on current vehicle speed along the longi. axis - float m_cur_wheel_revolutions; //!< Gears; measured wheel revolutions - int m_cur_gear; //!< Gears; Current gear {-1 = reverse, 0 = neutral, 1...21 = forward} - int m_cur_gear_range; //!< Gears - int m_num_gears; //!< Gears - std::vector m_gear_ratios; //!< Gears + float m_ref_wheel_revolutions; //!< Gears; estimated wheel revolutions based on current vehicle speed along the longi. axis + float m_cur_wheel_revolutions; //!< Gears; measured wheel revolutions + int m_cur_gear; //!< Gears; Current gear {-1 = reverse, 0 = neutral, 1...21 = forward} + int m_cur_gear_range; //!< Gears + int m_num_gears; //!< Gears + std::vector m_gear_ratios; //!< Gears // Clutch - float m_clutch_force; //!< Clutch attribute - float m_clutch_time; //!< Clutch attribute - float m_cur_clutch; - float m_cur_clutch_torque; + float m_clutch_force; //!< Clutch attribute + float m_clutch_time; //!< Clutch attribute + float m_cur_clutch; + float m_cur_clutch_torque; // Engine - bool m_engine_is_electric; //!< Engine attribute - bool m_starter_has_contact; //!< Engine state - bool m_engine_has_air; //!< Engine attribute - bool m_engine_has_turbo; //!< Engine attribute - int m_engine_turbo_mode; //!< Engine attribute - bool m_engine_is_running; //!< Engine state - char m_engine_type; //!< Engine attribute {'t' = truck (default), 'c' = car} - float m_braking_torque; //!< Engine attribute - float m_cur_acc; //!< Engine - float m_cur_engine_rpm; //!< Engine - float m_cur_engine_torque; //!< Engine - float m_diff_ratio; //!< Engine - float m_tcase_ratio; //!< Engine - float m_engine_torque; //!< Engine attribute - float m_hydropump_state; //!< Engine - float m_min_idle_mixture; //!< Engine attribute - float m_max_idle_mixture; //!< Engine attribute - float m_engine_inertia; //!< Engine attribute - float m_engine_max_rpm; //!< Engine attribute - float m_engine_min_rpm; //!< Engine attribute - float m_engine_idle_rpm; //!< Engine attribute - float m_engine_stall_rpm; //!< Engine attribute - bool m_engine_is_priming; //!< Engine - TorqueCurve* m_torque_curve; - float m_air_pressure; + bool m_engine_is_electric; //!< Engine attribute + bool m_starter_has_contact; //!< Engine state + bool m_engine_has_air; //!< Engine attribute + bool m_engine_has_turbo; //!< Engine attribute + int m_engine_turbo_mode; //!< Engine attribute + bool m_engine_is_running; //!< Engine state + char m_engine_type; //!< Engine attribute {'t' = truck (default), 'c' = car} + float m_braking_torque; //!< Engine attribute + float m_cur_acc; //!< Engine + float m_cur_engine_rpm; //!< Engine + float m_cur_engine_torque; //!< Engine + float m_diff_ratio; //!< Engine + float m_tcase_ratio; //!< Engine + float m_engine_torque; //!< Engine attribute + float m_hydropump_state; //!< Engine + float m_min_idle_mixture; //!< Engine attribute + float m_max_idle_mixture; //!< Engine attribute + float m_engine_inertia; //!< Engine attribute + float m_engine_max_rpm; //!< Engine attribute + float m_engine_min_rpm; //!< Engine attribute + float m_engine_idle_rpm; //!< Engine attribute + float m_engine_stall_rpm; //!< Engine attribute + bool m_engine_is_priming; //!< Engine + TorqueCurve *m_torque_curve; + float m_air_pressure; // Shifting - float m_post_shift_time; //!< Shift attribute - float m_post_shift_clock; - float m_shift_time; //!< Shift attribute - float m_shift_clock; - int m_post_shifting; - int m_shifting; - int m_shift_val; + float m_post_shift_time; //!< Shift attribute + float m_post_shift_clock; + float m_shift_time; //!< Shift attribute + float m_shift_clock; + int m_post_shifting; + int m_shifting; + int m_shift_val; // Auto transmission - int m_auto_mode; //!< Transmission mode (@see enum EngineSim::shiftmodes) - autoswitch m_autoselect; - float m_auto_cur_acc; - int m_starter; - float m_full_rpm_range; - float m_one_third_rpm_range; - float m_half_rpm_range; - float m_shift_behaviour; - int m_upshift_delay_counter; - int m_kickdown_delay_counter; + int m_auto_mode; //!< Transmission mode (@see enum EngineSim::shiftmodes) + autoswitch m_autoselect; + float m_auto_cur_acc; + int m_starter; + float m_full_rpm_range; + float m_one_third_rpm_range; + float m_half_rpm_range; + float m_shift_behaviour; + int m_upshift_delay_counter; + int m_kickdown_delay_counter; std::deque m_rpms; std::deque m_accs; std::deque m_brakes; // Turbo #define MAXTURBO 4 - int m_turbo_ver; - float m_cur_turbo_rpm[MAXTURBO]; - float m_turbo_inertia_factor; - int m_num_turbos; - int m_max_turbo_rpm; - float m_engine_addi_torque[MAXTURBO]; - float m_turbo_engine_rpm_operation; - bool m_turbo_has_bov; - float m_turbo_bov_rpm[MAXTURBO]; - int m_min_bov_psi; - bool m_turbo_has_wastegate; - float m_min_wastegate_psi; - bool m_turbo_flutters; - float m_turbo_wg_threshold_p; - float m_turbo_wg_threshold_n; - bool m_turbo_has_antilag; - float m_antilag_min_rpm; - float m_antilag_rand_chance; - float m_antilag_power_factor; + int m_turbo_ver; + float m_cur_turbo_rpm[MAXTURBO]; + float m_turbo_inertia_factor; + int m_num_turbos; + int m_max_turbo_rpm; + float m_engine_addi_torque[MAXTURBO]; + float m_turbo_engine_rpm_operation; + bool m_turbo_has_bov; + float m_turbo_bov_rpm[MAXTURBO]; + int m_min_bov_psi; + bool m_turbo_has_wastegate; + float m_min_wastegate_psi; + bool m_turbo_flutters; + float m_turbo_wg_threshold_p; + float m_turbo_wg_threshold_n; + bool m_turbo_has_antilag; + float m_antilag_min_rpm; + float m_antilag_rand_chance; + float m_antilag_power_factor; }; diff --git a/source/main/gameplay/Character.cpp b/source/main/gameplay/Character.cpp index 051cc4f86b..aca636dc42 100644 --- a/source/main/gameplay/Character.cpp +++ b/source/main/gameplay/Character.cpp @@ -39,32 +39,17 @@ using namespace RoR; #define LOGSTREAM Ogre::LogManager::getSingleton().stream() -Character::Character(int source, unsigned int streamid, UTFString player_name, int color_number, bool is_remote) : - m_actor_coupling(nullptr) - , m_can_jump(false) - , m_character_rotation(0.0f) - , m_character_h_speed(2.0f) - , m_character_v_speed(0.0f) - , m_color_number(color_number) - , m_anim_time(0.f) - , m_net_last_anim_time(0.f) - , m_net_last_update_time(0.f) - , m_net_username(player_name) - , m_is_remote(is_remote) - , m_source_id(source) - , m_stream_id(streamid) - , m_gfx_character(nullptr) - , m_driving_anim_length(0.f) - , m_anim_name("Idle_sway") +Character::Character(int source, unsigned int streamid, UTFString player_name, int color_number, bool is_remote) + : m_actor_coupling(nullptr), m_can_jump(false), m_character_rotation(0.0f), m_character_h_speed(2.0f), + m_character_v_speed(0.0f), m_color_number(color_number), m_anim_time(0.f), m_net_last_anim_time(0.f), + m_net_last_update_time(0.f), m_net_username(player_name), m_is_remote(is_remote), m_source_id(source), + m_stream_id(streamid), m_gfx_character(nullptr), m_driving_anim_length(0.f), m_anim_name("Idle_sway") { static int id_counter = 0; - m_instance_name = "Character" + TOSTRING(id_counter); + m_instance_name = "Character" + TOSTRING(id_counter); ++id_counter; - if (App::mp_state.GetActive() == MpState::CONNECTED) - { - this->SendStreamSetup(); - } + if (App::mp_state.GetActive() == MpState::CONNECTED) { this->SendStreamSetup(); } } Character::~Character() @@ -83,14 +68,14 @@ void Character::updateCharacterRotation() void Character::setPosition(Vector3 position) // TODO: updates OGRE objects --> belongs to GfxScene ~ only_a_ptr, 05/2018 { - //ASYNCSCENE OLD m_character_scenenode->setPosition(position); + // ASYNCSCENE OLD m_character_scenenode->setPosition(position); m_character_position = position; - m_prev_position = position; + m_prev_position = position; } Vector3 Character::getPosition() { - //ASYNCSCENE OLDreturn m_character_scenenode->getPosition(); + // ASYNCSCENE OLDreturn m_character_scenenode->getPosition(); return m_character_position; } @@ -101,13 +86,12 @@ void Character::setRotation(Radian rotation) void Character::SetAnimState(std::string mode, float time) { - if (mode.empty()) - return; // Multiplayer safe-guard + if (mode.empty()) return; // Multiplayer safe-guard if (m_anim_name != mode) { - m_anim_name = mode; - m_anim_time = time; + m_anim_name = mode; + m_anim_time = time; m_net_last_anim_time = 0.0f; } else @@ -121,8 +105,7 @@ float calculate_collision_depth(Vector3 pos) Vector3 query = pos + 0.3f * Vector3::UNIT_Y; while (query.y > pos.y) { - if (gEnv->collisions->collisionCorrect(&query, false)) - break; + if (gEnv->collisions->collisionCorrect(&query, false)) break; query.y -= 0.001f; } return query.y - pos.y; @@ -134,12 +117,9 @@ void Character::update(float dt) { // disable character movement when using the free camera mode or when the menu is opened // TODO: check for menu being opened - if (App::GetSimController()->AreControlsLocked()) - { - return; - } + if (App::GetSimController()->AreControlsLocked()) { return; } - Vector3 position = m_character_position; //ASYNCSCENE OLD m_character_scenenode->getPosition(); + Vector3 position = m_character_position; // ASYNCSCENE OLD m_character_scenenode->getPosition(); // gravity force is always on position.y += m_character_v_speed * dt; @@ -153,7 +133,7 @@ void Character::update(float dt) float depth = calculate_collision_depth(position); if (depth > 0.0f) { - m_can_jump = true; + m_can_jump = true; m_character_v_speed = std::max(0.0f, m_character_v_speed); position.y += std::min(depth, 2.0f * dt); } @@ -167,21 +147,18 @@ void Character::update(float dt) { for (int i = 0; i < actor->ar_num_collcabs; i++) { - int tmpv = actor->ar_collcabs[i] * 3; - Vector3 a = actor->ar_nodes[actor->ar_cabs[tmpv + 0]].AbsPosition; - Vector3 b = actor->ar_nodes[actor->ar_cabs[tmpv + 1]].AbsPosition; - Vector3 c = actor->ar_nodes[actor->ar_cabs[tmpv + 2]].AbsPosition; - auto result = Math::intersects(Ray(position, Vector3::UNIT_Y), a, b, c); - if (result.first && result.second < 1.8f) - { - depth = std::max(depth, result.second); - } + int tmpv = actor->ar_collcabs[i] * 3; + Vector3 a = actor->ar_nodes[actor->ar_cabs[tmpv + 0]].AbsPosition; + Vector3 b = actor->ar_nodes[actor->ar_cabs[tmpv + 1]].AbsPosition; + Vector3 c = actor->ar_nodes[actor->ar_cabs[tmpv + 2]].AbsPosition; + auto result = Math::intersects(Ray(position, Vector3::UNIT_Y), a, b, c); + if (result.first && result.second < 1.8f) { depth = std::max(depth, result.second); } } } } if (depth > 0.0f) { - m_can_jump = true; + m_can_jump = true; m_character_v_speed = std::max(0.0f, m_character_v_speed); position.y += std::min(depth, 0.05f); } @@ -191,15 +168,15 @@ void Character::update(float dt) if (position != m_prev_position) { const int numstep = 100; - Vector3 diff = position - m_prev_position; - Vector3 base = m_prev_position + Vector3::UNIT_Y * 0.25f; + Vector3 diff = position - m_prev_position; + Vector3 base = m_prev_position + Vector3::UNIT_Y * 0.25f; for (int i = 1; i < numstep; i++) { Vector3 query = base + diff * ((float)i / numstep); if (gEnv->collisions->collisionCorrect(&query, false)) { m_character_v_speed = std::max(0.0f, m_character_v_speed); - position = m_prev_position + diff * ((float)(i - 1) / numstep); + position = m_prev_position + diff * ((float)(i - 1) / numstep); position.y += 0.025f; break; } @@ -213,30 +190,28 @@ void Character::update(float dt) if (position.y < pheight) { - position.y = pheight; + position.y = pheight; m_character_v_speed = 0.0f; - m_can_jump = true; + m_can_jump = true; } // water stuff - bool isswimming = false; - float wheight = -99999; + bool isswimming = false; + float wheight = -99999; if (App::GetSimTerrain()->getWater()) { wheight = App::GetSimTerrain()->getWater()->CalcWavesHeight(position); if (position.y < wheight - 1.8f) { - position.y = wheight - 1.8f; + position.y = wheight - 1.8f; m_character_v_speed = 0.0f; } } // 0.1 due to 'jumping' from waves -> not nice looking if (App::GetSimTerrain()->getWater() && (wheight - pheight > 1.8f) && (position.y + 0.1f <= wheight)) - { - isswimming = true; - } + { isswimming = true; } float tmpJoy = 0.0f; if (m_can_jump) @@ -244,15 +219,15 @@ void Character::update(float dt) if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_JUMP)) { m_character_v_speed = 2.0f; - m_can_jump = false; + m_can_jump = false; } } - bool idleanim = true; - float tmpGoForward = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_FORWARD) - + RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_ROT_UP); - float tmpGoBackward = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_BACKWARDS) - + RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_ROT_DOWN); + bool idleanim = true; + float tmpGoForward = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_FORWARD) + + RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_ROT_UP); + float tmpGoBackward = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_BACKWARDS) + + RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_ROT_DOWN); bool not_walking = (tmpGoForward == 0.f && tmpGoBackward == 0.f); tmpJoy = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_RIGHT); @@ -280,15 +255,16 @@ void Character::update(float dt) } float tmpRun = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_RUN); - float accel = 1.0f; + float accel = 1.0f; tmpJoy = accel = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_SIDESTEP_LEFT); if (tmpJoy > 0.0f) { - if (tmpRun > 0.0f) - accel = 3.0f * tmpRun; + if (tmpRun > 0.0f) accel = 3.0f * tmpRun; // animation missing for that - position += dt * m_character_h_speed * 0.5f * accel * Vector3(cos(m_character_rotation.valueRadians() - Math::HALF_PI), 0.0f, sin(m_character_rotation.valueRadians() - Math::HALF_PI)); + position += dt * m_character_h_speed * 0.5f * accel * + Vector3(cos(m_character_rotation.valueRadians() - Math::HALF_PI), 0.0f, + sin(m_character_rotation.valueRadians() - Math::HALF_PI)); if (!isswimming && not_walking) { this->SetAnimState("Side_step", -dt); @@ -299,10 +275,11 @@ void Character::update(float dt) tmpJoy = accel = RoR::App::GetInputEngine()->getEventValue(EV_CHARACTER_SIDESTEP_RIGHT); if (tmpJoy > 0.0f) { - if (tmpRun > 0.0f) - accel = 3.0f * tmpRun; + if (tmpRun > 0.0f) accel = 3.0f * tmpRun; // animation missing for that - position += dt * m_character_h_speed * 0.5f * accel * Vector3(cos(m_character_rotation.valueRadians() + Math::HALF_PI), 0.0f, sin(m_character_rotation.valueRadians() + Math::HALF_PI)); + position += dt * m_character_h_speed * 0.5f * accel * + Vector3(cos(m_character_rotation.valueRadians() + Math::HALF_PI), 0.0f, + sin(m_character_rotation.valueRadians() + Math::HALF_PI)); if (!isswimming && not_walking) { this->SetAnimState("Side_step", dt); @@ -311,15 +288,14 @@ void Character::update(float dt) } tmpJoy = accel = tmpGoForward; - float tmpBack = tmpGoBackward; + float tmpBack = tmpGoBackward; - tmpJoy = std::min(tmpJoy, 1.0f); + tmpJoy = std::min(tmpJoy, 1.0f); tmpBack = std::min(tmpBack, 1.0f); if (tmpJoy > 0.0f || tmpRun > 0.0f) { - if (tmpRun > 0.0f) - accel = 3.0f * tmpRun; + if (tmpRun > 0.0f) accel = 3.0f * tmpRun; float time = dt * tmpJoy * m_character_h_speed; @@ -341,7 +317,8 @@ void Character::update(float dt) idleanim = false; } } - position += dt * m_character_h_speed * 1.5f * accel * Vector3(cos(m_character_rotation.valueRadians()), 0.0f, sin(m_character_rotation.valueRadians())); + position += dt * m_character_h_speed * 1.5f * accel * + Vector3(cos(m_character_rotation.valueRadians()), 0.0f, sin(m_character_rotation.valueRadians())); } else if (tmpBack > 0.0f) { @@ -356,15 +333,13 @@ void Character::update(float dt) this->SetAnimState("Walk", time); idleanim = false; } - position -= dt * m_character_h_speed * tmpBack * Vector3(cos(m_character_rotation.valueRadians()), 0.0f, sin(m_character_rotation.valueRadians())); + position -= dt * m_character_h_speed * tmpBack * + Vector3(cos(m_character_rotation.valueRadians()), 0.0f, sin(m_character_rotation.valueRadians())); } if (idleanim) { - if (isswimming) - { - this->SetAnimState("Spot_swim", dt * 2.0f); - } + if (isswimming) { this->SetAnimState("Spot_swim", dt * 2.0f); } else { this->SetAnimState("Idle_sway", dt * 1.0f); @@ -379,37 +354,28 @@ void Character::update(float dt) float angle = m_actor_coupling->ar_hydro_dir_wheel_display * -1.0f; // not getSteeringAngle(), but this, as its smoothed float anim_time_pos = ((angle + 1.0f) * 0.5f) * m_driving_anim_length; // prevent animation flickering on the borders: - if (anim_time_pos < 0.01f) - { - anim_time_pos = 0.01f; - } - if (anim_time_pos > m_driving_anim_length - 0.01f) - { - anim_time_pos = m_driving_anim_length - 0.01f; - } - m_anim_name = "Driving"; - m_anim_time = anim_time_pos; + if (anim_time_pos < 0.01f) { anim_time_pos = 0.01f; } + if (anim_time_pos > m_driving_anim_length - 0.01f) { anim_time_pos = m_driving_anim_length - 0.01f; } + m_anim_name = "Driving"; + m_anim_time = anim_time_pos; m_net_last_anim_time = 0.0f; } #ifdef USE_SOCKETW - if ((App::mp_state.GetActive() == MpState::CONNECTED) && !m_is_remote) - { - this->SendStreamData(); - } + if ((App::mp_state.GetActive() == MpState::CONNECTED) && !m_is_remote) { this->SendStreamData(); } #endif // USE_SOCKETW } void Character::move(Vector3 offset) { - m_character_position += offset; //ASYNCSCENE OLD m_character_scenenode->translate(offset); + m_character_position += offset; // ASYNCSCENE OLD m_character_scenenode->translate(offset); } // Helper function -void Character::ReportError(const char* detail) +void Character::ReportError(const char *detail) { #ifdef USE_SOCKETW - Ogre::UTFString username; + Ogre::UTFString username; RoRnet::UserInfo info; if (!RoR::Networking::GetUserInfo(m_source_id, info)) username = "~~ERROR getting username~~"; @@ -417,9 +383,8 @@ void Character::ReportError(const char* detail) username = info.username; char msg_buf[300]; - snprintf(msg_buf, 300, - "[RoR|Networking] ERROR on m_is_remote character (User: '%s', SourceID: %d, StreamID: %d): ", - username.asUTF8_c_str(), m_source_id, m_stream_id); + snprintf(msg_buf, 300, "[RoR|Networking] ERROR on m_is_remote character (User: '%s', SourceID: %d, StreamID: %d): ", + username.asUTF8_c_str(), m_source_id, m_stream_id); LOGSTREAM << msg_buf << detail; #endif @@ -428,14 +393,13 @@ void Character::ReportError(const char* detail) void Character::SendStreamSetup() { #ifdef USE_SOCKETW - if (m_is_remote) - return; + if (m_is_remote) return; RoRnet::StreamRegister reg; memset(®, 0, sizeof(reg)); reg.status = 1; strcpy(reg.name, "default"); - reg.type = 1; + reg.type = 1; reg.data[0] = 2; RoR::Networking::AddLocalStream(®, sizeof(RoRnet::StreamRegister)); @@ -448,45 +412,42 @@ void Character::SendStreamSetup() void Character::SendStreamData() { #ifdef USE_SOCKETW - if (m_net_timer.getMilliseconds() - m_net_last_update_time < 100) - return; + if (m_net_timer.getMilliseconds() - m_net_last_update_time < 100) return; // do not send position data if coupled to an actor already - if (m_actor_coupling) - return; + if (m_actor_coupling) return; m_net_last_update_time = m_net_timer.getMilliseconds(); Networking::CharacterMsgPos msg; - msg.command = Networking::CHARACTER_CMD_POSITION; - msg.pos_x = m_character_position.x; - msg.pos_y = m_character_position.y; - msg.pos_z = m_character_position.z; + msg.command = Networking::CHARACTER_CMD_POSITION; + msg.pos_x = m_character_position.x; + msg.pos_y = m_character_position.y; + msg.pos_z = m_character_position.z; msg.rot_angle = m_character_rotation.valueRadians(); strncpy(msg.anim_name, m_anim_name.c_str(), CHARACTER_ANIM_NAME_LEN); msg.anim_time = m_anim_time - m_net_last_anim_time; m_net_last_anim_time = m_anim_time; - RoR::Networking::AddPacket(m_stream_id, RoRnet::MSG2_STREAM_DATA_DISCARDABLE, sizeof(Networking::CharacterMsgPos), (char*)&msg); + RoR::Networking::AddPacket(m_stream_id, RoRnet::MSG2_STREAM_DATA_DISCARDABLE, sizeof(Networking::CharacterMsgPos), + (char *)&msg); #endif // USE_SOCKETW } -void Character::receiveStreamData(unsigned int& type, int& source, unsigned int& streamid, char* buffer) +void Character::receiveStreamData(unsigned int &type, int &source, unsigned int &streamid, char *buffer) { #ifdef USE_SOCKETW if (type == RoRnet::MSG2_STREAM_DATA && m_source_id == source && m_stream_id == streamid) { - auto* msg = reinterpret_cast(buffer); + auto *msg = reinterpret_cast(buffer); if (msg->command == Networking::CHARACTER_CMD_POSITION) { - auto* pos_msg = reinterpret_cast(buffer); + auto *pos_msg = reinterpret_cast(buffer); this->setPosition(Ogre::Vector3(pos_msg->pos_x, pos_msg->pos_y, pos_msg->pos_z)); this->setRotation(Ogre::Radian(pos_msg->rot_angle)); if (strnlen(pos_msg->anim_name, CHARACTER_ANIM_NAME_LEN) < CHARACTER_ANIM_NAME_LEN) - { - this->SetAnimState(pos_msg->anim_name, pos_msg->anim_time); - } + { this->SetAnimState(pos_msg->anim_name, pos_msg->anim_time); } } else if (msg->command == Networking::CHARACTER_CMD_DETACH) { @@ -497,18 +458,17 @@ void Character::receiveStreamData(unsigned int& type, int& source, unsigned int& } else if (msg->command == Networking::CHARACTER_CMD_ATTACH) { - auto* attach_msg = reinterpret_cast(buffer); - Actor* beam = App::GetSimController()->GetBeamFactory()->GetActorByNetworkLinks(attach_msg->source_id, attach_msg->stream_id); - if (beam != nullptr) - { - this->SetActorCoupling(true, beam); - } + auto * attach_msg = reinterpret_cast(buffer); + Actor *beam = + App::GetSimController()->GetBeamFactory()->GetActorByNetworkLinks(attach_msg->source_id, attach_msg->stream_id); + if (beam != nullptr) { this->SetActorCoupling(true, beam); } else { char err_buf[200]; - snprintf(err_buf, 200, "Received command `ATTACH` with target{SourceID: %d, StreamID: %d}, " - "but corresponding vehicle doesn't exist. Ignoring command.", - attach_msg->source_id, attach_msg->stream_id); + snprintf(err_buf, 200, + "Received command `ATTACH` with target{SourceID: %d, StreamID: %d}, " + "but corresponding vehicle doesn't exist. Ignoring command.", + attach_msg->source_id, attach_msg->stream_id); this->ReportError(err_buf); } } @@ -522,9 +482,7 @@ void Character::receiveStreamData(unsigned int& type, int& source, unsigned int& #endif } - - -void Character::SetActorCoupling(bool enabled, Actor* actor) +void Character::SetActorCoupling(bool enabled, Actor *actor) { m_actor_coupling = actor; #ifdef USE_SOCKETW @@ -533,24 +491,26 @@ void Character::SetActorCoupling(bool enabled, Actor* actor) if (enabled) { Networking::CharacterMsgAttach msg; - msg.command = Networking::CHARACTER_CMD_ATTACH; + msg.command = Networking::CHARACTER_CMD_ATTACH; msg.source_id = m_actor_coupling->ar_net_source_id; msg.stream_id = m_actor_coupling->ar_net_stream_id; - RoR::Networking::AddPacket(m_stream_id, RoRnet::MSG2_STREAM_DATA, sizeof(Networking::CharacterMsgAttach), (char*)&msg); + RoR::Networking::AddPacket(m_stream_id, RoRnet::MSG2_STREAM_DATA, sizeof(Networking::CharacterMsgAttach), + (char *)&msg); } else { Networking::CharacterMsgGeneric msg; msg.command = Networking::CHARACTER_CMD_DETACH; - RoR::Networking::AddPacket(m_stream_id, RoRnet::MSG2_STREAM_DATA, sizeof(Networking::CharacterMsgGeneric), (char*)&msg); + RoR::Networking::AddPacket(m_stream_id, RoRnet::MSG2_STREAM_DATA, sizeof(Networking::CharacterMsgGeneric), + (char *)&msg); } } #endif // USE_SOCKETW } -GfxCharacter* Character::SetupGfx() +GfxCharacter *Character::SetupGfx() { - Entity* entity = gEnv->sceneManager->createEntity(m_instance_name + "_mesh", "character.mesh"); + Entity *entity = gEnv->sceneManager->createEntity(m_instance_name + "_mesh", "character.mesh"); m_driving_anim_length = entity->getAnimationState("Driving")->getLength(); // fix disappearing mesh @@ -559,7 +519,7 @@ GfxCharacter* Character::SetupGfx() entity->getMesh()->_setBounds(aabb); // add entity to the scene node - Ogre::SceneNode* scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + Ogre::SceneNode *scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); scenenode->attachObject(entity); scenenode->setScale(0.02f, 0.02f, 0.02f); scenenode->setVisible(false); @@ -569,10 +529,10 @@ GfxCharacter* Character::SetupGfx() MaterialPtr mat2 = mat1->clone("tracks/" + m_instance_name); entity->setMaterialName("tracks/" + m_instance_name); - m_gfx_character = new GfxCharacter(); - m_gfx_character->xc_scenenode = scenenode; - m_gfx_character->xc_movable_text = nullptr; - m_gfx_character->xc_character = this; + m_gfx_character = new GfxCharacter(); + m_gfx_character->xc_scenenode = scenenode; + m_gfx_character->xc_movable_text = nullptr; + m_gfx_character->xc_character = this; m_gfx_character->xc_instance_name = m_instance_name; return m_gfx_character; @@ -581,14 +541,11 @@ GfxCharacter* Character::SetupGfx() RoR::GfxCharacter::~GfxCharacter() { App::GetSimController()->GetGfxScene().GetSurveyMap()->deleteMapEntity(xc_survey_map_entity); - Entity* ent = static_cast(xc_scenenode->getAttachedObject(0)); + Entity *ent = static_cast(xc_scenenode->getAttachedObject(0)); xc_scenenode->detachAllObjects(); gEnv->sceneManager->destroySceneNode(xc_scenenode); gEnv->sceneManager->destroyEntity(ent); - if (xc_movable_text != nullptr) - { - delete xc_movable_text; - } + if (xc_movable_text != nullptr) { delete xc_movable_text; } MaterialManager::getSingleton().unload("tracks/" + xc_instance_name); } @@ -596,14 +553,14 @@ void RoR::GfxCharacter::BufferSimulationData() { xc_simbuf_prev = xc_simbuf; - xc_simbuf.simbuf_character_pos = xc_character->getPosition(); - xc_simbuf.simbuf_character_rot = xc_character->getRotation(); - xc_simbuf.simbuf_color_number = xc_character->GetColorNum(); - xc_simbuf.simbuf_net_username = xc_character->GetNetUsername(); - xc_simbuf.simbuf_is_remote = xc_character->GetIsRemote(); - xc_simbuf.simbuf_actor_coupling = xc_character->GetActorCoupling(); - xc_simbuf.simbuf_anim_name = xc_character->GetAnimName(); - xc_simbuf.simbuf_anim_time = xc_character->GetAnimTime(); + xc_simbuf.simbuf_character_pos = xc_character->getPosition(); + xc_simbuf.simbuf_character_rot = xc_character->getRotation(); + xc_simbuf.simbuf_color_number = xc_character->GetColorNum(); + xc_simbuf.simbuf_net_username = xc_character->GetNetUsername(); + xc_simbuf.simbuf_is_remote = xc_character->GetIsRemote(); + xc_simbuf.simbuf_actor_coupling = xc_character->GetActorCoupling(); + xc_simbuf.simbuf_anim_name = xc_character->GetAnimName(); + xc_simbuf.simbuf_anim_time = xc_character->GetAnimTime(); } void RoR::GfxCharacter::UpdateCharacterInScene() @@ -614,20 +571,14 @@ void RoR::GfxCharacter::UpdateCharacterInScene() if (xc_simbuf.simbuf_actor_coupling != nullptr) { // Entering/switching vehicle - if (xc_movable_text != nullptr) - { - xc_movable_text->setVisible(false); - } + if (xc_movable_text != nullptr) { xc_movable_text->setVisible(false); } xc_scenenode->getAttachedObject(0)->setCastShadows(false); xc_scenenode->setVisible(xc_simbuf.simbuf_actor_coupling->GetGfxActor()->HasDriverSeatProp()); } else if (xc_simbuf_prev.simbuf_actor_coupling != nullptr) { // Leaving vehicle - if (xc_movable_text != nullptr) - { - xc_movable_text->setVisible(true); - } + if (xc_movable_text != nullptr) { xc_movable_text->setVisible(true); } xc_scenenode->getAttachedObject(0)->setCastShadows(true); xc_scenenode->resetOrientation(); } @@ -638,11 +589,8 @@ void RoR::GfxCharacter::UpdateCharacterInScene() { if (xc_simbuf.simbuf_actor_coupling->GetGfxActor()->HasDriverSeatProp()) { - if (xc_movable_text != nullptr) - { - xc_movable_text->setVisible(false); - } - Ogre::Vector3 pos; + if (xc_movable_text != nullptr) { xc_movable_text->setVisible(false); } + Ogre::Vector3 pos; Ogre::Quaternion rot; xc_simbuf.simbuf_actor_coupling->GetGfxActor()->CalculateDriverPos(pos, rot); xc_scenenode->setOrientation(rot); @@ -659,7 +607,7 @@ void RoR::GfxCharacter::UpdateCharacterInScene() } // Animation - Ogre::Entity* entity = static_cast(xc_scenenode->getAttachedObject(0)); + Ogre::Entity *entity = static_cast(xc_scenenode->getAttachedObject(0)); if (xc_simbuf.simbuf_anim_name != xc_simbuf_prev.simbuf_anim_name) { // 'Classic' method - enable one anim, exterminate the others ~ only_a_ptr, 06/2018 @@ -667,7 +615,7 @@ void RoR::GfxCharacter::UpdateCharacterInScene() while (it.hasMoreElements()) { - AnimationState* as = it.getNext(); + AnimationState *as = it.getNext(); if (as->getAnimationName() == xc_simbuf.simbuf_anim_name) { @@ -684,7 +632,7 @@ void RoR::GfxCharacter::UpdateCharacterInScene() } else { - auto* as_cur = entity->getAnimationState(xc_simbuf.simbuf_anim_name); + auto *as_cur = entity->getAnimationState(xc_simbuf.simbuf_anim_name); as_cur->setTimePosition(xc_simbuf.simbuf_anim_time); } @@ -692,9 +640,9 @@ void RoR::GfxCharacter::UpdateCharacterInScene() if (xc_survey_map_entity == nullptr) xc_survey_map_entity = App::GetSimController()->GetGfxScene().GetSurveyMap()->createMapEntity("person"); String caption = (App::mp_state.GetActive() == MpState::CONNECTED) ? xc_simbuf.simbuf_net_username : ""; - App::GetSimController()->GetGfxScene().GetSurveyMap()->UpdateMapEntity(xc_survey_map_entity, caption, - xc_simbuf.simbuf_character_pos, xc_simbuf.simbuf_character_rot.valueRadians(), - -static_cast(xc_simbuf.simbuf_is_remote), !xc_simbuf.simbuf_actor_coupling); + App::GetSimController()->GetGfxScene().GetSurveyMap()->UpdateMapEntity( + xc_survey_map_entity, caption, xc_simbuf.simbuf_character_pos, xc_simbuf.simbuf_character_rot.valueRadians(), + -static_cast(xc_simbuf.simbuf_is_remote), !xc_simbuf.simbuf_actor_coupling); // Multiplayer label #ifdef USE_SOCKETW @@ -713,13 +661,12 @@ void RoR::GfxCharacter::UpdateCharacterInScene() MaterialPtr mat = MaterialManager::getSingleton().getByName(materialName); if (!mat.isNull() && mat->getNumTechniques() > 0 && mat->getTechnique(0)->getNumPasses() > 1 && - mat->getTechnique(0)->getPass(1)->getNumTextureUnitStates() > 1) + mat->getTechnique(0)->getPass(1)->getNumTextureUnitStates() > 1) { - const auto& state = mat->getTechnique(0)->getPass(1)->getTextureUnitState(1); + const auto & state = mat->getTechnique(0)->getPass(1)->getTextureUnitState(1); Ogre::ColourValue color = Networking::GetPlayerColor(xc_simbuf.simbuf_color_number); state->setColourOperationEx(LBX_BLEND_CURRENT_ALPHA, LBS_MANUAL, LBS_CURRENT, color); - if (xc_movable_text != nullptr) - xc_movable_text->setColor(color); + if (xc_movable_text != nullptr) xc_movable_text->setColor(color); } if (xc_movable_text != nullptr) @@ -734,7 +681,8 @@ void RoR::GfxCharacter::UpdateCharacterInScene() xc_movable_text->setCaption(xc_simbuf.simbuf_net_username); if (camDist > 1000.0f) - xc_movable_text->setCaption(xc_simbuf.simbuf_net_username + " (" + TOSTRING((float)(ceil(camDist / 100) / 10.0f)) + " km)"); + xc_movable_text->setCaption(xc_simbuf.simbuf_net_username + " (" + + TOSTRING((float)(ceil(camDist / 100) / 10.0f)) + " km)"); else if (camDist > 20.0f && camDist <= 1000.0f) xc_movable_text->setCaption(xc_simbuf.simbuf_net_username + " (" + TOSTRING((int)camDist) + " m)"); else diff --git a/source/main/gameplay/Character.h b/source/main/gameplay/Character.h index 907464d9d2..3084d40735 100644 --- a/source/main/gameplay/Character.h +++ b/source/main/gameplay/Character.h @@ -28,91 +28,121 @@ class Character { -public: - - Character(int source = -1, unsigned int streamid = 0, Ogre::UTFString playerName = "", int color_number = 0, bool is_remote = true); + public: + Character(int source = -1, unsigned int streamid = 0, Ogre::UTFString playerName = "", int color_number = 0, + bool is_remote = true); ~Character(); - - int getSourceID() const { return m_source_id; } - bool isRemote() const { return m_is_remote; } - int GetColorNum() const { return m_color_number; } - bool GetIsRemote() const { return m_is_remote; } - Ogre::UTFString const& GetNetUsername() { return m_net_username; } - std::string const & GetAnimName() const { return m_anim_name; } - float GetAnimTime() const { return m_anim_time; } - Ogre::Radian getRotation() const { return m_character_rotation; } - Actor* GetActorCoupling() { return m_actor_coupling; } - void setColour(int color) { this->m_color_number = color; } - Ogre::Vector3 getPosition(); - void setPosition(Ogre::Vector3 position); - void setRotation(Ogre::Radian rotation); - void move(Ogre::Vector3 offset); - void update(float dt); - void updateCharacterRotation(); - void receiveStreamData(unsigned int& type, int& source, unsigned int& streamid, char* buffer); - void SetActorCoupling(bool enabled, Actor* actor); - - RoR::GfxCharacter* SetupGfx(); - -private: - - void ReportError(const char* detail); - void SendStreamData(); - void SendStreamSetup(); - void SetAnimState(std::string mode, float time = 0); - - Actor* m_actor_coupling; //!< The vehicle or machine which the character occupies - Ogre::Radian m_character_rotation; - float m_character_h_speed; - float m_character_v_speed; - Ogre::Vector3 m_character_position; - Ogre::Vector3 m_prev_position; - int m_color_number; - int m_stream_id; - int m_source_id; - bool m_can_jump; - bool m_is_remote; - std::string m_anim_name; - float m_anim_time; - float m_net_last_anim_time; - float m_driving_anim_length; - std::string m_instance_name; - Ogre::UTFString m_net_username; - Ogre::Timer m_net_timer; - unsigned long m_net_last_update_time; - - RoR::GfxCharacter* m_gfx_character; -}; -namespace RoR { + int getSourceID() const + { + return m_source_id; + } + bool isRemote() const + { + return m_is_remote; + } + int GetColorNum() const + { + return m_color_number; + } + bool GetIsRemote() const + { + return m_is_remote; + } + Ogre::UTFString const &GetNetUsername() + { + return m_net_username; + } + std::string const &GetAnimName() const + { + return m_anim_name; + } + float GetAnimTime() const + { + return m_anim_time; + } + Ogre::Radian getRotation() const + { + return m_character_rotation; + } + Actor *GetActorCoupling() + { + return m_actor_coupling; + } + void setColour(int color) + { + this->m_color_number = color; + } + Ogre::Vector3 getPosition(); + void setPosition(Ogre::Vector3 position); + void setRotation(Ogre::Radian rotation); + void move(Ogre::Vector3 offset); + void update(float dt); + void updateCharacterRotation(); + void receiveStreamData(unsigned int &type, int &source, unsigned int &streamid, char *buffer); + void SetActorCoupling(bool enabled, Actor *actor); + + RoR::GfxCharacter *SetupGfx(); + + private: + void ReportError(const char *detail); + void SendStreamData(); + void SendStreamSetup(); + void SetAnimState(std::string mode, float time = 0); + + Actor * m_actor_coupling; //!< The vehicle or machine which the character occupies + Ogre::Radian m_character_rotation; + float m_character_h_speed; + float m_character_v_speed; + Ogre::Vector3 m_character_position; + Ogre::Vector3 m_prev_position; + int m_color_number; + int m_stream_id; + int m_source_id; + bool m_can_jump; + bool m_is_remote; + std::string m_anim_name; + float m_anim_time; + float m_net_last_anim_time; + float m_driving_anim_length; + std::string m_instance_name; + Ogre::UTFString m_net_username; + Ogre::Timer m_net_timer; + unsigned long m_net_last_update_time; + + RoR::GfxCharacter *m_gfx_character; +}; -struct GfxCharacter +namespace RoR { - struct SimBuffer //!< Buffered simulation state for async gfx scene update + + struct GfxCharacter { - Ogre::Vector3 simbuf_character_pos; - Ogre::Radian simbuf_character_rot; //!< When on foot - Ogre::UTFString simbuf_net_username; - bool simbuf_is_remote; - int simbuf_color_number; - Actor* simbuf_actor_coupling; - std::string simbuf_anim_name; - float simbuf_anim_time; // Intentionally left empty = forces initial update. + struct SimBuffer //!< Buffered simulation state for async gfx scene update + { + Ogre::Vector3 simbuf_character_pos; + Ogre::Radian simbuf_character_rot; //!< When on foot + Ogre::UTFString simbuf_net_username; + bool simbuf_is_remote; + int simbuf_color_number; + Actor * simbuf_actor_coupling; + std::string simbuf_anim_name; + float simbuf_anim_time; // Intentionally left empty = forces initial update. + }; + + ~GfxCharacter(); + + void BufferSimulationData(); + void UpdateCharacterInScene(); + + SurveyMapEntity *xc_survey_map_entity; + Ogre::SceneNode *xc_scenenode; + Ogre::MovableText + * xc_movable_text; // TODO: Remake using GUI; the network labels shouldn't be part of scene. ~only_a_ptr, 05/2018 + SimBuffer xc_simbuf; + SimBuffer xc_simbuf_prev; + Character *xc_character; + std::string xc_instance_name; // TODO: Store MaterialPtr-s directly ~only_a_ptr, 05/2018 }; - - ~GfxCharacter(); - - void BufferSimulationData(); - void UpdateCharacterInScene(); - - SurveyMapEntity* xc_survey_map_entity; - Ogre::SceneNode* xc_scenenode; - Ogre::MovableText* xc_movable_text; // TODO: Remake using GUI; the network labels shouldn't be part of scene. ~only_a_ptr, 05/2018 - SimBuffer xc_simbuf; - SimBuffer xc_simbuf_prev; - Character* xc_character; - std::string xc_instance_name; // TODO: Store MaterialPtr-s directly ~only_a_ptr, 05/2018 -}; } // namespace RoR - diff --git a/source/main/gameplay/CharacterFactory.cpp b/source/main/gameplay/CharacterFactory.cpp index aeef48b50b..a12fbec86f 100644 --- a/source/main/gameplay/CharacterFactory.cpp +++ b/source/main/gameplay/CharacterFactory.cpp @@ -28,9 +28,9 @@ using namespace RoR; -Character* CharacterFactory::createLocal(Ogre::UTFString playerName, int playerColour) +Character *CharacterFactory::createLocal(Ogre::UTFString playerName, int playerColour) { - Character* ch = new Character(-1, 0, playerName, playerColour, false); + Character *ch = new Character(-1, 0, playerName, playerColour, false); App::GetSimController()->GetGfxScene().RegisterGfxCharacter(ch->SetupGfx()); return ch; } @@ -40,12 +40,12 @@ void CharacterFactory::createRemoteInstance(int sourceid, int streamid) #ifdef USE_SOCKETW RoRnet::UserInfo info; RoR::Networking::GetUserInfo(sourceid, info); - int colour = info.colournum; - Ogre::UTFString name = tryConvertUTF(info.username); + int colour = info.colournum; + Ogre::UTFString name = tryConvertUTF(info.username); LOG(" new character for " + TOSTRING(sourceid) + ":" + TOSTRING(streamid) + ", colour: " + TOSTRING(colour)); - Character* ch = new Character(sourceid, streamid, name, colour, true); + Character *ch = new Character(sourceid, streamid, name, colour, true); App::GetSimController()->GetGfxScene().RegisterGfxCharacter(ch->SetupGfx()); m_remote_characters.push_back(std::unique_ptr(ch)); #endif // USE_SOCKETW @@ -68,20 +68,17 @@ void CharacterFactory::update(float dt) { gEnv->player->update(dt); - for (auto& c : m_remote_characters) + for (auto &c : m_remote_characters) { c->update(dt); } } -void CharacterFactory::UndoRemoteActorCoupling(Actor* actor) +void CharacterFactory::UndoRemoteActorCoupling(Actor *actor) { - for (auto& c : m_remote_characters) + for (auto &c : m_remote_characters) { - if (c->GetActorCoupling() == actor) - { - c->SetActorCoupling(false, nullptr); - } + if (c->GetActorCoupling() == actor) { c->SetActorCoupling(false, nullptr); } } } @@ -97,11 +94,8 @@ void CharacterFactory::handleStreamData(std::vectortype == 1) - { - createRemoteInstance(packet.header.source, packet.header.streamid); - } + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)packet.buffer; + if (reg->type == 1) { createRemoteInstance(packet.header.source, packet.header.streamid); } } else if (packet.header.command == RoRnet::MSG2_USER_LEAVE) { @@ -109,7 +103,7 @@ void CharacterFactory::handleStreamData(std::vectorreceiveStreamData(packet.header.command, packet.header.source, packet.header.streamid, packet.buffer); } diff --git a/source/main/gameplay/CharacterFactory.h b/source/main/gameplay/CharacterFactory.h index 5df99db0a8..40b794c4e7 100644 --- a/source/main/gameplay/CharacterFactory.h +++ b/source/main/gameplay/CharacterFactory.h @@ -21,31 +21,32 @@ #pragma once -#include "RoRPrerequisites.h" - #include "Character.h" #include "Network.h" +#include "RoRPrerequisites.h" -namespace RoR { - -class CharacterFactory +namespace RoR { -public: - CharacterFactory() {} - Character* createLocal(Ogre::UTFString playerName, int playerColour); - void DeleteAllRemoteCharacters(); - void UndoRemoteActorCoupling(Actor* actor); - void update(float dt); + + class CharacterFactory + { + public: + CharacterFactory() + { + } + Character *createLocal(Ogre::UTFString playerName, int playerColour); + void DeleteAllRemoteCharacters(); + void UndoRemoteActorCoupling(Actor *actor); + void update(float dt); #ifdef USE_SOCKETW - void handleStreamData(std::vector packet); + void handleStreamData(std::vector packet); #endif // USE_SOCKETW -private: - - std::vector> m_remote_characters; + private: + std::vector> m_remote_characters; - void createRemoteInstance(int sourceid, int streamid); - void removeStreamSource(int sourceid); -}; + void createRemoteInstance(int sourceid, int streamid); + void removeStreamSource(int sourceid); + }; } // namespace RoR diff --git a/source/main/gameplay/ChatSystem.cpp b/source/main/gameplay/ChatSystem.cpp index 203efe962b..d519c9b962 100644 --- a/source/main/gameplay/ChatSystem.cpp +++ b/source/main/gameplay/ChatSystem.cpp @@ -24,172 +24,173 @@ #include "Language.h" #include "Utils.h" -namespace RoR { -namespace ChatSystem { +namespace RoR +{ + namespace ChatSystem + { -using namespace RoRnet; + using namespace RoRnet; -static int m_stream_id; + static int m_stream_id; #ifdef USE_SOCKETW -void SendStreamSetup() -{ - RoRnet::StreamRegister reg; - memset(®, 0, sizeof(RoRnet::StreamRegister)); - reg.status = 1; - strcpy(reg.name, "chat"); - reg.type = 3; + void SendStreamSetup() + { + RoRnet::StreamRegister reg; + memset(®, 0, sizeof(RoRnet::StreamRegister)); + reg.status = 1; + strcpy(reg.name, "chat"); + reg.type = 3; - RoR::Networking::AddLocalStream(®, sizeof(RoRnet::StreamRegister)); + RoR::Networking::AddLocalStream(®, sizeof(RoRnet::StreamRegister)); - m_stream_id = reg.origin_streamid; -} + m_stream_id = reg.origin_streamid; + } #endif // USE_SOCKETW -Ogre::UTFString GetColouredName(Ogre::UTFString nick, int colour_number) -{ + Ogre::UTFString GetColouredName(Ogre::UTFString nick, int colour_number) + { #ifdef USE_SOCKETW - Ogre::ColourValue col_val = Networking::GetPlayerColor(colour_number); - char tmp[255] = {0}; - sprintf(tmp, "#%02X%02X%02X", (unsigned int)(col_val.r * 255.0f), (unsigned int)(col_val.g * 255.0f), (unsigned int)(col_val.b * 255.0f)); - - // replace # with X in nickname so the user cannot fake the colour - for (unsigned int i = 0; i < nick.size(); i++) - if (nick[i] == '#') - nick[i] = 'X'; - - return tryConvertUTF(tmp) + nick; -#else // USE_SOCKETW - return nick; + Ogre::ColourValue col_val = Networking::GetPlayerColor(colour_number); + char tmp[255] = {0}; + sprintf(tmp, "#%02X%02X%02X", (unsigned int)(col_val.r * 255.0f), (unsigned int)(col_val.g * 255.0f), + (unsigned int)(col_val.b * 255.0f)); + + // replace # with X in nickname so the user cannot fake the colour + for (unsigned int i = 0; i < nick.size(); i++) + if (nick[i] == '#') nick[i] = 'X'; + + return tryConvertUTF(tmp) + nick; +#else // USE_SOCKETW + return nick; #endif // USE_SOCKETW -} + } #ifdef USE_SOCKETW -void ReceiveStreamData(unsigned int type, int source, char* buffer) -{ - if (type != MSG2_UTF8_CHAT && type != MSG2_UTF8_PRIVCHAT) - return; + void ReceiveStreamData(unsigned int type, int source, char *buffer) + { + if (type != MSG2_UTF8_CHAT && type != MSG2_UTF8_PRIVCHAT) return; - Ogre::UTFString msg = tryConvertUTF(buffer); + Ogre::UTFString msg = tryConvertUTF(buffer); - if (type == MSG2_UTF8_CHAT) - { - if (source == -1) - { - // server said something - } - else if (source == RoR::Networking::GetUID()) - { - // our message bounced back :D - Ogre::UTFString local_username = GetColouredName(RoR::Networking::GetUsername(), RoR::Networking::GetUserColor()); - msg = local_username + RoR::Color::NormalColour + ": " + msg; - } - else - { - RoRnet::UserInfo user; - if (RoR::Networking::GetUserInfo(source, user)) + if (type == MSG2_UTF8_CHAT) { - msg = GetColouredName(user.username, user.colournum) + RoR::Color::NormalColour + ": " + msg; + if (source == -1) + { + // server said something + } + else if (source == RoR::Networking::GetUID()) + { + // our message bounced back :D + Ogre::UTFString local_username = + GetColouredName(RoR::Networking::GetUsername(), RoR::Networking::GetUserColor()); + msg = local_username + RoR::Color::NormalColour + ": " + msg; + } + else + { + RoRnet::UserInfo user; + if (RoR::Networking::GetUserInfo(source, user)) + { msg = GetColouredName(user.username, user.colournum) + RoR::Color::NormalColour + ": " + msg; } + } } - } - } - else if (type == MSG2_UTF8_PRIVCHAT) - { - if (source == -1) - { - // server said something - msg = RoR::Color::WhisperColour + _L(" [whispered] ") + RoR::Color::NormalColour + msg; - } - else - { - RoRnet::UserInfo user; - if (RoR::Networking::GetUserInfo(source, user)) + else if (type == MSG2_UTF8_PRIVCHAT) { - msg = GetColouredName(user.username, user.colournum) + _L(" [whispered] ") + RoR::Color::NormalColour + ": " + msg; + if (source == -1) + { + // server said something + msg = RoR::Color::WhisperColour + _L(" [whispered] ") + RoR::Color::NormalColour + msg; + } + else + { + RoRnet::UserInfo user; + if (RoR::Networking::GetUserInfo(source, user)) + { + msg = GetColouredName(user.username, user.colournum) + _L(" [whispered] ") + RoR::Color::NormalColour + + ": " + msg; + } + } } + RoR::App::GetGuiManager()->pushMessageChatBox(msg); } - } - RoR::App::GetGuiManager()->pushMessageChatBox(msg); -} #endif // USE_SOCKETW #ifdef USE_SOCKETW -void HandleStreamData(std::vector packet_buffer) -{ - for (auto packet : packet_buffer) - { - ReceiveStreamData(packet.header.command, packet.header.source, packet.buffer); - } -} + void HandleStreamData(std::vector packet_buffer) + { + for (auto packet : packet_buffer) + { + ReceiveStreamData(packet.header.command, packet.header.source, packet.buffer); + } + } #endif // USE_SOCKETW -void SendChat(Ogre::UTFString chatline) -{ + void SendChat(Ogre::UTFString chatline) + { #ifdef USE_SOCKETW - const char* utf8_line = chatline.asUTF8_c_str(); - RoR::Networking::AddPacket(m_stream_id, MSG2_UTF8_CHAT, (unsigned int)strlen(utf8_line), (char *)utf8_line); + const char *utf8_line = chatline.asUTF8_c_str(); + RoR::Networking::AddPacket(m_stream_id, MSG2_UTF8_CHAT, (unsigned int)strlen(utf8_line), (char *)utf8_line); #endif // USE_SOCKETW -} + } -void SendPrivateChat(int target_uid, Ogre::UTFString chatline, Ogre::UTFString target_username) -{ + void SendPrivateChat(int target_uid, Ogre::UTFString chatline, Ogre::UTFString target_username) + { #ifdef USE_SOCKETW - char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; + char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; - const char* chat_msg = (const char *)chatline.asUTF8_c_str(); + const char *chat_msg = (const char *)chatline.asUTF8_c_str(); - // format: int of UID, then chat message - memcpy(buffer, &target_uid, sizeof(int)); - strncpy(buffer + sizeof(int), chat_msg, RORNET_MAX_MESSAGE_LENGTH - sizeof(int)); + // format: int of UID, then chat message + memcpy(buffer, &target_uid, sizeof(int)); + strncpy(buffer + sizeof(int), chat_msg, RORNET_MAX_MESSAGE_LENGTH - sizeof(int)); - size_t len = sizeof(int) + chatline.size() * sizeof(wchar_t); - buffer[len] = 0; + size_t len = sizeof(int) + chatline.size() * sizeof(wchar_t); + buffer[len] = 0; - RoR::Networking::AddPacket(m_stream_id, MSG2_UTF8_PRIVCHAT, (unsigned int)len, buffer); + RoR::Networking::AddPacket(m_stream_id, MSG2_UTF8_PRIVCHAT, (unsigned int)len, buffer); - if (target_username.empty()) - { - RoRnet::UserInfo user; - if (RoR::Networking::GetUserInfo(target_uid, user)) - { - target_username = GetColouredName(user.username, user.colournum); - } - } + if (target_username.empty()) + { + RoRnet::UserInfo user; + if (RoR::Networking::GetUserInfo(target_uid, user)) + { target_username = GetColouredName(user.username, user.colournum); } + } - // add local visual - Ogre::UTFString local_username = GetColouredName(RoR::Networking::GetUsername(), RoR::Networking::GetUserColor()); - Ogre::UTFString nmsg = local_username + RoR::Color::WhisperColour + _L(" [whispered to ") + RoR::Color::NormalColour + target_username + RoR::Color::WhisperColour + "]" + RoR::Color::NormalColour + ": " + chatline; - RoR::App::GetGuiManager()->pushMessageChatBox(nmsg); + // add local visual + Ogre::UTFString local_username = GetColouredName(RoR::Networking::GetUsername(), RoR::Networking::GetUserColor()); + Ogre::UTFString nmsg = local_username + RoR::Color::WhisperColour + _L(" [whispered to ") + RoR::Color::NormalColour + + target_username + RoR::Color::WhisperColour + "]" + RoR::Color::NormalColour + ": " + chatline; + RoR::App::GetGuiManager()->pushMessageChatBox(nmsg); #endif // USE_SOCKETW -} + } -void SendPrivateChat(Ogre::UTFString target_username, Ogre::UTFString chatline) -{ + void SendPrivateChat(Ogre::UTFString target_username, Ogre::UTFString chatline) + { #ifdef USE_SOCKETW - // first: find id to username: - RoRnet::UserInfo target_user; - std::vector users = RoR::Networking::GetUserInfos(); + // first: find id to username: + RoRnet::UserInfo target_user; + std::vector users = RoR::Networking::GetUserInfos(); - bool found_target = false; - for (auto user : users) - { - if (Ogre::UTFString(user.username) == target_username) - { - found_target = true; - target_user = user; - break; - } - } + bool found_target = false; + for (auto user : users) + { + if (Ogre::UTFString(user.username) == target_username) + { + found_target = true; + target_user = user; + break; + } + } - if (!found_target) - { - RoR::App::GetGuiManager()->pushMessageChatBox(RoR::Color::CommandColour + _L("user not found: ") + target_username); - return; - } + if (!found_target) + { + RoR::App::GetGuiManager()->pushMessageChatBox(RoR::Color::CommandColour + _L("user not found: ") + + target_username); + return; + } - SendPrivateChat(target_user.uniqueid, chatline, GetColouredName(target_user.username, target_user.colournum)); + SendPrivateChat(target_user.uniqueid, chatline, GetColouredName(target_user.username, target_user.colournum)); #endif // USE_SOCKETW -} + } -} // namespace ChatSystem + } // namespace ChatSystem } // namespace RoR diff --git a/source/main/gameplay/ChatSystem.h b/source/main/gameplay/ChatSystem.h index af0f5e7ec4..6e015c0d9e 100644 --- a/source/main/gameplay/ChatSystem.h +++ b/source/main/gameplay/ChatSystem.h @@ -21,23 +21,24 @@ #pragma once -#include "RoRPrerequisites.h" - #include "Network.h" +#include "RoRPrerequisites.h" -namespace RoR { -namespace ChatSystem { +namespace RoR +{ + namespace ChatSystem + { -void SendChat(Ogre::UTFString chatline); -void SendPrivateChat(Ogre::UTFString target_username, Ogre::UTFString chatline); + void SendChat(Ogre::UTFString chatline); + void SendPrivateChat(Ogre::UTFString target_username, Ogre::UTFString chatline); -void SendStreamSetup(); + void SendStreamSetup(); #ifdef USE_SOCKETW -void HandleStreamData(std::vector packet); + void HandleStreamData(std::vector packet); #endif // USE_SOCKETW -Ogre::UTFString GetColouredName(Ogre::UTFString nick, int colour_number); + Ogre::UTFString GetColouredName(Ogre::UTFString nick, int colour_number); -} // namespace Chatsystem + } // namespace ChatSystem } // namespace RoR diff --git a/source/main/gameplay/LandVehicleSimulation.cpp b/source/main/gameplay/LandVehicleSimulation.cpp index 80dc141097..ced918e5f3 100644 --- a/source/main/gameplay/LandVehicleSimulation.cpp +++ b/source/main/gameplay/LandVehicleSimulation.cpp @@ -24,33 +24,30 @@ #include "Application.h" #include "Beam.h" #include "BeamEngine.h" +#include "GUIManager.h" #include "GUI_GameConsole.h" #include "InputEngine.h" #include "Language.h" #include "SoundScriptManager.h" #include "TerrainManager.h" -#include "GUIManager.h" #include "VehicleAI.h" using namespace RoR; -void LandVehicleSimulation::UpdateCruiseControl(Actor* vehicle, float dt) +void LandVehicleSimulation::UpdateCruiseControl(Actor *vehicle, float dt) { - EngineSim* engine = vehicle->ar_engine; + EngineSim *engine = vehicle->ar_engine; if ((engine->GetGear() > 0 && RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE) > 0.05f) || (engine->GetGear() > 0 && vehicle->cc_target_speed < vehicle->cc_target_speed_lower_limit) || - (engine->GetGear() > 0 && vehicle->ar_parking_brake) || - (engine->GetGear() < 0) || - !engine->IsRunning() || + (engine->GetGear() > 0 && vehicle->ar_parking_brake) || (engine->GetGear() < 0) || !engine->IsRunning() || !engine->HasStarterContact()) { vehicle->ToggleCruiseControl(); return; } - if (engine->GetGear() != 0 && RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_MANUAL_CLUTCH) > 0.05f) - return; + if (engine->GetGear() != 0 && RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_MANUAL_CLUTCH) > 0.05f) return; float acc = engine->GetAccToHoldRPM(); @@ -68,10 +65,7 @@ void LandVehicleSimulation::UpdateCruiseControl(Actor* vehicle, float dt) } vehicle->cc_accs.push_front(Ogre::Math::Clamp(acc, -1.0f, +1.0f)); - if (vehicle->cc_accs.size() > 30) - { - vehicle->cc_accs.pop_back(); - } + if (vehicle->cc_accs.size() > 30) { vehicle->cc_accs.pop_back(); } float avg_acc = 0.0f; for (unsigned int i = 0; i < vehicle->cc_accs.size(); i++) @@ -88,10 +82,7 @@ void LandVehicleSimulation::UpdateCruiseControl(Actor* vehicle, float dt) { vehicle->cc_target_speed *= pow(2.0f, dt / 5.0f); vehicle->cc_target_speed = std::max(vehicle->cc_target_speed_lower_limit, vehicle->cc_target_speed); - if (vehicle->sl_enabled) - { - vehicle->cc_target_speed = std::min(vehicle->cc_target_speed, vehicle->sl_speed_limit); - } + if (vehicle->sl_enabled) { vehicle->cc_target_speed = std::min(vehicle->cc_target_speed, vehicle->sl_speed_limit); } } else if (engine->GetGear() == 0) // out of gear { @@ -115,26 +106,24 @@ void LandVehicleSimulation::UpdateCruiseControl(Actor* vehicle, float dt) if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_CRUISE_CONTROL_READJUST)) { vehicle->cc_target_speed = std::max(vehicle->ar_avg_wheel_speed, vehicle->cc_target_speed); - if (vehicle->sl_enabled) - { - vehicle->cc_target_speed = std::min(vehicle->cc_target_speed, vehicle->sl_speed_limit); - } + if (vehicle->sl_enabled) { vehicle->cc_target_speed = std::min(vehicle->cc_target_speed, vehicle->sl_speed_limit); } vehicle->cc_target_rpm = engine->GetEngineRpm(); } if (vehicle->cc_can_brake) { - if (vehicle->ar_avg_wheel_speed > vehicle->cc_target_speed + 0.5f && !RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE)) + if (vehicle->ar_avg_wheel_speed > vehicle->cc_target_speed + 0.5f && + !RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE)) { - float brake = (vehicle->ar_avg_wheel_speed - vehicle->cc_target_speed) * 0.5f; + float brake = (vehicle->ar_avg_wheel_speed - vehicle->cc_target_speed) * 0.5f; vehicle->ar_brake = std::min(brake, 1.0f); } } } -void LandVehicleSimulation::CheckSpeedLimit(Actor* vehicle, float dt) +void LandVehicleSimulation::CheckSpeedLimit(Actor *vehicle, float dt) { - EngineSim* engine = vehicle->ar_engine; + EngineSim *engine = vehicle->ar_engine; if (engine && engine->GetGear() != 0) { @@ -143,84 +132,69 @@ void LandVehicleSimulation::CheckSpeedLimit(Actor* vehicle, float dt) } } -void LandVehicleSimulation::UpdateVehicle(Actor* vehicle, float seconds_since_last_frame) +void LandVehicleSimulation::UpdateVehicle(Actor *vehicle, float seconds_since_last_frame) { - if (vehicle->isBeingReset() || vehicle->ar_physics_paused || vehicle->ar_replay_mode) - return; + if (vehicle->isBeingReset() || vehicle->ar_physics_paused || vehicle->ar_replay_mode) return; #ifdef USE_ANGELSCRIPT - if (vehicle->ar_vehicle_ai && vehicle->ar_vehicle_ai->IsActive()) - return; + if (vehicle->ar_vehicle_ai && vehicle->ar_vehicle_ai->IsActive()) return; #endif // USE_ANGELSCRIPT - EngineSim* engine = vehicle->ar_engine; + EngineSim *engine = vehicle->ar_engine; - if (engine && engine->HasStarterContact() && - engine->GetAutoShiftMode() == SimGearboxMode::AUTO && + if (engine && engine->HasStarterContact() && engine->GetAutoShiftMode() == SimGearboxMode::AUTO && engine->getAutoShift() != EngineSim::NEUTRAL) { - Ogre::Vector3 dirDiff = vehicle->getDirection(); - Ogre::Degree pitchAngle = Ogre::Radian(asin(dirDiff.dotProduct(Ogre::Vector3::UNIT_Y))); + Ogre::Vector3 dirDiff = vehicle->getDirection(); + Ogre::Degree pitchAngle = Ogre::Radian(asin(dirDiff.dotProduct(Ogre::Vector3::UNIT_Y))); if (std::abs(pitchAngle.valueDegrees()) > 2.0f) { - if (engine->getAutoShift() > EngineSim::NEUTRAL && vehicle->ar_avg_wheel_speed < +0.02f && pitchAngle.valueDegrees() > 0.0f || - engine->getAutoShift() < EngineSim::NEUTRAL && vehicle->ar_avg_wheel_speed > -0.02f && pitchAngle.valueDegrees() < 0.0f) + if (engine->getAutoShift() > EngineSim::NEUTRAL && vehicle->ar_avg_wheel_speed < +0.02f && + pitchAngle.valueDegrees() > 0.0f || + engine->getAutoShift() < EngineSim::NEUTRAL && vehicle->ar_avg_wheel_speed > -0.02f && + pitchAngle.valueDegrees() < 0.0f) { // anti roll back in SimGearboxMode::AUTO (DRIVE, TWO, ONE) mode // anti roll forth in SimGearboxMode::AUTO (REAR) mode - float g = std::abs(App::GetSimTerrain()->getGravity()); + float g = std::abs(App::GetSimTerrain()->getGravity()); float downhill_force = std::abs(sin(pitchAngle.valueRadians()) * vehicle->getTotalMass()) * g; - float engine_force = std::abs(engine->GetTorque()) / vehicle->getAvgPropedWheelRadius(); - float ratio = std::max(0.0f, 1.0f - (engine_force / downhill_force)); + float engine_force = std::abs(engine->GetTorque()) / vehicle->getAvgPropedWheelRadius(); + float ratio = std::max(0.0f, 1.0f - (engine_force / downhill_force)); if (vehicle->ar_avg_wheel_speed * pitchAngle.valueDegrees() > 0.0f) - { - ratio *= sqrt((0.02f - vehicle->ar_avg_wheel_speed) / 0.02f); - } + { ratio *= sqrt((0.02f - vehicle->ar_avg_wheel_speed) / 0.02f); } vehicle->ar_brake = sqrt(ratio); } } else if (vehicle->ar_brake == 0.0f && !vehicle->ar_parking_brake && engine->GetTorque() == 0.0f) { - float ratio = std::max(0.0f, 0.2f - std::abs(vehicle->ar_avg_wheel_speed)) / 0.2f; + float ratio = std::max(0.0f, 0.2f - std::abs(vehicle->ar_avg_wheel_speed)) / 0.2f; vehicle->ar_brake = ratio; } } - if (vehicle->cc_mode) - { - LandVehicleSimulation::UpdateCruiseControl(vehicle, seconds_since_last_frame); - } - if (vehicle->sl_enabled) - { - LandVehicleSimulation::CheckSpeedLimit(vehicle, seconds_since_last_frame); - } + if (vehicle->cc_mode) { LandVehicleSimulation::UpdateCruiseControl(vehicle, seconds_since_last_frame); } + if (vehicle->sl_enabled) { LandVehicleSimulation::CheckSpeedLimit(vehicle, seconds_since_last_frame); } } -void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_since_last_frame) +void LandVehicleSimulation::UpdateInputEvents(Actor *vehicle, float seconds_since_last_frame) { - if (vehicle->isBeingReset() || vehicle->ar_physics_paused || vehicle->ar_replay_mode) - return; + if (vehicle->isBeingReset() || vehicle->ar_physics_paused || vehicle->ar_replay_mode) return; #ifdef USE_ANGELSCRIPT - if (vehicle->ar_vehicle_ai && vehicle->ar_vehicle_ai->IsActive()) - return; + if (vehicle->ar_vehicle_ai && vehicle->ar_vehicle_ai->IsActive()) return; #endif // USE_ANGELSCRIPT - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_LEFT_MIRROR_LEFT)) - vehicle->ar_left_mirror_angle -= 0.001; + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_LEFT_MIRROR_LEFT)) vehicle->ar_left_mirror_angle -= 0.001; - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_LEFT_MIRROR_RIGHT)) - vehicle->ar_left_mirror_angle += 0.001; + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_LEFT_MIRROR_RIGHT)) vehicle->ar_left_mirror_angle += 0.001; - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_RIGHT_MIRROR_LEFT)) - vehicle->ar_right_mirror_angle -= 0.001; + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_RIGHT_MIRROR_LEFT)) vehicle->ar_right_mirror_angle -= 0.001; - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_RIGHT_MIRROR_RIGHT)) - vehicle->ar_right_mirror_angle += 0.001; + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_RIGHT_MIRROR_RIGHT)) vehicle->ar_right_mirror_angle += 0.001; // steering - float tmp_left_digital = App::GetInputEngine()->getEventValue(EV_TRUCK_STEER_LEFT , false, InputEngine::ET_DIGITAL); + float tmp_left_digital = App::GetInputEngine()->getEventValue(EV_TRUCK_STEER_LEFT, false, InputEngine::ET_DIGITAL); float tmp_right_digital = App::GetInputEngine()->getEventValue(EV_TRUCK_STEER_RIGHT, false, InputEngine::ET_DIGITAL); - float tmp_left_analog = App::GetInputEngine()->getEventValue(EV_TRUCK_STEER_LEFT , false, InputEngine::ET_ANALOG); + float tmp_left_analog = App::GetInputEngine()->getEventValue(EV_TRUCK_STEER_LEFT, false, InputEngine::ET_ANALOG); float tmp_right_analog = App::GetInputEngine()->getEventValue(EV_TRUCK_STEER_RIGHT, false, InputEngine::ET_ANALOG); float sum = -std::max(tmp_left_digital, tmp_left_analog) + std::max(tmp_right_digital, tmp_right_analog); @@ -229,25 +203,19 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc vehicle->ar_hydro_speed_coupling = (tmp_left_digital >= tmp_left_analog) && (tmp_right_digital >= tmp_right_analog); - EngineSim* engine = vehicle->ar_engine; + EngineSim *engine = vehicle->ar_engine; if (engine) { - float accl = RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE); + float accl = RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE); float brake = RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE); if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE_MODIFIER_25) || RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE_MODIFIER_50)) { float acclModifier = 0.0f; - if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE_MODIFIER_25)) - { - acclModifier += 0.25f; - } - if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE_MODIFIER_50)) - { - acclModifier += 0.50f; - } + if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE_MODIFIER_25)) { acclModifier += 0.25f; } + if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_ACCELERATE_MODIFIER_50)) { acclModifier += 0.50f; } accl *= acclModifier; } @@ -255,14 +223,8 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE_MODIFIER_50)) { float brakeModifier = 0.0f; - if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE_MODIFIER_25)) - { - brakeModifier += 0.25f; - } - if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE_MODIFIER_50)) - { - brakeModifier += 0.50f; - } + if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE_MODIFIER_25)) { brakeModifier += 0.25f; } + if (RoR::App::GetInputEngine()->getEventValue(EV_TRUCK_BRAKE_MODIFIER_50)) { brakeModifier += 0.50f; } brake *= brakeModifier; } @@ -276,10 +238,7 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc else { // start engine - if (engine->HasStarterContact() && !engine->IsRunning() && (accl > 0 || brake > 0)) - { - engine->StartEngine(); - } + if (engine->HasStarterContact() && !engine->IsRunning() && (accl > 0 || brake > 0)) { engine->StartEngine(); } // arcade controls: hey - people wanted it x| ... <- and it's convenient if (engine->GetGear() >= 0) @@ -298,17 +257,14 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc // only when the truck really is not moving anymore if (fabs(vehicle->ar_avg_wheel_speed) <= 1.0f) { - Ogre::Vector3 hdir = vehicle->getDirection(); - float velocity = hdir.dotProduct(vehicle->ar_nodes[0].Velocity); + Ogre::Vector3 hdir = vehicle->getDirection(); + float velocity = hdir.dotProduct(vehicle->ar_nodes[0].Velocity); // switching point, does the user want to drive forward from backward or the other way round? change gears? if (velocity < 1.0f && brake > 0.5f && accl < 0.5f && engine->GetGear() > 0) { // we are on the brake, jump to reverse gear - if (engine->GetAutoShiftMode() == SimGearboxMode::AUTO) - { - engine->autoShiftSet(EngineSim::REAR); - } + if (engine->GetAutoShiftMode() == SimGearboxMode::AUTO) { engine->autoShiftSet(EngineSim::REAR); } else { engine->SetGear(-1); @@ -317,10 +273,7 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc else if (velocity > -1.0f && brake < 0.5f && accl > 0.5f && engine->GetGear() < 0) { // we are on the gas pedal, jump to first gear when we were in rear gear - if (engine->GetAutoShiftMode() == SimGearboxMode::AUTO) - { - engine->autoShiftSet(EngineSim::DRIVE); - } + if (engine->GetAutoShiftMode() == SimGearboxMode::AUTO) { engine->autoShiftSet(EngineSim::DRIVE); } else { engine->SetGear(1); @@ -333,22 +286,14 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc // gear management -- it might, should be transferred to a standalone function of Beam or SimController if (engine->GetAutoShiftMode() == SimGearboxMode::AUTO) { - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_AUTOSHIFT_UP)) - { - engine->autoShiftUp(); - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_AUTOSHIFT_DOWN)) - { - engine->autoShiftDown(); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_AUTOSHIFT_UP)) { engine->autoShiftUp(); } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_AUTOSHIFT_DOWN)) { engine->autoShiftDown(); } } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_TOGGLE_CONTACT)) - { - engine->ToggleStarterContact(); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_TOGGLE_CONTACT)) { engine->ToggleStarterContact(); } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STARTER) && engine->HasStarterContact() && !engine->IsRunning()) + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STARTER) && engine->HasStarterContact() && + !engine->IsRunning()) { // starter engine->SetStarter(1); @@ -367,21 +312,17 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc // force gui update vehicle->RequestUpdateHudFeatures(); - const char* msg = nullptr; + const char *msg = nullptr; switch (engine->GetAutoShiftMode()) { - case SimGearboxMode::AUTO: msg = "Automatic shift"; - break; - case SimGearboxMode::SEMI_AUTO: msg = "Manual shift - Auto clutch"; - break; - case SimGearboxMode::MANUAL: msg = "Fully Manual: sequential shift"; - break; - case SimGearboxMode::MANUAL_STICK: msg = "Fully manual: stick shift"; - break; - case SimGearboxMode::MANUAL_RANGES: msg = "Fully Manual: stick shift with ranges"; - break; + case SimGearboxMode::AUTO: msg = "Automatic shift"; break; + case SimGearboxMode::SEMI_AUTO: msg = "Manual shift - Auto clutch"; break; + case SimGearboxMode::MANUAL: msg = "Fully Manual: sequential shift"; break; + case SimGearboxMode::MANUAL_STICK: msg = "Fully manual: stick shift"; break; + case SimGearboxMode::MANUAL_RANGES: msg = "Fully Manual: stick shift with ranges"; break; } - RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, _L(msg), "cog.png", 3000); + RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, _L(msg), + "cog.png", 3000); RoR::App::GetGuiManager()->PushNotification("Gearbox Mode:", msg); } @@ -393,32 +334,27 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc if (shiftmode <= SimGearboxMode::MANUAL) // auto, semi auto and sequential shifting { - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_UP)) - { - engine->shift(1); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_UP)) { engine->shift(1); } else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_DOWN)) { if (shiftmode > SimGearboxMode::SEMI_AUTO || shiftmode == SimGearboxMode::SEMI_AUTO && (!App::io_arcade_controls.GetActive()) || - shiftmode == SimGearboxMode::SEMI_AUTO && engine->GetGear() > 0 || - shiftmode == SimGearboxMode::AUTO) - { - engine->shift(-1); - } + shiftmode == SimGearboxMode::SEMI_AUTO && engine->GetGear() > 0 || shiftmode == SimGearboxMode::AUTO) + { engine->shift(-1); } } - else if (shiftmode != SimGearboxMode::AUTO && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_NEUTRAL)) + else if (shiftmode != SimGearboxMode::AUTO && + RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_NEUTRAL)) { engine->shiftTo(0); } } - else //if (shiftmode > SimGearboxMode::MANUAL) // h-shift or h-shift with ranges shifting + else // if (shiftmode > SimGearboxMode::MANUAL) // h-shift or h-shift with ranges shifting { bool gear_changed = false; - bool found = false; - int curgear = engine->GetGear(); - int curgearrange = engine->GetGearRange(); - int gearoffset = std::max(0, curgear - curgearrange * 6); + bool found = false; + int curgear = engine->GetGear(); + int curgearrange = engine->GetGearRange(); + int gearoffset = std::max(0, curgear - curgearrange * 6); // one can select range only if in neutral if (shiftmode == SimGearboxMode::MANUAL_RANGES && curgear == 0) @@ -428,29 +364,32 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc { engine->SetGearRange(0); gear_changed = true; - RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, _L("Low range selected"), "cog.png", 3000); + RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, + _L("Low range selected"), "cog.png", 3000); } - else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_MIDRANGE) && curgearrange != 1 && engine->getNumGearsRanges() > 1) + else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_MIDRANGE) && curgearrange != 1 && + engine->getNumGearsRanges() > 1) { engine->SetGearRange(1); gear_changed = true; - RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, _L("Mid range selected"), "cog.png", 3000); + RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, + _L("Mid range selected"), "cog.png", 3000); } - else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_HIGHRANGE) && curgearrange != 2 && engine->getNumGearsRanges() > 2) + else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_SHIFT_HIGHRANGE) && curgearrange != 2 && + engine->getNumGearsRanges() > 2) { engine->SetGearRange(2); gear_changed = true; - RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, _L("High range selected"), "cog.png", 3000); + RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, + _L("High range selected"), "cog.png", 3000); } } - //zaxxon - if (curgear == -1) - { - gear_changed = !RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_SHIFT_GEAR_REVERSE); - } + // zaxxon + if (curgear == -1) { gear_changed = !RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_SHIFT_GEAR_REVERSE); } else if (curgear > 0 && curgear < 19) { - gear_changed = !RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_SHIFT_GEAR01 + gearoffset - 1); // range mode + gear_changed = + !RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_SHIFT_GEAR01 + gearoffset - 1); // range mode } if (gear_changed || curgear == 0) @@ -490,17 +429,11 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc } } } - if (!found) - { - engine->shiftTo(0); - } + if (!found) { engine->shiftTo(0); } } // end of if (gear_changed) - } // end of shitmode > SimGearboxMode::MANUAL - } // end of ->engine - if (vehicle->ar_brake > 1.0f / 6.0f) - { - SOUND_START(vehicle, SS_TRIG_BRAKE); - } + } // end of shitmode > SimGearboxMode::MANUAL + } // end of ->engine + if (vehicle->ar_brake > 1.0f / 6.0f) { SOUND_START(vehicle, SS_TRIG_BRAKE); } else { SOUND_STOP(vehicle, SS_TRIG_BRAKE); @@ -532,17 +465,11 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc if (vehicle->ar_is_police) { - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_HORN)) - { - SOUND_TOGGLE(vehicle, SS_TRIG_HORN); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_HORN)) { SOUND_TOGGLE(vehicle, SS_TRIG_HORN); } } else { - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_HORN)) - { - SOUND_START(vehicle, SS_TRIG_HORN); - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_HORN)) { SOUND_START(vehicle, SS_TRIG_HORN); } else { SOUND_STOP(vehicle, SS_TRIG_HORN); @@ -550,23 +477,12 @@ void LandVehicleSimulation::UpdateInputEvents(Actor* vehicle, float seconds_sinc } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_PARKING_BRAKE) && - !RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_TRAILER_PARKING_BRAKE)) - { - vehicle->ToggleParkingBrake(); - } + !RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_TRAILER_PARKING_BRAKE)) + { vehicle->ToggleParkingBrake(); } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_ANTILOCK_BRAKE)) - { - vehicle->ToggleAntiLockBrake(); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_ANTILOCK_BRAKE)) { vehicle->ToggleAntiLockBrake(); } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_TRACTION_CONTROL)) - { - vehicle->ToggleTractionControl(); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_TRACTION_CONTROL)) { vehicle->ToggleTractionControl(); } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_CRUISE_CONTROL)) - { - vehicle->ToggleCruiseControl(); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_CRUISE_CONTROL)) { vehicle->ToggleCruiseControl(); } } diff --git a/source/main/gameplay/LandVehicleSimulation.h b/source/main/gameplay/LandVehicleSimulation.h index e4287d2a16..72418df992 100644 --- a/source/main/gameplay/LandVehicleSimulation.h +++ b/source/main/gameplay/LandVehicleSimulation.h @@ -23,31 +23,31 @@ #include "ForwardDeclarations.h" -namespace RoR { - -/// Stateless class which provides simulation logic. -struct LandVehicleSimulation +namespace RoR { - /** - * @param dt Delta time in seconds. - */ - static void UpdateCruiseControl(Actor* vehicle, float dt); - - /** - * @param dt Delta time in seconds. - */ - static void CheckSpeedLimit(Actor* vehicle, float dt); - - /** - * Logic: driving aids and such - */ - static void UpdateVehicle(Actor* vehicle, float seconds_since_last_frame); - - /** - * Logic: input, sound, vehicle state - */ - static void UpdateInputEvents(Actor* vehicle, float seconds_since_last_frame); - -}; + + /// Stateless class which provides simulation logic. + struct LandVehicleSimulation + { + /** + * @param dt Delta time in seconds. + */ + static void UpdateCruiseControl(Actor *vehicle, float dt); + + /** + * @param dt Delta time in seconds. + */ + static void CheckSpeedLimit(Actor *vehicle, float dt); + + /** + * Logic: driving aids and such + */ + static void UpdateVehicle(Actor *vehicle, float seconds_since_last_frame); + + /** + * Logic: input, sound, vehicle state + */ + static void UpdateInputEvents(Actor *vehicle, float seconds_since_last_frame); + }; } // namespace RoR diff --git a/source/main/gameplay/Landusemap.cpp b/source/main/gameplay/Landusemap.cpp index 0f18e9874d..4a83d81256 100644 --- a/source/main/gameplay/Landusemap.cpp +++ b/source/main/gameplay/Landusemap.cpp @@ -24,47 +24,42 @@ #include "Collisions.h" #include "ErrorUtils.h" #include "Language.h" -#include "TerrainManager.h" -#include "PropertyMaps.h" #include "PagedGeometry.h" +#include "PropertyMaps.h" +#include "TerrainManager.h" #include using namespace Ogre; using namespace RoR; -Landusemap::Landusemap(String configFilename) : - data(0) - , default_ground_model(nullptr) - , mapsize(App::GetSimTerrain()->getMaxTerrainSize()) +Landusemap::Landusemap(String configFilename) + : data(0), default_ground_model(nullptr), mapsize(App::GetSimTerrain()->getMaxTerrainSize()) { loadConfig(configFilename); } Landusemap::~Landusemap() { - if (data != nullptr) - delete[] data; + if (data != nullptr) delete[] data; } -ground_model_t* Landusemap::getGroundModelAt(int x, int z) +ground_model_t *Landusemap::getGroundModelAt(int x, int z) { - if (!data) - return nullptr; + if (!data) return nullptr; // we return the default ground model if we are not anymore in this map - if (x < 0 || x >= mapsize.x || z < 0 || z >= mapsize.z) - return default_ground_model; + if (x < 0 || x >= mapsize.x || z < 0 || z >= mapsize.z) return default_ground_model; return data[x + z * (int)mapsize.x]; } -int Landusemap::loadConfig(const Ogre::String& filename) +int Landusemap::loadConfig(const Ogre::String &filename) { std::map usemap; - String textureFilename = ""; + String textureFilename = ""; - LOG("Parsing landuse config: '"+filename+"'"); + LOG("Parsing landuse config: '" + filename + "'"); String group = ""; try @@ -85,22 +80,22 @@ int Landusemap::loadConfig(const Ogre::String& filename) else cfg.loadFromResourceSystem(filename, group, "\x09:=", true); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { ErrorUtils::ShowError(_L("Error while loading landuse config"), e.getFullDescription()); return 1; } Ogre::ConfigFile::SectionIterator seci = cfg.getSectionIterator(); - Ogre::String secName, kname, kvalue; + Ogre::String secName, kname, kvalue; while (seci.hasMoreElements()) { - secName = seci.peekNextKey(); - Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext(); + secName = seci.peekNextKey(); + Ogre::ConfigFile::SettingsMultiMap * settings = seci.getNext(); Ogre::ConfigFile::SettingsMultiMap::iterator i; for (i = settings->begin(); i != settings->end(); ++i) { - kname = i->first; + kname = i->first; kvalue = i->second; // we got all the data available now, processing now if (secName == "general" || secName == "config") @@ -120,16 +115,16 @@ int Landusemap::loadConfig(const Ogre::String& filename) LOG("invalid color in landuse line in " + filename); continue; } - char* ptr; //not used + char * ptr; // not used unsigned int color = strtoul(kname.c_str(), &ptr, 16); - usemap[color] = kvalue; + usemap[color] = kvalue; } } } // process the config data and load the buffers finally try { - Forests::ColorMap* colourMap = Forests::ColorMap::load(textureFilename, Forests::CHANNEL_COLOR); + Forests::ColorMap *colourMap = Forests::ColorMap::load(textureFilename, Forests::CHANNEL_COLOR); colourMap->setFilter(Forests::MAPFILTER_NONE); /* @@ -146,9 +141,9 @@ int Landusemap::loadConfig(const Ogre::String& filename) Ogre::TRect bounds = Forests::TBounds(0, 0, mapsize.x, mapsize.z); // now allocate the data buffer to hold pointers to ground models - data = new ground_model_t*[(int)(mapsize.x * mapsize.z)]; - ground_model_t** ptr = data; - //std::map < String, int > counters; + data = new ground_model_t *[(int)(mapsize.x * mapsize.z)]; + ground_model_t **ptr = data; + // std::map < String, int > counters; for (int z = 0; z < mapsize.z; z++) { for (int x = 0; x < mapsize.x; x++) @@ -163,7 +158,7 @@ int Landusemap::loadConfig(const Ogre::String& filename) col = cols; } String use = usemap[col]; - //if (use!="") + // if (use!="") // counters[use]++; // store the pointer to the ground model in the data slot @@ -172,15 +167,15 @@ int Landusemap::loadConfig(const Ogre::String& filename) } } } - catch (Ogre::Exception& oex) + catch (Ogre::Exception &oex) { - LogFormat("[RoR|Physics] Landuse: failed to load texture '%s', message: '%s'", - textureFilename.c_str(), oex.getFullDescription().c_str()); + LogFormat("[RoR|Physics] Landuse: failed to load texture '%s', message: '%s'", textureFilename.c_str(), + oex.getFullDescription().c_str()); } - catch (std::exception& stex) + catch (std::exception &stex) { - LogFormat("[RoR|Physics] Landuse: failed to load texture '%s', message: '%s'", - textureFilename.c_str(), stex.what()); + LogFormat("[RoR|Physics] Landuse: failed to load texture '%s', message: '%s'", textureFilename.c_str(), + stex.what()); } catch (...) { diff --git a/source/main/gameplay/Landusemap.h b/source/main/gameplay/Landusemap.h index d8ed0438ff..194c184853 100644 --- a/source/main/gameplay/Landusemap.h +++ b/source/main/gameplay/Landusemap.h @@ -18,7 +18,7 @@ along with Rigs of Rods. If not, see . */ -//created by thomas fischer 23 February 2009 +// created by thomas fischer 23 February 2009 #pragma once @@ -26,18 +26,16 @@ class Landusemap : public ZeroedMemoryAllocator { -public: - + public: Landusemap(Ogre::String cfgfilename); ~Landusemap(); - ground_model_t* getGroundModelAt(int x, int z); - int loadConfig(const Ogre::String& filename); - -protected: + ground_model_t *getGroundModelAt(int x, int z); + int loadConfig(const Ogre::String &filename); - ground_model_t** data; - ground_model_t* default_ground_model; + protected: + ground_model_t **data; + ground_model_t * default_ground_model; Ogre::Vector3 mapsize; }; diff --git a/source/main/gameplay/OutProtocol.cpp b/source/main/gameplay/OutProtocol.cpp index 9e6910fc21..cca31ae00b 100644 --- a/source/main/gameplay/OutProtocol.cpp +++ b/source/main/gameplay/OutProtocol.cpp @@ -32,22 +32,13 @@ using namespace Ogre; using namespace RoR; -OutProtocol::OutProtocol(void) : - delay(0.1f) - , id(0) - , mode(0) - , sockfd(-1) - , timer(0) - , working(false) +OutProtocol::OutProtocol(void) : delay(0.1f), id(0), mode(0), sockfd(-1), timer(0), working(false) { delay *= App::io_outgauge_delay.GetActive(); // TODO: Use the GVar directly, don't copy it. mode = App::io_outgauge_mode.GetActive(); // TODO: Use the GVar directly, don't copy it. - id = App::io_outgauge_id.GetActive(); // TODO: Use the GVar directly, don't copy it. + id = App::io_outgauge_id.GetActive(); // TODO: Use the GVar directly, don't copy it. - if (mode > 0) - { - startup(); - } + if (mode > 0) { startup(); } } OutProtocol::~OutProtocol(void) @@ -55,11 +46,11 @@ OutProtocol::~OutProtocol(void) if (sockfd != 0) { #ifdef USE_SOCKETW -# if _WIN32 + #if _WIN32 closesocket(sockfd); -# else - close( sockfd ); -# endif + #else + close(sockfd); + #endif #endif // USE_SOCKETW sockfd = 0; } @@ -86,18 +77,18 @@ void OutProtocol::startup() } // get the IP of the remote side, this function is compatible with windows 2000 - hostent* remoteHost = gethostbyname(App::io_outgauge_ip.GetActive()); - char* ip = inet_ntoa(*(struct in_addr *)*remoteHost->h_addr_list); + hostent *remoteHost = gethostbyname(App::io_outgauge_ip.GetActive()); + char * ip = inet_ntoa(*(struct in_addr *)*remoteHost->h_addr_list); // init socket data struct sockaddr_in sendaddr; memset(&sendaddr, 0, sizeof(sendaddr)); - sendaddr.sin_family = AF_INET; + sendaddr.sin_family = AF_INET; sendaddr.sin_addr.s_addr = inet_addr(ip); - sendaddr.sin_port = htons(App::io_outgauge_port.GetActive()); + sendaddr.sin_port = htons(App::io_outgauge_port.GetActive()); // connect - if (connect(sockfd, (struct sockaddr *) &sendaddr, sizeof(sendaddr)) == SOCKET_ERROR) + if (connect(sockfd, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) == SOCKET_ERROR) { LOG(String("[RoR|OutGauge] Error connecting socket for OutGauge: ").append(strerror(errno))); return; @@ -110,20 +101,14 @@ void OutProtocol::startup() #endif // _WIN32 } -bool OutProtocol::Update(float dt, Actor* truck) +bool OutProtocol::Update(float dt, Actor *truck) { #if defined(_WIN32) && defined(USE_SOCKETW) - if (!working) - { - return false; - } + if (!working) { return false; } // below the set delay? timer += dt; - if (timer < delay) - { - return true; - } + if (timer < delay) { return true; } timer = 0; // send a package @@ -131,8 +116,8 @@ bool OutProtocol::Update(float dt, Actor* truck) memset(&gd, 0, sizeof(gd)); // set some common things - gd.Time = Root::getSingleton().getTimer()->getMilliseconds(); - gd.ID = id; + gd.Time = Root::getSingleton().getTimer()->getMilliseconds(); + gd.ID = id; gd.Flags = 0 | OG_KM; sprintf(gd.Car, "RoR"); @@ -149,19 +134,16 @@ bool OutProtocol::Update(float dt, Actor* truck) else if (truck && truck->ar_engine) { // truck and engine valid - if (truck->ar_engine->HasTurbo()) - { - gd.Flags |= OG_TURBO; - } - gd.Gear = std::max(0, truck->ar_engine->GetGear() + 1); // we only support one reverse gear - gd.PLID = 0; - gd.Speed = fabs(truck->ar_wheel_speed); - gd.RPM = truck->ar_engine->GetEngineRpm(); - gd.Turbo = truck->ar_engine->GetTurboPsi() * 0.0689475729f; - gd.EngTemp = 0; // TODO - gd.Fuel = 0; // TODO + if (truck->ar_engine->HasTurbo()) { gd.Flags |= OG_TURBO; } + gd.Gear = std::max(0, truck->ar_engine->GetGear() + 1); // we only support one reverse gear + gd.PLID = 0; + gd.Speed = fabs(truck->ar_wheel_speed); + gd.RPM = truck->ar_engine->GetEngineRpm(); + gd.Turbo = truck->ar_engine->GetTurboPsi() * 0.0689475729f; + gd.EngTemp = 0; // TODO + gd.Fuel = 0; // TODO gd.OilPressure = 0; // TODO - gd.OilTemp = 0; // TODO + gd.OilTemp = 0; // TODO gd.DashLights = 0; gd.DashLights |= DL_HANDBRAKE; @@ -169,45 +151,32 @@ bool OutProtocol::Update(float dt, Actor* truck) gd.DashLights |= DL_SIGNAL_L; gd.DashLights |= DL_SIGNAL_R; gd.DashLights |= DL_SIGNAL_ANY; - if (!truck->tc_nodash) - gd.DashLights |= DL_TC; - if (!truck->alb_nodash) - gd.DashLights |= DL_ABS; + if (!truck->tc_nodash) gd.DashLights |= DL_TC; + if (!truck->alb_nodash) gd.DashLights |= DL_ABS; gd.ShowLights = 0; - if (truck->ar_parking_brake) - gd.ShowLights |= DL_HANDBRAKE; - if (truck->ar_lights) - gd.ShowLights |= DL_FULLBEAM; - if (truck->ar_engine->HasStarterContact() && !truck->ar_engine->IsRunning()) - gd.ShowLights |= DL_BATTERY; - if (truck->ar_left_blink_on) - gd.ShowLights |= DL_SIGNAL_L; - if (truck->ar_right_blink_on) - gd.ShowLights |= DL_SIGNAL_R; - if (truck->ar_warn_blink_on) - gd.ShowLights |= DL_SIGNAL_ANY; - if (truck->tc_mode) - gd.ShowLights |= DL_TC; - if (truck->alb_mode) - gd.ShowLights |= DL_ABS; + if (truck->ar_parking_brake) gd.ShowLights |= DL_HANDBRAKE; + if (truck->ar_lights) gd.ShowLights |= DL_FULLBEAM; + if (truck->ar_engine->HasStarterContact() && !truck->ar_engine->IsRunning()) gd.ShowLights |= DL_BATTERY; + if (truck->ar_left_blink_on) gd.ShowLights |= DL_SIGNAL_L; + if (truck->ar_right_blink_on) gd.ShowLights |= DL_SIGNAL_R; + if (truck->ar_warn_blink_on) gd.ShowLights |= DL_SIGNAL_ANY; + if (truck->tc_mode) gd.ShowLights |= DL_TC; + if (truck->alb_mode) gd.ShowLights |= DL_ABS; gd.Throttle = truck->ar_engine->GetAcceleration(); - gd.Brake = truck->ar_brake; - gd.Clutch = 1 - truck->ar_engine->GetClutch(); // 0-1 + gd.Brake = truck->ar_brake; + gd.Clutch = 1 - truck->ar_engine->GetClutch(); // 0-1 strncpy(gd.Display1, truck->ar_design_name.c_str(), 15); - if (truck->ar_design_name.length() > 15) - { - strncpy(gd.Display2, truck->ar_design_name.c_str() + 15, 15); - } + if (truck->ar_design_name.length() > 15) { strncpy(gd.Display2, truck->ar_design_name.c_str() + 15, 15); } } // send the package - send(sockfd, (const char*)&gd, sizeof(gd), NULL); + send(sockfd, (const char *)&gd, sizeof(gd), NULL); return true; #else // TODO: fix linux - return false; + return false; #endif // _WIN32 } diff --git a/source/main/gameplay/OutProtocol.h b/source/main/gameplay/OutProtocol.h index 2c316e7333..904782e768 100644 --- a/source/main/gameplay/OutProtocol.h +++ b/source/main/gameplay/OutProtocol.h @@ -28,43 +28,41 @@ #include "Singleton.h" #ifdef USE_SOCKETW -#include "SocketW.h" -#endif //USE_SOCKETW + #include "SocketW.h" +#endif // USE_SOCKETW #ifdef _WIN32 -#include -#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) + #include + #define PACK(__Declaration__) __pragma(pack(push, 1)) __Declaration__ __pragma(pack(pop)) #else -#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) + #define PACK(__Declaration__) __Declaration__ __attribute__((__packed__)) #endif // _WIN32 -class OutProtocol : public RoRSingleton< OutProtocol >, public ZeroedMemoryAllocator +class OutProtocol : public RoRSingleton, public ZeroedMemoryAllocator { -public: - + public: OutProtocol(void); ~OutProtocol(void); - bool Update(float dt, Actor* truck); - -private: + bool Update(float dt, Actor *truck); - bool working; + private: + bool working; float delay, timer; - int id; - int mode; - int sockfd; + int id; + int mode; + int sockfd; void startup(); // from LFS/doc/insim.txt enum { - OG_SHIFT = 1, // key - OG_CTRL = 2, // key - OG_TURBO = 8192, // show turbo gauge - OG_KM = 16384, // if not set - user prefers MILES - OG_BAR = 32768, // if not set - user prefers PSI + OG_SHIFT = 1, // key + OG_CTRL = 2, // key + OG_TURBO = 8192, // show turbo gauge + OG_KM = 16384, // if not set - user prefers MILES + OG_BAR = 32768, // if not set - user prefers PSI }; enum @@ -84,8 +82,7 @@ class OutProtocol : public RoRSingleton< OutProtocol >, public ZeroedMemoryAlloc DL_NUM = BITMASK(13) // bit 14 - end }; - PACK (struct OutGaugePack - { + PACK(struct OutGaugePack { unsigned int Time; // time in milliseconds (to check order) char Car[4]; // Car name unsigned short Flags; // Info (see OG_x below) @@ -108,4 +105,3 @@ class OutProtocol : public RoRSingleton< OutProtocol >, public ZeroedMemoryAlloc int ID; // optional - only if OutGauge ID is specified }); }; - diff --git a/source/main/gameplay/ProceduralManager.cpp b/source/main/gameplay/ProceduralManager.cpp index 07c9b85143..18714b72c2 100644 --- a/source/main/gameplay/ProceduralManager.cpp +++ b/source/main/gameplay/ProceduralManager.cpp @@ -25,8 +25,7 @@ using namespace Ogre; -ProceduralManager::ProceduralManager() : - objectcounter(0) +ProceduralManager::ProceduralManager() : objectcounter(0) { } @@ -34,12 +33,11 @@ ProceduralManager::~ProceduralManager() { for (ProceduralObject po : pObjects) { - if (po.road) - delete po.road; + if (po.road) delete po.road; } } -int ProceduralManager::deleteObject(ProceduralObject& po) +int ProceduralManager::deleteObject(ProceduralObject &po) { if (po.loadingState == 1 && po.road) { @@ -51,17 +49,17 @@ int ProceduralManager::deleteObject(ProceduralObject& po) return 0; } -std::vector& ProceduralManager::getObjects() +std::vector &ProceduralManager::getObjects() { return pObjects; } -int ProceduralManager::updateObject(ProceduralObject& po) +int ProceduralManager::updateObject(ProceduralObject &po) { - if (po.loadingState == 1 && po.road) - deleteObject(po); + if (po.loadingState == 1 && po.road) deleteObject(po); // create new road2 object - po.road = new Road2(objectcounter++);; + po.road = new Road2(objectcounter++); + ; std::vector::iterator it; for (it = po.points.begin(); it != po.points.end(); it++) @@ -97,7 +95,7 @@ int ProceduralManager::deleteAllObjects() return 0; } -int ProceduralManager::addObject(ProceduralObject& po) +int ProceduralManager::addObject(ProceduralObject &po) { updateObject(po); pObjects.push_back(po); diff --git a/source/main/gameplay/ProceduralManager.h b/source/main/gameplay/ProceduralManager.h index 9dad789015..d516837f0f 100644 --- a/source/main/gameplay/ProceduralManager.h +++ b/source/main/gameplay/ProceduralManager.h @@ -25,48 +25,48 @@ class ProceduralPoint : public ZeroedMemoryAllocator { -public: - Ogre::Vector3 position; + public: + Ogre::Vector3 position; Ogre::Quaternion rotation; - int type; - float width; - float bwidth; - float bheight; - int pillartype; + int type; + float width; + float bwidth; + float bheight; + int pillartype; }; class ProceduralObject : public ZeroedMemoryAllocator { -public: + public: ProceduralObject() : loadingState(-1), name(""), road(0) { } - int loadingState; - std::string name; + int loadingState; + std::string name; std::vector points; // runtime - Road2* road; + Road2 *road; }; class ProceduralManager : public ZeroedMemoryAllocator { -protected: + protected: std::vector pObjects; - int objectcounter; + int objectcounter; -public: + public: ProceduralManager(); ~ProceduralManager(); - int addObject(ProceduralObject& po); + int addObject(ProceduralObject &po); int updateAllObjects(); - int updateObject(ProceduralObject& po); + int updateObject(ProceduralObject &po); int deleteAllObjects(); - int deleteObject(ProceduralObject& po); + int deleteObject(ProceduralObject &po); - std::vector& getObjects(); + std::vector &getObjects(); }; diff --git a/source/main/gameplay/RandomTreeLoader.h b/source/main/gameplay/RandomTreeLoader.h index 5db3f1ee23..abe8bcfc62 100644 --- a/source/main/gameplay/RandomTreeLoader.h +++ b/source/main/gameplay/RandomTreeLoader.h @@ -19,106 +19,103 @@ along with Rigs of Rods. If not, see . */ #pragma once #ifndef __RandomTreeLoader_H__ -#define __RandomTreeLoader_H__ + #define __RandomTreeLoader_H__ -#include "RoRPrerequisites.h" -#include "PagedGeometry.h" -#include "PropertyMaps.h" -#include "TreeLoader2D.h" + #include "PagedGeometry.h" + #include "PropertyMaps.h" + #include "RoRPrerequisites.h" + #include "TreeLoader2D.h" - - - -namespace Forests { - -class TreeIterator3D; -class TreeIterator2D; - -class RandomTreeLoader : public TreeLoader2D, public ZeroedMemoryAllocator +namespace Forests { -public: - RandomTreeLoader(PagedGeometry *geom, const TBounds &bounds) : TreeLoader2D(geom, bounds) - { - } - - ~RandomTreeLoader() - { - } - - void loadPage(PageInfo &page) - { - //Calculate x/z indexes for the grid array - page.xIndex -= Math::Floor(gridBounds.left / pageSize); - page.zIndex -= Math::Floor(gridBounds.top / pageSize); - - //Check if the requested page is in bounds - if (page.xIndex < 0 || page.zIndex < 0 || page.xIndex >= pageGridX || page.zIndex >= pageGridZ) - return; - - // just take the first tree registered as an example - std::vector *pageGrid = pageGridList.begin()->second; - std::vector &treeList = _getGridPage(pageGrid, page.xIndex, page.zIndex); - - // example values - minimumScale=0.07; - maximumScale=0.13; - - // if there are no tress in the page to be loaded, add some randomly - if (treeList.size() == 0) - { - // only add trees if there are none in this page... - for (int n=0; n < pageSize/10; n++) - { - //Create the new tree - Real xrel = Math::RangeRandom(0, pageSize); - Real zrel = Math::RangeRandom(0, pageSize); - Degree yaw(Math::RangeRandom(0, 360)); - Real scale = Math::RangeRandom(minimumScale, maximumScale); - - TreeDef tree; - tree.xPos = 65535 * (xrel - (page.xIndex * pageSize)) / pageSize; - tree.zPos = 65535 * (zrel - (page.zIndex * pageSize)) / pageSize; - tree.rotation = 255 * (yaw.valueDegrees() / 360.0f); - tree.scale = 255 * ((scale - minimumScale) / maximumScale); - treeList.push_back(tree); - } - } - - // now load page as normal - TreeLoader2D::loadPage(page); - } - - void unloadPage(PageInfo &page) - { - //Calculate x/z indexes for the grid array - page.xIndex -= Math::Floor(gridBounds.left / pageSize); - page.zIndex -= Math::Floor(gridBounds.top / pageSize); - - //Check if the requested page is in bounds - if (page.xIndex < 0 || page.zIndex < 0 || page.xIndex >= pageGridX || page.zIndex >= pageGridZ) - return; - - // just take the first tree registered as an example - std::vector *pageGrid = pageGridList.begin()->second; - std::vector &treeList = _getGridPage(pageGrid, page.xIndex, page.zIndex); - - // clear all existing trees - uint32 i = 0; - while (i < treeList.size()){ - //Check if tree is in bounds -#ifdef USE_PAGEDGEOMETRY_USER_DATA - deletedUserData.push_back(treeList[i].userData); -#endif - // delete it - treeList[i] = treeList.back(); - treeList.pop_back(); - ++i; - } - - // now unload page as normal - TreeLoader2D::unloadPage(page); - } -}; - -} + + class TreeIterator3D; + class TreeIterator2D; + + class RandomTreeLoader : public TreeLoader2D, public ZeroedMemoryAllocator + { + public: + RandomTreeLoader(PagedGeometry *geom, const TBounds &bounds) : TreeLoader2D(geom, bounds) + { + } + + ~RandomTreeLoader() + { + } + + void loadPage(PageInfo &page) + { + // Calculate x/z indexes for the grid array + page.xIndex -= Math::Floor(gridBounds.left / pageSize); + page.zIndex -= Math::Floor(gridBounds.top / pageSize); + + // Check if the requested page is in bounds + if (page.xIndex < 0 || page.zIndex < 0 || page.xIndex >= pageGridX || page.zIndex >= pageGridZ) return; + + // just take the first tree registered as an example + std::vector *pageGrid = pageGridList.begin()->second; + std::vector &treeList = _getGridPage(pageGrid, page.xIndex, page.zIndex); + + // example values + minimumScale = 0.07; + maximumScale = 0.13; + + // if there are no tress in the page to be loaded, add some randomly + if (treeList.size() == 0) + { + // only add trees if there are none in this page... + for (int n = 0; n < pageSize / 10; n++) + { + // Create the new tree + Real xrel = Math::RangeRandom(0, pageSize); + Real zrel = Math::RangeRandom(0, pageSize); + Degree yaw(Math::RangeRandom(0, 360)); + Real scale = Math::RangeRandom(minimumScale, maximumScale); + + TreeDef tree; + tree.xPos = 65535 * (xrel - (page.xIndex * pageSize)) / pageSize; + tree.zPos = 65535 * (zrel - (page.zIndex * pageSize)) / pageSize; + tree.rotation = 255 * (yaw.valueDegrees() / 360.0f); + tree.scale = 255 * ((scale - minimumScale) / maximumScale); + treeList.push_back(tree); + } + } + + // now load page as normal + TreeLoader2D::loadPage(page); + } + + void unloadPage(PageInfo &page) + { + // Calculate x/z indexes for the grid array + page.xIndex -= Math::Floor(gridBounds.left / pageSize); + page.zIndex -= Math::Floor(gridBounds.top / pageSize); + + // Check if the requested page is in bounds + if (page.xIndex < 0 || page.zIndex < 0 || page.xIndex >= pageGridX || page.zIndex >= pageGridZ) return; + + // just take the first tree registered as an example + std::vector *pageGrid = pageGridList.begin()->second; + std::vector &treeList = _getGridPage(pageGrid, page.xIndex, page.zIndex); + + // clear all existing trees + uint32 i = 0; + while (i < treeList.size()) + { + // Check if tree is in bounds + #ifdef USE_PAGEDGEOMETRY_USER_DATA + deletedUserData.push_back(treeList[i].userData); + #endif + // delete it + treeList[i] = treeList.back(); + treeList.pop_back(); + ++i; + } + + // now unload page as normal + TreeLoader2D::unloadPage(page); + } + }; + +} // namespace Forests #endif \ No newline at end of file diff --git a/source/main/gameplay/Replay.cpp b/source/main/gameplay/Replay.cpp index de190a636b..3208495437 100644 --- a/source/main/gameplay/Replay.cpp +++ b/source/main/gameplay/Replay.cpp @@ -28,14 +28,14 @@ using namespace Ogre; -Replay::Replay(Actor* actor, int _numFrames) +Replay::Replay(Actor *actor, int _numFrames) { - numNodes = actor->ar_num_nodes; - numBeams = actor->ar_num_beams; + numNodes = actor->ar_num_nodes; + numBeams = actor->ar_num_beams; numFrames = _numFrames; curFrameTime = 0; - curOffset = 0; + curOffset = 0; replayTimer = new Timer(); @@ -46,23 +46,26 @@ Replay::Replay(Actor* actor, int _numFrames) outOfMemory = false; - unsigned long bsize = (numNodes * numFrames * sizeof(node_simple_t) + numBeams * numFrames * sizeof(beam_simple_t) + numFrames * sizeof(unsigned long)) / 1024.0f; + unsigned long bsize = (numNodes * numFrames * sizeof(node_simple_t) + numBeams * numFrames * sizeof(beam_simple_t) + + numFrames * sizeof(unsigned long)) / + 1024.0f; LOG("replay buffer size: " + TOSTRING(bsize) + " kB"); writeIndex = 0; - firstRun = 1; + firstRun = 1; - hidden = false; + hidden = false; visible = false; // windowing - int width = 300; + int width = 300; int height = 60; - int x = (MyGUI::RenderManager::getInstance().getViewSize().width - width) / 2; - int y = 0; + int x = (MyGUI::RenderManager::getInstance().getViewSize().width - width) / 2; + int y = 0; - panel = MyGUI::Gui::getInstance().createWidget("Panel", x, y, width, height, MyGUI::Align::HCenter | MyGUI::Align::Top, "Back"); - //panel->setCaption(_L("Replay")); + panel = MyGUI::Gui::getInstance().createWidget("Panel", x, y, width, height, + MyGUI::Align::HCenter | MyGUI::Align::Top, "Back"); + // panel->setCaption(_L("Replay")); panel->setAlpha(0.6); pr = panel->createWidget("Progress", 10, 10, 280, 20, MyGUI::Align::Default); @@ -89,39 +92,38 @@ Replay::~Replay() delete replayTimer; } -void* Replay::getWriteBuffer(int type) +void *Replay::getWriteBuffer(int type) { - if (outOfMemory) - return 0; + if (outOfMemory) return 0; if (!nodes) { // get memory - nodes = (node_simple_t*)calloc(numNodes * numFrames, sizeof(node_simple_t)); + nodes = (node_simple_t *)calloc(numNodes * numFrames, sizeof(node_simple_t)); if (!nodes) { outOfMemory = true; return 0; } - beams = (beam_simple_t*)calloc(numBeams * numFrames, sizeof(beam_simple_t)); + beams = (beam_simple_t *)calloc(numBeams * numFrames, sizeof(beam_simple_t)); if (!beams) { free(nodes); - nodes = 0; + nodes = 0; outOfMemory = true; return 0; } - times = (unsigned long*)calloc(numFrames, sizeof(unsigned long)); + times = (unsigned long *)calloc(numFrames, sizeof(unsigned long)); if (!times) { free(nodes); nodes = 0; free(beams); - beams = 0; + beams = 0; outOfMemory = true; return 0; } } - void* ptr = 0; + void *ptr = 0; times[writeIndex] = replayTimer->getMicroseconds(); if (type == 0) { @@ -138,23 +140,20 @@ void* Replay::getWriteBuffer(int type) void Replay::writeDone() { - if (outOfMemory) - return; + if (outOfMemory) return; writeIndex++; if (writeIndex == numFrames) { - firstRun = 0; + firstRun = 0; writeIndex = 0; } } -//we take negative offsets only -void* Replay::getReadBuffer(int offset, int type, unsigned long& time) +// we take negative offsets only +void *Replay::getReadBuffer(int offset, int type, unsigned long &time) { - if (offset >= 0) - offset = -1; - if (offset <= -numFrames) - offset = -numFrames + 1; + if (offset >= 0) offset = -1; + if (offset <= -numFrames) offset = -numFrames + 1; int delta = writeIndex + offset; if (delta < 0) @@ -166,13 +165,12 @@ void* Replay::getReadBuffer(int offset, int type, unsigned long& time) delta += numFrames; // set the time - time = times[delta]; + time = times[delta]; curFrameTime = time; - curOffset = offset; + curOffset = offset; updateGUI(); - if (outOfMemory) - return 0; + if (outOfMemory) return 0; // return buffer pointer if (type == 0) @@ -191,9 +189,9 @@ void Replay::updateGUI() } else { - wchar_t tmp[128] = L""; - unsigned long t = curFrameTime; - UTFString format = _L("Position: %0.6f s, frame %i / %i"); + wchar_t tmp[128] = L""; + unsigned long t = curFrameTime; + UTFString format = _L("Position: %0.6f s, frame %i / %i"); swprintf(tmp, 128, format.asWStr_c_str(), ((float)t) / 1000000.0f, curOffset, numFrames); txt->setCaption(convertToMyGUIString(tmp, 128)); pr->setProgressPosition(abs(curOffset)); diff --git a/source/main/gameplay/Replay.h b/source/main/gameplay/Replay.h index f036aaad6c..e017c588e9 100644 --- a/source/main/gameplay/Replay.h +++ b/source/main/gameplay/Replay.h @@ -30,52 +30,55 @@ struct node_simple_t struct beam_simple_t { - bool broken:1; - bool disabled:1; + bool broken : 1; + bool disabled : 1; }; class Replay : public ZeroedMemoryAllocator { -public: - Replay(Actor* b, int nframes); + public: + Replay(Actor *b, int nframes); ~Replay(); - void* getWriteBuffer(int type); - void* getReadBuffer(int offset, int type, unsigned long& time); + void * getWriteBuffer(int type); + void * getReadBuffer(int offset, int type, unsigned long &time); unsigned long getLastReadTime(); - void writeDone(); + void writeDone(); void setHidden(bool value); void setVisible(bool value); bool getVisible(); - bool isValid() { return numFrames && !outOfMemory; }; + bool isValid() + { + return numFrames && !outOfMemory; + }; -protected: - Ogre::Timer* replayTimer; - int numNodes; - int numBeams; - int numFrames; - bool outOfMemory; + protected: + Ogre::Timer *replayTimer; + int numNodes; + int numBeams; + int numFrames; + bool outOfMemory; bool hidden; bool visible; - int writeIndex; - int firstRun; + int writeIndex; + int firstRun; unsigned long curFrameTime; - int curOffset; + int curOffset; // malloc'ed - node_simple_t* nodes; - beam_simple_t* beams; - unsigned long* times; + node_simple_t *nodes; + beam_simple_t *beams; + unsigned long *times; // windowing - MyGUI::WidgetPtr panel; + MyGUI::WidgetPtr panel; MyGUI::StaticTextPtr txt; - MyGUI::ProgressPtr pr; + MyGUI::ProgressPtr pr; void updateGUI(); }; diff --git a/source/main/gameplay/RoRFrameListener.cpp b/source/main/gameplay/RoRFrameListener.cpp index 80b0e77841..4af531bb19 100644 --- a/source/main/gameplay/RoRFrameListener.cpp +++ b/source/main/gameplay/RoRFrameListener.cpp @@ -33,8 +33,15 @@ #include "Collisions.h" #include "ContentManager.h" #include "DashBoardManager.h" -#include "GfxScene.h" #include "ForceFeedback.h" +#include "GUIManager.h" +#include "GUI_FrictionSettings.h" +#include "GUI_GameConsole.h" +#include "GUI_LoadingWindow.h" +#include "GUI_MainSelector.h" +#include "GUI_MultiplayerClientList.h" +#include "GUI_SimUtils.h" +#include "GfxScene.h" #include "InputEngine.h" #include "LandVehicleSimulation.h" #include "Language.h" @@ -53,20 +60,11 @@ #include "SkyManager.h" #include "SkyXManager.h" #include "SoundScriptManager.h" +#include "SurveyMapManager.h" #include "TerrainManager.h" #include "TerrainObjectManager.h" #include "Utils.h" -#include "GUIManager.h" -#include "GUI_FrictionSettings.h" -#include "GUI_GameConsole.h" -#include "GUI_LoadingWindow.h" -#include "GUI_MainSelector.h" -#include "GUI_MultiplayerClientList.h" -#include "GUI_SimUtils.h" - -#include "SurveyMapManager.h" - #include #include #include @@ -75,55 +73,30 @@ #include #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 -#include + #include #else -#include -#include + #include + #include #endif using namespace Ogre; using namespace RoR; -#define simRUNNING(_S_) (_S_ == SimState::RUNNING ) -#define simPAUSED(_S_) (_S_ == SimState::PAUSED ) -#define simSELECT(_S_) (_S_ == SimState::SELECTING ) -#define simEDITOR(_S_) (_S_ == SimState::EDITOR_MODE) - -SimController::SimController(RoR::ForceFeedback* ff, RoR::SkidmarkConfig* skid_conf) : - m_player_actor(nullptr), - m_prev_player_actor(nullptr), - m_pending_player_actor(nullptr), - m_actor_manager(), - m_character_factory(), - m_dir_arrow_pointed(Vector3::ZERO), - m_force_feedback(ff), - m_skidmark_conf(skid_conf), - m_hide_gui(false), - m_is_pace_reset_pressed(false), - m_last_cache_selection(nullptr), - m_last_screenshot_date(""), - m_last_screenshot_id(1), - m_last_simulation_speed(0.1f), - m_last_skin_selection(nullptr), - m_physics_simulation_paused(false), - m_physics_simulation_time(0.0f), - m_pressure_pressed(false), - m_pressure_pressed_timer(0.0f), - m_race_id(-1), - m_race_start_time(0), - m_race_best_time(0), - m_race_time_diff(0), - m_reload_dir(Quaternion::IDENTITY), - m_reload_pos(Vector3::ZERO), - m_screenshot_request(false), - m_stats_on(0), - m_time(0), - m_time_until_next_toggle(0), - m_soft_reset_mode(false), - m_advanced_vehicle_repair(false), - m_advanced_vehicle_repair_timer(0.f), - m_actor_info_gui_visible(false), - m_terrain_editor_mouse_ray(Ray(Vector3::ZERO, Vector3::ZERO)) +#define simRUNNING(_S_) (_S_ == SimState::RUNNING) +#define simPAUSED(_S_) (_S_ == SimState::PAUSED) +#define simSELECT(_S_) (_S_ == SimState::SELECTING) +#define simEDITOR(_S_) (_S_ == SimState::EDITOR_MODE) + +SimController::SimController(RoR::ForceFeedback *ff, RoR::SkidmarkConfig *skid_conf) + : m_player_actor(nullptr), m_prev_player_actor(nullptr), m_pending_player_actor(nullptr), m_actor_manager(), + m_character_factory(), m_dir_arrow_pointed(Vector3::ZERO), m_force_feedback(ff), m_skidmark_conf(skid_conf), + m_hide_gui(false), m_is_pace_reset_pressed(false), m_last_cache_selection(nullptr), m_last_screenshot_date(""), + m_last_screenshot_id(1), m_last_simulation_speed(0.1f), m_last_skin_selection(nullptr), m_physics_simulation_paused(false), + m_physics_simulation_time(0.0f), m_pressure_pressed(false), m_pressure_pressed_timer(0.0f), m_race_id(-1), + m_race_start_time(0), m_race_best_time(0), m_race_time_diff(0), m_reload_dir(Quaternion::IDENTITY), + m_reload_pos(Vector3::ZERO), m_screenshot_request(false), m_stats_on(0), m_time(0), m_time_until_next_toggle(0), + m_soft_reset_mode(false), m_advanced_vehicle_repair(false), m_advanced_vehicle_repair_timer(0.f), + m_actor_info_gui_visible(false), m_terrain_editor_mouse_ray(Ray(Vector3::ZERO, Vector3::ZERO)) { } @@ -134,26 +107,24 @@ void SimController::UpdateForceFeedback() if (m_player_actor && m_player_actor->ar_driveable == TRUCK) { Ogre::Vector3 ff_vehicle = m_player_actor->GetFFbBodyForces(); - m_force_feedback->SetForces( - -ff_vehicle.dotProduct(m_player_actor->GetCameraRoll()) / 10000.0, - ff_vehicle.dotProduct(m_player_actor->GetCameraDir()) / 10000.0, - m_player_actor->ar_wheel_speed, - m_player_actor->ar_hydro_dir_command, - m_player_actor->GetFFbHydroForces()); + m_force_feedback->SetForces(-ff_vehicle.dotProduct(m_player_actor->GetCameraRoll()) / 10000.0, + ff_vehicle.dotProduct(m_player_actor->GetCameraDir()) / 10000.0, + m_player_actor->ar_wheel_speed, m_player_actor->ar_hydro_dir_command, + m_player_actor->GetFFbHydroForces()); } } void SimController::StartRaceTimer(int id) { m_race_start_time = m_time; - m_race_time_diff = 0.0f; - m_race_id = id; + m_race_time_diff = 0.0f; + m_race_id = id; } void SimController::StopRaceTimer() { m_race_start_time = 0.0f; - m_race_id = -1; + m_race_id = -1; } void SimController::HandleSavegameShortcuts() @@ -161,96 +132,35 @@ void SimController::HandleSavegameShortcuts() // Global savegames int slot = -1; - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_01, 1.0f)) - { - slot = 1; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_02, 1.0f)) - { - slot = 2; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_03, 1.0f)) - { - slot = 3; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_04, 1.0f)) - { - slot = 4; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_05, 1.0f)) - { - slot = 5; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_06, 1.0f)) - { - slot = 6; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_07, 1.0f)) - { - slot = 7; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_08, 1.0f)) - { - slot = 8; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_09, 1.0f)) - { - slot = 9; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_10, 1.0f)) - { - slot = 0; - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_01, 1.0f)) { slot = 1; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_02, 1.0f)) { slot = 2; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_03, 1.0f)) { slot = 3; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_04, 1.0f)) { slot = 4; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_05, 1.0f)) { slot = 5; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_06, 1.0f)) { slot = 6; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_07, 1.0f)) { slot = 7; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_08, 1.0f)) { slot = 8; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_09, 1.0f)) { slot = 9; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKLOAD_10, 1.0f)) { slot = 0; } if (slot != -1) { Ogre::String filename = Ogre::StringUtil::format("quicksave-%d.sav", slot); m_actor_manager.LoadScene(filename); } - if (App::sim_terrain_name.IsActiveEmpty() || App::sim_state.GetActive() != SimState::RUNNING) - return; + if (App::sim_terrain_name.IsActiveEmpty() || App::sim_state.GetActive() != SimState::RUNNING) return; slot = -1; - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_01, 1.0f)) - { - slot = 1; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_02, 1.0f)) - { - slot = 2; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_03, 1.0f)) - { - slot = 3; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_04, 1.0f)) - { - slot = 4; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_05, 1.0f)) - { - slot = 5; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_06, 1.0f)) - { - slot = 6; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_07, 1.0f)) - { - slot = 7; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_08, 1.0f)) - { - slot = 8; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_09, 1.0f)) - { - slot = 9; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_10, 1.0f)) - { - slot = 0; - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_01, 1.0f)) { slot = 1; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_02, 1.0f)) { slot = 2; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_03, 1.0f)) { slot = 3; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_04, 1.0f)) { slot = 4; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_05, 1.0f)) { slot = 5; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_06, 1.0f)) { slot = 6; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_07, 1.0f)) { slot = 7; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_08, 1.0f)) { slot = 8; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_09, 1.0f)) { slot = 9; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE_10, 1.0f)) { slot = 0; } if (slot != -1) { Ogre::String filename = Ogre::StringUtil::format("quicksave-%d.sav", slot); @@ -266,33 +176,25 @@ void SimController::HandleSavegameShortcuts() } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUICKSAVE)) - { - m_actor_manager.SaveScene(m_actor_manager.GetQuicksaveFilename()); - } + { m_actor_manager.SaveScene(m_actor_manager.GetQuicksaveFilename()); } } void SimController::UpdateInputEvents(float dt) { - if (dt == 0.0f) - return; + if (dt == 0.0f) return; - auto s = App::sim_state.GetActive(); + auto s = App::sim_state.GetActive(); auto gui_man = App::GetGuiManager(); RoR::App::GetInputEngine()->updateKeyBounces(dt); - if (!RoR::App::GetInputEngine()->getInputsChanged()) - return; + if (!RoR::App::GetInputEngine()->getInputsChanged()) return; // update overlays if enabled - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->update(dt); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->update(dt); if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_QUIT_GAME)) { - if (gui_man->IsVisible_MainSelector()) - { - gui_man->GetMainSelector()->Cancel(); - } + if (gui_man->IsVisible_MainSelector()) { gui_man->GetMainSelector()->Cancel(); } else if (simRUNNING(s)) { App::sim_state.SetPending(SimState::PAUSED); @@ -303,18 +205,13 @@ void SimController::UpdateInputEvents(float dt) } } - if (App::sim_state.GetActive() == SimState::PAUSED) - return; //Stop everything when pause menu is visible + if (App::sim_state.GetActive() == SimState::PAUSED) return; // Stop everything when pause menu is visible if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_CONSOLE_TOGGLE)) - { - gui_man->SetVisible_Console(! gui_man->IsVisible_Console()); - } + { gui_man->SetVisible_Console(!gui_man->IsVisible_Console()); } if (gui_man->IsVisible_FrictionSettings() && m_player_actor) - { - gui_man->GetFrictionSettings()->setActiveCol(m_player_actor->ar_last_fuzzy_ground_model); - } + { gui_man->GetFrictionSettings()->setActiveCol(m_player_actor->ar_last_fuzzy_ground_model); } const bool mp_connected = (App::mp_state.GetActive() == MpState::CONNECTED); if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_CHATMODE, 0.5f) && !m_hide_gui && mp_connected) @@ -325,22 +222,19 @@ void SimController::UpdateInputEvents(float dt) if (m_screenshot_request) { - std::time_t t = std::time(nullptr); + std::time_t t = std::time(nullptr); std::stringstream date; #if defined(__GNUC__) && (__GNUC__ < 5) - date << std::asctime(std::localtime(&t)); + date << std::asctime(std::localtime(&t)); #else date << std::put_time(std::localtime(&t), "%Y-%m-%d_%H-%M-%S"); #endif String fn_prefix = PathCombine(App::sys_screenshot_dir.GetActive(), "screenshot_"); - String fn_name = date.str() + String("_"); + String fn_name = date.str() + String("_"); String fn_suffix = String(".") + App::app_screenshot_format.GetActive(); - if (m_last_screenshot_date == date.str()) - { - m_last_screenshot_id++; - } + if (m_last_screenshot_date == date.str()) { m_last_screenshot_id++; } else { m_last_screenshot_id = 1; @@ -354,10 +248,10 @@ void SimController::UpdateInputEvents(float dt) if (std::strcmp(App::app_screenshot_format.GetActive(), "png") == 0) { // add some more data into the image - AdvancedScreen* as = new AdvancedScreen(RoR::App::GetOgreSubsystem()->GetRenderWindow(), tmpfn); - //as->addData("terrain_Name", loadedTerrain); - //as->addData("terrain_ModHash", terrainModHash); - //as->addData("terrain_FileHash", terrainFileHash); + AdvancedScreen *as = new AdvancedScreen(RoR::App::GetOgreSubsystem()->GetRenderWindow(), tmpfn); + // as->addData("terrain_Name", loadedTerrain); + // as->addData("terrain_ModHash", terrainModHash); + // as->addData("terrain_FileHash", terrainFileHash); if (m_player_actor) { as->addData("Truck_Num", TOSTRING(m_player_actor->ar_instance_id)); @@ -376,11 +270,11 @@ void SimController::UpdateInputEvents(float dt) as->addData("MP_NetworkEnabled", (App::mp_state.GetActive() == MpState::CONNECTED) ? "Yes" : "No"); as->addData("Camera_Position", TOSTRING(gEnv->mainCamera->getPosition())); - const RenderTarget::FrameStats& stats = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getStatistics(); + const RenderTarget::FrameStats &stats = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getStatistics(); as->addData("AVGFPS", TOSTRING(stats.avgFPS)); as->write(); - delete(as); + delete (as); } else { @@ -392,7 +286,8 @@ void SimController::UpdateInputEvents(float dt) // show new flash message String ssmsg = _L("Screenshot:") + String(" ") + fn_name + fn_suffix; LOG(ssmsg); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "camera.png", 10000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "camera.png", + 10000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); m_screenshot_request = false; @@ -406,12 +301,11 @@ void SimController::UpdateInputEvents(float dt) RoR::App::GetGuiManager()->SetMouseCursorVisibility(RoR::GUIManager::MouseCursorVisibility::HIDDEN); } - if ((m_player_actor != nullptr) && - (m_player_actor->ar_sim_state != Actor::SimState::NETWORKED_OK) && + if ((m_player_actor != nullptr) && (m_player_actor->ar_sim_state != Actor::SimState::NETWORKED_OK) && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCKEDIT_RELOAD, 0.5f)) { ActorModifyRequest rq; - rq.amr_type = ActorModifyRequest::Type::RELOAD; + rq.amr_type = ActorModifyRequest::Type::RELOAD; rq.amr_actor = m_player_actor; this->QueueActorModify(rq); @@ -433,7 +327,8 @@ void SimController::UpdateInputEvents(float dt) float simulation_speed = m_actor_manager.GetSimulationSpeed() * pow(2.0f, dt / 2.0f); m_actor_manager.SetSimulationSpeed(simulation_speed); String ssmsg = _L("New simulation speed: ") + TOSTRING(Round(simulation_speed * 100.0f, 1)) + "%"; - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); } if (m_race_id == -1 && RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_DECELERATE_SIMULATION)) @@ -441,7 +336,8 @@ void SimController::UpdateInputEvents(float dt) float simulation_speed = m_actor_manager.GetSimulationSpeed() * pow(0.5f, dt / 2.0f); m_actor_manager.SetSimulationSpeed(simulation_speed); String ssmsg = _L("New simulation speed: ") + TOSTRING(Round(simulation_speed * 100.0f, 1)) + "%"; - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); } if (m_race_id == -1 && RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_RESET_SIMULATION_PACE)) @@ -454,14 +350,16 @@ void SimController::UpdateInputEvents(float dt) m_last_simulation_speed = simulation_speed; m_actor_manager.SetSimulationSpeed(1.0f); UTFString ssmsg = _L("Simulation speed reset."); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); } else if (m_last_simulation_speed != 1.0f) { m_actor_manager.SetSimulationSpeed(m_last_simulation_speed); String ssmsg = _L("New simulation speed: ") + TOSTRING(Round(m_last_simulation_speed * 100.0f, 1)) + "%"; - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); } } @@ -474,16 +372,12 @@ void SimController::UpdateInputEvents(float dt) // Frozen physics logic if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_PHYSICS)) - { - m_physics_simulation_paused = !m_physics_simulation_paused; - } + { m_physics_simulation_paused = !m_physics_simulation_paused; } if (m_physics_simulation_paused && m_actor_manager.GetSimulationSpeed() > 0.0f) { if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REPLAY_FAST_FORWARD) || RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FORWARD, 0.25f)) - { - m_physics_simulation_time = PHYSICS_DT / m_actor_manager.GetSimulationSpeed(); - } + { m_physics_simulation_time = PHYSICS_DT / m_actor_manager.GetSimulationSpeed(); } } this->HandleSavegameShortcuts(); @@ -496,21 +390,20 @@ void SimController::UpdateInputEvents(float dt) if (fov_less || fov_more) { float fov = gEnv->mainCamera->getFOVy().valueDegrees(); - fov = (fov_less) ? (fov - 1.f) : (fov + 1.f); - fov = Round(fov); + fov = (fov_less) ? (fov - 1.f) : (fov + 1.f); + fov = Round(fov); if (fov >= 10 && fov <= 160) { gEnv->mainCamera->setFOVy(Degree(fov)); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("FOV: ") + TOSTRING(fov), "camera_edit.png", 2000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("FOV: ") + TOSTRING(fov), "camera_edit.png", 2000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("FOV: ") + TOSTRING(fov)); // save the settings if (this->GetCameraBehavior() == CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM) - { - App::gfx_fov_internal.SetActive(fov); - } + { App::gfx_fov_internal.SetActive(fov); } else { App::gfx_fov_external.SetActive(fov); @@ -518,7 +411,8 @@ void SimController::UpdateInputEvents(float dt) } else { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("FOV: Limit reached"), "camera_edit.png", 2000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("FOV: Limit reached"), "camera_edit.png", 2000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("FOV: Limit reached")); } } @@ -536,7 +430,8 @@ void SimController::UpdateInputEvents(float dt) App::gfx_fov_external.SetActive(fov); } gEnv->mainCamera->setFOVy(Degree(fov)); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("FOV: ") + TOSTRING(fov), "camera_edit.png", 2000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("FOV: ") + TOSTRING(fov), "camera_edit.png", 2000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("FOV: ") + TOSTRING(fov)); } } @@ -545,17 +440,15 @@ void SimController::UpdateInputEvents(float dt) if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_FULLSCREEN_TOGGLE, 2.0f)) { static int org_width = -1, org_height = -1; - int width = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getWidth(); - int height = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getHeight(); - if (org_width == -1) - org_width = width; - if (org_height == -1) - org_height = height; + int width = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getWidth(); + int height = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getHeight(); + if (org_width == -1) org_width = width; + if (org_height == -1) org_height = height; bool mode = RoR::App::GetOgreSubsystem()->GetRenderWindow()->isFullScreen(); if (!mode) { RoR::App::GetOgreSubsystem()->GetRenderWindow()->setFullscreen(true, org_width, org_height); - LOG(" ** switched to fullscreen: "+TOSTRING(width)+"x"+TOSTRING(height)); + LOG(" ** switched to fullscreen: " + TOSTRING(width) + "x" + TOSTRING(height)); } else { @@ -565,43 +458,46 @@ void SimController::UpdateInputEvents(float dt) } } - static auto& object_list = App::GetSimTerrain()->getObjectManager()->GetEditorObjects(); - static bool terrain_editing_track_object = true; - static int terrain_editing_rotation_axis = 1; - static std::string last_object_name = ""; - static int object_count = static_cast(object_list.size()); - static int object_index = -1; + static auto & object_list = App::GetSimTerrain()->getObjectManager()->GetEditorObjects(); + static bool terrain_editing_track_object = true; + static int terrain_editing_rotation_axis = 1; + static std::string last_object_name = ""; + static int object_count = static_cast(object_list.size()); + static int object_index = -1; - bool toggle_editor = (m_player_actor && simEDITOR(s)) || + bool toggle_editor = + (m_player_actor && simEDITOR(s)) || (!m_player_actor && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_TERRAIN_EDITOR)); if (toggle_editor) { App::sim_state.SetActive(simEDITOR(s) ? SimState::RUNNING : SimState::EDITOR_MODE); - s = App::sim_state.GetActive(); + s = App::sim_state.GetActive(); UTFString ssmsg = simEDITOR(s) ? _L("Entered terrain editing mode") : _L("Left terrain editing mode"); RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, - "infromation.png", 2000, false); + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); if (simEDITOR(s)) { - object_list = App::GetSimTerrain()->getObjectManager()->GetEditorObjects(); + object_list = App::GetSimTerrain()->getObjectManager()->GetEditorObjects(); object_index = -1; } else { - std::string path = PathCombine(RoR::App::sys_config_dir.GetActive(), "editor_out.cfg"); + std::string path = PathCombine(RoR::App::sys_config_dir.GetActive(), "editor_out.cfg"); std::ofstream file(path); if (file.is_open()) { for (auto object : object_list) { - SceneNode* sn = object.node; + SceneNode *sn = object.node; if (sn != nullptr) { - String pos = StringUtil::format("%8.3f, %8.3f, %8.3f" , object.position.x, object.position.y, object.position.z); - String rot = StringUtil::format("% 6.1f, % 6.1f, % 6.1f", object.rotation.x, object.rotation.y, object.rotation.z); + String pos = + StringUtil::format("%8.3f, %8.3f, %8.3f", object.position.x, object.position.y, object.position.z); + String rot = + StringUtil::format("% 6.1f, % 6.1f, % 6.1f", object.rotation.x, object.rotation.y, object.rotation.z); file << pos + ", " + rot + ", " + object.name + "\n"; } @@ -615,7 +511,7 @@ void SimController::UpdateInputEvents(float dt) } } - //OLD m_loading_state == ALL_LOADED + // OLD m_loading_state == ALL_LOADED if (simEDITOR(s) && object_list.size() > 0) { bool update = false; @@ -626,40 +522,37 @@ void SimController::UpdateInputEvents(float dt) } if (m_terrain_editor_mouse_ray.getDirection() != Vector3::ZERO) { - float min_dist = std::numeric_limits::max(); - Vector3 origin = m_terrain_editor_mouse_ray.getOrigin(); + float min_dist = std::numeric_limits::max(); + Vector3 origin = m_terrain_editor_mouse_ray.getOrigin(); Vector3 direction = m_terrain_editor_mouse_ray.getDirection(); for (int i = 0; i < (int)object_list.size(); i++) { Real ray_object_distance = direction.crossProduct(object_list[i].node->getPosition() - origin).length(); if (ray_object_distance < min_dist) { - min_dist = ray_object_distance; - update = (object_index != i); + min_dist = ray_object_distance; + update = (object_index != i); object_index = i; } } m_terrain_editor_mouse_ray.setDirection(Vector3::ZERO); } - if (object_index != -1) - { - last_object_name = object_list[object_index].name; - } + if (object_index != -1) { last_object_name = object_list[object_index].name; } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_OR_EXIT_TRUCK)) { if (object_index == -1) { // Select nearest object - Vector3 ref_pos = this->AreControlsLocked() ? gEnv->mainCamera->getPosition() : gEnv->player->getPosition(); - float min_dist = std::numeric_limits::max(); + Vector3 ref_pos = this->AreControlsLocked() ? gEnv->mainCamera->getPosition() : gEnv->player->getPosition(); + float min_dist = std::numeric_limits::max(); for (int i = 0; i < (int)object_list.size(); i++) { float dist = ref_pos.squaredDistance(object_list[i].node->getPosition()); if (dist < min_dist) { object_index = i; - min_dist = dist; - update = true; + min_dist = dist; + update = true; } } } @@ -668,119 +561,113 @@ void SimController::UpdateInputEvents(float dt) object_index = -1; } } - else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESPAWN_LAST_TRUCK) && - !last_object_name.empty()) + else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESPAWN_LAST_TRUCK) && !last_object_name.empty()) { Vector3 pos = gEnv->player->getPosition(); try { - SceneNode* bakeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - App::GetSimTerrain()->getObjectManager()->LoadTerrainObject(last_object_name, pos, Vector3::ZERO, bakeNode, "Console", ""); + SceneNode *bakeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + App::GetSimTerrain()->getObjectManager()->LoadTerrainObject(last_object_name, pos, Vector3::ZERO, bakeNode, + "Console", ""); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_REPLY, _L("Spawned object at position: ") + String("x: ") + TOSTRING(pos.x) + String("z: ") + TOSTRING(pos.z), "world.png"); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_REPLY, + _L("Spawned object at position: ") + String("x: ") + TOSTRING(pos.x) + + String("z: ") + TOSTRING(pos.z), + "world.png"); } - catch (std::exception& e) + catch (std::exception &e) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR, e.what(), "error.png"); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR, e.what(), + "error.png"); } } else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_NEXT_TRUCK, 0.25f)) { object_index = (object_index + 1 + (int)object_list.size()) % object_list.size(); - update = true; + update = true; } else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_PREVIOUS_TRUCK, 0.25f)) { object_index = (object_index - 1 + (int)object_list.size()) % object_list.size(); - update = true; + update = true; } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESCUE_TRUCK)) { UTFString axis = _L("ry"); if (terrain_editing_rotation_axis == 0) { - axis = _L("ry"); + axis = _L("ry"); terrain_editing_rotation_axis = 1; } else if (terrain_editing_rotation_axis == 1) { - axis = _L("rz"); + axis = _L("rz"); terrain_editing_rotation_axis = 2; } else if (terrain_editing_rotation_axis == 2) { - axis = _L("rx"); + axis = _L("rx"); terrain_editing_rotation_axis = 0; } UTFString ssmsg = _L("Rotating: ") + axis; - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); } if (RoR::App::GetInputEngine()->isKeyDownValueBounce(OIS::KC_SPACE)) { terrain_editing_track_object = !terrain_editing_track_object; UTFString ssmsg = terrain_editing_track_object ? _L("Enabled object tracking") : _L("Disabled object tracking"); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); } if (object_index != -1 && update) { - String ssmsg = _L("Selected object: [") + TOSTRING(object_index) + "/" + TOSTRING(object_list.size()) + "] (" + object_list[object_index].name + ")"; - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, "infromation.png", 2000, false); + String ssmsg = _L("Selected object: [") + TOSTRING(object_index) + "/" + TOSTRING(object_list.size()) + "] (" + + object_list[object_index].name + ")"; + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, ssmsg, + "infromation.png", 2000, false); RoR::App::GetGuiManager()->PushNotification("Notice:", ssmsg); - if (terrain_editing_track_object) - { - gEnv->player->setPosition(object_list[object_index].node->getPosition()); - } + if (terrain_editing_track_object) { gEnv->player->setPosition(object_list[object_index].node->getPosition()); } } if (object_index != -1 && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESET_TRUCK)) { - SceneNode* sn = object_list[object_index].node; + SceneNode *sn = object_list[object_index].node; object_list[object_index].position = object_list[object_index].initial_position; sn->setPosition(object_list[object_index].position); object_list[object_index].rotation = object_list[object_index].initial_rotation; - Vector3 rot = object_list[object_index].rotation; - sn->setOrientation(Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z)); + Vector3 rot = object_list[object_index].rotation; + sn->setOrientation(Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z)); sn->pitch(Degree(-90)); } if (object_index != -1 && !this->AreControlsLocked()) { - SceneNode* sn = object_list[object_index].node; + SceneNode *sn = object_list[object_index].node; Vector3 translation = Vector3::ZERO; - float rotation = 0.0f; + float rotation = 0.0f; - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_LEFT)) - { - rotation += 2.0f; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_LEFT)) { rotation += 2.0f; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_RIGHT)) { rotation -= 2.0f; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_ACCELERATE)) - { - translation.y += 0.5f; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_ACCELERATE)) { translation.y += 0.5f; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_BRAKE)) { translation.y -= 0.5f; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_FORWARD)) - { - translation.x += 0.5f; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_FORWARD)) { translation.x += 0.5f; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_BACKWARDS)) { translation.x -= 0.5f; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_RIGHT)) - { - translation.z += 0.5f; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_RIGHT)) { translation.z += 0.5f; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_LEFT)) { translation.z -= 0.5f; @@ -797,13 +684,11 @@ void SimController::UpdateInputEvents(float dt) object_list[object_index].rotation[terrain_editing_rotation_axis] += rotation * scale * dt; Vector3 rot = object_list[object_index].rotation; - sn->setOrientation(Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z)); + sn->setOrientation(Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z)); sn->pitch(Degree(-90)); - if (terrain_editing_track_object) - { - gEnv->player->setPosition(sn->getPosition()); - } + if (terrain_editing_track_object) { gEnv->player->setPosition(sn->getPosition()); } } else if (terrain_editing_track_object && gEnv->player->getPosition() != sn->getPosition()) { @@ -811,9 +696,7 @@ void SimController::UpdateInputEvents(float dt) sn->setPosition(gEnv->player->getPosition()); } if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REMOVE_CURRENT_TRUCK)) - { - App::GetSimTerrain()->getObjectManager()->unloadObject(object_list[object_index].instance_name); - } + { App::GetSimTerrain()->getObjectManager()->unloadObject(object_list[object_index].instance_name); } } else { @@ -844,9 +727,7 @@ void SimController::UpdateInputEvents(float dt) RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Enabled hard reset mode")); } if (!RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REPAIR_TRUCK)) - { - m_advanced_vehicle_repair_timer = 0.0f; - } + { m_advanced_vehicle_repair_timer = 0.0f; } if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_RESET_TRUCK) && !m_player_actor->ar_replay_mode) { ActorModifyRequest rq; @@ -854,32 +735,27 @@ void SimController::UpdateInputEvents(float dt) rq.amr_type = ActorModifyRequest::Type::RESET_ON_INIT_POS; this->QueueActorModify(rq); } - else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REMOVE_CURRENT_TRUCK) && !m_player_actor->ar_replay_mode) + else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REMOVE_CURRENT_TRUCK) && + !m_player_actor->ar_replay_mode) { this->QueueActorRemove(m_player_actor); } - else if ((RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REPAIR_TRUCK) || m_advanced_vehicle_repair) && !m_player_actor->ar_replay_mode) + else if ((RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REPAIR_TRUCK) || m_advanced_vehicle_repair) && + !m_player_actor->ar_replay_mode) { if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_REPAIR_TRUCK)) - { - m_advanced_vehicle_repair = m_advanced_vehicle_repair_timer > 1.0f; - } + { m_advanced_vehicle_repair = m_advanced_vehicle_repair_timer > 1.0f; } Vector3 translation = Vector3::ZERO; - float rotation = 0.0f; + float rotation = 0.0f; if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_ACCELERATE)) - { - translation += 2.0f * Vector3::UNIT_Y * dt; - } + { translation += 2.0f * Vector3::UNIT_Y * dt; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_BRAKE)) { translation -= 2.0f * Vector3::UNIT_Y * dt; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_LEFT)) - { - rotation += 0.5f * dt; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_LEFT)) { rotation += 0.5f * dt; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_STEER_RIGHT)) { rotation -= 0.5f * dt; @@ -958,14 +834,14 @@ void SimController::UpdateInputEvents(float dt) { ActorModifyRequest rq; rq.amr_actor = actor; - rq.amr_type = reset_type; + rq.amr_type = reset_type; this->QueueActorModify(rq); } } ActorModifyRequest rq; rq.amr_actor = m_player_actor; - rq.amr_type = reset_type; + rq.amr_type = reset_type; this->QueueActorModify(rq); } else @@ -985,11 +861,13 @@ void SimController::UpdateInputEvents(float dt) m_player_actor->ar_forward_commands = !m_player_actor->ar_forward_commands; if (m_player_actor->ar_forward_commands) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("forwardcommands enabled"), "information.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("forwardcommands enabled"), "information.png", 3000); } else { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("forwardcommands disabled"), "information.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("forwardcommands disabled"), "information.png", 3000); } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_TOGGLE_IMPORTCOMMANDS)) @@ -997,70 +875,57 @@ void SimController::UpdateInputEvents(float dt) m_player_actor->ar_import_commands = !m_player_actor->ar_import_commands; if (m_player_actor->ar_import_commands) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("importcommands enabled"), "information.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("importcommands enabled"), "information.png", 3000); } else { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("importcommands disabled"), "information.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("importcommands disabled"), "information.png", 3000); } } // replay mode if (m_player_actor->ar_replay_mode) { - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FORWARD, 0.1f) && m_player_actor->ar_replay_pos <= 0) - { - m_player_actor->ar_replay_pos++; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_BACKWARD, 0.1f) && m_player_actor->ar_replay_pos > -m_player_actor->ar_replay_length) - { - m_player_actor->ar_replay_pos--; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FAST_FORWARD, 0.1f) && m_player_actor->ar_replay_pos + 10 <= 0) - { - m_player_actor->ar_replay_pos += 10; - } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FAST_BACKWARD, 0.1f) && m_player_actor->ar_replay_pos - 10 > -m_player_actor->ar_replay_length) - { - m_player_actor->ar_replay_pos -= 10; - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FORWARD, 0.1f) && + m_player_actor->ar_replay_pos <= 0) + { m_player_actor->ar_replay_pos++; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_BACKWARD, 0.1f) && + m_player_actor->ar_replay_pos > -m_player_actor->ar_replay_length) + { m_player_actor->ar_replay_pos--; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FAST_FORWARD, 0.1f) && + m_player_actor->ar_replay_pos + 10 <= 0) + { m_player_actor->ar_replay_pos += 10; } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FAST_BACKWARD, 0.1f) && + m_player_actor->ar_replay_pos - 10 > -m_player_actor->ar_replay_length) + { m_player_actor->ar_replay_pos -= 10; } if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LMENU)) { - if (m_player_actor->ar_replay_pos <= 0 && m_player_actor->ar_replay_pos >= -m_player_actor->ar_replay_length) + if (m_player_actor->ar_replay_pos <= 0 && + m_player_actor->ar_replay_pos >= -m_player_actor->ar_replay_length) { - if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) || RoR::App::GetInputEngine()->isKeyDown(OIS::KC_RSHIFT)) - { - m_player_actor->ar_replay_pos += RoR::App::GetInputEngine()->getMouseState().X.rel * 1.5f; - } + if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) || + RoR::App::GetInputEngine()->isKeyDown(OIS::KC_RSHIFT)) + { m_player_actor->ar_replay_pos += RoR::App::GetInputEngine()->getMouseState().X.rel * 1.5f; } else { m_player_actor->ar_replay_pos += RoR::App::GetInputEngine()->getMouseState().X.rel * 0.05f; } - if (m_player_actor->ar_replay_pos > 0) - { - m_player_actor->ar_replay_pos = 0; - } + if (m_player_actor->ar_replay_pos > 0) { m_player_actor->ar_replay_pos = 0; } if (m_player_actor->ar_replay_pos < -m_player_actor->ar_replay_length) - { - m_player_actor->ar_replay_pos = -m_player_actor->ar_replay_length; - } + { m_player_actor->ar_replay_pos = -m_player_actor->ar_replay_length; } } } } - if (m_player_actor->ar_driveable == TRUCK) - { - LandVehicleSimulation::UpdateInputEvents(m_player_actor, dt); - } - if (m_player_actor->ar_driveable == AIRPLANE) - { - AircraftSimulation::UpdateInputEvents(m_player_actor, dt); - } + if (m_player_actor->ar_driveable == TRUCK) { LandVehicleSimulation::UpdateInputEvents(m_player_actor, dt); } + if (m_player_actor->ar_driveable == AIRPLANE) { AircraftSimulation::UpdateInputEvents(m_player_actor, dt); } if (m_player_actor->ar_driveable == BOAT) { - //BOAT SPECIFICS + // BOAT SPECIFICS - //throttle + // throttle if (RoR::App::GetInputEngine()->isEventDefined(EV_BOAT_THROTTLE_AXIS)) { float f = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_THROTTLE_AXIS); @@ -1071,33 +936,38 @@ void SimController::UpdateInputEvents(float dt) } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_BOAT_THROTTLE_DOWN, 0.1f)) { - //throttle down + // throttle down for (int i = 0; i < m_player_actor->ar_num_screwprops; i++) - m_player_actor->ar_screwprops[i]->setThrottle(m_player_actor->ar_screwprops[i]->getThrottle() - 0.05); + m_player_actor->ar_screwprops[i]->setThrottle(m_player_actor->ar_screwprops[i]->getThrottle() - + 0.05); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_BOAT_THROTTLE_UP, 0.1f)) { - //throttle up + // throttle up for (int i = 0; i < m_player_actor->ar_num_screwprops; i++) - m_player_actor->ar_screwprops[i]->setThrottle(m_player_actor->ar_screwprops[i]->getThrottle() + 0.05); + m_player_actor->ar_screwprops[i]->setThrottle(m_player_actor->ar_screwprops[i]->getThrottle() + + 0.05); } // steer - float tmp_steer_left = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_STEER_LEFT); + float tmp_steer_left = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_STEER_LEFT); float tmp_steer_right = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_STEER_RIGHT); - float stime = RoR::App::GetInputEngine()->getEventBounceTime(EV_BOAT_STEER_LEFT) + RoR::App::GetInputEngine()->getEventBounceTime(EV_BOAT_STEER_RIGHT); + float stime = RoR::App::GetInputEngine()->getEventBounceTime(EV_BOAT_STEER_LEFT) + + RoR::App::GetInputEngine()->getEventBounceTime(EV_BOAT_STEER_RIGHT); float sum_steer = (tmp_steer_left - tmp_steer_right) * dt; // do not center the rudder! if (fabs(sum_steer) > 0 && stime <= 0) { for (int i = 0; i < m_player_actor->ar_num_screwprops; i++) - m_player_actor->ar_screwprops[i]->setRudder(m_player_actor->ar_screwprops[i]->getRudder() + sum_steer); + m_player_actor->ar_screwprops[i]->setRudder(m_player_actor->ar_screwprops[i]->getRudder() + + sum_steer); } - if (RoR::App::GetInputEngine()->isEventDefined(EV_BOAT_STEER_LEFT_AXIS) && RoR::App::GetInputEngine()->isEventDefined(EV_BOAT_STEER_RIGHT_AXIS)) + if (RoR::App::GetInputEngine()->isEventDefined(EV_BOAT_STEER_LEFT_AXIS) && + RoR::App::GetInputEngine()->isEventDefined(EV_BOAT_STEER_RIGHT_AXIS)) { - tmp_steer_left = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_STEER_LEFT_AXIS); + tmp_steer_left = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_STEER_LEFT_AXIS); tmp_steer_right = RoR::App::GetInputEngine()->getEventValue(EV_BOAT_STEER_RIGHT_AXIS); - sum_steer = (tmp_steer_left - tmp_steer_right); + sum_steer = (tmp_steer_left - tmp_steer_right); for (int i = 0; i < m_player_actor->ar_num_screwprops; i++) m_player_actor->ar_screwprops[i]->setRudder(sum_steer); } @@ -1113,46 +983,36 @@ void SimController::UpdateInputEvents(float dt) m_player_actor->ar_screwprops[i]->toggleReverse(); } } - //COMMON KEYS + // COMMON KEYS if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TRUCK_REMOVE)) - { - this->QueueActorRemove(m_player_actor); - } + { this->QueueActorRemove(m_player_actor); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ROPELOCK)) - { - m_player_actor->ar_toggle_ropes = true; - } + { m_player_actor->ar_toggle_ropes = true; } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_LOCK)) { m_player_actor->ToggleHooks(-1, HOOK_TOGGLE, -1); - //SlideNodeLock + // SlideNodeLock m_player_actor->ToggleSlideNodeLock(); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_AUTOLOCK)) { - //unlock all autolocks + // unlock all autolocks m_player_actor->ToggleHooks(-2, HOOK_UNLOCK, -1); } - //strap + // strap if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_SECURE_LOAD)) - { - m_player_actor->ar_toggle_ties = true; - } + { m_player_actor->ar_toggle_ties = true; } - //replay mode + // replay mode if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_REPLAY_MODE)) { if (m_player_actor->getReplay() != nullptr) - { - m_player_actor->setReplayMode(!m_player_actor->ar_replay_mode); - } + { m_player_actor->setReplayMode(!m_player_actor->ar_replay_mode); } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_CUSTOM_PARTICLES)) - { - m_player_actor->ToggleCustomParticles(); - } + { m_player_actor->ToggleCustomParticles(); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_DEBUG_VIEW)) { @@ -1173,24 +1033,19 @@ void SimController::UpdateInputEvents(float dt) } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_TRUCK_LIGHTS)) - { - m_player_actor->ToggleLights(); - } + { m_player_actor->ToggleLights(); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_TRUCK_BEACONS)) - { - m_player_actor->ToggleBeacons(); - } + { m_player_actor->ToggleBeacons(); } - //camera mode + // camera mode if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_PRESSURE_LESS)) { float change = m_player_actor->GetTyrePressure() * (1.0f - pow(2.0f, dt / 2.0f)); - change = Math::Clamp(change, -dt * 10.0f, -dt * 1.0f); + change = Math::Clamp(change, -dt * 10.0f, -dt * 1.0f); if (m_pressure_pressed = m_player_actor->AddTyrePressure(change)) { - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->showPressureOverlay(true); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->showPressureOverlay(true); SOUND_START(m_player_actor, SS_TRIG_AIR); } @@ -1198,11 +1053,10 @@ void SimController::UpdateInputEvents(float dt) else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_COMMON_PRESSURE_MORE)) { float change = m_player_actor->GetTyrePressure() * (pow(2.0f, dt / 2.0f) - 1.0f); - change = Math::Clamp(change, +dt * 1.0f, +dt * 10.0f); + change = Math::Clamp(change, +dt * 1.0f, +dt * 10.0f); if (m_pressure_pressed = m_player_actor->AddTyrePressure(change)) { - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->showPressureOverlay(true); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->showPressureOverlay(true); SOUND_START(m_player_actor, SS_TRIG_AIR); } @@ -1210,7 +1064,7 @@ void SimController::UpdateInputEvents(float dt) else if (m_pressure_pressed) { SOUND_STOP(m_player_actor, SS_TRIG_AIR); - m_pressure_pressed = false; + m_pressure_pressed = false; m_pressure_pressed_timer = 1.5f; } else if (m_pressure_pressed_timer > 0.0f) @@ -1219,16 +1073,17 @@ void SimController::UpdateInputEvents(float dt) } else { - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->showPressureOverlay(false); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->showPressureOverlay(false); } - if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESCUE_TRUCK, 0.5f) && !mp_connected && m_player_actor->ar_driveable != AIRPLANE) + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESCUE_TRUCK, 0.5f) && !mp_connected && + m_player_actor->ar_driveable != AIRPLANE) { - Actor* rescuer = m_actor_manager.FetchRescueVehicle(); + Actor *rescuer = m_actor_manager.FetchRescueVehicle(); if (rescuer == nullptr) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("No rescue truck found!"), "warning.png"); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("No rescue truck found!"), "warning.png"); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("No rescue truck found!")); } else @@ -1248,9 +1103,7 @@ void SimController::UpdateInputEvents(float dt) if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_TRUCK_TOGGLE_VIDEOCAMERA, 0.5f)) { if (m_player_actor->GetGfxActor()->GetVideoCamState() == GfxActor::VideoCamState::VCSTATE_DISABLED) - { - m_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_ENABLED_ONLINE); - } + { m_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_ENABLED_ONLINE); } else { m_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_DISABLED); @@ -1292,12 +1145,11 @@ void SimController::UpdateInputEvents(float dt) if (this->GetPlayerActor() == nullptr) { // find the nearest vehicle - float mindist = 1000.0; - Actor* nearest_actor = nullptr; + float mindist = 1000.0; + Actor *nearest_actor = nullptr; for (auto actor : GetActors()) { - if (!actor->ar_driveable) - continue; + if (!actor->ar_driveable) continue; if (actor->ar_cinecam_node[0] == -1) { LOG("cinecam missing, cannot enter the actor!"); @@ -1306,21 +1158,19 @@ void SimController::UpdateInputEvents(float dt) float len = 0.0f; if (gEnv->player) { - len = actor->ar_nodes[actor->ar_cinecam_node[0]].AbsPosition.distance(gEnv->player->getPosition() + Vector3(0.0, 2.0, 0.0)); + len = actor->ar_nodes[actor->ar_cinecam_node[0]].AbsPosition.distance(gEnv->player->getPosition() + + Vector3(0.0, 2.0, 0.0)); } if (len < mindist) { - mindist = len; + mindist = len; nearest_actor = actor; } } - if (mindist < 20.0) - { - this->SetPendingPlayerActor(nearest_actor); - } + if (mindist < 20.0) { this->SetPendingPlayerActor(nearest_actor); } } else if (m_player_actor->ar_nodes[0].Velocity.squaredLength() < 1.0f || - m_player_actor->ar_sim_state == Actor::SimState::NETWORKED_OK) + m_player_actor->ar_sim_state == Actor::SimState::NETWORKED_OK) { this->SetPendingPlayerActor(nullptr); } @@ -1332,29 +1182,23 @@ void SimController::UpdateInputEvents(float dt) } else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_NEXT_TRUCK, 0.25f)) { - Actor* actor = m_actor_manager.FetchNextVehicleOnList(m_player_actor, m_prev_player_actor); - if (actor != m_player_actor) - { - this->SetPendingPlayerActor(actor); - } + Actor *actor = m_actor_manager.FetchNextVehicleOnList(m_player_actor, m_prev_player_actor); + if (actor != m_player_actor) { this->SetPendingPlayerActor(actor); } } else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_ENTER_PREVIOUS_TRUCK, 0.25f)) { - Actor* actor = m_actor_manager.FetchPreviousVehicleOnList(m_player_actor, m_prev_player_actor); - if (actor != m_player_actor) - { - this->SetPendingPlayerActor(actor); - } + Actor *actor = m_actor_manager.FetchPreviousVehicleOnList(m_player_actor, m_prev_player_actor); + if (actor != m_player_actor) { this->SetPendingPlayerActor(actor); } } else if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_RESPAWN_LAST_TRUCK, 0.25f)) { if (m_last_cache_selection != nullptr) { ActorSpawnRequest rq; - rq.asr_cache_entry = m_last_cache_selection; - rq.asr_config = m_last_section_config; - rq.asr_skin_entry = m_last_skin_selection; - rq.asr_origin = ActorSpawnRequest::Origin::USER; + rq.asr_cache_entry = m_last_cache_selection; + rq.asr_config = m_last_section_config; + rq.asr_skin_entry = m_last_skin_selection; + rq.asr_origin = ActorSpawnRequest::Origin::USER; m_actor_spawn_queue.push_back(rq); } } @@ -1362,16 +1206,13 @@ void SimController::UpdateInputEvents(float dt) #ifdef USE_CAELUM - const bool caelum_enabled = App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM; - SkyManager* sky_mgr = App::GetSimTerrain()->getSkyManager(); + const bool caelum_enabled = App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM; + SkyManager *sky_mgr = App::GetSimTerrain()->getSkyManager(); if (caelum_enabled && (sky_mgr != nullptr) && (simRUNNING(s) || simPAUSED(s) || simEDITOR(s))) { Real time_factor = 1.0f; - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_SKY_INCREASE_TIME)) - { - time_factor = 1000.0f; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_SKY_INCREASE_TIME)) { time_factor = 1000.0f; } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_SKY_INCREASE_TIME_FAST)) { time_factor = 10000.0f; @@ -1389,22 +1230,20 @@ void SimController::UpdateInputEvents(float dt) { sky_mgr->SetSkyTimeFactor(time_factor); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Time set to ") + sky_mgr->GetPrettyTime()); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Time set to ") + sky_mgr->GetPrettyTime(), "weather_sun.png", 1000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("Time set to ") + sky_mgr->GetPrettyTime(), "weather_sun.png", 1000); } } #endif // USE_CAELUM - - const bool skyx_enabled = App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX; - SkyXManager* skyx_mgr = App::GetSimTerrain()->getSkyXManager(); + const bool skyx_enabled = App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX; + SkyXManager *skyx_mgr = App::GetSimTerrain()->getSkyXManager(); if (skyx_enabled && (skyx_mgr != nullptr) && (simRUNNING(s) || simPAUSED(s) || simEDITOR(s))) { if (RoR::App::GetInputEngine()->getEventBoolValue(EV_SKY_INCREASE_TIME)) - { - skyx_mgr->GetSkyX()->setTimeMultiplier(1.0f); - } + { skyx_mgr->GetSkyX()->setTimeMultiplier(1.0f); } else if (RoR::App::GetInputEngine()->getEventBoolValue(EV_SKY_INCREASE_TIME_FAST)) { skyx_mgr->GetSkyX()->setTimeMultiplier(2.0f); @@ -1429,29 +1268,21 @@ void SimController::UpdateInputEvents(float dt) mSceneDetailIndex = (mSceneDetailIndex + 1) % 3; switch (mSceneDetailIndex) { - case 0: - gEnv->mainCamera->setPolygonMode(PM_SOLID); - break; - case 1: - gEnv->mainCamera->setPolygonMode(PM_WIREFRAME); - break; - case 2: - gEnv->mainCamera->setPolygonMode(PM_POINTS); - break; + case 0: gEnv->mainCamera->setPolygonMode(PM_SOLID); break; + case 1: gEnv->mainCamera->setPolygonMode(PM_WIREFRAME); break; + case 2: gEnv->mainCamera->setPolygonMode(PM_POINTS); break; } } } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TRUCK_INFO) && m_player_actor) { - m_actor_info_gui_visible = ! m_actor_info_gui_visible; + m_actor_info_gui_visible = !m_actor_info_gui_visible; gui_man->GetSimUtils()->SetActorInfoBoxVisible(m_actor_info_gui_visible); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TRUCK_DESCRIPTION) && m_player_actor) - { - gui_man->SetVisible_VehicleDescription(! gui_man->IsVisible_VehicleDescription()); - } + { gui_man->SetVisible_VehicleDescription(!gui_man->IsVisible_VehicleDescription()); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_HIDE_GUI)) { @@ -1461,16 +1292,12 @@ void SimController::UpdateInputEvents(float dt) if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_DASHBOARD)) { - if (RoR::App::GetOverlayWrapper()) - { - RoR::App::GetOverlayWrapper()->ToggleDashboardOverlays(m_player_actor); - } + if (RoR::App::GetOverlayWrapper()) { RoR::App::GetOverlayWrapper()->ToggleDashboardOverlays(m_player_actor); } } - if ((simRUNNING(s) || simPAUSED(s) || simEDITOR(s)) && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_STATS)) - { - gui_man->GetSimUtils()->SetFPSBoxVisible(! gui_man->GetSimUtils()->IsFPSBoxVisible()); - } + if ((simRUNNING(s) || simPAUSED(s) || simEDITOR(s)) && + RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_STATS)) + { gui_man->GetSimUtils()->SetFPSBoxVisible(!gui_man->GetSimUtils()->IsFPSBoxVisible()); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_MAT_DEBUG)) { @@ -1480,14 +1307,13 @@ void SimController::UpdateInputEvents(float dt) m_stats_on = 2; else if (m_stats_on == 2) m_stats_on = 0; - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->showDebugOverlay(m_stats_on); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->showDebugOverlay(m_stats_on); } if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_OUTPUT_POSITION)) { Vector3 position(Vector3::ZERO); - Radian rotation(0); + Radian rotation(0); if (m_player_actor == nullptr) { position = gEnv->player->getPosition(); @@ -1498,15 +1324,12 @@ void SimController::UpdateInputEvents(float dt) position = m_player_actor->getPosition(); rotation = m_player_actor->getRotation(); } - String pos = StringUtil::format("%8.3f, %8.3f, %8.3f" , position.x, position.y, position.z); - String rot = StringUtil::format("% 6.1f, % 6.1f, % 6.1f", 0.0f, rotation.valueDegrees() , 0.0f); + String pos = StringUtil::format("%8.3f, %8.3f, %8.3f", position.x, position.y, position.z); + String rot = StringUtil::format("% 6.1f, % 6.1f, % 6.1f", 0.0f, rotation.valueDegrees(), 0.0f); LOG("Position: " + pos + ", " + rot); } - if (m_time_until_next_toggle >= 0) - { - m_time_until_next_toggle -= dt; - } + if (m_time_until_next_toggle >= 0) { m_time_until_next_toggle -= dt; } } void SimController::TeleportPlayerXZ(float x, float z) @@ -1525,14 +1348,14 @@ void SimController::TeleportPlayerXZ(float x, float z) auto actors = m_player_actor->GetAllLinkedActors(); actors.push_back(m_player_actor); - float src_agl = std::numeric_limits::max(); - float dst_agl = std::numeric_limits::max(); + float src_agl = std::numeric_limits::max(); + float dst_agl = std::numeric_limits::max(); for (auto actor : actors) { for (int i = 0; i < actor->ar_num_nodes; i++) { Vector3 pos = actor->ar_nodes[i].AbsPosition; - src_agl = std::min(pos.y - gEnv->collisions->getSurfaceHeight(pos.x, pos.z), src_agl); + src_agl = std::min(pos.y - gEnv->collisions->getSurfaceHeight(pos.x, pos.z), src_agl); pos += translation; dst_agl = std::min(pos.y - gEnv->collisions->getSurfaceHeight(pos.x, pos.z), dst_agl); } @@ -1561,14 +1384,14 @@ void SimController::UpdateSimulation(float dt) m_character_factory.handleStreamData(packets); // Update characters last (or else beam coupling might fail) } } -#endif //SOCKETW +#endif // SOCKETW // ACTOR CHANGE REQUESTS - Handle early (so that other logic can reflect it) // 1. Removal requests - Done first; respective entries in 'modify' queue are erased. // 2. Modify requests - currently just reload, will be extended // 3. Spawn requests - may outdate others by changing player seating // 4. Player seating change requests - TODO; currently done ad-hoc - for (Actor* actor: m_actor_remove_queue) + for (Actor *actor : m_actor_remove_queue) { if (actor == m_player_actor) { @@ -1577,10 +1400,7 @@ void SimController::UpdateSimulation(float dt) gEnv->player->setPosition(center); } - if (actor == m_prev_player_actor) - { - m_prev_player_actor = nullptr; - } + if (actor == m_prev_player_actor) { m_prev_player_actor = nullptr; } if (actor == m_pending_player_actor) { @@ -1588,37 +1408,30 @@ void SimController::UpdateSimulation(float dt) } // Remove modify-requests for this actor - m_actor_modify_queue.erase( - std::remove_if( - m_actor_modify_queue.begin(), m_actor_modify_queue.end(), - [actor](ActorModifyRequest& rq) -> bool { return rq.amr_actor == actor; }), - m_actor_modify_queue.end()); + m_actor_modify_queue.erase(std::remove_if(m_actor_modify_queue.begin(), m_actor_modify_queue.end(), + [actor](ActorModifyRequest &rq) -> bool { return rq.amr_actor == actor; }), + m_actor_modify_queue.end()); this->RemoveActorDirectly(actor); } m_actor_remove_queue.clear(); - for (ActorModifyRequest& rq: m_actor_modify_queue) + for (ActorModifyRequest &rq : m_actor_modify_queue) { - if (rq.amr_type == ActorModifyRequest::Type::SOFT_RESET) - { - rq.amr_actor->SoftReset(); - } + if (rq.amr_type == ActorModifyRequest::Type::SOFT_RESET) { rq.amr_actor->SoftReset(); } if ((rq.amr_type == ActorModifyRequest::Type::RESET_ON_SPOT) || (rq.amr_type == ActorModifyRequest::Type::RESET_ON_INIT_POS)) - { - rq.amr_actor->SyncReset(rq.amr_type == ActorModifyRequest::Type::RESET_ON_INIT_POS); - } + { rq.amr_actor->SyncReset(rq.amr_type == ActorModifyRequest::Type::RESET_ON_INIT_POS); } if (rq.amr_type == ActorModifyRequest::Type::RELOAD) { if (m_player_actor == rq.amr_actor) // Check if the request is up-to-date { - String filename = m_player_actor->ar_filename; - auto reload_pos = m_player_actor->getPosition(); - auto reload_dir = Quaternion(Degree(270) - Radian(m_player_actor->getRotation()), Vector3::UNIT_Y); - auto debug_view = m_player_actor->GetGfxActor()->GetDebugView(); - auto asr_config = m_player_actor->GetSectionConfig(); - auto used_skin = m_player_actor->GetUsedSkin(); + String filename = m_player_actor->ar_filename; + auto reload_pos = m_player_actor->getPosition(); + auto reload_dir = Quaternion(Degree(270) - Radian(m_player_actor->getRotation()), Vector3::UNIT_Y); + auto debug_view = m_player_actor->GetGfxActor()->GetDebugView(); + auto asr_config = m_player_actor->GetSectionConfig(); + auto used_skin = m_player_actor->GetUsedSkin(); reload_pos.y = m_player_actor->GetMinHeight(); @@ -1628,12 +1441,12 @@ void SimController::UpdateSimulation(float dt) App::GetCacheSystem()->UnloadActorFromMemory(filename); // Force reload from filesystem ActorSpawnRequest srq; - srq.asr_position = reload_pos; - srq.asr_rotation = reload_dir; - srq.asr_config = asr_config; + srq.asr_position = reload_pos; + srq.asr_rotation = reload_dir; + srq.asr_config = asr_config; srq.asr_skin_entry = used_skin; - srq.asr_filename = filename; - Actor* new_actor = this->SpawnActorDirectly(srq); // try to load the same actor again + srq.asr_filename = filename; + Actor *new_actor = this->SpawnActorDirectly(srq); // try to load the same actor again if (new_actor) { this->SetPendingPlayerActor(new_actor); @@ -1644,7 +1457,7 @@ void SimController::UpdateSimulation(float dt) } m_actor_modify_queue.clear(); - for (ActorSpawnRequest& rq: m_actor_spawn_queue) + for (ActorSpawnRequest &rq : m_actor_spawn_queue) { if (rq.asr_origin == ActorSpawnRequest::Origin::USER) { @@ -1656,9 +1469,9 @@ void SimController::UpdateSimulation(float dt) { if (m_player_actor != nullptr) { - float h = m_player_actor->GetMaxHeight(true); - rq.asr_rotation = Quaternion(Degree(270) - Radian(m_player_actor->getRotation()), Vector3::UNIT_Y); - rq.asr_position = m_player_actor->GetRotationCenter(); + float h = m_player_actor->GetMaxHeight(true); + rq.asr_rotation = Quaternion(Degree(270) - Radian(m_player_actor->getRotation()), Vector3::UNIT_Y); + rq.asr_position = m_player_actor->GetRotationCenter(); rq.asr_position.y = gEnv->collisions->getSurfaceHeightBelow(rq.asr_position.x, rq.asr_position.z, h); rq.asr_position.y += m_player_actor->GetHeightAboveGroundBelow(h, true); // retain height above ground } @@ -1669,13 +1482,10 @@ void SimController::UpdateSimulation(float dt) } } - Actor* fresh_actor = this->SpawnActorDirectly(rq); + Actor *fresh_actor = this->SpawnActorDirectly(rq); if (fresh_actor != nullptr) { - if (fresh_actor->ar_driveable != NOT_DRIVEABLE) - { - this->SetPendingPlayerActor(fresh_actor); - } + if (fresh_actor->ar_driveable != NOT_DRIVEABLE) { this->SetPendingPlayerActor(fresh_actor); } if (rq.asr_spawnbox == nullptr) { // Try to resolve collisions with other actors @@ -1685,26 +1495,20 @@ void SimController::UpdateSimulation(float dt) } else if (rq.asr_origin == ActorSpawnRequest::Origin::CONFIG_FILE) { - Actor* fresh_actor = this->SpawnActorDirectly(rq); + Actor *fresh_actor = this->SpawnActorDirectly(rq); if (fresh_actor != nullptr) { - if (fresh_actor->ar_driveable != NOT_DRIVEABLE && - fresh_actor->ar_num_nodes > 0 && + if (fresh_actor->ar_driveable != NOT_DRIVEABLE && fresh_actor->ar_num_nodes > 0 && App::diag_preset_veh_enter.GetActive()) - { - this->SetPendingPlayerActor(fresh_actor); - } + { this->SetPendingPlayerActor(fresh_actor); } } } else if (rq.asr_origin == ActorSpawnRequest::Origin::TERRN_DEF) { - Actor* fresh_actor = this->SpawnActorDirectly(rq); + Actor *fresh_actor = this->SpawnActorDirectly(rq); if (fresh_actor != nullptr) { - if (rq.asr_terrn_machine) - { - fresh_actor->ar_driveable = MACHINE; - } + if (rq.asr_terrn_machine) { fresh_actor->ar_driveable = MACHINE; } String type = SurveyMapManager::getTypeByDriveable(fresh_actor->ar_driveable); App::GetSimController()->GetGfxScene().GetSurveyMap()->createMapEntity(type); @@ -1712,22 +1516,16 @@ void SimController::UpdateSimulation(float dt) } else { - Actor* fresh_actor = this->SpawnActorDirectly(rq); + Actor *fresh_actor = this->SpawnActorDirectly(rq); if (fresh_actor && fresh_actor->ar_driveable != NOT_DRIVEABLE && - rq.asr_origin != ActorSpawnRequest::Origin::NETWORK && - rq.asr_origin != ActorSpawnRequest::Origin::SAVEGAME) - { - this->SetPendingPlayerActor(fresh_actor); - } + rq.asr_origin != ActorSpawnRequest::Origin::NETWORK && rq.asr_origin != ActorSpawnRequest::Origin::SAVEGAME) + { this->SetPendingPlayerActor(fresh_actor); } } } m_actor_spawn_queue.clear(); - if (App::sim_load_savegame.GetActive()) - { - m_actor_manager.LoadScene(App::sim_savegame.GetActive()); - } + if (App::sim_load_savegame.GetActive()) { m_actor_manager.LoadScene(App::sim_savegame.GetActive()); } if (m_pending_player_actor != m_player_actor) { @@ -1738,10 +1536,7 @@ void SimController::UpdateSimulation(float dt) RoR::App::GetInputEngine()->Capture(); auto s = App::sim_state.GetActive(); - if (OutProtocol::getSingletonPtr()) - { - OutProtocol::getSingleton().Update(dt, m_player_actor); - } + if (OutProtocol::getSingletonPtr()) { OutProtocol::getSingleton().Update(dt, m_player_actor); } if (App::mp_state.GetActive() == MpState::CONNECTED) { @@ -1750,9 +1545,10 @@ void SimController::UpdateSimulation(float dt) // Update mumble (3d audio) #ifdef USE_MUMBLE // calculate orientation of avatar first - Ogre::Vector3 avatarDir = Ogre::Vector3(Math::Cos(gEnv->player->getRotation()), 0.0f, Math::Sin(gEnv->player->getRotation())); + Ogre::Vector3 avatarDir = + Ogre::Vector3(Math::Cos(gEnv->player->getRotation()), 0.0f, Math::Sin(gEnv->player->getRotation())); App::GetMumble()->update(gEnv->mainCamera->getPosition(), gEnv->mainCamera->getDirection(), gEnv->mainCamera->getUp(), - gEnv->player->getPosition() + Vector3(0, 1.8f, 0), avatarDir, Ogre::Vector3(0.0f, 1.0f, 0.0f)); + gEnv->player->getPosition() + Vector3(0, 1.8f, 0), avatarDir, Ogre::Vector3(0.0f, 1.0f, 0.0f)); #endif // USE_MUMBLE } @@ -1762,10 +1558,11 @@ void SimController::UpdateSimulation(float dt) #ifdef USE_OPENAL // update audio listener position static Vector3 lastCameraPosition; - Vector3 cameraSpeed = (gEnv->mainCamera->getPosition() - lastCameraPosition) / dt; - lastCameraPosition = gEnv->mainCamera->getPosition(); + Vector3 cameraSpeed = (gEnv->mainCamera->getPosition() - lastCameraPosition) / dt; + lastCameraPosition = gEnv->mainCamera->getPosition(); - SoundScriptManager::getSingleton().setCamera(gEnv->mainCamera->getPosition(), gEnv->mainCamera->getDirection(), gEnv->mainCamera->getUp(), cameraSpeed); + SoundScriptManager::getSingleton().setCamera(gEnv->mainCamera->getPosition(), gEnv->mainCamera->getDirection(), + gEnv->mainCamera->getUp(), cameraSpeed); #endif // USE_OPENAL } @@ -1803,31 +1600,34 @@ void SimController::UpdateSimulation(float dt) if (!simPAUSED(s) || (App::mp_state.GetActive() == MpState::CONNECTED)) { - m_actor_manager.UpdateActors(m_player_actor, m_physics_simulation_time); // *** Start new physics tasks. No reading from Actor N/B beyond this point. + m_actor_manager.UpdateActors( + m_player_actor, + m_physics_simulation_time); // *** Start new physics tasks. No reading from Actor N/B beyond this point. } } } -void SimController::ShowLoaderGUI(int type, const Ogre::String& instance, const Ogre::String& box) +void SimController::ShowLoaderGUI(int type, const Ogre::String &instance, const Ogre::String &box) { // first, test if the place if clear, BUT NOT IN MULTIPLAYER if (!(App::mp_state.GetActive() == MpState::CONNECTED)) { - collision_box_t* spawnbox = gEnv->collisions->getBox(instance, box); + collision_box_t *spawnbox = gEnv->collisions->getBox(instance, box); for (auto actor : GetActors()) { for (int i = 0; i < actor->ar_num_nodes; i++) { if (gEnv->collisions->isInside(actor->ar_nodes[i].AbsPosition, spawnbox)) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Please clear the place first"), "error.png"); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("Please clear the place first"), "error.png"); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Please clear the place first")); return; } } } } - + App::sim_state.SetActive(SimState::SELECTING); // TODO: use 'pending' mechanism ActorSpawnRequest rq; @@ -1837,10 +1637,9 @@ void SimController::ShowLoaderGUI(int type, const Ogre::String& instance, const App::GetGuiManager()->GetMainSelector()->Show(LoaderType(type), rq); } -void SimController::UpdateDirectionArrow(char* text, Vector3 position) +void SimController::UpdateDirectionArrow(char *text, Vector3 position) { - if (RoR::App::GetOverlayWrapper() == nullptr) - return; + if (RoR::App::GetOverlayWrapper() == nullptr) return; if (text == nullptr) { @@ -1855,53 +1654,48 @@ void SimController::UpdateDirectionArrow(char* text, Vector3 position) } /* --- Window Events ------------------------------------------ */ -void SimController::windowResized(Ogre::RenderWindow* rw) +void SimController::windowResized(Ogre::RenderWindow *rw) { - if (!rw) - return; + if (!rw) return; LOG("[RoR] Received 'window resized' notification"); - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->windowResized(); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->windowResized(); - m_gfx_scene.GetSurveyMap()->windowResized(); // TODO: we shouldn't update GfxScene-owned objects from simulation, we should queue the update ~ only_a_ptr, 05/2018 + m_gfx_scene.GetSurveyMap()->windowResized(); // TODO: we shouldn't update GfxScene-owned objects from simulation, we should + // queue the update ~ only_a_ptr, 05/2018 - //update mouse area + // update mouse area RoR::App::GetInputEngine()->windowResized(rw); m_actor_manager.NotifyActorsWindowResized(); } -void SimController::windowFocusChange(Ogre::RenderWindow* rw) +void SimController::windowFocusChange(Ogre::RenderWindow *rw) { RoR::App::GetInputEngine()->resetKeys(); } void SimController::HideGUI(bool hidden) { - if (m_player_actor && m_player_actor->getReplay()) - m_player_actor->getReplay()->setHidden(hidden); + if (m_player_actor && m_player_actor->getReplay()) m_player_actor->getReplay()->setHidden(hidden); #ifdef USE_SOCKETW - if (App::mp_state.GetActive() == MpState::CONNECTED) - App::GetGuiManager()->SetVisible_MpClientList(!hidden); + if (App::mp_state.GetActive() == MpState::CONNECTED) App::GetGuiManager()->SetVisible_MpClientList(!hidden); #endif // USE_SOCKETW - if (RoR::App::GetOverlayWrapper()) - RoR::App::GetOverlayWrapper()->showDashboardOverlays(!hidden, m_player_actor); + if (RoR::App::GetOverlayWrapper()) RoR::App::GetOverlayWrapper()->showDashboardOverlays(!hidden, m_player_actor); - m_gfx_scene.GetSurveyMap()->hideGUI(hidden); // TODO: we shouldn't update GfxScene-owned objects from simulation, but this whole HideGUI() function will likely end up being invoked by GfxActor in the future, so it's OK for now ~ only_a_ptr, 05/2018 + m_gfx_scene.GetSurveyMap()->hideGUI( + hidden); // TODO: we shouldn't update GfxScene-owned objects from simulation, but this whole HideGUI() function will + // likely end up being invoked by GfxActor in the future, so it's OK for now ~ only_a_ptr, 05/2018 App::GetGuiManager()->hideGUI(hidden); } -void SimController::RemoveActorByCollisionBox(std::string const & ev_src_instance_name, std::string const & box_name) +void SimController::RemoveActorByCollisionBox(std::string const &ev_src_instance_name, std::string const &box_name) { - Actor* actor = m_actor_manager.FindActorInsideBox(gEnv->collisions, ev_src_instance_name, box_name); - if (actor != nullptr) - { - this->QueueActorRemove(actor); - } + Actor *actor = m_actor_manager.FindActorInsideBox(gEnv->collisions, ev_src_instance_name, box_name); + if (actor != nullptr) { this->QueueActorRemove(actor); } } bool SimController::LoadTerrain() @@ -1924,10 +1718,10 @@ bool SimController::LoadTerrain() if (App::GetSimTerrain() != nullptr) { // remove old terrain - delete(App::GetSimTerrain()); // TODO: do it when leaving simulation. + delete (App::GetSimTerrain()); // TODO: do it when leaving simulation. } - TerrainManager* terrain = new TerrainManager(); + TerrainManager *terrain = new TerrainManager(); App::SetSimTerrain(terrain); // The terrain preparation logic relies on it. if (!terrain->LoadAndPrepareTerrain(terrain_file)) { @@ -1944,14 +1738,11 @@ bool SimController::LoadTerrain() if (gEnv->player != nullptr) { Vector3 spawn_pos = App::GetSimTerrain()->getSpawnPos(); - Real spawn_rot = 0.0f; + Real spawn_rot = 0.0f; // Classic behavior, retained for compatibility. // Required for maps like N-Labs or F1 Track. - if (!App::GetSimTerrain()->HasPredefinedActors()) - { - spawn_rot = 180.0f; - } + if (!App::GetSimTerrain()->HasPredefinedActors()) { spawn_rot = 180.0f; } if (!App::diag_preset_spawn_pos.IsActiveEmpty()) { @@ -1981,11 +1772,8 @@ bool SimController::LoadTerrain() // hide loading window App::GetGuiManager()->SetVisible_LoadingWindow(false); // hide wallpaper - MyGUI::Window* w = MyGUI::Gui::getInstance().findWidget("wallpaper"); - if (w != nullptr) - { - w->setVisibleSmooth(false); - } + MyGUI::Window *w = MyGUI::Gui::getInstance().findWidget("wallpaper"); + if (w != nullptr) { w->setVisibleSmooth(false); } return true; } @@ -1995,7 +1783,7 @@ void SimController::CleanupAfterSimulation() App::DestroyOverlayWrapper(); - //Unload all vehicules + // Unload all vehicules m_actor_manager.CleanUpAllActors(); delete gEnv->player; @@ -2005,7 +1793,7 @@ void SimController::CleanupAfterSimulation() if (App::GetSimTerrain() != nullptr) { // remove old terrain - delete(App::GetSimTerrain()); + delete (App::GetSimTerrain()); App::SetSimTerrain(nullptr); } @@ -2025,20 +1813,21 @@ bool SimController::SetupGameplayLoop() // Setup // ============================================================================ - int colourNum = -1; + int colourNum = -1; Ogre::UTFString playerName = ""; #ifdef USE_SOCKETW if (App::mp_state.GetActive() == MpState::CONNECTED) { - wchar_t tmp[255] = L""; - UTFString format = _L("Press %ls to start chatting"); - swprintf(tmp, 255, format.asWStr_c_str(), ANSI_TO_WCHAR(RoR::App::GetInputEngine()->getKeyForCommand(EV_COMMON_ENTER_CHATMODE)).c_str()); + wchar_t tmp[255] = L""; + UTFString format = _L("Press %ls to start chatting"); + swprintf(tmp, 255, format.asWStr_c_str(), + ANSI_TO_WCHAR(RoR::App::GetInputEngine()->getKeyForCommand(EV_COMMON_ENTER_CHATMODE)).c_str()); App::GetGuiManager()->pushMessageChatBox(UTFString(tmp)); RoRnet::UserInfo info = RoR::Networking::GetLocalUserData(); - colourNum = info.colournum; - playerName = tryConvertUTF(info.username); + colourNum = info.colournum; + playerName = tryConvertUTF(info.username); } #endif // USE_SOCKETW @@ -2051,22 +1840,18 @@ bool SimController::SetupGameplayLoop() // Loading map // ============================================================================ - if (!App::diag_preset_terrain.IsActiveEmpty()) - { - App::sim_terrain_name.SetPending(App::diag_preset_terrain.GetActive()); - } + if (!App::diag_preset_terrain.IsActiveEmpty()) { App::sim_terrain_name.SetPending(App::diag_preset_terrain.GetActive()); } // Terrain name lookup if (!App::sim_terrain_name.IsPendingEmpty()) { - size_t length = std::numeric_limits::max(); - const CacheEntry* lookup = nullptr; - String name = App::sim_terrain_name.GetPending(); + size_t length = std::numeric_limits::max(); + const CacheEntry *lookup = nullptr; + String name = App::sim_terrain_name.GetPending(); StringUtil::toLowerCase(name); - for (const auto& entry : App::GetCacheSystem()->GetEntries()) + for (const auto &entry : App::GetCacheSystem()->GetEntries()) { - if (entry.fext != "terrn2") - continue; + if (entry.fext != "terrn2") continue; String fname = entry.fname; StringUtil::toLowerCase(fname); if (fname.find(name) != std::string::npos) @@ -2083,10 +1868,7 @@ bool SimController::SetupGameplayLoop() } } } - if (lookup != nullptr) - { - App::sim_terrain_name.SetPending(lookup->fname.c_str()); - } + if (lookup != nullptr) { App::sim_terrain_name.SetPending(lookup->fname.c_str()); } } if (App::sim_load_savegame.GetActive()) @@ -2097,14 +1879,11 @@ bool SimController::SetupGameplayLoop() App::sim_savegame.SetActive(filename.c_str()); } m_actor_manager.LoadScene(App::sim_savegame.GetActive()); - } else if (App::sim_terrain_name.IsPendingEmpty()) + } + else if (App::sim_terrain_name.IsPendingEmpty()) { - CacheEntry* selected_map = RoR::App::GetGuiManager()->GetMainSelector()->GetSelectedEntry(); - if (selected_map != nullptr) - { - App::sim_terrain_name.SetPending(selected_map->fname.c_str()); - } - + CacheEntry *selected_map = RoR::App::GetGuiManager()->GetMainSelector()->GetSelectedEntry(); + if (selected_map != nullptr) { App::sim_terrain_name.SetPending(selected_map->fname.c_str()); } } if (App::sim_terrain_name.IsPendingEmpty()) { @@ -2115,7 +1894,7 @@ bool SimController::SetupGameplayLoop() App::diag_preset_terrain.SetActive(""); - if (! this->LoadTerrain()) + if (!this->LoadTerrain()) { LOG("Could not load map. Returning to menu."); App::GetMainMenu()->LeaveMultiplayerServer(); @@ -2130,17 +1909,16 @@ bool SimController::SetupGameplayLoop() if (!App::diag_preset_vehicle.IsActiveEmpty()) { // Vehicle name lookup - size_t length = std::numeric_limits::max(); - const CacheEntry* lookup = nullptr; - String name = App::diag_preset_vehicle.GetPending(); + size_t length = std::numeric_limits::max(); + const CacheEntry *lookup = nullptr; + String name = App::diag_preset_vehicle.GetPending(); StringUtil::toLowerCase(name); - for (const auto& entry : App::GetCacheSystem()->GetEntries()) + for (const auto &entry : App::GetCacheSystem()->GetEntries()) { - if (entry.fext == "terrn2") - continue; + if (entry.fext == "terrn2") continue; String fname = entry.fname; StringUtil::toLowerCase(fname); - if (fname.find(name) != std::string::npos) + if (fname.find(name) != std::string::npos) { if (fname == name) { @@ -2162,24 +1940,20 @@ bool SimController::SetupGameplayLoop() { auto cfgs = lookup->sectionconfigs; if (std::find(cfgs.begin(), cfgs.end(), App::diag_preset_veh_config.GetActive()) == cfgs.end()) - { - App::diag_preset_veh_config.SetActive(cfgs[0].c_str()); - } + { App::diag_preset_veh_config.SetActive(cfgs[0].c_str()); } } } RoR::LogFormat("[RoR|Diag] Preselected Truck: %s", App::diag_preset_vehicle.GetActive()); if (!App::diag_preset_veh_config.IsActiveEmpty()) - { - RoR::LogFormat("[RoR|Diag] Preselected Truck Config: %s", App::diag_preset_veh_config.GetActive()); - } + { RoR::LogFormat("[RoR|Diag] Preselected Truck Config: %s", App::diag_preset_veh_config.GetActive()); } ActorSpawnRequest rq; - rq.asr_filename = App::diag_preset_vehicle.GetActive(); - rq.asr_config = App::diag_preset_veh_config.GetActive(); - rq.asr_position = gEnv->player->getPosition(); - rq.asr_rotation = Quaternion(Degree(180) - gEnv->player->getRotation(), Vector3::UNIT_Y); - rq.asr_origin = ActorSpawnRequest::Origin::CONFIG_FILE; + rq.asr_filename = App::diag_preset_vehicle.GetActive(); + rq.asr_config = App::diag_preset_veh_config.GetActive(); + rq.asr_position = gEnv->player->getPosition(); + rq.asr_rotation = Quaternion(Degree(180) - gEnv->player->getRotation(), Vector3::UNIT_Y); + rq.asr_origin = ActorSpawnRequest::Origin::CONFIG_FILE; this->QueueActorSpawn(rq); } @@ -2187,18 +1961,12 @@ bool SimController::SetupGameplayLoop() // Extra setup // ======================================================================== - if (App::io_outgauge_mode.GetActive() > 0) - { - m_out_protocol = std::unique_ptr(new OutProtocol()); - } + if (App::io_outgauge_mode.GetActive() > 0) { m_out_protocol = std::unique_ptr(new OutProtocol()); } App::CreateOverlayWrapper(); App::GetOverlayWrapper()->SetupDirectionArrow(); - if (App::audio_menu_music.GetActive()) - { - SOUND_KILL(-1, SS_TRIG_MAIN_MENU); - } + if (App::audio_menu_music.GetActive()) { SOUND_KILL(-1, SS_TRIG_MAIN_MENU); } m_scene_mouse.InitializeVisuals(); // TODO: Move to GfxScene ~ only_a_ptr, 06/2018 @@ -2213,7 +1981,7 @@ void SimController::EnterGameplayLoop() { OgreBites::WindowEventUtilities::addWindowEventListener(App::GetOgreSubsystem()->GetRenderWindow(), this); - Ogre::RenderWindow* rw = RoR::App::GetOgreSubsystem()->GetRenderWindow(); + Ogre::RenderWindow *rw = RoR::App::GetOgreSubsystem()->GetRenderWindow(); auto start_time = std::chrono::high_resolution_clock::now(); @@ -2230,16 +1998,16 @@ void SimController::EnterGameplayLoop() if (App::gfx_fps_limit.GetActive() > 0) { const float min_frame_time = 1.0f / Ogre::Math::Clamp(App::gfx_fps_limit.GetActive(), 5, 240); - float dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); + float dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); while (dt < min_frame_time) { dt = std::chrono::duration(std::chrono::high_resolution_clock::now() - start_time).count(); } } - const auto now = std::chrono::high_resolution_clock::now(); + const auto now = std::chrono::high_resolution_clock::now(); const float dt_sec = std::chrono::duration(now - start_time).count(); - start_time = now; + start_time = now; // Check simulation state change if (App::sim_state.GetPending() != App::sim_state.GetActive()) @@ -2271,24 +2039,19 @@ void SimController::EnterGameplayLoop() if (RoR::App::sim_state.GetActive() != RoR::SimState::PAUSED) { m_gfx_scene.UpdateScene(dt_sec); - if (!m_physics_simulation_paused) - { - m_time += dt_sec; - } + if (!m_physics_simulation_paused) { m_time += dt_sec; } } } - // TODO: Ugly! Currently it seems drawing DearIMGUI only works when invoked from `Ogre::FrameListener::frameRenderingQueued`. + // TODO: Ugly! Currently it seems drawing DearIMGUI only works when invoked from + // `Ogre::FrameListener::frameRenderingQueued`. // We only want GUI on screen, not other targets (reflections etc...), so we can't have it attached permanently. // Research and find a more elegant solution. ~ only_a_ptr, 07/2018 RoR::App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(&App::GetGuiManager()->GetImGui()); RoR::App::GetOgreSubsystem()->GetOgreRoot()->renderOneFrame(); RoR::App::GetOgreSubsystem()->GetOgreRoot()->removeFrameListener(&App::GetGuiManager()->GetImGui()); - if (m_stats_on && RoR::App::GetOverlayWrapper()) - { - RoR::App::GetOverlayWrapper()->updateStats(); - } + if (m_stats_on && RoR::App::GetOverlayWrapper()) { RoR::App::GetOverlayWrapper()->updateStats(); } #ifdef USE_SOCKETW if ((App::mp_state.GetActive() == MpState::CONNECTED)) @@ -2300,14 +2063,13 @@ void SimController::EnterGameplayLoop() { case Networking::NetEvent::Type::SERVER_KICK: App::app_state.SetPending(AppState::MAIN_MENU); // Will perform `Networking::Disconnect()` - App::GetGuiManager()->ShowMessageBox( - _LC("Network", "Multiplayer: disconnected"), events.front().message.c_str()); + App::GetGuiManager()->ShowMessageBox(_LC("Network", "Multiplayer: disconnected"), + events.front().message.c_str()); break; case Networking::NetEvent::Type::RECV_ERROR: App::app_state.SetPending(AppState::MAIN_MENU); // Will perform `Networking::Disconnect()` - App::GetGuiManager()->ShowMessageBox( - _L("Network fatal error: "), events.front().message.c_str()); + App::GetGuiManager()->ShowMessageBox(_L("Network fatal error: "), events.front().message.c_str()); break; default:; @@ -2332,29 +2094,20 @@ void SimController::EnterGameplayLoop() OgreBites::WindowEventUtilities::removeWindowEventListener(App::GetOgreSubsystem()->GetRenderWindow(), this); } -void SimController::ChangePlayerActor(Actor* actor) +void SimController::ChangePlayerActor(Actor *actor) { - Actor* prev_player_actor = m_player_actor; - m_player_actor = actor; - m_pending_player_actor = actor; // Stays equal to 'player actor' until new change is queued + Actor *prev_player_actor = m_player_actor; + m_player_actor = actor; + m_pending_player_actor = actor; // Stays equal to 'player actor' until new change is queued // hide any old dashes - if (prev_player_actor && prev_player_actor->ar_dashboard) - { - prev_player_actor->ar_dashboard->setVisible3d(false); - } + if (prev_player_actor && prev_player_actor->ar_dashboard) { prev_player_actor->ar_dashboard->setVisible3d(false); } // show new - if (m_player_actor && m_player_actor->ar_dashboard) - { - m_player_actor->ar_dashboard->setVisible3d(true); - } + if (m_player_actor && m_player_actor->ar_dashboard) { m_player_actor->ar_dashboard->setVisible3d(true); } if (prev_player_actor) { - if (RoR::App::GetOverlayWrapper()) - { - RoR::App::GetOverlayWrapper()->showDashboardOverlays(false, prev_player_actor); - } + if (RoR::App::GetOverlayWrapper()) { RoR::App::GetOverlayWrapper()->showDashboardOverlays(false, prev_player_actor); } prev_player_actor->GetGfxActor()->SetRenderdashActive(false); @@ -2369,24 +2122,22 @@ void SimController::ChangePlayerActor(Actor* actor) if (prev_player_actor) { if (prev_player_actor->GetGfxActor()->GetVideoCamState() == GfxActor::VideoCamState::VCSTATE_ENABLED_ONLINE) - { - prev_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_ENABLED_OFFLINE); - } + { prev_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_ENABLED_OFFLINE); } prev_player_actor->prepareInside(false); // get player out of the vehicle - float h = prev_player_actor->getMinCameraRadius(); - float rotation = prev_player_actor->getRotation() - Math::HALF_PI; + float h = prev_player_actor->getMinCameraRadius(); + float rotation = prev_player_actor->getRotation() - Math::HALF_PI; Vector3 position = prev_player_actor->getPosition(); if (prev_player_actor->ar_cinecam_node[0] != -1) { // actor has a cinecam (find optimal exit position) - Vector3 l = position - 2.0f * prev_player_actor->GetCameraRoll(); - Vector3 r = position + 2.0f * prev_player_actor->GetCameraRoll(); - float l_h = gEnv->collisions->getSurfaceHeightBelow(l.x, l.z, l.y + h); - float r_h = gEnv->collisions->getSurfaceHeightBelow(r.x, r.z, r.y + h); - position = std::abs(r.y - r_h) * 1.2f < std::abs(l.y - l_h) ? r : l; + Vector3 l = position - 2.0f * prev_player_actor->GetCameraRoll(); + Vector3 r = position + 2.0f * prev_player_actor->GetCameraRoll(); + float l_h = gEnv->collisions->getSurfaceHeightBelow(l.x, l.z, l.y + h); + float r_h = gEnv->collisions->getSurfaceHeightBelow(r.x, r.z, r.y + h); + position = std::abs(r.y - r_h) * 1.2f < std::abs(l.y - l_h) ? r : l; } position.y = gEnv->collisions->getSurfaceHeightBelow(position.x, position.z, position.y + h); @@ -2400,31 +2151,24 @@ void SimController::ChangePlayerActor(Actor* actor) m_force_feedback->SetEnabled(false); - TRIGGER_EVENT(SE_TRUCK_EXIT, prev_player_actor?prev_player_actor->ar_instance_id:-1); + TRIGGER_EVENT(SE_TRUCK_EXIT, prev_player_actor ? prev_player_actor->ar_instance_id : -1); } else { // getting inside if (RoR::App::GetOverlayWrapper() != nullptr) - { - RoR::App::GetOverlayWrapper()->showDashboardOverlays(!m_hide_gui, m_player_actor); - } + { RoR::App::GetOverlayWrapper()->showDashboardOverlays(!m_hide_gui, m_player_actor); } if (m_player_actor->GetGfxActor()->GetVideoCamState() == GfxActor::VideoCamState::VCSTATE_ENABLED_OFFLINE) - { - m_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_ENABLED_ONLINE); - } + { m_player_actor->GetGfxActor()->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_ENABLED_ONLINE); } m_player_actor->GetGfxActor()->SetRenderdashActive(true); // force feedback - m_force_feedback->SetEnabled(m_player_actor->ar_driveable == TRUCK); //only for trucks so far + m_force_feedback->SetEnabled(m_player_actor->ar_driveable == TRUCK); // only for trucks so far // attach player to vehicle - if (gEnv->player) - { - gEnv->player->SetActorCoupling(true, m_player_actor); - } + if (gEnv->player) { gEnv->player->SetActorCoupling(true, m_player_actor); } if (RoR::App::GetOverlayWrapper()) { @@ -2432,19 +2176,22 @@ void SimController::ChangePlayerActor(Actor* actor) { if (!m_player_actor->ar_help_panel_material.empty()) { - OverlayManager::getSingleton().getOverlayElement("tracks/machinehelppanel")->setMaterialName(m_player_actor->ar_help_panel_material); + OverlayManager::getSingleton() + .getOverlayElement("tracks/machinehelppanel") + ->setMaterialName(m_player_actor->ar_help_panel_material); } else { OverlayManager::getSingleton().getOverlayElement("tracks/machinehelppanel")->setMaterialName("tracks/black"); } } - catch (Ogre::Exception& ex) + catch (Ogre::Exception &ex) { // Report the error std::stringstream msg; msg << "Error, help panel material (defined in 'help' or 'guisettings/helpMaterial') could not be loaded.\n" - "Exception occured, file:" << __FILE__ << ", line:" << __LINE__ << ", message:" << ex.what(); + "Exception occured, file:" + << __FILE__ << ", line:" << __LINE__ << ", message:" << ex.what(); LOG(msg.str()); // Do not retry @@ -2452,13 +2199,11 @@ void SimController::ChangePlayerActor(Actor* actor) } } - TRIGGER_EVENT(SE_TRUCK_ENTER, m_player_actor?m_player_actor->ar_instance_id:-1); + TRIGGER_EVENT(SE_TRUCK_ENTER, m_player_actor ? m_player_actor->ar_instance_id : -1); } if (prev_player_actor != nullptr || m_player_actor != nullptr) - { - m_camera_manager.NotifyVehicleChanged(prev_player_actor, m_player_actor); - } + { m_camera_manager.NotifyVehicleChanged(prev_player_actor, m_player_actor); } m_actor_manager.UpdateSleepingState(m_player_actor, 0.f); } @@ -2466,8 +2211,7 @@ void SimController::ChangePlayerActor(Actor* actor) bool SimController::AreControlsLocked() const { // TODO: remove camera manager from gEnv, see == SimCam == comment in CameraManager.cpp ~ only_a_ptr - return (m_camera_manager.IsCameraReady() - && m_camera_manager.gameControlsLocked()); + return (m_camera_manager.IsCameraReady() && m_camera_manager.gameControlsLocked()); } void SimController::ResetCamera() @@ -2483,15 +2227,12 @@ void SimController::ResetCamera() CameraManager::CameraBehaviors SimController::GetCameraBehavior() { - if (m_camera_manager.IsCameraReady()) - { - return m_camera_manager.GetCurrentBehavior(); - } + if (m_camera_manager.IsCameraReady()) { return m_camera_manager.GetCurrentBehavior(); } return CameraManager::CAMERA_BEHAVIOR_INVALID; } // Temporary interface until camera controls are refactored; see == SimCam == ~ only_a_ptr, 06/2018 -bool SimController::CameraManagerMouseMoved(const OIS::MouseEvent& _arg) +bool SimController::CameraManagerMouseMoved(const OIS::MouseEvent &_arg) { if (!m_camera_manager.IsCameraReady()) { @@ -2501,12 +2242,9 @@ bool SimController::CameraManagerMouseMoved(const OIS::MouseEvent& _arg) } // Temporary interface until camera controls are refactored; see == SimCam == ~ only_a_ptr, 06/2018 -void SimController::CameraManagerMousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +void SimController::CameraManagerMousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { - if (m_camera_manager.IsCameraReady()) - { - m_camera_manager.mousePressed(_arg, _id); - } + if (m_camera_manager.IsCameraReady()) { m_camera_manager.mousePressed(_arg, _id); } } void SimController::SetTerrainEditorMouseRay(Ray ray) @@ -2514,17 +2252,14 @@ void SimController::SetTerrainEditorMouseRay(Ray ray) m_terrain_editor_mouse_ray = ray; } -Actor* SimController::SpawnActorDirectly(RoR::ActorSpawnRequest rq) +Actor *SimController::SpawnActorDirectly(RoR::ActorSpawnRequest rq) { LOG(" ===== LOADING VEHICLE: " + rq.asr_filename); - if (rq.asr_cache_entry != nullptr) - { - rq.asr_filename = rq.asr_cache_entry->fname; - } + if (rq.asr_cache_entry != nullptr) { rq.asr_filename = rq.asr_cache_entry->fname; } - std::shared_ptr def = m_actor_manager.FetchActorDef( - rq.asr_filename, rq.asr_origin == ActorSpawnRequest::Origin::TERRN_DEF); + std::shared_ptr def = + m_actor_manager.FetchActorDef(rq.asr_filename, rq.asr_origin == ActorSpawnRequest::Origin::TERRN_DEF); if (def == nullptr) { return nullptr; // Error already reported @@ -2545,34 +2280,27 @@ Actor* SimController::SpawnActorDirectly(RoR::ActorSpawnRequest rq) if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { RoRnet::UserInfo info = RoR::Networking::GetLocalUserData(); - rq.asr_net_username = tryConvertUTF(info.username); - rq.asr_net_color = info.colournum; + rq.asr_net_username = tryConvertUTF(info.username); + rq.asr_net_color = info.colournum; } } -#endif //SOCKETW +#endif // SOCKETW - Actor* actor = m_actor_manager.CreateActorInstance(rq, def); + Actor *actor = m_actor_manager.CreateActorInstance(rq, def); // lock slide nodes after spawning the actor? - if (def->slide_nodes_connect_instantly) - { - actor->ToggleSlideNodeLock(); - } + if (def->slide_nodes_connect_instantly) { actor->ToggleSlideNodeLock(); } return actor; } -void SimController::RemoveActorDirectly(Actor* actor) +void SimController::RemoveActorDirectly(Actor *actor) { m_gfx_scene.RemoveGfxActor(actor->GetGfxActor()); #ifdef USE_SOCKETW - if (App::mp_state.GetActive() == MpState::CONNECTED) - { - m_character_factory.UndoRemoteActorCoupling(actor); - } -#endif //SOCKETW + if (App::mp_state.GetActive() == MpState::CONNECTED) { m_character_factory.UndoRemoteActorCoupling(actor); } +#endif // SOCKETW m_actor_manager.DeleteActorInternal(actor); } - diff --git a/source/main/gameplay/RoRFrameListener.h b/source/main/gameplay/RoRFrameListener.h index 2b43e9f1d2..a317b447ab 100644 --- a/source/main/gameplay/RoRFrameListener.h +++ b/source/main/gameplay/RoRFrameListener.h @@ -21,15 +21,14 @@ #pragma once -#include "RoRPrerequisites.h" - #include "BeamData.h" // RoR::ActorSpawnRequest #include "BeamFactory.h" #include "CameraManager.h" // CameraManager::CameraBehaviors #include "CharacterFactory.h" -#include "GfxScene.h" #include "ForceFeedback.h" +#include "GfxScene.h" #include "OutProtocol.h" +#include "RoRPrerequisites.h" #include "SceneMouse.h" /// The simulation controller object @@ -37,7 +36,8 @@ /// /// RoR's gameplay is quite simple in structure, it consists of: /// - static terrain: static elevation map, managed by `TerrainManager` singleton. -/// this includes static collision objects (or intrusion detection objects), managed by `TerrainObjectManager`. +/// this includes static collision objects (or intrusion detection objects), managed by +/// `TerrainObjectManager`. /// - softbody actors: a.k.a "trucks" or "vehicles", managed by `ActorManager`. They collide with static terrain and each other. /// this includes 'fixes' - actors with partially fixed position. /// - characters: player-controlled human figures with their own primitive physics, managed by `CharacterFactory` @@ -45,7 +45,8 @@ /// For convenience and to help manage interactions, this class provides methods to manipulate these elements. /// /// Architecture is currently undergoing a refactor. -/// OLD: We use threadpool; rendering loop runs on main thread, simulation is updated in between frames via 'Ogre::FrameListener' interface which also provides timing. +/// OLD: We use threadpool; rendering loop runs on main thread, simulation is updated in between frames via 'Ogre::FrameListener' +/// interface which also provides timing. /// 1. SimController::EnterGameplayLoop() invokes Ogre::Root::renderOneFrame() which invokes SimController::frameStarted() /// 2. Wait for simulation task to finish. /// 3. Gather user inputs; send/receive network data @@ -58,135 +59,222 @@ /// 2. Check time since last render; if necessary, copy sim. data and put an "update scene and render" task to threadpool. /// 2. Gather user inputs; send/receive network data /// 3. Update simulation -class SimController: public Ogre::WindowEventListener, public ZeroedMemoryAllocator +class SimController : public Ogre::WindowEventListener, public ZeroedMemoryAllocator { -public: - SimController(RoR::ForceFeedback* ff, RoR::SkidmarkConfig* skid_conf); + public: + SimController(RoR::ForceFeedback *ff, RoR::SkidmarkConfig *skid_conf); // Actor management interface - std::vector GetActors() const { return m_actor_manager.GetActors(); } - std::vector GetLocalActors() { return m_actor_manager.GetLocalActors(); } - Actor* GetActorById (int actor_id) { return m_actor_manager.GetActorByIdInternal(actor_id); } - std::pair GetNearestActor(Ogre::Vector3 position) { return m_actor_manager.GetNearestActor(position); }; - void ChangePlayerActor (Actor* actor); - void QueueActorSpawn (RoR::ActorSpawnRequest const & rq) { m_actor_spawn_queue.push_back(rq); } - void QueueActorModify (RoR::ActorModifyRequest const & rq) { m_actor_modify_queue.push_back(rq); } - void QueueActorRemove (Actor* actor) { m_actor_remove_queue.push_back(actor); } - Actor* SpawnActorDirectly (RoR::ActorSpawnRequest rq); - void RemoveActorDirectly (Actor* actor); - void RemoveActorByCollisionBox(std::string const & ev_src_instance_name, std::string const & box_name); ///< Scripting utility. TODO: Does anybody use it? ~ only_a_ptr, 08/2017 + std::vector GetActors() const + { + return m_actor_manager.GetActors(); + } + std::vector GetLocalActors() + { + return m_actor_manager.GetLocalActors(); + } + Actor *GetActorById(int actor_id) + { + return m_actor_manager.GetActorByIdInternal(actor_id); + } + std::pair GetNearestActor(Ogre::Vector3 position) + { + return m_actor_manager.GetNearestActor(position); + }; + void ChangePlayerActor(Actor *actor); + void QueueActorSpawn(RoR::ActorSpawnRequest const &rq) + { + m_actor_spawn_queue.push_back(rq); + } + void QueueActorModify(RoR::ActorModifyRequest const &rq) + { + m_actor_modify_queue.push_back(rq); + } + void QueueActorRemove(Actor *actor) + { + m_actor_remove_queue.push_back(actor); + } + Actor *SpawnActorDirectly(RoR::ActorSpawnRequest rq); + void RemoveActorDirectly(Actor *actor); + void RemoveActorByCollisionBox( + std::string const &ev_src_instance_name, + std::string const &box_name); ///< Scripting utility. TODO: Does anybody use it? ~ only_a_ptr, 08/2017 // Scripting interface - float getTime () { return m_time; } - void UpdateDirectionArrow (char* text, Ogre::Vector3 position); - void ShowLoaderGUI (int type, const Ogre::String& instance, const Ogre::String& box); - void StartRaceTimer (int id); // Do not call manually! - void StopRaceTimer (); // Do not call manually! - void SetRaceTimeDiff (float diff) { m_race_time_diff = diff; }; // Do not call manually! - float GetRaceTimeDiff () const { return m_race_time_diff; }; - void SetRaceBestTime (float time) { m_race_best_time = time; }; // Do not call manually! - float GetRaceBestTime () const { return m_race_best_time; }; - int GetRaceId () const { return m_race_id; } - float GetRaceTime () const { return static_cast(m_time - m_race_start_time); } - bool IsRaceInProgress () const { return m_race_id != -1; } - bool LoadTerrain (); ///< Reads GVar 'sim_terrain_pending' + float getTime() + { + return m_time; + } + void UpdateDirectionArrow(char *text, Ogre::Vector3 position); + void ShowLoaderGUI(int type, const Ogre::String &instance, const Ogre::String &box); + void StartRaceTimer(int id); // Do not call manually! + void StopRaceTimer(); // Do not call manually! + void SetRaceTimeDiff(float diff) + { + m_race_time_diff = diff; + }; // Do not call manually! + float GetRaceTimeDiff() const + { + return m_race_time_diff; + }; + void SetRaceBestTime(float time) + { + m_race_best_time = time; + }; // Do not call manually! + float GetRaceBestTime() const + { + return m_race_best_time; + }; + int GetRaceId() const + { + return m_race_id; + } + float GetRaceTime() const + { + return static_cast(m_time - m_race_start_time); + } + bool IsRaceInProgress() const + { + return m_race_id != -1; + } + bool LoadTerrain(); ///< Reads GVar 'sim_terrain_pending' // GUI interface - void TeleportPlayerXZ (float x, float y); // Teleport UI + void TeleportPlayerXZ(float x, float y); // Teleport UI /// @return True if everything was prepared OK and simulation may start. - bool SetupGameplayLoop (); - void EnterGameplayLoop (); - - // Temporary interface until camera controls are refactored; only for use by SceneMouse; see == SimCam == ~ only_a_ptr, 06/2018 - void CameraManagerMousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - bool CameraManagerMouseMoved(const OIS::MouseEvent& _arg); - - RoR::ActorManager* GetBeamFactory () { return &m_actor_manager; } // TODO: Eliminate this. All operations upon actors should be done through above methods. ~ only_a_ptr, 06/2017 - RoR::SkidmarkConfig* GetSkidmarkConf () { return m_skidmark_conf; } - RoR::GfxScene& GetGfxScene() { return m_gfx_scene; } - RoR::SceneMouse& GetSceneMouse() { return m_scene_mouse; } - Ogre::Vector3 GetDirArrowTarget() { return m_dir_arrow_pointed; } - bool IsPressurizingTyres() const { return m_pressure_pressed; } - bool AreControlsLocked() const; - bool IsGUIHidden() { return m_hide_gui; } - void ResetCamera(); + bool SetupGameplayLoop(); + void EnterGameplayLoop(); + + // Temporary interface until camera controls are refactored; only for use by SceneMouse; see == SimCam == ~ only_a_ptr, + // 06/2018 + void CameraManagerMousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + bool CameraManagerMouseMoved(const OIS::MouseEvent &_arg); + + RoR::ActorManager *GetBeamFactory() + { + return &m_actor_manager; + } // TODO: Eliminate this. All operations upon actors should be done through above methods. ~ only_a_ptr, 06/2017 + RoR::SkidmarkConfig *GetSkidmarkConf() + { + return m_skidmark_conf; + } + RoR::GfxScene &GetGfxScene() + { + return m_gfx_scene; + } + RoR::SceneMouse &GetSceneMouse() + { + return m_scene_mouse; + } + Ogre::Vector3 GetDirArrowTarget() + { + return m_dir_arrow_pointed; + } + bool IsPressurizingTyres() const + { + return m_pressure_pressed; + } + bool AreControlsLocked() const; + bool IsGUIHidden() + { + return m_hide_gui; + } + void ResetCamera(); RoR::CameraManager::CameraBehaviors GetCameraBehavior(); - Actor* GetPlayerActor() { return m_player_actor; }; - Actor* GetPrevPlayerActor() { return m_prev_player_actor; }; - - void SetPendingPlayerActor(Actor* actor) { m_pending_player_actor = actor; }; - void SetPrevPlayerActorInternal(Actor* actor) { m_prev_player_actor = actor; }; - - bool GetPhysicsPaused() { return m_physics_simulation_paused; }; - void SetPhysicsPausedInternal(bool paused) { m_physics_simulation_paused = paused; }; + Actor *GetPlayerActor() + { + return m_player_actor; + }; + Actor *GetPrevPlayerActor() + { + return m_prev_player_actor; + }; + + void SetPendingPlayerActor(Actor *actor) + { + m_pending_player_actor = actor; + }; + void SetPrevPlayerActorInternal(Actor *actor) + { + m_prev_player_actor = actor; + }; + + bool GetPhysicsPaused() + { + return m_physics_simulation_paused; + }; + void SetPhysicsPausedInternal(bool paused) + { + m_physics_simulation_paused = paused; + }; void SetTerrainEditorMouseRay(Ogre::Ray ray); -private: - + private: // Ogre::WindowEventListener interface - void windowFocusChange (Ogre::RenderWindow* rw); - void windowResized (Ogre::RenderWindow* rw); - - void UpdateForceFeedback (); - void HandleSavegameShortcuts (); - void UpdateInputEvents (float dt); - void HideGUI (bool hidden); - void CleanupAfterSimulation (); /// Unloads all data - void UpdateSimulation (float dt); - - Actor* m_player_actor; //!< Actor (vehicle or machine) mounted and controlled by player - Actor* m_prev_player_actor; //!< Previous actor (vehicle or machine) mounted and controlled by player - Actor* m_pending_player_actor; //!< Actor scheduled to be seated by player (when none scheduled, equals `player_actor`) - RoR::ActorManager m_actor_manager; + void windowFocusChange(Ogre::RenderWindow *rw); + void windowResized(Ogre::RenderWindow *rw); + + void UpdateForceFeedback(); + void HandleSavegameShortcuts(); + void UpdateInputEvents(float dt); + void HideGUI(bool hidden); + void CleanupAfterSimulation(); /// Unloads all data + void UpdateSimulation(float dt); + + Actor *m_player_actor; //!< Actor (vehicle or machine) mounted and controlled by player + Actor *m_prev_player_actor; //!< Previous actor (vehicle or machine) mounted and controlled by player + Actor *m_pending_player_actor; //!< Actor scheduled to be seated by player (when none scheduled, equals `player_actor`) + RoR::ActorManager m_actor_manager; std::vector m_actor_spawn_queue; std::vector m_actor_modify_queue; - std::vector m_actor_remove_queue; - RoR::CharacterFactory m_character_factory; - RoR::GfxScene m_gfx_scene; - RoR::SkidmarkConfig* m_skidmark_conf; - RoR::SceneMouse m_scene_mouse; - RoR::CameraManager m_camera_manager; - Ogre::Real m_time_until_next_toggle; //!< just to stop toggles flipping too fast - float m_last_simulation_speed; //!< previously used time ratio between real time (evt.timeSinceLastFrame) and physics time ('dt' used in calcPhysics) - bool m_is_pace_reset_pressed; - float m_physics_simulation_time; //!< Amount of time the physics simulation is going to be advanced - bool m_physics_simulation_paused; - int m_stats_on; - float m_time; - RoR::ForceFeedback* m_force_feedback; - bool m_hide_gui; - bool m_actor_info_gui_visible; - bool m_pressure_pressed; - - CacheEntry* m_last_cache_selection; //!< Vehicle/load - CacheEntry* m_last_skin_selection; - Ogre::String m_last_section_config; - - Ogre::Vector3 m_dir_arrow_pointed; - - int m_last_screenshot_id; - Ogre::String m_last_screenshot_date; - - int m_race_id; - float m_race_time_diff; - float m_race_best_time; - float m_race_start_time; - - bool m_soft_reset_mode; - bool m_advanced_vehicle_repair; - float m_advanced_vehicle_repair_timer; - - float m_pressure_pressed_timer; - - bool m_screenshot_request; - - Ogre::Vector3 m_reload_pos; - Ogre::Quaternion m_reload_dir; - - Ogre::Ray m_terrain_editor_mouse_ray; + std::vector m_actor_remove_queue; + RoR::CharacterFactory m_character_factory; + RoR::GfxScene m_gfx_scene; + RoR::SkidmarkConfig * m_skidmark_conf; + RoR::SceneMouse m_scene_mouse; + RoR::CameraManager m_camera_manager; + Ogre::Real m_time_until_next_toggle; //!< just to stop toggles flipping too fast + float m_last_simulation_speed; //!< previously used time ratio between real time (evt.timeSinceLastFrame) and physics time + //!< ('dt' used in calcPhysics) + bool m_is_pace_reset_pressed; + float m_physics_simulation_time; //!< Amount of time the physics simulation is going to be advanced + bool m_physics_simulation_paused; + int m_stats_on; + float m_time; + RoR::ForceFeedback *m_force_feedback; + bool m_hide_gui; + bool m_actor_info_gui_visible; + bool m_pressure_pressed; + + CacheEntry * m_last_cache_selection; //!< Vehicle/load + CacheEntry * m_last_skin_selection; + Ogre::String m_last_section_config; + + Ogre::Vector3 m_dir_arrow_pointed; + + int m_last_screenshot_id; + Ogre::String m_last_screenshot_date; + + int m_race_id; + float m_race_time_diff; + float m_race_best_time; + float m_race_start_time; + + bool m_soft_reset_mode; + bool m_advanced_vehicle_repair; + float m_advanced_vehicle_repair_timer; + + float m_pressure_pressed_timer; + + bool m_screenshot_request; + + Ogre::Vector3 m_reload_pos; + Ogre::Quaternion m_reload_dir; + + Ogre::Ray m_terrain_editor_mouse_ray; std::unique_ptr m_out_protocol; }; diff --git a/source/main/gameplay/Road.cpp b/source/main/gameplay/Road.cpp index 0a21e27551..ec06011860 100644 --- a/source/main/gameplay/Road.cpp +++ b/source/main/gameplay/Road.cpp @@ -24,13 +24,7 @@ using namespace Ogre; -Road::Road(Vector3 start) : - cur_rtype(0) - , free_rtype(0) - , lastpturn(0) - , ppitch(0) - , ppos(start) - , pturn(0) +Road::Road(Vector3 start) : cur_rtype(0), free_rtype(0), lastpturn(0), ppitch(0), ppos(start), pturn(0) { addRoadType("Road"); addRoadType("RoadBorderLeft"); @@ -45,10 +39,10 @@ Road::Road(Vector3 start) : void Road::preparePending() { - //setup rotation points + // setup rotation points lastpturn = pturn; - protl = ppos + Quaternion(Degree(pturn), Vector3::UNIT_Y) * Vector3(0, 0, 4.5); - protr = ppos + Quaternion(Degree(pturn), Vector3::UNIT_Y) * Vector3(0, 0, -4.5); + protl = ppos + Quaternion(Degree(pturn), Vector3::UNIT_Y) * Vector3(0, 0, 4.5); + protr = ppos + Quaternion(Degree(pturn), Vector3::UNIT_Y) * Vector3(0, 0, -4.5); tenode->setPosition(ppos); tenode->setOrientation(Quaternion(Degree(pturn), Vector3::UNIT_Y) * Quaternion(Degree(ppitch), Vector3::UNIT_Z)); tenode->pitch(Degree(-90)); @@ -57,9 +51,7 @@ void Road::preparePending() void Road::updatePending() { if (pturn - lastpturn > 0) - { - tenode->setPosition(Quaternion(Degree(pturn - lastpturn), Vector3::UNIT_Y) * (ppos - protl) + protl); - } + { tenode->setPosition(Quaternion(Degree(pturn - lastpturn), Vector3::UNIT_Y) * (ppos - protl) + protl); } else { if (pturn - lastpturn < 0) @@ -75,21 +67,21 @@ void Road::reset(Vector3 start) { cur_rtype = 0; lastpturn = 0; - ppitch = 0; - ppos = start; - pturn = 0; + ppitch = 0; + ppos = start; + pturn = 0; strcpy(curtype, rtypes[cur_rtype].name); tenode = rtypes[cur_rtype].node; tenode->setVisible(true); preparePending(); } -void Road::addRoadType(const char* name) +void Road::addRoadType(const char *name) { // create visuals - String entity_name = String("RoadPreview-").append(name); - String mesh_name = String(name).append(".mesh"); - Entity* te = gEnv->sceneManager->createEntity(entity_name, mesh_name); + String entity_name = String("RoadPreview-").append(name); + String mesh_name = String(name).append(".mesh"); + Entity *te = gEnv->sceneManager->createEntity(entity_name, mesh_name); te->setCastShadows(false); @@ -106,12 +98,9 @@ void Road::addRoadType(const char* name) void Road::toggleType() { Quaternion rot = tenode->getOrientation(); - Vector3 pos = tenode->getPosition(); + Vector3 pos = tenode->getPosition(); cur_rtype++; - if (cur_rtype >= free_rtype || cur_rtype >= MAX_RTYPES) - { - cur_rtype = 0; - } + if (cur_rtype >= free_rtype || cur_rtype >= MAX_RTYPES) { cur_rtype = 0; } strcpy(curtype, rtypes[cur_rtype].name); tenode->setVisible(false); tenode = rtypes[cur_rtype].node; @@ -136,10 +125,7 @@ void Road::append() { // register pending and set collision boxes // first, calculate the real position - if (pturn - lastpturn > 0) - { - rpos = Quaternion(Degree(pturn - lastpturn), Vector3::UNIT_Y) * (ppos - protl) + protl; - } + if (pturn - lastpturn > 0) { rpos = Quaternion(Degree(pturn - lastpturn), Vector3::UNIT_Y) * (ppos - protl) + protl; } else { if (pturn - lastpturn < 0) diff --git a/source/main/gameplay/Road.h b/source/main/gameplay/Road.h index 70e5c2d33b..3b61b55f6b 100644 --- a/source/main/gameplay/Road.h +++ b/source/main/gameplay/Road.h @@ -24,21 +24,19 @@ struct RoadType_t { - char name[256]; - Ogre::SceneNode* node; + char name[256]; + Ogre::SceneNode *node; }; class Road : public ZeroedMemoryAllocator { friend class SimController; -public: - + public: Road(Ogre::Vector3 start); -private: - - void addRoadType(const char* name); + private: + void addRoadType(const char *name); void append(); void dpitch(float v); void dturn(float v); @@ -48,9 +46,9 @@ class Road : public ZeroedMemoryAllocator void updatePending(); static const unsigned int MAX_RTYPES = 10; - RoadType_t rtypes[MAX_RTYPES]; + RoadType_t rtypes[MAX_RTYPES]; - Ogre::SceneNode* tenode; + Ogre::SceneNode *tenode; Ogre::Vector3 ppos; Ogre::Vector3 protl; diff --git a/source/main/gameplay/Road2.cpp b/source/main/gameplay/Road2.cpp index b5871e74ba..7c7b39e081 100644 --- a/source/main/gameplay/Road2.cpp +++ b/source/main/gameplay/Road2.cpp @@ -26,22 +26,14 @@ using namespace Ogre; -Road2::Road2(int id) : - first(true) - , mid(id) - , snode(0) - , tricount(0) - , vertexcount(0) +Road2::Road2(int id) : first(true), mid(id), snode(0), tricount(0), vertexcount(0) { msh.setNull(); } Road2::~Road2() { - if (snode) - { - snode->removeAndDestroyAllChildren(); - } + if (snode) { snode->removeAndDestroyAllChildren(); } if (!msh.isNull()) { MeshManager::getSingleton().remove(msh->getName()); @@ -62,10 +54,10 @@ void Road2::finish() addQuad(pts[3], pts[2], pts[1], pts[0], TEXFIT_NONE, true, lastpos, lastpos, lastwidth); createMesh(); - String entity_name = String("RoadSystem_Instance-").append(StringConverter::toString(mid)); - String mesh_name = String("RoadSystem-").append(StringConverter::toString(mid)); - Entity* ec = gEnv->sceneManager->createEntity(entity_name, mesh_name); - snode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + String entity_name = String("RoadSystem_Instance-").append(StringConverter::toString(mid)); + String mesh_name = String("RoadSystem-").append(StringConverter::toString(mid)); + Entity *ec = gEnv->sceneManager->createEntity(entity_name, mesh_name); + snode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); snode->attachObject(ec); } @@ -73,28 +65,23 @@ void Road2::addBlock(Vector3 pos, Quaternion rot, int type, float width, float b { if (type == ROAD_AUTOMATIC) { - width = 10.0; - bwidth = 1.4; + width = 10.0; + bwidth = 1.4; bheight = 0.2; - //define type - Vector3 leftv = pos + rot * Vector3(0, 0, bwidth + width / 2.0); + // define type + Vector3 leftv = pos + rot * Vector3(0, 0, bwidth + width / 2.0); Vector3 rightv = pos + rot * Vector3(0, 0, -bwidth - width / 2.0); - float dleft = leftv.y - RoR::App::GetSimTerrain()->GetHeightAt(leftv.x, leftv.z); - float dright = rightv.y - RoR::App::GetSimTerrain()->GetHeightAt(rightv.x, rightv.z); - if (dleft < bheight + 0.1 && dright < bheight + 0.1) - type = ROAD_FLAT; - if (dleft < bheight + 0.1 && dright >= bheight + 0.1 && dright < 4.0) - type = ROAD_LEFT; - if (dleft >= bheight + 0.1 && dleft < 4.0 && dright < bheight + 0.1) - type = ROAD_RIGHT; - if (dleft >= bheight + 0.1 && dleft < 4.0 && dright >= bheight + 0.1 && dright < 4.0) - type = ROAD_BOTH; - if (type == ROAD_AUTOMATIC) - type = ROAD_BRIDGE; + float dleft = leftv.y - RoR::App::GetSimTerrain()->GetHeightAt(leftv.x, leftv.z); + float dright = rightv.y - RoR::App::GetSimTerrain()->GetHeightAt(rightv.x, rightv.z); + if (dleft < bheight + 0.1 && dright < bheight + 0.1) type = ROAD_FLAT; + if (dleft < bheight + 0.1 && dright >= bheight + 0.1 && dright < 4.0) type = ROAD_LEFT; + if (dleft >= bheight + 0.1 && dleft < 4.0 && dright < bheight + 0.1) type = ROAD_RIGHT; + if (dleft >= bheight + 0.1 && dleft < 4.0 && dright >= bheight + 0.1 && dright < 4.0) type = ROAD_BOTH; + if (type == ROAD_AUTOMATIC) type = ROAD_BRIDGE; if (type != ROAD_FLAT) { - width = 10.0; - bwidth = 0.4; + width = 10.0; + bwidth = 0.4; bheight = 0.5; }; } @@ -102,13 +89,12 @@ void Road2::addBlock(Vector3 pos, Quaternion rot, int type, float width, float b { Vector3 pts[8]; Vector3 lpts[8]; - if (type == ROAD_MONORAIL) - pos.y += 2; + if (type == ROAD_MONORAIL) pos.y += 2; computePoints(pts, pos, rot, type, width, bwidth, bheight); computePoints(lpts, lastpos, lastrot, lasttype, lastwidth, lastbwidth, lastbheight); - //tarmac + // tarmac if (type == ROAD_MONORAIL) addQuad(pts[4], lpts[4], lpts[3], pts[3], TEXFIT_CONCRETETOP, true, pos, lastpos, width); else @@ -116,33 +102,37 @@ void Road2::addBlock(Vector3 pos, Quaternion rot, int type, float width, float b if (type == ROAD_FLAT && lasttype == ROAD_FLAT) { - //sides (close) + // sides (close) addQuad(pts[5], lpts[5], lpts[4], pts[4], TEXFIT_ROADS3, true, pos, lastpos, width); addQuad(pts[3], lpts[3], lpts[2], pts[2], TEXFIT_ROADS2, true, pos, lastpos, width); - //sides (far) + // sides (far) addQuad(pts[6], lpts[6], lpts[5], pts[5], TEXFIT_ROADS4, true, pos, lastpos, width); addQuad(pts[2], lpts[2], lpts[1], pts[1], TEXFIT_ROADS1, true, pos, lastpos, width); } else { - //sides (close) - addQuad(pts[5], lpts[5], lpts[4], pts[4], TEXFIT_CONCRETEWALLI, true, pos, lastpos, width, (type == ROAD_FLAT || type == ROAD_LEFT)); - addQuad(pts[3], lpts[3], lpts[2], pts[2], TEXFIT_CONCRETEWALLI, true, pos, lastpos, width, !(type == ROAD_FLAT || type == ROAD_RIGHT)); - //sides (far) - addQuad(pts[6], lpts[6], lpts[5], pts[5], TEXFIT_CONCRETETOP, true, pos, lastpos, width, (type == ROAD_FLAT || type == ROAD_LEFT)); - addQuad(pts[2], lpts[2], lpts[1], pts[1], TEXFIT_CONCRETETOP, true, pos, lastpos, width, !(type == ROAD_FLAT || type == ROAD_RIGHT)); + // sides (close) + addQuad(pts[5], lpts[5], lpts[4], pts[4], TEXFIT_CONCRETEWALLI, true, pos, lastpos, width, + (type == ROAD_FLAT || type == ROAD_LEFT)); + addQuad(pts[3], lpts[3], lpts[2], pts[2], TEXFIT_CONCRETEWALLI, true, pos, lastpos, width, + !(type == ROAD_FLAT || type == ROAD_RIGHT)); + // sides (far) + addQuad(pts[6], lpts[6], lpts[5], pts[5], TEXFIT_CONCRETETOP, true, pos, lastpos, width, + (type == ROAD_FLAT || type == ROAD_LEFT)); + addQuad(pts[2], lpts[2], lpts[1], pts[1], TEXFIT_CONCRETETOP, true, pos, lastpos, width, + !(type == ROAD_FLAT || type == ROAD_RIGHT)); } if (type == ROAD_BRIDGE || lasttype == ROAD_BRIDGE || type == ROAD_MONORAIL || lasttype == ROAD_MONORAIL) { - //walls + // walls addQuad(pts[1], lpts[1], lpts[0], pts[0], TEXFIT_CONCRETEWALL, true, pos, lastpos, width); addQuad(lpts[6], pts[6], pts[7], lpts[7], TEXFIT_CONCRETEWALL, true, pos, lastpos, width); - //underside - we flip the underside so it folds gracefully with the top + // underside - we flip the underside so it folds gracefully with the top addQuad(pts[0], lpts[0], lpts[7], pts[7], TEXFIT_CONCRETEUNDER, true, pos, lastpos, width, true); } else { - //walls + // walls addQuad(pts[1], lpts[1], lpts[0], pts[0], TEXFIT_BRICKWALL, true, pos, lastpos, width); addQuad(lpts[6], pts[6], pts[7], lpts[7], TEXFIT_BRICKWALL, true, pos, lastpos, width); } @@ -153,13 +143,12 @@ void Road2::addBlock(Vector3 pos, Quaternion rot, int type, float width, float b * @todo: create only a few pillars instead of so much! */ // construct the pillars - Vector3 leftv = pos + rot * Vector3(0, 0, bwidth + width / 2.0); - Vector3 rightv = pos + rot * Vector3(0, 0, -bwidth - width / 2.0); - Vector3 middle = lpts[0] - ((lpts[0] + (pts[1] - lpts[0]) / 2) - - (lpts[7] + (pts[6] - lpts[7]) / 2)) * 0.5; - float heightleft = RoR::App::GetSimTerrain()->GetHeightAt(leftv.x, leftv.z); - float heightright = RoR::App::GetSimTerrain()->GetHeightAt(rightv.x, rightv.z); - float heightmiddle = RoR::App::GetSimTerrain()->GetHeightAt(middle.x, middle.z); + Vector3 leftv = pos + rot * Vector3(0, 0, bwidth + width / 2.0); + Vector3 rightv = pos + rot * Vector3(0, 0, -bwidth - width / 2.0); + Vector3 middle = lpts[0] - ((lpts[0] + (pts[1] - lpts[0]) / 2) - (lpts[7] + (pts[6] - lpts[7]) / 2)) * 0.5; + float heightleft = RoR::App::GetSimTerrain()->GetHeightAt(leftv.x, leftv.z); + float heightright = RoR::App::GetSimTerrain()->GetHeightAt(rightv.x, rightv.z); + float heightmiddle = RoR::App::GetSimTerrain()->GetHeightAt(middle.x, middle.z); bool builtpillars = true; @@ -182,52 +171,40 @@ void Road2::addBlock(Vector3 pos, Quaternion rot, int type, float width, float b // always in the middle sidefactor = 0.5; // only build every fifth pillar - if (pillarcounter % 5) - builtpillars = false; + if (pillarcounter % 5) builtpillars = false; } - middle = lpts[0] - ((lpts[0] + (pts[1] - lpts[0]) / 2) - - (lpts[7] + (pts[6] - lpts[7]) / 2)) * sidefactor; - float len = middle.y - RoR::App::GetSimTerrain()->GetHeightAt(middle.x, middle.z) + 5; + middle = lpts[0] - ((lpts[0] + (pts[1] - lpts[0]) / 2) - (lpts[7] + (pts[6] - lpts[7]) / 2)) * sidefactor; + float len = middle.y - RoR::App::GetSimTerrain()->GetHeightAt(middle.x, middle.z) + 5; float width2 = len / 30; if (pillartype == 2 && len > 20) - // no over-long pillars + // no over-long pillars builtpillars = false; // do not draw too small pillars, the bridge may hold without them ;) - if (width2 > 5) - width2 = 5; + if (width2 > 5) width2 = 5; - if (pillartype == 2) - width2 = 0.2; + if (pillartype == 2) width2 = 0.2; if (width2 >= 0.2 && builtpillars) { - //sides - addQuad(middle + Vector3(-width2, -len, -width2), - middle + Vector3(-width2, 0, -width2), - middle + Vector3(width2, 0, -width2), - middle + Vector3(width2, -len, -width2), - TEXFIT_CONCRETETOP, true, pos, lastpos, width2); - - addQuad(middle + Vector3(width2, -len, width2), - middle + Vector3(width2, 0, width2), - middle + Vector3(-width2, 0, width2), - middle + Vector3(-width2, -len, width2), - TEXFIT_CONCRETETOP, true, pos, lastpos, width2); - - addQuad(middle + Vector3(-width2, -len, width2), - middle + Vector3(-width2, 0, width2), - middle + Vector3(-width2, 0, -width2), - middle + Vector3(-width2, -len, -width2), - TEXFIT_CONCRETETOP, true, pos, lastpos, width2); - - addQuad(middle + Vector3(width2, -len, -width2), - middle + Vector3(width2, 0, -width2), - middle + Vector3(width2, 0, width2), - middle + Vector3(width2, -len, width2), - TEXFIT_CONCRETETOP, true, pos, lastpos, width2); + // sides + addQuad(middle + Vector3(-width2, -len, -width2), middle + Vector3(-width2, 0, -width2), + middle + Vector3(width2, 0, -width2), middle + Vector3(width2, -len, -width2), TEXFIT_CONCRETETOP, true, + pos, lastpos, width2); + + addQuad(middle + Vector3(width2, -len, width2), middle + Vector3(width2, 0, width2), + middle + Vector3(-width2, 0, width2), middle + Vector3(-width2, -len, width2), TEXFIT_CONCRETETOP, true, + pos, lastpos, width2); + + addQuad(middle + Vector3(-width2, -len, width2), middle + Vector3(-width2, 0, width2), + middle + Vector3(-width2, 0, -width2), middle + Vector3(-width2, -len, -width2), TEXFIT_CONCRETETOP, true, + pos, lastpos, width2); + + addQuad(middle + Vector3(width2, -len, -width2), middle + Vector3(width2, 0, -width2), + middle + Vector3(width2, 0, width2), middle + Vector3(width2, -len, width2), TEXFIT_CONCRETETOP, true, + pos, lastpos, width2); } } } @@ -240,15 +217,15 @@ void Road2::addBlock(Vector3 pos, Quaternion rot, int type, float width, float b addQuad(pts[0], pts[3], pts[4], pts[7], TEXFIT_NONE, true, pos, pos, width); addQuad(pts[4], pts[5], pts[6], pts[7], TEXFIT_NONE, true, pos, pos, width); } - lastpos = pos; - lastrot = rot; - lastwidth = width; - lastbwidth = bwidth; + lastpos = pos; + lastrot = rot; + lastwidth = width; + lastbwidth = bwidth; lastbheight = bheight; - lasttype = type; + lasttype = type; } -void Road2::computePoints(Vector3* pts, Vector3 pos, Quaternion rot, int type, float width, float bwidth, float bheight) +void Road2::computePoints(Vector3 *pts, Vector3 pos, Quaternion rot, int type, float width, float bwidth, float bheight) { if (type == ROAD_FLAT) { @@ -322,52 +299,50 @@ inline Vector3 Road2::baseOf(Vector3 p) { float y = RoR::App::GetSimTerrain()->GetHeightAt(p.x, p.z) - 0.01; - if (y > p.y) - { - y = p.y - 0.01; - } + if (y > p.y) { y = p.y - 0.01; } return Vector3(p.x, y, p.z); } -void Road2::addQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfit, bool collision, Vector3 pos, Vector3 lastpos, float width, bool flip) +void Road2::addQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfit, bool collision, Vector3 pos, Vector3 lastpos, + float width, bool flip) { - if (vertexcount + 3 >= MAX_VERTEX || tricount * 3 + 3 + 2 >= MAX_TRIS * 3) - return; + if (vertexcount + 3 >= MAX_VERTEX || tricount * 3 + 3 + 2 >= MAX_TRIS * 3) return; Vector2 texf[4]; textureFit(p1, p2, p3, p4, texfit, texf, pos, lastpos, width); - //vertexes - vertex[vertexcount] = p1; - tex[vertexcount] = texf[0]; + // vertexes + vertex[vertexcount] = p1; + tex[vertexcount] = texf[0]; vertex[vertexcount + 1] = p2; - tex[vertexcount + 1] = texf[1]; + tex[vertexcount + 1] = texf[1]; vertex[vertexcount + 2] = p3; - tex[vertexcount + 2] = texf[2]; + tex[vertexcount + 2] = texf[2]; vertex[vertexcount + 3] = p4; - tex[vertexcount + 3] = texf[3]; - //tris + tex[vertexcount + 3] = texf[3]; + // tris if (flip) { - tris[tricount * 3] = vertexcount; - tris[tricount * 3 + 1] = vertexcount + 1; - tris[tricount * 3 + 2] = vertexcount + 3; - tris[tricount * 3 + 3] = vertexcount + 1; + tris[tricount * 3] = vertexcount; + tris[tricount * 3 + 1] = vertexcount + 1; + tris[tricount * 3 + 2] = vertexcount + 3; + tris[tricount * 3 + 3] = vertexcount + 1; tris[tricount * 3 + 3 + 1] = vertexcount + 2; tris[tricount * 3 + 3 + 2] = vertexcount + 3; } else { - tris[tricount * 3] = vertexcount; - tris[tricount * 3 + 1] = vertexcount + 1; - tris[tricount * 3 + 2] = vertexcount + 2; - tris[tricount * 3 + 3] = vertexcount; + tris[tricount * 3] = vertexcount; + tris[tricount * 3 + 1] = vertexcount + 1; + tris[tricount * 3 + 2] = vertexcount + 2; + tris[tricount * 3 + 3] = vertexcount; tris[tricount * 3 + 3 + 1] = vertexcount + 2; tris[tricount * 3 + 3 + 2] = vertexcount + 3; } if (collision) { - ground_model_t* gm = gEnv->collisions->getGroundModelByString("concrete"); - if (texfit == TEXFIT_ROAD || texfit == TEXFIT_ROADS1 || texfit == TEXFIT_ROADS2 || texfit == TEXFIT_ROADS3 || texfit == TEXFIT_ROADS4) + ground_model_t *gm = gEnv->collisions->getGroundModelByString("concrete"); + if (texfit == TEXFIT_ROAD || texfit == TEXFIT_ROADS1 || texfit == TEXFIT_ROADS2 || texfit == TEXFIT_ROADS3 || + texfit == TEXFIT_ROADS4) gm = gEnv->collisions->getGroundModelByString("asphalt"); addCollisionQuad(p1, p2, p3, p4, gm, flip); } @@ -375,32 +350,33 @@ void Road2::addQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfit, vertexcount += 4; } -void Road2::textureFit(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfit, Vector2* texc, Vector3 pos, Vector3 lastpos, float width) +void Road2::textureFit(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfit, Vector2 *texc, Vector3 pos, Vector3 lastpos, + float width) { int i; if (texfit == TEXFIT_BRICKWALL || texfit == TEXFIT_CONCRETEWALL || texfit == TEXFIT_CONCRETEWALLI) { Vector3 ps[4]; - ps[0] = p1; - ps[1] = p2; - ps[2] = p3; - ps[3] = p4; + ps[0] = p1; + ps[1] = p2; + ps[2] = p3; + ps[3] = p4; Vector3 pref1 = pos; Vector3 pref2 = lastpos; - //make matrix + // make matrix Vector3 bx = pref2 - pref1; bx.normalise(); Vector3 by = Vector3::UNIT_Y; Vector3 bz = bx.crossProduct(by); - //coordinates change matrix + // coordinates change matrix Matrix3 reverse; reverse.SetColumn(0, bx); reverse.SetColumn(1, by); reverse.SetColumn(2, bz); Matrix3 forward; forward = reverse.Inverse(); - //transpose + // transpose for (i = 0; i < 4; i++) { Vector3 trv = forward * (ps[i] - pref1); @@ -408,64 +384,61 @@ void Road2::textureFit(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfi { float ty = 0.746 - trv.y * 0.25 / 4.5; // fix overlapping - if (ty > 1) - ty = 1; + if (ty > 1) ty = 1; texc[i] = Vector2(trv.x / 10.0, ty); } if (texfit == TEXFIT_CONCRETEWALL) { // fix overlapping float ty = 0.496 - (trv.y - 0.7) * 0.25 / 4.5; - if (ty > 1) - ty = 1; + if (ty > 1) ty = 1; texc[i] = Vector2(trv.x / 10.0, ty); } if (texfit == TEXFIT_CONCRETEWALLI) { float ty = 0.496 + trv.y * 0.25 / 4.5; // fix overlapping - if (ty > 1) - ty = 1; + if (ty > 1) ty = 1; texc[i] = Vector2(trv.x / 10.0, ty); } } return; } - if (texfit == TEXFIT_ROAD || texfit == TEXFIT_ROADS1 || texfit == TEXFIT_ROADS2 || texfit == TEXFIT_ROADS3 || texfit == TEXFIT_ROADS4 || texfit == TEXFIT_CONCRETETOP || texfit == TEXFIT_CONCRETEUNDER) + if (texfit == TEXFIT_ROAD || texfit == TEXFIT_ROADS1 || texfit == TEXFIT_ROADS2 || texfit == TEXFIT_ROADS3 || + texfit == TEXFIT_ROADS4 || texfit == TEXFIT_CONCRETETOP || texfit == TEXFIT_CONCRETEUNDER) { Vector3 ps[4]; - ps[0] = p1; - ps[1] = p2; - ps[2] = p3; - ps[3] = p4; + ps[0] = p1; + ps[1] = p2; + ps[2] = p3; + ps[3] = p4; Vector3 pref1 = pos; Vector3 pref2 = lastpos; - //project + // project for (i = 0; i < 4; i++) ps[i].y = 0; pref1.y = 0; pref2.y = 0; - //make matrix + // make matrix Vector3 bx = pref2 - pref1; bx.normalise(); Vector3 by = Vector3::UNIT_Y; Vector3 bz = bx.crossProduct(by); - //coordinates change matrix + // coordinates change matrix Matrix3 reverse; reverse.SetColumn(0, bx); reverse.SetColumn(1, by); reverse.SetColumn(2, bz); Matrix3 forward; forward = reverse.Inverse(); - //transpose + // transpose float trvrefz = 0.0; for (i = 0; i < 4; i++) { Vector3 trv = forward * (ps[i] - pref1); if (texfit == TEXFIT_CONCRETETOP) { - if (i == 0) - trvrefz = trv.z; + if (i == 0) trvrefz = trv.z; texc[i] = Vector2(trv.x / 10.0, 0.621 + (trv.z - trvrefz) * 0.25 / 4.5); } else @@ -505,43 +478,38 @@ void Road2::textureFit(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, int texfi } return; } - //default + // default for (i = 0; i < 4; i++) texc[i] = Vector2(0, 0); } -void Road2::addCollisionQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, ground_model_t* gm, bool flip) +void Road2::addCollisionQuad(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, ground_model_t *gm, bool flip) { int triID = 0; if (flip) { triID = gEnv->collisions->addCollisionTri(p1, p2, p4, gm); - if (triID >= 0) - registeredCollTris.push_back(triID); + if (triID >= 0) registeredCollTris.push_back(triID); triID = gEnv->collisions->addCollisionTri(p4, p2, p3, gm); - if (triID >= 0) - registeredCollTris.push_back(triID); + if (triID >= 0) registeredCollTris.push_back(triID); } else { triID = gEnv->collisions->addCollisionTri(p1, p2, p3, gm); - if (triID >= 0) - registeredCollTris.push_back(triID); + if (triID >= 0) registeredCollTris.push_back(triID); triID = gEnv->collisions->addCollisionTri(p1, p3, p4, gm); - if (triID >= 0) - registeredCollTris.push_back(triID); + if (triID >= 0) registeredCollTris.push_back(triID); } } void Road2::createMesh() { AxisAlignedBox aab; - union - { - float* vertices; - CoVertice_t* covertices; + union { + float * vertices; + CoVertice_t *covertices; }; /// Create the mesh via the MeshManager Ogre::String mesh_name = Ogre::String("RoadSystem-").append(Ogre::StringConverter::toString(mid)); @@ -552,14 +520,14 @@ void Road2::createMesh() /// Define the vertices size_t vbufCount = (2 * 3 + 2) * vertexcount; - vertices = (float*)malloc(vbufCount * sizeof(float)); + vertices = (float *)malloc(vbufCount * sizeof(float)); int i; - //fill values + // fill values for (i = 0; i < vertexcount; i++) { covertices[i].texcoord = tex[i]; - covertices[i].vertex = vertex[i]; - //normals are computed later + covertices[i].vertex = vertex[i]; + // normals are computed later covertices[i].normal = Vector3::ZERO; aab.merge(vertex[i]); } @@ -567,7 +535,7 @@ void Road2::createMesh() /// Define triangles size_t ibufCount = 3 * tricount; - //compute normals + // compute normals for (i = 0; i < tricount && i * 3 + 2 < MAX_TRIS * 3; i++) { Vector3 v1, v2; @@ -579,19 +547,19 @@ void Road2::createMesh() covertices[tris[i * 3 + 1]].normal += v1; covertices[tris[i * 3 + 2]].normal += v1; } - //normalize + // normalize for (i = 0; i < vertexcount; i++) { covertices[i].normal.normalise(); } /// Create vertex data structure for vertices shared between sub meshes - msh->sharedVertexData = new VertexData(); + msh->sharedVertexData = new VertexData(); msh->sharedVertexData->vertexCount = vertexcount; /// Create declaration (memory format) of vertex data - VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration; - size_t offset = 0; + VertexDeclaration *decl = msh->sharedVertexData->vertexDeclaration; + size_t offset = 0; decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL); @@ -601,33 +569,29 @@ void Road2::createMesh() /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) - HardwareVertexBufferSharedPtr vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer - VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; + VertexBufferBinding *bind = msh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); - //for the face + // for the face /// Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - ibufCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, ibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card ibuf->writeData(0, ibuf->getSizeInBytes(), tris, true); /// Set parameters of the submesh - mainsub->useSharedVertices = true; + mainsub->useSharedVertices = true; mainsub->indexData->indexBuffer = ibuf; - mainsub->indexData->indexCount = ibufCount; - mainsub->indexData->indexStart = 0; + mainsub->indexData->indexCount = ibufCount; + mainsub->indexData->indexStart = 0; msh->_setBounds(aab, true); diff --git a/source/main/gameplay/Road2.h b/source/main/gameplay/Road2.h index 909c40e639..9ab54b51e1 100644 --- a/source/main/gameplay/Road2.h +++ b/source/main/gameplay/Road2.h @@ -20,30 +20,32 @@ #pragma once -#include - #include "RoRPrerequisites.h" +#include + // dynamic roads class Road2 : public ZeroedMemoryAllocator { -public: - + public: Road2(int id); ~Road2(); - void addBlock(Ogre::Vector3 pos, Ogre::Quaternion rot, int type, float width, float bwidth, float bheight, int pillartype = 1); + void addBlock(Ogre::Vector3 pos, Ogre::Quaternion rot, int type, float width, float bwidth, float bheight, + int pillartype = 1); /** * @param p1 Top left point. * @param p2 Top right point. */ - void addQuad(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, int texfit, bool collision, Ogre::Vector3 pos, Ogre::Vector3 lastpos, float width, bool flip = false); - void addCollisionQuad(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, ground_model_t* gm, bool flip = false); + void addQuad(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, int texfit, bool collision, + Ogre::Vector3 pos, Ogre::Vector3 lastpos, float width, bool flip = false); + void addCollisionQuad(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, ground_model_t *gm, + bool flip = false); void createMesh(); void finish(); static const unsigned int MAX_VERTEX = 50000; - static const unsigned int MAX_TRIS = 50000; + static const unsigned int MAX_TRIS = 50000; enum { @@ -71,11 +73,12 @@ class Road2 : public ZeroedMemoryAllocator TEXFIT_CONCRETEUNDER }; -private: - + private: inline Ogre::Vector3 baseOf(Ogre::Vector3 p); - void computePoints(Ogre::Vector3* pts, Ogre::Vector3 pos, Ogre::Quaternion rot, int type, float width, float bwidth, float bheight); - void textureFit(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, int texfit, Ogre::Vector2* texc, Ogre::Vector3 pos, Ogre::Vector3 lastpos, float width); + void computePoints(Ogre::Vector3 *pts, Ogre::Vector3 pos, Ogre::Quaternion rot, int type, float width, float bwidth, + float bheight); + void textureFit(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, int texfit, Ogre::Vector2 *texc, + Ogre::Vector3 pos, Ogre::Vector3 lastpos, float width); typedef struct { @@ -84,24 +87,23 @@ class Road2 : public ZeroedMemoryAllocator Ogre::Vector2 texcoord; } CoVertice_t; - Ogre::MeshPtr msh; - Ogre::SubMesh* mainsub; + Ogre::MeshPtr msh; + Ogre::SubMesh *mainsub; Ogre::Vector2 tex[MAX_VERTEX]; Ogre::Vector3 vertex[MAX_VERTEX]; - int tricount; - int vertexcount; - short tris[MAX_TRIS * 3]; + int tricount; + int vertexcount; + short tris[MAX_TRIS * 3]; Ogre::Quaternion lastrot; - Ogre::SceneNode* snode; - Ogre::Vector3 lastpos; - bool first; - float lastbheight; - float lastbwidth; - float lastwidth; - int lasttype; - int mid; + Ogre::SceneNode *snode; + Ogre::Vector3 lastpos; + bool first; + float lastbheight; + float lastbwidth; + float lastwidth; + int lasttype; + int mid; std::vector registeredCollTris; }; - diff --git a/source/main/gameplay/SceneMouse.cpp b/source/main/gameplay/SceneMouse.cpp index 9883efba98..3a508e6429 100644 --- a/source/main/gameplay/SceneMouse.cpp +++ b/source/main/gameplay/SceneMouse.cpp @@ -29,22 +29,18 @@ #include "Beam.h" #include "RoRFrameListener.h" -#include +#include #include #include +#include #include -#include using namespace Ogre; using namespace RoR; #define MOUSE_GRAB_FORCE 30000.0f -SceneMouse::SceneMouse() : - mouseGrabState(0), - grab_truck(nullptr), - pickLine(nullptr), - pickLineNode(nullptr) +SceneMouse::SceneMouse() : mouseGrabState(0), grab_truck(nullptr), pickLine(nullptr), pickLineNode(nullptr) { releaseMousePick(); // TODO: Yuck! Rewrite in proper code!! ~ only_a_ptr, 06/2018 } @@ -52,13 +48,15 @@ SceneMouse::SceneMouse() : void SceneMouse::InitializeVisuals() { // load 3d line for mouse picking - pickLine = gEnv->sceneManager->createManualObject("PickLineObject"); + pickLine = gEnv->sceneManager->createManualObject("PickLineObject"); pickLineNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode("PickLineNode"); - MaterialPtr pickLineMaterial = MaterialManager::getSingleton().getByName("PickLineMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + MaterialPtr pickLineMaterial = + MaterialManager::getSingleton().getByName("PickLineMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (pickLineMaterial.isNull()) { - pickLineMaterial = MaterialManager::getSingleton().create("PickLineMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + pickLineMaterial = + MaterialManager::getSingleton().create("PickLineMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } pickLineMaterial->setReceiveShadows(false); pickLineMaterial->getTechnique(0)->setLightingEnabled(true); @@ -94,30 +92,26 @@ void SceneMouse::releaseMousePick() if (App::sim_state.GetActive() == SimState::PAUSED) { return; } // Do nothing when paused // remove forces - if (grab_truck) - grab_truck->HandleMouseMove(minnode, Vector3::ZERO, 0); + if (grab_truck) grab_truck->HandleMouseMove(minnode, Vector3::ZERO, 0); // reset the variables - minnode = -1; - grab_truck = 0; - mindist = 99999; + minnode = -1; + grab_truck = 0; + mindist = 99999; mouseGrabState = 0; - lastgrabpos = Vector3::ZERO; - lastMouseX = 0; - lastMouseY = 0; + lastgrabpos = Vector3::ZERO; + lastMouseX = 0; + lastMouseY = 0; mouseGrabState = 0; } -bool SceneMouse::mouseMoved(const OIS::MouseEvent& _arg) +bool SceneMouse::mouseMoved(const OIS::MouseEvent &_arg) { const OIS::MouseState ms = _arg.state; // check if handled by the camera - if (App::GetSimController()->CameraManagerMouseMoved(_arg)) - { - return true; - } + if (App::GetSimController()->CameraManagerMouseMoved(_arg)) { return true; } // experimental mouse hack if (ms.buttonDown(OIS::MB_Left) && mouseGrabState == 0) @@ -128,7 +122,7 @@ bool SceneMouse::mouseMoved(const OIS::MouseEvent& _arg) Ray mouseRay = getMouseRay(); // walk all trucks - minnode = -1; + minnode = -1; grab_truck = NULL; for (auto actor : App::GetSimController()->GetActors()) { @@ -136,13 +130,11 @@ bool SceneMouse::mouseMoved(const OIS::MouseEvent& _arg) { // check if our ray intersects with the bounding box of the truck std::pair pair = mouseRay.intersects(actor->ar_bounding_box); - if (!pair.first) - continue; + if (!pair.first) continue; for (int j = 0; j < actor->ar_num_nodes; j++) { - if (actor->ar_nodes[j].nd_no_mouse_grab) - continue; + if (actor->ar_nodes[j].nd_no_mouse_grab) continue; // check if our ray intersects with the node std::pair pair = mouseRay.intersects(Sphere(actor->ar_nodes[j].AbsPosition, 0.1f)); @@ -151,8 +143,8 @@ bool SceneMouse::mouseMoved(const OIS::MouseEvent& _arg) // we hit it, check if its the nearest node if (pair.second < mindist) { - mindist = pair.second; - minnode = j; + mindist = pair.second; + minnode = j; grab_truck = actor; } } @@ -167,10 +159,7 @@ bool SceneMouse::mouseMoved(const OIS::MouseEvent& _arg) for (std::vector::iterator it = grab_truck->ar_hooks.begin(); it != grab_truck->ar_hooks.end(); it++) { - if (it->hk_hook_node->pos == minnode) - { - grab_truck->ToggleHooks(it->hk_group, MOUSE_HOOK_TOGGLE, minnode); - } + if (it->hk_hook_node->pos == minnode) { grab_truck->ToggleHooks(it->hk_group, MOUSE_HOOK_TOGGLE, minnode); } } } } @@ -198,7 +187,7 @@ void SceneMouse::UpdateSimulation() { // get values Ray mouseRay = getMouseRay(); // TODO: Touches OGRE Camera+Viewport which shouldn't happen here ~ only_a_ptr, 06/2018 - lastgrabpos = mouseRay.getPoint(mindist); + lastgrabpos = mouseRay.getPoint(mindist); // add forces grab_truck->HandleMouseMove(minnode, lastgrabpos, MOUSE_GRAB_FORCE); @@ -209,11 +198,11 @@ void SceneMouse::UpdateVisuals() { if (grab_truck == nullptr) { - pickLineNode->setVisible(false); // Hide the line + pickLineNode->setVisible(false); // Hide the line } else { - pickLineNode->setVisible(true); // Show the line + pickLineNode->setVisible(true); // Show the line // update visual line pickLine->beginUpdate(0); pickLine->position(grab_truck->GetGfxActor()->GetSimNodeBuffer()[minnode].AbsPosition); @@ -222,7 +211,7 @@ void SceneMouse::UpdateVisuals() } } -bool SceneMouse::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool SceneMouse::mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { if (App::sim_state.GetActive() == SimState::PAUSED) { return true; } // Do nothing when paused @@ -230,8 +219,8 @@ bool SceneMouse::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _i if (ms.buttonDown(OIS::MB_Middle)) { - lastMouseY = ms.Y.abs; - lastMouseX = ms.X.abs; + lastMouseY = ms.Y.abs; + lastMouseX = ms.X.abs; Ray mouseRay = getMouseRay(); if (App::sim_state.GetActive() == SimState::EDITOR_MODE) @@ -240,7 +229,7 @@ bool SceneMouse::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _i return true; } - Actor* player_actor = App::GetSimController()->GetPlayerActor(); + Actor *player_actor = App::GetSimController()->GetPlayerActor(); // Reselect the player actor { @@ -250,7 +239,7 @@ bool SceneMouse::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _i { if (actor != player_actor) { - Vector3 pos = actor->getPosition(); + Vector3 pos = actor->getPosition(); std::pair pair = mouseRay.intersects(Sphere(pos, actor->getMinCameraRadius())); if (pair.first) { @@ -269,21 +258,22 @@ bool SceneMouse::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _i if (player_actor && App::GetSimController()->GetCameraBehavior() == CameraManager::CAMERA_BEHAVIOR_VEHICLE) { Real nearest_camera_distance = std::numeric_limits::max(); - Real nearest_ray_distance = std::numeric_limits::max(); - int nearest_node_index = -1; + Real nearest_ray_distance = std::numeric_limits::max(); + int nearest_node_index = -1; for (int i = 0; i < player_actor->ar_num_nodes; i++) { - Vector3 pos = player_actor->ar_nodes[i].AbsPosition; + Vector3 pos = player_actor->ar_nodes[i].AbsPosition; std::pair pair = mouseRay.intersects(Sphere(pos, 0.25f)); if (pair.first) { Real ray_distance = mouseRay.getDirection().crossProduct(pos - mouseRay.getOrigin()).length(); - if (ray_distance < nearest_ray_distance || (ray_distance == nearest_ray_distance && pair.second < nearest_camera_distance)) + if (ray_distance < nearest_ray_distance || + (ray_distance == nearest_ray_distance && pair.second < nearest_camera_distance)) { nearest_camera_distance = pair.second; - nearest_ray_distance = ray_distance; - nearest_node_index = i; + nearest_ray_distance = ray_distance; + nearest_node_index = i; } } } @@ -301,33 +291,31 @@ bool SceneMouse::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _i return true; } -bool SceneMouse::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool SceneMouse::mouseReleased(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { if (App::sim_state.GetActive() == SimState::PAUSED) { return true; } // Do nothing when paused App::GetSimController()->SetTerrainEditorMouseRay(Ray(Vector3::ZERO, Vector3::ZERO)); - if (mouseGrabState == 1) - { - releaseMousePick(); - } + if (mouseGrabState == 1) { releaseMousePick(); } return true; } -bool SceneMouse::keyPressed(const OIS::KeyEvent& _arg) +bool SceneMouse::keyPressed(const OIS::KeyEvent &_arg) { return false; } -bool SceneMouse::keyReleased(const OIS::KeyEvent& _arg) +bool SceneMouse::keyReleased(const OIS::KeyEvent &_arg) { return false; } Ray SceneMouse::getMouseRay() { - Viewport* vp = gEnv->mainCamera->getViewport(); + Viewport *vp = gEnv->mainCamera->getViewport(); - return gEnv->mainCamera->getCameraToViewportRay((float)lastMouseX / (float)vp->getActualWidth(), (float)lastMouseY / (float)vp->getActualHeight()); + return gEnv->mainCamera->getCameraToViewportRay((float)lastMouseX / (float)vp->getActualWidth(), + (float)lastMouseY / (float)vp->getActualHeight()); } diff --git a/source/main/gameplay/SceneMouse.h b/source/main/gameplay/SceneMouse.h index 5bacf3be08..6e7c4e4577 100644 --- a/source/main/gameplay/SceneMouse.h +++ b/source/main/gameplay/SceneMouse.h @@ -28,39 +28,38 @@ #include "RoRPrerequisites.h" -namespace RoR { - -class SceneMouse +namespace RoR { -public: - - SceneMouse(); - - bool mouseMoved(const OIS::MouseEvent& _arg); - bool mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - bool mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - bool keyPressed(const OIS::KeyEvent& _arg); - bool keyReleased(const OIS::KeyEvent& _arg); - - void InitializeVisuals(); - void UpdateSimulation(); - void UpdateVisuals(); - void DiscardVisuals(); - -protected: - - Ogre::ManualObject* pickLine; - Ogre::SceneNode* pickLineNode; - int mouseGrabState; - - int minnode; - float mindist; - Actor* grab_truck; - Ogre::Vector3 lastgrabpos; - int lastMouseX, lastMouseY; - void releaseMousePick(); - Ogre::Ray getMouseRay(); -}; + class SceneMouse + { + public: + SceneMouse(); + + bool mouseMoved(const OIS::MouseEvent &_arg); + bool mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + bool mouseReleased(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + bool keyPressed(const OIS::KeyEvent &_arg); + bool keyReleased(const OIS::KeyEvent &_arg); + + void InitializeVisuals(); + void UpdateSimulation(); + void UpdateVisuals(); + void DiscardVisuals(); + + protected: + Ogre::ManualObject *pickLine; + Ogre::SceneNode * pickLineNode; + int mouseGrabState; + + int minnode; + float mindist; + Actor * grab_truck; + Ogre::Vector3 lastgrabpos; + int lastMouseX, lastMouseY; + + void releaseMousePick(); + Ogre::Ray getMouseRay(); + }; } // namespace RoR diff --git a/source/main/gameplay/ScriptEvents.h b/source/main/gameplay/ScriptEvents.h index 4f7d94756f..8ab50674d1 100644 --- a/source/main/gameplay/ScriptEvents.h +++ b/source/main/gameplay/ScriptEvents.h @@ -23,40 +23,55 @@ /// This enum describes what events are existing. The script can register to receive events. enum scriptEvents { - SE_COLLISION_BOX_ENTER = 0x00000001, //!< triggered when actor or person enters a previous registered collision box, the argument refers to the collision box ID - SE_COLLISION_BOX_LEAVE = 0x00000002, //!< triggered when actor or person leaves a previous registered and entered collision box, the argument refers to the collision box ID - - SE_TRUCK_ENTER = 0x00000004, //!< triggered when switching from person mode to vehicle mode, the argument refers to the actor ID of the vehicle - SE_TRUCK_EXIT = 0x00000008, //!< triggered when switching from vehicle mode to person mode, the argument refers to the actor ID of the vehicle - - SE_TRUCK_ENGINE_DIED = 0x00000010, //!< triggered when the vehicle's engine dies (from underrev, water, etc), the argument refers to the actor ID of the vehicle - SE_TRUCK_ENGINE_FIRE = 0x00000020, //!< triggered when the planes engines start to get on fire, the argument refers to the actor ID of the vehicle - SE_TRUCK_TOUCHED_WATER = 0x00000040, //!< triggered when any part of the actor touches water, the argument refers to the actor ID - SE_TRUCK_BEAM_BROKE = 0x00000080, //!< triggered when a beam breaks, the argument refers to the actor ID - SE_TRUCK_LOCKED = 0x00000100, //!< triggered when the actor got lock to another actor, the argument refers to the actor ID - SE_TRUCK_UNLOCKED = 0x00000200, //!< triggered when the actor unlocks again, the argument refers to the actor ID - SE_TRUCK_LIGHT_TOGGLE = 0x00000400, //!< triggered when the main light is toggled, the argument refers to the actor ID - SE_TRUCK_SKELETON_TOGGLE = 0x00000800, //!< triggered when the user enters or exits skeleton mode, the argument refers to the actor ID - SE_TRUCK_TIE_TOGGLE = 0x00001000, //!< triggered when the user toggles ties, the argument refers to the actor ID - SE_TRUCK_PARKINGBREAK_TOGGLE = 0x00002000, //!< triggered when the user toggles the parking break, the argument refers to the actor ID - SE_TRUCK_BEACONS_TOGGLE = 0x00004000, //!< triggered when the user toggles beacons, the argument refers to the actor ID - SE_TRUCK_CPARTICLES_TOGGLE = 0x00008000, //!< triggered when the user toggles custom particles, the argument refers to the actor ID - SE_TRUCK_GROUND_CONTACT_CHANGED = 0x00010000, //!< triggered when the trucks ground contact changed (no contact, different ground models, etc), the argument refers to the actor ID - - SE_GENERIC_NEW_TRUCK = 0x00020000, //!< triggered when the user spawns a new actor, the argument refers to the actor ID - SE_GENERIC_DELETED_TRUCK = 0x00040000, //!< triggered when the user deletes an actor, the argument refers to the actor ID - - SE_GENERIC_INPUT_EVENT = 0x00080000, //!< triggered when an input event bound to the scripting engine is toggled, the argument refers to event id - SE_GENERIC_MOUSE_BEAM_INTERACTION = 0x00100000, //!< triggered when the user uses the mouse to interact with the actor, the argument refers to the actor ID - - SE_TRUCK_RESET = 0x00200000, //!< triggered when the user resets the truck, the argument refers to the actor ID of the vehicle - SE_TRUCK_TELEPORT = 0x00400000, //!< triggered when the user teleports the truck, the argument refers to the actor ID of the vehicle - - SE_ANGELSCRIPT_MANIPULATIONS = 0x00800000, //!< triggered when the user tries to dynamically use the scripting capabilities (prevent cheating) - - SE_GENERIC_MESSAGEBOX_CLICK = 0x01000000, //!< triggered when the user clicks on a message box button, the argument refers to the button pressed - - SE_ALL_EVENTS = 0xffffffff, + SE_COLLISION_BOX_ENTER = 0x00000001, //!< triggered when actor or person enters a previous registered collision box, the + //!< argument refers to the collision box ID + SE_COLLISION_BOX_LEAVE = 0x00000002, //!< triggered when actor or person leaves a previous registered and entered collision + //!< box, the argument refers to the collision box ID + + SE_TRUCK_ENTER = 0x00000004, //!< triggered when switching from person mode to vehicle mode, the argument refers to the actor + //!< ID of the vehicle + SE_TRUCK_EXIT = 0x00000008, //!< triggered when switching from vehicle mode to person mode, the argument refers to the actor + //!< ID of the vehicle + + SE_TRUCK_ENGINE_DIED = 0x00000010, //!< triggered when the vehicle's engine dies (from underrev, water, etc), the argument + //!< refers to the actor ID of the vehicle + SE_TRUCK_ENGINE_FIRE = 0x00000020, //!< triggered when the planes engines start to get on fire, the argument refers to the + //!< actor ID of the vehicle + SE_TRUCK_TOUCHED_WATER = + 0x00000040, //!< triggered when any part of the actor touches water, the argument refers to the actor ID + SE_TRUCK_BEAM_BROKE = 0x00000080, //!< triggered when a beam breaks, the argument refers to the actor ID + SE_TRUCK_LOCKED = 0x00000100, //!< triggered when the actor got lock to another actor, the argument refers to the actor ID + SE_TRUCK_UNLOCKED = 0x00000200, //!< triggered when the actor unlocks again, the argument refers to the actor ID + SE_TRUCK_LIGHT_TOGGLE = 0x00000400, //!< triggered when the main light is toggled, the argument refers to the actor ID + SE_TRUCK_SKELETON_TOGGLE = + 0x00000800, //!< triggered when the user enters or exits skeleton mode, the argument refers to the actor ID + SE_TRUCK_TIE_TOGGLE = 0x00001000, //!< triggered when the user toggles ties, the argument refers to the actor ID + SE_TRUCK_PARKINGBREAK_TOGGLE = + 0x00002000, //!< triggered when the user toggles the parking break, the argument refers to the actor ID + SE_TRUCK_BEACONS_TOGGLE = 0x00004000, //!< triggered when the user toggles beacons, the argument refers to the actor ID + SE_TRUCK_CPARTICLES_TOGGLE = + 0x00008000, //!< triggered when the user toggles custom particles, the argument refers to the actor ID + SE_TRUCK_GROUND_CONTACT_CHANGED = 0x00010000, //!< triggered when the trucks ground contact changed (no contact, different + //!< ground models, etc), the argument refers to the actor ID + + SE_GENERIC_NEW_TRUCK = 0x00020000, //!< triggered when the user spawns a new actor, the argument refers to the actor ID + SE_GENERIC_DELETED_TRUCK = 0x00040000, //!< triggered when the user deletes an actor, the argument refers to the actor ID + + SE_GENERIC_INPUT_EVENT = + 0x00080000, //!< triggered when an input event bound to the scripting engine is toggled, the argument refers to event id + SE_GENERIC_MOUSE_BEAM_INTERACTION = + 0x00100000, //!< triggered when the user uses the mouse to interact with the actor, the argument refers to the actor ID + + SE_TRUCK_RESET = 0x00200000, //!< triggered when the user resets the truck, the argument refers to the actor ID of the vehicle + SE_TRUCK_TELEPORT = + 0x00400000, //!< triggered when the user teleports the truck, the argument refers to the actor ID of the vehicle + + SE_ANGELSCRIPT_MANIPULATIONS = + 0x00800000, //!< triggered when the user tries to dynamically use the scripting capabilities (prevent cheating) + + SE_GENERIC_MESSAGEBOX_CLICK = + 0x01000000, //!< triggered when the user clicks on a message box button, the argument refers to the button pressed + + SE_ALL_EVENTS = 0xffffffff, }; - diff --git a/source/main/gameplay/Scripting.h b/source/main/gameplay/Scripting.h index aa7bc9d6d3..3107d6538e 100644 --- a/source/main/gameplay/Scripting.h +++ b/source/main/gameplay/Scripting.h @@ -25,8 +25,8 @@ #include "ScriptEvents.h" #ifdef USE_ANGELSCRIPT -# include "ScriptEngine.h" -# define TRIGGER_EVENT(x, y) ScriptEngine::getSingleton().triggerEvent(x, y) + #include "ScriptEngine.h" + #define TRIGGER_EVENT(x, y) ScriptEngine::getSingleton().triggerEvent(x, y) #else -# define TRIGGER_EVENT(x, y) + #define TRIGGER_EVENT(x, y) #endif // USE_ANGELSCRIPT diff --git a/source/main/gameplay/SkinManager.cpp b/source/main/gameplay/SkinManager.cpp index 9c83e62b3c..bee86631d0 100644 --- a/source/main/gameplay/SkinManager.cpp +++ b/source/main/gameplay/SkinManager.cpp @@ -31,27 +31,24 @@ #include #include -std::vector> RoR::SkinParser::ParseSkins(Ogre::DataStreamPtr& stream) +std::vector> RoR::SkinParser::ParseSkins(Ogre::DataStreamPtr &stream) { std::vector> result; - std::unique_ptr curr_skin; + std::unique_ptr curr_skin; try { - while(!stream->eof()) + while (!stream->eof()) { std::string line = RoR::Utils::SanitizeUtf8String(stream->getLine()); // Ignore blanks & comments - if (!line.length() || line.substr(0, 2) == "//") - { - continue; - } + if (!line.length() || line.substr(0, 2) == "//") { continue; } if (!curr_skin) { // No current skin -- So first valid data should be skin name Ogre::StringUtil::trim(line); - curr_skin = std::unique_ptr(new SkinDef); + curr_skin = std::unique_ptr(new SkinDef); curr_skin->name = line; stream->skipLine("{"); } @@ -69,30 +66,65 @@ std::vector> RoR::SkinParser::ParseSkins(Ogre::Dat } } } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - RoR::LogFormat("[RoR] Error parsing skin file '%s', message: %s", - stream->getName().c_str(), e.getFullDescription().c_str()); + RoR::LogFormat("[RoR] Error parsing skin file '%s', message: %s", stream->getName().c_str(), + e.getFullDescription().c_str()); } return result; } -void RoR::SkinParser::ParseSkinAttribute(const std::string& line, SkinDef* skin_def) // static +void RoR::SkinParser::ParseSkinAttribute(const std::string &line, SkinDef *skin_def) // static { Ogre::StringVector params = Ogre::StringUtil::split(line, "\t=,;\n"); - for (unsigned int i=0; i < params.size(); i++) + for (unsigned int i = 0; i < params.size(); i++) { Ogre::StringUtil::trim(params[i]); } - Ogre::String& attrib = params[0]; + Ogre::String &attrib = params[0]; Ogre::StringUtil::toLowerCase(attrib); - if (attrib == "replacetexture" && params.size() == 3) { skin_def->replace_textures.insert(std::make_pair(params[1], params[2])); return; } - if (attrib == "replacematerial" && params.size() == 3) { skin_def->replace_materials.insert(std::make_pair(params[1], params[2])); return; } - if (attrib == "preview" && params.size() >= 2) { skin_def->thumbnail = params[1]; return; } - if (attrib == "description" && params.size() >= 2) { skin_def->description = params[1]; return; } - if (attrib == "authorname" && params.size() >= 2) { skin_def->author_name = params[1]; return; } - if (attrib == "authorid" && params.size() == 2) { skin_def->author_id = PARSEINT(params[1]); return; } - if (attrib == "guid" && params.size() >= 2) { skin_def->guid = params[1]; Ogre::StringUtil::trim(skin_def->guid); Ogre::StringUtil::toLowerCase(skin_def->guid); return; } - if (attrib == "name" && params.size() >= 2) { skin_def->name = params[1]; Ogre::StringUtil::trim(skin_def->name); return; } + if (attrib == "replacetexture" && params.size() == 3) + { + skin_def->replace_textures.insert(std::make_pair(params[1], params[2])); + return; + } + if (attrib == "replacematerial" && params.size() == 3) + { + skin_def->replace_materials.insert(std::make_pair(params[1], params[2])); + return; + } + if (attrib == "preview" && params.size() >= 2) + { + skin_def->thumbnail = params[1]; + return; + } + if (attrib == "description" && params.size() >= 2) + { + skin_def->description = params[1]; + return; + } + if (attrib == "authorname" && params.size() >= 2) + { + skin_def->author_name = params[1]; + return; + } + if (attrib == "authorid" && params.size() == 2) + { + skin_def->author_id = PARSEINT(params[1]); + return; + } + if (attrib == "guid" && params.size() >= 2) + { + skin_def->guid = params[1]; + Ogre::StringUtil::trim(skin_def->guid); + Ogre::StringUtil::toLowerCase(skin_def->guid); + return; + } + if (attrib == "name" && params.size() >= 2) + { + skin_def->name = params[1]; + Ogre::StringUtil::trim(skin_def->name); + return; + } } diff --git a/source/main/gameplay/SkinManager.h b/source/main/gameplay/SkinManager.h index f8d8d688df..1eefc36b55 100644 --- a/source/main/gameplay/SkinManager.h +++ b/source/main/gameplay/SkinManager.h @@ -24,37 +24,37 @@ #include "RoRPrerequisites.h" #include - #include -#include -#include #include +#include +#include -namespace RoR { - -struct SkinDef -{ - SkinDef(): author_id(-1) {} - - std::map replace_textures; - std::map replace_materials; - std::string name; - std::string guid; - std::string thumbnail; - std::string description; - std::string author_name; - int author_id; -}; - -class SkinParser +namespace RoR { -public: - - static std::vector> ParseSkins(Ogre::DataStreamPtr& stream); - -private: - static void ParseSkinAttribute(const std::string& line, SkinDef* skin_def); -}; + struct SkinDef + { + SkinDef() : author_id(-1) + { + } + + std::map replace_textures; + std::map replace_materials; + std::string name; + std::string guid; + std::string thumbnail; + std::string description; + std::string author_name; + int author_id; + }; + + class SkinParser + { + public: + static std::vector> ParseSkins(Ogre::DataStreamPtr &stream); + + private: + static void ParseSkinAttribute(const std::string &line, SkinDef *skin_def); + }; }; // namespace RoR diff --git a/source/main/gameplay/TorqueCurve.cpp b/source/main/gameplay/TorqueCurve.cpp index 55fdebd3b8..e9eb3e6d34 100644 --- a/source/main/gameplay/TorqueCurve.cpp +++ b/source/main/gameplay/TorqueCurve.cpp @@ -42,21 +42,18 @@ TorqueCurve::~TorqueCurve() Real TorqueCurve::getEngineTorque(Real rpm) { - if (!usedSpline) - return 0.0f; - if (usedSpline->getNumPoints() == 1) - return usedSpline->getPoint(0).y; + if (!usedSpline) return 0.0f; + if (usedSpline->getNumPoints() == 1) return usedSpline->getPoint(0).y; float minRPM = usedSpline->getPoint(0).x; float maxRPM = usedSpline->getPoint(usedSpline->getNumPoints() - 1).x; - if (minRPM == maxRPM) - return usedSpline->getPoint(0).y; + if (minRPM == maxRPM) return usedSpline->getPoint(0).y; float t = Math::Clamp((rpm - minRPM) / (maxRPM - minRPM), 0.0f, 1.0f); return usedSpline->interpolate(t).y; } int TorqueCurve::loadDefaultTorqueModels() { - //LOG("loading default torque Curves"); + // LOG("loading default torque Curves"); // check if we have a config file String group = ""; try @@ -74,17 +71,16 @@ int TorqueCurve::loadDefaultTorqueModels() } // open the file for reading - DataStreamPtr ds = ResourceGroupManager::getSingleton().openResource("torque_models.cfg", group); - String line = ""; - String currentModel = ""; + DataStreamPtr ds = ResourceGroupManager::getSingleton().openResource("torque_models.cfg", group); + String line = ""; + String currentModel = ""; while (!ds->eof()) { line = RoR::Utils::SanitizeUtf8String(ds->getLine()); StringUtil::trim(line); - if (line.empty() || line[0] == ';') - continue; + if (line.empty() || line[0] == ';') continue; Ogre::StringVector args = StringUtil::split(line, ","); @@ -95,8 +91,7 @@ int TorqueCurve::loadDefaultTorqueModels() } // process the line if we got a model - if (!currentModel.empty()) - processLine(args, currentModel); + if (!currentModel.empty()) processLine(args, currentModel); } return 0; } @@ -104,20 +99,17 @@ int TorqueCurve::loadDefaultTorqueModels() int TorqueCurve::processLine(Ogre::StringVector args, String model) { // if its just one arguments, it must be a known model - if (args.size() == 1) - return setTorqueModel(args[0]); + if (args.size() == 1) return setTorqueModel(args[0]); // we only accept 2 arguments - if (args.size() != 2) - return 1; + if (args.size() != 2) return 1; // parse the data - float pointx = StringConverter::parseReal(args[0]); - float pointy = StringConverter::parseReal(args[1]); - Vector3 point = Vector3(pointx, pointy, 0); + float pointx = StringConverter::parseReal(args[0]); + float pointy = StringConverter::parseReal(args[1]); + Vector3 point = Vector3(pointx, pointy, 0); // find the spline to attach the points - if (splines.find(model) == splines.end()) - splines[model] = SimpleSpline(); + if (splines.find(model) == splines.end()) splines[model] = SimpleSpline(); // attach the points to the spline // LOG("curve "+model+" : " + TOSTRING(point)); @@ -125,29 +117,22 @@ int TorqueCurve::processLine(Ogre::StringVector args, String model) // special case for custom model: // we set it as active curve as well! - if (model == TorqueCurve::customModel) - setTorqueModel(TorqueCurve::customModel); + if (model == TorqueCurve::customModel) setTorqueModel(TorqueCurve::customModel); return 0; } -bool TorqueCurve::CreateNewCurve(Ogre::String const& name) +bool TorqueCurve::CreateNewCurve(Ogre::String const &name) { - if (splines.find(name) != splines.end()) - { - return false; - } + if (splines.find(name) != splines.end()) { return false; } splines[name] = Ogre::SimpleSpline(); /* special case for custom model: we set it as active curve as well! */ - if (name == TorqueCurve::customModel) - { - setTorqueModel(TorqueCurve::customModel); - } + if (name == TorqueCurve::customModel) { setTorqueModel(TorqueCurve::customModel); } return true; } -void TorqueCurve::AddCurveSample(float rpm, float progress, Ogre::String const& model) +void TorqueCurve::AddCurveSample(float rpm, float progress, Ogre::String const &model) { /* attach the points to the spline */ splines[model].addPoint(Ogre::Vector3(rpm, progress, 0)); @@ -155,26 +140,25 @@ void TorqueCurve::AddCurveSample(float rpm, float progress, Ogre::String const& int TorqueCurve::setTorqueModel(String name) { - //LOG("using torque curve: " + name); + // LOG("using torque curve: " + name); // check if we have such a model loaded if (splines.find(name) == splines.end()) { - LOG("Torquemodel "+String(name)+" not found! ignoring that and using default model..."); + LOG("Torquemodel " + String(name) + " not found! ignoring that and using default model..."); return 1; } // use the model usedSpline = &splines.find(name)->second; - usedModel = name; + usedModel = name; return 0; } -int TorqueCurve::spaceCurveEvenly(Ogre::SimpleSpline* spline) +int TorqueCurve::spaceCurveEvenly(Ogre::SimpleSpline *spline) { - if (!spline) - return 2; + if (!spline) return 2; SimpleSpline tmpSpline = *spline; - Real points = tmpSpline.getNumPoints(); + Real points = tmpSpline.getNumPoints(); if (points > 1) { @@ -185,34 +169,32 @@ int TorqueCurve::spaceCurveEvenly(Ogre::SimpleSpline* spline) for (int i = 2; i < points; i++) { Real distance = tmpSpline.getPoint(i).x - tmpSpline.getPoint(i - 1).x; - minDistance = std::min(distance, minDistance); + minDistance = std::min(distance, minDistance); } // the rpm points must be in an ascending order, as the points should be added at the end of the spline - if (minDistance < 0) - return 1; + if (minDistance < 0) return 1; // first(smallest)- and last(greatest) rpm Vector3 minPoint = tmpSpline.getPoint(0); Vector3 maxPoint = tmpSpline.getPoint(points - 1); - Real rpmPoint = minPoint.x; - int pointIndex = 1; // this is the index used to interpolate between the rpm points + Real rpmPoint = minPoint.x; + int pointIndex = 1; // this is the index used to interpolate between the rpm points while (rpmPoint <= maxPoint.x && pointIndex < points) { // if actual rpm is higher than point of the spline, proceed to the next point - if (rpmPoint > tmpSpline.getPoint(pointIndex).x) - pointIndex++; + if (rpmPoint > tmpSpline.getPoint(pointIndex).x) pointIndex++; // interpolate(linear) - Real newPoint = tmpSpline.getPoint(pointIndex - 1).y + (tmpSpline.getPoint(pointIndex).y - tmpSpline.getPoint(pointIndex - 1).y) / - (tmpSpline.getPoint(pointIndex).x - tmpSpline.getPoint(pointIndex - 1).x) * (rpmPoint - tmpSpline.getPoint(pointIndex - 1).x); + Real newPoint = tmpSpline.getPoint(pointIndex - 1).y + + (tmpSpline.getPoint(pointIndex).y - tmpSpline.getPoint(pointIndex - 1).y) / + (tmpSpline.getPoint(pointIndex).x - tmpSpline.getPoint(pointIndex - 1).x) * + (rpmPoint - tmpSpline.getPoint(pointIndex - 1).x); spline->addPoint(Vector3(rpmPoint, newPoint, 0)); rpmPoint += minDistance; } // if the last point is missing due the even spacing, we add the last point manually // criterion is that it must be smaller than 1% of the maximum rpm. if (spline->getPoint(spline->getNumPoints() - 1).x < maxPoint.x && (rpmPoint - maxPoint.x) < 0.01 * maxPoint.x) - { - spline->addPoint(Vector3(rpmPoint, maxPoint.y, 0)); - } + { spline->addPoint(Vector3(rpmPoint, maxPoint.y, 0)); } } return 0; diff --git a/source/main/gameplay/TorqueCurve.h b/source/main/gameplay/TorqueCurve.h index bb41e8379a..e6ec9798fe 100644 --- a/source/main/gameplay/TorqueCurve.h +++ b/source/main/gameplay/TorqueCurve.h @@ -33,10 +33,10 @@ */ class TorqueCurve : public ZeroedMemoryAllocator { -public: + public: const static Ogre::String customModel; - TorqueCurve(); //!< Constructor + TorqueCurve(); //!< Constructor ~TorqueCurve(); //!< Destructor /** @@ -54,40 +54,46 @@ class TorqueCurve : public ZeroedMemoryAllocator int setTorqueModel(Ogre::String name); /** - * Creates new torque curve. - * @return True if created, false if already existed. - */ - bool CreateNewCurve(Ogre::String const& name = customModel); + * Creates new torque curve. + * @return True if created, false if already existed. + */ + bool CreateNewCurve(Ogre::String const &name = customModel); /** * Adds a point to the torque curve graph. * @param progress 0 - 1 * @param model Torque model name (i.e. 'turbodiesel'). */ - void AddCurveSample(float rpm, float progress, Ogre::String const& model = customModel); + void AddCurveSample(float rpm, float progress, Ogre::String const &model = customModel); /** * Returns the used spline. * @return The torque spline used by the vehicle. */ - Ogre::SimpleSpline* getUsedSpline() { return usedSpline; }; + Ogre::SimpleSpline *getUsedSpline() + { + return usedSpline; + }; /** * Returns the name of the torque model used by the vehicle. * @return The name of the torque model used by the vehicle. */ - Ogre::String getTorqueModel() { return usedModel; }; + Ogre::String getTorqueModel() + { + return usedModel; + }; /** * Spaces the points of a spline evenly; this is needed for the correct calculation of the Ogre simple spline. * @param spline Pointer to the spline which should be processed. * @return 0 on success, 1 on error */ - int spaceCurveEvenly(Ogre::SimpleSpline* spline); + int spaceCurveEvenly(Ogre::SimpleSpline *spline); -protected: - Ogre::SimpleSpline* usedSpline; //!< spline which is used for calculating the torque, set by setTorqueModel(). - Ogre::String usedModel; //!< name of the torque model used by the truck. + protected: + Ogre::SimpleSpline *usedSpline; //!< spline which is used for calculating the torque, set by setTorqueModel(). + Ogre::String usedModel; //!< name of the torque model used by the truck. std::map splines; //!< container were all torque curve splines are stored in. /** diff --git a/source/main/gameplay/VehicleAI.cpp b/source/main/gameplay/VehicleAI.cpp index ece58274b8..6a32c55193 100644 --- a/source/main/gameplay/VehicleAI.cpp +++ b/source/main/gameplay/VehicleAI.cpp @@ -22,21 +22,17 @@ #ifdef USE_ANGELSCRIPT -#include "VehicleAI.h" + #include "VehicleAI.h" -#include "Beam.h" -#include "BeamEngine.h" -#include "GUI_GameConsole.h" - -#include "MainMenu.h" - -#include "scriptdictionary/scriptdictionary.h" + #include "Beam.h" + #include "BeamEngine.h" + #include "GUI_GameConsole.h" + #include "MainMenu.h" + #include "scriptdictionary/scriptdictionary.h" using namespace Ogre; -VehicleAI::VehicleAI(Actor* b) : - is_waiting(false), - wait_time(0.0f) +VehicleAI::VehicleAI(Actor *b) : is_waiting(false), wait_time(0.0f) { beam = b; } @@ -55,10 +51,9 @@ bool VehicleAI::IsActive() return is_enabled; } -void VehicleAI::AddWaypoint(String& id, Vector3& point) +void VehicleAI::AddWaypoint(String &id, Vector3 &point) { - if (current_waypoint == Vector3::ZERO) - current_waypoint = point; + if (current_waypoint == Vector3::ZERO) current_waypoint = point; free_waypoints++; waypoints.emplace(free_waypoints, point); @@ -66,7 +61,7 @@ void VehicleAI::AddWaypoint(String& id, Vector3& point) waypoint_names.emplace(free_waypoints, id); } -void VehicleAI::AddWaypoints(AngelScript::CScriptDictionary& d) +void VehicleAI::AddWaypoints(AngelScript::CScriptDictionary &d) { for (auto item : d) { @@ -77,65 +72,53 @@ void VehicleAI::AddWaypoints(AngelScript::CScriptDictionary& d) } } -void VehicleAI::AddEvent(String& id, int& ev) +void VehicleAI::AddEvent(String &id, int &ev) { int waypointid = waypoint_ids[id]; - if (waypointid) - waypoint_events.emplace(waypointid, ev); + if (waypointid) waypoint_events.emplace(waypointid, ev); } -void VehicleAI::SetValueAtWaypoint(String& id, int& value_id, float& value) +void VehicleAI::SetValueAtWaypoint(String &id, int &value_id, float &value) { int waypointid = waypoint_ids[id]; if (waypointid) { switch (value_id) { - case AI_SPEED: - waypoint_speed.emplace(waypointid, value); - break; - case AI_POWER: - waypoint_power.emplace(waypointid, value); - break; - default: - break; + case AI_SPEED: waypoint_speed.emplace(waypointid, value); break; + case AI_POWER: waypoint_power.emplace(waypointid, value); break; + default: break; } } } void VehicleAI::updateWaypoint() { - RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_SCRIPT, RoR::Console::CONSOLE_SYSTEM_NOTICE, "Reached waypoint: " + waypoint_names[current_waypoint_id], "note.png"); + RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_SCRIPT, RoR::Console::CONSOLE_SYSTEM_NOTICE, + "Reached waypoint: " + waypoint_names[current_waypoint_id], "note.png"); int event = waypoint_events[current_waypoint_id]; if (event) { switch (event) { - case AI_LIGHTSTOGGLE: - beam->ToggleLights(); - break; - case AI_BEACONSTOGGLE: - beam->ToggleBeacons(); - break; - default: - break; + case AI_LIGHTSTOGGLE: beam->ToggleLights(); break; + case AI_BEACONSTOGGLE: beam->ToggleBeacons(); break; + default: break; } } float speed = waypoint_speed[current_waypoint_id]; - if (speed) - maxspeed = speed; + if (speed) maxspeed = speed; float power = waypoint_power[current_waypoint_id]; - if (power) - acc_power = power; + if (power) acc_power = power; current_waypoint_id++; if (current_waypoint_id > free_waypoints) { current_waypoint_id = 0; - is_enabled = false; + is_enabled = false; beam->ToggleParkingBrake(); } current_waypoint = waypoints[current_waypoint_id]; @@ -146,10 +129,7 @@ void VehicleAI::update(float dt, int doUpdate) if (is_waiting) { wait_time -= dt; - if (wait_time < 0) - { - is_waiting = false; - } + if (wait_time < 0) { is_waiting = false; } return; } @@ -161,18 +141,18 @@ void VehicleAI::update(float dt, int doUpdate) return; } - Vector3 TargetPosition = current_waypoint; - TargetPosition.y = 0; //Vector3 > Vector2 + Vector3 TargetPosition = current_waypoint; + TargetPosition.y = 0; // Vector3 > Vector2 Quaternion TargetOrientation = Quaternion::ZERO; - mAgentPosition.y = 0; //Vector3 > Vector2 + mAgentPosition.y = 0; // Vector3 > Vector2 Quaternion mAgentOrientation = Quaternion(Radian(beam->getRotation()), Vector3::NEGATIVE_UNIT_Y); mAgentOrientation.normalise(); Vector3 mVectorToTarget = TargetPosition - mAgentPosition; // A-B = B->A mAgentPosition.normalise(); - Vector3 mAgentHeading = mAgentOrientation * mAgentPosition; + Vector3 mAgentHeading = mAgentOrientation * mAgentPosition; Vector3 mTargetHeading = TargetOrientation * TargetPosition; mAgentHeading.normalise(); mTargetHeading.normalise(); @@ -181,9 +161,9 @@ void VehicleAI::update(float dt, int doUpdate) Vector3 mSteeringForce = mAgentOrientation.Inverse() * mVectorToTarget; mSteeringForce.normalise(); - float mYaw = mSteeringForce.x; + float mYaw = mSteeringForce.x; float mPitch = mSteeringForce.z; - //float mRoll = mTargetVO.getRotationTo( mAgentVO ).getRoll().valueRadians(); + // float mRoll = mTargetVO.getRotationTo( mAgentVO ).getRoll().valueRadians(); if (mPitch > 0) { @@ -194,13 +174,12 @@ void VehicleAI::update(float dt, int doUpdate) } // actually steer - beam->ar_hydro_dir_command = mYaw;//mYaw + beam->ar_hydro_dir_command = mYaw; // mYaw if (beam->ar_engine) { // start engine if not running - if (!beam->ar_engine->IsRunning()) - beam->ar_engine->StartEngine(); + if (!beam->ar_engine->IsRunning()) beam->ar_engine->StartEngine(); float kmh_wheel_speed = beam->getWheelSpeed() * 3.6; diff --git a/source/main/gameplay/VehicleAI.h b/source/main/gameplay/VehicleAI.h index fabf1f5bd5..09f4580e58 100644 --- a/source/main/gameplay/VehicleAI.h +++ b/source/main/gameplay/VehicleAI.h @@ -29,12 +29,12 @@ #ifdef USE_ANGELSCRIPT -#include "RoRPrerequisites.h" -#include "scriptdictionary/scriptdictionary.h" + #include "RoRPrerequisites.h" + #include "scriptdictionary/scriptdictionary.h" /** -* Enum with AI events -*/ + * Enum with AI events + */ enum Ai_events { AI_HORN, @@ -44,8 +44,8 @@ enum Ai_events }; /** -* Enum with AI values that can be set. -*/ + * Enum with AI values that can be set. + */ enum Ai_values { AI_SPEED, @@ -54,8 +54,8 @@ enum Ai_values class VehicleAI : public ZeroedMemoryAllocator { -public: - VehicleAI(Actor* b); + public: + VehicleAI(Actor *b); ~VehicleAI(); /** * Activates/Deactivates the AI. @@ -68,16 +68,12 @@ class VehicleAI : public ZeroedMemoryAllocator */ bool IsActive(); -#ifdef USE_ANGELSCRIPT + #ifdef USE_ANGELSCRIPT // we have to add this to be able to use the class as reference inside scripts - void addRef() - { - }; - - void release() - { - }; -#endif + void addRef(){}; + + void release(){}; + #endif /** * Updates the AI. */ @@ -88,12 +84,12 @@ class VehicleAI : public ZeroedMemoryAllocator * @param [in] id The waypoint ID. * @param [in] point The coordinates of the waypoint. */ - void AddWaypoint(Ogre::String& id, Ogre::Vector3& point); + void AddWaypoint(Ogre::String &id, Ogre::Vector3 &point); /** * Adds a dictionary with waypoints. * @param [in] d Dictionary with waypoints */ - void AddWaypoints(AngelScript::CScriptDictionary& d); + void AddWaypoints(AngelScript::CScriptDictionary &d); /** * Adds a event * @@ -102,7 +98,7 @@ class VehicleAI : public ZeroedMemoryAllocator * * @see Ai_events */ - void AddEvent(Ogre::String& id, int& ev); + void AddEvent(Ogre::String &id, int &ev); /** * Sets a value at a waypoint. * @@ -112,31 +108,31 @@ class VehicleAI : public ZeroedMemoryAllocator * * @see Ai_values */ - void SetValueAtWaypoint(Ogre::String& id, int& value_id, float& value); + void SetValueAtWaypoint(Ogre::String &id, int &value_id, float &value); -private: + private: /** * Updates the AI waypoint. */ void updateWaypoint(); - bool is_waiting;//!< - float wait_time;//!<(seconds) The amount of time the AI has to wait on this waypoint. - - float maxspeed = 50;//!<(KM/H) The max speed the AI is allowed to drive. - Actor* beam;//!< The verhicle the AI is driving. - bool is_enabled = false;//!< True if the AI is driving. - Ogre::Vector3 current_waypoint;//!< The coordinates of the waypoint that the AI is driving to. - int current_waypoint_id = 0;//!< The curent waypoint ID. - std::map waypoints;//!< Map with all waypoints. - std::map waypoint_ids;//!< Map with all waypoint IDs. - std::map waypoint_names;//!< Map with all waypoint names. - std::map waypoint_events;//!< Map with all waypoint events. - std::map waypoint_speed;//!< Map with all waypoint speeds. - std::map waypoint_power;//!< Map with all waypoint engine power. - std::map waypoint_wait_time;//!< Map with all waypoint wait times. - int free_waypoints = 0;//!< The amount of waypoints. - float acc_power = 0.8;//!< The engine power. + bool is_waiting; //!< + float wait_time; //!<(seconds) The amount of time the AI has to wait on this waypoint. + + float maxspeed = 50; //!<(KM/H) The max speed the AI is allowed to drive. + Actor * beam; //!< The verhicle the AI is driving. + bool is_enabled = false; //!< True if the AI is driving. + Ogre::Vector3 current_waypoint; //!< The coordinates of the waypoint that the AI is driving to. + int current_waypoint_id = 0; //!< The curent waypoint ID. + std::map waypoints; //!< Map with all waypoints. + std::map waypoint_ids; //!< Map with all waypoint IDs. + std::map waypoint_names; //!< Map with all waypoint names. + std::map waypoint_events; //!< Map with all waypoint events. + std::map waypoint_speed; //!< Map with all waypoint speeds. + std::map waypoint_power; //!< Map with all waypoint engine power. + std::map waypoint_wait_time; //!< Map with all waypoint wait times. + int free_waypoints = 0; //!< The amount of waypoints. + float acc_power = 0.8; //!< The engine power. }; #endif // USE_ANGELSCRIPT diff --git a/source/main/gfx/AdvancedScreen.h b/source/main/gfx/AdvancedScreen.h index f80abeae5e..d179498541 100644 --- a/source/main/gfx/AdvancedScreen.h +++ b/source/main/gfx/AdvancedScreen.h @@ -26,13 +26,13 @@ #include -#define SET_BIT(var, pos) ((var) |= (1<<(pos))) -#define CLEAR_BIT(var, pos) ((var) &= ~(1<<(pos))) -#define SET_LSB(var) ((var) |= 1) -#define CLEAR_LSB(var) ((var) &= ~1) -#define CHECK_BIT(var,pos) ((var) & (1<<(pos))) +#define SET_BIT(var, pos) ((var) |= (1 << (pos))) +#define CLEAR_BIT(var, pos) ((var) &= ~(1 << (pos))) +#define SET_LSB(var) ((var) |= 1) +#define CLEAR_LSB(var) ((var) &= ~1) +#define CHECK_BIT(var, pos) ((var) & (1 << (pos))) -void save(Ogre::uchar* data, Ogre::uchar* databuf, int mWidth, int mHeight, Ogre::PixelFormat pf, Ogre::String filename) +void save(Ogre::uchar *data, Ogre::uchar *databuf, int mWidth, int mHeight, Ogre::PixelFormat pf, Ogre::String filename) { Ogre::Image img; img.loadDynamicImage(data, mWidth, mHeight, 1, pf, false, 1, 0); @@ -46,11 +46,8 @@ void save(Ogre::uchar* data, Ogre::uchar* databuf, int mWidth, int mHeight, Ogre class AdvancedScreen : public ZeroedMemoryAllocator { -public: - - AdvancedScreen(Ogre::RenderWindow* win, Ogre::String filename) : - win(win) - , filename(filename) + public: + AdvancedScreen(Ogre::RenderWindow *win, Ogre::String filename) : win(win), filename(filename) { } @@ -60,8 +57,7 @@ class AdvancedScreen : public ZeroedMemoryAllocator void addData(Ogre::String name, Ogre::String value) { - if (value.empty()) - return; + if (value.empty()) return; map[name] = value; } @@ -69,24 +65,24 @@ class AdvancedScreen : public ZeroedMemoryAllocator { // please do not misinterpret this feature // its used in the forums like an EXTIF data to display things beside the screenshots - int mWidth = win->getWidth(); + int mWidth = win->getWidth(); int mHeight = win->getHeight(); // grab the image data - Ogre::PixelFormat pf = Ogre::PF_B8G8R8; //win->suggestPixelFormat(); - long isize = mWidth * mHeight * (long)Ogre::PixelUtil::getNumElemBytes(pf); - Ogre::uchar* data = OGRE_ALLOC_T(Ogre::uchar, isize, Ogre::MEMCATEGORY_RENDERSYS); - Ogre::PixelBox pb(mWidth, mHeight, 1, pf, data); + Ogre::PixelFormat pf = Ogre::PF_B8G8R8; // win->suggestPixelFormat(); + long isize = mWidth * mHeight * (long)Ogre::PixelUtil::getNumElemBytes(pf); + Ogre::uchar * data = OGRE_ALLOC_T(Ogre::uchar, isize, Ogre::MEMCATEGORY_RENDERSYS); + Ogre::PixelBox pb(mWidth, mHeight, 1, pf, data); win->copyContentsToMemory(pb); // now do the fancy stuff ;) // 0. allocate enough buffer - Ogre::uchar* databuf = OGRE_ALLOC_T(Ogre::uchar, 32768, Ogre::MEMCATEGORY_RENDERSYS); - char* ptr = (char *)databuf; + Ogre::uchar *databuf = OGRE_ALLOC_T(Ogre::uchar, 32768, Ogre::MEMCATEGORY_RENDERSYS); + char * ptr = (char *)databuf; // header long dsize = 0; - int w = sprintf(ptr, "RORED\n"); + int w = sprintf(ptr, "RORED\n"); ptr += w; dsize += w; @@ -99,16 +95,16 @@ class AdvancedScreen : public ZeroedMemoryAllocator } // now buffer ready, put it into the image - Ogre::uchar* ptri = data; + Ogre::uchar *ptri = data; // set data pointer to the start again - ptr = (char *)databuf; + ptr = (char *)databuf; int bc = 7; - for (long b = 0; b < isize && b < dsize * 8 + 40; b++ , ptri++) // 40 = 5 zero bytes + for (long b = 0; b < isize && b < dsize * 8 + 40; b++, ptri++) // 40 = 5 zero bytes { if (CHECK_BIT(*ptr, bc)) - SET_LSB(*ptri); + SET_LSB(*ptri); else - CLEAR_LSB(*ptri); + CLEAR_LSB(*ptri); bc--; if (bc < 0) { @@ -120,9 +116,8 @@ class AdvancedScreen : public ZeroedMemoryAllocator std::thread(save, data, databuf, mWidth, mHeight, pf, filename).detach(); } -protected: - - Ogre::RenderWindow* win; - Ogre::String filename; + protected: + Ogre::RenderWindow * win; + Ogre::String filename; std::map map; }; diff --git a/source/main/gfx/ColoredTextAreaOverlayElement.cpp b/source/main/gfx/ColoredTextAreaOverlayElement.cpp index 4deb52bfc7..cd4d134c13 100644 --- a/source/main/gfx/ColoredTextAreaOverlayElement.cpp +++ b/source/main/gfx/ColoredTextAreaOverlayElement.cpp @@ -28,10 +28,8 @@ using namespace Ogre; using namespace std; -ColoredTextAreaOverlayElement::ColoredTextAreaOverlayElement(const String& name) - : TextAreaOverlayElement(name) - , m_ValueTop(1.0f) - , m_ValueBottom(0.8f) +ColoredTextAreaOverlayElement::ColoredTextAreaOverlayElement(const String &name) + : TextAreaOverlayElement(name), m_ValueTop(1.0f), m_ValueBottom(0.8f) { } @@ -41,13 +39,13 @@ ColoredTextAreaOverlayElement::~ColoredTextAreaOverlayElement(void) void ColoredTextAreaOverlayElement::setValueBottom(float Value) { - m_ValueTop = Value; + m_ValueTop = Value; mColoursChanged = true; } void ColoredTextAreaOverlayElement::setValueTop(float Value) { - m_ValueBottom = Value; + m_ValueBottom = Value; mColoursChanged = true; } @@ -55,52 +53,38 @@ ColourValue ColoredTextAreaOverlayElement::GetColor(unsigned char ID, float Valu { switch (ID) { - case 0: - return ColourValue(0, 0, 0); // Black - case 1: - return ColourValue(Value, 0, 0); // Red - case 2: - return ColourValue(0, Value, 0); // Green - case 3: - return ColourValue(Value, Value, 0); // Yellow - case 4: - return ColourValue(0, 0, Value); // Blue - case 5: - return ColourValue(0, Value, Value); // Cyan - case 6: - return ColourValue(Value, 0, Value); // Magenta - case 7: - return ColourValue(Value, Value, Value); // White - case 8: - return ColourValue(Value * 0.9, Value * 0.9, Value * 0.9); // Gray - case 9: - return ColourValue(0.5, 0.5, Value * 0.9); // dark blue + case 0: return ColourValue(0, 0, 0); // Black + case 1: return ColourValue(Value, 0, 0); // Red + case 2: return ColourValue(0, Value, 0); // Green + case 3: return ColourValue(Value, Value, 0); // Yellow + case 4: return ColourValue(0, 0, Value); // Blue + case 5: return ColourValue(0, Value, Value); // Cyan + case 6: return ColourValue(Value, 0, Value); // Magenta + case 7: return ColourValue(Value, Value, Value); // White + case 8: return ColourValue(Value * 0.9, Value * 0.9, Value * 0.9); // Gray + case 9: return ColourValue(0.5, 0.5, Value * 0.9); // dark blue } return ColourValue::Black; } -DisplayString ColoredTextAreaOverlayElement::StripColors(const Ogre::String& otext) +DisplayString ColoredTextAreaOverlayElement::StripColors(const Ogre::String &otext) { try { DisplayString text = DisplayString(otext.c_str()); DisplayString StrippedText; - int i; + int i; for (i = 0; i < (int)text.size() - 1; ++i) { - if (text[i] == '^' && - text[i + 1] >= '0' && text[i + 1] <= '9') // This is a color code, ignore it - { - ++i; - } + if (text[i] == '^' && text[i + 1] >= '0' && text[i + 1] <= '9') // This is a color code, ignore it + { ++i; } else { StrippedText.append(1, text[i]); } } // One last character to add because loop went to size()-1 - if (i < (int)text.size()) - StrippedText.append(1, text[i]); + if (i < (int)text.size()) StrippedText.append(1, text[i]); return StrippedText; } catch (...) @@ -109,12 +93,12 @@ DisplayString ColoredTextAreaOverlayElement::StripColors(const Ogre::String& ote return String("UTF8 error (String cannot be displayed with current font set)"); } -void ColoredTextAreaOverlayElement::setCaption(const DisplayString& text) +void ColoredTextAreaOverlayElement::setCaption(const DisplayString &text) { m_Colors.clear(); m_Colors.resize(text.size(), 9); bool noColor = true; - int i, iNumColorCodes = 0, iNumSpaces = 0; + int i, iNumColorCodes = 0, iNumSpaces = 0; for (i = 0; i < (int)text.size() - 1; ++i) { if (text[i] == ' ' || text[i] == '\n') @@ -122,8 +106,7 @@ void ColoredTextAreaOverlayElement::setCaption(const DisplayString& text) // Spaces and newlines are skipped when rendering and as such can't have a color ++iNumSpaces; } - else if (text[i] == '^' && - text[i + 1] >= '0' && text[i + 1] <= '9') // This is a color code + else if (text[i] == '^' && text[i + 1] >= '0' && text[i + 1] <= '9') // This is a color code { // Fill the color array starting from this point to the end with the new color code // adjustments need to made because color codes will be removed and spaces are not counted @@ -131,32 +114,29 @@ void ColoredTextAreaOverlayElement::setCaption(const DisplayString& text) ++i; ++iNumColorCodes; mColoursChanged = true; - noColor = false; + noColor = false; } } - if (noColor) - mColoursChanged = true; + if (noColor) mColoursChanged = true; // Set the caption using the base class, but strip the color codes from it first TextAreaOverlayElement::setCaption(StripColors(text)); } void ColoredTextAreaOverlayElement::updateColours(void) { - if (!mRenderOp.vertexData) - return; + if (!mRenderOp.vertexData) return; // Convert to system-specific RGBA topColour, bottomColour; // Set default to white Root::getSingleton().convertColourValue(ColourValue::White, &topColour); Root::getSingleton().convertColourValue(ColourValue::White, &bottomColour); - HardwareVertexBufferSharedPtr vbuf = - mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); + HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); - //RGBA* pDest = static_cast( + // RGBA* pDest = static_cast( // vbuf->lock(HardwareBuffer::HBL_NORMAL) ); - RGBA* pDest = (RGBA*)malloc(vbuf->getSizeInBytes()); - RGBA* oDest = pDest; + RGBA *pDest = (RGBA *)malloc(vbuf->getSizeInBytes()); + RGBA *oDest = pDest; for (size_t i = 0; i < mAllocSize; ++i) { @@ -177,5 +157,5 @@ void ColoredTextAreaOverlayElement::updateColours(void) } vbuf->writeData(0, vbuf->getSizeInBytes(), oDest, true); free(oDest); - //vbuf->unlock(); + // vbuf->unlock(); } diff --git a/source/main/gfx/ColoredTextAreaOverlayElement.h b/source/main/gfx/ColoredTextAreaOverlayElement.h index fd7c867c31..6a850d3d74 100644 --- a/source/main/gfx/ColoredTextAreaOverlayElement.h +++ b/source/main/gfx/ColoredTextAreaOverlayElement.h @@ -20,27 +20,27 @@ #pragma once -#include -#include - #include "RoRPrerequisites.h" +#include +#include + class ColoredTextAreaOverlayElement : public Ogre::TextAreaOverlayElement { -public: - ColoredTextAreaOverlayElement(const Ogre::String& name); + public: + ColoredTextAreaOverlayElement(const Ogre::String &name); ~ColoredTextAreaOverlayElement(void); - void setValueBottom(float Value); - void setValueTop(float Value); - void setCaption(const Ogre::DisplayString& text); - static Ogre::DisplayString StripColors(const Ogre::String& text); - static Ogre::ColourValue GetColor(unsigned char ID, float Value = 1.0f); + void setValueBottom(float Value); + void setValueTop(float Value); + void setCaption(const Ogre::DisplayString &text); + static Ogre::DisplayString StripColors(const Ogre::String &text); + static Ogre::ColourValue GetColor(unsigned char ID, float Value = 1.0f); void updateColours(void); -protected: + protected: std::vector m_Colors; - float m_ValueTop; - float m_ValueBottom; + float m_ValueTop; + float m_ValueBottom; }; diff --git a/source/main/gfx/ColoredTextAreaOverlayElementFactory.h b/source/main/gfx/ColoredTextAreaOverlayElementFactory.h index 0e0bfd6b51..72128cebbf 100644 --- a/source/main/gfx/ColoredTextAreaOverlayElementFactory.h +++ b/source/main/gfx/ColoredTextAreaOverlayElementFactory.h @@ -20,25 +20,25 @@ #pragma once +#include "ColoredTextAreaOverlayElement.h" #include "RoRPrerequisites.h" #include #include #include -#include "ColoredTextAreaOverlayElement.h" /** Factory for creating TextAreaOverlayElement instances. */ class ColoredTextAreaOverlayElementFactory : public Ogre::OverlayElementFactory { -public: + public: /** See OverlayElementFactory */ - Ogre::OverlayElement* createOverlayElement(const Ogre::String& instanceName) + Ogre::OverlayElement *createOverlayElement(const Ogre::String &instanceName) { return new ColoredTextAreaOverlayElement(instanceName); } /** See OverlayElementFactory */ - const Ogre::String& getTypeName() const + const Ogre::String &getTypeName() const { static Ogre::String name = "ColoredTextArea"; return name; diff --git a/source/main/gfx/DecalManager.cpp b/source/main/gfx/DecalManager.cpp index 2f17923e5a..63b2790655 100644 --- a/source/main/gfx/DecalManager.cpp +++ b/source/main/gfx/DecalManager.cpp @@ -1,3 +1,3 @@ - // TODO: Remove this file - // Temporarily kept as placeholder +// TODO: Remove this file +// Temporarily kept as placeholder diff --git a/source/main/gfx/DecalManager.h b/source/main/gfx/DecalManager.h index 01f0fe5c8b..63b2790655 100644 --- a/source/main/gfx/DecalManager.h +++ b/source/main/gfx/DecalManager.h @@ -1,4 +1,3 @@ - // TODO: Remove this file - // Temporarily kept as placeholder - +// TODO: Remove this file +// Temporarily kept as placeholder diff --git a/source/main/gfx/DustPool.cpp b/source/main/gfx/DustPool.cpp index eb9cf332c3..26e4a9d1f3 100644 --- a/source/main/gfx/DustPool.cpp +++ b/source/main/gfx/DustPool.cpp @@ -20,24 +20,22 @@ #include "DustPool.h" -#include - #include "Application.h" #include "RoRPrerequisites.h" #include "TerrainManager.h" #include "Water.h" +#include + using namespace Ogre; #ifndef _WIN32 // This definitions is needed because the variable is declared but not defined in DustPool - const int DustPool::MAX_DUSTS; +const int DustPool::MAX_DUSTS; #endif // !_WIN32 -DustPool::DustPool(Ogre::SceneManager* sm, const char* dname, int dsize): - allocated(0), - size(std::min(dsize, static_cast(MAX_DUSTS))), - m_is_discarded(false) +DustPool::DustPool(Ogre::SceneManager *sm, const char *dname, int dsize) + : allocated(0), size(std::min(dsize, static_cast(MAX_DUSTS))), m_is_discarded(false) { for (int i = 0; i < size; i++) { @@ -50,34 +48,31 @@ DustPool::DustPool(Ogre::SceneManager* sm, const char* dname, int dsize): sns[i]->attachObject(pss[i]); pss[i]->setCastShadows(false); pss[i]->setVisibilityFlags(DEPTHMAP_DISABLED); - if (pss[i]->getNumEmitters() > 0) - { - pss[i]->getEmitter(0)->setEnabled(false); - } + if (pss[i]->getNumEmitters() > 0) { pss[i]->getEmitter(0)->setEnabled(false); } } } } DustPool::~DustPool() { - assert(m_is_discarded); + assert(m_is_discarded); } -void DustPool::Discard(Ogre::SceneManager* sm) +void DustPool::Discard(Ogre::SceneManager *sm) { - for (int i = 0; i < size; i++) - { - sns[i]->removeAndDestroyAllChildren(); - sm->destroySceneNode(sns[i]); - sns[i] = nullptr; - - if (pss[i]) - { - sm->destroyParticleSystem(pss[i]); - pss[i] = nullptr; - } - } - m_is_discarded = true; + for (int i = 0; i < size; i++) + { + sns[i]->removeAndDestroyAllChildren(); + sm->destroySceneNode(sns[i]); + sns[i] = nullptr; + + if (pss[i]) + { + sm->destroyParticleSystem(pss[i]); + pss[i] = nullptr; + } + } + m_is_discarded = true; } void DustPool::setVisible(bool s) @@ -88,40 +83,40 @@ void DustPool::setVisible(bool s) } } -//Dust +// Dust void DustPool::malloc(Vector3 pos, Vector3 vel, ColourValue col) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - colours[allocated] = col; - types[allocated] = DUST_NORMAL; + colours[allocated] = col; + types[allocated] = DUST_NORMAL; allocated++; } } -//Clumps +// Clumps void DustPool::allocClump(Vector3 pos, Vector3 vel, ColourValue col) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - colours[allocated] = col; - types[allocated] = DUST_CLUMP; + colours[allocated] = col; + types[allocated] = DUST_CLUMP; allocated++; } } -//Rubber smoke +// Rubber smoke void DustPool::allocSmoke(Vector3 pos, Vector3 vel) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - types[allocated] = DUST_RUBBER; + types[allocated] = DUST_RUBBER; allocated++; } } @@ -129,26 +124,25 @@ void DustPool::allocSmoke(Vector3 pos, Vector3 vel) // void DustPool::allocSparks(Vector3 pos, Vector3 vel) { - if (vel.length() < 0.1) - return; // try to prevent emitting sparks while standing + if (vel.length() < 0.1) return; // try to prevent emitting sparks while standing if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - types[allocated] = DUST_SPARKS; + types[allocated] = DUST_SPARKS; allocated++; } } -//Water vapour +// Water vapour void DustPool::allocVapour(Vector3 pos, Vector3 vel, float time) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - types[allocated] = DUST_VAPOUR; - rates[allocated] = 5.0 - time; + types[allocated] = DUST_VAPOUR; + rates[allocated] = 5.0 - time; allocated++; } } @@ -157,10 +151,10 @@ void DustPool::allocDrip(Vector3 pos, Vector3 vel, float time) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - types[allocated] = DUST_DRIP; - rates[allocated] = 5.0 - time; + types[allocated] = DUST_DRIP; + rates[allocated] = 5.0 - time; allocated++; } } @@ -169,9 +163,9 @@ void DustPool::allocSplash(Vector3 pos, Vector3 vel) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - types[allocated] = DUST_SPLASH; + types[allocated] = DUST_SPLASH; allocated++; } } @@ -180,9 +174,9 @@ void DustPool::allocRipple(Vector3 pos, Vector3 vel) { if (allocated < size) { - positions[allocated] = pos; + positions[allocated] = pos; velocities[allocated] = vel; - types[allocated] = DUST_RIPPLE; + types[allocated] = DUST_RIPPLE; allocated++; } } @@ -191,13 +185,12 @@ void DustPool::update() { for (int i = 0; i < allocated; i++) { - ParticleEmitter* emit = pss[i]->getEmitter(0); - Vector3 ndir = velocities[i]; - Real vel = ndir.length(); - ColourValue col = colours[i]; + ParticleEmitter *emit = pss[i]->getEmitter(0); + Vector3 ndir = velocities[i]; + Real vel = ndir.length(); + ColourValue col = colours[i]; - if (vel == 0) - vel += 0.0001; + if (vel == 0) vel += 0.0001; ndir = ndir / vel; emit->setEnabled(true); @@ -212,7 +205,7 @@ void DustPool::update() if (types[i] == DUST_NORMAL) { ndir.y = 0; - ndir = ndir / 2.0; + ndir = ndir / 2.0; col.a = vel * 0.05; emit->setTimeToLive(vel * 0.05 / 0.1); @@ -220,15 +213,14 @@ void DustPool::update() else if (types[i] == DUST_CLUMP) { ndir = ndir / 2.0; - if (ndir.y < 0) - ndir.y = -ndir.y; + if (ndir.y < 0) ndir.y = -ndir.y; col.a = 1.0; } else if (types[i] == DUST_RUBBER) { ndir.y = 0; - ndir = ndir / 4.0; + ndir = ndir / 4.0; col.a = sqrt(vel) * 0.1; col.b = 0.9; @@ -239,7 +231,7 @@ void DustPool::update() } else if (types[i] == DUST_SPARKS) { - //ugh + // ugh } else if (types[i] == DUST_VAPOUR) { @@ -258,8 +250,7 @@ void DustPool::update() } else if (types[i] == DUST_SPLASH) { - if (ndir.y < 0) - ndir.y = -ndir.y / 2.0; + if (ndir.y < 0) ndir.y = -ndir.y / 2.0; emit->setDirection(ndir); diff --git a/source/main/gfx/DustPool.h b/source/main/gfx/DustPool.h index a0c8802979..45f6e29ae2 100644 --- a/source/main/gfx/DustPool.h +++ b/source/main/gfx/DustPool.h @@ -26,23 +26,22 @@ class DustPool : public ZeroedMemoryAllocator { -public: - - DustPool(Ogre::SceneManager* sm, const char* dname, int dsize); + public: + DustPool(Ogre::SceneManager *sm, const char *dname, int dsize); ~DustPool(); - void Discard(Ogre::SceneManager* sm); + void Discard(Ogre::SceneManager *sm); void setVisible(bool s); - //Dust + // Dust void malloc(Ogre::Vector3 pos, Ogre::Vector3 vel, Ogre::ColourValue col = Ogre::ColourValue(0.83, 0.71, 0.64, 1.0)); - //clumps + // clumps void allocClump(Ogre::Vector3 pos, Ogre::Vector3 vel, Ogre::ColourValue col = Ogre::ColourValue(0.83, 0.71, 0.64, 1.0)); - //Rubber smoke + // Rubber smoke void allocSmoke(Ogre::Vector3 pos, Ogre::Vector3 vel); // void allocSparks(Ogre::Vector3 pos, Ogre::Vector3 vel); - //Water vapour + // Water vapour void allocVapour(Ogre::Vector3 pos, Ogre::Vector3 vel, float time); void allocDrip(Ogre::Vector3 pos, Ogre::Vector3 vel, float time); @@ -53,8 +52,7 @@ class DustPool : public ZeroedMemoryAllocator void update(); -protected: - + protected: static const int MAX_DUSTS = 100; enum DustTypes @@ -69,14 +67,14 @@ class DustPool : public ZeroedMemoryAllocator DUST_CLUMP }; - Ogre::ColourValue colours[MAX_DUSTS]; - Ogre::ParticleSystem* pss[MAX_DUSTS]; - Ogre::SceneNode* sns[MAX_DUSTS]; - Ogre::Vector3 positions[MAX_DUSTS]; - Ogre::Vector3 velocities[MAX_DUSTS]; - float rates[MAX_DUSTS]; - int allocated; - int size; - int types[MAX_DUSTS]; - bool m_is_discarded; + Ogre::ColourValue colours[MAX_DUSTS]; + Ogre::ParticleSystem *pss[MAX_DUSTS]; + Ogre::SceneNode * sns[MAX_DUSTS]; + Ogre::Vector3 positions[MAX_DUSTS]; + Ogre::Vector3 velocities[MAX_DUSTS]; + float rates[MAX_DUSTS]; + int allocated; + int size; + int types[MAX_DUSTS]; + bool m_is_discarded; }; diff --git a/source/main/gfx/EnvironmentMap.cpp b/source/main/gfx/EnvironmentMap.cpp index a16c009ec0..cde10b6736 100644 --- a/source/main/gfx/EnvironmentMap.cpp +++ b/source/main/gfx/EnvironmentMap.cpp @@ -25,9 +25,7 @@ #include "SkyManager.h" #include "TerrainManager.h" -RoR::GfxEnvmap::GfxEnvmap(): - m_is_initialized(false), - m_update_round(0) +RoR::GfxEnvmap::GfxEnvmap() : m_is_initialized(false), m_update_round(0) { memset(m_cameras, 0, sizeof(m_cameras)); memset(m_render_targets, 0, sizeof(m_render_targets)); @@ -40,7 +38,7 @@ void RoR::GfxEnvmap::SetupEnvMap() for (int face = 0; face < NUM_FACES; face++) { m_render_targets[face] = m_rtt_texture->getBuffer(face)->getRenderTarget(); - m_cameras[face] = gEnv->sceneManager->createCamera("EnvironmentCamera-" + TOSTRING(face)); + m_cameras[face] = gEnv->sceneManager->createCamera("EnvironmentCamera-" + TOSTRING(face)); m_cameras[face]->setAspectRatio(1.0); m_cameras[face]->setProjectionType(Ogre::PT_PERSPECTIVE); m_cameras[face]->setFixedYawAxis(false); @@ -48,7 +46,7 @@ void RoR::GfxEnvmap::SetupEnvMap() m_cameras[face]->setNearClipDistance(0.1f); m_cameras[face]->setFarClipDistance(gEnv->mainCamera->getFarClipDistance()); - Ogre::Viewport* v = m_render_targets[face]->addViewport(m_cameras[face]); + Ogre::Viewport *v = m_render_targets[face]->addViewport(m_cameras[face]); v->setOverlaysEnabled(false); v->setClearEveryFrame(true); v->setBackgroundColour(gEnv->mainCamera->getViewport()->getBackgroundColour()); @@ -65,22 +63,23 @@ void RoR::GfxEnvmap::SetupEnvMap() if (App::diag_envmap.GetActive()) { // create fancy mesh for debugging the envmap - Ogre::Overlay* overlay = Ogre::OverlayManager::getSingleton().create("EnvMapDebugOverlay"); + Ogre::Overlay *overlay = Ogre::OverlayManager::getSingleton().create("EnvMapDebugOverlay"); if (overlay) { Ogre::Vector3 position = Ogre::Vector3::ZERO; - float scale = 1.0f; + float scale = 1.0f; - Ogre::MeshPtr mesh = Ogre::MeshManager::getSingletonPtr()->createManual("cubeMapDebug", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + Ogre::MeshPtr mesh = Ogre::MeshManager::getSingletonPtr()->createManual( + "cubeMapDebug", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // create sub mesh - Ogre::SubMesh* sub = mesh->createSubMesh(); + Ogre::SubMesh *sub = mesh->createSubMesh(); // Initialize render operation sub->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; // sub->useSharedVertices = true; mesh->sharedVertexData = new Ogre::VertexData; - sub->indexData = new Ogre::IndexData; + sub->indexData = new Ogre::IndexData; // Create vertex declaration size_t offset = 0; @@ -89,35 +88,33 @@ void RoR::GfxEnvmap::SetupEnvMap() mesh->sharedVertexData->vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES); // Create and bind vertex buffer - mesh->sharedVertexData->vertexCount = 14; - Ogre::HardwareVertexBufferSharedPtr vertexBuffer = - Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - mesh->sharedVertexData->vertexDeclaration->getVertexSize(0), - mesh->sharedVertexData->vertexCount, - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); + mesh->sharedVertexData->vertexCount = 14; + Ogre::HardwareVertexBufferSharedPtr vertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + mesh->sharedVertexData->vertexDeclaration->getVertexSize(0), mesh->sharedVertexData->vertexCount, + Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); mesh->sharedVertexData->vertexBufferBinding->setBinding(0, vertexBuffer); // Vertex data static const float vertexData[] = { // Position Texture coordinates // Index - 0.0, 2.0, -1.0, 1.0, 1.0, // 0 - 0.0, 1.0, -1.0, -1.0, 1.0, // 1 - 1.0, 2.0, -1.0, 1.0, -1.0, // 2 + 0.0, 2.0, -1.0, 1.0, 1.0, // 0 + 0.0, 1.0, -1.0, -1.0, 1.0, // 1 + 1.0, 2.0, -1.0, 1.0, -1.0, // 2 1.0, 1.0, -1.0, -1.0, -1.0, // 3 - 2.0, 2.0, 1.0, 1.0, -1.0, // 4 - 2.0, 1.0, 1.0, -1.0, -1.0, // 5 - 3.0, 2.0, 1.0, 1.0, 1.0, // 6 - 3.0, 1.0, 1.0, -1.0, 1.0, // 7 - 4.0, 2.0, -1.0, 1.0, 1.0, // 8 - 4.0, 1.0, -1.0, -1.0, 1.0, // 9 - 1.0, 3.0, -1.0, 1.0, 1.0, // 10 - 2.0, 3.0, 1.0, 1.0, 1.0, // 11 - 1.0, 0.0, -1.0, -1.0, 1.0, // 12 - 2.0, 0.0, 1.0, -1.0, 1.0, // 13 + 2.0, 2.0, 1.0, 1.0, -1.0, // 4 + 2.0, 1.0, 1.0, -1.0, -1.0, // 5 + 3.0, 2.0, 1.0, 1.0, 1.0, // 6 + 3.0, 1.0, 1.0, -1.0, 1.0, // 7 + 4.0, 2.0, -1.0, 1.0, 1.0, // 8 + 4.0, 1.0, -1.0, -1.0, 1.0, // 9 + 1.0, 3.0, -1.0, 1.0, 1.0, // 10 + 2.0, 3.0, 1.0, 1.0, 1.0, // 11 + 1.0, 0.0, -1.0, -1.0, 1.0, // 12 + 2.0, 0.0, 1.0, -1.0, 1.0, // 13 }; // Fill vertex buffer - float* pData = static_cast(vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); + float *pData = static_cast(vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (size_t vertex = 0, i = 0; vertex < mesh->sharedVertexData->vertexCount; vertex++) { // Position @@ -133,29 +130,26 @@ void RoR::GfxEnvmap::SetupEnvMap() vertexBuffer->unlock(); // Create index buffer - sub->indexData->indexCount = 36; - Ogre::HardwareIndexBufferSharedPtr indexBuffer = - Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( - Ogre::HardwareIndexBuffer::IT_16BIT, - sub->indexData->indexCount, - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); + sub->indexData->indexCount = 36; + Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( + Ogre::HardwareIndexBuffer::IT_16BIT, sub->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); sub->indexData->indexBuffer = indexBuffer; // Index data static const Ogre::uint16 indexData[] = { // Indices // Face - 0, 1, 2, // 0 - 2, 1, 3, // 1 - 2, 3, 4, // 2 - 4, 3, 5, // 3 - 4, 5, 6, // 4 - 6, 5, 7, // 5 - 6, 7, 8, // 6 - 8, 7, 9, // 7 - 10, 2, 11, // 8 - 11, 2, 4, // 9 - 3, 12, 5, // 10 - 5, 12, 13, // 11 + 0, 1, 2, // 0 + 2, 1, 3, // 1 + 2, 3, 4, // 2 + 4, 3, 5, // 3 + 4, 5, 6, // 4 + 6, 5, 7, // 5 + 6, 7, 8, // 6 + 8, 7, 9, // 7 + 10, 2, 11, // 8 + 11, 2, 4, // 9 + 3, 12, 5, // 10 + 5, 12, 13, // 11 }; // Fill index buffer @@ -165,13 +159,13 @@ void RoR::GfxEnvmap::SetupEnvMap() mesh->_setBoundingSphereRadius(10); mesh->load(); - Ogre::Entity* e = gEnv->sceneManager->createEntity(mesh->getName()); + Ogre::Entity *e = gEnv->sceneManager->createEntity(mesh->getName()); e->setCastShadows(false); e->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1); e->setVisible(true); e->setMaterialName("tracks/EnvMapDebug"); - Ogre::SceneNode* mDebugSceneNode = new Ogre::SceneNode(gEnv->sceneManager); + Ogre::SceneNode *mDebugSceneNode = new Ogre::SceneNode(gEnv->sceneManager); mDebugSceneNode->attachObject(e); mDebugSceneNode->setPosition(Ogre::Vector3(0, 0, -5)); mDebugSceneNode->setFixedYawAxis(true, Ogre::Vector3::UNIT_Y); @@ -184,7 +178,7 @@ void RoR::GfxEnvmap::SetupEnvMap() } Ogre::Vector3 center = App::GetSimTerrain()->getMaxTerrainSize() / 2; - center.y = App::GetSimTerrain()->GetHeightAt(center.x, center.z) + 1.0f; + center.y = App::GetSimTerrain()->GetHeightAt(center.x, center.z) + 1.0f; UpdateEnvMap(center, nullptr); } @@ -200,13 +194,10 @@ RoR::GfxEnvmap::~GfxEnvmap() } } -void RoR::GfxEnvmap::UpdateEnvMap(Ogre::Vector3 center, GfxActor* gfx_actor) +void RoR::GfxEnvmap::UpdateEnvMap(Ogre::Vector3 center, GfxActor *gfx_actor) { const int update_rate = m_is_initialized ? App::gfx_envmap_rate.GetActive() : NUM_FACES; - if (!App::gfx_envmap_enabled.GetActive() || update_rate == 0) - { - return; - } + if (!App::gfx_envmap_enabled.GetActive() || update_rate == 0) { return; } for (int i = 0; i < NUM_FACES; i++) { @@ -224,18 +215,14 @@ void RoR::GfxEnvmap::UpdateEnvMap(Ogre::Vector3 center, GfxActor* gfx_actor) #ifdef USE_CAELUM // caelum needs to know that we changed the cameras if (App::GetSimTerrain()->getSkyManager()) - { - App::GetSimTerrain()->getSkyManager()->NotifySkyCameraChanged(m_cameras[m_update_round]); - } + { App::GetSimTerrain()->getSkyManager()->NotifySkyCameraChanged(m_cameras[m_update_round]); } #endif // USE_CAELUM m_render_targets[m_update_round]->update(); m_update_round = (m_update_round + 1) % NUM_FACES; } #ifdef USE_CAELUM if (App::GetSimTerrain()->getSkyManager()) - { - App::GetSimTerrain()->getSkyManager()->NotifySkyCameraChanged(gEnv->mainCamera); - } + { App::GetSimTerrain()->getSkyManager()->NotifySkyCameraChanged(gEnv->mainCamera); } #endif // USE_CAELUM if (gfx_actor != nullptr) diff --git a/source/main/gfx/EnvironmentMap.h b/source/main/gfx/EnvironmentMap.h index 713bc44643..cbdc11e829 100644 --- a/source/main/gfx/EnvironmentMap.h +++ b/source/main/gfx/EnvironmentMap.h @@ -22,33 +22,32 @@ #include "ForwardDeclarations.h" -#include #include +#include -namespace RoR { - -/// A dynamic environment probe; Creates a cubemap with realtime reflections around specified point. -class GfxEnvmap +namespace RoR { -public: - - GfxEnvmap(); - ~GfxEnvmap(); - void SetupEnvMap(); - void UpdateEnvMap(Ogre::Vector3 center, GfxActor* gfx_actor); + /// A dynamic environment probe; Creates a cubemap with realtime reflections around specified point. + class GfxEnvmap + { + public: + GfxEnvmap(); + ~GfxEnvmap(); -private: + void SetupEnvMap(); + void UpdateEnvMap(Ogre::Vector3 center, GfxActor *gfx_actor); - static const unsigned int NUM_FACES = 6; + private: + static const unsigned int NUM_FACES = 6; - void InitEnvMap(Ogre::Vector3 center); + void InitEnvMap(Ogre::Vector3 center); - Ogre::Camera* m_cameras[NUM_FACES]; - Ogre::RenderTarget* m_render_targets[NUM_FACES]; - Ogre::TexturePtr m_rtt_texture; - bool m_is_initialized; - int m_update_round; /// Render targets are updated one-by-one; this is the index of next target to update. -}; + Ogre::Camera * m_cameras[NUM_FACES]; + Ogre::RenderTarget *m_render_targets[NUM_FACES]; + Ogre::TexturePtr m_rtt_texture; + bool m_is_initialized; + int m_update_round; /// Render targets are updated one-by-one; this is the index of next target to update. + }; } // namespace RoR diff --git a/source/main/gfx/GfxActor.cpp b/source/main/gfx/GfxActor.cpp index b90aee6a89..9411eba505 100644 --- a/source/main/gfx/GfxActor.cpp +++ b/source/main/gfx/GfxActor.cpp @@ -21,89 +21,71 @@ #include "GfxActor.h" -#include "ApproxMath.h" #include "AirBrake.h" +#include "ApproxMath.h" #include "AutoPilot.h" #include "Beam.h" #include "BeamEngine.h" // EngineSim #include "Collisions.h" -#include "Renderdash.h" // classic 'renderdash' material #include "DustPool.h" // General particle gfx -#include "HydraxWater.h" #include "FlexAirfoil.h" #include "FlexBody.h" #include "FlexMeshWheel.h" #include "FlexObj.h" +#include "HydraxWater.h" #include "InputEngine.h" // TODO: Keys shouldn't be queried from here, but buffered in sim. loop ~ only_a_ptr, 06/2018 #include "MeshObject.h" #include "MovableText.h" +#include "Renderdash.h" // classic 'renderdash' material #include "RigSpawner.h" #include "RoRFrameListener.h" // SimController -#include "SlideNode.h" #include "SkyManager.h" +#include "SlideNode.h" #include "SoundScriptManager.h" -#include "Utils.h" #include "TerrainManager.h" -#include "imgui.h" #include "TurboJet.h" #include "TurboProp.h" +#include "Utils.h" +#include "imgui.h" #include #include #include -#include #include #include -#include #include #include -#include #include RoR::GfxActor::SimBuffer::SimBuffer() - : simbuf_ap_heading_mode(Autopilot::HEADING_NONE) - , simbuf_ap_heading_value(0) - , simbuf_ap_alt_mode(Autopilot::ALT_NONE) - , simbuf_ap_alt_value(1000) // from AutoPilot::reset() - , simbuf_ap_ias_mode(false) - , simbuf_ap_ias_value(150) // from AutoPilot::reset() - , simbuf_ap_gpws_mode(false) - , simbuf_ap_ils_available(false) - , simbuf_ap_ils_vdev(0.f) - , simbuf_ap_ils_hdev(0.f) - , simbuf_ap_vs_value(0) -{} - -RoR::GfxActor::GfxActor(Actor* actor, ActorSpawner* spawner, std::string ogre_resource_group, - std::vector& gfx_nodes, std::vector& props, - int driverseat_prop_idx, RoR::Renderdash* renderdash): - m_actor(actor), - m_custom_resource_group(ogre_resource_group), - m_vidcam_state(VideoCamState::VCSTATE_ENABLED_ONLINE), - m_debug_view(DebugViewType::DEBUGVIEW_NONE), - m_last_debug_view(DebugViewType::DEBUGVIEW_SKELETON), - m_rods_parent_scenenode(nullptr), - m_gfx_nodes(gfx_nodes), - m_props(props), - m_cab_scene_node(nullptr), - m_cab_mesh(nullptr), - m_cab_entity(nullptr), - m_driverseat_prop_index(driverseat_prop_idx), - m_renderdash(renderdash), - m_prop_anim_crankfactor_prev(0.f), - m_prop_anim_shift_timer(0.f), - m_survey_map_entity(nullptr), - m_beaconlight_active(true), // 'true' will trigger SetBeaconsEnabled(false) on the first buffer update - m_initialized(false) + : simbuf_ap_heading_mode(Autopilot::HEADING_NONE), simbuf_ap_heading_value(0), simbuf_ap_alt_mode(Autopilot::ALT_NONE), + simbuf_ap_alt_value(1000) // from AutoPilot::reset() + , + simbuf_ap_ias_mode(false), simbuf_ap_ias_value(150) // from AutoPilot::reset() + , + simbuf_ap_gpws_mode(false), simbuf_ap_ils_available(false), simbuf_ap_ils_vdev(0.f), simbuf_ap_ils_hdev(0.f), + simbuf_ap_vs_value(0) +{ +} + +RoR::GfxActor::GfxActor(Actor *actor, ActorSpawner *spawner, std::string ogre_resource_group, std::vector &gfx_nodes, + std::vector &props, int driverseat_prop_idx, RoR::Renderdash *renderdash) + : m_actor(actor), m_custom_resource_group(ogre_resource_group), m_vidcam_state(VideoCamState::VCSTATE_ENABLED_ONLINE), + m_debug_view(DebugViewType::DEBUGVIEW_NONE), m_last_debug_view(DebugViewType::DEBUGVIEW_SKELETON), + m_rods_parent_scenenode(nullptr), m_gfx_nodes(gfx_nodes), m_props(props), m_cab_scene_node(nullptr), m_cab_mesh(nullptr), + m_cab_entity(nullptr), m_driverseat_prop_index(driverseat_prop_idx), m_renderdash(renderdash), + m_prop_anim_crankfactor_prev(0.f), m_prop_anim_shift_timer(0.f), m_survey_map_entity(nullptr), + m_beaconlight_active(true), // 'true' will trigger SetBeaconsEnabled(false) on the first buffer update + m_initialized(false) { // Setup particles - RoR::GfxScene& dustman = RoR::App::GetSimController()->GetGfxScene(); - m_particles_drip = dustman.GetDustPool("drip"); - m_particles_misc = dustman.GetDustPool("dust"); // Dust, water vapour, tyre smoke - m_particles_splash = dustman.GetDustPool("splash"); - m_particles_ripple = dustman.GetDustPool("ripple"); - m_particles_sparks = dustman.GetDustPool("sparks"); - m_particles_clump = dustman.GetDustPool("clump"); + RoR::GfxScene &dustman = RoR::App::GetSimController()->GetGfxScene(); + m_particles_drip = dustman.GetDustPool("drip"); + m_particles_misc = dustman.GetDustPool("dust"); // Dust, water vapour, tyre smoke + m_particles_splash = dustman.GetDustPool("splash"); + m_particles_ripple = dustman.GetDustPool("ripple"); + m_particles_sparks = dustman.GetDustPool("sparks"); + m_particles_clump = dustman.GetDustPool("clump"); m_simbuf.simbuf_nodes.reset(new NodeData[actor->ar_num_nodes]); m_simbuf.simbuf_aeroengines.resize(actor->ar_num_aeroengines); @@ -111,11 +93,12 @@ RoR::GfxActor::GfxActor(Actor* actor, ActorSpawner* spawner, std::string ogre_re m_simbuf.simbuf_airbrakes.resize(spawner->GetMemoryRequirements().num_airbrakes); // Attributes - m_attr.xa_speedo_highest_kph = actor->ar_speedo_max_kph; // TODO: Remove the attribute from Actor altogether ~ only_a_ptr, 05/2018 + m_attr.xa_speedo_highest_kph = + actor->ar_speedo_max_kph; // TODO: Remove the attribute from Actor altogether ~ only_a_ptr, 05/2018 m_attr.xa_speedo_use_engine_max_rpm = actor->ar_gui_use_engine_max_rpm; // TODO: ditto - m_attr.xa_camera0_pos_node = 0; - m_attr.xa_camera0_roll_node = 0; - m_attr.xa_has_autopilot = (actor->ar_autopilot != nullptr); + m_attr.xa_camera0_pos_node = 0; + m_attr.xa_camera0_roll_node = 0; + m_attr.xa_has_autopilot = (actor->ar_autopilot != nullptr); if (actor->ar_num_cameras > 0) { m_attr.xa_camera0_pos_node = actor->ar_camera_node_pos[0]; @@ -123,7 +106,7 @@ RoR::GfxActor::GfxActor(Actor* actor, ActorSpawner* spawner, std::string ogre_re } if (actor->ar_engine != nullptr) { - m_attr.xa_num_gears = actor->ar_engine->getNumGears(); + m_attr.xa_num_gears = actor->ar_engine->getNumGears(); m_attr.xa_engine_max_rpm = actor->ar_engine->getMaxRPM(); } } @@ -134,7 +117,7 @@ RoR::GfxActor::~GfxActor() this->SetVideoCamState(VideoCamState::VCSTATE_DISABLED); while (!m_videocameras.empty()) { - VideoCamera& vcam = m_videocameras.back(); + VideoCamera &vcam = m_videocameras.back(); Ogre::TextureManager::getSingleton().remove(vcam.vcam_render_tex->getHandle()); vcam.vcam_render_tex.setNull(); vcam.vcam_render_target = nullptr; // Invalidated with parent texture @@ -146,11 +129,11 @@ RoR::GfxActor::~GfxActor() // Dispose rods if (m_rods_parent_scenenode != nullptr) { - for (Rod& rod: m_rods) + for (Rod &rod : m_rods) { - Ogre::MovableObject* ogre_object = rod.rod_scenenode->getAttachedObject(0); + Ogre::MovableObject *ogre_object = rod.rod_scenenode->getAttachedObject(0); rod.rod_scenenode->detachAllObjects(); - gEnv->sceneManager->destroyEntity(static_cast(ogre_object)); + gEnv->sceneManager->destroyEntity(static_cast(ogre_object)); } m_rods.clear(); @@ -162,10 +145,7 @@ RoR::GfxActor::~GfxActor() // delete meshwheels for (size_t i = 0; i < m_wheels.size(); i++) { - if (m_wheels[i].wx_flex_mesh != nullptr) - { - delete m_wheels[i].wx_flex_mesh; - } + if (m_wheels[i].wx_flex_mesh != nullptr) { delete m_wheels[i].wx_flex_mesh; } if (m_wheels[i].wx_scenenode != nullptr) { m_wheels[i].wx_scenenode->removeAndDestroyAllChildren(); @@ -174,7 +154,7 @@ RoR::GfxActor::~GfxActor() } // delete airbrakes - for (AirbrakeGfx& abx: m_gfx_airbrakes) + for (AirbrakeGfx &abx : m_gfx_airbrakes) { // scene node abx.abx_scenenode->detachAllObjects(); @@ -187,20 +167,17 @@ RoR::GfxActor::~GfxActor() m_gfx_airbrakes.clear(); // Delete props - for (prop_t & prop: m_props) + for (prop_t &prop : m_props) { for (int k = 0; k < 4; ++k) { if (prop.beacon_flare_billboard_scene_node[k]) { - Ogre::SceneNode* scene_node = prop.beacon_flare_billboard_scene_node[k]; + Ogre::SceneNode *scene_node = prop.beacon_flare_billboard_scene_node[k]; scene_node->removeAndDestroyAllChildren(); gEnv->sceneManager->destroySceneNode(scene_node); } - if (prop.beacon_light[k]) - { - gEnv->sceneManager->destroyLight(prop.beacon_light[k]); - } + if (prop.beacon_light[k]) { gEnv->sceneManager->destroyLight(prop.beacon_light[k]); } } if (prop.scene_node) @@ -213,19 +190,13 @@ RoR::GfxActor::~GfxActor() prop.wheel->removeAndDestroyAllChildren(); gEnv->sceneManager->destroySceneNode(prop.wheel); } - if (prop.mo) - { - delete prop.mo; - } - if (prop.wheelmo) - { - delete prop.wheelmo; - } + if (prop.mo) { delete prop.mo; } + if (prop.wheelmo) { delete prop.wheelmo; } } m_props.clear(); // Delete flexbodies - for (FlexBody* fb: m_flexbodies) + for (FlexBody *fb : m_flexbodies) { delete fb; } @@ -245,26 +216,20 @@ RoR::GfxActor::~GfxActor() } // Delete old dashboard RTT - if (m_renderdash != nullptr) - { - delete m_renderdash; - } + if (m_renderdash != nullptr) { delete m_renderdash; } } void RoR::GfxActor::AddMaterialFlare(int flareid, Ogre::MaterialPtr m) { RoR::GfxActor::FlareMaterial binding; - binding.flare_index = flareid; + binding.flare_index = flareid; binding.mat_instance = m; - if (m.isNull()) - return; - Ogre::Technique* tech = m->getTechnique(0); - if (!tech) - return; - Ogre::Pass* p = tech->getPass(0); - if (!p) - return; + if (m.isNull()) return; + Ogre::Technique *tech = m->getTechnique(0); + if (!tech) return; + Ogre::Pass *p = tech->getPass(0); + if (!p) return; // save emissive colour and then set to zero (light disabled by default) binding.emissive_color = p->getSelfIllumination(); p->setSelfIllumination(Ogre::ColourValue::ZERO); @@ -274,27 +239,22 @@ void RoR::GfxActor::AddMaterialFlare(int flareid, Ogre::MaterialPtr m) void RoR::GfxActor::SetMaterialFlareOn(int flare_index, bool state_on) { - for (FlareMaterial& entry: m_flare_materials) + for (FlareMaterial &entry : m_flare_materials) { - if (entry.flare_index != flare_index) - { - continue; - } + if (entry.flare_index != flare_index) { continue; } const int num_techniques = static_cast(entry.mat_instance->getNumTechniques()); for (int i = 0; i < num_techniques; i++) { - Ogre::Technique* tech = entry.mat_instance->getTechnique(i); - if (!tech) - continue; + Ogre::Technique *tech = entry.mat_instance->getTechnique(i); + if (!tech) continue; if (tech->getSchemeName() == "glow") { // glowing technique // set the ambient value as glow amount - Ogre::Pass* p = tech->getPass(0); - if (!p) - continue; + Ogre::Pass *p = tech->getPass(0); + if (!p) continue; if (state_on) { @@ -312,16 +272,13 @@ void RoR::GfxActor::SetMaterialFlareOn(int flare_index, bool state_on) else { // normal technique - Ogre::Pass* p = tech->getPass(0); - if (!p) - continue; + Ogre::Pass *p = tech->getPass(0); + if (!p) continue; - Ogre::TextureUnitState* tus = p->getTextureUnitState(0); - if (!tus) - continue; + Ogre::TextureUnitState *tus = p->getTextureUnitState(0); + if (!tus) continue; - if (tus->getNumFrames() < 2) - continue; + if (tus->getNumFrames() < 2) continue; int frame = state_on ? 1 : 0; @@ -339,11 +296,10 @@ void RoR::GfxActor::SetMaterialFlareOn(int flare_index, bool state_on) void RoR::GfxActor::RegisterCabMaterial(Ogre::MaterialPtr mat, Ogre::MaterialPtr mat_trans) { // Material instances of this actor - m_cab_mat_visual = mat; + m_cab_mat_visual = mat; m_cab_mat_visual_trans = mat_trans; - if (mat->getTechnique(0)->getNumPasses() == 1) - return; // No emissive pass -> nothing to do. + if (mat->getTechnique(0)->getNumPasses() == 1) return; // No emissive pass -> nothing to do. m_cab_mat_template_emissive = mat->clone("CabMaterialEmissive-" + mat->getName(), true, m_custom_resource_group); @@ -361,14 +317,14 @@ void RoR::GfxActor::SetCabLightsActive(bool state_on) // but in order to maintain all the existing material features working together, // we need to avoid any material swapping on runtime. ~ only_a_ptr, 05/2017 Ogre::MaterialPtr template_mat = (state_on) ? m_cab_mat_template_emissive : m_cab_mat_template_plain; - Ogre::Technique* dest_tech = m_cab_mat_visual->getTechnique(0); - Ogre::Technique* templ_tech = template_mat->getTechnique(0); + Ogre::Technique * dest_tech = m_cab_mat_visual->getTechnique(0); + Ogre::Technique * templ_tech = template_mat->getTechnique(0); dest_tech->removeAllPasses(); for (unsigned short i = 0; i < templ_tech->getNumPasses(); ++i) { - Ogre::Pass* templ_pass = templ_tech->getPass(i); - Ogre::Pass* dest_pass = dest_tech->createPass(); - *dest_pass = *templ_pass; // Copy the pass! Reference: http://www.ogre3d.org/forums/viewtopic.php?f=2&t=83453 + Ogre::Pass *templ_pass = templ_tech->getPass(i); + Ogre::Pass *dest_pass = dest_tech->createPass(); + *dest_pass = *templ_pass; // Copy the pass! Reference: http://www.ogre3d.org/forums/viewtopic.php?f=2&t=83453 } m_cab_mat_visual->compile(); } @@ -381,92 +337,81 @@ void RoR::GfxActor::SetVideoCamState(VideoCamState state) } const bool enable = (state == VideoCamState::VCSTATE_ENABLED_ONLINE); - for (VideoCamera vidcam: m_videocameras) + for (VideoCamera vidcam : m_videocameras) { if (vidcam.vcam_render_target != nullptr) { vidcam.vcam_render_target->setActive(enable); if (enable) - vidcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(vidcam.vcam_render_tex->getName()); + vidcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName( + vidcam.vcam_render_tex->getName()); else - vidcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(vidcam.vcam_off_tex_name); + vidcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName( + vidcam.vcam_off_tex_name); continue; } - if (vidcam.vcam_render_window != nullptr) - { - vidcam.vcam_render_window->setActive(enable); - } + if (vidcam.vcam_render_window != nullptr) { vidcam.vcam_render_window->setActive(enable); } } m_vidcam_state = state; } -RoR::GfxActor::VideoCamera::VideoCamera(): - vcam_type(VideoCamType::VCTYPE_INVALID), // VideoCamType - vcam_node_center(node_t::INVALID_IDX), - vcam_node_dir_y(node_t::INVALID_IDX), - vcam_node_dir_z(node_t::INVALID_IDX), - vcam_node_alt_pos(node_t::INVALID_IDX), - vcam_node_lookat(node_t::INVALID_IDX), - vcam_pos_offset(Ogre::Vector3::ZERO), // Ogre::Vector3 - vcam_ogre_camera(nullptr), // Ogre::Camera* - vcam_render_target(nullptr), // Ogre::RenderTexture* - vcam_debug_node(nullptr), // Ogre::SceneNode* - vcam_render_window(nullptr), // Ogre::RenderWindow* - vcam_prop_scenenode(nullptr) // Ogre::SceneNode* -{} - -RoR::GfxActor::NodeGfx::NodeGfx(uint16_t node_idx): - nx_node_idx(node_idx), - nx_wet_time_sec(-1.f), // node is dry - nx_no_particles(false), - nx_may_get_wet(false), - nx_is_hot(false), - nx_no_sparks(true), - nx_under_water_prev(false) -{} +RoR::GfxActor::VideoCamera::VideoCamera() + : vcam_type(VideoCamType::VCTYPE_INVALID), // VideoCamType + vcam_node_center(node_t::INVALID_IDX), vcam_node_dir_y(node_t::INVALID_IDX), vcam_node_dir_z(node_t::INVALID_IDX), + vcam_node_alt_pos(node_t::INVALID_IDX), vcam_node_lookat(node_t::INVALID_IDX), + vcam_pos_offset(Ogre::Vector3::ZERO), // Ogre::Vector3 + vcam_ogre_camera(nullptr), // Ogre::Camera* + vcam_render_target(nullptr), // Ogre::RenderTexture* + vcam_debug_node(nullptr), // Ogre::SceneNode* + vcam_render_window(nullptr), // Ogre::RenderWindow* + vcam_prop_scenenode(nullptr) // Ogre::SceneNode* +{ +} + +RoR::GfxActor::NodeGfx::NodeGfx(uint16_t node_idx) + : nx_node_idx(node_idx), nx_wet_time_sec(-1.f), // node is dry + nx_no_particles(false), nx_may_get_wet(false), nx_is_hot(false), nx_no_sparks(true), nx_under_water_prev(false) +{ +} void RoR::GfxActor::UpdateVideoCameras(float dt_sec) { - if (m_vidcam_state != VideoCamState::VCSTATE_ENABLED_ONLINE) - return; + if (m_vidcam_state != VideoCamState::VCSTATE_ENABLED_ONLINE) return; - for (GfxActor::VideoCamera vidcam: m_videocameras) + for (GfxActor::VideoCamera vidcam : m_videocameras) { #ifdef USE_CAELUM // caelum needs to know that we changed the cameras - SkyManager* sky = App::GetSimTerrain()->getSkyManager(); + SkyManager *sky = App::GetSimTerrain()->getSkyManager(); if ((sky != nullptr) && (RoR::App::app_state.GetActive() == RoR::AppState::SIMULATION)) - { - sky->NotifySkyCameraChanged(vidcam.vcam_ogre_camera); - } + { sky->NotifySkyCameraChanged(vidcam.vcam_ogre_camera); } #endif // USE_CAELUM - if ((vidcam.vcam_type == VideoCamType::VCTYPE_MIRROR_PROP_LEFT) - || (vidcam.vcam_type == VideoCamType::VCTYPE_MIRROR_PROP_RIGHT)) + if ((vidcam.vcam_type == VideoCamType::VCTYPE_MIRROR_PROP_LEFT) || + (vidcam.vcam_type == VideoCamType::VCTYPE_MIRROR_PROP_RIGHT)) { // Mirror prop - special processing. - float mirror_angle = 0.f; + float mirror_angle = 0.f; Ogre::Vector3 offset(Ogre::Vector3::ZERO); if (vidcam.vcam_type == VideoCamType::VCTYPE_MIRROR_PROP_LEFT) { mirror_angle = m_actor->ar_left_mirror_angle; - offset = Ogre::Vector3(0.07f, -0.22f, 0); + offset = Ogre::Vector3(0.07f, -0.22f, 0); } else { mirror_angle = m_actor->ar_right_mirror_angle; - offset = Ogre::Vector3(0.07f, +0.22f, 0); + offset = Ogre::Vector3(0.07f, +0.22f, 0); } - Ogre::Vector3 normal = vidcam.vcam_prop_scenenode->getOrientation() - * Ogre::Vector3(cos(mirror_angle), sin(mirror_angle), 0.0f); - Ogre::Vector3 center = vidcam.vcam_prop_scenenode->getPosition() - + vidcam.vcam_prop_scenenode->getOrientation() * offset; - Ogre::Radian roll = Ogre::Degree(360) - - Ogre::Radian(asin(m_actor->getDirection().dotProduct(Ogre::Vector3::UNIT_Y))); + Ogre::Vector3 normal = + vidcam.vcam_prop_scenenode->getOrientation() * Ogre::Vector3(cos(mirror_angle), sin(mirror_angle), 0.0f); + Ogre::Vector3 center = + vidcam.vcam_prop_scenenode->getPosition() + vidcam.vcam_prop_scenenode->getOrientation() * offset; + Ogre::Radian roll = Ogre::Degree(360) - Ogre::Radian(asin(m_actor->getDirection().dotProduct(Ogre::Vector3::UNIT_Y))); - Ogre::Plane plane = Ogre::Plane(normal, center); + Ogre::Plane plane = Ogre::Plane(normal, center); Ogre::Vector3 project = plane.projectVector(gEnv->mainCamera->getPosition() - center); vidcam.vcam_ogre_camera->setPosition(center); @@ -477,36 +422,33 @@ void RoR::GfxActor::UpdateVideoCameras(float dt_sec) } // update the texture now, otherwise shuttering - if (vidcam.vcam_render_target != nullptr) - vidcam.vcam_render_target->update(); + if (vidcam.vcam_render_target != nullptr) vidcam.vcam_render_target->update(); - if (vidcam.vcam_render_window != nullptr) - vidcam.vcam_render_window->update(); + if (vidcam.vcam_render_window != nullptr) vidcam.vcam_render_window->update(); // get the normal of the camera plane now - GfxActor::NodeData* node_buf = m_simbuf.simbuf_nodes.get(); + GfxActor::NodeData *node_buf = m_simbuf.simbuf_nodes.get(); const Ogre::Vector3 abs_pos_center = node_buf[vidcam.vcam_node_center].AbsPosition; - const Ogre::Vector3 abs_pos_z = node_buf[vidcam.vcam_node_dir_z].AbsPosition; - const Ogre::Vector3 abs_pos_y = node_buf[vidcam.vcam_node_dir_y].AbsPosition; - Ogre::Vector3 normal = (-(abs_pos_center - abs_pos_z)).crossProduct(-(abs_pos_center - abs_pos_y)); + const Ogre::Vector3 abs_pos_z = node_buf[vidcam.vcam_node_dir_z].AbsPosition; + const Ogre::Vector3 abs_pos_y = node_buf[vidcam.vcam_node_dir_y].AbsPosition; + Ogre::Vector3 normal = (-(abs_pos_center - abs_pos_z)).crossProduct(-(abs_pos_center - abs_pos_y)); normal.normalise(); // add user set offset - Ogre::Vector3 pos = node_buf[vidcam.vcam_node_alt_pos].AbsPosition + - (vidcam.vcam_pos_offset.x * normal) + - (vidcam.vcam_pos_offset.y * (abs_pos_center - abs_pos_y)) + - (vidcam.vcam_pos_offset.z * (abs_pos_center - abs_pos_z)); - - //avoid the camera roll - // camup orientates to frustrum of world by default -> rotating the cam related to trucks yaw, lets bind cam rotation videocamera base (nref,ny,nz) as frustum - // could this be done faster&better with a plane setFrustumExtents ? + Ogre::Vector3 pos = node_buf[vidcam.vcam_node_alt_pos].AbsPosition + (vidcam.vcam_pos_offset.x * normal) + + (vidcam.vcam_pos_offset.y * (abs_pos_center - abs_pos_y)) + + (vidcam.vcam_pos_offset.z * (abs_pos_center - abs_pos_z)); + + // avoid the camera roll + // camup orientates to frustrum of world by default -> rotating the cam related to trucks yaw, lets bind cam rotation + // videocamera base (nref,ny,nz) as frustum could this be done faster&better with a plane setFrustumExtents ? Ogre::Vector3 frustumUP = abs_pos_center - abs_pos_y; frustumUP.normalise(); vidcam.vcam_ogre_camera->setFixedYawAxis(true, frustumUP); if (vidcam.vcam_type == GfxActor::VideoCamType::VCTYPE_MIRROR) { - //rotate the normal of the mirror by user rotation setting so it reflects correct + // rotate the normal of the mirror by user rotation setting so it reflects correct normal = vidcam.vcam_rotation * normal; // merge camera direction and reflect it on our plane vidcam.vcam_ogre_camera->setDirection((pos - gEnv->mainCamera->getPosition()).reflect(normal)); @@ -519,7 +461,9 @@ void RoR::GfxActor::UpdateVideoCameras(float dt_sec) Ogre::Vector3 refy = abs_pos_center - abs_pos_y; refy.normalise(); Ogre::Quaternion rot = Ogre::Quaternion(-refx, -refy, -normal); - vidcam.vcam_ogre_camera->setOrientation(rot * vidcam.vcam_rotation); // rotate the camera orientation towards the calculated cam direction plus user rotation + vidcam.vcam_ogre_camera->setOrientation( + rot * + vidcam.vcam_rotation); // rotate the camera orientation towards the calculated cam direction plus user rotation } else if (vidcam.vcam_type == GfxActor::VideoCamType::VCTYPE_TRACKING_VIDEOCAM) { @@ -527,12 +471,14 @@ void RoR::GfxActor::UpdateVideoCameras(float dt_sec) normal.normalise(); Ogre::Vector3 refx = abs_pos_z - abs_pos_center; refx.normalise(); - // why does this flip ~2-3� around zero orientation and only with trackercam. back to slower crossproduct calc, a bit slower but better .. sigh - // Ogre::Vector3 refy = abs_pos_center - abs_pos_y; + // why does this flip ~2-3� around zero orientation and only with trackercam. back to slower crossproduct calc, a bit + // slower but better .. sigh Ogre::Vector3 refy = abs_pos_center - abs_pos_y; Ogre::Vector3 refy = refx.crossProduct(normal); refy.normalise(); Ogre::Quaternion rot = Ogre::Quaternion(-refx, -refy, -normal); - vidcam.vcam_ogre_camera->setOrientation(rot * vidcam.vcam_rotation); // rotate the camera orientation towards the calculated cam direction plus user rotation + vidcam.vcam_ogre_camera->setOrientation( + rot * + vidcam.vcam_rotation); // rotate the camera orientation towards the calculated cam direction plus user rotation } if (vidcam.vcam_debug_node != nullptr) @@ -549,32 +495,24 @@ void RoR::GfxActor::UpdateVideoCameras(float dt_sec) void RoR::GfxActor::UpdateParticles(float dt_sec) { float water_height = 0.f; // Unused if terrain has no water - if (App::GetSimTerrain()->getWater() != nullptr) - { - water_height = App::GetSimTerrain()->getWater()->GetStaticWaterHeight(); - } + if (App::GetSimTerrain()->getWater() != nullptr) { water_height = App::GetSimTerrain()->getWater()->GetStaticWaterHeight(); } - for (NodeGfx& nfx: m_gfx_nodes) + for (NodeGfx &nfx : m_gfx_nodes) { - const node_t& n = m_actor->ar_nodes[nfx.nx_node_idx]; + const node_t &n = m_actor->ar_nodes[nfx.nx_node_idx]; // 'Wet' effects - water dripping and vapour if (nfx.nx_may_get_wet && !nfx.nx_no_particles) { // Getting out of water? - if (!n.nd_under_water && nfx.nx_under_water_prev) - { - nfx.nx_wet_time_sec = 0.f; - } + if (!n.nd_under_water && nfx.nx_under_water_prev) { nfx.nx_wet_time_sec = 0.f; } // Dripping water? if (nfx.nx_wet_time_sec != -1) { nfx.nx_wet_time_sec += dt_sec; if (nfx.nx_wet_time_sec > 5.f) // Dries off in 5 sec - { - nfx.nx_wet_time_sec = -1.f; - } + { nfx.nx_wet_time_sec = -1.f; } else if (nfx.nx_may_get_wet) { if (m_particles_drip != nullptr) @@ -594,14 +532,8 @@ void RoR::GfxActor::UpdateParticles(float dt_sec) { if ((water_height - n.AbsPosition.y < 0.2f) && (n.Velocity.squaredLength() > 4.f)) { - if (m_particles_splash) - { - m_particles_splash->allocSplash(n.AbsPosition, n.Velocity); - } - if (m_particles_ripple) - { - m_particles_ripple->allocRipple(n.AbsPosition, n.Velocity); - } + if (m_particles_splash) { m_particles_splash->allocSplash(n.AbsPosition, n.Velocity); } + if (m_particles_ripple) { m_particles_ripple->allocRipple(n.AbsPosition, n.Velocity); } } } @@ -612,43 +544,35 @@ void RoR::GfxActor::UpdateParticles(float dt_sec) { case Collisions::FX_DUSTY: if (m_particles_misc != nullptr) - { - m_particles_misc->malloc(n.AbsPosition, n.Velocity / 2.0, n.nd_last_collision_gm->fx_colour); - } + { m_particles_misc->malloc(n.AbsPosition, n.Velocity / 2.0, n.nd_last_collision_gm->fx_colour); } break; case Collisions::FX_CLUMPY: if (m_particles_clump != nullptr && n.Velocity.squaredLength() > 1.f) - { - m_particles_clump->allocClump(n.AbsPosition, n.Velocity / 2.0, n.nd_last_collision_gm->fx_colour); - } + { m_particles_clump->allocClump(n.AbsPosition, n.Velocity / 2.0, n.nd_last_collision_gm->fx_colour); } break; case Collisions::FX_HARD: if (n.nd_tyre_node) // skidmarks and tyre smoke { - const float SMOKE_THRESHOLD = 8.f; + const float SMOKE_THRESHOLD = 8.f; const float SCREECH_THRESHOLD = 5.f; - const float slipv = n.nd_last_collision_slip.length(); - const float screech = std::min(slipv, n.nd_avg_collision_slip) - SCREECH_THRESHOLD; + const float slipv = n.nd_last_collision_slip.length(); + const float screech = std::min(slipv, n.nd_avg_collision_slip) - SCREECH_THRESHOLD; if (screech > 0.0f) { SOUND_MODULATE(m_actor, SS_MOD_SCREETCH, screech / SCREECH_THRESHOLD); SOUND_PLAY_ONCE(m_actor, SS_TRIG_SCREETCH); } if (m_particles_misc != nullptr && n.nd_avg_collision_slip > SMOKE_THRESHOLD) - { - m_particles_misc->allocSmoke(n.AbsPosition, n.Velocity); - } + { m_particles_misc->allocSmoke(n.AbsPosition, n.Velocity); } } else if (!nfx.nx_no_sparks) // Not a wheel => sparks { if (m_particles_sparks != nullptr && n.nd_avg_collision_slip > 5.f) { if (n.nd_last_collision_slip.squaredLength() > 25.f) - { - m_particles_sparks->allocSparks(n.AbsPosition, n.Velocity); - } + { m_particles_sparks->allocSparks(n.AbsPosition, n.Velocity); } } } break; @@ -661,22 +585,22 @@ void RoR::GfxActor::UpdateParticles(float dt_sec) } } -const ImU32 BEAM_COLOR (0xff556633); // All colors are in ABGR format (alpha, blue, green, red) -const float BEAM_THICKNESS (1.2f); -const ImU32 BEAM_BROKEN_COLOR (0xff4466dd); -const float BEAM_BROKEN_THICKNESS (1.8f); -const ImU32 BEAM_HYDRO_COLOR (0xff55a3e0); -const float BEAM_HYDRO_THICKNESS (1.4f); -const ImU32 BEAM_STRENGTH_TEXT_COLOR (0xffcfd0cc); -const ImU32 BEAM_STRESS_TEXT_COLOR (0xff58bbfc); +const ImU32 BEAM_COLOR(0xff556633); // All colors are in ABGR format (alpha, blue, green, red) +const float BEAM_THICKNESS(1.2f); +const ImU32 BEAM_BROKEN_COLOR(0xff4466dd); +const float BEAM_BROKEN_THICKNESS(1.8f); +const ImU32 BEAM_HYDRO_COLOR(0xff55a3e0); +const float BEAM_HYDRO_THICKNESS(1.4f); +const ImU32 BEAM_STRENGTH_TEXT_COLOR(0xffcfd0cc); +const ImU32 BEAM_STRESS_TEXT_COLOR(0xff58bbfc); // TODO: commands cannot be distinguished on runtime -const ImU32 NODE_COLOR (0xff44ddff); -const float NODE_RADIUS (2.f); -const ImU32 NODE_TEXT_COLOR (0xffcccccf); // node ID text color -const ImU32 NODE_MASS_TEXT_COLOR (0xff77bb66); -const ImU32 NODE_IMMOVABLE_COLOR (0xff0033ff); -const float NODE_IMMOVABLE_RADIUS (2.8f); +const ImU32 NODE_COLOR(0xff44ddff); +const float NODE_RADIUS(2.f); +const ImU32 NODE_TEXT_COLOR(0xffcccccf); // node ID text color +const ImU32 NODE_MASS_TEXT_COLOR(0xff77bb66); +const ImU32 NODE_IMMOVABLE_COLOR(0xff0033ff); +const float NODE_IMMOVABLE_RADIUS(2.8f); void RoR::GfxActor::UpdateDebugView() { @@ -687,16 +611,20 @@ void RoR::GfxActor::UpdateDebugView() // Original 'debugVisuals' and their replacements ~only_a_ptr, 06/2017 // ------------------------------------------------------------------- - // [1] node-numbers: ------- Draws node numbers (black letters with white outline), generated nodes (wheels...) get fake sequentially assigned numbers. - // Replacement: DEBUGVIEW_NODES; Note: real node_t::id value is displayed - generated nodes show "-1" - // [2] beam-numbers: ------- Draws beam numbers (sequentially assigned) as black (thick+distorted) text - almost unreadable, barely useful IMO. + // [1] node-numbers: ------- Draws node numbers (black letters with white outline), generated nodes (wheels...) get fake + // sequentially assigned numbers. + // Replacement: DEBUGVIEW_NODES; Note: real node_t::id value is displayed - generated nodes show + // "-1" + // [2] beam-numbers: ------- Draws beam numbers (sequentially assigned) as black (thick+distorted) text - almost unreadable, + // barely useful IMO. // Not preserved // [3] node-and-beam-numbers: [1] + [2] combined // Not preserved // [4] node-mass: ---------- Shows mass in same style as [1] // Replacement: Extra info in DEBUGVIEW_NODES with different text color, like "33 (3.3Kg)" // [5] node-locked: -------- Shows text "unlocked"/"locked" in same style as [1] - // replacement: colored circles around nodes showing PRELOCK and LOCKED states (not shown when ulocked) - used in all DEBUGVIEW_* modes + // replacement: colored circles around nodes showing PRELOCK and LOCKED states (not shown when + // ulocked) - used in all DEBUGVIEW_* modes // [6] beam-compression: --- A number shown per beam, same style as [2] - unreadable. Logic: // // float stress_ratio = beams[it->id].stress / beams[it->id].minmaxposnegstress; // // float color_scale = std::abs(stress_ratio); @@ -708,21 +636,25 @@ void RoR::GfxActor::UpdateDebugView() // Replacement - special coloring/display in DEBUGVIEW_* modes. // [8] beam-stress --------- Shows value of `beam_t::stress` in style of [2] // Replacement: DEBUGVIEW_BEAMS + specific text color - // [9] beam-hydro ---------- Shows a per-hydro number in style of [2], formula: `(beams[it->id].L / beams[it->id].Lhydro) * 100` + // [9] beam-hydro ---------- Shows a per-hydro number in style of [2], formula: `(beams[it->id].L / beams[it->id].Lhydro) * + // 100` // Replacement: DEBUGVIEW_BEAMS + specific text color - // [9] beam-commands ------- Shows a per-beam number in style of [2], formula: `(beams[it->id].L / beams[it->id].commandLong) * 100` - // Not preserved - there's no way to distinguish commands on runtime and the number makes no sense for all beams. TODO: make commands distinguishable on runtime! + // [9] beam-commands ------- Shows a per-beam number in style of [2], formula: `(beams[it->id].L / + // beams[it->id].commandLong) * 100` + // Not preserved - there's no way to distinguish commands on runtime and the number makes no sense + // for all beams. TODO: make commands distinguishable on runtime! // Var - ImVec2 screen_size = ImGui::GetIO().DisplaySize; - World2ScreenConverter world2screen( - gEnv->mainCamera->getViewMatrix(true), gEnv->mainCamera->getProjectionMatrix(), Ogre::Vector2(screen_size.x, screen_size.y)); + ImVec2 screen_size = ImGui::GetIO().DisplaySize; + World2ScreenConverter world2screen(gEnv->mainCamera->getViewMatrix(true), gEnv->mainCamera->getProjectionMatrix(), + Ogre::Vector2(screen_size.x, screen_size.y)); // Dummy fullscreen window to draw to - int window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoInputs - | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus; + int window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoBringToFrontOnFocus; ImGui::Begin(("RoR-SoftBodyView-" + TOSTRING(m_actor->ar_instance_id)).c_str(), NULL, screen_size, 0, window_flags); - ImDrawList* drawlist = ImGui::GetWindowDrawList(); + ImDrawList *drawlist = ImGui::GetWindowDrawList(); ImGui::End(); if (m_actor->ar_physics_paused && !RoR::App::GetSimController()->IsGUIHidden()) @@ -744,18 +676,16 @@ void RoR::GfxActor::UpdateDebugView() } // Skeleton display. NOTE: Order matters, it determines Z-ordering on render - if ((m_debug_view == DebugViewType::DEBUGVIEW_SKELETON) || - (m_debug_view == DebugViewType::DEBUGVIEW_NODES) || + if ((m_debug_view == DebugViewType::DEBUGVIEW_SKELETON) || (m_debug_view == DebugViewType::DEBUGVIEW_NODES) || (m_debug_view == DebugViewType::DEBUGVIEW_BEAMS)) { // Beams - const beam_t* beams = m_actor->ar_beams; - const size_t num_beams = static_cast(m_actor->ar_num_beams); + const beam_t *beams = m_actor->ar_beams; + const size_t num_beams = static_cast(m_actor->ar_num_beams); for (size_t i = 0; i < num_beams; ++i) { if (App::diag_hide_wheels.GetActive() && - (beams[i].p1->nd_tyre_node || beams[i].p1->nd_rim_node || - beams[i].p2->nd_tyre_node || beams[i].p2->nd_rim_node)) + (beams[i].p1->nd_tyre_node || beams[i].p1->nd_rim_node || beams[i].p2->nd_tyre_node || beams[i].p2->nd_rim_node)) continue; Ogre::Vector3 pos1 = world2screen.Convert(beams[i].p1->AbsPosition); @@ -769,16 +699,11 @@ void RoR::GfxActor::UpdateDebugView() if (beams[i].bm_broken) { if (!App::diag_hide_broken_beams.GetActive()) - { - drawlist->AddLine(pos1xy, pos2xy, BEAM_BROKEN_COLOR, BEAM_BROKEN_THICKNESS); - } + { drawlist->AddLine(pos1xy, pos2xy, BEAM_BROKEN_COLOR, BEAM_BROKEN_THICKNESS); } } else if (beams[i].bm_type == BEAM_HYDRO) { - if (!beams[i].bm_disabled) - { - drawlist->AddLine(pos1xy, pos2xy, BEAM_HYDRO_COLOR, BEAM_HYDRO_THICKNESS); - } + if (!beams[i].bm_disabled) { drawlist->AddLine(pos1xy, pos2xy, BEAM_HYDRO_COLOR, BEAM_HYDRO_THICKNESS); } } else { @@ -788,13 +713,13 @@ void RoR::GfxActor::UpdateDebugView() if (beams[i].stress > 0) { float stress_ratio = pow(beams[i].stress / beams[i].maxposstress, 2.0f); - float s = std::min(stress_ratio, 1.0f); + float s = std::min(stress_ratio, 1.0f); color = Ogre::ColourValue(0.2f * (1 + 2.0f * s), 0.4f * (1.0f - s), 0.33f, 1.0f).getAsABGR(); } else if (beams[i].stress < 0) { float stress_ratio = pow(beams[i].stress / beams[i].maxnegstress, 2.0f); - float s = std::min(stress_ratio, 1.0f); + float s = std::min(stress_ratio, 1.0f); color = Ogre::ColourValue(0.2f, 0.4f * (1.0f - s), 0.33f * (1 + 1.0f * s), 1.0f).getAsABGR(); } } @@ -806,22 +731,18 @@ void RoR::GfxActor::UpdateDebugView() if (!App::diag_hide_nodes.GetActive()) { // Nodes - const node_t* nodes = m_actor->ar_nodes; - const size_t num_nodes = static_cast(m_actor->ar_num_nodes); + const node_t *nodes = m_actor->ar_nodes; + const size_t num_nodes = static_cast(m_actor->ar_num_nodes); for (size_t i = 0; i < num_nodes; ++i) { - if (App::diag_hide_wheels.GetActive() && (nodes[i].nd_tyre_node || nodes[i].nd_rim_node)) - continue; + if (App::diag_hide_wheels.GetActive() && (nodes[i].nd_tyre_node || nodes[i].nd_rim_node)) continue; Ogre::Vector3 pos_xyz = world2screen.Convert(nodes[i].AbsPosition); if (pos_xyz.z < 0.f) { ImVec2 pos(pos_xyz.x, pos_xyz.y); - if (nodes[i].nd_immovable) - { - drawlist->AddCircleFilled(pos, NODE_IMMOVABLE_RADIUS, NODE_IMMOVABLE_COLOR); - } + if (nodes[i].nd_immovable) { drawlist->AddCircleFilled(pos, NODE_IMMOVABLE_RADIUS, NODE_IMMOVABLE_COLOR); } else { drawlist->AddCircleFilled(pos, NODE_RADIUS, NODE_COLOR); @@ -834,15 +755,15 @@ void RoR::GfxActor::UpdateDebugView() { for (size_t i = 0; i < num_nodes; ++i) { - if ((App::diag_hide_wheels.GetActive() || App::diag_hide_wheel_info.GetActive()) && - (nodes[i].nd_tyre_node || nodes[i].nd_rim_node)) + if ((App::diag_hide_wheels.GetActive() || App::diag_hide_wheel_info.GetActive()) && + (nodes[i].nd_tyre_node || nodes[i].nd_rim_node)) continue; Ogre::Vector3 pos = world2screen.Convert(nodes[i].AbsPosition); if (pos.z < 0.f) { - ImVec2 pos_xy(pos.x, pos.y); + ImVec2 pos_xy(pos.x, pos.y); Str<25> id_buf; id_buf << nodes[i].pos; drawlist->AddText(pos_xy, NODE_TEXT_COLOR, id_buf.ToCStr()); @@ -865,13 +786,13 @@ void RoR::GfxActor::UpdateDebugView() for (size_t i = 0; i < num_beams; ++i) { if ((App::diag_hide_wheels.GetActive() || App::diag_hide_wheel_info.GetActive()) && - (beams[i].p1->nd_tyre_node || beams[i].p1->nd_rim_node || - beams[i].p2->nd_tyre_node || beams[i].p2->nd_rim_node)) + (beams[i].p1->nd_tyre_node || beams[i].p1->nd_rim_node || beams[i].p2->nd_tyre_node || + beams[i].p2->nd_rim_node)) continue; // Position Ogre::Vector3 world_pos = (beams[i].p1->AbsPosition + beams[i].p2->AbsPosition) / 2.f; - Ogre::Vector3 pos_xyz = world2screen.Convert(world_pos); + Ogre::Vector3 pos_xyz = world2screen.Convert(world_pos); if (pos_xyz.z >= 0.f) { continue; // Behind the camera @@ -880,11 +801,9 @@ void RoR::GfxActor::UpdateDebugView() // Strength is usually in thousands or millions - we shorten it. const size_t BUF_LEN = 50; - char buf[BUF_LEN]; + char buf[BUF_LEN]; if (beams[i].strength >= 1000000000000.f) - { - snprintf(buf, BUF_LEN, "%.1fT", (beams[i].strength / 1000000000000.f)); - } + { snprintf(buf, BUF_LEN, "%.1fT", (beams[i].strength / 1000000000000.f)); } else if (beams[i].strength >= 1000000000.f) { snprintf(buf, BUF_LEN, "%.1fG", (beams[i].strength / 1000000000.f)); @@ -905,15 +824,16 @@ void RoR::GfxActor::UpdateDebugView() drawlist->AddText(ImVec2(pos.x - stren_text_size.x, pos.y), BEAM_STRENGTH_TEXT_COLOR, buf); // Stress - snprintf(buf, BUF_LEN, "|%.1f", beams[i].stress); + snprintf(buf, BUF_LEN, "|%.1f", beams[i].stress); drawlist->AddText(pos, BEAM_STRESS_TEXT_COLOR, buf); } } - } else if (m_debug_view == DebugViewType::DEBUGVIEW_WHEELS) + } + else if (m_debug_view == DebugViewType::DEBUGVIEW_WHEELS) { // Wheels - const wheel_t* wheels = m_actor->ar_wheels; - const size_t num_wheels = static_cast(m_actor->ar_num_wheels); + const wheel_t *wheels = m_actor->ar_wheels; + const size_t num_wheels = static_cast(m_actor->ar_num_wheels); for (int i = 0; i < num_wheels; i++) { Ogre::Vector3 axis = wheels[i].wh_axis_node_1->RelPosition - wheels[i].wh_axis_node_0->RelPosition; @@ -944,8 +864,8 @@ void RoR::GfxActor::UpdateDebugView() Ogre::Vector3 pos_xyz = pos1_xyz.midPoint(pos2_xyz); if (pos_xyz.z < 0.f) { - float v = ImGui::GetTextLineHeightWithSpacing(); - ImVec2 pos(pos_xyz.x, pos_xyz.y); + float v = ImGui::GetTextLineHeightWithSpacing(); + ImVec2 pos(pos_xyz.x, pos_xyz.y); Str<25> wheel_id_buf; wheel_id_buf << "Id: " << (i + 1); float h1 = ImGui::CalcTextSize(wheel_id_buf.ToCStr()).x / 2.0f; @@ -1057,21 +977,15 @@ void RoR::GfxActor::UpdateDebugView() { Ogre::Vector3 m = wheels[i].wh_axis_node_0->AbsPosition.midPoint(wheels[i].wh_axis_node_1->AbsPosition); Ogre::Real w = wheels[i].wh_axis_node_0->AbsPosition.distance(m); - Ogre::Vector3 u = - axis.crossProduct(m_simbuf.simbuf_direction); - if (!wheels[i].debug_force.isZeroLength()) - { - u = - wheels[i].debug_force.normalisedCopy(); - } - Ogre::Vector3 f = axis.crossProduct(u); - Ogre::Vector3 a = - axis * w + f * std::max(w, wheels[i].wh_radius * 0.5f); - Ogre::Vector3 b = + axis * w + f * std::max(w, wheels[i].wh_radius * 0.5f); - Ogre::Vector3 c = + axis * w - f * std::max(w, wheels[i].wh_radius * 0.5f); - Ogre::Vector3 d = - axis * w - f * std::max(w, wheels[i].wh_radius * 0.5f); + Ogre::Vector3 u = -axis.crossProduct(m_simbuf.simbuf_direction); + if (!wheels[i].debug_force.isZeroLength()) { u = -wheels[i].debug_force.normalisedCopy(); } + Ogre::Vector3 f = axis.crossProduct(u); + Ogre::Vector3 a = -axis * w + f * std::max(w, wheels[i].wh_radius * 0.5f); + Ogre::Vector3 b = +axis * w + f * std::max(w, wheels[i].wh_radius * 0.5f); + Ogre::Vector3 c = +axis * w - f * std::max(w, wheels[i].wh_radius * 0.5f); + Ogre::Vector3 d = -axis * w - f * std::max(w, wheels[i].wh_radius * 0.5f); Ogre::Quaternion r = Ogre::Quaternion::IDENTITY; - if (wheels[i].debug_vel.length() > 1.0f) - { - r = Ogre::Quaternion(f.angleBetween(wheels[i].debug_vel), u); - } + if (wheels[i].debug_vel.length() > 1.0f) { r = Ogre::Quaternion(f.angleBetween(wheels[i].debug_vel), u); } Ogre::Vector3 pos1_xyz = world2screen.Convert(m - u * wheels[i].wh_radius + r * a); Ogre::Vector3 pos2_xyz = world2screen.Convert(m - u * wheels[i].wh_radius + r * b); Ogre::Vector3 pos3_xyz = world2screen.Convert(m - u * wheels[i].wh_radius + r * c); @@ -1084,11 +998,11 @@ void RoR::GfxActor::UpdateDebugView() ImVec2 pos4xy(pos4_xyz.x, pos4_xyz.y); if (!wheels[i].debug_force.isZeroLength()) { - float slipv = wheels[i].debug_slip.length(); - float wheelv = wheels[i].debug_vel.length(); + float slipv = wheels[i].debug_slip.length(); + float wheelv = wheels[i].debug_vel.length(); float slip_ratio = std::min(slipv, wheelv) / std::max(1.0f, wheelv); - float scale = pow(slip_ratio, 2); - ImU32 col = Ogre::ColourValue(scale, 1.0f - scale, 0.0f, 0.2f).getAsABGR(); + float scale = pow(slip_ratio, 2); + ImU32 col = Ogre::ColourValue(scale, 1.0f - scale, 0.0f, 0.2f).getAsABGR(); drawlist->AddQuadFilled(pos1xy, pos2xy, pos3xy, pos4xy, col); } else @@ -1101,12 +1015,12 @@ void RoR::GfxActor::UpdateDebugView() // Slip vector if (!wheels[i].debug_vel.isZeroLength()) { - Ogre::Vector3 m = wheels[i].wh_axis_node_0->AbsPosition.midPoint(wheels[i].wh_axis_node_1->AbsPosition); - Ogre::Real w = wheels[i].wh_axis_node_0->AbsPosition.distance(m); - Ogre::Vector3 d = axis.crossProduct(m_simbuf.simbuf_direction) * wheels[i].wh_radius; - Ogre::Real slipv = wheels[i].debug_slip.length(); - Ogre::Real wheelv = wheels[i].debug_vel.length(); - Ogre::Vector3 s = wheels[i].debug_slip * (std::min(slipv, wheelv) / std::max(1.0f, wheelv)) / slipv; + Ogre::Vector3 m = wheels[i].wh_axis_node_0->AbsPosition.midPoint(wheels[i].wh_axis_node_1->AbsPosition); + Ogre::Real w = wheels[i].wh_axis_node_0->AbsPosition.distance(m); + Ogre::Vector3 d = axis.crossProduct(m_simbuf.simbuf_direction) * wheels[i].wh_radius; + Ogre::Real slipv = wheels[i].debug_slip.length(); + Ogre::Real wheelv = wheels[i].debug_vel.length(); + Ogre::Vector3 s = wheels[i].debug_slip * (std::min(slipv, wheelv) / std::max(1.0f, wheelv)) / slipv; Ogre::Vector3 pos1_xyz = world2screen.Convert(m + d); Ogre::Vector3 pos2_xyz = world2screen.Convert(m + d + s * std::max(w, wheels[i].wh_radius * 0.5f)); if ((pos1_xyz.z < 0.f) && (pos2_xyz.z < 0.f)) @@ -1119,10 +1033,10 @@ void RoR::GfxActor::UpdateDebugView() // Down force { - Ogre::Real f = wheels[i].debug_force.length(); - Ogre::Real mass = m_actor->getTotalMass(false) * num_wheels; + Ogre::Real f = wheels[i].debug_force.length(); + Ogre::Real mass = m_actor->getTotalMass(false) * num_wheels; Ogre::Vector3 normalised_force = wheels[i].debug_force.normalisedCopy() * std::min(f / mass, 1.0f); - Ogre::Vector3 m = wheels[i].wh_axis_node_0->AbsPosition.midPoint(wheels[i].wh_axis_node_1->AbsPosition); + Ogre::Vector3 m = wheels[i].wh_axis_node_0->AbsPosition.midPoint(wheels[i].wh_axis_node_1->AbsPosition); Ogre::Vector3 pos5_xyz = world2screen.Convert(m); Ogre::Vector3 pos6_xyz = world2screen.Convert(m + normalised_force * wheels[i].wh_radius); if ((pos5_xyz.z < 0.f) && (pos6_xyz.z < 0.f)) @@ -1133,30 +1047,23 @@ void RoR::GfxActor::UpdateDebugView() } } } - } else if (m_debug_view == DebugViewType::DEBUGVIEW_SHOCKS) + } + else if (m_debug_view == DebugViewType::DEBUGVIEW_SHOCKS) { // Shocks - const beam_t* beams = m_actor->ar_beams; - const size_t num_beams = static_cast(m_actor->ar_num_beams); + const beam_t *beams = m_actor->ar_beams; + const size_t num_beams = static_cast(m_actor->ar_num_beams); std::set node_ids; for (size_t i = 0; i < num_beams; ++i) { - if (beams[i].bm_type != BEAM_HYDRO) - continue; - if (!(beams[i].bounded == SHOCK1 || beams[i].bounded == SHOCK2 || beams[i].bounded == SHOCK3)) - continue; + if (beams[i].bm_type != BEAM_HYDRO) continue; + if (!(beams[i].bounded == SHOCK1 || beams[i].bounded == SHOCK2 || beams[i].bounded == SHOCK3)) continue; Ogre::Vector3 pos1_xyz = world2screen.Convert(beams[i].p1->AbsPosition); Ogre::Vector3 pos2_xyz = world2screen.Convert(beams[i].p2->AbsPosition); - if (pos1_xyz.z < 0.f) - { - node_ids.insert(beams[i].p1->pos); - } - if (pos2_xyz.z < 0.f) - { - node_ids.insert(beams[i].p2->pos); - } + if (pos1_xyz.z < 0.f) { node_ids.insert(beams[i].p1->pos); } + if (pos2_xyz.z < 0.f) { node_ids.insert(beams[i].p2->pos); } if ((pos1_xyz.z < 0.f) && (pos2_xyz.z < 0.f)) { @@ -1183,10 +1090,8 @@ void RoR::GfxActor::UpdateDebugView() } for (size_t i = 0; i < num_beams; ++i) { - if (beams[i].bm_type != BEAM_HYDRO) - continue; - if (!(beams[i].bounded == SHOCK1 || beams[i].bounded == SHOCK2 || beams[i].bounded == SHOCK3)) - continue; + if (beams[i].bm_type != BEAM_HYDRO) continue; + if (!(beams[i].bounded == SHOCK1 || beams[i].bounded == SHOCK2 || beams[i].bounded == SHOCK3)) continue; Ogre::Vector3 pos1_xyz = world2screen.Convert(beams[i].p1->AbsPosition); Ogre::Vector3 pos2_xyz = world2screen.Convert(beams[i].p2->AbsPosition); @@ -1195,13 +1100,13 @@ void RoR::GfxActor::UpdateDebugView() if (pos_xyz.z < 0.f) { // Shock info - float diff = beams[i].p1->AbsPosition.distance(beams[i].p2->AbsPosition) - beams[i].L; + float diff = beams[i].p1->AbsPosition.distance(beams[i].p2->AbsPosition) - beams[i].L; ImU32 text_color = (diff < 0.0f) ? 0xff66ee66 : 0xff8888ff; - float bound = (diff < 0.0f) ? beams[i].shortbound : beams[i].longbound; - float ratio = Ogre::Math::Clamp(diff / (bound * beams[i].L), -2.0f, +2.0f); + float bound = (diff < 0.0f) ? beams[i].shortbound : beams[i].longbound; + float ratio = Ogre::Math::Clamp(diff / (bound * beams[i].L), -2.0f, +2.0f); - float v = ImGui::GetTextLineHeightWithSpacing(); - ImVec2 pos(pos_xyz.x, pos_xyz.y - v - v); + float v = ImGui::GetTextLineHeightWithSpacing(); + ImVec2 pos(pos_xyz.x, pos_xyz.y - v - v); Str<25> len_buf; len_buf << "L: " << static_cast(Round(std::abs(ratio) * 100.0f)) << " %"; float h1 = ImGui::CalcTextSize(len_buf.ToCStr()).x / 2.0f; @@ -1220,12 +1125,13 @@ void RoR::GfxActor::UpdateDebugView() drawlist->AddText(ImVec2(pos.x - h4, pos.y + v + v + v), text_color, vel_buf); } } - } else if (m_debug_view == DebugViewType::DEBUGVIEW_ROTATORS) + } + else if (m_debug_view == DebugViewType::DEBUGVIEW_ROTATORS) { // Rotators - const node_t* nodes = m_actor->ar_nodes; - const rotator_t* rotators = m_actor->ar_rotators; - const size_t num_rotators = static_cast(m_actor->ar_num_rotators); + const node_t * nodes = m_actor->ar_nodes; + const rotator_t *rotators = m_actor->ar_rotators; + const size_t num_rotators = static_cast(m_actor->ar_num_rotators); for (int i = 0; i < num_rotators; i++) { Ogre::Vector3 pos1_xyz = world2screen.Convert(nodes[rotators[i].axis1].AbsPosition); @@ -1260,8 +1166,8 @@ void RoR::GfxActor::UpdateDebugView() Ogre::Vector3 pos_xyz = pos1_xyz.midPoint(pos2_xyz); if (pos_xyz.z < 0.f) { - float v = ImGui::GetTextLineHeightWithSpacing(); - ImVec2 pos(pos_xyz.x, pos_xyz.y); + float v = ImGui::GetTextLineHeightWithSpacing(); + ImVec2 pos(pos_xyz.x, pos_xyz.y); Str<25> rotator_id_buf; rotator_id_buf << "Id: " << (i + 1); float h1 = ImGui::CalcTextSize(rotator_id_buf.ToCStr()).x / 2.0f; @@ -1326,12 +1232,12 @@ void RoR::GfxActor::UpdateDebugView() // Projection plane { - Ogre::Vector3 mid = nodes[rotators[i].axis1].AbsPosition.midPoint(nodes[rotators[i].axis2].AbsPosition); + Ogre::Vector3 mid = nodes[rotators[i].axis1].AbsPosition.midPoint(nodes[rotators[i].axis2].AbsPosition); Ogre::Vector3 axis = nodes[rotators[i].axis1].RelPosition - nodes[rotators[i].axis2].RelPosition; - Ogre::Vector3 perp = axis.perpendicular(); + Ogre::Vector3 perp = axis.perpendicular(); axis.normalise(); - const int steps = 64; + const int steps = 64; Ogre::Plane plane = Ogre::Plane(axis, mid); Ogre::Real radius1 = 0.0f; @@ -1339,7 +1245,7 @@ void RoR::GfxActor::UpdateDebugView() for (int k = 0; k < 2; k++) { Ogre::Vector3 r1 = nodes[rotators[i].nodes1[k]].RelPosition - nodes[rotators[i].axis1].RelPosition; - Ogre::Real r = plane.projectVector(r1).length(); + Ogre::Real r = plane.projectVector(r1).length(); if (r > radius1) { radius1 = r; @@ -1350,23 +1256,18 @@ void RoR::GfxActor::UpdateDebugView() for (int k = 0; k < steps; k++) { Ogre::Quaternion rotation(Ogre::Radian(((float)k / steps) * Ogre::Math::TWO_PI), axis); - Ogre::Vector3 pos_xyz = world2screen.Convert(mid + axis * offset1 + rotation * perp * radius1); - if (pos_xyz.z < 0.f) - { - pos1_xy.push_back(ImVec2(pos_xyz.x, pos_xyz.y)); - } + Ogre::Vector3 pos_xyz = world2screen.Convert(mid + axis * offset1 + rotation * perp * radius1); + if (pos_xyz.z < 0.f) { pos1_xy.push_back(ImVec2(pos_xyz.x, pos_xyz.y)); } } if (!pos1_xy.empty()) - { - drawlist->AddConvexPolyFilled(pos1_xy.data(), static_cast(pos1_xy.size()), 0x33666666, false); - } + { drawlist->AddConvexPolyFilled(pos1_xy.data(), static_cast(pos1_xy.size()), 0x33666666, false); } Ogre::Real radius2 = 0.0f; Ogre::Real offset2 = 0.0f; for (int k = 0; k < 2; k++) { Ogre::Vector3 r2 = nodes[rotators[i].nodes2[k]].RelPosition - nodes[rotators[i].axis2].RelPosition; - Ogre::Real r = plane.projectVector(r2).length(); + Ogre::Real r = plane.projectVector(r2).length(); if (r > radius2) { radius2 = r; @@ -1377,22 +1278,17 @@ void RoR::GfxActor::UpdateDebugView() for (int k = 0; k < steps; k++) { Ogre::Quaternion rotation(Ogre::Radian(((float)k / steps) * Ogre::Math::TWO_PI), axis); - Ogre::Vector3 pos_xyz = world2screen.Convert(mid + axis * offset2 + rotation * perp * radius2); - if (pos_xyz.z < 0.f) - { - pos2_xy.push_back(ImVec2(pos_xyz.x, pos_xyz.y)); - } + Ogre::Vector3 pos_xyz = world2screen.Convert(mid + axis * offset2 + rotation * perp * radius2); + if (pos_xyz.z < 0.f) { pos2_xy.push_back(ImVec2(pos_xyz.x, pos_xyz.y)); } } if (!pos2_xy.empty()) - { - drawlist->AddConvexPolyFilled(pos2_xy.data(), static_cast(pos2_xy.size()), 0x1155a3e0, false); - } + { drawlist->AddConvexPolyFilled(pos2_xy.data(), static_cast(pos2_xy.size()), 0x1155a3e0, false); } for (int k = 0; k < 2; k++) { // Projected and rotated base plate arms (theory vectors) Ogre::Vector3 ref1 = plane.projectVector(nodes[rotators[i].nodes1[k]].AbsPosition - mid); - Ogre::Vector3 th1 = Ogre::Quaternion(Ogre::Radian(rotators[i].angle), axis) * ref1; + Ogre::Vector3 th1 = Ogre::Quaternion(Ogre::Radian(rotators[i].angle), axis) * ref1; { Ogre::Vector3 pos1_xyz = world2screen.Convert(mid + axis * offset1); Ogre::Vector3 pos2_xyz = world2screen.Convert(mid + axis * offset1 + th1); @@ -1417,7 +1313,7 @@ void RoR::GfxActor::UpdateDebugView() } // Virtual plate connections th1.normalise(); - Ogre::Real radius = std::min(radius1, radius2); + Ogre::Real radius = std::min(radius1, radius2); Ogre::Vector3 pos3_xyz = world2screen.Convert(mid + axis * offset1 + th1 * radius); Ogre::Vector3 pos4_xyz = world2screen.Convert(mid + axis * offset2 + th1 * radius); if ((pos3_xyz.z < 0.f) && (pos4_xyz.z < 0.f)) @@ -1429,10 +1325,11 @@ void RoR::GfxActor::UpdateDebugView() } } } - } else if (m_debug_view == DebugViewType::DEBUGVIEW_SLIDENODES) + } + else if (m_debug_view == DebugViewType::DEBUGVIEW_SLIDENODES) { // Slide nodes - const node_t* nodes = m_actor->ar_nodes; + const node_t *nodes = m_actor->ar_nodes; std::set node_ids; for (auto railgroup : m_actor->m_railgroups) { @@ -1441,14 +1338,8 @@ void RoR::GfxActor::UpdateDebugView() Ogre::Vector3 pos1 = world2screen.Convert(railsegment.rs_beam->p1->AbsPosition); Ogre::Vector3 pos2 = world2screen.Convert(railsegment.rs_beam->p2->AbsPosition); - if (pos1.z < 0.f) - { - node_ids.insert(railsegment.rs_beam->p1->pos); - } - if (pos2.z < 0.f) - { - node_ids.insert(railsegment.rs_beam->p2->pos); - } + if (pos1.z < 0.f) { node_ids.insert(railsegment.rs_beam->p1->pos); } + if (pos2.z < 0.f) { node_ids.insert(railsegment.rs_beam->p2->pos); } if ((pos1.z < 0.f) && (pos2.z < 0.f)) { ImVec2 pos1xy(pos1.x, pos1.y); @@ -1471,9 +1362,9 @@ void RoR::GfxActor::UpdateDebugView() drawlist->AddText(pos_xy, NODE_TEXT_COLOR, id_buf.ToCStr()); } } - for (auto slidenode : m_actor->m_slidenodes) + for (auto slidenode : m_actor->m_slidenodes) { - auto id = slidenode.GetSlideNodeId(); + auto id = slidenode.GetSlideNodeId(); Ogre::Vector3 pos_xyz = world2screen.Convert(nodes[id].AbsPosition); if (pos_xyz.z < 0.f) @@ -1486,28 +1377,29 @@ void RoR::GfxActor::UpdateDebugView() drawlist->AddText(pos, NODE_TEXT_COLOR, id_buf.ToCStr()); } } - } else if (m_debug_view == DebugViewType::DEBUGVIEW_SUBMESH) + } + else if (m_debug_view == DebugViewType::DEBUGVIEW_SUBMESH) { // Cabs - const node_t* nodes = m_actor->ar_nodes; - const auto cabs = m_actor->ar_cabs; - const auto num_cabs = m_actor->ar_num_cabs; - const auto buoycabs = m_actor->ar_buoycabs; - const auto num_buoycabs = m_actor->ar_num_buoycabs; - const auto collcabs = m_actor->ar_collcabs; - const auto num_collcabs = m_actor->ar_num_collcabs; + const node_t *nodes = m_actor->ar_nodes; + const auto cabs = m_actor->ar_cabs; + const auto num_cabs = m_actor->ar_num_cabs; + const auto buoycabs = m_actor->ar_buoycabs; + const auto num_buoycabs = m_actor->ar_num_buoycabs; + const auto collcabs = m_actor->ar_collcabs; + const auto num_collcabs = m_actor->ar_num_collcabs; std::vector> render_cabs; for (int i = 0; i < num_cabs; i++) { - Ogre::Vector3 pos1_xyz = world2screen.Convert(nodes[cabs[i*3+0]].AbsPosition); - Ogre::Vector3 pos2_xyz = world2screen.Convert(nodes[cabs[i*3+1]].AbsPosition); - Ogre::Vector3 pos3_xyz = world2screen.Convert(nodes[cabs[i*3+2]].AbsPosition); + Ogre::Vector3 pos1_xyz = world2screen.Convert(nodes[cabs[i * 3 + 0]].AbsPosition); + Ogre::Vector3 pos2_xyz = world2screen.Convert(nodes[cabs[i * 3 + 1]].AbsPosition); + Ogre::Vector3 pos3_xyz = world2screen.Convert(nodes[cabs[i * 3 + 2]].AbsPosition); if ((pos1_xyz.z < 0.f) && (pos2_xyz.z < 0.f) && (pos3_xyz.z < 0.f)) { float depth = pos1_xyz.z; - depth = std::max(depth, pos2_xyz.z); - depth = std::max(depth, pos3_xyz.z); + depth = std::max(depth, pos2_xyz.z); + depth = std::max(depth, pos3_xyz.z); render_cabs.push_back({depth, i}); } } @@ -1517,16 +1409,16 @@ void RoR::GfxActor::UpdateDebugView() std::vector node_ids; for (auto render_cab : render_cabs) { - int i = render_cab.second; + int i = render_cab.second; bool coll = std::find(collcabs, collcabs + num_collcabs, i) != (collcabs + num_collcabs); bool buoy = std::find(buoycabs, buoycabs + num_buoycabs, i) != (buoycabs + num_buoycabs); ImU32 fill_color = Ogre::ColourValue(0.5f * coll, 0.5f * !buoy, 0.5f * (coll ^ buoy), 0.27f).getAsABGR(); ImU32 beam_color = Ogre::ColourValue(0.5f * coll, 0.5f * !buoy, 0.5f * (coll ^ buoy), 0.53f).getAsABGR(); - Ogre::Vector3 pos1_xyz = world2screen.Convert(nodes[cabs[i*3+0]].AbsPosition); - Ogre::Vector3 pos2_xyz = world2screen.Convert(nodes[cabs[i*3+1]].AbsPosition); - Ogre::Vector3 pos3_xyz = world2screen.Convert(nodes[cabs[i*3+2]].AbsPosition); + Ogre::Vector3 pos1_xyz = world2screen.Convert(nodes[cabs[i * 3 + 0]].AbsPosition); + Ogre::Vector3 pos2_xyz = world2screen.Convert(nodes[cabs[i * 3 + 1]].AbsPosition); + Ogre::Vector3 pos3_xyz = world2screen.Convert(nodes[cabs[i * 3 + 2]].AbsPosition); if ((pos1_xyz.z < 0.f) && (pos2_xyz.z < 0.f) && (pos3_xyz.z < 0.f)) { ImVec2 pos1_xy(pos1_xyz.x, pos1_xyz.y); @@ -1537,7 +1429,7 @@ void RoR::GfxActor::UpdateDebugView() } for (int k = 0; k < 3; k++) { - int id = cabs[i*3+k]; + int id = cabs[i * 3 + k]; if (std::find(node_ids.begin(), node_ids.end(), id) == node_ids.end()) { Ogre::Vector3 pos_xyz = world2screen.Convert(nodes[id].AbsPosition); @@ -1567,105 +1459,119 @@ void RoR::GfxActor::ToggleDebugView() void RoR::GfxActor::SetDebugView(DebugViewType dv) { - if (dv == DebugViewType::DEBUGVIEW_WHEELS && m_actor->ar_num_wheels == 0 || - dv == DebugViewType::DEBUGVIEW_SHOCKS && m_actor->ar_num_shocks == 0 || - dv == DebugViewType::DEBUGVIEW_ROTATORS && m_actor->ar_num_rotators == 0 || + if (dv == DebugViewType::DEBUGVIEW_WHEELS && m_actor->ar_num_wheels == 0 || + dv == DebugViewType::DEBUGVIEW_SHOCKS && m_actor->ar_num_shocks == 0 || + dv == DebugViewType::DEBUGVIEW_ROTATORS && m_actor->ar_num_rotators == 0 || dv == DebugViewType::DEBUGVIEW_SLIDENODES && m_actor->hasSlidenodes() == 0 || - dv == DebugViewType::DEBUGVIEW_SUBMESH && m_actor->ar_num_cabs == 0) - { - dv = DebugViewType::DEBUGVIEW_NONE; - } + dv == DebugViewType::DEBUGVIEW_SUBMESH && m_actor->ar_num_cabs == 0) + { dv = DebugViewType::DEBUGVIEW_NONE; } m_debug_view = dv; - if (dv != DebugViewType::DEBUGVIEW_NONE) - { - m_last_debug_view = dv; - } + if (dv != DebugViewType::DEBUGVIEW_NONE) { m_last_debug_view = dv; } } void RoR::GfxActor::CycleDebugViews() { switch (m_debug_view) { - case DebugViewType::DEBUGVIEW_NONE: SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; - case DebugViewType::DEBUGVIEW_SKELETON: SetDebugView(DebugViewType::DEBUGVIEW_NODES); break; - case DebugViewType::DEBUGVIEW_NODES: SetDebugView(DebugViewType::DEBUGVIEW_BEAMS); break; + case DebugViewType::DEBUGVIEW_NONE: SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; + case DebugViewType::DEBUGVIEW_SKELETON: SetDebugView(DebugViewType::DEBUGVIEW_NODES); break; + case DebugViewType::DEBUGVIEW_NODES: SetDebugView(DebugViewType::DEBUGVIEW_BEAMS); break; case DebugViewType::DEBUGVIEW_BEAMS: { - if (m_actor->ar_num_wheels) SetDebugView(DebugViewType::DEBUGVIEW_WHEELS); - else if (m_actor->ar_num_shocks) SetDebugView(DebugViewType::DEBUGVIEW_SHOCKS); - else if (m_actor->ar_num_rotators) SetDebugView(DebugViewType::DEBUGVIEW_ROTATORS); - else if (m_actor->hasSlidenodes()) SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); - else if (m_actor->ar_num_cabs) SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); - else SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); + if (m_actor->ar_num_wheels) + SetDebugView(DebugViewType::DEBUGVIEW_WHEELS); + else if (m_actor->ar_num_shocks) + SetDebugView(DebugViewType::DEBUGVIEW_SHOCKS); + else if (m_actor->ar_num_rotators) + SetDebugView(DebugViewType::DEBUGVIEW_ROTATORS); + else if (m_actor->hasSlidenodes()) + SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); + else if (m_actor->ar_num_cabs) + SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); + else + SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; } case DebugViewType::DEBUGVIEW_WHEELS: { - if (m_actor->ar_num_shocks) SetDebugView(DebugViewType::DEBUGVIEW_SHOCKS); - else if (m_actor->ar_num_rotators) SetDebugView(DebugViewType::DEBUGVIEW_ROTATORS); - else if (m_actor->hasSlidenodes()) SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); - else if (m_actor->ar_num_cabs) SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); - else SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); + if (m_actor->ar_num_shocks) + SetDebugView(DebugViewType::DEBUGVIEW_SHOCKS); + else if (m_actor->ar_num_rotators) + SetDebugView(DebugViewType::DEBUGVIEW_ROTATORS); + else if (m_actor->hasSlidenodes()) + SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); + else if (m_actor->ar_num_cabs) + SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); + else + SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; } case DebugViewType::DEBUGVIEW_SHOCKS: { - if (m_actor->ar_num_rotators) SetDebugView(DebugViewType::DEBUGVIEW_ROTATORS); - else if (m_actor->hasSlidenodes()) SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); - else if (m_actor->ar_num_cabs) SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); - else SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); + if (m_actor->ar_num_rotators) + SetDebugView(DebugViewType::DEBUGVIEW_ROTATORS); + else if (m_actor->hasSlidenodes()) + SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); + else if (m_actor->ar_num_cabs) + SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); + else + SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; } case DebugViewType::DEBUGVIEW_ROTATORS: { - if (m_actor->hasSlidenodes()) SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); - else if (m_actor->ar_num_cabs) SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); - else SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); + if (m_actor->hasSlidenodes()) + SetDebugView(DebugViewType::DEBUGVIEW_SLIDENODES); + else if (m_actor->ar_num_cabs) + SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); + else + SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; } case DebugViewType::DEBUGVIEW_SLIDENODES: { - if (m_actor->ar_num_cabs) SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); - else SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); + if (m_actor->ar_num_cabs) + SetDebugView(DebugViewType::DEBUGVIEW_SUBMESH); + else + SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; } - case DebugViewType::DEBUGVIEW_SUBMESH: SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; + case DebugViewType::DEBUGVIEW_SUBMESH: SetDebugView(DebugViewType::DEBUGVIEW_SKELETON); break; default:; } } -void RoR::GfxActor::AddRod(int beam_index, int node1_index, int node2_index, const char* material_name, bool visible, float diameter_meters) +void RoR::GfxActor::AddRod(int beam_index, int node1_index, int node2_index, const char *material_name, bool visible, + float diameter_meters) { try { Str<100> entity_name; entity_name << "rod" << beam_index << "@actor" << m_actor->ar_instance_id; - Ogre::Entity* entity = gEnv->sceneManager->createEntity(entity_name.ToCStr(), "beam.mesh"); + Ogre::Entity *entity = gEnv->sceneManager->createEntity(entity_name.ToCStr(), "beam.mesh"); entity->setMaterialName(material_name); if (m_rods_parent_scenenode == nullptr) - { - m_rods_parent_scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - } + { m_rods_parent_scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); } Rod rod; rod.rod_scenenode = m_rods_parent_scenenode->createChildSceneNode(); rod.rod_scenenode->attachObject(entity); - rod.rod_scenenode->setVisible(visible, /*cascade=*/ false); + rod.rod_scenenode->setVisible(visible, /*cascade=*/false); rod.rod_scenenode->setScale(diameter_meters, -1, diameter_meters); rod.rod_diameter_mm = uint16_t(diameter_meters * 1000.f); - rod.rod_beam_index = static_cast(beam_index); - rod.rod_node1 = static_cast(node1_index); - rod.rod_node2 = static_cast(node2_index); + rod.rod_beam_index = static_cast(beam_index); + rod.rod_node1 = static_cast(node1_index); + rod.rod_node2 = static_cast(node2_index); rod.rod_target_actor = m_actor; - rod.rod_is_visible = false; + rod.rod_is_visible = false; m_rods.push_back(rod); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { LogFormat("[RoR|Gfx] Failed to create visuals for beam %d, message: %s", beam_index, e.getFullDescription().c_str()); } @@ -1673,20 +1579,19 @@ void RoR::GfxActor::AddRod(int beam_index, int node1_index, int node2_index, co void RoR::GfxActor::UpdateRods() { - for (Rod& rod: m_rods) + for (Rod &rod : m_rods) { rod.rod_scenenode->setVisible(rod.rod_is_visible); - if (!rod.rod_is_visible) - continue; + if (!rod.rod_is_visible) continue; - NodeData* nodes1 = this->GetSimNodeBuffer(); - Ogre::Vector3 pos1 = nodes1[rod.rod_node1].AbsPosition; - NodeData* nodes2 = rod.rod_target_actor->GetGfxActor()->GetSimNodeBuffer(); - Ogre::Vector3 pos2 = nodes2[rod.rod_node2].AbsPosition; + NodeData * nodes1 = this->GetSimNodeBuffer(); + Ogre::Vector3 pos1 = nodes1[rod.rod_node1].AbsPosition; + NodeData * nodes2 = rod.rod_target_actor->GetGfxActor()->GetSimNodeBuffer(); + Ogre::Vector3 pos2 = nodes2[rod.rod_node2].AbsPosition; // Classic method float beam_diameter = static_cast(rod.rod_diameter_mm) * 0.001; - float beam_length = pos1.distance(pos2); + float beam_length = pos1.distance(pos2); rod.rod_scenenode->setPosition(pos1.midPoint(pos2)); rod.rod_scenenode->setScale(beam_diameter, beam_length, beam_diameter); @@ -1694,7 +1599,7 @@ void RoR::GfxActor::UpdateRods() } } -Ogre::Quaternion RoR::GfxActor::SpecialGetRotationTo(const Ogre::Vector3& src, const Ogre::Vector3& dest) +Ogre::Quaternion RoR::GfxActor::SpecialGetRotationTo(const Ogre::Vector3 &src, const Ogre::Vector3 &dest) { // Based on Stan Melax's article in Game Programming Gems Ogre::Quaternion q; @@ -1708,10 +1613,7 @@ Ogre::Quaternion RoR::GfxActor::SpecialGetRotationTo(const Ogre::Vector3& src, c // when v0 == -v1 Ogre::Real d = v0.dotProduct(v1); // If dot == 1, vectors are the same - if (d >= 1.0f) - { - return Ogre::Quaternion::IDENTITY; - } + if (d >= 1.0f) { return Ogre::Quaternion::IDENTITY; } if (d < (1e-6f - 1.0f)) { // Generate an axis @@ -1724,11 +1626,10 @@ Ogre::Quaternion RoR::GfxActor::SpecialGetRotationTo(const Ogre::Vector3& src, c else { Ogre::Real s = fast_sqrt((1 + d) * 2); - if (s == 0) - return Ogre::Quaternion::IDENTITY; + if (s == 0) return Ogre::Quaternion::IDENTITY; - Ogre::Vector3 c = v0.crossProduct(v1); - Ogre::Real invs = 1 / s; + Ogre::Vector3 c = v0.crossProduct(v1); + Ogre::Real invs = 1 / s; q.x = c.x * invs; q.y = c.y * invs; @@ -1740,43 +1641,33 @@ Ogre::Quaternion RoR::GfxActor::SpecialGetRotationTo(const Ogre::Vector3& src, c void RoR::GfxActor::ScaleActor(Ogre::Vector3 relpos, float ratio) { - for (Rod& rod: m_rods) + for (Rod &rod : m_rods) { - float diameter2 = static_cast(rod.rod_diameter_mm) * (ratio*1000.f); + float diameter2 = static_cast(rod.rod_diameter_mm) * (ratio * 1000.f); rod.rod_diameter_mm = static_cast(diameter2); } // props and stuff // TOFIX: care about prop positions as well! - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { - if (prop.scene_node) - prop.scene_node->scale(ratio, ratio, ratio); + if (prop.scene_node) prop.scene_node->scale(ratio, ratio, ratio); - if (prop.wheel) - prop.wheel->scale(ratio, ratio, ratio); + if (prop.wheel) prop.wheel->scale(ratio, ratio, ratio); - if (prop.wheel) - prop.wheelpos = relpos + (prop.wheelpos - relpos) * ratio; + if (prop.wheel) prop.wheelpos = relpos + (prop.wheelpos - relpos) * ratio; - if (prop.beacon_flare_billboard_scene_node[0]) - prop.beacon_flare_billboard_scene_node[0]->scale(ratio, ratio, ratio); + if (prop.beacon_flare_billboard_scene_node[0]) prop.beacon_flare_billboard_scene_node[0]->scale(ratio, ratio, ratio); - if (prop.beacon_flare_billboard_scene_node[1]) - prop.beacon_flare_billboard_scene_node[1]->scale(ratio, ratio, ratio); + if (prop.beacon_flare_billboard_scene_node[1]) prop.beacon_flare_billboard_scene_node[1]->scale(ratio, ratio, ratio); - if (prop.beacon_flare_billboard_scene_node[2]) - prop.beacon_flare_billboard_scene_node[2]->scale(ratio, ratio, ratio); + if (prop.beacon_flare_billboard_scene_node[2]) prop.beacon_flare_billboard_scene_node[2]->scale(ratio, ratio, ratio); - if (prop.beacon_flare_billboard_scene_node[3]) - prop.beacon_flare_billboard_scene_node[3]->scale(ratio, ratio, ratio); + if (prop.beacon_flare_billboard_scene_node[3]) prop.beacon_flare_billboard_scene_node[3]->scale(ratio, ratio, ratio); } // Old cab mesh - if (m_cab_mesh) - { - m_cab_mesh->ScaleFlexObj(ratio); - } + if (m_cab_mesh) { m_cab_mesh->ScaleFlexObj(ratio); } } void RoR::GfxActor::SetRodsVisible(bool visible) @@ -1791,9 +1682,7 @@ void RoR::GfxActor::SetRodsVisible(bool visible) // 2. For OGRE up to 1.9 (I don't know about 1.10+) OGRE developers recommended to detach rather than hide. // ~ only_a_ptr, 12/2017 if (visible && !m_rods_parent_scenenode->isInSceneGraph()) - { - gEnv->sceneManager->getRootSceneNode()->addChild(m_rods_parent_scenenode); - } + { gEnv->sceneManager->getRootSceneNode()->addChild(m_rods_parent_scenenode); } else if (!visible && m_rods_parent_scenenode->isInSceneGraph()) { gEnv->sceneManager->getRootSceneNode()->removeChild(m_rods_parent_scenenode); @@ -1802,59 +1691,56 @@ void RoR::GfxActor::SetRodsVisible(bool visible) void RoR::GfxActor::UpdateSimDataBuffer() { - m_simbuf.simbuf_live_local = (m_actor->ar_sim_state == Actor::SimState::LOCAL_SIMULATED); - m_simbuf.simbuf_physics_paused = m_actor->ar_physics_paused; - m_simbuf.simbuf_pos = m_actor->GetRotationCenter(); - m_simbuf.simbuf_rotation = m_actor->getRotation(); - m_simbuf.simbuf_tyre_pressure = m_actor->GetTyrePressure(); - m_simbuf.simbuf_aabb = m_actor->ar_bounding_box; - m_simbuf.simbuf_wheel_speed = m_actor->ar_wheel_speed; - m_simbuf.simbuf_beaconlight_active = m_actor->m_beacon_light_is_active; - m_simbuf.simbuf_cur_cinecam = m_actor->ar_current_cinecam; - m_simbuf.simbuf_parking_brake = m_actor->ar_parking_brake; - m_simbuf.simbuf_brake = m_actor->ar_brake; - m_simbuf.simbuf_hydro_dir_state = m_actor->ar_hydro_dir_state; - m_simbuf.simbuf_hydro_aileron_state = m_actor->ar_hydro_aileron_state; - m_simbuf.simbuf_hydro_elevator_state = m_actor->ar_hydro_elevator_state; + m_simbuf.simbuf_live_local = (m_actor->ar_sim_state == Actor::SimState::LOCAL_SIMULATED); + m_simbuf.simbuf_physics_paused = m_actor->ar_physics_paused; + m_simbuf.simbuf_pos = m_actor->GetRotationCenter(); + m_simbuf.simbuf_rotation = m_actor->getRotation(); + m_simbuf.simbuf_tyre_pressure = m_actor->GetTyrePressure(); + m_simbuf.simbuf_aabb = m_actor->ar_bounding_box; + m_simbuf.simbuf_wheel_speed = m_actor->ar_wheel_speed; + m_simbuf.simbuf_beaconlight_active = m_actor->m_beacon_light_is_active; + m_simbuf.simbuf_cur_cinecam = m_actor->ar_current_cinecam; + m_simbuf.simbuf_parking_brake = m_actor->ar_parking_brake; + m_simbuf.simbuf_brake = m_actor->ar_brake; + m_simbuf.simbuf_hydro_dir_state = m_actor->ar_hydro_dir_state; + m_simbuf.simbuf_hydro_aileron_state = m_actor->ar_hydro_aileron_state; + m_simbuf.simbuf_hydro_elevator_state = m_actor->ar_hydro_elevator_state; m_simbuf.simbuf_hydro_aero_rudder_state = m_actor->ar_hydro_rudder_state; - m_simbuf.simbuf_aero_flap_state = m_actor->ar_aerial_flap; - m_simbuf.simbuf_airbrake_state = m_actor->ar_airbrake_intensity; - m_simbuf.simbuf_headlight_on = m_actor->ar_lights != 0; - m_simbuf.simbuf_direction = m_actor->getDirection(); - m_simbuf.simbuf_node0_velo = m_actor->ar_nodes[0].Velocity; - m_simbuf.simbuf_net_username = m_actor->m_net_username; - m_simbuf.simbuf_is_remote = m_actor->ar_sim_state == Actor::SimState::NETWORKED_OK; + m_simbuf.simbuf_aero_flap_state = m_actor->ar_aerial_flap; + m_simbuf.simbuf_airbrake_state = m_actor->ar_airbrake_intensity; + m_simbuf.simbuf_headlight_on = m_actor->ar_lights != 0; + m_simbuf.simbuf_direction = m_actor->getDirection(); + m_simbuf.simbuf_node0_velo = m_actor->ar_nodes[0].Velocity; + m_simbuf.simbuf_net_username = m_actor->m_net_username; + m_simbuf.simbuf_is_remote = m_actor->ar_sim_state == Actor::SimState::NETWORKED_OK; // nodes const int num_nodes = m_actor->ar_num_nodes; for (int i = 0; i < num_nodes; ++i) { - auto node = m_actor->ar_nodes[i]; - m_simbuf.simbuf_nodes.get()[i].AbsPosition = node.AbsPosition; + auto node = m_actor->ar_nodes[i]; + m_simbuf.simbuf_nodes.get()[i].AbsPosition = node.AbsPosition; m_simbuf.simbuf_nodes.get()[i].nd_has_contact = node.nd_has_ground_contact || node.nd_has_mesh_contact; } - for (NodeGfx& nx: m_gfx_nodes) + for (NodeGfx &nx : m_gfx_nodes) { m_simbuf.simbuf_nodes.get()[nx.nx_node_idx].nd_is_wet = (nx.nx_wet_time_sec != -1.f); } // beams - for (Rod& rod: m_rods) + for (Rod &rod : m_rods) { - const beam_t& beam = m_actor->ar_beams[rod.rod_beam_index]; - rod.rod_node1 = static_cast(beam.p1->pos); - rod.rod_node2 = static_cast(beam.p2->pos); - if (beam.bm_inter_actor) - { - rod.rod_target_actor = beam.bm_locked_actor; - } + const beam_t &beam = m_actor->ar_beams[rod.rod_beam_index]; + rod.rod_node1 = static_cast(beam.p1->pos); + rod.rod_node2 = static_cast(beam.p2->pos); + if (beam.bm_inter_actor) { rod.rod_target_actor = beam.bm_locked_actor; } rod.rod_is_visible = !beam.bm_disabled && !beam.bm_broken; } // airbrakes const size_t num_airbrakes = m_actor->ar_airbrakes.size(); - for (size_t i=0; i< num_airbrakes; ++i) + for (size_t i = 0; i < num_airbrakes; ++i) { m_simbuf.simbuf_airbrakes[i].simbuf_ab_ratio = m_actor->ar_airbrakes[i]->ratio; } @@ -1862,17 +1748,14 @@ void RoR::GfxActor::UpdateSimDataBuffer() // Engine (+drivetrain) if (m_actor->ar_engine != nullptr) { - m_simbuf.simbuf_gear = m_actor->ar_engine->GetGear(); - m_simbuf.simbuf_autoshift = m_actor->ar_engine->getAutoShift(); - m_simbuf.simbuf_engine_rpm = m_actor->ar_engine->GetEngineRpm(); - m_simbuf.simbuf_engine_turbo_psi= m_actor->ar_engine->GetTurboPsi(); - m_simbuf.simbuf_engine_accel = m_actor->ar_engine->GetAcceleration(); - m_simbuf.simbuf_clutch = m_actor->ar_engine->GetClutch(); - } - if (m_actor->m_num_wheel_diffs > 0) - { - m_simbuf.simbuf_diff_type = m_actor->m_wheel_diffs[0]->GetActiveDiffType(); + m_simbuf.simbuf_gear = m_actor->ar_engine->GetGear(); + m_simbuf.simbuf_autoshift = m_actor->ar_engine->getAutoShift(); + m_simbuf.simbuf_engine_rpm = m_actor->ar_engine->GetEngineRpm(); + m_simbuf.simbuf_engine_turbo_psi = m_actor->ar_engine->GetTurboPsi(); + m_simbuf.simbuf_engine_accel = m_actor->ar_engine->GetAcceleration(); + m_simbuf.simbuf_clutch = m_actor->ar_engine->GetClutch(); } + if (m_actor->m_num_wheel_diffs > 0) { m_simbuf.simbuf_diff_type = m_actor->m_wheel_diffs[0]->GetActiveDiffType(); } // Command keys const int num_commandkeys = MAX_COMMANDS + 10; @@ -1884,36 +1767,35 @@ void RoR::GfxActor::UpdateSimDataBuffer() // Aeroengines for (int i = 0; i < m_actor->ar_num_aeroengines; ++i) { - AeroEngine* src = m_actor->ar_aeroengines[i]; - SimBuffer::AeroEngineSB& dst = m_simbuf.simbuf_aeroengines[i]; + AeroEngine * src = m_actor->ar_aeroengines[i]; + SimBuffer::AeroEngineSB &dst = m_simbuf.simbuf_aeroengines[i]; - dst.simbuf_ae_throttle = src->getThrottle(); - dst.simbuf_ae_rpm = src->getRPM(); - dst.simbuf_ae_rpmpc = src->getRPMpc(); - dst.simbuf_ae_turboprop = (src->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP); - dst.simbuf_ae_ignition = src->getIgnition(); - dst.simbuf_ae_failed = src->isFailed(); + dst.simbuf_ae_throttle = src->getThrottle(); + dst.simbuf_ae_rpm = src->getRPM(); + dst.simbuf_ae_rpmpc = src->getRPMpc(); + dst.simbuf_ae_turboprop = (src->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP); + dst.simbuf_ae_ignition = src->getIgnition(); + dst.simbuf_ae_failed = src->isFailed(); if (dst.simbuf_ae_turboprop) { - Turboprop* tp = static_cast(src); - dst.simbuf_tp_aetorque = (100.0 * tp->indicated_torque / tp->max_torque); // TODO: Code ported as-is from calcAnimators(); what does it do? ~ only_a_ptr, 06/2018 + Turboprop *tp = static_cast(src); + dst.simbuf_tp_aetorque = + (100.0 * tp->indicated_torque / + tp->max_torque); // TODO: Code ported as-is from calcAnimators(); what does it do? ~ only_a_ptr, 06/2018 dst.simbuf_tp_aepitch = tp->pitch; } else // turbojet { - Turbojet* tj = static_cast(src); - dst.simbuf_tj_afterburn = tj->getAfterburner() != 0.f; - dst.simbuf_tj_ab_thrust = tj->getAfterburnThrust(); + Turbojet *tj = static_cast(src); + dst.simbuf_tj_afterburn = tj->getAfterburner() != 0.f; + dst.simbuf_tj_ab_thrust = tj->getAfterburnThrust(); dst.simbuf_tj_exhaust_velo = tj->getExhaustVelocity(); } } // Wings - if (m_actor->ar_num_wings > 4) - { - m_simbuf.simbuf_wing4_aoa = m_actor->ar_wings[4].fa->aoa; - } + if (m_actor->ar_num_wings > 4) { m_simbuf.simbuf_wing4_aoa = m_actor->ar_wings[4].fa->aoa; } else { m_simbuf.simbuf_wing4_aoa = 0.f; @@ -1950,18 +1832,12 @@ bool RoR::GfxActor::IsActorLive() const void RoR::GfxActor::UpdateCabMesh() { - if ((m_cab_entity != nullptr) && (m_cab_mesh != nullptr)) - { - m_cab_scene_node->setPosition(m_cab_mesh->UpdateFlexObj()); - } + if ((m_cab_entity != nullptr) && (m_cab_mesh != nullptr)) { m_cab_scene_node->setPosition(m_cab_mesh->UpdateFlexObj()); } } void RoR::GfxActor::SetWheelVisuals(uint16_t index, WheelGfx wheel_gfx) { - if (m_wheels.size() <= index) - { - m_wheels.resize(index + 1); - } + if (m_wheels.size() <= index) { m_wheels.resize(index + 1); } m_wheels[index] = wheel_gfx; } @@ -1969,14 +1845,11 @@ void RoR::GfxActor::UpdateWheelVisuals() { m_flexwheel_tasks.clear(); - for (WheelGfx& w: m_wheels) + for (WheelGfx &w : m_wheels) { if (w.wx_flex_mesh != nullptr && w.wx_flex_mesh->flexitPrepare()) { - auto func = std::function([this, w]() - { - w.wx_flex_mesh->flexitCompute(); - }); + auto func = std::function([this, w]() { w.wx_flex_mesh->flexitCompute(); }); auto task_handle = gEnv->threadPool->RunTask(func); m_flexwheel_tasks.push_back(task_handle); } @@ -1985,69 +1858,69 @@ void RoR::GfxActor::UpdateWheelVisuals() void RoR::GfxActor::FinishWheelUpdates() { - for (auto& task: m_flexwheel_tasks) + for (auto &task : m_flexwheel_tasks) { task->join(); } - for (WheelGfx& w: m_wheels) + for (WheelGfx &w : m_wheels) { if (w.wx_scenenode != nullptr && w.wx_flex_mesh != nullptr) - { - w.wx_scenenode->setPosition(w.wx_flex_mesh->flexitFinal()); - } + { w.wx_scenenode->setPosition(w.wx_flex_mesh->flexitFinal()); } } } void RoR::GfxActor::SetWheelsVisible(bool value) { - for (WheelGfx& w: m_wheels) + for (WheelGfx &w : m_wheels) { - if (w.wx_scenenode != nullptr) - { - w.wx_scenenode->setVisible(value); - } + if (w.wx_scenenode != nullptr) { w.wx_scenenode->setVisible(value); } if (w.wx_flex_mesh != nullptr) { w.wx_flex_mesh->setVisible(value); if (w.wx_is_meshwheel) { - Ogre::Entity* e = ((FlexMeshWheel*)(w.wx_flex_mesh))->getRimEntity(); - if (e != nullptr) - { - e->setVisible(false); - } + Ogre::Entity *e = ((FlexMeshWheel *)(w.wx_flex_mesh))->getRimEntity(); + if (e != nullptr) { e->setVisible(false); } } } } } - -int RoR::GfxActor::GetActorId () const { return m_actor->ar_instance_id; } -int RoR::GfxActor::GetActorState () const { return static_cast(m_actor->ar_sim_state); } -int RoR::GfxActor::GetActorDriveable () const { return m_actor->ar_driveable; } +int RoR::GfxActor::GetActorId() const +{ + return m_actor->ar_instance_id; +} +int RoR::GfxActor::GetActorState() const +{ + return static_cast(m_actor->ar_sim_state); +} +int RoR::GfxActor::GetActorDriveable() const +{ + return m_actor->ar_driveable; +} void RoR::GfxActor::RegisterAirbrakes() { // TODO: Quick hacky setup with `friend` access - we rely on old init code in RigSpawner/Airbrake. - for (Airbrake* ab: m_actor->ar_airbrakes) + for (Airbrake *ab : m_actor->ar_airbrakes) { AirbrakeGfx abx; // entity abx.abx_entity = ab->ec; - ab->ec = nullptr; + ab->ec = nullptr; // mesh abx.abx_mesh = ab->msh; ab->msh.setNull(); // scenenode abx.abx_scenenode = ab->snode; - ab->snode = nullptr; + ab->snode = nullptr; // offset abx.abx_offset = ab->offset; - ab->offset = Ogre::Vector3::ZERO; + ab->offset = Ogre::Vector3::ZERO; // Nodes - just copy abx.abx_ref_node = ab->noderef->pos; - abx.abx_x_node = ab->nodex->pos; - abx.abx_y_node = ab->nodey->pos; + abx.abx_x_node = ab->nodex->pos; + abx.abx_y_node = ab->nodey->pos; m_gfx_airbrakes.push_back(abx); } @@ -2056,12 +1929,12 @@ void RoR::GfxActor::RegisterAirbrakes() void RoR::GfxActor::UpdateAirbrakes() { const size_t num_airbrakes = m_gfx_airbrakes.size(); - NodeData* nodes = m_simbuf.simbuf_nodes.get(); - for (size_t i=0; iar_airbrakes[i]->maxangle; // Friend access + AirbrakeGfx abx = m_gfx_airbrakes[i]; + const float ratio = m_simbuf.simbuf_airbrakes[i].simbuf_ab_ratio; + const float maxangle = m_actor->ar_airbrakes[i]->maxangle; // Friend access Ogre::Vector3 ref_node_pos = nodes[m_gfx_airbrakes[i].abx_ref_node].AbsPosition; Ogre::Vector3 x_node_pos = nodes[m_gfx_airbrakes[i].abx_x_node].AbsPosition; Ogre::Vector3 y_node_pos = nodes[m_gfx_airbrakes[i].abx_y_node].AbsPosition; @@ -2069,29 +1942,31 @@ void RoR::GfxActor::UpdateAirbrakes() // -- Ported from `AirBrake::updatePosition()` -- Ogre::Vector3 normal = (y_node_pos - ref_node_pos).crossProduct(x_node_pos - ref_node_pos); normal.normalise(); - //position - Ogre::Vector3 mposition = ref_node_pos + abx.abx_offset.x * (x_node_pos - ref_node_pos) + abx.abx_offset.y * (y_node_pos - ref_node_pos); + // position + Ogre::Vector3 mposition = + ref_node_pos + abx.abx_offset.x * (x_node_pos - ref_node_pos) + abx.abx_offset.y * (y_node_pos - ref_node_pos); abx.abx_scenenode->setPosition(mposition + normal * abx.abx_offset.z); - //orientation + // orientation Ogre::Vector3 refx = x_node_pos - ref_node_pos; refx.normalise(); - Ogre::Vector3 refy = refx.crossProduct(normal); - Ogre::Quaternion orientation = Ogre::Quaternion(Ogre::Degree(-ratio * maxangle), (x_node_pos - ref_node_pos).normalisedCopy()) * Ogre::Quaternion(refx, normal, refy); + Ogre::Vector3 refy = refx.crossProduct(normal); + Ogre::Quaternion orientation = + Ogre::Quaternion(Ogre::Degree(-ratio * maxangle), (x_node_pos - ref_node_pos).normalisedCopy()) * + Ogre::Quaternion(refx, normal, refy); abx.abx_scenenode->setOrientation(orientation); - } } // TODO: Also move the data structure + setup code to GfxActor ~ only_a_ptr, 05/2018 void RoR::GfxActor::UpdateCParticles() { - //update custom particle systems - NodeData* nodes = m_simbuf.simbuf_nodes.get(); + // update custom particle systems + NodeData *nodes = m_simbuf.simbuf_nodes.get(); for (int i = 0; i < m_actor->ar_num_custom_particles; i++) { Ogre::Vector3 pos = nodes[m_actor->ar_custom_particles[i].emitterNode].AbsPosition; Ogre::Vector3 dir = pos - nodes[m_actor->ar_custom_particles[i].directionNode].AbsPosition; - dir = fast_normalise(dir); + dir = fast_normalise(dir); m_actor->ar_custom_particles[i].snode->setPosition(pos); for (int j = 0; j < m_actor->ar_custom_particles[i].psys->getNumEmitters(); j++) { @@ -2129,13 +2004,12 @@ void RoR::GfxActor::UpdateNetLabels(float dt) if (vlen > 1000) // 1000 ... vlen { - m_actor->m_net_label_mt->setCaption( - m_simbuf.simbuf_net_username + " (" + TOSTRING((float)(ceil(vlen / 100) / 10.0) ) + " km)"); + m_actor->m_net_label_mt->setCaption(m_simbuf.simbuf_net_username + " (" + TOSTRING((float)(ceil(vlen / 100) / 10.0)) + + " km)"); } else if (vlen > 20) // 20 ... vlen ... 1000 { - m_actor->m_net_label_mt->setCaption( - m_simbuf.simbuf_net_username + " (" + TOSTRING((int)vlen) + " m)"); + m_actor->m_net_label_mt->setCaption(m_simbuf.simbuf_net_username + " (" + TOSTRING((int)vlen) + " m)"); } else // 0 ... vlen ... 20 { @@ -2145,19 +2019,19 @@ void RoR::GfxActor::UpdateNetLabels(float dt) } } -void RoR::GfxActor::CalculateDriverPos(Ogre::Vector3& out_pos, Ogre::Quaternion& out_rot) +void RoR::GfxActor::CalculateDriverPos(Ogre::Vector3 &out_pos, Ogre::Quaternion &out_rot) { assert(m_driverseat_prop_index != -1); - prop_t* driverseat_prop = &m_props[m_driverseat_prop_index]; + prop_t *driverseat_prop = &m_props[m_driverseat_prop_index]; - NodeData* nodes = this->GetSimNodeBuffer(); + NodeData *nodes = this->GetSimNodeBuffer(); - const Ogre::Vector3 x_pos = nodes[driverseat_prop->nodex].AbsPosition; - const Ogre::Vector3 y_pos = nodes[driverseat_prop->nodey].AbsPosition; + const Ogre::Vector3 x_pos = nodes[driverseat_prop->nodex].AbsPosition; + const Ogre::Vector3 y_pos = nodes[driverseat_prop->nodey].AbsPosition; const Ogre::Vector3 center_pos = nodes[driverseat_prop->noderef].AbsPosition; - const Ogre::Vector3 x_vec = x_pos - center_pos; - const Ogre::Vector3 y_vec = y_pos - center_pos; + const Ogre::Vector3 x_vec = x_pos - center_pos; + const Ogre::Vector3 y_vec = y_pos - center_pos; const Ogre::Vector3 normal = (y_vec.crossProduct(x_vec)).normalisedCopy(); // Output position @@ -2170,49 +2044,52 @@ void RoR::GfxActor::CalculateDriverPos(Ogre::Vector3& out_pos, Ogre::Quaternion& // Output orientation const Ogre::Vector3 x_vec_norm = x_vec.normalisedCopy(); const Ogre::Vector3 y_vec_norm = x_vec_norm.crossProduct(normal); - Ogre::Quaternion rot(x_vec_norm, normal, y_vec_norm); - rot = rot * driverseat_prop->rot; - rot = rot * Ogre::Quaternion(Ogre::Degree(180), Ogre::Vector3::UNIT_Y); // rotate towards the driving direction + Ogre::Quaternion rot(x_vec_norm, normal, y_vec_norm); + rot = rot * driverseat_prop->rot; + rot = rot * Ogre::Quaternion(Ogre::Degree(180), Ogre::Vector3::UNIT_Y); // rotate towards the driving direction out_rot = rot; } -void RoR::GfxActor::UpdateBeaconFlare(prop_t & prop, float dt, bool is_player_actor) +void RoR::GfxActor::UpdateBeaconFlare(prop_t &prop, float dt, bool is_player_actor) { // TODO: Quick and dirty port from Beam::updateFlares(), clean it up ~ only_a_ptr, 06/2018 using namespace Ogre; - bool enableAll = !((App::gfx_flares_mode.GetActive() == GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY) && !is_player_actor); - NodeData* nodes = this->GetSimNodeBuffer(); + bool enableAll = !((App::gfx_flares_mode.GetActive() == GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY) && !is_player_actor); + NodeData *nodes = this->GetSimNodeBuffer(); if (prop.beacontype == 'b') { // Get data - Ogre::SceneNode* beacon_scene_node = prop.scene_node; - Ogre::Quaternion beacon_orientation = beacon_scene_node->getOrientation(); - Ogre::Light* beacon_light = prop.beacon_light[0]; - float beacon_rotation_rate = prop.beacon_light_rotation_rate[0]; - float beacon_rotation_angle = prop.beacon_light_rotation_angle[0]; // Updated at end of block + Ogre::SceneNode *beacon_scene_node = prop.scene_node; + Ogre::Quaternion beacon_orientation = beacon_scene_node->getOrientation(); + Ogre::Light * beacon_light = prop.beacon_light[0]; + float beacon_rotation_rate = prop.beacon_light_rotation_rate[0]; + float beacon_rotation_angle = prop.beacon_light_rotation_angle[0]; // Updated at end of block // Transform beacon_light->setPosition(beacon_scene_node->getPosition() + beacon_orientation * Ogre::Vector3(0, 0, 0.12)); - beacon_rotation_angle += dt * beacon_rotation_rate;//rotate baby! + beacon_rotation_angle += dt * beacon_rotation_rate; // rotate baby! beacon_light->setDirection(beacon_orientation * Ogre::Vector3(cos(beacon_rotation_angle), sin(beacon_rotation_angle), 0)); - //billboard - Ogre::Vector3 vdir = beacon_light->getPosition() - gEnv->mainCamera->getPosition(); // TODO: verify the position is already updated here ~ only_a_ptr, 06/2018 + // billboard + Ogre::Vector3 vdir = + beacon_light->getPosition() - + gEnv->mainCamera->getPosition(); // TODO: verify the position is already updated here ~ only_a_ptr, 06/2018 float vlen = vdir.length(); if (vlen > 100.0) { prop.beacon_flare_billboard_scene_node[0]->setVisible(false); return; } - //normalize + // normalize vdir = vdir / vlen; prop.beacon_flare_billboard_scene_node[0]->setPosition(beacon_light->getPosition() - vdir * 0.1); float amplitude = beacon_light->getDirection().dotProduct(vdir); if (amplitude > 0) { prop.beacon_flare_billboard_scene_node[0]->setVisible(true); - prop.beacon_flares_billboard_system[0]->setDefaultDimensions(amplitude * amplitude * amplitude, amplitude * amplitude * amplitude); + prop.beacon_flares_billboard_system[0]->setDefaultDimensions(amplitude * amplitude * amplitude, + amplitude * amplitude * amplitude); } else { @@ -2228,37 +2105,43 @@ void RoR::GfxActor::UpdateBeaconFlare(prop_t & prop, float dt, bool is_player_ac { for (int k = 0; k < 4; k++) { - //update light + // update light Quaternion orientation = prop.scene_node->getOrientation(); switch (k) { - case 0: prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(-0.64, 0, 0.14)); + case 0: + prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(-0.64, 0, 0.14)); break; - case 1: prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(-0.32, 0, 0.14)); + case 1: + prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(-0.32, 0, 0.14)); break; - case 2: prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(+0.32, 0, 0.14)); + case 2: + prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(+0.32, 0, 0.14)); break; - case 3: prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(+0.64, 0, 0.14)); + case 3: + prop.beacon_light[k]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(+0.64, 0, 0.14)); break; } - prop.beacon_light_rotation_angle[k] += dt * prop.beacon_light_rotation_rate[k];//rotate baby! - prop.beacon_light[k]->setDirection(orientation * Vector3(cos(prop.beacon_light_rotation_angle[k]), sin(prop.beacon_light_rotation_angle[k]), 0)); - //billboard + prop.beacon_light_rotation_angle[k] += dt * prop.beacon_light_rotation_rate[k]; // rotate baby! + prop.beacon_light[k]->setDirection( + orientation * Vector3(cos(prop.beacon_light_rotation_angle[k]), sin(prop.beacon_light_rotation_angle[k]), 0)); + // billboard Vector3 vdir = prop.beacon_light[k]->getPosition() - gEnv->mainCamera->getPosition(); - float vlen = vdir.length(); + float vlen = vdir.length(); if (vlen > 100.0) { prop.beacon_flare_billboard_scene_node[k]->setVisible(false); continue; } - //normalize + // normalize vdir = vdir / vlen; prop.beacon_flare_billboard_scene_node[k]->setPosition(prop.beacon_light[k]->getPosition() - vdir * 0.2); float amplitude = prop.beacon_light[k]->getDirection().dotProduct(vdir); if (amplitude > 0) { prop.beacon_flare_billboard_scene_node[k]->setVisible(true); - prop.beacon_flares_billboard_system[k]->setDefaultDimensions(amplitude * amplitude * amplitude, amplitude * amplitude * amplitude); + prop.beacon_flares_billboard_system[k]->setDefaultDimensions(amplitude * amplitude * amplitude, + amplitude * amplitude * amplitude); } else { @@ -2269,26 +2152,26 @@ void RoR::GfxActor::UpdateBeaconFlare(prop_t & prop, float dt, bool is_player_ac } else if (prop.beacontype == 'r') { - //update light + // update light Quaternion orientation = prop.scene_node->getOrientation(); prop.beacon_light[0]->setPosition(prop.scene_node->getPosition() + orientation * Vector3(0, 0, 0.06)); - prop.beacon_light_rotation_angle[0] += dt * prop.beacon_light_rotation_rate[0];//rotate baby! - //billboard + prop.beacon_light_rotation_angle[0] += dt * prop.beacon_light_rotation_rate[0]; // rotate baby! + // billboard Vector3 vdir = prop.beacon_light[0]->getPosition() - gEnv->mainCamera->getPosition(); - float vlen = vdir.length(); + float vlen = vdir.length(); if (vlen > 100.0) { prop.beacon_flare_billboard_scene_node[0]->setVisible(false); return; } - //normalize + // normalize vdir = vdir / vlen; prop.beacon_flare_billboard_scene_node[0]->setPosition(prop.beacon_light[0]->getPosition() - vdir * 0.1); bool visible = false; if (prop.beacon_light_rotation_angle[0] > 1.0) { prop.beacon_light_rotation_angle[0] = 0.0; - visible = true; + visible = true; } visible = visible && enableAll; prop.beacon_light[0]->setVisible(visible); @@ -2296,40 +2179,44 @@ void RoR::GfxActor::UpdateBeaconFlare(prop_t & prop, float dt, bool is_player_ac } else if (prop.beacontype == 'R' || prop.beacontype == 'L') // Avionic navigation lights (red/green) { - Vector3 mposition = nodes[prop.noderef].AbsPosition + prop.offsetx * (nodes[prop.nodex].AbsPosition - nodes[prop.noderef].AbsPosition) + prop.offsety * (nodes[prop.nodey].AbsPosition - nodes[prop.noderef].AbsPosition); - //billboard + Vector3 mposition = nodes[prop.noderef].AbsPosition + + prop.offsetx * (nodes[prop.nodex].AbsPosition - nodes[prop.noderef].AbsPosition) + + prop.offsety * (nodes[prop.nodey].AbsPosition - nodes[prop.noderef].AbsPosition); + // billboard Vector3 vdir = mposition - gEnv->mainCamera->getPosition(); - float vlen = vdir.length(); + float vlen = vdir.length(); if (vlen > 100.0) { prop.beacon_flare_billboard_scene_node[0]->setVisible(false); return; } - //normalize + // normalize vdir = vdir / vlen; prop.beacon_flare_billboard_scene_node[0]->setPosition(mposition - vdir * 0.1); } else if (prop.beacontype == 'w') // Avionic navigation lights (white rotating beacon) { - Vector3 mposition = nodes[prop.noderef].AbsPosition + prop.offsetx * (nodes[prop.nodex].AbsPosition - nodes[prop.noderef].AbsPosition) + prop.offsety * (nodes[prop.nodey].AbsPosition - nodes[prop.noderef].AbsPosition); + Vector3 mposition = nodes[prop.noderef].AbsPosition + + prop.offsetx * (nodes[prop.nodex].AbsPosition - nodes[prop.noderef].AbsPosition) + + prop.offsety * (nodes[prop.nodey].AbsPosition - nodes[prop.noderef].AbsPosition); prop.beacon_light[0]->setPosition(mposition); - prop.beacon_light_rotation_angle[0] += dt * prop.beacon_light_rotation_rate[0];//rotate baby! - //billboard + prop.beacon_light_rotation_angle[0] += dt * prop.beacon_light_rotation_rate[0]; // rotate baby! + // billboard Vector3 vdir = mposition - gEnv->mainCamera->getPosition(); - float vlen = vdir.length(); + float vlen = vdir.length(); if (vlen > 100.0) { prop.beacon_flare_billboard_scene_node[0]->setVisible(false); return; } - //normalize + // normalize vdir = vdir / vlen; prop.beacon_flare_billboard_scene_node[0]->setPosition(mposition - vdir * 0.1); bool visible = false; if (prop.beacon_light_rotation_angle[0] > 1.0) { prop.beacon_light_rotation_angle[0] = 0.0; - visible = true; + visible = true; } visible = visible && enableAll; prop.beacon_light[0]->setVisible(visible); @@ -2341,10 +2228,10 @@ void RoR::GfxActor::UpdateProps(float dt, bool is_player_actor) { using namespace Ogre; - NodeData* nodes = this->GetSimNodeBuffer(); + NodeData *nodes = this->GetSimNodeBuffer(); // Update prop meshes - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { if (prop.scene_node == nullptr) // Wing beacons don't have scenenodes continue; @@ -2353,7 +2240,7 @@ void RoR::GfxActor::UpdateProps(float dt, bool is_player_actor) if (prop.pp_aero_propeller_blade || prop.pp_aero_propeller_spin) { const float SPINNER_THRESHOLD = 200.f; // TODO: magic! ~ only_a_ptr, 09/2018 - const bool show_spinner = m_simbuf.simbuf_aeroengines[prop.pp_aero_engine_idx].simbuf_ae_rpm > SPINNER_THRESHOLD; + const bool show_spinner = m_simbuf.simbuf_aeroengines[prop.pp_aero_engine_idx].simbuf_ae_rpm > SPINNER_THRESHOLD; if (prop.pp_aero_propeller_blade) prop.scene_node->setVisible(!show_spinner); else if (prop.pp_aero_propeller_spin) @@ -2379,15 +2266,15 @@ void RoR::GfxActor::UpdateProps(float dt, bool is_player_actor) Vector3 mposition = nodes[prop.noderef].AbsPosition + prop.offsetx * diffX + prop.offsety * diffY; prop.scene_node->setPosition(mposition + normal * prop.offsetz); - Vector3 refx = diffX.normalisedCopy(); - Vector3 refy = refx.crossProduct(normal); + Vector3 refx = diffX.normalisedCopy(); + Vector3 refy = refx.crossProduct(normal); Quaternion orientation = Quaternion(refx, normal, refy) * prop.rot; prop.scene_node->setOrientation(orientation); if (prop.wheel) // special prop - steering wheel { Quaternion brot = Quaternion(Degree(-59.0), Vector3::UNIT_X); - brot = brot * Quaternion(Degree(m_simbuf.simbuf_hydro_dir_state * prop.wheelrotdegree), Vector3::UNIT_Y); + brot = brot * Quaternion(Degree(m_simbuf.simbuf_hydro_dir_state * prop.wheelrotdegree), Vector3::UNIT_Y); prop.wheel->setPosition(mposition + normal * prop.offsetz + orientation * prop.wheelpos); prop.wheel->setOrientation(orientation * brot); } @@ -2400,58 +2287,46 @@ void RoR::GfxActor::UpdateProps(float dt, bool is_player_actor) this->SetBeaconsEnabled(m_beaconlight_active); } - if ((App::gfx_flares_mode.GetActive() != GfxFlaresMode::NONE) - && m_beaconlight_active) + if ((App::gfx_flares_mode.GetActive() != GfxFlaresMode::NONE) && m_beaconlight_active) { - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { - if (prop.beacontype != 0) - { - this->UpdateBeaconFlare(prop, dt, is_player_actor); - } + if (prop.beacontype != 0) { this->UpdateBeaconFlare(prop, dt, is_player_actor); } } } } void RoR::GfxActor::SetPropsVisible(bool visible) { - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { - if (prop.mo) - prop.mo->setVisible(visible); - if (prop.wheel) - prop.wheel->setVisible(visible); - if (prop.beacon_flare_billboard_scene_node[0]) - prop.beacon_flare_billboard_scene_node[0]->setVisible(visible); - if (prop.beacon_flare_billboard_scene_node[1]) - prop.beacon_flare_billboard_scene_node[1]->setVisible(visible); - if (prop.beacon_flare_billboard_scene_node[2]) - prop.beacon_flare_billboard_scene_node[2]->setVisible(visible); - if (prop.beacon_flare_billboard_scene_node[3]) - prop.beacon_flare_billboard_scene_node[3]->setVisible(visible); + if (prop.mo) prop.mo->setVisible(visible); + if (prop.wheel) prop.wheel->setVisible(visible); + if (prop.beacon_flare_billboard_scene_node[0]) prop.beacon_flare_billboard_scene_node[0]->setVisible(visible); + if (prop.beacon_flare_billboard_scene_node[1]) prop.beacon_flare_billboard_scene_node[1]->setVisible(visible); + if (prop.beacon_flare_billboard_scene_node[2]) prop.beacon_flare_billboard_scene_node[2]->setVisible(visible); + if (prop.beacon_flare_billboard_scene_node[3]) prop.beacon_flare_billboard_scene_node[3]->setVisible(visible); } } void RoR::GfxActor::SetRenderdashActive(bool active) { - if (m_renderdash != nullptr) - { - m_renderdash->setEnable(active); - } + if (m_renderdash != nullptr) { m_renderdash->setEnable(active); } } void RoR::GfxActor::SetBeaconsEnabled(bool beacon_light_is_active) { const bool enableLight = (App::gfx_flares_mode.GetActive() != GfxFlaresMode::NO_LIGHTSOURCES); - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { char beacon_type = prop.beacontype; if (beacon_type == 'b') { prop.beacon_light[0]->setVisible(beacon_light_is_active && enableLight); prop.beacon_flare_billboard_scene_node[0]->setVisible(beacon_light_is_active); - if (prop.beacon_flares_billboard_system[0] && beacon_light_is_active && !prop.beacon_flare_billboard_scene_node[0]->numAttachedObjects()) + if (prop.beacon_flares_billboard_system[0] && beacon_light_is_active && + !prop.beacon_flare_billboard_scene_node[0]->numAttachedObjects()) { prop.beacon_flares_billboard_system[0]->setVisible(true); prop.beacon_flare_billboard_scene_node[0]->attachObject(prop.beacon_flares_billboard_system[0]); @@ -2465,7 +2340,8 @@ void RoR::GfxActor::SetBeaconsEnabled(bool beacon_light_is_active) else if (beacon_type == 'R' || beacon_type == 'L') { prop.beacon_flare_billboard_scene_node[0]->setVisible(beacon_light_is_active); - if (prop.beacon_flares_billboard_system[0] && beacon_light_is_active && !prop.beacon_flare_billboard_scene_node[0]->numAttachedObjects()) + if (prop.beacon_flares_billboard_system[0] && beacon_light_is_active && + !prop.beacon_flare_billboard_scene_node[0]->numAttachedObjects()) prop.beacon_flare_billboard_scene_node[0]->attachObject(prop.beacon_flares_billboard_system[0]); else if (prop.beacon_flares_billboard_system[0] && !beacon_light_is_active) prop.beacon_flare_billboard_scene_node[0]->detachAllObjects(); @@ -2476,7 +2352,8 @@ void RoR::GfxActor::SetBeaconsEnabled(bool beacon_light_is_active) { prop.beacon_light[k]->setVisible(beacon_light_is_active && enableLight); prop.beacon_flare_billboard_scene_node[k]->setVisible(beacon_light_is_active); - if (prop.beacon_flares_billboard_system[k] && beacon_light_is_active && !prop.beacon_flare_billboard_scene_node[k]->numAttachedObjects()) + if (prop.beacon_flares_billboard_system[k] && beacon_light_is_active && + !prop.beacon_flare_billboard_scene_node[k]->numAttachedObjects()) prop.beacon_flare_billboard_scene_node[k]->attachObject(prop.beacon_flares_billboard_system[k]); else if (prop.beacon_flares_billboard_system[k] && !beacon_light_is_active) prop.beacon_flare_billboard_scene_node[k]->detachAllObjects(); @@ -2486,18 +2363,14 @@ void RoR::GfxActor::SetBeaconsEnabled(bool beacon_light_is_active) { for (int k = 0; k < 4; k++) { - if (prop.beacon_light[k]) - { - prop.beacon_light[k]->setVisible(beacon_light_is_active && enableLight); - } + if (prop.beacon_light[k]) { prop.beacon_light[k]->setVisible(beacon_light_is_active && enableLight); } if (prop.beacon_flare_billboard_scene_node[k]) { prop.beacon_flare_billboard_scene_node[k]->setVisible(beacon_light_is_active); - if (prop.beacon_flares_billboard_system[k] && beacon_light_is_active && !prop.beacon_flare_billboard_scene_node[k]->numAttachedObjects()) - { - prop.beacon_flare_billboard_scene_node[k]->attachObject(prop.beacon_flares_billboard_system[k]); - } + if (prop.beacon_flares_billboard_system[k] && beacon_light_is_active && + !prop.beacon_flare_billboard_scene_node[k]->numAttachedObjects()) + { prop.beacon_flare_billboard_scene_node[k]->attachObject(prop.beacon_flares_billboard_system[k]); } else if (prop.beacon_flares_billboard_system[k] && !beacon_light_is_active) { prop.beacon_flare_billboard_scene_node[k]->detachAllObjects(); @@ -2508,62 +2381,54 @@ void RoR::GfxActor::SetBeaconsEnabled(bool beacon_light_is_active) } } - -void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div, float dt, const float lower_limit, const float upper_limit, const float option3) +void RoR::GfxActor::CalcPropAnimation(const int flag_state, float &cstate, int &div, float dt, const float lower_limit, + const float upper_limit, const float option3) { // ## DEV NOTE: // ## This function is a modified copypaste of `Actor::calcAnimators()` which was used // ## for both animator-beams (physics, part of softbody) and animated props (visual-only). // ## ~ only_a_ptr, 06/2018 - //boat rudder + // boat rudder if (flag_state & ANIM_FLAG_BRUDDER) { size_t spi; - float ctmp = 0.0f; + float ctmp = 0.0f; for (spi = 0; spi < m_simbuf.simbuf_screwprops.size(); spi++) { ctmp += m_simbuf.simbuf_screwprops[spi].simbuf_sp_rudder; } - if (spi > 0) - ctmp = ctmp / spi; + if (spi > 0) ctmp = ctmp / spi; cstate = ctmp; div++; } - //boat throttle + // boat throttle if (flag_state & ANIM_FLAG_BTHROTTLE) { size_t spi; - float ctmp = 0.0f; + float ctmp = 0.0f; for (spi = 0; spi < m_simbuf.simbuf_screwprops.size(); spi++) { ctmp += m_simbuf.simbuf_screwprops[spi].simbuf_sp_throttle; } - if (spi > 0) - ctmp = ctmp / spi; + if (spi > 0) ctmp = ctmp / spi; cstate = ctmp; div++; } - //differential lock status + // differential lock status if (flag_state & ANIM_FLAG_DIFFLOCK) { if (m_actor->m_num_wheel_diffs > 0) // read-only attribute - safe to read from here { switch (m_simbuf.simbuf_diff_type) { - case DiffType::OPEN_DIFF: - cstate = 0.0f; - break; - case DiffType::SPLIT_DIFF: - cstate = 0.5f; - break; - case DiffType::LOCKED_DIFF: - cstate = 1.0f; - break; + case DiffType::OPEN_DIFF: cstate = 0.0f; break; + case DiffType::SPLIT_DIFF: cstate = 0.5f; break; + case DiffType::LOCKED_DIFF: cstate = 1.0f; break; default:; } } @@ -2573,7 +2438,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //heading + // heading if (flag_state & ANIM_FLAG_HEADING) { // rad2deg limitedrange -1 to +1 @@ -2581,25 +2446,23 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //torque - WRITES - const bool has_engine = (m_actor->ar_engine!= nullptr); + // torque - WRITES + const bool has_engine = (m_actor->ar_engine != nullptr); if (has_engine && flag_state & ANIM_FLAG_TORQUE) { float torque = m_simbuf.simbuf_engine_crankfactor; - if (torque <= 0.0f) - torque = 0.0f; + if (torque <= 0.0f) torque = 0.0f; if (torque >= m_prop_anim_crankfactor_prev) cstate -= torque / 10.0f; else cstate = 0.0f; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate <= -1.0f) cstate = -1.0f; m_prop_anim_crankfactor_prev = torque; div++; } - //shifterseq, to amimate sequentiell shifting + // shifterseq, to amimate sequentiell shifting if (has_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 3.0f) { // opt1 &opt2 = 0 this is a shifter @@ -2608,12 +2471,12 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& int shifter = m_simbuf.simbuf_gear; if (shifter > m_prop_anim_prev_gear) { - cstate = 1.0f; + cstate = 1.0f; m_prop_anim_shift_timer = 0.2f; } if (shifter < m_prop_anim_prev_gear) { - cstate = -1.0f; + cstate = -1.0f; m_prop_anim_shift_timer = -0.2f; } m_prop_anim_prev_gear = shifter; @@ -2622,40 +2485,33 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& { cstate = 1.0f; m_prop_anim_shift_timer -= dt; - if (m_prop_anim_shift_timer < 0.0f) - m_prop_anim_shift_timer = 0.0f; + if (m_prop_anim_shift_timer < 0.0f) m_prop_anim_shift_timer = 0.0f; } if (m_prop_anim_shift_timer < 0.0f) { cstate = -1.0f; m_prop_anim_shift_timer += dt; - if (m_prop_anim_shift_timer > 0.0f) - m_prop_anim_shift_timer = 0.0f; + if (m_prop_anim_shift_timer > 0.0f) m_prop_anim_shift_timer = 0.0f; } } else { // check if lower_limit is a valid to get commandvalue, then get commandvalue if (lower_limit >= 1.0f && lower_limit <= 48.0) - if (m_simbuf.simbuf_commandkey[int(lower_limit)].simbuf_cmd_value > 0) - cstate += 1.0f; + if (m_simbuf.simbuf_commandkey[int(lower_limit)].simbuf_cmd_value > 0) cstate += 1.0f; // check if upper_limit is a valid to get commandvalue, then get commandvalue if (upper_limit >= 1.0f && upper_limit <= 48.0) - if (m_simbuf.simbuf_commandkey[int(upper_limit)].simbuf_cmd_value > 0) - cstate -= 1.0f; + if (m_simbuf.simbuf_commandkey[int(upper_limit)].simbuf_cmd_value > 0) cstate -= 1.0f; } div++; } - //shifterman1, left/right + // shifterman1, left/right if (has_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 1.0f) { int shifter = m_simbuf.simbuf_gear; - if (!shifter) - { - cstate = -0.5f; - } + if (!shifter) { cstate = -0.5f; } else if (shifter < 0) { cstate = 1.0f; @@ -2667,32 +2523,26 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //shifterman2, up/down + // shifterman2, up/down if (has_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 2.0f) { int shifter = m_simbuf.simbuf_gear; - cstate = 0.5f; - if (shifter < 0) - { - cstate = 1.0f; - } - if (shifter > 0) - { - cstate = shifter % 2; - } + cstate = 0.5f; + if (shifter < 0) { cstate = 1.0f; } + if (shifter > 0) { cstate = shifter % 2; } div++; } - //shifterlinear, to amimate cockpit gearselect gauge and autotransmission stick + // shifterlinear, to amimate cockpit gearselect gauge and autotransmission stick if (has_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 4.0f) { - int shifter = m_simbuf.simbuf_gear; + int shifter = m_simbuf.simbuf_gear; int numgears = m_attr.xa_num_gears; cstate -= (shifter + 2.0) / (numgears + 2.0); div++; } - //parking brake + // parking brake if (flag_state & ANIM_FLAG_PBRAKE) { float pbrake = static_cast(m_simbuf.simbuf_parking_brake); // Bool --> float @@ -2700,7 +2550,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //speedo ( scales with speedomax ) + // speedo ( scales with speedomax ) if (flag_state & ANIM_FLAG_SPEEDO) { float speedo = m_simbuf.simbuf_wheel_speed / m_attr.xa_speedo_highest_kph; @@ -2708,7 +2558,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //engine tacho ( scales with maxrpm, default is 3500 ) + // engine tacho ( scales with maxrpm, default is 3500 ) if (has_engine && flag_state & ANIM_FLAG_TACHO) { float tacho = m_simbuf.simbuf_engine_rpm / m_attr.xa_engine_max_rpm; @@ -2716,7 +2566,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //turbo + // turbo if (has_engine && flag_state & ANIM_FLAG_TURBO) { float turbo = m_simbuf.simbuf_engine_turbo_psi * 3.34; @@ -2724,7 +2574,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //brake + // brake if (flag_state & ANIM_FLAG_BRAKE) { float brakes = m_simbuf.simbuf_brake; @@ -2732,7 +2582,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //accelerator + // accelerator if (has_engine && flag_state & ANIM_FLAG_ACCEL) { float accel = m_simbuf.simbuf_engine_accel; @@ -2741,7 +2591,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //clutch + // clutch if (has_engine && flag_state & ANIM_FLAG_CLUTCH) { float clutch = m_simbuf.simbuf_clutch; @@ -2749,7 +2599,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //aeroengines rpm + throttle + torque ( turboprop ) + pitch ( turboprop ) + status + fire + // aeroengines rpm + throttle + torque ( turboprop ) + pitch ( turboprop ) + status + fire // `option3` is aeroengine number (starting from 1) if (option3 > 0.f && option3 <= float(m_simbuf.simbuf_aeroengines.size())) { @@ -2795,120 +2645,110 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& cstate = 0.0f; else cstate = 0.5f; - if (m_simbuf.simbuf_aeroengines[aenum].simbuf_ae_failed) - cstate = 1.0f; + if (m_simbuf.simbuf_aeroengines[aenum].simbuf_ae_failed) cstate = 1.0f; div++; } } - const Ogre::Vector3 node0_pos = this->GetSimNodeBuffer()[0].AbsPosition; + const Ogre::Vector3 node0_pos = this->GetSimNodeBuffer()[0].AbsPosition; const Ogre::Vector3 node0_velo = m_simbuf.simbuf_node0_velo; - //airspeed indicator + // airspeed indicator if (flag_state & ANIM_FLAG_AIRSPEED) { float ground_speed_kt = node0_velo.length() * 1.9438; - float altitude = node0_pos.y; + float altitude = node0_pos.y; - float sea_level_pressure = 101325; //in Pa + float sea_level_pressure = 101325; // in Pa - float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa - float airdensity = airpressure * 0.0000120896;//1.225 at sea level - float kt = ground_speed_kt * sqrt(airdensity / 1.225); + float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896; // 1.225 at sea level + float kt = ground_speed_kt * sqrt(airdensity / 1.225); cstate -= kt / 100.0f; div++; } - //vvi indicator + // vvi indicator if (flag_state & ANIM_FLAG_VVI) { float vvi = node0_velo.y * 196.85; // limit vvi scale to +/- 6m/s cstate -= vvi / 6000.0f; - if (cstate >= 1.0f) - cstate = 1.0f; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate >= 1.0f) cstate = 1.0f; + if (cstate <= -1.0f) cstate = -1.0f; div++; } - //altimeter + // altimeter if (flag_state & ANIM_FLAG_ALTIMETER) { - //altimeter indicator 1k oscillating + // altimeter indicator 1k oscillating if (option3 == 3.0f) { float altimeter = (node0_pos.y * 1.1811) / 360.0f; - int alti_int = int(altimeter); - float alti_mod = (altimeter - alti_int); + int alti_int = int(altimeter); + float alti_mod = (altimeter - alti_int); cstate -= alti_mod; } - //altimeter indicator 10k oscillating + // altimeter indicator 10k oscillating if (option3 == 2.0f) { - float alti = node0_pos.y * 1.1811 / 3600.0f; - int alti_int = int(alti); + float alti = node0_pos.y * 1.1811 / 3600.0f; + int alti_int = int(alti); float alti_mod = (alti - alti_int); cstate -= alti_mod; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate <= -1.0f) cstate = -1.0f; } - //altimeter indicator 100k limited + // altimeter indicator 100k limited if (option3 == 1.0f) { float alti = node0_pos.y * 1.1811 / 36000.0f; cstate -= alti; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate <= -1.0f) cstate = -1.0f; } div++; } - //AOA + // AOA if (flag_state & ANIM_FLAG_AOA) { float aoa = m_simbuf.simbuf_wing4_aoa / 25.f; - if ((node0_velo.length() * 1.9438) < 10.0f) - aoa = 0; + if ((node0_velo.length() * 1.9438) < 10.0f) aoa = 0; cstate -= aoa; - if (cstate <= -1.0f) - cstate = -1.0f; - if (cstate >= 1.0f) - cstate = 1.0f; + if (cstate <= -1.0f) cstate = -1.0f; + if (cstate >= 1.0f) cstate = 1.0f; div++; } - Ogre::Vector3 cam_pos = this->GetSimNodeBuffer()[m_actor->ar_main_camera_node_pos ].AbsPosition; + Ogre::Vector3 cam_pos = this->GetSimNodeBuffer()[m_actor->ar_main_camera_node_pos].AbsPosition; Ogre::Vector3 cam_roll = this->GetSimNodeBuffer()[m_actor->ar_main_camera_node_roll].AbsPosition; - Ogre::Vector3 cam_dir = this->GetSimNodeBuffer()[m_actor->ar_main_camera_node_dir ].AbsPosition; + Ogre::Vector3 cam_dir = this->GetSimNodeBuffer()[m_actor->ar_main_camera_node_dir].AbsPosition; // roll if (flag_state & ANIM_FLAG_ROLL) { - Ogre::Vector3 rollv = (cam_pos - cam_roll).normalisedCopy(); - Ogre::Vector3 dirv = (cam_pos - cam_dir).normalisedCopy(); - Ogre::Vector3 upv = dirv.crossProduct(-rollv); - float rollangle = asin(rollv.dotProduct(Ogre::Vector3::UNIT_Y)); + Ogre::Vector3 rollv = (cam_pos - cam_roll).normalisedCopy(); + Ogre::Vector3 dirv = (cam_pos - cam_dir).normalisedCopy(); + Ogre::Vector3 upv = dirv.crossProduct(-rollv); + float rollangle = asin(rollv.dotProduct(Ogre::Vector3::UNIT_Y)); // rad to deg rollangle = Ogre::Math::RadiansToDegrees(rollangle); // flip to other side when upside down - if (upv.y < 0) - rollangle = 180.0f - rollangle; + if (upv.y < 0) rollangle = 180.0f - rollangle; cstate = rollangle / 180.0f; // data output is -0.5 to 1.5, normalize to -1 to +1 without changing the zero position. // this is vital for the animator beams and does not effect the animated props - if (cstate >= 1.0f) - cstate = cstate - 2.0f; + if (cstate >= 1.0f) cstate = cstate - 2.0f; div++; } // pitch if (flag_state & ANIM_FLAG_PITCH) { - Ogre::Vector3 dirv = (cam_pos - cam_dir).normalisedCopy(); - float pitchangle = asin(dirv.dotProduct(Ogre::Vector3::UNIT_Y)); + Ogre::Vector3 dirv = (cam_pos - cam_dir).normalisedCopy(); + float pitchangle = asin(dirv.dotProduct(Ogre::Vector3::UNIT_Y)); // radian to degrees with a max cstate of +/- 1.0 cstate = (Ogre::Math::RadiansToDegrees(pitchangle) / 90.0f); div++; @@ -2923,7 +2763,7 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& div++; } - //flaps + // flaps if (flag_state & ANIM_FLAG_FLAP) { float flaps = flapangles[m_simbuf.simbuf_aero_flap_state]; @@ -2935,21 +2775,21 @@ void RoR::GfxActor::CalcPropAnimation(const int flag_state, float& cstate, int& void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) { - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { - int animnum = 0; - float rx = 0.0f; - float ry = 0.0f; - float rz = 0.0f; + int animnum = 0; + float rx = 0.0f; + float ry = 0.0f; + float rz = 0.0f; while (prop.animFlags[animnum]) { - float cstate = 0.0f; - int div = 0.0f; - int flagstate = prop.animFlags[animnum]; + float cstate = 0.0f; + int div = 0.0f; + int flagstate = prop.animFlags[animnum]; const float lower_limit = prop.constraints[animnum].lower_limit; const float upper_limit = prop.constraints[animnum].upper_limit; - float animOpt3 = prop.animOpt3[animnum]; + float animOpt3 = prop.animOpt3[animnum]; this->CalcPropAnimation(flagstate, cstate, div, dt, lower_limit, upper_limit, animOpt3); @@ -2968,7 +2808,7 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) else if (!prop.animKeyState[animnum]) { // a key was pressed and a toggle was done already, so bypass - //toggle now + // toggle now if (!prop.lastanimKS[animnum]) { prop.lastanimKS[animnum] = 1.0f; @@ -2990,7 +2830,8 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) } else { - // keyevent exists and keylock is enabled but the key isnt pressed right now = get lastanimkeystatus for cstate and reset keypressed bool animkey + // keyevent exists and keylock is enabled but the key isnt pressed right now = get lastanimkeystatus for + // cstate and reset keypressed bool animkey if (prop.animKeyState[animnum] != -1.0f) { cstate += prop.lastanimKS[animnum]; @@ -2999,31 +2840,26 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) } } - //propanimation placed here to avoid interference with existing hydros(cstate) and permanent prop animation - //land vehicle steering - if (prop.animFlags[animnum] & ANIM_FLAG_STEERING) - cstate += m_simbuf.simbuf_hydro_dir_state; - //aileron - if (prop.animFlags[animnum] & ANIM_FLAG_AILERONS) - cstate += m_simbuf.simbuf_hydro_aileron_state; - //elevator - if (prop.animFlags[animnum] & ANIM_FLAG_ELEVATORS) - cstate += m_simbuf.simbuf_hydro_elevator_state; - //rudder - if (prop.animFlags[animnum] & ANIM_FLAG_ARUDDER) - cstate += m_simbuf.simbuf_hydro_aero_rudder_state; - //permanent - if (prop.animFlags[animnum] & ANIM_FLAG_PERMANENT) - cstate += 1.0f; + // propanimation placed here to avoid interference with existing hydros(cstate) and permanent prop animation + // land vehicle steering + if (prop.animFlags[animnum] & ANIM_FLAG_STEERING) cstate += m_simbuf.simbuf_hydro_dir_state; + // aileron + if (prop.animFlags[animnum] & ANIM_FLAG_AILERONS) cstate += m_simbuf.simbuf_hydro_aileron_state; + // elevator + if (prop.animFlags[animnum] & ANIM_FLAG_ELEVATORS) cstate += m_simbuf.simbuf_hydro_elevator_state; + // rudder + if (prop.animFlags[animnum] & ANIM_FLAG_ARUDDER) cstate += m_simbuf.simbuf_hydro_aero_rudder_state; + // permanent + if (prop.animFlags[animnum] & ANIM_FLAG_PERMANENT) cstate += 1.0f; cstate *= prop.animratio[animnum]; // autoanimate noflip_bouncer - if (prop.animOpt5[animnum]) - cstate *= (prop.animOpt5[animnum]); + if (prop.animOpt5[animnum]) cstate *= (prop.animOpt5[animnum]); - //rotate prop - if ((prop.animMode[animnum] & ANIM_MODE_ROTA_X) || (prop.animMode[animnum] & ANIM_MODE_ROTA_Y) || (prop.animMode[animnum] & ANIM_MODE_ROTA_Z)) + // rotate prop + if ((prop.animMode[animnum] & ANIM_MODE_ROTA_X) || (prop.animMode[animnum] & ANIM_MODE_ROTA_Y) || + (prop.animMode[animnum] & ANIM_MODE_ROTA_Z)) { float limiter = 0.0f; // This code was formerly executed within a fixed timestep of 0.5ms and finetuned accordingly. @@ -3049,12 +2885,9 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) } else { - if (prop.animMode[animnum] & ANIM_MODE_ROTA_X) - rx += cstate; - if (prop.animMode[animnum] & ANIM_MODE_ROTA_Y) - ry += cstate; - if (prop.animMode[animnum] & ANIM_MODE_ROTA_Z) - rz += cstate; + if (prop.animMode[animnum] & ANIM_MODE_ROTA_X) rx += cstate; + if (prop.animMode[animnum] & ANIM_MODE_ROTA_Y) ry += cstate; + if (prop.animMode[animnum] & ANIM_MODE_ROTA_Z) rz += cstate; } bool limiterchanged = false; @@ -3064,7 +2897,7 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) { if (prop.animMode[animnum] & ANIM_MODE_NOFLIP) { - limiter = upper_limit; // stop at limit + limiter = upper_limit; // stop at limit prop.animOpt5[animnum] *= -1.0f; // change cstate multiplier if bounce is set } else @@ -3078,7 +2911,7 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) { if (prop.animMode[animnum] & ANIM_MODE_NOFLIP) { - limiter = lower_limit; // stop at limit + limiter = lower_limit; // stop at limit prop.animOpt5[animnum] *= -1.0f; // change cstate multiplier if active } else @@ -3090,41 +2923,36 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) if (limiterchanged) { - if (prop.animMode[animnum] & ANIM_MODE_ROTA_X) - prop.rotaX = limiter; - if (prop.animMode[animnum] & ANIM_MODE_ROTA_Y) - prop.rotaY = limiter; - if (prop.animMode[animnum] & ANIM_MODE_ROTA_Z) - prop.rotaZ = limiter; + if (prop.animMode[animnum] & ANIM_MODE_ROTA_X) prop.rotaX = limiter; + if (prop.animMode[animnum] & ANIM_MODE_ROTA_Y) prop.rotaY = limiter; + if (prop.animMode[animnum] & ANIM_MODE_ROTA_Z) prop.rotaZ = limiter; } } - //offset prop + // offset prop - if ((prop.animMode[animnum] & ANIM_MODE_OFFSET_X) || (prop.animMode[animnum] & ANIM_MODE_OFFSET_Y) || (prop.animMode[animnum] & ANIM_MODE_OFFSET_Z)) + if ((prop.animMode[animnum] & ANIM_MODE_OFFSET_X) || (prop.animMode[animnum] & ANIM_MODE_OFFSET_Y) || + (prop.animMode[animnum] & ANIM_MODE_OFFSET_Z)) { - float offset = 0.0f; + float offset = 0.0f; float autooffset = 0.0f; - if (prop.animMode[animnum] & ANIM_MODE_OFFSET_X) - offset = prop.orgoffsetX; - if (prop.animMode[animnum] & ANIM_MODE_OFFSET_Y) - offset = prop.orgoffsetY; - if (prop.animMode[animnum] & ANIM_MODE_OFFSET_Z) - offset = prop.orgoffsetZ; + if (prop.animMode[animnum] & ANIM_MODE_OFFSET_X) offset = prop.orgoffsetX; + if (prop.animMode[animnum] & ANIM_MODE_OFFSET_Y) offset = prop.orgoffsetY; + if (prop.animMode[animnum] & ANIM_MODE_OFFSET_Z) offset = prop.orgoffsetZ; if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) { // This code was formerly executed within a fixed timestep of 0.5ms and finetuned accordingly. // This is now taken into account by factoring in the respective fraction of the variable timestep. float const dt_frac = dt * 2000.f; - autooffset = offset + cstate * dt_frac; + autooffset = offset + cstate * dt_frac; if (autooffset > upper_limit) { if (prop.animMode[animnum] & ANIM_MODE_NOFLIP) { - autooffset = upper_limit; // stop at limit + autooffset = upper_limit; // stop at limit prop.animOpt5[animnum] *= -1.0f; // change cstate multiplier if active } else @@ -3137,7 +2965,7 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) { if (prop.animMode[animnum] & ANIM_MODE_NOFLIP) { - autooffset = lower_limit; // stop at limit + autooffset = lower_limit; // stop at limit prop.animOpt5[animnum] *= -1.0f; // change cstate multiplier if active } else @@ -3151,30 +2979,27 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) if (prop.animMode[animnum] & ANIM_MODE_OFFSET_X) { prop.offsetx = offset; - if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) - prop.orgoffsetX = autooffset; + if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) prop.orgoffsetX = autooffset; } if (prop.animMode[animnum] & ANIM_MODE_OFFSET_Y) { prop.offsety = offset; - if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) - prop.orgoffsetY = autooffset; + if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) prop.orgoffsetY = autooffset; } if (prop.animMode[animnum] & ANIM_MODE_OFFSET_Z) { prop.offsetz = offset; - if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) - prop.orgoffsetZ = autooffset; + if (prop.animMode[animnum] & ANIM_MODE_AUTOANIMATE) prop.orgoffsetZ = autooffset; } } animnum++; } - //recalc the quaternions with final stacked rotation values ( rx, ry, rz ) + // recalc the quaternions with final stacked rotation values ( rx, ry, rz ) rx += prop.rotaX; ry += prop.rotaY; rz += prop.rotaZ; - prop.rot = Ogre::Quaternion(Ogre::Degree(rz), Ogre::Vector3::UNIT_Z) * + prop.rot = Ogre::Quaternion(Ogre::Degree(rz), Ogre::Vector3::UNIT_Z) * Ogre::Quaternion(Ogre::Degree(ry), Ogre::Vector3::UNIT_Y) * Ogre::Quaternion(Ogre::Degree(rx), Ogre::Vector3::UNIT_X); } @@ -3182,22 +3007,19 @@ void RoR::GfxActor::UpdatePropAnimations(float dt, bool is_player_connected) void RoR::GfxActor::SortFlexbodies() { - std::sort(m_flexbodies.begin(), m_flexbodies.end(), [](FlexBody* a, FlexBody* b) { return a->size() > b->size(); }); + std::sort(m_flexbodies.begin(), m_flexbodies.end(), [](FlexBody *a, FlexBody *b) { return a->size() > b->size(); }); } void RoR::GfxActor::UpdateFlexbodies() { m_flexbody_tasks.clear(); - for (FlexBody* fb: m_flexbodies) + for (FlexBody *fb : m_flexbodies) { const int camera_mode = fb->getCameraMode(); if ((camera_mode == -2) || (camera_mode == m_simbuf.simbuf_cur_cinecam)) { - auto func = std::function([fb]() - { - fb->ComputeFlexbody(); - }); + auto func = std::function([fb]() { fb->ComputeFlexbody(); }); auto task_handle = gEnv->threadPool->RunTask(func); m_flexbody_tasks.push_back(task_handle); } @@ -3210,7 +3032,7 @@ void RoR::GfxActor::UpdateFlexbodies() void RoR::GfxActor::ResetFlexbodies() { - for (FlexBody* fb: m_flexbodies) + for (FlexBody *fb : m_flexbodies) { fb->reset(); } @@ -3218,7 +3040,7 @@ void RoR::GfxActor::ResetFlexbodies() void RoR::GfxActor::SetFlexbodyVisible(bool visible) { - for (FlexBody* fb: m_flexbodies) + for (FlexBody *fb : m_flexbodies) { fb->setVisible(visible); } @@ -3226,11 +3048,11 @@ void RoR::GfxActor::SetFlexbodyVisible(bool visible) void RoR::GfxActor::FinishFlexbodyTasks() { - for (auto& task: m_flexbody_tasks) + for (auto &task : m_flexbody_tasks) { task->join(); } - for (FlexBody* fb: m_flexbodies) + for (FlexBody *fb : m_flexbodies) { fb->UpdateFlexbodyVertexBuffers(); } @@ -3240,43 +3062,40 @@ void RoR::GfxActor::UpdateFlares(float dt_sec, bool is_player) { // == Flare states are determined in simulation, this function only applies them to OGRE objects == - bool enableAll = ((App::gfx_flares_mode.GetActive() == GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY) && !is_player); - NodeData* nodes = this->GetSimNodeBuffer(); + bool enableAll = ((App::gfx_flares_mode.GetActive() == GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY) && !is_player); + NodeData *nodes = this->GetSimNodeBuffer(); int num_flares = static_cast(m_actor->ar_flares.size()); - for (int i=0; iar_flares[i]; - - //TODO: Following code is a quick+dirty port from `Actor::updateFlares()` - tidy it up! ~only_a_ptr, 06/2018 + flare_t &flare = m_actor->ar_flares[i]; - if (flare.fl_type == FlareType::HEADLIGHT) - { - this->SetMaterialFlareOn(i, m_simbuf.simbuf_headlight_on); - } + // TODO: Following code is a quick+dirty port from `Actor::updateFlares()` - tidy it up! ~only_a_ptr, 06/2018 + + if (flare.fl_type == FlareType::HEADLIGHT) { this->SetMaterialFlareOn(i, m_simbuf.simbuf_headlight_on); } else { this->SetMaterialFlareOn(i, flare.isVisible); flare.snode->setVisible(flare.isVisible); - if (flare.light != nullptr) - { - flare.light->setVisible(flare.isVisible && enableAll); - } + if (flare.light != nullptr) { flare.light->setVisible(flare.isVisible && enableAll); } } - Ogre::Vector3 normal = (nodes[flare.nodey].AbsPosition - nodes[flare.noderef].AbsPosition).crossProduct(nodes[flare.nodex].AbsPosition - nodes[flare.noderef].AbsPosition); + Ogre::Vector3 normal = (nodes[flare.nodey].AbsPosition - nodes[flare.noderef].AbsPosition) + .crossProduct(nodes[flare.nodex].AbsPosition - nodes[flare.noderef].AbsPosition); normal.normalise(); - Ogre::Vector3 mposition = nodes[flare.noderef].AbsPosition + flare.offsetx * (nodes[flare.nodex].AbsPosition - nodes[flare.noderef].AbsPosition) + flare.offsety * (nodes[flare.nodey].AbsPosition - nodes[flare.noderef].AbsPosition); + Ogre::Vector3 mposition = nodes[flare.noderef].AbsPosition + + flare.offsetx * (nodes[flare.nodex].AbsPosition - nodes[flare.noderef].AbsPosition) + + flare.offsety * (nodes[flare.nodey].AbsPosition - nodes[flare.noderef].AbsPosition); Ogre::Vector3 vdir = mposition - gEnv->mainCamera->getPosition(); - float vlen = vdir.length(); + float vlen = vdir.length(); // not visible from 500m distance if (vlen > 500.0) { flare.snode->setVisible(false); continue; } - //normalize - vdir = vdir / vlen; + // normalize + vdir = vdir / vlen; float amplitude = normal.dotProduct(vdir); flare.snode->setPosition(mposition - 0.1 * amplitude * normal * flare.offsetz); flare.snode->setDirection(normal); @@ -3311,51 +3130,44 @@ void RoR::GfxActor::SetCastShadows(bool value) { // Cab mesh if (m_cab_scene_node != nullptr) - { - static_cast(m_cab_scene_node->getAttachedObject(0))->setCastShadows(value); - } + { static_cast(m_cab_scene_node->getAttachedObject(0))->setCastShadows(value); } // Props - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { - if (prop.mo != nullptr && prop.mo->getEntity()) - prop.mo->getEntity()->setCastShadows(value); - if (prop.wheelmo != nullptr && prop.wheelmo->getEntity()) - prop.wheelmo->getEntity()->setCastShadows(value); + if (prop.mo != nullptr && prop.mo->getEntity()) prop.mo->getEntity()->setCastShadows(value); + if (prop.wheelmo != nullptr && prop.wheelmo->getEntity()) prop.wheelmo->getEntity()->setCastShadows(value); } // Wheels - for (WheelGfx& wheel: m_wheels) + for (WheelGfx &wheel : m_wheels) { - static_cast(wheel.wx_scenenode->getAttachedObject(0))->setCastShadows(value); + static_cast(wheel.wx_scenenode->getAttachedObject(0))->setCastShadows(value); } // Softbody beams - for (Rod& rod: m_rods) + for (Rod &rod : m_rods) { - static_cast(rod.rod_scenenode->getAttachedObject(0))->setCastShadows(value); + static_cast(rod.rod_scenenode->getAttachedObject(0))->setCastShadows(value); } // Flexbody meshes - for (FlexBody* fb: m_flexbodies) + for (FlexBody *fb : m_flexbodies) { fb->SetFlexbodyCastShadow(value); } } -void RoR::GfxActor::RegisterCabMesh(Ogre::Entity* ent, Ogre::SceneNode* snode, FlexObj* flexobj) +void RoR::GfxActor::RegisterCabMesh(Ogre::Entity *ent, Ogre::SceneNode *snode, FlexObj *flexobj) { - m_cab_mesh = flexobj; - m_cab_entity = ent; + m_cab_mesh = flexobj; + m_cab_entity = ent; m_cab_scene_node = snode; } void RoR::GfxActor::SetAllMeshesVisible(bool visible) { - if (m_cab_entity != nullptr) - { - m_cab_entity->setVisible(visible); - } + if (m_cab_entity != nullptr) { m_cab_entity->setVisible(visible); } this->SetWheelsVisible(visible); this->SetPropsVisible(visible); this->SetFlexbodyVisible(visible); @@ -3365,7 +3177,7 @@ void RoR::GfxActor::UpdateWingMeshes() { for (int i = 0; i < m_actor->ar_num_wings; ++i) { - wing_t& wing = m_actor->ar_wings[i]; + wing_t &wing = m_actor->ar_wings[i]; wing.cnode->setPosition(wing.fa->updateVerticesGfx(this)); wing.fa->uploadVertices(); } diff --git a/source/main/gfx/GfxActor.h b/source/main/gfx/GfxActor.h index 2a951ba230..43c606d7c4 100644 --- a/source/main/gfx/GfxActor.h +++ b/source/main/gfx/GfxActor.h @@ -43,353 +43,402 @@ namespace RoR { -class GfxActor -{ - friend class ::ActorSpawner; // The factory - -public: - - struct FlareMaterial - { - int flare_index; - Ogre::MaterialPtr mat_instance; - Ogre::ColourValue emissive_color; - }; - - enum class VideoCamState - { - VCSTATE_INVALID, - VCSTATE_DISABLED, - VCSTATE_ENABLED_OFFLINE, - VCSTATE_ENABLED_ONLINE, - }; - - enum class VideoCamType - { - VCTYPE_INVALID, - VCTYPE_VIDEOCAM, - VCTYPE_TRACKING_VIDEOCAM, - VCTYPE_MIRROR, - VCTYPE_MIRROR_PROP_LEFT, ///< The classic 'special prop/rear view mirror' - VCTYPE_MIRROR_PROP_RIGHT, ///< The classic 'special prop/rear view mirror' - }; - - enum class DebugViewType - { - DEBUGVIEW_NONE, - DEBUGVIEW_SKELETON, - DEBUGVIEW_NODES, - DEBUGVIEW_BEAMS, - DEBUGVIEW_WHEELS, - DEBUGVIEW_SHOCKS, - DEBUGVIEW_ROTATORS, - DEBUGVIEW_SLIDENODES, - DEBUGVIEW_SUBMESH, - }; - - /// An Ogre::Camera mounted on the actor and rendering into - /// either in-scene texture or external window. - struct VideoCamera + class GfxActor { - VideoCamera(); - - VideoCamType vcam_type; // old 'camRole' - uint16_t vcam_node_center; // old 'nref' - uint16_t vcam_node_dir_y; // old 'ny' - uint16_t vcam_node_dir_z; // old 'nz' - uint16_t vcam_node_alt_pos; // old 'camNode' - uint16_t vcam_node_lookat; // old 'lookat' - only present for type=VCTYPE_TRACK_CAM - Ogre::Quaternion vcam_rotation; // old 'rotation' - Ogre::Vector3 vcam_pos_offset; // old 'offset' - Ogre::MaterialPtr vcam_material; // old 'mat' + 'materialName' - std::string vcam_off_tex_name; // old 'disabledTexture' - used when videocamera is offline. - Ogre::Camera* vcam_ogre_camera; // old 'mVidCam' - Ogre::RenderTexture* vcam_render_target; // old 'rttTex' - Ogre::TexturePtr vcam_render_tex; - Ogre::SceneNode* vcam_debug_node; // old 'debugNode' - Ogre::RenderWindow* vcam_render_window; // old 'rwMirror' - Ogre::SceneNode* vcam_prop_scenenode; // Only for type=MIRROR_PROP_* - }; + friend class ::ActorSpawner; // The factory - /// Gfx attributes/state of a softbody node - struct NodeGfx - { - NodeGfx(uint16_t node_idx); + public: + struct FlareMaterial + { + int flare_index; + Ogre::MaterialPtr mat_instance; + Ogre::ColourValue emissive_color; + }; - float nx_wet_time_sec; //!< 'Wet' means "already out of water, producing dripping particles". Set to -1 when not 'wet'. - uint16_t nx_node_idx; + enum class VideoCamState + { + VCSTATE_INVALID, + VCSTATE_DISABLED, + VCSTATE_ENABLED_OFFLINE, + VCSTATE_ENABLED_ONLINE, + }; - // Bit flags - bool nx_no_particles:1; //!< User-defined attr; disable all particles - bool nx_may_get_wet:1; //!< Attr; enables water drip and vapour - bool nx_is_hot:1; //!< User-defined attr; emits vapour particles when in contact with water. - bool nx_under_water_prev:1; //!< State - bool nx_no_sparks:1; //!< User-defined attr; + enum class VideoCamType + { + VCTYPE_INVALID, + VCTYPE_VIDEOCAM, + VCTYPE_TRACKING_VIDEOCAM, + VCTYPE_MIRROR, + VCTYPE_MIRROR_PROP_LEFT, ///< The classic 'special prop/rear view mirror' + VCTYPE_MIRROR_PROP_RIGHT, ///< The classic 'special prop/rear view mirror' + }; - }; // more to come... ~only_a_ptr, 04/2018 + enum class DebugViewType + { + DEBUGVIEW_NONE, + DEBUGVIEW_SKELETON, + DEBUGVIEW_NODES, + DEBUGVIEW_BEAMS, + DEBUGVIEW_WHEELS, + DEBUGVIEW_SHOCKS, + DEBUGVIEW_ROTATORS, + DEBUGVIEW_SLIDENODES, + DEBUGVIEW_SUBMESH, + }; - /// Copy of node simulation state - struct NodeData - { - Ogre::Vector3 AbsPosition; - bool nd_has_contact:1; - bool nd_is_wet:1; - }; + /// An Ogre::Camera mounted on the actor and rendering into + /// either in-scene texture or external window. + struct VideoCamera + { + VideoCamera(); + + VideoCamType vcam_type; // old 'camRole' + uint16_t vcam_node_center; // old 'nref' + uint16_t vcam_node_dir_y; // old 'ny' + uint16_t vcam_node_dir_z; // old 'nz' + uint16_t vcam_node_alt_pos; // old 'camNode' + uint16_t vcam_node_lookat; // old 'lookat' - only present for type=VCTYPE_TRACK_CAM + Ogre::Quaternion vcam_rotation; // old 'rotation' + Ogre::Vector3 vcam_pos_offset; // old 'offset' + Ogre::MaterialPtr vcam_material; // old 'mat' + 'materialName' + std::string vcam_off_tex_name; // old 'disabledTexture' - used when videocamera is offline. + Ogre::Camera * vcam_ogre_camera; // old 'mVidCam' + Ogre::RenderTexture *vcam_render_target; // old 'rttTex' + Ogre::TexturePtr vcam_render_tex; + Ogre::SceneNode * vcam_debug_node; // old 'debugNode' + Ogre::RenderWindow * vcam_render_window; // old 'rwMirror' + Ogre::SceneNode * vcam_prop_scenenode; // Only for type=MIRROR_PROP_* + }; - /// Visuals of softbody beam (`beam_t` struct); Partially updated along with SimBuffer - struct Rod - { - // We don't keep pointer to the Ogre::Entity - we rely on the SceneNode keeping it attached all the time. - Ogre::SceneNode* rod_scenenode; - uint16_t rod_beam_index; //!< Index of the associated `beam_t` instance; assumes Actor has at most 65536 beams (RoR doesn't have a soft limit now, but until v0.4.8 it was 5000 beams). - uint16_t rod_diameter_mm; //!< Diameter in millimeters - - // Assumption: Actor has at most 65536 nodes (RoR doesn't have a soft limit right now, but until v0.4.8 it was 1000 nodes). - uint16_t rod_node1; //!< Node index - may change during simulation! - uint16_t rod_node2; //!< Node index - may change during simulation! - Actor* rod_target_actor; - bool rod_is_visible; - }; + /// Gfx attributes/state of a softbody node + struct NodeGfx + { + NodeGfx(uint16_t node_idx); - struct WheelGfx - { - WheelGfx(): wx_flex_mesh(nullptr), wx_scenenode(nullptr), wx_is_meshwheel(false) {} + float + nx_wet_time_sec; //!< 'Wet' means "already out of water, producing dripping particles". Set to -1 when not 'wet'. + uint16_t nx_node_idx; - Flexable* wx_flex_mesh; - Ogre::SceneNode* wx_scenenode; - bool wx_is_meshwheel; - }; + // Bit flags + bool nx_no_particles : 1; //!< User-defined attr; disable all particles + bool nx_may_get_wet : 1; //!< Attr; enables water drip and vapour + bool nx_is_hot : 1; //!< User-defined attr; emits vapour particles when in contact with water. + bool nx_under_water_prev : 1; //!< State + bool nx_no_sparks : 1; //!< User-defined attr; - struct AirbrakeGfx - { - Ogre::MeshPtr abx_mesh; - Ogre::SceneNode* abx_scenenode; - Ogre::Entity* abx_entity; - Ogre::Vector3 abx_offset; - uint16_t abx_ref_node; - uint16_t abx_x_node; - uint16_t abx_y_node; - }; + }; // more to come... ~only_a_ptr, 04/2018 - struct SimBuffer /// Buffered simulation data - { - SimBuffer(); + /// Copy of node simulation state + struct NodeData + { + Ogre::Vector3 AbsPosition; + bool nd_has_contact : 1; + bool nd_is_wet : 1; + }; - struct ScrewPropSB + /// Visuals of softbody beam (`beam_t` struct); Partially updated along with SimBuffer + struct Rod { - float simbuf_sp_rudder; - float simbuf_sp_throttle; + // We don't keep pointer to the Ogre::Entity - we rely on the SceneNode keeping it attached all the time. + Ogre::SceneNode *rod_scenenode; + uint16_t rod_beam_index; //!< Index of the associated `beam_t` instance; assumes Actor has at most 65536 beams (RoR + //!< doesn't have a soft limit now, but until v0.4.8 it was 5000 beams). + uint16_t rod_diameter_mm; //!< Diameter in millimeters + + // Assumption: Actor has at most 65536 nodes (RoR doesn't have a soft limit right now, but until v0.4.8 it was 1000 + // nodes). + uint16_t rod_node1; //!< Node index - may change during simulation! + uint16_t rod_node2; //!< Node index - may change during simulation! + Actor * rod_target_actor; + bool rod_is_visible; }; - struct CommandKeySB + struct WheelGfx { - float simbuf_cmd_value; + WheelGfx() : wx_flex_mesh(nullptr), wx_scenenode(nullptr), wx_is_meshwheel(false) + { + } + + Flexable * wx_flex_mesh; + Ogre::SceneNode *wx_scenenode; + bool wx_is_meshwheel; }; - struct AeroEngineSB + struct AirbrakeGfx { - float simbuf_ae_rpm; - float simbuf_ae_rpmpc; - float simbuf_ae_throttle; - float simbuf_tp_aetorque; //!< Turboprop torque, used by animation "aetorque" - float simbuf_tp_aepitch; //!< Turboprop pitch, used by animation "aepitch" - float simbuf_tj_ab_thrust; //! Turbojet afterburner - float simbuf_tj_exhaust_velo; //! Turbojet - bool simbuf_ae_turboprop:1; //!< This is a TurboProp/PistonProp - bool simbuf_ae_ignition:1; - bool simbuf_ae_failed:1; - bool simbuf_tj_afterburn:1; //! Turbojet afterburner + Ogre::MeshPtr abx_mesh; + Ogre::SceneNode *abx_scenenode; + Ogre::Entity * abx_entity; + Ogre::Vector3 abx_offset; + uint16_t abx_ref_node; + uint16_t abx_x_node; + uint16_t abx_y_node; }; - struct AirbrakeSB + struct SimBuffer /// Buffered simulation data { - float simbuf_ab_ratio; + SimBuffer(); + + struct ScrewPropSB + { + float simbuf_sp_rudder; + float simbuf_sp_throttle; + }; + + struct CommandKeySB + { + float simbuf_cmd_value; + }; + + struct AeroEngineSB + { + float simbuf_ae_rpm; + float simbuf_ae_rpmpc; + float simbuf_ae_throttle; + float simbuf_tp_aetorque; //!< Turboprop torque, used by animation "aetorque" + float simbuf_tp_aepitch; //!< Turboprop pitch, used by animation "aepitch" + float simbuf_tj_ab_thrust; //! Turbojet afterburner + float simbuf_tj_exhaust_velo; //! Turbojet + bool simbuf_ae_turboprop : 1; //!< This is a TurboProp/PistonProp + bool simbuf_ae_ignition : 1; + bool simbuf_ae_failed : 1; + bool simbuf_tj_afterburn : 1; //! Turbojet afterburner + }; + + struct AirbrakeSB + { + float simbuf_ab_ratio; + }; + + std::unique_ptr simbuf_nodes; + Ogre::Vector3 simbuf_pos; + Ogre::Vector3 simbuf_node0_velo; + bool simbuf_live_local; + bool simbuf_physics_paused; + float simbuf_rotation; + float simbuf_tyre_pressure; + Ogre::AxisAlignedBox simbuf_aabb; + std::string simbuf_net_username; + bool simbuf_is_remote; + int simbuf_gear; + int simbuf_autoshift; + float simbuf_wheel_speed; + float simbuf_engine_rpm; + float simbuf_engine_crankfactor; + float simbuf_engine_turbo_psi; + float simbuf_engine_accel; + bool simbuf_beaconlight_active; + float simbuf_hydro_dir_state; // State of steering actuator ('hydro'), for steeringwheel display + float simbuf_hydro_aileron_state; + float simbuf_hydro_elevator_state; + float simbuf_hydro_aero_rudder_state; + int simbuf_cur_cinecam; + std::vector simbuf_screwprops; + std::vector simbuf_commandkey; + std::vector simbuf_aeroengines; + std::vector simbuf_airbrakes; + DiffType simbuf_diff_type; + bool simbuf_parking_brake; + float simbuf_brake; + float simbuf_clutch; + int simbuf_aero_flap_state; + int simbuf_airbrake_state; + float simbuf_wing4_aoa; + bool simbuf_headlight_on; + Ogre::Vector3 simbuf_direction; //!< Output of `Actor::getDirection()` + // Autopilot + int simbuf_ap_heading_mode; + int simbuf_ap_heading_value; + int simbuf_ap_alt_mode; + int simbuf_ap_alt_value; + bool simbuf_ap_ias_mode; + int simbuf_ap_ias_value; + bool simbuf_ap_gpws_mode; + bool simbuf_ap_ils_available; + float simbuf_ap_ils_vdev; + float simbuf_ap_ils_hdev; + int simbuf_ap_vs_value; }; - std::unique_ptr simbuf_nodes; - Ogre::Vector3 simbuf_pos; - Ogre::Vector3 simbuf_node0_velo; - bool simbuf_live_local; - bool simbuf_physics_paused; - float simbuf_rotation; - float simbuf_tyre_pressure; - Ogre::AxisAlignedBox simbuf_aabb; - std::string simbuf_net_username; - bool simbuf_is_remote; - int simbuf_gear; - int simbuf_autoshift; - float simbuf_wheel_speed; - float simbuf_engine_rpm; - float simbuf_engine_crankfactor; - float simbuf_engine_turbo_psi; - float simbuf_engine_accel; - bool simbuf_beaconlight_active; - float simbuf_hydro_dir_state; // State of steering actuator ('hydro'), for steeringwheel display - float simbuf_hydro_aileron_state; - float simbuf_hydro_elevator_state; - float simbuf_hydro_aero_rudder_state; - int simbuf_cur_cinecam; - std::vector simbuf_screwprops; - std::vector simbuf_commandkey; - std::vector simbuf_aeroengines; - std::vector simbuf_airbrakes; - DiffType simbuf_diff_type; - bool simbuf_parking_brake; - float simbuf_brake; - float simbuf_clutch; - int simbuf_aero_flap_state; - int simbuf_airbrake_state; - float simbuf_wing4_aoa; - bool simbuf_headlight_on; - Ogre::Vector3 simbuf_direction; //!< Output of `Actor::getDirection()` - // Autopilot - int simbuf_ap_heading_mode; - int simbuf_ap_heading_value; - int simbuf_ap_alt_mode; - int simbuf_ap_alt_value; - bool simbuf_ap_ias_mode; - int simbuf_ap_ias_value; - bool simbuf_ap_gpws_mode; - bool simbuf_ap_ils_available; - float simbuf_ap_ils_vdev; - float simbuf_ap_ils_hdev; - int simbuf_ap_vs_value; - }; + struct Attributes //!< Actor visual attributes + { + float xa_speedo_highest_kph; + bool xa_speedo_use_engine_max_rpm; + int xa_num_gears; //!< Gearbox + float xa_engine_max_rpm; + int xa_camera0_pos_node; + int xa_camera0_roll_node; + bool xa_has_autopilot; + }; - struct Attributes //!< Actor visual attributes - { - float xa_speedo_highest_kph; - bool xa_speedo_use_engine_max_rpm; - int xa_num_gears; //!< Gearbox - float xa_engine_max_rpm; - int xa_camera0_pos_node; - int xa_camera0_roll_node; - bool xa_has_autopilot; + GfxActor(Actor *actor, ActorSpawner *spawner, std::string ogre_resource_group, std::vector &gfx_nodes, + std::vector &props, int driverseat_prop_idx, RoR::Renderdash *renderdash); + + ~GfxActor(); + + void AddMaterialFlare(int flare_index, Ogre::MaterialPtr mat); + void SetMaterialFlareOn(int flare_index, bool state_on); + void RegisterCabMaterial(Ogre::MaterialPtr mat, Ogre::MaterialPtr mat_trans); + void RegisterCabMesh(Ogre::Entity *ent, Ogre::SceneNode *snode, FlexObj *flexobj); + void SetCabLightsActive(bool state_on); + void SetVideoCamState(VideoCamState state); + void UpdateVideoCameras(float dt_sec); + void UpdateParticles(float dt_sec); + void AddRod(int beam_index, int node1_index, int node2_index, const char *material_name, bool visible, + float diameter_meters); + void UpdateRods(); + void SetRodsVisible(bool visible); + void ScaleActor(Ogre::Vector3 relpos, float ratio); + bool IsActorLive() const; //!< Should the visuals be updated for this actor? + bool IsActorInitialized() const + { + return m_initialized; + } //!< Temporary TODO: Remove once the spawn routine is fixed + void InitializeActor() + { + m_initialized = true; + } //!< Temporary TODO: Remove once the spawn routine is fixed + void UpdateSimDataBuffer(); //!< Copies sim. data from `Actor` to `GfxActor` for later update + void SetWheelVisuals(uint16_t index, WheelGfx wheel_gfx); + void CalculateDriverPos(Ogre::Vector3 &out_pos, Ogre::Quaternion &out_rot); + void UpdateWheelVisuals(); + void FinishWheelUpdates(); + void UpdateFlexbodies(); + void FinishFlexbodyTasks(); + void SetFlexbodyVisible(bool visible); + void SetWheelsVisible(bool value); + void SetAllMeshesVisible(bool value); + void SetCastShadows(bool value); + void UpdateDebugView(); + void ToggleDebugView(); + void CycleDebugViews(); + void UpdateCabMesh(); + void UpdateWingMeshes(); + int GetActorId() const; + int GetActorState() const; + int GetNumFlexbodies() const + { + return static_cast(m_flexbodies.size()); + } + void ResetFlexbodies(); + void SetFlexbodiesVisible(bool visible); + int GetActorDriveable() const; + void RegisterAirbrakes(); + void UpdateAirbrakes(); + void UpdateCParticles(); + void UpdateAeroEngines(); + void UpdateNetLabels(float dt); + void SetDebugView(DebugViewType dv); + void SortFlexbodies(); + void AddFlexbody(FlexBody *fb) + { + m_flexbodies.push_back(fb); + } + Attributes &GetAttributes() + { + return m_attr; + } + inline Ogre::MaterialPtr &GetCabTransMaterial() + { + return m_cab_mat_visual_trans; + } + inline VideoCamState GetVideoCamState() const + { + return m_vidcam_state; + } + inline DebugViewType GetDebugView() const + { + return m_debug_view; + } + SimBuffer &GetSimDataBuffer() + { + return m_simbuf; + } + NodeData *GetSimNodeBuffer() + { + return m_simbuf.simbuf_nodes.get(); + } + void SetSurveyMapEntity(SurveyMapEntity *e) + { + m_survey_map_entity = e; + } + SurveyMapEntity *GetSurveyMapEntity() + { + return m_survey_map_entity; + } + std::set GetLinkedGfxActors() + { + return m_linked_gfx_actors; + } + Ogre::String GetResourceGroup() + { + return m_custom_resource_group; + } + bool HasDriverSeatProp() const + { + return m_driverseat_prop_index != -1; + } + void UpdateBeaconFlare(prop_t &prop, float dt, bool is_player_actor); + void UpdateProps(float dt, bool is_player_actor); + void UpdatePropAnimations(float dt, bool is_player_connected); + void SetPropsVisible(bool visible); + void SetRenderdashActive(bool active); + void SetBeaconsEnabled(bool beacon_light_is_active); + void CalcPropAnimation(const int flag_state, float &cstate, int &div, float timer, const float lower_limit, + const float upper_limit, const float option3); + void UpdateFlares(float dt_sec, bool is_player); + + private: + static Ogre::Quaternion SpecialGetRotationTo(const Ogre::Vector3 &src, const Ogre::Vector3 &dest); + + Actor *m_actor; + + std::string m_custom_resource_group; + std::vector m_flare_materials; + VideoCamState m_vidcam_state; + std::vector m_videocameras; + DebugViewType m_debug_view; + DebugViewType m_last_debug_view; + std::vector m_gfx_nodes; + std::vector m_gfx_airbrakes; + std::vector m_props; + std::vector m_flexbodies; + int m_driverseat_prop_index; + Attributes m_attr; + DustPool * m_particles_drip; + DustPool * m_particles_misc; // This is "dust" in RoR::GfxScene; handles dust, vapour and tyre smoke + DustPool * m_particles_splash; + DustPool * m_particles_ripple; + DustPool * m_particles_sparks; + DustPool * m_particles_clump; + std::vector m_rods; + std::vector m_wheels; + Ogre::SceneNode * m_rods_parent_scenenode; + RoR::Renderdash * m_renderdash; + std::vector> m_flexwheel_tasks; + std::vector> m_flexbody_tasks; + bool m_beaconlight_active; + float m_prop_anim_crankfactor_prev; + float m_prop_anim_shift_timer; + int m_prop_anim_prev_gear; + std::set m_linked_gfx_actors; + + bool m_initialized; + + SimBuffer m_simbuf; + + SurveyMapEntity *m_survey_map_entity; + + // Old cab mesh + FlexObj * m_cab_mesh; + Ogre::SceneNode *m_cab_scene_node; + Ogre::Entity * m_cab_entity; + + // Cab materials and their features + Ogre::MaterialPtr m_cab_mat_visual; ///< Updated in-place from templates + Ogre::MaterialPtr m_cab_mat_visual_trans; + Ogre::MaterialPtr m_cab_mat_template_plain; + Ogre::MaterialPtr m_cab_mat_template_emissive; }; - GfxActor(Actor* actor, ActorSpawner* spawner, std::string ogre_resource_group, - std::vector& gfx_nodes, std::vector& props, int driverseat_prop_idx, RoR::Renderdash* renderdash); - - ~GfxActor(); - - void AddMaterialFlare (int flare_index, Ogre::MaterialPtr mat); - void SetMaterialFlareOn (int flare_index, bool state_on); - void RegisterCabMaterial(Ogre::MaterialPtr mat, Ogre::MaterialPtr mat_trans); - void RegisterCabMesh (Ogre::Entity* ent, Ogre::SceneNode* snode, FlexObj* flexobj); - void SetCabLightsActive (bool state_on); - void SetVideoCamState (VideoCamState state); - void UpdateVideoCameras (float dt_sec); - void UpdateParticles (float dt_sec); - void AddRod (int beam_index, int node1_index, int node2_index, const char* material_name, bool visible, float diameter_meters); - void UpdateRods (); - void SetRodsVisible (bool visible); - void ScaleActor (Ogre::Vector3 relpos, float ratio); - bool IsActorLive () const; //!< Should the visuals be updated for this actor? - bool IsActorInitialized () const { return m_initialized; } //!< Temporary TODO: Remove once the spawn routine is fixed - void InitializeActor () { m_initialized = true; } //!< Temporary TODO: Remove once the spawn routine is fixed - void UpdateSimDataBuffer(); //!< Copies sim. data from `Actor` to `GfxActor` for later update - void SetWheelVisuals (uint16_t index, WheelGfx wheel_gfx); - void CalculateDriverPos (Ogre::Vector3& out_pos, Ogre::Quaternion& out_rot); - void UpdateWheelVisuals (); - void FinishWheelUpdates (); - void UpdateFlexbodies (); - void FinishFlexbodyTasks(); - void SetFlexbodyVisible (bool visible); - void SetWheelsVisible (bool value); - void SetAllMeshesVisible(bool value); - void SetCastShadows (bool value); - void UpdateDebugView (); - void ToggleDebugView (); - void CycleDebugViews (); - void UpdateCabMesh (); - void UpdateWingMeshes (); - int GetActorId () const; - int GetActorState () const; - int GetNumFlexbodies () const { return static_cast(m_flexbodies.size()); } - void ResetFlexbodies (); - void SetFlexbodiesVisible(bool visible); - int GetActorDriveable () const; - void RegisterAirbrakes (); - void UpdateAirbrakes (); - void UpdateCParticles (); - void UpdateAeroEngines (); - void UpdateNetLabels (float dt); - void SetDebugView (DebugViewType dv); - void SortFlexbodies (); - void AddFlexbody (FlexBody* fb) { m_flexbodies.push_back(fb); } - Attributes& GetAttributes () { return m_attr; } - inline Ogre::MaterialPtr& GetCabTransMaterial() { return m_cab_mat_visual_trans; } - inline VideoCamState GetVideoCamState () const { return m_vidcam_state; } - inline DebugViewType GetDebugView () const { return m_debug_view; } - SimBuffer & GetSimDataBuffer () { return m_simbuf; } - NodeData* GetSimNodeBuffer () { return m_simbuf.simbuf_nodes.get(); } - void SetSurveyMapEntity (SurveyMapEntity* e) { m_survey_map_entity = e; } - SurveyMapEntity* GetSurveyMapEntity () { return m_survey_map_entity; } - std::set GetLinkedGfxActors () { return m_linked_gfx_actors; } - Ogre::String GetResourceGroup () { return m_custom_resource_group; } - bool HasDriverSeatProp () const { return m_driverseat_prop_index != -1; } - void UpdateBeaconFlare (prop_t & prop, float dt, bool is_player_actor); - void UpdateProps (float dt, bool is_player_actor); - void UpdatePropAnimations(float dt, bool is_player_connected); - void SetPropsVisible (bool visible); - void SetRenderdashActive (bool active); - void SetBeaconsEnabled (bool beacon_light_is_active); - void CalcPropAnimation (const int flag_state, float& cstate, int& div, float timer, - const float lower_limit, const float upper_limit, const float option3); - void UpdateFlares (float dt_sec, bool is_player); - -private: - - static Ogre::Quaternion SpecialGetRotationTo(const Ogre::Vector3& src, const Ogre::Vector3& dest); - - Actor* m_actor; - - std::string m_custom_resource_group; - std::vector m_flare_materials; - VideoCamState m_vidcam_state; - std::vector m_videocameras; - DebugViewType m_debug_view; - DebugViewType m_last_debug_view; - std::vector m_gfx_nodes; - std::vector m_gfx_airbrakes; - std::vector m_props; - std::vector m_flexbodies; - int m_driverseat_prop_index; - Attributes m_attr; - DustPool* m_particles_drip; - DustPool* m_particles_misc; // This is "dust" in RoR::GfxScene; handles dust, vapour and tyre smoke - DustPool* m_particles_splash; - DustPool* m_particles_ripple; - DustPool* m_particles_sparks; - DustPool* m_particles_clump; - std::vector m_rods; - std::vector m_wheels; - Ogre::SceneNode* m_rods_parent_scenenode; - RoR::Renderdash* m_renderdash; - std::vector> m_flexwheel_tasks; - std::vector> m_flexbody_tasks; - bool m_beaconlight_active; - float m_prop_anim_crankfactor_prev; - float m_prop_anim_shift_timer; - int m_prop_anim_prev_gear; - std::set m_linked_gfx_actors; - - bool m_initialized; - - SimBuffer m_simbuf; - - SurveyMapEntity* m_survey_map_entity; - - // Old cab mesh - FlexObj* m_cab_mesh; - Ogre::SceneNode* m_cab_scene_node; - Ogre::Entity* m_cab_entity; - - // Cab materials and their features - Ogre::MaterialPtr m_cab_mat_visual; ///< Updated in-place from templates - Ogre::MaterialPtr m_cab_mat_visual_trans; - Ogre::MaterialPtr m_cab_mat_template_plain; - Ogre::MaterialPtr m_cab_mat_template_emissive; -}; - } // Namespace RoR diff --git a/source/main/gfx/GfxScene.cpp b/source/main/gfx/GfxScene.cpp index 6c4a9b2bd2..b07f775982 100644 --- a/source/main/gfx/GfxScene.cpp +++ b/source/main/gfx/GfxScene.cpp @@ -37,8 +37,7 @@ using namespace Ogre; -RoR::GfxScene::GfxScene() - : m_ogre_scene(nullptr) +RoR::GfxScene::GfxScene() : m_ogre_scene(nullptr) { m_survey_map = std::unique_ptr(new SurveyMapManager()); } @@ -53,12 +52,12 @@ RoR::GfxScene::~GfxScene() m_dustpools.clear(); } -void RoR::GfxScene::InitScene(Ogre::SceneManager* sm) +void RoR::GfxScene::InitScene(Ogre::SceneManager *sm) { - m_dustpools["dust"] = new DustPool(sm, "tracks/Dust", 20); - m_dustpools["clump"] = new DustPool(sm, "tracks/Clump", 20); + m_dustpools["dust"] = new DustPool(sm, "tracks/Dust", 20); + m_dustpools["clump"] = new DustPool(sm, "tracks/Clump", 20); m_dustpools["sparks"] = new DustPool(sm, "tracks/Sparks", 10); - m_dustpools["drip"] = new DustPool(sm, "tracks/Drip", 50); + m_dustpools["drip"] = new DustPool(sm, "tracks/Drip", 50); m_dustpools["splash"] = new DustPool(sm, "tracks/Splash", 20); m_dustpools["ripple"] = new DustPool(sm, "tracks/Ripple", 20); @@ -71,30 +70,28 @@ void RoR::GfxScene::InitScene(Ogre::SceneManager* sm) void RoR::GfxScene::UpdateScene(float dt_sec) { // Actors - start threaded tasks - for (GfxActor* gfx_actor: m_live_gfx_actors) + for (GfxActor *gfx_actor : m_live_gfx_actors) { - gfx_actor->UpdateFlexbodies(); // Push flexbody tasks to threadpool + gfx_actor->UpdateFlexbodies(); // Push flexbody tasks to threadpool gfx_actor->UpdateWheelVisuals(); // Push flexwheel tasks to threadpool } // Var - GfxActor* player_gfx_actor = nullptr; - std::set player_connected_gfx_actors; + GfxActor * player_gfx_actor = nullptr; + std::set player_connected_gfx_actors; if (m_simbuf.simbuf_player_actor != nullptr) { - player_gfx_actor = m_simbuf.simbuf_player_actor->GetGfxActor(); + player_gfx_actor = m_simbuf.simbuf_player_actor->GetGfxActor(); player_connected_gfx_actors = player_gfx_actor->GetLinkedGfxActors(); } // Particles if (RoR::App::gfx_particles_mode.GetActive() == 1) { - for (GfxActor* gfx_actor: m_all_gfx_actors) + for (GfxActor *gfx_actor : m_all_gfx_actors) { if (!m_simbuf.simbuf_sim_paused && !gfx_actor->GetSimDataBuffer().simbuf_physics_paused) - { - gfx_actor->UpdateParticles(m_simbuf.simbuf_sim_speed * dt_sec); - } + { gfx_actor->UpdateParticles(m_simbuf.simbuf_sim_speed * dt_sec); } } for (auto itor : m_dustpools) { @@ -103,7 +100,8 @@ void RoR::GfxScene::UpdateScene(float dt_sec) } // Realtime reflections on player vehicle - // IMPORTANT: Toggles visibility of all meshes -> must be done before any other visibility control is evaluated (i.e. aero propellers) + // IMPORTANT: Toggles visibility of all meshes -> must be done before any other visibility control is evaluated (i.e. aero + // propellers) if (player_gfx_actor != nullptr) { // Safe to be called here, only modifies OGRE objects, doesn't read any physics state. @@ -114,17 +112,17 @@ void RoR::GfxScene::UpdateScene(float dt_sec) App::GetSimTerrain()->getObjectManager()->UpdateTerrainObjects(dt_sec); // Terrain - lightmap; TODO: ported as-is from TerrainManager::update(), is it needed? ~ only_a_ptr, 05/2018 - App::GetSimTerrain()->getGeometryManager()->UpdateMainLightPosition(); // TODO: Is this necessary? I'm leaving it here just in case ~ only_a_ptr, 04/2017 + App::GetSimTerrain() + ->getGeometryManager() + ->UpdateMainLightPosition(); // TODO: Is this necessary? I'm leaving it here just in case ~ only_a_ptr, 04/2017 // Terrain - water - IWater* water = App::GetSimTerrain()->getWater(); + IWater *water = App::GetSimTerrain()->getWater(); if (water) { water->WaterSetCamera(gEnv->mainCamera); if (player_gfx_actor != nullptr) - { - water->SetReflectionPlaneHeight(water->CalcWavesHeight(player_gfx_actor->GetSimDataBuffer().simbuf_pos)); - } + { water->SetReflectionPlaneHeight(water->CalcWavesHeight(player_gfx_actor->GetSimDataBuffer().simbuf_pos)); } else { water->SetReflectionPlaneHeight(water->GetStaticWaterHeight()); @@ -134,36 +132,33 @@ void RoR::GfxScene::UpdateScene(float dt_sec) // Terrain - sky #ifdef USE_CAELUM - SkyManager* sky = App::GetSimTerrain()->getSkyManager(); - if (sky != nullptr) - { - sky->DetectSkyUpdate(); - } + SkyManager *sky = App::GetSimTerrain()->getSkyManager(); + if (sky != nullptr) { sky->DetectSkyUpdate(); } #endif - SkyXManager* skyx_man = App::GetSimTerrain()->getSkyXManager(); + SkyXManager *skyx_man = App::GetSimTerrain()->getSkyXManager(); if (skyx_man != nullptr) { - skyx_man->update(dt_sec); // Light update + skyx_man->update(dt_sec); // Light update } // GUI - Direction arrow if (App::GetOverlayWrapper() && App::GetOverlayWrapper()->IsDirectionArrowVisible()) { - App::GetOverlayWrapper()->UpdateDirectionArrowHud( - player_gfx_actor, m_simbuf.simbuf_dir_arrow_target, m_simbuf.simbuf_character_pos); + App::GetOverlayWrapper()->UpdateDirectionArrowHud(player_gfx_actor, m_simbuf.simbuf_dir_arrow_target, + m_simbuf.simbuf_character_pos); } // GUI - Survey map if (m_survey_map != nullptr) { m_survey_map->Update(dt_sec, m_simbuf.simbuf_player_actor); - for (GfxActor* gfx_actor: m_all_gfx_actors) + for (GfxActor *gfx_actor : m_all_gfx_actors) { - auto& simbuf = gfx_actor->GetSimDataBuffer(); + auto & simbuf = gfx_actor->GetSimDataBuffer(); String caption = (App::mp_state.GetActive() == MpState::CONNECTED) ? simbuf.simbuf_net_username : ""; - m_survey_map->UpdateMapEntity(gfx_actor->GetSurveyMapEntity(), caption, - simbuf.simbuf_pos, simbuf.simbuf_rotation, gfx_actor->GetActorState(), true); + m_survey_map->UpdateMapEntity(gfx_actor->GetSurveyMapEntity(), caption, simbuf.simbuf_pos, simbuf.simbuf_rotation, + gfx_actor->GetActorState(), true); } } @@ -171,39 +166,32 @@ void RoR::GfxScene::UpdateScene(float dt_sec) if (m_simbuf.simbuf_race_in_progress != m_simbuf.simbuf_race_in_progress_prev) { if (m_simbuf.simbuf_race_in_progress) // Started - { - RoR::App::GetOverlayWrapper()->ShowRacingOverlay(); - } + { RoR::App::GetOverlayWrapper()->ShowRacingOverlay(); } else // Ended { RoR::App::GetOverlayWrapper()->HideRacingOverlay(); } } - if (m_simbuf.simbuf_race_in_progress) - { - RoR::App::GetOverlayWrapper()->UpdateRacingGui(this); - } + if (m_simbuf.simbuf_race_in_progress) { RoR::App::GetOverlayWrapper()->UpdateRacingGui(this); } // GUI - vehicle pressure if (m_simbuf.simbuf_tyrepressurize_active) - { - RoR::App::GetOverlayWrapper()->UpdatePressureTexture(m_simbuf.simbuf_player_actor->GetGfxActor()); - } + { RoR::App::GetOverlayWrapper()->UpdatePressureTexture(m_simbuf.simbuf_player_actor->GetGfxActor()); } // HUD - network labels (always update) - for (GfxActor* gfx_actor: m_all_gfx_actors) + for (GfxActor *gfx_actor : m_all_gfx_actors) { gfx_actor->UpdateNetLabels(m_simbuf.simbuf_sim_speed * dt_sec); } // Player avatars - for (GfxCharacter* a: m_all_gfx_characters) + for (GfxCharacter *a : m_all_gfx_characters) { a->UpdateCharacterInScene(); } // Actors - update misc visuals - for (GfxActor* gfx_actor: m_live_gfx_actors) + for (GfxActor *gfx_actor : m_live_gfx_actors) { bool is_player_connected = (player_connected_gfx_actors.find(gfx_actor) != player_connected_gfx_actors.end()); gfx_actor->UpdateRods(); @@ -222,9 +210,7 @@ void RoR::GfxScene::UpdateScene(float dt_sec) // The old-style render-to-texture dashboard (based on OGRE overlays) if (m_simbuf.simbuf_player_actor->ar_driveable == TRUCK && m_simbuf.simbuf_player_actor->ar_engine != nullptr) - { - RoR::App::GetOverlayWrapper()->UpdateLandVehicleHUD(player_gfx_actor); - } + { RoR::App::GetOverlayWrapper()->UpdateLandVehicleHUD(player_gfx_actor); } else if (m_simbuf.simbuf_player_actor->ar_driveable == AIRPLANE) { RoR::App::GetOverlayWrapper()->UpdateAerialHUD(player_gfx_actor); @@ -234,7 +220,7 @@ void RoR::GfxScene::UpdateScene(float dt_sec) App::GetSimController()->GetSceneMouse().UpdateVisuals(); // Actors - finalize threaded tasks - for (GfxActor* gfx_actor: m_live_gfx_actors) + for (GfxActor *gfx_actor : m_live_gfx_actors) { gfx_actor->FinishWheelUpdates(); gfx_actor->FinishFlexbodyTasks(); @@ -249,20 +235,17 @@ void RoR::GfxScene::SetParticlesVisible(bool visible) } } -DustPool* RoR::GfxScene::GetDustPool(const char* name) +DustPool *RoR::GfxScene::GetDustPool(const char *name) { auto found = m_dustpools.find(name); - if (found != m_dustpools.end()) - { - return found->second; - } + if (found != m_dustpools.end()) { return found->second; } else { return nullptr; } } -void RoR::GfxScene::RegisterGfxActor(RoR::GfxActor* gfx_actor) +void RoR::GfxScene::RegisterGfxActor(RoR::GfxActor *gfx_actor) { m_all_gfx_actors.push_back(gfx_actor); @@ -275,20 +258,20 @@ void RoR::GfxScene::RegisterGfxActor(RoR::GfxActor* gfx_actor) void RoR::GfxScene::BufferSimulationData() { - m_simbuf.simbuf_player_actor = App::GetSimController()->GetPlayerActor(); - m_simbuf.simbuf_character_pos = gEnv->player->getPosition(); - m_simbuf.simbuf_dir_arrow_target = App::GetSimController()->GetDirArrowTarget(); + m_simbuf.simbuf_player_actor = App::GetSimController()->GetPlayerActor(); + m_simbuf.simbuf_character_pos = gEnv->player->getPosition(); + m_simbuf.simbuf_dir_arrow_target = App::GetSimController()->GetDirArrowTarget(); m_simbuf.simbuf_tyrepressurize_active = App::GetSimController()->IsPressurizingTyres(); - m_simbuf.simbuf_sim_paused = App::GetSimController()->GetPhysicsPaused(); - m_simbuf.simbuf_sim_speed = App::GetSimController()->GetBeamFactory()->GetSimulationSpeed(); - m_simbuf.simbuf_race_time = App::GetSimController()->GetRaceTime(); - m_simbuf.simbuf_race_best_time = App::GetSimController()->GetRaceBestTime(); - m_simbuf.simbuf_race_time_diff = App::GetSimController()->GetRaceTimeDiff(); + m_simbuf.simbuf_sim_paused = App::GetSimController()->GetPhysicsPaused(); + m_simbuf.simbuf_sim_speed = App::GetSimController()->GetBeamFactory()->GetSimulationSpeed(); + m_simbuf.simbuf_race_time = App::GetSimController()->GetRaceTime(); + m_simbuf.simbuf_race_best_time = App::GetSimController()->GetRaceBestTime(); + m_simbuf.simbuf_race_time_diff = App::GetSimController()->GetRaceTimeDiff(); m_simbuf.simbuf_race_in_progress_prev = m_simbuf.simbuf_race_in_progress; - m_simbuf.simbuf_race_in_progress = App::GetSimController()->IsRaceInProgress(); + m_simbuf.simbuf_race_in_progress = App::GetSimController()->IsRaceInProgress(); m_live_gfx_actors.clear(); - for (GfxActor* a: m_all_gfx_actors) + for (GfxActor *a : m_all_gfx_actors) { if (a->IsActorLive() || !a->IsActorInitialized()) { @@ -298,43 +281,34 @@ void RoR::GfxScene::BufferSimulationData() } } - for (GfxCharacter* a: m_all_gfx_characters) + for (GfxCharacter *a : m_all_gfx_characters) { a->BufferSimulationData(); } } -void RoR::GfxScene::RemoveGfxActor(RoR::GfxActor* remove_me) +void RoR::GfxScene::RemoveGfxActor(RoR::GfxActor *remove_me) { auto itor = std::remove(m_all_gfx_actors.begin(), m_all_gfx_actors.end(), remove_me); m_all_gfx_actors.erase(itor, m_all_gfx_actors.end()); - if (m_survey_map != nullptr) - { - m_survey_map->deleteMapEntity(remove_me->GetSurveyMapEntity()); - } + if (m_survey_map != nullptr) { m_survey_map->deleteMapEntity(remove_me->GetSurveyMapEntity()); } } -void RoR::GfxScene::RegisterGfxCharacter(RoR::GfxCharacter* gfx_character) +void RoR::GfxScene::RegisterGfxCharacter(RoR::GfxCharacter *gfx_character) { m_all_gfx_characters.push_back(gfx_character); } -void RoR::GfxScene::RemoveGfxCharacter(RoR::GfxCharacter* remove_me) +void RoR::GfxScene::RemoveGfxCharacter(RoR::GfxCharacter *remove_me) { auto itor = std::remove(m_all_gfx_characters.begin(), m_all_gfx_characters.end(), remove_me); m_all_gfx_characters.erase(itor, m_all_gfx_characters.end()); } -RoR::GfxScene::SimBuffer::SimBuffer(): - simbuf_player_actor(nullptr), - simbuf_character_pos(Ogre::Vector3::ZERO), - simbuf_tyrepressurize_active(false), - simbuf_race_in_progress(false), - simbuf_race_in_progress_prev(false), - simbuf_sim_speed(1.0f), - simbuf_race_time(0.0f), - simbuf_race_best_time(0.0f), - simbuf_race_time_diff(0.0f), - simbuf_dir_arrow_target(Ogre::Vector3::ZERO) -{} +RoR::GfxScene::SimBuffer::SimBuffer() + : simbuf_player_actor(nullptr), simbuf_character_pos(Ogre::Vector3::ZERO), simbuf_tyrepressurize_active(false), + simbuf_race_in_progress(false), simbuf_race_in_progress_prev(false), simbuf_sim_speed(1.0f), simbuf_race_time(0.0f), + simbuf_race_best_time(0.0f), simbuf_race_time_diff(0.0f), simbuf_dir_arrow_target(Ogre::Vector3::ZERO) +{ +} diff --git a/source/main/gfx/GfxScene.h b/source/main/gfx/GfxScene.h index 6e0d27087d..50cc7cefa8 100644 --- a/source/main/gfx/GfxScene.h +++ b/source/main/gfx/GfxScene.h @@ -25,65 +25,73 @@ #pragma once -#include "ForwardDeclarations.h" #include "EnvironmentMap.h" // RoR::GfxEnvmap +#include "ForwardDeclarations.h" #include -#include #include +#include -namespace RoR { - -/// Provides a 3D graphical representation of the simulation -/// Idea: simulation runs at it's own constant rate, scene updates and rendering run asynchronously. -class GfxScene +namespace RoR { -public: - struct SimBuffer /// Buffered simulation state + /// Provides a 3D graphical representation of the simulation + /// Idea: simulation runs at it's own constant rate, scene updates and rendering run asynchronously. + class GfxScene { - SimBuffer(); - - Actor* simbuf_player_actor; - Ogre::Vector3 simbuf_character_pos; - Ogre::Vector3 simbuf_dir_arrow_target; - bool simbuf_tyrepressurize_active; - bool simbuf_sim_paused; - float simbuf_sim_speed; - float simbuf_race_time; - float simbuf_race_best_time; - float simbuf_race_time_diff; - bool simbuf_race_in_progress; - bool simbuf_race_in_progress_prev; + public: + struct SimBuffer /// Buffered simulation state + { + SimBuffer(); + + Actor * simbuf_player_actor; + Ogre::Vector3 simbuf_character_pos; + Ogre::Vector3 simbuf_dir_arrow_target; + bool simbuf_tyrepressurize_active; + bool simbuf_sim_paused; + float simbuf_sim_speed; + float simbuf_race_time; + float simbuf_race_best_time; + float simbuf_race_time_diff; + bool simbuf_race_in_progress; + bool simbuf_race_in_progress_prev; + }; + + GfxScene(); + ~GfxScene(); + + void InitScene(Ogre::SceneManager *sm); + DustPool * GetDustPool(const char *name); + void SetParticlesVisible(bool visible); + void UpdateScene(float dt_sec); + void RegisterGfxActor(RoR::GfxActor *gfx_actor); + void RemoveGfxActor(RoR::GfxActor *gfx_actor); + void RegisterGfxCharacter(RoR::GfxCharacter *gfx_character); + void RemoveGfxCharacter(RoR::GfxCharacter *gfx_character); + void BufferSimulationData(); //!< Run this when simulation is halted + SimBuffer &GetSimDataBuffer() + { + return m_simbuf; + } + SurveyMapManager *GetSurveyMap() + { + return m_survey_map.get(); + } + std::vector GetGfxActors() + { + return m_all_gfx_actors; + } + + private: + std::map m_dustpools; + Ogre::SceneManager * m_ogre_scene; + std::vector m_all_gfx_actors; + std::vector m_live_gfx_actors; + std::vector m_all_gfx_characters; + RoR::GfxEnvmap m_envmap; + SimBuffer m_simbuf; + std::unique_ptr + m_survey_map; //!< Minimap; placed here rather than GUIManager because it's lifetime is tied to terrain. }; - GfxScene(); - ~GfxScene(); - - void InitScene(Ogre::SceneManager* sm); - DustPool* GetDustPool(const char* name); - void SetParticlesVisible(bool visible); - void UpdateScene(float dt_sec); - void RegisterGfxActor(RoR::GfxActor* gfx_actor); - void RemoveGfxActor(RoR::GfxActor* gfx_actor); - void RegisterGfxCharacter(RoR::GfxCharacter* gfx_character); - void RemoveGfxCharacter(RoR::GfxCharacter* gfx_character); - void BufferSimulationData(); //!< Run this when simulation is halted - SimBuffer& GetSimDataBuffer() { return m_simbuf; } - SurveyMapManager* GetSurveyMap() { return m_survey_map.get(); } - std::vector GetGfxActors() { return m_all_gfx_actors; } - -private: - - std::map m_dustpools; - Ogre::SceneManager* m_ogre_scene; - std::vector m_all_gfx_actors; - std::vector m_live_gfx_actors; - std::vector m_all_gfx_characters; - RoR::GfxEnvmap m_envmap; - SimBuffer m_simbuf; - std::unique_ptr m_survey_map; //!< Minimap; placed here rather than GUIManager because it's lifetime is tied to terrain. - -}; - } // namespace RoR diff --git a/source/main/gfx/HydraxWater.cpp b/source/main/gfx/HydraxWater.cpp index d399d3377c..62d14c308f 100644 --- a/source/main/gfx/HydraxWater.cpp +++ b/source/main/gfx/HydraxWater.cpp @@ -26,19 +26,15 @@ #include "TerrainManager.h" #ifdef USE_CAELUM -#include + #include #endif // USE_CAELUM using namespace Ogre; // HydraxWater -HydraxWater::HydraxWater(float water_height, Ogre::String conf_file): - waternoise(0) - , mHydrax(0) - , waterHeight(water_height) - , waveHeight(water_height) - , mRenderCamera(gEnv->mainCamera) - , CurrentConfigFile(conf_file) +HydraxWater::HydraxWater(float water_height, Ogre::String conf_file) + : waternoise(0), mHydrax(0), waterHeight(water_height), waveHeight(water_height), mRenderCamera(gEnv->mainCamera), + CurrentConfigFile(conf_file) { mRenderCamera->setNearClipDistance(0.1f); @@ -56,7 +52,7 @@ void HydraxWater::InitHydrax() mHydrax = new Hydrax::Hydrax(gEnv->sceneManager, mRenderCamera, RoR::App::GetOgreSubsystem()->GetViewport()); waternoise = new Hydrax::Noise::Perlin(); - mModule = new Hydrax::Module::ProjectedGrid(// Hydrax parent pointer + mModule = new Hydrax::Module::ProjectedGrid( // Hydrax parent pointer mHydrax, // Noise module waternoise, @@ -67,15 +63,14 @@ void HydraxWater::InitHydrax() // Projected grid options Hydrax::Module::ProjectedGrid::Options()); - mHydrax->setModule(static_cast(mModule)); + mHydrax->setModule(static_cast(mModule)); mHydrax->loadCfg(CurrentConfigFile); // Choose shader language based on renderer (HLSL=0, CG=1, GLSL=2) - if (Root::getSingleton().getRenderSystem()->getName() == "Direct3D9 Rendering Subsystem" || Root::getSingleton().getRenderSystem()->getName() == "Direct3D11 Rendering Subsystem") - { - mHydrax->setShaderMode(static_cast(0)); - } + if (Root::getSingleton().getRenderSystem()->getName() == "Direct3D9 Rendering Subsystem" || + Root::getSingleton().getRenderSystem()->getName() == "Direct3D11 Rendering Subsystem") + { mHydrax->setShaderMode(static_cast(0)); } else { mHydrax->setShaderMode(static_cast(2)); @@ -87,8 +82,7 @@ void HydraxWater::InitHydrax() bool HydraxWater::IsUnderWater(Ogre::Vector3 pos) { - if (pos.y < CalcWavesHeight(Ogre::Vector3(pos.x, pos.y, pos.z))) - return true; + if (pos.y < CalcWavesHeight(Ogre::Vector3(pos.x, pos.y, pos.z))) return true; return false; } @@ -97,11 +91,13 @@ void HydraxWater::UpdateWater() #ifdef USE_CAELUM if (RoR::App::GetSimTerrain()->getSkyManager() != nullptr) { - SkyManager* sky = RoR::App::GetSimTerrain()->getSkyManager(); + SkyManager * sky = RoR::App::GetSimTerrain()->getSkyManager(); Ogre::Vector3 sunPosition = gEnv->mainCamera->getDerivedPosition(); sunPosition -= sky->GetCaelumSys()->getSun()->getLightDirection() * 80000; mHydrax->setSunPosition(sunPosition); - mHydrax->setSunColor(Ogre::Vector3(sky->GetCaelumSys()->getSun()->getBodyColour().r, sky->GetCaelumSys()->getSun()->getBodyColour().g, sky->GetCaelumSys()->getSun()->getBodyColour().b)); + mHydrax->setSunColor(Ogre::Vector3(sky->GetCaelumSys()->getSun()->getBodyColour().r, + sky->GetCaelumSys()->getSun()->getBodyColour().g, + sky->GetCaelumSys()->getSun()->getBodyColour().b)); } #endif // USE_CAELUM } @@ -118,40 +114,30 @@ void HydraxWater::SetStaticWaterHeight(float value) void HydraxWater::SetWaterVisible(bool value) { - if (mHydrax) - mHydrax->setVisible(value); + if (mHydrax) mHydrax->setVisible(value); } float HydraxWater::CalcWavesHeight(Vector3 pos) { - if (!RoR::App::gfx_water_waves.GetActive()) - { - return waterHeight; - } + if (!RoR::App::gfx_water_waves.GetActive()) { return waterHeight; } waveHeight = mHydrax->getHeigth(pos); return waveHeight; } Vector3 HydraxWater::CalcWavesVelocity(Vector3 pos) { - if (!RoR::App::gfx_water_waves.GetActive()) - return Vector3(0, 0, 0); + if (!RoR::App::gfx_water_waves.GetActive()) return Vector3(0, 0, 0); - return Vector3(0, 0, 0); //TODO + return Vector3(0, 0, 0); // TODO } void HydraxWater::WaterSetSunPosition(Ogre::Vector3 pos) { - if (mHydrax) - mHydrax->setSunPosition(pos); + if (mHydrax) mHydrax->setSunPosition(pos); } void HydraxWater::FrameStepWater(float dt) { - if (mHydrax) - { - mHydrax->update(dt); - } + if (mHydrax) { mHydrax->update(dt); } this->UpdateWater(); } - diff --git a/source/main/gfx/HydraxWater.h b/source/main/gfx/HydraxWater.h index a39c3116a0..ecee9e398b 100644 --- a/source/main/gfx/HydraxWater.h +++ b/source/main/gfx/HydraxWater.h @@ -28,32 +28,33 @@ class HydraxWater : public IWater { -public: - + public: HydraxWater(float waterHeight, Ogre::String configFile = "HydraxDefault.hdx"); ~HydraxWater(); // Interface IWater - float GetStaticWaterHeight() override; - void SetStaticWaterHeight(float value) override; - float CalcWavesHeight(Ogre::Vector3 pos) override; - Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) override; - void SetWaterVisible(bool value) override; - void WaterSetSunPosition(Ogre::Vector3) override; - bool IsUnderWater(Ogre::Vector3 pos) override; - void FrameStepWater(float dt) override; - void UpdateWater() override; - - Hydrax::Hydrax* GetHydrax() { return mHydrax; } - -protected: - - void InitHydrax(); - Hydrax::Hydrax* mHydrax; - float waveHeight; - float waterHeight; - Ogre::Camera* mRenderCamera; - Hydrax::Noise::Perlin* waternoise; - Hydrax::Module::ProjectedGrid* mModule; - Ogre::String CurrentConfigFile; + float GetStaticWaterHeight() override; + void SetStaticWaterHeight(float value) override; + float CalcWavesHeight(Ogre::Vector3 pos) override; + Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) override; + void SetWaterVisible(bool value) override; + void WaterSetSunPosition(Ogre::Vector3) override; + bool IsUnderWater(Ogre::Vector3 pos) override; + void FrameStepWater(float dt) override; + void UpdateWater() override; + + Hydrax::Hydrax *GetHydrax() + { + return mHydrax; + } + + protected: + void InitHydrax(); + Hydrax::Hydrax * mHydrax; + float waveHeight; + float waterHeight; + Ogre::Camera * mRenderCamera; + Hydrax::Noise::Perlin * waternoise; + Hydrax::Module::ProjectedGrid *mModule; + Ogre::String CurrentConfigFile; }; diff --git a/source/main/gfx/IWater.h b/source/main/gfx/IWater.h index 9ecdaccd1f..d67cf65265 100644 --- a/source/main/gfx/IWater.h +++ b/source/main/gfx/IWater.h @@ -22,11 +22,12 @@ #pragma once #include "ForwardDeclarations.h" + #include class IWater //!< TODO: Mixed gfx+physics (waves) - must be separated ~ only_a_ptr, 02/2018 { -public: + public: IWater() { } @@ -35,18 +36,28 @@ class IWater //!< TODO: Mixed gfx+physics (waves) - must be separated ~ only_a_p { } - virtual float GetStaticWaterHeight() = 0; //!< Returns static water level configured in 'terrn2' - virtual void SetStaticWaterHeight(float value) = 0; - virtual void SetWaterBottomHeight(float value) {}; - virtual float CalcWavesHeight(Ogre::Vector3 pos) = 0; - virtual Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) = 0; - virtual void SetWaterVisible(bool value) = 0; - virtual void WaterSetCamera(Ogre::Camera* cam) {} - virtual void WaterSetSunPosition(Ogre::Vector3) {} - virtual bool IsUnderWater(Ogre::Vector3 pos) = 0; - virtual void FrameStepWater(float dt) = 0; - virtual void SetReflectionPlaneHeight(float centerheight) {} - virtual void UpdateReflectionPlane(float h) {} - virtual void WaterPrepareShutdown() {} - virtual void UpdateWater() = 0; + virtual float GetStaticWaterHeight() = 0; //!< Returns static water level configured in 'terrn2' + virtual void SetStaticWaterHeight(float value) = 0; + virtual void SetWaterBottomHeight(float value){}; + virtual float CalcWavesHeight(Ogre::Vector3 pos) = 0; + virtual Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) = 0; + virtual void SetWaterVisible(bool value) = 0; + virtual void WaterSetCamera(Ogre::Camera *cam) + { + } + virtual void WaterSetSunPosition(Ogre::Vector3) + { + } + virtual bool IsUnderWater(Ogre::Vector3 pos) = 0; + virtual void FrameStepWater(float dt) = 0; + virtual void SetReflectionPlaneHeight(float centerheight) + { + } + virtual void UpdateReflectionPlane(float h) + { + } + virtual void WaterPrepareShutdown() + { + } + virtual void UpdateWater() = 0; }; diff --git a/source/main/gfx/MovableText.cpp b/source/main/gfx/MovableText.cpp index 20989c1206..068888f129 100644 --- a/source/main/gfx/MovableText.cpp +++ b/source/main/gfx/MovableText.cpp @@ -30,32 +30,21 @@ using namespace Ogre; -#define POS_TEX_BINDING 0 -#define COLOUR_BINDING 1 - -MovableText::MovableText(const UTFString& name, const UTFString& caption, const UTFString& fontName, Real charHeight, const ColourValue& color) - : mpCam(NULL) - , mpWin(NULL) - , mpFont(NULL) - , mName(name) - , mCaption(caption) - , mFontName(fontName) - , mCharHeight(charHeight) - , mColor(color) - , mType("MovableText") - , mTimeUntilNextToggle(0) - , mSpaceWidth(0.2f) - , mUpdateColors(true) - , mOnTop(false) - , mHorizontalAlignment(H_LEFT) - , mVerticalAlignment(V_BELOW) - , mAdditionalHeight(0.0) +#define POS_TEX_BINDING 0 +#define COLOUR_BINDING 1 + +MovableText::MovableText(const UTFString &name, const UTFString &caption, const UTFString &fontName, Real charHeight, + const ColourValue &color) + : mpCam(NULL), mpWin(NULL), mpFont(NULL), mName(name), mCaption(caption), mFontName(fontName), mCharHeight(charHeight), + mColor(color), mType("MovableText"), mTimeUntilNextToggle(0), mSpaceWidth(0.2f), mUpdateColors(true), mOnTop(false), + mHorizontalAlignment(H_LEFT), mVerticalAlignment(V_BELOW), mAdditionalHeight(0.0) { if (name == "") throw Exception(Exception::ERR_INVALIDPARAMS, "Trying to create MovableText without name", "MovableText::MovableText"); if (caption == "") - // throw Exception(Exception::ERR_INVALIDPARAMS, "Trying to create MovableText without caption", "MovableText::MovableText"); + // throw Exception(Exception::ERR_INVALIDPARAMS, "Trying to create MovableText without caption", + // "MovableText::MovableText"); mCaption = "."; mRenderOp.vertexData = NULL; @@ -65,21 +54,18 @@ MovableText::MovableText(const UTFString& name, const UTFString& caption, const MovableText::~MovableText() { - if (mRenderOp.vertexData) - delete mRenderOp.vertexData; + if (mRenderOp.vertexData) delete mRenderOp.vertexData; } -void MovableText::setFontName(const UTFString& fontName) +void MovableText::setFontName(const UTFString &fontName) { if ((Ogre::MaterialManager::getSingletonPtr()->resourceExists(mName + "Material"))) - { - Ogre::MaterialManager::getSingleton().remove(mName + "Material"); - } + { Ogre::MaterialManager::getSingleton().remove(mName + "Material"); } if (mFontName != fontName || mpMaterial.isNull() || !mpFont) { mFontName = fontName; - mpFont = (Font *)FontManager::getSingleton().getResourceByName(mFontName).getPointer(); + mpFont = (Font *)FontManager::getSingleton().getResourceByName(mFontName).getPointer(); if (!mpFont) throw Exception(Exception::ERR_ITEM_NOT_FOUND, "Could not find font " + fontName, "MovableText::setFontName"); @@ -92,8 +78,7 @@ void MovableText::setFontName(const UTFString& fontName) } mpMaterial = mpFont->getMaterial()->clone(mName + "Material"); - if (!mpMaterial->isLoaded()) - mpMaterial->load(); + if (!mpMaterial->isLoaded()) mpMaterial->load(); mpMaterial->setDepthCheckEnabled(!mOnTop); mpMaterial->setDepthBias(1.0, 1.0); @@ -104,20 +89,20 @@ void MovableText::setFontName(const UTFString& fontName) } } -void MovableText::setCaption(const UTFString& caption) +void MovableText::setCaption(const UTFString &caption) { if (caption != mCaption) { - mCaption = caption; + mCaption = caption; mNeedUpdate = true; } } -void MovableText::setColor(const ColourValue& color) +void MovableText::setColor(const ColourValue &color) { if (color != mColor) { - mColor = color; + mColor = color; mUpdateColors = true; } } @@ -140,17 +125,17 @@ void MovableText::setSpaceWidth(Real width) } } -void MovableText::setTextAlignment(const HorizontalAlignment& horizontalAlignment, const VerticalAlignment& verticalAlignment) +void MovableText::setTextAlignment(const HorizontalAlignment &horizontalAlignment, const VerticalAlignment &verticalAlignment) { if (mHorizontalAlignment != horizontalAlignment) { mHorizontalAlignment = horizontalAlignment; - mNeedUpdate = true; + mNeedUpdate = true; } if (mVerticalAlignment != verticalAlignment) { mVerticalAlignment = verticalAlignment; - mNeedUpdate = true; + mNeedUpdate = true; } } @@ -159,7 +144,7 @@ void MovableText::setAdditionalHeight(Real height) if (fabs(mAdditionalHeight - height) > 0.00001f) { mAdditionalHeight = height; - mNeedUpdate = true; + mNeedUpdate = true; } } @@ -186,72 +171,66 @@ void MovableText::_setupGeometry() // Removed this test as it causes problems when replacing a caption // of the same size: replacing "Hello" with "hello" // as well as when changing the text alignment - //if (mRenderOp.vertexData->vertexCount != vertexCount) + // if (mRenderOp.vertexData->vertexCount != vertexCount) { delete mRenderOp.vertexData; mRenderOp.vertexData = NULL; - mUpdateColors = true; + mUpdateColors = true; } } - if (!mRenderOp.vertexData) - mRenderOp.vertexData = new VertexData(); + if (!mRenderOp.vertexData) mRenderOp.vertexData = new VertexData(); - mRenderOp.indexData = 0; + mRenderOp.indexData = 0; mRenderOp.vertexData->vertexStart = 0; mRenderOp.vertexData->vertexCount = vertexCount; - mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; - mRenderOp.useIndexes = false; + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; + mRenderOp.useIndexes = false; - VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; - VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; - size_t offset = 0; + VertexDeclaration * decl = mRenderOp.vertexData->vertexDeclaration; + VertexBufferBinding *bind = mRenderOp.vertexData->vertexBufferBinding; + size_t offset = 0; // create/bind positions/tex.ccord. buffer - if (!decl->findElementBySemantic(VES_POSITION)) - decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION); + if (!decl->findElementBySemantic(VES_POSITION)) decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); if (!decl->findElementBySemantic(VES_TEXTURE_COORDINATES)) decl->addElement(POS_TEX_BINDING, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0); - HardwareVertexBufferSharedPtr ptbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(POS_TEX_BINDING), - mRenderOp.vertexData->vertexCount, - HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + HardwareVertexBufferSharedPtr ptbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + decl->getVertexSize(POS_TEX_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(POS_TEX_BINDING, ptbuf); // Colours - store these in a separate buffer because they change less often - if (!decl->findElementBySemantic(VES_DIFFUSE)) - decl->addElement(COLOUR_BINDING, 0, VET_COLOUR, VES_DIFFUSE); + if (!decl->findElementBySemantic(VES_DIFFUSE)) decl->addElement(COLOUR_BINDING, 0, VET_COLOUR, VES_DIFFUSE); - HardwareVertexBufferSharedPtr cbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(COLOUR_BINDING), - mRenderOp.vertexData->vertexCount, - HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + HardwareVertexBufferSharedPtr cbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + decl->getVertexSize(COLOUR_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(COLOUR_BINDING, cbuf); - //Real *pPCBuff = static_cast(ptbuf->lock(HardwareBuffer::HBL_NORMAL)); - Real* pPCBuff = (Real*)malloc(ptbuf->getSizeInBytes()); - Real* oPCBuff = pPCBuff; + // Real *pPCBuff = static_cast(ptbuf->lock(HardwareBuffer::HBL_NORMAL)); + Real *pPCBuff = (Real *)malloc(ptbuf->getSizeInBytes()); + Real *oPCBuff = pPCBuff; float largestWidth = 0; - float left = 0 * 2.0 - 1.0; - float top = -((0 * 2.0) - 1.0); + float left = 0 * 2.0 - 1.0; + float top = -((0 * 2.0) - 1.0); // Derive space width from a capital A - if (fabs(mSpaceWidth) < 0.00001f) - mSpaceWidth = mpFont->getGlyphAspectRatio('A') * mCharHeight * 2.0; + if (fabs(mSpaceWidth) < 0.00001f) mSpaceWidth = mpFont->getGlyphAspectRatio('A') * mCharHeight * 2.0; // for calculation of AABB Ogre::Vector3 min = Ogre::Vector3::ZERO, max = Ogre::Vector3::ZERO, currPos = Ogre::Vector3::ZERO; - Ogre::Real maxSquaredRadius = 0.0f; - bool first = true; + Ogre::Real maxSquaredRadius = 0.0f; + bool first = true; // Use iterator UTFString::iterator i, iend; - iend = mCaption.end(); + iend = mCaption.end(); bool newLine = true; - Real len = 0.0f; + Real len = 0.0f; if (mVerticalAlignment == MovableText::V_ABOVE) { @@ -259,8 +238,7 @@ void MovableText::_setupGeometry() top += mCharHeight; for (i = mCaption.begin(); i != iend; ++i) { - if (*i == '\n') - top += mCharHeight * 2.0; + if (*i == '\n') top += mCharHeight * 2.0; } } @@ -296,14 +274,14 @@ void MovableText::_setupGeometry() continue; } - Real horiz_height = mpFont->getGlyphAspectRatio(*i); - Real u1, u2, v1, v2; + Real horiz_height = mpFont->getGlyphAspectRatio(*i); + Real u1, u2, v1, v2; Ogre::Font::UVRect utmp; utmp = mpFont->getGlyphTexCoords(*i); - u1 = utmp.left; - u2 = utmp.right; - v1 = utmp.top; - v2 = utmp.bottom; + u1 = utmp.left; + u2 = utmp.right; + v1 = utmp.top; + v2 = utmp.bottom; // each vert is (x, y, z, u, v) //------------------------------------------------------------------------------------- @@ -326,9 +304,9 @@ void MovableText::_setupGeometry() currPos = Ogre::Vector3(left - (len / 2), top, -1.0); if (first) { - min = max = currPos; + min = max = currPos; maxSquaredRadius = currPos.squaredLength(); - first = false; + first = false; } else { @@ -439,21 +417,19 @@ void MovableText::_setupGeometry() top += mCharHeight * 2.0; float currentWidth = (left + 1) / 2 - 0; - if (currentWidth > largestWidth) - largestWidth = currentWidth; + if (currentWidth > largestWidth) largestWidth = currentWidth; } // Unlock vertex buffer - //ptbuf->unlock(); + // ptbuf->unlock(); ptbuf->writeData(0, ptbuf->getSizeInBytes(), oPCBuff, true); free(oPCBuff); // update AABB/Sphere radius - mAABB = Ogre::AxisAlignedBox(min, max); + mAABB = Ogre::AxisAlignedBox(min, max); mRadius = Ogre::Math::Sqrt(maxSquaredRadius); - if (mUpdateColors) - this->_updateColors(); + if (mUpdateColors) this->_updateColors(); mNeedUpdate = false; } @@ -467,30 +443,30 @@ void MovableText::_updateColors(void) RGBA color; Root::getSingleton().convertColourValue(mColor, &color); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); - //RGBA *pDest = static_cast(vbuf->lock(HardwareBuffer::HBL_NORMAL)); - RGBA* pDest = (RGBA*)malloc(vbuf->getSizeInBytes()); - RGBA* oDest = pDest; + // RGBA *pDest = static_cast(vbuf->lock(HardwareBuffer::HBL_NORMAL)); + RGBA *pDest = (RGBA *)malloc(vbuf->getSizeInBytes()); + RGBA *oDest = pDest; for (uint i = 0; i < mRenderOp.vertexData->vertexCount; ++i) *pDest++ = color; - //vbuf->unlock(); + // vbuf->unlock(); vbuf->writeData(0, vbuf->getSizeInBytes(), oDest, true); free(oDest); mUpdateColors = false; } -const Quaternion& MovableText::getWorldOrientation(void) const +const Quaternion &MovableText::getWorldOrientation(void) const { assert(mpCam); - return const_cast(mpCam->getDerivedOrientation()); + return const_cast(mpCam->getDerivedOrientation()); } -const Vector3& MovableText::getWorldPosition(void) const +const Vector3 &MovableText::getWorldPosition(void) const { assert(mParentNode); return mParentNode->_getDerivedPosition(); } -void MovableText::getWorldTransforms(Matrix4* xform) const +void MovableText::getWorldTransforms(Matrix4 *xform) const { if (this->isVisible() && mpCam) { @@ -513,31 +489,27 @@ void MovableText::getWorldTransforms(Matrix4* xform) const } } -void MovableText::getRenderOperation(RenderOperation& op) +void MovableText::getRenderOperation(RenderOperation &op) { if (this->isVisible()) { - if (mNeedUpdate) - this->_setupGeometry(); - if (mUpdateColors) - this->_updateColors(); + if (mNeedUpdate) this->_setupGeometry(); + if (mUpdateColors) this->_updateColors(); op = mRenderOp; } } -void MovableText::_notifyCurrentCamera(Camera* cam) +void MovableText::_notifyCurrentCamera(Camera *cam) { mpCam = cam; } -void MovableText::_updateRenderQueue(RenderQueue* queue) +void MovableText::_updateRenderQueue(RenderQueue *queue) { if (this->isVisible()) { - if (mNeedUpdate) - this->_setupGeometry(); - if (mUpdateColors) - this->_updateColors(); + if (mNeedUpdate) this->_setupGeometry(); + if (mUpdateColors) this->_updateColors(); queue->addRenderable(this, mRenderQueueID, OGRE_RENDERABLE_DEFAULT_PRIORITY); // queue->addRenderable(this, mRenderQueueID, RENDER_QUEUE_SKIES_LATE); diff --git a/source/main/gfx/MovableText.h b/source/main/gfx/MovableText.h index 7bca57ec4f..99d922b34d 100644 --- a/source/main/gfx/MovableText.h +++ b/source/main/gfx/MovableText.h @@ -25,104 +25,159 @@ #pragma once -#include -#include - #include "RoRPrerequisites.h" -namespace Ogre { +#include +#include -class MovableText : public MovableObject, public Renderable +namespace Ogre { - /******************************** MovableText data ****************************/ -public: - enum HorizontalAlignment {H_LEFT, H_CENTER}; - enum VerticalAlignment {V_BELOW, V_ABOVE}; - -protected: - UTFString mFontName; - UTFString mType; - String mName; - UTFString mCaption; - HorizontalAlignment mHorizontalAlignment; - VerticalAlignment mVerticalAlignment; - - ColourValue mColor; - RenderOperation mRenderOp; - AxisAlignedBox mAABB; - LightList mLList; - - Real mCharHeight; - Real mSpaceWidth; - - bool mNeedUpdate; - bool mUpdateColors; - bool mOnTop; - - Real mTimeUntilNextToggle; - Real mRadius; - Real mAdditionalHeight; - - Camera *mpCam; - RenderWindow *mpWin; - Font *mpFont; - MaterialPtr mpMaterial; - MaterialPtr mpBackgroundMaterial; - - /******************************** public methods ******************************/ -public: - MovableText(const UTFString &name, const UTFString &caption, const UTFString &fontName = "highcontrast_black", Real charHeight = 1.0, const ColourValue &color = ColourValue::Black); - virtual ~MovableText(); - - // Add to build on Shoggoth: - virtual void visitRenderables(Ogre::Renderable::Visitor* visitor, bool debugRenderables = false) {}; - - // Set settings - void setFontName(const UTFString &fontName); - void setCaption(const UTFString &caption); - void setColor(const ColourValue &color); - void setCharacterHeight(Real height); - void setSpaceWidth(Real width); - void setTextAlignment(const HorizontalAlignment& horizontalAlignment, const VerticalAlignment& verticalAlignment); - void setAdditionalHeight( Real height ); - void showOnTop(bool show=true); - - // Get settings - const UTFString &getFontName() const {return mFontName;} - const UTFString &getCaption() const {return mCaption;} - const ColourValue &getColor() const {return mColor;} - - uint getCharacterHeight() const {return (uint) mCharHeight;} - uint getSpaceWidth() const {return (uint) mSpaceWidth;} - Real getAdditionalHeight() const {return mAdditionalHeight;} - bool getShowOnTop() const {return mOnTop;} - AxisAlignedBox GetAABB(void) { return mAABB; } - - /******************************** protected methods and overload **************/ -protected: - - // from MovableText, create the object - void _setupGeometry(); - void _updateColors(); - - // from MovableObject - void getWorldTransforms(Matrix4 *xform) const; - Real getBoundingRadius(void) const {return mRadius;}; - Real getSquaredViewDepth(const Camera *cam) const {return 0;}; - const Quaternion &getWorldOrientation(void) const; - const Vector3 &getWorldPosition(void) const; - const AxisAlignedBox &getBoundingBox(void) const {return mAABB;}; - const String &getName(void) const {return mName;}; - const String &getMovableType(void) const {static Ogre::String movType = "MovableText"; return movType;}; - - void _notifyCurrentCamera(Camera *cam); - void _updateRenderQueue(RenderQueue* queue); - - // from renderable - void getRenderOperation(RenderOperation &op); - const MaterialPtr &getMaterial(void) const {assert(!mpMaterial.isNull());return mpMaterial;}; - const LightList &getLights(void) const {return mLList;}; -}; - -} // namespace + class MovableText : public MovableObject, public Renderable + { + /******************************** MovableText data ****************************/ + public: + enum HorizontalAlignment + { + H_LEFT, + H_CENTER + }; + enum VerticalAlignment + { + V_BELOW, + V_ABOVE + }; + + protected: + UTFString mFontName; + UTFString mType; + String mName; + UTFString mCaption; + HorizontalAlignment mHorizontalAlignment; + VerticalAlignment mVerticalAlignment; + + ColourValue mColor; + RenderOperation mRenderOp; + AxisAlignedBox mAABB; + LightList mLList; + + Real mCharHeight; + Real mSpaceWidth; + + bool mNeedUpdate; + bool mUpdateColors; + bool mOnTop; + + Real mTimeUntilNextToggle; + Real mRadius; + Real mAdditionalHeight; + + Camera * mpCam; + RenderWindow *mpWin; + Font * mpFont; + MaterialPtr mpMaterial; + MaterialPtr mpBackgroundMaterial; + + /******************************** public methods ******************************/ + public: + MovableText(const UTFString &name, const UTFString &caption, const UTFString &fontName = "highcontrast_black", + Real charHeight = 1.0, const ColourValue &color = ColourValue::Black); + virtual ~MovableText(); + + // Add to build on Shoggoth: + virtual void visitRenderables(Ogre::Renderable::Visitor *visitor, bool debugRenderables = false){}; + + // Set settings + void setFontName(const UTFString &fontName); + void setCaption(const UTFString &caption); + void setColor(const ColourValue &color); + void setCharacterHeight(Real height); + void setSpaceWidth(Real width); + void setTextAlignment(const HorizontalAlignment &horizontalAlignment, const VerticalAlignment &verticalAlignment); + void setAdditionalHeight(Real height); + void showOnTop(bool show = true); + + // Get settings + const UTFString &getFontName() const + { + return mFontName; + } + const UTFString &getCaption() const + { + return mCaption; + } + const ColourValue &getColor() const + { + return mColor; + } + + uint getCharacterHeight() const + { + return (uint)mCharHeight; + } + uint getSpaceWidth() const + { + return (uint)mSpaceWidth; + } + Real getAdditionalHeight() const + { + return mAdditionalHeight; + } + bool getShowOnTop() const + { + return mOnTop; + } + AxisAlignedBox GetAABB(void) + { + return mAABB; + } + + /******************************** protected methods and overload **************/ + protected: + // from MovableText, create the object + void _setupGeometry(); + void _updateColors(); + + // from MovableObject + void getWorldTransforms(Matrix4 *xform) const; + Real getBoundingRadius(void) const + { + return mRadius; + }; + Real getSquaredViewDepth(const Camera *cam) const + { + return 0; + }; + const Quaternion & getWorldOrientation(void) const; + const Vector3 & getWorldPosition(void) const; + const AxisAlignedBox &getBoundingBox(void) const + { + return mAABB; + }; + const String &getName(void) const + { + return mName; + }; + const String &getMovableType(void) const + { + static Ogre::String movType = "MovableText"; + return movType; + }; + + void _notifyCurrentCamera(Camera *cam); + void _updateRenderQueue(RenderQueue *queue); + + // from renderable + void getRenderOperation(RenderOperation &op); + const MaterialPtr &getMaterial(void) const + { + assert(!mpMaterial.isNull()); + return mpMaterial; + }; + const LightList &getLights(void) const + { + return mLList; + }; + }; + +} // namespace Ogre diff --git a/source/main/gfx/OgreSubsystem.cpp b/source/main/gfx/OgreSubsystem.cpp index 61ca0edba4..7dedf6ad99 100644 --- a/source/main/gfx/OgreSubsystem.cpp +++ b/source/main/gfx/OgreSubsystem.cpp @@ -19,12 +19,10 @@ along with Rigs of Rods. If not, see . */ - /// @file OgreSubsystem.cpp /// @author Petr Ohlidal /// @date 05/2014 - #include "OgreSubsystem.h" #include "Application.h" @@ -34,6 +32,7 @@ #include "RoRVersion.h" #include "Utils.h" +#include #include #include #include @@ -42,172 +41,161 @@ #include #include #include -#include namespace RoR { -OgreSubsystem::OgreSubsystem() : - m_ogre_root(nullptr), - m_render_window(nullptr), - m_viewport(nullptr) -{} + OgreSubsystem::OgreSubsystem() : m_ogre_root(nullptr), m_render_window(nullptr), m_viewport(nullptr) + { + } -OgreSubsystem::~OgreSubsystem() -{ - LOG("Shutting down OGRE subsystem"); -} + OgreSubsystem::~OgreSubsystem() + { + LOG("Shutting down OGRE subsystem"); + } -bool OgreSubsystem::Configure() -{ - try + bool OgreSubsystem::Configure() { - if (!m_ogre_root->restoreConfig()) + try { - const auto render_systems = App::GetOgreSubsystem()->GetOgreRoot()->getAvailableRenderers(); - if (!render_systems.empty()) - m_ogre_root->setRenderSystem(render_systems.front()); - else - ErrorUtils::ShowError (_L("Startup error"), _L("No render system plugin available. Check your plugins.cfg")); + if (!m_ogre_root->restoreConfig()) + { + const auto render_systems = App::GetOgreSubsystem()->GetOgreRoot()->getAvailableRenderers(); + if (!render_systems.empty()) + m_ogre_root->setRenderSystem(render_systems.front()); + else + ErrorUtils::ShowError(_L("Startup error"), _L("No render system plugin available. Check your plugins.cfg")); + } + } + catch (...) + { + auto dialog = OgreBites::getNativeConfigDialog(); + if (dialog->display()) m_ogre_root->saveConfig(); } - } - catch (...) - { - auto dialog = OgreBites::getNativeConfigDialog(); - if (dialog->display()) - m_ogre_root->saveConfig(); - } + const auto rs = m_ogre_root->getRenderSystemByName(App::app_rendersys_override.GetActive()); + if (rs != nullptr && rs != m_ogre_root->getRenderSystem()) + { + // The user has selected a different render system during the previous session. + m_ogre_root->setRenderSystem(rs); + m_ogre_root->saveConfig(); + } + App::app_rendersys_override.SetActive(""); - const auto rs = m_ogre_root->getRenderSystemByName(App::app_rendersys_override.GetActive()); - if (rs != nullptr && rs != m_ogre_root->getRenderSystem()) - { - // The user has selected a different render system during the previous session. - m_ogre_root->setRenderSystem(rs); - m_ogre_root->saveConfig(); - } - App::app_rendersys_override.SetActive(""); - - m_render_window = m_ogre_root->initialise(false); - - Ogre::ConfigOptionMap ropts = m_ogre_root->getRenderSystem()->getConfigOptions(); - Ogre::uint32 width, height; - Ogre::NameValuePairList miscParams; - - std::istringstream mode (ropts["Video Mode"].currentValue); - Ogre::String token; - mode >> width; - mode >> token; // 'x' as seperator between width and height - mode >> height; - - if(width < 800) width = 800; - if(height < 600) height = 600; - - miscParams["FSAA"] = ropts["FSAA"].currentValue; - miscParams["vsync"] = ropts["VSync"].currentValue; - miscParams["gamma"] = ropts["sRGB Gamma Conversion"].currentValue; - miscParams["border"] = "fixed"; -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - const auto rd = ropts["Rendering Device"]; - const auto it = std::find(rd.possibleValues.begin(), rd.possibleValues.end(), rd.currentValue); - const int idx = std::distance(rd.possibleValues.begin(), it); - miscParams["monitorIndex"] = Ogre::StringConverter::toString(idx); - miscParams["windowProc"] = Ogre::StringConverter::toString((size_t)OgreBites::WindowEventUtilities::_WndProc); -#endif + m_render_window = m_ogre_root->initialise(false); - m_render_window = Ogre::Root::getSingleton().createRenderWindow ( - "Rigs of Rods version " + Ogre::String (ROR_VERSION_STRING), - width, height, ropts["Full Screen"].currentValue == "Yes", &miscParams); - OgreBites::WindowEventUtilities::_addRenderWindow(m_render_window); + Ogre::ConfigOptionMap ropts = m_ogre_root->getRenderSystem()->getConfigOptions(); + Ogre::uint32 width, height; + Ogre::NameValuePairList miscParams; - // set window icon correctly - fixRenderWindowIcon(m_render_window); + std::istringstream mode(ropts["Video Mode"].currentValue); + Ogre::String token; + mode >> width; + mode >> token; // 'x' as seperator between width and height + mode >> height; - return true; -} + if (width < 800) width = 800; + if (height < 600) height = 600; -bool OgreSubsystem::LoadOgrePlugins(Ogre::String const & pluginsfile) -{ - Ogre::ConfigFile cfg; + miscParams["FSAA"] = ropts["FSAA"].currentValue; + miscParams["vsync"] = ropts["VSync"].currentValue; + miscParams["gamma"] = ropts["sRGB Gamma Conversion"].currentValue; + miscParams["border"] = "fixed"; +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + const auto rd = ropts["Rendering Device"]; + const auto it = std::find(rd.possibleValues.begin(), rd.possibleValues.end(), rd.currentValue); + const int idx = std::distance(rd.possibleValues.begin(), it); + miscParams["monitorIndex"] = Ogre::StringConverter::toString(idx); + miscParams["windowProc"] = Ogre::StringConverter::toString((size_t)OgreBites::WindowEventUtilities::_WndProc); +#endif - try - { - cfg.load( pluginsfile ); - } - catch (Ogre::Exception& e) - { - Ogre::LogManager::getSingleton().logMessage(pluginsfile + " not found, automatic plugin loading disabled. Message: " + e.getFullDescription()); - return false; - } + m_render_window = + Ogre::Root::getSingleton().createRenderWindow("Rigs of Rods version " + Ogre::String(ROR_VERSION_STRING), width, + height, ropts["Full Screen"].currentValue == "Yes", &miscParams); + OgreBites::WindowEventUtilities::_addRenderWindow(m_render_window); - Ogre::String pluginDir = cfg.getSetting("PluginFolder"); - Ogre::StringVector pluginList = cfg.getMultiSetting("Plugin"); + // set window icon correctly + fixRenderWindowIcon(m_render_window); - if (pluginDir.empty()) - { - pluginDir = RoR::App::sys_process_dir.GetActive(); + return true; } - for ( Ogre::StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it ) + bool OgreSubsystem::LoadOgrePlugins(Ogre::String const &pluginsfile) { - Ogre::String pluginFilename = RoR::PathCombine(pluginDir, *it); + Ogre::ConfigFile cfg; + try { - m_ogre_root->loadPlugin(pluginFilename); + cfg.load(pluginsfile); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - LOG("failed to load plugin: " + pluginFilename + ": " + e.getFullDescription()); + Ogre::LogManager::getSingleton().logMessage( + pluginsfile + " not found, automatic plugin loading disabled. Message: " + e.getFullDescription()); + return false; } + + Ogre::String pluginDir = cfg.getSetting("PluginFolder"); + Ogre::StringVector pluginList = cfg.getMultiSetting("Plugin"); + + if (pluginDir.empty()) { pluginDir = RoR::App::sys_process_dir.GetActive(); } + + for (Ogre::StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it) + { + Ogre::String pluginFilename = RoR::PathCombine(pluginDir, *it); + try + { + m_ogre_root->loadPlugin(pluginFilename); + } + catch (Ogre::Exception &e) + { + LOG("failed to load plugin: " + pluginFilename + ": " + e.getFullDescription()); + } + } + return true; } - return true; -} -bool OgreSubsystem::StartOgre(Ogre::String const & hwnd, Ogre::String const & mainhwnd) -{ - m_hwnd = hwnd; - m_main_hwnd = mainhwnd; + bool OgreSubsystem::StartOgre(Ogre::String const &hwnd, Ogre::String const &mainhwnd) + { + m_hwnd = hwnd; + m_main_hwnd = mainhwnd; - CreateFolder(RoR::App::sys_logs_dir.GetActive()); - CreateFolder(RoR::App::sys_config_dir.GetActive()); + CreateFolder(RoR::App::sys_logs_dir.GetActive()); + CreateFolder(RoR::App::sys_config_dir.GetActive()); - std::string log_filepath = PathCombine(RoR::App::sys_logs_dir.GetActive(), "RoR.log"); - std::string cfg_filepath = PathCombine(RoR::App::sys_config_dir.GetActive(), "ogre.cfg"); - m_ogre_root = new Ogre::Root("", cfg_filepath, log_filepath); + std::string log_filepath = PathCombine(RoR::App::sys_logs_dir.GetActive(), "RoR.log"); + std::string cfg_filepath = PathCombine(RoR::App::sys_config_dir.GetActive(), "ogre.cfg"); + m_ogre_root = new Ogre::Root("", cfg_filepath, log_filepath); - // load plugins manually + // load plugins manually #ifdef _DEBUG - std::string plugins_path = PathCombine(RoR::App::sys_process_dir.GetActive(), "plugins_d.cfg"); + std::string plugins_path = PathCombine(RoR::App::sys_process_dir.GetActive(), "plugins_d.cfg"); #else - std::string plugins_path = PathCombine(RoR::App::sys_process_dir.GetActive(), "plugins.cfg"); + std::string plugins_path = PathCombine(RoR::App::sys_process_dir.GetActive(), "plugins.cfg"); #endif - this->LoadOgrePlugins(plugins_path); - - // configure RoR - this->Configure(); + this->LoadOgrePlugins(plugins_path); - m_viewport = m_render_window->addViewport(nullptr); + // configure RoR + this->Configure(); - m_viewport->setBackgroundColour(Ogre::ColourValue(0.5f, 0.5f, 0.5f, 1.0f)); + m_viewport = m_render_window->addViewport(nullptr); - m_viewport->setCamera(nullptr); - m_viewport->setBackgroundColour(Ogre::ColourValue::Black); + m_viewport->setBackgroundColour(Ogre::ColourValue(0.5f, 0.5f, 0.5f, 1.0f)); - Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5); + m_viewport->setCamera(nullptr); + m_viewport->setBackgroundColour(Ogre::ColourValue::Black); - m_render_window->setActive(true); + Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5); - return true; -} + m_render_window->setActive(true); + return true; + } -void OgreSubsystem::WindowResized(Ogre::Vector2 const & size) -{ - // Set the aspect ratio for the new size - if (m_viewport->getCamera()) + void OgreSubsystem::WindowResized(Ogre::Vector2 const &size) { - m_viewport->getCamera()->setAspectRatio(Ogre::Real(size.x) / Ogre::Real(size.y)); + // Set the aspect ratio for the new size + if (m_viewport->getCamera()) { m_viewport->getCamera()->setAspectRatio(Ogre::Real(size.x) / Ogre::Real(size.y)); } } -} } // namespace RoR diff --git a/source/main/gfx/OgreSubsystem.h b/source/main/gfx/OgreSubsystem.h index 50c2387d7d..7e2ac61cb6 100644 --- a/source/main/gfx/OgreSubsystem.h +++ b/source/main/gfx/OgreSubsystem.h @@ -30,55 +30,54 @@ #include -namespace RoR { - -class OgreSubsystem : public ZeroedMemoryAllocator +namespace RoR { -public: - - OgreSubsystem(); - ~OgreSubsystem(); - - bool StartOgre(Ogre::String const & hwnd, Ogre::String const & mainhwnd); - - void WindowResized(Ogre::Vector2 const & size); - Ogre::String GetMainHWND() - { - return m_main_hwnd; - } - - Ogre::Root* GetOgreRoot() - { - return m_ogre_root; - } - - Ogre::RenderWindow* GetRenderWindow() + class OgreSubsystem : public ZeroedMemoryAllocator { - return m_render_window; - } - - Ogre::Viewport* GetViewport() - { - return m_viewport; - } - - void SetViewport(Ogre::Viewport* viewport) - { - m_viewport = viewport; - } - -private: - - Ogre::String m_hwnd; - Ogre::String m_main_hwnd; - - Ogre::Root* m_ogre_root; - Ogre::RenderWindow* m_render_window; - Ogre::Viewport* m_viewport; - - bool Configure(); - bool LoadOgrePlugins(Ogre::String const & pluginsfile); -}; + public: + OgreSubsystem(); + ~OgreSubsystem(); + + bool StartOgre(Ogre::String const &hwnd, Ogre::String const &mainhwnd); + + void WindowResized(Ogre::Vector2 const &size); + + Ogre::String GetMainHWND() + { + return m_main_hwnd; + } + + Ogre::Root *GetOgreRoot() + { + return m_ogre_root; + } + + Ogre::RenderWindow *GetRenderWindow() + { + return m_render_window; + } + + Ogre::Viewport *GetViewport() + { + return m_viewport; + } + + void SetViewport(Ogre::Viewport *viewport) + { + m_viewport = viewport; + } + + private: + Ogre::String m_hwnd; + Ogre::String m_main_hwnd; + + Ogre::Root * m_ogre_root; + Ogre::RenderWindow *m_render_window; + Ogre::Viewport * m_viewport; + + bool Configure(); + bool LoadOgrePlugins(Ogre::String const &pluginsfile); + }; } // namespace RoR diff --git a/source/main/gfx/Renderdash.cpp b/source/main/gfx/Renderdash.cpp index 56655b9e65..93e7ea8f3a 100644 --- a/source/main/gfx/Renderdash.cpp +++ b/source/main/gfx/Renderdash.cpp @@ -20,42 +20,38 @@ #include "Renderdash.h" -#include #include +#include -RoR::Renderdash::Renderdash(std::string const& rg_name, std::string const& tex_name, std::string const& cam_name) - : m_dash_cam(nullptr) - , m_rtt_tex(nullptr) - , m_blend_overlay(nullptr) - , m_dash_overlay(nullptr) - , m_fps_overlay(nullptr) - , m_needles_overlay(nullptr) - , m_fps_displayed(false) +RoR::Renderdash::Renderdash(std::string const &rg_name, std::string const &tex_name, std::string const &cam_name) + : m_dash_cam(nullptr), m_rtt_tex(nullptr), m_blend_overlay(nullptr), m_dash_overlay(nullptr), m_fps_overlay(nullptr), + m_needles_overlay(nullptr), m_fps_displayed(false) { - m_texture = Ogre::TextureManager::getSingleton().createManual( - tex_name, rg_name, Ogre::TEX_TYPE_2D, 1024, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); + m_texture = Ogre::TextureManager::getSingleton().createManual(tex_name, rg_name, Ogre::TEX_TYPE_2D, 1024, 512, 0, + Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); m_rtt_tex = m_texture->getBuffer()->getRenderTarget(); static int cam_counter = 0; - m_dash_cam = gEnv->sceneManager->createCamera(cam_name); + m_dash_cam = gEnv->sceneManager->createCamera(cam_name); m_dash_cam->setNearClipDistance(1.0); m_dash_cam->setFarClipDistance(10.0); m_dash_cam->setPosition(Ogre::Vector3(0.0, -10000.0, 0.0)); m_dash_cam->setAspectRatio(2.0); - Ogre::Viewport* v = m_rtt_tex->addViewport(m_dash_cam); + Ogre::Viewport *v = m_rtt_tex->addViewport(m_dash_cam); v->setClearEveryFrame(true); v->setBackgroundColour(Ogre::ColourValue::Black); - // NOTE: The 'renderdash' material is defined as a dummy in file 'ror.material' which is loaded into every actor's resource group. + // NOTE: The 'renderdash' material is defined as a dummy in file 'ror.material' which is loaded into every actor's resource + // group. Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName("renderdash", rg_name); mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(m_texture); - m_dash_overlay = Ogre::OverlayManager::getSingleton().getByName("tracks/3D_DashboardOverlay"); + m_dash_overlay = Ogre::OverlayManager::getSingleton().getByName("tracks/3D_DashboardOverlay"); m_needles_overlay = Ogre::OverlayManager::getSingleton().getByName("tracks/3D_NeedlesOverlay"); - m_blend_overlay = Ogre::OverlayManager::getSingleton().getByName("tracks/3D_BlendOverlay"); + m_blend_overlay = Ogre::OverlayManager::getSingleton().getByName("tracks/3D_BlendOverlay"); m_rtt_tex->addListener(this); m_rtt_tex->setActive(false); @@ -63,8 +59,7 @@ RoR::Renderdash::Renderdash(std::string const& rg_name, std::string const& tex_n RoR::Renderdash::~Renderdash() { - if (m_rtt_tex != nullptr) - m_rtt_tex->removeListener(this); + if (m_rtt_tex != nullptr) m_rtt_tex->removeListener(this); gEnv->sceneManager->destroyCamera(m_dash_cam); Ogre::TextureManager::getSingleton().remove(m_texture); } @@ -74,7 +69,7 @@ void RoR::Renderdash::setEnable(bool en) m_rtt_tex->setActive(en); } -void RoR::Renderdash::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +void RoR::Renderdash::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { // hide everything gEnv->sceneManager->setFindVisibleObjects(false); @@ -83,10 +78,7 @@ void RoR::Renderdash::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) if (m_fps_overlay) { m_fps_displayed = m_fps_overlay->isVisible(); - if (m_fps_displayed) - { - m_fps_overlay->hide(); - } + if (m_fps_displayed) { m_fps_overlay->hide(); } } else { @@ -94,22 +86,19 @@ void RoR::Renderdash::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) m_fps_overlay = Ogre::OverlayManager::getSingleton().getByName("Core/DebugOverlay"); } - //show overlay + // show overlay m_dash_overlay->show(); m_needles_overlay->show(); m_blend_overlay->show(); } -void RoR::Renderdash::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +void RoR::Renderdash::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { // show everything gEnv->sceneManager->setFindVisibleObjects(true); // show everything again, if it was displayed before hiding it... - if (m_fps_overlay && m_fps_displayed) - { - m_fps_overlay->show(); - } + if (m_fps_overlay && m_fps_displayed) { m_fps_overlay->show(); } // hide overlay m_dash_overlay->hide(); diff --git a/source/main/gfx/Renderdash.h b/source/main/gfx/Renderdash.h index 609ff7d21c..bcbb892aa6 100644 --- a/source/main/gfx/Renderdash.h +++ b/source/main/gfx/Renderdash.h @@ -24,31 +24,35 @@ #include -namespace RoR { - -/// 'renderdash' is a name of a classic Render-To-Texture animated material with gauges and other dashboard info. -class Renderdash: public Ogre::RenderTargetListener +namespace RoR { -public: - Renderdash(std::string const& rg_name, std::string const& tex_name, std::string const& cam_name); - ~Renderdash(); - - void setEnable(bool en); - Ogre::TexturePtr getTexture() { return m_texture; } - - // Ogre::RenderTargetListener - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) override; - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) override; - -private: - Ogre::Camera* m_dash_cam; - Ogre::RenderTexture* m_rtt_tex; - Ogre::TexturePtr m_texture; - Ogre::Overlay* m_blend_overlay; - Ogre::Overlay* m_dash_overlay; - Ogre::Overlay* m_fps_overlay; - Ogre::Overlay* m_needles_overlay; - bool m_fps_displayed; -}; + + /// 'renderdash' is a name of a classic Render-To-Texture animated material with gauges and other dashboard info. + class Renderdash : public Ogre::RenderTargetListener + { + public: + Renderdash(std::string const &rg_name, std::string const &tex_name, std::string const &cam_name); + ~Renderdash(); + + void setEnable(bool en); + Ogre::TexturePtr getTexture() + { + return m_texture; + } + + // Ogre::RenderTargetListener + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; + + private: + Ogre::Camera * m_dash_cam; + Ogre::RenderTexture *m_rtt_tex; + Ogre::TexturePtr m_texture; + Ogre::Overlay * m_blend_overlay; + Ogre::Overlay * m_dash_overlay; + Ogre::Overlay * m_fps_overlay; + Ogre::Overlay * m_needles_overlay; + bool m_fps_displayed; + }; } // namespace RoR diff --git a/source/main/gfx/ShadowManager.cpp b/source/main/gfx/ShadowManager.cpp index c67f854298..15c739346a 100644 --- a/source/main/gfx/ShadowManager.cpp +++ b/source/main/gfx/ShadowManager.cpp @@ -21,20 +21,20 @@ #include "ShadowManager.h" #include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace Ogre; ShadowManager::ShadowManager() { PSSM_Shadows.mPSSMSetup.setNull(); - PSSM_Shadows.mDepthShadows = false; + PSSM_Shadows.mDepthShadows = false; PSSM_Shadows.ShadowsTextureNum = 3; - PSSM_Shadows.Quality = RoR::App::gfx_shadow_quality.GetActive(); //0 = Low quality, 1 = mid, 2 = hq, 3 = ultra + PSSM_Shadows.Quality = RoR::App::gfx_shadow_quality.GetActive(); // 0 = Low quality, 1 = mid, 2 = hq, 3 = ultra } ShadowManager::~ShadowManager() @@ -61,20 +61,22 @@ int ShadowManager::updateShadowTechnique() { // add the overlay elements to show the shadow maps: // init overlay elements - OverlayManager& mgr = Ogre::OverlayManager::getSingleton(); - Overlay* overlay = mgr.create("DebugOverlay"); + OverlayManager &mgr = Ogre::OverlayManager::getSingleton(); + Overlay * overlay = mgr.create("DebugOverlay"); for (int i = 0; i < PSSM_Shadows.ShadowsTextureNum; ++i) { TexturePtr tex = gEnv->sceneManager->getShadowTexture(i); // Set up a debug panel to display the shadow - MaterialPtr debugMat = MaterialManager::getSingleton().create("Ogre/DebugTexture" + StringConverter::toString(i), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + MaterialPtr debugMat = MaterialManager::getSingleton().create("Ogre/DebugTexture" + StringConverter::toString(i), + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); - TextureUnitState* t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); + TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - OverlayContainer* debugPanel = (OverlayContainer*)(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i))); + OverlayContainer *debugPanel = (OverlayContainer *)(OverlayManager::getSingleton().createOverlayElement( + "Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i))); debugPanel->_setPosition(0.8, i * 0.25); debugPanel->_setDimensions(0.2, 0.24); debugPanel->setMaterialName(debugMat->getName()); @@ -99,7 +101,7 @@ void ShadowManager::processPSSM() gEnv->sceneManager->setShadowTextureSelfShadow(true); gEnv->sceneManager->setShadowCasterRenderBackFaces(true); - //Caster is set via materials + // Caster is set via materials MaterialPtr shadowMat = MaterialManager::getSingleton().getByName("Ogre/shadow/depth/caster"); gEnv->sceneManager->setShadowTextureCasterMaterial(shadowMat); @@ -135,9 +137,10 @@ void ShadowManager::processPSSM() if (PSSM_Shadows.mPSSMSetup.isNull()) { // shadow camera setup - Ogre::PSSMShadowCameraSetup* pssmSetup = new Ogre::PSSMShadowCameraSetup(); + Ogre::PSSMShadowCameraSetup *pssmSetup = new Ogre::PSSMShadowCameraSetup(); - pssmSetup->calculateSplitPoints(3, gEnv->mainCamera->getNearClipDistance(), gEnv->sceneManager->getShadowFarDistance(), PSSM_Shadows.lambda); + pssmSetup->calculateSplitPoints(3, gEnv->mainCamera->getNearClipDistance(), gEnv->sceneManager->getShadowFarDistance(), + PSSM_Shadows.lambda); pssmSetup->setSplitPadding(gEnv->mainCamera->getNearClipDistance()); pssmSetup->setOptimalAdjustFactor(0, -1); @@ -146,7 +149,7 @@ void ShadowManager::processPSSM() PSSM_Shadows.mPSSMSetup.bind(pssmSetup); - //Send split info to managed materials + // Send split info to managed materials setManagedMaterialSplitPoints(pssmSetup->getSplitPoints()); } gEnv->sceneManager->setShadowCameraSetup(PSSM_Shadows.mPSSMSetup); @@ -154,16 +157,15 @@ void ShadowManager::processPSSM() void ShadowManager::updatePSSM() { - if (!PSSM_Shadows.mPSSMSetup.get()) - return; - //Ugh what here? + if (!PSSM_Shadows.mPSSMSetup.get()) return; + // Ugh what here? } -void ShadowManager::updateTerrainMaterial(Ogre::TerrainPSSMMaterialGenerator::SM2Profile* matProfile) +void ShadowManager::updateTerrainMaterial(Ogre::TerrainPSSMMaterialGenerator::SM2Profile *matProfile) { if (RoR::App::gfx_shadow_type.GetActive() == RoR::GfxShadowType::PSSM) { - Ogre::PSSMShadowCameraSetup* pssmSetup = static_cast(PSSM_Shadows.mPSSMSetup.get()); + Ogre::PSSMShadowCameraSetup *pssmSetup = static_cast(PSSM_Shadows.mPSSMSetup.get()); matProfile->setReceiveDynamicShadowsDepth(true); matProfile->setReceiveDynamicShadowsLowLod(false); matProfile->setReceiveDynamicShadowsEnabled(true); diff --git a/source/main/gfx/ShadowManager.h b/source/main/gfx/ShadowManager.h index b6a7142f0c..657791075a 100644 --- a/source/main/gfx/ShadowManager.h +++ b/source/main/gfx/ShadowManager.h @@ -24,29 +24,27 @@ #pragma once -#include -#include -#include - #include "Application.h" +#include "OgreTerrainPSSMMaterialGenerator.h" #include "RoRPrerequisites.h" -#include "OgreTerrainPSSMMaterialGenerator.h" +#include +#include +#include -//Store datas using structs +// Store datas using structs struct PSSM_Shadows_Data { Ogre::ShadowCameraSetupPtr mPSSMSetup; - bool mDepthShadows; - int ShadowsTextureNum; - int Quality; - float lambda; + bool mDepthShadows; + int ShadowsTextureNum; + int Quality; + float lambda; }; class ShadowManager : public ZeroedMemoryAllocator { -public: - + public: ShadowManager(); ~ShadowManager(); @@ -54,10 +52,9 @@ class ShadowManager : public ZeroedMemoryAllocator void updatePSSM(); - void updateTerrainMaterial(Ogre::TerrainPSSMMaterialGenerator::SM2Profile* matProfile); - -protected: + void updateTerrainMaterial(Ogre::TerrainPSSMMaterialGenerator::SM2Profile *matProfile); + protected: void processPSSM(); void setManagedMaterialSplitPoints(Ogre::PSSMShadowCameraSetup::SplitPointList splitPointList); diff --git a/source/main/gfx/Skidmark.cpp b/source/main/gfx/Skidmark.cpp index 3b528ecdbc..6b38e9eccb 100644 --- a/source/main/gfx/Skidmark.cpp +++ b/source/main/gfx/Skidmark.cpp @@ -46,17 +46,16 @@ void RoR::SkidmarkConfig::LoadDefaultSkidmarkDefs() return; } - Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton().openResource("skidmarks.cfg", group); - Ogre::String line = ""; - Ogre::String currentModel = ""; + Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton().openResource("skidmarks.cfg", group); + Ogre::String line = ""; + Ogre::String currentModel = ""; while (!ds->eof()) { line = RoR::Utils::SanitizeUtf8String(ds->getLine()); Ogre::StringUtil::trim(line); - if (line.empty() || line[0] == ';') - continue; + if (line.empty() || line[0] == ';') continue; Ogre::StringVector args = Ogre::StringUtil::split(line, ","); @@ -67,8 +66,7 @@ void RoR::SkidmarkConfig::LoadDefaultSkidmarkDefs() } // process the line if we got a model - if (!currentModel.empty()) - this->ProcessSkidmarkConfLine(args, currentModel); + if (!currentModel.empty()) this->ProcessSkidmarkConfLine(args, currentModel); } } catch (...) @@ -83,8 +81,7 @@ void RoR::SkidmarkConfig::LoadDefaultSkidmarkDefs() int RoR::SkidmarkConfig::ProcessSkidmarkConfLine(Ogre::StringVector args, Ogre::String modelName) { // we only accept 4 arguments - if (args.size() != 4) - return 1; + if (args.size() != 4) return 1; // parse the data SkidmarkDef cfg; @@ -94,19 +91,17 @@ int RoR::SkidmarkConfig::ProcessSkidmarkConfLine(Ogre::StringVector args, Ogre:: Ogre::StringUtil::trim(cfg.texture); cfg.slipFrom = Ogre::StringConverter::parseReal(args[2]); - cfg.slipTo = Ogre::StringConverter::parseReal(args[3]); + cfg.slipTo = Ogre::StringConverter::parseReal(args[3]); - if (!m_models.size() || m_models.find(modelName) == m_models.end()) - m_models[modelName] = std::vector(); + if (!m_models.size() || m_models.find(modelName) == m_models.end()) m_models[modelName] = std::vector(); m_models[modelName].push_back(cfg); return 0; } -int RoR::SkidmarkConfig::getTexture(Ogre::String model, Ogre::String ground, float slip, Ogre::String& texture) +int RoR::SkidmarkConfig::getTexture(Ogre::String model, Ogre::String ground, float slip, Ogre::String &texture) { - if (m_models.find(model) == m_models.end()) - return 1; + if (m_models.find(model) == m_models.end()) return 1; for (std::vector::iterator it = m_models[model].begin(); it != m_models[model].end(); it++) { if (it->ground == ground && it->slipFrom <= slip && it->slipTo > slip) @@ -119,23 +114,15 @@ int RoR::SkidmarkConfig::getTexture(Ogre::String model, Ogre::String ground, flo } // this is a hardcoded array which we use to map ground types to a certain texture with UV/ coords -Ogre::Vector2 RoR::Skidmark::m_tex_coords[4] = {Ogre::Vector2(0, 0), Ogre::Vector2(0, 1), Ogre::Vector2(1, 0), Ogre::Vector2(1, 1)}; - -RoR::Skidmark::Skidmark(RoR::SkidmarkConfig* config, wheel_t* m_wheel, - Ogre::SceneNode* snode, int m_length /* = 500 */, int m_bucket_count /* = 20 */) - : m_scene_node(snode) - , m_is_dirty(true) - , m_length(m_length) - , m_bucket_count(m_bucket_count) - , m_wheel(m_wheel) - , m_min_distance(0.25f) - , m_max_distance(std::max(0.5f, m_wheel->wh_width * 1.1f)) - , m_config(config) +Ogre::Vector2 RoR::Skidmark::m_tex_coords[4] = {Ogre::Vector2(0, 0), Ogre::Vector2(0, 1), Ogre::Vector2(1, 0), + Ogre::Vector2(1, 1)}; + +RoR::Skidmark::Skidmark(RoR::SkidmarkConfig *config, wheel_t *m_wheel, Ogre::SceneNode *snode, int m_length /* = 500 */, + int m_bucket_count /* = 20 */) + : m_scene_node(snode), m_is_dirty(true), m_length(m_length), m_bucket_count(m_bucket_count), m_wheel(m_wheel), + m_min_distance(0.25f), m_max_distance(std::max(0.5f, m_wheel->wh_width * 1.1f)), m_config(config) { - if (m_length % 2) - { - m_length--; - } + if (m_length % 2) { m_length--; } } RoR::Skidmark::~Skidmark() @@ -146,7 +133,7 @@ RoR::Skidmark::~Skidmark() void RoR::Skidmark::AddObject(Ogre::Vector3 start, Ogre::String texture) { SkidmarkSegment skid; - skid.pos = 0; + skid.pos = 0; skid.lastPointAv = start; skid.facecounter = 0; @@ -154,7 +141,7 @@ void RoR::Skidmark::AddObject(Ogre::Vector3 start, Ogre::String texture) char bname[256] = ""; sprintf(bname, "mat-skidmark-%d", m_instance_counter); skid.material = Ogre::MaterialManager::getSingleton().create(bname, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - Ogre::Pass* p = skid.material->getTechnique(0)->getPass(0); + Ogre::Pass *p = skid.material->getTechnique(0)->getPass(0); p->createTextureUnitState(texture); p->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); @@ -172,8 +159,8 @@ void RoR::Skidmark::AddObject(Ogre::Vector3 start, Ogre::String texture) skid.obj->begin(bname, Ogre::RenderOperation::OT_TRIANGLE_STRIP); for (int i = 0; i < m_length; i++) { - skid.points[i] = start; - skid.faceSizes[i] = 0; + skid.points[i] = start; + skid.faceSizes[i] = 0; skid.groundTexture[i] = "0.png"; skid.obj->position(start); skid.obj->textureCoord(0, 0); @@ -188,7 +175,7 @@ void RoR::Skidmark::AddObject(Ogre::Vector3 start, Ogre::String texture) void RoR::Skidmark::PopSegment() { - SkidmarkSegment& skid = m_objects.front(); + SkidmarkSegment &skid = m_objects.front(); skid.points.clear(); skid.faceSizes.clear(); Ogre::MaterialManager::getSingleton().remove(skid.material->getName()); @@ -199,16 +186,13 @@ void RoR::Skidmark::PopSegment() void RoR::Skidmark::LimitObjects() { - if ((int)m_objects.size() > m_bucket_count) - { - this->PopSegment(); - } + if ((int)m_objects.size() > m_bucket_count) { this->PopSegment(); } } -void RoR::Skidmark::SetPointInt(unsigned short index, const Ogre::Vector3& value, Ogre::Real fsize, Ogre::String texture) +void RoR::Skidmark::SetPointInt(unsigned short index, const Ogre::Vector3 &value, Ogre::Real fsize, Ogre::String texture) { - m_objects.back().points[index] = value; - m_objects.back().faceSizes[index] = fsize; + m_objects.back().points[index] = value; + m_objects.back().faceSizes[index] = fsize; m_objects.back().groundTexture[index] = texture; m_is_dirty = true; @@ -217,23 +201,18 @@ void RoR::Skidmark::SetPointInt(unsigned short index, const Ogre::Vector3& value void RoR::Skidmark::UpdatePoint(Ogre::Vector3 contact_point, int index, float slip, Ogre::String ground_model_name) { Ogre::Vector3 thisPoint = contact_point; - Ogre::Vector3 axis = m_wheel->wh_axis_node_1->RelPosition - m_wheel->wh_axis_node_0->RelPosition; - if (index % 2) - { - axis = -axis; - } + Ogre::Vector3 axis = m_wheel->wh_axis_node_1->RelPosition - m_wheel->wh_axis_node_0->RelPosition; + if (index % 2) { axis = -axis; } Ogre::Vector3 thisPointAV = thisPoint + axis * 0.5f; - Ogre::Real distance = 0; - Ogre::Real maxDist = m_max_distance; - Ogre::String texture = "none"; + Ogre::Real distance = 0; + Ogre::Real maxDist = m_max_distance; + Ogre::String texture = "none"; m_config->getTexture("default", ground_model_name, slip, texture); // dont add points with no texture - if (texture == "none") - return; + if (texture == "none") return; - if (m_wheel->wh_speed > 1) - maxDist *= m_wheel->wh_speed; + if (m_wheel->wh_speed > 1) maxDist *= m_wheel->wh_speed; if (!m_objects.size()) { @@ -249,7 +228,7 @@ void RoR::Skidmark::UpdatePoint(Ogre::Vector3 contact_point, int index, float sl // too near to update? if (distance < m_min_distance) { - //LOG("E: too near for update"); + // LOG("E: too near for update"); return; } @@ -311,12 +290,9 @@ void RoR::Skidmark::UpdatePoint(Ogre::Vector3 contact_point, int index, float sl m_objects.back().lastPointAv = thisPointAV; } -void RoR::Skidmark::AddPoint(const Ogre::Vector3& value, Ogre::Real fsize, Ogre::String texture) +void RoR::Skidmark::AddPoint(const Ogre::Vector3 &value, Ogre::Real fsize, Ogre::String texture) { - if (m_objects.back().pos >= m_length) - { - return; - } + if (m_objects.back().pos >= m_length) { return; } this->SetPointInt(m_objects.back().pos, value, fsize, texture); m_objects.back().pos++; } @@ -330,29 +306,24 @@ void RoR::Skidmark::reset() void RoR::Skidmark::update(Ogre::Vector3 contact_point, int index, float slip, Ogre::String ground_model_name) { this->UpdatePoint(contact_point, index, slip, ground_model_name); - if (!m_is_dirty) - return; - if (!m_objects.size()) - return; - SkidmarkSegment skid = m_objects.back(); - Ogre::Vector3 vaabMin = skid.points[0]; - Ogre::Vector3 vaabMax = skid.points[0]; + if (!m_is_dirty) return; + if (!m_objects.size()) return; + SkidmarkSegment skid = m_objects.back(); + Ogre::Vector3 vaabMin = skid.points[0]; + Ogre::Vector3 vaabMax = skid.points[0]; skid.obj->beginUpdate(0); - bool behindEnd = false; - Ogre::Vector3 lastValid = Ogre::Vector3::ZERO; - int to_counter = 0; - float tcox_counter = 0; + bool behindEnd = false; + Ogre::Vector3 lastValid = Ogre::Vector3::ZERO; + int to_counter = 0; + float tcox_counter = 0; - for (int i = 0; i < m_length; i++ , to_counter++) + for (int i = 0; i < m_length; i++, to_counter++) { - if (i >= skid.pos) - behindEnd = true; + if (i >= skid.pos) behindEnd = true; - if (to_counter > 3) - to_counter = 0; + if (to_counter > 3) to_counter = 0; - if (!behindEnd) - tcox_counter += skid.faceSizes[i] / m_min_distance; + if (!behindEnd) tcox_counter += skid.faceSizes[i] / m_min_distance; while (tcox_counter > 1) tcox_counter--; @@ -373,18 +344,12 @@ void RoR::Skidmark::update(Ogre::Vector3 contact_point, int index, float slip, O lastValid = skid.points[i]; } - if (skid.points[i].x < vaabMin.x) - vaabMin.x = skid.points[i].x; - if (skid.points[i].y < vaabMin.y) - vaabMin.y = skid.points[i].y; - if (skid.points[i].z < vaabMin.z) - vaabMin.z = skid.points[i].z; - if (skid.points[i].x > vaabMax.x) - vaabMax.x = skid.points[i].x; - if (skid.points[i].y > vaabMax.y) - vaabMax.y = skid.points[i].y; - if (skid.points[i].z > vaabMax.z) - vaabMax.z = skid.points[i].z; + if (skid.points[i].x < vaabMin.x) vaabMin.x = skid.points[i].x; + if (skid.points[i].y < vaabMin.y) vaabMin.y = skid.points[i].y; + if (skid.points[i].z < vaabMin.z) vaabMin.z = skid.points[i].z; + if (skid.points[i].x > vaabMax.x) vaabMax.x = skid.points[i].x; + if (skid.points[i].y > vaabMax.y) vaabMax.y = skid.points[i].y; + if (skid.points[i].z > vaabMax.z) vaabMax.z = skid.points[i].z; } skid.obj->end(); diff --git a/source/main/gfx/Skidmark.h b/source/main/gfx/Skidmark.h index 23b1ebd3e6..76b5df33ea 100644 --- a/source/main/gfx/Skidmark.h +++ b/source/main/gfx/Skidmark.h @@ -27,75 +27,72 @@ #include #include -namespace RoR { - -class SkidmarkConfig ///< Skidmark config file parser and data container +namespace RoR { -public: - - SkidmarkConfig(); - - int getTexture(Ogre::String model, Ogre::String ground, float slip, Ogre::String& texture); -private: - - struct SkidmarkDef + class SkidmarkConfig ///< Skidmark config file parser and data container { - Ogre::String ground; ///< Ground model name, see `struct ground_model_t` - Ogre::String texture; - float slipFrom; ///< Minimum slipping velocity - float slipTo; ///< Maximum slipping velocity - }; + public: + SkidmarkConfig(); - void LoadDefaultSkidmarkDefs(); - int ProcessSkidmarkConfLine(Ogre::StringVector args, Ogre::String model); + int getTexture(Ogre::String model, Ogre::String ground, float slip, Ogre::String &texture); - std::map> m_models; -}; + private: + struct SkidmarkDef + { + Ogre::String ground; ///< Ground model name, see `struct ground_model_t` + Ogre::String texture; + float slipFrom; ///< Minimum slipping velocity + float slipTo; ///< Maximum slipping velocity + }; -class Skidmark -{ -public: - - /// Constructor - see setOperationType() for description of argument. - Skidmark(SkidmarkConfig* config, wheel_t* m_wheel, Ogre::SceneNode* snode, int m_length = 500, int m_bucket_count = 20); - virtual ~Skidmark(); - - void reset(); - void update(Ogre::Vector3 contact_point, int index, float slip, Ogre::String ground_model_name); + void LoadDefaultSkidmarkDefs(); + int ProcessSkidmarkConfLine(Ogre::StringVector args, Ogre::String model); -private: + std::map> m_models; + }; - struct SkidmarkSegment ///< Also reffered to as 'bucket' + class Skidmark { - Ogre::ManualObject* obj; - Ogre::MaterialPtr material; - std::vector points; - std::vector faceSizes; - std::vector groundTexture; - Ogre::Vector3 lastPointAv; - int pos; - int facecounter; + public: + /// Constructor - see setOperationType() for description of argument. + Skidmark(SkidmarkConfig *config, wheel_t *m_wheel, Ogre::SceneNode *snode, int m_length = 500, int m_bucket_count = 20); + virtual ~Skidmark(); + + void reset(); + void update(Ogre::Vector3 contact_point, int index, float slip, Ogre::String ground_model_name); + + private: + struct SkidmarkSegment ///< Also reffered to as 'bucket' + { + Ogre::ManualObject * obj; + Ogre::MaterialPtr material; + std::vector points; + std::vector faceSizes; + std::vector groundTexture; + Ogre::Vector3 lastPointAv; + int pos; + int facecounter; + }; + + void PopSegment(); + void LimitObjects(); + void AddObject(Ogre::Vector3 start, Ogre::String texture); + void SetPointInt(unsigned short index, const Ogre::Vector3 &value, Ogre::Real fsize, Ogre::String texture); + void AddPoint(const Ogre::Vector3 &value, Ogre::Real fsize, Ogre::String texture); + void UpdatePoint(Ogre::Vector3 contact_point, int index, float slip, Ogre::String ground_model_name); + + static int m_instance_counter; + bool m_is_dirty; + std::queue m_objects; + float m_max_distance; + float m_min_distance; + static Ogre::Vector2 m_tex_coords[4]; + int m_bucket_count; + int m_length; + wheel_t * m_wheel; + Ogre::SceneNode * m_scene_node; + SkidmarkConfig * m_config; }; - void PopSegment(); - void LimitObjects(); - void AddObject(Ogre::Vector3 start, Ogre::String texture); - void SetPointInt(unsigned short index, const Ogre::Vector3& value, Ogre::Real fsize, Ogre::String texture); - void AddPoint(const Ogre::Vector3& value, Ogre::Real fsize, Ogre::String texture); - void UpdatePoint(Ogre::Vector3 contact_point, int index, float slip, Ogre::String ground_model_name); - - static int m_instance_counter; - bool m_is_dirty; - std::queue m_objects; - float m_max_distance; - float m_min_distance; - static Ogre::Vector2 m_tex_coords[4]; - int m_bucket_count; - int m_length; - wheel_t* m_wheel; - Ogre::SceneNode* m_scene_node; - SkidmarkConfig* m_config; -}; - } // namespace RoR diff --git a/source/main/gfx/SkyManager.cpp b/source/main/gfx/SkyManager.cpp index 71b657cc06..3d7881044f 100644 --- a/source/main/gfx/SkyManager.cpp +++ b/source/main/gfx/SkyManager.cpp @@ -21,25 +21,22 @@ #ifdef USE_CAELUM -#include "SkyManager.h" + #include "SkyManager.h" -#include "Application.h" -#include "OgreSubsystem.h" -#include "TerrainManager.h" -#include "TerrainGeometryManager.h" + #include "Application.h" + #include "OgreSubsystem.h" + #include "TerrainGeometryManager.h" + #include "TerrainManager.h" -#include + #include using namespace RoR; SkyManager::SkyManager() : m_caelum_system(nullptr), m_last_clock(0.0) { // Initialise CaelumSystem. - m_caelum_system = new Caelum::CaelumSystem( - RoR::App::GetOgreSubsystem()->GetOgreRoot(), - gEnv->sceneManager, - Caelum::CaelumSystem::CAELUM_COMPONENTS_DEFAULT - ); + m_caelum_system = new Caelum::CaelumSystem(RoR::App::GetOgreSubsystem()->GetOgreRoot(), gEnv->sceneManager, + Caelum::CaelumSystem::CAELUM_COMPONENTS_DEFAULT); m_caelum_system->attachViewport(RoR::App::GetOgreSubsystem()->GetViewport()); @@ -55,26 +52,21 @@ SkyManager::~SkyManager() m_caelum_system = nullptr; } -void SkyManager::NotifySkyCameraChanged(Ogre::Camera* cam) +void SkyManager::NotifySkyCameraChanged(Ogre::Camera *cam) { - if (m_caelum_system) - m_caelum_system->notifyCameraChanged(cam); + if (m_caelum_system) m_caelum_system->notifyCameraChanged(cam); } void SkyManager::DetectSkyUpdate() { - if (!m_caelum_system || !App::GetSimTerrain()) - { - return; - } + if (!m_caelum_system || !App::GetSimTerrain()) { return; } Caelum::LongReal c = m_caelum_system->getUniversalClock()->getJulianDay(); if (c - m_last_clock > 0.001f) { - TerrainGeometryManager* gm = App::GetSimTerrain()->getGeometryManager(); - if (gm) - gm->updateLightMap(); + TerrainGeometryManager *gm = App::GetSimTerrain()->getGeometryManager(); + if (gm) gm->updateLightMap(); } m_last_clock = c; @@ -88,7 +80,7 @@ void SkyManager::LoadCaelumScript(std::string script, int fogStart, int fogEnd) Caelum::CaelumPlugin::getSingleton().loadCaelumSystemFromScript(m_caelum_system, script); // overwrite some settings -#ifdef CAELUM_VERSION_SEC + #ifdef CAELUM_VERSION_SEC // important: overwrite fog settings if not using infinite farclip if (fogStart != -1 && fogEnd != -1 && fogStart < fogEnd) { @@ -101,10 +93,7 @@ void SkyManager::LoadCaelumScript(std::string script, int fogStart, int fogEnd) } else if (gEnv->mainCamera->getFarClipDistance() > 0) { - if (fogStart != -1 && fogEnd != -1) - { - LOG("CaelumFogStart must be smaller then CaelumFogEnd. Ignoring boundaries."); - } + if (fogStart != -1 && fogEnd != -1) { LOG("CaelumFogStart must be smaller then CaelumFogEnd. Ignoring boundaries."); } else if (fogStart != -1 || fogEnd != -1) { LOG("You always need to define both boundaries (CaelumFogStart AND CaelumFogEnd). Ignoring boundaries."); @@ -120,14 +109,14 @@ void SkyManager::LoadCaelumScript(std::string script, int fogStart, int fogEnd) // no fog in infinite farclip m_caelum_system->setManageSceneFog(Ogre::FOG_NONE); } -#else -#error please use a recent Caelum version, see http://www.rigsofrods.org/wiki/pages/Compiling_3rd_party_libraries#Caelum -#endif // CAELUM_VERSION - // now optimize the moon a bit + #else + #error please use a recent Caelum version, see http://www.rigsofrods.org/wiki/pages/Compiling_3rd_party_libraries#Caelum + #endif // CAELUM_VERSION + // now optimize the moon a bit if (m_caelum_system->getMoon()) { m_caelum_system->getMoon()->setAutoDisable(true); - //m_caelum_system->getMoon()->setAutoDisableThreshold(1); + // m_caelum_system->getMoon()->setAutoDisableThreshold(1); m_caelum_system->getMoon()->setForceDisable(true); m_caelum_system->getMoon()->getMainLight()->setCastShadows(false); } @@ -138,7 +127,7 @@ void SkyManager::LoadCaelumScript(std::string script, int fogStart, int fogEnd) // enforcing update, so shadows are set correctly before creating the terrain m_caelum_system->updateSubcomponents(0.1); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { RoR::LogFormat("[RoR] Exception while loading sky script: %s", e.getFullDescription().c_str()); } @@ -151,12 +140,9 @@ void SkyManager::SetSkyTimeFactor(float factor) m_caelum_system->getUniversalClock()->setTimeScale(factor); } -Ogre::Light* SkyManager::GetSkyMainLight() +Ogre::Light *SkyManager::GetSkyMainLight() { - if (m_caelum_system && m_caelum_system->getSun()) - { - return m_caelum_system->getSun()->getMainLight(); - } + if (m_caelum_system && m_caelum_system->getSun()) { return m_caelum_system->getSun()->getMainLight(); } return nullptr; } @@ -167,16 +153,16 @@ float SkyManager::GetSkyTimeFactor() std::string SkyManager::GetPrettyTime() { - int ignore; - int hour; - int minute; + int ignore; + int hour; + int minute; Caelum::LongReal second; - Caelum::Astronomy::getGregorianDateTimeFromJulianDay(m_caelum_system->getJulianDay() - , ignore, ignore, ignore, hour, minute, second); + Caelum::Astronomy::getGregorianDateTimeFromJulianDay(m_caelum_system->getJulianDay(), ignore, ignore, ignore, hour, minute, + second); char buf[100]; snprintf(buf, 100, "%02d:%02d:%02d", hour, minute, static_cast(second)); return buf; } -#endif //USE_CAELUM +#endif // USE_CAELUM diff --git a/source/main/gfx/SkyManager.h b/source/main/gfx/SkyManager.h index 52e97dd5f3..e3ed8966cb 100644 --- a/source/main/gfx/SkyManager.h +++ b/source/main/gfx/SkyManager.h @@ -21,34 +21,41 @@ #ifdef USE_CAELUM -#pragma once + #pragma once -#include "RoRPrerequisites.h" - -#include "CaelumPrerequisites.h" + #include "CaelumPrerequisites.h" + #include "RoRPrerequisites.h" class SkyManager : public ZeroedMemoryAllocator { -public: - + public: SkyManager(); ~SkyManager(); - void LoadCaelumScript(Ogre::String script, int fogStart = -1, int fogEnd = -1); - void SetSkyTimeFactor(Ogre::Real f); //!< change the time scale - Ogre::Light* GetSkyMainLight(); - float GetSkyTimeFactor(); //!< gets the current time scale - std::string GetPrettyTime(); //!< prints the current time of the simulation in the format of HH:MM:SS - double GetTime() { return m_caelum_system->getJulianDay(); }; - void SetTime(double time) { m_caelum_system->setJulianDay(time); }; - bool UpdateSky(float dt); - void NotifySkyCameraChanged(Ogre::Camera* cam); - void DetectSkyUpdate(); - Caelum::CaelumSystem* GetCaelumSys() { return m_caelum_system; } - -private: + void LoadCaelumScript(Ogre::String script, int fogStart = -1, int fogEnd = -1); + void SetSkyTimeFactor(Ogre::Real f); //!< change the time scale + Ogre::Light *GetSkyMainLight(); + float GetSkyTimeFactor(); //!< gets the current time scale + std::string GetPrettyTime(); //!< prints the current time of the simulation in the format of HH:MM:SS + double GetTime() + { + return m_caelum_system->getJulianDay(); + }; + void SetTime(double time) + { + m_caelum_system->setJulianDay(time); + }; + bool UpdateSky(float dt); + void NotifySkyCameraChanged(Ogre::Camera *cam); + void DetectSkyUpdate(); + Caelum::CaelumSystem *GetCaelumSys() + { + return m_caelum_system; + } + + private: Caelum::LongReal m_last_clock; - Caelum::CaelumSystem* m_caelum_system; + Caelum::CaelumSystem *m_caelum_system; }; #endif // USE_CAELUM diff --git a/source/main/gfx/SkyXManager.cpp b/source/main/gfx/SkyXManager.cpp index 1ae06df546..9c67caa61a 100644 --- a/source/main/gfx/SkyXManager.cpp +++ b/source/main/gfx/SkyXManager.cpp @@ -1,22 +1,22 @@ /* - This source file is part of Rigs of Rods - Copyright 2005-2012 Pierre-Michel Ricordel - Copyright 2007-2012 Thomas Fischer - Copyright 2013-2014 Petr Ohlidal + This source file is part of Rigs of Rods + Copyright 2005-2012 Pierre-Michel Ricordel + Copyright 2007-2012 Thomas Fischer + Copyright 2013-2014 Petr Ohlidal - For more information, see http://www.rigsofrods.com/ + For more information, see http://www.rigsofrods.com/ - Rigs of Rods is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License version 3, as - published by the Free Software Foundation. + Rigs of Rods is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License version 3, as + published by the Free Software Foundation. - Rigs of Rods is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + Rigs of Rods is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Rigs of Rods. If not, see . + You should have received a copy of the GNU General Public License + along with Rigs of Rods. If not, see . */ #include "SkyXManager.h" @@ -24,28 +24,28 @@ #include "Application.h" #include "HydraxWater.h" #include "OgreSubsystem.h" -#include "TerrainManager.h" #include "TerrainGeometryManager.h" +#include "TerrainManager.h" using namespace Ogre; using namespace RoR; SkyXManager::SkyXManager(Ogre::String configFile) { - InitLight(); + InitLight(); - //Ogre::ResourceGroupManager::getSingleton().addResourceLocation("..\\resource\\SkyX\\","FileSystem", "SkyX",true); //Temp + // Ogre::ResourceGroupManager::getSingleton().addResourceLocation("..\\resource\\SkyX\\","FileSystem", "SkyX",true); //Temp - mBasicController = new SkyX::BasicController(); - mSkyX = new SkyX::SkyX(gEnv->sceneManager, mBasicController); + mBasicController = new SkyX::BasicController(); + mSkyX = new SkyX::SkyX(gEnv->sceneManager, mBasicController); - mCfgFileManager = new SkyX::CfgFileManager(mSkyX, mBasicController, gEnv->mainCamera); - mCfgFileManager->load(configFile); + mCfgFileManager = new SkyX::CfgFileManager(mSkyX, mBasicController, gEnv->mainCamera); + mCfgFileManager->load(configFile); - mSkyX->create(); + mSkyX->create(); - RoR::App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(mSkyX); - RoR::App::GetOgreSubsystem()->GetRenderWindow()->addListener(mSkyX); + RoR::App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(mSkyX); + RoR::App::GetOgreSubsystem()->GetRenderWindow()->addListener(mSkyX); } SkyXManager::~SkyXManager() @@ -61,132 +61,127 @@ SkyXManager::~SkyXManager() Vector3 SkyXManager::getMainLightDirection() { - if (mBasicController != nullptr) - return mBasicController->getSunDirection(); - return Ogre::Vector3(0.0,0.0,0.0); + if (mBasicController != nullptr) return mBasicController->getSunDirection(); + return Ogre::Vector3(0.0, 0.0, 0.0); } Light *SkyXManager::getMainLight() { - return mLight1; + return mLight1; } bool SkyXManager::update(float dt) { - UpdateSkyLight(); - mSkyX->update(dt); - return true; + UpdateSkyLight(); + mSkyX->update(dt); + return true; } - bool SkyXManager::UpdateSkyLight() { - Ogre::Vector3 lightDir = -getMainLightDirection(); - Ogre::Vector3 sunPos = gEnv->mainCamera->getDerivedPosition() - lightDir*mSkyX->getMeshManager()->getSkydomeRadius(gEnv->mainCamera); + Ogre::Vector3 lightDir = -getMainLightDirection(); + Ogre::Vector3 sunPos = + gEnv->mainCamera->getDerivedPosition() - lightDir * mSkyX->getMeshManager()->getSkydomeRadius(gEnv->mainCamera); - // Calculate current color gradients point - float point = (-lightDir.y + 1.0f) / 2.0f; + // Calculate current color gradients point + float point = (-lightDir.y + 1.0f) / 2.0f; - if (App::GetSimTerrain ()->getHydraxManager ()) + if (App::GetSimTerrain()->getHydraxManager()) { - App::GetSimTerrain ()->getHydraxManager ()->GetHydrax ()->setWaterColor (mWaterGradient.getColor (point)); - App::GetSimTerrain ()->getHydraxManager ()->GetHydrax ()->setSunPosition (sunPos*0.1); + App::GetSimTerrain()->getHydraxManager()->GetHydrax()->setWaterColor(mWaterGradient.getColor(point)); + App::GetSimTerrain()->getHydraxManager()->GetHydrax()->setSunPosition(sunPos * 0.1); } - - mLight0 = gEnv->sceneManager->getLight("Light0"); - mLight1 = gEnv->sceneManager->getLight("Light1"); + mLight0 = gEnv->sceneManager->getLight("Light0"); + mLight1 = gEnv->sceneManager->getLight("Light1"); + + mLight0->setPosition(sunPos * 0.02); + mLight1->setDirection(lightDir); + if (App::GetSimTerrain()->getWater()) { App::GetSimTerrain()->getWater()->WaterSetSunPosition(sunPos * 0.1); } - mLight0->setPosition(sunPos*0.02); - mLight1->setDirection(lightDir); - if (App::GetSimTerrain()->getWater()) + // setFadeColour was removed with https://github.com/RigsOfRods/rigs-of-rods/pull/1459 + /* Ogre::Vector3 sunCol = mSunGradient.getColor(point); + mLight0->setSpecularColour(sunCol.x, sunCol.y, sunCol.z); + if (App::GetSimTerrain()->getWater()) App::GetSimTerrain()->getWater()->setFadeColour(Ogre::ColourValue(sunCol.x, + sunCol.y, sunCol.z)); + */ + Ogre::Vector3 ambientCol = mAmbientGradient.getColor(point); + mLight1->setDiffuseColour(ambientCol.x, ambientCol.y, ambientCol.z); + mLight1->setPosition(100, 100, 100); + + if (mBasicController->getTime().x > 12) { - App::GetSimTerrain()->getWater()->WaterSetSunPosition(sunPos*0.1); + if (mBasicController->getTime().x > mBasicController->getTime().z) + mLight0->setVisible(false); + else + mLight0->setVisible(true); } - - //setFadeColour was removed with https://github.com/RigsOfRods/rigs-of-rods/pull/1459 -/* Ogre::Vector3 sunCol = mSunGradient.getColor(point); - mLight0->setSpecularColour(sunCol.x, sunCol.y, sunCol.z); - if (App::GetSimTerrain()->getWater()) App::GetSimTerrain()->getWater()->setFadeColour(Ogre::ColourValue(sunCol.x, sunCol.y, sunCol.z)); - */ - Ogre::Vector3 ambientCol = mAmbientGradient.getColor(point); - mLight1->setDiffuseColour(ambientCol.x, ambientCol.y, ambientCol.z); - mLight1->setPosition(100,100,100); - - if (mBasicController->getTime().x > 12) - { - if (mBasicController->getTime().x > mBasicController->getTime().z) - mLight0->setVisible(false); - else - mLight0->setVisible(true); - } else { - if (mBasicController->getTime ().x < mBasicController->getTime ().z) - mLight0->setVisible (false); + if (mBasicController->getTime().x < mBasicController->getTime().z) + mLight0->setVisible(false); else - mLight0->setVisible (true); + mLight0->setVisible(true); } - - if (round (mBasicController->getTime ().x) != mLastHour) + + if (round(mBasicController->getTime().x) != mLastHour) { - TerrainGeometryManager* gm = App::GetSimTerrain ()->getGeometryManager (); - if (gm) - gm->updateLightMap (); + TerrainGeometryManager *gm = App::GetSimTerrain()->getGeometryManager(); + if (gm) gm->updateLightMap(); - mLastHour = round (mBasicController->getTime ().x); + mLastHour = round(mBasicController->getTime().x); } - return true; + return true; } bool SkyXManager::InitLight() { - // Water - mWaterGradient = SkyX::ColorGradient(); - mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209,0.535822,0.779105)*0.4, 1)); - mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209,0.535822,0.729105)*0.3, 0.8)); - mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209,0.535822,0.679105)*0.25, 0.6)); - mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209,0.535822,0.679105)*0.2, 0.5)); - mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209,0.535822,0.679105)*0.1, 0.45)); - mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209,0.535822,0.679105)*0.025, 0)); - // Sun - mSunGradient = SkyX::ColorGradient(); - mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.8,0.75,0.55)*1.5, 1.0f)); - mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.8,0.75,0.55)*1.4, 0.75f)); - mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.8,0.75,0.55)*1.3, 0.5625f)); - mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*1.5, 0.5f)); - mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.5,0.5)*0.25, 0.45f)); - mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.5,0.5)*0.01, 0.0f)); - // Ambient - mAmbientGradient = SkyX::ColorGradient(); - mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*1, 1.0f)); - mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*1, 0.6f)); - mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.6, 0.5f)); - mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.3, 0.45f)); - mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.1, 0.35f)); - mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.05, 0.0f)); - - gEnv->sceneManager->setAmbientLight(ColourValue(0.35,0.35,0.35)); //Not needed because terrn2 has ambientlight settings - - // Light - mLight0 = gEnv->sceneManager->createLight("Light0"); - mLight0->setDiffuseColour(1, 1, 1); - mLight0->setCastShadows(false); - - mLight1 = gEnv->sceneManager->createLight("Light1"); - mLight1->setType(Ogre::Light::LT_DIRECTIONAL); - - return true; + // Water + mWaterGradient = SkyX::ColorGradient(); + mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209, 0.535822, 0.779105) * 0.4, 1)); + mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209, 0.535822, 0.729105) * 0.3, 0.8)); + mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209, 0.535822, 0.679105) * 0.25, 0.6)); + mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209, 0.535822, 0.679105) * 0.2, 0.5)); + mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209, 0.535822, 0.679105) * 0.1, 0.45)); + mWaterGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.058209, 0.535822, 0.679105) * 0.025, 0)); + // Sun + mSunGradient = SkyX::ColorGradient(); + mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.8, 0.75, 0.55) * 1.5, 1.0f)); + mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.8, 0.75, 0.55) * 1.4, 0.75f)); + mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.8, 0.75, 0.55) * 1.3, 0.5625f)); + mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 1.5, 0.5f)); + mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.5, 0.5) * 0.25, 0.45f)); + mSunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.5, 0.5) * 0.01, 0.0f)); + // Ambient + mAmbientGradient = SkyX::ColorGradient(); + mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 1, 1.0f)); + mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 1, 0.6f)); + mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.6, 0.5f)); + mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.3, 0.45f)); + mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.1, 0.35f)); + mAmbientGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.05, 0.0f)); + + gEnv->sceneManager->setAmbientLight(ColourValue(0.35, 0.35, 0.35)); // Not needed because terrn2 has ambientlight settings + + // Light + mLight0 = gEnv->sceneManager->createLight("Light0"); + mLight0->setDiffuseColour(1, 1, 1); + mLight0->setCastShadows(false); + + mLight1 = gEnv->sceneManager->createLight("Light1"); + mLight1->setType(Ogre::Light::LT_DIRECTIONAL); + + return true; } size_t SkyXManager::getMemoryUsage() { - //TODO - return 0; + // TODO + return 0; } void SkyXManager::freeResources() { - //TODO + // TODO } diff --git a/source/main/gfx/SkyXManager.h b/source/main/gfx/SkyXManager.h index 00c225b1c6..f922853069 100644 --- a/source/main/gfx/SkyXManager.h +++ b/source/main/gfx/SkyXManager.h @@ -21,43 +21,43 @@ along with Rigs of Rods. If not, see . #pragma once #include "RoRPrerequisites.h" - #include "gfx/skyx/SkyX.h" class SkyXManager : public ZeroedMemoryAllocator { -public: - SkyXManager(Ogre::String configFile); - ~SkyXManager(); + public: + SkyXManager(Ogre::String configFile); + ~SkyXManager(); + + Ogre::Vector3 getMainLightDirection(); - Ogre::Vector3 getMainLightDirection(); + Ogre::Light *getMainLight(); - Ogre::Light* getMainLight(); + bool update(float dt); - bool update( float dt ); + bool InitLight(); - bool InitLight(); + size_t getMemoryUsage(); - size_t getMemoryUsage(); + void freeResources(); - void freeResources(); + bool UpdateSkyLight(); - bool UpdateSkyLight(); + SkyX::SkyX *GetSkyX() + { + return mSkyX; + } - SkyX::SkyX* GetSkyX() { return mSkyX; } + protected: + Ogre::Light *mLight0; + Ogre::Light *mLight1; -protected: - Ogre::Light *mLight0; - Ogre::Light *mLight1; - - SkyX::SkyX* mSkyX; - SkyX::BasicController* mBasicController; + SkyX::SkyX * mSkyX; + SkyX::BasicController *mBasicController; - SkyX::ColorGradient mWaterGradient, - mSunGradient, - mAmbientGradient; + SkyX::ColorGradient mWaterGradient, mSunGradient, mAmbientGradient; - SkyX::CfgFileManager* mCfgFileManager; + SkyX::CfgFileManager *mCfgFileManager; int mLastHour = 0; }; diff --git a/source/main/gfx/Water.cpp b/source/main/gfx/Water.cpp index d7122e6a60..7659d98631 100644 --- a/source/main/gfx/Water.cpp +++ b/source/main/gfx/Water.cpp @@ -34,53 +34,39 @@ using namespace RoR; static const int WAVEREZ = 100; -Water::Water() : - m_max_ampl(0), - m_water_visible(true), - m_waterplane_mesh_scale(1.0f), - m_refract_rtt_viewport(0), - m_reflect_rtt_viewport(0), - m_render_cam(gEnv->mainCamera), - m_bottom_height(0), - m_water_height(0), - m_waterplane_node(0), - m_waterplane_force_update_pos(false), - m_frame_counter(0), - m_refract_rtt_target(0), - m_reflect_rtt_target(0), - m_reflect_cam(0), - m_refract_cam(0) +Water::Water() + : m_max_ampl(0), m_water_visible(true), m_waterplane_mesh_scale(1.0f), m_refract_rtt_viewport(0), m_reflect_rtt_viewport(0), + m_render_cam(gEnv->mainCamera), m_bottom_height(0), m_water_height(0), m_waterplane_node(0), + m_waterplane_force_update_pos(false), m_frame_counter(0), m_refract_rtt_target(0), m_reflect_rtt_target(0), + m_reflect_cam(0), m_refract_cam(0) { - //Ugh.. Why so ugly and hard to read - m_map_size = App::GetSimTerrain()->getMaxTerrainSize(); + // Ugh.. Why so ugly and hard to read + m_map_size = App::GetSimTerrain()->getMaxTerrainSize(); m_reflect_listener.scene_mgr = gEnv->sceneManager; m_refract_listener.scene_mgr = gEnv->sceneManager; - if (m_map_size.x < 1500 && m_map_size.z < 1500) - m_waterplane_mesh_scale = 1.5f; + if (m_map_size.x < 1500 && m_map_size.z < 1500) m_waterplane_mesh_scale = 1.5f; - char line[1024] = {}; - std::string filepath = PathCombine(RoR::App::sys_config_dir.GetActive(), "wavefield.cfg"); - FILE* fd = fopen(filepath.c_str(), "r"); + char line[1024] = {}; + std::string filepath = PathCombine(RoR::App::sys_config_dir.GetActive(), "wavefield.cfg"); + FILE * fd = fopen(filepath.c_str(), "r"); if (fd) { while (!feof(fd)) { int res = fscanf(fd, " %[^\n\r]", line); - if (line[0] == ';') - continue; + if (line[0] == ';') continue; float wl, amp, mx, dir; res = sscanf(line, "%f, %f, %f, %f", &wl, &, &mx, &dir); - if (res < 4) - continue; + if (res < 4) continue; WaveTrain wavetrain; wavetrain.wavelength = wl; - wavetrain.amplitude = amp; - wavetrain.maxheight = mx; - wavetrain.direction = dir / 57.0; - wavetrain.dir_sin = sin(wavetrain.direction); - wavetrain.dir_cos = cos(wavetrain.direction); + wavetrain.amplitude = amp; + wavetrain.maxheight = mx; + wavetrain.direction = dir / 57.0; + wavetrain.dir_sin = sin(wavetrain.direction); + wavetrain.dir_cos = cos(wavetrain.direction); m_wavetrain_defs.push_back(wavetrain); } @@ -129,7 +115,7 @@ Water::~Water() } m_water_height = m_bottom_height = 0; - m_render_cam = nullptr; + m_render_cam = nullptr; if (m_refract_rtt_target) { @@ -177,45 +163,46 @@ Water::~Water() void Water::PrepareWater() { m_water_plane.normal = Vector3::UNIT_Y; - m_water_plane.d = 0; + m_water_plane.d = 0; - const auto type = App::gfx_water_mode.GetActive(); + const auto type = App::gfx_water_mode.GetActive(); const bool full_gfx = type == GfxWaterMode::FULL_HQ || type == GfxWaterMode::FULL_FAST; if (full_gfx || type == GfxWaterMode::REFLECT) { // Check prerequisites first - const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); + const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities(); if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM))) { - OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Your card does not support vertex and fragment programs, so cannot " - "run Water effects. Sorry!", - "Water effects"); + OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, + "Your card does not support vertex and fragment programs, so cannot " + "run Water effects. Sorry!", + "Water effects"); } else { if (!GpuProgramManager::getSingleton().isSyntaxSupported("arbfp1") && !GpuProgramManager::getSingleton().isSyntaxSupported("ps_2_0") && - !GpuProgramManager::getSingleton().isSyntaxSupported("ps_1_4") - ) + !GpuProgramManager::getSingleton().isSyntaxSupported("ps_1_4")) { - OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Your card does not support advanced fragment programs, " - "so cannot run Water effects. Sorry!", - "Water effects"); + OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, + "Your card does not support advanced fragment programs, " + "so cannot run Water effects. Sorry!", + "Water effects"); } } // Ok // Define a floor plane mesh m_reflect_plane.normal = Vector3::UNIT_Y; - m_reflect_plane.d = - 0.15; + m_reflect_plane.d = -0.15; m_refract_plane.normal = -Vector3::UNIT_Y; - m_refract_plane.d = 0.15; + m_refract_plane.d = 0.15; if (full_gfx) { - TexturePtr m_refract_rtt_targetPtr = Ogre::TextureManager::getSingleton ().getByName ("Refraction"); - m_refract_rtt_texture = m_refract_rtt_targetPtr; - m_refract_rtt_target = m_refract_rtt_targetPtr->getBuffer()->getRenderTarget(); + TexturePtr m_refract_rtt_targetPtr = Ogre::TextureManager::getSingleton().getByName("Refraction"); + m_refract_rtt_texture = m_refract_rtt_targetPtr; + m_refract_rtt_target = m_refract_rtt_targetPtr->getBuffer()->getRenderTarget(); { m_refract_cam = gEnv->sceneManager->createCamera("RefractCam"); m_refract_cam->setNearClipDistance(m_render_cam->getNearClipDistance()); @@ -238,7 +225,7 @@ void Water::PrepareWater() m_refract_rtt_target->addListener(&m_refract_listener); - //optimisation + // optimisation m_refract_rtt_target->setAutoUpdated(false); // Also clip @@ -246,9 +233,9 @@ void Water::PrepareWater() } } - TexturePtr m_reflect_rtt_targetPtr = Ogre::TextureManager::getSingleton ().getByName ("Reflection"); - m_reflect_rtt_texture = m_reflect_rtt_targetPtr; - m_reflect_rtt_target = m_reflect_rtt_targetPtr->getBuffer()->getRenderTarget(); + TexturePtr m_reflect_rtt_targetPtr = Ogre::TextureManager::getSingleton().getByName("Reflection"); + m_reflect_rtt_texture = m_reflect_rtt_targetPtr; + m_reflect_rtt_target = m_reflect_rtt_targetPtr->getBuffer()->getRenderTarget(); { m_reflect_cam = gEnv->sceneManager->createCamera("ReflectCam"); m_reflect_cam->setNearClipDistance(m_render_cam->getNearClipDistance()); @@ -280,7 +267,7 @@ void Water::PrepareWater() m_reflect_rtt_target->addListener(&m_reflect_listener); - //optimisation + // optimisation m_reflect_rtt_target->setAutoUpdated(false); // set up linked reflection @@ -289,10 +276,10 @@ void Water::PrepareWater() m_reflect_cam->enableCustomNearClipPlane(m_reflect_plane); } - m_waterplane_mesh = MeshManager::getSingleton().createPlane("ReflectPlane", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - m_water_plane, - m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, WAVEREZ, WAVEREZ, true, 1, 50, 50, Vector3::UNIT_Z, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + m_waterplane_mesh = MeshManager::getSingleton().createPlane( + "ReflectPlane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, m_water_plane, + m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, WAVEREZ, WAVEREZ, true, 1, 50, 50, + Vector3::UNIT_Z, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); m_waterplane_entity = gEnv->sceneManager->createEntity("plane", "ReflectPlane"); if (full_gfx) @@ -302,10 +289,10 @@ void Water::PrepareWater() } else { - m_waterplane_mesh = MeshManager::getSingleton().createPlane("WaterPlane", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - m_water_plane, - m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, WAVEREZ, WAVEREZ, true, 1, 50, 50, Vector3::UNIT_Z, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + m_waterplane_mesh = MeshManager::getSingleton().createPlane( + "WaterPlane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, m_water_plane, + m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, WAVEREZ, WAVEREZ, true, 1, 50, 50, + Vector3::UNIT_Z, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); m_waterplane_entity = gEnv->sceneManager->createEntity("plane", "WaterPlane"); m_waterplane_entity->setMaterialName("tracks/basicwater"); } @@ -313,33 +300,34 @@ void Water::PrepareWater() m_waterplane_entity->setCastShadows(false); m_reflect_listener.waterplane_entity = m_waterplane_entity; m_refract_listener.waterplane_entity = m_waterplane_entity; - //position + // position m_waterplane_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode("WaterPlane"); m_waterplane_node->attachObject(m_waterplane_entity); - m_waterplane_node->setPosition(Vector3((m_map_size.x * m_waterplane_mesh_scale) / 2, m_water_height, (m_map_size.z * m_waterplane_mesh_scale) / 2)); + m_waterplane_node->setPosition( + Vector3((m_map_size.x * m_waterplane_mesh_scale) / 2, m_water_height, (m_map_size.z * m_waterplane_mesh_scale) / 2)); - //bottom + // bottom m_bottom_plane.normal = Vector3::UNIT_Y; - m_bottom_plane.d = -m_bottom_height; //30m below waterline - MeshManager::getSingleton().createPlane("BottomPlane", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - m_bottom_plane, - m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, 1, 1, true, 1, 1, 1, Vector3::UNIT_Z); - Entity* pE = gEnv->sceneManager->createEntity("bplane", "BottomPlane"); + m_bottom_plane.d = -m_bottom_height; // 30m below waterline + MeshManager::getSingleton().createPlane("BottomPlane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, m_bottom_plane, + m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, 1, 1, + true, 1, 1, 1, Vector3::UNIT_Z); + Entity *pE = gEnv->sceneManager->createEntity("bplane", "BottomPlane"); pE->setMaterialName("tracks/seabottom"); pE->setCastShadows(false); - //position + // position m_bottomplane_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode("BottomWaterPlane"); m_bottomplane_node->attachObject(pE); - m_bottomplane_node->setPosition(Vector3((m_map_size.x * m_waterplane_mesh_scale) / 2, 0, (m_map_size.z * m_waterplane_mesh_scale) / 2)); + m_bottomplane_node->setPosition( + Vector3((m_map_size.x * m_waterplane_mesh_scale) / 2, 0, (m_map_size.z * m_waterplane_mesh_scale) / 2)); - //setup for waves + // setup for waves m_waterplane_vert_buf = m_waterplane_mesh->sharedVertexData->vertexBufferBinding->getBuffer(0); if (m_waterplane_vert_buf->getSizeInBytes() == (WAVEREZ + 1) * (WAVEREZ + 1) * 32) { - m_waterplane_vert_buf_local = (float*)malloc(m_waterplane_vert_buf->getSizeInBytes()); + m_waterplane_vert_buf_local = (float *)malloc(m_waterplane_vert_buf->getSizeInBytes()); m_waterplane_vert_buf->readData(0, m_waterplane_vert_buf->getSizeInBytes(), m_waterplane_vert_buf_local); } else @@ -349,27 +337,21 @@ void Water::PrepareWater() void Water::SetWaterVisible(bool value) { m_water_visible = value; - if (m_waterplane_entity) - m_waterplane_entity->setVisible(value); - if (m_waterplane_node) - m_waterplane_node->setVisible(value); - if (m_bottomplane_node) - m_bottomplane_node->setVisible(value); + if (m_waterplane_entity) m_waterplane_entity->setVisible(value); + if (m_waterplane_node) m_waterplane_node->setVisible(value); + if (m_bottomplane_node) m_bottomplane_node->setVisible(value); } void Water::SetReflectionPlaneHeight(float centerheight) { const auto type = App::gfx_water_mode.GetActive(); if (type == GfxWaterMode::FULL_HQ || type == GfxWaterMode::FULL_FAST || type == GfxWaterMode::REFLECT) - { - this->UpdateReflectionPlane(centerheight); - } + { this->UpdateReflectionPlane(centerheight); } } void Water::ShowWave(Vector3 refpos) { - if (!m_waterplane_vert_buf_local) - return; + if (!m_waterplane_vert_buf_local) return; float xScaled = m_map_size.x * m_waterplane_mesh_scale; float zScaled = m_map_size.z * m_waterplane_mesh_scale; @@ -378,21 +360,27 @@ void Water::ShowWave(Vector3 refpos) { for (int px = 0; px < WAVEREZ + 1; px++) { - m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 1] = CalcWavesHeight(refpos + Vector3(xScaled * 0.5 - (float)px * xScaled / WAVEREZ, 0, (float)pz * zScaled / WAVEREZ - zScaled * 0.5)) - m_water_height; + m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 1] = + CalcWavesHeight(refpos + Vector3(xScaled * 0.5 - (float)px * xScaled / WAVEREZ, 0, + (float)pz * zScaled / WAVEREZ - zScaled * 0.5)) - + m_water_height; } } - //normals + // normals for (int pz = 0; pz < WAVEREZ + 1; pz++) { for (int px = 0; px < WAVEREZ + 1; px++) { - int left = std::max(0, px - 1); + int left = std::max(0, px - 1); int right = std::min(px + 1, WAVEREZ); - int up = std::max(0, pz - 1); - int down = std::min(pz + 1, WAVEREZ); + int up = std::max(0, pz - 1); + int down = std::min(pz + 1, WAVEREZ); - Vector3 normal = (Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + left) * 8)) - Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + right) * 8))).crossProduct(Vector3(m_waterplane_vert_buf_local + ((up * (WAVEREZ + 1) + px) * 8)) - Vector3(m_waterplane_vert_buf_local + ((down * (WAVEREZ + 1) + px) * 8))); + Vector3 normal = (Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + left) * 8)) - + Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + right) * 8))) + .crossProduct(Vector3(m_waterplane_vert_buf_local + ((up * (WAVEREZ + 1) + px) * 8)) - + Vector3(m_waterplane_vert_buf_local + ((down * (WAVEREZ + 1) + px) * 8))); normal.normalise(); m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 3] = normal.x; @@ -406,34 +394,29 @@ void Water::ShowWave(Vector3 refpos) bool Water::IsCameraUnderWater() { - if (m_render_cam) - { - return (m_render_cam->getPosition().y < CalcWavesHeight(m_render_cam->getPosition())); - } + if (m_render_cam) { return (m_render_cam->getPosition().y < CalcWavesHeight(m_render_cam->getPosition())); } return false; } void Water::UpdateWater() { - if (!m_water_visible || !m_render_cam) - return; + if (!m_water_visible || !m_render_cam) return; if (m_waterplane_node) { Vector3 cameraPos(m_render_cam->getPosition().x, m_water_height, m_render_cam->getPosition().z); Vector3 sightPos(cameraPos); - Ray lineOfSight(m_render_cam->getPosition(), m_render_cam->getDirection()); + Ray lineOfSight(m_render_cam->getPosition(), m_render_cam->getDirection()); Plane waterPlane(Vector3::UNIT_Y, Vector3::UNIT_Y * m_water_height); std::pair intersection = lineOfSight.intersects(waterPlane); - if (intersection.first && intersection.second > 0.0f) - sightPos = lineOfSight.getPoint(intersection.second); + if (intersection.first && intersection.second > 0.0f) sightPos = lineOfSight.getPoint(intersection.second); Real offset = std::min(cameraPos.distance(sightPos), std::min(m_map_size.x, m_map_size.z) * 0.5f); - Vector3 waterPos = cameraPos + (sightPos - cameraPos).normalisedCopy() * offset; + Vector3 waterPos = cameraPos + (sightPos - cameraPos).normalisedCopy() * offset; Vector3 bottomPos = Vector3(waterPos.x, m_bottom_height, waterPos.z); if (waterPos.distance(m_waterplane_node->getPosition()) > 200.0f || m_waterplane_force_update_pos) @@ -487,10 +470,8 @@ void Water::UpdateWater() void Water::WaterPrepareShutdown() { - if (m_refract_rtt_target) - m_refract_rtt_target->removeListener(&m_refract_listener); - if (m_reflect_rtt_target) - m_reflect_rtt_target->removeListener(&m_reflect_listener); + if (m_refract_rtt_target) m_refract_rtt_target->removeListener(&m_refract_listener); + if (m_reflect_rtt_target) m_reflect_rtt_target->removeListener(&m_reflect_listener); } float Water::GetStaticWaterHeight() @@ -500,7 +481,7 @@ float Water::GetStaticWaterHeight() void Water::SetStaticWaterHeight(float value) { - m_water_height = value; + m_water_height = value; m_waterplane_force_update_pos = true; } @@ -519,13 +500,13 @@ float Water::CalcWavesHeight(Vector3 pos) } // uh, some upper limit?! - if (pos.y > m_water_height + m_max_ampl) - return m_water_height; + if (pos.y > m_water_height + m_max_ampl) return m_water_height; float waveheight = GetWaveHeight(pos); // we will store the result in this variable, init it with the default height float result = m_water_height; - // now walk through all the wave trains. One 'train' is one sin/cos set that will generate once wave. All the trains together will sum up, so that they generate a 'rough' sea + // now walk through all the wave trains. One 'train' is one sin/cos set that will generate once wave. All the trains together + // will sum up, so that they generate a 'rough' sea for (size_t i = 0; i < m_wavetrain_defs.size(); i++) { // calculate the amplitude that this wave will have. wavetrains[i].amplitude is read from the config @@ -533,7 +514,9 @@ float Water::CalcWavesHeight(Vector3 pos) float amp = std::min(m_wavetrain_defs[i].amplitude * waveheight, m_wavetrain_defs[i].maxheight); // now the main thing: // calculate the sinus with the values of the config file and add it to the result - result += amp * sin(Math::TWO_PI * ((gEnv->mrTime * m_wavetrain_defs[i].wavespeed + m_wavetrain_defs[i].dir_sin * pos.x + m_wavetrain_defs[i].dir_cos * pos.z) / m_wavetrain_defs[i].wavelength)); + result += amp * sin(Math::TWO_PI * ((gEnv->mrTime * m_wavetrain_defs[i].wavespeed + m_wavetrain_defs[i].dir_sin * pos.x + + m_wavetrain_defs[i].dir_cos * pos.z) / + m_wavetrain_defs[i].wavelength)); } // return the summed up waves return result; @@ -547,8 +530,7 @@ bool Water::IsUnderWater(Vector3 pos) { float waveheight = GetWaveHeight(pos); - if (pos.y > m_water_height + m_max_ampl * waveheight || pos.y > m_water_height + m_max_ampl) - return false; + if (pos.y > m_water_height + m_max_ampl * waveheight || pos.y > m_water_height + m_max_ampl) return false; waterheight = CalcWavesHeight(pos); } @@ -558,21 +540,22 @@ bool Water::IsUnderWater(Vector3 pos) Vector3 Water::CalcWavesVelocity(Vector3 pos) { - if (!RoR::App::gfx_water_waves.GetActive() || RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) - return Vector3::ZERO; + if (!RoR::App::gfx_water_waves.GetActive() || RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) return Vector3::ZERO; float waveheight = GetWaveHeight(pos); - if (pos.y > m_water_height + m_max_ampl) - return Vector3::ZERO; + if (pos.y > m_water_height + m_max_ampl) return Vector3::ZERO; Vector3 result(Vector3::ZERO); for (size_t i = 0; i < m_wavetrain_defs.size(); i++) { - float amp = std::min(m_wavetrain_defs[i].amplitude * waveheight, m_wavetrain_defs[i].maxheight); + float amp = std::min(m_wavetrain_defs[i].amplitude * waveheight, m_wavetrain_defs[i].maxheight); float speed = Math::TWO_PI * amp / (m_wavetrain_defs[i].wavelength / m_wavetrain_defs[i].wavespeed); - float coeff = Math::TWO_PI * (gEnv->mrTime * m_wavetrain_defs[i].wavespeed + m_wavetrain_defs[i].dir_sin * pos.x + m_wavetrain_defs[i].dir_cos * pos.z) / m_wavetrain_defs[i].wavelength; + float coeff = Math::TWO_PI * + (gEnv->mrTime * m_wavetrain_defs[i].wavespeed + m_wavetrain_defs[i].dir_sin * pos.x + + m_wavetrain_defs[i].dir_cos * pos.z) / + m_wavetrain_defs[i].wavelength; result.y += speed * cos(coeff); result += Vector3(m_wavetrain_defs[i].dir_sin, 0, m_wavetrain_defs[i].dir_cos) * speed * sin(coeff); } @@ -595,9 +578,9 @@ void Water::UpdateReflectionPlane(float h) { m_reflect_plane.normal = Vector3::UNIT_Y; m_refract_plane.normal = -Vector3::UNIT_Y; - m_reflect_plane.d = -h + 0.15; - m_refract_plane.d = h + 0.15; - m_water_plane.d = -h; + m_reflect_plane.d = -h + 0.15; + m_refract_plane.d = h + 0.15; + m_water_plane.d = -h; if (m_reflect_cam) { m_reflect_cam->enableReflection(m_water_plane); @@ -605,23 +588,17 @@ void Water::UpdateReflectionPlane(float h) } } - if (m_refract_cam) - { - m_refract_cam->enableCustomNearClipPlane(m_refract_plane); - } + if (m_refract_cam) { m_refract_cam->enableCustomNearClipPlane(m_refract_plane); } } -void Water::WaterSetCamera(Ogre::Camera* cam) +void Water::WaterSetCamera(Ogre::Camera *cam) { m_render_cam = cam; } void Water::FrameStepWater(float dt) { - if (dt) - { - this->UpdateWater(); - } + if (dt) { this->UpdateWater(); } } float Water::GetWaveHeight(Vector3 pos) @@ -630,36 +607,37 @@ float Water::GetWaveHeight(Vector3 pos) // (mapsize.x * m_waterplane_mesh_scale) / 2 = terrain width / 2 // (mapsize.z * m_waterplane_mesh_scale) / 2 = terrain height / 2 // calculate distance to the center of the terrain and divide by 3.000.000 - float waveheight = (pos - Vector3((m_map_size.x * m_waterplane_mesh_scale) * 0.5, m_water_height, (m_map_size.z * m_waterplane_mesh_scale) * 0.5)).squaredLength() / 3000000.0; + float waveheight = (pos - Vector3((m_map_size.x * m_waterplane_mesh_scale) * 0.5, m_water_height, + (m_map_size.z * m_waterplane_mesh_scale) * 0.5)) + .squaredLength() / + 3000000.0; return waveheight; } - // ------------------------- The listeners ------------------------- - -void Water::RefractionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +void Water::RefractionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(false); this->waterplane_entity->setVisible(false); App::GetSimController()->GetGfxScene().SetParticlesVisible(false); // Hide water spray } -void Water::RefractionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +void Water::RefractionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(true); this->waterplane_entity->setVisible(true); App::GetSimController()->GetGfxScene().SetParticlesVisible(true); // Restore water spray } -void Water::ReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +void Water::ReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(false); this->waterplane_entity->setVisible(false); } -void Water::ReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +void Water::ReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(true); this->waterplane_entity->setVisible(true); diff --git a/source/main/gfx/Water.h b/source/main/gfx/Water.h index f919bed067..c241096b8d 100644 --- a/source/main/gfx/Water.h +++ b/source/main/gfx/Water.h @@ -34,28 +34,26 @@ class Water : public IWater, public ZeroedMemoryAllocator { -public: - + public: Water(); ~Water(); // Interface `IWater` - float GetStaticWaterHeight() override; - void SetStaticWaterHeight(float value) override; - void SetWaterBottomHeight(float value) override; - float CalcWavesHeight(Ogre::Vector3 pos) override; - Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) override; - void SetWaterVisible(bool value) override; - void WaterSetCamera(Ogre::Camera* cam) override; - bool IsUnderWater(Ogre::Vector3 pos) override; - void SetReflectionPlaneHeight(float centerheight) override; - void UpdateReflectionPlane(float h) override; - void WaterPrepareShutdown() override; - void UpdateWater() override; - void FrameStepWater(float dt) override; - -private: - + float GetStaticWaterHeight() override; + void SetStaticWaterHeight(float value) override; + void SetWaterBottomHeight(float value) override; + float CalcWavesHeight(Ogre::Vector3 pos) override; + Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) override; + void SetWaterVisible(bool value) override; + void WaterSetCamera(Ogre::Camera *cam) override; + bool IsUnderWater(Ogre::Vector3 pos) override; + void SetReflectionPlaneHeight(float centerheight) override; + void UpdateReflectionPlane(float h) override; + void WaterPrepareShutdown() override; + void UpdateWater() override; + void FrameStepWater(float dt) override; + + private: struct WaveTrain { float amplitude; @@ -67,61 +65,65 @@ class Water : public IWater, public ZeroedMemoryAllocator float dir_cos; }; - struct ReflectionListener: Ogre::RenderTargetListener + struct ReflectionListener : Ogre::RenderTargetListener { - ReflectionListener(): scene_mgr(nullptr), waterplane_entity(nullptr) {} + ReflectionListener() : scene_mgr(nullptr), waterplane_entity(nullptr) + { + } - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) override; - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) override; + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; - Ogre::SceneManager* scene_mgr; - Ogre::Entity* waterplane_entity; + Ogre::SceneManager *scene_mgr; + Ogre::Entity * waterplane_entity; }; - struct RefractionListener: Ogre::RenderTargetListener + struct RefractionListener : Ogre::RenderTargetListener { - RefractionListener(): scene_mgr(nullptr), waterplane_entity(nullptr) {} + RefractionListener() : scene_mgr(nullptr), waterplane_entity(nullptr) + { + } - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) override; - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) override; + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; - Ogre::SceneManager* scene_mgr; - Ogre::Entity* waterplane_entity; + Ogre::SceneManager *scene_mgr; + Ogre::Entity * waterplane_entity; }; - float GetWaveHeight(Ogre::Vector3 pos); - void ShowWave(Ogre::Vector3 refpos); - bool IsCameraUnderWater(); - void PrepareWater(); - - bool m_water_visible; - float m_water_height; - float m_bottom_height; - float m_max_ampl; - float m_waterplane_mesh_scale; - int m_frame_counter; - Ogre::Vector3 m_map_size; - Ogre::Camera* m_render_cam; - Ogre::Plane m_water_plane; - Ogre::MeshPtr m_waterplane_mesh; - Ogre::Entity* m_waterplane_entity; - Ogre::SceneNode* m_waterplane_node; - Ogre::HardwareVertexBufferSharedPtr m_waterplane_vert_buf; - float* m_waterplane_vert_buf_local; - bool m_waterplane_force_update_pos; - Ogre::Plane m_reflect_plane; - Ogre::Plane m_refract_plane; - ReflectionListener m_reflect_listener; - RefractionListener m_refract_listener; - Ogre::Camera* m_reflect_cam; - Ogre::Camera* m_refract_cam; - Ogre::RenderTexture* m_refract_rtt_target; - Ogre::RenderTexture* m_reflect_rtt_target; - Ogre::TexturePtr m_refract_rtt_texture; - Ogre::TexturePtr m_reflect_rtt_texture; - Ogre::Viewport* m_refract_rtt_viewport; - Ogre::Viewport* m_reflect_rtt_viewport; - Ogre::SceneNode* m_bottomplane_node; - Ogre::Plane m_bottom_plane; - std::vector m_wavetrain_defs; + float GetWaveHeight(Ogre::Vector3 pos); + void ShowWave(Ogre::Vector3 refpos); + bool IsCameraUnderWater(); + void PrepareWater(); + + bool m_water_visible; + float m_water_height; + float m_bottom_height; + float m_max_ampl; + float m_waterplane_mesh_scale; + int m_frame_counter; + Ogre::Vector3 m_map_size; + Ogre::Camera * m_render_cam; + Ogre::Plane m_water_plane; + Ogre::MeshPtr m_waterplane_mesh; + Ogre::Entity * m_waterplane_entity; + Ogre::SceneNode * m_waterplane_node; + Ogre::HardwareVertexBufferSharedPtr m_waterplane_vert_buf; + float * m_waterplane_vert_buf_local; + bool m_waterplane_force_update_pos; + Ogre::Plane m_reflect_plane; + Ogre::Plane m_refract_plane; + ReflectionListener m_reflect_listener; + RefractionListener m_refract_listener; + Ogre::Camera * m_reflect_cam; + Ogre::Camera * m_refract_cam; + Ogre::RenderTexture * m_refract_rtt_target; + Ogre::RenderTexture * m_reflect_rtt_target; + Ogre::TexturePtr m_refract_rtt_texture; + Ogre::TexturePtr m_reflect_rtt_texture; + Ogre::Viewport * m_refract_rtt_viewport; + Ogre::Viewport * m_reflect_rtt_viewport; + Ogre::SceneNode * m_bottomplane_node; + Ogre::Plane m_bottom_plane; + std::vector m_wavetrain_defs; }; diff --git a/source/main/gfx/camera/CameraManager.cpp b/source/main/gfx/camera/CameraManager.cpp index 4526d1f622..fe47a1e744 100644 --- a/source/main/gfx/camera/CameraManager.cpp +++ b/source/main/gfx/camera/CameraManager.cpp @@ -27,14 +27,14 @@ #include "BeamFactory.h" #include "Character.h" #include "Collisions.h" +#include "GUIManager.h" #include "GUI_GameConsole.h" #include "InputEngine.h" #include "Language.h" #include "OverlayWrapper.h" +#include "PerVehicleCameraContext.h" #include "RoRFrameListener.h" #include "TerrainManager.h" -#include "GUIManager.h" -#include "PerVehicleCameraContext.h" #include "Water.h" // ========== Project 'SimCam' (started June 2018) ========== @@ -55,21 +55,21 @@ // SceneMouse.cpp: getViewport() // DepthOfFieldEffect.cpp: getFOVy, setFOVy, getPosition, getViewport // EnvironmentMap.cpp: setFarClipDistance, getFarClipDistance, getBackgroundColour -// GfxActor.cpp: getPosition(), +// GfxActor.cpp: getPosition(), // Heathaze.cpp: get/addViewport() // HydraxWater.cpp, skyxManager: getDerivedPosition() -// Scripting: setPosition setDirection setOrientation yaw pitch roll getPosition getDirection getOrientation lookAt -// SimController: getUp() +// Scripting: setPosition setDirection setOrientation yaw pitch roll getPosition getDirection +// getOrientation lookAt SimController: getUp() using namespace Ogre; using namespace RoR; static const Ogre::Vector3 CHARACTERCAM_OFFSET_1ST_PERSON(0.0f, 1.82f, 0.0f); static const Ogre::Vector3 CHARACTERCAM_OFFSET_3RD_PERSON(0.0f, 1.1f, 0.0f); -static const int SPLINECAM_DRAW_RESOLUTION = 200; +static const int SPLINECAM_DRAW_RESOLUTION = 200; static const int DEFAULT_INTERNAL_CAM_PITCH = -15; -static const float TRANS_SPEED = 50.f; -static const float ROTATE_SPEED = 100.f; +static const float TRANS_SPEED = 50.f; +static const float ROTATE_SPEED = 100.f; bool intersectsTerrain(Vector3 a, Vector3 b) // internal helper { @@ -79,11 +79,8 @@ bool intersectsTerrain(Vector3 a, Vector3 b) // internal helper for (int i = 1; i < steps; i++) { Vector3 pos = a + (b - a) * (float)i / steps; - float h = App::GetSimTerrain()->GetHeightAt(pos.x, pos.z); - if (h > pos.y) - { - return true; - } + float h = App::GetSimTerrain()->GetHeightAt(pos.x, pos.z); + if (h > pos.y) { return true; } } return gEnv->collisions->intersectsTris(Ray(a, b - a)).first; } @@ -94,45 +91,21 @@ bool intersectsTerrain(Vector3 a, Vector3 start, Vector3 end, float interval) // for (int i = 0; i <= steps; i++) { Vector3 b = start + (end - start) * (float)i / steps; - if (intersectsTerrain(a, b)) - { - return true; - } + if (intersectsTerrain(a, b)) { return true; } } return false; } -CameraManager::CameraManager() : - m_current_behavior(CAMERA_BEHAVIOR_INVALID) - , m_cct_dt(0.0f) - , m_cct_trans_scale(1.0f) - , m_cct_sim_speed(1.0f) - , m_cam_before_toggled(CAMERA_BEHAVIOR_INVALID) - , m_prev_toggled_cam(CAMERA_BEHAVIOR_INVALID) - , m_charactercam_is_3rdperson(true) - , m_splinecam_num_linked_beams(0) - , m_splinecam_auto_tracking(false) - , m_splinecam_spline(new SimpleSpline()) - , m_splinecam_spline_closed(false) - , m_splinecam_spline_len(1.0f) - , m_splinecam_mo(0) - , m_splinecam_spline_pos(0.5f) - , m_staticcam_force_update(false) - , m_staticcam_fov_exponent(1.0f) - , m_cam_rot_x(0.0f) - , m_cam_rot_y(0.3f) - , m_cam_dist(5.f) - , m_cam_dist_min(0.f) - , m_cam_dist_max(0.f) - , m_cam_target_direction(0.f) - , m_cam_target_pitch(0.f) - , m_cam_ratio (11.f) - , m_cam_look_at(Ogre::Vector3::ZERO) - , m_cam_look_at_last(Ogre::Vector3::ZERO) - , m_cam_look_at_smooth(Ogre::Vector3::ZERO) - , m_cam_look_at_smooth_last(Ogre::Vector3::ZERO) - , m_cam_limit_movement(true) - , m_camera_ready(false) +CameraManager::CameraManager() + : m_current_behavior(CAMERA_BEHAVIOR_INVALID), m_cct_dt(0.0f), m_cct_trans_scale(1.0f), m_cct_sim_speed(1.0f), + m_cam_before_toggled(CAMERA_BEHAVIOR_INVALID), m_prev_toggled_cam(CAMERA_BEHAVIOR_INVALID), + m_charactercam_is_3rdperson(true), m_splinecam_num_linked_beams(0), m_splinecam_auto_tracking(false), + m_splinecam_spline(new SimpleSpline()), m_splinecam_spline_closed(false), m_splinecam_spline_len(1.0f), m_splinecam_mo(0), + m_splinecam_spline_pos(0.5f), m_staticcam_force_update(false), m_staticcam_fov_exponent(1.0f), m_cam_rot_x(0.0f), + m_cam_rot_y(0.3f), m_cam_dist(5.f), m_cam_dist_min(0.f), m_cam_dist_max(0.f), m_cam_target_direction(0.f), + m_cam_target_pitch(0.f), m_cam_ratio(11.f), m_cam_look_at(Ogre::Vector3::ZERO), m_cam_look_at_last(Ogre::Vector3::ZERO), + m_cam_look_at_smooth(Ogre::Vector3::ZERO), m_cam_look_at_smooth_last(Ogre::Vector3::ZERO), m_cam_limit_movement(true), + m_camera_ready(false) { m_cct_player_actor = nullptr; @@ -141,17 +114,16 @@ CameraManager::CameraManager() : CameraManager::~CameraManager() { - if (m_splinecam_spline) - delete m_splinecam_spline; - if (m_splinecam_mo) - delete m_splinecam_mo; + if (m_splinecam_spline) delete m_splinecam_spline; + if (m_splinecam_mo) delete m_splinecam_mo; } bool CameraManager::EvaluateSwitchBehavior() { - switch(m_current_behavior) + switch (m_current_behavior) + { + case CAMERA_BEHAVIOR_CHARACTER: { - case CAMERA_BEHAVIOR_CHARACTER: { if (m_charactercam_is_3rdperson) { m_charactercam_is_3rdperson = false; @@ -164,12 +136,13 @@ bool CameraManager::EvaluateSwitchBehavior() return true; } } - case CAMERA_BEHAVIOR_STATIC: return true; - case CAMERA_BEHAVIOR_VEHICLE: return true; - case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return true; - case CAMERA_BEHAVIOR_VEHICLE_CINECAM: { - if ( (m_cct_player_actor != nullptr) - && (m_cct_player_actor->ar_current_cinecam) < (m_cct_player_actor->ar_num_cinecams-1) ) + case CAMERA_BEHAVIOR_STATIC: return true; + case CAMERA_BEHAVIOR_VEHICLE: return true; + case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return true; + case CAMERA_BEHAVIOR_VEHICLE_CINECAM: + { + if ((m_cct_player_actor != nullptr) && + (m_cct_player_actor->ar_current_cinecam) < (m_cct_player_actor->ar_num_cinecams - 1)) { m_cct_player_actor->ar_current_cinecam++; m_cct_player_actor->NotifyActorCameraChanged(); @@ -177,24 +150,24 @@ bool CameraManager::EvaluateSwitchBehavior() } return true; } - case CAMERA_BEHAVIOR_FREE: return true; - case CAMERA_BEHAVIOR_FIXED: return true; - case CAMERA_BEHAVIOR_ISOMETRIC: return true; - case CAMERA_BEHAVIOR_INVALID: return true; - default: return false; + case CAMERA_BEHAVIOR_FREE: return true; + case CAMERA_BEHAVIOR_FIXED: return true; + case CAMERA_BEHAVIOR_ISOMETRIC: return true; + case CAMERA_BEHAVIOR_INVALID: return true; + default: return false; } } void CameraManager::UpdateCurrentBehavior() { - switch(m_current_behavior) + switch (m_current_behavior) { - case CAMERA_BEHAVIOR_CHARACTER: { - if (!gEnv->player) - return; + case CAMERA_BEHAVIOR_CHARACTER: + { + if (!gEnv->player) return; m_cam_target_direction = -gEnv->player->getRotation() - Radian(Math::HALF_PI); - Ogre::Vector3 offset = (!m_charactercam_is_3rdperson) ? CHARACTERCAM_OFFSET_1ST_PERSON : CHARACTERCAM_OFFSET_3RD_PERSON; - m_cam_look_at = gEnv->player->getPosition() + offset; + Ogre::Vector3 offset = (!m_charactercam_is_3rdperson) ? CHARACTERCAM_OFFSET_1ST_PERSON : CHARACTERCAM_OFFSET_3RD_PERSON; + m_cam_look_at = gEnv->player->getPosition() + offset; CameraManager::CameraBehaviorOrbitUpdate(); return; @@ -205,45 +178,46 @@ void CameraManager::UpdateCurrentBehavior() this->UpdateCameraBehaviorStatic(); return; - case CAMERA_BEHAVIOR_VEHICLE: this->UpdateCameraBehaviorVehicle(); return; - case CAMERA_BEHAVIOR_VEHICLE_SPLINE: this->CameraBehaviorVehicleSplineUpdate(); return; - case CAMERA_BEHAVIOR_VEHICLE_CINECAM: { + case CAMERA_BEHAVIOR_VEHICLE: this->UpdateCameraBehaviorVehicle(); return; + case CAMERA_BEHAVIOR_VEHICLE_SPLINE: this->CameraBehaviorVehicleSplineUpdate(); return; + case CAMERA_BEHAVIOR_VEHICLE_CINECAM: + { CameraManager::CameraBehaviorOrbitUpdate(); - int pos_node = m_cct_player_actor->ar_camera_node_pos [m_cct_player_actor->ar_current_cinecam]; - int dir_node = m_cct_player_actor->ar_camera_node_dir [m_cct_player_actor->ar_current_cinecam]; + int pos_node = m_cct_player_actor->ar_camera_node_pos[m_cct_player_actor->ar_current_cinecam]; + int dir_node = m_cct_player_actor->ar_camera_node_dir[m_cct_player_actor->ar_current_cinecam]; int roll_node = m_cct_player_actor->ar_camera_node_roll[m_cct_player_actor->ar_current_cinecam]; - Vector3 dir = (m_cct_player_actor->ar_nodes[pos_node].AbsPosition - - m_cct_player_actor->ar_nodes[dir_node].AbsPosition).normalisedCopy(); - Vector3 roll = (m_cct_player_actor->ar_nodes[pos_node].AbsPosition - - m_cct_player_actor->ar_nodes[roll_node].AbsPosition).normalisedCopy(); + Vector3 dir = (m_cct_player_actor->ar_nodes[pos_node].AbsPosition - m_cct_player_actor->ar_nodes[dir_node].AbsPosition) + .normalisedCopy(); + Vector3 roll = (m_cct_player_actor->ar_nodes[pos_node].AbsPosition - m_cct_player_actor->ar_nodes[roll_node].AbsPosition) + .normalisedCopy(); - if ( m_cct_player_actor->ar_camera_node_roll_inv[m_cct_player_actor->ar_current_cinecam] ) - { - roll = -roll; - } + if (m_cct_player_actor->ar_camera_node_roll_inv[m_cct_player_actor->ar_current_cinecam]) { roll = -roll; } Vector3 up = dir.crossProduct(roll); - roll = up.crossProduct(dir); + roll = up.crossProduct(dir); - Quaternion orientation = Quaternion(m_cam_rot_x, up) * Quaternion(Degree(180.0) + m_cam_rot_y, roll) * Quaternion(roll, up, dir); + Quaternion orientation = + Quaternion(m_cam_rot_x, up) * Quaternion(Degree(180.0) + m_cam_rot_y, roll) * Quaternion(roll, up, dir); - gEnv->mainCamera->setPosition(m_cct_player_actor->ar_nodes[m_cct_player_actor->ar_cinecam_node[m_cct_player_actor->ar_current_cinecam]].AbsPosition); + gEnv->mainCamera->setPosition( + m_cct_player_actor->ar_nodes[m_cct_player_actor->ar_cinecam_node[m_cct_player_actor->ar_current_cinecam]] + .AbsPosition); gEnv->mainCamera->setOrientation(orientation); return; } - case CAMERA_BEHAVIOR_FREE: this->UpdateCameraBehaviorFree(); return; - case CAMERA_BEHAVIOR_FIXED: this->UpdateCameraBehaviorFixed(); return; - case CAMERA_BEHAVIOR_ISOMETRIC: return; - case CAMERA_BEHAVIOR_INVALID: return; - default: return; + case CAMERA_BEHAVIOR_FREE: this->UpdateCameraBehaviorFree(); return; + case CAMERA_BEHAVIOR_FIXED: this->UpdateCameraBehaviorFixed(); return; + case CAMERA_BEHAVIOR_ISOMETRIC: return; + case CAMERA_BEHAVIOR_INVALID: return; + default: return; } } -bool CameraManager::Update(float dt, Actor* player_vehicle, float sim_speed) // Called every frame +bool CameraManager::Update(float dt, Actor *player_vehicle, float sim_speed) // Called every frame { - const float trans_scale = TRANS_SPEED * dt; + const float trans_scale = TRANS_SPEED * dt; const float rot_scale = ROTATE_SPEED * dt; m_cct_player_actor = player_vehicle; @@ -257,28 +231,18 @@ bool CameraManager::Update(float dt, Actor* player_vehicle, float sim_speed) // return true; // Do nothing when paused } - if ( m_current_behavior < CAMERA_BEHAVIOR_END && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_CHANGE) ) + if (m_current_behavior < CAMERA_BEHAVIOR_END && RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_CHANGE)) { - if ( (m_current_behavior == CAMERA_BEHAVIOR_INVALID) || this->EvaluateSwitchBehavior() ) - { - this->switchToNextBehavior(); - } + if ((m_current_behavior == CAMERA_BEHAVIOR_INVALID) || this->EvaluateSwitchBehavior()) { this->switchToNextBehavior(); } } - if ( RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_FREE_MODE_FIX) ) - { - this->ToggleCameraBehavior(CAMERA_BEHAVIOR_FIXED); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_FREE_MODE_FIX)) + { this->ToggleCameraBehavior(CAMERA_BEHAVIOR_FIXED); } - if ( RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_FREE_MODE) ) - { - this->ToggleCameraBehavior(CAMERA_BEHAVIOR_FREE); - } + if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_FREE_MODE)) + { this->ToggleCameraBehavior(CAMERA_BEHAVIOR_FREE); } - if (m_current_behavior != CAMERA_BEHAVIOR_INVALID) - { - this->UpdateCurrentBehavior(); - } + if (m_current_behavior != CAMERA_BEHAVIOR_INVALID) { this->UpdateCurrentBehavior(); } else { switchBehavior(CAMERA_BEHAVIOR_CHARACTER); @@ -295,26 +259,27 @@ void CameraManager::switchToNextBehavior() void CameraManager::ResetCurrentBehavior() { - switch(m_current_behavior) + switch (m_current_behavior) + { + case CAMERA_BEHAVIOR_CHARACTER: { - case CAMERA_BEHAVIOR_CHARACTER: { CameraManager::CameraBehaviorOrbitReset(); // Vars from CameraBehaviorOrbit if (!m_charactercam_is_3rdperson) { m_cam_rot_y = 0.1f; - m_cam_dist = 0.1f; + m_cam_dist = 0.1f; m_cam_ratio = 0.0f; } else { m_cam_rot_y = 0.3f; - m_cam_dist = 5.0f; + m_cam_dist = 5.0f; m_cam_ratio = 11.0f; } - m_cam_dist_min = 0; - m_cam_target_pitch = 0.0f; + m_cam_dist_min = 0; + m_cam_target_pitch = 0.0f; return; } @@ -323,22 +288,20 @@ void CameraManager::ResetCurrentBehavior() App::gfx_static_cam_fov_exp.SetActive(1.0f); return; - case CAMERA_BEHAVIOR_VEHICLE: - this->CameraBehaviorVehicleReset(); - return; + case CAMERA_BEHAVIOR_VEHICLE: this->CameraBehaviorVehicleReset(); return; - case CAMERA_BEHAVIOR_VEHICLE_SPLINE: this->CameraBehaviorVehicleSplineReset(); return; + case CAMERA_BEHAVIOR_VEHICLE_SPLINE: this->CameraBehaviorVehicleSplineReset(); return; case CAMERA_BEHAVIOR_VEHICLE_CINECAM: CameraManager::CameraBehaviorOrbitReset(); m_cam_rot_y = Degree(DEFAULT_INTERNAL_CAM_PITCH); gEnv->mainCamera->setFOVy(Degree(App::gfx_fov_internal.GetActive())); return; - case CAMERA_BEHAVIOR_FREE: return; - case CAMERA_BEHAVIOR_FIXED: return; - case CAMERA_BEHAVIOR_ISOMETRIC: return; - case CAMERA_BEHAVIOR_INVALID: return; - default: return; + case CAMERA_BEHAVIOR_FREE: return; + case CAMERA_BEHAVIOR_FIXED: return; + case CAMERA_BEHAVIOR_ISOMETRIC: return; + case CAMERA_BEHAVIOR_INVALID: return; + default: return; } } @@ -351,22 +314,22 @@ void CameraManager::ActivateNewBehavior(CameraBehaviors new_behavior, bool reset switch (new_behavior) { case CAMERA_BEHAVIOR_FREE: - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Free camera"), "camera_go.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Free camera"), + "camera_go.png", 3000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Free camera")); break; case CAMERA_BEHAVIOR_ISOMETRIC: case CAMERA_BEHAVIOR_FIXED: - RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, _L("Fixed camera"), "camera_link.png", 3000); + RoR::App::GetConsole()->putMessage(RoR::Console::CONSOLE_MSGTYPE_INFO, RoR::Console::CONSOLE_SYSTEM_NOTICE, + _L("Fixed camera"), "camera_link.png", 3000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Fixed camera")); break; - case CAMERA_BEHAVIOR_STATIC: - m_staticcam_previous_fov = gEnv->mainCamera->getFOVy(); - break; + case CAMERA_BEHAVIOR_STATIC: m_staticcam_previous_fov = gEnv->mainCamera->getFOVy(); break; case CAMERA_BEHAVIOR_VEHICLE_SPLINE: - if ( (m_cct_player_actor == nullptr) || m_cct_player_actor->ar_num_camera_rails <= 0) + if ((m_cct_player_actor == nullptr) || m_cct_player_actor->ar_num_camera_rails <= 0) { this->switchToNextBehavior(); return; @@ -385,7 +348,7 @@ void CameraManager::ActivateNewBehavior(CameraBehaviors new_behavior, bool reset this->switchToNextBehavior(); return; } - else if ( reset ) + else if (reset) { this->ResetCurrentBehavior(); } @@ -394,7 +357,7 @@ void CameraManager::ActivateNewBehavior(CameraBehaviors new_behavior, bool reset m_cct_player_actor->prepareInside(true); - if ( RoR::App::GetOverlayWrapper() != nullptr ) + if (RoR::App::GetOverlayWrapper() != nullptr) { bool visible = m_cct_player_actor->ar_driveable == AIRPLANE && !RoR::App::GetSimController()->IsGUIHidden(); RoR::App::GetOverlayWrapper()->showDashboardOverlays(visible, m_cct_player_actor); @@ -407,12 +370,12 @@ void CameraManager::ActivateNewBehavior(CameraBehaviors new_behavior, bool reset break; case CAMERA_BEHAVIOR_VEHICLE: - if ( m_cct_player_actor == nullptr ) + if (m_cct_player_actor == nullptr) { this->switchToNextBehavior(); return; } - else if ( reset ) + else if (reset) { this->ResetCurrentBehavior(); } @@ -437,13 +400,10 @@ void CameraManager::ActivateNewBehavior(CameraBehaviors new_behavior, bool reset void CameraManager::DeactivateCurrentBehavior() { - if (m_current_behavior == CAMERA_BEHAVIOR_STATIC) - { - gEnv->mainCamera->setFOVy(m_staticcam_previous_fov); - } + if (m_current_behavior == CAMERA_BEHAVIOR_STATIC) { gEnv->mainCamera->setFOVy(m_staticcam_previous_fov); } else if (m_current_behavior == CAMERA_BEHAVIOR_VEHICLE_CINECAM) { - if ( m_cct_player_actor != nullptr ) + if (m_cct_player_actor != nullptr) { gEnv->mainCamera->setFOVy(Degree(App::gfx_fov_external.GetActive())); m_cct_player_actor->prepareInside(false); @@ -454,35 +414,24 @@ void CameraManager::DeactivateCurrentBehavior() void CameraManager::switchBehavior(CameraBehaviors new_behavior) { - if (new_behavior == m_current_behavior) - { - return; - } + if (new_behavior == m_current_behavior) { return; } this->DeactivateCurrentBehavior(); if (m_cct_player_actor != nullptr) { m_cct_player_actor->GetCameraContext()->behavior = RoR::PerVehicleCameraContext::CAMCTX_BEHAVIOR_EXTERNAL; - if ( RoR::App::GetOverlayWrapper() != nullptr && !RoR::App::GetSimController()->IsGUIHidden() ) - { - RoR::App::GetOverlayWrapper()->showDashboardOverlays(true, m_cct_player_actor); - } - if (m_current_behavior == CAMERA_BEHAVIOR_VEHICLE_CINECAM) - { - m_cct_player_actor->ar_current_cinecam = -1; - } + if (RoR::App::GetOverlayWrapper() != nullptr && !RoR::App::GetSimController()->IsGUIHidden()) + { RoR::App::GetOverlayWrapper()->showDashboardOverlays(true, m_cct_player_actor); } + if (m_current_behavior == CAMERA_BEHAVIOR_VEHICLE_CINECAM) { m_cct_player_actor->ar_current_cinecam = -1; } } this->ActivateNewBehavior(new_behavior, true); } -void CameraManager::SwitchBehaviorOnVehicleChange(CameraBehaviors new_behavior, Actor* new_vehicle) +void CameraManager::SwitchBehaviorOnVehicleChange(CameraBehaviors new_behavior, Actor *new_vehicle) { - if (new_behavior == m_current_behavior) - { - this->NotifyContextChange(); - } + if (new_behavior == m_current_behavior) { this->NotifyContextChange(); } this->DeactivateCurrentBehavior(); @@ -496,17 +445,17 @@ bool CameraManager::hasActiveBehavior() return m_current_behavior != CAMERA_BEHAVIOR_INVALID; } -bool CameraManager::mouseMoved(const OIS::MouseEvent& _arg) +bool CameraManager::mouseMoved(const OIS::MouseEvent &_arg) { - switch(m_current_behavior) + switch (m_current_behavior) { - case CAMERA_BEHAVIOR_CHARACTER: { - if (!gEnv->player) - return false; + case CAMERA_BEHAVIOR_CHARACTER: + { + if (!gEnv->player) return false; if (!m_charactercam_is_3rdperson) { - const OIS::MouseState ms = _arg.state; - Radian angle = gEnv->player->getRotation(); + const OIS::MouseState ms = _arg.state; + Radian angle = gEnv->player->getRotation(); m_cam_rot_y += Degree(ms.Y.rel * 0.13f); angle += Degree(ms.X.rel * 0.13f); @@ -523,11 +472,12 @@ bool CameraManager::mouseMoved(const OIS::MouseEvent& _arg) return CameraManager::CameraBehaviorOrbitMouseMoved(_arg); } - case CAMERA_BEHAVIOR_STATIC: return CameraBehaviorStaticMouseMoved(_arg); - case CAMERA_BEHAVIOR_VEHICLE: return CameraBehaviorOrbitMouseMoved(_arg); - case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return this->CameraBehaviorVehicleSplineMouseMoved(_arg); + case CAMERA_BEHAVIOR_STATIC: return CameraBehaviorStaticMouseMoved(_arg); + case CAMERA_BEHAVIOR_VEHICLE: return CameraBehaviorOrbitMouseMoved(_arg); + case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return this->CameraBehaviorVehicleSplineMouseMoved(_arg); case CAMERA_BEHAVIOR_VEHICLE_CINECAM: return CameraBehaviorOrbitMouseMoved(_arg); - case CAMERA_BEHAVIOR_FREE: { + case CAMERA_BEHAVIOR_FREE: + { const OIS::MouseState ms = _arg.state; gEnv->mainCamera->yaw(Degree(-ms.X.rel * 0.13f)); @@ -538,34 +488,31 @@ bool CameraManager::mouseMoved(const OIS::MouseEvent& _arg) return true; } - case CAMERA_BEHAVIOR_FIXED: return false; - case CAMERA_BEHAVIOR_ISOMETRIC: return false; - case CAMERA_BEHAVIOR_INVALID: return false; - default: return false; + case CAMERA_BEHAVIOR_FIXED: return false; + case CAMERA_BEHAVIOR_ISOMETRIC: return false; + case CAMERA_BEHAVIOR_INVALID: return false; + default: return false; } } -bool CameraManager::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool CameraManager::mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { const OIS::MouseState ms = _arg.state; - if (ms.buttonDown(OIS::MB_Right) && _id == OIS::MB_Middle) - { - ResetCurrentBehavior(); - } + if (ms.buttonDown(OIS::MB_Right) && _id == OIS::MB_Middle) { ResetCurrentBehavior(); } - switch(m_current_behavior) + switch (m_current_behavior) { - case CAMERA_BEHAVIOR_CHARACTER: return false; - case CAMERA_BEHAVIOR_STATIC: return false; - case CAMERA_BEHAVIOR_VEHICLE: return this->CameraBehaviorVehicleMousePressed(_arg, _id); - case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return this->CameraBehaviorVehicleMousePressed(_arg, _id); + case CAMERA_BEHAVIOR_CHARACTER: return false; + case CAMERA_BEHAVIOR_STATIC: return false; + case CAMERA_BEHAVIOR_VEHICLE: return this->CameraBehaviorVehicleMousePressed(_arg, _id); + case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return this->CameraBehaviorVehicleMousePressed(_arg, _id); case CAMERA_BEHAVIOR_VEHICLE_CINECAM: return this->CameraBehaviorVehicleMousePressed(_arg, _id); - case CAMERA_BEHAVIOR_FREE: return false; - case CAMERA_BEHAVIOR_FIXED: return false; - case CAMERA_BEHAVIOR_ISOMETRIC: return false; - case CAMERA_BEHAVIOR_INVALID: return false; - default: return false; + case CAMERA_BEHAVIOR_FREE: return false; + case CAMERA_BEHAVIOR_FIXED: return false; + case CAMERA_BEHAVIOR_ISOMETRIC: return false; + case CAMERA_BEHAVIOR_INVALID: return false; + default: return false; } } @@ -577,37 +524,32 @@ bool CameraManager::gameControlsLocked() const void CameraManager::NotifyContextChange() { - switch(m_current_behavior) + switch (m_current_behavior) { case CAMERA_BEHAVIOR_CHARACTER: case CAMERA_BEHAVIOR_VEHICLE: case CAMERA_BEHAVIOR_VEHICLE_SPLINE: - case CAMERA_BEHAVIOR_VEHICLE_CINECAM: - m_cam_look_at_last = Vector3::ZERO; - return; + case CAMERA_BEHAVIOR_VEHICLE_CINECAM: m_cam_look_at_last = Vector3::ZERO; return; - default: - return; + default: return; } } -void CameraManager::NotifyVehicleChanged(Actor* old_vehicle, Actor* new_vehicle) +void CameraManager::NotifyVehicleChanged(Actor *old_vehicle, Actor *new_vehicle) { // Getting out of vehicle if (new_vehicle == nullptr) { m_cct_player_actor = nullptr; if (this->m_current_behavior != CAMERA_BEHAVIOR_FIXED && this->m_current_behavior != CAMERA_BEHAVIOR_STATIC && - this->m_current_behavior != CAMERA_BEHAVIOR_FREE) - { - this->switchBehavior(CAMERA_BEHAVIOR_CHARACTER); - } + this->m_current_behavior != CAMERA_BEHAVIOR_FREE) + { this->switchBehavior(CAMERA_BEHAVIOR_CHARACTER); } return; } // Getting in vehicle if (this->m_current_behavior != CAMERA_BEHAVIOR_FIXED && this->m_current_behavior != CAMERA_BEHAVIOR_STATIC && - this->m_current_behavior != CAMERA_BEHAVIOR_FREE) + this->m_current_behavior != CAMERA_BEHAVIOR_FREE) { // Change camera switch (new_vehicle->GetCameraContext()->behavior) @@ -624,8 +566,7 @@ void CameraManager::NotifyVehicleChanged(Actor* old_vehicle, Actor* new_vehicle) this->SwitchBehaviorOnVehicleChange(CAMERA_BEHAVIOR_VEHICLE_CINECAM, new_vehicle); break; - default: - this->SwitchBehaviorOnVehicleChange(CAMERA_BEHAVIOR_VEHICLE, new_vehicle); + default: this->SwitchBehaviorOnVehicleChange(CAMERA_BEHAVIOR_VEHICLE, new_vehicle); } } } @@ -649,10 +590,7 @@ void CameraManager::ToggleCameraBehavior(CameraBehaviors new_behavior) // Only a } else // Entering toggled mode { - if (m_cam_before_toggled == CAMERA_BEHAVIOR_INVALID) - { - m_cam_before_toggled = m_current_behavior; - } + if (m_cam_before_toggled == CAMERA_BEHAVIOR_INVALID) { m_cam_before_toggled = m_current_behavior; } else { m_prev_toggled_cam = m_current_behavior; @@ -666,25 +604,20 @@ void CameraManager::UpdateCameraBehaviorStatic() const auto water = App::GetSimTerrain()->getWater(); Vector3 velocity = Vector3::ZERO; - Radian angle = Degree(90); - float radius = 3.0f; - float speed = 0.0f; + Radian angle = Degree(90); + float radius = 3.0f; + float speed = 0.0f; if (m_cct_player_actor) { if (m_cct_player_actor->isBeingReset()) - { - m_staticcam_force_update |= m_cct_player_actor->getPosition().distance(m_staticcam_look_at) > 100.0f; - } + { m_staticcam_force_update |= m_cct_player_actor->getPosition().distance(m_staticcam_look_at) > 100.0f; } m_staticcam_look_at = m_cct_player_actor->getPosition(); - velocity = m_cct_player_actor->ar_nodes[0].Velocity * m_cct_sim_speed; - radius = m_cct_player_actor->getMinCameraRadius(); - angle = (m_staticcam_look_at - m_staticcam_position).angleBetween(velocity); - speed = velocity.normalise(); - if (m_cct_player_actor->ar_replay_mode) - { - speed *= m_cct_player_actor->ar_replay_precision; - } + velocity = m_cct_player_actor->ar_nodes[0].Velocity * m_cct_sim_speed; + radius = m_cct_player_actor->getMinCameraRadius(); + angle = (m_staticcam_look_at - m_staticcam_position).angleBetween(velocity); + speed = velocity.normalise(); + if (m_cct_player_actor->ar_replay_mode) { speed *= m_cct_player_actor->ar_replay_precision; } } else { @@ -695,19 +628,17 @@ void CameraManager::UpdateCameraBehaviorStatic() if (m_staticcam_force_update || m_staticcam_update_timer.getMilliseconds() > 1000) { - Vector3 lookAt = m_staticcam_look_at; + Vector3 lookAt = m_staticcam_look_at; Vector3 lookAtPrediction = lookAt + velocity * speed; - float distance = m_staticcam_position.distance(lookAt); - float interval = std::max(radius, speed); - float cmradius = std::max(radius, App::gfx_camera_height.GetActive() / 7.0f); - - if (m_staticcam_force_update || - (distance > cmradius * 8.0f && angle < Degree(30)) || - (distance < cmradius * 2.0f && angle > Degree(150)) || - distance > cmradius * std::max(25.0f, speed * 1.15f) || - intersectsTerrain(m_staticcam_position, lookAt, lookAtPrediction, interval)) + float distance = m_staticcam_position.distance(lookAt); + float interval = std::max(radius, speed); + float cmradius = std::max(radius, App::gfx_camera_height.GetActive() / 7.0f); + + if (m_staticcam_force_update || (distance > cmradius * 8.0f && angle < Degree(30)) || + (distance < cmradius * 2.0f && angle > Degree(150)) || distance > cmradius * std::max(25.0f, speed * 1.15f) || + intersectsTerrain(m_staticcam_position, lookAt, lookAtPrediction, interval)) { - float water_height = (water && !water->IsUnderWater(lookAt)) ? water->GetStaticWaterHeight() : 0.0f; + float water_height = (water && !water->IsUnderWater(lookAt)) ? water->GetStaticWaterHeight() : 0.0f; float desired_offset = std::max(std::sqrt(radius) * 2.89f, (float)App::gfx_camera_height.GetActive()); std::vector> viable_positions; @@ -724,7 +655,7 @@ void CameraManager::UpdateCameraBehaviorStatic() float dist = std::max(cmradius * 2.5f, std::sqrt(cmradius) * speed); float mrnd = Math::Clamp(0.6f * cmradius / dist, 0.0f, 0.3f); float arnd = mrnd + frand() * (1.0f - mrnd); - float rnd = frand() > 0.5f ? arnd : -arnd; + float rnd = frand() > 0.5f ? arnd : -arnd; pos += (velocity + velocity.crossProduct(Vector3::UNIT_Y) * rnd) * dist; } pos.y = std::max(pos.y, water_height); @@ -734,15 +665,14 @@ void CameraManager::UpdateCameraBehaviorStatic() { float hdiff = std::abs(pos.y - lookAt.y - desired_offset); viable_positions.push_back({hdiff, pos}); - if (hdiff < 1.0f || viable_positions.size() > 2) - break; + if (hdiff < 1.0f || viable_positions.size() > 2) break; } } if (!viable_positions.empty()) { std::sort(viable_positions.begin(), viable_positions.end()); m_staticcam_update_timer.reset(); - m_staticcam_position = viable_positions.front().second; + m_staticcam_position = viable_positions.front().second; m_staticcam_force_update = false; } } @@ -752,14 +682,14 @@ void CameraManager::UpdateCameraBehaviorStatic() fovExp = (1.0f / (m_cam_ratio + 1.0f)) * m_staticcam_fov_exponent + (m_cam_ratio / (m_cam_ratio + 1.0f)) * fovExp; float camDist = m_staticcam_position.distance(m_staticcam_look_at); - float fov = atan2(20.0f, std::pow(camDist, fovExp)); + float fov = atan2(20.0f, std::pow(camDist, fovExp)); gEnv->mainCamera->setPosition(m_staticcam_position); gEnv->mainCamera->lookAt(m_staticcam_look_at); gEnv->mainCamera->setFOVy(Radian(fov)); } -bool CameraManager::CameraBehaviorStaticMouseMoved(const OIS::MouseEvent& _arg) +bool CameraManager::CameraBehaviorStaticMouseMoved(const OIS::MouseEvent &_arg) { const OIS::MouseState ms = _arg.state; @@ -779,75 +709,60 @@ void CameraManager::CameraBehaviorOrbitUpdate() { if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_LOOKBACK)) { - if (m_cam_rot_x > Degree(0)) - { - m_cam_rot_x = Degree(0); - } + if (m_cam_rot_x > Degree(0)) { m_cam_rot_x = Degree(0); } else { m_cam_rot_x = Degree(180); } } - m_cam_rot_x += (RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_RIGHT) - RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_LEFT)) * m_cct_rot_scale; - m_cam_rot_y += (RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_UP) - RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_DOWN)) * m_cct_rot_scale; + m_cam_rot_x += (RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_RIGHT) - + RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_LEFT)) * + m_cct_rot_scale; + m_cam_rot_y += (RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_UP) - + RoR::App::GetInputEngine()->getEventValue(EV_CAMERA_ROTATE_DOWN)) * + m_cct_rot_scale; m_cam_rot_y = std::max((Radian)Degree(-80), m_cam_rot_y); m_cam_rot_y = std::min(m_cam_rot_y, (Radian)Degree(88)); - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_IN) && m_cam_dist > 1) - { - m_cam_dist -= m_cct_trans_scale; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_IN) && m_cam_dist > 1) { m_cam_dist -= m_cct_trans_scale; } if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_IN_FAST) && m_cam_dist > 1) - { - m_cam_dist -= m_cct_trans_scale * 10; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_OUT)) - { - m_cam_dist += m_cct_trans_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_OUT_FAST)) - { - m_cam_dist += m_cct_trans_scale * 10; - } + { m_cam_dist -= m_cct_trans_scale * 10; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_OUT)) { m_cam_dist += m_cct_trans_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_ZOOM_OUT_FAST)) { m_cam_dist += m_cct_trans_scale * 10; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_RESET)) - { - ResetCurrentBehavior(); - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_RESET)) { ResetCurrentBehavior(); } if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_RSHIFT) && RoR::App::GetInputEngine()->isKeyDownValueBounce(OIS::KC_SPACE)) { m_cam_limit_movement = !m_cam_limit_movement; if (m_cam_limit_movement) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Limited camera movement enabled"), "camera_go.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("Limited camera movement enabled"), "camera_go.png", 3000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Limited camera movement enabled")); } else { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Limited camera movement disabled"), "camera_go.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("Limited camera movement disabled"), "camera_go.png", 3000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Limited camera movement disabled")); } } - if (m_cam_limit_movement && m_cam_dist_min > 0.0f) - { - m_cam_dist = std::max(m_cam_dist_min, m_cam_dist); - } - if (m_cam_limit_movement && m_cam_dist_max > 0.0f) - { - m_cam_dist = std::min(m_cam_dist, m_cam_dist_max); - } + if (m_cam_limit_movement && m_cam_dist_min > 0.0f) { m_cam_dist = std::max(m_cam_dist_min, m_cam_dist); } + if (m_cam_limit_movement && m_cam_dist_max > 0.0f) { m_cam_dist = std::min(m_cam_dist, m_cam_dist_max); } m_cam_dist = std::max(0.0f, m_cam_dist); - Vector3 desiredPosition = m_cam_look_at + m_cam_dist * 0.5f * Vector3( - sin(m_cam_target_direction.valueRadians() + m_cam_rot_x.valueRadians()) * cos(m_cam_target_pitch.valueRadians() + m_cam_rot_y.valueRadians()) - , sin(m_cam_target_pitch.valueRadians() + m_cam_rot_y.valueRadians()) - , cos(m_cam_target_direction.valueRadians() + m_cam_rot_x.valueRadians()) * cos(m_cam_target_pitch.valueRadians() + m_cam_rot_y.valueRadians()) - ); + Vector3 desiredPosition = + m_cam_look_at + m_cam_dist * 0.5f * + Vector3(sin(m_cam_target_direction.valueRadians() + m_cam_rot_x.valueRadians()) * + cos(m_cam_target_pitch.valueRadians() + m_cam_rot_y.valueRadians()), + sin(m_cam_target_pitch.valueRadians() + m_cam_rot_y.valueRadians()), + cos(m_cam_target_direction.valueRadians() + m_cam_rot_x.valueRadians()) * + cos(m_cam_target_pitch.valueRadians() + m_cam_rot_y.valueRadians())); if (m_cam_limit_movement) { @@ -856,24 +771,16 @@ void CameraManager::CameraBehaviorOrbitUpdate() desiredPosition.y = std::max(h, desiredPosition.y); } - if (m_cam_look_at_last == Vector3::ZERO) - { - m_cam_look_at_last = m_cam_look_at; - } - if (m_cam_look_at_smooth == Vector3::ZERO) - { - m_cam_look_at_smooth = m_cam_look_at; - } - if (m_cam_look_at_smooth_last == Vector3::ZERO) - { - m_cam_look_at_smooth_last = m_cam_look_at_smooth; - } + if (m_cam_look_at_last == Vector3::ZERO) { m_cam_look_at_last = m_cam_look_at; } + if (m_cam_look_at_smooth == Vector3::ZERO) { m_cam_look_at_smooth = m_cam_look_at; } + if (m_cam_look_at_smooth_last == Vector3::ZERO) { m_cam_look_at_smooth_last = m_cam_look_at_smooth; } - Vector3 camDisplacement = m_cam_look_at - m_cam_look_at_last; - Vector3 precedingLookAt = m_cam_look_at_smooth_last + camDisplacement; + Vector3 camDisplacement = m_cam_look_at - m_cam_look_at_last; + Vector3 precedingLookAt = m_cam_look_at_smooth_last + camDisplacement; Vector3 precedingPosition = gEnv->mainCamera->getPosition() + camDisplacement; - Vector3 camPosition = (1.0f / (m_cam_ratio + 1.0f)) * desiredPosition + (m_cam_ratio / (m_cam_ratio + 1.0f)) * precedingPosition; + Vector3 camPosition = + (1.0f / (m_cam_ratio + 1.0f)) * desiredPosition + (m_cam_ratio / (m_cam_ratio + 1.0f)) * precedingPosition; if (gEnv->collisions && gEnv->collisions->forcecam) { @@ -890,12 +797,12 @@ void CameraManager::CameraBehaviorOrbitUpdate() m_cam_look_at_smooth = (1.0f / (m_cam_ratio + 1.0f)) * m_cam_look_at + (m_cam_ratio / (m_cam_ratio + 1.0f)) * precedingLookAt; - m_cam_look_at_last = m_cam_look_at; + m_cam_look_at_last = m_cam_look_at; m_cam_look_at_smooth_last = m_cam_look_at_smooth; gEnv->mainCamera->lookAt(m_cam_look_at_smooth); } -bool CameraManager::CameraBehaviorOrbitMouseMoved(const OIS::MouseEvent& _arg) +bool CameraManager::CameraBehaviorOrbitMouseMoved(const OIS::MouseEvent &_arg) { const OIS::MouseState ms = _arg.state; @@ -913,21 +820,21 @@ bool CameraManager::CameraBehaviorOrbitMouseMoved(const OIS::MouseEvent& _arg) void CameraManager::CameraBehaviorOrbitReset() { - m_cam_rot_x = 0.0f; - m_cam_rot_y = 0.3f; - m_cam_look_at_last = Vector3::ZERO; - m_cam_look_at_smooth = Vector3::ZERO; + m_cam_rot_x = 0.0f; + m_cam_rot_y = 0.3f; + m_cam_look_at_last = Vector3::ZERO; + m_cam_look_at_smooth = Vector3::ZERO; m_cam_look_at_smooth_last = Vector3::ZERO; gEnv->mainCamera->setFOVy(Degree(App::gfx_fov_external.GetActive())); } void CameraManager::UpdateCameraBehaviorFree() { - Degree mRotX(0.0f); - Degree mRotY(0.0f); - Degree cct_rot_scale(m_cct_rot_scale * 5.0f * m_cct_dt); + Degree mRotX(0.0f); + Degree mRotY(0.0f); + Degree cct_rot_scale(m_cct_rot_scale * 5.0f * m_cct_dt); Vector3 mTrans(Vector3::ZERO); - Real cct_trans_scale(m_cct_trans_scale * 5.0f * m_cct_dt); + Real cct_trans_scale(m_cct_trans_scale * 5.0f * m_cct_dt); if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) || RoR::App::GetInputEngine()->isKeyDown(OIS::KC_RSHIFT)) { @@ -945,59 +852,30 @@ void CameraManager::UpdateCameraBehaviorFree() cct_trans_scale *= 0.2f; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_LEFT)) - { - mTrans.x -= cct_trans_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_RIGHT)) - { - mTrans.x += cct_trans_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_FORWARD)) - { - mTrans.z -= cct_trans_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_BACKWARDS)) - { - mTrans.z += cct_trans_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_UP)) - { - mTrans.y += cct_trans_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_DOWN)) - { - mTrans.y -= cct_trans_scale; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_LEFT)) { mTrans.x -= cct_trans_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_SIDESTEP_RIGHT)) { mTrans.x += cct_trans_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_FORWARD)) { mTrans.z -= cct_trans_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_BACKWARDS)) { mTrans.z += cct_trans_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_UP)) { mTrans.y += cct_trans_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CAMERA_DOWN)) { mTrans.y -= cct_trans_scale; } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_RIGHT)) - { - mRotX -= cct_rot_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_LEFT)) - { - mRotX += cct_rot_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_ROT_UP)) - { - mRotY += cct_rot_scale; - } - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_ROT_DOWN)) - { - mRotY -= cct_rot_scale; - } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_RIGHT)) { mRotX -= cct_rot_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_LEFT)) { mRotX += cct_rot_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_ROT_UP)) { mRotY += cct_rot_scale; } + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_CHARACTER_ROT_DOWN)) { mRotY -= cct_rot_scale; } gEnv->mainCamera->yaw(mRotX); gEnv->mainCamera->pitch(mRotY); - Vector3 camPosition = gEnv->mainCamera->getPosition() + gEnv->mainCamera->getOrientation() * mTrans.normalisedCopy() * cct_trans_scale; + Vector3 camPosition = + gEnv->mainCamera->getPosition() + gEnv->mainCamera->getOrientation() * mTrans.normalisedCopy() * cct_trans_scale; gEnv->mainCamera->setPosition(camPosition); } void CameraManager::UpdateCameraBehaviorFixed() { - if (App::gfx_fixed_cam_tracking.GetActive()) + if (App::gfx_fixed_cam_tracking.GetActive()) { Vector3 look_at = m_cct_player_actor ? m_cct_player_actor->getPosition() : gEnv->player->getPosition(); gEnv->mainCamera->lookAt(look_at); @@ -1006,70 +884,68 @@ void CameraManager::UpdateCameraBehaviorFixed() void CameraManager::UpdateCameraBehaviorVehicle() { - Vector3 dir = m_cct_player_actor->getDirection(); + Vector3 dir = m_cct_player_actor->getDirection(); - m_cam_target_direction = -atan2(dir.dotProduct(Vector3::UNIT_X), dir.dotProduct(-Vector3::UNIT_Z)); - m_cam_target_pitch = 0.0f; + m_cam_target_direction = -atan2(dir.dotProduct(Vector3::UNIT_X), dir.dotProduct(-Vector3::UNIT_Z)); + m_cam_target_pitch = 0.0f; - if ( RoR::App::gfx_extcam_mode.GetActive() == RoR::GfxExtCamMode::PITCHING) - { - m_cam_target_pitch = -asin(dir.dotProduct(Vector3::UNIT_Y)); - } + if (RoR::App::gfx_extcam_mode.GetActive() == RoR::GfxExtCamMode::PITCHING) + { m_cam_target_pitch = -asin(dir.dotProduct(Vector3::UNIT_Y)); } - m_cam_ratio = 1.0f / (m_cct_dt * 4.0f); + m_cam_ratio = 1.0f / (m_cct_dt * 4.0f); - m_cam_dist_min = std::min(m_cct_player_actor->getMinimalCameraRadius() * 2.0f, 33.0f); + m_cam_dist_min = std::min(m_cct_player_actor->getMinimalCameraRadius() * 2.0f, 33.0f); - m_cam_look_at = m_cct_player_actor->getPosition(); + m_cam_look_at = m_cct_player_actor->getPosition(); - CameraManager::CameraBehaviorOrbitUpdate(); + CameraManager::CameraBehaviorOrbitUpdate(); } void CameraManager::CameraBehaviorVehicleReset() { - CameraManager::CameraBehaviorOrbitReset(); - m_cam_rot_y = 0.35f; - m_cam_dist_min = std::min(m_cct_player_actor->getMinimalCameraRadius() * 2.0f, 33.0f); - m_cam_dist = m_cam_dist_min * 1.5f + 2.0f; + CameraManager::CameraBehaviorOrbitReset(); + m_cam_rot_y = 0.35f; + m_cam_dist_min = std::min(m_cct_player_actor->getMinimalCameraRadius() * 2.0f, 33.0f); + m_cam_dist = m_cam_dist_min * 1.5f + 2.0f; } -bool CameraManager::CameraBehaviorVehicleMousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool CameraManager::CameraBehaviorVehicleMousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { - const OIS::MouseState ms = _arg.state; - - if ( ms.buttonDown(OIS::MB_Middle) && RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) ) - { - if ( m_cct_player_actor && m_cct_player_actor->ar_custom_camera_node >= 0 ) - { - // Calculate new camera distance - Vector3 lookAt = m_cct_player_actor->ar_nodes[m_cct_player_actor->ar_custom_camera_node].AbsPosition; - m_cam_dist = 2.0f * gEnv->mainCamera->getPosition().distance(lookAt); - - // Calculate new camera pitch - Vector3 camDir = (gEnv->mainCamera->getPosition() - lookAt).normalisedCopy(); - m_cam_rot_y = asin(camDir.y); - - // Calculate new camera yaw - Vector3 dir = -m_cct_player_actor->getDirection(); - Quaternion rotX = dir.getRotationTo(camDir, Vector3::UNIT_Y); - m_cam_rot_x = rotX.getYaw(); - - // Corner case handling - Radian angle = dir.angleBetween(camDir); - if ( angle > Radian(Math::HALF_PI) ) - { - if ( std::abs(Radian(m_cam_rot_x).valueRadians()) < Math::HALF_PI ) - { - if ( m_cam_rot_x < Radian(0.0f) ) - m_cam_rot_x -= Radian(Math::HALF_PI); - else - m_cam_rot_x += Radian(Math::HALF_PI); - } - } - } - } - - return false; + const OIS::MouseState ms = _arg.state; + + if (ms.buttonDown(OIS::MB_Middle) && RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT)) + { + if (m_cct_player_actor && m_cct_player_actor->ar_custom_camera_node >= 0) + { + // Calculate new camera distance + Vector3 lookAt = m_cct_player_actor->ar_nodes[m_cct_player_actor->ar_custom_camera_node].AbsPosition; + m_cam_dist = 2.0f * gEnv->mainCamera->getPosition().distance(lookAt); + + // Calculate new camera pitch + Vector3 camDir = (gEnv->mainCamera->getPosition() - lookAt).normalisedCopy(); + m_cam_rot_y = asin(camDir.y); + + // Calculate new camera yaw + Vector3 dir = -m_cct_player_actor->getDirection(); + Quaternion rotX = dir.getRotationTo(camDir, Vector3::UNIT_Y); + m_cam_rot_x = rotX.getYaw(); + + // Corner case handling + Radian angle = dir.angleBetween(camDir); + if (angle > Radian(Math::HALF_PI)) + { + if (std::abs(Radian(m_cam_rot_x).valueRadians()) < Math::HALF_PI) + { + if (m_cam_rot_x < Radian(0.0f)) + m_cam_rot_x -= Radian(Math::HALF_PI); + else + m_cam_rot_x += Radian(Math::HALF_PI); + } + } + } + } + + return false; } void CameraManager::CameraBehaviorVehicleSplineUpdate() @@ -1085,14 +961,10 @@ void CameraManager::CameraBehaviorVehicleSplineUpdate() m_cam_target_pitch = 0.0f; if (App::gfx_extcam_mode.GetActive() == GfxExtCamMode::PITCHING) - { - m_cam_target_pitch = -asin(dir.dotProduct(Vector3::UNIT_Y)); - } + { m_cam_target_pitch = -asin(dir.dotProduct(Vector3::UNIT_Y)); } if (m_cct_player_actor->GetAllLinkedActors().size() != m_splinecam_num_linked_beams) - { - this->CameraBehaviorVehicleSplineCreateSpline(); - } + { this->CameraBehaviorVehicleSplineCreateSpline(); } this->CameraBehaviorVehicleSplineUpdateSpline(); this->CameraBehaviorVehicleSplineUpdateSplineDisplay(); @@ -1103,12 +975,14 @@ void CameraManager::CameraBehaviorVehicleSplineUpdate() m_splinecam_auto_tracking = !m_splinecam_auto_tracking; if (m_splinecam_auto_tracking) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Auto tracking enabled"), "camera_go.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("Auto tracking enabled"), "camera_go.png", 3000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Auto tracking enabled")); } else { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Auto tracking disabled"), "camera_go.png", 3000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, + _L("Auto tracking disabled"), "camera_go.png", 3000); RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Auto tracking disabled")); } } @@ -1120,18 +994,17 @@ void CameraManager::CameraBehaviorVehicleSplineUpdate() { centerDir.normalise(); Radian oldTargetDirection = m_cam_target_direction; - m_cam_target_direction = -atan2(centerDir.dotProduct(Vector3::UNIT_X), centerDir.dotProduct(-Vector3::UNIT_Z)); - if (m_cam_target_direction.valueRadians() * oldTargetDirection.valueRadians() < 0.0f && centerDir.length() < m_cam_dist_min) - { - m_cam_rot_x = -m_cam_rot_x; - } + m_cam_target_direction = -atan2(centerDir.dotProduct(Vector3::UNIT_X), centerDir.dotProduct(-Vector3::UNIT_Z)); + if (m_cam_target_direction.valueRadians() * oldTargetDirection.valueRadians() < 0.0f && + centerDir.length() < m_cam_dist_min) + { m_cam_rot_x = -m_cam_rot_x; } } } CameraManager::CameraBehaviorOrbitUpdate(); } -bool CameraManager::CameraBehaviorVehicleSplineMouseMoved( const OIS::MouseEvent& _arg) +bool CameraManager::CameraBehaviorVehicleSplineMouseMoved(const OIS::MouseEvent &_arg) { const OIS::MouseState ms = _arg.state; @@ -1142,23 +1015,15 @@ bool CameraManager::CameraBehaviorVehicleSplineMouseMoved( const OIS::MouseEven Real splinePosDiff = ms.X.rel * std::max(0.00005f, m_splinecam_spline_len * 0.0000001f); if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) || RoR::App::GetInputEngine()->isKeyDown(OIS::KC_RSHIFT)) - { - splinePosDiff *= 3.0f; - } + { splinePosDiff *= 3.0f; } - if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LMENU)) - { - splinePosDiff *= 0.1f; - } + if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LMENU)) { splinePosDiff *= 0.1f; } m_splinecam_spline_pos += splinePosDiff; if (ms.X.rel > 0 && m_splinecam_spline_pos > 0.99f) { - if (m_splinecam_spline_closed) - { - m_splinecam_spline_pos -= 1.0f; - } + if (m_splinecam_spline_closed) { m_splinecam_spline_pos -= 1.0f; } else { // u - turn @@ -1166,10 +1031,7 @@ bool CameraManager::CameraBehaviorVehicleSplineMouseMoved( const OIS::MouseEven } else if (ms.X.rel < 0 && m_splinecam_spline_pos < 0.01f) { - if (m_splinecam_spline_closed) - { - m_splinecam_spline_pos += 1.0f; - } + if (m_splinecam_spline_closed) { m_splinecam_spline_pos += 1.0f; } else { // u - turn @@ -1199,7 +1061,7 @@ void CameraManager::CameraBehaviorVehicleSplineReset() void CameraManager::CameraBehaviorVehicleSplineCreateSpline() { m_splinecam_spline_closed = false; - m_splinecam_spline_len = 1.0f; + m_splinecam_spline_len = 1.0f; m_splinecam_spline->clear(); m_splinecam_spline_nodes.clear(); @@ -1217,14 +1079,13 @@ void CameraManager::CameraBehaviorVehicleSplineCreateSpline() { for (auto actor : linkedBeams) { - if (actor->ar_num_camera_rails <= 0) - continue; + if (actor->ar_num_camera_rails <= 0) continue; Vector3 curSplineFront = m_splinecam_spline_nodes.front()->AbsPosition; - Vector3 curSplineBack = m_splinecam_spline_nodes.back()->AbsPosition; + Vector3 curSplineBack = m_splinecam_spline_nodes.back()->AbsPosition; Vector3 linkedSplineFront = actor->ar_nodes[actor->ar_camera_rail[0]].AbsPosition; - Vector3 linkedSplineBack = actor->ar_nodes[actor->ar_camera_rail[actor->ar_num_camera_rails - 1]].AbsPosition; + Vector3 linkedSplineBack = actor->ar_nodes[actor->ar_camera_rail[actor->ar_num_camera_rails - 1]].AbsPosition; if (curSplineBack.distance(linkedSplineFront) < 5.0f) { @@ -1263,12 +1124,9 @@ void CameraManager::CameraBehaviorVehicleSplineCreateSpline() } Vector3 firstPoint = m_splinecam_spline->getPoint(0); - Vector3 lastPoint = m_splinecam_spline->getPoint(m_splinecam_spline->getNumPoints() - 1); + Vector3 lastPoint = m_splinecam_spline->getPoint(m_splinecam_spline->getNumPoints() - 1); - if (firstPoint.distance(lastPoint) < 1.0f) - { - m_splinecam_spline_closed = true; - } + if (firstPoint.distance(lastPoint) < 1.0f) { m_splinecam_spline_closed = true; } for (int i = 1; i < m_splinecam_spline->getNumPoints(); i++) { @@ -1279,8 +1137,8 @@ void CameraManager::CameraBehaviorVehicleSplineCreateSpline() if (!m_splinecam_mo && RoR::App::diag_camera.GetActive()) { - m_splinecam_mo = gEnv->sceneManager->createManualObject(); - SceneNode* splineNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + m_splinecam_mo = gEnv->sceneManager->createManualObject(); + SceneNode *splineNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_splinecam_mo->begin("tracks/transred", Ogre::RenderOperation::OT_LINE_STRIP); for (int i = 0; i < SPLINECAM_DRAW_RESOLUTION; i++) @@ -1303,14 +1161,13 @@ void CameraManager::CameraBehaviorVehicleSplineUpdateSpline() void CameraManager::CameraBehaviorVehicleSplineUpdateSplineDisplay() { - if (!m_splinecam_mo) - return; + if (!m_splinecam_mo) return; m_splinecam_mo->beginUpdate(0); for (int i = 0; i < SPLINECAM_DRAW_RESOLUTION; i++) { - Real parametricDist = i / (float)SPLINECAM_DRAW_RESOLUTION; - Vector3 position = m_splinecam_spline->interpolate(parametricDist); + Real parametricDist = i / (float)SPLINECAM_DRAW_RESOLUTION; + Vector3 position = m_splinecam_spline->interpolate(parametricDist); m_splinecam_mo->position(position); } m_splinecam_mo->end(); diff --git a/source/main/gfx/camera/CameraManager.h b/source/main/gfx/camera/CameraManager.h index 44a6f4e003..a0fbb53de3 100644 --- a/source/main/gfx/camera/CameraManager.h +++ b/source/main/gfx/camera/CameraManager.h @@ -24,124 +24,132 @@ #include "RoRPrerequisites.h" #include -#include #include // Degree, Radian #include +#include -namespace RoR { - -class CameraManager +namespace RoR { - friend class SimController; -public: - - CameraManager(); - ~CameraManager(); - - enum CameraBehaviors + class CameraManager { - CAMERA_BEHAVIOR_CHARACTER=0, - CAMERA_BEHAVIOR_STATIC, - CAMERA_BEHAVIOR_VEHICLE, - CAMERA_BEHAVIOR_VEHICLE_SPLINE, - CAMERA_BEHAVIOR_VEHICLE_CINECAM, - CAMERA_BEHAVIOR_END, - CAMERA_BEHAVIOR_FREE, - CAMERA_BEHAVIOR_FIXED, - CAMERA_BEHAVIOR_ISOMETRIC, - CAMERA_BEHAVIOR_INVALID = -1, + friend class SimController; + + public: + CameraManager(); + ~CameraManager(); + + enum CameraBehaviors + { + CAMERA_BEHAVIOR_CHARACTER = 0, + CAMERA_BEHAVIOR_STATIC, + CAMERA_BEHAVIOR_VEHICLE, + CAMERA_BEHAVIOR_VEHICLE_SPLINE, + CAMERA_BEHAVIOR_VEHICLE_CINECAM, + CAMERA_BEHAVIOR_END, + CAMERA_BEHAVIOR_FREE, + CAMERA_BEHAVIOR_FIXED, + CAMERA_BEHAVIOR_ISOMETRIC, + CAMERA_BEHAVIOR_INVALID = -1, + }; + + bool Update(float dt, Actor *player_vehicle, float sim_speed); + + bool gameControlsLocked() const; + bool hasActiveBehavior(); + + CameraBehaviors GetCurrentBehavior() + { + return m_current_behavior; + } + + void NotifyContextChange(); + void NotifyVehicleChanged(Actor *old_vehicle, Actor *new_vehicle); + + void CameraBehaviorOrbitReset(); + bool CameraBehaviorOrbitMouseMoved(const OIS::MouseEvent &_arg); + void CameraBehaviorOrbitUpdate(); + + bool IsCameraReady() const + { + return m_camera_ready; + } // Temporary; replaces (gEnv->cameraManager != nullptr) checks; see == SimCam == + void SetCameraReady() + { + m_camera_ready = true; + } + + protected: + void switchToNextBehavior(); + void switchBehavior(CameraBehaviors new_behavior); + void SwitchBehaviorOnVehicleChange(CameraBehaviors new_behavior, Actor *new_vehicle); + void ToggleCameraBehavior(CameraBehaviors new_behavior); //!< Only accepts FREE and FREEFIX modes + void ActivateNewBehavior(CameraBehaviors new_behavior, bool reset); + bool EvaluateSwitchBehavior(); + void UpdateCurrentBehavior(); + void ResetCurrentBehavior(); + void DeactivateCurrentBehavior(); + void UpdateCameraBehaviorStatic(); + bool CameraBehaviorStaticMouseMoved(const OIS::MouseEvent &_arg); + void UpdateCameraBehaviorFree(); + void UpdateCameraBehaviorFixed(); + void UpdateCameraBehaviorVehicle(); + void CameraBehaviorVehicleReset(); + bool CameraBehaviorVehicleMousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + void CameraBehaviorVehicleSplineUpdate(); + bool CameraBehaviorVehicleSplineMouseMoved(const OIS::MouseEvent &_arg); + void CameraBehaviorVehicleSplineReset(); + void CameraBehaviorVehicleSplineCreateSpline(); + void CameraBehaviorVehicleSplineUpdateSpline(); + void CameraBehaviorVehicleSplineUpdateSplineDisplay(); + + CameraBehaviors m_current_behavior; + CameraBehaviors m_cam_before_toggled; ///< Toggled modes (FREE, FREEFIX) remember original state. + CameraBehaviors m_prev_toggled_cam; ///< Switching toggled modes (FREE, FREEFIX) keeps 1-slot history. + // Old `CameraContext` + Actor * m_cct_player_actor; // TODO: duplicates `SimController::m_player_actor` + Ogre::Degree m_cct_rot_scale; + Ogre::Real m_cct_dt; + Ogre::Real m_cct_trans_scale; + float m_cct_sim_speed; // TODO: duplicates `ActorManager::m_simulation_speed` + // Old `CameraBehaviorOrbit` attributes + Ogre::Radian m_cam_rot_x; + Ogre::Radian m_cam_rot_y; + Ogre::Radian m_cam_target_direction; + Ogre::Radian m_cam_target_pitch; + float m_cam_dist; + float m_cam_dist_min; + float m_cam_dist_max; + float m_cam_ratio; + Ogre::Vector3 m_cam_look_at; + bool m_cam_limit_movement; + Ogre::Vector3 m_cam_look_at_last; + Ogre::Vector3 m_cam_look_at_smooth; + Ogre::Vector3 m_cam_look_at_smooth_last; + // Static cam attributes + bool m_staticcam_force_update; + float m_staticcam_fov_exponent; + Ogre::Radian m_staticcam_previous_fov; + Ogre::Vector3 m_staticcam_look_at; + Ogre::Vector3 m_staticcam_position; + Ogre::Timer m_staticcam_update_timer; + // Character cam attributes + bool m_charactercam_is_3rdperson; + // Spline cam attributes + Ogre::ManualObject * m_splinecam_mo; + Ogre::SimpleSpline * m_splinecam_spline; + Ogre::Real m_splinecam_spline_len; + Ogre::Real m_splinecam_spline_pos; + bool m_splinecam_spline_closed; + bool m_splinecam_auto_tracking; + std::deque m_splinecam_spline_nodes; + unsigned int m_splinecam_num_linked_beams; + + bool m_camera_ready; // Temporary flag; replaces (gEnv->cameraManager != nullptr) checks; see == SimCam == + + public: // Temporary; only for use by SimController (for some reason the friend decl. is not enough); see == SimCam == + bool mouseMoved(const OIS::MouseEvent &_arg); + bool mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); }; - bool Update(float dt, Actor* player_vehicle, float sim_speed); - - bool gameControlsLocked() const; - bool hasActiveBehavior(); - - CameraBehaviors GetCurrentBehavior() { return m_current_behavior; } - - void NotifyContextChange(); - void NotifyVehicleChanged(Actor* old_vehicle, Actor* new_vehicle); - - void CameraBehaviorOrbitReset(); - bool CameraBehaviorOrbitMouseMoved(const OIS::MouseEvent& _arg); - void CameraBehaviorOrbitUpdate(); - - bool IsCameraReady() const { return m_camera_ready; } // Temporary; replaces (gEnv->cameraManager != nullptr) checks; see == SimCam == - void SetCameraReady() { m_camera_ready = true; } - -protected: - - void switchToNextBehavior(); - void switchBehavior(CameraBehaviors new_behavior); - void SwitchBehaviorOnVehicleChange(CameraBehaviors new_behavior, Actor* new_vehicle); - void ToggleCameraBehavior(CameraBehaviors new_behavior); //!< Only accepts FREE and FREEFIX modes - void ActivateNewBehavior(CameraBehaviors new_behavior, bool reset); - bool EvaluateSwitchBehavior(); - void UpdateCurrentBehavior(); - void ResetCurrentBehavior(); - void DeactivateCurrentBehavior(); - void UpdateCameraBehaviorStatic(); - bool CameraBehaviorStaticMouseMoved(const OIS::MouseEvent& _arg); - void UpdateCameraBehaviorFree(); - void UpdateCameraBehaviorFixed(); - void UpdateCameraBehaviorVehicle(); - void CameraBehaviorVehicleReset(); - bool CameraBehaviorVehicleMousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - void CameraBehaviorVehicleSplineUpdate(); - bool CameraBehaviorVehicleSplineMouseMoved(const OIS::MouseEvent& _arg); - void CameraBehaviorVehicleSplineReset(); - void CameraBehaviorVehicleSplineCreateSpline(); - void CameraBehaviorVehicleSplineUpdateSpline(); - void CameraBehaviorVehicleSplineUpdateSplineDisplay(); - - CameraBehaviors m_current_behavior; - CameraBehaviors m_cam_before_toggled; ///< Toggled modes (FREE, FREEFIX) remember original state. - CameraBehaviors m_prev_toggled_cam; ///< Switching toggled modes (FREE, FREEFIX) keeps 1-slot history. - // Old `CameraContext` - Actor* m_cct_player_actor; // TODO: duplicates `SimController::m_player_actor` - Ogre::Degree m_cct_rot_scale; - Ogre::Real m_cct_dt; - Ogre::Real m_cct_trans_scale; - float m_cct_sim_speed; // TODO: duplicates `ActorManager::m_simulation_speed` - // Old `CameraBehaviorOrbit` attributes - Ogre::Radian m_cam_rot_x; - Ogre::Radian m_cam_rot_y; - Ogre::Radian m_cam_target_direction; - Ogre::Radian m_cam_target_pitch; - float m_cam_dist; - float m_cam_dist_min; - float m_cam_dist_max; - float m_cam_ratio; - Ogre::Vector3 m_cam_look_at; - bool m_cam_limit_movement; - Ogre::Vector3 m_cam_look_at_last; - Ogre::Vector3 m_cam_look_at_smooth; - Ogre::Vector3 m_cam_look_at_smooth_last; - // Static cam attributes - bool m_staticcam_force_update; - float m_staticcam_fov_exponent; - Ogre::Radian m_staticcam_previous_fov; - Ogre::Vector3 m_staticcam_look_at; - Ogre::Vector3 m_staticcam_position; - Ogre::Timer m_staticcam_update_timer; - // Character cam attributes - bool m_charactercam_is_3rdperson; - // Spline cam attributes - Ogre::ManualObject* m_splinecam_mo; - Ogre::SimpleSpline* m_splinecam_spline; - Ogre::Real m_splinecam_spline_len; - Ogre::Real m_splinecam_spline_pos; - bool m_splinecam_spline_closed; - bool m_splinecam_auto_tracking; - std::deque m_splinecam_spline_nodes; - unsigned int m_splinecam_num_linked_beams; - - bool m_camera_ready; // Temporary flag; replaces (gEnv->cameraManager != nullptr) checks; see == SimCam == - -public: // Temporary; only for use by SimController (for some reason the friend decl. is not enough); see == SimCam == - bool mouseMoved(const OIS::MouseEvent& _arg); - bool mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); -}; - } // namespace RoR diff --git a/source/main/gfx/camera/PerVehicleCameraContext.h b/source/main/gfx/camera/PerVehicleCameraContext.h index d26a155447..0e9cde0f42 100644 --- a/source/main/gfx/camera/PerVehicleCameraContext.h +++ b/source/main/gfx/camera/PerVehicleCameraContext.h @@ -4,22 +4,22 @@ namespace RoR { -struct PerVehicleCameraContext -{ - enum CameraCtxBehavior + struct PerVehicleCameraContext { - CAMCTX_BEHAVIOR_INVALID, - CAMCTX_BEHAVIOR_EXTERNAL, - CAMCTX_BEHAVIOR_VEHICLE_3rdPERSON, - CAMCTX_BEHAVIOR_VEHICLE_SPLINE, - CAMCTX_BEHAVIOR_VEHICLE_CINECAM - }; + enum CameraCtxBehavior + { + CAMCTX_BEHAVIOR_INVALID, + CAMCTX_BEHAVIOR_EXTERNAL, + CAMCTX_BEHAVIOR_VEHICLE_3rdPERSON, + CAMCTX_BEHAVIOR_VEHICLE_SPLINE, + CAMCTX_BEHAVIOR_VEHICLE_CINECAM + }; - PerVehicleCameraContext(): - behavior(CAMCTX_BEHAVIOR_EXTERNAL) - {} + PerVehicleCameraContext() : behavior(CAMCTX_BEHAVIOR_EXTERNAL) + { + } - CameraCtxBehavior behavior; -}; + CameraCtxBehavior behavior; + }; } // namespace RoR diff --git a/source/main/gfx/hydrax/CfgFileManager.cpp b/source/main/gfx/hydrax/CfgFileManager.cpp index d9833e6268..6df0850f68 100644 --- a/source/main/gfx/hydrax/CfgFileManager.cpp +++ b/source/main/gfx/hydrax/CfgFileManager.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -27,391 +27,352 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace Hydrax { - CfgFileManager::CfgFileManager(Hydrax* h) - : mHydrax(h) - { - } - - CfgFileManager::~CfgFileManager() - { - } - - const bool CfgFileManager::load(const Ogre::String& File) const - { - std::pair CfgFileResult; - _loadCfgFile(File, CfgFileResult); - - if (!CfgFileResult.first) - { - return false; - } - - Ogre::ConfigFile &CfgFile = CfgFileResult.second; - - if (!_checkVersion(CfgFile)) - { - return false; - } - - // Load main options - mHydrax->setPosition(_getVector3Value(CfgFile,"Position")); - mHydrax->setPlanesError(_getFloatValue(CfgFile,"PlanesError")); - mHydrax->setShaderMode(static_cast(_getIntValue(CfgFile, "ShaderMode"))); - mHydrax->setFullReflectionDistance(_getFloatValue(CfgFile,"FullReflectionDistance")); - mHydrax->setGlobalTransparency(_getFloatValue(CfgFile,"GlobalTransparency")); - mHydrax->setNormalDistortion(_getFloatValue(CfgFile,"NormalDistortion")); - mHydrax->setWaterColor(_getVector3Value(CfgFile,"WaterColor")); - - // Load components settings - _loadComponentsSettings(CfgFile); - - // Load rtt settings - _loadRttSettings(CfgFile); - - // Load module and noise settings - if (mHydrax->getModule()) - { - mHydrax->getModule()->loadCfg(CfgFile); - - if (mHydrax->getModule()->getNoise()) - { - mHydrax->getModule()->getNoise()->loadCfg(CfgFile); - } - } - - return true; - } - - const bool CfgFileManager::save(const Ogre::String& File, const Ogre::String& Path) const - { - Ogre::String Data = - "#Hydrax cfg file.\n\n"; - - Data += "#Hydrax version field\n"; - Data += _getVersionCfgString(); - - Data += "#Main options field\n"; - Data += _getCfgString("Position", mHydrax->getPosition()); - Data += _getCfgString("PlanesError", mHydrax->getPlanesError()); - Data += "#Shader mode: 0=HLSL, 1=CG, 2=GLSL\n"; - Data += _getCfgString("ShaderMode", static_cast(mHydrax->getShaderMode())); - Data += _getCfgString("FullReflectionDistance", mHydrax->getFullReflectionDistance()); - Data += _getCfgString("GlobalTransparency", mHydrax->getGlobalTransparency()); - Data += _getCfgString("NormalDistortion", mHydrax->getNormalDistortion()); - Data += _getCfgString("WaterColor", mHydrax->getWaterColor()); Data += "\n"; - - Data += "#Components field\n"; - Data += _getComponentsCfgString(); - - Data += "#Rtt quality field(0x0 = Auto)\n"; - Data += _getRttCfgString(); Data += "\n"; - - if (mHydrax->getModule()) - { - mHydrax->getModule()->saveCfg(Data); - - if (mHydrax->getModule()->getNoise()) - { - mHydrax->getModule()->getNoise()->saveCfg(Data); - } - } - - return _saveToFile(Data, File, Path); - } - - const bool CfgFileManager::_saveToFile(const Ogre::String& Data, const Ogre::String& File, const Ogre::String& Path) const - { - FILE *DestinationFile = fopen((Path+"/"+File).c_str(), "w"); - - if (!DestinationFile) - { - return false; - } - - fprintf(DestinationFile, "%s", Data.c_str()); - fclose(DestinationFile); - - HydraxLOG(File + " saved in " + Path + " ."); - - return true; - } - - const void CfgFileManager::_loadCfgFile(const Ogre::String& File, std::pair &Result) const - { - try - { - Result.second.load(Ogre::ResourceGroupManager::getSingleton().openResource(File, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)); - Result.first = true; - - } catch(...) - { - HydraxLOG("CfgFileManager::_getCfgFile(...): " + File + " not found in any resource group."); - Result.first = false; - } - - HydraxLOG(File + " loaded."); - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const int &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Real &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const bool &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector2 &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + Ogre::StringConverter::toString(Value.y) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector3 &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + Ogre::StringConverter::toString(Value.y) + "x" + Ogre::StringConverter::toString(Value.z) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String& Name, const Size& Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value.Width) + "x" + Ogre::StringConverter::toString(Value.Height) + "\n"; - } - - const Ogre::String CfgFileManager::_getComponentsCfgString() const - { - Ogre::String Cmpnts = "Components="; - - std::pair Cmp[8] = { - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_SUN), "Sun"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_FOAM), "Foam"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_DEPTH), "Depth"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_SMOOTH), "Smooth"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_CAUSTICS), "Caustics"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER), "Underwater"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS), "UnderwaterReflections"), - std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS), "UnderwaterGodRays"),}; - - for (int k = 0; k < 8; k++) - { - if (Cmp[k].first) - { - Cmpnts += Cmp[k].second; - - bool isLast = true; - - for (int u = k+1; u < 8; u++) - { - if (Cmp[u].first) - { - isLast = false; - } - } - - if (!isLast) - { - Cmpnts += "|"; - } - else - { - Cmpnts += "\n\n"; - } - } - } - - // Sun parameters - if (Cmp[0].first) - { - Cmpnts += "#Sun parameters\n"; - Cmpnts += _getCfgString("SunPosition", mHydrax->getSunPosition()); - Cmpnts += _getCfgString("SunStrength", mHydrax->getSunStrength()); - Cmpnts += _getCfgString("SunArea", mHydrax->getSunArea()); - Cmpnts += _getCfgString("SunColor", mHydrax->getSunColor()); Cmpnts += "\n"; - } - // Foam parameters - if (Cmp[1].first) - { - Cmpnts += "#Foam parameters\n"; - Cmpnts += _getCfgString("FoamMaxDistance", mHydrax->getFoamMaxDistance()); - Cmpnts += _getCfgString("FoamScale", mHydrax->getFoamScale()); - Cmpnts += _getCfgString("FoamStart", mHydrax->getFoamStart()); - Cmpnts += _getCfgString("FoamTransparency", mHydrax->getFoamTransparency()); Cmpnts += "\n"; - } - // Depth parameters - if (Cmp[2].first) - { - Cmpnts += "#Depth parameters\n"; - Cmpnts += _getCfgString("DepthLimit", mHydrax->getDepthLimit()); Cmpnts += "\n"; - } - // Smooth transitions parameters - if (Cmp[3].first) - { - Cmpnts += "#Smooth transitions parameters\n"; - Cmpnts += _getCfgString("SmoothPower", mHydrax->getSmoothPower()); Cmpnts += "\n"; - } - // Caustics parameters - if (Cmp[4].first) - { - Cmpnts += "#Caustics parameters\n"; - Cmpnts += _getCfgString("CausticsScale", mHydrax->getCausticsScale()); - Cmpnts += _getCfgString("CausticsPower", mHydrax->getCausticsPower()); - Cmpnts += _getCfgString("CausticsEnd", mHydrax->getCausticsEnd()); Cmpnts += "\n"; - } - // God rays parameters - if (Cmp[7].first) - { - Cmpnts += "#God rays parameters\n"; - Cmpnts += _getCfgString("GodRaysExposure", mHydrax->getGodRaysExposure()); - Cmpnts += _getCfgString("GodRaysIntensity", mHydrax->getGodRaysIntensity()); - Cmpnts += _getCfgString("GodRaysSpeed", mHydrax->getGodRaysManager()->getSimulationSpeed()); - Cmpnts += _getCfgString("GodRaysNumberOfRays", mHydrax->getGodRaysManager()->getNumberOfRays()); - Cmpnts += _getCfgString("GodRaysRaysSize", mHydrax->getGodRaysManager()->getRaysSize()); - Cmpnts += _getCfgString("GodRaysIntersections", mHydrax->getGodRaysManager()->areObjectsIntersectionsEnabled()); Cmpnts += "\n"; - } - - return Cmpnts; - } - - bool CfgFileManager::_isStringInList(const Ogre::StringVector &List, const Ogre::String &Find) - { - for (unsigned int k = 0; k < List.size(); k++) - { - if (List[k] == Find) - { - return true; - } - } - - return false; - } - - const void CfgFileManager::_loadComponentsSettings(Ogre::ConfigFile& CfgFile) const - { - Ogre::StringVector Cmpnts = Ogre::StringUtil::split(CfgFile.getSetting("Components"), "|"); - - HydraxComponent ComponentsToLoad[8] = { - HYDRAX_COMPONENTS_NONE,HYDRAX_COMPONENTS_NONE,HYDRAX_COMPONENTS_NONE,HYDRAX_COMPONENTS_NONE, - HYDRAX_COMPONENTS_NONE,HYDRAX_COMPONENTS_NONE,HYDRAX_COMPONENTS_NONE,HYDRAX_COMPONENTS_NONE}; - - if (_isStringInList(Cmpnts, "Sun")) - { - ComponentsToLoad[0] = HYDRAX_COMPONENT_SUN; - } - if (_isStringInList(Cmpnts, "Foam")) - { - ComponentsToLoad[1] = HYDRAX_COMPONENT_FOAM; - } - if (_isStringInList(Cmpnts, "Depth")) - { - ComponentsToLoad[2] = HYDRAX_COMPONENT_DEPTH; - } - if (_isStringInList(Cmpnts, "Smooth")) - { - ComponentsToLoad[3] = HYDRAX_COMPONENT_SMOOTH; - } - if (_isStringInList(Cmpnts, "Caustics")) - { - ComponentsToLoad[4] = HYDRAX_COMPONENT_CAUSTICS; - } - if (_isStringInList(Cmpnts, "Underwater")) - { - ComponentsToLoad[5] = HYDRAX_COMPONENT_UNDERWATER; - } - if (_isStringInList(Cmpnts, "UnderwaterReflections")) - { - ComponentsToLoad[6] = HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS; - } - if (_isStringInList(Cmpnts, "UnderwaterGodRays")) - { - ComponentsToLoad[7] = HYDRAX_COMPONENT_UNDERWATER_GODRAYS; - } - - mHydrax->setComponents(static_cast( - ComponentsToLoad[0] | ComponentsToLoad[1] | ComponentsToLoad[2] | ComponentsToLoad[3] | - ComponentsToLoad[4] | ComponentsToLoad[5] | ComponentsToLoad[6] | ComponentsToLoad[7])); - - if (_isStringInList(Cmpnts, "Sun")) - { - mHydrax->setSunPosition(_getVector3Value(CfgFile,"SunPosition")); - mHydrax->setSunStrength(_getFloatValue(CfgFile,"SunStrength")); - mHydrax->setSunArea(_getFloatValue(CfgFile,"SunArea")); - mHydrax->setSunColor(_getVector3Value(CfgFile,"SunColor")); - } - - if (_isStringInList(Cmpnts, "Foam")) - { - mHydrax->setFoamMaxDistance(_getFloatValue(CfgFile,"FoamMaxDistance")); - mHydrax->setFoamScale(_getFloatValue(CfgFile,"FoamScale")); - mHydrax->setFoamStart(_getFloatValue(CfgFile,"FoamStart")); - mHydrax->setFoamTransparency(_getFloatValue(CfgFile,"FoamTransparency")); - } - - if (_isStringInList(Cmpnts, "Depth")) - { - mHydrax->setDepthLimit(_getFloatValue(CfgFile,"DepthLimit")); - mHydrax->setDistLimit(_getFloatValue(CfgFile,"DistLimit")); - } - - if (_isStringInList(Cmpnts, "Smooth")) - { - mHydrax->setSmoothPower(_getFloatValue(CfgFile,"SmoothPower")); - } - - if (_isStringInList(Cmpnts, "Caustics")) - { - mHydrax->setCausticsScale(_getFloatValue(CfgFile,"CausticsScale")); - mHydrax->setCausticsPower(_getFloatValue(CfgFile,"CausticsPower")); - mHydrax->setCausticsEnd(_getFloatValue(CfgFile,"CausticsEnd")); - } - - if (_isStringInList(Cmpnts, "UnderwaterGodRays")) - { - mHydrax->setGodRaysExposure(_getVector3Value(CfgFile,"GodRaysExposure")); - mHydrax->setGodRaysIntensity(_getFloatValue(CfgFile,"GodRaysIntensity")); - mHydrax->getGodRaysManager()->SetSimulationSpeed(_getFloatValue(CfgFile,"GodRaysSpeed")); - mHydrax->getGodRaysManager()->setNumberOfRays(_getIntValue(CfgFile,"GodRaysNumberOfRays")); - mHydrax->getGodRaysManager()->setRaysSize(_getFloatValue(CfgFile,"GodRaysRaysSize")); - mHydrax->getGodRaysManager()->setObjectIntersectionsEnabled(_getBoolValue(CfgFile,"GodRaysIntersections")); - } - } - - const Ogre::String CfgFileManager::_getRttCfgString() const - { - return - _getCfgString("Rtt_Quality_Reflection", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_REFLECTION)) + - _getCfgString("Rtt_Quality_Refraction", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_REFRACTION)) + - _getCfgString("Rtt_Quality_Depth", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_DEPTH)) + - _getCfgString("Rtt_Quality_URDepth", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_DEPTH_REFLECTION)) + - _getCfgString("Rtt_Quality_GPUNormalMap", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_GPU_NORMAL_MAP)); - } - - const void CfgFileManager::_loadRttSettings(Ogre::ConfigFile& CfgFile) const - { - mHydrax->getRttManager()->setTextureSize(RttManager::RTT_REFLECTION,_getSizeValue(CfgFile,"Rtt_Quality_Reflection")); - mHydrax->getRttManager()->setTextureSize(RttManager::RTT_REFRACTION,_getSizeValue(CfgFile,"Rtt_Quality_Refraction")); - mHydrax->getRttManager()->setTextureSize(RttManager::RTT_DEPTH,_getSizeValue(CfgFile,"Rtt_Quality_Depth")); - mHydrax->getRttManager()->setTextureSize(RttManager::RTT_DEPTH_REFLECTION,_getSizeValue(CfgFile,"Rtt_Quality_URDepth")); - mHydrax->getRttManager()->setTextureSize(RttManager::RTT_GPU_NORMAL_MAP,_getSizeValue(CfgFile,"Rtt_Quality_GPUNormalMap")); - } - - const Ogre::String CfgFileManager::_getVersionCfgString() const - { - return "HydraxVersion=" + - // Major - Ogre::StringConverter::toString(HYDRAX_VERSION_MAJOR)+"." + - // Minor - Ogre::StringConverter::toString(HYDRAX_VERSION_MINOR)+"." + - // Patch - Ogre::StringConverter::toString(HYDRAX_VERSION_PATCH)+"\n\n"; - } - - const bool CfgFileManager::_checkVersion(Ogre::ConfigFile& CfgFile) const - { - // accept any + CfgFileManager::CfgFileManager(Hydrax *h) : mHydrax(h) + { + } + + CfgFileManager::~CfgFileManager() + { + } + + const bool CfgFileManager::load(const Ogre::String &File) const + { + std::pair CfgFileResult; + _loadCfgFile(File, CfgFileResult); + + if (!CfgFileResult.first) { return false; } + + Ogre::ConfigFile &CfgFile = CfgFileResult.second; + + if (!_checkVersion(CfgFile)) { return false; } + + // Load main options + mHydrax->setPosition(_getVector3Value(CfgFile, "Position")); + mHydrax->setPlanesError(_getFloatValue(CfgFile, "PlanesError")); + mHydrax->setShaderMode(static_cast(_getIntValue(CfgFile, "ShaderMode"))); + mHydrax->setFullReflectionDistance(_getFloatValue(CfgFile, "FullReflectionDistance")); + mHydrax->setGlobalTransparency(_getFloatValue(CfgFile, "GlobalTransparency")); + mHydrax->setNormalDistortion(_getFloatValue(CfgFile, "NormalDistortion")); + mHydrax->setWaterColor(_getVector3Value(CfgFile, "WaterColor")); + + // Load components settings + _loadComponentsSettings(CfgFile); + + // Load rtt settings + _loadRttSettings(CfgFile); + + // Load module and noise settings + if (mHydrax->getModule()) + { + mHydrax->getModule()->loadCfg(CfgFile); + + if (mHydrax->getModule()->getNoise()) { mHydrax->getModule()->getNoise()->loadCfg(CfgFile); } + } + + return true; + } + + const bool CfgFileManager::save(const Ogre::String &File, const Ogre::String &Path) const + { + Ogre::String Data = "#Hydrax cfg file.\n\n"; + + Data += "#Hydrax version field\n"; + Data += _getVersionCfgString(); + + Data += "#Main options field\n"; + Data += _getCfgString("Position", mHydrax->getPosition()); + Data += _getCfgString("PlanesError", mHydrax->getPlanesError()); + Data += "#Shader mode: 0=HLSL, 1=CG, 2=GLSL\n"; + Data += _getCfgString("ShaderMode", static_cast(mHydrax->getShaderMode())); + Data += _getCfgString("FullReflectionDistance", mHydrax->getFullReflectionDistance()); + Data += _getCfgString("GlobalTransparency", mHydrax->getGlobalTransparency()); + Data += _getCfgString("NormalDistortion", mHydrax->getNormalDistortion()); + Data += _getCfgString("WaterColor", mHydrax->getWaterColor()); + Data += "\n"; + + Data += "#Components field\n"; + Data += _getComponentsCfgString(); + + Data += "#Rtt quality field(0x0 = Auto)\n"; + Data += _getRttCfgString(); + Data += "\n"; + + if (mHydrax->getModule()) + { + mHydrax->getModule()->saveCfg(Data); + + if (mHydrax->getModule()->getNoise()) { mHydrax->getModule()->getNoise()->saveCfg(Data); } + } + + return _saveToFile(Data, File, Path); + } + + const bool CfgFileManager::_saveToFile(const Ogre::String &Data, const Ogre::String &File, const Ogre::String &Path) const + { + FILE *DestinationFile = fopen((Path + "/" + File).c_str(), "w"); + + if (!DestinationFile) { return false; } + + fprintf(DestinationFile, "%s", Data.c_str()); + fclose(DestinationFile); + + HydraxLOG(File + " saved in " + Path + " ."); + + return true; + } + + const void CfgFileManager::_loadCfgFile(const Ogre::String &File, std::pair &Result) const + { + try + { + Result.second.load(Ogre::ResourceGroupManager::getSingleton().openResource( + File, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)); + Result.first = true; + } + catch (...) + { + HydraxLOG("CfgFileManager::_getCfgFile(...): " + File + " not found in any resource group."); + Result.first = false; + } + + HydraxLOG(File + " loaded."); + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const int &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Real &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const bool &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector2 &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + + Ogre::StringConverter::toString(Value.y) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector3 &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + + Ogre::StringConverter::toString(Value.y) + "x" + Ogre::StringConverter::toString(Value.z) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Size &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value.Width) + "x" + + Ogre::StringConverter::toString(Value.Height) + "\n"; + } + + const Ogre::String CfgFileManager::_getComponentsCfgString() const + { + Ogre::String Cmpnts = "Components="; + + std::pair Cmp[8] = { + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_SUN), "Sun"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_FOAM), "Foam"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_DEPTH), "Depth"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_SMOOTH), "Smooth"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_CAUSTICS), "Caustics"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER), "Underwater"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS), "UnderwaterReflections"), + std::pair(mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS), "UnderwaterGodRays"), + }; + + for (int k = 0; k < 8; k++) + { + if (Cmp[k].first) + { + Cmpnts += Cmp[k].second; + + bool isLast = true; + + for (int u = k + 1; u < 8; u++) + { + if (Cmp[u].first) { isLast = false; } + } + + if (!isLast) { Cmpnts += "|"; } + else + { + Cmpnts += "\n\n"; + } + } + } + + // Sun parameters + if (Cmp[0].first) + { + Cmpnts += "#Sun parameters\n"; + Cmpnts += _getCfgString("SunPosition", mHydrax->getSunPosition()); + Cmpnts += _getCfgString("SunStrength", mHydrax->getSunStrength()); + Cmpnts += _getCfgString("SunArea", mHydrax->getSunArea()); + Cmpnts += _getCfgString("SunColor", mHydrax->getSunColor()); + Cmpnts += "\n"; + } + // Foam parameters + if (Cmp[1].first) + { + Cmpnts += "#Foam parameters\n"; + Cmpnts += _getCfgString("FoamMaxDistance", mHydrax->getFoamMaxDistance()); + Cmpnts += _getCfgString("FoamScale", mHydrax->getFoamScale()); + Cmpnts += _getCfgString("FoamStart", mHydrax->getFoamStart()); + Cmpnts += _getCfgString("FoamTransparency", mHydrax->getFoamTransparency()); + Cmpnts += "\n"; + } + // Depth parameters + if (Cmp[2].first) + { + Cmpnts += "#Depth parameters\n"; + Cmpnts += _getCfgString("DepthLimit", mHydrax->getDepthLimit()); + Cmpnts += "\n"; + } + // Smooth transitions parameters + if (Cmp[3].first) + { + Cmpnts += "#Smooth transitions parameters\n"; + Cmpnts += _getCfgString("SmoothPower", mHydrax->getSmoothPower()); + Cmpnts += "\n"; + } + // Caustics parameters + if (Cmp[4].first) + { + Cmpnts += "#Caustics parameters\n"; + Cmpnts += _getCfgString("CausticsScale", mHydrax->getCausticsScale()); + Cmpnts += _getCfgString("CausticsPower", mHydrax->getCausticsPower()); + Cmpnts += _getCfgString("CausticsEnd", mHydrax->getCausticsEnd()); + Cmpnts += "\n"; + } + // God rays parameters + if (Cmp[7].first) + { + Cmpnts += "#God rays parameters\n"; + Cmpnts += _getCfgString("GodRaysExposure", mHydrax->getGodRaysExposure()); + Cmpnts += _getCfgString("GodRaysIntensity", mHydrax->getGodRaysIntensity()); + Cmpnts += _getCfgString("GodRaysSpeed", mHydrax->getGodRaysManager()->getSimulationSpeed()); + Cmpnts += _getCfgString("GodRaysNumberOfRays", mHydrax->getGodRaysManager()->getNumberOfRays()); + Cmpnts += _getCfgString("GodRaysRaysSize", mHydrax->getGodRaysManager()->getRaysSize()); + Cmpnts += _getCfgString("GodRaysIntersections", mHydrax->getGodRaysManager()->areObjectsIntersectionsEnabled()); + Cmpnts += "\n"; + } + + return Cmpnts; + } + + bool CfgFileManager::_isStringInList(const Ogre::StringVector &List, const Ogre::String &Find) + { + for (unsigned int k = 0; k < List.size(); k++) + { + if (List[k] == Find) { return true; } + } + + return false; + } + + const void CfgFileManager::_loadComponentsSettings(Ogre::ConfigFile &CfgFile) const + { + Ogre::StringVector Cmpnts = Ogre::StringUtil::split(CfgFile.getSetting("Components"), "|"); + + HydraxComponent ComponentsToLoad[8] = {HYDRAX_COMPONENTS_NONE, HYDRAX_COMPONENTS_NONE, HYDRAX_COMPONENTS_NONE, + HYDRAX_COMPONENTS_NONE, HYDRAX_COMPONENTS_NONE, HYDRAX_COMPONENTS_NONE, + HYDRAX_COMPONENTS_NONE, HYDRAX_COMPONENTS_NONE}; + + if (_isStringInList(Cmpnts, "Sun")) { ComponentsToLoad[0] = HYDRAX_COMPONENT_SUN; } + if (_isStringInList(Cmpnts, "Foam")) { ComponentsToLoad[1] = HYDRAX_COMPONENT_FOAM; } + if (_isStringInList(Cmpnts, "Depth")) { ComponentsToLoad[2] = HYDRAX_COMPONENT_DEPTH; } + if (_isStringInList(Cmpnts, "Smooth")) { ComponentsToLoad[3] = HYDRAX_COMPONENT_SMOOTH; } + if (_isStringInList(Cmpnts, "Caustics")) { ComponentsToLoad[4] = HYDRAX_COMPONENT_CAUSTICS; } + if (_isStringInList(Cmpnts, "Underwater")) { ComponentsToLoad[5] = HYDRAX_COMPONENT_UNDERWATER; } + if (_isStringInList(Cmpnts, "UnderwaterReflections")) { ComponentsToLoad[6] = HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS; } + if (_isStringInList(Cmpnts, "UnderwaterGodRays")) { ComponentsToLoad[7] = HYDRAX_COMPONENT_UNDERWATER_GODRAYS; } + + mHydrax->setComponents(static_cast(ComponentsToLoad[0] | ComponentsToLoad[1] | ComponentsToLoad[2] | + ComponentsToLoad[3] | ComponentsToLoad[4] | ComponentsToLoad[5] | + ComponentsToLoad[6] | ComponentsToLoad[7])); + + if (_isStringInList(Cmpnts, "Sun")) + { + mHydrax->setSunPosition(_getVector3Value(CfgFile, "SunPosition")); + mHydrax->setSunStrength(_getFloatValue(CfgFile, "SunStrength")); + mHydrax->setSunArea(_getFloatValue(CfgFile, "SunArea")); + mHydrax->setSunColor(_getVector3Value(CfgFile, "SunColor")); + } + + if (_isStringInList(Cmpnts, "Foam")) + { + mHydrax->setFoamMaxDistance(_getFloatValue(CfgFile, "FoamMaxDistance")); + mHydrax->setFoamScale(_getFloatValue(CfgFile, "FoamScale")); + mHydrax->setFoamStart(_getFloatValue(CfgFile, "FoamStart")); + mHydrax->setFoamTransparency(_getFloatValue(CfgFile, "FoamTransparency")); + } + + if (_isStringInList(Cmpnts, "Depth")) + { + mHydrax->setDepthLimit(_getFloatValue(CfgFile, "DepthLimit")); + mHydrax->setDistLimit(_getFloatValue(CfgFile, "DistLimit")); + } + + if (_isStringInList(Cmpnts, "Smooth")) { mHydrax->setSmoothPower(_getFloatValue(CfgFile, "SmoothPower")); } + + if (_isStringInList(Cmpnts, "Caustics")) + { + mHydrax->setCausticsScale(_getFloatValue(CfgFile, "CausticsScale")); + mHydrax->setCausticsPower(_getFloatValue(CfgFile, "CausticsPower")); + mHydrax->setCausticsEnd(_getFloatValue(CfgFile, "CausticsEnd")); + } + + if (_isStringInList(Cmpnts, "UnderwaterGodRays")) + { + mHydrax->setGodRaysExposure(_getVector3Value(CfgFile, "GodRaysExposure")); + mHydrax->setGodRaysIntensity(_getFloatValue(CfgFile, "GodRaysIntensity")); + mHydrax->getGodRaysManager()->SetSimulationSpeed(_getFloatValue(CfgFile, "GodRaysSpeed")); + mHydrax->getGodRaysManager()->setNumberOfRays(_getIntValue(CfgFile, "GodRaysNumberOfRays")); + mHydrax->getGodRaysManager()->setRaysSize(_getFloatValue(CfgFile, "GodRaysRaysSize")); + mHydrax->getGodRaysManager()->setObjectIntersectionsEnabled(_getBoolValue(CfgFile, "GodRaysIntersections")); + } + } + + const Ogre::String CfgFileManager::_getRttCfgString() const + { + return _getCfgString("Rtt_Quality_Reflection", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_REFLECTION)) + + _getCfgString("Rtt_Quality_Refraction", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_REFRACTION)) + + _getCfgString("Rtt_Quality_Depth", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_DEPTH)) + + _getCfgString("Rtt_Quality_URDepth", mHydrax->getRttManager()->getTextureSize(RttManager::RTT_DEPTH_REFLECTION)) + + _getCfgString("Rtt_Quality_GPUNormalMap", + mHydrax->getRttManager()->getTextureSize(RttManager::RTT_GPU_NORMAL_MAP)); + } + + const void CfgFileManager::_loadRttSettings(Ogre::ConfigFile &CfgFile) const + { + mHydrax->getRttManager()->setTextureSize(RttManager::RTT_REFLECTION, _getSizeValue(CfgFile, "Rtt_Quality_Reflection")); + mHydrax->getRttManager()->setTextureSize(RttManager::RTT_REFRACTION, _getSizeValue(CfgFile, "Rtt_Quality_Refraction")); + mHydrax->getRttManager()->setTextureSize(RttManager::RTT_DEPTH, _getSizeValue(CfgFile, "Rtt_Quality_Depth")); + mHydrax->getRttManager()->setTextureSize(RttManager::RTT_DEPTH_REFLECTION, _getSizeValue(CfgFile, "Rtt_Quality_URDepth")); + mHydrax->getRttManager()->setTextureSize(RttManager::RTT_GPU_NORMAL_MAP, + _getSizeValue(CfgFile, "Rtt_Quality_GPUNormalMap")); + } + + const Ogre::String CfgFileManager::_getVersionCfgString() const + { + return "HydraxVersion=" + + // Major + Ogre::StringConverter::toString(HYDRAX_VERSION_MAJOR) + "." + + // Minor + Ogre::StringConverter::toString(HYDRAX_VERSION_MINOR) + "." + + // Patch + Ogre::StringConverter::toString(HYDRAX_VERSION_PATCH) + "\n\n"; + } + + const bool CfgFileManager::_checkVersion(Ogre::ConfigFile &CfgFile) const + { + // accept any #if 0 if(CfgFile.getSetting("HydraxVersion") != ( // Major @@ -426,94 +387,76 @@ namespace Hydrax return false; } #endif // 0 - return true; - } - - int CfgFileManager::_getIntValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return 0; - } - else - { - return Ogre::StringConverter::parseInt(Value); - } - } - - Ogre::Real CfgFileManager::_getFloatValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return 0; - } - else - { - return Ogre::StringConverter::parseReal(Value); - } - } - - bool CfgFileManager::_getBoolValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return false; - } - else - { - return Ogre::StringConverter::parseBool(Value); - } - } - - Ogre::Vector2 CfgFileManager::_getVector2Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Ogre::Vector2(0,0); - } - else - { - return Ogre::Vector2(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1])); - } - } - - Ogre::Vector3 CfgFileManager::_getVector3Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Ogre::Vector3(0,0,0); - } - else - { - return Ogre::Vector3(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[2])); - } - } - - Size CfgFileManager::_getSizeValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Size(0); - } - else - { - return Size(Ogre::StringConverter::parseInt(Ogre::StringUtil::split(Value, "x")[0]), - Ogre::StringConverter::parseInt(Ogre::StringUtil::split(Value, "x")[1])); - } - } -} + return true; + } + + int CfgFileManager::_getIntValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return 0; } + else + { + return Ogre::StringConverter::parseInt(Value); + } + } + + Ogre::Real CfgFileManager::_getFloatValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return 0; } + else + { + return Ogre::StringConverter::parseReal(Value); + } + } + + bool CfgFileManager::_getBoolValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return false; } + else + { + return Ogre::StringConverter::parseBool(Value); + } + } + + Ogre::Vector2 CfgFileManager::_getVector2Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Ogre::Vector2(0, 0); } + else + { + return Ogre::Vector2(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1])); + } + } + + Ogre::Vector3 CfgFileManager::_getVector3Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Ogre::Vector3(0, 0, 0); } + else + { + return Ogre::Vector3(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[2])); + } + } + + Size CfgFileManager::_getSizeValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Size(0); } + else + { + return Size(Ogre::StringConverter::parseInt(Ogre::StringUtil::split(Value, "x")[0]), + Ogre::StringConverter::parseInt(Ogre::StringUtil::split(Value, "x")[1])); + } + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/CfgFileManager.h b/source/main/gfx/hydrax/CfgFileManager.h index eb38929237..44e573cc3b 100644 --- a/source/main/gfx/hydrax/CfgFileManager.h +++ b/source/main/gfx/hydrax/CfgFileManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,188 +25,188 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_CfgFileManager_H_ #define _Hydrax_CfgFileManager_H_ -#include "Prerequisites.h" - #include "Help.h" +#include "Prerequisites.h" namespace Hydrax { - class Hydrax; - - /** Config file manager. - Class to load/save all Hydrax options from/to a config file - */ - class CfgFileManager - { - public: - /** Constructor - @param h Hydrax parent pointer - */ - CfgFileManager(Hydrax *h); - - /** Destructor - */ + class Hydrax; + + /** Config file manager. + Class to load/save all Hydrax options from/to a config file + */ + class CfgFileManager + { + public: + /** Constructor + @param h Hydrax parent pointer + */ + CfgFileManager(Hydrax *h); + + /** Destructor + */ ~CfgFileManager(); - /** Load hydrax cfg file - @param File File name - @return false if an error has been ocurred(Check the log file in this case). - */ - const bool load(const Ogre::String& File) const; - - /** Save current hydrax config to a file - @param File Destination file name - @param Path File path - @return false if an error has been ocurred(Check the log file in this case). - */ - const bool save(const Ogre::String& File, const Ogre::String& Path = "") const; - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return int cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const int& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Ogre::Real cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Ogre::Real& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return bool cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const bool& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Ogre::Vector2 cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Ogre::Vector2& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Ogre::Vector3 cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Ogre::Vector3& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Hydrax::Size cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Size& Value); - - /** Get int value - @param CfgFile Config file - @param Name Parameter name - @return int value - @remarks if the parameter isn't found or the data type is not an int value, return 0 as default - */ - static int _getIntValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get float value - @param CfgFile Config file - @param Name Parameter name - @return float value - @remarks if the parameter isn't found or the data type is not a float value, return 0 as default - */ - static Ogre::Real _getFloatValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get bool value - @param CfgFile Config file - @param Name Parameter name - @return bool value - @remarks if the parameter isn't found or the data type is not a bool value, return false as default - */ - static bool _getBoolValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get vector2 value - @param CfgFile Config file - @param Name Parameter name - @return vector2 value - @remarks if the parameter isn't found or the data type is not an int value, returns (0,0) as default - */ - static Ogre::Vector2 _getVector2Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get vector3 value - @param CfgFile Config file - @param Name Parameter name - @return vector3 value - @remarks if the parameter isn't found or the data type is not an int value, returns (0,0,0) as default - */ - static Ogre::Vector3 _getVector3Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get size value - @param CfgFile Config file - @param Name Parameter name - @return size value - @remarks if the parameter isn't found or the data type is not an int value, returns (0,0) as default - */ - static Size _getSizeValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Check is a std::vector contains a specified Ogre::String - @param List String list - @param Find String to find - @return true if it's contained, false if not - */ - static bool _isStringInList(const Ogre::StringVector &List, const Ogre::String &Find); - - private: - /** Save a string in file - @param Data Data - @param File Destination file - @param Path File path - @return false if an error has ocurred - */ - const bool _saveToFile(const Ogre::String& Data, const Ogre::String& File, const Ogre::String& Path) const; - - /** Load a cfg file in an Ogre::ConfigFile - @param File File name - @param Result, std::pair First: False if the file isn't in the Hydrax resource group, Second: Ogre::ConfigFile - */ - const void _loadCfgFile(const Ogre::String& File, std::pair &Result) const; - - /** Get components config string - @return Components cfg string - */ - const Ogre::String _getComponentsCfgString() const; - - /** Load components settings - @param CfgFile Config file - */ - const void _loadComponentsSettings(Ogre::ConfigFile& CfgFile) const; - - /** Get rtt quality config string - @return Rtt quality cfg string - */ - const Ogre::String _getRttCfgString() const; - - /** Load rtt settings - @param CfgFile Config file - */ - const void _loadRttSettings(Ogre::ConfigFile& CfgFile) const; - - /** Get hydrax version cfg string - @return Hydrax version cfg string - */ - const Ogre::String _getVersionCfgString() const; - - /** Check hydrax version cfg file - @param CfgFile Config file - @return true if it's the same version, false if not. - */ - const bool _checkVersion(Ogre::ConfigFile& CfgFile) const; - - /// Hydrax parent pointer - Hydrax* mHydrax; - }; -}; + /** Load hydrax cfg file + @param File File name + @return false if an error has been ocurred(Check the log file in this case). + */ + const bool load(const Ogre::String &File) const; + + /** Save current hydrax config to a file + @param File Destination file name + @param Path File path + @return false if an error has been ocurred(Check the log file in this case). + */ + const bool save(const Ogre::String &File, const Ogre::String &Path = "") const; + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return int cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const int &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Ogre::Real cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Real &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return bool cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const bool &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Ogre::Vector2 cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Vector2 &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Ogre::Vector3 cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Vector3 &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Hydrax::Size cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Size &Value); + + /** Get int value + @param CfgFile Config file + @param Name Parameter name + @return int value + @remarks if the parameter isn't found or the data type is not an int value, return 0 as default + */ + static int _getIntValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get float value + @param CfgFile Config file + @param Name Parameter name + @return float value + @remarks if the parameter isn't found or the data type is not a float value, return 0 as default + */ + static Ogre::Real _getFloatValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get bool value + @param CfgFile Config file + @param Name Parameter name + @return bool value + @remarks if the parameter isn't found or the data type is not a bool value, return false as default + */ + static bool _getBoolValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get vector2 value + @param CfgFile Config file + @param Name Parameter name + @return vector2 value + @remarks if the parameter isn't found or the data type is not an int value, returns (0,0) as default + */ + static Ogre::Vector2 _getVector2Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get vector3 value + @param CfgFile Config file + @param Name Parameter name + @return vector3 value + @remarks if the parameter isn't found or the data type is not an int value, returns (0,0,0) as default + */ + static Ogre::Vector3 _getVector3Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get size value + @param CfgFile Config file + @param Name Parameter name + @return size value + @remarks if the parameter isn't found or the data type is not an int value, returns (0,0) as default + */ + static Size _getSizeValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Check is a std::vector contains a specified Ogre::String + @param List String list + @param Find String to find + @return true if it's contained, false if not + */ + static bool _isStringInList(const Ogre::StringVector &List, const Ogre::String &Find); + + private: + /** Save a string in file + @param Data Data + @param File Destination file + @param Path File path + @return false if an error has ocurred + */ + const bool _saveToFile(const Ogre::String &Data, const Ogre::String &File, const Ogre::String &Path) const; + + /** Load a cfg file in an Ogre::ConfigFile + @param File File name + @param Result, std::pair First: False if the file isn't in the Hydrax resource group, Second: + Ogre::ConfigFile + */ + const void _loadCfgFile(const Ogre::String &File, std::pair &Result) const; + + /** Get components config string + @return Components cfg string + */ + const Ogre::String _getComponentsCfgString() const; + + /** Load components settings + @param CfgFile Config file + */ + const void _loadComponentsSettings(Ogre::ConfigFile &CfgFile) const; + + /** Get rtt quality config string + @return Rtt quality cfg string + */ + const Ogre::String _getRttCfgString() const; + + /** Load rtt settings + @param CfgFile Config file + */ + const void _loadRttSettings(Ogre::ConfigFile &CfgFile) const; + + /** Get hydrax version cfg string + @return Hydrax version cfg string + */ + const Ogre::String _getVersionCfgString() const; + + /** Check hydrax version cfg file + @param CfgFile Config file + @return true if it's the same version, false if not. + */ + const bool _checkVersion(Ogre::ConfigFile &CfgFile) const; + + /// Hydrax parent pointer + Hydrax *mHydrax; + }; +}; // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/DecalsManager.cpp b/source/main/gfx/hydrax/DecalsManager.cpp index fc0d131b95..a8177e4245 100644 --- a/source/main/gfx/hydrax/DecalsManager.cpp +++ b/source/main/gfx/hydrax/DecalsManager.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -23,303 +23,276 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to */ #include - #include namespace Hydrax { - Decal::Decal(Hydrax *h, const Ogre::String &TextureName, const int& Id) - : mHydrax(h) - , mTextureName(TextureName) - , mId(Id) - , mRegisteredPass(0) - , mPosition(Ogre::Vector2(0,0)) - , mSize(Ogre::Vector2(1,1)) - , mOrientation(Ogre::Radian(0)) - , mTransparency(1) - , mVisible(true) - { - mProjector = new Ogre::Frustum(); - mProjector->setProjectionType(Ogre::PT_ORTHOGRAPHIC); - - mSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + Decal::Decal(Hydrax *h, const Ogre::String &TextureName, const int &Id) + : mHydrax(h), mTextureName(TextureName), mId(Id), mRegisteredPass(0), mPosition(Ogre::Vector2(0, 0)), + mSize(Ogre::Vector2(1, 1)), mOrientation(Ogre::Radian(0)), mTransparency(1), mVisible(true) + { + mProjector = new Ogre::Frustum(); + mProjector->setProjectionType(Ogre::PT_ORTHOGRAPHIC); + + mSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); mSceneNode->attachObject(mProjector); - mSceneNode->setPosition(Ogre::Vector3(0,0,0)); + mSceneNode->setPosition(Ogre::Vector3(0, 0, 0)); mSceneNode->setOrientation(Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::NEGATIVE_UNIT_X)); - setPosition(mPosition); - setSize(mSize); - setOrientation(mOrientation); - } + setPosition(mPosition); + setSize(mSize); + setOrientation(mOrientation); + } - Decal::~Decal() - { - unregister(); + Decal::~Decal() + { + unregister(); - mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); + mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); - delete mProjector; - } + delete mProjector; + } - void Decal::registerPass(Ogre::Pass* _Pass) - { - unregister(); + void Decal::registerPass(Ogre::Pass *_Pass) + { + unregister(); - _Pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - _Pass->setCullingMode(Ogre::CULL_NONE); - _Pass->setDepthBias(1,1); + _Pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); + _Pass->setCullingMode(Ogre::CULL_NONE); + _Pass->setDepthBias(1, 1); _Pass->setLightingEnabled(false); - _Pass->setDepthWriteEnabled(false); + _Pass->setDepthWriteEnabled(false); - Ogre::TextureUnitState *DecalTexture = _Pass->createTextureUnitState(mTextureName); + Ogre::TextureUnitState *DecalTexture = _Pass->createTextureUnitState(mTextureName); DecalTexture->setProjectiveTexturing(true, mProjector); - DecalTexture->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - DecalTexture->setTextureFiltering(Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); - DecalTexture->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, mTransparency); - - mRegisteredPass = _Pass; - } - - void Decal::unregister() - { - if (mRegisteredPass) - { - mRegisteredPass->getParent()->removePass(mRegisteredPass->getIndex()); - mRegisteredPass = static_cast(NULL); - } - } - - void Decal::setPosition(const Ogre::Vector2& Position) - { - mPosition = Position; - - mSceneNode->setPosition(Position.x, 0, Position.y); - } - - void Decal::setSize(const Ogre::Vector2& Size) - { - mSize = Size; - - // This method is only available in the CVS HEAD, - // if you have problems compiling, just comment the - // following line: - mProjector->setOrthoWindow(Size.x, Size.y); - } - - void Decal::setOrientation(const Ogre::Radian& Orientation) - { - mSceneNode->rotate(Ogre::Vector3::UNIT_Z, -mOrientation + Orientation); - - mOrientation = Orientation; - } - - void Decal::setTransparency(const Ogre::Real& Transparency) - { - mTransparency = Transparency; - - if (mRegisteredPass) - { - mRegisteredPass->getTextureUnitState(0) - ->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, mTransparency); - } - } - - void Decal::setVisible(const bool& Visible) - { - mVisible = Visible; - - unregister(); - - mHydrax->getDecalsManager()->_forceToUpdate(); - } - - // -------------------------------------------------------------------- - - DecalsManager::DecalsManager(Hydrax *h) - : mHydrax(h) - , mNextId(0) - , mLastUnderwater(false) - , mWaterStrength(5) - , mForceToUpdate(false) - { - } - - DecalsManager::~DecalsManager() - { - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + DecalTexture->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + DecalTexture->setTextureFiltering(Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); + DecalTexture->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, mTransparency); + + mRegisteredPass = _Pass; + } + + void Decal::unregister() + { + if (mRegisteredPass) { - delete (*DecalIt); - } - - mDecals.clear(); - } - - void DecalsManager::update() - { - if (mHydrax->getCamera()->getDerivedPosition() == mLastPosition && - mHydrax->getCamera()->getDerivedOrientation() == mLastOrientation && - !mForceToUpdate) - { - return; - } - - if (mForceToUpdate) - { - mForceToUpdate = false; - } - - Ogre::Vector2 DPos; - Ogre::Real HHeight = mHydrax->getPosition().y; - Ogre::Vector2 DSize; - Ogre::AxisAlignedBox DecalBox; - - if (mLastUnderwater != mHydrax->_isCurrentFrameUnderwater()) - { - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) - { - if (!(*DecalIt)->isVisible()) - { - continue; - } - - if ((*DecalIt)->getRegisteredPass()) - { - (*DecalIt)->unregister(); - - if (!mHydrax->_isCurrentFrameUnderwater()) - { - (*DecalIt)->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_WATER)-> - getTechnique(0)->createPass()); - } - else - { - (*DecalIt)->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_UNDERWATER)-> - getTechnique(0)->createPass()); - } - } - - } - } - - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + mRegisteredPass->getParent()->removePass(mRegisteredPass->getIndex()); + mRegisteredPass = static_cast(NULL); + } + } + + void Decal::setPosition(const Ogre::Vector2 &Position) + { + mPosition = Position; + + mSceneNode->setPosition(Position.x, 0, Position.y); + } + + void Decal::setSize(const Ogre::Vector2 &Size) + { + mSize = Size; + + // This method is only available in the CVS HEAD, + // if you have problems compiling, just comment the + // following line: + mProjector->setOrthoWindow(Size.x, Size.y); + } + + void Decal::setOrientation(const Ogre::Radian &Orientation) + { + mSceneNode->rotate(Ogre::Vector3::UNIT_Z, -mOrientation + Orientation); + + mOrientation = Orientation; + } + + void Decal::setTransparency(const Ogre::Real &Transparency) + { + mTransparency = Transparency; + + if (mRegisteredPass) { - if (!(*DecalIt)->isVisible()) - { - continue; - } - - DPos = (*DecalIt)->getPosition(); - DSize = (*DecalIt)->getSize()/2; - - DecalBox = Ogre::AxisAlignedBox(DPos.x - DSize.x, HHeight - mWaterStrength, DPos.y - DSize.y, - DPos.x + DSize.x, HHeight + mWaterStrength, DPos.y + DSize.y); - - if (mHydrax->getCamera()->isVisible(DecalBox)) - { - if (!(*DecalIt)->getRegisteredPass()) - { - if (!mHydrax->_isCurrentFrameUnderwater()) - { - (*DecalIt)->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_WATER)-> - getTechnique(0)->createPass()); - } - else - { - (*DecalIt)->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_UNDERWATER)-> - getTechnique(0)->createPass()); - } - } - } - else - { - (*DecalIt)->unregister(); - } - } - - mLastPosition = mHydrax->getCamera()->getDerivedPosition(); - mLastOrientation = mHydrax->getCamera()->getDerivedOrientation(); - mLastUnderwater = mHydrax->_isCurrentFrameUnderwater(); - } - - Decal* DecalsManager::add(const Ogre::String& TextureName) - { - Decal* NewDecal = new Decal(mHydrax, TextureName, mNextId); - - mDecals.push_back(NewDecal); - - if (mHydrax->getMaterialManager()->isCreated()) - { - NewDecal->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_WATER)-> - getTechnique(0)->createPass()); - } - - mNextId++; - - return NewDecal; - } - - Decal* DecalsManager::get(const int& Id) - { - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + mRegisteredPass->getTextureUnitState(0)->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, + 1.0, mTransparency); + } + } + + void Decal::setVisible(const bool &Visible) + { + mVisible = Visible; + + unregister(); + + mHydrax->getDecalsManager()->_forceToUpdate(); + } + + // -------------------------------------------------------------------- + + DecalsManager::DecalsManager(Hydrax *h) + : mHydrax(h), mNextId(0), mLastUnderwater(false), mWaterStrength(5), mForceToUpdate(false) + { + } + + DecalsManager::~DecalsManager() + { + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + { + delete (*DecalIt); + } + + mDecals.clear(); + } + + void DecalsManager::update() + { + if (mHydrax->getCamera()->getDerivedPosition() == mLastPosition && + mHydrax->getCamera()->getDerivedOrientation() == mLastOrientation && !mForceToUpdate) + { return; } + + if (mForceToUpdate) { mForceToUpdate = false; } + + Ogre::Vector2 DPos; + Ogre::Real HHeight = mHydrax->getPosition().y; + Ogre::Vector2 DSize; + Ogre::AxisAlignedBox DecalBox; + + if (mLastUnderwater != mHydrax->_isCurrentFrameUnderwater()) { - if((*DecalIt)->getId() == Id) + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) { - return (*DecalIt); + if (!(*DecalIt)->isVisible()) { continue; } + + if ((*DecalIt)->getRegisteredPass()) + { + (*DecalIt)->unregister(); + + if (!mHydrax->_isCurrentFrameUnderwater()) + { + (*DecalIt)->registerPass(mHydrax->getMaterialManager() + ->getMaterial(MaterialManager::MAT_WATER) + ->getTechnique(0) + ->createPass()); + } + else + { + (*DecalIt)->registerPass(mHydrax->getMaterialManager() + ->getMaterial(MaterialManager::MAT_UNDERWATER) + ->getTechnique(0) + ->createPass()); + } + } } - } + } - return static_cast(NULL); - } + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + { + if (!(*DecalIt)->isVisible()) { continue; } + + DPos = (*DecalIt)->getPosition(); + DSize = (*DecalIt)->getSize() / 2; + + DecalBox = Ogre::AxisAlignedBox(DPos.x - DSize.x, HHeight - mWaterStrength, DPos.y - DSize.y, DPos.x + DSize.x, + HHeight + mWaterStrength, DPos.y + DSize.y); + + if (mHydrax->getCamera()->isVisible(DecalBox)) + { + if (!(*DecalIt)->getRegisteredPass()) + { + if (!mHydrax->_isCurrentFrameUnderwater()) + { + (*DecalIt)->registerPass(mHydrax->getMaterialManager() + ->getMaterial(MaterialManager::MAT_WATER) + ->getTechnique(0) + ->createPass()); + } + else + { + (*DecalIt)->registerPass(mHydrax->getMaterialManager() + ->getMaterial(MaterialManager::MAT_UNDERWATER) + ->getTechnique(0) + ->createPass()); + } + } + } + else + { + (*DecalIt)->unregister(); + } + } + + mLastPosition = mHydrax->getCamera()->getDerivedPosition(); + mLastOrientation = mHydrax->getCamera()->getDerivedOrientation(); + mLastUnderwater = mHydrax->_isCurrentFrameUnderwater(); + } - void DecalsManager::remove(const int& Id) - { - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + Decal *DecalsManager::add(const Ogre::String &TextureName) + { + Decal *NewDecal = new Decal(mHydrax, TextureName, mNextId); + + mDecals.push_back(NewDecal); + + if (mHydrax->getMaterialManager()->isCreated()) { - if((*DecalIt)->getId() == Id) + NewDecal->registerPass( + mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_WATER)->getTechnique(0)->createPass()); + } + + mNextId++; + + return NewDecal; + } + + Decal *DecalsManager::get(const int &Id) + { + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + { + if ((*DecalIt)->getId() == Id) { return (*DecalIt); } + } + + return static_cast(NULL); + } + + void DecalsManager::remove(const int &Id) + { + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + { + if ((*DecalIt)->getId() == Id) { - delete (*DecalIt); - mDecals.erase(DecalIt); + delete (*DecalIt); + mDecals.erase(DecalIt); - return; + return; } - } - } + } + } - void DecalsManager::removeAll() - { - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + void DecalsManager::removeAll() + { + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) { - delete (*DecalIt); - } + delete (*DecalIt); + } - mDecals.clear(); + mDecals.clear(); - mNextId = 0; - } + mNextId = 0; + } - void DecalsManager::registerAll() - { - for(DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) + void DecalsManager::registerAll() + { + for (DecalIt = mDecals.begin(); DecalIt != mDecals.end(); DecalIt++) { - (*DecalIt)->unregister(); - - if (!mHydrax->_isCurrentFrameUnderwater()) - { - (*DecalIt)->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_WATER)-> - getTechnique(0)->createPass()); - } - else - { - (*DecalIt)->registerPass( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_UNDERWATER)-> - getTechnique(0)->createPass()); - } - } - } -} + (*DecalIt)->unregister(); + + if (!mHydrax->_isCurrentFrameUnderwater()) + { + (*DecalIt)->registerPass( + mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_WATER)->getTechnique(0)->createPass()); + } + else + { + (*DecalIt)->registerPass( + mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_UNDERWATER)->getTechnique(0)->createPass()); + } + } + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/DecalsManager.h b/source/main/gfx/hydrax/DecalsManager.h index 92b4b39df9..2258fb2063 100644 --- a/source/main/gfx/hydrax/DecalsManager.h +++ b/source/main/gfx/hydrax/DecalsManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -29,264 +29,264 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace Hydrax { - class Hydrax; - - /** Decal class. - */ - class Decal - { - public: - /** Constructor - @param h Hydrax parent pointer - @param TextureName Texture name - @param Id Decal Id - */ - Decal(Hydrax *h, const Ogre::String &TextureName, const int& Id); - - /** Destructor - */ + class Hydrax; + + /** Decal class. + */ + class Decal + { + public: + /** Constructor + @param h Hydrax parent pointer + @param TextureName Texture name + @param Id Decal Id + */ + Decal(Hydrax *h, const Ogre::String &TextureName, const int &Id); + + /** Destructor + */ ~Decal(); - /** Register the decal int the specified pass - @param _Pass Pass to be registred - */ - void registerPass(Ogre::Pass* _Pass); - - /** Unregister from current technique - */ - void unregister(); - - /** Get decal texture name - @return Decal texture name - */ - inline const Ogre::String& getTextureName() const - { - return mTextureName; - } - - /** Get the decal Id - @return Decal Id - */ - inline const int& getId() const - { - return mId; - } - - /** Get the decal projector - @return Projector frustum - */ - inline Ogre::Frustum* getProjector() - { - return mProjector; - } - - /** Get the decal scene node - @return Decal scene node - */ - inline Ogre::SceneNode* getSceneNode() - { - return mSceneNode; - } - - /** Get the pass the decal is in - @return Registered pass - @remarks return NULL if decal isn't registered - */ - inline Ogre::Pass *getRegisteredPass() - { - return mRegisteredPass; - } - - /** Get decal position - @return Decal position - */ - inline const Ogre::Vector2& getPosition() const - { - return mPosition; - } - - /** Get decal size - @return Decal size - */ - inline const Ogre::Vector2& getSize() const - { - return mSize; - } - - /** Get decal orientation - @return Decal orientation - */ - inline const Ogre::Radian& getOrientation() const - { - return mOrientation; - } - - /** Get decal transparency - @return Decal transparency - */ - inline const Ogre::Real& getTransparency() const - { - return mTransparency; - } - - /** Is decal visile? - @return true if decal is visible - */ - inline const bool& isVisible() const - { - return mVisible; - } - - /** Set decal position - @param Position Decal position - */ - void setPosition(const Ogre::Vector2& Position); - - /** Set decal size - @param Size Decal size in world coordinates - */ - void setSize(const Ogre::Vector2& Size); - - /** Set decal orientation - @param Orientation Decal orientation - */ - void setOrientation(const Ogre::Radian& Orientation); - - /** Set decal transparency - @param Transparency Decal transparency in [0,1] range - @remarks 0 = Full transparent, 1 = Full opacity - */ - void setTransparency(const Ogre::Real& Transparency); - - /** Set decal visibile or not - @param Visible true if yes, false if not - */ - void setVisible(const bool& Visible); - - private: - /// Decal texture name - Ogre::String mTextureName; - /// Decal Id - int mId; - /// Decal projector - Ogre::Frustum *mProjector; - /// Decal scene node - Ogre::SceneNode *mSceneNode; - /// Registered pass - Ogre::Pass *mRegisteredPass; - - /// Position - Ogre::Vector2 mPosition; - /// Size - Ogre::Vector2 mSize; - /// Orientation - Ogre::Radian mOrientation; - /// Transparency - Ogre::Real mTransparency; - /// Is decal visible? - bool mVisible; - - /// Hydrax parent pointer - Hydrax *mHydrax; - }; - - /** Decals manager class. Use it for place any kind of texture - over the water! Like ship trails, overwater vegetables, ... - */ - class DecalsManager - { - public: - /** Constructor - @param h Hydrax parent pointer - */ - DecalsManager(Hydrax *h); - - /** Destructor - */ + /** Register the decal int the specified pass + @param _Pass Pass to be registred + */ + void registerPass(Ogre::Pass *_Pass); + + /** Unregister from current technique + */ + void unregister(); + + /** Get decal texture name + @return Decal texture name + */ + inline const Ogre::String &getTextureName() const + { + return mTextureName; + } + + /** Get the decal Id + @return Decal Id + */ + inline const int &getId() const + { + return mId; + } + + /** Get the decal projector + @return Projector frustum + */ + inline Ogre::Frustum *getProjector() + { + return mProjector; + } + + /** Get the decal scene node + @return Decal scene node + */ + inline Ogre::SceneNode *getSceneNode() + { + return mSceneNode; + } + + /** Get the pass the decal is in + @return Registered pass + @remarks return NULL if decal isn't registered + */ + inline Ogre::Pass *getRegisteredPass() + { + return mRegisteredPass; + } + + /** Get decal position + @return Decal position + */ + inline const Ogre::Vector2 &getPosition() const + { + return mPosition; + } + + /** Get decal size + @return Decal size + */ + inline const Ogre::Vector2 &getSize() const + { + return mSize; + } + + /** Get decal orientation + @return Decal orientation + */ + inline const Ogre::Radian &getOrientation() const + { + return mOrientation; + } + + /** Get decal transparency + @return Decal transparency + */ + inline const Ogre::Real &getTransparency() const + { + return mTransparency; + } + + /** Is decal visile? + @return true if decal is visible + */ + inline const bool &isVisible() const + { + return mVisible; + } + + /** Set decal position + @param Position Decal position + */ + void setPosition(const Ogre::Vector2 &Position); + + /** Set decal size + @param Size Decal size in world coordinates + */ + void setSize(const Ogre::Vector2 &Size); + + /** Set decal orientation + @param Orientation Decal orientation + */ + void setOrientation(const Ogre::Radian &Orientation); + + /** Set decal transparency + @param Transparency Decal transparency in [0,1] range + @remarks 0 = Full transparent, 1 = Full opacity + */ + void setTransparency(const Ogre::Real &Transparency); + + /** Set decal visibile or not + @param Visible true if yes, false if not + */ + void setVisible(const bool &Visible); + + private: + /// Decal texture name + Ogre::String mTextureName; + /// Decal Id + int mId; + /// Decal projector + Ogre::Frustum *mProjector; + /// Decal scene node + Ogre::SceneNode *mSceneNode; + /// Registered pass + Ogre::Pass *mRegisteredPass; + + /// Position + Ogre::Vector2 mPosition; + /// Size + Ogre::Vector2 mSize; + /// Orientation + Ogre::Radian mOrientation; + /// Transparency + Ogre::Real mTransparency; + /// Is decal visible? + bool mVisible; + + /// Hydrax parent pointer + Hydrax *mHydrax; + }; + + /** Decals manager class. Use it for place any kind of texture + over the water! Like ship trails, overwater vegetables, ... + */ + class DecalsManager + { + public: + /** Constructor + @param h Hydrax parent pointer + */ + DecalsManager(Hydrax *h); + + /** Destructor + */ ~DecalsManager(); - /** Update decal manager - @remarks Call each frame - */ - void update(); - - /** Add decal - @param TextureName Texture name - @return Hydrax::Decal* Use it as a usual Ogre::SceneNode(Decal::getSceneNode()) for position, rotate...etc! - */ - Decal* add(const Ogre::String& TextureName); - - /** Get decal - @param Id Decal Id - @return Hydrax::Decal* - */ - Decal* get(const int& Id); - - /** Remove decal - @param Id Decal Id - */ - void remove(const int& Id); - - /** Remove all decals - */ - void removeAll(); - - /** Register all decals - @remarks Use it when water material is (re)created - */ - void registerAll(); - - /** Get decals std::vector - @return std::vector list - */ - inline std::vector getDecals() - { - return mDecals; - } - - /** Get water strength (used for decals culling) - @return Water strength - */ - inline const Ogre::Real _getWaterStrength() const - { - return mWaterStrength; - } - - /** Set water strength (used for decals culling) - @param WaterStrength Water strength - */ - inline void _setWaterStrength(const Ogre::Real &WaterStrength) - { - mWaterStrength = WaterStrength; - } - - /** Call to force to update decals - */ - inline void _forceToUpdate() - { - mForceToUpdate = true; - } - - private: - /// Decals std::vector - std::vector mDecals; - /// Decal iterator - std::vector::iterator DecalIt; - /// Next Id - int mNextId; - - /// Water strength (For decals culling) - Ogre::Real mWaterStrength; - - /// Last camera position, orientation, underwater - Ogre::Vector3 mLastPosition; - Ogre::Quaternion mLastOrientation; - bool mLastUnderwater; - bool mForceToUpdate; - - /// Hydrax parent pointer - Hydrax *mHydrax; - }; -}; + /** Update decal manager + @remarks Call each frame + */ + void update(); + + /** Add decal + @param TextureName Texture name + @return Hydrax::Decal* Use it as a usual Ogre::SceneNode(Decal::getSceneNode()) for position, rotate...etc! + */ + Decal *add(const Ogre::String &TextureName); + + /** Get decal + @param Id Decal Id + @return Hydrax::Decal* + */ + Decal *get(const int &Id); + + /** Remove decal + @param Id Decal Id + */ + void remove(const int &Id); + + /** Remove all decals + */ + void removeAll(); + + /** Register all decals + @remarks Use it when water material is (re)created + */ + void registerAll(); + + /** Get decals std::vector + @return std::vector list + */ + inline std::vector getDecals() + { + return mDecals; + } + + /** Get water strength (used for decals culling) + @return Water strength + */ + inline const Ogre::Real _getWaterStrength() const + { + return mWaterStrength; + } + + /** Set water strength (used for decals culling) + @param WaterStrength Water strength + */ + inline void _setWaterStrength(const Ogre::Real &WaterStrength) + { + mWaterStrength = WaterStrength; + } + + /** Call to force to update decals + */ + inline void _forceToUpdate() + { + mForceToUpdate = true; + } + + private: + /// Decals std::vector + std::vector mDecals; + /// Decal iterator + std::vector::iterator DecalIt; + /// Next Id + int mNextId; + + /// Water strength (For decals culling) + Ogre::Real mWaterStrength; + + /// Last camera position, orientation, underwater + Ogre::Vector3 mLastPosition; + Ogre::Quaternion mLastOrientation; + bool mLastUnderwater; + bool mForceToUpdate; + + /// Hydrax parent pointer + Hydrax *mHydrax; + }; +}; // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/Enums.h b/source/main/gfx/hydrax/Enums.h index 457c495380..bd53972ab0 100644 --- a/source/main/gfx/hydrax/Enums.h +++ b/source/main/gfx/hydrax/Enums.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -33,16 +33,16 @@ namespace Hydrax */ enum TextureQuality { - TEX_QUA_2 = 2, - TEX_QUA_4 = 4, - TEX_QUA_8 = 8, - TEX_QUA_16 = 16, - TEX_QUA_32 = 32, - TEX_QUA_64 = 64, - TEX_QUA_128 = 128, - TEX_QUA_256 = 256, - TEX_QUA_512 = 512, - TEX_QUA_1024 = 1024 + TEX_QUA_2 = 2, + TEX_QUA_4 = 4, + TEX_QUA_8 = 8, + TEX_QUA_16 = 16, + TEX_QUA_32 = 32, + TEX_QUA_64 = 64, + TEX_QUA_128 = 128, + TEX_QUA_256 = 256, + TEX_QUA_512 = 512, + TEX_QUA_1024 = 1024 }; /** Hydrax flags to select components wich we want to use. @@ -50,20 +50,20 @@ namespace Hydrax */ enum HydraxComponent { - HYDRAX_COMPONENT_SUN = 1 << 0, - HYDRAX_COMPONENT_FOAM = 1 << 1, - HYDRAX_COMPONENT_DEPTH = 1 << 2, + HYDRAX_COMPONENT_SUN = 1 << 0, + HYDRAX_COMPONENT_FOAM = 1 << 1, + HYDRAX_COMPONENT_DEPTH = 1 << 2, /// Smooth transitions and caustics components need depth component HYDRAX_COMPONENT_SMOOTH = 1 << 3, HYDRAX_COMPONENT_CAUSTICS = 1 << 4, - HYDRAX_COMPONENT_UNDERWATER = 1 << 5, - /// Underwater reflections and god rays need underwater component - HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS = 1 << 6, - HYDRAX_COMPONENT_UNDERWATER_GODRAYS = 1 << 7, + HYDRAX_COMPONENT_UNDERWATER = 1 << 5, + /// Underwater reflections and god rays need underwater component + HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS = 1 << 6, + HYDRAX_COMPONENT_UNDERWATER_GODRAYS = 1 << 7, - HYDRAX_COMPONENTS_NONE = 0x0000, - HYDRAX_COMPONENTS_ALL = 0x001F, + HYDRAX_COMPONENTS_NONE = 0x0000, + HYDRAX_COMPONENTS_ALL = 0x001F, }; -} +} // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/FFT.cpp b/source/main/gfx/hydrax/FFT.cpp index 755a06970c..74180aeaaf 100644 --- a/source/main/gfx/hydrax/FFT.cpp +++ b/source/main/gfx/hydrax/FFT.cpp @@ -23,779 +23,690 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to */ #include "FFT.h" + #include "OgrePixelFormat.h" #include -namespace Hydrax{namespace Noise +namespace Hydrax { - inline float uniform_deviate() - { - return rand() * ( 1.0f / ( RAND_MAX + 1.0f ) ); - } - - FFT::FFT() - : Noise("FFT", true) - , resolution(128) - , re(0) - , img(0) - , maximalValue(2) - , initialWaves(0) - , currentWaves(0) - , angularFrequencies(0) - , time(10) - , mGPUNormalMapManager(0) - { - } - - FFT::FFT(const Options &Options) - : Noise("FFT", true) - , mOptions(Options) - , resolution(128) - , re(0) - , img(0) - , maximalValue(2) - , initialWaves(0) - , currentWaves(0) - , angularFrequencies(0) - , time(10) - , mGPUNormalMapManager(0) - { - } - - FFT::~FFT() - { - remove(); - - HydraxLOG(getName() + " destroyed."); - } - - void FFT::create() - { - if (isCreated()) - { - return; - } - - _initNoise(); - - Noise::create(); - } - - void FFT::remove() - { - if (areGPUNormalMapResourcesCreated()) - { - Noise::removeGPUNormalMapResources(mGPUNormalMapManager); - } - - if (!isCreated()) - { - return; - } - - if (currentWaves) - { - delete [] currentWaves; - } - if (re) - { - delete [] re; - } - if (img) - { - delete [] img; - } - if (initialWaves) - { - delete [] initialWaves; - } - - if (angularFrequencies) - { - delete [] angularFrequencies; - } - - maximalValue = 2; - time = 10; - - Noise::remove(); - } - - void FFT::setOptions(const Options &Options) - { - if (isCreated()) - { - if (mOptions.Resolution != Options.Resolution || - mOptions.Amplitude != Options.Amplitude || - mOptions.KwPower != Options.KwPower || - mOptions.PhysicalResolution != Options.PhysicalResolution || - mOptions.WindDirection != Options.WindDirection) - { - remove(); - - mOptions = Options; - resolution = Options.Resolution; - - create(); - - if (mGPUNormalMapManager) - { - createGPUNormalMapResources(mGPUNormalMapManager); - } - - return; - } - else - { - if (isGPUNormalMapSupported() && areGPUNormalMapResourcesCreated()) - { - mGPUNormalMapManager->getNormalMapMaterial()-> - getTechnique(0)->getPass(0)-> - getVertexProgramParameters()-> - setNamedConstant("uScale", Options.Scale); - - mGPUNormalMapManager->getNormalMapMaterial()-> - getTechnique(0)->getPass(0)-> - getFragmentProgramParameters()-> - setNamedConstant("uStrength", Options.GPU_Strength); - - mGPUNormalMapManager->getNormalMapMaterial()-> - getTechnique(0)->getPass(0)-> - getFragmentProgramParameters()-> - setNamedConstant("uLODParameters", Options.GPU_LODParameters); - } - } - } - - mOptions = Options; - resolution = Options.Resolution; - } - - bool FFT::createGPUNormalMapResources(GPUNormalMapManager *g) - { - if (!Noise::createGPUNormalMapResources(g)) - { - return false; - } - - mGPUNormalMapManager = g; - - // Create our FFT texture - Ogre::TexturePtr mFFTTexture - = Ogre::TextureManager::getSingleton(). - createManual("_Hydrax_FFT_Noise", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - resolution, resolution, 0, - Ogre::PF_L16, - Ogre::TU_DYNAMIC_WRITE_ONLY); - - mGPUNormalMapManager->addTexture(mFFTTexture); - - // Create our normal map generator material - - MaterialManager *mMaterialManager = g->getHydrax()->getMaterialManager(); - - Ogre::String VertexProgramData, FragmentProgramData; - Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; - Ogre::String EntryPoints[2] = {"main_vp", "main_fp"}; - Ogre::String GpuProgramsData[2]; Ogre::String GpuProgramNames[2]; - - // Vertex program - - switch (g->getHydrax()->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float3 oPosition_ : TEXCOORD0,\n" + - "out float4 oWorldUV : TEXCOORD1,\n" + - "out float oScale : TEXCOORD2,\n" + - "out float3 oCameraPos : TEXCOORD3,\n" + - "out float3 oCameraToPixel : TEXCOORD4,\n" + - // UNIFORM - "uniform float4x4 uWorldViewProj,\n" + - "uniform float4x4 uWorld, \n" + - "uniform float3 uCameraPos,\n"+ - "uniform float uScale)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n" + - "oPosition_ = iPosition.xyz;\n" + - "float2 Scale = uScale*mul(uWorld, iPosition).xz*0.0078125;\n" + - "oWorldUV.xy = Scale;\n" + - "oWorldUV.zw = Scale*16;\n" + - "oScale = uScale;\n" + - "oCameraPos = uCameraPos,\n" + - "oCameraToPixel = iPosition - uCameraPos;\n"+ - "}\n"; - } - break; - - case MaterialManager::SM_GLSL: - {} - break; - } - - // Fragment program - - switch (g->getHydrax()->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition : TEXCOORD0,\n" + - "float4 iWorldCoord : TEXCOORD1,\n" + - "float iScale : TEXCOORD2,\n" + - "float3 iCameraPos : TEXCOORD3,\n" + - "float3 iCameraToPixel : TEXCOORD4,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float uStrength,\n" + - "uniform float3 uLODParameters,\n" + // x: Initial derivation, y: Final derivation, z: Step - "uniform float3 uCameraPos,\n" + - "uniform sampler2D uFFT : register(s0))\n" + - "{\n" + - "float Distance = length(iCameraToPixel);\n" + - "float Attenuation = saturate(Distance/uLODParameters.z);\n" + - - "uLODParameters.x += (uLODParameters.y-uLODParameters.x)*Attenuation;\n"+ - "uLODParameters.x *= iScale;\n" + - - "float AngleAttenuation = 1/abs(normalize(iCameraToPixel).y);\n"+ - "uLODParameters.x *= AngleAttenuation;\n"+ - - "float2 dx = float2(uLODParameters.x*0.0078125, 0);\n" + - "float2 dy = float2(0, dx.x);\n" + - - "float3 p_dx, m_dx, p_dy, m_dy;\n" + - - "p_dx = float3(\n" + - // x+ - "iPosition.x+uLODParameters.x,\n" + - // y+ - "tex2D(uFFT, iWorldCoord.xy+dx).x,\n" + - // z - "iPosition.z);\n" + - - "m_dx = float3(\n" + - // x- - "iPosition.x-uLODParameters.x,\n" + - // y- - "tex2D(uFFT, iWorldCoord.xy-dx).x, \n" + - // z - "iPosition.z);\n" + - - "p_dy = float3(\n" + - // x - "iPosition.x,\n" + - // y+ - "tex2D(uFFT, iWorldCoord.xy+dy).x,\n" + - // z+ - "iPosition.z+uLODParameters.x);\n" + - - "m_dy = float3(\n" + - // x - "iPosition.x,\n" + - // y- - "tex2D(uFFT, iWorldCoord.xy-dy).x,\n" + - // z- - "iPosition.z-uLODParameters.x);\n" + - - "uStrength *= (1-Attenuation);\n" + - "p_dx.y *= uStrength; m_dx.y *= uStrength;\n" + - "p_dy.y *= uStrength; m_dy.y *= uStrength;\n" + - - "float3 normal = normalize(cross(p_dx-m_dx, p_dy-m_dy));\n" + - - "oColor = float4(saturate(1-(0.5+0.5*normal)),1);\n" + - "}\n"; - - } - break; - - case MaterialManager::SM_GLSL: - {} - break; - } - - // Build our material - - Ogre::MaterialPtr &mNormalMapMaterial = mGPUNormalMapManager->getNormalMapMaterial(); - mNormalMapMaterial = Ogre::MaterialManager::getSingleton().create("_Hydrax_GPU_Normal_Map_Material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::Pass *Technique0_Pass0 = mNormalMapMaterial->getTechnique(0)->getPass(0); - - Technique0_Pass0->setLightingEnabled(false); - Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); - Technique0_Pass0->setDepthWriteEnabled(true); - Technique0_Pass0->setDepthCheckEnabled(true); - - GpuProgramsData[0] = VertexProgramData; GpuProgramsData[1] = FragmentProgramData; - GpuProgramNames[0] = "_Hydrax_GPU_Normal_Map_VP"; GpuProgramNames[1] = "_Hydrax_GPU_Normal_Map_FP"; - - mMaterialManager->fillGpuProgramsToPass(Technique0_Pass0, GpuProgramNames, g->getHydrax()->getShaderMode(), EntryPoints, GpuProgramsData); - - VP_Parameters = Technique0_Pass0->getVertexProgramParameters(); - - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - VP_Parameters->setNamedConstant("uScale", mOptions.Scale); - - FP_Parameters = Technique0_Pass0->getFragmentProgramParameters(); - - FP_Parameters->setNamedConstant("uStrength", mOptions.GPU_Strength); - FP_Parameters->setNamedConstant("uLODParameters", mOptions.GPU_LODParameters); - - Technique0_Pass0->createTextureUnitState(mGPUNormalMapManager->getTexture(0)->getName(), 0) - ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - - mNormalMapMaterial->load(); + namespace Noise + { + inline float uniform_deviate() + { + return rand() * (1.0f / (RAND_MAX + 1.0f)); + } + + FFT::FFT() + : Noise("FFT", true), resolution(128), re(0), img(0), maximalValue(2), initialWaves(0), currentWaves(0), + angularFrequencies(0), time(10), mGPUNormalMapManager(0) + { + } + + FFT::FFT(const Options &Options) + : Noise("FFT", true), mOptions(Options), resolution(128), re(0), img(0), maximalValue(2), initialWaves(0), + currentWaves(0), angularFrequencies(0), time(10), mGPUNormalMapManager(0) + { + } + + FFT::~FFT() + { + remove(); + + HydraxLOG(getName() + " destroyed."); + } + + void FFT::create() + { + if (isCreated()) { return; } + + _initNoise(); + + Noise::create(); + } + + void FFT::remove() + { + if (areGPUNormalMapResourcesCreated()) { Noise::removeGPUNormalMapResources(mGPUNormalMapManager); } + + if (!isCreated()) { return; } + + if (currentWaves) { delete[] currentWaves; } + if (re) { delete[] re; } + if (img) { delete[] img; } + if (initialWaves) { delete[] initialWaves; } + + if (angularFrequencies) { delete[] angularFrequencies; } + + maximalValue = 2; + time = 10; + + Noise::remove(); + } + + void FFT::setOptions(const Options &Options) + { + if (isCreated()) + { + if (mOptions.Resolution != Options.Resolution || mOptions.Amplitude != Options.Amplitude || + mOptions.KwPower != Options.KwPower || mOptions.PhysicalResolution != Options.PhysicalResolution || + mOptions.WindDirection != Options.WindDirection) + { + remove(); + + mOptions = Options; + resolution = Options.Resolution; + + create(); + + if (mGPUNormalMapManager) { createGPUNormalMapResources(mGPUNormalMapManager); } + + return; + } + else + { + if (isGPUNormalMapSupported() && areGPUNormalMapResourcesCreated()) + { + mGPUNormalMapManager->getNormalMapMaterial() + ->getTechnique(0) + ->getPass(0) + ->getVertexProgramParameters() + ->setNamedConstant("uScale", Options.Scale); + + mGPUNormalMapManager->getNormalMapMaterial() + ->getTechnique(0) + ->getPass(0) + ->getFragmentProgramParameters() + ->setNamedConstant("uStrength", Options.GPU_Strength); + + mGPUNormalMapManager->getNormalMapMaterial() + ->getTechnique(0) + ->getPass(0) + ->getFragmentProgramParameters() + ->setNamedConstant("uLODParameters", Options.GPU_LODParameters); + } + } + } + + mOptions = Options; + resolution = Options.Resolution; + } + + bool FFT::createGPUNormalMapResources(GPUNormalMapManager *g) + { + if (!Noise::createGPUNormalMapResources(g)) { return false; } + + mGPUNormalMapManager = g; + + // Create our FFT texture + Ogre::TexturePtr mFFTTexture = Ogre::TextureManager::getSingleton().createManual( + "_Hydrax_FFT_Noise", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, resolution, + resolution, 0, Ogre::PF_L16, Ogre::TU_DYNAMIC_WRITE_ONLY); + + mGPUNormalMapManager->addTexture(mFFTTexture); + + // Create our normal map generator material + + MaterialManager *mMaterialManager = g->getHydrax()->getMaterialManager(); + + Ogre::String VertexProgramData, FragmentProgramData; + Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; + Ogre::String EntryPoints[2] = {"main_vp", "main_fp"}; + Ogre::String GpuProgramsData[2]; + Ogre::String GpuProgramNames[2]; + + // Vertex program + + switch (g->getHydrax()->getShaderMode()) + { + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float3 oPosition_ : TEXCOORD0,\n" + + "out float4 oWorldUV : TEXCOORD1,\n" + "out float oScale : TEXCOORD2,\n" + + "out float3 oCameraPos : TEXCOORD3,\n" + "out float3 oCameraToPixel : TEXCOORD4,\n" + + // UNIFORM + "uniform float4x4 uWorldViewProj,\n" + "uniform float4x4 uWorld, \n" + + "uniform float3 uCameraPos,\n" + "uniform float uScale)\n" + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + "oPosition_ = iPosition.xyz;\n" + + "float2 Scale = uScale*mul(uWorld, iPosition).xz*0.0078125;\n" + "oWorldUV.xy = Scale;\n" + + "oWorldUV.zw = Scale*16;\n" + "oScale = uScale;\n" + "oCameraPos = uCameraPos,\n" + + "oCameraToPixel = iPosition - uCameraPos;\n" + "}\n"; + } + break; + + case MaterialManager::SM_GLSL: + { + } + break; + } + + // Fragment program + + switch (g->getHydrax()->getShaderMode()) + { + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: + { + FragmentProgramData += + Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition : TEXCOORD0,\n" + "float4 iWorldCoord : TEXCOORD1,\n" + + "float iScale : TEXCOORD2,\n" + "float3 iCameraPos : TEXCOORD3,\n" + + "float3 iCameraToPixel : TEXCOORD4,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float uStrength,\n" + + "uniform float3 uLODParameters,\n" + // x: Initial derivation, y: Final derivation, z: Step + "uniform float3 uCameraPos,\n" + "uniform sampler2D uFFT : register(s0))\n" + "{\n" + + "float Distance = length(iCameraToPixel);\n" + "float Attenuation = saturate(Distance/uLODParameters.z);\n" + + + "uLODParameters.x += (uLODParameters.y-uLODParameters.x)*Attenuation;\n" + "uLODParameters.x *= iScale;\n" + + + "float AngleAttenuation = 1/abs(normalize(iCameraToPixel).y);\n" + "uLODParameters.x *= AngleAttenuation;\n" + + + "float2 dx = float2(uLODParameters.x*0.0078125, 0);\n" + "float2 dy = float2(0, dx.x);\n" + + + "float3 p_dx, m_dx, p_dy, m_dy;\n" + + + "p_dx = float3(\n" + + // x+ + "iPosition.x+uLODParameters.x,\n" + + // y+ + "tex2D(uFFT, iWorldCoord.xy+dx).x,\n" + + // z + "iPosition.z);\n" + + + "m_dx = float3(\n" + + // x- + "iPosition.x-uLODParameters.x,\n" + + // y- + "tex2D(uFFT, iWorldCoord.xy-dx).x, \n" + + // z + "iPosition.z);\n" + + + "p_dy = float3(\n" + + // x + "iPosition.x,\n" + + // y+ + "tex2D(uFFT, iWorldCoord.xy+dy).x,\n" + + // z+ + "iPosition.z+uLODParameters.x);\n" + + + "m_dy = float3(\n" + + // x + "iPosition.x,\n" + + // y- + "tex2D(uFFT, iWorldCoord.xy-dy).x,\n" + + // z- + "iPosition.z-uLODParameters.x);\n" + + + "uStrength *= (1-Attenuation);\n" + "p_dx.y *= uStrength; m_dx.y *= uStrength;\n" + + "p_dy.y *= uStrength; m_dy.y *= uStrength;\n" + + + "float3 normal = normalize(cross(p_dx-m_dx, p_dy-m_dy));\n" + + + "oColor = float4(saturate(1-(0.5+0.5*normal)),1);\n" + "}\n"; + } + break; + + case MaterialManager::SM_GLSL: + { + } + break; + } + + // Build our material + + Ogre::MaterialPtr &mNormalMapMaterial = mGPUNormalMapManager->getNormalMapMaterial(); + mNormalMapMaterial = Ogre::MaterialManager::getSingleton().create( + "_Hydrax_GPU_Normal_Map_Material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *Technique0_Pass0 = mNormalMapMaterial->getTechnique(0)->getPass(0); + + Technique0_Pass0->setLightingEnabled(false); + Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + Technique0_Pass0->setDepthWriteEnabled(true); + Technique0_Pass0->setDepthCheckEnabled(true); + + GpuProgramsData[0] = VertexProgramData; + GpuProgramsData[1] = FragmentProgramData; + GpuProgramNames[0] = "_Hydrax_GPU_Normal_Map_VP"; + GpuProgramNames[1] = "_Hydrax_GPU_Normal_Map_FP"; + + mMaterialManager->fillGpuProgramsToPass(Technique0_Pass0, GpuProgramNames, g->getHydrax()->getShaderMode(), + EntryPoints, GpuProgramsData); + + VP_Parameters = Technique0_Pass0->getVertexProgramParameters(); + + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + VP_Parameters->setNamedConstant("uScale", mOptions.Scale); + + FP_Parameters = Technique0_Pass0->getFragmentProgramParameters(); + + FP_Parameters->setNamedConstant("uStrength", mOptions.GPU_Strength); + FP_Parameters->setNamedConstant("uLODParameters", mOptions.GPU_LODParameters); + + Technique0_Pass0->createTextureUnitState(mGPUNormalMapManager->getTexture(0)->getName(), 0) + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + + mNormalMapMaterial->load(); + + mGPUNormalMapManager->create(); + + return true; + } + + void FFT::_updateGPUNormalMapResources() + { + Ogre::uchar * Data; + Ogre::HardwarePixelBufferSharedPtr PixelBuffer = mGPUNormalMapManager->getTexture(0)->getBuffer(); + + PixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); - mGPUNormalMapManager->create(); + const Ogre::PixelBox &PixelBox = PixelBuffer->getCurrentLock(); - return true; - } + Data = PixelBox.data; - void FFT::_updateGPUNormalMapResources() - { - Ogre::uchar *Data; - Ogre::HardwarePixelBufferSharedPtr PixelBuffer - = mGPUNormalMapManager->getTexture(0)->getBuffer(); + for (int u = 0; u < resolution * resolution; u++) + { + Data[u] = (re[u] * 65535); + } - PixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); + PixelBuffer->unlock(); + } - const Ogre::PixelBox& PixelBox = PixelBuffer->getCurrentLock(); + void FFT::saveCfg(Ogre::String &Data) + { + Noise::saveCfg(Data); - Data = PixelBox.data; + Data += CfgFileManager::_getCfgString("FFT_Resolution", mOptions.Resolution); + Data += CfgFileManager::_getCfgString("FFT_PhysycalResolution", mOptions.PhysicalResolution); + Data += CfgFileManager::_getCfgString("FFT_Scale", mOptions.Scale); + Data += CfgFileManager::_getCfgString("FFT_WindDirection", mOptions.WindDirection); + Data += CfgFileManager::_getCfgString("FFT_AnimationSpeed", mOptions.AnimationSpeed); + Data += CfgFileManager::_getCfgString("FFT_KwPower", mOptions.KwPower); + Data += CfgFileManager::_getCfgString("FFT_Amplitude", mOptions.Amplitude); + Data += "\n"; + } - for (int u = 0; u < resolution*resolution; u++) - { - Data[u] = (re[u]*65535); - } + bool FFT::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (!Noise::loadCfg(CfgFile)) { return false; } - PixelBuffer->unlock(); - } + setOptions(Options(CfgFileManager::_getIntValue(CfgFile, "FFT_Resolution"), + CfgFileManager::_getFloatValue(CfgFile, "FFT_PhysycalResolution"), + CfgFileManager::_getFloatValue(CfgFile, "FFT_Scale"), + CfgFileManager::_getVector2Value(CfgFile, "FFT_WindDirection"), + CfgFileManager::_getFloatValue(CfgFile, "FFT_AnimationSpeed"), + CfgFileManager::_getFloatValue(CfgFile, "FFT_KwPower"), + CfgFileManager::_getFloatValue(CfgFile, "FFT_Amplitude"))); - void FFT::saveCfg(Ogre::String &Data) - { - Noise::saveCfg(Data); + return true; + } - Data += CfgFileManager::_getCfgString("FFT_Resolution", mOptions.Resolution); - Data += CfgFileManager::_getCfgString("FFT_PhysycalResolution", mOptions.PhysicalResolution); - Data += CfgFileManager::_getCfgString("FFT_Scale", mOptions.Scale); - Data += CfgFileManager::_getCfgString("FFT_WindDirection", mOptions.WindDirection); - Data += CfgFileManager::_getCfgString("FFT_AnimationSpeed", mOptions.AnimationSpeed); - Data += CfgFileManager::_getCfgString("FFT_KwPower", mOptions.KwPower); - Data += CfgFileManager::_getCfgString("FFT_Amplitude", mOptions.Amplitude); Data += "\n"; - } + void FFT::update(const Ogre::Real &timeSinceLastFrame) + { + _calculeNoise(timeSinceLastFrame); - bool FFT::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (!Noise::loadCfg(CfgFile)) - { - return false; - } + if (areGPUNormalMapResourcesCreated()) { _updateGPUNormalMapResources(); } + } - setOptions( - Options(CfgFileManager::_getIntValue(CfgFile,"FFT_Resolution"), - CfgFileManager::_getFloatValue(CfgFile,"FFT_PhysycalResolution"), - CfgFileManager::_getFloatValue(CfgFile,"FFT_Scale"), - CfgFileManager::_getVector2Value(CfgFile,"FFT_WindDirection"), - CfgFileManager::_getFloatValue(CfgFile,"FFT_AnimationSpeed"), - CfgFileManager::_getFloatValue(CfgFile,"FFT_KwPower"), - CfgFileManager::_getFloatValue(CfgFile,"FFT_Amplitude"))); + void FFT::_initNoise() + { + initialWaves = new std::complex[resolution * resolution]; + currentWaves = new std::complex[resolution * resolution]; + angularFrequencies = new float[resolution * resolution]; - return true; - } + re = new float[resolution * resolution]; + img = new float[resolution * resolution]; - void FFT::update(const Ogre::Real &timeSinceLastFrame) - { - _calculeNoise(timeSinceLastFrame); + Ogre::Vector2 wave = Ogre::Vector2(0, 0); - if (areGPUNormalMapResourcesCreated()) - { - _updateGPUNormalMapResources(); - } - } + std::complex *pInitialWavesData = initialWaves; + float * pAngularFrequenciesData = angularFrequencies; - void FFT::_initNoise() - { - initialWaves = new std::complex[resolution*resolution]; - currentWaves = new std::complex[resolution*resolution]; - angularFrequencies = new float[resolution*resolution]; + float u, v, temp; - re = new float[resolution*resolution]; - img = new float[resolution*resolution]; + for (u = 0; u < resolution; u++) + { + wave.x = (-0.5f * resolution + u) * (2.0f * Ogre::Math::PI / mOptions.PhysicalResolution); - Ogre::Vector2 wave = Ogre::Vector2(0,0); + for (v = 0; v < resolution; v++) + { + wave.y = (-0.5f * resolution + v) * (2.0f * Ogre::Math::PI / mOptions.PhysicalResolution); - std::complex* pInitialWavesData = initialWaves; - float* pAngularFrequenciesData = angularFrequencies; + temp = Ogre::Math::Sqrt(0.5f * _getPhillipsSpectrum(wave, mOptions.WindDirection, mOptions.KwPower)); + *pInitialWavesData++ = + std::complex(_getGaussianRandomFloat() * temp, _getGaussianRandomFloat() * temp); - float u, v, - temp; + temp = 9.81f * wave.length(); + *pAngularFrequenciesData++ = Ogre::Math::Sqrt(temp); + } + } - for (u = 0; u < resolution; u++) - { - wave.x = (-0.5f * resolution + u) * (2.0f* Ogre::Math::PI / mOptions.PhysicalResolution); - - for (v = 0; v < resolution; v++) - { - wave.y = (-0.5f * resolution + v) * (2.0f* Ogre::Math::PI / mOptions.PhysicalResolution); - - temp = Ogre::Math::Sqrt(0.5f * _getPhillipsSpectrum(wave, mOptions.WindDirection, mOptions.KwPower)); - *pInitialWavesData++ = std::complex(_getGaussianRandomFloat() * temp, _getGaussianRandomFloat() * temp); - - temp=9.81f * wave.length(); - *pAngularFrequenciesData++ = Ogre::Math::Sqrt(temp); - } - } - - _calculeNoise(0); - } - - void FFT::_calculeNoise(const float &delta) - { - time += delta*mOptions.AnimationSpeed; - - std::complex* pData = currentWaves; - - int u, v; - - float wt, - coswt, sinwt, - realVal, imagVal; - - for (u = 0; u < resolution; u++) - { - for (v = 0; v< resolution ; v++) - { - const std::complex& positive_h0 = initialWaves[u * (resolution)+v]; - const std::complex& negative_h0 = initialWaves[(resolution-1 - u) * (resolution) + (resolution-1- v)]; - - wt = angularFrequencies[u * (resolution) + v] * time; - - coswt = Ogre::Math::Cos(wt); - sinwt = Ogre::Math::Sin(wt); - - realVal = - positive_h0.real() * coswt - positive_h0.imag() * sinwt + negative_h0.real() * coswt - (-negative_h0.imag()) * (-sinwt), - imagVal = - positive_h0.real() * sinwt + positive_h0.imag() * coswt + negative_h0.real() * (-sinwt) + (-negative_h0.imag()) * coswt; - - *pData++ = std::complex(realVal, imagVal); - } - } - - _executeInverseFFT(); - _normalizeFFTData(0); - } - - const float FFT::_getGaussianRandomFloat() const - { - float x1, x2, w, y1; - - do - { - x1 = 2.0f * uniform_deviate() - 1.0f; - x2 = 2.0f * uniform_deviate() - 1.0f; - - w = x1 * x1 + x2 * x2; - - } while ( w >= 1.0f ); - - w = Ogre::Math::Sqrt( (-2.0f * Ogre::Math::Log( w ) ) / w ); - y1 = x1 * w; - - return y1; - } - - const float FFT::_getPhillipsSpectrum(const Ogre::Vector2& waveVector, const Ogre::Vector2& wind, const float& kwPower_) const - { - // Compute the length of the vector - float k = waveVector.length(); - - // To avoid division by 0 - if (k < 0.0000001f) - { - return 0; - } - else - { - float windVelocity = wind.length(), - l = pow(windVelocity,2.0f)/9.81f, - dot=waveVector.dotProduct(wind); - - return mOptions.Amplitude* - (Ogre::Math::Exp(-1 / pow(k * l,2)) / (Ogre::Math::Pow(k,2) * - Ogre::Math::Pow(k,2))) * Ogre::Math::Pow(-dot/ (k * windVelocity), kwPower_); - } - } - - void FFT::_executeInverseFFT() - { - int l2n = 0, p = 1; - while (p < resolution) - { - p *= 2; l2n++; - } - int l2m = 0; p = 1; - while (p < resolution) - { - p *= 2; l2m++; - } - - resolution = 1<re[i]) min=re[i]; - if (maxmax) ? min : max; - - if (currentMax>maximalValue) maximalValue=currentMax; - - scaleCoef += maximalValue; - } - else - { // User defined scale - scaleCoef=scale; - } - - // Scale all the value, and clamp to [0,1] range - int x, y; - for(x=0;x(xScale)%resolution, - ys = static_cast(yScale)%resolution; - - // If data-space coords are negative, transform it to positive - if (x<0) xs += resolution-1; - if (y<0) ys += resolution-1; - - // Determine x and y diff for linear interpolation - int xINT = (x>0) ? static_cast(xScale) : static_cast(xScale-1), - yINT = (y>0) ? static_cast(yScale) : static_cast(yScale-1); - - // Calculate interpolation coeficients - float xDIFF = xScale-xINT, - yDIFF = yScale-yINT, - _xDIFF = 1-xDIFF, - _yDIFF = 1-yDIFF; - - // To adjust the index if coords are out of range - int xxs = (xs==resolution-1) ? -1 : xs, - yys = (ys==resolution-1) ? -1 : ys; - - // A B - // - // - // C D - float A = re[(ys*resolution+xs)], - B = re[(ys*resolution+xxs+1)], - C = re[((yys+1)*resolution+xs)], - D = re[((yys+1)*resolution+xxs+1)]; - - // Return the result of the linear interpolation - return (A*_xDIFF*_yDIFF + - B* xDIFF*_yDIFF + - C*_xDIFF* yDIFF + - D* xDIFF* yDIFF) // Range [-0.3, 0.3] - *0.6f-0.3f; - } -}} + _calculeNoise(0); + } + + void FFT::_calculeNoise(const float &delta) + { + time += delta * mOptions.AnimationSpeed; + + std::complex *pData = currentWaves; + + int u, v; + + float wt, coswt, sinwt, realVal, imagVal; + + for (u = 0; u < resolution; u++) + { + for (v = 0; v < resolution; v++) + { + const std::complex &positive_h0 = initialWaves[u * (resolution) + v]; + const std::complex &negative_h0 = + initialWaves[(resolution - 1 - u) * (resolution) + (resolution - 1 - v)]; + + wt = angularFrequencies[u * (resolution) + v] * time; + + coswt = Ogre::Math::Cos(wt); + sinwt = Ogre::Math::Sin(wt); + + realVal = positive_h0.real() * coswt - positive_h0.imag() * sinwt + negative_h0.real() * coswt - + (-negative_h0.imag()) * (-sinwt), + imagVal = positive_h0.real() * sinwt + positive_h0.imag() * coswt + negative_h0.real() * (-sinwt) + + (-negative_h0.imag()) * coswt; + + *pData++ = std::complex(realVal, imagVal); + } + } + + _executeInverseFFT(); + _normalizeFFTData(0); + } + + const float FFT::_getGaussianRandomFloat() const + { + float x1, x2, w, y1; + + do + { + x1 = 2.0f * uniform_deviate() - 1.0f; + x2 = 2.0f * uniform_deviate() - 1.0f; + + w = x1 * x1 + x2 * x2; + + } while (w >= 1.0f); + + w = Ogre::Math::Sqrt((-2.0f * Ogre::Math::Log(w)) / w); + y1 = x1 * w; + + return y1; + } + + const float FFT::_getPhillipsSpectrum(const Ogre::Vector2 &waveVector, const Ogre::Vector2 &wind, + const float &kwPower_) const + { + // Compute the length of the vector + float k = waveVector.length(); + + // To avoid division by 0 + if (k < 0.0000001f) { return 0; } + else + { + float windVelocity = wind.length(), l = pow(windVelocity, 2.0f) / 9.81f, dot = waveVector.dotProduct(wind); + + return mOptions.Amplitude * + (Ogre::Math::Exp(-1 / pow(k * l, 2)) / (Ogre::Math::Pow(k, 2) * Ogre::Math::Pow(k, 2))) * + Ogre::Math::Pow(-dot / (k * windVelocity), kwPower_); + } + } + + void FFT::_executeInverseFFT() + { + int l2n = 0, p = 1; + while (p < resolution) + { + p *= 2; + l2n++; + } + int l2m = 0; + p = 1; + while (p < resolution) + { + p *= 2; + l2m++; + } + + resolution = 1 << l2m; + resolution = 1 << l2n; + + int x, y, i; + + for (x = 0; x < resolution; x++) + { + for (y = 0; y < resolution; y++) + { + re[resolution * x + y] = currentWaves[resolution * x + y].real(); + img[resolution * x + y] = currentWaves[resolution * x + y].imag(); + } + } + + // Bit reversal of each row + int j, k; + for (y = 0; y < resolution; y++) // for each row + { + j = 0; + for (i = 0; i < resolution - 1; i++) + { + re[resolution * i + y] = currentWaves[resolution * j + y].real(); + img[resolution * i + y] = currentWaves[resolution * j + y].imag(); + + k = resolution / 2; + while (k <= j) + { + j -= k; + k /= 2; + } + + j += k; + } + } + + // Bit reversal of each column + float tx = 0, ty = 0; + for (x = 0; x < resolution; x++) // for each column + { + j = 0; + for (i = 0; i < resolution - 1; i++) + { + if (i < j) + { + tx = re[resolution * x + i]; + ty = img[resolution * x + i]; + re[resolution * x + i] = re[resolution * x + j]; + img[resolution * x + i] = img[resolution * x + j]; + re[resolution * x + j] = tx; + img[resolution * x + j] = ty; + } + k = resolution / 2; + while (k <= j) + { + j -= k; + k /= 2; + } + j += k; + } + } + + // Calculate the FFT of the columns + float ca, sa, u1, u2, t1, t2, z; + + int l1, l2, l, i1; + + for (x = 0; x < resolution; x++) // for each column + { + // This is the 1D FFT: + ca = -1.0; + sa = 0.0; + l1 = 1, l2 = 1; + + for (l = 0; l < l2n; l++) + { + l1 = l2; + l2 *= 2; + u1 = 1.0; + u2 = 0.0; + for (j = 0; j < l1; j++) + { + for (i = j; i < resolution; i += l2) + { + i1 = i + l1; + t1 = u1 * re[resolution * x + i1] - u2 * img[resolution * x + i1]; + t2 = u1 * img[resolution * x + i1] + u2 * re[resolution * x + i1]; + re[resolution * x + i1] = re[resolution * x + i] - t1; + img[resolution * x + i1] = img[resolution * x + i] - t2; + re[resolution * x + i] += t1; + img[resolution * x + i] += t2; + } + z = u1 * ca - u2 * sa; + u2 = u1 * sa + u2 * ca; + u1 = z; + } + sa = Ogre::Math::Sqrt((1.0f - ca) / 2.0f); + ca = Ogre::Math::Sqrt((1.0f + ca) / 2.0f); + } + } + // Calculate the FFT of the rows + for (y = 0; y < resolution; y++) // for each row + { + // This is the 1D FFT: + ca = -1.0; + sa = 0.0; + l1 = 1, l2 = 1; + + for (l = 0; l < l2m; l++) + { + l1 = l2; + l2 *= 2; + u1 = 1.0; + u2 = 0.0; + for (j = 0; j < l1; j++) + { + for (i = j; i < resolution; i += l2) + { + i1 = i + l1; + t1 = u1 * re[resolution * i1 + y] - u2 * img[resolution * i1 + y]; + t2 = u1 * img[resolution * i1 + y] + u2 * re[resolution * i1 + y]; + re[resolution * i1 + y] = re[resolution * i + y] - t1; + img[resolution * i1 + y] = img[resolution * i + y] - t2; + re[resolution * i + y] += t1; + img[resolution * i + y] += t2; + } + z = u1 * ca - u2 * sa; + u2 = u1 * sa + u2 * ca; + u1 = z; + } + sa = Ogre::Math::Sqrt((1.0f - ca) / 2.0f); + ca = Ogre::Math::Sqrt((1.0f + ca) / 2.0f); + } + } + + for (x = 0; x < resolution; x++) + { + for (y = 0; y < resolution; y++) + { + if (((x + y) & 0x1) == 1) { re[x * resolution + y] *= 1; } + else + { + re[x * resolution + y] *= -1; + } + } + } + } + + void FFT::_normalizeFFTData(const float &scale) + { + float scaleCoef = 0.000001f; + int i; + + // Perform automatic detection of maximum value + if (scale == 0.0f) + { + float min = re[0], max = re[0], currentMax = maximalValue; + ; + + for (i = 1; i < resolution * resolution; i++) + { + if (min > re[i]) min = re[i]; + if (max < re[i]) max = re[i]; + } + + min = Ogre::Math::Abs(min); + max = Ogre::Math::Abs(max); + + currentMax = (min > max) ? min : max; + + if (currentMax > maximalValue) maximalValue = currentMax; + + scaleCoef += maximalValue; + } + else + { // User defined scale + scaleCoef = scale; + } + + // Scale all the value, and clamp to [0,1] range + int x, y; + for (x = 0; x < resolution; x++) + { + for (y = 0; y < resolution; y++) + { + i = x * resolution + y; + re[i] = (re[i] + scaleCoef) / (scaleCoef * 2); + } + } + } + + float FFT::getValue(const float &x, const float &y) + { + // Scale world coords + float xScale = x * mOptions.Scale, yScale = y * mOptions.Scale; + + // Convert coords from world-space to data-space + int xs = static_cast(xScale) % resolution, ys = static_cast(yScale) % resolution; + + // If data-space coords are negative, transform it to positive + if (x < 0) xs += resolution - 1; + if (y < 0) ys += resolution - 1; + + // Determine x and y diff for linear interpolation + int xINT = (x > 0) ? static_cast(xScale) : static_cast(xScale - 1), + yINT = (y > 0) ? static_cast(yScale) : static_cast(yScale - 1); + + // Calculate interpolation coeficients + float xDIFF = xScale - xINT, yDIFF = yScale - yINT, _xDIFF = 1 - xDIFF, _yDIFF = 1 - yDIFF; + + // To adjust the index if coords are out of range + int xxs = (xs == resolution - 1) ? -1 : xs, yys = (ys == resolution - 1) ? -1 : ys; + + // A B + // + // + // C D + float A = re[(ys * resolution + xs)], B = re[(ys * resolution + xxs + 1)], C = re[((yys + 1) * resolution + xs)], + D = re[((yys + 1) * resolution + xxs + 1)]; + + // Return the result of the linear interpolation + return (A * _xDIFF * _yDIFF + B * xDIFF * _yDIFF + C * _xDIFF * yDIFF + D * xDIFF * yDIFF) // Range [-0.3, 0.3] + * 0.6f - + 0.3f; + } + } // namespace Noise +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/FFT.h b/source/main/gfx/hydrax/FFT.h index e8ebc885a0..99fb0e5cb7 100644 --- a/source/main/gfx/hydrax/FFT.h +++ b/source/main/gfx/hydrax/FFT.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,249 +25,224 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Noise_FFT_H_ #define _Hydrax_Noise_FFT_H_ - - #include "Noise.h" #include -namespace Hydrax{ namespace Noise +namespace Hydrax { - /** FFT noise module class - */ - class FFT : public Noise - { - public: - /** Struct wich contains fft noise module options - */ - struct Options - { - /// Noise resolution (2^n) - int Resolution; - /// Physical resolution - float PhysicalResolution; - /// Noise scale - float Scale; - /// Wind direction - Ogre::Vector2 WindDirection; - /// Animation speed - float AnimationSpeed; - /// KwPower - float KwPower; - /// Noise amplitude - float Amplitude; - - /** GPU Normal map generator parameters - Only if GPU normal map generation is active - */ - /// Representes the strength of the normals (i.e. Amplitude) - float GPU_Strength; - /** LOD Parameters, in order to obtain a smooth normal map we need to - decrease the detail level when the pixel is far to the camera. - This parameters are stored in an Ogre::Vector3: - x -> Initial LOD value (Bigger values -> less detail) - y -> Final LOD value - z -> Final distance - */ - Ogre::Vector3 GPU_LODParameters; - - /** Default constructor - */ - Options() - : Resolution(128) - , PhysicalResolution(32.0f) - , Scale(0.25f) - , WindDirection(Ogre::Vector2(4,5)) - , AnimationSpeed(1) - , KwPower(6.0f) - , Amplitude(1.0f) - , GPU_Strength(2.0f) - , GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) - { - } - - /** User constructor - @param _Resolution FFT Resolution (2^n) - @param _PhysicalResolution Physical resolution of the surface - @param _Scale Noise scale - @param _WindDirection Wind direction - @param _AnimationSpeed Animation speed coeficient - @param _KwPower KwPower - @param _Amplitude Noise amplitude - */ - Options(const int& _Resolution, - const float& _PhysicalResolution, - const float& _Scale, - const Ogre::Vector2& _WindDirection, - const float& _AnimationSpeed, - const float& _KwPower, - const float& _Amplitude) - : Resolution(_Resolution) - , PhysicalResolution(_PhysicalResolution) - , Scale(_Scale) - , WindDirection(_WindDirection) - , AnimationSpeed(_AnimationSpeed) - , KwPower(_KwPower) - , Amplitude(_Amplitude) - , GPU_Strength(2.0f) - , GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) - { - } - - /** User constructor - @param _Resolution FFT Resolution (2^n) - @param _PhysicalResolution Physical resolution of the surface - @param _Scale Noise scale - @param _WindDirection Wind direction - @param _AnimationSpeed Animation speed coeficient - @param _KwPower KwPower - @param _Amplitude Noise amplitude - @param _GPU_Strength GPU_Strength - @param _GPU_LODParameters GPU_LODParameters - */ - Options(const int& _Resolution, - const float& _PhysicalResolution, - const float& _Scale, - const Ogre::Vector2& _WindDirection, - const float& _AnimationSpeed, - const float& _KwPower, - const float& _Amplitude, - const float &_GPU_Strength, - const Ogre::Vector3 &_GPU_LODParameters) - : Resolution(_Resolution) - , PhysicalResolution(_PhysicalResolution) - , Scale(_Scale) - , WindDirection(_WindDirection) - , AnimationSpeed(_AnimationSpeed) - , KwPower(_KwPower) - , Amplitude(_Amplitude) - , GPU_Strength(_GPU_Strength) - , GPU_LODParameters(_GPU_LODParameters) - { - } - }; - - /** Default constructor - */ - FFT(); - - /** Constructor - @param Options FFT noise options - */ - FFT(const Options &Options); - - /** Destructor - */ - ~FFT(); - - /** Create - */ - void create(); - - /** Create GPUNormalMap resources - @param g GPUNormalMapManager pointer - @return true if it needs to be created, false if not - */ - bool createGPUNormalMapResources(GPUNormalMapManager *g); - - /** Remove - */ - void remove(); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Save config - @param Data String reference - */ - void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct noise config - */ - bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get the especified x/y noise value - @param x X Coord - @param y Y Coord - @return Noise value - */ - float getValue(const float &x, const float &y); - - /** Set/Update fft noise options - @param Options FFT noise options - */ - void setOptions(const Options &Options); - - /** Get current FFT noise options - @return Current fft noise options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - private: - /** Initialize noise - */ - void _initNoise(); - - /** Calcule noise - @param delta Time elapsed since last frame - */ - void _calculeNoise(const float &delta); - - /** Execute inverse fast fourier transform - */ - void _executeInverseFFT(); - - /** Normalize fft data - @param scale User defined scale - */ - void _normalizeFFTData(const float& scale); - - /** Get the Philipps Spectrum, used to create the amplitudes and phases - @param waveVector Wave vector - @param wind Wind direction - @param kwPower_ kwPower - @return Philipps Spectrum - */ - const float _getPhillipsSpectrum(const Ogre::Vector2& waveVector, const Ogre::Vector2& wind, const float& kwPower_ = 2.0f) const; - - /** Get a Gaussian random number with mean 0 and standard deviation 1, using Box - muller transform - @return Gaussian random number with mean 0 and standard deviation 1, using Box - muller transform - */ - const float _getGaussianRandomFloat() const; - - /** Update gpu normal map resources - */ - void _updateGPUNormalMapResources(); - - /// FFT resolution - int resolution; - /// Pointers to resolution*resolution float size arrays - float *re, *img; - /// The minimal value of the result data of the fft transformation - float maximalValue; - - /// the data which is referred as h0{x,t), that is, the data of the simulation at the time 0. - std::complex *initialWaves; - /// the data of the simulation at time t, which is formed using the data at time 0 and the angular frequencies at time t - std::complex *currentWaves; - /// the angular frequencies - float *angularFrequencies; - /// Current time - float time; - - /// GPUNormalMapManager pointer - GPUNormalMapManager *mGPUNormalMapManager; - - /// Perlin noise options - Options mOptions; - }; -}} + namespace Noise + { + /** FFT noise module class + */ + class FFT : public Noise + { + public: + /** Struct wich contains fft noise module options + */ + struct Options + { + /// Noise resolution (2^n) + int Resolution; + /// Physical resolution + float PhysicalResolution; + /// Noise scale + float Scale; + /// Wind direction + Ogre::Vector2 WindDirection; + /// Animation speed + float AnimationSpeed; + /// KwPower + float KwPower; + /// Noise amplitude + float Amplitude; + + /** GPU Normal map generator parameters + Only if GPU normal map generation is active + */ + /// Representes the strength of the normals (i.e. Amplitude) + float GPU_Strength; + /** LOD Parameters, in order to obtain a smooth normal map we need to + decrease the detail level when the pixel is far to the camera. + This parameters are stored in an Ogre::Vector3: + x -> Initial LOD value (Bigger values -> less detail) + y -> Final LOD value + z -> Final distance + */ + Ogre::Vector3 GPU_LODParameters; + + /** Default constructor + */ + Options() + : Resolution(128), PhysicalResolution(32.0f), Scale(0.25f), WindDirection(Ogre::Vector2(4, 5)), + AnimationSpeed(1), KwPower(6.0f), Amplitude(1.0f), GPU_Strength(2.0f), + GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) + { + } + + /** User constructor + @param _Resolution FFT Resolution (2^n) + @param _PhysicalResolution Physical resolution of the surface + @param _Scale Noise scale + @param _WindDirection Wind direction + @param _AnimationSpeed Animation speed coeficient + @param _KwPower KwPower + @param _Amplitude Noise amplitude + */ + Options(const int &_Resolution, const float &_PhysicalResolution, const float &_Scale, + const Ogre::Vector2 &_WindDirection, const float &_AnimationSpeed, const float &_KwPower, + const float &_Amplitude) + : Resolution(_Resolution), PhysicalResolution(_PhysicalResolution), Scale(_Scale), + WindDirection(_WindDirection), AnimationSpeed(_AnimationSpeed), KwPower(_KwPower), Amplitude(_Amplitude), + GPU_Strength(2.0f), GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) + { + } + + /** User constructor + @param _Resolution FFT Resolution (2^n) + @param _PhysicalResolution Physical resolution of the surface + @param _Scale Noise scale + @param _WindDirection Wind direction + @param _AnimationSpeed Animation speed coeficient + @param _KwPower KwPower + @param _Amplitude Noise amplitude + @param _GPU_Strength GPU_Strength + @param _GPU_LODParameters GPU_LODParameters + */ + Options(const int &_Resolution, const float &_PhysicalResolution, const float &_Scale, + const Ogre::Vector2 &_WindDirection, const float &_AnimationSpeed, const float &_KwPower, + const float &_Amplitude, const float &_GPU_Strength, const Ogre::Vector3 &_GPU_LODParameters) + : Resolution(_Resolution), PhysicalResolution(_PhysicalResolution), Scale(_Scale), + WindDirection(_WindDirection), AnimationSpeed(_AnimationSpeed), KwPower(_KwPower), Amplitude(_Amplitude), + GPU_Strength(_GPU_Strength), GPU_LODParameters(_GPU_LODParameters) + { + } + }; + + /** Default constructor + */ + FFT(); + + /** Constructor + @param Options FFT noise options + */ + FFT(const Options &Options); + + /** Destructor + */ + ~FFT(); + + /** Create + */ + void create(); + + /** Create GPUNormalMap resources + @param g GPUNormalMapManager pointer + @return true if it needs to be created, false if not + */ + bool createGPUNormalMapResources(GPUNormalMapManager *g); + + /** Remove + */ + void remove(); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Save config + @param Data String reference + */ + void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct noise config + */ + bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get the especified x/y noise value + @param x X Coord + @param y Y Coord + @return Noise value + */ + float getValue(const float &x, const float &y); + + /** Set/Update fft noise options + @param Options FFT noise options + */ + void setOptions(const Options &Options); + + /** Get current FFT noise options + @return Current fft noise options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + private: + /** Initialize noise + */ + void _initNoise(); + + /** Calcule noise + @param delta Time elapsed since last frame + */ + void _calculeNoise(const float &delta); + + /** Execute inverse fast fourier transform + */ + void _executeInverseFFT(); + + /** Normalize fft data + @param scale User defined scale + */ + void _normalizeFFTData(const float &scale); + + /** Get the Philipps Spectrum, used to create the amplitudes and phases + @param waveVector Wave vector + @param wind Wind direction + @param kwPower_ kwPower + @return Philipps Spectrum + */ + const float _getPhillipsSpectrum(const Ogre::Vector2 &waveVector, const Ogre::Vector2 &wind, + const float &kwPower_ = 2.0f) const; + + /** Get a Gaussian random number with mean 0 and standard deviation 1, using Box - muller transform + @return Gaussian random number with mean 0 and standard deviation 1, using Box - muller transform + */ + const float _getGaussianRandomFloat() const; + + /** Update gpu normal map resources + */ + void _updateGPUNormalMapResources(); + + /// FFT resolution + int resolution; + /// Pointers to resolution*resolution float size arrays + float *re, *img; + /// The minimal value of the result data of the fft transformation + float maximalValue; + + /// the data which is referred as h0{x,t), that is, the data of the simulation at the time 0. + std::complex *initialWaves; + /// the data of the simulation at time t, which is formed using the data at time 0 and the angular frequencies at time + /// t + std::complex *currentWaves; + /// the angular frequencies + float *angularFrequencies; + /// Current time + float time; + + /// GPUNormalMapManager pointer + GPUNormalMapManager *mGPUNormalMapManager; + + /// Perlin noise options + Options mOptions; + }; + } // namespace Noise +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/GPUNormalMapManager.cpp b/source/main/gfx/hydrax/GPUNormalMapManager.cpp index 6b7575bd9a..90c0166336 100644 --- a/source/main/gfx/hydrax/GPUNormalMapManager.cpp +++ b/source/main/gfx/hydrax/GPUNormalMapManager.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -23,65 +23,60 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to */ #include - #include namespace Hydrax { - GPUNormalMapManager::GPUNormalMapManager(Hydrax* h) - : mHydrax(h) - , mRttManager(h->getRttManager()) - , mCreated(false) - { - mRttManager->setBitsPerChannel(RttManager::RTT_GPU_NORMAL_MAP, RttManager::BPC_16); - mRttManager->setNumberOfChannels(RttManager::RTT_GPU_NORMAL_MAP, RttManager::NOC_3); - - mNormalMapMaterial.setNull(); - } - - GPUNormalMapManager::~GPUNormalMapManager() - { - remove(); - } - - void GPUNormalMapManager::create() - { - mRttManager->initialize(RttManager::RTT_GPU_NORMAL_MAP); - - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); - - if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER); - } - - mCreated = true; - } - - void GPUNormalMapManager::remove() - { - if (!mCreated) - { - return; - } - - for (unsigned int k = 0; k < mTextures.size(); k++) - { - Ogre::TextureManager::getSingleton().remove(mTextures.at(k)->getName()); - } - - mTextures.clear(); - - mRttManager->remove(RttManager::RTT_GPU_NORMAL_MAP); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(mNormalMapMaterial->getTechnique(0)->getPass(0)->getVertexProgramName()); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(mNormalMapMaterial->getTechnique(0)->getPass(0)->getFragmentProgramName()); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(mNormalMapMaterial->getTechnique(0)->getPass(0)->getVertexProgramName()); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(mNormalMapMaterial->getTechnique(0)->getPass(0)->getFragmentProgramName()); - - Ogre::MaterialManager::getSingleton().remove(mNormalMapMaterial->getName()); - mNormalMapMaterial.setNull(); - - mCreated = false; - } -} + GPUNormalMapManager::GPUNormalMapManager(Hydrax *h) : mHydrax(h), mRttManager(h->getRttManager()), mCreated(false) + { + mRttManager->setBitsPerChannel(RttManager::RTT_GPU_NORMAL_MAP, RttManager::BPC_16); + mRttManager->setNumberOfChannels(RttManager::RTT_GPU_NORMAL_MAP, RttManager::NOC_3); + + mNormalMapMaterial.setNull(); + } + + GPUNormalMapManager::~GPUNormalMapManager() + { + remove(); + } + + void GPUNormalMapManager::create() + { + mRttManager->initialize(RttManager::RTT_GPU_NORMAL_MAP); + + mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); + + if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER); } + + mCreated = true; + } + + void GPUNormalMapManager::remove() + { + if (!mCreated) { return; } + + for (unsigned int k = 0; k < mTextures.size(); k++) + { + Ogre::TextureManager::getSingleton().remove(mTextures.at(k)->getName()); + } + + mTextures.clear(); + + mRttManager->remove(RttManager::RTT_GPU_NORMAL_MAP); + + Ogre::HighLevelGpuProgramManager::getSingleton().unload( + mNormalMapMaterial->getTechnique(0)->getPass(0)->getVertexProgramName()); + Ogre::HighLevelGpuProgramManager::getSingleton().unload( + mNormalMapMaterial->getTechnique(0)->getPass(0)->getFragmentProgramName()); + Ogre::HighLevelGpuProgramManager::getSingleton().remove( + mNormalMapMaterial->getTechnique(0)->getPass(0)->getVertexProgramName()); + Ogre::HighLevelGpuProgramManager::getSingleton().remove( + mNormalMapMaterial->getTechnique(0)->getPass(0)->getFragmentProgramName()); + + Ogre::MaterialManager::getSingleton().remove(mNormalMapMaterial->getName()); + mNormalMapMaterial.setNull(); + + mCreated = false; + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/GPUNormalMapManager.h b/source/main/gfx/hydrax/GPUNormalMapManager.h index 5c60c843c1..d0c21c0f91 100644 --- a/source/main/gfx/hydrax/GPUNormalMapManager.h +++ b/source/main/gfx/hydrax/GPUNormalMapManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,131 +25,126 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_GPUNormalMapManager_H_ #define _Hydrax_GPUNormalMapManager_H_ -#include "Prerequisites.h" - #include "Enums.h" +#include "Prerequisites.h" #include "RttManager.h" namespace Hydrax { - class Hydrax; - - /** Class to manager GPU normal maps - */ - class GPUNormalMapManager - { - public: - /** Constructor - @param h Hydrax main pointer - */ - GPUNormalMapManager(Hydrax* h); - - /** Destructor - */ - ~GPUNormalMapManager(); - - /** Create - @remarks mNormalMapMaterial must have been created by the noise module before calling create() - */ - void create(); - - /** Remove - */ - void remove(); - - /** Set active - @param Active true for yes, false for not - */ - inline void setActive(const bool& Active) - { - if (Active) - { - mRttManager->initialize(RttManager::RTT_GPU_NORMAL_MAP); - } - else - { - mRttManager->remove(RttManager::RTT_GPU_NORMAL_MAP); - } - } - - /** Has been created() already called? - @return true if yes, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Get the Hydrax parent pointer - @remarks Needed by noise module in order to acced to the - MaterialManager to create vertex/fragment programs - and more if needed. - */ - inline Hydrax* getHydrax() - { - return mHydrax; - } - - /** Get the normal map material - @return Normal map generator material - */ - inline Ogre::MaterialPtr &getNormalMapMaterial() - { - return mNormalMapMaterial; - } - - /** Get a texture - @param Index Texture index - @return Ogre::TexturePtr - */ - inline Ogre::TexturePtr &getTexture(const int& Index) - { - return mTextures.at(Index); - } - - /** Create a texture - @param Texture Ogre::TexturePtr - */ - void addTexture(Ogre::TexturePtr &Texture) - { - mTextures.push_back(Texture); - } - - /** Remove a texture - @param Index Texture index - */ - inline void removeTexture(const int& Index) - { - Ogre::TextureManager::getSingleton().remove(mTextures.at(Index)->getName()); - - std::vector::iterator TexIt = mTextures.begin() + Index; - - mTextures.erase(TexIt); - } - - private: - - /// Hydrax main pointer - Hydrax *mHydrax; - /// Rtt manager pointer - RttManager *mRttManager; - - /// Has been create() already called? - bool mCreated; - - /** This material must be created in the noise module, - in order to be according with the Hydrax modulable interface - in all cases the Fragment program must have a 'uStrength' parameter - will represents the intensity of the normals. - */ - Ogre::MaterialPtr mNormalMapMaterial; - - /** The normal map material needs some textures wich will be filled by code. - The following std::vector will store all textures, and after they need - to be modified in the noise module. - */ - std::vector mTextures; - }; -} + class Hydrax; + + /** Class to manager GPU normal maps + */ + class GPUNormalMapManager + { + public: + /** Constructor + @param h Hydrax main pointer + */ + GPUNormalMapManager(Hydrax *h); + + /** Destructor + */ + ~GPUNormalMapManager(); + + /** Create + @remarks mNormalMapMaterial must have been created by the noise module before calling create() + */ + void create(); + + /** Remove + */ + void remove(); + + /** Set active + @param Active true for yes, false for not + */ + inline void setActive(const bool &Active) + { + if (Active) { mRttManager->initialize(RttManager::RTT_GPU_NORMAL_MAP); } + else + { + mRttManager->remove(RttManager::RTT_GPU_NORMAL_MAP); + } + } + + /** Has been created() already called? + @return true if yes, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Get the Hydrax parent pointer + @remarks Needed by noise module in order to acced to the + MaterialManager to create vertex/fragment programs + and more if needed. + */ + inline Hydrax *getHydrax() + { + return mHydrax; + } + + /** Get the normal map material + @return Normal map generator material + */ + inline Ogre::MaterialPtr &getNormalMapMaterial() + { + return mNormalMapMaterial; + } + + /** Get a texture + @param Index Texture index + @return Ogre::TexturePtr + */ + inline Ogre::TexturePtr &getTexture(const int &Index) + { + return mTextures.at(Index); + } + + /** Create a texture + @param Texture Ogre::TexturePtr + */ + void addTexture(Ogre::TexturePtr &Texture) + { + mTextures.push_back(Texture); + } + + /** Remove a texture + @param Index Texture index + */ + inline void removeTexture(const int &Index) + { + Ogre::TextureManager::getSingleton().remove(mTextures.at(Index)->getName()); + + std::vector::iterator TexIt = mTextures.begin() + Index; + + mTextures.erase(TexIt); + } + + private: + /// Hydrax main pointer + Hydrax *mHydrax; + /// Rtt manager pointer + RttManager *mRttManager; + + /// Has been create() already called? + bool mCreated; + + /** This material must be created in the noise module, + in order to be according with the Hydrax modulable interface + in all cases the Fragment program must have a 'uStrength' parameter + will represents the intensity of the normals. + */ + Ogre::MaterialPtr mNormalMapMaterial; + + /** The normal map material needs some textures wich will be filled by code. + The following std::vector will store all textures, and after they need + to be modified in the noise module. + */ + std::vector mTextures; + }; +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/GodRaysManager.cpp b/source/main/gfx/hydrax/GodRaysManager.cpp index b59e1937fd..5ceac2a527 100644 --- a/source/main/gfx/hydrax/GodRaysManager.cpp +++ b/source/main/gfx/hydrax/GodRaysManager.cpp @@ -1,7 +1,7 @@ /* -------------------------------------------------------------------------------- This source file is part of sssHydrax. -sssHydrax is a modified version of Hydrax (Copyright (C) 2008 Xavier Verguín González) +sssHydrax is a modified version of Hydrax (Copyright (C) 2008 Xavier Vergu�n Gonz�lez) to adapt it to SonSilentSea. This program is free software; you can redistribute it and/or modify it under @@ -18,410 +18,376 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. -Author: Jose Luis Cercós Pita +Author: Jose Luis Cerc�s Pita -------------------------------------------------------------------------------- */ #include - #include #define _def_GodRays_Projector_Camera_Name "_Hydrax_GodRays_Projector_Camera" -#define _def_GodRays_ManualObject_Name "_Hydrax_GodRays_ManualObject" -#define _def_GodRays_Depth_Map "_Hydrax_GodRays_Depth_Map" +#define _def_GodRays_ManualObject_Name "_Hydrax_GodRays_ManualObject" +#define _def_GodRays_Depth_Map "_Hydrax_GodRays_Depth_Map" -#define _def_GodRays_Material_Name "_Hydrax_GodRays_Material" +#define _def_GodRays_Material_Name "_Hydrax_GodRays_Material" #define _def_GodRays_Shader_VP_Name "_Hydrax_GodRays_VP" #define _def_GodRays_Shader_FP_Name "_Hydrax_GodRays_FP" -#define _def_GodRaysDepth_Material_Name "_Hydrax_GodRaysDepth_Material" +#define _def_GodRaysDepth_Material_Name "_Hydrax_GodRaysDepth_Material" #define _def_GodRaysDepth_Shader_VP_Name "_Hydrax_GodRaysDepth_VP" #define _def_GodRaysDepth_Shader_FP_Name "_Hydrax_GodRaysDepth_FP" -const Ogre::Matrix4 - PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE( - 0.5, 0, 0, 0.5, - 0, -0.5, 0, 0.5, - 0, 0, 1, 0, - 0, 0, 0, 1); +const Ogre::Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(0.5, 0, 0, 0.5, 0, -0.5, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1); namespace Hydrax { - GodRaysManager::GodRaysManager(Hydrax *h) - : mCreated(false) - , mManualGodRays(0) - , mProjectorCamera(0) - , mProjectorSN(0) - , mPerlin(0) - , mNoiseDerivation(3) - , mNoisePositionMultiplier(50) - , mNoiseYNormalMultiplier(10) - , mNoiseNormalMultiplier(0.175) - , mSimulationSpeed(5.0f) - , mNumberOfRays(100) - , mRaysSize(0.03f) - , mObjectsIntersections(false) - , mHydrax(h) - { - for (int k = 0; k < 2; k++) - { - mMaterials[k].setNull(); - } - } - - GodRaysManager::~GodRaysManager() - { - remove(); - } - - void GodRaysManager::create(const HydraxComponent& HC) - { - if (mCreated) - { - remove(); - } - - // Create our perlin noise module - mPerlin = new Noise::Perlin(Noise::Perlin::Options(8, 0.085f, 0.49, 2, 0.672)); - mPerlin->create(); - - // Initial values, some of them need to be updated each frame - mProjectorCamera = mHydrax->getSceneManager()->createCamera(_def_GodRays_Projector_Camera_Name); - mProjectorCamera->setProjectionType(Ogre::PT_PERSPECTIVE); - // Not forget to set near+far distance in materials - mProjectorCamera->setNearClipDistance(8); - mProjectorCamera->setFarClipDistance(40); - mProjectorCamera->setAspectRatio(1); - mProjectorCamera->setFOVy(Ogre::Degree(45.0f)); - mProjectorCamera->setVisible(false); - mProjectorSN = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - mProjectorSN->setPosition(0,0,0); - mProjectorSN->attachObject(mProjectorCamera); - mProjectorSN->setDirection(0, -1, 0); - - if (mObjectsIntersections) - { - _createDepthRTT(); - } - - _createMaterials(HC); - - std::vector::iterator TechIt; - - for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) - { - if (!(*TechIt)) - { - mDepthTechniques.erase(TechIt); - // TechIt-- ? - continue; - } - - addDepthTechnique((*TechIt), false); - } - - _createGodRays(); - - mCreated = true; - } - - void GodRaysManager::_createGodRays() + GodRaysManager::GodRaysManager(Hydrax *h) + : mCreated(false), mManualGodRays(0), mProjectorCamera(0), mProjectorSN(0), mPerlin(0), mNoiseDerivation(3), + mNoisePositionMultiplier(50), mNoiseYNormalMultiplier(10), mNoiseNormalMultiplier(0.175), mSimulationSpeed(5.0f), + mNumberOfRays(100), mRaysSize(0.03f), mObjectsIntersections(false), mHydrax(h) + { + for (int k = 0; k < 2; k++) + { + mMaterials[k].setNull(); + } + } + + GodRaysManager::~GodRaysManager() + { + remove(); + } + + void GodRaysManager::create(const HydraxComponent &HC) + { + if (mCreated) { remove(); } + + // Create our perlin noise module + mPerlin = new Noise::Perlin(Noise::Perlin::Options(8, 0.085f, 0.49, 2, 0.672)); + mPerlin->create(); + + // Initial values, some of them need to be updated each frame + mProjectorCamera = mHydrax->getSceneManager()->createCamera(_def_GodRays_Projector_Camera_Name); + mProjectorCamera->setProjectionType(Ogre::PT_PERSPECTIVE); + // Not forget to set near+far distance in materials + mProjectorCamera->setNearClipDistance(8); + mProjectorCamera->setFarClipDistance(40); + mProjectorCamera->setAspectRatio(1); + mProjectorCamera->setFOVy(Ogre::Degree(45.0f)); + mProjectorCamera->setVisible(false); + mProjectorSN = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + mProjectorSN->setPosition(0, 0, 0); + mProjectorSN->attachObject(mProjectorCamera); + mProjectorSN->setDirection(0, -1, 0); + + if (mObjectsIntersections) { _createDepthRTT(); } + + _createMaterials(HC); + + std::vector::iterator TechIt; + + for (TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) + { + if (!(*TechIt)) + { + mDepthTechniques.erase(TechIt); + // TechIt-- ? + continue; + } + + addDepthTechnique((*TechIt), false); + } + + _createGodRays(); + + mCreated = true; + } + + void GodRaysManager::_createGodRays() { - mManualGodRays = mHydrax->getSceneManager()->createManualObject(_def_GodRays_ManualObject_Name); - mManualGodRays->setDynamic(true); - mManualGodRays->setVisible(mHydrax->_isCurrentFrameUnderwater()); - - mManualGodRays->begin(_def_GodRays_Material_Name, Ogre::RenderOperation::OT_TRIANGLE_LIST); - mManualGodRays->setRenderQueueGroup(Ogre::RENDER_QUEUE_9+1); - - for(int r = 0; r < mNumberOfRays; r++) - { - // Rays are modeled as pyramids, 12 vertex each ray - for (int k = 0; k < 12; k++) - { - mManualGodRays->position(0, 0, 0); - mManualGodRays->index(k); - } - } + mManualGodRays = mHydrax->getSceneManager()->createManualObject(_def_GodRays_ManualObject_Name); + mManualGodRays->setDynamic(true); + mManualGodRays->setVisible(mHydrax->_isCurrentFrameUnderwater()); + + mManualGodRays->begin(_def_GodRays_Material_Name, Ogre::RenderOperation::OT_TRIANGLE_LIST); + mManualGodRays->setRenderQueueGroup(Ogre::RENDER_QUEUE_9 + 1); + + for (int r = 0; r < mNumberOfRays; r++) + { + // Rays are modeled as pyramids, 12 vertex each ray + for (int k = 0; k < 12; k++) + { + mManualGodRays->position(0, 0, 0); + mManualGodRays->index(k); + } + } mManualGodRays->end(); mProjectorSN->attachObject(mManualGodRays); } - void GodRaysManager::remove() - { - if (!mCreated) - { - return; - } - - delete mPerlin; - mPerlin = static_cast(NULL); - - mHydrax->getSceneManager()->destroyManualObject(mManualGodRays); - mManualGodRays = static_cast(NULL); - - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRays_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_GodRays_Material_Name); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRays_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRays_Shader_FP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRays_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRays_Shader_FP_Name); - } - - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRaysDepth_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_GodRaysDepth_Material_Name); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRaysDepth_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRaysDepth_Shader_FP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRaysDepth_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRaysDepth_Shader_FP_Name); - } - - for (int k = 0; k < 2; k++) - { - mMaterials[k].setNull(); - } - - if (!mProjectorRTT.isNull()) - { - Ogre::RenderTarget* RT = mProjectorRTT->getBuffer()->getRenderTarget(); + void GodRaysManager::remove() + { + if (!mCreated) { return; } + + delete mPerlin; + mPerlin = static_cast(NULL); + + mHydrax->getSceneManager()->destroyManualObject(mManualGodRays); + mManualGodRays = static_cast(NULL); + + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRays_Material_Name)) + { + Ogre::MaterialManager::getSingleton().remove(_def_GodRays_Material_Name); + + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRays_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRays_Shader_FP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRays_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRays_Shader_FP_Name); + } + + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRaysDepth_Material_Name)) + { + Ogre::MaterialManager::getSingleton().remove(_def_GodRaysDepth_Material_Name); + + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRaysDepth_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRaysDepth_Shader_FP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRaysDepth_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRaysDepth_Shader_FP_Name); + } + + for (int k = 0; k < 2; k++) + { + mMaterials[k].setNull(); + } + + if (!mProjectorRTT.isNull()) + { + Ogre::RenderTarget *RT = mProjectorRTT->getBuffer()->getRenderTarget(); RT->removeAllListeners(); RT->removeAllViewports(); - Ogre::TextureManager::getSingleton().remove(mProjectorRTT->getName()); - mProjectorRTT.setNull(); - } + Ogre::TextureManager::getSingleton().remove(mProjectorRTT->getName()); + mProjectorRTT.setNull(); + } - mHydrax->getSceneManager()->destroyCamera(mProjectorCamera); - mProjectorCamera = static_cast(NULL); + mHydrax->getSceneManager()->destroyCamera(mProjectorCamera); + mProjectorCamera = static_cast(NULL); - mProjectorSN->detachAllObjects(); - mProjectorSN->getParentSceneNode()->removeAndDestroyChild(mProjectorSN); - mProjectorSN = static_cast(NULL); + mProjectorSN->detachAllObjects(); + mProjectorSN->getParentSceneNode()->removeAndDestroyChild(mProjectorSN); + mProjectorSN = static_cast(NULL); - mCreated = false; - } + mCreated = false; + } - void GodRaysManager::update(const Ogre::Real& timeSinceLastFrame) - { - if (!mCreated || !mHydrax->_isCurrentFrameUnderwater()) - { - return; - } + void GodRaysManager::update(const Ogre::Real &timeSinceLastFrame) + { + if (!mCreated || !mHydrax->_isCurrentFrameUnderwater()) { return; } - mPerlin->update(timeSinceLastFrame); + mPerlin->update(timeSinceLastFrame); - _updateRays(); - _updateProjector(); + _updateRays(); + _updateProjector(); - if (mObjectsIntersections) - { - _updateMaterialsParameters(); - mProjectorRTT->getBuffer()->getRenderTarget()->update(); - } - } + if (mObjectsIntersections) + { + _updateMaterialsParameters(); + mProjectorRTT->getBuffer()->getRenderTarget()->update(); + } + } - void GodRaysManager::_updateRays() - { - // Get frustum corners to calculate far plane dimensions - const Ogre::Vector3 *FrustumCorners = mProjectorCamera->getWorldSpaceCorners(); - // Calcule far plane dimensions - float FarWidth = (FrustumCorners[4] - FrustumCorners[5]).length(); - Ogre::Real RaysLength = mProjectorCamera->getFarClipDistance(); + void GodRaysManager::_updateRays() + { + // Get frustum corners to calculate far plane dimensions + const Ogre::Vector3 *FrustumCorners = mProjectorCamera->getWorldSpaceCorners(); + // Calcule far plane dimensions + float FarWidth = (FrustumCorners[4] - FrustumCorners[5]).length(); + Ogre::Real RaysLength = mProjectorCamera->getFarClipDistance(); - mManualGodRays->beginUpdate(0); + mManualGodRays->beginUpdate(0); - Ogre::Vector2 Pos; - Ogre::Real Dis, RayLength; + Ogre::Vector2 Pos; + Ogre::Real Dis, RayLength; - // Rays are modeled as piramids, 12 vertex each ray - // - // // 0\\ + // Rays are modeled as piramids, 12 vertex each ray + // + // // 0\\ // /| | | - // || | | - // || | | (0,0) (1,0) - // || | | A B - // || | | - // |A----|-|B (0,1) (1,1) - // |/ |/ C D - // C------D - - for(int k = 0; k < mNumberOfRays; k++) - { - Pos = _calculateRayPosition(k); - Dis = mRaysSize*RaysLength; - RayLength = RaysLength*(0.95+Pos.length()); - - Pos *= FarWidth/2; - - // 4 Planes, 3 vertices each plane, 12 vertices per ray - // ----> 1/4 - // 0 + // || | | + // || | | (0,0) (1,0) + // || | | A B + // || | | + // |A----|-|B (0,1) (1,1) + // |/ |/ C D + // C------D + + for (int k = 0; k < mNumberOfRays; k++) + { + Pos = _calculateRayPosition(k); + Dis = mRaysSize * RaysLength; + RayLength = RaysLength * (0.95 + Pos.length()); + + Pos *= FarWidth / 2; + + // 4 Planes, 3 vertices each plane, 12 vertices per ray + // ----> 1/4 + // 0 mManualGodRays->position(0, 0, 0); - // A + // A mManualGodRays->position(Pos.x, Pos.y, -RayLength); - // B - mManualGodRays->position(Pos.x+Dis, Pos.y, -RayLength); - // ----> 2/4 - // 0 + // B + mManualGodRays->position(Pos.x + Dis, Pos.y, -RayLength); + // ----> 2/4 + // 0 mManualGodRays->position(0, 0, 0); - // D - mManualGodRays->position(Pos.x+Dis, Pos.y+Dis, -RayLength); - // B - mManualGodRays->position(Pos.x+Dis, Pos.y, -RayLength); - // ----> 3/4 - // 0 + // D + mManualGodRays->position(Pos.x + Dis, Pos.y + Dis, -RayLength); + // B + mManualGodRays->position(Pos.x + Dis, Pos.y, -RayLength); + // ----> 3/4 + // 0 mManualGodRays->position(0, 0, 0); - // C - mManualGodRays->position(Pos.x, Pos.y+Dis, -RayLength); - // D - mManualGodRays->position(Pos.x+Dis, Pos.y+Dis, -RayLength); - // ----> 4/4 - // 0 + // C + mManualGodRays->position(Pos.x, Pos.y + Dis, -RayLength); + // D + mManualGodRays->position(Pos.x + Dis, Pos.y + Dis, -RayLength); + // ----> 4/4 + // 0 mManualGodRays->position(0, 0, 0); - // C - mManualGodRays->position(Pos.x, Pos.y+Dis, -RayLength); - // A + // C + mManualGodRays->position(Pos.x, Pos.y + Dis, -RayLength); + // A mManualGodRays->position(Pos.x, Pos.y, -RayLength); - } + } - mManualGodRays->end(); - } + mManualGodRays->end(); + } - Ogre::Vector2 GodRaysManager::_calculateRayPosition(const int& RayNumber) - { - Ogre::Real sqrt_NumberOfRays = Ogre::Math::Sqrt(mNumberOfRays); - Ogre::Real XCoord = RayNumber; + Ogre::Vector2 GodRaysManager::_calculateRayPosition(const int &RayNumber) + { + Ogre::Real sqrt_NumberOfRays = Ogre::Math::Sqrt(mNumberOfRays); + Ogre::Real XCoord = RayNumber; - while (XCoord >= sqrt_NumberOfRays) - { - XCoord -= sqrt_NumberOfRays; - } + while (XCoord >= sqrt_NumberOfRays) + { + XCoord -= sqrt_NumberOfRays; + } - Ogre::Vector2 RayPos = - Ogre::Vector2( // X coord - static_cast(XCoord), - // Y coord - static_cast((RayNumber+sqrt_NumberOfRays)/sqrt_NumberOfRays)-1); + Ogre::Vector2 RayPos = Ogre::Vector2( // X coord + static_cast(XCoord), + // Y coord + static_cast((RayNumber + sqrt_NumberOfRays) / sqrt_NumberOfRays) - 1); - RayPos /= sqrt_NumberOfRays; - RayPos -= Ogre::Vector2(0.5, 0.5); - RayPos *= 2; + RayPos /= sqrt_NumberOfRays; + RayPos -= Ogre::Vector2(0.5, 0.5); + RayPos *= 2; - Ogre::Vector2 Position = RayPos*mNoisePositionMultiplier + Ogre::Vector2(mProjectorSN->getPosition().x, mProjectorSN->getPosition().z); + Ogre::Vector2 Position = + RayPos * mNoisePositionMultiplier + Ogre::Vector2(mProjectorSN->getPosition().x, mProjectorSN->getPosition().z); - Ogre::Vector3 - m_x = Ogre::Vector3(Position.x-mNoiseDerivation, mPerlin->getValue(Position.x-mNoiseDerivation,0), 0), - p_x = Ogre::Vector3(Position.x+mNoiseDerivation, mPerlin->getValue(Position.x+mNoiseDerivation,0), 0), - m_y = Ogre::Vector3(0, mPerlin->getValue(0,Position.y-mNoiseDerivation), Position.y-mNoiseDerivation), - p_y = Ogre::Vector3(0, mPerlin->getValue(0,Position.y+mNoiseDerivation), Position.y+mNoiseDerivation); + Ogre::Vector3 m_x = Ogre::Vector3(Position.x - mNoiseDerivation, mPerlin->getValue(Position.x - mNoiseDerivation, 0), 0), + p_x = Ogre::Vector3(Position.x + mNoiseDerivation, mPerlin->getValue(Position.x + mNoiseDerivation, 0), 0), + m_y = Ogre::Vector3(0, mPerlin->getValue(0, Position.y - mNoiseDerivation), Position.y - mNoiseDerivation), + p_y = Ogre::Vector3(0, mPerlin->getValue(0, Position.y + mNoiseDerivation), Position.y + mNoiseDerivation); - m_x.y *= mNoiseYNormalMultiplier; p_x.y *= mNoiseYNormalMultiplier; - m_y.y *= mNoiseYNormalMultiplier; p_y.y *= mNoiseYNormalMultiplier; + m_x.y *= mNoiseYNormalMultiplier; + p_x.y *= mNoiseYNormalMultiplier; + m_y.y *= mNoiseYNormalMultiplier; + p_y.y *= mNoiseYNormalMultiplier; - Ogre::Vector3 Normal = (p_x-m_x).crossProduct((p_y-m_y)); + Ogre::Vector3 Normal = (p_x - m_x).crossProduct((p_y - m_y)); - Normal *= mNoiseNormalMultiplier; + Normal *= mNoiseNormalMultiplier; - return RayPos + Ogre::Vector2(Normal.x, Normal.z); - } + return RayPos + Ogre::Vector2(Normal.x, Normal.z); + } - void GodRaysManager::setNumberOfRays(const int& NumberOfRays) - { - mNumberOfRays = NumberOfRays; + void GodRaysManager::setNumberOfRays(const int &NumberOfRays) + { + mNumberOfRays = NumberOfRays; - if (!mCreated) - { - return; - } + if (!mCreated) { return; } - mProjectorSN->detachObject(mManualGodRays); + mProjectorSN->detachObject(mManualGodRays); - mHydrax->getSceneManager()->destroyManualObject(mManualGodRays); - mManualGodRays = static_cast(NULL); + mHydrax->getSceneManager()->destroyManualObject(mManualGodRays); + mManualGodRays = static_cast(NULL); - _createGodRays(); - } + _createGodRays(); + } - void GodRaysManager::setObjectIntersectionsEnabled(const bool& Enable) - { - mObjectsIntersections = Enable; + void GodRaysManager::setObjectIntersectionsEnabled(const bool &Enable) + { + mObjectsIntersections = Enable; - const HydraxComponent& Components = mHydrax->getComponents(); + const HydraxComponent &Components = mHydrax->getComponents(); - create(Components); - } + create(Components); + } - void GodRaysManager::_updateMaterialsParameters() - { - if (!mObjectsIntersections) - { - return; - } + void GodRaysManager::_updateMaterialsParameters() + { + if (!mObjectsIntersections) { return; } - Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; + Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; - // God rays material - VP_Parameters = mMaterials[0]->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - FP_Parameters = mMaterials[0]->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + // God rays material + VP_Parameters = mMaterials[0]->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + FP_Parameters = mMaterials[0]->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - Ogre::Matrix4 TexViewProj = - PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * - mProjectorCamera->getProjectionMatrixWithRSDepth() * - mProjectorCamera->getViewMatrix(); + Ogre::Matrix4 TexViewProj = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * + mProjectorCamera->getProjectionMatrixWithRSDepth() * mProjectorCamera->getViewMatrix(); - VP_Parameters->setNamedConstant("uTexViewProj", TexViewProj); + VP_Parameters->setNamedConstant("uTexViewProj", TexViewProj); - FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); - FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); + FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); + FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); - // Depth material - FP_Parameters = mMaterials[1]->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + // Depth material + FP_Parameters = mMaterials[1]->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); - FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); + FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); + FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); - std::vector::iterator TechIt; + std::vector::iterator TechIt; - for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) - { - if (!(*TechIt)) - { - mDepthTechniques.erase(TechIt); - // TechIt-- ? - continue; - } + for (TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) + { + if (!(*TechIt)) + { + mDepthTechniques.erase(TechIt); + // TechIt-- ? + continue; + } - (*TechIt)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); - (*TechIt)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); - } - } + (*TechIt)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightPosition", + mProjectorSN->getPosition()); + (*TechIt)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightFarClipDistance", + mProjectorCamera->getFarClipDistance()); + } + } - void GodRaysManager::_updateProjector() - { - const Ogre::Vector3& SunPosition = mHydrax->getSunPosition(); - const Ogre::Vector3& CameraPosition = mHydrax->getCamera()->getDerivedPosition(); + void GodRaysManager::_updateProjector() + { + const Ogre::Vector3 &SunPosition = mHydrax->getSunPosition(); + const Ogre::Vector3 &CameraPosition = mHydrax->getCamera()->getDerivedPosition(); - Ogre::Plane WaterPlane = Ogre::Plane(Ogre::Vector3(0,1,0), mHydrax->getPosition()); - Ogre::Ray SunToCameraRay = Ogre::Ray(SunPosition, CameraPosition-SunPosition); + Ogre::Plane WaterPlane = Ogre::Plane(Ogre::Vector3(0, 1, 0), mHydrax->getPosition()); + Ogre::Ray SunToCameraRay = Ogre::Ray(SunPosition, CameraPosition - SunPosition); - Ogre::Vector3 WaterProjectionPoint = SunToCameraRay.getPoint(SunToCameraRay.intersects(WaterPlane).second); + Ogre::Vector3 WaterProjectionPoint = SunToCameraRay.getPoint(SunToCameraRay.intersects(WaterPlane).second); - mProjectorSN->setPosition(WaterProjectionPoint); - mProjectorCamera->setFarClipDistance((WaterProjectionPoint-CameraPosition).length()); - mProjectorSN->setDirection(-(WaterProjectionPoint-CameraPosition).normalisedCopy(), Ogre::Node::TS_WORLD); - } + mProjectorSN->setPosition(WaterProjectionPoint); + mProjectorCamera->setFarClipDistance((WaterProjectionPoint - CameraPosition).length()); + mProjectorSN->setDirection(-(WaterProjectionPoint - CameraPosition).normalisedCopy(), Ogre::Node::TS_WORLD); + } - void GodRaysManager::_createMaterials(const HydraxComponent& HC) - { - Ogre::String VertexProgramData, FragmentProgramData; - Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; - Ogre::String EntryPoints[2]; - if(mHydrax->getShaderMode() == MaterialManager::SM_GLSL) + void GodRaysManager::_createMaterials(const HydraxComponent &HC) + { + Ogre::String VertexProgramData, FragmentProgramData; + Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; + Ogre::String EntryPoints[2]; + if (mHydrax->getShaderMode() == MaterialManager::SM_GLSL) { EntryPoints[0] = Ogre::String("main"); EntryPoints[1] = Ogre::String("main"); @@ -431,484 +397,394 @@ namespace Hydrax EntryPoints[0] = Ogre::String("main_vp"); EntryPoints[1] = Ogre::String("main_fp"); } - Ogre::String GpuProgramsData[2]; Ogre::String GpuProgramNames[2]; - MaterialManager *mMaterialManager = mHydrax->getMaterialManager(); - - int NumberOfDepthChannels = 0; - Ogre::String GB[2] = {"0, 1, 0", "0, 0, 1"}; - - if (_isComponent(HC, HYDRAX_COMPONENT_CAUSTICS)) - { - NumberOfDepthChannels++; - } - - // God Rays material - - VertexProgramData = ""; - FragmentProgramData = ""; - - // Vertex program - - switch (mHydrax->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n"; - if (mObjectsIntersections) - { - VertexProgramData += Ogre::String( - "out float3 oPosition_ : TEXCOORD0,\n") + - "out float4 oProjUV : TEXCOORD1,\n" + - // UNIFORM - "uniform float4x4 uWorld,\n" + - "uniform float4x4 uTexViewProj,\n"; - } - VertexProgramData += Ogre::String( - "uniform float4x4 uWorldViewProj)\n") + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n"; - if (mObjectsIntersections) - { - VertexProgramData += Ogre::String( - "float4 wPos = mul(uWorld, iPosition);\n")+ - "oPosition_ = wPos.xyz;\n"+ - "oProjUV = mul(uTexViewProj, wPos);\n"; - } - VertexProgramData += - "}\n"; - } - break; - - case MaterialManager::SM_GLSL: - { - VertexProgramData += Ogre::String( "\n" ); - // UNIFORMS - if (mObjectsIntersections) - { - VertexProgramData += Ogre::String( - "uniform mat4 uWorld;\n") + - "uniform mat4 uTexViewProj;\n"; - } - // IN - // OUT - if (mObjectsIntersections) - { - VertexProgramData += Ogre::String( - "varying vec3 Position_;\n") + - "varying vec4 ProjUV;\n"; - } - // main function - VertexProgramData += Ogre::String( - "void main()\n") + - "{\n" + - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"; - if (mObjectsIntersections) - { - VertexProgramData += Ogre::String( - "vec4 wPos = uWorld * gl_Vertex);\n")+ - "Position_ = wPos.xyz;\n"+ - "ProjUV = uTexViewProj * wPos;\n"; - } - VertexProgramData += - "}\n"; - } - break; - } - - // Fragment program - - switch (mHydrax->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - if (mObjectsIntersections) - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition : TEXCOORD0,\n" + - "float4 iProjUV : TEXCOORD1,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float3 uLightPosition,\n"+ - "uniform float uLightFarClipDistance,\n" + - "uniform sampler2D uDepthMap : register(s0))\n" + - "{\n" + - "iProjUV = iProjUV / iProjUV.w;\n"+ - "float Depth = tex2D(uDepthMap, iProjUV.xy).r;\n"+ - "if (Depth < saturate( length(iPosition-uLightPosition) / uLightFarClipDistance ))\n"+ - "{\n"+ - "oColor = float4(0,0,0,1);\n"+ - "}\n"+ - "else\n"+ - "{\n"+ - "oColor = float4(float3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1);\n"+ - "}\n"+ - "}\n"; - else - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // OUT - "out float4 oColor : COLOR)\n" + - "{\n" + - "oColor = float4(float3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1);\n"+ - "}\n"; - } - break; - - case MaterialManager::SM_GLSL: - { - if (mObjectsIntersections) - FragmentProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform vec3 uLightPosition;\n"+ - "uniform float uLightFarClipDistance;\n" + - "uniform sampler2D uDepthMap;\n" + - // IN - "varying vec3 Position_;\n" + - "varying vec4 ProjUV;\n" + - // OUT - // main function - "void main()\n" + - "{\n" + - "ProjUV /= ProjUV.w;\n" + - "float Depth = texture2D(uDepthMap, ProjUV.xy).x;\n" + - "if(Depth < clamp( length(Position_-uLightPosition) / uLightFarClipDistance ), 0.0, 1.0)\n" + - "{\n"+ - "gl_FragColor = vec4(0.0,0.0,0.0,1.0);\n"+ - "}\n"+ - "else\n"+ - "{\n"+ - "gl_FragColor = vec4(vec3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1.0);\n"+ - "}\n"+ - "}\n"; - else - FragmentProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform vec3 uLightPosition;\n"+ - "uniform float uLightFarClipDistance;\n" + - "uniform sampler2D uDepthMap;\n" + - // IN - "varying vec3 Position_;\n" + - "varying vec4 ProjUV;\n" + - // OUT - // main function - "void main()\n" + - "{\n" + - "gl_FragColor = vec4(vec3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1.0);\n"+ - "}\n"; - } - break; - } - - // Build our material - mMaterials[0] = Ogre::MaterialManager::getSingleton(). - create(_def_GodRays_Material_Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + Ogre::String GpuProgramsData[2]; + Ogre::String GpuProgramNames[2]; + MaterialManager *mMaterialManager = mHydrax->getMaterialManager(); - Ogre::Pass *GR_Technique0_Pass0 = mMaterials[0]->getTechnique(0)->getPass(0); + int NumberOfDepthChannels = 0; + Ogre::String GB[2] = {"0, 1, 0", "0, 0, 1"}; - GR_Technique0_Pass0->setLightingEnabled(false); - GR_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); - GR_Technique0_Pass0->setDepthWriteEnabled(false); - GR_Technique0_Pass0->setDepthCheckEnabled(mObjectsIntersections); - GR_Technique0_Pass0->setSceneBlending(Ogre::SBT_ADD); + if (_isComponent(HC, HYDRAX_COMPONENT_CAUSTICS)) { NumberOfDepthChannels++; } - GpuProgramsData[0] = VertexProgramData; GpuProgramsData[1] = FragmentProgramData; - GpuProgramNames[0] = _def_GodRays_Shader_VP_Name; GpuProgramNames[1] = _def_GodRays_Shader_FP_Name; + // God Rays material - mMaterialManager->fillGpuProgramsToPass(GR_Technique0_Pass0, GpuProgramNames, mHydrax->getShaderMode(), EntryPoints, GpuProgramsData); + VertexProgramData = ""; + FragmentProgramData = ""; - VP_Parameters = GR_Technique0_Pass0->getVertexProgramParameters(); - FP_Parameters = GR_Technique0_Pass0->getFragmentProgramParameters(); + // Vertex program - if(mHydrax->getShaderMode() != MaterialManager::SM_GLSL) + switch (mHydrax->getShaderMode()) + { + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n"; + if (mObjectsIntersections) + { + VertexProgramData += Ogre::String("out float3 oPosition_ : TEXCOORD0,\n") + + "out float4 oProjUV : TEXCOORD1,\n" + + // UNIFORM + "uniform float4x4 uWorld,\n" + "uniform float4x4 uTexViewProj,\n"; + } + VertexProgramData += + Ogre::String("uniform float4x4 uWorldViewProj)\n") + "{\n" + "oPosition = mul(uWorldViewProj, iPosition);\n"; + if (mObjectsIntersections) + { + VertexProgramData += Ogre::String("float4 wPos = mul(uWorld, iPosition);\n") + "oPosition_ = wPos.xyz;\n" + + "oProjUV = mul(uTexViewProj, wPos);\n"; + } + VertexProgramData += "}\n"; } + break; - if (!mObjectsIntersections) - { - return; - } - - Ogre::Matrix4 TexViewProj = - PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * - mProjectorCamera->getProjectionMatrixWithRSDepth() * - mProjectorCamera->getViewMatrix(); - - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedConstant("uTexViewProj", TexViewProj); + case MaterialManager::SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + if (mObjectsIntersections) + { VertexProgramData += Ogre::String("uniform mat4 uWorld;\n") + "uniform mat4 uTexViewProj;\n"; } + // IN + // OUT + if (mObjectsIntersections) + { VertexProgramData += Ogre::String("varying vec3 Position_;\n") + "varying vec4 ProjUV;\n"; } + // main function + VertexProgramData += + Ogre::String("void main()\n") + "{\n" + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"; + if (mObjectsIntersections) + { + VertexProgramData += Ogre::String("vec4 wPos = uWorld * gl_Vertex);\n") + "Position_ = wPos.xyz;\n" + + "ProjUV = uTexViewProj * wPos;\n"; + } + VertexProgramData += "}\n"; + } + break; + } - FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); - FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); + // Fragment program - int GLSLTextUnit = 0; - if(mHydrax->getShaderMode() == MaterialManager::SM_GLSL) + switch (mHydrax->getShaderMode()) { - FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit); - GLSLTextUnit++; + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: + { + if (mObjectsIntersections) + FragmentProgramData += Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition : TEXCOORD0,\n" + "float4 iProjUV : TEXCOORD1,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float3 uLightPosition,\n" + "uniform float uLightFarClipDistance,\n" + + "uniform sampler2D uDepthMap : register(s0))\n" + "{\n" + + "iProjUV = iProjUV / iProjUV.w;\n" + "float Depth = tex2D(uDepthMap, iProjUV.xy).r;\n" + + "if (Depth < saturate( length(iPosition-uLightPosition) / uLightFarClipDistance ))\n" + + "{\n" + "oColor = float4(0,0,0,1);\n" + "}\n" + "else\n" + "{\n" + + "oColor = float4(float3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1);\n" + "}\n" + "}\n"; + else + FragmentProgramData += Ogre::String("void main_fp(\n") + + // OUT + "out float4 oColor : COLOR)\n" + "{\n" + "oColor = float4(float3(" + + GB[NumberOfDepthChannels] + ") * 0.1, 1);\n" + "}\n"; } - GR_Technique0_Pass0->createTextureUnitState(_def_GodRays_Depth_Map)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - GR_Technique0_Pass0->getTextureUnitState(0)->setTextureName(_def_GodRays_Depth_Map); - - // Depth material - - VertexProgramData = ""; - FragmentProgramData = ""; - - // Vertex program - - switch (mHydrax->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float2 iUV : TEXCOORD0,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float3 oPosition_ : TEXCOORD0,\n" + - // UNIFORM - "uniform float4x4 uWorld,\n" + - "uniform float4x4 uWorldViewProj)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n"+ - "float4 wPos = mul(uWorld, iPosition);\n"+ - "oPosition_ = wPos.xyz;\n"+ - "}\n"; - } - break; - - case MaterialManager::SM_GLSL: - { - VertexProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform mat4 uWorld;\n" + - // IN - // OUT - "varying vec3 Position_;\n" + - // main function - "void main()\n" + - "{\n" + - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"+ - "vec4 wPos = uWorld * gl_Vertex;\n"+ - "Position_ = wPos.xyz;\n"+ - "}\n"; - } - break; - } - - // Fragment program - - switch (mHydrax->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition : TEXCOORD0,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float3 uLightPosition,\n" + - "uniform float uLightFarClipDistance)\n" + - "{\n" + - "float depth = saturate( length(iPosition-uLightPosition) / uLightFarClipDistance );\n"+ - "oColor = float4(depth, 0, 0, 0);\n"+ - "}\n"; - } - break; - - case MaterialManager::SM_GLSL: - { - VertexProgramData += Ogre::String( "\n" ) + + break; + + case MaterialManager::SM_GLSL: + { + if (mObjectsIntersections) + FragmentProgramData += + Ogre::String("\n") + // UNIFORMS - "uniform vec3 uLightPosition;\n" + - "uniform float uLightFarClipDistance;\n" + + "uniform vec3 uLightPosition;\n" + "uniform float uLightFarClipDistance;\n" + + "uniform sampler2D uDepthMap;\n" + // IN - "varying vec3 Position_;\n" + + "varying vec3 Position_;\n" + "varying vec4 ProjUV;\n" + // OUT // main function - "void main()\n" + - "{\n" + - "float depth = clamp( length(Position_-uLightPosition) / uLightFarClipDistance , 0.0, 1.0);\n"+ - "gl_FragColor = vec4(depth, 0.0, 0.0, 0.0);\n"+ - "}\n"; - } - break; - } + "void main()\n" + "{\n" + "ProjUV /= ProjUV.w;\n" + "float Depth = texture2D(uDepthMap, ProjUV.xy).x;\n" + + "if(Depth < clamp( length(Position_-uLightPosition) / uLightFarClipDistance ), 0.0, 1.0)\n" + "{\n" + + "gl_FragColor = vec4(0.0,0.0,0.0,1.0);\n" + "}\n" + "else\n" + "{\n" + "gl_FragColor = vec4(vec3(" + + GB[NumberOfDepthChannels] + ") * 0.1, 1.0);\n" + "}\n" + "}\n"; + else + FragmentProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform vec3 uLightPosition;\n" + "uniform float uLightFarClipDistance;\n" + + "uniform sampler2D uDepthMap;\n" + + // IN + "varying vec3 Position_;\n" + "varying vec4 ProjUV;\n" + + // OUT + // main function + "void main()\n" + "{\n" + "gl_FragColor = vec4(vec3(" + GB[NumberOfDepthChannels] + + ") * 0.1, 1.0);\n" + "}\n"; + } + break; + } - // Build our material - mMaterials[1] = Ogre::MaterialManager::getSingleton(). - create(_def_GodRaysDepth_Material_Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + // Build our material + mMaterials[0] = Ogre::MaterialManager::getSingleton().create(_def_GodRays_Material_Name, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - Ogre::Pass *GRD_Technique0_Pass0 = mMaterials[1]->getTechnique(0)->getPass(0); + Ogre::Pass *GR_Technique0_Pass0 = mMaterials[0]->getTechnique(0)->getPass(0); - mMaterials[1]->getTechnique(0)->setSchemeName("HydraxGodRaysDepth"); + GR_Technique0_Pass0->setLightingEnabled(false); + GR_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + GR_Technique0_Pass0->setDepthWriteEnabled(false); + GR_Technique0_Pass0->setDepthCheckEnabled(mObjectsIntersections); + GR_Technique0_Pass0->setSceneBlending(Ogre::SBT_ADD); - GRD_Technique0_Pass0->setLightingEnabled(false); - GRD_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + GpuProgramsData[0] = VertexProgramData; + GpuProgramsData[1] = FragmentProgramData; + GpuProgramNames[0] = _def_GodRays_Shader_VP_Name; + GpuProgramNames[1] = _def_GodRays_Shader_FP_Name; - GpuProgramsData[0] = VertexProgramData; GpuProgramsData[1] = FragmentProgramData; - GpuProgramNames[0] = _def_GodRaysDepth_Shader_VP_Name; GpuProgramNames[1] = _def_GodRaysDepth_Shader_FP_Name; + mMaterialManager->fillGpuProgramsToPass(GR_Technique0_Pass0, GpuProgramNames, mHydrax->getShaderMode(), EntryPoints, + GpuProgramsData); - mMaterialManager->fillGpuProgramsToPass(GRD_Technique0_Pass0, GpuProgramNames, mHydrax->getShaderMode(), EntryPoints, GpuProgramsData); + VP_Parameters = GR_Technique0_Pass0->getVertexProgramParameters(); + FP_Parameters = GR_Technique0_Pass0->getFragmentProgramParameters(); - VP_Parameters = GRD_Technique0_Pass0->getVertexProgramParameters(); - FP_Parameters = GRD_Technique0_Pass0->getFragmentProgramParameters(); + if (mHydrax->getShaderMode() != MaterialManager::SM_GLSL) + { VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } - if(mHydrax->getShaderMode() != MaterialManager::SM_GLSL) - { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + if (!mObjectsIntersections) { return; } - FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); - FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); - } + Ogre::Matrix4 TexViewProj = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * + mProjectorCamera->getProjectionMatrixWithRSDepth() * mProjectorCamera->getViewMatrix(); - void GodRaysManager::addDepthTechnique(Ogre::Technique *Technique, const bool& AutoUpdate) - { - if (!Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRaysDepth_Material_Name)) - { - HydraxLOG("GodRaysManager::addDepthTechnique(...) Objects intersection must be enabled and Hydrax::create() already called, skipping..."); + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedConstant("uTexViewProj", TexViewProj); - return; - } + FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); + FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); - Technique->removeAllPasses(); - Technique->createPass(); - Technique->setSchemeName("HydraxGodRaysDepth"); + int GLSLTextUnit = 0; + if (mHydrax->getShaderMode() == MaterialManager::SM_GLSL) + { + FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit); + GLSLTextUnit++; + } + GR_Technique0_Pass0->createTextureUnitState(_def_GodRays_Depth_Map) + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + GR_Technique0_Pass0->getTextureUnitState(0)->setTextureName(_def_GodRays_Depth_Map); - Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0); + // Depth material - DM_Technique_Pass0->setVertexProgram(_def_GodRaysDepth_Shader_VP_Name); - DM_Technique_Pass0->setFragmentProgram(_def_GodRaysDepth_Shader_FP_Name); + VertexProgramData = ""; + FragmentProgramData = ""; - Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters(); + // Vertex program - if(mHydrax->getShaderMode() != MaterialManager::SM_GLSL) + switch (mHydrax->getShaderMode()) { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float2 iUV : TEXCOORD0,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float3 oPosition_ : TEXCOORD0,\n" + + // UNIFORM + "uniform float4x4 uWorld,\n" + "uniform float4x4 uWorldViewProj)\n" + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + "float4 wPos = mul(uWorld, iPosition);\n" + + "oPosition_ = wPos.xyz;\n" + "}\n"; } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + break; - FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); - FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); + case MaterialManager::SM_GLSL: + { + VertexProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform mat4 uWorld;\n" + + // IN + // OUT + "varying vec3 Position_;\n" + + // main function + "void main()\n" + "{\n" + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + + "vec4 wPos = uWorld * gl_Vertex;\n" + "Position_ = wPos.xyz;\n" + "}\n"; + } + break; + } - if (AutoUpdate) - { - mDepthTechniques.push_back(Technique); - } - } + // Fragment program - bool GodRaysManager::_isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const - { - if (List & ToCheck) + switch (mHydrax->getShaderMode()) + { + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: { - return true; + FragmentProgramData += Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition : TEXCOORD0,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float3 uLightPosition,\n" + "uniform float uLightFarClipDistance)\n" + "{\n" + + "float depth = saturate( length(iPosition-uLightPosition) / uLightFarClipDistance );\n" + + "oColor = float4(depth, 0, 0, 0);\n" + "}\n"; } + break; - if (ToCheck == HYDRAX_COMPONENTS_NONE && List == HYDRAX_COMPONENTS_NONE) + case MaterialManager::SM_GLSL: { - return true; + VertexProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform vec3 uLightPosition;\n" + "uniform float uLightFarClipDistance;\n" + + // IN + "varying vec3 Position_;\n" + + // OUT + // main function + "void main()\n" + "{\n" + + "float depth = clamp( length(Position_-uLightPosition) / uLightFarClipDistance , 0.0, 1.0);\n" + + "gl_FragColor = vec4(depth, 0.0, 0.0, 0.0);\n" + "}\n"; } + break; + } + + // Build our material + mMaterials[1] = Ogre::MaterialManager::getSingleton().create(_def_GodRaysDepth_Material_Name, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *GRD_Technique0_Pass0 = mMaterials[1]->getTechnique(0)->getPass(0); + + mMaterials[1]->getTechnique(0)->setSchemeName("HydraxGodRaysDepth"); + + GRD_Technique0_Pass0->setLightingEnabled(false); + GRD_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + + GpuProgramsData[0] = VertexProgramData; + GpuProgramsData[1] = FragmentProgramData; + GpuProgramNames[0] = _def_GodRaysDepth_Shader_VP_Name; + GpuProgramNames[1] = _def_GodRaysDepth_Shader_FP_Name; + + mMaterialManager->fillGpuProgramsToPass(GRD_Technique0_Pass0, GpuProgramNames, mHydrax->getShaderMode(), EntryPoints, + GpuProgramsData); + + VP_Parameters = GRD_Technique0_Pass0->getVertexProgramParameters(); + FP_Parameters = GRD_Technique0_Pass0->getFragmentProgramParameters(); - if (ToCheck == HYDRAX_COMPONENTS_ALL && List == HYDRAX_COMPONENTS_ALL) + if (mHydrax->getShaderMode() != MaterialManager::SM_GLSL) + { VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + + FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); + FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); + } + + void GodRaysManager::addDepthTechnique(Ogre::Technique *Technique, const bool &AutoUpdate) + { + if (!Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRaysDepth_Material_Name)) { - return true; + HydraxLOG("GodRaysManager::addDepthTechnique(...) Objects intersection must be enabled and Hydrax::create() already " + "called, skipping..."); + + return; } + Technique->removeAllPasses(); + Technique->createPass(); + Technique->setSchemeName("HydraxGodRaysDepth"); + + Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0); + + DM_Technique_Pass0->setVertexProgram(_def_GodRaysDepth_Shader_VP_Name); + DM_Technique_Pass0->setFragmentProgram(_def_GodRaysDepth_Shader_FP_Name); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters(); + + if (mHydrax->getShaderMode() != MaterialManager::SM_GLSL) + { VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + + FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition()); + FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance()); + + if (AutoUpdate) { mDepthTechniques.push_back(Technique); } + } + + bool GodRaysManager::_isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const + { + if (List & ToCheck) { return true; } + + if (ToCheck == HYDRAX_COMPONENTS_NONE && List == HYDRAX_COMPONENTS_NONE) { return true; } + + if (ToCheck == HYDRAX_COMPONENTS_ALL && List == HYDRAX_COMPONENTS_ALL) { return true; } + return false; - } - - void GodRaysManager::_createDepthRTT() - { - mProjectorRTT = Ogre::TextureManager::getSingleton() - .createManual(_def_GodRays_Depth_Map, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - // 256*256 must be sufficient - 256, - 256, - 0, - // Only one channel - Ogre::PF_L8, - Ogre::TU_RENDERTARGET); - - Ogre::RenderTarget* RT_Texture = mProjectorRTT->getBuffer()->getRenderTarget(); - RT_Texture->setAutoUpdated(false); + } + + void GodRaysManager::_createDepthRTT() + { + mProjectorRTT = Ogre::TextureManager::getSingleton().createManual( + _def_GodRays_Depth_Map, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, + // 256*256 must be sufficient + 256, 256, 0, + // Only one channel + Ogre::PF_L8, Ogre::TU_RENDERTARGET); + + Ogre::RenderTarget *RT_Texture = mProjectorRTT->getBuffer()->getRenderTarget(); + RT_Texture->setAutoUpdated(false); Ogre::Viewport *RT_Texture_Viewport = RT_Texture->addViewport(mProjectorCamera); RT_Texture_Viewport->setClearEveryFrame(true); - RT_Texture_Viewport->setMaterialScheme("HydraxGodRaysDepth"); - RT_Texture_Viewport->setBackgroundColour(Ogre::ColourValue::White); + RT_Texture_Viewport->setMaterialScheme("HydraxGodRaysDepth"); + RT_Texture_Viewport->setBackgroundColour(Ogre::ColourValue::White); RT_Texture_Viewport->setOverlaysEnabled(false); RT_Texture_Viewport->setSkiesEnabled(false); - RT_Texture_Viewport->setShadowsEnabled(false); - mDepthMapListener.mGodRaysManager = this; - RT_Texture->addListener(&mDepthMapListener); - } - - void GodRaysManager::DepthMapListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) - { - Ogre::SceneManager::MovableObjectIterator EntityIterator = mGodRaysManager->mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); - Ogre::Entity * CurrentEntity = NULL; - unsigned int k = 0; - - mMaterials.empty(); - - mGodRaysManager->mHydrax->getMesh()->getEntity()->setVisible(false); - - while( EntityIterator.hasMoreElements() ) - { - CurrentEntity = static_cast(EntityIterator.peekNextValue()); - - for( k = 0; k < CurrentEntity->getNumSubEntities(); k++ ) - { - mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName()); - CurrentEntity->getSubEntity(k)->setMaterialName(_def_GodRaysDepth_Material_Name); - } - - EntityIterator.moveNext(); - } - } - - void GodRaysManager::DepthMapListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) - { - Ogre::SceneManager::MovableObjectIterator EntityIterator = mGodRaysManager->mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); - Ogre::Entity * CurrentEntity = NULL; - unsigned int k = 0; - - mGodRaysManager->mHydrax->getMesh()->getEntity()->setVisible(true); - - while( EntityIterator.hasMoreElements() ) - { - CurrentEntity = static_cast(EntityIterator.peekNextValue()); - - for( k = 0; k < CurrentEntity->getNumSubEntities(); k++ ) - { - CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front()); - mMaterials.pop(); - } - - EntityIterator.moveNext(); - } - } -} + RT_Texture_Viewport->setShadowsEnabled(false); + mDepthMapListener.mGodRaysManager = this; + RT_Texture->addListener(&mDepthMapListener); + } + + void GodRaysManager::DepthMapListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) + { + Ogre::SceneManager::MovableObjectIterator EntityIterator = + mGodRaysManager->mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); + Ogre::Entity *CurrentEntity = NULL; + unsigned int k = 0; + + mMaterials.empty(); + + mGodRaysManager->mHydrax->getMesh()->getEntity()->setVisible(false); + + while (EntityIterator.hasMoreElements()) + { + CurrentEntity = static_cast(EntityIterator.peekNextValue()); + + for (k = 0; k < CurrentEntity->getNumSubEntities(); k++) + { + mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName()); + CurrentEntity->getSubEntity(k)->setMaterialName(_def_GodRaysDepth_Material_Name); + } + + EntityIterator.moveNext(); + } + } + + void GodRaysManager::DepthMapListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) + { + Ogre::SceneManager::MovableObjectIterator EntityIterator = + mGodRaysManager->mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); + Ogre::Entity *CurrentEntity = NULL; + unsigned int k = 0; + + mGodRaysManager->mHydrax->getMesh()->getEntity()->setVisible(true); + + while (EntityIterator.hasMoreElements()) + { + CurrentEntity = static_cast(EntityIterator.peekNextValue()); + + for (k = 0; k < CurrentEntity->getNumSubEntities(); k++) + { + CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front()); + mMaterials.pop(); + } + + EntityIterator.moveNext(); + } + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/GodRaysManager.h b/source/main/gfx/hydrax/GodRaysManager.h index e73c89bf2b..35678ae9dc 100644 --- a/source/main/gfx/hydrax/GodRaysManager.h +++ b/source/main/gfx/hydrax/GodRaysManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,311 +25,302 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_GodRaysManager_H_ #define _Hydrax_GodRaysManager_H_ -#include "Prerequisites.h" -#include "Perlin.h" - #include "Enums.h" +#include "Perlin.h" +#include "Prerequisites.h" namespace Hydrax { - class Hydrax; - - /** Underwater god rays manager class - God rays - */ - class GodRaysManager - { - public: - /** God rays material enumeration - */ - enum MaterialType - { - // Material used for god rays - MAT_GODRAYS = 0, - // Used for depth mat(for objects intersections) - MAT_DEPTH = 1 - }; - - /** Constructor - @param h Hydrax parent pointer - */ - GodRaysManager(Hydrax *h); - - /** Destructor - */ - ~GodRaysManager(); - - /** Create - @param HC Current Hydrax components - */ - void create(const HydraxComponent& HC); - - /** Remove - */ - void remove(); - - /** Call each frame - @param timeSinceLastFrame Time since last frame - */ - void update(const Ogre::Real& timeSinceLastFrame); - - /** Has been create() already called? - @return true If yes - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Add god rays depth technique to an especified material - @param Technique Technique where depth technique will be added - @param AutoUpdate The technique will be automatically updated when god rays parameters change - @remarks Call it after Hydrax::create()/Hydrax::setComponents(...) - - The technique will be automatically updated when god rays parameters change if parameter AutoUpdate == true - Add depth technique when a material is not an Ogre::Entity, such terrains, PLSM2 materials, etc. - This depth technique will be added with "HydraxGodRaysDepth" scheme in ordeto can use it in the G.R. depth RTT. - */ - void addDepthTechnique(Ogre::Technique *Technique, const bool& AutoUpdate = true); - - /** Set god rays simulation speed - @param Speed Simulation speed - */ - inline void SetSimulationSpeed(const Ogre::Real& Speed) - { - mSimulationSpeed = Speed; - } - - /** Get god rays simulation speed - @return Simlation speed - */ - inline const Ogre::Real& getSimulationSpeed() const - { - return mSimulationSpeed; - } - - /** Set the number of god rays - @param NumberOfRays Number of god rays - */ - void setNumberOfRays(const int& NumberOfRays); - - /** Get number of god rays - @return Number of god rays - */ - inline const int& getNumberOfRays() const - { - return mNumberOfRays; - } - - /** Set god rays size - @param Size God rays size - */ - inline void setRaysSize(const Ogre::Real& Size) - { - mRaysSize = Size; - } - - /** Get god rays size - @return Rays size - */ - inline const Ogre::Real& getRaysSize() const - { - return mRaysSize; - } - - /** Get perlin noise module - @return Perlin noise module - */ - inline Noise::Perlin* getPerlin() - { - return mPerlin; - } - - /** Get good rays scene node - @return God rays scene node - */ - inline Ogre::SceneNode* getSceneNode() - { - return mProjectorSN; - } - - /** Set visible - @param Visible true = yes; false = no - */ - inline void setVisible(const bool& Visible) - { - if (mCreated) - { - mManualGodRays->setVisible(Visible); - } - } - - /** Is visible? - @return true if it's visible, false if not - */ - inline const bool isVisible() const - { - if (!mCreated) - { - return false; - } - - return mManualGodRays->isVisible(); - } - - /** Set objects intersections enabled - @param Enable true for yes, false for not - */ - void setObjectIntersectionsEnabled(const bool& Enable); - - /** Are rays objects intersections enabled? - @return true if yes, false if not - */ - inline const bool& areObjectsIntersectionsEnabled() const - { - return mObjectsIntersections; - } - - /** Get noise params - @return Ogre::Vector4 that stores 4 parameters: - x-> Noise derivation - y-> Position multiplier - z-> Y normal component multiplier - w-> Normal multiplier - */ - inline const Ogre::Vector4 getNoiseParameters() const - { - return Ogre::Vector4(mNoiseDerivation, - mNoisePositionMultiplier, - mNoiseYNormalMultiplier, - mNoiseNormalMultiplier); - } - - /** Set noise params - @param Params: x-> Noise derivation - y-> Position multiplier - z-> Y normal component multiplier - w-> Normal multiplier - */ - inline void setNoiseParameters(Ogre::Vector4 Params) - { - mNoiseDerivation = Params.x; - mNoisePositionMultiplier = Params.y; - mNoiseYNormalMultiplier = Params.z; - mNoiseNormalMultiplier = Params.w; - } - - private: - /** GodRaysManager::DepthMapListener class - */ - class DepthMapListener : public Ogre::RenderTargetListener - { - public: - /// God rays manager pointer - GodRaysManager* mGodRaysManager; - - /// std::string to store entity's original materials name - std::queue mMaterials; - - /** Funtion that is called before the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - /** Funtion that is called after the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - }; - - /** Calculate the current position of a ray - @param RayNumber Number of the ray range[0,NumerOfRays] - @return Ray position range[-1,1]x[-1,1] - */ - Ogre::Vector2 _calculateRayPosition(const int& RayNumber); - - /** Create god rays manual object - */ - void _createGodRays(); - - /** Create materials that we need(God rays depth too if it's needed) - @param HC Current Hydrax components - */ - void _createMaterials(const HydraxComponent& HC); - - /** Update god rays - */ - void _updateRays(); - - /** Update materials parameters - */ - void _updateMaterialsParameters(); - - /** Update projector - */ - void _updateProjector(); - - /** Create depth RTT - */ - void _createDepthRTT(); - - /** Is component in the given list? - @param List Components list - @param ToCheck Component to check - @return true if the component is in the given list. - */ - bool _isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const; - - /// Has been create() already called? - bool mCreated; - - /// Manual object to create god rays - Ogre::ManualObject* mManualGodRays; - /// Camera used to project rays - Ogre::Camera *mProjectorCamera; - /// Projector scene node - Ogre::SceneNode *mProjectorSN; - - /// Our Perlin noise module - Noise::Perlin *mPerlin; - - /** Noise parameters (Used in _calculateRayPosition(...)) - */ - /// Normal derivation value - Ogre::Real mNoiseDerivation; - /// PositionMultiplier value - Ogre::Real mNoisePositionMultiplier; - /// Y normal component multiplier - Ogre::Real mNoiseYNormalMultiplier; - /// Normal multiplier - Ogre::Real mNoiseNormalMultiplier; - - /// God rays materials - /// 0-God rays, 1-Depth - Ogre::MaterialPtr mMaterials[2]; - /// Technique vector for addDepthTechnique(...) - std::vector mDepthTechniques; - - /// God rays simulation speed - Ogre::Real mSimulationSpeed; - /// Number of rays - int mNumberOfRays; - /// God rays size - Ogre::Real mRaysSize; - /// Are god rays objects intersections active? - bool mObjectsIntersections; - - /// For rays intersection with objects we use a depth map based technique - /// Depth RTT texture - Ogre::TexturePtr mProjectorRTT; - /// Depth RTT listener - DepthMapListener mDepthMapListener; - - /// Hydrax parent pointer - Hydrax *mHydrax; - }; -}; + class Hydrax; + + /** Underwater god rays manager class + God rays + */ + class GodRaysManager + { + public: + /** God rays material enumeration + */ + enum MaterialType + { + // Material used for god rays + MAT_GODRAYS = 0, + // Used for depth mat(for objects intersections) + MAT_DEPTH = 1 + }; + + /** Constructor + @param h Hydrax parent pointer + */ + GodRaysManager(Hydrax *h); + + /** Destructor + */ + ~GodRaysManager(); + + /** Create + @param HC Current Hydrax components + */ + void create(const HydraxComponent &HC); + + /** Remove + */ + void remove(); + + /** Call each frame + @param timeSinceLastFrame Time since last frame + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Has been create() already called? + @return true If yes + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Add god rays depth technique to an especified material + @param Technique Technique where depth technique will be added + @param AutoUpdate The technique will be automatically updated when god rays parameters change + @remarks Call it after Hydrax::create()/Hydrax::setComponents(...) + + The technique will be automatically updated when god rays parameters change if parameter AutoUpdate == true + Add depth technique when a material is not an Ogre::Entity, such terrains, PLSM2 materials, etc. + This depth technique will be added with "HydraxGodRaysDepth" scheme in ordeto can use it in the G.R. depth + RTT. + */ + void addDepthTechnique(Ogre::Technique *Technique, const bool &AutoUpdate = true); + + /** Set god rays simulation speed + @param Speed Simulation speed + */ + inline void SetSimulationSpeed(const Ogre::Real &Speed) + { + mSimulationSpeed = Speed; + } + + /** Get god rays simulation speed + @return Simlation speed + */ + inline const Ogre::Real &getSimulationSpeed() const + { + return mSimulationSpeed; + } + + /** Set the number of god rays + @param NumberOfRays Number of god rays + */ + void setNumberOfRays(const int &NumberOfRays); + + /** Get number of god rays + @return Number of god rays + */ + inline const int &getNumberOfRays() const + { + return mNumberOfRays; + } + + /** Set god rays size + @param Size God rays size + */ + inline void setRaysSize(const Ogre::Real &Size) + { + mRaysSize = Size; + } + + /** Get god rays size + @return Rays size + */ + inline const Ogre::Real &getRaysSize() const + { + return mRaysSize; + } + + /** Get perlin noise module + @return Perlin noise module + */ + inline Noise::Perlin *getPerlin() + { + return mPerlin; + } + + /** Get good rays scene node + @return God rays scene node + */ + inline Ogre::SceneNode *getSceneNode() + { + return mProjectorSN; + } + + /** Set visible + @param Visible true = yes; false = no + */ + inline void setVisible(const bool &Visible) + { + if (mCreated) { mManualGodRays->setVisible(Visible); } + } + + /** Is visible? + @return true if it's visible, false if not + */ + inline const bool isVisible() const + { + if (!mCreated) { return false; } + + return mManualGodRays->isVisible(); + } + + /** Set objects intersections enabled + @param Enable true for yes, false for not + */ + void setObjectIntersectionsEnabled(const bool &Enable); + + /** Are rays objects intersections enabled? + @return true if yes, false if not + */ + inline const bool &areObjectsIntersectionsEnabled() const + { + return mObjectsIntersections; + } + + /** Get noise params + @return Ogre::Vector4 that stores 4 parameters: + x-> Noise derivation + y-> Position multiplier + z-> Y normal component multiplier + w-> Normal multiplier + */ + inline const Ogre::Vector4 getNoiseParameters() const + { + return Ogre::Vector4(mNoiseDerivation, mNoisePositionMultiplier, mNoiseYNormalMultiplier, mNoiseNormalMultiplier); + } + + /** Set noise params + @param Params: x-> Noise derivation + y-> Position multiplier + z-> Y normal component multiplier + w-> Normal multiplier + */ + inline void setNoiseParameters(Ogre::Vector4 Params) + { + mNoiseDerivation = Params.x; + mNoisePositionMultiplier = Params.y; + mNoiseYNormalMultiplier = Params.z; + mNoiseNormalMultiplier = Params.w; + } + + private: + /** GodRaysManager::DepthMapListener class + */ + class DepthMapListener : public Ogre::RenderTargetListener + { + public: + /// God rays manager pointer + GodRaysManager *mGodRaysManager; + + /// std::string to store entity's original materials name + std::queue mMaterials; + + /** Funtion that is called before the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + + /** Funtion that is called after the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + }; + + /** Calculate the current position of a ray + @param RayNumber Number of the ray range[0,NumerOfRays] + @return Ray position range[-1,1]x[-1,1] + */ + Ogre::Vector2 _calculateRayPosition(const int &RayNumber); + + /** Create god rays manual object + */ + void _createGodRays(); + + /** Create materials that we need(God rays depth too if it's needed) + @param HC Current Hydrax components + */ + void _createMaterials(const HydraxComponent &HC); + + /** Update god rays + */ + void _updateRays(); + + /** Update materials parameters + */ + void _updateMaterialsParameters(); + + /** Update projector + */ + void _updateProjector(); + + /** Create depth RTT + */ + void _createDepthRTT(); + + /** Is component in the given list? + @param List Components list + @param ToCheck Component to check + @return true if the component is in the given list. + */ + bool _isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const; + + /// Has been create() already called? + bool mCreated; + + /// Manual object to create god rays + Ogre::ManualObject *mManualGodRays; + /// Camera used to project rays + Ogre::Camera *mProjectorCamera; + /// Projector scene node + Ogre::SceneNode *mProjectorSN; + + /// Our Perlin noise module + Noise::Perlin *mPerlin; + + /** Noise parameters (Used in _calculateRayPosition(...)) + */ + /// Normal derivation value + Ogre::Real mNoiseDerivation; + /// PositionMultiplier value + Ogre::Real mNoisePositionMultiplier; + /// Y normal component multiplier + Ogre::Real mNoiseYNormalMultiplier; + /// Normal multiplier + Ogre::Real mNoiseNormalMultiplier; + + /// God rays materials + /// 0-God rays, 1-Depth + Ogre::MaterialPtr mMaterials[2]; + /// Technique vector for addDepthTechnique(...) + std::vector mDepthTechniques; + + /// God rays simulation speed + Ogre::Real mSimulationSpeed; + /// Number of rays + int mNumberOfRays; + /// God rays size + Ogre::Real mRaysSize; + /// Are god rays objects intersections active? + bool mObjectsIntersections; + + /// For rays intersection with objects we use a depth map based technique + /// Depth RTT texture + Ogre::TexturePtr mProjectorRTT; + /// Depth RTT listener + DepthMapListener mDepthMapListener; + + /// Hydrax parent pointer + Hydrax *mHydrax; + }; +}; // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/Help.cpp b/source/main/gfx/hydrax/Help.cpp index aa70cccc25..5fa91e6256 100644 --- a/source/main/gfx/hydrax/Help.cpp +++ b/source/main/gfx/hydrax/Help.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -26,49 +26,42 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace Hydrax { - Ogre::Vector2 Math::intersectionOfTwoLines(const Ogre::Vector2 &a, const Ogre::Vector2 &b, - const Ogre::Vector2 &c, const Ogre::Vector2 &d) - { - float r, s, denominator = (b.x - a.x) * (d.y - c.y) - (b.y - a.y) * (d.x - c.x); + Ogre::Vector2 Math::intersectionOfTwoLines(const Ogre::Vector2 &a, const Ogre::Vector2 &b, const Ogre::Vector2 &c, + const Ogre::Vector2 &d) + { + float r, s, denominator = (b.x - a.x) * (d.y - c.y) - (b.y - a.y) * (d.x - c.x); - // If the denominator in above is zero, AB & CD are colinear - if (denominator == 0) - { - return Ogre::Vector2::ZERO; - } + // If the denominator in above is zero, AB & CD are colinear + if (denominator == 0) { return Ogre::Vector2::ZERO; } - float numeratorR = (a.y - c.y) * (d.x - c.x) - (a.x - c.x) * (d.y - c.y); - // If the numerator above is also zero, AB & CD are collinear. - // If they are collinear, then the segments may be projected to the x- - // or y-axis, and overlap of the projected intervals checked. + float numeratorR = (a.y - c.y) * (d.x - c.x) - (a.x - c.x) * (d.y - c.y); + // If the numerator above is also zero, AB & CD are collinear. + // If they are collinear, then the segments may be projected to the x- + // or y-axis, and overlap of the projected intervals checked. - r = numeratorR / denominator; + r = numeratorR / denominator; - float numeratorS = (a.y - c.y) * (b.x - a.x) - (a.x - c.x) * (b.y - a.y); + float numeratorS = (a.y - c.y) * (b.x - a.x) - (a.x - c.x) * (b.y - a.y); - s = numeratorS / denominator; + s = numeratorS / denominator; - // If 0<=r<=1 & 0<=s<=1, intersection exists - // r<0 or r>1 or s<0 or s>1 line segments do not intersect - if (r < 0 || r > 1 || s < 0 || s > 1) - { - return Ogre::Vector2::ZERO; - } + // If 0<=r<=1 & 0<=s<=1, intersection exists + // r<0 or r>1 or s<0 or s>1 line segments do not intersect + if (r < 0 || r > 1 || s < 0 || s > 1) { return Ogre::Vector2::ZERO; } - ///* - // Note: - // If the intersection point of the 2 lines are needed (lines in this - // context mean infinite lines) regardless whether the two line - // segments intersect, then - // - // If r>1, P is located on extension of AB - // If r<0, P is located on extension of BA - // If s>1, P is located on extension of CD - // If s<0, P is located on extension of DC - //*/ + ///* + // Note: + // If the intersection point of the 2 lines are needed (lines in this + // context mean infinite lines) regardless whether the two line + // segments intersect, then + // + // If r>1, P is located on extension of AB + // If r<0, P is located on extension of BA + // If s>1, P is located on extension of CD + // If s<0, P is located on extension of DC + //*/ - // Find intersection point - return Ogre::Vector2((a.x + (r * (b.x - a.x))), - (a.y + (r * (b.y - a.y)))); - } -} + // Find intersection point + return Ogre::Vector2((a.x + (r * (b.x - a.x))), (a.y + (r * (b.y - a.y)))); + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Help.h b/source/main/gfx/hydrax/Help.h index 0ad1839257..7d9abdf72e 100644 --- a/source/main/gfx/hydrax/Help.h +++ b/source/main/gfx/hydrax/Help.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -30,7 +30,7 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace Hydrax { /** Struct wich contains an especific width and height value - */ + */ struct Size { /// Width value @@ -39,7 +39,7 @@ namespace Hydrax int Height; /** Default constructor - */ + */ Size() { Width = 0; @@ -47,7 +47,7 @@ namespace Hydrax } /** Constructor - @param size The width and height values + @param size The width and height values */ Size(const int &size) { @@ -56,8 +56,8 @@ namespace Hydrax } /** Constructor - @param width Width value - @param height Height value + @param width Width value + @param height Height value */ Size(const int &width, const int &height) { @@ -66,13 +66,13 @@ namespace Hydrax } /** Destructor - */ + */ ~Size() { } /** Sets the same width and height value - @param size The width and height values + @param size The width and height values */ void setSize(const int &size) { @@ -81,8 +81,8 @@ namespace Hydrax } /** Sets the especified values - @param width Width value - @param height Height value + @param width Width value + @param height Height value */ void setSize(const int &width, const int &height) { @@ -91,28 +91,28 @@ namespace Hydrax } }; - /** Math class with some help funtions - */ - class Math - { - public: - /** Constructor - */ - Math(){}; - /** Destructor - */ - ~Math(){}; - - /** Find the intersection point of two lines - @param a First line origin - @param b First line final - @param c First line origin - @param d First line final - @return Ogre::Vector2::ZERO if there isn't intersection, intersection point - */ - static Ogre::Vector2 intersectionOfTwoLines(const Ogre::Vector2 &a, const Ogre::Vector2 &b, - const Ogre::Vector2 &c, const Ogre::Vector2 &d); - }; -} + /** Math class with some help funtions + */ + class Math + { + public: + /** Constructor + */ + Math(){}; + /** Destructor + */ + ~Math(){}; + + /** Find the intersection point of two lines + @param a First line origin + @param b First line final + @param c First line origin + @param d First line final + @return Ogre::Vector2::ZERO if there isn't intersection, intersection point + */ + static Ogre::Vector2 intersectionOfTwoLines(const Ogre::Vector2 &a, const Ogre::Vector2 &b, const Ogre::Vector2 &c, + const Ogre::Vector2 &d); + }; +} // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/Hydrax.cpp b/source/main/gfx/hydrax/Hydrax.cpp index 3374793439..67efdec5e9 100644 --- a/source/main/gfx/hydrax/Hydrax.cpp +++ b/source/main/gfx/hydrax/Hydrax.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -23,78 +23,46 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to -------------------------------------------------------------------------------- Contributors: - Jose Luis Cercós Pita + Jose Luis Cerc�s Pita -------------------------------------------------------------------------------- */ -#pragma warning(disable:4355) +#pragma warning(disable : 4355) #include namespace Hydrax { - Hydrax::Hydrax(Ogre::SceneManager *sm, Ogre::Camera *c, Ogre::Viewport *v) - : mSceneManager(sm) - , mCamera(c) - , mViewport(v) - , mCreated(false) - , mVisible(true) - , mPolygonMode(Ogre::PM_SOLID) - , mShaderMode(MaterialManager::SM_HLSL) - , mPosition(Ogre::Vector3(0,0,0)) - , mPlanesError(0) - , mFullReflectionDistance(99999997952.0) - , mGlobalTransparency(0.05) - , mWaterColor(Ogre::Vector3(0,0.1,0.172)) - , mNormalDistortion(0.09) - , mSunPosition(Ogre::Vector3(5000,3000,1)) - , mSunStrength(1.75) - , mSunArea(150) - , mSunColor(Ogre::Vector3(1,0.75,0.25)) - , mFoamMaxDistance(75000000.0) - , mFoamScale(0.0075) - , mFoamStart(0) - , mFoamTransparency(1) - , mDepthLimit(0) - , mSmoothPower(30) - , mCausticsScale(20) - , mCausticsPower(15) - , mCausticsEnd(0.55) - , mGodRaysExposure(Ogre::Vector3(0.76,2.46,2.29)) - , mGodRaysIntensity(0.015) - , mUnderwaterCameraSwitchDelta(0.1f) - , mCurrentFrameUnderwater(false) - , mMesh(new Mesh(this)) - , mMaterialManager(new MaterialManager(this)) - , mRttManager(new RttManager(this)) - , mTextureManager(new TextureManager(this)) - , mGodRaysManager(new GodRaysManager(this)) - , mDecalsManager(new DecalsManager(this)) - , mGPUNormalMapManager(new GPUNormalMapManager(this)) - , mCfgFileManager(new CfgFileManager(this)) - , mModule(0) - , mComponents(HYDRAX_COMPONENTS_NONE) + Hydrax::Hydrax(Ogre::SceneManager *sm, Ogre::Camera *c, Ogre::Viewport *v) + : mSceneManager(sm), mCamera(c), mViewport(v), mCreated(false), mVisible(true), mPolygonMode(Ogre::PM_SOLID), + mShaderMode(MaterialManager::SM_HLSL), mPosition(Ogre::Vector3(0, 0, 0)), mPlanesError(0), + mFullReflectionDistance(99999997952.0), mGlobalTransparency(0.05), mWaterColor(Ogre::Vector3(0, 0.1, 0.172)), + mNormalDistortion(0.09), mSunPosition(Ogre::Vector3(5000, 3000, 1)), mSunStrength(1.75), mSunArea(150), + mSunColor(Ogre::Vector3(1, 0.75, 0.25)), mFoamMaxDistance(75000000.0), mFoamScale(0.0075), mFoamStart(0), + mFoamTransparency(1), mDepthLimit(0), mSmoothPower(30), mCausticsScale(20), mCausticsPower(15), mCausticsEnd(0.55), + mGodRaysExposure(Ogre::Vector3(0.76, 2.46, 2.29)), mGodRaysIntensity(0.015), mUnderwaterCameraSwitchDelta(0.1f), + mCurrentFrameUnderwater(false), mMesh(new Mesh(this)), mMaterialManager(new MaterialManager(this)), + mRttManager(new RttManager(this)), mTextureManager(new TextureManager(this)), mGodRaysManager(new GodRaysManager(this)), + mDecalsManager(new DecalsManager(this)), mGPUNormalMapManager(new GPUNormalMapManager(this)), + mCfgFileManager(new CfgFileManager(this)), mModule(0), mComponents(HYDRAX_COMPONENTS_NONE) { HydraxLOG("Hydrax created."); } Hydrax::~Hydrax() { - remove(); - - if (mModule) - { - delete mModule; - } - - delete mTextureManager; - delete mMaterialManager; - delete mGPUNormalMapManager; - delete mDecalsManager; - delete mGodRaysManager; - delete mRttManager; - delete mCfgFileManager; + remove(); + + if (mModule) { delete mModule; } + + delete mTextureManager; + delete mMaterialManager; + delete mGPUNormalMapManager; + delete mDecalsManager; + delete mGodRaysManager; + delete mRttManager; + delete mCfgFileManager; delete mMesh; HydraxLOG("Hydrax object removed."); @@ -102,12 +70,12 @@ namespace Hydrax void Hydrax::create() { - if (!mModule) - { - HydraxLOG("Module isn't set, skipping..."); + if (!mModule) + { + HydraxLOG("Module isn't set, skipping..."); return; - } + } if (mCreated) { @@ -119,641 +87,513 @@ namespace Hydrax HydraxLOG("Creating module..."); mModule->create(); - if (mModule->getNormalMode() == MaterialManager::NM_RTT) - { - if (!mModule->getNoise()->createGPUNormalMapResources(mGPUNormalMapManager)) - { - HydraxLOG(mModule->getNoise()->getName() + " doesn't support GPU Normal map generation."); - } - } - else - { - if (mModule->getNoise()->areGPUNormalMapResourcesCreated()) - { - mModule->getNoise()->removeGPUNormalMapResources(mGPUNormalMapManager); - } - } + if (mModule->getNormalMode() == MaterialManager::NM_RTT) + { + if (!mModule->getNoise()->createGPUNormalMapResources(mGPUNormalMapManager)) + { HydraxLOG(mModule->getNoise()->getName() + " doesn't support GPU Normal map generation."); } + } + else + { + if (mModule->getNoise()->areGPUNormalMapResourcesCreated()) + { mModule->getNoise()->removeGPUNormalMapResources(mGPUNormalMapManager); } + } HydraxLOG("Module created."); - HydraxLOG("Initializating RTT Manager..."); - mRttManager->initialize(RttManager::RTT_REFLECTION); - mRttManager->initialize(RttManager::RTT_REFRACTION); - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - mRttManager->initialize(RttManager::RTT_DEPTH); - } + HydraxLOG("Initializating RTT Manager..."); + mRttManager->initialize(RttManager::RTT_REFLECTION); + mRttManager->initialize(RttManager::RTT_REFRACTION); + if (isComponent(HYDRAX_COMPONENT_DEPTH)) { mRttManager->initialize(RttManager::RTT_DEPTH); } HydraxLOG("RTT manager initialized."); - HydraxLOG("Registring device restored listener..."); - mDeviceListener.mHydrax = this; - Ogre::Root::getSingleton().getRenderSystem()->addListener(&mDeviceListener); - HydraxLOG("Device restored listener registred."); + HydraxLOG("Registring device restored listener..."); + mDeviceListener.mHydrax = this; + Ogre::Root::getSingleton().getRenderSystem()->addListener(&mDeviceListener); + HydraxLOG("Device restored listener registred."); - HydraxLOG("Creating materials..."); - mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, mModule->getNormalMode())); - mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); - HydraxLOG("Materials created."); + HydraxLOG("Creating materials..."); + mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, mModule->getNormalMode())); + mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); + HydraxLOG("Materials created."); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - HydraxLOG("Creating god rays..."); - mGodRaysManager->create(mComponents); - HydraxLOG("God rays created."); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) + { + HydraxLOG("Creating god rays..."); + mGodRaysManager->create(mComponents); + HydraxLOG("God rays created."); + } HydraxLOG("Creating water mesh..."); - mMesh->setOptions(mModule->getMeshOptions()); + mMesh->setOptions(mModule->getMeshOptions()); mMesh->create(); HydraxLOG("Water mesh created."); mCreated = true; - // Hide if !mVisible - _checkVisible(); - // Check for underwater - _checkUnderwater(0); + // Hide if !mVisible + _checkVisible(); + // Check for underwater + _checkUnderwater(0); } - void Hydrax::remove() - { - if (!mCreated) - { - return; - } - - Ogre::Root::getSingleton().getRenderSystem()->removeListener(&mDeviceListener); - - mMesh->remove(); - mDecalsManager->removeAll(); - mMaterialManager->removeMaterials(); - mRttManager->removeAll(); - mGodRaysManager->remove(); - mModule->remove(); + void Hydrax::remove() + { + if (!mCreated) { return; } + + Ogre::Root::getSingleton().getRenderSystem()->removeListener(&mDeviceListener); + + mMesh->remove(); + mDecalsManager->removeAll(); + mMaterialManager->removeMaterials(); + mRttManager->removeAll(); + mGodRaysManager->remove(); + mModule->remove(); mTextureManager->remove(); - mCreated = false; - } + mCreated = false; + } - void Hydrax::setVisible(const bool& Visible) - { - mVisible = Visible; + void Hydrax::setVisible(const bool &Visible) + { + mVisible = Visible; - _checkVisible(); - } + _checkVisible(); + } - void Hydrax::_checkVisible() - { - if (!mCreated) - { - return; - } + void Hydrax::_checkVisible() + { + if (!mCreated) { return; } - if (!mVisible) - { - // Stop RTTs: + if (!mVisible) + { + // Stop RTTs: mRttManager->removeAll(); - // Hide hydrax mesh - mMesh->getSceneNode()->setVisible(false); - - // Stop compositor (MaterialManager::setCompositorEnable(...) checks if underwater compositor exists) - mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false); - } - else - { - // Start reflection and refraction RTTs: - mRttManager->initialize(RttManager::RTT_REFLECTION); - mRttManager->initialize(RttManager::RTT_REFRACTION); - - // Start depth rtt if needed: - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - mRttManager->initialize(RttManager::RTT_DEPTH); - } - - // Start GPU normals rtt if needed: - if (mModule->getNormalMode() == MaterialManager::NM_RTT) - { - mGPUNormalMapManager->create(); - } - - // Set over-water material and check for underwater: - mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); - mMaterialManager->reload(MaterialManager::MAT_WATER); - - _checkUnderwater(0); - - // Set hydrax mesh node visible - mMesh->getSceneNode()->setVisible(true); - } - } - - void Hydrax::DeviceListener::eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList *parameters) - { - // If needed... - - if (eventName == "DeviceLost") - {} - - if (eventName == "DeviceRestored") - {} - } - - void Hydrax::setPolygonMode(const Ogre::PolygonMode& PM) + // Hide hydrax mesh + mMesh->getSceneNode()->setVisible(false); + + // Stop compositor (MaterialManager::setCompositorEnable(...) checks if underwater compositor exists) + mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false); + } + else + { + // Start reflection and refraction RTTs: + mRttManager->initialize(RttManager::RTT_REFLECTION); + mRttManager->initialize(RttManager::RTT_REFRACTION); + + // Start depth rtt if needed: + if (isComponent(HYDRAX_COMPONENT_DEPTH)) { mRttManager->initialize(RttManager::RTT_DEPTH); } + + // Start GPU normals rtt if needed: + if (mModule->getNormalMode() == MaterialManager::NM_RTT) { mGPUNormalMapManager->create(); } + + // Set over-water material and check for underwater: + mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); + mMaterialManager->reload(MaterialManager::MAT_WATER); + + _checkUnderwater(0); + + // Set hydrax mesh node visible + mMesh->getSceneNode()->setVisible(true); + } + } + + void Hydrax::DeviceListener::eventOccurred(const Ogre::String &eventName, const Ogre::NameValuePairList *parameters) { - if (!mCreated) - { - return; - } + // If needed... + + if (eventName == "DeviceLost") {} - mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getTechnique(0)->getPass(0)->setPolygonMode(PM); + if (eventName == "DeviceRestored") {} + } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getTechnique(0)->getPass(0)->setPolygonMode(PM); - } + void Hydrax::setPolygonMode(const Ogre::PolygonMode &PM) + { + if (!mCreated) { return; } - mPolygonMode = PM; + mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getTechnique(0)->getPass(0)->setPolygonMode(PM); + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getTechnique(0)->getPass(0)->setPolygonMode(PM); } + + mPolygonMode = PM; } - void Hydrax::setShaderMode(const MaterialManager::ShaderMode& ShaderMode) - { - mShaderMode = ShaderMode; + void Hydrax::setShaderMode(const MaterialManager::ShaderMode &ShaderMode) + { + mShaderMode = ShaderMode; - if (mCreated && mModule) - { - mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, mModule->getNormalMode())); + if (mCreated && mModule) + { + mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, mModule->getNormalMode())); - mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); - } - } + mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); + } + } void Hydrax::update(const Ogre::Real &timeSinceLastFrame) - { - if (mCreated && mModule && mVisible) - { + { + if (mCreated && mModule && mVisible) + { mModule->update(timeSinceLastFrame); - mDecalsManager->update(); - _checkUnderwater(timeSinceLastFrame); - } + mDecalsManager->update(); + _checkUnderwater(timeSinceLastFrame); + } } void Hydrax::setComponents(const HydraxComponent &Components) { mComponents = Components; - if (isComponent(HYDRAX_COMPONENT_SMOOTH) || isComponent(HYDRAX_COMPONENT_CAUSTICS) || isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) + if (isComponent(HYDRAX_COMPONENT_SMOOTH) || isComponent(HYDRAX_COMPONENT_CAUSTICS) || + isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) { - // Delete smooth and/or caustics components wich needs depth component + // Delete smooth and/or caustics components wich needs depth component if (!isComponent(HYDRAX_COMPONENT_DEPTH)) { - HydraxComponent s = HYDRAX_COMPONENTS_NONE, - f = HYDRAX_COMPONENTS_NONE, - u = HYDRAX_COMPONENTS_NONE, - ur = HYDRAX_COMPONENTS_NONE; - - if (isComponent(HYDRAX_COMPONENT_SUN)) - { - s = HYDRAX_COMPONENT_SUN; - } - if (isComponent(HYDRAX_COMPONENT_FOAM)) - { - f = HYDRAX_COMPONENT_FOAM; - } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - u = HYDRAX_COMPONENT_UNDERWATER; - } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - ur = HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS; - } - - if (isComponent(HYDRAX_COMPONENT_SMOOTH)) - { - HydraxLOG("Smooth component needs depth component... smooth component desactivated."); - } - if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - HydraxLOG("Caustics component needs depth component... caustics component desactivated."); - } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - HydraxLOG("God rays component needs depth component... god rays component desactivated."); - } - - mComponents = static_cast(s|f|u|ur); + HydraxComponent s = HYDRAX_COMPONENTS_NONE, f = HYDRAX_COMPONENTS_NONE, u = HYDRAX_COMPONENTS_NONE, + ur = HYDRAX_COMPONENTS_NONE; + + if (isComponent(HYDRAX_COMPONENT_SUN)) { s = HYDRAX_COMPONENT_SUN; } + if (isComponent(HYDRAX_COMPONENT_FOAM)) { f = HYDRAX_COMPONENT_FOAM; } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) { u = HYDRAX_COMPONENT_UNDERWATER; } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) { ur = HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS; } + + if (isComponent(HYDRAX_COMPONENT_SMOOTH)) + { HydraxLOG("Smooth component needs depth component... smooth component desactivated."); } + if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) + { HydraxLOG("Caustics component needs depth component... caustics component desactivated."); } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) + { HydraxLOG("God rays component needs depth component... god rays component desactivated."); } + + mComponents = static_cast(s | f | u | ur); } } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS) || isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - // Delete underwater reflections components wich needs underwater component - if (!isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - HydraxComponent s = HYDRAX_COMPONENTS_NONE, - f = HYDRAX_COMPONENTS_NONE, - d = HYDRAX_COMPONENTS_NONE, - sm = HYDRAX_COMPONENTS_NONE, - c = HYDRAX_COMPONENTS_NONE; - - if (isComponent(HYDRAX_COMPONENT_SUN)) - { - s = HYDRAX_COMPONENT_SUN; - } - if (isComponent(HYDRAX_COMPONENT_FOAM)) - { - f = HYDRAX_COMPONENT_FOAM; - } - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - d = HYDRAX_COMPONENT_DEPTH; - } - if (isComponent(HYDRAX_COMPONENT_SMOOTH)) - { - sm = HYDRAX_COMPONENT_SMOOTH; - } - if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - c = HYDRAX_COMPONENT_CAUSTICS; - } - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - HydraxLOG("Underwater reflections component needs underwater component... underwater reflections component desactivated."); - } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - HydraxLOG("God rays component needs underwater component... god rays component desactivated."); - } - - mComponents = static_cast(s|f|d|sm|c); - } - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS) && !isComponent(HYDRAX_COMPONENT_SUN)) - { - HydraxLOG("God rays component needs sun component... god rays component desactivated."); - - HydraxComponent f = HYDRAX_COMPONENTS_NONE, - d = HYDRAX_COMPONENTS_NONE, - c = HYDRAX_COMPONENTS_NONE, - sm = HYDRAX_COMPONENTS_NONE, - u = HYDRAX_COMPONENTS_NONE, - ur = HYDRAX_COMPONENTS_NONE; - - if (isComponent(HYDRAX_COMPONENT_FOAM)) - { - f = HYDRAX_COMPONENT_FOAM; - } - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - d = HYDRAX_COMPONENT_DEPTH; - } - if (isComponent(HYDRAX_COMPONENT_SMOOTH)) - { - sm = HYDRAX_COMPONENT_SMOOTH; - } - if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - c = HYDRAX_COMPONENT_CAUSTICS; - } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - u = HYDRAX_COMPONENT_UNDERWATER; - } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - ur = HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS; - } - - mComponents = static_cast(f|d|sm|c|u|ur); - } - } - - int NumberOfDepthChannels = 0; - - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - NumberOfDepthChannels++; - - if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - NumberOfDepthChannels++; - } - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - NumberOfDepthChannels++; - } - } - - if (NumberOfDepthChannels > 0) - { - mRttManager->setNumberOfChannels(RttManager::RTT_DEPTH, static_cast(NumberOfDepthChannels)); - } - - if (!mCreated || !mModule) - { - return; - } - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - mGodRaysManager->create(mComponents); - } - else - { - mGodRaysManager->remove(); - } - - // Check for Rtt's - if (mCurrentFrameUnderwater && isComponent(HYDRAX_COMPONENT_UNDERWATER) && !isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - mRttManager->remove(RttManager::RTT_REFLECTION); - } - else - { - mRttManager->initialize(RttManager::RTT_REFLECTION); - } - - if (!isComponent(HYDRAX_COMPONENT_DEPTH)) - { - mRttManager->remove(RttManager::RTT_DEPTH); - mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION); - } - else - { - mRttManager->initialize(RttManager::RTT_DEPTH); - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS) && mCurrentFrameUnderwater) - { - mRttManager->initialize(RttManager::RTT_DEPTH_REFLECTION); - } - else - { - mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION); - } - } - if (!isComponent(HYDRAX_COMPONENT_UNDERWATER) && mCurrentFrameUnderwater) - { - mRttManager->getTexture(RttManager::RTT_REFRACTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setSkiesEnabled(false); - - mRttManager->getTexture(RttManager::RTT_REFLECTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setSkiesEnabled(true); - } - - mMesh->setMaterialName("BaseWhiteNoLighting"); - mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, mModule->getNormalMode())); - - if (!isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mCurrentFrameUnderwater = false; - } - - mMesh->setMaterialName(mCurrentFrameUnderwater ? - mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName() : - mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); - - if (mCurrentFrameUnderwater) - { - mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true); - } - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS) || isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) + { + // Delete underwater reflections components wich needs underwater component + if (!isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + HydraxComponent s = HYDRAX_COMPONENTS_NONE, f = HYDRAX_COMPONENTS_NONE, d = HYDRAX_COMPONENTS_NONE, + sm = HYDRAX_COMPONENTS_NONE, c = HYDRAX_COMPONENTS_NONE; + + if (isComponent(HYDRAX_COMPONENT_SUN)) { s = HYDRAX_COMPONENT_SUN; } + if (isComponent(HYDRAX_COMPONENT_FOAM)) { f = HYDRAX_COMPONENT_FOAM; } + if (isComponent(HYDRAX_COMPONENT_DEPTH)) { d = HYDRAX_COMPONENT_DEPTH; } + if (isComponent(HYDRAX_COMPONENT_SMOOTH)) { sm = HYDRAX_COMPONENT_SMOOTH; } + if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) { c = HYDRAX_COMPONENT_CAUSTICS; } + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { + HydraxLOG("Underwater reflections component needs underwater component... underwater reflections component " + "desactivated."); + } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) + { HydraxLOG("God rays component needs underwater component... god rays component desactivated."); } + + mComponents = static_cast(s | f | d | sm | c); + } - void Hydrax::setModule(Module::Module* Module, const bool& DeleteOldModule) - { - if (mModule) - { - if (mModule->getNormalMode() != Module->getNormalMode()) - { - mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, Module->getNormalMode())); - - mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); - } - - if (mModule->getNormalMode() == MaterialManager::NM_RTT && mModule->isCreated() && mModule->getNoise()->areGPUNormalMapResourcesCreated()) - { - mModule->getNoise()->removeGPUNormalMapResources(mGPUNormalMapManager); - } - - if (DeleteOldModule) - { - delete mModule; - } - else - { - mModule->remove(); - } - - // Due to modules can change -internally- scene nodes position, - // just reset them to the original position. - setPosition(mPosition); - } - - mModule = Module; - - if (mCreated) - { - if (!mModule->isCreated()) - { - mModule->create(); - - if (mModule->getNormalMode() == MaterialManager::NM_RTT) - { - if (!mModule->getNoise()->createGPUNormalMapResources(mGPUNormalMapManager)) - { - HydraxLOG(mModule->getNoise()->getName() + " doesn't support GPU Normal map generation."); - } - } - } - else - { - if (mModule->getNormalMode() == MaterialManager::NM_RTT) - { - if (!mModule->getNoise()->areGPUNormalMapResourcesCreated()) - { - if (!mModule->getNoise()->createGPUNormalMapResources(mGPUNormalMapManager)) - { - HydraxLOG(mModule->getNoise()->getName() + " doesn't support GPU Normal map generation."); - } - } - } - else - { - if (mModule->getNoise()->areGPUNormalMapResourcesCreated()) - { - mModule->getNoise()->removeGPUNormalMapResources(mGPUNormalMapManager); - } - } - } - - HydraxLOG("Updating water mesh..."); - Ogre::String MaterialNameTmp = mMesh->getMaterialName(); - - HydraxLOG("Deleting water mesh..."); - mMesh->remove(); - HydraxLOG("Water mesh deleted."); - - HydraxLOG("Creating water mesh..."); - mMesh->setOptions(mModule->getMeshOptions()); - mMesh->setMaterialName(MaterialNameTmp); - mMesh->create(); - setPosition(mPosition); - HydraxLOG("Water mesh created."); - - HydraxLOG("Module set."); - } - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS) && !isComponent(HYDRAX_COMPONENT_SUN)) + { + HydraxLOG("God rays component needs sun component... god rays component desactivated."); - bool Hydrax::isComponent(const HydraxComponent &Component) - { - if (mComponents & Component) + HydraxComponent f = HYDRAX_COMPONENTS_NONE, d = HYDRAX_COMPONENTS_NONE, c = HYDRAX_COMPONENTS_NONE, + sm = HYDRAX_COMPONENTS_NONE, u = HYDRAX_COMPONENTS_NONE, ur = HYDRAX_COMPONENTS_NONE; + + if (isComponent(HYDRAX_COMPONENT_FOAM)) { f = HYDRAX_COMPONENT_FOAM; } + if (isComponent(HYDRAX_COMPONENT_DEPTH)) { d = HYDRAX_COMPONENT_DEPTH; } + if (isComponent(HYDRAX_COMPONENT_SMOOTH)) { sm = HYDRAX_COMPONENT_SMOOTH; } + if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) { c = HYDRAX_COMPONENT_CAUSTICS; } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) { u = HYDRAX_COMPONENT_UNDERWATER; } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) { ur = HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS; } + + mComponents = static_cast(f | d | sm | c | u | ur); + } + } + + int NumberOfDepthChannels = 0; + + if (isComponent(HYDRAX_COMPONENT_DEPTH)) + { + NumberOfDepthChannels++; + + if (isComponent(HYDRAX_COMPONENT_CAUSTICS)) { NumberOfDepthChannels++; } + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) { NumberOfDepthChannels++; } + } + + if (NumberOfDepthChannels > 0) + { + mRttManager->setNumberOfChannels(RttManager::RTT_DEPTH, + static_cast(NumberOfDepthChannels)); + } + + if (!mCreated || !mModule) { return; } + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) { mGodRaysManager->create(mComponents); } + else { - return true; + mGodRaysManager->remove(); } - if (Component == HYDRAX_COMPONENTS_NONE && mComponents == HYDRAX_COMPONENTS_NONE) + // Check for Rtt's + if (mCurrentFrameUnderwater && isComponent(HYDRAX_COMPONENT_UNDERWATER) && + !isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { mRttManager->remove(RttManager::RTT_REFLECTION); } + else { - return true; + mRttManager->initialize(RttManager::RTT_REFLECTION); } - if (Component == HYDRAX_COMPONENTS_ALL && mComponents == HYDRAX_COMPONENTS_ALL) + if (!isComponent(HYDRAX_COMPONENT_DEPTH)) + { + mRttManager->remove(RttManager::RTT_DEPTH); + mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION); + } + else + { + mRttManager->initialize(RttManager::RTT_DEPTH); + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS) && mCurrentFrameUnderwater) + { mRttManager->initialize(RttManager::RTT_DEPTH_REFLECTION); } + else + { + mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION); + } + } + if (!isComponent(HYDRAX_COMPONENT_UNDERWATER) && mCurrentFrameUnderwater) { - return true; + mRttManager->getTexture(RttManager::RTT_REFRACTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setSkiesEnabled(false); + + mRttManager->getTexture(RttManager::RTT_REFLECTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setSkiesEnabled(true); } + mMesh->setMaterialName("BaseWhiteNoLighting"); + mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, mModule->getNormalMode())); + + if (!isComponent(HYDRAX_COMPONENT_UNDERWATER)) { mCurrentFrameUnderwater = false; } + + mMesh->setMaterialName(mCurrentFrameUnderwater ? mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName() + : mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); + + if (mCurrentFrameUnderwater) { mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true); } + } + + void Hydrax::setModule(Module::Module *Module, const bool &DeleteOldModule) + { + if (mModule) + { + if (mModule->getNormalMode() != Module->getNormalMode()) + { + mMaterialManager->createMaterials(mComponents, MaterialManager::Options(mShaderMode, Module->getNormalMode())); + + mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); + } + + if (mModule->getNormalMode() == MaterialManager::NM_RTT && mModule->isCreated() && + mModule->getNoise()->areGPUNormalMapResourcesCreated()) + { mModule->getNoise()->removeGPUNormalMapResources(mGPUNormalMapManager); } + + if (DeleteOldModule) { delete mModule; } + else + { + mModule->remove(); + } + + // Due to modules can change -internally- scene nodes position, + // just reset them to the original position. + setPosition(mPosition); + } + + mModule = Module; + + if (mCreated) + { + if (!mModule->isCreated()) + { + mModule->create(); + + if (mModule->getNormalMode() == MaterialManager::NM_RTT) + { + if (!mModule->getNoise()->createGPUNormalMapResources(mGPUNormalMapManager)) + { HydraxLOG(mModule->getNoise()->getName() + " doesn't support GPU Normal map generation."); } + } + } + else + { + if (mModule->getNormalMode() == MaterialManager::NM_RTT) + { + if (!mModule->getNoise()->areGPUNormalMapResourcesCreated()) + { + if (!mModule->getNoise()->createGPUNormalMapResources(mGPUNormalMapManager)) + { HydraxLOG(mModule->getNoise()->getName() + " doesn't support GPU Normal map generation."); } + } + } + else + { + if (mModule->getNoise()->areGPUNormalMapResourcesCreated()) + { mModule->getNoise()->removeGPUNormalMapResources(mGPUNormalMapManager); } + } + } + + HydraxLOG("Updating water mesh..."); + Ogre::String MaterialNameTmp = mMesh->getMaterialName(); + + HydraxLOG("Deleting water mesh..."); + mMesh->remove(); + HydraxLOG("Water mesh deleted."); + + HydraxLOG("Creating water mesh..."); + mMesh->setOptions(mModule->getMeshOptions()); + mMesh->setMaterialName(MaterialNameTmp); + mMesh->create(); + setPosition(mPosition); + HydraxLOG("Water mesh created."); + + HydraxLOG("Module set."); + } + } + + bool Hydrax::isComponent(const HydraxComponent &Component) + { + if (mComponents & Component) { return true; } + + if (Component == HYDRAX_COMPONENTS_NONE && mComponents == HYDRAX_COMPONENTS_NONE) { return true; } + + if (Component == HYDRAX_COMPONENTS_ALL && mComponents == HYDRAX_COMPONENTS_ALL) { return true; } + return false; } - void Hydrax::_checkUnderwater(const Ogre::Real& timeSinceLastFrame) - { - if (!isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mCurrentFrameUnderwater = false; - - return; - } - - // If the camera is under the current water x/z position - if (getHeigth(mCamera->getDerivedPosition()) > mCamera->getDerivedPosition().y-mUnderwaterCameraSwitchDelta) - { - mCurrentFrameUnderwater = true; - - if (mMesh->getMaterialName() != mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName()) - { - mRttManager->getTexture(RttManager::RTT_REFRACTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setSkiesEnabled(true); - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - mRttManager->getTexture(RttManager::RTT_REFLECTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setSkiesEnabled(false); - - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - mRttManager->initialize(RttManager::RTT_DEPTH_REFLECTION); - } - } - else - { - mRttManager->remove(RttManager::RTT_REFLECTION); - } - - if (isComponent(HYDRAX_COMPONENT_DEPTH) && isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - mRttManager->initialize(RttManager::RTT_DEPTH_REFLECTION); - } - - mMaterialManager->reload(MaterialManager::MAT_UNDERWATER); - - mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true); - - mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName()); - } - - // Update god rays - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - mGodRaysManager->update(timeSinceLastFrame); - } - } - else - { - mCurrentFrameUnderwater = false; - - if (mMesh->getMaterialName() != mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()) - { - // We asume that RefractionRtt/ReflectionRtt are initialized - mRttManager->getTexture(RttManager::RTT_REFRACTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setSkiesEnabled(false); - - if (!isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - mRttManager->initialize(RttManager::RTT_REFLECTION); - mMaterialManager->reload(MaterialManager::MAT_WATER); - } - - mRttManager->getTexture(RttManager::RTT_REFLECTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setSkiesEnabled(true); - - if (isComponent(HYDRAX_COMPONENT_DEPTH) && isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION); - } - - mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false); - - mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); - } - } - - } + void Hydrax::_checkUnderwater(const Ogre::Real &timeSinceLastFrame) + { + if (!isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mCurrentFrameUnderwater = false; + + return; + } + + // If the camera is under the current water x/z position + if (getHeigth(mCamera->getDerivedPosition()) > mCamera->getDerivedPosition().y - mUnderwaterCameraSwitchDelta) + { + mCurrentFrameUnderwater = true; + + if (mMesh->getMaterialName() != mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName()) + { + mRttManager->getTexture(RttManager::RTT_REFRACTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setSkiesEnabled(true); + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { + mRttManager->getTexture(RttManager::RTT_REFLECTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setSkiesEnabled(false); + + if (isComponent(HYDRAX_COMPONENT_DEPTH)) { mRttManager->initialize(RttManager::RTT_DEPTH_REFLECTION); } + } + else + { + mRttManager->remove(RttManager::RTT_REFLECTION); + } + + if (isComponent(HYDRAX_COMPONENT_DEPTH) && isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { mRttManager->initialize(RttManager::RTT_DEPTH_REFLECTION); } + + mMaterialManager->reload(MaterialManager::MAT_UNDERWATER); + + mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true); + + mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName()); + } + + // Update god rays + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) { mGodRaysManager->update(timeSinceLastFrame); } + } + else + { + mCurrentFrameUnderwater = false; + + if (mMesh->getMaterialName() != mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()) + { + // We asume that RefractionRtt/ReflectionRtt are initialized + mRttManager->getTexture(RttManager::RTT_REFRACTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setSkiesEnabled(false); + + if (!isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { + mRttManager->initialize(RttManager::RTT_REFLECTION); + mMaterialManager->reload(MaterialManager::MAT_WATER); + } + + mRttManager->getTexture(RttManager::RTT_REFLECTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setSkiesEnabled(true); + + if (isComponent(HYDRAX_COMPONENT_DEPTH) && isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION); } + + mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false); + + mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName()); + } + } + } void Hydrax::setPosition(const Ogre::Vector3 &Position) { mPosition = Position; - if (!mCreated) - { - return; - } + if (!mCreated) { return; } - if (isComponent(HYDRAX_COMPONENT_DEPTH)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_VERTEX, MaterialManager::MAT_DEPTH, - "uPlaneYPos", Position.y); - } + if (isComponent(HYDRAX_COMPONENT_DEPTH)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_VERTEX, MaterialManager::MAT_DEPTH, "uPlaneYPos", + Position.y); + } - mMesh->getSceneNode()->setPosition(Position.x-mMesh->getSize().Width/2, Position.y, Position.z-mMesh->getSize().Height/2); - mRttManager->getPlanesSceneNode()->setPosition(Position); + mMesh->getSceneNode()->setPosition(Position.x - mMesh->getSize().Width / 2, Position.y, + Position.z - mMesh->getSize().Height / 2); + mRttManager->getPlanesSceneNode()->setPosition(Position); - // For world-space -> object-space conversion - setSunPosition(mSunPosition); + // For world-space -> object-space conversion + setSunPosition(mSunPosition); } - void Hydrax::rotate(const Ogre::Quaternion &q) - { - if (!mCreated) - { - HydraxLOG("Hydrax::rotate(...) must be called after Hydrax::create(), skipping..."); + void Hydrax::rotate(const Ogre::Quaternion &q) + { + if (!mCreated) + { + HydraxLOG("Hydrax::rotate(...) must be called after Hydrax::create(), skipping..."); - return; - } + return; + } - mMesh->getSceneNode()->rotate(q); - mRttManager->getPlanesSceneNode()->rotate(q); + mMesh->getSceneNode()->rotate(q); + mRttManager->getPlanesSceneNode()->rotate(q); - // For world-space -> object-space conversion - setSunPosition(mSunPosition); - } + // For world-space -> object-space conversion + setSunPosition(mSunPosition); + } void Hydrax::setPlanesError(const Ogre::Real &PlanesError) { @@ -762,397 +602,311 @@ namespace Hydrax void Hydrax::_setStrength(const Ogre::Real &Strength) { - if (isComponent(HYDRAX_COMPONENT_FOAM)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uFoamRange", Strength); - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uFoamRange", Strength); - } - } - - mDecalsManager->_setWaterStrength(Strength); + if (isComponent(HYDRAX_COMPONENT_FOAM)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uFoamRange", + Strength); + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uFoamRange", Strength); + } + } + + mDecalsManager->_setWaterStrength(Strength); } void Hydrax::setFullReflectionDistance(const Ogre::Real &FullReflectionDistance) { mFullReflectionDistance = FullReflectionDistance; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uFullReflectionDistance", FullReflectionDistance); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, + "uFullReflectionDistance", FullReflectionDistance); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uFullReflectionDistance", FullReflectionDistance); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uFullReflectionDistance", FullReflectionDistance); + } } void Hydrax::setGlobalTransparency(const Ogre::Real &GlobalTransparency) { mGlobalTransparency = GlobalTransparency; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uGlobalTransparency", GlobalTransparency); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, + "uGlobalTransparency", GlobalTransparency); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uGlobalTransparency", GlobalTransparency); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uGlobalTransparency", GlobalTransparency); + } } - void Hydrax::setWaterColor(const Ogre::Vector3 &WaterColor) + void Hydrax::setWaterColor(const Ogre::Vector3 &WaterColor) { mWaterColor = WaterColor; - if (!mCreated) - { - return; - } - - Ogre::ColourValue WC = Ogre::ColourValue(WaterColor.x, WaterColor.y, WaterColor.z); + if (!mCreated) { return; } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS) || !_isCurrentFrameUnderwater()) - { - mRttManager->getTexture(RttManager::RTT_REFLECTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setBackgroundColour(WC); - } - mRttManager->getTexture(RttManager::RTT_REFRACTION)-> - getBuffer()->getRenderTarget()->getViewport(0)-> - setBackgroundColour(WC); + Ogre::ColourValue WC = Ogre::ColourValue(WaterColor.x, WaterColor.y, WaterColor.z); - if (!isComponent(HYDRAX_COMPONENT_DEPTH)) + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS) || !_isCurrentFrameUnderwater()) { - return; + mRttManager->getTexture(RttManager::RTT_REFLECTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setBackgroundColour(WC); } + mRttManager->getTexture(RttManager::RTT_REFRACTION) + ->getBuffer() + ->getRenderTarget() + ->getViewport(0) + ->setBackgroundColour(WC); - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uWaterColor", WaterColor); + if (!isComponent(HYDRAX_COMPONENT_DEPTH)) { return; } - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uWaterColor", WaterColor); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uWaterColor", + WaterColor); - //mMaterialManager->getCompositor(MaterialManager::COMP_UNDERWATER)-> - // getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(WC); + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uWaterColor", WaterColor); + + // mMaterialManager->getCompositor(MaterialManager::COMP_UNDERWATER)-> + // getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(WC); /* Active creation/destruction - if (getHeigth(mCamera->getDerivedPosition()) > mCamera->getDerivedPosition().y-1.25f) - { - if (mMaterialManager->isCompositorEnable(MaterialManager::COMP_UNDERWATER)) - { - mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false); - mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true); - } - } - */ - } + if (getHeigth(mCamera->getDerivedPosition()) > mCamera->getDerivedPosition().y-1.25f) + { + if (mMaterialManager->isCompositorEnable(MaterialManager::COMP_UNDERWATER)) + { + mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false); + mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true); + } + } + */ + } } - void Hydrax::setNormalDistortion(const Ogre::Real &NormalDistortion) { mNormalDistortion = NormalDistortion; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uNormalDistortion", NormalDistortion); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uNormalDistortion", + NormalDistortion); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uNormalDistortion", NormalDistortion); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uNormalDistortion", NormalDistortion); + } } void Hydrax::setSunPosition(const Ogre::Vector3 &SunPosition) { - if (!isComponent(HYDRAX_COMPONENT_SUN)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_SUN)) { return; } mSunPosition = SunPosition; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uSunPosition", mMesh->getObjectSpacePosition(SunPosition)); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uSunPosition", + mMesh->getObjectSpacePosition(SunPosition)); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uSunPosition", mMesh->getObjectSpacePosition(SunPosition)); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uSunPosition", mMesh->getObjectSpacePosition(SunPosition)); + } } void Hydrax::setSunStrength(const Ogre::Real &SunStrength) { - if (!isComponent(HYDRAX_COMPONENT_SUN)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_SUN)) { return; } mSunStrength = SunStrength; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uSunStrength", SunStrength); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uSunStrength", + SunStrength); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uSunStrength", SunStrength); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uSunStrength", SunStrength); + } } void Hydrax::setSunArea(const Ogre::Real &SunArea) { - if (!isComponent(HYDRAX_COMPONENT_SUN)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_SUN)) { return; } mSunArea = SunArea; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uSunArea", SunArea); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uSunArea", SunArea); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uSunArea", SunArea); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, "uSunArea", + SunArea); + } } - void Hydrax::setSunColor(const Ogre::Vector3 &SunColor) + void Hydrax::setSunColor(const Ogre::Vector3 &SunColor) { - if (!isComponent(HYDRAX_COMPONENT_SUN)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_SUN)) { return; } mSunColor = SunColor; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uSunColor", SunColor); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uSunColor", + SunColor); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uSunColor", SunColor); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, "uSunColor", + SunColor); + } } void Hydrax::setFoamMaxDistance(const Ogre::Real &FoamMaxDistance) { - if (!isComponent(HYDRAX_COMPONENT_FOAM)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_FOAM)) { return; } mFoamMaxDistance = FoamMaxDistance; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uFoamMaxDistance", FoamMaxDistance); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uFoamMaxDistance", + FoamMaxDistance); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uFoamMaxDistance", FoamMaxDistance); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uFoamMaxDistance", FoamMaxDistance); + } } void Hydrax::setFoamScale(const Ogre::Real &FoamScale) { - if (!isComponent(HYDRAX_COMPONENT_FOAM)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_FOAM)) { return; } mFoamScale = FoamScale; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uFoamScale", FoamScale); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uFoamScale", + FoamScale); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uFoamScale", FoamScale); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uFoamScale", FoamScale); + } } void Hydrax::setFoamStart(const Ogre::Real &FoamStart) { - if (!isComponent(HYDRAX_COMPONENT_FOAM)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_FOAM)) { return; } mFoamStart = FoamStart; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uFoamStart", FoamStart); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uFoamStart", + FoamStart); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uFoamStart", FoamStart); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uFoamStart", FoamStart); + } } void Hydrax::setFoamTransparency(const Ogre::Real &FoamTransparency) { - if (!isComponent(HYDRAX_COMPONENT_FOAM)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_FOAM)) { return; } mFoamTransparency = FoamTransparency; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uFoamTransparency", FoamTransparency); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uFoamTransparency", + FoamTransparency); - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uFoamTransparency", FoamTransparency); - } + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uFoamTransparency", FoamTransparency); + } } void Hydrax::setDepthLimit(const Ogre::Real &DepthLimit) { - if (!isComponent(HYDRAX_COMPONENT_DEPTH)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_DEPTH)) { return; } - mDepthLimit = DepthLimit; + mDepthLimit = DepthLimit; - if (mDepthLimit <= 0) - { - mDepthLimit = 1; - } + if (mDepthLimit <= 0) { mDepthLimit = 1; } - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, - "uDepthLimit", 1/mDepthLimit); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, "uDepthLimit", + 1 / mDepthLimit); } - void Hydrax::setDistLimit(const Ogre::Real &DistLimit) - { - if (!isComponent(HYDRAX_COMPONENT_DEPTH)) - { - return; - } + void Hydrax::setDistLimit(const Ogre::Real &DistLimit) + { + if (!isComponent(HYDRAX_COMPONENT_DEPTH)) { return; } - mDistLimit = DistLimit; + mDistLimit = DistLimit; - if (mDistLimit <= 0) - { - mDistLimit = 1; - } + if (mDistLimit <= 0) { mDistLimit = 1; } - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, - "uDistLimit", 1/mDistLimit); - } + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, "uDistLimit", + 1 / mDistLimit); + } void Hydrax::setSmoothPower(const Ogre::Real &SmoothPower) { - if (!isComponent(HYDRAX_COMPONENT_SMOOTH)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_SMOOTH)) { return; } mSmoothPower = SmoothPower; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uSmoothPower", SmoothPower); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uSmoothPower", + SmoothPower); } void Hydrax::setCausticsScale(const Ogre::Real &CausticsScale) { - if (!isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_CAUSTICS)) { return; } mCausticsScale = CausticsScale; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, - "uCausticsScale", CausticsScale); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, "uCausticsScale", + CausticsScale); } void Hydrax::setCausticsPower(const Ogre::Real &CausticsPower) { - if (!isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_CAUSTICS)) { return; } mCausticsPower = CausticsPower; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, - "uCausticsPower", CausticsPower); - - if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) - { - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, - "uCausticsPower", CausticsPower); - } - - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER_COMPOSITOR, - "uCausticsPower", CausticsPower); - } + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_WATER, "uCausticsPower", + CausticsPower); + + if (isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + if (isComponent(HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS)) + { + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER, + "uCausticsPower", CausticsPower); + } + + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER_COMPOSITOR, + "uCausticsPower", CausticsPower); + } } void Hydrax::setCausticsEnd(const Ogre::Real &CausticsEnd) { - if (!isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - return; - } + if (!isComponent(HYDRAX_COMPONENT_CAUSTICS)) { return; } mCausticsEnd = CausticsEnd; - mMaterialManager->setGpuProgramParameter( - MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, - "uCausticsEnd", CausticsEnd); + mMaterialManager->setGpuProgramParameter(MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_DEPTH, "uCausticsEnd", + CausticsEnd); } -} +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Hydrax.h b/source/main/gfx/hydrax/Hydrax.h index d26c5087e0..b802aa4d66 100644 --- a/source/main/gfx/hydrax/Hydrax.h +++ b/source/main/gfx/hydrax/Hydrax.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,52 +25,51 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Hydrax_H_ #define _Hydrax_Hydrax_H_ -#include "Prerequisites.h" -#include "RoRPrerequisites.h" - +#include "CfgFileManager.h" +#include "DecalsManager.h" #include "Enums.h" +#include "GPUNormalMapManager.h" +#include "GodRaysManager.h" #include "Help.h" -#include "Mesh.h" #include "Image.h" #include "MaterialManager.h" +#include "Mesh.h" +#include "Module.h" +#include "Prerequisites.h" +#include "RoRPrerequisites.h" #include "RttManager.h" #include "TextureManager.h" -#include "GodRaysManager.h" -#include "DecalsManager.h" -#include "GPUNormalMapManager.h" -#include "CfgFileManager.h" -#include "Module.h" namespace Hydrax { /** Main Hydrax class. - Hydrax is a plugin for the Ogre3D engine whose aim is rendering realistic water scenes. - Do not use two instances of the Hydrax class. + Hydrax is a plugin for the Ogre3D engine whose aim is rendering realistic water scenes. + Do not use two instances of the Hydrax class. */ class Hydrax { - public: + public: /** Constructor @param sm Ogre SceneManager pointer @param c Ogre Camera pointer - @param v Ogre Main window viewport pointer + @param v Ogre Main window viewport pointer */ - Hydrax(Ogre::SceneManager *sm, Ogre::Camera *c, Ogre::Viewport *v); + Hydrax(Ogre::SceneManager *sm, Ogre::Camera *c, Ogre::Viewport *v); /** Destructor */ ~Hydrax(); /** Create all resources according with current Hydrax components and - add Hydrax to the scene. + add Hydrax to the scene. @remarks Call when all params are set */ void create(); - /** Remove hydrax, you can call this method to remove Hydrax from the scene - or release (secondary) Hydrax memory, call create() to return Hydrax to the scene. - */ - void remove(); + /** Remove hydrax, you can call this method to remove Hydrax from the scene + or release (secondary) Hydrax memory, call create() to return Hydrax to the scene. + */ + void remove(); /** Call every frame @todo Add listener interface @@ -88,55 +87,55 @@ namespace Hydrax */ void setComponents(const HydraxComponent &Components); - /** Set Hydrax module - @param Module Hydrax module - @param DeleteOldModule Delete, if exists, the old module - @remark Module will be set before call create() - */ - void setModule(Module::Module* Module, const bool& DeleteOldModule = true); + /** Set Hydrax module + @param Module Hydrax module + @param DeleteOldModule Delete, if exists, the old module + @remark Module will be set before call create() + */ + void setModule(Module::Module *Module, const bool &DeleteOldModule = true); /** Set polygon mode (Solid, Wireframe, Points) @param PM Polygon mode */ - void setPolygonMode(const Ogre::PolygonMode& PM); + void setPolygonMode(const Ogre::PolygonMode &PM); - /** Set shader mode - @param ShaderMode Shader mode - */ - void setShaderMode(const MaterialManager::ShaderMode &ShaderMode); + /** Set shader mode + @param ShaderMode Shader mode + */ + void setShaderMode(const MaterialManager::ShaderMode &ShaderMode); /** Set water position @param Position Water position */ void setPosition(const Ogre::Vector3 &Position); - /** Rotate water and planes - @param q const Ogre::Quaternion& - */ - void rotate(const Ogre::Quaternion &q); - - /** Save hydrax config to file - @param File File name - @param Path File path - @return false if an error has been ocurred(Check the log file in this case). - @remarks If module isn't set, module/noise options won't be saved. - */ - inline const bool saveCfg(const Ogre::String &File, const Ogre::String& Path = "") const - { - return mCfgFileManager->save(File, Path); - } - - /** Load config from file - @param File File name - @return false if an error has been ocurred(Check the log file in this case). - @remarks The file must be registred in Hydrax resource group. - If module isn't set, or module isn't the same from - config file, module options won't be loaded. - */ - inline const bool loadCfg(const Ogre::String &File) const - { - return mCfgFileManager->load(File); - } + /** Rotate water and planes + @param q const Ogre::Quaternion& + */ + void rotate(const Ogre::Quaternion &q); + + /** Save hydrax config to file + @param File File name + @param Path File path + @return false if an error has been ocurred(Check the log file in this case). + @remarks If module isn't set, module/noise options won't be saved. + */ + inline const bool saveCfg(const Ogre::String &File, const Ogre::String &Path = "") const + { + return mCfgFileManager->save(File, Path); + } + + /** Load config from file + @param File File name + @return false if an error has been ocurred(Check the log file in this case). + @remarks The file must be registred in Hydrax resource group. + If module isn't set, or module isn't the same from + config file, module options won't be loaded. + */ + inline const bool loadCfg(const Ogre::String &File) const + { + return mCfgFileManager->load(File); + } /** Set clip planes error @param PlanesError Clip planes error @@ -158,7 +157,7 @@ namespace Hydrax */ void setGlobalTransparency(const Ogre::Real &GlobalTransparency); - /** Set water color + /** Set water color @param DepthColor Water color */ void setWaterColor(const Ogre::Vector3 &WaterColor); @@ -240,154 +239,154 @@ namespace Hydrax */ void setCausticsEnd(const Ogre::Real &CausticsEnd); - /** Set god rays exposure - @param GodRaysExposure God rays exposure - */ - void setGodRaysExposure(const Ogre::Vector3 &GodRaysExposure) - { - mGodRaysExposure = GodRaysExposure; - } - - /** Set god rays intensity - @param GodRaysIntensity God rays intensity - */ - void setGodRaysIntensity(const Ogre::Real &GodRaysIntensity) - { - mGodRaysIntensity = GodRaysIntensity; - } - - /** Set the y-displacement under the water needed to change between underwater and overwater mode - @param UnderwaterCameraSwitchDelta Underwater camera switch delta factor - @remarks Useful to get a nice underwater-overwater transition, it depends of the world scale - */ - inline void setUnderwaterCameraSwitchDelta(const Ogre::Real& UnderwaterCameraSwitchDelta) - { - mUnderwaterCameraSwitchDelta = UnderwaterCameraSwitchDelta; - } + /** Set god rays exposure + @param GodRaysExposure God rays exposure + */ + void setGodRaysExposure(const Ogre::Vector3 &GodRaysExposure) + { + mGodRaysExposure = GodRaysExposure; + } + + /** Set god rays intensity + @param GodRaysIntensity God rays intensity + */ + void setGodRaysIntensity(const Ogre::Real &GodRaysIntensity) + { + mGodRaysIntensity = GodRaysIntensity; + } + + /** Set the y-displacement under the water needed to change between underwater and overwater mode + @param UnderwaterCameraSwitchDelta Underwater camera switch delta factor + @remarks Useful to get a nice underwater-overwater transition, it depends of the world scale + */ + inline void setUnderwaterCameraSwitchDelta(const Ogre::Real &UnderwaterCameraSwitchDelta) + { + mUnderwaterCameraSwitchDelta = UnderwaterCameraSwitchDelta; + } /** Has create() already called? @return true is yes, false if not */ - inline const bool& isCreated() const + inline const bool &isCreated() const { return mCreated; } - /** Show/Hide hydrax water - @param Visible true to show, false to hide - @remarks Resources aren't going to be realeased(Use remove() for this), - only RTT's are going to be stopped. - */ - void setVisible(const bool& Visible); - - /** Is hydrax water visible? - @return true if yes, false if not - */ - inline const bool& isVisible() const - { - return mVisible; - } - - /** Get rendering camera - @return Ogre::Camera pointer - */ - inline Ogre::Camera* getCamera() - { - return mCamera; - } - - /** Get main window viewport - @return Ogre::Viewport pointer - */ - inline Ogre::Viewport* getViewport() - { - return mViewport; - } - - /** Get scene manager - @return Ogre::SceneManager pointer - */ - inline Ogre::SceneManager* getSceneManager() - { - return mSceneManager; - } - - /** Get Hydrax::Mesh - @return Hydrax::Mesh pointer - */ - inline Mesh* getMesh() - { - return mMesh; - } - - /** Get Hydrax::MaterialManager - @return Hydrax::MaterialManager pointer - */ - inline MaterialManager* getMaterialManager() - { - return mMaterialManager; - } - - /** Get Hydrax::RttManager - @return Hydrax::RttManager pointer - */ - inline RttManager* getRttManager() - { - return mRttManager; - } - - /** Get Hydrax::TextureManager - @return Hydrax::TextureManager pointer - */ - inline TextureManager* getTextureManager() - { - return mTextureManager; - } - - /** Get Hydrax::GodRaysManager - @return Hydrax::GodRaysManager pointer - */ - inline GodRaysManager* getGodRaysManager() - { - return mGodRaysManager; - } - - /** Get Hydrax::DecalsManager - @return Hydrax::DecalsManager pointer - */ - inline DecalsManager* getDecalsManager() - { - return mDecalsManager; - } - - /** Get Hydrax::GPUNormalMapManager - @return Hydrax::GPUNormalMapManager pointer - */ - inline GPUNormalMapManager* getGPUNormalMapManager() - { - return mGPUNormalMapManager; - } - - /** Get Hydrax::CfgFileManager - @return Hydrax::CfgFileManager pointer - */ - inline CfgFileManager* getCfgFileManager() - { - return mCfgFileManager; - } - - /** Get our Hydrax::Module::Module - @return Hydrax::Module::Module pointer or NULL if Module isn't set. - */ - inline Module::Module* getModule() - { - return mModule; - } + /** Show/Hide hydrax water + @param Visible true to show, false to hide + @remarks Resources aren't going to be realeased(Use remove() for this), + only RTT's are going to be stopped. + */ + void setVisible(const bool &Visible); + + /** Is hydrax water visible? + @return true if yes, false if not + */ + inline const bool &isVisible() const + { + return mVisible; + } + + /** Get rendering camera + @return Ogre::Camera pointer + */ + inline Ogre::Camera *getCamera() + { + return mCamera; + } + + /** Get main window viewport + @return Ogre::Viewport pointer + */ + inline Ogre::Viewport *getViewport() + { + return mViewport; + } + + /** Get scene manager + @return Ogre::SceneManager pointer + */ + inline Ogre::SceneManager *getSceneManager() + { + return mSceneManager; + } + + /** Get Hydrax::Mesh + @return Hydrax::Mesh pointer + */ + inline Mesh *getMesh() + { + return mMesh; + } + + /** Get Hydrax::MaterialManager + @return Hydrax::MaterialManager pointer + */ + inline MaterialManager *getMaterialManager() + { + return mMaterialManager; + } + + /** Get Hydrax::RttManager + @return Hydrax::RttManager pointer + */ + inline RttManager *getRttManager() + { + return mRttManager; + } + + /** Get Hydrax::TextureManager + @return Hydrax::TextureManager pointer + */ + inline TextureManager *getTextureManager() + { + return mTextureManager; + } + + /** Get Hydrax::GodRaysManager + @return Hydrax::GodRaysManager pointer + */ + inline GodRaysManager *getGodRaysManager() + { + return mGodRaysManager; + } + + /** Get Hydrax::DecalsManager + @return Hydrax::DecalsManager pointer + */ + inline DecalsManager *getDecalsManager() + { + return mDecalsManager; + } + + /** Get Hydrax::GPUNormalMapManager + @return Hydrax::GPUNormalMapManager pointer + */ + inline GPUNormalMapManager *getGPUNormalMapManager() + { + return mGPUNormalMapManager; + } + + /** Get Hydrax::CfgFileManager + @return Hydrax::CfgFileManager pointer + */ + inline CfgFileManager *getCfgFileManager() + { + return mCfgFileManager; + } + + /** Get our Hydrax::Module::Module + @return Hydrax::Module::Module pointer or NULL if Module isn't set. + */ + inline Module::Module *getModule() + { + return mModule; + } /** Get hydrax components selected @return Hydrax components */ - inline const HydraxComponent& getComponents() const + inline const HydraxComponent &getComponents() const { return mComponents; } @@ -395,62 +394,59 @@ namespace Hydrax /** Get current polygon mode @return Current polygon mode */ - inline const Ogre::PolygonMode& getPolygonMode() const + inline const Ogre::PolygonMode &getPolygonMode() const { return mPolygonMode; } - /** Get current shader mode - @return Current shader mode - */ - inline const MaterialManager::ShaderMode& getShaderMode() const - { - return mShaderMode; - } + /** Get current shader mode + @return Current shader mode + */ + inline const MaterialManager::ShaderMode &getShaderMode() const + { + return mShaderMode; + } /** Get water position @return Water position */ - inline const Ogre::Vector3& getPosition() const + inline const Ogre::Vector3 &getPosition() const { return mPosition; } - /** Get current clip planes error - @return Current clip planes error - */ - inline const Ogre::Real& getPlanesError() const - { - return mPlanesError; - } - - /** Get the current heigth at a especified world-space point - @param Position X/Z World position - @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 - */ - inline float getHeigth(const Ogre::Vector2 &Position) - { - if (mModule) - { - return mModule->getHeigth(Position); - } - - return -1; - } - - /** Get the current heigth at a especified world-space point - @param Position X/(Y)/Z World position - @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 - */ - inline float getHeigth(const Ogre::Vector3 &Position) - { - return getHeigth(Ogre::Vector2(Position.x, Position.z)); - } + /** Get current clip planes error + @return Current clip planes error + */ + inline const Ogre::Real &getPlanesError() const + { + return mPlanesError; + } + + /** Get the current heigth at a especified world-space point + @param Position X/Z World position + @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 + */ + inline float getHeigth(const Ogre::Vector2 &Position) + { + if (mModule) { return mModule->getHeigth(Position); } + + return -1; + } + + /** Get the current heigth at a especified world-space point + @param Position X/(Y)/Z World position + @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 + */ + inline float getHeigth(const Ogre::Vector3 &Position) + { + return getHeigth(Ogre::Vector2(Position.x, Position.z)); + } /** Get full reflection distance @return Hydrax water full reflection distance */ - inline const Ogre::Real& getFullReflectionDistance() const + inline const Ogre::Real &getFullReflectionDistance() const { return mFullReflectionDistance; } @@ -458,7 +454,7 @@ namespace Hydrax /** Get global transparency @return Hydrax water global transparency */ - inline const Ogre::Real& getGlobalTransparency() const + inline const Ogre::Real &getGlobalTransparency() const { return mGlobalTransparency; } @@ -466,15 +462,15 @@ namespace Hydrax /** Get sun position @return Sun position */ - inline const Ogre::Vector3& getSunPosition() const + inline const Ogre::Vector3 &getSunPosition() const { return mSunPosition; } - /** Get water color + /** Get water color @return Water color */ - inline const Ogre::Vector3& getWaterColor() const + inline const Ogre::Vector3 &getWaterColor() const { return mWaterColor; } @@ -482,7 +478,7 @@ namespace Hydrax /** Get normal distortion @return Hydrax normal distortion */ - inline const Ogre::Real& getNormalDistortion() const + inline const Ogre::Real &getNormalDistortion() const { return mNormalDistortion; } @@ -490,7 +486,7 @@ namespace Hydrax /** Get water strength @return Hydrax water strength */ - inline const Ogre::Real& getSunStrength() const + inline const Ogre::Real &getSunStrength() const { return mSunStrength; } @@ -498,7 +494,7 @@ namespace Hydrax /** Get sun area @return Sun area */ - inline const Ogre::Real& getSunArea() const + inline const Ogre::Real &getSunArea() const { return mSunArea; } @@ -506,7 +502,7 @@ namespace Hydrax /** Get sun color @return Sun color */ - inline const Ogre::Vector3& getSunColor() const + inline const Ogre::Vector3 &getSunColor() const { return mSunColor; } @@ -514,7 +510,7 @@ namespace Hydrax /** Get foam max distance @return Foam max distance */ - inline const Ogre::Real& getFoamMaxDistance() const + inline const Ogre::Real &getFoamMaxDistance() const { return mFoamMaxDistance; } @@ -522,7 +518,7 @@ namespace Hydrax /** Get foam scale @return Foam scale */ - inline const Ogre::Real& getFoamScale() const + inline const Ogre::Real &getFoamScale() const { return mFoamScale; } @@ -530,7 +526,7 @@ namespace Hydrax /** Get foam start @return Foam start */ - inline const Ogre::Real& getFoamStart() const + inline const Ogre::Real &getFoamStart() const { return mFoamStart; } @@ -538,7 +534,7 @@ namespace Hydrax /** Get foam transparency @return Foam scale */ - inline const Ogre::Real& getFoamTransparency() const + inline const Ogre::Real &getFoamTransparency() const { return mFoamTransparency; } @@ -546,7 +542,7 @@ namespace Hydrax /** Get depth limit @return Depth limit */ - inline const Ogre::Real& getDepthLimit() const + inline const Ogre::Real &getDepthLimit() const { return mDepthLimit; } @@ -554,7 +550,7 @@ namespace Hydrax /** Get distance limit (viewable underwater) @return Distance limit */ - inline const Ogre::Real& getDistLimit() const + inline const Ogre::Real &getDistLimit() const { return mDistLimit; } @@ -562,15 +558,15 @@ namespace Hydrax /** Get smooth power @return Smooth power */ - inline const Ogre::Real& getSmoothPower() const + inline const Ogre::Real &getSmoothPower() const { return mSmoothPower; } - /** Get caustics scale + /** Get caustics scale @return Caustics scale */ - inline const Ogre::Real& getCausticsScale() const + inline const Ogre::Real &getCausticsScale() const { return mCausticsScale; } @@ -578,7 +574,7 @@ namespace Hydrax /** Get caustics power @return Caustics power */ - inline const Ogre::Real& getCausticsPower() const + inline const Ogre::Real &getCausticsPower() const { return mCausticsPower; } @@ -586,90 +582,89 @@ namespace Hydrax /** Get caustics end @return Caustics end */ - inline const Ogre::Real& getCausticsEnd() const + inline const Ogre::Real &getCausticsEnd() const { return mCausticsEnd; } - /** Get God rays exposure factors - @return God rays exposure factors - */ - inline const Ogre::Vector3& getGodRaysExposure() const - { - return mGodRaysExposure; - } - - /** Get God rays intensity - @return God rays intensity - */ - inline const Ogre::Real& getGodRaysIntensity() const - { - return mGodRaysIntensity; - } - - /** Get the y-displacement under the water needed to change between underwater and overwater mode - @return Underwater camera switch delta - @remarks Useful to get a nice underwater-overwater transition, it depends of the world scale - */ - inline const Ogre::Real& getUnderwaterCameraSwitchDelta() const - { - return mUnderwaterCameraSwitchDelta; - } - - /** Is current frame underwater? - @return true If yes, false if not - */ - inline const bool& _isCurrentFrameUnderwater() const - { - return mCurrentFrameUnderwater; - } - - private: + /** Get God rays exposure factors + @return God rays exposure factors + */ + inline const Ogre::Vector3 &getGodRaysExposure() const + { + return mGodRaysExposure; + } + /** Get God rays intensity + @return God rays intensity + */ + inline const Ogre::Real &getGodRaysIntensity() const + { + return mGodRaysIntensity; + } + + /** Get the y-displacement under the water needed to change between underwater and overwater mode + @return Underwater camera switch delta + @remarks Useful to get a nice underwater-overwater transition, it depends of the world scale + */ + inline const Ogre::Real &getUnderwaterCameraSwitchDelta() const + { + return mUnderwaterCameraSwitchDelta; + } + + /** Is current frame underwater? + @return true If yes, false if not + */ + inline const bool &_isCurrentFrameUnderwater() const + { + return mCurrentFrameUnderwater; + } + + private: /** Device listener - */ - class DeviceListener : public Ogre::RenderSystem::Listener - { - public: - /// Hydrax manager pointer - Hydrax* mHydrax; - - /** Event occurred - @param eventName Name of the event - @param parameters Ogre::NameValuePairList pointer - */ - void eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList *parameters); - }; + */ + class DeviceListener : public Ogre::RenderSystem::Listener + { + public: + /// Hydrax manager pointer + Hydrax *mHydrax; + + /** Event occurred + @param eventName Name of the event + @param parameters Ogre::NameValuePairList pointer + */ + void eventOccurred(const Ogre::String &eventName, const Ogre::NameValuePairList *parameters); + }; /** Update normal map textures */ void _updateNM(); - /** setVisible() helper funtion - */ - void _checkVisible(); + /** setVisible() helper funtion + */ + void _checkVisible(); - /** Check for underwater effects - @param timeSinceLastFrame Time since last frame - */ - void _checkUnderwater(const Ogre::Real& timeSinceLastFrame); + /** Check for underwater effects + @param timeSinceLastFrame Time since last frame + */ + void _checkUnderwater(const Ogre::Real &timeSinceLastFrame); /// Has create() already called? bool mCreated; - /// Is hydrax water visible? - bool mVisible; + /// Is hydrax water visible? + bool mVisible; /// Hydrax components HydraxComponent mComponents; - /// Current shader mode - MaterialManager::ShaderMode mShaderMode; + /// Current shader mode + MaterialManager::ShaderMode mShaderMode; - /// Device listener - DeviceListener mDeviceListener; + /// Device listener + DeviceListener mDeviceListener; - /// Polygon mode (Solid, Wireframe, Points) - Ogre::PolygonMode mPolygonMode; + /// Polygon mode (Solid, Wireframe, Points) + Ogre::PolygonMode mPolygonMode; /// Water position Ogre::Vector3 mPosition; /// Planes error, y axis clipplanes displacement @@ -679,7 +674,7 @@ namespace Hydrax Ogre::Real mFullReflectionDistance; /// Global transparency param Ogre::Real mGlobalTransparency; - /// Water color param + /// Water color param Ogre::Vector3 mWaterColor; /// Normal distortion param Ogre::Real mNormalDistortion; @@ -704,8 +699,8 @@ namespace Hydrax /// Depth limit param Ogre::Real mDepthLimit; - /// Distance limit param (viewable underwater) - Ogre::Real mDistLimit; + /// Distance limit param (viewable underwater) + Ogre::Real mDistLimit; /// Smooth power param Ogre::Real mSmoothPower; @@ -717,43 +712,43 @@ namespace Hydrax /// Caustics end Ogre::Real mCausticsEnd; - /// God rays exposure factors - Ogre::Vector3 mGodRaysExposure; - /// God rays intensity - Ogre::Real mGodRaysIntensity; + /// God rays exposure factors + Ogre::Vector3 mGodRaysExposure; + /// God rays intensity + Ogre::Real mGodRaysIntensity; - // Delta-displacement in Y-AXIS before changing to underwater mode - Ogre::Real mUnderwaterCameraSwitchDelta; + // Delta-displacement in Y-AXIS before changing to underwater mode + Ogre::Real mUnderwaterCameraSwitchDelta; - /// Is current frame underwater? - bool mCurrentFrameUnderwater; + /// Is current frame underwater? + bool mCurrentFrameUnderwater; /// Our Hydrax::Mesh pointer Mesh *mMesh; - /// Our Hydrax::MaterialManager - MaterialManager *mMaterialManager; - /// Our Hydrax::RttManager - RttManager *mRttManager; - /// Our Hydrax::TextureManager pointer - TextureManager *mTextureManager; - /// Our Hydrax::GodRaysManager pointer - GodRaysManager *mGodRaysManager; - /// Our Hydrax::DecalsManager pointer - DecalsManager *mDecalsManager; - /// Our Hydrax::GPUNormalMapManager pointer - GPUNormalMapManager *mGPUNormalMapManager; - /// Our Hydrax::CfgFileManager pointer - CfgFileManager *mCfgFileManager; - /// Our Hydrax::Module::Module pointer - Module::Module *mModule; + /// Our Hydrax::MaterialManager + MaterialManager *mMaterialManager; + /// Our Hydrax::RttManager + RttManager *mRttManager; + /// Our Hydrax::TextureManager pointer + TextureManager *mTextureManager; + /// Our Hydrax::GodRaysManager pointer + GodRaysManager *mGodRaysManager; + /// Our Hydrax::DecalsManager pointer + DecalsManager *mDecalsManager; + /// Our Hydrax::GPUNormalMapManager pointer + GPUNormalMapManager *mGPUNormalMapManager; + /// Our Hydrax::CfgFileManager pointer + CfgFileManager *mCfgFileManager; + /// Our Hydrax::Module::Module pointer + Module::Module *mModule; /// Pointer to Ogre::SceneManager Ogre::SceneManager *mSceneManager; /// Pointer to Ogre::Camera Ogre::Camera *mCamera; - /// Pointer to main window viewport - Ogre::Viewport *mViewport; + /// Pointer to main window viewport + Ogre::Viewport *mViewport; }; -} +} // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/Image.cpp b/source/main/gfx/hydrax/Image.cpp index aaea2fa9a0..f7b4e59793 100644 --- a/source/main/gfx/hydrax/Image.cpp +++ b/source/main/gfx/hydrax/Image.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -26,233 +26,199 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace Hydrax { - Image::Image(const Size &Size) - : mSize(Hydrax::Size(Size.Width+1,Size.Height+1)) - , mChannels(static_cast(TYPE_RGBA)) - , mData(0) - { - _Initialize(0); - } - - Image::Image(const Size &Size, const Type &Type) - : mSize(Hydrax::Size(Size.Width+1,Size.Height+1)) - , mChannels(static_cast(Type)) - , mData(0) - { - _Initialize(0); - } - - Image::Image(const Size &Size, const Type &Type, const float &v) - : mSize(Hydrax::Size(Size.Width+1,Size.Height+1)) - , mChannels(static_cast(Type)) - , mData(0) - { - _Initialize(v); - } - - Image::~Image() - { - delete mData; - } - - const float& Image::getValue(const int &x, const int &y, const int &c) const - { + Image::Image(const Size &Size) + : mSize(Hydrax::Size(Size.Width + 1, Size.Height + 1)), mChannels(static_cast(TYPE_RGBA)), mData(0) + { + _Initialize(0); + } + + Image::Image(const Size &Size, const Type &Type) + : mSize(Hydrax::Size(Size.Width + 1, Size.Height + 1)), mChannels(static_cast(Type)), mData(0) + { + _Initialize(0); + } + + Image::Image(const Size &Size, const Type &Type, const float &v) + : mSize(Hydrax::Size(Size.Width + 1, Size.Height + 1)), mChannels(static_cast(Type)), mData(0) + { + _Initialize(v); + } + + Image::~Image() + { + delete mData; + } + + const float &Image::getValue(const int &x, const int &y, const int &c) const + { #if HYDRAX_IMAGE_CHECK_PIXELS == 1 - if (c < 0 || c > mChannels || - x < 0 || x > mSize.Width || - y < 0 || y > mSize.Height) - { - HydraxLOG("Error in Image::getValue, x = " + Ogre::StringConverter::toString(x) - + " y = " + Ogre::StringConverter::toString(y) - + " Channel = " + Ogre::StringConverter::toString(c)); - - return 0; - } + if (c < 0 || c > mChannels || x < 0 || x > mSize.Width || y < 0 || y > mSize.Height) + { + HydraxLOG("Error in Image::getValue, x = " + Ogre::StringConverter::toString(x) + + " y = " + Ogre::StringConverter::toString(y) + " Channel = " + Ogre::StringConverter::toString(c)); + + return 0; + } #endif - return mData[(y*mSize.Width+x)*mChannels+c]; - } + return mData[(y * mSize.Width + x) * mChannels + c]; + } - float Image::getValueLI(const float &x, const float &y, const int &c) const - { + float Image::getValueLI(const float &x, const float &y, const int &c) const + { #if HYDRAX_IMAGE_CHECK_PIXELS == 1 - if (c < 0 || c > mChannels || - x < 0 || x > mSize.Width || - y < 0 || y > mSize.Height) - { - HydraxLOG("Error in Image::getValue, x = " + Ogre::StringConverter::toString(x) - + " y = " + Ogre::StringConverter::toString(y) - + " Channel = " + Ogre::StringConverter::toString(c)); - - return 0; - } + if (c < 0 || c > mChannels || x < 0 || x > mSize.Width || y < 0 || y > mSize.Height) + { + HydraxLOG("Error in Image::getValue, x = " + Ogre::StringConverter::toString(x) + + " y = " + Ogre::StringConverter::toString(y) + " Channel = " + Ogre::StringConverter::toString(c)); + + return 0; + } #endif - int xINT = static_cast(x), - yINT = static_cast(y); - - float xDIFF = x-xINT, - yDIFF = y-yINT, - _xDIFF = 1-xDIFF, - _yDIFF = 1-yDIFF; - - // A B - // - // - // C D - float A = mData[(yINT*mSize.Width+xINT)*mChannels+c], - B = mData[(yINT*mSize.Width+xINT+1)*mChannels+c], - C = mData[((yINT+1)*mSize.Width+xINT)*mChannels+c], - D = mData[((yINT+1)*mSize.Width+xINT+1)*mChannels+c]; - - return A*_xDIFF*_yDIFF + - B* xDIFF*_yDIFF + - C*_xDIFF* yDIFF + - D* xDIFF* yDIFF; - } + int xINT = static_cast(x), yINT = static_cast(y); + + float xDIFF = x - xINT, yDIFF = y - yINT, _xDIFF = 1 - xDIFF, _yDIFF = 1 - yDIFF; + + // A B + // + // + // C D + float A = mData[(yINT * mSize.Width + xINT) * mChannels + c], B = mData[(yINT * mSize.Width + xINT + 1) * mChannels + c], + C = mData[((yINT + 1) * mSize.Width + xINT) * mChannels + c], + D = mData[((yINT + 1) * mSize.Width + xINT + 1) * mChannels + c]; + + return A * _xDIFF * _yDIFF + B * xDIFF * _yDIFF + C * _xDIFF * yDIFF + D * xDIFF * yDIFF; + } Image::Pixel Image::getPixel(const int &x, const int &y) const - { + { #if HYDRAX_IMAGE_CHECK_PIXELS == 1 - if (x < 0 || x > mSize.Width || - y < 0 || y > mSize.Height) - { - HydraxLOG("Error in Image::getPixel, x = " + Ogre::StringConverter::toString(x) - + " y = " + Ogre::StringConverter::toString(y)); - - return Pixel(0); - } + if (x < 0 || x > mSize.Width || y < 0 || y > mSize.Height) + { + HydraxLOG("Error in Image::getPixel, x = " + Ogre::StringConverter::toString(x) + + " y = " + Ogre::StringConverter::toString(y)); + + return Pixel(0); + } #endif - float v[4]; - - for(int k = 0; k < 4; k++) - { - if (mChannels >= k) - { - v[k] = getValue(x, y, k); - } - else - { - v[k] = 0; - } - } - - return Pixel(v[0], v[1], v[2], v[3]); - } - - Image::Pixel Image::getPixelLI(const float &x, const float &y) const - { + float v[4]; + + for (int k = 0; k < 4; k++) + { + if (mChannels >= k) { v[k] = getValue(x, y, k); } + else + { + v[k] = 0; + } + } + + return Pixel(v[0], v[1], v[2], v[3]); + } + + Image::Pixel Image::getPixelLI(const float &x, const float &y) const + { #if HYDRAX_IMAGE_CHECK_PIXELS == 1 - if (x < 0 || x > mSize.Width || - y < 0 || y > mSize.Height) - { - HydraxLOG("Error in Image::getPixel, x = " + Ogre::StringConverter::toString(x) - + " y = " + Ogre::StringConverter::toString(y)); - - return Pixel(0); - } + if (x < 0 || x > mSize.Width || y < 0 || y > mSize.Height) + { + HydraxLOG("Error in Image::getPixel, x = " + Ogre::StringConverter::toString(x) + + " y = " + Ogre::StringConverter::toString(y)); + + return Pixel(0); + } #endif - float v[4]; - - for(int k = 0; k < 4; k++) - { - if (mChannels >= k) - { - v[k] = getValueLI(x, y, k); - } - else - { - v[k] = 0; - } - } - - return Pixel(v[0], v[1], v[2], v[3]); - } - - void Image::setValue(const int &x, const int &y, const int &c, const float &v) - { + float v[4]; + + for (int k = 0; k < 4; k++) + { + if (mChannels >= k) { v[k] = getValueLI(x, y, k); } + else + { + v[k] = 0; + } + } + + return Pixel(v[0], v[1], v[2], v[3]); + } + + void Image::setValue(const int &x, const int &y, const int &c, const float &v) + { #if HYDRAX_IMAGE_CHECK_PIXELS == 1 - if (c < 0 || c > mChannels || - x < 0 || x > mSize.Width || - y < 0 || y > mSize.Height) - { - HydraxLOG("Error in Image::setValue, x = " + Ogre::StringConverter::toString(x) - + " y = " + Ogre::StringConverter::toString(y) - + " Channel = " + Ogre::StringConverter::toString(c)); - - return; - } + if (c < 0 || c > mChannels || x < 0 || x > mSize.Width || y < 0 || y > mSize.Height) + { + HydraxLOG("Error in Image::setValue, x = " + Ogre::StringConverter::toString(x) + + " y = " + Ogre::StringConverter::toString(y) + " Channel = " + Ogre::StringConverter::toString(c)); + + return; + } #endif - mData[(y*mSize.Width+x)*mChannels+c] = v; - } + mData[(y * mSize.Width + x) * mChannels + c] = v; + } - void Image::setPixel(const int &x, const int &y, const Pixel &p) - { + void Image::setPixel(const int &x, const int &y, const Pixel &p) + { #if HYDRAX_IMAGE_CHECK_PIXELS == 1 - if (x < 0 || x > mSize.Width || - y < 0 || y > mSize.Height) - { - HydraxLOG("Error in Image::setPixel, x = " + Ogre::StringConverter::toString(x) - + " y = " + Ogre::StringConverter::toString(y)); - - return; - } + if (x < 0 || x > mSize.Width || y < 0 || y > mSize.Height) + { + HydraxLOG("Error in Image::setPixel, x = " + Ogre::StringConverter::toString(x) + + " y = " + Ogre::StringConverter::toString(y)); + + return; + } #endif - switch(mChannels) - { - case 1: - { - setValue(x, y, 0, p.red); - } - break; - - case 2: - { - setValue(x, y, 0, p.red); - setValue(x, y, 1, p.green); - } - break; - - case 3: - { - setValue(x, y, 0, p.red); - setValue(x, y, 1, p.green); - setValue(x, y, 2, p.blue); - } - break; - - case 4: - { - setValue(x, y, 0, p.red); - setValue(x, y, 1, p.green); - setValue(x, y, 2, p.blue); - setValue(x, y, 3, p.alpha); - } - break; - } - } - - void Image::_Initialize(const float &v) - { - mData = new float[(mSize.Width) * - (mSize.Height) * - mChannels]; - - int x,y,c; - - for (x = 0; x < mSize.Width; x++) - { - for (y = 0; y < mSize.Height; y++) - { - for(c = 0; c < mChannels; c++) - { - mData[(y*mSize.Width+x)*mChannels+c] = v; - } - } - } - } -} + switch (mChannels) + { + case 1: + { + setValue(x, y, 0, p.red); + } + break; + + case 2: + { + setValue(x, y, 0, p.red); + setValue(x, y, 1, p.green); + } + break; + + case 3: + { + setValue(x, y, 0, p.red); + setValue(x, y, 1, p.green); + setValue(x, y, 2, p.blue); + } + break; + + case 4: + { + setValue(x, y, 0, p.red); + setValue(x, y, 1, p.green); + setValue(x, y, 2, p.blue); + setValue(x, y, 3, p.alpha); + } + break; + } + } + + void Image::_Initialize(const float &v) + { + mData = new float[(mSize.Width) * (mSize.Height) * mChannels]; + + int x, y, c; + + for (x = 0; x < mSize.Width; x++) + { + for (y = 0; y < mSize.Height; y++) + { + for (c = 0; c < mChannels; c++) + { + mData[(y * mSize.Width + x) * mChannels + c] = v; + } + } + } + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Image.h b/source/main/gfx/hydrax/Image.h index 129dc50c32..65d089c0f8 100644 --- a/source/main/gfx/hydrax/Image.h +++ b/source/main/gfx/hydrax/Image.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,244 +25,219 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Image_H_ #define _Hydrax_Image_H_ -#include "Prerequisites.h" - #include "Help.h" +#include "Prerequisites.h" namespace Hydrax { - /** Class for store variable channels of an image - */ - class Image - { - public: - /** Image type enum - */ - enum Type - { - TYPE_ONE_CHANNEL = 1, - TYPE_TWO_CHANNELS = 2, - TYPE_RGB = 3, - /// Default - TYPE_RGBA = 4 - }; - - /** Channel enum - */ - enum Channel - { - CHANNEL_R = 0, // Red - CHANNEL_G = 1, // Green - CHANNEL_B = 2, // Blue - CHANNEL_A = 3 // Alpha - }; - - /** Pixel structure - */ - struct Pixel - { - /** Default constructor - */ - Pixel() - : red(0) - , green(0) - , blue(0) - , alpha(0) - { - } - - /** Constructor - @param v RGBA Value - */ - Pixel(const float &v) - : red(v) - , green(v) - , blue(v) - , alpha(v) - { - } - - /** Constructor - @param r Red value - @param g Green value - @param b Blue value - @remarks Alpha component = 0 - */ - Pixel(const float &r, - const float &g, - const float &b) - : red(r) - , green(g) - , blue(b) - , alpha(0) - { - } - - /** Constructor - @param r Red value - @param g Green value - @param b Blue value - @param a Alpha value - */ - Pixel(const float &r, - const float &g, - const float &b, - const float &a) - : red(r) - , green(g) - , blue(b) - , alpha(a) - { - } - - /// Pixel values (RGBA) - float red, - green, - blue, - alpha; - }; - - /** Constructor - @param Size Image size - */ - Image(const Size &Size); - - /** Constructor - @param Size Image size - @param Type Image type - */ - Image(const Size &Size, const Type &Type); - - /** Constructor - @param Size Image size - @param Type Image type - @param v Initial channel values - */ - Image(const Size &Size, const Type &Type, const float &v); - - /** Destructor - */ - ~Image(); - - /** Get a pixel value - @param x X value - @param y Y value - @param c Channel - @return Pixel channel value - */ - const float& getValue(const int &x, const int &y, const int &c) const; - - /** Get a pixel value with linear interpolation, - like x = 4.56, y = 8.34 - @param x X value - @param y Y value - @param c Channel - @return Pixel channel value - */ - float getValueLI(const float &x, const float &y, const int &c) const; - - /** Get a pixel value - @param x X value - @param y Y value - @param c Channel - @return Pixel channel value - */ - inline const float& getValue(const int &x, const int &y, const Channel &c) const - { - return getValue(x, y, static_cast(c)); - } - - /** Get a pixel value with linear interpolation, - like x = 4.56, y = 8.34 - @param x X value - @param y Y value - @param c Channel - @return Pixel channel value - */ - inline float getValueLI(const float &x, const float &y, const Channel &c) const - { - return getValueLI(x, y, static_cast(c)); - } - - /** Get a pixel - @param x X value - @param y Y value - @return Pixel - */ - Pixel getPixel(const int &x, const int &y) const; - - /** Get a pixel with linear interpolation, - like x = 4.56, y = 8.34 - @param x X value - @param y Y value - @return Pixel - */ - Pixel getPixelLI(const float &x, const float &y) const; - - /** Set a pixel value - @param x X value - @param y Y value - @param c Channel - @param v Value - */ - void setValue(const int &x, const int &y, const int &c, const float &v); - - /** Set a pixel value - @param x X value - @param y Y value - @param c Channel - @param v Value - */ - inline void setValue(const int &x, const int &y, const Channel &c, const float &v) - { - setValue(x, y, static_cast(c), v); - } - - /** Set a pixel - @param x X value - @param y Y value - @param p Pixel - */ - void setPixel(const int &x, const int &y, const Pixel &p); - - /** Get image size - @return Image size - */ - inline Size getSize() const - { - return Size(mSize.Width-1,mSize.Height-1); - } - - /** Get image type - @return Image type - */ - inline Type getType() const - { - return static_cast(mChannels); - } - - /** Get number of channels - @return Number of channels - */ - inline const int& getNumberOfChannels() const - { - return mChannels; - } - - private: - /** Initialize array (Reserve dynamic memory) - @param v Initial values - */ - void _Initialize(const float &v); - - /// Image size - Size mSize; - /// Number of channels - int mChannels; - - /// Our image data - float *mData; - }; -} + /** Class for store variable channels of an image + */ + class Image + { + public: + /** Image type enum + */ + enum Type + { + TYPE_ONE_CHANNEL = 1, + TYPE_TWO_CHANNELS = 2, + TYPE_RGB = 3, + /// Default + TYPE_RGBA = 4 + }; + + /** Channel enum + */ + enum Channel + { + CHANNEL_R = 0, // Red + CHANNEL_G = 1, // Green + CHANNEL_B = 2, // Blue + CHANNEL_A = 3 // Alpha + }; + + /** Pixel structure + */ + struct Pixel + { + /** Default constructor + */ + Pixel() : red(0), green(0), blue(0), alpha(0) + { + } + + /** Constructor + @param v RGBA Value + */ + Pixel(const float &v) : red(v), green(v), blue(v), alpha(v) + { + } + + /** Constructor + @param r Red value + @param g Green value + @param b Blue value + @remarks Alpha component = 0 + */ + Pixel(const float &r, const float &g, const float &b) : red(r), green(g), blue(b), alpha(0) + { + } + + /** Constructor + @param r Red value + @param g Green value + @param b Blue value + @param a Alpha value + */ + Pixel(const float &r, const float &g, const float &b, const float &a) : red(r), green(g), blue(b), alpha(a) + { + } + + /// Pixel values (RGBA) + float red, green, blue, alpha; + }; + + /** Constructor + @param Size Image size + */ + Image(const Size &Size); + + /** Constructor + @param Size Image size + @param Type Image type + */ + Image(const Size &Size, const Type &Type); + + /** Constructor + @param Size Image size + @param Type Image type + @param v Initial channel values + */ + Image(const Size &Size, const Type &Type, const float &v); + + /** Destructor + */ + ~Image(); + + /** Get a pixel value + @param x X value + @param y Y value + @param c Channel + @return Pixel channel value + */ + const float &getValue(const int &x, const int &y, const int &c) const; + + /** Get a pixel value with linear interpolation, + like x = 4.56, y = 8.34 + @param x X value + @param y Y value + @param c Channel + @return Pixel channel value + */ + float getValueLI(const float &x, const float &y, const int &c) const; + + /** Get a pixel value + @param x X value + @param y Y value + @param c Channel + @return Pixel channel value + */ + inline const float &getValue(const int &x, const int &y, const Channel &c) const + { + return getValue(x, y, static_cast(c)); + } + + /** Get a pixel value with linear interpolation, + like x = 4.56, y = 8.34 + @param x X value + @param y Y value + @param c Channel + @return Pixel channel value + */ + inline float getValueLI(const float &x, const float &y, const Channel &c) const + { + return getValueLI(x, y, static_cast(c)); + } + + /** Get a pixel + @param x X value + @param y Y value + @return Pixel + */ + Pixel getPixel(const int &x, const int &y) const; + + /** Get a pixel with linear interpolation, + like x = 4.56, y = 8.34 + @param x X value + @param y Y value + @return Pixel + */ + Pixel getPixelLI(const float &x, const float &y) const; + + /** Set a pixel value + @param x X value + @param y Y value + @param c Channel + @param v Value + */ + void setValue(const int &x, const int &y, const int &c, const float &v); + + /** Set a pixel value + @param x X value + @param y Y value + @param c Channel + @param v Value + */ + inline void setValue(const int &x, const int &y, const Channel &c, const float &v) + { + setValue(x, y, static_cast(c), v); + } + + /** Set a pixel + @param x X value + @param y Y value + @param p Pixel + */ + void setPixel(const int &x, const int &y, const Pixel &p); + + /** Get image size + @return Image size + */ + inline Size getSize() const + { + return Size(mSize.Width - 1, mSize.Height - 1); + } + + /** Get image type + @return Image type + */ + inline Type getType() const + { + return static_cast(mChannels); + } + + /** Get number of channels + @return Number of channels + */ + inline const int &getNumberOfChannels() const + { + return mChannels; + } + + private: + /** Initialize array (Reserve dynamic memory) + @param v Initial values + */ + void _Initialize(const float &v); + + /// Image size + Size mSize; + /// Number of channels + int mChannels; + + /// Our image data + float *mData; + }; +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/MaterialManager.cpp b/source/main/gfx/hydrax/MaterialManager.cpp index 5998cd9c7d..fb703cd58a 100644 --- a/source/main/gfx/hydrax/MaterialManager.cpp +++ b/source/main/gfx/hydrax/MaterialManager.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -23,32 +23,30 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to -------------------------------------------------------------------------------- Contributors: - Jose Luis Cercós Pita + Jose Luis Cerc�s Pita -------------------------------------------------------------------------------- */ -#include - -#include - #include +#include +#include -#define _def_Water_Material_Name "_Hydrax_Water_Material" +#define _def_Water_Material_Name "_Hydrax_Water_Material" #define _def_Water_Shader_VP_Name "_Hydrax_Water_VP" #define _def_Water_Shader_FP_Name "_Hydrax_Water_FP" -#define _def_Depth_Material_Name "_Hydrax_Depth_Material" +#define _def_Depth_Material_Name "_Hydrax_Depth_Material" #define _def_Depth_Shader_VP_Name "_Hydrax_Depth_VP" #define _def_Depth_Shader_FP_Name "_Hydrax_Depth_FP" #define _def_DepthTexture_Shader_VP_Name "_Hydrax_DepthTexture_VP" #define _def_DepthTexture_Shader_FP_Name "_Hydrax_DepthTexture_FP" -#define _def_Underwater_Material_Name "_Hydrax_Underwater_Material" +#define _def_Underwater_Material_Name "_Hydrax_Underwater_Material" #define _def_Underwater_Shader_VP_Name "_Hydrax_Underwater_Shader_VP" #define _def_Underwater_Shader_FP_Name "_Hydrax_Underwater_Shader_FP" -#define _def_Underwater_Compositor_Material_Name "_Hydrax_Underwater_Compositor_Material" +#define _def_Underwater_Compositor_Material_Name "_Hydrax_Underwater_Compositor_Material" #define _def_Underwater_Compositor_Shader_VP_Name "_Hydrax_Underwater_Compositor_Shader_VP" #define _def_Underwater_Compositor_Shader_FP_Name "_Hydrax_Underwater_Compositor_Shader_FP" @@ -59,3716 +57,3045 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace Hydrax { - MaterialManager::MaterialManager(Hydrax *h) - : mCreated(false) - , mComponents(HYDRAX_COMPONENTS_NONE) - , mHydrax(h) - { - for (int k = 0; k < 6; k++) - { - mMaterials[k].setNull(); - } - - for (int k = 0; k < 1; k++) - { - mCompositorsEnable[k] = false; - mCompositorsNeedToBeReloaded[k] = false; - } - - mUnderwaterCompositorListener.mMaterialManager = this; - } - - MaterialManager::~MaterialManager() - { - removeMaterials(); - } - - void MaterialManager::removeMaterials() - { - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Water_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_Water_Material_Name); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Water_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Water_Shader_FP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Water_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Water_Shader_FP_Name); - } - - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Depth_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_Depth_Material_Name); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Depth_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Depth_Shader_FP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Depth_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Depth_Shader_FP_Name); - } - - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Underwater_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_Underwater_Material_Name); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Shader_FP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Shader_FP_Name); - } - - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Simple_Red_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_Simple_Red_Material_Name); - } - - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Simple_Black_Material_Name)) - { - Ogre::MaterialManager::getSingleton().remove(_def_Simple_Black_Material_Name); - } - - Ogre::String AlphaChannels[] = {"x","y","z","w", - "r","g","b","a"}; - - for (int k = 0; k<8; k++) - { - if (Ogre::HighLevelGpuProgramManager::getSingleton().resourceExists(_def_DepthTexture_Shader_VP_Name + AlphaChannels[k])) - { - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_DepthTexture_Shader_VP_Name + AlphaChannels[k]); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_DepthTexture_Shader_FP_Name + AlphaChannels[k]); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_DepthTexture_Shader_VP_Name + AlphaChannels[k]); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_DepthTexture_Shader_FP_Name + AlphaChannels[k]); - } - } - - removeCompositor(); - - mCreated = false; - } - - void MaterialManager::removeCompositor() - { - if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Underwater_Compositor_Material_Name)) - { - setCompositorEnable(COMP_UNDERWATER, false); - Ogre::CompositorManager::getSingleton().remove(_def_Underwater_Compositor_Name); - - Ogre::MaterialManager::getSingleton().remove(_def_Underwater_Compositor_Material_Name); - - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Compositor_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Compositor_Shader_FP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Compositor_Shader_VP_Name); - Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Compositor_Shader_FP_Name); - } - } - - bool MaterialManager::createMaterials(const HydraxComponent &Components, const Options &Options) - { - removeMaterials(); - - HydraxLOG("Creating water material..."); - if (!_createWaterMaterial(Components, Options)) - { - return false; - } - mHydrax->getDecalsManager()->registerAll(); - HydraxLOG("Water material created."); - - if (_isComponent(Components, HYDRAX_COMPONENT_DEPTH)) - { - HydraxLOG("Creating depth material..."); - if(!_createDepthMaterial(Components, Options)) - { - return false; - } - HydraxLOG("Depth material created."); - } - - if (_isComponent(Components, HYDRAX_COMPONENT_UNDERWATER)) - { - HydraxLOG("Creating underwater material..."); - if(!_createUnderwaterMaterial(Components, Options)) - { - return false; - } - if(!_createUnderwaterCompositor(Components, Options)) - { - return false; - } - if(!_createSimpleColorMaterial(Ogre::ColourValue::Red, MAT_SIMPLE_RED, _def_Simple_Red_Material_Name, false)) - { - return false; - } - HydraxLOG("Underwater material created."); - } - - mComponents = Components; - mOptions = Options; - mCreated = true; - - std::vector::iterator TechIt; - - for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) - { - if (!(*TechIt)) - { - mDepthTechniques.erase(TechIt); - // TechIt-- ? - continue; - } - - bool isTextureDepthTechnique = - ((*TechIt)->getName() == "_Hydrax_Depth_Technique") ? false : true; - - if (isTextureDepthTechnique) - { - Ogre::String DepthTextureName = - ((*TechIt)->getPass(0)->getTextureUnitState(0)->getName() == "_DetphTexture_Hydrax") ? - (*TechIt)->getPass(0)->getTextureUnitState(0)->getTextureName() : (*TechIt)->getPass(0)->getTextureUnitState(1)->getTextureName(); - - // Alpha channel will be stored in pass 0 name - addDepthTextureTechnique((*TechIt), DepthTextureName, (*TechIt)->getPass(0)->getName() , false); - } - else - { - addDepthTechnique((*TechIt), false); - } - } - - return true; - } - - bool MaterialManager::fillGpuProgramsToPass(Ogre::Pass* Pass, - const Ogre::String GpuProgramNames[2], - const ShaderMode& SM, - const Ogre::String EntryPoints[2], - const Ogre::String Data[2]) - { - GpuProgram GpuPrograms[2] = {GPUP_VERTEX, GPUP_FRAGMENT}; - - for (int k = 0; k < 2; k++) - { - if (!createGpuProgram(GpuProgramNames[k], SM, GpuPrograms[k], EntryPoints[k], Data[k])) - { - return false; - } - } - - Pass->setVertexProgram(GpuProgramNames[0]); - Pass->setFragmentProgram(GpuProgramNames[1]); - - return true; - } - - bool MaterialManager::createGpuProgram(const Ogre::String &Name, - const ShaderMode& SM, - const GpuProgram& GPUP, - const Ogre::String& EntryPoint, - const Ogre::String& Data) - { - if (Ogre::HighLevelGpuProgramManager::getSingleton().resourceExists(Name)) - { - HydraxLOG("Error in bool MaterialManager::createGpuProgram(): "+ Name + " exists."); - return false; - } - - Ogre::String ShaderModesStr[3] = {"hlsl", "cg", "glsl"}; - Ogre::String Profiles[2]; - - switch (SM) - { - case SM_HLSL: - { - Profiles[0] = "target"; - - if (GPUP == GPUP_VERTEX) - { - Profiles[1] = "vs_1_1"; - } - else - { - Profiles[1] = "ps_2_0"; - } - } - break; - - case SM_CG: - { - Profiles[0] = "profiles"; - - if (GPUP == GPUP_VERTEX) - { - Profiles[1] = "vs_1_1 arbvp1"; - } - else - { - Profiles[1] = "ps_2_0 arbfp1 fp20"; - } - } - break; - - case SM_GLSL: - { - Profiles[0] = ""; // Dont needed - if (GPUP == GPUP_VERTEX) - { - Profiles[1] = ""; // Dont needed - } - else - { - Profiles[1] = ""; // Dont needed - } - } - break; - } - - Ogre::GpuProgramType GpuPType; - - if (GPUP == GPUP_VERTEX) - { - GpuPType = Ogre::GPT_VERTEX_PROGRAM; - } - else - { - GpuPType = Ogre::GPT_FRAGMENT_PROGRAM; - } - - Ogre::HighLevelGpuProgramPtr HLGpuProgram = - Ogre::HighLevelGpuProgramManager::getSingleton(). - createProgram(Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - ShaderModesStr[SM], - GpuPType); - - HLGpuProgram->setSource(Data); - HLGpuProgram->setParameter("entry_point", EntryPoint); - HLGpuProgram->setParameter(Profiles[0], Profiles[1]); - HLGpuProgram->load(); - - return true; - } - - bool MaterialManager::_createWaterMaterial(const HydraxComponent &Components, const Options &Options) - { - const bool cDepth = _isComponent(Components, HYDRAX_COMPONENT_DEPTH ); - const bool cSmooth = _isComponent(Components, HYDRAX_COMPONENT_SMOOTH ); - const bool cSun = _isComponent(Components, HYDRAX_COMPONENT_SUN ); - const bool cFoam = _isComponent(Components, HYDRAX_COMPONENT_FOAM ); - const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); - - Ogre::String VertexProgramData, FragmentProgramData; - - // Vertex program - - switch (Options.NM) - { - case NM_TEXTURE: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float2 iUv : TEXCOORD0,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float4 oPosition_ : TEXCOORD0,\n" + - "out float2 oUvNoise : TEXCOORD1,\n" + - "out float4 oUvProjection : TEXCOORD2,\n"; - // UNIFORM - if (cFoam) - { - VertexProgramData += Ogre::String( - "out float4 oWorldPosition : TEXCOORD3,\n") + - "uniform float4x4 uWorld,\n"; - } - VertexProgramData += Ogre::String( - "uniform float4x4 uWorldViewProj)\n") + - "{\n" + - "oPosition_ = iPosition;\n"; - if (cFoam) - { - VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; - } - VertexProgramData += - Ogre::String( - "oPosition = mul(uWorldViewProj, iPosition);\n") + - // Projective texture coordinates, adjust for mapping - "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5,"+ - "0,-0.5, 0, 0.5,"+ - "0, 0, 0.5, 0.5,"+ - "0, 0, 0, 1);\n" + - "oUvProjection = mul(scalemat, oPosition);\n" + - "oUvNoise = iUv;\n" + - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n"); - // UNIFORMS - if(cFoam) - { - VertexProgramData += "uniform mat4 uWorld;\n"; - } - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec4 Position_;\n") + - "varying vec4 UVProjection;\n"; - if(cFoam) - { - VertexProgramData += "varying vec4 WorldPosition;\n"; - } - // PROGRAM - VertexProgramData += Ogre::String( - "void main()\n") + - "{\n" + - "Position_ = gl_Vertex;\n"; - if(cFoam) - { - VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; - } - VertexProgramData += Ogre::String( - "gl_Position = ftransform();\n") + - "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + - " 0.0, -1.0, 0.0, 0.0,\n" + - " 0.0, 0.0, 1.0, 0.0,\n" + - " 0.0, 0.0, 0.0, 1.0);\n" + - "UVProjection = scalemat * gl_Position;\n" + - "gl_TexCoord[0] = gl_MultiTexCoord0;\n" + - "}\n"; - } - break; - } - } - break; - - case NM_VERTEX: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float3 iNormal : NORMAL,\n"+ - // OUT - "out float4 oPosition : POSITION,\n" + - "out float4 oPosition_ : TEXCOORD0,\n" + - "out float4 oUvProjection : TEXCOORD1,\n" + - "out float3 oNormal : TEXCOORD2,\n"; - if (cFoam) - { - VertexProgramData += "out float4 oWorldPosition : TEXCOORD3,\n uniform float4x4 uWorld,\n"; - } - VertexProgramData += - Ogre::String( - // UNIFORM - "uniform float4x4 uWorldViewProj)\n") + - "{\n" + - "oPosition_ = iPosition;\n"; - if (cFoam) - { - VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; - } - VertexProgramData += - Ogre::String( - "oPosition = mul(uWorldViewProj, iPosition);\n") + - // Projective texture coordinates, adjust for mapping - "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5,"+ - "0,-0.5, 0, 0.5,"+ - "0, 0, 0.5, 0.5,"+ - "0, 0, 0, 1);\n" + - "oUvProjection = mul(scalemat, oPosition);\n" + - "oNormal = normalize(iNormal);\n"+ - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n"); - // UNIFORMS - if(cFoam) - { - VertexProgramData += "uniform mat4 uWorld;\n"; - } - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec4 Position_;\n") + - "varying vec4 UVProjection;\n" + - "varying vec3 Normal;\n"; - if(cFoam) - { - VertexProgramData += "varying vec4 WorldPosition;\n"; - } - // PROGRAM - VertexProgramData += Ogre::String( - "void main()\n") + - "{\n" + - "Position_ = gl_Vertex;\n"; - if(cFoam) - { - VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; - } - VertexProgramData += Ogre::String( - "gl_Position = ftransform();\n") + - "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + - " 0.0, -1.0, 0.0, 0.0,\n" + - " 0.0, 0.0, 1.0, 0.0,\n" + - " 0.0, 0.0, 0.0, 1.0);\n" + - "UVProjection = scalemat * gl_Position;\n" + - "Normal = normalize(gl_Normal);\n" + - "}\n"; - } - break; - } - } - break; - - case NM_RTT: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float4 oPosition_ : TEXCOORD0,\n" + - "out float4 oUvProjection : TEXCOORD1,\n"; - if (cFoam) - { - VertexProgramData += "out float4 oWorldPosition : TEXCOORD2,\n uniform float4x4 uWorld,\n"; - } - VertexProgramData += - Ogre::String( - // UNIFORM - "uniform float4x4 uWorldViewProj)\n") + - "{\n" + - "oPosition_ = iPosition;\n"; - if (cFoam) - { - VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; - } - VertexProgramData += - Ogre::String( - "oPosition = mul(uWorldViewProj, iPosition);\n") + - // Projective texture coordinates, adjust for mapping - "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5,"+ - "0,-0.5, 0, 0.5,"+ - "0, 0, 0.5, 0.5,"+ - "0, 0, 0, 1);\n" + - "oUvProjection = mul(scalemat, oPosition);\n" + - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n"); - // UNIFORMS - if(cFoam) - { - VertexProgramData += "uniform mat4 uWorld;\n"; - } - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec4 Position_;\n") + - "varying vec4 UVProjection;\n"; - if(cFoam) - { - VertexProgramData += "varying vec4 WorldPosition;\n"; - } - // PROGRAM - VertexProgramData +=Ogre::String( - "void main()\n") + - "{\n" + - "Position_ = gl_Vertex;\n"; - if(cFoam) - { - VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; - } - VertexProgramData += Ogre::String( - "gl_Position = ftransform();\n") + - "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + - " 0.0, -1.0, 0.0, 0.0,\n" + - " 0.0, 0.0, 1.0, 0.0,\n" + - " 0.0, 0.0, 0.0, 1.0);\n" + - "UVProjection = scalemat * gl_Position;\n" + - "}\n"; - } - break; - } - } - break; - } - - - // Fragment program - - switch (Options.NM) - { - case NM_TEXTURE: case NM_VERTEX: case NM_RTT: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - FragmentProgramData += - Ogre::String("float3 expand(float3 v)\n") + - "{\n" + - "return (v - 0.5) * 2;\n" + - "}\n\n" + - - "void main_fp(" + - // IN - "float4 iPosition : TEXCOORD0,\n"; - int TEXCOORDNUM = 1; - if (Options.NM == NM_TEXTURE) - { - FragmentProgramData += - "float2 iUvNoise : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - } - FragmentProgramData += - "float4 iUvProjection : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "float4 iNormal : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - } - if (cFoam) - { - FragmentProgramData += - "float4 iWorldPosition : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - } - FragmentProgramData += - Ogre::String( - // OUT - "out float4 oColor : COLOR,\n") + - // UNIFORM - "uniform float3 uEyePosition,\n" + - "uniform float uFullReflectionDistance,\n" + - "uniform float uGlobalTransparency,\n" + - "uniform float uNormalDistortion,\n"; - - if (cDepth) - { - FragmentProgramData += - "uniform float3 uWaterColor,\n"; - } - if (cSmooth) - { - FragmentProgramData += - "uniform float uSmoothPower,\n"; - } - if (cSun) - { - FragmentProgramData += Ogre::String( - "uniform float3 uSunPosition,\n") + - "uniform float uSunStrength,\n" + - "uniform float uSunArea,\n" + - "uniform float3 uSunColor,\n"; - } - if (cFoam) - { - FragmentProgramData += Ogre::String( - "uniform float uFoamRange,\n") + - "uniform float uFoamMaxDistance,\n" + - "uniform float uFoamScale,\n" + - "uniform float uFoamStart,\n" + - "uniform float uFoamTransparency,\n"; - } - if (cCaustics) - { - FragmentProgramData += - "uniform float uCausticsPower,\n"; - } - - int TexNum = 0; - - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "uniform sampler2D uNormalMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; - TexNum++; - } - - FragmentProgramData += - Ogre::String( - "uniform sampler2D uReflectionMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n") + - "uniform sampler2D uRefractionMap : register(s" + Ogre::StringConverter::toString(TexNum+1) + "),\n"; - - TexNum += 2; - - if (cDepth) - { - FragmentProgramData += - "uniform sampler2D uDepthMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; - TexNum++; - } - - FragmentProgramData += - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "uniform sampler1D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; - #else - "uniform sampler2D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; - #endif - TexNum++; - - if (cFoam) - { - FragmentProgramData += Ogre::String( - ",\nuniform sampler2D uFoamMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")\n"); - } - - FragmentProgramData += - Ogre::String( ")\n") + - "{\n" + - "float2 ProjectionCoord = iUvProjection.xy / iUvProjection.w;\n" + - "float3 camToSurface = iPosition.xyz - uEyePosition;\n" + - "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; - - if (cFoam) - { - // Calculate the foam visibility as a function fo distance specified by user - FragmentProgramData += - "float foamVisibility=1.0f-saturate(additionalReflection/uFoamMaxDistance);\n"; - } - - FragmentProgramData += - Ogre::String( - "additionalReflection/=uFullReflectionDistance;\n") + - "camToSurface=normalize(-camToSurface);\n"; - if (Options.NM == NM_TEXTURE) - { - FragmentProgramData += Ogre::String( - "float3 pixelNormal = tex2D(uNormalMap,iUvNoise);\n") + - // Inverte y with z, because at creation our local normal to the plane was z - "pixelNormal.yz=pixelNormal.zy;\n" + - // Remap from [0,1] to [-1,1] - "pixelNormal.xyz=expand(pixelNormal.xyz);\n"; - } - else if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "float3 pixelNormal = iNormal;\n"; - } - else // NM_RTT - { - FragmentProgramData += - "float3 pixelNormal = 2.0*tex2D(uNormalMap, ProjectionCoord.xy) - 1.0;\n"; - } - FragmentProgramData += - "float2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "float dotProduct=dot(camToSurface,pixelNormal);\n"; - } - else - { - FragmentProgramData += - "float dotProduct=dot(-camToSurface,pixelNormal);\n"; - } - FragmentProgramData += - Ogre::String( - "dotProduct=saturate(dotProduct);\n") + - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "float fresnel = tex1D(uFresnelMap,dotProduct);\n" + - #else - "float fresnel = tex2D(uFresnelMap,float2(dotProduct,dotProduct));\n" + - #endif - // Add additional reflection and saturate - "fresnel+=additionalReflection;\n" + - "fresnel=saturate(fresnel);\n" + - // Decrease the transparency and saturate - "fresnel-=uGlobalTransparency;\n" + - "fresnel=saturate(fresnel);\n" + - #if OGRE_PLATFORM != OGRE_PLATFORM_WIN32 - // Reversing projection if underwater - "if(uEyePosition.y < 0.0)\n" + - "{\n" + - "ProjectionCoord.y = 1.0 - ProjectionCoord.y;\n" + - "}\n" + - #endif - // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal - "float3 reflection=tex2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified);\n" + - "float3 refraction=tex2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified);\n"; - - if (cDepth) - { - if (cCaustics) - { - FragmentProgramData += Ogre::String( - "float2 depth = tex2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).rg;\n") + - "refraction *= 1+depth.y*uCausticsPower;\n" + - "refraction = lerp(uWaterColor,refraction,depth.x);\n"; - } - else - { - FragmentProgramData += Ogre::String( - "float depth = tex2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).r;\n") + - "refraction = lerp(uWaterColor,refraction,depth);\n"; - } - } - - FragmentProgramData += - "oColor = float4(lerp(refraction,reflection,fresnel),1);\n"; - - if (cSun) - { - FragmentProgramData += Ogre::String( - "float3 relfectedVector = normalize(reflect(-camToSurface,pixelNormal.xyz));\n") + - "float3 surfaceToSun=normalize(uSunPosition-iPosition.xyz);\n" + - "float3 sunlight = uSunStrength*pow(saturate(dot(relfectedVector,surfaceToSun)),uSunArea)*uSunColor;\n" + - "oColor.xyz+=sunlight;\n"; - } - - if (cFoam) - { - FragmentProgramData += Ogre::String( - "float hmap = iPosition.y/uFoamRange*foamVisibility;\n") + - "float2 foamTex=iWorldPosition.xz*uFoamScale+pixelNormalModified;\n" + - "float foam=tex2D(uFoamMap,foamTex).r;\n" + - "float foamTransparency=saturate(hmap-uFoamStart)*uFoamTransparency;\n" + - "oColor.xyz=lerp(oColor.xyz,1,foamTransparency*foam);\n"; - } - - if (cSmooth) - { - FragmentProgramData += - "oColor.xyz = lerp(tex2D(uRefractionMap,ProjectionCoord.xy).xyz,oColor.xyz,saturate((1-tex2D(uDepthMap,ProjectionCoord.xy).r)*uSmoothPower));\n"; - } - - FragmentProgramData += - "}\n"; - } - break; - - case SM_GLSL: - FragmentProgramData += Ogre::String("\n") + - // UNIFORMS - "uniform vec3 uEyePosition;\n" + - "uniform float uFullReflectionDistance;\n" + - "uniform float uGlobalTransparency;\n" + - "uniform float uNormalDistortion;\n" + - "uniform vec3 uWaterColor;\n"; - - if (cSmooth) - { - FragmentProgramData += - "uniform float uSmoothPower;\n"; - } - if (cSun) - { - FragmentProgramData += Ogre::String( - "uniform vec3 uSunPosition;\n") + - "uniform float uSunStrength;\n" + - "uniform float uSunArea;\n" + - "uniform vec3 uSunColor;\n"; - } - if (cFoam) - { - FragmentProgramData += Ogre::String( - "uniform float uFoamRange;\n") + - "uniform float uFoamMaxDistance;\n" + - "uniform float uFoamScale;\n" + - "uniform float uFoamStart;\n" + - "uniform float uFoamTransparency;\n"; - } - if (cCaustics) - { - FragmentProgramData += - "uniform float uCausticsPower;\n"; - } - - int TexNum = 0; - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "uniform sampler2D uNormalMap;\n"; - TexNum++; - } - - FragmentProgramData += Ogre::String( - "uniform sampler2D uReflectionMap;\n") + - "uniform sampler2D uRefractionMap;\n"; - TexNum += 2; - - if (cDepth) - { - FragmentProgramData += - "uniform sampler2D uDepthMap;\n"; - TexNum++; - } - - FragmentProgramData += - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "uniform sampler1D uFresnelMap;\n"; - #else - "uniform sampler2D uFresnelMap;\n"; - #endif - TexNum++; - - if (cFoam) - { - FragmentProgramData += - "uniform sampler2D uFoamMap;\n"; - } - // IN - FragmentProgramData += - "varying vec4 Position_;\n"; - int TEXCOORDNUM = 1; - if (Options.NM == NM_TEXTURE) - { - TEXCOORDNUM++; - } - FragmentProgramData += - "varying vec4 UVProjection;\n"; - TEXCOORDNUM++; - if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "varying vec3 Normal;\n"; - TEXCOORDNUM++; - } - if (cFoam) - { - FragmentProgramData += - "varying vec4 WorldPosition;\n"; - } - // Expand function - FragmentProgramData += Ogre::String( - "vec3 expand(vec3 v)\n") + - "{\n" + - "return (v - 0.5) * 2.0;\n" + - "}\n\n" + - // main function - "void main()\n" + - "{\n" + - "vec2 ProjectionCoord = UVProjection.xy / UVProjection.w;\n" + - "ProjectionCoord += 1.0;\n" + - "ProjectionCoord *= 0.5;\n" + - "vec3 camToSurface = Position_.xyz - uEyePosition;\n" + - "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; - if (cFoam) - { - // Calculate the foam visibility as a function fo distance specified by user - FragmentProgramData += - "float foamVisibility=1.0-clamp(additionalReflection/uFoamMaxDistance, 0.0, 1.0);\n"; - } - FragmentProgramData += Ogre::String( - "additionalReflection/=uFullReflectionDistance;\n") + - "camToSurface=normalize(-camToSurface);\n"; - if (Options.NM == NM_TEXTURE) - { - FragmentProgramData += Ogre::String( - "vec3 pixelNormal = texture2D(uNormalMap,gl_TexCoord[0].xy).xyz;\n") + - // Inverte y with z, because at creation our local normal to the plane was z - "pixelNormal.yz=pixelNormal.zy;\n" + - // Remap from [0,1] to [-1,1] - "pixelNormal.xyz=expand(pixelNormal.xyz);\n"; - } - else if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "vec3 pixelNormal = Normal;\n"; - } - else // NM_RTT - { - FragmentProgramData += - "vec3 pixelNormal = 2.0*texture2D(uNormalMap, ProjectionCoord.xy).xyz - 1.0;\n"; - } - FragmentProgramData += - "vec2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "float dotProduct=dot(camToSurface,pixelNormal);\n"; - } - else - { - FragmentProgramData += - "float dotProduct=dot(-camToSurface,pixelNormal);\n"; - } - FragmentProgramData += Ogre::String( - "dotProduct=clamp(dotProduct, 0.0, 1.0);\n") + - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "float fresnel = texture1D(uFresnelMap,dotProduct).x;\n" + - #else - "float fresnel = texture2D(uFresnelMap,vec2(dotProduct,dotProduct)).x;\n" + - #endif - // Add additional reflection and saturate - "fresnel +=additionalReflection;\n" + - "fresnel = clamp(fresnel, 0.0, 1.0);\n" + - // Decrease the transparency and saturate - "fresnel -= uGlobalTransparency;\n" + - "fresnel = clamp(fresnel*fresnel, 0.0, 1.0);\n" + - // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal - "vec3 reflection=texture2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified).xyz;\n" + - "vec3 refraction=texture2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified).xyz;\n"; - if (cDepth) - { - if (cCaustics) - { - FragmentProgramData += Ogre::String( - "vec2 depth = texture2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).xy;\n") + - "refraction *= 1.0 + depth.y*uCausticsPower;\n" + - "refraction = mix(uWaterColor,refraction,depth.x);\n"; - } - else - { - FragmentProgramData += Ogre::String( - "float depth = texture2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).x;\n") + - "refraction = mix(uWaterColor,refraction,depth);\n"; - } - } - FragmentProgramData += Ogre::String( - "gl_FragColor = vec4(mix(refraction,reflection,fresnel),1.0);\n") + - "gl_FragColor.xyz = mix(gl_FragColor.xyz, uWaterColor, uGlobalTransparency);\n"; - if (cSun) - { - FragmentProgramData += Ogre::String( - "vec3 relfectedVector = normalize(reflect(-camToSurface,pixelNormal.xyz));\n") + - "vec3 surfaceToSun=normalize(uSunPosition-Position_.xyz);\n" + - "vec3 sunlight = uSunStrength*pow(clamp(dot(relfectedVector,surfaceToSun),0.0,1.0),uSunArea)*uSunColor;\n" + - "gl_FragColor.xyz+=sunlight;\n"; - } - if (cFoam) - { - FragmentProgramData += Ogre::String( - "float hmap = Position_.y/uFoamRange*foamVisibility;\n") + - "vec2 foamTex=WorldPosition.xz*uFoamScale+pixelNormalModified;\n" + - "float foam=texture2D(uFoamMap,foamTex).x;\n" + - "float foamTransparency=clamp(hmap-uFoamStart, 0.0, 1.0)*uFoamTransparency;\n" + - "gl_FragColor.xyz=mix(gl_FragColor.xyz,vec3(1.0,1.0,1.0),foamTransparency*foam);\n"; - } - if (cSmooth) - { - FragmentProgramData += - "gl_FragColor.xyz = mix(texture2D(uRefractionMap,ProjectionCoord.xy).xyz,gl_FragColor.xyz,clamp((1.0-texture2D(uDepthMap,ProjectionCoord.xy).x)*uSmoothPower, 0.0, 1.0));\n"; - } - FragmentProgramData += - "}\n"; - break; - } - } - break; - } - - // Build our material - Ogre::MaterialPtr &WaterMaterial = getMaterial(MAT_WATER); - WaterMaterial = Ogre::MaterialManager::getSingleton(). - create(_def_Water_Material_Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::Pass *WM_Technique0_Pass0 = WaterMaterial->getTechnique(0)->getPass(0); - - WM_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); - WM_Technique0_Pass0->setDepthWriteEnabled(true); - - Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; - Ogre::String GpuProgramNames[2] = {_def_Water_Shader_VP_Name, _def_Water_Shader_FP_Name}; - Ogre::String EntryPoints[2]; - if(Options.SM == SM_GLSL) + MaterialManager::MaterialManager(Hydrax *h) : mCreated(false), mComponents(HYDRAX_COMPONENTS_NONE), mHydrax(h) + { + for (int k = 0; k < 6; k++) { - EntryPoints[0] = Ogre::String("main"); - EntryPoints[1] = Ogre::String("main"); + mMaterials[k].setNull(); } - else + + for (int k = 0; k < 1; k++) { - EntryPoints[0] = Ogre::String("main_vp"); - EntryPoints[1] = Ogre::String("main_fp"); + mCompositorsEnable[k] = false; + mCompositorsNeedToBeReloaded[k] = false; } - fillGpuProgramsToPass(WM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + mUnderwaterCompositorListener.mMaterialManager = this; + } - Ogre::GpuProgramParametersSharedPtr VP_Parameters = WM_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = WM_Technique0_Pass0->getFragmentProgramParameters(); + MaterialManager::~MaterialManager() + { + removeMaterials(); + } - if(Options.SM != SM_GLSL) + void MaterialManager::removeMaterials() + { + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Water_Material_Name)) { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - } - if (cFoam) - { - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - } - FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + Ogre::MaterialManager::getSingleton().remove(_def_Water_Material_Name); - FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); - FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); - FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); - - FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); - if (cSmooth) - { - FP_Parameters->setNamedConstant("uSmoothPower", mHydrax->getSmoothPower()); - } - if (cSun) - { - FP_Parameters->setNamedConstant("uSunPosition", mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); - FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); - FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); - FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); - } - if (cFoam) - { - FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); - FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); - FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); - FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); - FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); - } - if (cCaustics) - { - FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); - } - - int GLSLTextUnit = 0; - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uNormalMap", GLSLTextUnit); - GLSLTextUnit++; - } - WM_Technique0_Pass0->createTextureUnitState("HydraxNormalMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - } + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Water_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Water_Shader_FP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Water_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Water_Shader_FP_Name); + } - if(Options.SM == SM_GLSL) + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Depth_Material_Name)) { - FP_Parameters->setNamedConstant("uReflectionMap", GLSLTextUnit); - GLSLTextUnit++; + Ogre::MaterialManager::getSingleton().remove(_def_Depth_Material_Name); + + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Depth_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Depth_Shader_FP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Depth_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Depth_Shader_FP_Name); } - WM_Technique0_Pass0->createTextureUnitState("HydraxReflectionMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - if(Options.SM == SM_GLSL) + + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Underwater_Material_Name)) { - FP_Parameters->setNamedConstant("uRefractionMap", GLSLTextUnit); - GLSLTextUnit++; + Ogre::MaterialManager::getSingleton().remove(_def_Underwater_Material_Name); + + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Shader_FP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Shader_FP_Name); } - WM_Technique0_Pass0->createTextureUnitState("HydraxRefractionMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - if (cDepth) - { - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit); - GLSLTextUnit++; - } - WM_Technique0_Pass0->createTextureUnitState("HydraxDepthMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - } + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Simple_Red_Material_Name)) + { Ogre::MaterialManager::getSingleton().remove(_def_Simple_Red_Material_Name); } - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uFresnelMap", GLSLTextUnit); - GLSLTextUnit++; - } - WM_Technique0_Pass0->createTextureUnitState("Fresnel.bmp")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Simple_Black_Material_Name)) + { Ogre::MaterialManager::getSingleton().remove(_def_Simple_Black_Material_Name); } - if (cFoam) - { - if(Options.SM == SM_GLSL) + Ogre::String AlphaChannels[] = {"x", "y", "z", "w", "r", "g", "b", "a"}; + + for (int k = 0; k < 8; k++) + { + if (Ogre::HighLevelGpuProgramManager::getSingleton().resourceExists(_def_DepthTexture_Shader_VP_Name + + AlphaChannels[k])) { - FP_Parameters->setNamedConstant("uFoamMap", GLSLTextUnit); - GLSLTextUnit++; + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_DepthTexture_Shader_VP_Name + AlphaChannels[k]); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_DepthTexture_Shader_FP_Name + AlphaChannels[k]); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_DepthTexture_Shader_VP_Name + AlphaChannels[k]); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_DepthTexture_Shader_FP_Name + AlphaChannels[k]); } - WM_Technique0_Pass0->createTextureUnitState("Foam.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - } - - WaterMaterial->setReceiveShadows(false); - WaterMaterial->load(); - - return true; - } - - bool MaterialManager::_createDepthMaterial(const HydraxComponent &Components, const Options &Options) - { - const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); - - Ogre::String VertexProgramData, FragmentProgramData; - - // Vertex program - - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - // No caustics - if (!cCaustics) - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float oPosition_ : TEXCOORD0,\n" + - "out float2 oDistance : TEXCOORD1,\n" + - // UNIFORM - "uniform float uPlaneYPos,\n" + - "uniform float uPlanesError,\n" + - "uniform float3 uCameraPos,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float4x4 uWorldView,\n" + - "uniform float4x4 uWorldViewProj)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n" + - "float3 wPos = mul(uWorld, iPosition).xyz;\n" + - "float3 wCam = uCameraPos;\n" + - "wPos.y -= uPlaneYPos;\n" + - "wCam.y -= uPlaneYPos;\n" + - "oPosition_ = wPos.y;\n" + - // Distance - "oDistance.x = distance(wPos, wCam);\n" + - "oDistance.y = 1.0;\n" + - // If exist water plane between points, occlusion effect must be changed. - "if(wCam.y > 0.0) {\n" + - "oDistance.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + - "}\n" + - "if(wPos.y > uPlanesError) {\n" + - "oDistance.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + - "oDistance.y = 0.0;\n" + - "}\n" + - "}\n"; - } - else // Caustics - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float oPosition_ : TEXCOORD0,\n" + - "out float2 oDistance : TEXCOORD1,\n" + - "out float2 oUvWorld : TEXCOORD2,\n" + - // UNIFORM - "uniform float uPlaneYPos,\n" + - "uniform float uPlanesError,\n" + - "uniform float3 uCameraPos,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float4x4 uWorldViewProj)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n" + - "float3 wPos = mul(uWorld, iPosition).xyz;\n" + - "float3 wCam = uCameraPos;\n" + - "wPos.y -= uPlaneYPos;\n" + - "wCam.y -= uPlaneYPos;\n" + - "oPosition_ = wPos.y;\n" + - // Distance - "oDistance.x = distance(wPos, wCam);\n" + - "oDistance.y = 1.0;\n" + - // If exist water plane between points, occlusion effect must be changed. - "if(wCam.y > 0.0) {\n" + - "oDistance.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + - "}\n" + - "if(wPos.y > uPlanesError) {\n" + - "oDistance.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + - "oDistance.y = 0.0;\n" + - "}\n" + - "oUvWorld = wPos.xz;\n" + - "}\n"; - } - } - break; - - case SM_GLSL: - // No caustics - if (!cCaustics) - { - VertexProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uPlaneYPos;\n" + - "uniform float uPlanesError;\n" + - "uniform mat4 uWorld;\n" + - // IN - // OUT - "varying float Position_;\n" + - "varying vec2 Distance_;\n" + - // main function - "void main()\n" + - "{\n" + - // Point and camera position - "vec3 wPos = ( uWorld * gl_Vertex ).xyz;\n" + - "vec3 wCam = ( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).xyz;\n" + - "wPos.y -= uPlaneYPos;\n" + - "wCam.y -= uPlaneYPos;\n" + - "Position_ = wPos.y;\n" + - // Distance - "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + - "Distance_.x = abs(mwPos.z);\n" + - "Distance_.y = 1.0;\n" + - // If exist water plane between points, occlusion effect must be changed. - "if(wCam.y > 0.0) {\n" + - "Distance_.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + - "}\n" + - "if(wPos.y > uPlanesError) {\n" + - "Distance_.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + - "Distance_.y = 0.0;\n" + - "}\n" + - "}\n"; - } - else // Caustics - { - VertexProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uPlaneYPos;\n" + - "uniform float uPlanesError;\n" + - "uniform mat4 uWorld;\n" + - // IN - // OUT - "varying float Position_;\n" + - "varying vec2 Distance_;\n" + - "varying vec2 UVWorld;\n" + - // main function - "void main()\n" + - "{\n" + - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + - // Point and camera position - "vec3 wPos = ( uWorld * gl_Vertex ).xyz;\n" + - "vec3 wCam = ( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).xyz;\n" + - "wPos.y -= uPlaneYPos;\n" + - "wCam.y -= uPlaneYPos;\n" + - "Position_ = wPos.y;\n" + - // Distance - "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + - "Distance_.x = abs(mwPos.z);\n" + - "Distance_.y = 1.0;\n" + - // If exist water plane between points, occlusion effect must be changed. - "if(wCam.y > 0.0) {\n" + - "Distance_.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + - "}\n" + - "if(wPos.y > uPlanesError) {\n" + - /* - "vec3 wFocus = ( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.1, 1.0) ).xyz;\n" + - "vec3 CamToFreeSurface = wFocus - wCam;\n" + - "CamToFreeSurface *= wCam.y / CamToFreeSurface.y;\n" + - "Distance_.x = length(CamToFreeSurface);\n" + - */ - "Distance_.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + - "Distance_.y = 0.0;\n" + - "}\n" + - "UVWorld = wPos.xz;\n" + - "}\n"; - } - break; - } - - // Fragment program - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - // No caustics - if (!cCaustics) - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float iPosition : TEXCOORD0,\n" + - "float2 iDistance : TEXCOORD1,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float uDepthLimit,\n" + - "uniform float uDistLimit)\n" + - "{\n" + - "float pixelYDepth = saturate(iPosition*uDepthLimit + 1.0);\n" + - "float pixelDepth = saturate(1.0 - iDistance.x*uDistLimit);\n" + - "pixelDepth = min(pixelYDepth, pixelDepth);\n" + - "oColor = float4(pixelDepth,0,0,0);\n" + - "}\n"; - } - else // Caustics - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float iPosition : TEXCOORD0,\n" + - "float2 iDistance : TEXCOORD1,\n" + - "float2 iUvWorld : TEXCOORD2,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float uDepthLimit,\n" + - "uniform float uDistLimit,\n" + - "uniform float uCausticsScale,\n" + - "uniform float uCausticsEnd,\n" + - "uniform sampler2D uCaustics : register(s0))\n" + - "{\n" + - "float pixelYDepth = saturate(iPosition*uDepthLimit + 1.0);\n" + - // "float pixelDepth = saturate(1.0 - iDistance.x*uDistLimit);\n" + - "float pixelDepth = saturate(1.0 - iDistance.x*uDistLimit);\n" + - "pixelDepth = min(pixelYDepth, pixelDepth);\n" + - "oColor = float4(pixelDepth,0.0,0.0,0.0);\n" + - "oColor.g = iDistance.y*saturate((pixelYDepth-uCausticsEnd)/(1.0-uCausticsEnd))*tex2D(uCaustics, iUvWorld/uCausticsScale).x;\n" + - "}\n"; - } - } - break; - - case SM_GLSL: - // No caustics - if (!cCaustics) - { - FragmentProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uDepthLimit;\n" + - "uniform float uDistLimit;\n" + - // IN - "varying float Position_;\n" + - "varying float Distance_;\n" + - // OUT - // main function - "void main()" + - "{\n" + - "float pixelYDepth = clamp(1.0 + Position_*uDepthLimit, 0.0, 1.0);\n" + - "float pixelDepth = clamp(1.0 - Distance_.x*uDistLimit, 0.0, 1.0);\n" + - "pixelDepth = min(pixelYDepth,pixelDepth);\n" + - "gl_FragColor = vec4(pixelDepth,0.0,0.0,1.0);\n" + - "}\n"; - } - else // Caustics - { - FragmentProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uDepthLimit;\n" + - "uniform float uDistLimit;\n" + - "uniform float uCausticsScale;\n" + - "uniform float uCausticsEnd;\n" + - "uniform sampler2D uCaustics;\n" + - // IN - "varying float Position_;\n" + - "varying vec2 Distance_;\n" + - "varying vec2 UVWorld;\n" + - // OUT - // main function - "void main()" + - "{\n" + - "float pixelYDepth = clamp(1.0 + Position_*uDepthLimit, 0.0, 1.0);\n" + - "float pixelDepth = clamp(1.0 - Distance_.x*uDistLimit, 0.0, 1.0);\n" + - "pixelDepth = min(pixelYDepth,pixelDepth);\n" + - "gl_FragColor = vec4(pixelDepth,0.0,0.0,1.0);\n" + - "gl_FragColor.y = Distance_.y*clamp((pixelYDepth-uCausticsEnd)/(1.0-uCausticsEnd), 0.0, 1.0)*texture2D(uCaustics, UVWorld/uCausticsScale).x;\n" + - "}\n"; - } - break; - } - - // Build our material - Ogre::MaterialPtr &DepthMaterial = getMaterial(MAT_DEPTH); - DepthMaterial = Ogre::MaterialManager::getSingleton(). - create(_def_Depth_Material_Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - DepthMaterial->getTechnique(0)->setSchemeName("HydraxDepth"); - - Ogre::Pass *DM_Technique0_Pass0 = DepthMaterial->getTechnique(0)->getPass(0); - - Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; - Ogre::String GpuProgramNames[2] = {_def_Depth_Shader_VP_Name, _def_Depth_Shader_FP_Name}; - Ogre::String EntryPoints[2]; - if(Options.SM == SM_GLSL) - { - EntryPoints[0] = Ogre::String("main"); - EntryPoints[1] = Ogre::String("main"); - } - else - { - EntryPoints[0] = Ogre::String("main_vp"); - EntryPoints[1] = Ogre::String("main_fp"); } - fillGpuProgramsToPass(DM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + removeCompositor(); - Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique0_Pass0->getFragmentProgramParameters(); + mCreated = false; + } - if(Options.SM != SM_GLSL) + void MaterialManager::removeCompositor() + { + if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Underwater_Compositor_Material_Name)) { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - // VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); - } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); - VP_Parameters->setNamedConstant("uPlanesError", (float) mHydrax->getPlanesError()); - - FP_Parameters->setNamedConstant("uDepthLimit", 1.f/mHydrax->getDepthLimit()); - FP_Parameters->setNamedConstant("uDistLimit", 1.f/mHydrax->getDistLimit()); + setCompositorEnable(COMP_UNDERWATER, false); + Ogre::CompositorManager::getSingleton().remove(_def_Underwater_Compositor_Name); - if (cCaustics) - { - FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); - FP_Parameters->setNamedConstant("uCausticsEnd", 1.f - mHydrax->getCausticsEnd()); + Ogre::MaterialManager::getSingleton().remove(_def_Underwater_Compositor_Material_Name); - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uCaustics", 0); - } - Ogre::TextureUnitState *TUS_Caustics = DM_Technique0_Pass0->createTextureUnitState("Caustics.bmp"); - TUS_Caustics->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - TUS_Caustics->setAnimatedTextureName("Caustics.bmp", 32, 1.5); - } - - DepthMaterial->setReceiveShadows(false); - DepthMaterial->load(); - - return true; - } - - bool MaterialManager::_createDepthTextureGPUPrograms(const HydraxComponent &Components, const Options &Options, const Ogre::String& AlphaChannel) - { - const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); - - Ogre::String VertexProgramData, FragmentProgramData; - - // Vertex program - - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - // No caustics - if (!cCaustics) - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float2 iUV : TEXCOORD0,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float3 oPosition_UV : TEXCOORD0,\n" + - // UNIFORM - "uniform float uPlaneYPos,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float4x4 uWorldViewProj)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n" + - "oPosition_UV.x = mul(uWorld, iPosition).y;\n" + - "oPosition_UV.x-=uPlaneYPos;\n" + - "oPosition_UV.yz = iUV;\n" + - "}\n"; - } - else // Caustics - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float2 iUV : TEXCOORD0,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float3 oPosition_UV : TEXCOORD0,\n" + - "out float2 oUvWorld : TEXCOORD1,\n" + - // UNIFORM - "uniform float uPlaneYPos,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float4x4 uWorldViewProj)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n" + - "float3 wPos = mul(uWorld, iPosition);\n" + - "oPosition_UV.x = wPos.y;\n" + - "oPosition_UV.x-=uPlaneYPos;\n" + - "oPosition_UV.yz = iUV;\n" + - "oUvWorld = wPos.xz;\n" + - "}\n"; - } - } - break; - - case SM_GLSL: - // No caustics - if (!cCaustics) - { - VertexProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uPlaneYPos;\n" + - "uniform mat4 uWorld;\n" + - // IN - // OUT - "varying vec3 Position_UV;\n" + - // main function - "void main()\n" + - "{\n" + - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + - "Position_UV.x = (uWorld * gl_Vertex).y;\n" + - "Position_UV.x -= uPlaneYPos;\n" + - "Position_UV.yz = gl_MultiTexCoord0;\n" + - "}\n"; - } - else // Caustics - { - VertexProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uPlaneYPos;\n" + - "uniform mat4 uWorld;\n" + - // IN - // OUT - "varying vec3 Position_UV;\n" + - "varying vec2 UVWorld;\n" + - // main function - "void main()\n" + - "{\n" + - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + - "vec3 wPos = uWorld * iPosition;\n" + - "Position_UV.x = wPos.y;\n" + - "Position_UV.x -= uPlaneYPos;\n" + - "Position_UV.yz = gl_MultiTexCoord0;\n" + - "UVWorld = wPos.xz;\n" + - "}\n"; - } - break; - } - - // Fragment program - - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - // No caustics - if (!cCaustics) - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition_UV : TEXCOORD0,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float uDepthLimit,\n" + - "uniform sampler2D uAlphaTex : register(s0))\n" + - "{\n" + - "float pixelYDepth = (iPosition_UV.x*uDepthLimit+1);\n" + - "pixelYDepth = saturate(pixelYDepth);\n" + - "oColor = float4(pixelYDepth,0,0,0);\n" + - "oColor.a = tex2D(uAlphaTex, iPosition_UV.yz)."+AlphaChannel+";" + - "}\n"; - } - else // Caustics - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition_UV : TEXCOORD0,\n" + - "float2 iUvWorld : TEXCOORD1,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float uDepthLimit,\n" + - "uniform float uCausticsScale,\n" + - "uniform float uCausticsEnd,\n" + - "uniform sampler2D uCaustics : register(s0),\n" + - "uniform sampler2D uAlphaTex : register(s1))\n" + - "{\n" + - "float pixelYDepth = (iPosition_UV.x*uDepthLimit+1);\n" + - "pixelYDepth = saturate(pixelYDepth);\n" + - "oColor = float4(pixelYDepth,0,0,0);\n" + - "oColor.g = saturate(uCausticsEnd-pixelYDepth)*tex2D(uCaustics, iUvWorld/uCausticsScale).r;\n" + - "oColor.a = tex2D(uAlphaTex, iPosition_UV.yz)."+AlphaChannel+";" + - "}\n"; - } - } - break; - - case SM_GLSL: - { - Ogre::String AlphaChannelGLSL = AlphaChannel; - std::replace( AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'r', 'x' ); - std::replace( AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'g', 'y' ); - std::replace( AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'b', 'z' ); - std::replace( AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'a', 'w' ); - // No caustics - if (!cCaustics) - { - FragmentProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uDepthLimit;\n" + - "uniform float uDistLimit;\n" + - "uniform sampler2D uAlphaTex;\n" + - // IN - "variying vec3 Position_UV;\n" + - // OUT - // main function - "void main()\n" + - "{\n" + - "float pixelYDepth = clamp(Position_UV.x*uDepthLimit + 1.0, 0.0, 1.0);\n" + - "gl_FragColor = vec4(pixelYDepth,0.0,0.0,0.0);\n" + - "gl_FragColor.w = texture2D(uAlphaTex, iPosition_UV.yz)."+AlphaChannelGLSL+";" + - "}\n"; - } - else // Caustics - { - FragmentProgramData += Ogre::String( "\n" ) + - // UNIFORMS - "uniform float uDistLimit;\n" + - "uniform float uCausticsScale;\n" + - "uniform float uCausticsEnd;\n" + - "uniform sampler2D uCaustics;\n" + - "uniform sampler2D uAlphaTex;\n" + - // IN - "variying vec3 Position_UV;\n" + - "variying vec2 UVWorld;\n" + - // OUT - // main function - "void main()\n" + - "{\n" + - "float pixelYDepth = clamp(Position_UV.x*uDepthLimit + 1.0, 0.0, 1.0);\n" + - "gl_FragColor = vec4(pixelYDepth,0.0,0.0,0.0);\n" + - "gl_FragColor.y = clamp(uCausticsEnd-pixelYDepth, 0.0, 1.0)*texture2D(uCaustics, UVWorld/uCausticsScale).x;\n" + - "gl_FragColor.w = texture2D(uAlphaTex, iPosition_UV.yz)."+AlphaChannelGLSL+";" + - "}\n"; - } - } - break; - } - - Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; - Ogre::String GpuProgramNames[2] = {_def_DepthTexture_Shader_VP_Name+AlphaChannel, _def_DepthTexture_Shader_FP_Name+AlphaChannel}; - Ogre::String EntryPoints[2]; - if(Options.SM == SM_GLSL) - { - EntryPoints[0] = Ogre::String("main"); - EntryPoints[1] = Ogre::String("main"); - } - else - { - EntryPoints[0] = Ogre::String("main_vp"); - EntryPoints[1] = Ogre::String("main_fp"); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Compositor_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_Underwater_Compositor_Shader_FP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Compositor_Shader_VP_Name); + Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_Underwater_Compositor_Shader_FP_Name); } + } - GpuProgram GpuPrograms[2] = {GPUP_VERTEX, GPUP_FRAGMENT}; - - for (int k = 0; k < 2; k++) - { - if (!createGpuProgram(GpuProgramNames[k], Options.SM, GpuPrograms[k], EntryPoints[k], GpuProgramsData[k])) - { - return false; - } - } - - return true; - } - - bool MaterialManager::_createUnderwaterMaterial(const HydraxComponent &Components, const Options &Options) - { - const bool cDepth = _isComponent(Components, HYDRAX_COMPONENT_DEPTH ); - //const bool cSmooth = _isComponent(Components, HYDRAX_COMPONENT_SMOOTH ); // cSmooth uneeded underwater - const bool cSun = _isComponent(Components, HYDRAX_COMPONENT_SUN ); - //const bool cFoam = _isComponent(Components, HYDRAX_COMPONENT_FOAM ); - const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); - const bool cUReflections = _isComponent(Components, HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS); - - Ogre::String VertexProgramData, FragmentProgramData; - - // Vertex program - - switch (Options.NM) - { - case NM_TEXTURE: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float2 iUv : TEXCOORD0,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float4 oPosition_ : TEXCOORD0,\n" + - "out float2 oUvNoise : TEXCOORD1,\n" + - "out float4 oUvProjection : TEXCOORD2,\n" + - "out float2 oDistance : TEXCOORD3,\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += - "out float4 oWorldPosition : TEXCOORD4,\n"; - } - */ - VertexProgramData += Ogre::String( - // UNIFORM - "uniform float4x4 uWorldViewProj,\n") + - "uniform float4x4 uWorldView,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float3 uCameraPos)\n" + - "{\n" + - "oPosition_ = iPosition;\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += - "oWorldPosition = mul(uWorld, iPosition);\n"; - } - */ - VertexProgramData += Ogre::String( - "oPosition = mul(uWorldViewProj, iPosition);\n") + - // Projective texture coordinates, adjust for mapping - "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5,"+ - "0,-0.5, 0, 0.5,"+ - "0, 0, 0.5, 0.5,"+ - "0, 0, 0, 1);\n" + - "oUvProjection = mul(scalemat, oPosition);\n" + - "oUvNoise = iUv;\n" + - // Distance - "float4 mwPos = mul(uWorldView, iPosition);\n" + - "oDistance.x = abs(mwPos.z);\n" + - "oDistance.y = -mul( uWorld, float4(uCameraPos, 1.0) ).y;\n" + - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n" ); - // UNIFORMS - VertexProgramData += "uniform mat4 uWorld;\n"; - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec4 Position_;\n") + - "varying vec4 UVProjection;\n" + - "varying vec2 Distance_;\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += "varying vec4 WorldPosition;\n"; - } - */ - // main function - VertexProgramData += Ogre::String( - "void main()\n") + - "{\n" + - "Position_ = gl_Vertex;\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; - } - */ - VertexProgramData += Ogre::String( - // Projective texture coordinates, adjust for mapping - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n") + - "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + - " 0.0, -1.0, 0.0, 0.0,\n" + - " 0.0, 0.0, 1.0, 0.0,\n" + - " 0.0, 0.0, 0.0, 1.0);\n" + - "UVProjection = scalemat * gl_Position;\n" + - "gl_TexCoord[0] = gl_MultiTexCoord0;\n" + - // Distance - "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + - "Distance_.x = abs(mwPos.z);\n" + - "Distance_.y = -( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).y;\n" + - "}\n"; - } - break; - } - } - break; - - case NM_VERTEX: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - "float3 iNormal : NORMAL,\n"+ - // OUT - "out float4 oPosition : POSITION,\n" + - "out float4 oPosition_ : TEXCOORD0,\n" + - "out float4 oUvProjection : TEXCOORD1,\n" + - "out float3 oNormal : TEXCOORD2,\n" + - "out float2 oDistance : TEXCOORD3,\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += - "out float4 oWorldPosition : TEXCOORD4,\n"; - } - */ - VertexProgramData += Ogre::String( - // UNIFORM - "uniform float4x4 uWorldViewProj,\n") + - "uniform float4x4 uWorldView,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float3 uCameraPos)\n" + - "{\n" + - "oPosition_ = iPosition;\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; - } - */ - VertexProgramData += Ogre::String( - "oPosition = mul(uWorldViewProj, iPosition);\n") + - // Projective texture coordinates, adjust for mapping - "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5,"+ - "0,-0.5, 0, 0.5,"+ - "0, 0, 0.5, 0.5,"+ - "0, 0, 0, 1);\n" + - "oUvProjection = mul(scalemat, oPosition);\n" + - "oNormal = normalize(iNormal);\n"+ - // Distance - "float4 mwPos = mul(uWorldView, iPosition);\n" + - "oDistance.x = abs(mwPos.z);\n" + - "oDistance.y = -mul( uWorld, float4(uCameraPos, 1.0) ).y;\n" + - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n"); - // UNIFORMS - VertexProgramData += "uniform mat4 uWorld;\n"; - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec4 Position_;\n") + - "varying vec4 UVProjection;\n" + - "varying vec3 Normal;\n" + - "varying vec2 Distance_;\n"; - /* Foam is not visible underwater - if(cFoam) - { - VertexProgramData += "varying vec4 WorldPosition;\n"; - } - */ - // PROGRAM - VertexProgramData += Ogre::String( - "void main()\n") + - "{\n" + - "Position_ = gl_Vertex;\n"; - /* Foam is not visible underwater - if(cFoam) - { - VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; - } - */ - VertexProgramData += Ogre::String( - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n") + - "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + - " 0.0, -1.0, 0.0, 0.0,\n" + - " 0.0, 0.0, 1.0, 0.0,\n" + - " 0.0, 0.0, 0.0, 1.0);\n" + - "UVProjection = scalemat * gl_Position;\n" + - "Normal = normalize(gl_Normal);\n" + - // Distance - "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + - "Distance_.x = abs(mwPos.z);\n" + - "Distance_.y = -( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).y;\n" + - "}\n"; - } - break; - } - } - break; - - case NM_RTT: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float4 oPosition_ : TEXCOORD0,\n" + - "out float4 oUvProjection : TEXCOORD1,\n" + - "out float2 oDistance : TEXCOORD2,\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += - "out float4 oWorldPosition : TEXCOORD3,\n"; - } - */ - VertexProgramData += Ogre::String( - // UNIFORM - "uniform float4x4 uWorldViewProj,\n") + - "uniform float4x4 uWorldView,\n" + - "uniform float4x4 uWorld,\n" + - "uniform float3 uCameraPos)\n" + - "{\n" + - "oPosition_ = iPosition;\n"; - /* Foam is not visible underwater - if (cFoam) - { - VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; - } - */ - VertexProgramData += Ogre::String( - "oPosition = mul(uWorldViewProj, iPosition);\n") + - // Projective texture coordinates, adjust for mapping - "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5,"+ - "0,-0.5, 0, 0.5,"+ - "0, 0, 0.5, 0.5,"+ - "0, 0, 0, 1);\n" + - "oUvProjection = mul(scalemat, oPosition);\n" + - // Distance - "float4 mwPos = mul(uWorldView, iPosition);\n" + - "oDistance.x = abs(mwPos.z);\n" + - "oDistance.y = -mul( uWorld, float4(uCameraPos, 1.0) ).y;\n" + - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n"); - // UNIFORMS - VertexProgramData += "uniform mat4 uWorld;\n"; - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec4 Position_;\n") + - "varying vec4 UVProjection;\n" + - "varying vec2 Distance_;\n"; - /* Foam is not visible underwater - if(cFoam) - { - VertexProgramData += "varying vec4 WorldPosition;\n"; - } - */ - // PROGRAM - VertexProgramData +=Ogre::String( - "void main()\n") + - "{\n" + - "Position_ = gl_Vertex;\n"; - /* Foam is not visible underwater - if(cFoam) - { - VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; - } - */ - VertexProgramData += Ogre::String( - "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n") + - "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + - " 0.0, -1.0, 0.0, 0.0,\n" + - " 0.0, 0.0, 1.0, 0.0,\n" + - " 0.0, 0.0, 0.0, 1.0);\n" + - "UVProjection = scalemat * gl_Position;\n" + - // Distance - "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + - "Distance_.x = abs(mwPos.z);\n" + - "Distance_.y = -( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).y;\n" + - "}\n"; - } - break; - } - } - break; - } - - // Fragment program - - switch (Options.NM) - { - case NM_TEXTURE: case NM_VERTEX: case NM_RTT: - { - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - FragmentProgramData += - Ogre::String("float3 expand(float3 v)\n") + - "{\n" + - "return (v - 0.5) * 2;\n" + - "}\n\n" + - - "void main_fp(" + - // IN - "float4 iPosition : TEXCOORD0,\n"; - int TEXCOORDNUM = 1; - if (Options.NM == NM_TEXTURE) - { - FragmentProgramData += - "float2 iUvNoise : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - } - FragmentProgramData += - "float4 iUvProjection : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "float3 iNormal : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - } - FragmentProgramData += - "float2 iDistance : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - TEXCOORDNUM++; - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += - "float4 iWorldPosition : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; - } - */ - - FragmentProgramData += Ogre::String( - // OUT - "out float4 oColor : COLOR,\n") + - // UNIFORM - "uniform float3 uEyePosition,\n" + - "uniform float uFullReflectionDistance,\n" + - "uniform float uGlobalTransparency,\n" + - "uniform float uNormalDistortion,\n" + - "uniform float uDistLimit,\n" + - "uniform float3 uWaterColor,\n"; - if (cSun) - { - FragmentProgramData += Ogre::String( - "uniform float3 uSunPosition,\n") + - "uniform float uSunStrength,\n" + - "uniform float uSunArea,\n" + - "uniform float3 uSunColor,\n" + - "uniform float uDepthLimit,\n"; - } - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += Ogre::String( - "uniform float uFoamRange,\n") + - "uniform float uFoamMaxDistance,\n" + - "uniform float uFoamScale,\n" + - "uniform float uFoamStart,\n" + - "uniform float uFoamTransparency,\n"; - } - */ - if (cCaustics && cUReflections) - { - FragmentProgramData += - "uniform float uCausticsPower,\n"; - } - - int TexNum = 0; - - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "uniform sampler2D uNormalMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; - TexNum++; - } - if (cUReflections) - { - FragmentProgramData += - "uniform sampler2D uReflectionMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; - TexNum++; - } - - FragmentProgramData += - "uniform sampler2D uRefractionMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; - TexNum++; - - if (cDepth && cUReflections) - { - FragmentProgramData += - "uniform sampler2D uDepthReflectionMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; - TexNum++; - } - - FragmentProgramData += - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "uniform sampler1D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; - #else - "uniform sampler2D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; - #endif - TexNum++; - - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += Ogre::String( - ",\nuniform sampler2D uFoamMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")\n"); - } - */ - FragmentProgramData += Ogre::String( - ")\n") + - "{\n" + - "float2 ProjectionCoord = iUvProjection.xy / iUvProjection.w;\n" + - "float3 camToSurface = iPosition.xyz - uEyePosition;\n" + - "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; - - /* Foam is not visible underwater - if (cFoam) - { - // Calculate the foam visibility as a function fo distance specified by user - FragmentProgramData += - "float foamVisibility=1.0f-saturate(additionalReflection/uFoamMaxDistance);\n"; - } - */ - - FragmentProgramData += Ogre::String( - "additionalReflection/=uFullReflectionDistance;\n") + - "camToSurface=normalize(-camToSurface);\n"; - if (Options.NM == NM_TEXTURE) - { - FragmentProgramData += Ogre::String( - "float3 pixelNormal = tex2D(uNormalMap,iUvNoise).xyz;\n") + - // Inverte y with z, because at creation our local normal to the plane was z - "pixelNormal.yz=pixelNormal.zy;\n" + - // Remap from [0,1] to [-1,1] - "pixelNormal.xyz=-expand(pixelNormal.xyz);\n"; - } - else if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "float3 pixelNormal = -iNormal;\n"; - } - else // NM_RTT - { - FragmentProgramData += - "float3 pixelNormal = -(2.0*tex2D(uNormalMap, ProjectionCoord.xy).xyz - 1.0);\n"; - } - FragmentProgramData += - "float2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; - - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "float dotProduct=dot(camToSurface,pixelNormal);\n"; - } - else - { - FragmentProgramData += - "float dotProduct=dot(-camToSurface,pixelNormal);\n"; - } - FragmentProgramData += Ogre::String( - "dotProduct=saturate(dotProduct);\n") + - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "float fresnel = tex1D(uFresnelMap,dotProduct);\n" + - #else - "float fresnel = tex2D(uFresnelMap,float2(dotProduct,dotProduct));\n" + - #endif - // Add additional reflection and saturate - "fresnel+=additionalReflection;\n" + - "fresnel=saturate(fresnel);\n" + - // Decrease the transparency and saturate - "fresnel-=uGlobalTransparency;\n" + - "fresnel=saturate(fresnel);\n" + - "float3 reflection;\n" + - #if OGRE_PLATFORM != OGRE_PLATFORM_WIN32 - // Reversing projection if underwater - "if(uEyePosition.y < 0.0)\n" + - "{\n" + - "ProjectionCoord.y = 1.0 - ProjectionCoord.y;\n" + - "}\n" + - #endif - // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal - "float3 refraction=tex2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified).xyz;\n"; - if (cUReflections) - { - FragmentProgramData += - "reflection=tex2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified).xyz;\n"; - } - else - { - FragmentProgramData += - "reflection=uWaterColor;\n"; - } - - if (cDepth && cUReflections) - { - if (cCaustics) - { - FragmentProgramData += Ogre::String( - "float2 depth = tex2D(uDepthReflectionMap,ProjectionCoord.xy+pixelNormalModified).rg;\n") + - "reflection *= 1+depth.y*uCausticsPower;\n" + - "reflection = lerp(uWaterColor,reflection,depth.x);\n"; - } - else - { - FragmentProgramData += Ogre::String( - "float depth = tex2D(uDepthReflectionMap,ProjectionCoord.xy-pixelNormalModified).r;\n") + - "reflection = lerp(uWaterColor,reflection,depth);\n"; - } - } - FragmentProgramData += Ogre::String( - "float4 Color = float4(lerp(refraction,reflection,fresnel),1);\n" ) + - "float Distance = saturate(1.0 - iDistance.x*uDistLimit);\n" + - "Color.xyz = lerp(uWaterColor, Color.xyz, Distance);\n" + - "Color.xyz = lerp(Color.xyz, uWaterColor, uGlobalTransparency);\n"; - - if (cSun) - { - FragmentProgramData += Ogre::String( - "float3 refractedVector = normalize(reflect(camToSurface, pixelNormal.xyz));\n") + - "float3 surfaceToSun=normalize(uSunPosition-iPosition.xyz);\n" + - // Temporally solution, fix this - "surfaceToSun.xz = -surfaceToSun.xz;" + - "float3 sunlight = uSunStrength*pow(saturate(dot(refractedVector,surfaceToSun)),uSunArea)*uSunColor;\n" + - "Distance = saturate(1.0 - iDistance.y*uDepthLimit);\n" + - "Color.xyz+=Distance*sunlight*saturate(1.0-additionalReflection);\n"; - } - - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += Ogre::String( - "float hmap = iPosition.y/uFoamRange*foamVisibility;\n") + - "float2 foamTex=iWorldPosition.xz*uFoamScale+pixelNormalModified;\n" + - "float foam=tex2D(uFoamMap,foamTex).r;\n" + - "float foamTransparency=saturate(hmap-uFoamStart)*uFoamTransparency;\n" + - "Color.xyz=lerp(Color.xyz,1,foamTransparency*foam);\n"; - } - */ - FragmentProgramData += Ogre::String( - "oColor = Color;\n") + - "}\n"; - } - break; - - case SM_GLSL: - FragmentProgramData += Ogre::String("\n") + - // UNIFORMS - "uniform vec3 uEyePosition;\n" + - "uniform float uFullReflectionDistance;\n" + - "uniform float uGlobalTransparency;\n" + - "uniform float uNormalDistortion;\n" + - "uniform float uDistLimit;\n" + - "uniform vec3 uWaterColor;\n"; - - if (cSun) - { - FragmentProgramData += Ogre::String( - "uniform vec3 uSunPosition;\n") + - "uniform float uSunStrength;\n" + - "uniform float uSunArea;\n" + - "uniform vec3 uSunColor;\n" + - "uniform float uDepthLimit;\n"; - } - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += Ogre::String( - "uniform float uFoamRange;\n") + - "uniform float uFoamMaxDistance;\n" + - "uniform float uFoamScale;\n" + - "uniform float uFoamStart;\n" + - "uniform float uFoamTransparency;\n"; - } - */ - if (cCaustics && cUReflections) - { - FragmentProgramData += - "uniform float uCausticsPower;\n"; - } - - int TexNum = 0; - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "uniform sampler2D uNormalMap;\n"; - TexNum++; - } - - if (cUReflections) - { - FragmentProgramData += Ogre::String( - "uniform sampler2D uReflectionMap;\n"); - TexNum++; - } - FragmentProgramData += Ogre::String( - "uniform sampler2D uRefractionMap;\n"); - TexNum++; - - if (cDepth && cUReflections) - { - FragmentProgramData += - "uniform sampler2D uDepthReflectionMap;\n"; - TexNum++; - } - - FragmentProgramData += - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "uniform sampler1D uFresnelMap;\n"; - #else - "uniform sampler2D uFresnelMap;\n"; - #endif - TexNum++; - - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += - "uniform sampler2D uFoamMap;\n"; - } - */ - // IN - FragmentProgramData += - "varying vec4 Position_;\n"; - int TEXCOORDNUM = 1; - if (Options.NM == NM_TEXTURE) - { - TEXCOORDNUM++; - } - FragmentProgramData += - "varying vec4 UVProjection;\n"; - TEXCOORDNUM++; - if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "varying vec3 Normal;\n"; - TEXCOORDNUM++; - } - /* Foam is not visible underwater - if (cFoam) - { - FragmentProgramData += - "varying vec4 WorldPosition;\n"; - } - */ - FragmentProgramData += - "varying vec2 Distance_;\n"; - // Expand function - FragmentProgramData += Ogre::String( - "vec3 expand(vec3 v)\n") + - "{\n" + - "return (v - 0.5) * 2.0;\n" + - "}\n\n" + - // main function - "void main()\n" + - "{\n" + - "vec2 ProjectionCoord = UVProjection.xy / UVProjection.w;\n" + - "ProjectionCoord += 1.0;\n" + - "ProjectionCoord *= 0.5;\n" + - "vec3 camToSurface = Position_.xyz - uEyePosition;\n" + - "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; - /* Must not view foam underwater - if (cFoam) - { - // Calculate the foam visibility as a function fo distance specified by user - FragmentProgramData += - "float foamVisibility=1.0-clamp(additionalReflection/uFoamMaxDistance, 0.0, 1.0);\n"; - } - */ - FragmentProgramData += Ogre::String( - "additionalReflection/=uFullReflectionDistance;\n") + - "camToSurface=normalize(-camToSurface);\n"; - if (Options.NM == NM_TEXTURE) - { - FragmentProgramData += Ogre::String( - "vec3 pixelNormal = texture2D(uNormalMap,gl_TexCoord[0].xy).xyz;\n") + - // Inverte y with z, because at creation our local normal to the plane was z - "pixelNormal.yz=pixelNormal.zy;\n" + - // Remap from [0,1] to [-1,1] - "pixelNormal.xyz=-expand(pixelNormal.xyz);\n"; - } - else if (Options.NM == NM_VERTEX) - { - FragmentProgramData += - "vec3 pixelNormal = -Normal;\n"; - } - else // NM_RTT - { - FragmentProgramData += - "vec3 pixelNormal = -2.0*texture2D(uNormalMap, ProjectionCoord.xy).xyz - 1.0;\n"; - } - FragmentProgramData += - "vec2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - FragmentProgramData += - "float dotProduct=dot(camToSurface,pixelNormal);\n"; - } - else - { - FragmentProgramData += - "float dotProduct=dot(-camToSurface,pixelNormal);\n"; - } - FragmentProgramData += Ogre::String( - "dotProduct=clamp(dotProduct, 0.0, 1.0);\n") + - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - "float fresnel = texture1D(uFresnelMap,dotProduct).x;\n" + - #else - "float fresnel = texture2D(uFresnelMap,vec2(dotProduct,dotProduct)).x;\n" + - #endif - // Add additional reflection and saturate - "fresnel +=additionalReflection;\n" + - "fresnel = clamp(fresnel, 0.0, 1.0);\n" + - // Decrease the transparency and saturate - "fresnel -= uGlobalTransparency;\n" + - "fresnel = clamp(fresnel, 0.0, 1.0);\n" + - // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal - "vec3 reflection;\n" + - #if OGRE_PLATFORM != OGRE_PLATFORM_WIN32 - // Reversing projection if underwater - "if(uEyePosition.y < 0.0)\n" + - "{\n" + - "ProjectionCoord.y = 1.0 - ProjectionCoord.y;\n" + - "}\n" + - #endif - "vec3 refraction=texture2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified).xyz;\n"; - if (cUReflections) - { - FragmentProgramData += - "reflection=texture2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified).xyz;\n"; - } - else - { - FragmentProgramData += - "reflection=uWaterColor;\n"; - } - if (cDepth && cUReflections) - { - if (cCaustics) - { - FragmentProgramData += Ogre::String( - "vec2 depth = texture2D(uDepthReflectionMap,ProjectionCoord.xy+pixelNormalModified).xy;\n") + - "reflection *= 1.0 + depth.y*uCausticsPower;\n" + - "reflection = mix(uWaterColor,reflection,depth.x);\n"; - } - else - { - FragmentProgramData += Ogre::String( - "float depth = texture2D(uDepthReflectionMap,ProjectionCoord.xy+pixelNormalModified).x;\n") + - "reflection = mix(uWaterColor,reflection,depth);\n"; - } - } - FragmentProgramData += Ogre::String( - "gl_FragColor = vec4(mix(refraction,reflection,fresnel),1.0);\n") + - "float Distance = clamp(1.0 - Distance_.x*uDistLimit, 0.0, 1.0);\n" + - "gl_FragColor.xyz = mix(uWaterColor, gl_FragColor.xyz, Distance);\n" + - "gl_FragColor.xyz = mix(gl_FragColor.xyz, uWaterColor, uGlobalTransparency);\n"; - if (cSun) - { - FragmentProgramData += Ogre::String( - "vec3 refractedVector = normalize(reflect(-camToSurface,pixelNormal.xyz));\n") + - "vec3 surfaceToSun=normalize(uSunPosition-Position_.xyz);\n" + - // Temporally solution, fix this - "surfaceToSun.xz = -surfaceToSun.xz;" + - "vec3 sunlight = uSunStrength*pow(clamp(dot(refractedVector,surfaceToSun),0.0,1.0),uSunArea)*uSunColor;\n" + - "Distance = clamp(1.0 - Distance_.y*uDepthLimit, 0.0, 1.0);\n"; - "gl_FragColor.xyz+=Distance*sunlight*clamp(1.0 - additionalReflection, 0.0, 1.0);\n"; - } - /* Must not view foam underwater - if (cFoam) - { - FragmentProgramData += Ogre::String( - "float hmap = Position_.y/uFoamRange*foamVisibility;\n") + - "vec2 foamTex=WorldPosition.xz*uFoamScale+pixelNormalModified;\n" + - "float foam=texture2D(uFoamMap,foamTex).x;\n" + - "float foamTransparency=clamp(hmap-uFoamStart, 0.0, 1.0)*uFoamTransparency;\n" + - "gl_FragColor.xyz=mix(gl_FragColor.xyz,vec3(1.0,1.0,1.0),foamTransparency*foam);\n"; - } - */ - FragmentProgramData += - "}\n"; - break; - } - } - break; - } - - // Second: build our material - Ogre::MaterialPtr &UnderwaterMaterial = getMaterial(MAT_UNDERWATER); - UnderwaterMaterial = Ogre::MaterialManager::getSingleton(). - create(_def_Underwater_Material_Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::Pass *UM_Technique0_Pass0 = UnderwaterMaterial->getTechnique(0)->getPass(0); - - UM_Technique0_Pass0->setDepthWriteEnabled(true); - UM_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + bool MaterialManager::createMaterials(const HydraxComponent &Components, const Options &Options) + { + removeMaterials(); - Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; - Ogre::String GpuProgramNames[2] = {_def_Underwater_Shader_VP_Name, _def_Underwater_Shader_FP_Name}; - Ogre::String EntryPoints[2]; - if(Options.SM == SM_GLSL) + HydraxLOG("Creating water material..."); + if (!_createWaterMaterial(Components, Options)) { return false; } + mHydrax->getDecalsManager()->registerAll(); + HydraxLOG("Water material created."); + + if (_isComponent(Components, HYDRAX_COMPONENT_DEPTH)) { - EntryPoints[0] = Ogre::String("main"); - EntryPoints[1] = Ogre::String("main"); + HydraxLOG("Creating depth material..."); + if (!_createDepthMaterial(Components, Options)) { return false; } + HydraxLOG("Depth material created."); } - else + + if (_isComponent(Components, HYDRAX_COMPONENT_UNDERWATER)) { - EntryPoints[0] = Ogre::String("main_vp"); - EntryPoints[1] = Ogre::String("main_fp"); + HydraxLOG("Creating underwater material..."); + if (!_createUnderwaterMaterial(Components, Options)) { return false; } + if (!_createUnderwaterCompositor(Components, Options)) { return false; } + if (!_createSimpleColorMaterial(Ogre::ColourValue::Red, MAT_SIMPLE_RED, _def_Simple_Red_Material_Name, false)) + { return false; } + HydraxLOG("Underwater material created."); } - fillGpuProgramsToPass(UM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); - - Ogre::GpuProgramParametersSharedPtr VP_Parameters = UM_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = UM_Technique0_Pass0->getFragmentProgramParameters(); + mComponents = Components; + mOptions = Options; + mCreated = true; - if(Options.SM != SM_GLSL) - { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + std::vector::iterator TechIt; - FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); - FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); - FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); - FP_Parameters->setNamedConstant("uDistLimit", 1.f/mHydrax->getDistLimit()); - if (cSun) + for (TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) { - } - FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); - - if (cSun) - { - FP_Parameters->setNamedConstant("uSunPosition", mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); - FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); - FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); - FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); - FP_Parameters->setNamedConstant("uDepthLimit", 1.f/mHydrax->getDepthLimit()); - } - /* Foam is not visible underwater - if (cFoam) - { - FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); - FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); - FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); - FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); - FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); - } - */ - if (cCaustics && cDepth && cUReflections) - { - FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); - } - - int GLSLTextUnit = 0; - - if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) - { - if(Options.SM == SM_GLSL) + if (!(*TechIt)) { - FP_Parameters->setNamedConstant("uNormalMap", GLSLTextUnit); - GLSLTextUnit++; + mDepthTechniques.erase(TechIt); + // TechIt-- ? + continue; } - UM_Technique0_Pass0->createTextureUnitState("HydraxNormalMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - } - if (cUReflections) - { - if(Options.SM == SM_GLSL) + bool isTextureDepthTechnique = ((*TechIt)->getName() == "_Hydrax_Depth_Technique") ? false : true; + + if (isTextureDepthTechnique) { - FP_Parameters->setNamedConstant("uReflectionMap", GLSLTextUnit); - GLSLTextUnit++; - } - UM_Technique0_Pass0->createTextureUnitState("HydraxReflectionMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - } - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uRefractionMap", GLSLTextUnit); - GLSLTextUnit++; - } - UM_Technique0_Pass0->createTextureUnitState("HydraxRefractionMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + Ogre::String DepthTextureName = + ((*TechIt)->getPass(0)->getTextureUnitState(0)->getName() == "_DetphTexture_Hydrax") + ? (*TechIt)->getPass(0)->getTextureUnitState(0)->getTextureName() + : (*TechIt)->getPass(0)->getTextureUnitState(1)->getTextureName(); - if (cDepth && cUReflections) - { - if(Options.SM == SM_GLSL) + // Alpha channel will be stored in pass 0 name + addDepthTextureTechnique((*TechIt), DepthTextureName, (*TechIt)->getPass(0)->getName(), false); + } + else { - FP_Parameters->setNamedConstant("uDepthReflectionMap", GLSLTextUnit); - GLSLTextUnit++; + addDepthTechnique((*TechIt), false); } - UM_Technique0_Pass0->createTextureUnitState()->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - } - - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uFresnelMap", GLSLTextUnit); - GLSLTextUnit++; } - UM_Technique0_Pass0->createTextureUnitState("Fresnel.bmp")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - /* Foam is not visible underwater - if (cFoam) - { - if(Options.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uFoamMap", GLSLTextUnit); - GLSLTextUnit++; - } - UM_Technique0_Pass0->createTextureUnitState("Foam.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - } - */ + return true; + } - UnderwaterMaterial->setReceiveShadows(false); - UnderwaterMaterial->load(); - - return true; - } - - bool MaterialManager::_createUnderwaterCompositor(const HydraxComponent &Components, const Options &Options) - { - const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); - const bool cDepth = _isComponent(Components, HYDRAX_COMPONENT_DEPTH); - const bool cGodRays = _isComponent(Components, HYDRAX_COMPONENT_UNDERWATER_GODRAYS); - - Ogre::String VertexProgramData, FragmentProgramData; - - // Vertex program - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float3 oPosition_ : TEXCOORD0,\n" + - "out float2 oUV : TEXCOORD1,\n"; - // UNIFORM - if (cGodRays) - { - VertexProgramData += - Ogre::String( - "uniform float3 uCorner0,\n") + - "uniform float3 uCorner01,\n" + - "uniform float3 uCorner02,\n"; - } - VertexProgramData += - Ogre::String( - "uniform float4x4 uWorldViewProj)\n") + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n"+ - "iPosition.xy = sign(iPosition.xy);\n"+ - "oUV = (float2(iPosition.x, -iPosition.y) + 1.0f) * 0.5f;"; - if (cGodRays) - { - VertexProgramData += Ogre::String( - "uCorner01 *= oUV.x;\n")+ - "uCorner02 *= oUV.y;\n"+ - "oPosition_ = uCorner0+uCorner01+uCorner02;"; - } - VertexProgramData += - "}\n"; - } - break; - - case SM_GLSL: - { - VertexProgramData += Ogre::String( "\n" ); - // UNIFORMS - if (cGodRays) - { - VertexProgramData += Ogre::String( - "uniform vec3 uCorner0;\n") + - "uniform vec3 uCorner01;\n" + - "uniform vec3 uCorner02;\n"; - } - // IN - // OUT - VertexProgramData += Ogre::String( - "varying vec3 Position_;\n") + - "varying vec2 UV;\n" + - // main function - "void main()\n" + - "{\n" + - "gl_Position = ftransform();\n" + - "vec2 iPosition = sign(gl_Vertex.xy);\n"+ - "UV = (vec2(iPosition.x, -iPosition.y) + 1.0) * 0.5;\n"; - if (cGodRays) - { - VertexProgramData += Ogre::String( - "vec3 vCorner01 = uCorner01 * UV.x;\n")+ - "vec3 vCorner02 = uCorner02 * UV.y;\n"+ - "Position_ = uCorner0+vCorner01+vCorner02;\n"; - } - VertexProgramData += - "}\n"; - } - break; - } - - // Fragment program - switch (Options.SM) - { - case SM_HLSL: case SM_CG: - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition : TEXCOORD0,\n" + - "float2 iUV : TEXCOORD1,\n" + - // OUT - "out float4 oColor : COLOR,\n"; - // UNIFORM - if (cCaustics) - { - FragmentProgramData += - "uniform float uCausticsPower,\n"; - } - if (cGodRays) - { - FragmentProgramData += Ogre::String( - "uniform float3 uSunColor,\n") + - "uniform float3 uLightDirection,\n"+ - "uniform float uIntensity,\n"+ - "uniform float3 uHGg,\n"+ - "uniform float3 uCameraPos,\n"; - } - FragmentProgramData += Ogre::String( - "uniform float uTime,\n") + - "uniform float3 uWaterColor,\n" + - "uniform sampler2D uOriginalMap : register(s0),\n" + - "uniform sampler2D uDistortMap : register(s1)\n"; - if (cDepth) - { - FragmentProgramData += - ",\nuniform sampler2D uDepthMap : register(s2)"; - } - FragmentProgramData += Ogre::String( - ")\n" ) + - "{\n" + - "float2 distortUV = (tex2D(uDistortMap, float2(iUV.x + uTime, iUV.y + uTime)).xy - 0.5)/50.0;\n"; - if (cCaustics) // Depth, caustics - { - FragmentProgramData += Ogre::String( - "float2 depth = tex2D(uDepthMap, iUV+distortUV).xy;\n") + - "float4 Color = float4(lerp(uWaterColor,tex2D(uOriginalMap, iUV+distortUV)*(1.0+depth.y*uCausticsPower), depth.x),1.0);\n"; - if (cGodRays) - { - FragmentProgramData += Ogre::String( - "float3 view_vector = normalize(iPosition-uCameraPos);\n") + - "float dot_product = dot(view_vector, -uLightDirection);\n"+ - "float num = uHGg.x;\n"+ - "float den = (uHGg.y - uHGg.z*dot_product);\n"+ - "den = rsqrt(den);\n"+ - "float phase = num * (den*den*den);\n" + - "Color.xyz += (0.15 + uIntensity*tex2D(uDepthMap, iUV).z)*phase*uSunColor;\n"; - } - } - else if (cDepth) // Depth, no caustics - { - FragmentProgramData += - "float4 Color = float4(lerp(uWaterColor,tex2D(uOriginalMap, iUV+distortUV).xyz,tex2D(uDepthMap, iUV+distortUV).r),1.0);\n"; - if (cGodRays) - { - FragmentProgramData += Ogre::String( - "float3 view_vector = normalize(iPosition-uCameraPos);") + - "float dot_product = dot(view_vector, -uLightDirection);"+ - "float num = uHGg.x;"+ - "float den = (uHGg.y - uHGg.z*dot_product); "+ - "den = rsqrt(den); "+ - "float phase = num * (den*den*den);"+ - "Color.xyz += (0.15 + uIntensity*tex2D(uDepthMap, iUV).y)*phase*uSunColor;"; - } - } - else // No depth, no caustics - { - FragmentProgramData += - "float4 Color = tex2D(uOriginalMap, iUV+distortUV);"; - } - FragmentProgramData += Ogre::String( - "oColor = Color;\n") + - "}\n"; - } - break; - - case SM_GLSL: - { - FragmentProgramData += Ogre::String( "\n" ); - // UNIFORM - if (cCaustics) - { - FragmentProgramData += - "uniform float uCausticsPower;\n"; - } - if (cGodRays) - { - FragmentProgramData += Ogre::String( - "uniform vec3 uSunColor;\n") + - "uniform vec3 uLightDirection;\n"+ - "uniform float uIntensity;\n"+ - "uniform vec3 uHGg;\n"+ - "uniform vec3 uCameraPos;\n"; - } - FragmentProgramData += Ogre::String( - "uniform float uTime;\n") + - "uniform float uGlobalTransparency;\n" + - "uniform vec3 uWaterColor;\n" + - "uniform sampler2D uOriginalMap;\n" + - "uniform sampler2D uDistortMap;\n"; - if (cDepth) - { - FragmentProgramData += - "uniform sampler2D uDepthMap;\n"; - } - // IN - FragmentProgramData += Ogre::String( - "varying vec3 Position_;\n") + - "varying vec2 UV;\n" + - // OUT - // main function - "void main()\n" + - "{\n" + - "vec2 distortUV = (texture2D(uDistortMap, vec2(UV.x + uTime, UV.y + uTime)).xy - 0.5)*0.02;\n"; - // "vec2 distortUV = vec2(0.0,0.0);\n"; - if (cCaustics) // Depth, caustics - { - FragmentProgramData += Ogre::String( - "vec2 depth = texture2D(uDepthMap, UV+distortUV).xy;\n") + - "gl_FragColor = vec4(mix(uWaterColor,texture2D(uOriginalMap, UV+distortUV).xyz*(1.0+depth.y*uCausticsPower), depth.x),1.0);\n"; - if (cGodRays) - { - FragmentProgramData += Ogre::String( - "vec3 view_vector = normalize(Position_-uCameraPos);\n") + - "float dot_product = dot(view_vector, -uLightDirection);\n"+ - "float num = uHGg.x;\n"+ - "float den = (uHGg.y - uHGg.z*dot_product);\n"+ - "den = inversesqrt(den);\n"+ - "float phase = num * pow(den, 3.0);\n"+ - "gl_FragColor.xyz += (0.15 + uIntensity*texture2D(uDepthMap, UV).z)*phase*uSunColor;"; - } - } - else if (cDepth) // Depth, no caustics - { - FragmentProgramData += - "gl_FragColor = vec4(mix(uWaterColor,texture2D(uOriginalMap, UV+distortUV).xyz,texture2D(uDepthMap, UV+distortUV).r),1.0);\n"; - if (cGodRays) - { - FragmentProgramData += Ogre::String( - "vec3 view_vector = normalize(Position_-uCameraPos);\n") + - "float dot_product = dot(view_vector, -uLightDirection);\n"+ - "float num = uHGg.x;\n"+ - "float den = (uHGg.y - uHGg.z*dot_product);\n"+ - "den = inversesqrt(den);\n"+ - "float phase = num * pow(den, 3.0);\n"+ - "gl_FragColor.xyz += (0.15 + uIntensity*texture2D(uDepthMap, UV).z)*phase*uSunColor;\n"; - } - } - else // No depth, no caustics - { - FragmentProgramData += - "gl_FragColor = texture2D(uOriginalMap, UV+distortUV);\n"; - } - FragmentProgramData += - "}\n"; - } - break; - } - - // Build our material - Ogre::MaterialPtr &UnderwaterCompositorMaterial = getMaterial(MAT_UNDERWATER_COMPOSITOR); - UnderwaterCompositorMaterial = Ogre::MaterialManager::getSingleton(). - create(_def_Underwater_Compositor_Material_Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::Pass *DM_Technique0_Pass0 = UnderwaterCompositorMaterial->getTechnique(0)->getPass(0); - - DM_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); - DM_Technique0_Pass0->setDepthFunction(Ogre::CMPF_ALWAYS_PASS); - - Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; - Ogre::String GpuProgramNames[2] = {_def_Underwater_Compositor_Shader_VP_Name, _def_Underwater_Compositor_Shader_FP_Name}; - Ogre::String EntryPoints[2]; - if(Options.SM == SM_GLSL) - { - EntryPoints[0] = Ogre::String("main"); - EntryPoints[1] = Ogre::String("main"); - } - else + bool MaterialManager::fillGpuProgramsToPass(Ogre::Pass *Pass, const Ogre::String GpuProgramNames[2], const ShaderMode &SM, + const Ogre::String EntryPoints[2], const Ogre::String Data[2]) + { + GpuProgram GpuPrograms[2] = {GPUP_VERTEX, GPUP_FRAGMENT}; + + for (int k = 0; k < 2; k++) { - EntryPoints[0] = Ogre::String("main_vp"); - EntryPoints[1] = Ogre::String("main_fp"); + if (!createGpuProgram(GpuProgramNames[k], SM, GpuPrograms[k], EntryPoints[k], Data[k])) { return false; } } - fillGpuProgramsToPass(DM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + Pass->setVertexProgram(GpuProgramNames[0]); + Pass->setFragmentProgram(GpuProgramNames[1]); - Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique0_Pass0->getFragmentProgramParameters(); + return true; + } - if(Options.SM != SM_GLSL) + bool MaterialManager::createGpuProgram(const Ogre::String &Name, const ShaderMode &SM, const GpuProgram &GPUP, + const Ogre::String &EntryPoint, const Ogre::String &Data) + { + if (Ogre::HighLevelGpuProgramManager::getSingleton().resourceExists(Name)) { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + HydraxLOG("Error in bool MaterialManager::createGpuProgram(): " + Name + " exists."); + return false; } - FP_Parameters->setNamedConstantFromTime("uTime", 0.1f); - FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); + Ogre::String ShaderModesStr[3] = {"hlsl", "cg", "glsl"}; + Ogre::String Profiles[2]; - if (cCaustics) - { - FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); - } - - if (cGodRays) - { - FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); - FP_Parameters->setNamedConstant("uLightDirection", - (mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getCamera()->getPosition()) - - mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())) - .normalisedCopy()); - FP_Parameters->setNamedConstant("uIntensity", mHydrax->getGodRaysIntensity()); - FP_Parameters->setNamedConstant("uHGg", mHydrax->getGodRaysExposure()); - FP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); - } - - // From compositor, original scene - int GLSLTextUnit = 0; - if(Options.SM == SM_GLSL) + switch (SM) { - FP_Parameters->setNamedConstant("uOriginalMap", GLSLTextUnit); - GLSLTextUnit++; + case SM_HLSL: + { + Profiles[0] = "target"; + + if (GPUP == GPUP_VERTEX) { Profiles[1] = "vs_1_1"; } + else + { + Profiles[1] = "ps_2_0"; + } } - DM_Technique0_Pass0->createTextureUnitState()->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - if(Options.SM == SM_GLSL) + break; + + case SM_CG: { - FP_Parameters->setNamedConstant("uDistortMap", GLSLTextUnit); - GLSLTextUnit++; + Profiles[0] = "profiles"; + + if (GPUP == GPUP_VERTEX) { Profiles[1] = "vs_1_1 arbvp1"; } + else + { + Profiles[1] = "ps_2_0 arbfp1 fp20"; + } } - DM_Technique0_Pass0->createTextureUnitState("UnderwaterDistortion.jpg")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - if (cDepth) - { - if(Options.SM == SM_GLSL) + break; + + case SM_GLSL: + { + Profiles[0] = ""; // Dont needed + if (GPUP == GPUP_VERTEX) { - FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit); - GLSLTextUnit++; + Profiles[1] = ""; // Dont needed + } + else + { + Profiles[1] = ""; // Dont needed } - DM_Technique0_Pass0->createTextureUnitState("HydraxDepthMap")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - //Ogre::Viewport *Viewport = mHydrax->getCamera()->getViewport(); - } + } + break; + } - UnderwaterCompositorMaterial->setReceiveShadows(false); - UnderwaterCompositorMaterial->load(); + Ogre::GpuProgramType GpuPType; - Ogre::CompositorPtr &UnderwaterCompositor = getCompositor(COMP_UNDERWATER); - UnderwaterCompositor = Ogre::CompositorManager::getSingleton(). - create(_def_Underwater_Compositor_Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + if (GPUP == GPUP_VERTEX) { GpuPType = Ogre::GPT_VERTEX_PROGRAM; } + else + { + GpuPType = Ogre::GPT_FRAGMENT_PROGRAM; + } - Ogre::CompositionTechnique* UnderWaterComp_Technique = UnderwaterCompositor->createTechnique(); + Ogre::HighLevelGpuProgramPtr HLGpuProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( + Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, ShaderModesStr[SM], GpuPType); - // Create the texture definition to render the original scene - Ogre::CompositionTechnique::TextureDefinition* TDef = UnderWaterComp_Technique->createTextureDefinition("OriginalScene"); - TDef->width = 0; - TDef->height = 0; - Ogre::PixelFormatList l; - l.push_back(Ogre::PF_A8R8G8B8); - TDef->formatList = l; + HLGpuProgram->setSource(Data); + HLGpuProgram->setParameter("entry_point", EntryPoint); + HLGpuProgram->setParameter(Profiles[0], Profiles[1]); + HLGpuProgram->load(); - // Render the original scene - Ogre::CompositionTargetPass* CTPass = UnderWaterComp_Technique->createTargetPass(); - CTPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE); - CTPass->setOutputName("OriginalScene"); - Ogre::CompositionPass* CPassClear = CTPass->createPass(); - CPassClear->setType(Ogre::CompositionPass::PT_CLEAR); + return true; + } - const Ogre::Vector3& WC = mHydrax->getWaterColor(); - CPassClear->setClearColour(Ogre::ColourValue(WC.x, WC.y, WC.z)); + bool MaterialManager::_createWaterMaterial(const HydraxComponent &Components, const Options &Options) + { + const bool cDepth = _isComponent(Components, HYDRAX_COMPONENT_DEPTH); + const bool cSmooth = _isComponent(Components, HYDRAX_COMPONENT_SMOOTH); + const bool cSun = _isComponent(Components, HYDRAX_COMPONENT_SUN); + const bool cFoam = _isComponent(Components, HYDRAX_COMPONENT_FOAM); + const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); - Ogre::CompositionPass* CPass = CTPass->createPass(); - CPass->setType(Ogre::CompositionPass::PT_RENDERSCENE); - CPass->setFirstRenderQueue(Ogre::RENDER_QUEUE_SKIES_EARLY+1); + Ogre::String VertexProgramData, FragmentProgramData; - // Build the output target pass - Ogre::CompositionTargetPass* CTOutputPass = UnderWaterComp_Technique->getOutputTargetPass(); - CTOutputPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE); + // Vertex program - // Final composition pass - Ogre::CompositionPass* COutputPass = CTOutputPass->createPass(); - COutputPass->setType(Ogre::CompositionPass::PT_RENDERQUAD); - COutputPass->setMaterial(getMaterial(MAT_UNDERWATER_COMPOSITOR)); - COutputPass->setInput(0, "OriginalScene"); - COutputPass->setLastRenderQueue(0); - - Ogre::CompositorManager::getSingleton(). - addCompositor(mHydrax->getViewport(),_def_Underwater_Compositor_Name)-> - addListener(&mUnderwaterCompositorListener); - - return true; - } - - bool MaterialManager::_createSimpleColorMaterial(const Ogre::ColourValue& Color, const MaterialType& MT, const Ogre::String& Name, const bool& DepthCheck, const bool& DepthWrite) - { - Ogre::MaterialPtr &SimpleColorMaterial = getMaterial(MT); - SimpleColorMaterial = Ogre::MaterialManager::getSingleton(). - create(Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::Pass *SCM_T0_Pass0 = SimpleColorMaterial->getTechnique(0)->getPass(0); - SCM_T0_Pass0->setLightingEnabled(false); - SCM_T0_Pass0->setDepthCheckEnabled(DepthCheck); - SCM_T0_Pass0->setDepthWriteEnabled(DepthWrite); - SCM_T0_Pass0->setCullingMode(Ogre::CULL_NONE); - SCM_T0_Pass0->createTextureUnitState()->setColourOperationEx(Ogre::LBX_MODULATE,Ogre::LBS_MANUAL,Ogre::LBS_CURRENT, Color); - - SimpleColorMaterial->setReceiveShadows(false); - SimpleColorMaterial->load(); - - return true; - } - - void MaterialManager::reload(const MaterialType &Material) - { - Ogre::MaterialPtr &Mat = getMaterial(Material); - - if (Mat.isNull()) - { - return; - } - - Mat->reload(); - - const bool cDepth = _isComponent(mComponents, HYDRAX_COMPONENT_DEPTH ); - const bool cSmooth = _isComponent(mComponents, HYDRAX_COMPONENT_SMOOTH ); - const bool cSun = _isComponent(mComponents, HYDRAX_COMPONENT_SUN ); - const bool cFoam = _isComponent(mComponents, HYDRAX_COMPONENT_FOAM ); - const bool cCaustics = _isComponent(mComponents, HYDRAX_COMPONENT_CAUSTICS); - const bool cUReflections = _isComponent(mComponents, HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS); - - switch (Material) - { - case MAT_WATER: - { - Ogre::Pass *M_Technique0_Pass0 = Mat->getTechnique(0)->getPass(0); - - switch (mOptions.NM) - { - case NM_TEXTURE: case NM_RTT: - { - M_Technique0_Pass0->getTextureUnitState(0)->setTextureName("HydraxNormalMap"); - M_Technique0_Pass0->getTextureUnitState(1)->setTextureName("HydraxReflectionMap"); - M_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxRefractionMap"); - if (cDepth) - { - M_Technique0_Pass0->getTextureUnitState(3)->setTextureName("HydraxDepthMap"); - } - } - break; - - case NM_VERTEX: - { - M_Technique0_Pass0->getTextureUnitState(0)->setTextureName("HydraxReflectionMap"); - M_Technique0_Pass0->getTextureUnitState(1)->setTextureName("HydraxRefractionMap"); - if (cDepth) - { - M_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap"); - } - } - break; - } - - Ogre::GpuProgramParametersSharedPtr VP_Parameters = M_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = M_Technique0_Pass0->getFragmentProgramParameters(); - - if(mOptions.SM != SM_GLSL) - { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - } - if (cFoam) - { - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - } - FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - - FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); - FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); - FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); - - FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); - if (cSmooth) - { - FP_Parameters->setNamedConstant("uSmoothPower", mHydrax->getSmoothPower()); - } - if (cSun) - { - FP_Parameters->setNamedConstant("uSunPosition", mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); - FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); - FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); - FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); - } - if (cFoam) - { - FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); - FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); - FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); - FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); - FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); - } - if (cCaustics) - { - FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); - } - } - break; - - case MAT_DEPTH: - { - Ogre::Pass *M_Technique0_Pass0 = Mat->getTechnique(0)->getPass(0); - - Ogre::GpuProgramParametersSharedPtr VP_Parameters = M_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = M_Technique0_Pass0->getFragmentProgramParameters(); - - if(mOptions.SM != SM_GLSL) - { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - // VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); - } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); - VP_Parameters->setNamedConstant("uPlanesError", (float) mHydrax->getPlanesError()); - - FP_Parameters->setNamedConstant("uDepthLimit", 1.f/mHydrax->getDepthLimit()); - FP_Parameters->setNamedConstant("uDistLimit", 1.f/mHydrax->getDistLimit()); - - if (cCaustics) - { - FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); - FP_Parameters->setNamedConstant("uCausticsEnd", mHydrax->getCausticsEnd()); - } - } - break; - - case MAT_UNDERWATER: - { - Ogre::Pass *M_Technique0_Pass0 = Mat->getTechnique(0)->getPass(0); - - switch (mOptions.NM) - { - case NM_TEXTURE: case NM_RTT: - { - M_Technique0_Pass0->getTextureUnitState(0)->setTextureName("HydraxNormalMap"); - int Index = 1; - if (cUReflections) - { - M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxReflectionMap"); - Index++; - } - M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxRefractionMap"); - Index++; - if (cDepth && cUReflections) - { - M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxDepthReflectionMap"); - } - } - break; - - case NM_VERTEX: - { - int Index = 0; - if (cUReflections) - { - M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxReflectionMap"); - Index++; - } - M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxRefractionMap"); - Index++; - if (cDepth && cUReflections) - { - M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxDepthReflectionMap"); - } - } - break; - } - - Ogre::GpuProgramParametersSharedPtr VP_Parameters = M_Technique0_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = M_Technique0_Pass0->getFragmentProgramParameters(); - - if(mOptions.SM != SM_GLSL) - { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - - FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); - FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); - FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); - FP_Parameters->setNamedConstant("uDistLimit", 1.f/mHydrax->getDistLimit()); - - if ((cDepth && cUReflections) || (!cUReflections)) - { - FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); - } - - if (cSun) - { - FP_Parameters->setNamedConstant("uSunPosition", mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); - FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); - FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); - FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); - FP_Parameters->setNamedConstant("uDepthLimit", 1.f/mHydrax->getDistLimit()); - } - /* Foam is not visible underwater - if (cFoam) - { - FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); - FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); - FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); - FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); - FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); - } - */ - if (cCaustics && cDepth && cUReflections) - { - FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); - } - } - break; - - case MAT_UNDERWATER_COMPOSITOR: - { - mCompositorsNeedToBeReloaded[COMP_UNDERWATER] = true; - } - break; - - case MAT_SIMPLE_RED: - { - } - break; - case MAT_SIMPLE_BLACK: - { - } - break; - } - } - - void MaterialManager::addDepthTechnique(Ogre::Technique *Technique, const bool& AutoUpdate) - { - if (!Ogre::MaterialManager::getSingleton().resourceExists(_def_Depth_Material_Name)) - { - _createDepthMaterial(mComponents, mOptions); - } - - Technique->removeAllPasses(); - Technique->createPass(); - Technique->setName("_Hydrax_Depth_Technique"); - Technique->setSchemeName("HydraxDepth"); - - Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0); - - DM_Technique_Pass0->setVertexProgram(_def_Depth_Shader_VP_Name); - DM_Technique_Pass0->setFragmentProgram(_def_Depth_Shader_FP_Name); - - Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters(); - - if(mOptions.SM != SM_GLSL) + switch (Options.NM) { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); + case NM_TEXTURE: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float2 iUv : TEXCOORD0,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float4 oPosition_ : TEXCOORD0,\n" + + "out float2 oUvNoise : TEXCOORD1,\n" + "out float4 oUvProjection : TEXCOORD2,\n"; + // UNIFORM + if (cFoam) + { + VertexProgramData += + Ogre::String("out float4 oWorldPosition : TEXCOORD3,\n") + "uniform float4x4 uWorld,\n"; + } + VertexProgramData += + Ogre::String("uniform float4x4 uWorldViewProj)\n") + "{\n" + "oPosition_ = iPosition;\n"; + if (cFoam) { VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; } + VertexProgramData += Ogre::String("oPosition = mul(uWorldViewProj, iPosition);\n") + + // Projective texture coordinates, adjust for mapping + "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5," + "0,-0.5, 0, 0.5," + + "0, 0, 0.5, 0.5," + "0, 0, 0, 1);\n" + + "oUvProjection = mul(scalemat, oPosition);\n" + "oUvNoise = iUv;\n" + "}\n"; + } + break; + + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + if (cFoam) { VertexProgramData += "uniform mat4 uWorld;\n"; } + // IN + // OUT + VertexProgramData += Ogre::String("varying vec4 Position_;\n") + "varying vec4 UVProjection;\n"; + if (cFoam) { VertexProgramData += "varying vec4 WorldPosition;\n"; } + // PROGRAM + VertexProgramData += Ogre::String("void main()\n") + "{\n" + "Position_ = gl_Vertex;\n"; + if (cFoam) { VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; } + VertexProgramData += + Ogre::String("gl_Position = ftransform();\n") + "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + + " 0.0, -1.0, 0.0, 0.0,\n" + " 0.0, 0.0, 1.0, 0.0,\n" + " 0.0, 0.0, 0.0, 1.0);\n" + + "UVProjection = scalemat * gl_Position;\n" + "gl_TexCoord[0] = gl_MultiTexCoord0;\n" + "}\n"; + } + break; + } } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); - VP_Parameters->setNamedConstant("uPlanesError", (float) mHydrax->getPlanesError()); + break; - FP_Parameters->setNamedConstant("uDepthLimit", 1/mHydrax->getDepthLimit()); - FP_Parameters->setNamedConstant("uDistLimit", 1/mHydrax->getDistLimit()); + case NM_VERTEX: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float3 iNormal : NORMAL,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float4 oPosition_ : TEXCOORD0,\n" + + "out float4 oUvProjection : TEXCOORD1,\n" + "out float3 oNormal : TEXCOORD2,\n"; + if (cFoam) { VertexProgramData += "out float4 oWorldPosition : TEXCOORD3,\n uniform float4x4 uWorld,\n"; } + VertexProgramData += Ogre::String( + // UNIFORM + "uniform float4x4 uWorldViewProj)\n") + + "{\n" + "oPosition_ = iPosition;\n"; + if (cFoam) { VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; } + VertexProgramData += Ogre::String("oPosition = mul(uWorldViewProj, iPosition);\n") + + // Projective texture coordinates, adjust for mapping + "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5," + "0,-0.5, 0, 0.5," + + "0, 0, 0.5, 0.5," + "0, 0, 0, 1);\n" + + "oUvProjection = mul(scalemat, oPosition);\n" + "oNormal = normalize(iNormal);\n" + "}\n"; + } + break; - if (_isComponent(mComponents, HYDRAX_COMPONENT_CAUSTICS)) - { - FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); - FP_Parameters->setNamedConstant("uCausticsEnd", mHydrax->getCausticsEnd()); + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + if (cFoam) { VertexProgramData += "uniform mat4 uWorld;\n"; } + // IN + // OUT + VertexProgramData += + Ogre::String("varying vec4 Position_;\n") + "varying vec4 UVProjection;\n" + "varying vec3 Normal;\n"; + if (cFoam) { VertexProgramData += "varying vec4 WorldPosition;\n"; } + // PROGRAM + VertexProgramData += Ogre::String("void main()\n") + "{\n" + "Position_ = gl_Vertex;\n"; + if (cFoam) { VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; } + VertexProgramData += Ogre::String("gl_Position = ftransform();\n") + + "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + " 0.0, -1.0, 0.0, 0.0,\n" + + " 0.0, 0.0, 1.0, 0.0,\n" + " 0.0, 0.0, 0.0, 1.0);\n" + + "UVProjection = scalemat * gl_Position;\n" + "Normal = normalize(gl_Normal);\n" + "}\n"; + } + break; + } + } + break; - if(mOptions.SM == SM_GLSL) + case NM_RTT: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: { - FP_Parameters->setNamedConstant("uCaustics", 0); + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float4 oPosition_ : TEXCOORD0,\n" + + "out float4 oUvProjection : TEXCOORD1,\n"; + if (cFoam) { VertexProgramData += "out float4 oWorldPosition : TEXCOORD2,\n uniform float4x4 uWorld,\n"; } + VertexProgramData += Ogre::String( + // UNIFORM + "uniform float4x4 uWorldViewProj)\n") + + "{\n" + "oPosition_ = iPosition;\n"; + if (cFoam) { VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; } + VertexProgramData += Ogre::String("oPosition = mul(uWorldViewProj, iPosition);\n") + + // Projective texture coordinates, adjust for mapping + "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5," + "0,-0.5, 0, 0.5," + + "0, 0, 0.5, 0.5," + "0, 0, 0, 1);\n" + + "oUvProjection = mul(scalemat, oPosition);\n" + "}\n"; } - Ogre::TextureUnitState *TUS_Caustics = DM_Technique_Pass0->createTextureUnitState("Caustics.bmp"); - TUS_Caustics->setName("Caustics"); - TUS_Caustics->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - TUS_Caustics->setAnimatedTextureName("Caustics.bmp", 32, 1.5); - } + break; - if (AutoUpdate) - { - mDepthTechniques.push_back(Technique); - } - } + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + if (cFoam) { VertexProgramData += "uniform mat4 uWorld;\n"; } + // IN + // OUT + VertexProgramData += Ogre::String("varying vec4 Position_;\n") + "varying vec4 UVProjection;\n"; + if (cFoam) { VertexProgramData += "varying vec4 WorldPosition;\n"; } + // PROGRAM + VertexProgramData += Ogre::String("void main()\n") + "{\n" + "Position_ = gl_Vertex;\n"; + if (cFoam) { VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; } + VertexProgramData += Ogre::String("gl_Position = ftransform();\n") + + "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + " 0.0, -1.0, 0.0, 0.0,\n" + + " 0.0, 0.0, 1.0, 0.0,\n" + " 0.0, 0.0, 0.0, 1.0);\n" + + "UVProjection = scalemat * gl_Position;\n" + "}\n"; + } + break; + } + } + break; + } - void MaterialManager::addDepthTextureTechnique(Ogre::Technique *Technique, const Ogre::String& TextureName, const Ogre::String& AlphaChannel, const bool& AutoUpdate) - { - if (!Ogre::HighLevelGpuProgramManager::getSingleton().resourceExists(_def_DepthTexture_Shader_VP_Name+AlphaChannel)) - { - _createDepthTextureGPUPrograms(mComponents, mOptions, AlphaChannel); - } + // Fragment program - Technique->removeAllPasses(); - Technique->createPass(); - Technique->setName("_Hydrax_DepthTexture_Technique"); - Technique->setSchemeName("HydraxDepth"); + switch (Options.NM) + { + case NM_TEXTURE: + case NM_VERTEX: + case NM_RTT: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + FragmentProgramData += Ogre::String("float3 expand(float3 v)\n") + "{\n" + "return (v - 0.5) * 2;\n" + "}\n\n" + - Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0); + "void main_fp(" + + // IN + "float4 iPosition : TEXCOORD0,\n"; + int TEXCOORDNUM = 1; + if (Options.NM == NM_TEXTURE) + { + FragmentProgramData += + "float2 iUvNoise : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + } + FragmentProgramData += "float4 iUvProjection : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + if (Options.NM == NM_VERTEX) + { + FragmentProgramData += + "float4 iNormal : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + } + if (cFoam) + { + FragmentProgramData += + "float4 iWorldPosition : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + } + FragmentProgramData += + Ogre::String( + // OUT + "out float4 oColor : COLOR,\n") + + // UNIFORM + "uniform float3 uEyePosition,\n" + "uniform float uFullReflectionDistance,\n" + + "uniform float uGlobalTransparency,\n" + "uniform float uNormalDistortion,\n"; - // Alpha channel will be stored in pass 0 name: - DM_Technique_Pass0->setName(AlphaChannel); + if (cDepth) { FragmentProgramData += "uniform float3 uWaterColor,\n"; } + if (cSmooth) { FragmentProgramData += "uniform float uSmoothPower,\n"; } + if (cSun) + { + FragmentProgramData += Ogre::String("uniform float3 uSunPosition,\n") + + "uniform float uSunStrength,\n" + "uniform float uSunArea,\n" + + "uniform float3 uSunColor,\n"; + } + if (cFoam) + { + FragmentProgramData += Ogre::String("uniform float uFoamRange,\n") + + "uniform float uFoamMaxDistance,\n" + "uniform float uFoamScale,\n" + + "uniform float uFoamStart,\n" + "uniform float uFoamTransparency,\n"; + } + if (cCaustics) { FragmentProgramData += "uniform float uCausticsPower,\n"; } - DM_Technique_Pass0->setVertexProgram(_def_DepthTexture_Shader_VP_Name+AlphaChannel); - DM_Technique_Pass0->setFragmentProgram(_def_DepthTexture_Shader_FP_Name+AlphaChannel); + int TexNum = 0; - DM_Technique_Pass0->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - DM_Technique_Pass0->setDepthCheckEnabled(true); - DM_Technique_Pass0->setDepthWriteEnabled(false); + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { + FragmentProgramData += + "uniform sampler2D uNormalMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; + TexNum++; + } - Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters(); - Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters(); + FragmentProgramData += Ogre::String("uniform sampler2D uReflectionMap : register(s" + + Ogre::StringConverter::toString(TexNum) + "),\n") + + "uniform sampler2D uRefractionMap : register(s" + + Ogre::StringConverter::toString(TexNum + 1) + "),\n"; - if(mOptions.SM != SM_GLSL) - { - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); - } - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); - VP_Parameters->setNamedConstant("uPlanesError", (float) mHydrax->getPlanesError()); + TexNum += 2; - FP_Parameters->setNamedConstant("uDepthLimit", 1/mHydrax->getDepthLimit()); - FP_Parameters->setNamedConstant("uDistLimit", 1/mHydrax->getDistLimit()); + if (cDepth) + { + FragmentProgramData += + "uniform sampler2D uDepthMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; + TexNum++; + } - if (_isComponent(mComponents, HYDRAX_COMPONENT_CAUSTICS)) - { - FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); - FP_Parameters->setNamedConstant("uCausticsEnd", mHydrax->getCausticsEnd()); + FragmentProgramData += +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "uniform sampler1D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; +#else + "uniform sampler2D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; +#endif + TexNum++; - if(mOptions.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uCaustics", 0); - } - Ogre::TextureUnitState *TUS_Caustics = DM_Technique_Pass0->createTextureUnitState("Caustics.bmp"); - TUS_Caustics->setName("Caustics"); - TUS_Caustics->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - TUS_Caustics->setAnimatedTextureName("Caustics.bmp", 32, 1.5); - } + if (cFoam) + { + FragmentProgramData += Ogre::String(",\nuniform sampler2D uFoamMap : register(s" + + Ogre::StringConverter::toString(TexNum) + ")\n"); + } - if(mOptions.SM == SM_GLSL) - { - FP_Parameters->setNamedConstant("uAlphaTex", 0); + FragmentProgramData += + Ogre::String(")\n") + "{\n" + "float2 ProjectionCoord = iUvProjection.xy / iUvProjection.w;\n" + + "float3 camToSurface = iPosition.xyz - uEyePosition;\n" + + "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; + + if (cFoam) + { + // Calculate the foam visibility as a function fo distance specified by user + FragmentProgramData += "float foamVisibility=1.0f-saturate(additionalReflection/uFoamMaxDistance);\n"; + } + + FragmentProgramData += + Ogre::String("additionalReflection/=uFullReflectionDistance;\n") + "camToSurface=normalize(-camToSurface);\n"; + if (Options.NM == NM_TEXTURE) + { + FragmentProgramData += Ogre::String("float3 pixelNormal = tex2D(uNormalMap,iUvNoise);\n") + + // Inverte y with z, because at creation our local normal to the plane was z + "pixelNormal.yz=pixelNormal.zy;\n" + + // Remap from [0,1] to [-1,1] + "pixelNormal.xyz=expand(pixelNormal.xyz);\n"; + } + else if (Options.NM == NM_VERTEX) + { + FragmentProgramData += "float3 pixelNormal = iNormal;\n"; + } + else // NM_RTT + { + FragmentProgramData += "float3 pixelNormal = 2.0*tex2D(uNormalMap, ProjectionCoord.xy) - 1.0;\n"; + } + FragmentProgramData += "float2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { FragmentProgramData += "float dotProduct=dot(camToSurface,pixelNormal);\n"; } + else + { + FragmentProgramData += "float dotProduct=dot(-camToSurface,pixelNormal);\n"; + } + FragmentProgramData += Ogre::String("dotProduct=saturate(dotProduct);\n") + +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "float fresnel = tex1D(uFresnelMap,dotProduct);\n" + +#else + "float fresnel = tex2D(uFresnelMap,float2(dotProduct,dotProduct));\n" + +#endif + // Add additional reflection and saturate + "fresnel+=additionalReflection;\n" + "fresnel=saturate(fresnel);\n" + + // Decrease the transparency and saturate + "fresnel-=uGlobalTransparency;\n" + "fresnel=saturate(fresnel);\n" + +#if OGRE_PLATFORM != OGRE_PLATFORM_WIN32 + // Reversing projection if underwater + "if(uEyePosition.y < 0.0)\n" + "{\n" + "ProjectionCoord.y = 1.0 - ProjectionCoord.y;\n" + + "}\n" + +#endif + // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal + "float3 reflection=tex2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified);\n" + + "float3 refraction=tex2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified);\n"; + + if (cDepth) + { + if (cCaustics) + { + FragmentProgramData += + Ogre::String("float2 depth = tex2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).rg;\n") + + "refraction *= 1+depth.y*uCausticsPower;\n" + "refraction = lerp(uWaterColor,refraction,depth.x);\n"; + } + else + { + FragmentProgramData += + Ogre::String("float depth = tex2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).r;\n") + + "refraction = lerp(uWaterColor,refraction,depth);\n"; + } + } + + FragmentProgramData += "oColor = float4(lerp(refraction,reflection,fresnel),1);\n"; + + if (cSun) + { + FragmentProgramData += + Ogre::String("float3 relfectedVector = normalize(reflect(-camToSurface,pixelNormal.xyz));\n") + + "float3 surfaceToSun=normalize(uSunPosition-iPosition.xyz);\n" + + "float3 sunlight = uSunStrength*pow(saturate(dot(relfectedVector,surfaceToSun)),uSunArea)*uSunColor;\n" + + "oColor.xyz+=sunlight;\n"; + } + + if (cFoam) + { + FragmentProgramData += Ogre::String("float hmap = iPosition.y/uFoamRange*foamVisibility;\n") + + "float2 foamTex=iWorldPosition.xz*uFoamScale+pixelNormalModified;\n" + + "float foam=tex2D(uFoamMap,foamTex).r;\n" + + "float foamTransparency=saturate(hmap-uFoamStart)*uFoamTransparency;\n" + + "oColor.xyz=lerp(oColor.xyz,1,foamTransparency*foam);\n"; + } + + if (cSmooth) + { + FragmentProgramData += + "oColor.xyz = " + "lerp(tex2D(uRefractionMap,ProjectionCoord.xy).xyz,oColor.xyz,saturate((1-tex2D(uDepthMap," + "ProjectionCoord.xy).r)*uSmoothPower));\n"; + } + + FragmentProgramData += "}\n"; + } + break; + + case SM_GLSL: + FragmentProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform vec3 uEyePosition;\n" + "uniform float uFullReflectionDistance;\n" + + "uniform float uGlobalTransparency;\n" + "uniform float uNormalDistortion;\n" + + "uniform vec3 uWaterColor;\n"; + + if (cSmooth) { FragmentProgramData += "uniform float uSmoothPower;\n"; } + if (cSun) + { + FragmentProgramData += Ogre::String("uniform vec3 uSunPosition;\n") + "uniform float uSunStrength;\n" + + "uniform float uSunArea;\n" + "uniform vec3 uSunColor;\n"; + } + if (cFoam) + { + FragmentProgramData += Ogre::String("uniform float uFoamRange;\n") + "uniform float uFoamMaxDistance;\n" + + "uniform float uFoamScale;\n" + "uniform float uFoamStart;\n" + + "uniform float uFoamTransparency;\n"; + } + if (cCaustics) { FragmentProgramData += "uniform float uCausticsPower;\n"; } + + int TexNum = 0; + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { + FragmentProgramData += "uniform sampler2D uNormalMap;\n"; + TexNum++; + } + + FragmentProgramData += + Ogre::String("uniform sampler2D uReflectionMap;\n") + "uniform sampler2D uRefractionMap;\n"; + TexNum += 2; + + if (cDepth) + { + FragmentProgramData += "uniform sampler2D uDepthMap;\n"; + TexNum++; + } + + FragmentProgramData += +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "uniform sampler1D uFresnelMap;\n"; +#else + "uniform sampler2D uFresnelMap;\n"; +#endif + TexNum++; + + if (cFoam) { FragmentProgramData += "uniform sampler2D uFoamMap;\n"; } + // IN + FragmentProgramData += "varying vec4 Position_;\n"; + int TEXCOORDNUM = 1; + if (Options.NM == NM_TEXTURE) { TEXCOORDNUM++; } + FragmentProgramData += "varying vec4 UVProjection;\n"; + TEXCOORDNUM++; + if (Options.NM == NM_VERTEX) + { + FragmentProgramData += "varying vec3 Normal;\n"; + TEXCOORDNUM++; + } + if (cFoam) { FragmentProgramData += "varying vec4 WorldPosition;\n"; } + // Expand function + FragmentProgramData += + Ogre::String("vec3 expand(vec3 v)\n") + "{\n" + "return (v - 0.5) * 2.0;\n" + "}\n\n" + + // main function + "void main()\n" + "{\n" + "vec2 ProjectionCoord = UVProjection.xy / UVProjection.w;\n" + + "ProjectionCoord += 1.0;\n" + "ProjectionCoord *= 0.5;\n" + + "vec3 camToSurface = Position_.xyz - uEyePosition;\n" + + "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; + if (cFoam) + { + // Calculate the foam visibility as a function fo distance specified by user + FragmentProgramData += "float foamVisibility=1.0-clamp(additionalReflection/uFoamMaxDistance, 0.0, 1.0);\n"; + } + FragmentProgramData += + Ogre::String("additionalReflection/=uFullReflectionDistance;\n") + "camToSurface=normalize(-camToSurface);\n"; + if (Options.NM == NM_TEXTURE) + { + FragmentProgramData += Ogre::String("vec3 pixelNormal = texture2D(uNormalMap,gl_TexCoord[0].xy).xyz;\n") + + // Inverte y with z, because at creation our local normal to the plane was z + "pixelNormal.yz=pixelNormal.zy;\n" + + // Remap from [0,1] to [-1,1] + "pixelNormal.xyz=expand(pixelNormal.xyz);\n"; + } + else if (Options.NM == NM_VERTEX) + { + FragmentProgramData += "vec3 pixelNormal = Normal;\n"; + } + else // NM_RTT + { + FragmentProgramData += "vec3 pixelNormal = 2.0*texture2D(uNormalMap, ProjectionCoord.xy).xyz - 1.0;\n"; + } + FragmentProgramData += "vec2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { FragmentProgramData += "float dotProduct=dot(camToSurface,pixelNormal);\n"; } + else + { + FragmentProgramData += "float dotProduct=dot(-camToSurface,pixelNormal);\n"; + } + FragmentProgramData += Ogre::String("dotProduct=clamp(dotProduct, 0.0, 1.0);\n") + +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "float fresnel = texture1D(uFresnelMap,dotProduct).x;\n" + +#else + "float fresnel = texture2D(uFresnelMap,vec2(dotProduct,dotProduct)).x;\n" + +#endif + // Add additional reflection and saturate + "fresnel +=additionalReflection;\n" + "fresnel = clamp(fresnel, 0.0, 1.0);\n" + + // Decrease the transparency and saturate + "fresnel -= uGlobalTransparency;\n" + "fresnel = clamp(fresnel*fresnel, 0.0, 1.0);\n" + + // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal + "vec3 reflection=texture2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified).xyz;\n" + + "vec3 refraction=texture2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified).xyz;\n"; + if (cDepth) + { + if (cCaustics) + { + FragmentProgramData += + Ogre::String("vec2 depth = texture2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).xy;\n") + + "refraction *= 1.0 + depth.y*uCausticsPower;\n" + + "refraction = mix(uWaterColor,refraction,depth.x);\n"; + } + else + { + FragmentProgramData += + Ogre::String("float depth = texture2D(uDepthMap,ProjectionCoord.xy-pixelNormalModified).x;\n") + + "refraction = mix(uWaterColor,refraction,depth);\n"; + } + } + FragmentProgramData += Ogre::String("gl_FragColor = vec4(mix(refraction,reflection,fresnel),1.0);\n") + + "gl_FragColor.xyz = mix(gl_FragColor.xyz, uWaterColor, uGlobalTransparency);\n"; + if (cSun) + { + FragmentProgramData += + Ogre::String("vec3 relfectedVector = normalize(reflect(-camToSurface,pixelNormal.xyz));\n") + + "vec3 surfaceToSun=normalize(uSunPosition-Position_.xyz);\n" + + "vec3 sunlight = " + "uSunStrength*pow(clamp(dot(relfectedVector,surfaceToSun),0.0,1.0),uSunArea)*uSunColor;\n" + + "gl_FragColor.xyz+=sunlight;\n"; + } + if (cFoam) + { + FragmentProgramData += Ogre::String("float hmap = Position_.y/uFoamRange*foamVisibility;\n") + + "vec2 foamTex=WorldPosition.xz*uFoamScale+pixelNormalModified;\n" + + "float foam=texture2D(uFoamMap,foamTex).x;\n" + + "float foamTransparency=clamp(hmap-uFoamStart, 0.0, 1.0)*uFoamTransparency;\n" + + "gl_FragColor.xyz=mix(gl_FragColor.xyz,vec3(1.0,1.0,1.0),foamTransparency*foam);\n"; + } + if (cSmooth) + { + FragmentProgramData += "gl_FragColor.xyz = " + "mix(texture2D(uRefractionMap,ProjectionCoord.xy).xyz,gl_FragColor.xyz,clamp((1.0-" + "texture2D(uDepthMap,ProjectionCoord.xy).x)*uSmoothPower, 0.0, 1.0));\n"; + } + FragmentProgramData += "}\n"; + break; + } + } + break; + } + + // Build our material + Ogre::MaterialPtr &WaterMaterial = getMaterial(MAT_WATER); + WaterMaterial = Ogre::MaterialManager::getSingleton().create(_def_Water_Material_Name, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *WM_Technique0_Pass0 = WaterMaterial->getTechnique(0)->getPass(0); + + WM_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + WM_Technique0_Pass0->setDepthWriteEnabled(true); + + Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; + Ogre::String GpuProgramNames[2] = {_def_Water_Shader_VP_Name, _def_Water_Shader_FP_Name}; + Ogre::String EntryPoints[2]; + if (Options.SM == SM_GLSL) + { + EntryPoints[0] = Ogre::String("main"); + EntryPoints[1] = Ogre::String("main"); + } + else + { + EntryPoints[0] = Ogre::String("main_vp"); + EntryPoints[1] = Ogre::String("main_fp"); + } + + fillGpuProgramsToPass(WM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = WM_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = WM_Technique0_Pass0->getFragmentProgramParameters(); + + if (Options.SM != SM_GLSL) + { VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } + if (cFoam) { VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); } + FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + + FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); + FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); + FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); + + FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); + if (cSmooth) { FP_Parameters->setNamedConstant("uSmoothPower", mHydrax->getSmoothPower()); } + if (cSun) + { + FP_Parameters->setNamedConstant("uSunPosition", + mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); + FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); + FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); + FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); + } + if (cFoam) + { + FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); + FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); + FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); + FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); + FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); + } + if (cCaustics) { FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); } + + int GLSLTextUnit = 0; + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uNormalMap", GLSLTextUnit); + GLSLTextUnit++; + } + WM_Technique0_Pass0->createTextureUnitState("HydraxNormalMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + } + + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uReflectionMap", GLSLTextUnit); + GLSLTextUnit++; + } + WM_Technique0_Pass0->createTextureUnitState("HydraxReflectionMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uRefractionMap", GLSLTextUnit); + GLSLTextUnit++; + } + WM_Technique0_Pass0->createTextureUnitState("HydraxRefractionMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + + if (cDepth) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit); + GLSLTextUnit++; + } + WM_Technique0_Pass0->createTextureUnitState("HydraxDepthMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + } + + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uFresnelMap", GLSLTextUnit); + GLSLTextUnit++; + } + WM_Technique0_Pass0->createTextureUnitState("Fresnel.bmp")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + + if (cFoam) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uFoamMap", GLSLTextUnit); + GLSLTextUnit++; + } + WM_Technique0_Pass0->createTextureUnitState("Foam.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + } + + WaterMaterial->setReceiveShadows(false); + WaterMaterial->load(); + + return true; + } + + bool MaterialManager::_createDepthMaterial(const HydraxComponent &Components, const Options &Options) + { + const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); + + Ogre::String VertexProgramData, FragmentProgramData; + + // Vertex program + + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + // No caustics + if (!cCaustics) + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float oPosition_ : TEXCOORD0,\n" + + "out float2 oDistance : TEXCOORD1,\n" + + // UNIFORM + "uniform float uPlaneYPos,\n" + "uniform float uPlanesError,\n" + + "uniform float3 uCameraPos,\n" + "uniform float4x4 uWorld,\n" + + "uniform float4x4 uWorldView,\n" + "uniform float4x4 uWorldViewProj)\n" + + "{\n" + "oPosition = mul(uWorldViewProj, iPosition);\n" + + "float3 wPos = mul(uWorld, iPosition).xyz;\n" + "float3 wCam = uCameraPos;\n" + + "wPos.y -= uPlaneYPos;\n" + "wCam.y -= uPlaneYPos;\n" + "oPosition_ = wPos.y;\n" + + // Distance + "oDistance.x = distance(wPos, wCam);\n" + "oDistance.y = 1.0;\n" + + // If exist water plane between points, occlusion effect must be changed. + "if(wCam.y > 0.0) {\n" + "oDistance.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + "}\n" + + "if(wPos.y > uPlanesError) {\n" + "oDistance.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + + "oDistance.y = 0.0;\n" + "}\n" + "}\n"; + } + else // Caustics + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float oPosition_ : TEXCOORD0,\n" + + "out float2 oDistance : TEXCOORD1,\n" + "out float2 oUvWorld : TEXCOORD2,\n" + + // UNIFORM + "uniform float uPlaneYPos,\n" + "uniform float uPlanesError,\n" + + "uniform float3 uCameraPos,\n" + "uniform float4x4 uWorld,\n" + + "uniform float4x4 uWorldViewProj)\n" + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + + "float3 wPos = mul(uWorld, iPosition).xyz;\n" + "float3 wCam = uCameraPos;\n" + + "wPos.y -= uPlaneYPos;\n" + "wCam.y -= uPlaneYPos;\n" + "oPosition_ = wPos.y;\n" + + // Distance + "oDistance.x = distance(wPos, wCam);\n" + "oDistance.y = 1.0;\n" + + // If exist water plane between points, occlusion effect must be changed. + "if(wCam.y > 0.0) {\n" + "oDistance.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + "}\n" + + "if(wPos.y > uPlanesError) {\n" + "oDistance.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + + "oDistance.y = 0.0;\n" + "}\n" + "oUvWorld = wPos.xz;\n" + "}\n"; + } + } + break; + + case SM_GLSL: + // No caustics + if (!cCaustics) + { + VertexProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform float uPlaneYPos;\n" + "uniform float uPlanesError;\n" + "uniform mat4 uWorld;\n" + + // IN + // OUT + "varying float Position_;\n" + "varying vec2 Distance_;\n" + + // main function + "void main()\n" + "{\n" + + // Point and camera position + "vec3 wPos = ( uWorld * gl_Vertex ).xyz;\n" + + "vec3 wCam = ( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).xyz;\n" + + "wPos.y -= uPlaneYPos;\n" + "wCam.y -= uPlaneYPos;\n" + "Position_ = wPos.y;\n" + + // Distance + "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + "Distance_.x = abs(mwPos.z);\n" + + "Distance_.y = 1.0;\n" + + // If exist water plane between points, occlusion effect must be changed. + "if(wCam.y > 0.0) {\n" + "Distance_.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + "}\n" + + "if(wPos.y > uPlanesError) {\n" + "Distance_.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + + "Distance_.y = 0.0;\n" + "}\n" + "}\n"; + } + else // Caustics + { + VertexProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform float uPlaneYPos;\n" + "uniform float uPlanesError;\n" + "uniform mat4 uWorld;\n" + + // IN + // OUT + "varying float Position_;\n" + "varying vec2 Distance_;\n" + "varying vec2 UVWorld;\n" + + // main function + "void main()\n" + "{\n" + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + + // Point and camera position + "vec3 wPos = ( uWorld * gl_Vertex ).xyz;\n" + + "vec3 wCam = ( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).xyz;\n" + + "wPos.y -= uPlaneYPos;\n" + "wCam.y -= uPlaneYPos;\n" + "Position_ = wPos.y;\n" + + // Distance + "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + "Distance_.x = abs(mwPos.z);\n" + + "Distance_.y = 1.0;\n" + + // If exist water plane between points, occlusion effect must be changed. + "if(wCam.y > 0.0) {\n" + "Distance_.x *= 1.0 - wCam.y/(wCam.y + abs(wPos.y));\n" + "}\n" + + "if(wPos.y > uPlanesError) {\n" + + /* + "vec3 wFocus = ( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.1, 1.0) ).xyz;\n" + + "vec3 CamToFreeSurface = wFocus - wCam;\n" + + "CamToFreeSurface *= wCam.y / CamToFreeSurface.y;\n" + + "Distance_.x = length(CamToFreeSurface);\n" + + */ + "Distance_.x *= abs(wCam.y)/(abs(wCam.y) + wPos.y);\n" + "Distance_.y = 0.0;\n" + "}\n" + + "UVWorld = wPos.xz;\n" + "}\n"; + } + break; + } + + // Fragment program + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + // No caustics + if (!cCaustics) + { + FragmentProgramData += Ogre::String("void main_fp(\n") + + // IN + "float iPosition : TEXCOORD0,\n" + "float2 iDistance : TEXCOORD1,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float uDepthLimit,\n" + "uniform float uDistLimit)\n" + "{\n" + + "float pixelYDepth = saturate(iPosition*uDepthLimit + 1.0);\n" + + "float pixelDepth = saturate(1.0 - iDistance.x*uDistLimit);\n" + + "pixelDepth = min(pixelYDepth, pixelDepth);\n" + "oColor = float4(pixelDepth,0,0,0);\n" + + "}\n"; + } + else // Caustics + { + FragmentProgramData += + Ogre::String("void main_fp(\n") + + // IN + "float iPosition : TEXCOORD0,\n" + "float2 iDistance : TEXCOORD1,\n" + + "float2 iUvWorld : TEXCOORD2,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float uDepthLimit,\n" + "uniform float uDistLimit,\n" + + "uniform float uCausticsScale,\n" + "uniform float uCausticsEnd,\n" + + "uniform sampler2D uCaustics : register(s0))\n" + "{\n" + + "float pixelYDepth = saturate(iPosition*uDepthLimit + 1.0);\n" + + // "float pixelDepth = saturate(1.0 - iDistance.x*uDistLimit);\n" + + "float pixelDepth = saturate(1.0 - iDistance.x*uDistLimit);\n" + + "pixelDepth = min(pixelYDepth, pixelDepth);\n" + "oColor = float4(pixelDepth,0.0,0.0,0.0);\n" + + "oColor.g = iDistance.y*saturate((pixelYDepth-uCausticsEnd)/(1.0-uCausticsEnd))*tex2D(uCaustics, " + "iUvWorld/uCausticsScale).x;\n" + + "}\n"; + } + } + break; + + case SM_GLSL: + // No caustics + if (!cCaustics) + { + FragmentProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform float uDepthLimit;\n" + "uniform float uDistLimit;\n" + + // IN + "varying float Position_;\n" + "varying float Distance_;\n" + + // OUT + // main function + "void main()" + "{\n" + + "float pixelYDepth = clamp(1.0 + Position_*uDepthLimit, 0.0, 1.0);\n" + + "float pixelDepth = clamp(1.0 - Distance_.x*uDistLimit, 0.0, 1.0);\n" + + "pixelDepth = min(pixelYDepth,pixelDepth);\n" + + "gl_FragColor = vec4(pixelDepth,0.0,0.0,1.0);\n" + "}\n"; + } + else // Caustics + { + FragmentProgramData += + Ogre::String("\n") + + // UNIFORMS + "uniform float uDepthLimit;\n" + "uniform float uDistLimit;\n" + + "uniform float uCausticsScale;\n" + "uniform float uCausticsEnd;\n" + + "uniform sampler2D uCaustics;\n" + + // IN + "varying float Position_;\n" + "varying vec2 Distance_;\n" + "varying vec2 UVWorld;\n" + + // OUT + // main function + "void main()" + "{\n" + "float pixelYDepth = clamp(1.0 + Position_*uDepthLimit, 0.0, 1.0);\n" + + "float pixelDepth = clamp(1.0 - Distance_.x*uDistLimit, 0.0, 1.0);\n" + + "pixelDepth = min(pixelYDepth,pixelDepth);\n" + "gl_FragColor = vec4(pixelDepth,0.0,0.0,1.0);\n" + + "gl_FragColor.y = Distance_.y*clamp((pixelYDepth-uCausticsEnd)/(1.0-uCausticsEnd), 0.0, " + "1.0)*texture2D(uCaustics, UVWorld/uCausticsScale).x;\n" + + "}\n"; + } + break; + } + + // Build our material + Ogre::MaterialPtr &DepthMaterial = getMaterial(MAT_DEPTH); + DepthMaterial = Ogre::MaterialManager::getSingleton().create(_def_Depth_Material_Name, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + DepthMaterial->getTechnique(0)->setSchemeName("HydraxDepth"); + + Ogre::Pass *DM_Technique0_Pass0 = DepthMaterial->getTechnique(0)->getPass(0); + + Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; + Ogre::String GpuProgramNames[2] = {_def_Depth_Shader_VP_Name, _def_Depth_Shader_FP_Name}; + Ogre::String EntryPoints[2]; + if (Options.SM == SM_GLSL) + { + EntryPoints[0] = Ogre::String("main"); + EntryPoints[1] = Ogre::String("main"); + } + else + { + EntryPoints[0] = Ogre::String("main_vp"); + EntryPoints[1] = Ogre::String("main_fp"); + } + + fillGpuProgramsToPass(DM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique0_Pass0->getFragmentProgramParameters(); + + if (Options.SM != SM_GLSL) + { + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + // VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); + } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); + VP_Parameters->setNamedConstant("uPlanesError", (float)mHydrax->getPlanesError()); + + FP_Parameters->setNamedConstant("uDepthLimit", 1.f / mHydrax->getDepthLimit()); + FP_Parameters->setNamedConstant("uDistLimit", 1.f / mHydrax->getDistLimit()); + + if (cCaustics) + { + FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); + FP_Parameters->setNamedConstant("uCausticsEnd", 1.f - mHydrax->getCausticsEnd()); + + if (Options.SM == SM_GLSL) { FP_Parameters->setNamedConstant("uCaustics", 0); } + Ogre::TextureUnitState *TUS_Caustics = DM_Technique0_Pass0->createTextureUnitState("Caustics.bmp"); + TUS_Caustics->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + TUS_Caustics->setAnimatedTextureName("Caustics.bmp", 32, 1.5); + } + + DepthMaterial->setReceiveShadows(false); + DepthMaterial->load(); + + return true; + } + + bool MaterialManager::_createDepthTextureGPUPrograms(const HydraxComponent &Components, const Options &Options, + const Ogre::String &AlphaChannel) + { + const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); + + Ogre::String VertexProgramData, FragmentProgramData; + + // Vertex program + + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + // No caustics + if (!cCaustics) + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float2 iUV : TEXCOORD0,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float3 oPosition_UV : TEXCOORD0,\n" + + // UNIFORM + "uniform float uPlaneYPos,\n" + "uniform float4x4 uWorld,\n" + + "uniform float4x4 uWorldViewProj)\n" + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + + "oPosition_UV.x = mul(uWorld, iPosition).y;\n" + "oPosition_UV.x-=uPlaneYPos;\n" + + "oPosition_UV.yz = iUV;\n" + "}\n"; + } + else // Caustics + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float2 iUV : TEXCOORD0,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float3 oPosition_UV : TEXCOORD0,\n" + + "out float2 oUvWorld : TEXCOORD1,\n" + + // UNIFORM + "uniform float uPlaneYPos,\n" + "uniform float4x4 uWorld,\n" + + "uniform float4x4 uWorldViewProj)\n" + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + "float3 wPos = mul(uWorld, iPosition);\n" + + "oPosition_UV.x = wPos.y;\n" + "oPosition_UV.x-=uPlaneYPos;\n" + "oPosition_UV.yz = iUV;\n" + + "oUvWorld = wPos.xz;\n" + "}\n"; + } + } + break; + + case SM_GLSL: + // No caustics + if (!cCaustics) + { + VertexProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform float uPlaneYPos;\n" + "uniform mat4 uWorld;\n" + + // IN + // OUT + "varying vec3 Position_UV;\n" + + // main function + "void main()\n" + "{\n" + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + + "Position_UV.x = (uWorld * gl_Vertex).y;\n" + "Position_UV.x -= uPlaneYPos;\n" + + "Position_UV.yz = gl_MultiTexCoord0;\n" + "}\n"; + } + else // Caustics + { + VertexProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform float uPlaneYPos;\n" + "uniform mat4 uWorld;\n" + + // IN + // OUT + "varying vec3 Position_UV;\n" + "varying vec2 UVWorld;\n" + + // main function + "void main()\n" + "{\n" + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + + "vec3 wPos = uWorld * iPosition;\n" + "Position_UV.x = wPos.y;\n" + + "Position_UV.x -= uPlaneYPos;\n" + "Position_UV.yz = gl_MultiTexCoord0;\n" + + "UVWorld = wPos.xz;\n" + "}\n"; + } + break; + } + + // Fragment program + + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + // No caustics + if (!cCaustics) + { + FragmentProgramData += Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition_UV : TEXCOORD0,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float uDepthLimit,\n" + + "uniform sampler2D uAlphaTex : register(s0))\n" + "{\n" + + "float pixelYDepth = (iPosition_UV.x*uDepthLimit+1);\n" + + "pixelYDepth = saturate(pixelYDepth);\n" + "oColor = float4(pixelYDepth,0,0,0);\n" + + "oColor.a = tex2D(uAlphaTex, iPosition_UV.yz)." + AlphaChannel + ";" + "}\n"; + } + else // Caustics + { + FragmentProgramData += + Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition_UV : TEXCOORD0,\n" + "float2 iUvWorld : TEXCOORD1,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float uDepthLimit,\n" + "uniform float uCausticsScale,\n" + + "uniform float uCausticsEnd,\n" + "uniform sampler2D uCaustics : register(s0),\n" + + "uniform sampler2D uAlphaTex : register(s1))\n" + "{\n" + + "float pixelYDepth = (iPosition_UV.x*uDepthLimit+1);\n" + "pixelYDepth = saturate(pixelYDepth);\n" + + "oColor = float4(pixelYDepth,0,0,0);\n" + + "oColor.g = saturate(uCausticsEnd-pixelYDepth)*tex2D(uCaustics, iUvWorld/uCausticsScale).r;\n" + + "oColor.a = tex2D(uAlphaTex, iPosition_UV.yz)." + AlphaChannel + ";" + "}\n"; + } + } + break; + + case SM_GLSL: + { + Ogre::String AlphaChannelGLSL = AlphaChannel; + std::replace(AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'r', 'x'); + std::replace(AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'g', 'y'); + std::replace(AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'b', 'z'); + std::replace(AlphaChannelGLSL.begin(), AlphaChannelGLSL.end(), 'a', 'w'); + // No caustics + if (!cCaustics) + { + FragmentProgramData += + Ogre::String("\n") + + // UNIFORMS + "uniform float uDepthLimit;\n" + "uniform float uDistLimit;\n" + "uniform sampler2D uAlphaTex;\n" + + // IN + "variying vec3 Position_UV;\n" + + // OUT + // main function + "void main()\n" + "{\n" + "float pixelYDepth = clamp(Position_UV.x*uDepthLimit + 1.0, 0.0, 1.0);\n" + + "gl_FragColor = vec4(pixelYDepth,0.0,0.0,0.0);\n" + + "gl_FragColor.w = texture2D(uAlphaTex, iPosition_UV.yz)." + AlphaChannelGLSL + ";" + "}\n"; + } + else // Caustics + { + FragmentProgramData += + Ogre::String("\n") + + // UNIFORMS + "uniform float uDistLimit;\n" + "uniform float uCausticsScale;\n" + + "uniform float uCausticsEnd;\n" + "uniform sampler2D uCaustics;\n" + "uniform sampler2D uAlphaTex;\n" + + // IN + "variying vec3 Position_UV;\n" + "variying vec2 UVWorld;\n" + + // OUT + // main function + "void main()\n" + "{\n" + "float pixelYDepth = clamp(Position_UV.x*uDepthLimit + 1.0, 0.0, 1.0);\n" + + "gl_FragColor = vec4(pixelYDepth,0.0,0.0,0.0);\n" + + "gl_FragColor.y = clamp(uCausticsEnd-pixelYDepth, 0.0, 1.0)*texture2D(uCaustics, " + "UVWorld/uCausticsScale).x;\n" + + "gl_FragColor.w = texture2D(uAlphaTex, iPosition_UV.yz)." + AlphaChannelGLSL + ";" + "}\n"; + } + } + break; + } + + Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; + Ogre::String GpuProgramNames[2] = {_def_DepthTexture_Shader_VP_Name + AlphaChannel, + _def_DepthTexture_Shader_FP_Name + AlphaChannel}; + Ogre::String EntryPoints[2]; + if (Options.SM == SM_GLSL) + { + EntryPoints[0] = Ogre::String("main"); + EntryPoints[1] = Ogre::String("main"); + } + else + { + EntryPoints[0] = Ogre::String("main_vp"); + EntryPoints[1] = Ogre::String("main_fp"); + } + + GpuProgram GpuPrograms[2] = {GPUP_VERTEX, GPUP_FRAGMENT}; + + for (int k = 0; k < 2; k++) + { + if (!createGpuProgram(GpuProgramNames[k], Options.SM, GpuPrograms[k], EntryPoints[k], GpuProgramsData[k])) + { return false; } + } + + return true; + } + + bool MaterialManager::_createUnderwaterMaterial(const HydraxComponent &Components, const Options &Options) + { + const bool cDepth = _isComponent(Components, HYDRAX_COMPONENT_DEPTH); + // const bool cSmooth = _isComponent(Components, HYDRAX_COMPONENT_SMOOTH ); // cSmooth uneeded underwater + const bool cSun = _isComponent(Components, HYDRAX_COMPONENT_SUN); + // const bool cFoam = _isComponent(Components, HYDRAX_COMPONENT_FOAM ); + const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); + const bool cUReflections = _isComponent(Components, HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS); + + Ogre::String VertexProgramData, FragmentProgramData; + + // Vertex program + + switch (Options.NM) + { + case NM_TEXTURE: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float2 iUv : TEXCOORD0,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float4 oPosition_ : TEXCOORD0,\n" + + "out float2 oUvNoise : TEXCOORD1,\n" + "out float4 oUvProjection : TEXCOORD2,\n" + + "out float2 oDistance : TEXCOORD3,\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += + "out float4 oWorldPosition : TEXCOORD4,\n"; + } + */ + VertexProgramData += Ogre::String( + // UNIFORM + "uniform float4x4 uWorldViewProj,\n") + + "uniform float4x4 uWorldView,\n" + "uniform float4x4 uWorld,\n" + + "uniform float3 uCameraPos)\n" + "{\n" + "oPosition_ = iPosition;\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += + "oWorldPosition = mul(uWorld, iPosition);\n"; + } + */ + VertexProgramData += Ogre::String("oPosition = mul(uWorldViewProj, iPosition);\n") + + // Projective texture coordinates, adjust for mapping + "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5," + "0,-0.5, 0, 0.5," + + "0, 0, 0.5, 0.5," + "0, 0, 0, 1);\n" + + "oUvProjection = mul(scalemat, oPosition);\n" + "oUvNoise = iUv;\n" + + // Distance + "float4 mwPos = mul(uWorldView, iPosition);\n" + "oDistance.x = abs(mwPos.z);\n" + + "oDistance.y = -mul( uWorld, float4(uCameraPos, 1.0) ).y;\n" + "}\n"; + } + break; + + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + VertexProgramData += "uniform mat4 uWorld;\n"; + // IN + // OUT + VertexProgramData += + Ogre::String("varying vec4 Position_;\n") + "varying vec4 UVProjection;\n" + "varying vec2 Distance_;\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += "varying vec4 WorldPosition;\n"; + } + */ + // main function + VertexProgramData += Ogre::String("void main()\n") + "{\n" + "Position_ = gl_Vertex;\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; + } + */ + VertexProgramData += Ogre::String( + // Projective texture coordinates, adjust for mapping + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n") + + "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + " 0.0, -1.0, 0.0, 0.0,\n" + + " 0.0, 0.0, 1.0, 0.0,\n" + " 0.0, 0.0, 0.0, 1.0);\n" + + "UVProjection = scalemat * gl_Position;\n" + "gl_TexCoord[0] = gl_MultiTexCoord0;\n" + + // Distance + "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + "Distance_.x = abs(mwPos.z);\n" + + "Distance_.y = -( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).y;\n" + + "}\n"; + } + break; + } + } + break; + + case NM_VERTEX: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + "float3 iNormal : NORMAL,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float4 oPosition_ : TEXCOORD0,\n" + + "out float4 oUvProjection : TEXCOORD1,\n" + "out float3 oNormal : TEXCOORD2,\n" + + "out float2 oDistance : TEXCOORD3,\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += + "out float4 oWorldPosition : TEXCOORD4,\n"; + } + */ + VertexProgramData += Ogre::String( + // UNIFORM + "uniform float4x4 uWorldViewProj,\n") + + "uniform float4x4 uWorldView,\n" + "uniform float4x4 uWorld,\n" + + "uniform float3 uCameraPos)\n" + "{\n" + "oPosition_ = iPosition;\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; + } + */ + VertexProgramData += Ogre::String("oPosition = mul(uWorldViewProj, iPosition);\n") + + // Projective texture coordinates, adjust for mapping + "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5," + "0,-0.5, 0, 0.5," + + "0, 0, 0.5, 0.5," + "0, 0, 0, 1);\n" + + "oUvProjection = mul(scalemat, oPosition);\n" + "oNormal = normalize(iNormal);\n" + + // Distance + "float4 mwPos = mul(uWorldView, iPosition);\n" + "oDistance.x = abs(mwPos.z);\n" + + "oDistance.y = -mul( uWorld, float4(uCameraPos, 1.0) ).y;\n" + "}\n"; + } + break; + + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + VertexProgramData += "uniform mat4 uWorld;\n"; + // IN + // OUT + VertexProgramData += Ogre::String("varying vec4 Position_;\n") + "varying vec4 UVProjection;\n" + + "varying vec3 Normal;\n" + "varying vec2 Distance_;\n"; + /* Foam is not visible underwater + if(cFoam) + { + VertexProgramData += "varying vec4 WorldPosition;\n"; + } + */ + // PROGRAM + VertexProgramData += Ogre::String("void main()\n") + "{\n" + "Position_ = gl_Vertex;\n"; + /* Foam is not visible underwater + if(cFoam) + { + VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; + } + */ + VertexProgramData += Ogre::String("gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n") + + "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + " 0.0, -1.0, 0.0, 0.0,\n" + + " 0.0, 0.0, 1.0, 0.0,\n" + " 0.0, 0.0, 0.0, 1.0);\n" + + "UVProjection = scalemat * gl_Position;\n" + "Normal = normalize(gl_Normal);\n" + + // Distance + "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + "Distance_.x = abs(mwPos.z);\n" + + "Distance_.y = -( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).y;\n" + + "}\n"; + } + break; + } + } + break; + + case NM_RTT: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float4 oPosition_ : TEXCOORD0,\n" + + "out float4 oUvProjection : TEXCOORD1,\n" + "out float2 oDistance : TEXCOORD2,\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += + "out float4 oWorldPosition : TEXCOORD3,\n"; + } + */ + VertexProgramData += Ogre::String( + // UNIFORM + "uniform float4x4 uWorldViewProj,\n") + + "uniform float4x4 uWorldView,\n" + "uniform float4x4 uWorld,\n" + + "uniform float3 uCameraPos)\n" + "{\n" + "oPosition_ = iPosition;\n"; + /* Foam is not visible underwater + if (cFoam) + { + VertexProgramData += "oWorldPosition = mul(uWorld, iPosition);\n"; + } + */ + VertexProgramData += Ogre::String("oPosition = mul(uWorldViewProj, iPosition);\n") + + // Projective texture coordinates, adjust for mapping + "float4x4 scalemat = float4x4(0.5, 0, 0, 0.5," + "0,-0.5, 0, 0.5," + + "0, 0, 0.5, 0.5," + "0, 0, 0, 1);\n" + + "oUvProjection = mul(scalemat, oPosition);\n" + + // Distance + "float4 mwPos = mul(uWorldView, iPosition);\n" + "oDistance.x = abs(mwPos.z);\n" + + "oDistance.y = -mul( uWorld, float4(uCameraPos, 1.0) ).y;\n" + "}\n"; + } + break; + + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + VertexProgramData += "uniform mat4 uWorld;\n"; + // IN + // OUT + VertexProgramData += + Ogre::String("varying vec4 Position_;\n") + "varying vec4 UVProjection;\n" + "varying vec2 Distance_;\n"; + /* Foam is not visible underwater + if(cFoam) + { + VertexProgramData += "varying vec4 WorldPosition;\n"; + } + */ + // PROGRAM + VertexProgramData += Ogre::String("void main()\n") + "{\n" + "Position_ = gl_Vertex;\n"; + /* Foam is not visible underwater + if(cFoam) + { + VertexProgramData += "WorldPosition = uWorld * gl_Vertex;\n"; + } + */ + VertexProgramData += + Ogre::String("gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n") + + "mat4 scalemat = mat4( 1.0, 0.0, 0.0, 0.0,\n" + " 0.0, -1.0, 0.0, 0.0,\n" + + " 0.0, 0.0, 1.0, 0.0,\n" + " 0.0, 0.0, 0.0, 1.0);\n" + "UVProjection = scalemat * gl_Position;\n" + + // Distance + "vec4 mwPos = gl_ModelViewMatrix * gl_Vertex;\n" + "Distance_.x = abs(mwPos.z);\n" + + "Distance_.y = -( uWorld * gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0) ).y;\n" + "}\n"; + } + break; + } + } + break; + } + + // Fragment program + + switch (Options.NM) + { + case NM_TEXTURE: + case NM_VERTEX: + case NM_RTT: + { + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + FragmentProgramData += Ogre::String("float3 expand(float3 v)\n") + "{\n" + "return (v - 0.5) * 2;\n" + "}\n\n" + + + "void main_fp(" + + // IN + "float4 iPosition : TEXCOORD0,\n"; + int TEXCOORDNUM = 1; + if (Options.NM == NM_TEXTURE) + { + FragmentProgramData += + "float2 iUvNoise : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + } + FragmentProgramData += "float4 iUvProjection : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + if (Options.NM == NM_VERTEX) + { + FragmentProgramData += + "float3 iNormal : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + } + FragmentProgramData += "float2 iDistance : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + TEXCOORDNUM++; + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += + "float4 iWorldPosition : TEXCOORD" + Ogre::StringConverter::toString(TEXCOORDNUM) + ",\n"; + } + */ + + FragmentProgramData += + Ogre::String( + // OUT + "out float4 oColor : COLOR,\n") + + // UNIFORM + "uniform float3 uEyePosition,\n" + "uniform float uFullReflectionDistance,\n" + + "uniform float uGlobalTransparency,\n" + "uniform float uNormalDistortion,\n" + + "uniform float uDistLimit,\n" + "uniform float3 uWaterColor,\n"; + if (cSun) + { + FragmentProgramData += Ogre::String("uniform float3 uSunPosition,\n") + + "uniform float uSunStrength,\n" + "uniform float uSunArea,\n" + + "uniform float3 uSunColor,\n" + "uniform float uDepthLimit,\n"; + } + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += Ogre::String( + "uniform float uFoamRange,\n") + + "uniform float uFoamMaxDistance,\n" + + "uniform float uFoamScale,\n" + + "uniform float uFoamStart,\n" + + "uniform float uFoamTransparency,\n"; + } + */ + if (cCaustics && cUReflections) { FragmentProgramData += "uniform float uCausticsPower,\n"; } + + int TexNum = 0; + + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { + FragmentProgramData += + "uniform sampler2D uNormalMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; + TexNum++; + } + if (cUReflections) + { + FragmentProgramData += + "uniform sampler2D uReflectionMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; + TexNum++; + } + + FragmentProgramData += + "uniform sampler2D uRefractionMap : register(s" + Ogre::StringConverter::toString(TexNum) + "),\n"; + TexNum++; + + if (cDepth && cUReflections) + { + FragmentProgramData += "uniform sampler2D uDepthReflectionMap : register(s" + + Ogre::StringConverter::toString(TexNum) + "),\n"; + TexNum++; + } + + FragmentProgramData += +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "uniform sampler1D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; +#else + "uniform sampler2D uFresnelMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")"; +#endif + TexNum++; + + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += Ogre::String( + ",\nuniform sampler2D uFoamMap : register(s" + Ogre::StringConverter::toString(TexNum) + ")\n"); + } + */ + FragmentProgramData += + Ogre::String(")\n") + "{\n" + "float2 ProjectionCoord = iUvProjection.xy / iUvProjection.w;\n" + + "float3 camToSurface = iPosition.xyz - uEyePosition;\n" + + "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; + + /* Foam is not visible underwater + if (cFoam) + { + // Calculate the foam visibility as a function fo distance specified by user + FragmentProgramData += + "float foamVisibility=1.0f-saturate(additionalReflection/uFoamMaxDistance);\n"; + } + */ + + FragmentProgramData += + Ogre::String("additionalReflection/=uFullReflectionDistance;\n") + "camToSurface=normalize(-camToSurface);\n"; + if (Options.NM == NM_TEXTURE) + { + FragmentProgramData += Ogre::String("float3 pixelNormal = tex2D(uNormalMap,iUvNoise).xyz;\n") + + // Inverte y with z, because at creation our local normal to the plane was z + "pixelNormal.yz=pixelNormal.zy;\n" + + // Remap from [0,1] to [-1,1] + "pixelNormal.xyz=-expand(pixelNormal.xyz);\n"; + } + else if (Options.NM == NM_VERTEX) + { + FragmentProgramData += "float3 pixelNormal = -iNormal;\n"; + } + else // NM_RTT + { + FragmentProgramData += "float3 pixelNormal = -(2.0*tex2D(uNormalMap, ProjectionCoord.xy).xyz - 1.0);\n"; + } + FragmentProgramData += "float2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; + + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { FragmentProgramData += "float dotProduct=dot(camToSurface,pixelNormal);\n"; } + else + { + FragmentProgramData += "float dotProduct=dot(-camToSurface,pixelNormal);\n"; + } + FragmentProgramData += + Ogre::String("dotProduct=saturate(dotProduct);\n") + +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "float fresnel = tex1D(uFresnelMap,dotProduct);\n" + +#else + "float fresnel = tex2D(uFresnelMap,float2(dotProduct,dotProduct));\n" + +#endif + // Add additional reflection and saturate + "fresnel+=additionalReflection;\n" + "fresnel=saturate(fresnel);\n" + + // Decrease the transparency and saturate + "fresnel-=uGlobalTransparency;\n" + "fresnel=saturate(fresnel);\n" + "float3 reflection;\n" + +#if OGRE_PLATFORM != OGRE_PLATFORM_WIN32 + // Reversing projection if underwater + "if(uEyePosition.y < 0.0)\n" + "{\n" + "ProjectionCoord.y = 1.0 - ProjectionCoord.y;\n" + "}\n" + +#endif + // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal + "float3 refraction=tex2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified).xyz;\n"; + if (cUReflections) + { FragmentProgramData += "reflection=tex2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified).xyz;\n"; } + else + { + FragmentProgramData += "reflection=uWaterColor;\n"; + } + + if (cDepth && cUReflections) + { + if (cCaustics) + { + FragmentProgramData += + Ogre::String( + "float2 depth = tex2D(uDepthReflectionMap,ProjectionCoord.xy+pixelNormalModified).rg;\n") + + "reflection *= 1+depth.y*uCausticsPower;\n" + "reflection = lerp(uWaterColor,reflection,depth.x);\n"; + } + else + { + FragmentProgramData += + Ogre::String("float depth = tex2D(uDepthReflectionMap,ProjectionCoord.xy-pixelNormalModified).r;\n") + + "reflection = lerp(uWaterColor,reflection,depth);\n"; + } + } + FragmentProgramData += Ogre::String("float4 Color = float4(lerp(refraction,reflection,fresnel),1);\n") + + "float Distance = saturate(1.0 - iDistance.x*uDistLimit);\n" + + "Color.xyz = lerp(uWaterColor, Color.xyz, Distance);\n" + + "Color.xyz = lerp(Color.xyz, uWaterColor, uGlobalTransparency);\n"; + + if (cSun) + { + FragmentProgramData += + Ogre::String("float3 refractedVector = normalize(reflect(camToSurface, pixelNormal.xyz));\n") + + "float3 surfaceToSun=normalize(uSunPosition-iPosition.xyz);\n" + + // Temporally solution, fix this + "surfaceToSun.xz = -surfaceToSun.xz;" + + "float3 sunlight = uSunStrength*pow(saturate(dot(refractedVector,surfaceToSun)),uSunArea)*uSunColor;\n" + + "Distance = saturate(1.0 - iDistance.y*uDepthLimit);\n" + + "Color.xyz+=Distance*sunlight*saturate(1.0-additionalReflection);\n"; + } + + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += Ogre::String( + "float hmap = iPosition.y/uFoamRange*foamVisibility;\n") + + "float2 foamTex=iWorldPosition.xz*uFoamScale+pixelNormalModified;\n" + + "float foam=tex2D(uFoamMap,foamTex).r;\n" + + "float foamTransparency=saturate(hmap-uFoamStart)*uFoamTransparency;\n" + + "Color.xyz=lerp(Color.xyz,1,foamTransparency*foam);\n"; + } + */ + FragmentProgramData += Ogre::String("oColor = Color;\n") + "}\n"; + } + break; + + case SM_GLSL: + FragmentProgramData += Ogre::String("\n") + + // UNIFORMS + "uniform vec3 uEyePosition;\n" + "uniform float uFullReflectionDistance;\n" + + "uniform float uGlobalTransparency;\n" + "uniform float uNormalDistortion;\n" + + "uniform float uDistLimit;\n" + "uniform vec3 uWaterColor;\n"; + + if (cSun) + { + FragmentProgramData += Ogre::String("uniform vec3 uSunPosition;\n") + "uniform float uSunStrength;\n" + + "uniform float uSunArea;\n" + "uniform vec3 uSunColor;\n" + + "uniform float uDepthLimit;\n"; + } + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += Ogre::String( + "uniform float uFoamRange;\n") + + "uniform float uFoamMaxDistance;\n" + + "uniform float uFoamScale;\n" + + "uniform float uFoamStart;\n" + + "uniform float uFoamTransparency;\n"; + } + */ + if (cCaustics && cUReflections) { FragmentProgramData += "uniform float uCausticsPower;\n"; } + + int TexNum = 0; + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { + FragmentProgramData += "uniform sampler2D uNormalMap;\n"; + TexNum++; + } + + if (cUReflections) + { + FragmentProgramData += Ogre::String("uniform sampler2D uReflectionMap;\n"); + TexNum++; + } + FragmentProgramData += Ogre::String("uniform sampler2D uRefractionMap;\n"); + TexNum++; + + if (cDepth && cUReflections) + { + FragmentProgramData += "uniform sampler2D uDepthReflectionMap;\n"; + TexNum++; + } + + FragmentProgramData += +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "uniform sampler1D uFresnelMap;\n"; +#else + "uniform sampler2D uFresnelMap;\n"; +#endif + TexNum++; + + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += + "uniform sampler2D uFoamMap;\n"; + } + */ + // IN + FragmentProgramData += "varying vec4 Position_;\n"; + int TEXCOORDNUM = 1; + if (Options.NM == NM_TEXTURE) { TEXCOORDNUM++; } + FragmentProgramData += "varying vec4 UVProjection;\n"; + TEXCOORDNUM++; + if (Options.NM == NM_VERTEX) + { + FragmentProgramData += "varying vec3 Normal;\n"; + TEXCOORDNUM++; + } + /* Foam is not visible underwater + if (cFoam) + { + FragmentProgramData += + "varying vec4 WorldPosition;\n"; + } + */ + FragmentProgramData += "varying vec2 Distance_;\n"; + // Expand function + FragmentProgramData += + Ogre::String("vec3 expand(vec3 v)\n") + "{\n" + "return (v - 0.5) * 2.0;\n" + "}\n\n" + + // main function + "void main()\n" + "{\n" + "vec2 ProjectionCoord = UVProjection.xy / UVProjection.w;\n" + + "ProjectionCoord += 1.0;\n" + "ProjectionCoord *= 0.5;\n" + + "vec3 camToSurface = Position_.xyz - uEyePosition;\n" + + "float additionalReflection=camToSurface.x*camToSurface.x+camToSurface.z*camToSurface.z;\n"; + /* Must not view foam underwater + if (cFoam) + { + // Calculate the foam visibility as a function fo distance specified by user + FragmentProgramData += + "float foamVisibility=1.0-clamp(additionalReflection/uFoamMaxDistance, 0.0, 1.0);\n"; + } + */ + FragmentProgramData += + Ogre::String("additionalReflection/=uFullReflectionDistance;\n") + "camToSurface=normalize(-camToSurface);\n"; + if (Options.NM == NM_TEXTURE) + { + FragmentProgramData += Ogre::String("vec3 pixelNormal = texture2D(uNormalMap,gl_TexCoord[0].xy).xyz;\n") + + // Inverte y with z, because at creation our local normal to the plane was z + "pixelNormal.yz=pixelNormal.zy;\n" + + // Remap from [0,1] to [-1,1] + "pixelNormal.xyz=-expand(pixelNormal.xyz);\n"; + } + else if (Options.NM == NM_VERTEX) + { + FragmentProgramData += "vec3 pixelNormal = -Normal;\n"; + } + else // NM_RTT + { + FragmentProgramData += "vec3 pixelNormal = -2.0*texture2D(uNormalMap, ProjectionCoord.xy).xyz - 1.0;\n"; + } + FragmentProgramData += "vec2 pixelNormalModified = uNormalDistortion*pixelNormal.zx;\n"; + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { FragmentProgramData += "float dotProduct=dot(camToSurface,pixelNormal);\n"; } + else + { + FragmentProgramData += "float dotProduct=dot(-camToSurface,pixelNormal);\n"; + } + FragmentProgramData += Ogre::String("dotProduct=clamp(dotProduct, 0.0, 1.0);\n") + +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "float fresnel = texture1D(uFresnelMap,dotProduct).x;\n" + +#else + "float fresnel = texture2D(uFresnelMap,vec2(dotProduct,dotProduct)).x;\n" + +#endif + // Add additional reflection and saturate + "fresnel +=additionalReflection;\n" + "fresnel = clamp(fresnel, 0.0, 1.0);\n" + + // Decrease the transparency and saturate + "fresnel -= uGlobalTransparency;\n" + "fresnel = clamp(fresnel, 0.0, 1.0);\n" + + // Get the reflection/refraction pixels. Make sure to disturb the texcoords by pixelnormal + "vec3 reflection;\n" + +#if OGRE_PLATFORM != OGRE_PLATFORM_WIN32 + // Reversing projection if underwater + "if(uEyePosition.y < 0.0)\n" + "{\n" + "ProjectionCoord.y = 1.0 - ProjectionCoord.y;\n" + + "}\n" + +#endif + "vec3 refraction=texture2D(uRefractionMap,ProjectionCoord.xy-pixelNormalModified).xyz;\n"; + if (cUReflections) + { FragmentProgramData += "reflection=texture2D(uReflectionMap,ProjectionCoord.xy+pixelNormalModified).xyz;\n"; } + else + { + FragmentProgramData += "reflection=uWaterColor;\n"; + } + if (cDepth && cUReflections) + { + if (cCaustics) + { + FragmentProgramData += + Ogre::String( + "vec2 depth = texture2D(uDepthReflectionMap,ProjectionCoord.xy+pixelNormalModified).xy;\n") + + "reflection *= 1.0 + depth.y*uCausticsPower;\n" + + "reflection = mix(uWaterColor,reflection,depth.x);\n"; + } + else + { + FragmentProgramData += + Ogre::String( + "float depth = texture2D(uDepthReflectionMap,ProjectionCoord.xy+pixelNormalModified).x;\n") + + "reflection = mix(uWaterColor,reflection,depth);\n"; + } + } + FragmentProgramData += Ogre::String("gl_FragColor = vec4(mix(refraction,reflection,fresnel),1.0);\n") + + "float Distance = clamp(1.0 - Distance_.x*uDistLimit, 0.0, 1.0);\n" + + "gl_FragColor.xyz = mix(uWaterColor, gl_FragColor.xyz, Distance);\n" + + "gl_FragColor.xyz = mix(gl_FragColor.xyz, uWaterColor, uGlobalTransparency);\n"; + if (cSun) + { + FragmentProgramData += + Ogre::String("vec3 refractedVector = normalize(reflect(-camToSurface,pixelNormal.xyz));\n") + + "vec3 surfaceToSun=normalize(uSunPosition-Position_.xyz);\n" + + // Temporally solution, fix this + "surfaceToSun.xz = -surfaceToSun.xz;" + + "vec3 sunlight = " + "uSunStrength*pow(clamp(dot(refractedVector,surfaceToSun),0.0,1.0),uSunArea)*uSunColor;\n" + + "Distance = clamp(1.0 - Distance_.y*uDepthLimit, 0.0, 1.0);\n"; + "gl_FragColor.xyz+=Distance*sunlight*clamp(1.0 - additionalReflection, 0.0, 1.0);\n"; + } + /* Must not view foam underwater + if (cFoam) + { + FragmentProgramData += Ogre::String( + "float hmap = Position_.y/uFoamRange*foamVisibility;\n") + + "vec2 foamTex=WorldPosition.xz*uFoamScale+pixelNormalModified;\n" + + "float foam=texture2D(uFoamMap,foamTex).x;\n" + + "float foamTransparency=clamp(hmap-uFoamStart, 0.0, 1.0)*uFoamTransparency;\n" + + "gl_FragColor.xyz=mix(gl_FragColor.xyz,vec3(1.0,1.0,1.0),foamTransparency*foam);\n"; + } + */ + FragmentProgramData += "}\n"; + break; + } + } + break; + } + + // Second: build our material + Ogre::MaterialPtr &UnderwaterMaterial = getMaterial(MAT_UNDERWATER); + UnderwaterMaterial = Ogre::MaterialManager::getSingleton().create( + _def_Underwater_Material_Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *UM_Technique0_Pass0 = UnderwaterMaterial->getTechnique(0)->getPass(0); + + UM_Technique0_Pass0->setDepthWriteEnabled(true); + UM_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + + Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; + Ogre::String GpuProgramNames[2] = {_def_Underwater_Shader_VP_Name, _def_Underwater_Shader_FP_Name}; + Ogre::String EntryPoints[2]; + if (Options.SM == SM_GLSL) + { + EntryPoints[0] = Ogre::String("main"); + EntryPoints[1] = Ogre::String("main"); + } + else + { + EntryPoints[0] = Ogre::String("main_vp"); + EntryPoints[1] = Ogre::String("main_fp"); + } + + fillGpuProgramsToPass(UM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = UM_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = UM_Technique0_Pass0->getFragmentProgramParameters(); + + if (Options.SM != SM_GLSL) + { + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + + FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); + FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); + FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); + FP_Parameters->setNamedConstant("uDistLimit", 1.f / mHydrax->getDistLimit()); + if (cSun) {} + FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); + + if (cSun) + { + FP_Parameters->setNamedConstant("uSunPosition", + mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); + FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); + FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); + FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); + FP_Parameters->setNamedConstant("uDepthLimit", 1.f / mHydrax->getDepthLimit()); + } + /* Foam is not visible underwater + if (cFoam) + { + FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); + FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); + FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); + FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); + FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); + } + */ + if (cCaustics && cDepth && cUReflections) + { FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); } + + int GLSLTextUnit = 0; + + if (Options.NM == NM_TEXTURE || Options.NM == NM_RTT) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uNormalMap", GLSLTextUnit); + GLSLTextUnit++; + } + UM_Technique0_Pass0->createTextureUnitState("HydraxNormalMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + } + + if (cUReflections) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uReflectionMap", GLSLTextUnit); + GLSLTextUnit++; + } + UM_Technique0_Pass0->createTextureUnitState("HydraxReflectionMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + } + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uRefractionMap", GLSLTextUnit); + GLSLTextUnit++; + } + UM_Technique0_Pass0->createTextureUnitState("HydraxRefractionMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + + if (cDepth && cUReflections) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uDepthReflectionMap", GLSLTextUnit); + GLSLTextUnit++; + } + UM_Technique0_Pass0->createTextureUnitState()->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + } + + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uFresnelMap", GLSLTextUnit); + GLSLTextUnit++; + } + UM_Technique0_Pass0->createTextureUnitState("Fresnel.bmp")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + + /* Foam is not visible underwater + if (cFoam) + { + if(Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uFoamMap", GLSLTextUnit); + GLSLTextUnit++; + } + UM_Technique0_Pass0->createTextureUnitState("Foam.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + } + */ + + UnderwaterMaterial->setReceiveShadows(false); + UnderwaterMaterial->load(); + + return true; + } + + bool MaterialManager::_createUnderwaterCompositor(const HydraxComponent &Components, const Options &Options) + { + const bool cCaustics = _isComponent(Components, HYDRAX_COMPONENT_CAUSTICS); + const bool cDepth = _isComponent(Components, HYDRAX_COMPONENT_DEPTH); + const bool cGodRays = _isComponent(Components, HYDRAX_COMPONENT_UNDERWATER_GODRAYS); + + Ogre::String VertexProgramData, FragmentProgramData; + + // Vertex program + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float3 oPosition_ : TEXCOORD0,\n" + + "out float2 oUV : TEXCOORD1,\n"; + // UNIFORM + if (cGodRays) + { + VertexProgramData += Ogre::String("uniform float3 uCorner0,\n") + "uniform float3 uCorner01,\n" + + "uniform float3 uCorner02,\n"; + } + VertexProgramData += Ogre::String("uniform float4x4 uWorldViewProj)\n") + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + "iPosition.xy = sign(iPosition.xy);\n" + + "oUV = (float2(iPosition.x, -iPosition.y) + 1.0f) * 0.5f;"; + if (cGodRays) + { + VertexProgramData += Ogre::String("uCorner01 *= oUV.x;\n") + "uCorner02 *= oUV.y;\n" + + "oPosition_ = uCorner0+uCorner01+uCorner02;"; + } + VertexProgramData += "}\n"; + } + break; + + case SM_GLSL: + { + VertexProgramData += Ogre::String("\n"); + // UNIFORMS + if (cGodRays) + { + VertexProgramData += + Ogre::String("uniform vec3 uCorner0;\n") + "uniform vec3 uCorner01;\n" + "uniform vec3 uCorner02;\n"; + } + // IN + // OUT + VertexProgramData += Ogre::String("varying vec3 Position_;\n") + "varying vec2 UV;\n" + + // main function + "void main()\n" + "{\n" + "gl_Position = ftransform();\n" + + "vec2 iPosition = sign(gl_Vertex.xy);\n" + + "UV = (vec2(iPosition.x, -iPosition.y) + 1.0) * 0.5;\n"; + if (cGodRays) + { + VertexProgramData += Ogre::String("vec3 vCorner01 = uCorner01 * UV.x;\n") + + "vec3 vCorner02 = uCorner02 * UV.y;\n" + "Position_ = uCorner0+vCorner01+vCorner02;\n"; + } + VertexProgramData += "}\n"; + } + break; + } + + // Fragment program + switch (Options.SM) + { + case SM_HLSL: + case SM_CG: + { + FragmentProgramData += Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition : TEXCOORD0,\n" + "float2 iUV : TEXCOORD1,\n" + + // OUT + "out float4 oColor : COLOR,\n"; + // UNIFORM + if (cCaustics) { FragmentProgramData += "uniform float uCausticsPower,\n"; } + if (cGodRays) + { + FragmentProgramData += Ogre::String("uniform float3 uSunColor,\n") + "uniform float3 uLightDirection,\n" + + "uniform float uIntensity,\n" + "uniform float3 uHGg,\n" + + "uniform float3 uCameraPos,\n"; + } + FragmentProgramData += Ogre::String("uniform float uTime,\n") + "uniform float3 uWaterColor,\n" + + "uniform sampler2D uOriginalMap : register(s0),\n" + + "uniform sampler2D uDistortMap : register(s1)\n"; + if (cDepth) { FragmentProgramData += ",\nuniform sampler2D uDepthMap : register(s2)"; } + FragmentProgramData += + Ogre::String(")\n") + "{\n" + + "float2 distortUV = (tex2D(uDistortMap, float2(iUV.x + uTime, iUV.y + uTime)).xy - 0.5)/50.0;\n"; + if (cCaustics) // Depth, caustics + { + FragmentProgramData += Ogre::String("float2 depth = tex2D(uDepthMap, iUV+distortUV).xy;\n") + + "float4 Color = float4(lerp(uWaterColor,tex2D(uOriginalMap, " + "iUV+distortUV)*(1.0+depth.y*uCausticsPower), depth.x),1.0);\n"; + if (cGodRays) + { + FragmentProgramData += Ogre::String("float3 view_vector = normalize(iPosition-uCameraPos);\n") + + "float dot_product = dot(view_vector, -uLightDirection);\n" + "float num = uHGg.x;\n" + + "float den = (uHGg.y - uHGg.z*dot_product);\n" + "den = rsqrt(den);\n" + + "float phase = num * (den*den*den);\n" + + "Color.xyz += (0.15 + uIntensity*tex2D(uDepthMap, iUV).z)*phase*uSunColor;\n"; + } + } + else if (cDepth) // Depth, no caustics + { + FragmentProgramData += "float4 Color = float4(lerp(uWaterColor,tex2D(uOriginalMap, " + "iUV+distortUV).xyz,tex2D(uDepthMap, iUV+distortUV).r),1.0);\n"; + if (cGodRays) + { + FragmentProgramData += Ogre::String("float3 view_vector = normalize(iPosition-uCameraPos);") + + "float dot_product = dot(view_vector, -uLightDirection);" + "float num = uHGg.x;" + + "float den = (uHGg.y - uHGg.z*dot_product); " + "den = rsqrt(den); " + + "float phase = num * (den*den*den);" + + "Color.xyz += (0.15 + uIntensity*tex2D(uDepthMap, iUV).y)*phase*uSunColor;"; + } + } + else // No depth, no caustics + { + FragmentProgramData += "float4 Color = tex2D(uOriginalMap, iUV+distortUV);"; + } + FragmentProgramData += Ogre::String("oColor = Color;\n") + "}\n"; + } + break; + + case SM_GLSL: + { + FragmentProgramData += Ogre::String("\n"); + // UNIFORM + if (cCaustics) { FragmentProgramData += "uniform float uCausticsPower;\n"; } + if (cGodRays) + { + FragmentProgramData += Ogre::String("uniform vec3 uSunColor;\n") + "uniform vec3 uLightDirection;\n" + + "uniform float uIntensity;\n" + "uniform vec3 uHGg;\n" + "uniform vec3 uCameraPos;\n"; + } + FragmentProgramData += Ogre::String("uniform float uTime;\n") + "uniform float uGlobalTransparency;\n" + + "uniform vec3 uWaterColor;\n" + "uniform sampler2D uOriginalMap;\n" + + "uniform sampler2D uDistortMap;\n"; + if (cDepth) { FragmentProgramData += "uniform sampler2D uDepthMap;\n"; } + // IN + FragmentProgramData += Ogre::String("varying vec3 Position_;\n") + "varying vec2 UV;\n" + + // OUT + // main function + "void main()\n" + "{\n" + + "vec2 distortUV = (texture2D(uDistortMap, vec2(UV.x + uTime, UV.y + uTime)).xy - 0.5)*0.02;\n"; + // "vec2 distortUV = vec2(0.0,0.0);\n"; + if (cCaustics) // Depth, caustics + { + FragmentProgramData += Ogre::String("vec2 depth = texture2D(uDepthMap, UV+distortUV).xy;\n") + + "gl_FragColor = vec4(mix(uWaterColor,texture2D(uOriginalMap, " + "UV+distortUV).xyz*(1.0+depth.y*uCausticsPower), depth.x),1.0);\n"; + if (cGodRays) + { + FragmentProgramData += Ogre::String("vec3 view_vector = normalize(Position_-uCameraPos);\n") + + "float dot_product = dot(view_vector, -uLightDirection);\n" + "float num = uHGg.x;\n" + + "float den = (uHGg.y - uHGg.z*dot_product);\n" + "den = inversesqrt(den);\n" + + "float phase = num * pow(den, 3.0);\n" + + "gl_FragColor.xyz += (0.15 + uIntensity*texture2D(uDepthMap, UV).z)*phase*uSunColor;"; + } + } + else if (cDepth) // Depth, no caustics + { + FragmentProgramData += "gl_FragColor = vec4(mix(uWaterColor,texture2D(uOriginalMap, " + "UV+distortUV).xyz,texture2D(uDepthMap, UV+distortUV).r),1.0);\n"; + if (cGodRays) + { + FragmentProgramData += + Ogre::String("vec3 view_vector = normalize(Position_-uCameraPos);\n") + + "float dot_product = dot(view_vector, -uLightDirection);\n" + "float num = uHGg.x;\n" + + "float den = (uHGg.y - uHGg.z*dot_product);\n" + "den = inversesqrt(den);\n" + + "float phase = num * pow(den, 3.0);\n" + + "gl_FragColor.xyz += (0.15 + uIntensity*texture2D(uDepthMap, UV).z)*phase*uSunColor;\n"; + } + } + else // No depth, no caustics + { + FragmentProgramData += "gl_FragColor = texture2D(uOriginalMap, UV+distortUV);\n"; + } + FragmentProgramData += "}\n"; + } + break; + } + + // Build our material + Ogre::MaterialPtr &UnderwaterCompositorMaterial = getMaterial(MAT_UNDERWATER_COMPOSITOR); + UnderwaterCompositorMaterial = Ogre::MaterialManager::getSingleton().create( + _def_Underwater_Compositor_Material_Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *DM_Technique0_Pass0 = UnderwaterCompositorMaterial->getTechnique(0)->getPass(0); + + DM_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + DM_Technique0_Pass0->setDepthFunction(Ogre::CMPF_ALWAYS_PASS); + + Ogre::String GpuProgramsData[2] = {VertexProgramData, FragmentProgramData}; + Ogre::String GpuProgramNames[2] = {_def_Underwater_Compositor_Shader_VP_Name, _def_Underwater_Compositor_Shader_FP_Name}; + Ogre::String EntryPoints[2]; + if (Options.SM == SM_GLSL) + { + EntryPoints[0] = Ogre::String("main"); + EntryPoints[1] = Ogre::String("main"); + } + else + { + EntryPoints[0] = Ogre::String("main_vp"); + EntryPoints[1] = Ogre::String("main_fp"); + } + + fillGpuProgramsToPass(DM_Technique0_Pass0, GpuProgramNames, Options.SM, EntryPoints, GpuProgramsData); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique0_Pass0->getFragmentProgramParameters(); + + if (Options.SM != SM_GLSL) + { VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } + + FP_Parameters->setNamedConstantFromTime("uTime", 0.1f); + FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); + + if (cCaustics) { FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); } + + if (cGodRays) + { + FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); + FP_Parameters->setNamedConstant("uLightDirection", + (mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getCamera()->getPosition()) - + mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())) + .normalisedCopy()); + FP_Parameters->setNamedConstant("uIntensity", mHydrax->getGodRaysIntensity()); + FP_Parameters->setNamedConstant("uHGg", mHydrax->getGodRaysExposure()); + FP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); + } + + // From compositor, original scene + int GLSLTextUnit = 0; + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uOriginalMap", GLSLTextUnit); + GLSLTextUnit++; + } + DM_Technique0_Pass0->createTextureUnitState()->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uDistortMap", GLSLTextUnit); + GLSLTextUnit++; + } + DM_Technique0_Pass0->createTextureUnitState("UnderwaterDistortion.jpg") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + if (cDepth) + { + if (Options.SM == SM_GLSL) + { + FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit); + GLSLTextUnit++; + } + DM_Technique0_Pass0->createTextureUnitState("HydraxDepthMap") + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + // Ogre::Viewport *Viewport = mHydrax->getCamera()->getViewport(); + } + + UnderwaterCompositorMaterial->setReceiveShadows(false); + UnderwaterCompositorMaterial->load(); + + Ogre::CompositorPtr &UnderwaterCompositor = getCompositor(COMP_UNDERWATER); + UnderwaterCompositor = Ogre::CompositorManager::getSingleton().create( + _def_Underwater_Compositor_Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::CompositionTechnique *UnderWaterComp_Technique = UnderwaterCompositor->createTechnique(); + + // Create the texture definition to render the original scene + Ogre::CompositionTechnique::TextureDefinition *TDef = UnderWaterComp_Technique->createTextureDefinition("OriginalScene"); + TDef->width = 0; + TDef->height = 0; + Ogre::PixelFormatList l; + l.push_back(Ogre::PF_A8R8G8B8); + TDef->formatList = l; + + // Render the original scene + Ogre::CompositionTargetPass *CTPass = UnderWaterComp_Technique->createTargetPass(); + CTPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE); + CTPass->setOutputName("OriginalScene"); + Ogre::CompositionPass *CPassClear = CTPass->createPass(); + CPassClear->setType(Ogre::CompositionPass::PT_CLEAR); + + const Ogre::Vector3 &WC = mHydrax->getWaterColor(); + CPassClear->setClearColour(Ogre::ColourValue(WC.x, WC.y, WC.z)); + + Ogre::CompositionPass *CPass = CTPass->createPass(); + CPass->setType(Ogre::CompositionPass::PT_RENDERSCENE); + CPass->setFirstRenderQueue(Ogre::RENDER_QUEUE_SKIES_EARLY + 1); + + // Build the output target pass + Ogre::CompositionTargetPass *CTOutputPass = UnderWaterComp_Technique->getOutputTargetPass(); + CTOutputPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE); + + // Final composition pass + Ogre::CompositionPass *COutputPass = CTOutputPass->createPass(); + COutputPass->setType(Ogre::CompositionPass::PT_RENDERQUAD); + COutputPass->setMaterial(getMaterial(MAT_UNDERWATER_COMPOSITOR)); + COutputPass->setInput(0, "OriginalScene"); + COutputPass->setLastRenderQueue(0); + + Ogre::CompositorManager::getSingleton() + .addCompositor(mHydrax->getViewport(), _def_Underwater_Compositor_Name) + ->addListener(&mUnderwaterCompositorListener); + + return true; + } + + bool MaterialManager::_createSimpleColorMaterial(const Ogre::ColourValue &Color, const MaterialType &MT, + const Ogre::String &Name, const bool &DepthCheck, const bool &DepthWrite) + { + Ogre::MaterialPtr &SimpleColorMaterial = getMaterial(MT); + SimpleColorMaterial = + Ogre::MaterialManager::getSingleton().create(Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *SCM_T0_Pass0 = SimpleColorMaterial->getTechnique(0)->getPass(0); + SCM_T0_Pass0->setLightingEnabled(false); + SCM_T0_Pass0->setDepthCheckEnabled(DepthCheck); + SCM_T0_Pass0->setDepthWriteEnabled(DepthWrite); + SCM_T0_Pass0->setCullingMode(Ogre::CULL_NONE); + SCM_T0_Pass0->createTextureUnitState()->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, + Color); + + SimpleColorMaterial->setReceiveShadows(false); + SimpleColorMaterial->load(); + + return true; + } + + void MaterialManager::reload(const MaterialType &Material) + { + Ogre::MaterialPtr &Mat = getMaterial(Material); + + if (Mat.isNull()) { return; } + + Mat->reload(); + + const bool cDepth = _isComponent(mComponents, HYDRAX_COMPONENT_DEPTH); + const bool cSmooth = _isComponent(mComponents, HYDRAX_COMPONENT_SMOOTH); + const bool cSun = _isComponent(mComponents, HYDRAX_COMPONENT_SUN); + const bool cFoam = _isComponent(mComponents, HYDRAX_COMPONENT_FOAM); + const bool cCaustics = _isComponent(mComponents, HYDRAX_COMPONENT_CAUSTICS); + const bool cUReflections = _isComponent(mComponents, HYDRAX_COMPONENT_UNDERWATER_REFLECTIONS); + + switch (Material) + { + case MAT_WATER: + { + Ogre::Pass *M_Technique0_Pass0 = Mat->getTechnique(0)->getPass(0); + + switch (mOptions.NM) + { + case NM_TEXTURE: + case NM_RTT: + { + M_Technique0_Pass0->getTextureUnitState(0)->setTextureName("HydraxNormalMap"); + M_Technique0_Pass0->getTextureUnitState(1)->setTextureName("HydraxReflectionMap"); + M_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxRefractionMap"); + if (cDepth) { M_Technique0_Pass0->getTextureUnitState(3)->setTextureName("HydraxDepthMap"); } + } + break; + + case NM_VERTEX: + { + M_Technique0_Pass0->getTextureUnitState(0)->setTextureName("HydraxReflectionMap"); + M_Technique0_Pass0->getTextureUnitState(1)->setTextureName("HydraxRefractionMap"); + if (cDepth) { M_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap"); } + } + break; + } + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = M_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = M_Technique0_Pass0->getFragmentProgramParameters(); + + if (mOptions.SM != SM_GLSL) + { VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } + if (cFoam) { VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); } + FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + + FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); + FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); + FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); + + FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); + if (cSmooth) { FP_Parameters->setNamedConstant("uSmoothPower", mHydrax->getSmoothPower()); } + if (cSun) + { + FP_Parameters->setNamedConstant("uSunPosition", + mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); + FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); + FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); + FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); + } + if (cFoam) + { + FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); + FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); + FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); + FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); + FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); + } + if (cCaustics) { FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); } + } + break; + + case MAT_DEPTH: + { + Ogre::Pass *M_Technique0_Pass0 = Mat->getTechnique(0)->getPass(0); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = M_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = M_Technique0_Pass0->getFragmentProgramParameters(); + + if (mOptions.SM != SM_GLSL) + { + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + // VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); + } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); + VP_Parameters->setNamedConstant("uPlanesError", (float)mHydrax->getPlanesError()); + + FP_Parameters->setNamedConstant("uDepthLimit", 1.f / mHydrax->getDepthLimit()); + FP_Parameters->setNamedConstant("uDistLimit", 1.f / mHydrax->getDistLimit()); + + if (cCaustics) + { + FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); + FP_Parameters->setNamedConstant("uCausticsEnd", mHydrax->getCausticsEnd()); + } + } + break; + + case MAT_UNDERWATER: + { + Ogre::Pass *M_Technique0_Pass0 = Mat->getTechnique(0)->getPass(0); + + switch (mOptions.NM) + { + case NM_TEXTURE: + case NM_RTT: + { + M_Technique0_Pass0->getTextureUnitState(0)->setTextureName("HydraxNormalMap"); + int Index = 1; + if (cUReflections) + { + M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxReflectionMap"); + Index++; + } + M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxRefractionMap"); + Index++; + if (cDepth && cUReflections) + { M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxDepthReflectionMap"); } + } + break; + + case NM_VERTEX: + { + int Index = 0; + if (cUReflections) + { + M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxReflectionMap"); + Index++; + } + M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxRefractionMap"); + Index++; + if (cDepth && cUReflections) + { M_Technique0_Pass0->getTextureUnitState(Index)->setTextureName("HydraxDepthReflectionMap"); } + } + break; + } + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = M_Technique0_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = M_Technique0_Pass0->getFragmentProgramParameters(); + + if (mOptions.SM != SM_GLSL) + { + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VP_Parameters->setNamedAutoConstant("uWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + FP_Parameters->setNamedAutoConstant("uEyePosition", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + + FP_Parameters->setNamedConstant("uFullReflectionDistance", mHydrax->getFullReflectionDistance()); + FP_Parameters->setNamedConstant("uGlobalTransparency", mHydrax->getGlobalTransparency()); + FP_Parameters->setNamedConstant("uNormalDistortion", mHydrax->getNormalDistortion()); + FP_Parameters->setNamedConstant("uDistLimit", 1.f / mHydrax->getDistLimit()); + + if ((cDepth && cUReflections) || (!cUReflections)) + { FP_Parameters->setNamedConstant("uWaterColor", mHydrax->getWaterColor()); } + + if (cSun) + { + FP_Parameters->setNamedConstant("uSunPosition", + mHydrax->getMesh()->getObjectSpacePosition(mHydrax->getSunPosition())); + FP_Parameters->setNamedConstant("uSunStrength", mHydrax->getSunStrength()); + FP_Parameters->setNamedConstant("uSunArea", mHydrax->getSunArea()); + FP_Parameters->setNamedConstant("uSunColor", mHydrax->getSunColor()); + FP_Parameters->setNamedConstant("uDepthLimit", 1.f / mHydrax->getDistLimit()); + } + /* Foam is not visible underwater + if (cFoam) + { + FP_Parameters->setNamedConstant("uFoamRange", mHydrax->getMesh()->getOptions().MeshStrength); + FP_Parameters->setNamedConstant("uFoamMaxDistance", mHydrax->getFoamMaxDistance()); + FP_Parameters->setNamedConstant("uFoamScale", mHydrax->getFoamScale()); + FP_Parameters->setNamedConstant("uFoamStart", mHydrax->getFoamStart()); + FP_Parameters->setNamedConstant("uFoamTransparency", mHydrax->getFoamTransparency()); + } + */ + if (cCaustics && cDepth && cUReflections) + { FP_Parameters->setNamedConstant("uCausticsPower", mHydrax->getCausticsPower()); } + } + break; + + case MAT_UNDERWATER_COMPOSITOR: + { + mCompositorsNeedToBeReloaded[COMP_UNDERWATER] = true; + } + break; + + case MAT_SIMPLE_RED: + { + } + break; + case MAT_SIMPLE_BLACK: + { } - Ogre::TextureUnitState *TUS_AlphaTex = DM_Technique_Pass0->createTextureUnitState(TextureName); - TUS_AlphaTex->setName("_DetphTexture_Hydrax"); - TUS_AlphaTex->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + break; + } + } + + void MaterialManager::addDepthTechnique(Ogre::Technique *Technique, const bool &AutoUpdate) + { + if (!Ogre::MaterialManager::getSingleton().resourceExists(_def_Depth_Material_Name)) + { _createDepthMaterial(mComponents, mOptions); } - if (AutoUpdate) - { - mDepthTechniques.push_back(Technique); - } - } + Technique->removeAllPasses(); + Technique->createPass(); + Technique->setName("_Hydrax_Depth_Technique"); + Technique->setSchemeName("HydraxDepth"); - void MaterialManager::setCompositorEnable(const CompositorType &Compositor, const bool &Enable) - { - Ogre::CompositorPtr &Comp = mCompositors[static_cast(Compositor)]; + Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0); - if (Comp.isNull()) - { - return; - } + DM_Technique_Pass0->setVertexProgram(_def_Depth_Shader_VP_Name); + DM_Technique_Pass0->setFragmentProgram(_def_Depth_Shader_FP_Name); - Ogre::CompositorManager::getSingleton(). - setCompositorEnabled(mHydrax->getViewport(), Comp->getName(), Enable); + Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters(); + + if (mOptions.SM != SM_GLSL) + { + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); + } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); + VP_Parameters->setNamedConstant("uPlanesError", (float)mHydrax->getPlanesError()); - mCompositorsEnable[static_cast(Compositor)] = Enable; - } + FP_Parameters->setNamedConstant("uDepthLimit", 1 / mHydrax->getDepthLimit()); + FP_Parameters->setNamedConstant("uDistLimit", 1 / mHydrax->getDistLimit()); - bool MaterialManager::_isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const - { - if (List & ToCheck) + if (_isComponent(mComponents, HYDRAX_COMPONENT_CAUSTICS)) { - return true; + FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); + FP_Parameters->setNamedConstant("uCausticsEnd", mHydrax->getCausticsEnd()); + + if (mOptions.SM == SM_GLSL) { FP_Parameters->setNamedConstant("uCaustics", 0); } + Ogre::TextureUnitState *TUS_Caustics = DM_Technique_Pass0->createTextureUnitState("Caustics.bmp"); + TUS_Caustics->setName("Caustics"); + TUS_Caustics->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + TUS_Caustics->setAnimatedTextureName("Caustics.bmp", 32, 1.5); } - if (ToCheck == HYDRAX_COMPONENTS_NONE && List == HYDRAX_COMPONENTS_NONE) + if (AutoUpdate) { mDepthTechniques.push_back(Technique); } + } + + void MaterialManager::addDepthTextureTechnique(Ogre::Technique *Technique, const Ogre::String &TextureName, + const Ogre::String &AlphaChannel, const bool &AutoUpdate) + { + if (!Ogre::HighLevelGpuProgramManager::getSingleton().resourceExists(_def_DepthTexture_Shader_VP_Name + AlphaChannel)) + { _createDepthTextureGPUPrograms(mComponents, mOptions, AlphaChannel); } + + Technique->removeAllPasses(); + Technique->createPass(); + Technique->setName("_Hydrax_DepthTexture_Technique"); + Technique->setSchemeName("HydraxDepth"); + + Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0); + + // Alpha channel will be stored in pass 0 name: + DM_Technique_Pass0->setName(AlphaChannel); + + DM_Technique_Pass0->setVertexProgram(_def_DepthTexture_Shader_VP_Name + AlphaChannel); + DM_Technique_Pass0->setFragmentProgram(_def_DepthTexture_Shader_FP_Name + AlphaChannel); + + DM_Technique_Pass0->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); + DM_Technique_Pass0->setDepthCheckEnabled(true); + DM_Technique_Pass0->setDepthWriteEnabled(false); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters(); + Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters(); + + if (mOptions.SM != SM_GLSL) { - return true; + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION); } + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedConstant("uPlaneYPos", mHydrax->getPosition().y); + VP_Parameters->setNamedConstant("uPlanesError", (float)mHydrax->getPlanesError()); + + FP_Parameters->setNamedConstant("uDepthLimit", 1 / mHydrax->getDepthLimit()); + FP_Parameters->setNamedConstant("uDistLimit", 1 / mHydrax->getDistLimit()); - if (ToCheck == HYDRAX_COMPONENTS_ALL && List == HYDRAX_COMPONENTS_ALL) + if (_isComponent(mComponents, HYDRAX_COMPONENT_CAUSTICS)) { - return true; + FP_Parameters->setNamedConstant("uCausticsScale", mHydrax->getCausticsScale()); + FP_Parameters->setNamedConstant("uCausticsEnd", mHydrax->getCausticsEnd()); + + if (mOptions.SM == SM_GLSL) { FP_Parameters->setNamedConstant("uCaustics", 0); } + Ogre::TextureUnitState *TUS_Caustics = DM_Technique_Pass0->createTextureUnitState("Caustics.bmp"); + TUS_Caustics->setName("Caustics"); + TUS_Caustics->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + TUS_Caustics->setAnimatedTextureName("Caustics.bmp", 32, 1.5); } + if (mOptions.SM == SM_GLSL) { FP_Parameters->setNamedConstant("uAlphaTex", 0); } + Ogre::TextureUnitState *TUS_AlphaTex = DM_Technique_Pass0->createTextureUnitState(TextureName); + TUS_AlphaTex->setName("_DetphTexture_Hydrax"); + TUS_AlphaTex->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); + + if (AutoUpdate) { mDepthTechniques.push_back(Technique); } + } + + void MaterialManager::setCompositorEnable(const CompositorType &Compositor, const bool &Enable) + { + Ogre::CompositorPtr &Comp = mCompositors[static_cast(Compositor)]; + + if (Comp.isNull()) { return; } + + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mHydrax->getViewport(), Comp->getName(), Enable); + + mCompositorsEnable[static_cast(Compositor)] = Enable; + } + + bool MaterialManager::_isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const + { + if (List & ToCheck) { return true; } + + if (ToCheck == HYDRAX_COMPONENTS_NONE && List == HYDRAX_COMPONENTS_NONE) { return true; } + + if (ToCheck == HYDRAX_COMPONENTS_ALL && List == HYDRAX_COMPONENTS_ALL) { return true; } + return false; - } - - void MaterialManager::setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, const Ogre::Real &Value) - { - if (!mCreated) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - - if (MType == MAT_DEPTH) - { - std::vector::iterator TechIt; - - for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) - { - if (!(*TechIt)) - { - mDepthTechniques.erase(TechIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*TechIt)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*TechIt)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - } - } - } - - void MaterialManager::setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, const Ogre::Vector2 &Value) - { - if (!mCreated) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - float Value_[2] = {Value.x, Value.y}; - - if (MType == MAT_DEPTH) - { - std::vector::iterator TechIt; - - for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) - { - if (!(*TechIt)) - { - mDepthTechniques.erase(TechIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*TechIt)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*TechIt)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value_, 1, 2); - } - } - } - - void MaterialManager::setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, const Ogre::Vector3 &Value) - { - if (!mCreated) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - - if (MType == MAT_DEPTH) - { - std::vector::iterator TechIt; - - for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) - { - if (!(*TechIt)) - { - mDepthTechniques.erase(TechIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*TechIt)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*TechIt)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - } - } - } - - void MaterialManager::UnderwaterCompositorListener::notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat) - { - if (mMaterialManager->_isComponent(mMaterialManager->mComponents, HYDRAX_COMPONENT_DEPTH)) - { - Ogre::Pass* DM_Technique0_Pass0 = mat->getTechnique(0)->getPass(0); - DM_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap"); - } - } - - void MaterialManager::UnderwaterCompositorListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat) - { - const Ogre::Vector3& WC = mMaterialManager->mHydrax->getWaterColor(); - Ogre::CompositorPtr &UnderwaterCompositor = mMaterialManager->getCompositor(COMP_UNDERWATER); - UnderwaterCompositor->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(Ogre::ColourValue(WC.x, WC.y, WC.z)); - - Ogre::GpuProgramParametersSharedPtr FP_Parameters = mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - - if (mMaterialManager->mHydrax->isComponent(HYDRAX_COMPONENT_DEPTH)) - { - FP_Parameters-> - setNamedConstant("uWaterColor", mMaterialManager->mHydrax->getWaterColor()); - } - - if (mMaterialManager->mHydrax->isComponent(HYDRAX_COMPONENT_CAUSTICS)) - { - FP_Parameters-> - setNamedConstant("uCausticsPower", mMaterialManager->mHydrax->getCausticsPower()); - } - - if (mMaterialManager->mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) - { - FP_Parameters-> - setNamedConstant("uSunColor", mMaterialManager->mHydrax->getSunColor()); - - FP_Parameters->setNamedConstant("uLightDirection", - (mMaterialManager->mHydrax->getMesh()->getObjectSpacePosition(mMaterialManager->mHydrax->getCamera()->getPosition()) - - mMaterialManager->mHydrax->getMesh()->getObjectSpacePosition(mMaterialManager->mHydrax->getSunPosition())) - .normalisedCopy()); - - FP_Parameters->setNamedConstant("uIntensity", mMaterialManager->mHydrax->getGodRaysIntensity()); - FP_Parameters->setNamedConstant("uHGg", mMaterialManager->mHydrax->getGodRaysExposure()); - - Ogre::GpuProgramParametersSharedPtr VP_Parameters = mat->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - - // FAR_LEFT_TOP - VP_Parameters-> - setNamedConstant( "uCorner0", mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[5] ); - // FAR_RIGHT_TOP - FAR_LEFT_TOP - VP_Parameters-> - setNamedConstant( "uCorner01", mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[4] - mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[5]); - // FAR_LEFT_BOTTOM - FAR_LEFT_TOP - VP_Parameters-> - setNamedConstant( "uCorner02", mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[6] - mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[5]); - } - - /* + } + + void MaterialManager::setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, + const Ogre::Real &Value) + { + if (!mCreated) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + + if (MType == MAT_DEPTH) + { + std::vector::iterator TechIt; + + for (TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) + { + if (!(*TechIt)) + { + mDepthTechniques.erase(TechIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*TechIt)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*TechIt)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + } + } + } + + void MaterialManager::setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, + const Ogre::Vector2 &Value) + { + if (!mCreated) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + float Value_[2] = {Value.x, Value.y}; + + if (MType == MAT_DEPTH) + { + std::vector::iterator TechIt; + + for (TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) + { + if (!(*TechIt)) + { + mDepthTechniques.erase(TechIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*TechIt)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*TechIt)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value_, 1, 2); + } + } + } + + void MaterialManager::setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, + const Ogre::Vector3 &Value) + { + if (!mCreated) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = getMaterial(MType)->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + + if (MType == MAT_DEPTH) + { + std::vector::iterator TechIt; + + for (TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++) + { + if (!(*TechIt)) + { + mDepthTechniques.erase(TechIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*TechIt)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*TechIt)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + } + } + } + + void MaterialManager::UnderwaterCompositorListener::notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat) + { + if (mMaterialManager->_isComponent(mMaterialManager->mComponents, HYDRAX_COMPONENT_DEPTH)) + { + Ogre::Pass *DM_Technique0_Pass0 = mat->getTechnique(0)->getPass(0); + DM_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap"); + } + } + + void MaterialManager::UnderwaterCompositorListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat) + { + const Ogre::Vector3 &WC = mMaterialManager->mHydrax->getWaterColor(); + Ogre::CompositorPtr &UnderwaterCompositor = mMaterialManager->getCompositor(COMP_UNDERWATER); + UnderwaterCompositor->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(Ogre::ColourValue(WC.x, WC.y, WC.z)); + + Ogre::GpuProgramParametersSharedPtr FP_Parameters = mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + + if (mMaterialManager->mHydrax->isComponent(HYDRAX_COMPONENT_DEPTH)) + { FP_Parameters->setNamedConstant("uWaterColor", mMaterialManager->mHydrax->getWaterColor()); } + + if (mMaterialManager->mHydrax->isComponent(HYDRAX_COMPONENT_CAUSTICS)) + { FP_Parameters->setNamedConstant("uCausticsPower", mMaterialManager->mHydrax->getCausticsPower()); } + + if (mMaterialManager->mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER_GODRAYS)) + { + FP_Parameters->setNamedConstant("uSunColor", mMaterialManager->mHydrax->getSunColor()); + + FP_Parameters->setNamedConstant("uLightDirection", (mMaterialManager->mHydrax->getMesh()->getObjectSpacePosition( + mMaterialManager->mHydrax->getCamera()->getPosition()) - + mMaterialManager->mHydrax->getMesh()->getObjectSpacePosition( + mMaterialManager->mHydrax->getSunPosition())) + .normalisedCopy()); + + FP_Parameters->setNamedConstant("uIntensity", mMaterialManager->mHydrax->getGodRaysIntensity()); + FP_Parameters->setNamedConstant("uHGg", mMaterialManager->mHydrax->getGodRaysExposure()); + + Ogre::GpuProgramParametersSharedPtr VP_Parameters = mat->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + + // FAR_LEFT_TOP + VP_Parameters->setNamedConstant("uCorner0", mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[5]); + // FAR_RIGHT_TOP - FAR_LEFT_TOP + VP_Parameters->setNamedConstant("uCorner01", mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[4] - + mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[5]); + // FAR_LEFT_BOTTOM - FAR_LEFT_TOP + VP_Parameters->setNamedConstant("uCorner02", mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[6] - + mMaterialManager->mHydrax->getCamera()->getWorldSpaceCorners()[5]); + } + + /* if (mMaterialManager->_isComponent(mMaterialManager->mComponents, HYDRAX_COMPONENT_DEPTH)) { Ogre::Viewport *Viewport = mMaterialManager->mHydrax->getCamera()->getViewport(); } - */ + */ - if (mMaterialManager->mCompositorsNeedToBeReloaded[COMP_UNDERWATER]) - { - if (mMaterialManager->_isComponent(mMaterialManager->mComponents, HYDRAX_COMPONENT_DEPTH)) - { - Ogre::Pass* DM_Technique0_Pass0 = mat->getTechnique(0)->getPass(0); - DM_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap"); - } + if (mMaterialManager->mCompositorsNeedToBeReloaded[COMP_UNDERWATER]) + { + if (mMaterialManager->_isComponent(mMaterialManager->mComponents, HYDRAX_COMPONENT_DEPTH)) + { + Ogre::Pass *DM_Technique0_Pass0 = mat->getTechnique(0)->getPass(0); + DM_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap"); + } - mMaterialManager->mCompositorsNeedToBeReloaded[COMP_UNDERWATER] = false; - } - } -} + mMaterialManager->mCompositorsNeedToBeReloaded[COMP_UNDERWATER] = false; + } + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/MaterialManager.h b/source/main/gfx/hydrax/MaterialManager.h index 3f24b1c424..d7b467be6d 100644 --- a/source/main/gfx/hydrax/MaterialManager.h +++ b/source/main/gfx/hydrax/MaterialManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,356 +25,350 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_MaterialManager_H_ #define _Hydrax_MaterialManager_H_ -#include "Prerequisites.h" - #include "Enums.h" +#include "Prerequisites.h" namespace Hydrax { - class Hydrax; - - /** Material/Shader manager class - */ - class MaterialManager - { - public: - /** Material type enum - @remarks Use in getMaterial(MaterialType) - */ - enum MaterialType - { - // Water material - MAT_WATER = 0, - // Depth material - MAT_DEPTH = 1, - // Underwater material - MAT_UNDERWATER = 2, - // Compositor material(material wich is used in underwater compositor) - MAT_UNDERWATER_COMPOSITOR = 3, - // Simple red material - MAT_SIMPLE_RED = 4, - // Simple black material - MAT_SIMPLE_BLACK = 5 - }; - - /** Compositor type enum - @remarks Use in getCompositor(CompositorType) - */ - enum CompositorType - { - // Underwater compositor - COMP_UNDERWATER = 0 - }; - - /** Gpu program enum - @remarks Use in setGpuProgramParameter() - */ - enum GpuProgram - { - // Vertex program - GPUP_VERTEX = 0, - // Fragment program - GPUP_FRAGMENT = 1 - }; - - /** Shader mode - */ - enum ShaderMode - { - // HLSL - SM_HLSL = 0, - // Cg - SM_CG = 1, - // GLSL - SM_GLSL = 2 - }; - - /** Normal generation mode - */ - enum NormalMode - { - // Normal map from precomputed texture(CPU) - NM_TEXTURE = 0, - // Normal map from vertex(CPU) - NM_VERTEX = 1, - // Normal map from RTT(GPU) - NM_RTT = 2 - }; - - /** Material options - */ - struct Options - { - /** Default constructor - */ - Options() - : SM(SM_HLSL) - , NM(NM_TEXTURE) - { - } - - /** Constructor - @param _SM Shader mode - @param _NM Normal generation mode - */ - Options(const ShaderMode &_SM, - const NormalMode &_NM) - : SM(_SM) - , NM(_NM) - { - } - - /// Shader mode - ShaderMode SM; - /// Normal map generation mode - NormalMode NM; - }; - - /** Underwater compositor listener - */ - class UnderwaterCompositorListener : public Ogre::CompositorInstance::Listener - { - public: - /// On material setup - void notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat); - - /// On material render - void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat); - - /// Material manager parent pointer - MaterialManager *mMaterialManager; - }; - - /** Constructor - @param h Hydrax pointer - */ - MaterialManager(Hydrax *h); - - /** Destructor - */ + class Hydrax; + + /** Material/Shader manager class + */ + class MaterialManager + { + public: + /** Material type enum + @remarks Use in getMaterial(MaterialType) + */ + enum MaterialType + { + // Water material + MAT_WATER = 0, + // Depth material + MAT_DEPTH = 1, + // Underwater material + MAT_UNDERWATER = 2, + // Compositor material(material wich is used in underwater compositor) + MAT_UNDERWATER_COMPOSITOR = 3, + // Simple red material + MAT_SIMPLE_RED = 4, + // Simple black material + MAT_SIMPLE_BLACK = 5 + }; + + /** Compositor type enum + @remarks Use in getCompositor(CompositorType) + */ + enum CompositorType + { + // Underwater compositor + COMP_UNDERWATER = 0 + }; + + /** Gpu program enum + @remarks Use in setGpuProgramParameter() + */ + enum GpuProgram + { + // Vertex program + GPUP_VERTEX = 0, + // Fragment program + GPUP_FRAGMENT = 1 + }; + + /** Shader mode + */ + enum ShaderMode + { + // HLSL + SM_HLSL = 0, + // Cg + SM_CG = 1, + // GLSL + SM_GLSL = 2 + }; + + /** Normal generation mode + */ + enum NormalMode + { + // Normal map from precomputed texture(CPU) + NM_TEXTURE = 0, + // Normal map from vertex(CPU) + NM_VERTEX = 1, + // Normal map from RTT(GPU) + NM_RTT = 2 + }; + + /** Material options + */ + struct Options + { + /** Default constructor + */ + Options() : SM(SM_HLSL), NM(NM_TEXTURE) + { + } + + /** Constructor + @param _SM Shader mode + @param _NM Normal generation mode + */ + Options(const ShaderMode &_SM, const NormalMode &_NM) : SM(_SM), NM(_NM) + { + } + + /// Shader mode + ShaderMode SM; + /// Normal map generation mode + NormalMode NM; + }; + + /** Underwater compositor listener + */ + class UnderwaterCompositorListener : public Ogre::CompositorInstance::Listener + { + public: + /// On material setup + void notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat); + + /// On material render + void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat); + + /// Material manager parent pointer + MaterialManager *mMaterialManager; + }; + + /** Constructor + @param h Hydrax pointer + */ + MaterialManager(Hydrax *h); + + /** Destructor + */ ~MaterialManager(); - /** Create materials - @param Components Components of the shader - @param Options Material options - */ - bool createMaterials(const HydraxComponent &Components, const Options &Options); - - /** Remove materials - @remarks removeCompositor() is called too. - */ - void removeMaterials(); - - /** Remove compositor - */ - void removeCompositor(); - - /** Reload material - @param Material Material to reload - */ - void reload(const MaterialType &Material); - - /** Fill GPU vertex and fragment program to a pass - @param Pass Pass to fill Gpu programs - @param GpuProgramNames [0]: Vertex program name, [1]: Fragment program name - @param SM Shader mode, note: Provided data strings will correspong with selected shader mode - @param EntryPoints [0]: Vertex program entry point, [1]: Fragment program entry point - @param Data [0] Vertex program data, [1]: Fragment program data - */ - bool fillGpuProgramsToPass(Ogre::Pass* Pass, - const Ogre::String GpuProgramNames[2], - const ShaderMode& SM, - const Ogre::String EntryPoints[2], - const Ogre::String Data[2]); - - /** Create GPU program - @param Name HighLevelGpuProgram name - @param SM Shader mode - @param GPUP GpuProgram type - @param EntryPoint Entry point - @param Data - */ - bool createGpuProgram(const Ogre::String &Name, - const ShaderMode& SM, - const GpuProgram& GPUP, - const Ogre::String& EntryPoint, - const Ogre::String& Data); - - /** Is createMaterials() already called? - @return true If yes - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Get material - @param Material Material to get - @return Material to get - */ - inline Ogre::MaterialPtr &getMaterial(const MaterialType &Material) - { - return mMaterials[static_cast(Material)]; - } - - /** Get compositor - @param Compositor to get - @return Compositor to get - */ - inline Ogre::CompositorPtr &getCompositor(const CompositorType &Compositor) - { - return mCompositors[static_cast(Compositor)]; - } - - /** Is the compositor enable? - @param Compositor compositor to check - @return true if it's enabled - */ - inline const bool& isCompositorEnable(const CompositorType &Compositor) const - { - return mCompositorsEnable[static_cast(Compositor)]; - } - - /** Set a compositor enable/disable - @param Compositor compositor to change - @param Enable true to enable, false to disable - */ - void setCompositorEnable(const CompositorType &Compositor, const bool &Enable); - - /** Get the last MaterialManager::Options used in a material generation - @return Last MaterialManager::Options used in a material generation - */ - inline const Options &getLastOptions() const - { - return mOptions; - } - - /** Add depth technique to an especified material - @param Technique Technique where depth technique will be added - @param AutoUpdate The technique will be automatically updated when water parameters change - @remarks Call it after Hydrax::create()/Hydrax::setComponents(...) - - The technique will be automatically updated when water parameters change if parameter AutoUpdate == true - Add depth technique when a material is not an Ogre::Entity, such terrains, PLSM2 materials, etc. - This depth technique will be added with "HydraxDepth" scheme in ordeto can use it in the Depth RTT. - */ - void addDepthTechnique(Ogre::Technique *Technique, const bool& AutoUpdate = true); - - /** Add depth texture technique to an especified material - @param Technique Technique where depth technique will be added - @param TextureName Texture name - @param AlphaChannel "x","y","z","w" or "r","g","b","a" (Channel where alpha information is stored) - @param AutoUpdate The technique will be automatically updated when water parameters change - @remarks Call it after Hydrax::create()/Hydrax::setComponents(...) - - The technique will be automatically updated when water parameters change if parameter AutoUpdate == true - Add depth technique when a material is not an Ogre::Entity, such terrains, PLSM2 materials, etc. - This depth technique will be added with "HydraxDepth" scheme in ordeto can use it in the Depth RTT. - */ - void addDepthTextureTechnique(Ogre::Technique *Technique, const Ogre::String& TextureName, const Ogre::String& AlphaChannel = "w", const bool& AutoUpdate = true); - - /** Get external depth techniques - @return std::vector of external depth techniques - */ - inline std::vector &getDepthTechniques() - { - return mDepthTechniques; - } - - /** Set gpu program Ogre::Real parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param MType Water/Depth material - @param Name param name - @param Value value - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, const Ogre::Real &Value); - - /** Set gpu program Ogre::Vector2 parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param MType Water/Depth material - @param Name param name - @param Value value - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, const Ogre::Vector2 &Value); - - /** Set gpu program Ogre::Vector3 parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param MType Water/Depth material - @param Name param name - @param Value value - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, const Ogre::Vector3 &Value); - - private: - /** Is component in the given list? - @param List Components list - @param ToCheck Component to check - @return true if the component is in the given list. - */ - bool _isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const; - - /** Create water material - @param Components Components of the shader - @param Options Material options - */ - bool _createWaterMaterial(const HydraxComponent &Components, const Options &Options); - - /** Create depth material - @param Components Components of the shader - @param Options Material options - */ - bool _createDepthMaterial(const HydraxComponent &Components, const Options &Options); - - /** Create depth texture gpu programs - @param Components Components of the sahder - @param Options Material options - @param AlphaChannel "x","y","z","w" or "r","g","b","a" (Channel where alpha information is stored) - @return true if no problems had happend, false if yes - */ - bool _createDepthTextureGPUPrograms(const HydraxComponent &Components, const Options &Options, const Ogre::String& AlphaChannel); - - /** Create underwater material - @param Components Components of the shader - @param Options Material options - */ - bool _createUnderwaterMaterial(const HydraxComponent &Components, const Options &Options); - - /** Create underwater compositor - @param Components Components of the shader - @param Options Material options - */ - bool _createUnderwaterCompositor(const HydraxComponent &Components, const Options &Options); - - /** Create a simple color material - @param Colour Material color - @param MT Material type - @param Name Material name - @param DepthCheck Depth check enabled - @param DepthWrite Depth write enabled - */ - bool _createSimpleColorMaterial(const Ogre::ColourValue& Color, const MaterialType& MT, const Ogre::String& Name, const bool& DepthCheck = true, const bool& DepthWrite = true); - - /// Is createMaterials() already called? - bool mCreated; - /// Hydrax materials vector - Ogre::MaterialPtr mMaterials[6]; - /// Hydrax compositors vector - Ogre::CompositorPtr mCompositors[1]; - /// Hydrax compositors boolean: Need to be reloaded? - bool mCompositorsNeedToBeReloaded[1]; - /// Hydrax compostor enable vector - bool mCompositorsEnable[1]; - /// Technique vector for addDepthTechnique(...) - std::vector mDepthTechniques; - /// Actual material components - HydraxComponent mComponents; - /// Actual material options - Options mOptions; - /// Underwater compositor listener - UnderwaterCompositorListener mUnderwaterCompositorListener; - /// Hydrax main pointer - Hydrax *mHydrax; - }; -}; + /** Create materials + @param Components Components of the shader + @param Options Material options + */ + bool createMaterials(const HydraxComponent &Components, const Options &Options); + + /** Remove materials + @remarks removeCompositor() is called too. + */ + void removeMaterials(); + + /** Remove compositor + */ + void removeCompositor(); + + /** Reload material + @param Material Material to reload + */ + void reload(const MaterialType &Material); + + /** Fill GPU vertex and fragment program to a pass + @param Pass Pass to fill Gpu programs + @param GpuProgramNames [0]: Vertex program name, [1]: Fragment program name + @param SM Shader mode, note: Provided data strings will correspong with selected shader mode + @param EntryPoints [0]: Vertex program entry point, [1]: Fragment program entry point + @param Data [0] Vertex program data, [1]: Fragment program data + */ + bool fillGpuProgramsToPass(Ogre::Pass *Pass, const Ogre::String GpuProgramNames[2], const ShaderMode &SM, + const Ogre::String EntryPoints[2], const Ogre::String Data[2]); + + /** Create GPU program + @param Name HighLevelGpuProgram name + @param SM Shader mode + @param GPUP GpuProgram type + @param EntryPoint Entry point + @param Data + */ + bool createGpuProgram(const Ogre::String &Name, const ShaderMode &SM, const GpuProgram &GPUP, + const Ogre::String &EntryPoint, const Ogre::String &Data); + + /** Is createMaterials() already called? + @return true If yes + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Get material + @param Material Material to get + @return Material to get + */ + inline Ogre::MaterialPtr &getMaterial(const MaterialType &Material) + { + return mMaterials[static_cast(Material)]; + } + + /** Get compositor + @param Compositor to get + @return Compositor to get + */ + inline Ogre::CompositorPtr &getCompositor(const CompositorType &Compositor) + { + return mCompositors[static_cast(Compositor)]; + } + + /** Is the compositor enable? + @param Compositor compositor to check + @return true if it's enabled + */ + inline const bool &isCompositorEnable(const CompositorType &Compositor) const + { + return mCompositorsEnable[static_cast(Compositor)]; + } + + /** Set a compositor enable/disable + @param Compositor compositor to change + @param Enable true to enable, false to disable + */ + void setCompositorEnable(const CompositorType &Compositor, const bool &Enable); + + /** Get the last MaterialManager::Options used in a material generation + @return Last MaterialManager::Options used in a material generation + */ + inline const Options &getLastOptions() const + { + return mOptions; + } + + /** Add depth technique to an especified material + @param Technique Technique where depth technique will be added + @param AutoUpdate The technique will be automatically updated when water parameters change + @remarks Call it after Hydrax::create()/Hydrax::setComponents(...) + + The technique will be automatically updated when water parameters change if parameter AutoUpdate == true + Add depth technique when a material is not an Ogre::Entity, such terrains, PLSM2 materials, etc. + This depth technique will be added with "HydraxDepth" scheme in ordeto can use it in the Depth RTT. + */ + void addDepthTechnique(Ogre::Technique *Technique, const bool &AutoUpdate = true); + + /** Add depth texture technique to an especified material + @param Technique Technique where depth technique will be added + @param TextureName Texture name + @param AlphaChannel "x","y","z","w" or "r","g","b","a" (Channel where alpha information is stored) + @param AutoUpdate The technique will be automatically updated when water parameters change + @remarks Call it after Hydrax::create()/Hydrax::setComponents(...) + + The technique will be automatically updated when water parameters change if parameter AutoUpdate == true + Add depth technique when a material is not an Ogre::Entity, such terrains, PLSM2 materials, etc. + This depth technique will be added with "HydraxDepth" scheme in ordeto can use it in the Depth RTT. + */ + void addDepthTextureTechnique(Ogre::Technique *Technique, const Ogre::String &TextureName, + const Ogre::String &AlphaChannel = "w", const bool &AutoUpdate = true); + + /** Get external depth techniques + @return std::vector of external depth techniques + */ + inline std::vector &getDepthTechniques() + { + return mDepthTechniques; + } + + /** Set gpu program Ogre::Real parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param MType Water/Depth material + @param Name param name + @param Value value + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, + const Ogre::Real &Value); + + /** Set gpu program Ogre::Vector2 parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param MType Water/Depth material + @param Name param name + @param Value value + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, + const Ogre::Vector2 &Value); + + /** Set gpu program Ogre::Vector3 parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param MType Water/Depth material + @param Name param name + @param Value value + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const MaterialType &MType, const Ogre::String &Name, + const Ogre::Vector3 &Value); + + private: + /** Is component in the given list? + @param List Components list + @param ToCheck Component to check + @return true if the component is in the given list. + */ + bool _isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const; + + /** Create water material + @param Components Components of the shader + @param Options Material options + */ + bool _createWaterMaterial(const HydraxComponent &Components, const Options &Options); + + /** Create depth material + @param Components Components of the shader + @param Options Material options + */ + bool _createDepthMaterial(const HydraxComponent &Components, const Options &Options); + + /** Create depth texture gpu programs + @param Components Components of the sahder + @param Options Material options + @param AlphaChannel "x","y","z","w" or "r","g","b","a" (Channel where alpha information is stored) + @return true if no problems had happend, false if yes + */ + bool _createDepthTextureGPUPrograms(const HydraxComponent &Components, const Options &Options, + const Ogre::String &AlphaChannel); + + /** Create underwater material + @param Components Components of the shader + @param Options Material options + */ + bool _createUnderwaterMaterial(const HydraxComponent &Components, const Options &Options); + + /** Create underwater compositor + @param Components Components of the shader + @param Options Material options + */ + bool _createUnderwaterCompositor(const HydraxComponent &Components, const Options &Options); + + /** Create a simple color material + @param Colour Material color + @param MT Material type + @param Name Material name + @param DepthCheck Depth check enabled + @param DepthWrite Depth write enabled + */ + bool _createSimpleColorMaterial(const Ogre::ColourValue &Color, const MaterialType &MT, const Ogre::String &Name, + const bool &DepthCheck = true, const bool &DepthWrite = true); + + /// Is createMaterials() already called? + bool mCreated; + /// Hydrax materials vector + Ogre::MaterialPtr mMaterials[6]; + /// Hydrax compositors vector + Ogre::CompositorPtr mCompositors[1]; + /// Hydrax compositors boolean: Need to be reloaded? + bool mCompositorsNeedToBeReloaded[1]; + /// Hydrax compostor enable vector + bool mCompositorsEnable[1]; + /// Technique vector for addDepthTechnique(...) + std::vector mDepthTechniques; + /// Actual material components + HydraxComponent mComponents; + /// Actual material options + Options mOptions; + /// Underwater compositor listener + UnderwaterCompositorListener mUnderwaterCompositorListener; + /// Hydrax main pointer + Hydrax *mHydrax; + }; +}; // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/Mesh.cpp b/source/main/gfx/hydrax/Mesh.cpp index 92799db669..2f6c3e7e34 100644 --- a/source/main/gfx/hydrax/Mesh.cpp +++ b/source/main/gfx/hydrax/Mesh.cpp @@ -25,129 +25,110 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "Mesh.h" #include "Hydrax.h" + #include namespace Hydrax { - Mesh::Mesh(Hydrax *h) - : mHydrax(h) - , mCreated(false) - , mMesh() - , mSubMesh(0) - , mEntity(0) - , mNumFaces(0) - , mNumVertices(0) - , mVertexBuffer() - , mIndexBuffer() - , mSceneNode(0) - , mMaterialName("_NULL_") + Mesh::Mesh(Hydrax *h) + : mHydrax(h), mCreated(false), mMesh(), mSubMesh(0), mEntity(0), mNumFaces(0), mNumVertices(0), mVertexBuffer(), + mIndexBuffer(), mSceneNode(0), mMaterialName("_NULL_") { } Mesh::~Mesh() { - remove(); + remove(); + } + + void Mesh::remove() + { + if (!mCreated) { return; } + + mSceneNode->detachAllObjects(); + mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); + mSceneNode = 0; + + Ogre::MeshManager::getSingleton().remove("HydraxMesh"); + mHydrax->getSceneManager()->destroyEntity(mEntity); + + mMesh.setNull(); + mSubMesh = 0; + mEntity = 0; + mNumFaces = 0; + mNumVertices = 0; + mVertexBuffer.setNull(); + mIndexBuffer.setNull(); + mMaterialName = "_NULL_"; + + mCreated = false; } - void Mesh::remove() - { - if (!mCreated) - { - return; - } - - mSceneNode->detachAllObjects(); - mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); - mSceneNode = 0; - - Ogre::MeshManager::getSingleton().remove("HydraxMesh"); - mHydrax->getSceneManager()->destroyEntity(mEntity); - - mMesh.setNull(); - mSubMesh = 0; - mEntity = 0; - mNumFaces = 0; - mNumVertices = 0; - mVertexBuffer.setNull(); - mIndexBuffer.setNull(); - mMaterialName = "_NULL_"; - - mCreated = false; - } - - void Mesh::setOptions(const Options& Options) + void Mesh::setOptions(const Options &Options) { - if (mCreated) - { - Ogre::AxisAlignedBox meshBounds; - - if (Options.MeshSize.Width == 0 && Options.MeshSize.Height == 0) - { - meshBounds = Ogre::AxisAlignedBox(-1000000, -Options.MeshStrength/2,-1000000, - 1000000, Options.MeshStrength/2, 1000000); - } - else - { - meshBounds = Ogre::AxisAlignedBox(0, -Options.MeshStrength/2, 0, - Options.MeshSize.Width, Options.MeshStrength/2, Options.MeshSize.Height); - } - - mMesh->_setBounds(meshBounds); - mSceneNode->_updateBounds(); - - if (mOptions.MeshSize.Width != Options.MeshSize.Width || mOptions.MeshSize.Height != Options.MeshSize.Height) - { - mSceneNode->setPosition(mHydrax->getPosition().x-Options.MeshSize.Width/2,mHydrax->getPosition().y,mHydrax->getPosition().z-Options.MeshSize.Height/2); - } - } - - mOptions = Options; + if (mCreated) + { + Ogre::AxisAlignedBox meshBounds; + + if (Options.MeshSize.Width == 0 && Options.MeshSize.Height == 0) + { + meshBounds = Ogre::AxisAlignedBox(-1000000, -Options.MeshStrength / 2, -1000000, 1000000, + Options.MeshStrength / 2, 1000000); + } + else + { + meshBounds = Ogre::AxisAlignedBox(0, -Options.MeshStrength / 2, 0, Options.MeshSize.Width, + Options.MeshStrength / 2, Options.MeshSize.Height); + } + + mMesh->_setBounds(meshBounds); + mSceneNode->_updateBounds(); + + if (mOptions.MeshSize.Width != Options.MeshSize.Width || mOptions.MeshSize.Height != Options.MeshSize.Height) + { + mSceneNode->setPosition(mHydrax->getPosition().x - Options.MeshSize.Width / 2, mHydrax->getPosition().y, + mHydrax->getPosition().z - Options.MeshSize.Height / 2); + } + } + + mOptions = Options; } void Mesh::setMaterialName(const Ogre::String &MaterialName) { mMaterialName = MaterialName; - if (mEntity) - { - mEntity->setMaterialName(mMaterialName); - } + if (mEntity) { mEntity->setMaterialName(mMaterialName); } } - void Mesh::create() - { - if (mCreated) - { - return; - } - - // Create mesh and submesh - mMesh = Ogre::MeshManager::getSingleton().createManual("HydraxMesh", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - mSubMesh = mMesh->createSubMesh(); + void Mesh::create() + { + if (mCreated) { return; } + + // Create mesh and submesh + mMesh = + Ogre::MeshManager::getSingleton().createManual("HydraxMesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + mSubMesh = mMesh->createSubMesh(); mSubMesh->useSharedVertices = false; - if (mHydrax->getModule()) - { - if (!mHydrax->getModule()->_createGeometry(this)) - { - _createGeometry(); - } - } + if (mHydrax->getModule()) + { + if (!mHydrax->getModule()->_createGeometry(this)) { _createGeometry(); } + } - // End mesh creation + // End mesh creation Ogre::AxisAlignedBox meshBounds; - if (mOptions.MeshSize.Width == 0 && mOptions.MeshSize.Height == 0) - { - meshBounds = Ogre::AxisAlignedBox(-1000000, -mOptions.MeshStrength/2,-1000000, - 1000000, mOptions.MeshStrength/2, 1000000); - } - else - { - meshBounds = Ogre::AxisAlignedBox(0, -mOptions.MeshStrength/2, 0, - mOptions.MeshSize.Width, mOptions.MeshStrength/2, mOptions.MeshSize.Height); - } + if (mOptions.MeshSize.Width == 0 && mOptions.MeshSize.Height == 0) + { + meshBounds = + Ogre::AxisAlignedBox(-1000000, -mOptions.MeshStrength / 2, -1000000, 1000000, mOptions.MeshStrength / 2, 1000000); + } + else + { + meshBounds = Ogre::AxisAlignedBox(0, -mOptions.MeshStrength / 2, 0, mOptions.MeshSize.Width, + mOptions.MeshStrength / 2, mOptions.MeshSize.Height); + } mMesh->_setBounds(meshBounds); mMesh->load(); @@ -155,297 +136,243 @@ namespace Hydrax mEntity = mHydrax->getSceneManager()->createEntity("HydraxMeshEnt", "HydraxMesh"); mEntity->setMaterialName(mMaterialName); - mEntity->setCastShadows(false); - mEntity->setRenderQueueGroup(Ogre::RENDER_QUEUE_1); + mEntity->setCastShadows(false); + mEntity->setRenderQueueGroup(Ogre::RENDER_QUEUE_1); - mSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - mSceneNode->showBoundingBox(false); + mSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + mSceneNode->showBoundingBox(false); mSceneNode->attachObject(mEntity); - mSceneNode->setPosition(mHydrax->getPosition().x-mOptions.MeshSize.Width/2,mHydrax->getPosition().y,mHydrax->getPosition().z-mOptions.MeshSize.Height/2); - - mCreated = true; - } - - void Mesh::_createGeometry() - { - int& Complexity = mOptions.MeshComplexity; - - int numVertices = Complexity*Complexity; - int numEle = 6 * (Complexity-1)*(Complexity-1); - - // Vertex buffers - mSubMesh->vertexData = new Ogre::VertexData(); - mSubMesh->vertexData->vertexStart = 0; - mSubMesh->vertexData->vertexCount = numVertices; - - Ogre::VertexDeclaration* vdecl = mSubMesh->vertexData->vertexDeclaration; - Ogre::VertexBufferBinding* vbind = mSubMesh->vertexData->vertexBufferBinding; - - size_t offset = 0; - - switch (mOptions.MeshVertexType) - { - case VT_POS_NORM_UV: - { - vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); - - mVertexBuffer = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(POS_NORM_UV_VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - } - break; - - case VT_POS_NORM: - { - vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - - mVertexBuffer = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(POS_NORM_VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - } - break; - - case VT_POS_UV: - { - vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); - - mVertexBuffer = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(POS_UV_VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - } - break; - - case VT_POS: - { - vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - - mVertexBuffer = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(POS_VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - } - break; - } - - vbind->setBinding(0, mVertexBuffer); - - unsigned int *indexbuffer = new unsigned int[numEle]; - - int i = 0; - for(int v=0; v - writeData(0, - mIndexBuffer->getSizeInBytes(), - indexbuffer, - true); - - delete []indexbuffer; - - // Set index buffer for this submesh - mSubMesh->indexData->indexBuffer = mIndexBuffer; - mSubMesh->indexData->indexStart = 0; - mSubMesh->indexData->indexCount = numEle; - } - - bool Mesh::updateGeometry(const int &numVer, void* verArray) - { - if (numVer != mVertexBuffer->getNumVertices() || !mCreated) - { - return false; - } - - if (verArray) - { - mVertexBuffer-> - writeData(0, - mVertexBuffer->getSizeInBytes(), - verArray, - true); - } - - return true; - } - - bool Mesh::isPointInGrid(const Ogre::Vector2 &Position) - { - Ogre::AxisAlignedBox WordMeshBox = mEntity->getWorldBoundingBox(); - - // Get our mesh grid rectangle: - // c-----------d - // | | - // | | - // | | - // a-----------b - Ogre::Vector3 - a = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM), - b = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM), - c = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM), - d = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM); - - // Transform all corners to Ogre::Vector2 array - Ogre::Vector2 Corners2D[4] = - {Ogre::Vector2(a.x, a.z), - Ogre::Vector2(b.x, b.z), - Ogre::Vector2(c.x, c.z), - Ogre::Vector2(d.x, d.z)}; - - // Determinate if Position is into our rectangle, we use a line intersection detection - // because our mesh rectangle can be rotated, if the number of collisions with the four - // segments AB, BC, CD, DA is one, the Position point is into the rectangle, else(if number - // of collisions are 0 or 2, the Position point is outside the rectangle. - int NumberOfCollisions = 0; - // Find a point wich isn't be inside the rectangle - Ogre::Vector2 DestPoint = Corners2D[0] + (Corners2D[1]-Corners2D[0])*2; - for (int k = 0; k < 3; k++) - { - if (Math::intersectionOfTwoLines(Corners2D[k], Corners2D[k+1], Position, DestPoint) != Ogre::Vector2::ZERO) - { - NumberOfCollisions ++; - } - - if (k == 2) - { - if (Math::intersectionOfTwoLines(Corners2D[3], Corners2D[0], Position, DestPoint) != Ogre::Vector2::ZERO) - { - NumberOfCollisions ++; - } - } - } - if (NumberOfCollisions == 1) - { - return true; - } - - return false; - } - - Ogre::Vector2 Mesh::getGridPosition(const Ogre::Vector2 &Position) - { - if (mOptions.MeshSize.Width == 0 && mOptions.MeshSize.Height == 0) - { - return Position; - } - - if (!isPointInGrid(Position)) - { - return Ogre::Vector2(-1,-1); - } - - Ogre::AxisAlignedBox WordMeshBox = mEntity->getWorldBoundingBox(); - - // Get our mesh grid rectangle: (Only a,b,c corners) - // c - // | - // | - // | - // a-----------b - Ogre::Vector3 - a = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM), - b = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM), - c = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM); - - // Transform all corners to Ogre::Vector2 array - Ogre::Vector2 Corners2D[3] = - {Ogre::Vector2(a.x, a.z), - Ogre::Vector2(b.x, b.z), - Ogre::Vector2(c.x, c.z)}; - - // Get segments AB and AC - Ogre::Vector2 AB = Corners2D[1]-Corners2D[0], - AC = Corners2D[2]-Corners2D[0]; - - // Find the X/Y position projecting the Position point to AB and AC segments. - Ogre::Vector2 XProjectedPoint = Position-AC, - YProjectedPoint = Position-AB; - - // Fint the intersections points - Ogre::Vector2 XPoint = Math::intersectionOfTwoLines(Corners2D[0],Corners2D[1],Position,XProjectedPoint), - YPoint = Math::intersectionOfTwoLines(Corners2D[0],Corners2D[2],Position,YProjectedPoint); - - // Find lengths - Ogre::Real ABLength = AB.length(), - ACLength = AC.length(), - XLength = (XPoint-Corners2D[0]).length(), - YLength = (YPoint-Corners2D[0]).length(); - - // Find final x/y grid positions in [0,1] range - Ogre::Real XFinal = XLength / ABLength, - YFinal = YLength / ACLength; - - return Ogre::Vector2(XFinal,YFinal); - } - - const Ogre::Vector3 Mesh::getObjectSpacePosition(const Ogre::Vector3& WorldSpacePosition) const - { - Ogre::Affine3 mWorldMatrix; - - if (mCreated) - { - mWorldMatrix = mEntity->getParentSceneNode()->_getFullTransform(); + mSceneNode->setPosition(mHydrax->getPosition().x - mOptions.MeshSize.Width / 2, mHydrax->getPosition().y, + mHydrax->getPosition().z - mOptions.MeshSize.Height / 2); + + mCreated = true; + } + + void Mesh::_createGeometry() + { + int &Complexity = mOptions.MeshComplexity; + + int numVertices = Complexity * Complexity; + int numEle = 6 * (Complexity - 1) * (Complexity - 1); + + // Vertex buffers + mSubMesh->vertexData = new Ogre::VertexData(); + mSubMesh->vertexData->vertexStart = 0; + mSubMesh->vertexData->vertexCount = numVertices; + + Ogre::VertexDeclaration * vdecl = mSubMesh->vertexData->vertexDeclaration; + Ogre::VertexBufferBinding *vbind = mSubMesh->vertexData->vertexBufferBinding; + + size_t offset = 0; + + switch (mOptions.MeshVertexType) + { + case VT_POS_NORM_UV: + { + vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); + + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(POS_NORM_UV_VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); } - else - { - Ogre::SceneNode *mTmpSN = new Ogre::SceneNode(0); - mTmpSN->setPosition(mHydrax->getPosition()); + break; - mWorldMatrix = mTmpSN->_getFullTransform(); + case VT_POS_NORM: + { + vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); + + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(POS_NORM_VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + } + break; + + case VT_POS_UV: + { + vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); + + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(POS_UV_VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + } + break; + + case VT_POS: + { + vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(POS_VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + } + break; + } - delete mTmpSN; - } + vbind->setBinding(0, mVertexBuffer); - return mWorldMatrix.inverse()*(WorldSpacePosition); - } + unsigned int *indexbuffer = new unsigned int[numEle]; - const Ogre::Vector3 Mesh::getWorldSpacePosition(const Ogre::Vector3& ObjectSpacePosition) const - { - Ogre::Affine3 mWorldMatrix; + int i = 0; + for (int v = 0; v < Complexity - 1; v++) + { + for (int u = 0; u < Complexity - 1; u++) + { + // face 1 |/ + indexbuffer[i++] = v * Complexity + u; + indexbuffer[i++] = v * Complexity + u + 1; + indexbuffer[i++] = (v + 1) * Complexity + u; + + // face 2 /| + indexbuffer[i++] = (v + 1) * Complexity + u; + indexbuffer[i++] = v * Complexity + u + 1; + indexbuffer[i++] = (v + 1) * Complexity + u + 1; + } + } + + // Prepare buffer for indices + mIndexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_32BIT, numEle, + Ogre::HardwareBuffer::HBU_STATIC, true); + + mIndexBuffer->writeData(0, mIndexBuffer->getSizeInBytes(), indexbuffer, true); + + delete[] indexbuffer; + + // Set index buffer for this submesh + mSubMesh->indexData->indexBuffer = mIndexBuffer; + mSubMesh->indexData->indexStart = 0; + mSubMesh->indexData->indexCount = numEle; + } + + bool Mesh::updateGeometry(const int &numVer, void *verArray) + { + if (numVer != mVertexBuffer->getNumVertices() || !mCreated) { return false; } + + if (verArray) { mVertexBuffer->writeData(0, mVertexBuffer->getSizeInBytes(), verArray, true); } + + return true; + } - if (mCreated) - { - mWorldMatrix = mEntity->getParentSceneNode()->_getFullTransform(); + bool Mesh::isPointInGrid(const Ogre::Vector2 &Position) + { + Ogre::AxisAlignedBox WordMeshBox = mEntity->getWorldBoundingBox(); + + // Get our mesh grid rectangle: + // c-----------d + // | | + // | | + // | | + // a-----------b + Ogre::Vector3 a = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM), + b = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM), + c = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM), + d = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM); + + // Transform all corners to Ogre::Vector2 array + Ogre::Vector2 Corners2D[4] = {Ogre::Vector2(a.x, a.z), Ogre::Vector2(b.x, b.z), Ogre::Vector2(c.x, c.z), + Ogre::Vector2(d.x, d.z)}; + + // Determinate if Position is into our rectangle, we use a line intersection detection + // because our mesh rectangle can be rotated, if the number of collisions with the four + // segments AB, BC, CD, DA is one, the Position point is into the rectangle, else(if number + // of collisions are 0 or 2, the Position point is outside the rectangle. + int NumberOfCollisions = 0; + // Find a point wich isn't be inside the rectangle + Ogre::Vector2 DestPoint = Corners2D[0] + (Corners2D[1] - Corners2D[0]) * 2; + for (int k = 0; k < 3; k++) + { + if (Math::intersectionOfTwoLines(Corners2D[k], Corners2D[k + 1], Position, DestPoint) != Ogre::Vector2::ZERO) + { NumberOfCollisions++; } + + if (k == 2) + { + if (Math::intersectionOfTwoLines(Corners2D[3], Corners2D[0], Position, DestPoint) != Ogre::Vector2::ZERO) + { NumberOfCollisions++; } + } } - else - { - Ogre::SceneNode *mTmpSN = new Ogre::SceneNode(0); - mTmpSN->setPosition(mHydrax->getPosition()); + if (NumberOfCollisions == 1) { return true; } + + return false; + } + + Ogre::Vector2 Mesh::getGridPosition(const Ogre::Vector2 &Position) + { + if (mOptions.MeshSize.Width == 0 && mOptions.MeshSize.Height == 0) { return Position; } + + if (!isPointInGrid(Position)) { return Ogre::Vector2(-1, -1); } + + Ogre::AxisAlignedBox WordMeshBox = mEntity->getWorldBoundingBox(); + + // Get our mesh grid rectangle: (Only a,b,c corners) + // c + // | + // | + // | + // a-----------b + Ogre::Vector3 a = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM), + b = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM), + c = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM); + + // Transform all corners to Ogre::Vector2 array + Ogre::Vector2 Corners2D[3] = {Ogre::Vector2(a.x, a.z), Ogre::Vector2(b.x, b.z), Ogre::Vector2(c.x, c.z)}; + + // Get segments AB and AC + Ogre::Vector2 AB = Corners2D[1] - Corners2D[0], AC = Corners2D[2] - Corners2D[0]; + + // Find the X/Y position projecting the Position point to AB and AC segments. + Ogre::Vector2 XProjectedPoint = Position - AC, YProjectedPoint = Position - AB; + + // Fint the intersections points + Ogre::Vector2 XPoint = Math::intersectionOfTwoLines(Corners2D[0], Corners2D[1], Position, XProjectedPoint), + YPoint = Math::intersectionOfTwoLines(Corners2D[0], Corners2D[2], Position, YProjectedPoint); + + // Find lengths + Ogre::Real ABLength = AB.length(), ACLength = AC.length(), XLength = (XPoint - Corners2D[0]).length(), + YLength = (YPoint - Corners2D[0]).length(); + + // Find final x/y grid positions in [0,1] range + Ogre::Real XFinal = XLength / ABLength, YFinal = YLength / ACLength; + + return Ogre::Vector2(XFinal, YFinal); + } + + const Ogre::Vector3 Mesh::getObjectSpacePosition(const Ogre::Vector3 &WorldSpacePosition) const + { + Ogre::Affine3 mWorldMatrix; + + if (mCreated) { mWorldMatrix = mEntity->getParentSceneNode()->_getFullTransform(); } + else + { + Ogre::SceneNode *mTmpSN = new Ogre::SceneNode(0); + mTmpSN->setPosition(mHydrax->getPosition()); + + mWorldMatrix = mTmpSN->_getFullTransform(); + + delete mTmpSN; + } + + return mWorldMatrix.inverse() * (WorldSpacePosition); + } + + const Ogre::Vector3 Mesh::getWorldSpacePosition(const Ogre::Vector3 &ObjectSpacePosition) const + { + Ogre::Affine3 mWorldMatrix; + + if (mCreated) { mWorldMatrix = mEntity->getParentSceneNode()->_getFullTransform(); } + else + { + Ogre::SceneNode *mTmpSN = new Ogre::SceneNode(0); + mTmpSN->setPosition(mHydrax->getPosition()); mWorldMatrix = mTmpSN->_getFullTransform(); - delete mTmpSN; - } + delete mTmpSN; + } - //return mWorldMatrix.transformAffine(ObjectSpacePosition); - return mWorldMatrix*(ObjectSpacePosition); - } -} + // return mWorldMatrix.transformAffine(ObjectSpacePosition); + return mWorldMatrix * (ObjectSpacePosition); + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Mesh.h b/source/main/gfx/hydrax/Mesh.h index 5b95560f0f..67dd08d520 100644 --- a/source/main/gfx/hydrax/Mesh.h +++ b/source/main/gfx/hydrax/Mesh.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,118 +25,107 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Mesh_H_ #define _Hydrax_Mesh_H_ -#include "Prerequisites.h" - #include "Help.h" #include "Image.h" +#include "Prerequisites.h" namespace Hydrax { - class Hydrax; + class Hydrax; /** Class wich contains all funtions/variables related to Hydrax water mesh */ class Mesh { - public: - /** Vertex struct for position, normals and uv data. - */ - struct POS_NORM_UV_VERTEX - { - float x,y,z; - float nx,ny,nz; - float tu,tv; - }; - - /** Vertex struct for position and normals data. - */ - struct POS_NORM_VERTEX - { - float x,y,z; - float nx,ny,nz; - }; - - /** Vertex struct for position and uv data. - */ - struct POS_UV_VERTEX - { - float x,y,z; - float tu,tv; - }; - - /** Vertex struct for position data. - */ - struct POS_VERTEX - { - float x,y,z; - }; - - /** Mesh vertex type enum - */ - enum VertexType - { - VT_POS_NORM_UV = 0, - VT_POS_NORM = 1, - VT_POS_UV = 2, - VT_POS = 3, - }; - - /** Base Hydrax mesh options - */ - struct Options - { - /** Constructor - */ - Options() - : MeshComplexity(128) - , MeshSize(Size(0)) - , MeshStrength(10) - , MeshVertexType(VT_POS_NORM_UV) - { - } - - /** Constructor - @param meshComplexity Grid complexity - @param meshSize grid size (X/Z) world space. - @param meshVertexType Mesh::VertexType - */ - Options(const int &meshComplexity, const Size &meshSize, const VertexType &meshVertexType) - : MeshComplexity(meshComplexity) - , MeshSize(meshSize) - , MeshStrength(10) - , MeshVertexType(meshVertexType) - { - } - - /** Constructor - @param meshComplexity Grid complexity - @param meshSize grid size (X/Z) world space. - @param meshStrength Water strength(Y axis multiplier) - @param meshVertexType Mesh::VertexType - */ - Options(const int &meshComplexity, const Size &meshSize, const float &meshStrength, const VertexType &meshVertexType) - : MeshComplexity(meshComplexity) - , MeshSize(meshSize) - , MeshStrength(meshStrength) - , MeshVertexType(meshVertexType) - { - } - - /// Mesh complexity - int MeshComplexity; - /// Grid size (X/Z) world space. - Size MeshSize; - /// Water strength - float MeshStrength; - /// Vertex type - VertexType MeshVertexType; - }; + public: + /** Vertex struct for position, normals and uv data. + */ + struct POS_NORM_UV_VERTEX + { + float x, y, z; + float nx, ny, nz; + float tu, tv; + }; + + /** Vertex struct for position and normals data. + */ + struct POS_NORM_VERTEX + { + float x, y, z; + float nx, ny, nz; + }; + + /** Vertex struct for position and uv data. + */ + struct POS_UV_VERTEX + { + float x, y, z; + float tu, tv; + }; + + /** Vertex struct for position data. + */ + struct POS_VERTEX + { + float x, y, z; + }; + + /** Mesh vertex type enum + */ + enum VertexType + { + VT_POS_NORM_UV = 0, + VT_POS_NORM = 1, + VT_POS_UV = 2, + VT_POS = 3, + }; + + /** Base Hydrax mesh options + */ + struct Options + { + /** Constructor + */ + Options() : MeshComplexity(128), MeshSize(Size(0)), MeshStrength(10), MeshVertexType(VT_POS_NORM_UV) + { + } + + /** Constructor + @param meshComplexity Grid complexity + @param meshSize grid size (X/Z) world space. + @param meshVertexType Mesh::VertexType + */ + Options(const int &meshComplexity, const Size &meshSize, const VertexType &meshVertexType) + : MeshComplexity(meshComplexity), MeshSize(meshSize), MeshStrength(10), MeshVertexType(meshVertexType) + { + } + + /** Constructor + @param meshComplexity Grid complexity + @param meshSize grid size (X/Z) world space. + @param meshStrength Water strength(Y axis multiplier) + @param meshVertexType Mesh::VertexType + */ + Options(const int &meshComplexity, const Size &meshSize, const float &meshStrength, const VertexType &meshVertexType) + : MeshComplexity(meshComplexity), MeshSize(meshSize), MeshStrength(meshStrength), MeshVertexType(meshVertexType) + { + } + + /// Mesh complexity + int MeshComplexity; + /// Grid size (X/Z) world space. + Size MeshSize; + /// Water strength + float MeshStrength; + /// Vertex type + VertexType MeshVertexType; + }; /** Constructor @param h Hydrax pointer */ - Mesh(Hydrax *h); + Mesh(Hydrax *h); /** Destructor */ @@ -144,7 +133,7 @@ namespace Hydrax /** Update options @param Options Mesh options - @remarks Call it before create(...) + @remarks Call it before create(...) */ void setOptions(const Options &Options); @@ -158,40 +147,40 @@ namespace Hydrax */ void create(); - /** Remove all resources - */ - void remove(); - - /** Update geomtry - @param numVer Number of vertices - @param verArray Vertices array - @return false If number of vertices do not correspond. - */ - bool updateGeometry(const int &numVer, void* verArray); - - /** Get if a Position point is inside of the grid - @param Position World-space point - @return true if Position point is inside of the grid, else false. - */ - bool isPointInGrid(const Ogre::Vector2 &Position); - - /** Get the [0,1] range x/y grid position from a 2D world space x/z point - @param Position World-space point - @return (-1,-1) if the point isn't in the grid. - */ - Ogre::Vector2 getGridPosition(const Ogre::Vector2 &Position); - - /** Get the object-space position from world-space position - @param WorldSpacePosition Position in world coords - @return Position in object-space - */ - const Ogre::Vector3 getObjectSpacePosition(const Ogre::Vector3& WorldSpacePosition) const; - - /** Get the world-space position from object-space position - @param ObjectSpacePosition Position in object coords - @return Position in world-space - */ - const Ogre::Vector3 getWorldSpacePosition(const Ogre::Vector3& ObjectSpacePosition) const; + /** Remove all resources + */ + void remove(); + + /** Update geomtry + @param numVer Number of vertices + @param verArray Vertices array + @return false If number of vertices do not correspond. + */ + bool updateGeometry(const int &numVer, void *verArray); + + /** Get if a Position point is inside of the grid + @param Position World-space point + @return true if Position point is inside of the grid, else false. + */ + bool isPointInGrid(const Ogre::Vector2 &Position); + + /** Get the [0,1] range x/y grid position from a 2D world space x/z point + @param Position World-space point + @return (-1,-1) if the point isn't in the grid. + */ + Ogre::Vector2 getGridPosition(const Ogre::Vector2 &Position); + + /** Get the object-space position from world-space position + @param WorldSpacePosition Position in world coords + @return Position in object-space + */ + const Ogre::Vector3 getObjectSpacePosition(const Ogre::Vector3 &WorldSpacePosition) const; + + /** Get the world-space position from object-space position + @param ObjectSpacePosition Position in object coords + @return Position in world-space + */ + const Ogre::Vector3 getWorldSpacePosition(const Ogre::Vector3 &ObjectSpacePosition) const; /** Get mesh @return Mesh @@ -204,7 +193,7 @@ namespace Hydrax /** Get sub mesh @return Sub mesh */ - inline Ogre::SubMesh* getSubMesh() + inline Ogre::SubMesh *getSubMesh() { return mSubMesh; } @@ -212,39 +201,39 @@ namespace Hydrax /** Get entity @return Entity */ - inline Ogre::Entity* getEntity() + inline Ogre::Entity *getEntity() { return mEntity; } /** Get options - @return Mesh options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - /** Get mesh size - @return Mesh size - */ - inline const Size& getSize() const - { - return mOptions.MeshSize; - } - - /** Get vertex type - return Mesh vertex type - */ - inline const VertexType& getVertexType() const - { - return mOptions.MeshVertexType; - } + @return Mesh options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + /** Get mesh size + @return Mesh size + */ + inline const Size &getSize() const + { + return mOptions.MeshSize; + } + + /** Get vertex type + return Mesh vertex type + */ + inline const VertexType &getVertexType() const + { + return mOptions.MeshVertexType; + } /** Get number of faces @return Number of faces */ - inline const int& getNumFaces() const + inline const int &getNumFaces() const { return mNumFaces; } @@ -252,7 +241,7 @@ namespace Hydrax /** Get number of vertices @return Number of vertices */ - inline const int& getNumVertices() const + inline const int &getNumVertices() const { return mNumVertices; } @@ -260,12 +249,12 @@ namespace Hydrax /** Get material name @return Material name */ - inline const Ogre::String& getMaterialName() const + inline const Ogre::String &getMaterialName() const { return mMaterialName; } - /** Get hardware vertex buffer reference + /** Get hardware vertex buffer reference @return Ogre::HardwareVertexBufferSharedPtr reference */ inline Ogre::HardwareVertexBufferSharedPtr &getHardwareVertexBuffer() @@ -273,39 +262,39 @@ namespace Hydrax return mVertexBuffer; } - /** Get hardware index buffer reference - @return Ogre::HardwareIndexBufferSharedPtr reference - */ - inline Ogre::HardwareIndexBufferSharedPtr &getHardwareIndexBuffer() - { - return mIndexBuffer; - } - - /** Get the Ogre::SceneNode pointer where Hydrax mesh is attached - @return Ogre::SceneNode* - */ - inline Ogre::SceneNode* getSceneNode() - { - return mSceneNode; - } - - /** Is _createGeometry() called? - @return true if created() have been already called - */ - inline const bool& isCreated() const - { - return mCreated; - } - - private: - /** Create mesh geometry - */ - void _createGeometry(); + /** Get hardware index buffer reference + @return Ogre::HardwareIndexBufferSharedPtr reference + */ + inline Ogre::HardwareIndexBufferSharedPtr &getHardwareIndexBuffer() + { + return mIndexBuffer; + } + + /** Get the Ogre::SceneNode pointer where Hydrax mesh is attached + @return Ogre::SceneNode* + */ + inline Ogre::SceneNode *getSceneNode() + { + return mSceneNode; + } + + /** Is _createGeometry() called? + @return true if created() have been already called + */ + inline const bool &isCreated() const + { + return mCreated; + } + + private: + /** Create mesh geometry + */ + void _createGeometry(); /// Mesh options Options mOptions; - /// Is _createGeometry() called? - bool mCreated; + /// Is _createGeometry() called? + bool mCreated; /// Ogre::MeshPtr Ogre::MeshPtr mMesh; /// Ogre::Submesh pointer @@ -320,17 +309,17 @@ namespace Hydrax /// Vertex buffer Ogre::HardwareVertexBufferSharedPtr mVertexBuffer; /// Index buffer - Ogre::HardwareIndexBufferSharedPtr mIndexBuffer; + Ogre::HardwareIndexBufferSharedPtr mIndexBuffer; - /// Ogre::SceneNode pointer - Ogre::SceneNode* mSceneNode; + /// Ogre::SceneNode pointer + Ogre::SceneNode *mSceneNode; /// Material name Ogre::String mMaterialName; /// Hydrax pointer - Hydrax *mHydrax; + Hydrax *mHydrax; }; -} +} // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/Module.cpp b/source/main/gfx/hydrax/Module.cpp index 6878afc59d..0bee3f51bc 100644 --- a/source/main/gfx/hydrax/Module.cpp +++ b/source/main/gfx/hydrax/Module.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -22,100 +22,89 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to -------------------------------------------------------------------------------- */ -#include"Module.h" +#include "Module.h" -namespace Hydrax{namespace Module +namespace Hydrax { - Module::Module(const Ogre::String &Name, - Noise::Noise *n, - const Mesh::Options &MeshOptions, - const MaterialManager::NormalMode &NormalMode) - : mName(Name) - , mNoise(n) - , mMeshOptions(MeshOptions) - , mNormalMode(NormalMode) - , mCreated(false) - { - } - - Module::~Module() - { - delete mNoise; - } - - void Module::create() - { - mNoise->create(); - - mCreated = true; - } - - void Module::remove() - { - mNoise->remove(); - - mCreated = false; - } - - void Module::setNoise(Noise::Noise* Noise, GPUNormalMapManager* g, const bool& DeleteOldNoise) - { - if (DeleteOldNoise) - { - delete mNoise; - } - - mNoise = Noise; - - if (mCreated) - { - if (!mNoise->isCreated()) - { - mNoise->create(); - } - - if (getNormalMode() == MaterialManager::NM_RTT) - { - if (!mNoise->createGPUNormalMapResources(g)) - { - HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation"); - } - } - else - { - mNoise->removeGPUNormalMapResources(g); - } - } - else - { - mNoise->removeGPUNormalMapResources(g); - } - } - - void Module::update(const Ogre::Real &timeSinceLastFrame) - { - mNoise->update(timeSinceLastFrame); - } - - void Module::saveCfg(Ogre::String &Data) - { - Data += "#Module options\n"; - Data += "Module="+mName+"\n\n"; - } - - bool Module::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (CfgFile.getSetting("Module") == mName) - { - HydraxLOG(mName + " options entry found."); - return true; - } - - HydraxLOG("Error (Module::loadCfg):\t" + mName + " options entry can not be found."); - return false; - } - - float Module::getHeigth(const Ogre::Vector2 &Position) - { - return -1; - } -}} + namespace Module + { + Module::Module(const Ogre::String &Name, Noise::Noise *n, const Mesh::Options &MeshOptions, + const MaterialManager::NormalMode &NormalMode) + : mName(Name), mNoise(n), mMeshOptions(MeshOptions), mNormalMode(NormalMode), mCreated(false) + { + } + + Module::~Module() + { + delete mNoise; + } + + void Module::create() + { + mNoise->create(); + + mCreated = true; + } + + void Module::remove() + { + mNoise->remove(); + + mCreated = false; + } + + void Module::setNoise(Noise::Noise *Noise, GPUNormalMapManager *g, const bool &DeleteOldNoise) + { + if (DeleteOldNoise) { delete mNoise; } + + mNoise = Noise; + + if (mCreated) + { + if (!mNoise->isCreated()) { mNoise->create(); } + + if (getNormalMode() == MaterialManager::NM_RTT) + { + if (!mNoise->createGPUNormalMapResources(g)) + { HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation"); } + } + else + { + mNoise->removeGPUNormalMapResources(g); + } + } + else + { + mNoise->removeGPUNormalMapResources(g); + } + } + + void Module::update(const Ogre::Real &timeSinceLastFrame) + { + mNoise->update(timeSinceLastFrame); + } + + void Module::saveCfg(Ogre::String &Data) + { + Data += "#Module options\n"; + Data += "Module=" + mName + "\n\n"; + } + + bool Module::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (CfgFile.getSetting("Module") == mName) + { + HydraxLOG(mName + " options entry found."); + return true; + } + + HydraxLOG("Error (Module::loadCfg):\t" + mName + " options entry can not be found."); + return false; + } + + float Module::getHeigth(const Ogre::Vector2 &Position) + { + return -1; + } + } // namespace Module +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Module.h b/source/main/gfx/hydrax/Module.h index a3e336c78e..ea24ab9165 100644 --- a/source/main/gfx/hydrax/Module.h +++ b/source/main/gfx/hydrax/Module.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,137 +25,138 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Module_H_ #define _Hydrax_Module_H_ +#include "GPUNormalMapManager.h" +#include "MaterialManager.h" +#include "Mesh.h" +#include "Noise.h" #include "Prerequisites.h" #include "RoRPrerequisites.h" -#include "Noise.h" -#include "Mesh.h" -#include "MaterialManager.h" -#include "GPUNormalMapManager.h" -namespace Hydrax{ namespace Module +namespace Hydrax { - /** Base module class, - Override it for create different ways of create water noise. - */ - class Module - { - public: - /** Constructor - @param Name Module name - @param n Hydrax::Noise::Noise generator pointer - @param MeshOptions Mesh options - @param NormalMode Normal generation mode - */ - Module(const Ogre::String &Name, - Noise::Noise *n, - const Mesh::Options &MeshOptions, - const MaterialManager::NormalMode &NormalMode); - - /** Destructor - */ - virtual ~Module(); - - /** Create - @remark Not forgot call in the override class - */ - virtual void create(); - - /** Remove - @remark Not forgot call in the override class - */ - virtual void remove(); - - /** Set noise - @param Noise New noise module - @param g GPUNormalMapManager pointer, default: NULL, use it if GPU Normal map generation is needed - @param DeleteOldNoise Delete the old noise module (Default = true) - */ - void setNoise(Noise::Noise* Noise, GPUNormalMapManager* g = 0, const bool& DeleteOldNoise = true); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - virtual void update(const Ogre::Real &timeSinceLastFrame); - - /** Save config - @param Data String reference - */ - virtual void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct module config - */ - virtual bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get module name - @return Module name - */ - inline const Ogre::String& getName() const - { - return mName; - } - - /** Is created() called? - @return true if created() have been already called - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Create geometry in module(If special geometry is needed) - @param mMesh Mesh - @return false if it must be create by default Mesh::_createGeometry() fnc. - @remarks Override it if any especial geometry mesh creation is needed. - */ - inline virtual const bool _createGeometry(Mesh *mMesh) const - { - return false; - } - - /** Get the normal generation mode - @return Module normal generation mode - */ - inline const MaterialManager::NormalMode& getNormalMode() const - { - return mNormalMode; - } - - /** Get the mesh options for this module - @return Mesh options for this module - */ - inline const Mesh::Options& getMeshOptions() const - { - return mMeshOptions; - } - - /** Get the Hydrax::Noise module pointer - @return Hydrax::Noise pointer - */ - inline Noise::Noise* getNoise() - { - return mNoise; - } - - /** Get the current heigth at a especified world-space point - @param Position X/Z World position - @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 - */ - virtual float getHeigth(const Ogre::Vector2 &Position); - - protected: - /// Module name - Ogre::String mName; - /// Noise generator pointer - Noise::Noise *mNoise; - /// Module mesh options - Mesh::Options mMeshOptions; - /// Normal map generation mode - MaterialManager::NormalMode mNormalMode; - /// Is create() called? - bool mCreated; - }; -}} + namespace Module + { + /** Base module class, + Override it for create different ways of create water noise. + */ + class Module + { + public: + /** Constructor + @param Name Module name + @param n Hydrax::Noise::Noise generator pointer + @param MeshOptions Mesh options + @param NormalMode Normal generation mode + */ + Module(const Ogre::String &Name, Noise::Noise *n, const Mesh::Options &MeshOptions, + const MaterialManager::NormalMode &NormalMode); + + /** Destructor + */ + virtual ~Module(); + + /** Create + @remark Not forgot call in the override class + */ + virtual void create(); + + /** Remove + @remark Not forgot call in the override class + */ + virtual void remove(); + + /** Set noise + @param Noise New noise module + @param g GPUNormalMapManager pointer, default: NULL, use it if GPU Normal map generation is needed + @param DeleteOldNoise Delete the old noise module (Default = true) + */ + void setNoise(Noise::Noise *Noise, GPUNormalMapManager *g = 0, const bool &DeleteOldNoise = true); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + virtual void update(const Ogre::Real &timeSinceLastFrame); + + /** Save config + @param Data String reference + */ + virtual void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct module config + */ + virtual bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get module name + @return Module name + */ + inline const Ogre::String &getName() const + { + return mName; + } + + /** Is created() called? + @return true if created() have been already called + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Create geometry in module(If special geometry is needed) + @param mMesh Mesh + @return false if it must be create by default Mesh::_createGeometry() fnc. + @remarks Override it if any especial geometry mesh creation is needed. + */ + inline virtual const bool _createGeometry(Mesh *mMesh) const + { + return false; + } + + /** Get the normal generation mode + @return Module normal generation mode + */ + inline const MaterialManager::NormalMode &getNormalMode() const + { + return mNormalMode; + } + + /** Get the mesh options for this module + @return Mesh options for this module + */ + inline const Mesh::Options &getMeshOptions() const + { + return mMeshOptions; + } + + /** Get the Hydrax::Noise module pointer + @return Hydrax::Noise pointer + */ + inline Noise::Noise *getNoise() + { + return mNoise; + } + + /** Get the current heigth at a especified world-space point + @param Position X/Z World position + @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 + */ + virtual float getHeigth(const Ogre::Vector2 &Position); + + protected: + /// Module name + Ogre::String mName; + /// Noise generator pointer + Noise::Noise *mNoise; + /// Module mesh options + Mesh::Options mMeshOptions; + /// Normal map generation mode + MaterialManager::NormalMode mNormalMode; + /// Is create() called? + bool mCreated; + }; + } // namespace Module +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/Noise.cpp b/source/main/gfx/hydrax/Noise.cpp index cc11e87179..b844676b32 100644 --- a/source/main/gfx/hydrax/Noise.cpp +++ b/source/main/gfx/hydrax/Noise.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -23,76 +23,74 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to */ #include "Noise.h" + #include "RoRPrerequisites.h" -namespace Hydrax{namespace Noise +namespace Hydrax { - Noise::Noise(const Ogre::String &Name, const bool& GPUNormalMapSupported) - : mName(Name) - , mCreated(false) - , mGPUNormalMapSupported(GPUNormalMapSupported) - , mGPUNormalMapResourcesCreated(false) - { - } - - Noise::~Noise() - { - } - - void Noise::create() - { - mCreated = true; - } - - void Noise::remove() - { - mCreated = false; - } - - bool Noise::createGPUNormalMapResources(GPUNormalMapManager *g) - { - if (mGPUNormalMapSupported) - { - if (mGPUNormalMapResourcesCreated) - { - removeGPUNormalMapResources(g); - } - - mGPUNormalMapResourcesCreated = true; - - g->remove(); - - return true; - } - - return false; - } - - void Noise::removeGPUNormalMapResources(GPUNormalMapManager *g) - { - if (mGPUNormalMapSupported && mGPUNormalMapResourcesCreated) - { - mGPUNormalMapResourcesCreated = false; - - g->remove(); - } - } - - void Noise::saveCfg(Ogre::String &Data) - { - Data += "#Noise options\n"; - Data += "Noise="+mName+"\n\n"; - } - - bool Noise::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (CfgFile.getSetting("Noise") == mName) - { - HydraxLOG(mName + " options entry found."); - return true; - } - - HydraxLOG("Error (Noise::loadCfg):\t" + mName + " options entry can not be found."); - return false; - } -}} + namespace Noise + { + Noise::Noise(const Ogre::String &Name, const bool &GPUNormalMapSupported) + : mName(Name), mCreated(false), mGPUNormalMapSupported(GPUNormalMapSupported), mGPUNormalMapResourcesCreated(false) + { + } + + Noise::~Noise() + { + } + + void Noise::create() + { + mCreated = true; + } + + void Noise::remove() + { + mCreated = false; + } + + bool Noise::createGPUNormalMapResources(GPUNormalMapManager *g) + { + if (mGPUNormalMapSupported) + { + if (mGPUNormalMapResourcesCreated) { removeGPUNormalMapResources(g); } + + mGPUNormalMapResourcesCreated = true; + + g->remove(); + + return true; + } + + return false; + } + + void Noise::removeGPUNormalMapResources(GPUNormalMapManager *g) + { + if (mGPUNormalMapSupported && mGPUNormalMapResourcesCreated) + { + mGPUNormalMapResourcesCreated = false; + + g->remove(); + } + } + + void Noise::saveCfg(Ogre::String &Data) + { + Data += "#Noise options\n"; + Data += "Noise=" + mName + "\n\n"; + } + + bool Noise::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (CfgFile.getSetting("Noise") == mName) + { + HydraxLOG(mName + " options entry found."); + return true; + } + + HydraxLOG("Error (Noise::loadCfg):\t" + mName + " options entry can not be found."); + return false; + } + } // namespace Noise +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Noise.h b/source/main/gfx/hydrax/Noise.h index 73988a21e5..3e4eb16733 100644 --- a/source/main/gfx/hydrax/Noise.h +++ b/source/main/gfx/hydrax/Noise.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,112 +25,115 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Noise_H_ #define _Hydrax_Noise_H_ -#include "Prerequisites.h" #include "GPUNormalMapManager.h" +#include "Prerequisites.h" -namespace Hydrax{ namespace Noise +namespace Hydrax { - /** Base noise class, - Override it for create different ways of create water noise. - */ - class Noise - { - public: - /** Constructor - @param Name Noise name - @param GPUNormalMapSupported Is GPU normal map generation supported? - */ - Noise(const Ogre::String &Name, const bool& GPUNormalMapSupported); - - /** Destructor - */ - virtual ~Noise(); - - /** Create - */ - virtual void create(); - - /** Remove - */ - virtual void remove(); - - /** Create GPUNormalMap resources - @param g GPUNormalMapManager pointer - @return true if it needs to be created, false if not - */ - virtual bool createGPUNormalMapResources(GPUNormalMapManager *g); - - /** Remove GPUNormalMap resources - @param g GPUNormalMapManager pointer - */ - virtual void removeGPUNormalMapResources(GPUNormalMapManager *g); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - virtual void update(const Ogre::Real &timeSinceLastFrame) = 0; - - /** Save config - @param Data String reference - */ - virtual void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct noise config - */ - virtual bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get noise name - @return Noise name - */ - inline const Ogre::String& getName() const - { - return mName; - } - - /** Is created() called? - @return true if create() have been already called - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Is GPU Normal map generation supported - @return true if yes, false if not - */ - inline const bool& isGPUNormalMapSupported() const - { - return mGPUNormalMapSupported; - } - - /** Are GPU normal map resources created? - @return true if yes, false if not - */ - inline const bool& areGPUNormalMapResourcesCreated() const - { - return mGPUNormalMapResourcesCreated; - } - - /** Get the especified x/y noise value - @param x X Coord - @param y Y Coord - @return Noise value - */ - virtual float getValue(const float &x, const float &y) = 0; - - protected: - /// Module name - Ogre::String mName; - /// Has create() been already called? - bool mCreated; - - /// Is GPU normal map generation supported? - bool mGPUNormalMapSupported; - /// Are GPU normal map resources created? - bool mGPUNormalMapResourcesCreated; - }; -}} + namespace Noise + { + /** Base noise class, + Override it for create different ways of create water noise. + */ + class Noise + { + public: + /** Constructor + @param Name Noise name + @param GPUNormalMapSupported Is GPU normal map generation supported? + */ + Noise(const Ogre::String &Name, const bool &GPUNormalMapSupported); + + /** Destructor + */ + virtual ~Noise(); + + /** Create + */ + virtual void create(); + + /** Remove + */ + virtual void remove(); + + /** Create GPUNormalMap resources + @param g GPUNormalMapManager pointer + @return true if it needs to be created, false if not + */ + virtual bool createGPUNormalMapResources(GPUNormalMapManager *g); + + /** Remove GPUNormalMap resources + @param g GPUNormalMapManager pointer + */ + virtual void removeGPUNormalMapResources(GPUNormalMapManager *g); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + virtual void update(const Ogre::Real &timeSinceLastFrame) = 0; + + /** Save config + @param Data String reference + */ + virtual void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct noise config + */ + virtual bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get noise name + @return Noise name + */ + inline const Ogre::String &getName() const + { + return mName; + } + + /** Is created() called? + @return true if create() have been already called + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Is GPU Normal map generation supported + @return true if yes, false if not + */ + inline const bool &isGPUNormalMapSupported() const + { + return mGPUNormalMapSupported; + } + + /** Are GPU normal map resources created? + @return true if yes, false if not + */ + inline const bool &areGPUNormalMapResourcesCreated() const + { + return mGPUNormalMapResourcesCreated; + } + + /** Get the especified x/y noise value + @param x X Coord + @param y Y Coord + @return Noise value + */ + virtual float getValue(const float &x, const float &y) = 0; + + protected: + /// Module name + Ogre::String mName; + /// Has create() been already called? + bool mCreated; + + /// Is GPU normal map generation supported? + bool mGPUNormalMapSupported; + /// Are GPU normal map resources created? + bool mGPUNormalMapResourcesCreated; + }; + } // namespace Noise +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/Perlin.cpp b/source/main/gfx/hydrax/Perlin.cpp index 3a73f40165..c4ca7d200e 100644 --- a/source/main/gfx/hydrax/Perlin.cpp +++ b/source/main/gfx/hydrax/Perlin.cpp @@ -26,564 +26,502 @@ Based on the perlin noise code from Claes Johanson thesis: -------------------------------------------------------------------------------- */ -#include - #include +#include #define _def_PackedNoise true -namespace Hydrax{namespace Noise +namespace Hydrax { - Perlin::Perlin() - : Noise("Perlin", true) - , time(0) - , r_noise(0) - , magnitude(n_dec_magn * 0.085f) - , mGPUNormalMapManager(0) - { - } - - Perlin::Perlin(const Options &Options) - : Noise("Perlin", true) - , mOptions(Options) - , time(0) - , r_noise(0) - , magnitude(n_dec_magn * Options.Scale) - , mGPUNormalMapManager(0) - { - } - - Perlin::~Perlin() - { - remove(); - - HydraxLOG(getName() + " destroyed."); - } - - void Perlin::create() - { - if (isCreated()) - { - return; - } - - Noise::create(); - _initNoise(); - } - - void Perlin::remove() - { - if (areGPUNormalMapResourcesCreated()) - { - Noise::removeGPUNormalMapResources(mGPUNormalMapManager); - } - - if (!isCreated()) - { - return; - } - - time = 0; - - Noise::remove(); - } - - void Perlin::setOptions(const Options &Options) - { - if (isCreated()) - { - int Octaves_ = Options.Octaves; - mOptions = Options; - mOptions.Octaves = Octaves_; - - if (isGPUNormalMapSupported() && areGPUNormalMapResourcesCreated()) - { - mGPUNormalMapManager->getNormalMapMaterial()-> - getTechnique(0)->getPass(0)-> - getVertexProgramParameters()-> - setNamedConstant("uScale", Options.Scale); - - mGPUNormalMapManager->getNormalMapMaterial()-> - getTechnique(0)->getPass(0)-> - getFragmentProgramParameters()-> - setNamedConstant("uStrength", Options.GPU_Strength); - - mGPUNormalMapManager->getNormalMapMaterial()-> - getTechnique(0)->getPass(0)-> - getFragmentProgramParameters()-> - setNamedConstant("uLODParameters", Options.GPU_LODParameters); - } - } - else - { - mOptions = Options; - mOptions.Octaves = (mOptions.OctavesaddTexture(mPerlinTexture0); - mGPUNormalMapManager->addTexture(mPerlinTexture1); - - // Create our normal map generator material - - MaterialManager *mMaterialManager = g->getHydrax()->getMaterialManager(); - - Ogre::String VertexProgramData, FragmentProgramData; - Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; - Ogre::String EntryPoints[2] = {"main_vp", "main_fp"}; - Ogre::String GpuProgramsData[2]; Ogre::String GpuProgramNames[2]; - - // Vertex program - - switch (g->getHydrax()->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - VertexProgramData += - Ogre::String( - "void main_vp(\n") + - // IN - "float4 iPosition : POSITION,\n" + - // OUT - "out float4 oPosition : POSITION,\n" + - "out float3 oPosition_ : TEXCOORD0,\n" + - "out float4 oWorldUV : TEXCOORD1,\n" + - "out float oScale : TEXCOORD2,\n" + - "out float3 oCameraPos : TEXCOORD3,\n" + - "out float3 oCameraToPixel : TEXCOORD4,\n" + - // UNIFORM - "uniform float4x4 uWorldViewProj,\n" + - "uniform float4x4 uWorld, \n" + - "uniform float3 uCameraPos,\n"+ - "uniform float uScale)\n" + - "{\n" + - "oPosition = mul(uWorldViewProj, iPosition);\n" + - "oPosition_ = iPosition.xyz;\n" + - "float2 Scale = uScale*mul(uWorld, iPosition).xz*0.0078125;\n" + - "oWorldUV.xy = Scale;\n" + - "oWorldUV.zw = Scale*16;\n" + - "oScale = uScale;\n" + - "oCameraPos = uCameraPos,\n" + - "oCameraToPixel = iPosition - uCameraPos;\n"+ - "}\n"; - } - break; - - case MaterialManager::SM_GLSL: - {} - break; - } - - // Fragment program - - switch (g->getHydrax()->getShaderMode()) - { - case MaterialManager::SM_HLSL: case MaterialManager::SM_CG: - { - FragmentProgramData += - Ogre::String( - "void main_fp(\n") + - // IN - "float3 iPosition : TEXCOORD0,\n" + - "float4 iWorldCoord : TEXCOORD1,\n" + - "float iScale : TEXCOORD2,\n" + - "float3 iCameraPos : TEXCOORD3,\n" + - "float3 iCameraToPixel : TEXCOORD4,\n" + - // OUT - "out float4 oColor : COLOR,\n" + - // UNIFORM - "uniform float uStrength,\n" + - "uniform float3 uLODParameters,\n" + // x: Initial derivation, y: Final derivation, z: Step - "uniform float3 uCameraPos,\n" + - "uniform sampler2D uNoise0 : register(s0),\n" + - "uniform sampler2D uNoise1 : register(s1))\n" + - "{\n" + - "float Distance = length(iCameraToPixel);\n" + - "float Attenuation = saturate(Distance/uLODParameters.z);\n" + - - "uLODParameters.x += (uLODParameters.y-uLODParameters.x)*Attenuation;\n"+ - "uLODParameters.x *= iScale;\n" + - - "float AngleAttenuation = 1/abs(normalize(iCameraToPixel).y);\n"+ - "uLODParameters.x *= AngleAttenuation;\n"+ - - "float2 dx = float2(uLODParameters.x*0.0078125, 0);\n" + - "float2 dy = float2(0, dx.x);\n" + - - "float3 p_dx, m_dx, p_dy, m_dy;\n" + - - "p_dx = float3(\n" + - // x+ - "iPosition.x+uLODParameters.x,\n" + - // y+ - "tex2D(uNoise0, iWorldCoord.xy+dx).x + tex2D(uNoise1, iWorldCoord.zw+dx*16).x,\n" + - // z - "iPosition.z);\n" + - - "m_dx = float3(\n" + - // x- - "iPosition.x-uLODParameters.x,\n" + - // y- - "tex2D(uNoise0, iWorldCoord.xy-dx).x + tex2D(uNoise1, iWorldCoord.zw-dx*16).x,\n" + - // z - "iPosition.z);\n" + - - "p_dy = float3(\n" + - // x - "iPosition.x,\n" + - // y+ - "tex2D(uNoise0, iWorldCoord.xy+dy).x + tex2D(uNoise1, iWorldCoord.zw+dy*16).x,\n" + - // z+ - "iPosition.z+uLODParameters.x);\n" + - - "m_dy = float3(\n" + - // x - "iPosition.x,\n" + - // y- - "tex2D(uNoise0, iWorldCoord.xy-dy).x + tex2D(uNoise1, iWorldCoord.zw-dy*16).x,\n" + - // z- - "iPosition.z-uLODParameters.x);\n" + - - "uStrength *= (1-Attenuation);\n" + - "p_dx.y *= uStrength; m_dx.y *= uStrength;\n" + - "p_dy.y *= uStrength; m_dy.y *= uStrength;\n" + - - "float3 normal = normalize(cross(p_dx-m_dx, p_dy-m_dy));\n" + - - "oColor = float4(saturate(1-(0.5+0.5*normal)),1);\n" + - "}\n"; - - } - break; - - case MaterialManager::SM_GLSL: - {} - break; - } - - // Build our material - - Ogre::MaterialPtr &mNormalMapMaterial = mGPUNormalMapManager->getNormalMapMaterial(); - mNormalMapMaterial = Ogre::MaterialManager::getSingleton().create("_Hydrax_GPU_Normal_Map_Material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::Pass *Technique0_Pass0 = mNormalMapMaterial->getTechnique(0)->getPass(0); - - Technique0_Pass0->setLightingEnabled(false); - Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); - Technique0_Pass0->setDepthWriteEnabled(true); - Technique0_Pass0->setDepthCheckEnabled(true); - - GpuProgramsData[0] = VertexProgramData; GpuProgramsData[1] = FragmentProgramData; - GpuProgramNames[0] = "_Hydrax_GPU_Normal_Map_VP"; GpuProgramNames[1] = "_Hydrax_GPU_Normal_Map_FP"; - - mMaterialManager->fillGpuProgramsToPass(Technique0_Pass0, GpuProgramNames, g->getHydrax()->getShaderMode(), EntryPoints, GpuProgramsData); - - VP_Parameters = Technique0_Pass0->getVertexProgramParameters(); - - VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); - VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - VP_Parameters->setNamedConstant("uScale", mOptions.Scale); - - FP_Parameters = Technique0_Pass0->getFragmentProgramParameters(); - - FP_Parameters->setNamedConstant("uStrength", mOptions.GPU_Strength); - FP_Parameters->setNamedConstant("uLODParameters", mOptions.GPU_LODParameters); - - Technique0_Pass0->createTextureUnitState(mGPUNormalMapManager->getTexture(0)->getName(), 0) - ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_MIRROR); - Technique0_Pass0->createTextureUnitState(mGPUNormalMapManager->getTexture(1)->getName(), 1) - ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_MIRROR); - - mNormalMapMaterial->load(); - - mGPUNormalMapManager->create(); - - return true; - } - - void Perlin::saveCfg(Ogre::String &Data) - { - Noise::saveCfg(Data); - - Data += CfgFileManager::_getCfgString("Perlin_Octaves", mOptions.Octaves); - Data += CfgFileManager::_getCfgString("Perlin_Scale", mOptions.Scale); - Data += CfgFileManager::_getCfgString("Perlin_Falloff", mOptions.Falloff); - Data += CfgFileManager::_getCfgString("Perlin_Animspeed", mOptions.Animspeed); - Data += CfgFileManager::_getCfgString("Perlin_Timemulti", mOptions.Timemulti); - Data += CfgFileManager::_getCfgString("Perlin_GPU_Strength", mOptions.GPU_Strength); - Data += CfgFileManager::_getCfgString("Perlin_GPU_LODParameters", mOptions.GPU_LODParameters); Data += "\n"; - } - - bool Perlin::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (!Noise::loadCfg(CfgFile)) - { - return false; - } - - setOptions( - Options(CfgFileManager::_getIntValue(CfgFile,"Perlin_Octaves"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Scale"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Falloff"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Animspeed"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Timemulti"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_GPU_Strength"), - CfgFileManager::_getVector3Value(CfgFile,"Perlin_GPU_LODParameters"))); - - return true; - } - - void Perlin::update(const Ogre::Real &timeSinceLastFrame) - { - time += timeSinceLastFrame*mOptions.Animspeed; - _calculeNoise(); - - if (areGPUNormalMapResourcesCreated()) - { - _updateGPUNormalMapResources(); - } - } - - void Perlin::_updateGPUNormalMapResources() - { - unsigned short *Data; - int Offset; - Ogre::HardwarePixelBufferSharedPtr PixelBuffer; - - for (int k = 0; k < 2; k++) - { - Offset = np_size_sq*k; - PixelBuffer = mGPUNormalMapManager->getTexture(k)->getBuffer(); - - PixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); - const Ogre::PixelBox& PixelBox = PixelBuffer->getCurrentLock(); - - Data = reinterpret_cast(PixelBox.data); - - for (int u = 0; u < np_size_sq; u++) - { - Data[u] = 32768+p_noise[u+Offset];//std::cout << p_noise[u+Offset] << std::endl; - } - - PixelBuffer->unlock(); - } - } - - float Perlin::getValue(const float &x, const float &y) - { - return _getHeigthDual(x, y); - } - - void Perlin::_initNoise() - { - // Create noise (uniform) - float tempnoise[n_size_sq*noise_frames], temp; - - int i, frame, v, u, - v0, v1, v2, u0, u1, u2, f; - - for(i=0; i<(n_size_sq*noise_frames); i++) - { - temp = static_cast(rand())/RAND_MAX; - tempnoise[i] = 4*(temp - 0.5f); - } - - for(frame=0; frame(dImage); - - amount[0] = scale_magnitude*f_multitable[o]*(pow(sin((fraction+2)*PI_3),2)/1.5); - amount[1] = scale_magnitude*f_multitable[o]*(pow(sin((fraction+1)*PI_3),2)/1.5); - amount[2] = scale_magnitude*f_multitable[o]*(pow(sin((fraction )*PI_3),2)/1.5); - - image[0] = (iImage ) & noise_frames_m1; - image[1] = (iImage+1) & noise_frames_m1; - image[2] = (iImage+2) & noise_frames_m1; - - for (i=0; i>scale_decimalbits) + - ((amount[1] * noise[i + n_size_sq * image[1]])>>scale_decimalbits) + - ((amount[2] * noise[i + n_size_sq * image[2]])>>scale_decimalbits)); - } - - r_timemulti *= mOptions.Timemulti; - } - - if(_def_PackedNoise) - { - int octavepack = 0; - for(o=0; o>n_dec_bits)&np_size_m1; - iv = ((v>>n_dec_bits)&np_size_m1)*np_size; - - iup = ((u>>n_dec_bits) + 1)&np_size_m1; - ivp = (((v>>n_dec_bits) + 1)&np_size_m1)*np_size; - - fu = u & n_dec_magn_m1; - fv = v & n_dec_magn_m1; - - ut01 = ((n_dec_magn-fu)*r_noise[iv + iu] + fu*r_noise[iv + iup])>>n_dec_bits; - ut23 = ((n_dec_magn-fu)*r_noise[ivp + iu] + fu*r_noise[ivp + iup])>>n_dec_bits; - ut = ((n_dec_magn-fv)*ut01 + fv*ut23) >> n_dec_bits; - - return ut; - } - - float Perlin::_getHeigthDual(float u, float v) - { - // Pointer to the current noise source octave - r_noise = p_noise; - - int ui = u*magnitude, - vi = v*magnitude, - i, - value = 0, - hoct = mOptions.Octaves / n_packsize; - - for(i=0; i(value)/noise_magnitude; - } - - int Perlin::_mapSample(const int &u, const int &v, const int &upsamplepower, const int &octave) - { - int magnitude = 1<> upsamplepower, - pv = v >> upsamplepower, - - fu = u & (magnitude-1), - fv = v & (magnitude-1), - - fu_m = magnitude - fu, - fv_m = magnitude - fv, - - o = fu_m*fv_m*o_noise[octave*n_size_sq + ((pv) &n_size_m1)*n_size + ((pu) &n_size_m1)] + - fu* fv_m*o_noise[octave*n_size_sq + ((pv) &n_size_m1)*n_size + ((pu+1)&n_size_m1)] + - fu_m*fv* o_noise[octave*n_size_sq + ((pv+1)&n_size_m1)*n_size + ((pu) &n_size_m1)] + - fu* fv* o_noise[octave*n_size_sq + ((pv+1)&n_size_m1)*n_size + ((pu+1)&n_size_m1)]; - - return o >> (upsamplepower+upsamplepower); - } -}} + namespace Noise + { + Perlin::Perlin() : Noise("Perlin", true), time(0), r_noise(0), magnitude(n_dec_magn * 0.085f), mGPUNormalMapManager(0) + { + } + + Perlin::Perlin(const Options &Options) + : Noise("Perlin", true), mOptions(Options), time(0), r_noise(0), magnitude(n_dec_magn * Options.Scale), + mGPUNormalMapManager(0) + { + } + + Perlin::~Perlin() + { + remove(); + + HydraxLOG(getName() + " destroyed."); + } + + void Perlin::create() + { + if (isCreated()) { return; } + + Noise::create(); + _initNoise(); + } + + void Perlin::remove() + { + if (areGPUNormalMapResourcesCreated()) { Noise::removeGPUNormalMapResources(mGPUNormalMapManager); } + + if (!isCreated()) { return; } + + time = 0; + + Noise::remove(); + } + + void Perlin::setOptions(const Options &Options) + { + if (isCreated()) + { + int Octaves_ = Options.Octaves; + mOptions = Options; + mOptions.Octaves = Octaves_; + + if (isGPUNormalMapSupported() && areGPUNormalMapResourcesCreated()) + { + mGPUNormalMapManager->getNormalMapMaterial() + ->getTechnique(0) + ->getPass(0) + ->getVertexProgramParameters() + ->setNamedConstant("uScale", Options.Scale); + + mGPUNormalMapManager->getNormalMapMaterial() + ->getTechnique(0) + ->getPass(0) + ->getFragmentProgramParameters() + ->setNamedConstant("uStrength", Options.GPU_Strength); + + mGPUNormalMapManager->getNormalMapMaterial() + ->getTechnique(0) + ->getPass(0) + ->getFragmentProgramParameters() + ->setNamedConstant("uLODParameters", Options.GPU_LODParameters); + } + } + else + { + mOptions = Options; + mOptions.Octaves = (mOptions.Octaves < max_octaves) ? mOptions.Octaves : max_octaves; + } + + magnitude = n_dec_magn * mOptions.Scale; + } + + bool Perlin::createGPUNormalMapResources(GPUNormalMapManager *g) + { + if (!Noise::createGPUNormalMapResources(g)) { return false; } + + mGPUNormalMapManager = g; + + // Create our perlin textures + Ogre::TexturePtr mPerlinTexture0 = Ogre::TextureManager::getSingleton().createManual( + "_Hydrax_Perlin_Noise0", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, np_size, + np_size, 0, Ogre::PF_L16, Ogre::TU_DYNAMIC_WRITE_ONLY); + + Ogre::TexturePtr mPerlinTexture1 = Ogre::TextureManager::getSingleton().createManual( + "_Hydrax_Perlin_Noise1", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, np_size, + np_size, 0, Ogre::PF_L16, Ogre::TU_DYNAMIC_WRITE_ONLY); + + mGPUNormalMapManager->addTexture(mPerlinTexture0); + mGPUNormalMapManager->addTexture(mPerlinTexture1); + + // Create our normal map generator material + + MaterialManager *mMaterialManager = g->getHydrax()->getMaterialManager(); + + Ogre::String VertexProgramData, FragmentProgramData; + Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters; + Ogre::String EntryPoints[2] = {"main_vp", "main_fp"}; + Ogre::String GpuProgramsData[2]; + Ogre::String GpuProgramNames[2]; + + // Vertex program + + switch (g->getHydrax()->getShaderMode()) + { + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: + { + VertexProgramData += Ogre::String("void main_vp(\n") + + // IN + "float4 iPosition : POSITION,\n" + + // OUT + "out float4 oPosition : POSITION,\n" + "out float3 oPosition_ : TEXCOORD0,\n" + + "out float4 oWorldUV : TEXCOORD1,\n" + "out float oScale : TEXCOORD2,\n" + + "out float3 oCameraPos : TEXCOORD3,\n" + "out float3 oCameraToPixel : TEXCOORD4,\n" + + // UNIFORM + "uniform float4x4 uWorldViewProj,\n" + "uniform float4x4 uWorld, \n" + + "uniform float3 uCameraPos,\n" + "uniform float uScale)\n" + "{\n" + + "oPosition = mul(uWorldViewProj, iPosition);\n" + "oPosition_ = iPosition.xyz;\n" + + "float2 Scale = uScale*mul(uWorld, iPosition).xz*0.0078125;\n" + "oWorldUV.xy = Scale;\n" + + "oWorldUV.zw = Scale*16;\n" + "oScale = uScale;\n" + "oCameraPos = uCameraPos,\n" + + "oCameraToPixel = iPosition - uCameraPos;\n" + "}\n"; + } + break; + + case MaterialManager::SM_GLSL: + { + } + break; + } + + // Fragment program + + switch (g->getHydrax()->getShaderMode()) + { + case MaterialManager::SM_HLSL: + case MaterialManager::SM_CG: + { + FragmentProgramData += + Ogre::String("void main_fp(\n") + + // IN + "float3 iPosition : TEXCOORD0,\n" + "float4 iWorldCoord : TEXCOORD1,\n" + + "float iScale : TEXCOORD2,\n" + "float3 iCameraPos : TEXCOORD3,\n" + + "float3 iCameraToPixel : TEXCOORD4,\n" + + // OUT + "out float4 oColor : COLOR,\n" + + // UNIFORM + "uniform float uStrength,\n" + + "uniform float3 uLODParameters,\n" + // x: Initial derivation, y: Final derivation, z: Step + "uniform float3 uCameraPos,\n" + "uniform sampler2D uNoise0 : register(s0),\n" + + "uniform sampler2D uNoise1 : register(s1))\n" + "{\n" + "float Distance = length(iCameraToPixel);\n" + + "float Attenuation = saturate(Distance/uLODParameters.z);\n" + + + "uLODParameters.x += (uLODParameters.y-uLODParameters.x)*Attenuation;\n" + "uLODParameters.x *= iScale;\n" + + + "float AngleAttenuation = 1/abs(normalize(iCameraToPixel).y);\n" + "uLODParameters.x *= AngleAttenuation;\n" + + + "float2 dx = float2(uLODParameters.x*0.0078125, 0);\n" + "float2 dy = float2(0, dx.x);\n" + + + "float3 p_dx, m_dx, p_dy, m_dy;\n" + + + "p_dx = float3(\n" + + // x+ + "iPosition.x+uLODParameters.x,\n" + + // y+ + "tex2D(uNoise0, iWorldCoord.xy+dx).x + tex2D(uNoise1, iWorldCoord.zw+dx*16).x,\n" + + // z + "iPosition.z);\n" + + + "m_dx = float3(\n" + + // x- + "iPosition.x-uLODParameters.x,\n" + + // y- + "tex2D(uNoise0, iWorldCoord.xy-dx).x + tex2D(uNoise1, iWorldCoord.zw-dx*16).x,\n" + + // z + "iPosition.z);\n" + + + "p_dy = float3(\n" + + // x + "iPosition.x,\n" + + // y+ + "tex2D(uNoise0, iWorldCoord.xy+dy).x + tex2D(uNoise1, iWorldCoord.zw+dy*16).x,\n" + + // z+ + "iPosition.z+uLODParameters.x);\n" + + + "m_dy = float3(\n" + + // x + "iPosition.x,\n" + + // y- + "tex2D(uNoise0, iWorldCoord.xy-dy).x + tex2D(uNoise1, iWorldCoord.zw-dy*16).x,\n" + + // z- + "iPosition.z-uLODParameters.x);\n" + + + "uStrength *= (1-Attenuation);\n" + "p_dx.y *= uStrength; m_dx.y *= uStrength;\n" + + "p_dy.y *= uStrength; m_dy.y *= uStrength;\n" + + + "float3 normal = normalize(cross(p_dx-m_dx, p_dy-m_dy));\n" + + + "oColor = float4(saturate(1-(0.5+0.5*normal)),1);\n" + "}\n"; + } + break; + + case MaterialManager::SM_GLSL: + { + } + break; + } + + // Build our material + + Ogre::MaterialPtr &mNormalMapMaterial = mGPUNormalMapManager->getNormalMapMaterial(); + mNormalMapMaterial = Ogre::MaterialManager::getSingleton().create( + "_Hydrax_GPU_Normal_Map_Material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + Ogre::Pass *Technique0_Pass0 = mNormalMapMaterial->getTechnique(0)->getPass(0); + + Technique0_Pass0->setLightingEnabled(false); + Technique0_Pass0->setCullingMode(Ogre::CULL_NONE); + Technique0_Pass0->setDepthWriteEnabled(true); + Technique0_Pass0->setDepthCheckEnabled(true); + + GpuProgramsData[0] = VertexProgramData; + GpuProgramsData[1] = FragmentProgramData; + GpuProgramNames[0] = "_Hydrax_GPU_Normal_Map_VP"; + GpuProgramNames[1] = "_Hydrax_GPU_Normal_Map_FP"; + + mMaterialManager->fillGpuProgramsToPass(Technique0_Pass0, GpuProgramNames, g->getHydrax()->getShaderMode(), + EntryPoints, GpuProgramsData); + + VP_Parameters = Technique0_Pass0->getVertexProgramParameters(); + + VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); + VP_Parameters->setNamedAutoConstant("uCameraPos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + VP_Parameters->setNamedConstant("uScale", mOptions.Scale); + + FP_Parameters = Technique0_Pass0->getFragmentProgramParameters(); + + FP_Parameters->setNamedConstant("uStrength", mOptions.GPU_Strength); + FP_Parameters->setNamedConstant("uLODParameters", mOptions.GPU_LODParameters); + + Technique0_Pass0->createTextureUnitState(mGPUNormalMapManager->getTexture(0)->getName(), 0) + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_MIRROR); + Technique0_Pass0->createTextureUnitState(mGPUNormalMapManager->getTexture(1)->getName(), 1) + ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_MIRROR); + + mNormalMapMaterial->load(); + + mGPUNormalMapManager->create(); + + return true; + } + + void Perlin::saveCfg(Ogre::String &Data) + { + Noise::saveCfg(Data); + + Data += CfgFileManager::_getCfgString("Perlin_Octaves", mOptions.Octaves); + Data += CfgFileManager::_getCfgString("Perlin_Scale", mOptions.Scale); + Data += CfgFileManager::_getCfgString("Perlin_Falloff", mOptions.Falloff); + Data += CfgFileManager::_getCfgString("Perlin_Animspeed", mOptions.Animspeed); + Data += CfgFileManager::_getCfgString("Perlin_Timemulti", mOptions.Timemulti); + Data += CfgFileManager::_getCfgString("Perlin_GPU_Strength", mOptions.GPU_Strength); + Data += CfgFileManager::_getCfgString("Perlin_GPU_LODParameters", mOptions.GPU_LODParameters); + Data += "\n"; + } + + bool Perlin::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (!Noise::loadCfg(CfgFile)) { return false; } + + setOptions(Options(CfgFileManager::_getIntValue(CfgFile, "Perlin_Octaves"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Scale"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Falloff"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Animspeed"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Timemulti"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_GPU_Strength"), + CfgFileManager::_getVector3Value(CfgFile, "Perlin_GPU_LODParameters"))); + + return true; + } + + void Perlin::update(const Ogre::Real &timeSinceLastFrame) + { + time += timeSinceLastFrame * mOptions.Animspeed; + _calculeNoise(); + + if (areGPUNormalMapResourcesCreated()) { _updateGPUNormalMapResources(); } + } + + void Perlin::_updateGPUNormalMapResources() + { + unsigned short * Data; + int Offset; + Ogre::HardwarePixelBufferSharedPtr PixelBuffer; + + for (int k = 0; k < 2; k++) + { + Offset = np_size_sq * k; + PixelBuffer = mGPUNormalMapManager->getTexture(k)->getBuffer(); + + PixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); + const Ogre::PixelBox &PixelBox = PixelBuffer->getCurrentLock(); + + Data = reinterpret_cast(PixelBox.data); + + for (int u = 0; u < np_size_sq; u++) + { + Data[u] = 32768 + p_noise[u + Offset]; // std::cout << p_noise[u+Offset] << std::endl; + } + + PixelBuffer->unlock(); + } + } + + float Perlin::getValue(const float &x, const float &y) + { + return _getHeigthDual(x, y); + } + + void Perlin::_initNoise() + { + // Create noise (uniform) + float tempnoise[n_size_sq * noise_frames], temp; + + int i, frame, v, u, v0, v1, v2, u0, u1, u2, f; + + for (i = 0; i < (n_size_sq * noise_frames); i++) + { + temp = static_cast(rand()) / RAND_MAX; + tempnoise[i] = 4 * (temp - 0.5f); + } + + for (frame = 0; frame < noise_frames; frame++) + { + for (v = 0; v < n_size; v++) + { + for (u = 0; u < n_size; u++) + { + v0 = ((v - 1) & n_size_m1) * n_size; + v1 = v * n_size; + v2 = ((v + 1) & n_size_m1) * n_size; + u0 = ((u - 1) & n_size_m1); + u1 = u; + u2 = ((u + 1) & n_size_m1); + f = frame * n_size_sq; + + temp = (1.0f / 14.0f) * (tempnoise[f + v0 + u0] + tempnoise[f + v0 + u1] + tempnoise[f + v0 + u2] + + tempnoise[f + v1 + u0] + 6.0f * tempnoise[f + v1 + u1] + tempnoise[f + v1 + u2] + + tempnoise[f + v2 + u0] + tempnoise[f + v2 + u1] + tempnoise[f + v2 + u2]); + + noise[frame * n_size_sq + v * n_size + u] = noise_magnitude * temp; + } + } + } + } + + void Perlin::_calculeNoise() + { + int i, o, v, u, multitable[max_octaves], amount[3], iImage; + + unsigned int image[3]; + + float sum = 0.0f, f_multitable[max_octaves]; + + double dImage, fraction; + + // calculate the strength of each octave + for (i = 0; i < mOptions.Octaves; i++) + { + f_multitable[i] = powf(mOptions.Falloff, 1.0f * i); + sum += f_multitable[i]; + } + + for (i = 0; i < mOptions.Octaves; i++) + { + f_multitable[i] /= sum; + } + + for (i = 0; i < mOptions.Octaves; i++) + { + multitable[i] = scale_magnitude * f_multitable[i]; + } + + double r_timemulti = 1.0; + const float PI_3 = Ogre::Math::PI / 3; + + for (o = 0; o < mOptions.Octaves; o++) + { + fraction = modf(time * r_timemulti, &dImage); + iImage = static_cast(dImage); + + amount[0] = scale_magnitude * f_multitable[o] * (pow(sin((fraction + 2) * PI_3), 2) / 1.5); + amount[1] = scale_magnitude * f_multitable[o] * (pow(sin((fraction + 1) * PI_3), 2) / 1.5); + amount[2] = scale_magnitude * f_multitable[o] * (pow(sin((fraction)*PI_3), 2) / 1.5); + + image[0] = (iImage)&noise_frames_m1; + image[1] = (iImage + 1) & noise_frames_m1; + image[2] = (iImage + 2) & noise_frames_m1; + + for (i = 0; i < n_size_sq; i++) + { + o_noise[i + n_size_sq * o] = (((amount[0] * noise[i + n_size_sq * image[0]]) >> scale_decimalbits) + + ((amount[1] * noise[i + n_size_sq * image[1]]) >> scale_decimalbits) + + ((amount[2] * noise[i + n_size_sq * image[2]]) >> scale_decimalbits)); + } + + r_timemulti *= mOptions.Timemulti; + } + + if (_def_PackedNoise) + { + int octavepack = 0; + for (o = 0; o < mOptions.Octaves; o += n_packsize) + { + for (v = 0; v < np_size; v++) + { + for (u = 0; u < np_size; u++) + { + p_noise[v * np_size + u + octavepack * np_size_sq] = + o_noise[(o + 3) * n_size_sq + (v & n_size_m1) * n_size + (u & n_size_m1)]; + p_noise[v * np_size + u + octavepack * np_size_sq] += _mapSample(u, v, 3, o); + p_noise[v * np_size + u + octavepack * np_size_sq] += _mapSample(u, v, 2, o + 1); + p_noise[v * np_size + u + octavepack * np_size_sq] += _mapSample(u, v, 1, o + 2); + } + } + + octavepack++; + } + } + } + + int Perlin::_readTexelLinearDual(const int &u, const int &v, const int &o) + { + int iu, iup, iv, ivp, fu, fv, ut01, ut23, ut; + + iu = (u >> n_dec_bits) & np_size_m1; + iv = ((v >> n_dec_bits) & np_size_m1) * np_size; + + iup = ((u >> n_dec_bits) + 1) & np_size_m1; + ivp = (((v >> n_dec_bits) + 1) & np_size_m1) * np_size; + + fu = u & n_dec_magn_m1; + fv = v & n_dec_magn_m1; + + ut01 = ((n_dec_magn - fu) * r_noise[iv + iu] + fu * r_noise[iv + iup]) >> n_dec_bits; + ut23 = ((n_dec_magn - fu) * r_noise[ivp + iu] + fu * r_noise[ivp + iup]) >> n_dec_bits; + ut = ((n_dec_magn - fv) * ut01 + fv * ut23) >> n_dec_bits; + + return ut; + } + + float Perlin::_getHeigthDual(float u, float v) + { + // Pointer to the current noise source octave + r_noise = p_noise; + + int ui = u * magnitude, vi = v * magnitude, i, value = 0, hoct = mOptions.Octaves / n_packsize; + + for (i = 0; i < hoct; i++) + { + value += _readTexelLinearDual(ui, vi, 0); + ui = ui << n_packsize; + vi = vi << n_packsize; + r_noise += np_size_sq; + } + + return static_cast(value) / noise_magnitude; + } + + int Perlin::_mapSample(const int &u, const int &v, const int &upsamplepower, const int &octave) + { + int magnitude = 1 << upsamplepower, + + pu = u >> upsamplepower, pv = v >> upsamplepower, + + fu = u & (magnitude - 1), fv = v & (magnitude - 1), + + fu_m = magnitude - fu, fv_m = magnitude - fv, + + o = fu_m * fv_m * o_noise[octave * n_size_sq + ((pv)&n_size_m1) * n_size + ((pu)&n_size_m1)] + + fu * fv_m * o_noise[octave * n_size_sq + ((pv)&n_size_m1) * n_size + ((pu + 1) & n_size_m1)] + + fu_m * fv * o_noise[octave * n_size_sq + ((pv + 1) & n_size_m1) * n_size + ((pu)&n_size_m1)] + + fu * fv * o_noise[octave * n_size_sq + ((pv + 1) & n_size_m1) * n_size + ((pu + 1) & n_size_m1)]; + + return o >> (upsamplepower + upsamplepower); + } + } // namespace Noise +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Perlin.h b/source/main/gfx/hydrax/Perlin.h index 90a6d532c7..d9f1fab544 100644 --- a/source/main/gfx/hydrax/Perlin.h +++ b/source/main/gfx/hydrax/Perlin.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -31,251 +31,231 @@ Based on the perlin noise code from Claes Johanson thesis: #include "Noise.h" -#define n_bits 5 -#define n_size (1<<(n_bits-1)) -#define n_size_m1 (n_size - 1) -#define n_size_sq (n_size*n_size) -#define n_size_sq_m1 (n_size_sq - 1) +#define n_bits 5 +#define n_size (1 << (n_bits - 1)) +#define n_size_m1 (n_size - 1) +#define n_size_sq (n_size * n_size) +#define n_size_sq_m1 (n_size_sq - 1) -#define n_packsize 4 +#define n_packsize 4 -#define np_bits (n_bits+n_packsize-1) -#define np_size (1<<(np_bits-1)) -#define np_size_m1 (np_size-1) -#define np_size_sq (np_size*np_size) -#define np_size_sq_m1 (np_size_sq-1) +#define np_bits (n_bits + n_packsize - 1) +#define np_size (1 << (np_bits - 1)) +#define np_size_m1 (np_size - 1) +#define np_size_sq (np_size * np_size) +#define np_size_sq_m1 (np_size_sq - 1) -#define n_dec_bits 12 -#define n_dec_magn 4096 -#define n_dec_magn_m1 4095 +#define n_dec_bits 12 +#define n_dec_magn 4096 +#define n_dec_magn_m1 4095 -#define max_octaves 32 +#define max_octaves 32 -#define noise_frames 256 -#define noise_frames_m1 (noise_frames-1) +#define noise_frames 256 +#define noise_frames_m1 (noise_frames - 1) -#define noise_decimalbits 15 -#define noise_magnitude (1<<(noise_decimalbits-1)) +#define noise_decimalbits 15 +#define noise_magnitude (1 << (noise_decimalbits - 1)) -#define scale_decimalbits 15 -#define scale_magnitude (1<<(scale_decimalbits-1)) +#define scale_decimalbits 15 +#define scale_magnitude (1 << (scale_decimalbits - 1)) -namespace Hydrax{ namespace Noise +namespace Hydrax { - /** Perlin noise module class - */ - class Perlin : public Noise - { - public: - /** Struct wich contains Perlin noise module options - */ - struct Options - { - /// Octaves - int Octaves; - /// Scale - float Scale; - /// Falloff - float Falloff; - /// Animspeed - float Animspeed; - /// Timemulti - float Timemulti; - - /** GPU Normal map generator parameters - Only if GPU normal map generation is active - */ - /// Representes the strength of the normals (i.e. Amplitude) - float GPU_Strength; - /** LOD Parameters, in order to obtain a smooth normal map we need to - decrease the detail level when the pixel is far to the camera. - This parameters are stored in an Ogre::Vector3: - x -> Initial LOD value (Bigger values -> less detail) - y -> Final LOD value - z -> Final distance - */ - Ogre::Vector3 GPU_LODParameters; - - /** Default constructor - */ - Options() - : Octaves(8) - , Scale(0.085f) - , Falloff(0.49f) - , Animspeed(1.4f) - , Timemulti(1.27f) - , GPU_Strength(2.0f) - , GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) - { - } - - /** Constructor - @param _Octaves Perlin noise octaves - @param _Scale Noise scale - @param _Falloff Noise fall off - @param _Animspeed Animation speed - @param _Timemulti Timemulti - */ - Options(const int &_Octaves, - const float &_Scale, - const float &_Falloff, - const float &_Animspeed, - const float &_Timemulti) - : Octaves(_Octaves) - , Scale(_Scale) - , Falloff(_Falloff) - , Animspeed(_Animspeed) - , Timemulti(_Timemulti) - , GPU_Strength(2.0f) - , GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) - { - } - - /** Constructor - @param _Octaves Perlin noise octaves - @param _Scale Noise scale - @param _Falloff Noise fall off - @param _Animspeed Animation speed - @param _Timemulti Timemulti - @param _GPU_Strength GPU_Strength - @param _GPU_LODParameters GPU_LODParameters - */ - Options(const int &_Octaves, - const float &_Scale, - const float &_Falloff, - const float &_Animspeed, - const float &_Timemulti, - const float &_GPU_Strength, - const Ogre::Vector3 &_GPU_LODParameters) - : Octaves(_Octaves) - , Scale(_Scale) - , Falloff(_Falloff) - , Animspeed(_Animspeed) - , Timemulti(_Timemulti) - , GPU_Strength(_GPU_Strength) - , GPU_LODParameters(_GPU_LODParameters) - { - } - }; - - /** Default constructor - */ - Perlin(); - - /** Constructor - @param Options Perlin noise options - */ - Perlin(const Options &Options); - - /** Destructor - */ - ~Perlin(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Create GPUNormalMap resources - @param g GPUNormalMapManager pointer - @return true if it needs to be created, false if not - */ - bool createGPUNormalMapResources(GPUNormalMapManager *g); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Save config - @param Data String reference - */ - void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct noise config - */ - bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get the especified x/y noise value - @param x X Coord - @param y Y Coord - @return Noise value - @remarks range [~-0.2, ~0.2] - */ - float getValue(const float &x, const float &y); - - /** Set/Update perlin noise options - @param Options Perlin noise options - @remarks If create() have been already called, Octaves option doesn't be updated. - */ - void setOptions(const Options &Options); - - /** Get current Perlin noise options - @return Current perlin noise options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - private: - /** Initialize noise - */ - void _initNoise(); - - /** Calcule noise - */ - void _calculeNoise(); - - /** Update gpu normal map resources - */ - void _updateGPUNormalMapResources(); - - /** Read texel linear dual - @param u u - @param v v - @param o Octave - @return int - */ - int _readTexelLinearDual(const int &u, const int &v, const int &o); - - /** Read texel linear - @param u u - @param v v - @return Heigth - */ - float _getHeigthDual(float u, float v); - - /** Map sample - @param u u - @param v v - @param level Level - @param octave Octave - @return Map sample - */ - int _mapSample(const int &u, const int &v, const int &upsamplepower, const int &octave); - - /// Perlin noise variables - int noise[n_size_sq*noise_frames]; - int o_noise[n_size_sq*max_octaves]; - int p_noise[np_size_sq*(max_octaves>>(n_packsize-1))]; - int *r_noise; - float magnitude; - - /// Elapsed time - double time; - - /// GPUNormalMapManager pointer - GPUNormalMapManager *mGPUNormalMapManager; - - /// Perlin noise options - Options mOptions; - }; -}} + namespace Noise + { + /** Perlin noise module class + */ + class Perlin : public Noise + { + public: + /** Struct wich contains Perlin noise module options + */ + struct Options + { + /// Octaves + int Octaves; + /// Scale + float Scale; + /// Falloff + float Falloff; + /// Animspeed + float Animspeed; + /// Timemulti + float Timemulti; + + /** GPU Normal map generator parameters + Only if GPU normal map generation is active + */ + /// Representes the strength of the normals (i.e. Amplitude) + float GPU_Strength; + /** LOD Parameters, in order to obtain a smooth normal map we need to + decrease the detail level when the pixel is far to the camera. + This parameters are stored in an Ogre::Vector3: + x -> Initial LOD value (Bigger values -> less detail) + y -> Final LOD value + z -> Final distance + */ + Ogre::Vector3 GPU_LODParameters; + + /** Default constructor + */ + Options() + : Octaves(8), Scale(0.085f), Falloff(0.49f), Animspeed(1.4f), Timemulti(1.27f), GPU_Strength(2.0f), + GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) + { + } + + /** Constructor + @param _Octaves Perlin noise octaves + @param _Scale Noise scale + @param _Falloff Noise fall off + @param _Animspeed Animation speed + @param _Timemulti Timemulti + */ + Options(const int &_Octaves, const float &_Scale, const float &_Falloff, const float &_Animspeed, + const float &_Timemulti) + : Octaves(_Octaves), Scale(_Scale), Falloff(_Falloff), Animspeed(_Animspeed), Timemulti(_Timemulti), + GPU_Strength(2.0f), GPU_LODParameters(Ogre::Vector3(0.5f, 50, 150000)) + { + } + + /** Constructor + @param _Octaves Perlin noise octaves + @param _Scale Noise scale + @param _Falloff Noise fall off + @param _Animspeed Animation speed + @param _Timemulti Timemulti + @param _GPU_Strength GPU_Strength + @param _GPU_LODParameters GPU_LODParameters + */ + Options(const int &_Octaves, const float &_Scale, const float &_Falloff, const float &_Animspeed, + const float &_Timemulti, const float &_GPU_Strength, const Ogre::Vector3 &_GPU_LODParameters) + : Octaves(_Octaves), Scale(_Scale), Falloff(_Falloff), Animspeed(_Animspeed), Timemulti(_Timemulti), + GPU_Strength(_GPU_Strength), GPU_LODParameters(_GPU_LODParameters) + { + } + }; + + /** Default constructor + */ + Perlin(); + + /** Constructor + @param Options Perlin noise options + */ + Perlin(const Options &Options); + + /** Destructor + */ + ~Perlin(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Create GPUNormalMap resources + @param g GPUNormalMapManager pointer + @return true if it needs to be created, false if not + */ + bool createGPUNormalMapResources(GPUNormalMapManager *g); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Save config + @param Data String reference + */ + void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct noise config + */ + bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get the especified x/y noise value + @param x X Coord + @param y Y Coord + @return Noise value + @remarks range [~-0.2, ~0.2] + */ + float getValue(const float &x, const float &y); + + /** Set/Update perlin noise options + @param Options Perlin noise options + @remarks If create() have been already called, Octaves option doesn't be updated. + */ + void setOptions(const Options &Options); + + /** Get current Perlin noise options + @return Current perlin noise options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + private: + /** Initialize noise + */ + void _initNoise(); + + /** Calcule noise + */ + void _calculeNoise(); + + /** Update gpu normal map resources + */ + void _updateGPUNormalMapResources(); + + /** Read texel linear dual + @param u u + @param v v + @param o Octave + @return int + */ + int _readTexelLinearDual(const int &u, const int &v, const int &o); + + /** Read texel linear + @param u u + @param v v + @return Heigth + */ + float _getHeigthDual(float u, float v); + + /** Map sample + @param u u + @param v v + @param level Level + @param octave Octave + @return Map sample + */ + int _mapSample(const int &u, const int &v, const int &upsamplepower, const int &octave); + + /// Perlin noise variables + int noise[n_size_sq * noise_frames]; + int o_noise[n_size_sq * max_octaves]; + int p_noise[np_size_sq * (max_octaves >> (n_packsize - 1))]; + int * r_noise; + float magnitude; + + /// Elapsed time + double time; + + /// GPUNormalMapManager pointer + GPUNormalMapManager *mGPUNormalMapManager; + + /// Perlin noise options + Options mOptions; + }; + } // namespace Noise +} // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/Prerequisites.h b/source/main/gfx/hydrax/Prerequisites.h index e54634849e..c64989a4d6 100644 --- a/source/main/gfx/hydrax/Prerequisites.h +++ b/source/main/gfx/hydrax/Prerequisites.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -33,8 +33,9 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #define HYDRAX_VERSION_MINOR 5 #define HYDRAX_VERSION_PATCH 4 -#define HYDRAX_IMAGE_CHECK_PIXELS 0 // See Image.cpp, 1 = Check pixels / 0 = No check pixels - // Use it for debug mode only +#define HYDRAX_IMAGE_CHECK_PIXELS \ + 0 // See Image.cpp, 1 = Check pixels / 0 = No check pixels + // Use it for debug mode only // Windows math library backport #ifndef M_PI diff --git a/source/main/gfx/hydrax/PressurePoint.cpp b/source/main/gfx/hydrax/PressurePoint.cpp index 6689f1596e..47228187cb 100644 --- a/source/main/gfx/hydrax/PressurePoint.cpp +++ b/source/main/gfx/hydrax/PressurePoint.cpp @@ -44,17 +44,12 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to using namespace Hydrax::Noise; -PressurePoint::PressurePoint(Ogre::Vector2 Orig, float p, float T, float L) - : mTime(0) - , mPos(Orig) - , mP(p) - , mT(T) - , mL(L) +PressurePoint::PressurePoint(Ogre::Vector2 Orig, float p, float T, float L) : mTime(0), mPos(Orig), mP(p), mT(T), mL(L) { mA = mP / _HydraxDensity_ / _HydraxGravity_; mK = 2.f * M_PI / mL; - mC = 5.f*sqrt(mL); - mW = mC*mK; + mC = 5.f * sqrt(mL); + mW = mC * mK; } PressurePoint::~PressurePoint() @@ -64,12 +59,13 @@ PressurePoint::~PressurePoint() bool PressurePoint::update(const Ogre::Real &timeSinceLastFrame) { mTime += timeSinceLastFrame; - if(mTime >= mT) { + if (mTime >= mT) + { mK1 = 0.f; return false; } - mK1 = exp(_LN001_/mT*mTime) - 0.01f; + mK1 = exp(_LN001_ / mT * mTime) - 0.01f; return true; } @@ -77,36 +73,32 @@ bool PressurePoint::update(const Ogre::Real &timeSinceLastFrame) float PressurePoint::getValue(const float &x, const float &y) { //! 1st.- Calculate distance. - float R = mC*mTime; + float R = mC * mTime; float dx = x - mPos.x; - if(dx > R) - return 0.f; + if (dx > R) return 0.f; float dy = y - mPos.y; - if(dy > R) - return 0.f; - #if _DECAYFUNCTION_ == 0 - float r = sqrt(dx*dx + dy*dy); - #elif _DECAYFUNCTION_ == 1 - float r = sqrt(dx*dx + dy*dy); - #elif _DECAYFUNCTION_ == 2 - float r = dx*dx + dy*dy; - float R2 = R*R; - #endif + if (dy > R) return 0.f; +#if _DECAYFUNCTION_ == 0 + float r = sqrt(dx * dx + dy * dy); +#elif _DECAYFUNCTION_ == 1 + float r = sqrt(dx * dx + dy * dy); +#elif _DECAYFUNCTION_ == 2 + float r = dx * dx + dy * dy; + float R2 = R * R; +#endif //! 2nd.- Calculate time decay factors - if(mTime >= mT) - return 0.f; + if (mTime >= mT) return 0.f; //! 2nd.- Calculate distance decay factors - if(r >= R) - return 0.f; - #if _DECAYFUNCTION_ == 0 - mK2 = 1.f - r/R; - #elif _DECAYFUNCTION_ == 1 - mK2 = exp(_LN001_*r/R) - 0.01f; - #elif _DECAYFUNCTION_ == 2 - float f = r/R2; - mK2 = 1.f - f; - r = f*R; - #endif + if (r >= R) return 0.f; +#if _DECAYFUNCTION_ == 0 + mK2 = 1.f - r / R; +#elif _DECAYFUNCTION_ == 1 + mK2 = exp(_LN001_ * r / R) - 0.01f; +#elif _DECAYFUNCTION_ == 2 + float f = r / R2; + mK2 = 1.f - f; + r = f * R; +#endif //! 3rd.- Calculate height - return mK1*mK2*mA*sin(mW*mTime - mK*r); + return mK1 * mK2 * mA * sin(mW * mTime - mK * r); } diff --git a/source/main/gfx/hydrax/PressurePoint.h b/source/main/gfx/hydrax/PressurePoint.h index c1215ac176..db36e1d10c 100644 --- a/source/main/gfx/hydrax/PressurePoint.h +++ b/source/main/gfx/hydrax/PressurePoint.h @@ -51,102 +51,117 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #define _HydraxGravity_ 9.81 #endif -namespace Hydrax{ namespace Noise +namespace Hydrax { - -/** @class PressurePoint PressurePoint.h Noise/PressurePoint/PressurePoint.h - * @brief A PressurePoint defined by the origen, pressure pulse, Maximum time of perturbation - * and wave longitude. \n - * Pressure points can be used to add object falling at sea, or, adding sucessive point, to simulate - * ship Kelvin wakes. - */ -class PressurePoint -{ -public: - /** Default constructor - * @param Orig Origin of perturbation. - * @param p Pressure pulse (N·m). \n - * The maximum half-amplitude of the wave will result from divide this value - * with g*rho. So, a pressure of 10000 N·m produces 2 m waves. - * @param T Maximum time of perturbation (s). \n - * The effect of the perturbation will decay. When T time will be elapsed, - * any effects will remain. - * @param L wave length. \n - * To objects falling, similar values to amplitude can be OK. For ships Kelvin - * wakes probably length of the ship is a better choice. - */ - PressurePoint(Ogre::Vector2 Orig, float p, float T, float L); - - /** Destructor - */ - ~PressurePoint(); - - /** Call it each frame - * @param timeSinceLastFrame Time since last frame(delta) - * @return false if the point can be deleted because time - * elapsed is bigger than maximum time. - */ - bool update(const Ogre::Real &timeSinceLastFrame); - - /** Get the especified x/y noise value - * @param x X Coord - * @param y Y Coord - * @return Noise value - * @remarks range [~-0.2, ~0.2] - */ - float getValue(const float &x, const float &y); - - /** Returns origin of the PressurePoint. - * @return Origin point. - */ - inline Ogre::Vector2 getOrigin() const{return mPos;} - /** Returns pressure pulse. - * @return Pressure. - */ - inline float GetTyrePressure() const{return mP;} - /** Returns maximum time. - * @return Maximum time. - */ - inline float getMaximumTime() const{return mT;} - /** Returns time ellapsed. - * @return Time elapsed. - */ - inline float getTime() const{return mTime;} - /** Returns wave length. - * @return Wave length. - */ - inline float getLength() const{return mL;} - -protected: - - -private: - /// Elapsed time - double mTime; - - /// Direction (must be normalised) - Ogre::Vector2 mPos; - /// Pressure - float mP; - /// Period - float mT; - /// Lenght - float mL; - /// Ampliutde - float mA; - /// Dispersion factor - float mK; - /// Speed (calculated) - float mC; - /// Angular frec. - float mW; - /// Time decay term - float mK1; - /// Distance decay term - float mK2; - -}; - -}} // Namespace + namespace Noise + { + + /** @class PressurePoint PressurePoint.h Noise/PressurePoint/PressurePoint.h + * @brief A PressurePoint defined by the origen, pressure pulse, Maximum time of perturbation + * and wave longitude. \n + * Pressure points can be used to add object falling at sea, or, adding sucessive point, to simulate + * ship Kelvin wakes. + */ + class PressurePoint + { + public: + /** Default constructor + * @param Orig Origin of perturbation. + * @param p Pressure pulse (N·m). \n + * The maximum half-amplitude of the wave will result from divide this value + * with g*rho. So, a pressure of 10000 N·m produces 2 m waves. + * @param T Maximum time of perturbation (s). \n + * The effect of the perturbation will decay. When T time will be elapsed, + * any effects will remain. + * @param L wave length. \n + * To objects falling, similar values to amplitude can be OK. For ships Kelvin + * wakes probably length of the ship is a better choice. + */ + PressurePoint(Ogre::Vector2 Orig, float p, float T, float L); + + /** Destructor + */ + ~PressurePoint(); + + /** Call it each frame + * @param timeSinceLastFrame Time since last frame(delta) + * @return false if the point can be deleted because time + * elapsed is bigger than maximum time. + */ + bool update(const Ogre::Real &timeSinceLastFrame); + + /** Get the especified x/y noise value + * @param x X Coord + * @param y Y Coord + * @return Noise value + * @remarks range [~-0.2, ~0.2] + */ + float getValue(const float &x, const float &y); + + /** Returns origin of the PressurePoint. + * @return Origin point. + */ + inline Ogre::Vector2 getOrigin() const + { + return mPos; + } + /** Returns pressure pulse. + * @return Pressure. + */ + inline float GetTyrePressure() const + { + return mP; + } + /** Returns maximum time. + * @return Maximum time. + */ + inline float getMaximumTime() const + { + return mT; + } + /** Returns time ellapsed. + * @return Time elapsed. + */ + inline float getTime() const + { + return mTime; + } + /** Returns wave length. + * @return Wave length. + */ + inline float getLength() const + { + return mL; + } + + protected: + private: + /// Elapsed time + double mTime; + + /// Direction (must be normalised) + Ogre::Vector2 mPos; + /// Pressure + float mP; + /// Period + float mT; + /// Lenght + float mL; + /// Ampliutde + float mA; + /// Dispersion factor + float mK; + /// Speed (calculated) + float mC; + /// Angular frec. + float mW; + /// Time decay term + float mK1; + /// Distance decay term + float mK2; + }; + + } // namespace Noise +} // namespace Hydrax #endif // PRESSUREPOINT_H_INCLUDED diff --git a/source/main/gfx/hydrax/ProjectedGrid.cpp b/source/main/gfx/hydrax/ProjectedGrid.cpp index fa951192a9..fb7e3691ed 100644 --- a/source/main/gfx/hydrax/ProjectedGrid.cpp +++ b/source/main/gfx/hydrax/ProjectedGrid.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -32,811 +32,751 @@ and Ren Cheng Ogre3D implementation: #define _def_MaxFarClipDistance 99999 -namespace Hydrax{namespace Module +namespace Hydrax { - Mesh::VertexType _PG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode& NormalMode) - { - if (NormalMode == MaterialManager::NM_VERTEX) - { - return Mesh::VT_POS_NORM; - } - - // NM_RTT - return Mesh::VT_POS; - } - - Ogre::String _PG_getNormalModeString(const MaterialManager::NormalMode& NormalMode) - { - if (NormalMode == MaterialManager::NM_VERTEX) - { - return "Vertex"; - } - - return "Rtt"; - } - - ProjectedGrid::ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode& NormalMode) - : Module("ProjectedGrid" + _PG_getNormalModeString(NormalMode), - n, Mesh::Options(256, Size(0), _PG_getVertexTypeFromNormalMode(NormalMode)), NormalMode) - , mHydrax(h) - , mVertices(0) - , mVerticesChoppyBuffer(0) - , mBasePlane(BasePlane) - , mNormal(BasePlane.normal) - , mPos(Ogre::Vector3(0,0,0)) - , mProjectingCamera(0) - , mTmpRndrngCamera(0) - , mRenderingCamera(h->getCamera()) - { - } - - ProjectedGrid::ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode& NormalMode, const Options &Options) - : Module("ProjectedGrid" + _PG_getNormalModeString(NormalMode), - n, Mesh::Options(Options.Complexity, Size(0), _PG_getVertexTypeFromNormalMode(NormalMode)), NormalMode) - , mHydrax(h) - , mVertices(0) - , mVerticesChoppyBuffer(0) - , mBasePlane(BasePlane) - , mNormal(BasePlane.normal) - , mPos(Ogre::Vector3(0,0,0)) - , mProjectingCamera(0) - , mTmpRndrngCamera(0) - , mRenderingCamera(h->getCamera()) - { - setOptions(Options); - } - - ProjectedGrid::~ProjectedGrid() - { - remove(); - - HydraxLOG(getName() + " destroyed."); - } - - void ProjectedGrid::setOptions(const Options &Options) - { - // Size(0) -> Infinite mesh - mMeshOptions.MeshSize = Size(0); - mMeshOptions.MeshStrength = Options.Strength; - mMeshOptions.MeshComplexity = Options.Complexity; - - mHydrax->getMesh()->setOptions(mMeshOptions); - mHydrax->_setStrength(Options.Strength); - - // Re-create geometry if it's needed - if (isCreated() && Options.Complexity != mOptions.Complexity) - { - remove(); - mOptions = Options; - create(); - - if (mNormalMode == MaterialManager::NM_RTT) - { - if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) - { - HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); - } - } - - Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); - mHydrax->getMesh()->remove(); - mHydrax->getMesh()->setOptions(getMeshOptions()); - mHydrax->getMesh()->setMaterialName(MaterialNameTmp); - mHydrax->getMesh()->create(); - - // Force to recalculate the geometry on next frame - mLastPosition = Ogre::Vector3(0,0,0); - mLastOrientation = Ogre::Quaternion(); - - return; - } - - mOptions = Options; - } - - void ProjectedGrid::create() - { - HydraxLOG("Creating " + getName() + " module."); - - Module::create(); - - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - mVertices = new Mesh::POS_NORM_VERTEX[mOptions.Complexity*mOptions.Complexity]; - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for (int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - Vertices[i].nx = 0; - Vertices[i].ny = -1; - Vertices[i].nz = 0; - } - - mVerticesChoppyBuffer = new Mesh::POS_NORM_VERTEX[mOptions.Complexity*mOptions.Complexity]; - } - else if(getNormalMode() == MaterialManager::NM_RTT) - { - mVertices = new Mesh::POS_VERTEX[mOptions.Complexity*mOptions.Complexity]; - } - - _setDisplacementAmplitude(0.0f); - - mTmpRndrngCamera = new Ogre::Camera("PG_TmpRndrngCamera", NULL); - mProjectingCamera = new Ogre::Camera("PG_ProjectingCamera", NULL); - - HydraxLOG(getName() + " created."); - } - - void ProjectedGrid::remove() - { - if (!isCreated()) - { - return; - } - - Module::remove(); - - if (mVertices) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - delete [] static_cast(mVertices); - mVertices = 0; - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - delete [] static_cast(mVertices); - mVertices = 0; - } - } - - if (mVerticesChoppyBuffer) - { - delete [] mVerticesChoppyBuffer; - } - - if (mTmpRndrngCamera) - { - delete mTmpRndrngCamera; - delete mProjectingCamera; - } - - mLastPosition = Ogre::Vector3(0,0,0); - mLastOrientation = Ogre::Quaternion(); - } - - void ProjectedGrid::saveCfg(Ogre::String &Data) - { - Module::saveCfg(Data); - - Data += CfgFileManager::_getCfgString("PG_ChoopyStrength", mOptions.ChoppyStrength); - Data += CfgFileManager::_getCfgString("PG_ChoppyWaves", mOptions.ChoppyWaves); - Data += CfgFileManager::_getCfgString("PG_Complexity", mOptions.Complexity); - Data += CfgFileManager::_getCfgString("PG_Elevation", mOptions.Elevation); - Data += CfgFileManager::_getCfgString("PG_ForceRecalculateGeometry", mOptions.ForceRecalculateGeometry); - Data += CfgFileManager::_getCfgString("PG_Smooth", mOptions.Smooth); - Data += CfgFileManager::_getCfgString("PG_Strength", mOptions.Strength); Data += "\n"; - } - - bool ProjectedGrid::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (!Module::loadCfg(CfgFile)) - { - return false; - } - - HydraxLOG("\tReading options..."); - setOptions( - Options(CfgFileManager::_getIntValue(CfgFile, "PG_Complexity"), - CfgFileManager::_getFloatValue(CfgFile, "PG_Strength"), - CfgFileManager::_getFloatValue(CfgFile, "PG_Elevation"), - CfgFileManager::_getBoolValue(CfgFile, "PG_Smooth"), - CfgFileManager::_getBoolValue(CfgFile, "PG_ForceRecalculateGeometry"), - CfgFileManager::_getBoolValue(CfgFile, "PG_ChoppyWaves"), - CfgFileManager::_getFloatValue(CfgFile, "PG_ChoopyStrength"))); - - HydraxLOG("\tOptions readed."); - - return true; - } - - void ProjectedGrid::update(const Ogre::Real &timeSinceLastFrame) - { - if (!isCreated()) - { - return; - } - - Module::update(timeSinceLastFrame); - - Ogre::Vector3 RenderingCameraPos = mRenderingCamera->getDerivedPosition(); - - if (mLastPosition != RenderingCameraPos || - mLastOrientation != mRenderingCamera->getDerivedOrientation() || - mOptions.ForceRecalculateGeometry) - { - if (mLastPosition != RenderingCameraPos) - { - Ogre::Vector3 HydraxPos = Ogre::Vector3(RenderingCameraPos.x,mHydrax->getPosition().y,RenderingCameraPos.z); - - mHydrax->getMesh()->getSceneNode()->setPosition(HydraxPos); - mHydrax->getRttManager()->getPlanesSceneNode()->setPosition(HydraxPos); - - // For world-space -> object-space conversion - mHydrax->setSunPosition(mHydrax->getSunPosition()); - } - - float RenderingFarClipDistance = mRenderingCamera->getFarClipDistance(); - - if (RenderingFarClipDistance > _def_MaxFarClipDistance) - { - mRenderingCamera->setFarClipDistance(_def_MaxFarClipDistance); - } - - mLastMinMax = _getMinMax(&mRange); - - if (mLastMinMax) - { - _renderGeometry(mRange, mProjectingCamera->getViewMatrix(), RenderingCameraPos); - - mHydrax->getMesh()->updateGeometry(mOptions.Complexity*mOptions.Complexity, mVertices); - } - - mRenderingCamera->setFarClipDistance(RenderingFarClipDistance); - } - else if (mLastMinMax) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - if (mOptions.ChoppyWaves) - { - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - Vertices[i] = mVerticesChoppyBuffer[i]; - Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, RenderingCameraPos.z + Vertices[i].z)*mOptions.Strength; - } - } - else - { - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, RenderingCameraPos.z + Vertices[i].z)*mOptions.Strength; - } - } - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, RenderingCameraPos.z + Vertices[i].z)*mOptions.Strength; - } - } - - // Smooth the heightdata - if (mOptions.Smooth) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(int v=1; v<(mOptions.Complexity-1); v++) - { - for(int u=1; u<(mOptions.Complexity-1); u++) - { - Vertices[v*mOptions.Complexity + u].y = - 0.2f * - (Vertices[v *mOptions.Complexity + u ].y + - Vertices[v *mOptions.Complexity + (u+1)].y + - Vertices[v *mOptions.Complexity + (u-1)].y + - Vertices[(v+1)*mOptions.Complexity + u ].y + - Vertices[(v-1)*mOptions.Complexity + u ].y); - } - } - } - else if(getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(int v=1; v<(mOptions.Complexity-1); v++) - { - for(int u=1; u<(mOptions.Complexity-1); u++) - { - Vertices[v*mOptions.Complexity + u].y = - 0.2f * - (Vertices[v *mOptions.Complexity + u ].y + - Vertices[v *mOptions.Complexity + (u+1)].y + - Vertices[v *mOptions.Complexity + (u-1)].y + - Vertices[(v+1)*mOptions.Complexity + u ].y + - Vertices[(v-1)*mOptions.Complexity + u ].y); - } - } - } - } - - _calculeNormals(); - - _performChoppyWaves(); - - mHydrax->getMesh()->updateGeometry(mOptions.Complexity*mOptions.Complexity, mVertices); - } - - mLastPosition = RenderingCameraPos; - mLastOrientation = mRenderingCamera->getDerivedOrientation(); - } - - bool ProjectedGrid::_renderGeometry(const Ogre::Matrix4& m,const Ogre::Matrix4& _viewMat, const Ogre::Vector3& WorldPos) - { - t_corners0 = _calculeWorldPosition(Ogre::Vector2( 0.0f, 0.0f),m,_viewMat); - t_corners1 = _calculeWorldPosition(Ogre::Vector2(+1.0f, 0.0f),m,_viewMat); - t_corners2 = _calculeWorldPosition(Ogre::Vector2( 0.0f,+1.0f),m,_viewMat); - t_corners3 = _calculeWorldPosition(Ogre::Vector2(+1.0f,+1.0f),m,_viewMat); - - float du = 1.0f/(mOptions.Complexity-1), - dv = 1.0f/(mOptions.Complexity-1), - u,v = 0.0f, - // _1_u = (1.0f-u) - _1_u, _1_v = 1.0f, - divide; - - Ogre::Vector4 result; - - int i = 0, iv, iu; - - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(iv=0; ivgetValue(WorldPos.x + result.x, WorldPos.z + result.z)*mOptions.Strength; - - i++; - u += du; - _1_u = 1.0f-u; - } - v += dv; - _1_v = 1.0f-v; - } - - if (mOptions.ChoppyWaves) - { - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - mVerticesChoppyBuffer[i] = Vertices[i]; - } - } - } - else if(getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(iv=0; ivgetValue(WorldPos.x + result.x, WorldPos.z + result.z)*mOptions.Strength; - - i++; - u += du; - _1_u = 1.0f-u; - } - v += dv; - _1_v = 1.0f-v; - } - } - - // Smooth the heightdata - if (mOptions.Smooth) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(iv=1; iv<(mOptions.Complexity-1); iv++) - { - for(iu=1; iu<(mOptions.Complexity-1); iu++) - { - Vertices[iv*mOptions.Complexity + iu].y = - 0.2f * - (Vertices[iv *mOptions.Complexity + iu ].y + - Vertices[iv *mOptions.Complexity + (iu+1)].y + - Vertices[iv *mOptions.Complexity + (iu-1)].y + - Vertices[(iv+1)*mOptions.Complexity + iu ].y + - Vertices[(iv-1)*mOptions.Complexity + iu ].y); - } - } - } - else if(getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(iv=1; iv<(mOptions.Complexity-1); iv++) - { - for(iu=1; iu<(mOptions.Complexity-1); iu++) - { - Vertices[iv*mOptions.Complexity + iu].y = - 0.2f * - (Vertices[iv *mOptions.Complexity + iu ].y + - Vertices[iv *mOptions.Complexity + (iu+1)].y + - Vertices[iv *mOptions.Complexity + (iu-1)].y + - Vertices[(iv+1)*mOptions.Complexity + iu ].y + - Vertices[(iv-1)*mOptions.Complexity + iu ].y); - } - } - } - } - - _calculeNormals(); - - _performChoppyWaves(); - - return true; - } - - void ProjectedGrid::_calculeNormals() - { - if (getNormalMode() != MaterialManager::NM_VERTEX) - { - return; - } - - int v, u; - Ogre::Vector3 vec1, vec2, normal; - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(v=1; v<(mOptions.Complexity-1); v++) - { - for(u=1; u<(mOptions.Complexity-1); u++) - { - vec1 = Ogre::Vector3( - Vertices[v*mOptions.Complexity + u + 1].x-Vertices[v*mOptions.Complexity + u - 1].x, - Vertices[v*mOptions.Complexity + u + 1].y-Vertices[v*mOptions.Complexity + u - 1].y, - Vertices[v*mOptions.Complexity + u + 1].z-Vertices[v*mOptions.Complexity + u - 1].z); - - vec2 = Ogre::Vector3( - Vertices[(v+1)*mOptions.Complexity + u].x - Vertices[(v-1)*mOptions.Complexity + u].x, - Vertices[(v+1)*mOptions.Complexity + u].y - Vertices[(v-1)*mOptions.Complexity + u].y, - Vertices[(v+1)*mOptions.Complexity + u].z - Vertices[(v-1)*mOptions.Complexity + u].z); - - normal = vec2.crossProduct(vec1); - - Vertices[v*mOptions.Complexity + u].nx = normal.x; - Vertices[v*mOptions.Complexity + u].ny = normal.y; - Vertices[v*mOptions.Complexity + u].nz = normal.z; - } - } - } - - void ProjectedGrid::_performChoppyWaves() - { - if (getNormalMode() != MaterialManager::NM_VERTEX || !mOptions.ChoppyWaves) - { - return; - } - - int v, u, - Underwater = 1; - - if (mHydrax->_isCurrentFrameUnderwater()) - { - Underwater = -1; - } - - float Dis1, Dis2;//, - // Dis1_, Dis2_; - - Ogre::Vector3 CameraDir, Norm; - Ogre::Vector2 Dir, Perp, Norm2; - - CameraDir = mRenderingCamera->getDerivedDirection(); - Dir = Ogre::Vector2(CameraDir.x, CameraDir.z).normalisedCopy(); - Perp = Dir.perpendicular(); - - if (Dir.x < 0 ) Dir.x = -Dir.x; - if (Dir.y < 0 ) Dir.y = -Dir.y; - - if (Perp.x < 0 ) Perp.x = -Perp.x; - if (Perp.y < 0 ) Perp.y = -Perp.y; - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(v=1; v<(mOptions.Complexity-1); v++) - { - Dis1 = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + 1].x, - mVerticesChoppyBuffer[v*mOptions.Complexity + 1].z) - - Ogre::Vector2(mVerticesChoppyBuffer[(v+1)*mOptions.Complexity + 1].x, - mVerticesChoppyBuffer[(v+1)*mOptions.Complexity + 1].z)).length(); - - /*Dis1_ = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + 1].x, - mVerticesChoppyBuffer[v*mOptions.Complexity + 1].z) - - Ogre::Vector2(mVerticesChoppyBuffer[(v-1)*mOptions.Complexity + 1].x, - mVerticesChoppyBuffer[(v-1)*mOptions.Complexity + 1].z)).length(); - - Dis1 = (Dis1+Dis1_)/2;*/ - - for(u=1; u<(mOptions.Complexity-1); u++) - { - Dis2 = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u].x, - mVerticesChoppyBuffer[v*mOptions.Complexity + u].z) - - Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u+1].x, - mVerticesChoppyBuffer[v*mOptions.Complexity + u+1].z)).length(); -/* - Dis2_ = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u].x, - mVerticesChoppyBuffer[v*mOptions.Complexity + u].z) - - Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u-1].x, - mVerticesChoppyBuffer[v*mOptions.Complexity + u-1].z)).length(); - - Dis2 = (Dis2+Dis2_)/2;*/ - - Norm = Ogre::Vector3(Vertices[v*mOptions.Complexity + u].nx, - Vertices[v*mOptions.Complexity + u].ny, - Vertices[v*mOptions.Complexity + u].nz). - normalisedCopy(); - - Norm2 = Ogre::Vector2(Norm.x, Norm.z) * - ( (Dir * Dis1) + - (Perp * Dis2)) * - mOptions.ChoppyStrength; - - Vertices[v*mOptions.Complexity + u].x = mVerticesChoppyBuffer[v*mOptions.Complexity + u].x + Norm2.x * Underwater; - Vertices[v*mOptions.Complexity + u].z = mVerticesChoppyBuffer[v*mOptions.Complexity + u].z + Norm2.y * Underwater; - } - } - } - - // Check the point of intersection with the plane (0,1,0,0) and return the position in homogenous coordinates - Ogre::Vector4 ProjectedGrid::_calculeWorldPosition(const Ogre::Vector2 &uv, const Ogre::Matrix4& m, const Ogre::Matrix4& _viewMat) - { - Ogre::Vector4 origin(uv.x,uv.y,-1,1); - Ogre::Vector4 direction(uv.x,uv.y,1,1); - - origin = m*origin; - direction = m*direction; - - Ogre::Vector3 _org(origin.x/origin.w,origin.y/origin.w,origin.z/origin.w); - Ogre::Vector3 _dir(direction.x/direction.w,direction.y/direction.w,direction.z/direction.w); - _dir -= _org; - _dir.normalise(); - - Ogre::Ray _ray(_org,_dir); - std::pair _result = _ray.intersects(mBasePlane); - float l = _result.second; - Ogre::Vector3 worldPos = _org + _dir*l; - Ogre::Vector4 _tempVec = _viewMat*Ogre::Vector4(worldPos); - float _temp = -_tempVec.z/_tempVec.w; - Ogre::Vector4 retPos(worldPos); - retPos /= _temp; - - return retPos; - } - - bool ProjectedGrid::_getMinMax(Ogre::Matrix4 *range) - { - _setDisplacementAmplitude(mOptions.Strength); - - float x_min,y_min,x_max,y_max; - Ogre::Vector3 frustum[8],proj_points[24]; - - int i, - n_points = 0, - src, dst; - - int cube[] = - {0,1, 0,2, 2,3, 1,3, - 0,4, 2,6, 3,7, 1,5, - 4,6, 4,5, 5,7, 6,7}; - - Ogre::Vector3 _testLine; - Ogre::Real _dist; - Ogre::Ray _ray; - - std::pair _result; - - // Set temporal rendering camera parameters - mTmpRndrngCamera->setFrustumOffset(mRenderingCamera->getFrustumOffset()); - mTmpRndrngCamera->setAspectRatio(mRenderingCamera->getAspectRatio()); - mTmpRndrngCamera->setDirection(mRenderingCamera->getDerivedDirection()); - mTmpRndrngCamera->setFarClipDistance(mRenderingCamera->getFarClipDistance()); - mTmpRndrngCamera->setFOVy(mRenderingCamera->getFOVy()); - mTmpRndrngCamera->setNearClipDistance(mRenderingCamera->getNearClipDistance()); - mTmpRndrngCamera->setOrientation(mRenderingCamera->getDerivedOrientation()); - mTmpRndrngCamera->setPosition(0, mRenderingCamera->getDerivedPosition().y - mHydrax->getPosition().y, 0); - - Ogre::Matrix4 invviewproj = (mTmpRndrngCamera->getProjectionMatrixWithRSDepth()*mTmpRndrngCamera->getViewMatrix()).inverse(); - frustum[0] = invviewproj * Ogre::Vector3(-1,-1,0); - frustum[1] = invviewproj * Ogre::Vector3(+1,-1,0); - frustum[2] = invviewproj * Ogre::Vector3(-1,+1,0); - frustum[3] = invviewproj * Ogre::Vector3(+1,+1,0); - frustum[4] = invviewproj * Ogre::Vector3(-1,-1,+1); - frustum[5] = invviewproj * Ogre::Vector3(+1,-1,+1); - frustum[6] = invviewproj * Ogre::Vector3(-1,+1,+1); - frustum[7] = invviewproj * Ogre::Vector3(+1,+1,+1); - - // Check intersections with upper_bound and lower_bound - for(i=0; i<12; i++) - { - src=cube[i*2]; dst=cube[i*2+1]; - _testLine = frustum[dst]-frustum[src]; - _dist = _testLine.normalise(); - _ray = Ogre::Ray(frustum[src], _testLine); - _result = Ogre::Math::intersects(_ray,mUpperBoundPlane); - if ((_result.first) && (_result.second<_dist+0.00001)) - { - proj_points[n_points++] = frustum[src] + _result.second * _testLine; - } - _result = Ogre::Math::intersects(_ray,mLowerBoundPlane); - if ((_result.first) && (_result.second<_dist+0.00001)) - { - proj_points[n_points++] = frustum[src] + _result.second * _testLine; - } - } - - // Check if any of the frustums vertices lie between the upper_bound and lower_bound planes - for(i=0; i<8; i++) - { - if(mUpperBoundPlane.getDistance(frustum[i])/mLowerBoundPlane.getDistance(frustum[i]) < 0) - { - proj_points[n_points++] = frustum[i]; - } - } - - // Set projecting camera parameters - mProjectingCamera->setFrustumOffset(mTmpRndrngCamera->getFrustumOffset()); - mProjectingCamera->setAspectRatio(mTmpRndrngCamera->getAspectRatio()); - mProjectingCamera->setDirection(mTmpRndrngCamera->getDerivedDirection()); - mProjectingCamera->setFarClipDistance(mTmpRndrngCamera->getFarClipDistance()); - mProjectingCamera->setFOVy(mTmpRndrngCamera->getFOVy()); - mProjectingCamera->setNearClipDistance(mTmpRndrngCamera->getNearClipDistance()); - mProjectingCamera->setOrientation(mTmpRndrngCamera->getDerivedOrientation()); - mProjectingCamera->setPosition(mTmpRndrngCamera->getDerivedPosition()); - - // Make sure the camera isn't too close to the plane - float height_in_plane = mBasePlane.getDistance(mProjectingCamera->getRealPosition()); - - bool keep_it_simple = false, - underwater = false; - - if (height_in_plane < 0.0f) - { - underwater = true; - } - - if (keep_it_simple) - { - mProjectingCamera->setDirection(mTmpRndrngCamera->getDerivedDirection()); - } - else - { - Ogre::Vector3 aimpoint, aimpoint2; - - if (height_in_plane < (mOptions.Strength + mOptions.Elevation)) - { - if (underwater) - { - mProjectingCamera->setPosition(mProjectingCamera->getRealPosition()+mLowerBoundPlane.normal*(mOptions.Strength + mOptions.Elevation - 2*height_in_plane)); - } - else - { - mProjectingCamera->setPosition(mProjectingCamera->getRealPosition()+mLowerBoundPlane.normal*(mOptions.Strength + mOptions.Elevation - height_in_plane)); - } - } - - // Aim the projector at the point where the camera view-vector intersects the plane - // if the camera is aimed away from the plane, mirror it's view-vector against the plane - if (((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedDirection()) < 0.0f) || ((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedPosition()) < 0.0f ) ) - { - _ray = Ogre::Ray(mTmpRndrngCamera->getDerivedPosition(), mTmpRndrngCamera->getDerivedDirection()); - _result = Ogre::Math::intersects(_ray,mBasePlane); - - if(!_result.first) - { - _result.second = -_result.second; - } - - aimpoint = mTmpRndrngCamera->getDerivedPosition() + _result.second * mTmpRndrngCamera->getDerivedDirection(); - } - else - { - Ogre::Vector3 flipped = mTmpRndrngCamera->getDerivedDirection() - 2*mNormal* (mTmpRndrngCamera->getDerivedDirection()).dotProduct(mNormal); - flipped.normalise(); - _ray = Ogre::Ray( mTmpRndrngCamera->getDerivedPosition(), flipped); - _result = Ogre::Math::intersects(_ray,mBasePlane); - - aimpoint = mTmpRndrngCamera->getDerivedPosition() + _result.second * flipped; - } - - // Force the point the camera is looking at in a plane, and have the projector look at it - // works well against horizon, even when camera is looking upwards - // doesn't work straight down/up - float af = fabs((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedDirection())); - aimpoint2 = mTmpRndrngCamera->getDerivedPosition() + 10.0*mTmpRndrngCamera->getDerivedDirection(); - aimpoint2 = aimpoint2 - mNormal* (aimpoint2.dotProduct(mNormal)); - - // Fade between aimpoint & aimpoint2 depending on view angle - aimpoint = aimpoint*af + aimpoint2*(1.0f-af); - - mProjectingCamera->setDirection(aimpoint-mProjectingCamera->getRealPosition()); - } - - for(i=0; igetViewMatrix() * proj_points[i]; - proj_points[i] = mProjectingCamera->getProjectionMatrixWithRSDepth() * proj_points[i]; - } - - // Get max/min x & y-values to determine how big the "projection window" must be - if (n_points > 0) - { - x_min = proj_points[0].x; - x_max = proj_points[0].x; - y_min = proj_points[0].y; - y_max = proj_points[0].y; - - for(i=1; i x_max) x_max = proj_points[i].x; - if (proj_points[i].x < x_min) x_min = proj_points[i].x; - if (proj_points[i].y > y_max) y_max = proj_points[i].y; - if (proj_points[i].y < y_min) y_min = proj_points[i].y; - } - - // Build the packing matrix that spreads the grid across the "projection window" - Ogre::Matrix4 pack(x_max-x_min, 0, 0, x_min, - 0, y_max-y_min, 0, y_min, - 0, 0, 1, 0, - 0, 0, 0, 1); - - Ogre::Matrix4 invviewproj = (mProjectingCamera->getProjectionMatrixWithRSDepth()*mProjectingCamera->getViewMatrix()).inverse(); - *range = invviewproj * pack; - - return true; - } - - return false; - } - - void ProjectedGrid::_setDisplacementAmplitude(const float &Amplitude) - { - mUpperBoundPlane = Ogre::Plane( mNormal, mPos + Amplitude * mNormal); - mLowerBoundPlane = Ogre::Plane( mNormal, mPos - Amplitude * mNormal); - } - - float ProjectedGrid::getHeigth(const Ogre::Vector2 &Position) - { - return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y)*mOptions.Strength; - } -}} + namespace Module + { + Mesh::VertexType _PG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode &NormalMode) + { + if (NormalMode == MaterialManager::NM_VERTEX) { return Mesh::VT_POS_NORM; } + + // NM_RTT + return Mesh::VT_POS; + } + + Ogre::String _PG_getNormalModeString(const MaterialManager::NormalMode &NormalMode) + { + if (NormalMode == MaterialManager::NM_VERTEX) { return "Vertex"; } + + return "Rtt"; + } + + ProjectedGrid::ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, + const MaterialManager::NormalMode &NormalMode) + : Module("ProjectedGrid" + _PG_getNormalModeString(NormalMode), n, + Mesh::Options(256, Size(0), _PG_getVertexTypeFromNormalMode(NormalMode)), NormalMode), + mHydrax(h), mVertices(0), mVerticesChoppyBuffer(0), mBasePlane(BasePlane), mNormal(BasePlane.normal), + mPos(Ogre::Vector3(0, 0, 0)), mProjectingCamera(0), mTmpRndrngCamera(0), mRenderingCamera(h->getCamera()) + { + } + + ProjectedGrid::ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, + const MaterialManager::NormalMode &NormalMode, const Options &Options) + : Module("ProjectedGrid" + _PG_getNormalModeString(NormalMode), n, + Mesh::Options(Options.Complexity, Size(0), _PG_getVertexTypeFromNormalMode(NormalMode)), NormalMode), + mHydrax(h), mVertices(0), mVerticesChoppyBuffer(0), mBasePlane(BasePlane), mNormal(BasePlane.normal), + mPos(Ogre::Vector3(0, 0, 0)), mProjectingCamera(0), mTmpRndrngCamera(0), mRenderingCamera(h->getCamera()) + { + setOptions(Options); + } + + ProjectedGrid::~ProjectedGrid() + { + remove(); + + HydraxLOG(getName() + " destroyed."); + } + + void ProjectedGrid::setOptions(const Options &Options) + { + // Size(0) -> Infinite mesh + mMeshOptions.MeshSize = Size(0); + mMeshOptions.MeshStrength = Options.Strength; + mMeshOptions.MeshComplexity = Options.Complexity; + + mHydrax->getMesh()->setOptions(mMeshOptions); + mHydrax->_setStrength(Options.Strength); + + // Re-create geometry if it's needed + if (isCreated() && Options.Complexity != mOptions.Complexity) + { + remove(); + mOptions = Options; + create(); + + if (mNormalMode == MaterialManager::NM_RTT) + { + if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) + { HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); } + } + + Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); + mHydrax->getMesh()->remove(); + mHydrax->getMesh()->setOptions(getMeshOptions()); + mHydrax->getMesh()->setMaterialName(MaterialNameTmp); + mHydrax->getMesh()->create(); + + // Force to recalculate the geometry on next frame + mLastPosition = Ogre::Vector3(0, 0, 0); + mLastOrientation = Ogre::Quaternion(); + + return; + } + + mOptions = Options; + } + + void ProjectedGrid::create() + { + HydraxLOG("Creating " + getName() + " module."); + + Module::create(); + + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + mVertices = new Mesh::POS_NORM_VERTEX[mOptions.Complexity * mOptions.Complexity]; + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + Vertices[i].nx = 0; + Vertices[i].ny = -1; + Vertices[i].nz = 0; + } + + mVerticesChoppyBuffer = new Mesh::POS_NORM_VERTEX[mOptions.Complexity * mOptions.Complexity]; + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + mVertices = new Mesh::POS_VERTEX[mOptions.Complexity * mOptions.Complexity]; + } + + _setDisplacementAmplitude(0.0f); + + mTmpRndrngCamera = new Ogre::Camera("PG_TmpRndrngCamera", NULL); + mProjectingCamera = new Ogre::Camera("PG_ProjectingCamera", NULL); + + HydraxLOG(getName() + " created."); + } + + void ProjectedGrid::remove() + { + if (!isCreated()) { return; } + + Module::remove(); + + if (mVertices) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + delete[] static_cast(mVertices); + mVertices = 0; + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + delete[] static_cast(mVertices); + mVertices = 0; + } + } + + if (mVerticesChoppyBuffer) { delete[] mVerticesChoppyBuffer; } + + if (mTmpRndrngCamera) + { + delete mTmpRndrngCamera; + delete mProjectingCamera; + } + + mLastPosition = Ogre::Vector3(0, 0, 0); + mLastOrientation = Ogre::Quaternion(); + } + + void ProjectedGrid::saveCfg(Ogre::String &Data) + { + Module::saveCfg(Data); + + Data += CfgFileManager::_getCfgString("PG_ChoopyStrength", mOptions.ChoppyStrength); + Data += CfgFileManager::_getCfgString("PG_ChoppyWaves", mOptions.ChoppyWaves); + Data += CfgFileManager::_getCfgString("PG_Complexity", mOptions.Complexity); + Data += CfgFileManager::_getCfgString("PG_Elevation", mOptions.Elevation); + Data += CfgFileManager::_getCfgString("PG_ForceRecalculateGeometry", mOptions.ForceRecalculateGeometry); + Data += CfgFileManager::_getCfgString("PG_Smooth", mOptions.Smooth); + Data += CfgFileManager::_getCfgString("PG_Strength", mOptions.Strength); + Data += "\n"; + } + + bool ProjectedGrid::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (!Module::loadCfg(CfgFile)) { return false; } + + HydraxLOG("\tReading options..."); + setOptions(Options( + CfgFileManager::_getIntValue(CfgFile, "PG_Complexity"), CfgFileManager::_getFloatValue(CfgFile, "PG_Strength"), + CfgFileManager::_getFloatValue(CfgFile, "PG_Elevation"), CfgFileManager::_getBoolValue(CfgFile, "PG_Smooth"), + CfgFileManager::_getBoolValue(CfgFile, "PG_ForceRecalculateGeometry"), + CfgFileManager::_getBoolValue(CfgFile, "PG_ChoppyWaves"), + CfgFileManager::_getFloatValue(CfgFile, "PG_ChoopyStrength"))); + + HydraxLOG("\tOptions readed."); + + return true; + } + + void ProjectedGrid::update(const Ogre::Real &timeSinceLastFrame) + { + if (!isCreated()) { return; } + + Module::update(timeSinceLastFrame); + + Ogre::Vector3 RenderingCameraPos = mRenderingCamera->getDerivedPosition(); + + if (mLastPosition != RenderingCameraPos || mLastOrientation != mRenderingCamera->getDerivedOrientation() || + mOptions.ForceRecalculateGeometry) + { + if (mLastPosition != RenderingCameraPos) + { + Ogre::Vector3 HydraxPos = Ogre::Vector3(RenderingCameraPos.x, mHydrax->getPosition().y, RenderingCameraPos.z); + + mHydrax->getMesh()->getSceneNode()->setPosition(HydraxPos); + mHydrax->getRttManager()->getPlanesSceneNode()->setPosition(HydraxPos); + + // For world-space -> object-space conversion + mHydrax->setSunPosition(mHydrax->getSunPosition()); + } + + float RenderingFarClipDistance = mRenderingCamera->getFarClipDistance(); + + if (RenderingFarClipDistance > _def_MaxFarClipDistance) + { mRenderingCamera->setFarClipDistance(_def_MaxFarClipDistance); } + + mLastMinMax = _getMinMax(&mRange); + + if (mLastMinMax) + { + _renderGeometry(mRange, mProjectingCamera->getViewMatrix(), RenderingCameraPos); + + mHydrax->getMesh()->updateGeometry(mOptions.Complexity * mOptions.Complexity, mVertices); + } + + mRenderingCamera->setFarClipDistance(RenderingFarClipDistance); + } + else if (mLastMinMax) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + if (mOptions.ChoppyWaves) + { + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + Vertices[i] = mVerticesChoppyBuffer[i]; + Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, + RenderingCameraPos.z + Vertices[i].z) * + mOptions.Strength; + } + } + else + { + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, + RenderingCameraPos.z + Vertices[i].z) * + mOptions.Strength; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, + RenderingCameraPos.z + Vertices[i].z) * + mOptions.Strength; + } + } + + // Smooth the heightdata + if (mOptions.Smooth) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (int v = 1; v < (mOptions.Complexity - 1); v++) + { + for (int u = 1; u < (mOptions.Complexity - 1); u++) + { + Vertices[v * mOptions.Complexity + u].y = 0.2f * (Vertices[v * mOptions.Complexity + u].y + + Vertices[v * mOptions.Complexity + (u + 1)].y + + Vertices[v * mOptions.Complexity + (u - 1)].y + + Vertices[(v + 1) * mOptions.Complexity + u].y + + Vertices[(v - 1) * mOptions.Complexity + u].y); + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (int v = 1; v < (mOptions.Complexity - 1); v++) + { + for (int u = 1; u < (mOptions.Complexity - 1); u++) + { + Vertices[v * mOptions.Complexity + u].y = 0.2f * (Vertices[v * mOptions.Complexity + u].y + + Vertices[v * mOptions.Complexity + (u + 1)].y + + Vertices[v * mOptions.Complexity + (u - 1)].y + + Vertices[(v + 1) * mOptions.Complexity + u].y + + Vertices[(v - 1) * mOptions.Complexity + u].y); + } + } + } + } + + _calculeNormals(); + + _performChoppyWaves(); + + mHydrax->getMesh()->updateGeometry(mOptions.Complexity * mOptions.Complexity, mVertices); + } + + mLastPosition = RenderingCameraPos; + mLastOrientation = mRenderingCamera->getDerivedOrientation(); + } + + bool ProjectedGrid::_renderGeometry(const Ogre::Matrix4 &m, const Ogre::Matrix4 &_viewMat, const Ogre::Vector3 &WorldPos) + { + t_corners0 = _calculeWorldPosition(Ogre::Vector2(0.0f, 0.0f), m, _viewMat); + t_corners1 = _calculeWorldPosition(Ogre::Vector2(+1.0f, 0.0f), m, _viewMat); + t_corners2 = _calculeWorldPosition(Ogre::Vector2(0.0f, +1.0f), m, _viewMat); + t_corners3 = _calculeWorldPosition(Ogre::Vector2(+1.0f, +1.0f), m, _viewMat); + + float du = 1.0f / (mOptions.Complexity - 1), dv = 1.0f / (mOptions.Complexity - 1), u, v = 0.0f, + // _1_u = (1.0f-u) + _1_u, _1_v = 1.0f, divide; + + Ogre::Vector4 result; + + int i = 0, iv, iu; + + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (iv = 0; iv < mOptions.Complexity; iv++) + { + u = 0.0f; + _1_u = 1.0f; + for (iu = 0; iu < mOptions.Complexity; iu++) + { + result.x = _1_v * (_1_u * t_corners0.x + u * t_corners1.x) + v * (_1_u * t_corners2.x + u * t_corners3.x); + result.z = _1_v * (_1_u * t_corners0.z + u * t_corners1.z) + v * (_1_u * t_corners2.z + u * t_corners3.z); + result.w = _1_v * (_1_u * t_corners0.w + u * t_corners1.w) + v * (_1_u * t_corners2.w + u * t_corners3.w); + + divide = 1.0f / result.w; + result.x *= divide; + result.z *= divide; + + Vertices[i].x = result.x; + Vertices[i].z = result.z; + Vertices[i].y = + -mBasePlane.d + mNoise->getValue(WorldPos.x + result.x, WorldPos.z + result.z) * mOptions.Strength; + + i++; + u += du; + _1_u = 1.0f - u; + } + v += dv; + _1_v = 1.0f - v; + } + + if (mOptions.ChoppyWaves) + { + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + mVerticesChoppyBuffer[i] = Vertices[i]; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (iv = 0; iv < mOptions.Complexity; iv++) + { + u = 0.0f; + _1_u = 1.0f; + for (iu = 0; iu < mOptions.Complexity; iu++) + { + result.x = _1_v * (_1_u * t_corners0.x + u * t_corners1.x) + v * (_1_u * t_corners2.x + u * t_corners3.x); + result.z = _1_v * (_1_u * t_corners0.z + u * t_corners1.z) + v * (_1_u * t_corners2.z + u * t_corners3.z); + result.w = _1_v * (_1_u * t_corners0.w + u * t_corners1.w) + v * (_1_u * t_corners2.w + u * t_corners3.w); + + divide = 1.0f / result.w; + result.x *= divide; + result.z *= divide; + + Vertices[i].x = result.x; + Vertices[i].z = result.z; + Vertices[i].y = + -mBasePlane.d + mNoise->getValue(WorldPos.x + result.x, WorldPos.z + result.z) * mOptions.Strength; + + i++; + u += du; + _1_u = 1.0f - u; + } + v += dv; + _1_v = 1.0f - v; + } + } + + // Smooth the heightdata + if (mOptions.Smooth) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (iv = 1; iv < (mOptions.Complexity - 1); iv++) + { + for (iu = 1; iu < (mOptions.Complexity - 1); iu++) + { + Vertices[iv * mOptions.Complexity + iu].y = 0.2f * (Vertices[iv * mOptions.Complexity + iu].y + + Vertices[iv * mOptions.Complexity + (iu + 1)].y + + Vertices[iv * mOptions.Complexity + (iu - 1)].y + + Vertices[(iv + 1) * mOptions.Complexity + iu].y + + Vertices[(iv - 1) * mOptions.Complexity + iu].y); + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (iv = 1; iv < (mOptions.Complexity - 1); iv++) + { + for (iu = 1; iu < (mOptions.Complexity - 1); iu++) + { + Vertices[iv * mOptions.Complexity + iu].y = 0.2f * (Vertices[iv * mOptions.Complexity + iu].y + + Vertices[iv * mOptions.Complexity + (iu + 1)].y + + Vertices[iv * mOptions.Complexity + (iu - 1)].y + + Vertices[(iv + 1) * mOptions.Complexity + iu].y + + Vertices[(iv - 1) * mOptions.Complexity + iu].y); + } + } + } + } + + _calculeNormals(); + + _performChoppyWaves(); + + return true; + } + + void ProjectedGrid::_calculeNormals() + { + if (getNormalMode() != MaterialManager::NM_VERTEX) { return; } + + int v, u; + Ogre::Vector3 vec1, vec2, normal; + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (v = 1; v < (mOptions.Complexity - 1); v++) + { + for (u = 1; u < (mOptions.Complexity - 1); u++) + { + vec1 = + Ogre::Vector3(Vertices[v * mOptions.Complexity + u + 1].x - Vertices[v * mOptions.Complexity + u - 1].x, + Vertices[v * mOptions.Complexity + u + 1].y - Vertices[v * mOptions.Complexity + u - 1].y, + Vertices[v * mOptions.Complexity + u + 1].z - Vertices[v * mOptions.Complexity + u - 1].z); + + vec2 = Ogre::Vector3( + Vertices[(v + 1) * mOptions.Complexity + u].x - Vertices[(v - 1) * mOptions.Complexity + u].x, + Vertices[(v + 1) * mOptions.Complexity + u].y - Vertices[(v - 1) * mOptions.Complexity + u].y, + Vertices[(v + 1) * mOptions.Complexity + u].z - Vertices[(v - 1) * mOptions.Complexity + u].z); + + normal = vec2.crossProduct(vec1); + + Vertices[v * mOptions.Complexity + u].nx = normal.x; + Vertices[v * mOptions.Complexity + u].ny = normal.y; + Vertices[v * mOptions.Complexity + u].nz = normal.z; + } + } + } + + void ProjectedGrid::_performChoppyWaves() + { + if (getNormalMode() != MaterialManager::NM_VERTEX || !mOptions.ChoppyWaves) { return; } + + int v, u, Underwater = 1; + + if (mHydrax->_isCurrentFrameUnderwater()) { Underwater = -1; } + + float Dis1, Dis2; //, + // Dis1_, Dis2_; + + Ogre::Vector3 CameraDir, Norm; + Ogre::Vector2 Dir, Perp, Norm2; + + CameraDir = mRenderingCamera->getDerivedDirection(); + Dir = Ogre::Vector2(CameraDir.x, CameraDir.z).normalisedCopy(); + Perp = Dir.perpendicular(); + + if (Dir.x < 0) Dir.x = -Dir.x; + if (Dir.y < 0) Dir.y = -Dir.y; + + if (Perp.x < 0) Perp.x = -Perp.x; + if (Perp.y < 0) Perp.y = -Perp.y; + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (v = 1; v < (mOptions.Complexity - 1); v++) + { + Dis1 = (Ogre::Vector2(mVerticesChoppyBuffer[v * mOptions.Complexity + 1].x, + mVerticesChoppyBuffer[v * mOptions.Complexity + 1].z) - + Ogre::Vector2(mVerticesChoppyBuffer[(v + 1) * mOptions.Complexity + 1].x, + mVerticesChoppyBuffer[(v + 1) * mOptions.Complexity + 1].z)) + .length(); + + /*Dis1_ = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + 1].x, + mVerticesChoppyBuffer[v*mOptions.Complexity + 1].z) - + Ogre::Vector2(mVerticesChoppyBuffer[(v-1)*mOptions.Complexity + 1].x, + mVerticesChoppyBuffer[(v-1)*mOptions.Complexity + 1].z)).length(); + + Dis1 = (Dis1+Dis1_)/2;*/ + + for (u = 1; u < (mOptions.Complexity - 1); u++) + { + Dis2 = (Ogre::Vector2(mVerticesChoppyBuffer[v * mOptions.Complexity + u].x, + mVerticesChoppyBuffer[v * mOptions.Complexity + u].z) - + Ogre::Vector2(mVerticesChoppyBuffer[v * mOptions.Complexity + u + 1].x, + mVerticesChoppyBuffer[v * mOptions.Complexity + u + 1].z)) + .length(); + /* + Dis2_ = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u].x, + mVerticesChoppyBuffer[v*mOptions.Complexity + u].z) - + Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u-1].x, + mVerticesChoppyBuffer[v*mOptions.Complexity + u-1].z)).length(); + + Dis2 = (Dis2+Dis2_)/2;*/ + + Norm = Ogre::Vector3(Vertices[v * mOptions.Complexity + u].nx, Vertices[v * mOptions.Complexity + u].ny, + Vertices[v * mOptions.Complexity + u].nz) + .normalisedCopy(); + + Norm2 = Ogre::Vector2(Norm.x, Norm.z) * ((Dir * Dis1) + (Perp * Dis2)) * mOptions.ChoppyStrength; + + Vertices[v * mOptions.Complexity + u].x = + mVerticesChoppyBuffer[v * mOptions.Complexity + u].x + Norm2.x * Underwater; + Vertices[v * mOptions.Complexity + u].z = + mVerticesChoppyBuffer[v * mOptions.Complexity + u].z + Norm2.y * Underwater; + } + } + } + + // Check the point of intersection with the plane (0,1,0,0) and return the position in homogenous coordinates + Ogre::Vector4 ProjectedGrid::_calculeWorldPosition(const Ogre::Vector2 &uv, const Ogre::Matrix4 &m, + const Ogre::Matrix4 &_viewMat) + { + Ogre::Vector4 origin(uv.x, uv.y, -1, 1); + Ogre::Vector4 direction(uv.x, uv.y, 1, 1); + + origin = m * origin; + direction = m * direction; + + Ogre::Vector3 _org(origin.x / origin.w, origin.y / origin.w, origin.z / origin.w); + Ogre::Vector3 _dir(direction.x / direction.w, direction.y / direction.w, direction.z / direction.w); + _dir -= _org; + _dir.normalise(); + + Ogre::Ray _ray(_org, _dir); + std::pair _result = _ray.intersects(mBasePlane); + float l = _result.second; + Ogre::Vector3 worldPos = _org + _dir * l; + Ogre::Vector4 _tempVec = _viewMat * Ogre::Vector4(worldPos); + float _temp = -_tempVec.z / _tempVec.w; + Ogre::Vector4 retPos(worldPos); + retPos /= _temp; + + return retPos; + } + + bool ProjectedGrid::_getMinMax(Ogre::Matrix4 *range) + { + _setDisplacementAmplitude(mOptions.Strength); + + float x_min, y_min, x_max, y_max; + Ogre::Vector3 frustum[8], proj_points[24]; + + int i, n_points = 0, src, dst; + + int cube[] = {0, 1, 0, 2, 2, 3, 1, 3, 0, 4, 2, 6, 3, 7, 1, 5, 4, 6, 4, 5, 5, 7, 6, 7}; + + Ogre::Vector3 _testLine; + Ogre::Real _dist; + Ogre::Ray _ray; + + std::pair _result; + + // Set temporal rendering camera parameters + mTmpRndrngCamera->setFrustumOffset(mRenderingCamera->getFrustumOffset()); + mTmpRndrngCamera->setAspectRatio(mRenderingCamera->getAspectRatio()); + mTmpRndrngCamera->setDirection(mRenderingCamera->getDerivedDirection()); + mTmpRndrngCamera->setFarClipDistance(mRenderingCamera->getFarClipDistance()); + mTmpRndrngCamera->setFOVy(mRenderingCamera->getFOVy()); + mTmpRndrngCamera->setNearClipDistance(mRenderingCamera->getNearClipDistance()); + mTmpRndrngCamera->setOrientation(mRenderingCamera->getDerivedOrientation()); + mTmpRndrngCamera->setPosition(0, mRenderingCamera->getDerivedPosition().y - mHydrax->getPosition().y, 0); + + Ogre::Matrix4 invviewproj = + (mTmpRndrngCamera->getProjectionMatrixWithRSDepth() * mTmpRndrngCamera->getViewMatrix()).inverse(); + frustum[0] = invviewproj * Ogre::Vector3(-1, -1, 0); + frustum[1] = invviewproj * Ogre::Vector3(+1, -1, 0); + frustum[2] = invviewproj * Ogre::Vector3(-1, +1, 0); + frustum[3] = invviewproj * Ogre::Vector3(+1, +1, 0); + frustum[4] = invviewproj * Ogre::Vector3(-1, -1, +1); + frustum[5] = invviewproj * Ogre::Vector3(+1, -1, +1); + frustum[6] = invviewproj * Ogre::Vector3(-1, +1, +1); + frustum[7] = invviewproj * Ogre::Vector3(+1, +1, +1); + + // Check intersections with upper_bound and lower_bound + for (i = 0; i < 12; i++) + { + src = cube[i * 2]; + dst = cube[i * 2 + 1]; + _testLine = frustum[dst] - frustum[src]; + _dist = _testLine.normalise(); + _ray = Ogre::Ray(frustum[src], _testLine); + _result = Ogre::Math::intersects(_ray, mUpperBoundPlane); + if ((_result.first) && (_result.second < _dist + 0.00001)) + { proj_points[n_points++] = frustum[src] + _result.second * _testLine; } + _result = Ogre::Math::intersects(_ray, mLowerBoundPlane); + if ((_result.first) && (_result.second < _dist + 0.00001)) + { proj_points[n_points++] = frustum[src] + _result.second * _testLine; } + } + + // Check if any of the frustums vertices lie between the upper_bound and lower_bound planes + for (i = 0; i < 8; i++) + { + if (mUpperBoundPlane.getDistance(frustum[i]) / mLowerBoundPlane.getDistance(frustum[i]) < 0) + { proj_points[n_points++] = frustum[i]; } + } + + // Set projecting camera parameters + mProjectingCamera->setFrustumOffset(mTmpRndrngCamera->getFrustumOffset()); + mProjectingCamera->setAspectRatio(mTmpRndrngCamera->getAspectRatio()); + mProjectingCamera->setDirection(mTmpRndrngCamera->getDerivedDirection()); + mProjectingCamera->setFarClipDistance(mTmpRndrngCamera->getFarClipDistance()); + mProjectingCamera->setFOVy(mTmpRndrngCamera->getFOVy()); + mProjectingCamera->setNearClipDistance(mTmpRndrngCamera->getNearClipDistance()); + mProjectingCamera->setOrientation(mTmpRndrngCamera->getDerivedOrientation()); + mProjectingCamera->setPosition(mTmpRndrngCamera->getDerivedPosition()); + + // Make sure the camera isn't too close to the plane + float height_in_plane = mBasePlane.getDistance(mProjectingCamera->getRealPosition()); + + bool keep_it_simple = false, underwater = false; + + if (height_in_plane < 0.0f) { underwater = true; } + + if (keep_it_simple) { mProjectingCamera->setDirection(mTmpRndrngCamera->getDerivedDirection()); } + else + { + Ogre::Vector3 aimpoint, aimpoint2; + + if (height_in_plane < (mOptions.Strength + mOptions.Elevation)) + { + if (underwater) + { + mProjectingCamera->setPosition(mProjectingCamera->getRealPosition() + + mLowerBoundPlane.normal * + (mOptions.Strength + mOptions.Elevation - 2 * height_in_plane)); + } + else + { + mProjectingCamera->setPosition(mProjectingCamera->getRealPosition() + + mLowerBoundPlane.normal * + (mOptions.Strength + mOptions.Elevation - height_in_plane)); + } + } + + // Aim the projector at the point where the camera view-vector intersects the plane + // if the camera is aimed away from the plane, mirror it's view-vector against the plane + if (((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedDirection()) < 0.0f) || + ((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedPosition()) < 0.0f)) + { + _ray = Ogre::Ray(mTmpRndrngCamera->getDerivedPosition(), mTmpRndrngCamera->getDerivedDirection()); + _result = Ogre::Math::intersects(_ray, mBasePlane); + + if (!_result.first) { _result.second = -_result.second; } + + aimpoint = mTmpRndrngCamera->getDerivedPosition() + _result.second * mTmpRndrngCamera->getDerivedDirection(); + } + else + { + Ogre::Vector3 flipped = mTmpRndrngCamera->getDerivedDirection() - + 2 * mNormal * (mTmpRndrngCamera->getDerivedDirection()).dotProduct(mNormal); + flipped.normalise(); + _ray = Ogre::Ray(mTmpRndrngCamera->getDerivedPosition(), flipped); + _result = Ogre::Math::intersects(_ray, mBasePlane); + + aimpoint = mTmpRndrngCamera->getDerivedPosition() + _result.second * flipped; + } + + // Force the point the camera is looking at in a plane, and have the projector look at it + // works well against horizon, even when camera is looking upwards + // doesn't work straight down/up + float af = fabs((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedDirection())); + aimpoint2 = mTmpRndrngCamera->getDerivedPosition() + 10.0 * mTmpRndrngCamera->getDerivedDirection(); + aimpoint2 = aimpoint2 - mNormal * (aimpoint2.dotProduct(mNormal)); + + // Fade between aimpoint & aimpoint2 depending on view angle + aimpoint = aimpoint * af + aimpoint2 * (1.0f - af); + + mProjectingCamera->setDirection(aimpoint - mProjectingCamera->getRealPosition()); + } + + for (i = 0; i < n_points; i++) + { + // Project the point onto the surface plane + proj_points[i] = proj_points[i] - mBasePlane.normal * mBasePlane.getDistance(proj_points[i]); + proj_points[i] = mProjectingCamera->getViewMatrix() * proj_points[i]; + proj_points[i] = mProjectingCamera->getProjectionMatrixWithRSDepth() * proj_points[i]; + } + + // Get max/min x & y-values to determine how big the "projection window" must be + if (n_points > 0) + { + x_min = proj_points[0].x; + x_max = proj_points[0].x; + y_min = proj_points[0].y; + y_max = proj_points[0].y; + + for (i = 1; i < n_points; i++) + { + if (proj_points[i].x > x_max) x_max = proj_points[i].x; + if (proj_points[i].x < x_min) x_min = proj_points[i].x; + if (proj_points[i].y > y_max) y_max = proj_points[i].y; + if (proj_points[i].y < y_min) y_min = proj_points[i].y; + } + + // Build the packing matrix that spreads the grid across the "projection window" + Ogre::Matrix4 pack(x_max - x_min, 0, 0, x_min, 0, y_max - y_min, 0, y_min, 0, 0, 1, 0, 0, 0, 0, 1); + + Ogre::Matrix4 invviewproj = + (mProjectingCamera->getProjectionMatrixWithRSDepth() * mProjectingCamera->getViewMatrix()).inverse(); + *range = invviewproj * pack; + + return true; + } + + return false; + } + + void ProjectedGrid::_setDisplacementAmplitude(const float &Amplitude) + { + mUpperBoundPlane = Ogre::Plane(mNormal, mPos + Amplitude * mNormal); + mLowerBoundPlane = Ogre::Plane(mNormal, mPos - Amplitude * mNormal); + } + + float ProjectedGrid::getHeigth(const Ogre::Vector2 &Position) + { + return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y) * mOptions.Strength; + } + } // namespace Module +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/ProjectedGrid.h b/source/main/gfx/hydrax/ProjectedGrid.h index 562baf7e38..2961da6240 100644 --- a/source/main/gfx/hydrax/ProjectedGrid.h +++ b/source/main/gfx/hydrax/ProjectedGrid.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -31,248 +31,222 @@ and Ren Cheng Ogre3D implementation: #ifndef _Hydrax_Modules_ProjectedGrid_H_ #define _Hydrax_Modules_ProjectedGrid_H_ - - #include "Hydrax.h" #include "Mesh.h" #include "Module.h" -namespace Hydrax{ namespace Module +namespace Hydrax { - /** Hydrax projected grid module - */ - class ProjectedGrid : public Module - { - public: - /** Struct wich contains Hydrax projected grid module options - */ - struct Options - { - /// Projected grid complexity (N*N) - int Complexity; - /// Strength - float Strength; - /// Elevation - float Elevation; - /// Smooth - bool Smooth; - /// Force recalculate mesh geometry each frame - bool ForceRecalculateGeometry; - /// Choppy waves - bool ChoppyWaves; - /// Choppy waves strength - float ChoppyStrength; - - /** Default constructor - */ - Options() - : Complexity(256) - , Strength(35.0f) - , Elevation(50.0f) - , Smooth(false) - , ForceRecalculateGeometry(false) - , ChoppyWaves(true) - , ChoppyStrength(3.75f) - { - } - - /** Constructor - @param _Complexity Projected grid complexity - */ - Options(const int &_Complexity) - : Complexity(_Complexity) - , Strength(35.0f) - , Elevation(50.0f) - , Smooth(false) - , ForceRecalculateGeometry(false) - , ChoppyWaves(true) - , ChoppyStrength(3.75f) - { - } - - /** Constructor - @param _Complexity Projected grid complexity - @param _Strength Perlin noise strength - @param _Elevation Elevation - @param _Smooth Smooth vertex? - */ - Options(const int &_Complexity, - const float &_Strength, - const float &_Elevation, - const bool &_Smooth) - : Complexity(_Complexity) - , Strength(_Strength) - , Elevation(_Elevation) - , Smooth(_Smooth) - , ForceRecalculateGeometry(false) - , ChoppyWaves(true) - , ChoppyStrength(3.75f) - { - } - - /** Constructor - @param _Complexity Projected grid complexity - @param _Strength Perlin noise strength - @param _Elevation Elevation - @param _Smooth Smooth vertex? - @param _ForceRecalculateGeometry Force to recalculate the projected grid geometry each frame - @param _ChoppyWaves Choppy waves enabled? Note: Only with Materialmanager::NM_VERTEX normal mode. - @param _ChoppyStrength Choppy waves strength - */ - Options(const int &_Complexity, - const float &_Strength, - const float &_Elevation, - const bool &_Smooth, - const bool &_ForceRecalculateGeometry, - const bool &_ChoppyWaves, - const float &_ChoppyStrength) - : Complexity(_Complexity) - , Strength(_Strength) - , Elevation(_Elevation) - , Smooth(_Smooth) - , ForceRecalculateGeometry(_ForceRecalculateGeometry) - , ChoppyWaves(_ChoppyWaves) - , ChoppyStrength(_ChoppyStrength) - { - } - }; - - /** Constructor - @param h Hydrax manager pointer - @param n Hydrax noise module - @param BasePlane Noise base plane - @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT - */ - ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode& NormalMode); - - /** Constructor - @param h Hydrax manager pointer - @param n Hydrax noise module - @param BasePlane Noise base plane - @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT - @param Options Perlin options - */ - ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode& NormalMode, const Options &Options); - - /** Destructor - */ - ~ProjectedGrid(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Set options - @param Options Options - */ - void setOptions(const Options &Options); - - /** Save config - @param Data String reference - */ - void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct module config - */ - bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get the current heigth at a especified world-space point - @param Position X/Z World position - @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 - */ - float getHeigth(const Ogre::Vector2 &Position); - - /** Get current options - @return Current options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - private: - /** Calcule current normals - */ - void _calculeNormals(); - - /** Perform choppy waves - */ - void _performChoppyWaves(); - - /** Render geometry - @param m Range - @param _viewMat View matrix - @param WorldPos Origin world position - @return true if it's sucesfful - */ - bool _renderGeometry(const Ogre::Matrix4& m,const Ogre::Matrix4& _viewMat, const Ogre::Vector3& WorldPos); - - /** Calcule world position - @param uv uv - @param m Range - @param _viewMat View matrix - @return The position in homogenous coordinates - */ - Ogre::Vector4 _calculeWorldPosition(const Ogre::Vector2 &uv, const Ogre::Matrix4& m,const Ogre::Matrix4& _viewMat); - - /** Get min/max - @param range Range - @return true if it's in min/max - */ - bool _getMinMax(Ogre::Matrix4 *range); - - /** Set displacement amplitude - @param Amplitude Amplitude to set - */ - void _setDisplacementAmplitude(const float &Amplitude); - - /// Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX) - void *mVertices; - - /// Use it to store vertex positions when choppy displacement is enabled - Mesh::POS_NORM_VERTEX* mVerticesChoppyBuffer; - - /// For corners - Ogre::Vector4 t_corners0,t_corners1,t_corners2,t_corners3; - - /// Range matrix - Ogre::Matrix4 mRange; - - /// Planes - Ogre::Plane mBasePlane, - mUpperBoundPlane, - mLowerBoundPlane; - - /// Cameras - Ogre::Camera *mProjectingCamera, // The camera that does the actual projection - *mRenderingCamera, // The camera whose frustum the projection is created for - *mTmpRndrngCamera; // Used to allow cameras with any inherited from a node or nodes - - /// Normal and position - Ogre::Vector3 mNormal, mPos; - - /// Last camera position, orientation - Ogre::Vector3 mLastPosition; - Ogre::Quaternion mLastOrientation; - bool mLastMinMax; - - /// Our projected grid options - Options mOptions; - - /// Our Hydrax pointer - Hydrax* mHydrax; - }; -}} + namespace Module + { + /** Hydrax projected grid module + */ + class ProjectedGrid : public Module + { + public: + /** Struct wich contains Hydrax projected grid module options + */ + struct Options + { + /// Projected grid complexity (N*N) + int Complexity; + /// Strength + float Strength; + /// Elevation + float Elevation; + /// Smooth + bool Smooth; + /// Force recalculate mesh geometry each frame + bool ForceRecalculateGeometry; + /// Choppy waves + bool ChoppyWaves; + /// Choppy waves strength + float ChoppyStrength; + + /** Default constructor + */ + Options() + : Complexity(256), Strength(35.0f), Elevation(50.0f), Smooth(false), ForceRecalculateGeometry(false), + ChoppyWaves(true), ChoppyStrength(3.75f) + { + } + + /** Constructor + @param _Complexity Projected grid complexity + */ + Options(const int &_Complexity) + : Complexity(_Complexity), Strength(35.0f), Elevation(50.0f), Smooth(false), ForceRecalculateGeometry(false), + ChoppyWaves(true), ChoppyStrength(3.75f) + { + } + + /** Constructor + @param _Complexity Projected grid complexity + @param _Strength Perlin noise strength + @param _Elevation Elevation + @param _Smooth Smooth vertex? + */ + Options(const int &_Complexity, const float &_Strength, const float &_Elevation, const bool &_Smooth) + : Complexity(_Complexity), Strength(_Strength), Elevation(_Elevation), Smooth(_Smooth), + ForceRecalculateGeometry(false), ChoppyWaves(true), ChoppyStrength(3.75f) + { + } + + /** Constructor + @param _Complexity Projected grid complexity + @param _Strength Perlin noise strength + @param _Elevation Elevation + @param _Smooth Smooth vertex? + @param _ForceRecalculateGeometry Force to recalculate the projected grid geometry each frame + @param _ChoppyWaves Choppy waves enabled? Note: Only with Materialmanager::NM_VERTEX normal mode. + @param _ChoppyStrength Choppy waves strength + */ + Options(const int &_Complexity, const float &_Strength, const float &_Elevation, const bool &_Smooth, + const bool &_ForceRecalculateGeometry, const bool &_ChoppyWaves, const float &_ChoppyStrength) + : Complexity(_Complexity), Strength(_Strength), Elevation(_Elevation), Smooth(_Smooth), + ForceRecalculateGeometry(_ForceRecalculateGeometry), ChoppyWaves(_ChoppyWaves), + ChoppyStrength(_ChoppyStrength) + { + } + }; + + /** Constructor + @param h Hydrax manager pointer + @param n Hydrax noise module + @param BasePlane Noise base plane + @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT + */ + ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, + const MaterialManager::NormalMode &NormalMode); + + /** Constructor + @param h Hydrax manager pointer + @param n Hydrax noise module + @param BasePlane Noise base plane + @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT + @param Options Perlin options + */ + ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode &NormalMode, + const Options &Options); + + /** Destructor + */ + ~ProjectedGrid(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Set options + @param Options Options + */ + void setOptions(const Options &Options); + + /** Save config + @param Data String reference + */ + void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct module config + */ + bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get the current heigth at a especified world-space point + @param Position X/Z World position + @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 + */ + float getHeigth(const Ogre::Vector2 &Position); + + /** Get current options + @return Current options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + private: + /** Calcule current normals + */ + void _calculeNormals(); + + /** Perform choppy waves + */ + void _performChoppyWaves(); + + /** Render geometry + @param m Range + @param _viewMat View matrix + @param WorldPos Origin world position + @return true if it's sucesfful + */ + bool _renderGeometry(const Ogre::Matrix4 &m, const Ogre::Matrix4 &_viewMat, const Ogre::Vector3 &WorldPos); + + /** Calcule world position + @param uv uv + @param m Range + @param _viewMat View matrix + @return The position in homogenous coordinates + */ + Ogre::Vector4 _calculeWorldPosition(const Ogre::Vector2 &uv, const Ogre::Matrix4 &m, const Ogre::Matrix4 &_viewMat); + + /** Get min/max + @param range Range + @return true if it's in min/max + */ + bool _getMinMax(Ogre::Matrix4 *range); + + /** Set displacement amplitude + @param Amplitude Amplitude to set + */ + void _setDisplacementAmplitude(const float &Amplitude); + + /// Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX) + void *mVertices; + + /// Use it to store vertex positions when choppy displacement is enabled + Mesh::POS_NORM_VERTEX *mVerticesChoppyBuffer; + + /// For corners + Ogre::Vector4 t_corners0, t_corners1, t_corners2, t_corners3; + + /// Range matrix + Ogre::Matrix4 mRange; + + /// Planes + Ogre::Plane mBasePlane, mUpperBoundPlane, mLowerBoundPlane; + + /// Cameras + Ogre::Camera *mProjectingCamera, // The camera that does the actual projection + *mRenderingCamera, // The camera whose frustum the projection is created for + *mTmpRndrngCamera; // Used to allow cameras with any inherited from a node or nodes + + /// Normal and position + Ogre::Vector3 mNormal, mPos; + + /// Last camera position, orientation + Ogre::Vector3 mLastPosition; + Ogre::Quaternion mLastOrientation; + bool mLastMinMax; + + /// Our projected grid options + Options mOptions; + + /// Our Hydrax pointer + Hydrax *mHydrax; + }; + } // namespace Module +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/RadialGrid.cpp b/source/main/gfx/hydrax/RadialGrid.cpp index 88757dcb6d..f0da208f47 100644 --- a/source/main/gfx/hydrax/RadialGrid.cpp +++ b/source/main/gfx/hydrax/RadialGrid.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -24,646 +24,591 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include -namespace Hydrax{namespace Module +namespace Hydrax { - Mesh::VertexType _RG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode& NormalMode) - { - if (NormalMode == MaterialManager::NM_VERTEX) - { - return Mesh::VT_POS_NORM; - } - - // NM_RTT - return Mesh::VT_POS; - } - - Ogre::String _RG_getNormalModeString(const MaterialManager::NormalMode& NormalMode) - { - if (NormalMode == MaterialManager::NM_VERTEX) - { - return "Vertex"; - } - - return "Rtt"; - } - - RadialGrid::RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode) - : Module("RadialGrid" + _RG_getNormalModeString(NormalMode), - n, Mesh::Options(0, Size(200), _RG_getVertexTypeFromNormalMode(NormalMode)), NormalMode) - , mHydrax(h) - , mVertices(0) - , mVerticesChoppyBuffer(0) - { - } - - RadialGrid::RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode, const Options &Options) - : Module("RadialGrid" + _RG_getNormalModeString(NormalMode), - n, Mesh::Options(0, Size(Options.Radius*2), _RG_getVertexTypeFromNormalMode(NormalMode)), NormalMode) - , mHydrax(h) - , mVertices(0) - , mVerticesChoppyBuffer(0) - { - setOptions(Options); - } - - RadialGrid::~RadialGrid() - { - remove(); - - HydraxLOG(getName() + " destroyed."); - } - - void RadialGrid::setOptions(const Options &Options) - { - mMeshOptions.MeshSize = Size(Options.Radius*2); - mMeshOptions.MeshStrength = Options.Strength; - - mHydrax->getMesh()->setOptions(mMeshOptions); - mHydrax->_setStrength(mOptions.Strength); - - if (isCreated()) - { - if ((Options.Steps != mOptions.Steps) || (Options.Circles != mOptions.Circles)) - { - remove(); - mOptions = Options; - create(); - - if (mNormalMode == MaterialManager::NM_RTT) - { - if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) - { - HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); - } - } - - Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); - mHydrax->getMesh()->remove(); - mHydrax->getMesh()->setOptions(getMeshOptions()); - mHydrax->getMesh()->setMaterialName(MaterialNameTmp); - mHydrax->getMesh()->create(); - - return; - } - - mOptions = Options; - - int x, y; - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - Vertices[0].x = mOptions.Radius; - Vertices[0].z = mOptions.Radius; - - float r_scale = mOptions.Radius/ - (mOptions.StepSizeLin * mOptions.Circles + - mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + - mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); - - for(y=0;y(mVertices); - - Vertices[0].x = mOptions.Radius; - Vertices[0].z = mOptions.Radius; - - float r_scale = mOptions.Radius/ - (mOptions.StepSizeLin * mOptions.Circles + - mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + - mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); - - for(y=0;y(mVertices); - - Vertices[0].x = mOptions.Radius; - Vertices[0].y = 0; - Vertices[0].z = mOptions.Radius; - - Vertices[0].nx = 0; - Vertices[0].ny = -1; - Vertices[0].nz = 0; - - float r_scale = mOptions.Radius/ - (mOptions.StepSizeLin * mOptions.Circles + - mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + - mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); - - for(y=0;y(mVertices); - - Vertices[0].x = mOptions.Radius; - Vertices[0].y = 0; - Vertices[0].z = mOptions.Radius; - - float r_scale = mOptions.Radius/ - (mOptions.StepSizeLin * mOptions.Circles + - mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + - mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); - - for(y=0;ygetSubMesh()->vertexData = new Ogre::VertexData(); - mMesh->getSubMesh()->vertexData->vertexStart = 0; - mMesh->getSubMesh()->vertexData->vertexCount = numVertices; - - Ogre::VertexDeclaration* vdecl = mMesh->getSubMesh()->vertexData->vertexDeclaration; - Ogre::VertexBufferBinding* vbind = mMesh->getSubMesh()->vertexData->vertexBufferBinding; - - size_t offset = 0; - - switch (mMeshOptions.MeshVertexType) - { - case Mesh::VT_POS_NORM: - { - vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - - mMesh->getHardwareVertexBuffer() = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(Mesh::POS_NORM_VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - } - break; - - case Mesh::VT_POS: - { - vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - - mMesh->getHardwareVertexBuffer() = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(Mesh::POS_VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - } - break; - } - - vbind->setBinding(0, mMesh->getHardwareVertexBuffer()); - - unsigned int *indexbuffer = new unsigned int[numEle]; - - for (int k = 0; k < mOptions.Steps; k++) - { - indexbuffer[k*3+2] = 0; - indexbuffer[k*3+1] = k+1; - - if (k != mOptions.Steps-1) - { - indexbuffer[k*3] = k+2; - } - else - { - indexbuffer[k*3] = 1; - } - } - - for(int y=0; ygetHardwareIndexBuffer() = - Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( - Ogre::HardwareIndexBuffer::IT_32BIT, - numEle, - Ogre::HardwareBuffer::HBU_STATIC, true); - - mMesh->getHardwareIndexBuffer()-> - writeData(0, - mMesh->getHardwareIndexBuffer()->getSizeInBytes(), - indexbuffer, - true); - - delete []indexbuffer; - - // Set index buffer for this submesh - mMesh->getSubMesh()->indexData->indexBuffer = mMesh->getHardwareIndexBuffer(); - mMesh->getSubMesh()->indexData->indexStart = 0; - mMesh->getSubMesh()->indexData->indexCount = numEle; - - return true; - } - - void RadialGrid::remove() - { - if (!isCreated()) - { - return; - } - - Module::remove(); - - if (mVertices) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - delete [] static_cast(mVertices); - mVertices = 0; - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - delete [] static_cast(mVertices); - mVertices = 0; - } - } - - if (mVerticesChoppyBuffer) - { - delete [] mVerticesChoppyBuffer; - } - } - - void RadialGrid::saveCfg(Ogre::String &Data) - { - Module::saveCfg(Data); - - Data += CfgFileManager::_getCfgString("RG_Steps", mOptions.Steps); - Data += CfgFileManager::_getCfgString("RG_Circles", mOptions.Circles); - Data += CfgFileManager::_getCfgString("RG_Radius", mOptions.Radius); - Data += CfgFileManager::_getCfgString("RG_Smooth", mOptions.Smooth); - Data += CfgFileManager::_getCfgString("RG_ChoppyWaves", mOptions.ChoppyWaves); - Data += CfgFileManager::_getCfgString("RG_ChoppyStrength", mOptions.ChoppyStrength); - Data += CfgFileManager::_getCfgString("RG_StepSizeCube", mOptions.StepSizeCube); - Data += CfgFileManager::_getCfgString("RG_StepSizeFive", mOptions.StepSizeFive); - Data += CfgFileManager::_getCfgString("RG_StepSizeLin", mOptions.StepSizeLin); - Data += CfgFileManager::_getCfgString("RG_Strength", mOptions.Strength);Data += "\n"; - } - - bool RadialGrid::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (!Module::loadCfg(CfgFile)) - { - return false; - } - - setOptions( - Options(CfgFileManager::_getIntValue(CfgFile, "RG_Steps"), - CfgFileManager::_getIntValue(CfgFile, "RG_Circles"), - CfgFileManager::_getFloatValue(CfgFile, "RG_Radius"), - CfgFileManager::_getBoolValue(CfgFile, "RG_Smooth"), - CfgFileManager::_getBoolValue(CfgFile, "RG_ChoppyWaves"), - CfgFileManager::_getFloatValue(CfgFile, "RG_ChoppyStrength"), - CfgFileManager::_getFloatValue(CfgFile, "RG_StepSizeCube"), - CfgFileManager::_getFloatValue(CfgFile, "RG_StepSizeFive"), - CfgFileManager::_getFloatValue(CfgFile, "RG_StepSizeLin"), - CfgFileManager::_getFloatValue(CfgFile, "RG_Strength"))); - - return true; - } - - void RadialGrid::update(const Ogre::Real &timeSinceLastFrame) - { - if (!isCreated()) - { - return; - } - - Module::update(timeSinceLastFrame); - - // Update heigths - int i, x, y; - - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - if (mOptions.ChoppyWaves) - { - for(i = 0; i < 1+mOptions.Circles*mOptions.Steps; i++) - { - Vertices[i] = mVerticesChoppyBuffer[i]; - } - } - - Ogre::Vector3 HydraxPos = mHydrax->getPosition(); - - for(i = 0; i <1+mOptions.Circles*mOptions.Steps; i++) - { - Vertices[i].y = mNoise->getValue(HydraxPos.x + Vertices[i].x, HydraxPos.z + Vertices[i].z)*mOptions.Strength; - } - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - Ogre::Vector3 HydraxPos = mHydrax->getPosition(); - - for(i = 0; i <1+mOptions.Circles*mOptions.Steps; i++) - { - Vertices[i].y = mNoise->getValue(HydraxPos.x + Vertices[i].x, HydraxPos.z + Vertices[i].z)*mOptions.Strength; - } - } - - // Smooth the heightdata - if (mOptions.Smooth) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(y=1;y(mVertices); - - for(y=1;ygetMesh()->updateGeometry(1+mOptions.Steps * mOptions.Circles, mVertices); - } - - void RadialGrid::_calculeNormals() - { - if (getNormalMode() != MaterialManager::NM_VERTEX) - { - return; - } - - int x, y; - Ogre::Vector3 vec1, vec2, normal; - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - int Steps_4 = static_cast(mOptions.Steps/4); - - // Calculate the normal of the center grid point - vec2 = Ogre::Vector3( - Vertices[1].x-Vertices[1+Steps_4*2].x, - Vertices[1].y-Vertices[1+Steps_4*2].y, - Vertices[1].z-Vertices[1+Steps_4*2].z); - - vec1 = Ogre::Vector3( - Vertices[1+Steps_4].x - Vertices[1+Steps_4*3].x, - Vertices[1+Steps_4].y - Vertices[1+Steps_4*3].y, - Vertices[1+Steps_4].z - Vertices[1+Steps_4*3].z); - - normal = vec2.crossProduct(vec1); - - Vertices[0].nx = normal.x; - Vertices[0].ny = normal.y; - Vertices[0].nz = normal.z; - - // Calculate first circle normals - for(x=0;x_isCurrentFrameUnderwater()) - { - Underwater = -1; - } - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - Ogre::Vector2 Current, NearStep, CircleStep, - Proportion, - Dir, Perp, - Norm2; - Ogre::Vector3 Norm; - - for(y=0;ygetPosition().y + mNoise->getValue(Position.x, Position.y)*mOptions.Strength; - } -}} + namespace Module + { + Mesh::VertexType _RG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode &NormalMode) + { + if (NormalMode == MaterialManager::NM_VERTEX) { return Mesh::VT_POS_NORM; } + + // NM_RTT + return Mesh::VT_POS; + } + + Ogre::String _RG_getNormalModeString(const MaterialManager::NormalMode &NormalMode) + { + if (NormalMode == MaterialManager::NM_VERTEX) { return "Vertex"; } + + return "Rtt"; + } + + RadialGrid::RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode) + : Module("RadialGrid" + _RG_getNormalModeString(NormalMode), n, + Mesh::Options(0, Size(200), _RG_getVertexTypeFromNormalMode(NormalMode)), NormalMode), + mHydrax(h), mVertices(0), mVerticesChoppyBuffer(0) + { + } + + RadialGrid::RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode, const Options &Options) + : Module("RadialGrid" + _RG_getNormalModeString(NormalMode), n, + Mesh::Options(0, Size(Options.Radius * 2), _RG_getVertexTypeFromNormalMode(NormalMode)), NormalMode), + mHydrax(h), mVertices(0), mVerticesChoppyBuffer(0) + { + setOptions(Options); + } + + RadialGrid::~RadialGrid() + { + remove(); + + HydraxLOG(getName() + " destroyed."); + } + + void RadialGrid::setOptions(const Options &Options) + { + mMeshOptions.MeshSize = Size(Options.Radius * 2); + mMeshOptions.MeshStrength = Options.Strength; + + mHydrax->getMesh()->setOptions(mMeshOptions); + mHydrax->_setStrength(mOptions.Strength); + + if (isCreated()) + { + if ((Options.Steps != mOptions.Steps) || (Options.Circles != mOptions.Circles)) + { + remove(); + mOptions = Options; + create(); + + if (mNormalMode == MaterialManager::NM_RTT) + { + if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) + { HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); } + } + + Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); + mHydrax->getMesh()->remove(); + mHydrax->getMesh()->setOptions(getMeshOptions()); + mHydrax->getMesh()->setMaterialName(MaterialNameTmp); + mHydrax->getMesh()->create(); + + return; + } + + mOptions = Options; + + int x, y; + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + Vertices[0].x = mOptions.Radius; + Vertices[0].z = mOptions.Radius; + + float r_scale = mOptions.Radius / (mOptions.StepSizeLin * mOptions.Circles + + mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); + + for (y = 0; y < mOptions.Circles; y++) + { + float r = r_scale * (mOptions.StepSizeLin * (y + 1) + mOptions.StepSizeCube * Ogre::Math::Pow(y + 1, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(y + 1, 5)); + + for (x = 0; x < mOptions.Steps; x++) + { + Vertices[1 + y * mOptions.Steps + x].x = + mOptions.Radius + r * Ogre::Math::Cos(Ogre::Math::TWO_PI * x / mOptions.Steps); + Vertices[1 + y * mOptions.Steps + x].z = + mOptions.Radius + r * Ogre::Math::Sin(Ogre::Math::TWO_PI * x / mOptions.Steps); + } + } + + if (mOptions.ChoppyWaves && mVerticesChoppyBuffer) + { + for (int i = 0; i < 1 + mOptions.Circles * mOptions.Steps; i++) + { + mVerticesChoppyBuffer[i] = Vertices[i]; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + Vertices[0].x = mOptions.Radius; + Vertices[0].z = mOptions.Radius; + + float r_scale = mOptions.Radius / (mOptions.StepSizeLin * mOptions.Circles + + mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); + + for (y = 0; y < mOptions.Circles; y++) + { + float r = r_scale * (mOptions.StepSizeLin * (y + 1) + mOptions.StepSizeCube * Ogre::Math::Pow(y + 1, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(y + 1, 5)); + + for (x = 0; x < mOptions.Steps; x++) + { + Vertices[1 + y * mOptions.Steps + x].x = + mOptions.Radius + r * Ogre::Math::Cos(Ogre::Math::TWO_PI * x / mOptions.Steps); + Vertices[1 + y * mOptions.Steps + x].z = + mOptions.Radius + r * Ogre::Math::Sin(Ogre::Math::TWO_PI * x / mOptions.Steps); + } + } + } + + return; + } + + mOptions = Options; + } + + void RadialGrid::create() + { + HydraxLOG("Creating " + getName() + " module."); + + Module::create(); + + int x, y; + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + mVertices = new Mesh::POS_NORM_VERTEX[1 + mOptions.Steps * mOptions.Circles]; + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + Vertices[0].x = mOptions.Radius; + Vertices[0].y = 0; + Vertices[0].z = mOptions.Radius; + + Vertices[0].nx = 0; + Vertices[0].ny = -1; + Vertices[0].nz = 0; + + float r_scale = mOptions.Radius / (mOptions.StepSizeLin * mOptions.Circles + + mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); + + for (y = 0; y < mOptions.Circles; y++) + { + float r = r_scale * (mOptions.StepSizeLin * (y + 1) + mOptions.StepSizeCube * Ogre::Math::Pow(y + 1, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(y + 1, 5)); + + for (x = 0; x < mOptions.Steps; x++) + { + Vertices[1 + y * mOptions.Steps + x].x = + mOptions.Radius + r * Ogre::Math::Cos(Ogre::Math::TWO_PI * x / mOptions.Steps); + Vertices[1 + y * mOptions.Steps + x].y = 0; + Vertices[1 + y * mOptions.Steps + x].z = + mOptions.Radius + r * Ogre::Math::Sin(Ogre::Math::TWO_PI * x / mOptions.Steps); + + Vertices[1 + y * mOptions.Steps + x].nx = 0; + Vertices[1 + y * mOptions.Steps + x].ny = -1; + Vertices[1 + y * mOptions.Steps + x].nz = 0; + } + } + + if (mOptions.ChoppyWaves) + { + mVerticesChoppyBuffer = new Mesh::POS_NORM_VERTEX[1 + mOptions.Circles * mOptions.Steps]; + + for (int i = 0; i < 1 + mOptions.Circles * mOptions.Steps; i++) + { + mVerticesChoppyBuffer[i] = Vertices[i]; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + mVertices = new Mesh::POS_VERTEX[1 + mOptions.Steps * mOptions.Circles]; + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + Vertices[0].x = mOptions.Radius; + Vertices[0].y = 0; + Vertices[0].z = mOptions.Radius; + + float r_scale = mOptions.Radius / (mOptions.StepSizeLin * mOptions.Circles + + mOptions.StepSizeCube * Ogre::Math::Pow(mOptions.Circles, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(mOptions.Circles, 5)); + + for (y = 0; y < mOptions.Circles; y++) + { + float r = r_scale * (mOptions.StepSizeLin * (y + 1) + mOptions.StepSizeCube * Ogre::Math::Pow(y + 1, 3) + + mOptions.StepSizeFive * Ogre::Math::Pow(y + 1, 5)); + + for (x = 0; x < mOptions.Steps; x++) + { + Vertices[1 + y * mOptions.Steps + x].x = + mOptions.Radius + r * Ogre::Math::Cos(Ogre::Math::TWO_PI * x / mOptions.Steps); + Vertices[1 + y * mOptions.Steps + x].y = 0; + Vertices[1 + y * mOptions.Steps + x].z = + mOptions.Radius + r * Ogre::Math::Sin(Ogre::Math::TWO_PI * x / mOptions.Steps); + } + } + } + + HydraxLOG(getName() + " created."); + } + + const bool RadialGrid::_createGeometry(Mesh *mMesh) const + { + int numVertices = mOptions.Steps * mOptions.Circles + 1; + int numEle = 6 * mOptions.Steps * (mOptions.Circles - 1) + 3 * mOptions.Steps; + + // Vertex buffers + mMesh->getSubMesh()->vertexData = new Ogre::VertexData(); + mMesh->getSubMesh()->vertexData->vertexStart = 0; + mMesh->getSubMesh()->vertexData->vertexCount = numVertices; + + Ogre::VertexDeclaration * vdecl = mMesh->getSubMesh()->vertexData->vertexDeclaration; + Ogre::VertexBufferBinding *vbind = mMesh->getSubMesh()->vertexData->vertexBufferBinding; + + size_t offset = 0; + + switch (mMeshOptions.MeshVertexType) + { + case Mesh::VT_POS_NORM: + { + vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); + + mMesh->getHardwareVertexBuffer() = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(Mesh::POS_NORM_VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + } + break; + + case Mesh::VT_POS: + { + vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + + mMesh->getHardwareVertexBuffer() = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(Mesh::POS_VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + } + break; + } + + vbind->setBinding(0, mMesh->getHardwareVertexBuffer()); + + unsigned int *indexbuffer = new unsigned int[numEle]; + + for (int k = 0; k < mOptions.Steps; k++) + { + indexbuffer[k * 3 + 2] = 0; + indexbuffer[k * 3 + 1] = k + 1; + + if (k != mOptions.Steps - 1) { indexbuffer[k * 3] = k + 2; } + else + { + indexbuffer[k * 3] = 1; + } + } + + for (int y = 0; y < mOptions.Circles - 1; y++) + { + for (int x = 0; x < mOptions.Steps; x++) + { + unsigned int *twoface = indexbuffer + (y * mOptions.Steps + x) * 6 + 3 * mOptions.Steps; + + int p0 = 1 + y * mOptions.Steps + x; + int p1 = 1 + y * mOptions.Steps + x + 1; + int p2 = 1 + (y + 1) * mOptions.Steps + x; + int p3 = 1 + (y + 1) * mOptions.Steps + x + 1; + + if (x == mOptions.Steps - 1) + { + p1 -= x + 1; + p3 -= x + 1; + } + + // First triangle + twoface[0] = p0; + twoface[1] = p1; + twoface[2] = p2; + + // Second triangle + twoface[3] = p1; + twoface[4] = p3; + twoface[5] = p2; + } + } + + // Prepare buffer for indices + mMesh->getHardwareIndexBuffer() = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( + Ogre::HardwareIndexBuffer::IT_32BIT, numEle, Ogre::HardwareBuffer::HBU_STATIC, true); + + mMesh->getHardwareIndexBuffer()->writeData(0, mMesh->getHardwareIndexBuffer()->getSizeInBytes(), indexbuffer, true); + + delete[] indexbuffer; + + // Set index buffer for this submesh + mMesh->getSubMesh()->indexData->indexBuffer = mMesh->getHardwareIndexBuffer(); + mMesh->getSubMesh()->indexData->indexStart = 0; + mMesh->getSubMesh()->indexData->indexCount = numEle; + + return true; + } + + void RadialGrid::remove() + { + if (!isCreated()) { return; } + + Module::remove(); + + if (mVertices) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + delete[] static_cast(mVertices); + mVertices = 0; + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + delete[] static_cast(mVertices); + mVertices = 0; + } + } + + if (mVerticesChoppyBuffer) { delete[] mVerticesChoppyBuffer; } + } + + void RadialGrid::saveCfg(Ogre::String &Data) + { + Module::saveCfg(Data); + + Data += CfgFileManager::_getCfgString("RG_Steps", mOptions.Steps); + Data += CfgFileManager::_getCfgString("RG_Circles", mOptions.Circles); + Data += CfgFileManager::_getCfgString("RG_Radius", mOptions.Radius); + Data += CfgFileManager::_getCfgString("RG_Smooth", mOptions.Smooth); + Data += CfgFileManager::_getCfgString("RG_ChoppyWaves", mOptions.ChoppyWaves); + Data += CfgFileManager::_getCfgString("RG_ChoppyStrength", mOptions.ChoppyStrength); + Data += CfgFileManager::_getCfgString("RG_StepSizeCube", mOptions.StepSizeCube); + Data += CfgFileManager::_getCfgString("RG_StepSizeFive", mOptions.StepSizeFive); + Data += CfgFileManager::_getCfgString("RG_StepSizeLin", mOptions.StepSizeLin); + Data += CfgFileManager::_getCfgString("RG_Strength", mOptions.Strength); + Data += "\n"; + } + + bool RadialGrid::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (!Module::loadCfg(CfgFile)) { return false; } + + setOptions( + Options(CfgFileManager::_getIntValue(CfgFile, "RG_Steps"), CfgFileManager::_getIntValue(CfgFile, "RG_Circles"), + CfgFileManager::_getFloatValue(CfgFile, "RG_Radius"), CfgFileManager::_getBoolValue(CfgFile, "RG_Smooth"), + CfgFileManager::_getBoolValue(CfgFile, "RG_ChoppyWaves"), + CfgFileManager::_getFloatValue(CfgFile, "RG_ChoppyStrength"), + CfgFileManager::_getFloatValue(CfgFile, "RG_StepSizeCube"), + CfgFileManager::_getFloatValue(CfgFile, "RG_StepSizeFive"), + CfgFileManager::_getFloatValue(CfgFile, "RG_StepSizeLin"), + CfgFileManager::_getFloatValue(CfgFile, "RG_Strength"))); + + return true; + } + + void RadialGrid::update(const Ogre::Real &timeSinceLastFrame) + { + if (!isCreated()) { return; } + + Module::update(timeSinceLastFrame); + + // Update heigths + int i, x, y; + + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + if (mOptions.ChoppyWaves) + { + for (i = 0; i < 1 + mOptions.Circles * mOptions.Steps; i++) + { + Vertices[i] = mVerticesChoppyBuffer[i]; + } + } + + Ogre::Vector3 HydraxPos = mHydrax->getPosition(); + + for (i = 0; i < 1 + mOptions.Circles * mOptions.Steps; i++) + { + Vertices[i].y = + mNoise->getValue(HydraxPos.x + Vertices[i].x, HydraxPos.z + Vertices[i].z) * mOptions.Strength; + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + Ogre::Vector3 HydraxPos = mHydrax->getPosition(); + + for (i = 0; i < 1 + mOptions.Circles * mOptions.Steps; i++) + { + Vertices[i].y = + mNoise->getValue(HydraxPos.x + Vertices[i].x, HydraxPos.z + Vertices[i].z) * mOptions.Strength; + } + } + + // Smooth the heightdata + if (mOptions.Smooth) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (y = 1; y < mOptions.Circles - 1; y++) + { + for (x = 1; x < mOptions.Steps - 1; x++) + { + Vertices[y * mOptions.Steps + x].y = + 0.2f * (Vertices[y * mOptions.Steps + x].y + Vertices[y * mOptions.Steps + x + 1].y + + Vertices[y * mOptions.Steps + x - 1].y + Vertices[(y + 1) * mOptions.Steps + x].y + + Vertices[(y - 1) * mOptions.Steps + x].y); + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (y = 1; y < mOptions.Circles - 1; y++) + { + for (x = 1; x < mOptions.Steps - 1; x++) + { + Vertices[y * mOptions.Steps + x].y = + 0.2f * (Vertices[y * mOptions.Steps + x].y + Vertices[y * mOptions.Steps + x + 1].y + + Vertices[y * mOptions.Steps + x - 1].y + Vertices[(y + 1) * mOptions.Steps + x].y + + Vertices[(y - 1) * mOptions.Steps + x].y); + } + } + } + } + + // Update normals + _calculeNormals(); + + // Perform choppy waves + _performChoppyWaves(); + + // Upload geometry changes + mHydrax->getMesh()->updateGeometry(1 + mOptions.Steps * mOptions.Circles, mVertices); + } + + void RadialGrid::_calculeNormals() + { + if (getNormalMode() != MaterialManager::NM_VERTEX) { return; } + + int x, y; + Ogre::Vector3 vec1, vec2, normal; + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + int Steps_4 = static_cast(mOptions.Steps / 4); + + // Calculate the normal of the center grid point + vec2 = Ogre::Vector3(Vertices[1].x - Vertices[1 + Steps_4 * 2].x, Vertices[1].y - Vertices[1 + Steps_4 * 2].y, + Vertices[1].z - Vertices[1 + Steps_4 * 2].z); + + vec1 = Ogre::Vector3(Vertices[1 + Steps_4].x - Vertices[1 + Steps_4 * 3].x, + Vertices[1 + Steps_4].y - Vertices[1 + Steps_4 * 3].y, + Vertices[1 + Steps_4].z - Vertices[1 + Steps_4 * 3].z); + + normal = vec2.crossProduct(vec1); + + Vertices[0].nx = normal.x; + Vertices[0].ny = normal.y; + Vertices[0].nz = normal.z; + + // Calculate first circle normals + for (x = 0; x < mOptions.Steps; x++) + { + vec2 = Ogre::Vector3(Vertices[x + 2].x - Vertices[x].x, Vertices[x + 2].y - Vertices[x].y, + Vertices[x + 2].z - Vertices[x].z); + + vec1 = + Ogre::Vector3(Vertices[0].x - Vertices[mOptions.Steps + x].x, Vertices[0].y - Vertices[mOptions.Steps + x].y, + Vertices[0].z - Vertices[mOptions.Steps + x].z); + + normal = vec2.crossProduct(vec1); + + Vertices[1 + x].nx = normal.x; + Vertices[1 + x].ny = normal.y; + Vertices[1 + x].nz = normal.z; + } + + // Calculate all the other vertex normals + for (y = 1; y < mOptions.Circles - 1; y++) + { + for (x = 0; x < mOptions.Steps; x++) + { + vec2 = Ogre::Vector3(Vertices[y * mOptions.Steps + x + 2].x - Vertices[y * mOptions.Steps + x].x, + Vertices[y * mOptions.Steps + x + 2].y - Vertices[y * mOptions.Steps + x].y, + Vertices[y * mOptions.Steps + x + 2].z - Vertices[y * mOptions.Steps + x].z); + + vec1 = Ogre::Vector3(Vertices[(y - 1) * mOptions.Steps + x + 1].x - Vertices[(y + 1) * mOptions.Steps + x].x, + Vertices[(y - 1) * mOptions.Steps + x + 1].y - Vertices[(y + 1) * mOptions.Steps + x].y, + Vertices[(y - 1) * mOptions.Steps + x + 1].z - Vertices[(y + 1) * mOptions.Steps + x].z); + + normal = vec2.crossProduct(vec1); + + Vertices[1 + y * mOptions.Steps + x].nx = normal.x; + Vertices[1 + y * mOptions.Steps + x].ny = normal.y; + Vertices[1 + y * mOptions.Steps + x].nz = normal.z; + } + } + } + + void RadialGrid::_performChoppyWaves() + { + if (getNormalMode() != MaterialManager::NM_VERTEX || !mOptions.ChoppyWaves) { return; } + + int x, y, Underwater = 1; + + if (mHydrax->_isCurrentFrameUnderwater()) { Underwater = -1; } + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + Ogre::Vector2 Current, NearStep, CircleStep, Proportion, Dir, Perp, Norm2; + Ogre::Vector3 Norm; + + for (y = 0; y < mOptions.Circles - 1; y++) + { + Current = Ogre::Vector2(Vertices[y * mOptions.Steps + 1].x, Vertices[y * mOptions.Steps + 1].z); + NearStep = Ogre::Vector2(Vertices[y * mOptions.Steps + 2].x, Vertices[y * mOptions.Steps + 2].z); + CircleStep = Ogre::Vector2(Vertices[(y + 1) * mOptions.Steps + 1].x, Vertices[(y + 1) * mOptions.Steps + 1].z); + + Proportion = Ogre::Vector2( + // Distance per step vertex + (Current - NearStep).length(), + // Distance per circle vertex + (Current - CircleStep).length()); + + for (x = 0; x < mOptions.Steps; x++) + { + Dir = Ogre::Vector2(Vertices[1 + y * mOptions.Steps + x].nx, Vertices[1 + y * mOptions.Steps + x].nz) + .normalisedCopy(); + Perp = Dir.perpendicular(); + + if (Dir.x < 0) Dir.x = -Dir.x; + if (Dir.y < 0) Dir.y = -Dir.y; + + if (Perp.x < 0) Perp.x = -Perp.x; + if (Perp.y < 0) Perp.y = -Perp.y; + + Norm = Ogre::Vector3(Vertices[1 + y * mOptions.Steps + x].nx, Vertices[1 + y * mOptions.Steps + x].ny, + Vertices[1 + y * mOptions.Steps + x].nz) + .normalisedCopy(); + + Norm2 = + Ogre::Vector2(Norm.x, Norm.z) * ((Dir * Proportion.x) + (Perp * Proportion.y)) * mOptions.ChoppyStrength; + + Vertices[1 + y * mOptions.Steps + x].x += Norm2.x * Underwater; + Vertices[1 + y * mOptions.Steps + x].z += Norm2.y * Underwater; + } + } + } + + float RadialGrid::getHeigth(const Ogre::Vector2 &Position) + { + return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y) * mOptions.Strength; + } + } // namespace Module +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/RadialGrid.h b/source/main/gfx/hydrax/RadialGrid.h index 14db4e30ac..bcc465ec2e 100644 --- a/source/main/gfx/hydrax/RadialGrid.h +++ b/source/main/gfx/hydrax/RadialGrid.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,206 +25,175 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Modules_RadialGrid_H_ #define _Hydrax_Modules_RadialGrid_H_ - - #include "Hydrax.h" #include "Mesh.h" #include "Module.h" -namespace Hydrax{ namespace Module +namespace Hydrax { - /** Hydrax radial grid module - */ - class RadialGrid : public Module - { - public: - /** Struct wich contains Hydrax simple grid module options - */ - struct Options - { - /// Number of steps (Per circle) - int Steps; - /// Number of circles - int Circles; - /// Radius (In world units) - float Radius; - /// Smooth - bool Smooth; - /// Choppy waves - bool ChoppyWaves; - /// Choppy waves strength - float ChoppyStrength; - /// Step cube size - float StepSizeCube; - /// Step size five - float StepSizeFive; - /// Step lin size - float StepSizeLin; - /// Water strength - float Strength; - - /** Default constructor - */ - Options() - : Steps(250) - , Circles(250) - , Radius(100) - , Smooth(false) - , ChoppyWaves(true) - , ChoppyStrength(3.5f) - , StepSizeCube(0.00001f) - , StepSizeFive(0.0f) - , StepSizeLin(0.1f) - , Strength(32.5f) - { - } - - /** Constructor - @param _Steps Number of steps per circle - @param _Circles Number of circles - @param _Radius Mesh radius - */ - Options(const int &_Steps, - const int &_Circles, - const float &_Radius) - : Steps(_Steps) - , Circles(_Circles) - , Radius(_Radius) - , Smooth(false) - , ChoppyWaves(true) - , ChoppyStrength(3.5f) - , StepSizeCube(0.00001f) - , StepSizeFive(0.0f) - , StepSizeLin(0.1f) - , Strength(32.5f) - { - } - - /** Constructor - @param _Steps Number of steps per circle - @param _Circles Number of circles - @param _Radius Mesh radius - @param _Smooth Smooth vertex? - @param _ChoppyWaves Choppy waves enabled? Note: Only with Materialmanager::NM_VERTEX normal mode. - @param _ChoppyStrength Choppy waves strength Note: Only with Materialmanager::NM_VERTEX normal mode. - @param _StepSizeCube Step cube size - @param _StepSizeFive Step five size - @param _StepSizeLin Step lin size - @param _Strength Water strength - */ - Options(const int &_Steps, - const int &_Circles, - const float &_Radius, - const bool &_Smooth, - const bool &_ChoppyWaves, - const float &_ChoppyStrength, - const float &_StepSizeCube, - const float &_StepSizeFive, - const float &_StepSizeLin, - const float &_Strength) - : Steps(_Steps) - , Circles(_Circles) - , Radius(_Radius) - , Smooth(_Smooth) - , ChoppyWaves(_ChoppyWaves) - , ChoppyStrength(_ChoppyStrength) - , StepSizeCube(_StepSizeCube) - , StepSizeFive(_StepSizeFive) - , StepSizeLin(_StepSizeLin) - , Strength(_Strength) - { - } - }; - - /** Constructor - @param h Hydrax manager pointer - @param n Hydrax noise module - @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT - */ - RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode); - - /** Constructor - @param h Hydrax manager pointer - @param n Hydrax noise module - @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT - @param Options Perlin options - */ - RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode, const Options &Options); - - /** Destructor - */ - ~RadialGrid(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Set options - @param Options Options - */ - void setOptions(const Options &Options); - - /** Save config - @param Data String reference - */ - void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct module config - */ - bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get the current heigth at a especified world-space point - @param Position X/Z World position - @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 - */ - float getHeigth(const Ogre::Vector2 &Position); - - /** Get current options - @return Current options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - /** Create geometry in module(If special geometry is needed) - @param mMesh Mesh - @return false if it must be create by default Mesh::_createGeometry() fnc. - */ - const bool _createGeometry(Mesh *mMesh) const; - - private: - /** Calcule current normals - */ - void _calculeNormals(); - - /** Perform choppy waves - */ - void _performChoppyWaves(); - - /// Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX) - void *mVertices; - - /// Use it to store vertex positions when choppy displacement is enabled - Mesh::POS_NORM_VERTEX* mVerticesChoppyBuffer; - - /// Our projected grid options - Options mOptions; - - /// Our Hydrax pointer - Hydrax* mHydrax; - }; -}} + namespace Module + { + /** Hydrax radial grid module + */ + class RadialGrid : public Module + { + public: + /** Struct wich contains Hydrax simple grid module options + */ + struct Options + { + /// Number of steps (Per circle) + int Steps; + /// Number of circles + int Circles; + /// Radius (In world units) + float Radius; + /// Smooth + bool Smooth; + /// Choppy waves + bool ChoppyWaves; + /// Choppy waves strength + float ChoppyStrength; + /// Step cube size + float StepSizeCube; + /// Step size five + float StepSizeFive; + /// Step lin size + float StepSizeLin; + /// Water strength + float Strength; + + /** Default constructor + */ + Options() + : Steps(250), Circles(250), Radius(100), Smooth(false), ChoppyWaves(true), ChoppyStrength(3.5f), + StepSizeCube(0.00001f), StepSizeFive(0.0f), StepSizeLin(0.1f), Strength(32.5f) + { + } + + /** Constructor + @param _Steps Number of steps per circle + @param _Circles Number of circles + @param _Radius Mesh radius + */ + Options(const int &_Steps, const int &_Circles, const float &_Radius) + : Steps(_Steps), Circles(_Circles), Radius(_Radius), Smooth(false), ChoppyWaves(true), ChoppyStrength(3.5f), + StepSizeCube(0.00001f), StepSizeFive(0.0f), StepSizeLin(0.1f), Strength(32.5f) + { + } + + /** Constructor + @param _Steps Number of steps per circle + @param _Circles Number of circles + @param _Radius Mesh radius + @param _Smooth Smooth vertex? + @param _ChoppyWaves Choppy waves enabled? Note: Only with Materialmanager::NM_VERTEX normal mode. + @param _ChoppyStrength Choppy waves strength Note: Only with Materialmanager::NM_VERTEX normal mode. + @param _StepSizeCube Step cube size + @param _StepSizeFive Step five size + @param _StepSizeLin Step lin size + @param _Strength Water strength + */ + Options(const int &_Steps, const int &_Circles, const float &_Radius, const bool &_Smooth, + const bool &_ChoppyWaves, const float &_ChoppyStrength, const float &_StepSizeCube, + const float &_StepSizeFive, const float &_StepSizeLin, const float &_Strength) + : Steps(_Steps), Circles(_Circles), Radius(_Radius), Smooth(_Smooth), ChoppyWaves(_ChoppyWaves), + ChoppyStrength(_ChoppyStrength), StepSizeCube(_StepSizeCube), StepSizeFive(_StepSizeFive), + StepSizeLin(_StepSizeLin), Strength(_Strength) + { + } + }; + + /** Constructor + @param h Hydrax manager pointer + @param n Hydrax noise module + @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT + */ + RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode); + + /** Constructor + @param h Hydrax manager pointer + @param n Hydrax noise module + @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT + @param Options Perlin options + */ + RadialGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode, const Options &Options); + + /** Destructor + */ + ~RadialGrid(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Set options + @param Options Options + */ + void setOptions(const Options &Options); + + /** Save config + @param Data String reference + */ + void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct module config + */ + bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get the current heigth at a especified world-space point + @param Position X/Z World position + @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 + */ + float getHeigth(const Ogre::Vector2 &Position); + + /** Get current options + @return Current options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + /** Create geometry in module(If special geometry is needed) + @param mMesh Mesh + @return false if it must be create by default Mesh::_createGeometry() fnc. + */ + const bool _createGeometry(Mesh *mMesh) const; + + private: + /** Calcule current normals + */ + void _calculeNormals(); + + /** Perform choppy waves + */ + void _performChoppyWaves(); + + /// Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX) + void *mVertices; + + /// Use it to store vertex positions when choppy displacement is enabled + Mesh::POS_NORM_VERTEX *mVerticesChoppyBuffer; + + /// Our projected grid options + Options mOptions; + + /// Our Hydrax pointer + Hydrax *mHydrax; + }; + } // namespace Module +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/Real.cpp b/source/main/gfx/hydrax/Real.cpp index d7060c67c1..76f89c749e 100644 --- a/source/main/gfx/hydrax/Real.cpp +++ b/source/main/gfx/hydrax/Real.cpp @@ -33,162 +33,154 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #define _def_PackedNoise true -namespace Hydrax{ namespace Noise{ - -Real::Real() - : Noise("Real", true) - , mTime(0) - , mPerlinNoise(0) - , mGPUNormalMapManager(0) +namespace Hydrax { - mPerlinNoise = new Perlin(/*Generic one*/); -} + namespace Noise + { -Real::~Real() -{ - remove(); - delete mPerlinNoise; + Real::Real() : Noise("Real", true), mTime(0), mPerlinNoise(0), mGPUNormalMapManager(0) + { + mPerlinNoise = new Perlin(/*Generic one*/); + } - HydraxLOG(getName() + " destroyed."); -} + Real::~Real() + { + remove(); + delete mPerlinNoise; -void Real::create() -{ - if (isCreated()) - { - return; - } + HydraxLOG(getName() + " destroyed."); + } - Noise::create(); - mPerlinNoise->create(); -} + void Real::create() + { + if (isCreated()) { return; } -void Real::remove() -{ - if (areGPUNormalMapResourcesCreated()) - { - Noise::removeGPUNormalMapResources(mGPUNormalMapManager); - } + Noise::create(); + mPerlinNoise->create(); + } - if (!isCreated()) - { - return; - } + void Real::remove() + { + if (areGPUNormalMapResourcesCreated()) { Noise::removeGPUNormalMapResources(mGPUNormalMapManager); } - mTime = 0; + if (!isCreated()) { return; } - mPerlinNoise->remove(); - mWaves.clear(); - mPressurePoints.clear(); - Noise::remove(); -} + mTime = 0; -int Real::addWave(Ogre::Vector2 dir, float A, float T, float p) -{ - mWaves.push_back(Wave(dir,A,T,p)); - return static_cast(mWaves.size()); -} + mPerlinNoise->remove(); + mWaves.clear(); + mPressurePoints.clear(); + Noise::remove(); + } -int Real::addPressurePoint(Ogre::Vector2 Orig, float p, float T, float L) -{ - mPressurePoints.push_back(PressurePoint(Orig,p,T,L)); - return static_cast(mPressurePoints.size()); -} + int Real::addWave(Ogre::Vector2 dir, float A, float T, float p) + { + mWaves.push_back(Wave(dir, A, T, p)); + return static_cast(mWaves.size()); + } -Wave Real::getWave(int id) const -{ - return mWaves.at(id); -} + int Real::addPressurePoint(Ogre::Vector2 Orig, float p, float T, float L) + { + mPressurePoints.push_back(PressurePoint(Orig, p, T, L)); + return static_cast(mPressurePoints.size()); + } -bool Real::eraseWave(int id) -{ - if( (id < 0) || (id >= (int)mWaves.size()) ){ - HydraxLOG("Error (Real::eraseWave):\tCan't delete the wave."); - HydraxLOG("\tIdentifier exceed the waves vector dimensions."); - return false; - } - size_t Size = mWaves.size(); - mWaves.erase(mWaves.begin() + id); - if(mWaves.size() == Size){ - HydraxLOG("Error (Real::eraseWave):\tCan't delete the wave."); - HydraxLOG("\tThe size before deletion matchs with the size after the operation."); - return false; - } - return true; -} - -bool Real::modifyWave(int id,Ogre::Vector2 dir, float A, float T, float p) -{ - if( (id < 0) || (id >= (int)mWaves.size()) ){ - HydraxLOG("Error (Real::eraseWave):\tCan't delete the wave."); - HydraxLOG("\tIdentifier exceed the waves vector dimensions."); - return false; - } - mWaves.at(id) = Wave(dir,A,T,p); - return true; -} - -bool Real::createGPUNormalMapResources(GPUNormalMapManager *g) -{ - /// @todo Create gpuNormal creator. - return false; -} + Wave Real::getWave(int id) const + { + return mWaves.at(id); + } -void Real::saveCfg(Ogre::String &Data) -{ - mPerlinNoise->saveCfg(Data); -} + bool Real::eraseWave(int id) + { + if ((id < 0) || (id >= (int)mWaves.size())) + { + HydraxLOG("Error (Real::eraseWave):\tCan't delete the wave."); + HydraxLOG("\tIdentifier exceed the waves vector dimensions."); + return false; + } + size_t Size = mWaves.size(); + mWaves.erase(mWaves.begin() + id); + if (mWaves.size() == Size) + { + HydraxLOG("Error (Real::eraseWave):\tCan't delete the wave."); + HydraxLOG("\tThe size before deletion matchs with the size after the operation."); + return false; + } + return true; + } -bool Real::loadCfg(Ogre::ConfigFile &CfgFile) -{ - if (!Noise::loadCfg(CfgFile)) - { - return false; - } - - HydraxLOG("\tReading options..."); - mPerlinNoise->setOptions( - Perlin::Options(CfgFileManager::_getIntValue(CfgFile,"Perlin_Octaves"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Scale"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Falloff"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Animspeed"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_Timemulti"), - CfgFileManager::_getFloatValue(CfgFile,"Perlin_GPU_Strength"), - CfgFileManager::_getVector3Value(CfgFile,"Perlin_GPU_LODParameters"))); - HydraxLOG("\tOptions readed."); - - return true; -} - -void Real::update(const Ogre::Real &timeSinceLastFrame) -{ - int i; - mTime += timeSinceLastFrame; - mPerlinNoise->update(timeSinceLastFrame); - for(i=(int)mWaves.size()-1;i>=0;i--) { - mWaves.at(i).update(timeSinceLastFrame); - } - for(i=(int)mPressurePoints.size()-1;i>=0;i--) { - if(!mPressurePoints.at(i).update(timeSinceLastFrame)) { - mPressurePoints.erase(mPressurePoints.begin() + i); + bool Real::modifyWave(int id, Ogre::Vector2 dir, float A, float T, float p) + { + if ((id < 0) || (id >= (int)mWaves.size())) + { + HydraxLOG("Error (Real::eraseWave):\tCan't delete the wave."); + HydraxLOG("\tIdentifier exceed the waves vector dimensions."); + return false; + } + mWaves.at(id) = Wave(dir, A, T, p); + return true; } - } -} -float Real::getValue(const float &x, const float &y) -{ - int i; - /// 1st.- Perlin height - float H = mPerlinNoise->getValue(x,y); - /// 2nd.- Waves height - for(i=0;i<(int)mWaves.size();i++) { - H += mWaves.at(i).getValue(x,y); - } - /// 3rd.- Pressure points height - for(i=0;i<(int)mPressurePoints.size();i++) { - H += mPressurePoints.at(i).getValue(x,y); - } - return H; -} - -}} // namespace Hydrax::Noise + bool Real::createGPUNormalMapResources(GPUNormalMapManager *g) + { + /// @todo Create gpuNormal creator. + return false; + } + + void Real::saveCfg(Ogre::String &Data) + { + mPerlinNoise->saveCfg(Data); + } + + bool Real::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (!Noise::loadCfg(CfgFile)) { return false; } + + HydraxLOG("\tReading options..."); + mPerlinNoise->setOptions(Perlin::Options(CfgFileManager::_getIntValue(CfgFile, "Perlin_Octaves"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Scale"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Falloff"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Animspeed"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_Timemulti"), + CfgFileManager::_getFloatValue(CfgFile, "Perlin_GPU_Strength"), + CfgFileManager::_getVector3Value(CfgFile, "Perlin_GPU_LODParameters"))); + HydraxLOG("\tOptions readed."); + + return true; + } + + void Real::update(const Ogre::Real &timeSinceLastFrame) + { + int i; + mTime += timeSinceLastFrame; + mPerlinNoise->update(timeSinceLastFrame); + for (i = (int)mWaves.size() - 1; i >= 0; i--) + { + mWaves.at(i).update(timeSinceLastFrame); + } + for (i = (int)mPressurePoints.size() - 1; i >= 0; i--) + { + if (!mPressurePoints.at(i).update(timeSinceLastFrame)) { mPressurePoints.erase(mPressurePoints.begin() + i); } + } + } + + float Real::getValue(const float &x, const float &y) + { + int i; + /// 1st.- Perlin height + float H = mPerlinNoise->getValue(x, y); + /// 2nd.- Waves height + for (i = 0; i < (int)mWaves.size(); i++) + { + H += mWaves.at(i).getValue(x, y); + } + /// 3rd.- Pressure points height + for (i = 0; i < (int)mPressurePoints.size(); i++) + { + H += mPressurePoints.at(i).getValue(x, y); + } + return H; + } + + } // namespace Noise +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/Real.h b/source/main/gfx/hydrax/Real.h index 087dab54a0..d8cdb8d050 100644 --- a/source/main/gfx/hydrax/Real.h +++ b/source/main/gfx/hydrax/Real.h @@ -47,140 +47,143 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to // ---------------------------------------------------------------------------- // Include the components // ---------------------------------------------------------------------------- -#include "Wave.h" #include "PressurePoint.h" +#include "Wave.h" -namespace Hydrax{ namespace Noise -{ - -/** @class Real Real.h Noise/Real/Real.h - * @brief This class is a sea elevation module that combines several effects: \n - * Waves, defined by direction, amplitude, period and optionally, phase. - * Perlin noise, used to randomize the sea surface. - * Pressure points, used to create puntual waves. - */ -class Real : public Noise +namespace Hydrax { -public: - /** Default constructor - */ - Real(); - - /** Destructor - */ - ~Real(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Adds a wave to the system. - * @param dir Direction of the wave. - * @param A Amplitude of the wave (m). - * @param T Period of the wave (s). - * @param p Phase of the wave (rad). - * @return Id of the wave. - */ - int addWave(Ogre::Vector2 dir, float A, float T, float p=0.f); - - /** Adds a pressure point to the system - * @param Orig Origin of perturbation. - * @param p Pressure pulse (N·m). \n - * The maximum half-amplitude of the wave will result from divide this value - * with g*rho. So, a pressure of 10000 N·m produces 2 m waves. - * @param T Maximum time of perturbation (s). \n - * The effect of the perturbation will decay. When T time will be elapsed, - * any effects will remain. - * @param L wave length. \n - * To objects falling, similar values to amplitude can be OK. For ships Kelvin - * wakes probably length of the ship is a better choice. - * @return Id of the pressure point. - * @warning Pressure point will be autodestroyed when it have not any effect, - * so it's not available any modify after the creation. - */ - int addPressurePoint(Ogre::Vector2 Orig, float p, float T, float L); - - /** Returns a wave to the system. - * @param id Identifier of the wave. - * @return Selected wave. - */ - Wave getWave(int id) const; - - /** Removes a wave from the system. - * @param id Identifier of the wave. - * @return true if all gone right, or false if errors happen. - */ - bool eraseWave(int id); - - /** Modify a wave from the system. - * @param id Identifier of the wave. - * @param A Amplitude of the wave (m). - * @param T Period of the wave (s). - * @param p Phase of the wave (rad). - * @return true if all gone right, or false if errors happen. - */ - bool modifyWave(int id,Ogre::Vector2 dir, float A, float T, float p=0.f); - - /** Create GPUNormalMap resources - @param g GPUNormalMapManager pointer - @return true if it needs to be created, false if not - */ - bool createGPUNormalMapResources(GPUNormalMapManager *g); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Save config - @param Data String reference - */ - void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct noise config - */ - bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get the especified x/y noise value - @param x X Coord - @param y Y Coord - @return Noise value - @remarks range [~-0.2, ~0.2] - */ - float getValue(const float &x, const float &y); - - /** Get current Real noise options - @return Current Real noise options - */ - inline Perlin* getPerlinNoise() const{return mPerlinNoise;} - -protected: - - -private: - /// Elapsed time - double mTime; - - /// Perlin noise - Perlin *mPerlinNoise; - - /// GPUNormalMapManager pointer - GPUNormalMapManager *mGPUNormalMapManager; - - /// Vector of waves - std::vector mWaves; - - /// Vector of pressure points - std::vector mPressurePoints; -}; - - -}} // Namespace + namespace Noise + { + + /** @class Real Real.h Noise/Real/Real.h + * @brief This class is a sea elevation module that combines several effects: \n + * Waves, defined by direction, amplitude, period and optionally, phase. + * Perlin noise, used to randomize the sea surface. + * Pressure points, used to create puntual waves. + */ + class Real : public Noise + { + public: + /** Default constructor + */ + Real(); + + /** Destructor + */ + ~Real(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Adds a wave to the system. + * @param dir Direction of the wave. + * @param A Amplitude of the wave (m). + * @param T Period of the wave (s). + * @param p Phase of the wave (rad). + * @return Id of the wave. + */ + int addWave(Ogre::Vector2 dir, float A, float T, float p = 0.f); + + /** Adds a pressure point to the system + * @param Orig Origin of perturbation. + * @param p Pressure pulse (N·m). \n + * The maximum half-amplitude of the wave will result from divide this value + * with g*rho. So, a pressure of 10000 N·m produces 2 m waves. + * @param T Maximum time of perturbation (s). \n + * The effect of the perturbation will decay. When T time will be elapsed, + * any effects will remain. + * @param L wave length. \n + * To objects falling, similar values to amplitude can be OK. For ships Kelvin + * wakes probably length of the ship is a better choice. + * @return Id of the pressure point. + * @warning Pressure point will be autodestroyed when it have not any effect, + * so it's not available any modify after the creation. + */ + int addPressurePoint(Ogre::Vector2 Orig, float p, float T, float L); + + /** Returns a wave to the system. + * @param id Identifier of the wave. + * @return Selected wave. + */ + Wave getWave(int id) const; + + /** Removes a wave from the system. + * @param id Identifier of the wave. + * @return true if all gone right, or false if errors happen. + */ + bool eraseWave(int id); + + /** Modify a wave from the system. + * @param id Identifier of the wave. + * @param A Amplitude of the wave (m). + * @param T Period of the wave (s). + * @param p Phase of the wave (rad). + * @return true if all gone right, or false if errors happen. + */ + bool modifyWave(int id, Ogre::Vector2 dir, float A, float T, float p = 0.f); + + /** Create GPUNormalMap resources + @param g GPUNormalMapManager pointer + @return true if it needs to be created, false if not + */ + bool createGPUNormalMapResources(GPUNormalMapManager *g); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Save config + @param Data String reference + */ + void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct noise config + */ + bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get the especified x/y noise value + @param x X Coord + @param y Y Coord + @return Noise value + @remarks range [~-0.2, ~0.2] + */ + float getValue(const float &x, const float &y); + + /** Get current Real noise options + @return Current Real noise options + */ + inline Perlin *getPerlinNoise() const + { + return mPerlinNoise; + } + + protected: + private: + /// Elapsed time + double mTime; + + /// Perlin noise + Perlin *mPerlinNoise; + + /// GPUNormalMapManager pointer + GPUNormalMapManager *mGPUNormalMapManager; + + /// Vector of waves + std::vector mWaves; + + /// Vector of pressure points + std::vector mPressurePoints; + }; + + } // namespace Noise +} // namespace Hydrax #endif // REAL_H_INCLUDED diff --git a/source/main/gfx/hydrax/RttManager.cpp b/source/main/gfx/hydrax/RttManager.cpp index 4e10ccbda7..6e34e8975a 100644 --- a/source/main/gfx/hydrax/RttManager.cpp +++ b/source/main/gfx/hydrax/RttManager.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -22,753 +22,723 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to -------------------------------------------------------------------------------- */ -#pragma warning(disable:4267) +#pragma warning(disable : 4267) #include "RttManager.h" #include "Hydrax.h" -#define _def_Hydrax_Reflection_Rtt_Name "HydraxReflectionMap" -#define _def_Hydrax_Refraction_Rtt_Name "HydraxRefractionMap" -#define _def_Hydrax_Depth_Rtt_Name "HydraxDepthMap" -#define _def_Hydrax_Depth_Reflection_Rtt_Name "HydraxDepthReflectionMap" -#define _def_Hydrax_API_Rtt_Name "HydraxAPIMap" -#define _def_Hydrax_GPU_Normal_Map_Rtt_Name "HydraxNormalMap" +#define _def_Hydrax_Reflection_Rtt_Name "HydraxReflectionMap" +#define _def_Hydrax_Refraction_Rtt_Name "HydraxRefractionMap" +#define _def_Hydrax_Depth_Rtt_Name "HydraxDepthMap" +#define _def_Hydrax_Depth_Reflection_Rtt_Name "HydraxDepthReflectionMap" +#define _def_Hydrax_API_Rtt_Name "HydraxAPIMap" +#define _def_Hydrax_GPU_Normal_Map_Rtt_Name "HydraxNormalMap" namespace Hydrax { - RttManager::RttManager(Hydrax *h) - : mHydrax(h) - , mPlanesSceneNode(0) - , mReflectionDisplacementError(0.5f) - { - Ogre::String RttNames[6] = - {_def_Hydrax_Reflection_Rtt_Name, - _def_Hydrax_Refraction_Rtt_Name, - _def_Hydrax_Depth_Rtt_Name, - _def_Hydrax_Depth_Reflection_Rtt_Name, - _def_Hydrax_API_Rtt_Name, - _def_Hydrax_GPU_Normal_Map_Rtt_Name}; - - for (int k = 0; k < 6; k++) - { - mPlanes[k] = static_cast(NULL); - mTextures[k].setNull(); - mRttOptions[k].Name = RttNames[k]; - mRttOptions[k].Size_ = Size(0); - mRttOptions[k].NumberOfChannels_ = NOC_3; - mRttOptions[k].BitsPerChannel_ = BPC_8; - } - - mReflectionListener.mRttManager = this; - mReflectionListener.mCReflectionQueueListener.mRttManager = this; - mReflectionListener.mCReflectionQueueListener.mActive = false; - mRefractionListener.mRttManager = this; - mDepthListener.mRttManager = this; - mDepthReflectionListener.mRttManager = this; - mDepthReflectionListener.mRttManager = this; - mGPUNormalMapListener.mRttManager = this; - } - - RttManager::~RttManager() - { - removeAll(); - } - - void RttManager::initialize(const RttType& Rtt) - { - if (!mPlanesSceneNode) - { - mPlanesSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - mHydrax->getSceneManager()->addRenderQueueListener(&mReflectionListener.mCReflectionQueueListener); - } - - switch(Rtt) - { - case RTT_REFLECTION: - { - const Ogre::Vector3& WC = mHydrax->getWaterColor(); - - bool RenderSkyBox = !mHydrax->_isCurrentFrameUnderwater(); - - _initializeRtt(Rtt, Ogre::Vector3::UNIT_Y, Ogre::ColourValue(WC.x, WC.y, WC.z), RenderSkyBox, &mReflectionListener); - } - break; - - case RTT_REFRACTION: - { - const Ogre::Vector3& WC = mHydrax->getWaterColor(); - - bool RenderSkyBox = mHydrax->_isCurrentFrameUnderwater(); - - _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue(WC.x, WC.y, WC.z), RenderSkyBox, &mRefractionListener); - } - break; - - case RTT_DEPTH: - { - _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue::Black, false, &mDepthListener, "HydraxDepth", false); - } - break; - - case RTT_DEPTH_REFLECTION: - { - _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue::Black, false, &mDepthReflectionListener, "HydraxDepth", false); - } - break; - - case RTT_GPU_NORMAL_MAP: - { - _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue(0.5,1,0.5), false, &mGPUNormalMapListener, "", false); - } - break; - } - } - - void RttManager::remove(const RttType& Rtt) - { - Ogre::TexturePtr &Tex = mTextures[Rtt]; - - if (!Tex.isNull()) - { - Ogre::RenderTarget* RT = Tex->getBuffer()->getRenderTarget(); + RttManager::RttManager(Hydrax *h) : mHydrax(h), mPlanesSceneNode(0), mReflectionDisplacementError(0.5f) + { + Ogre::String RttNames[6] = {_def_Hydrax_Reflection_Rtt_Name, _def_Hydrax_Refraction_Rtt_Name, + _def_Hydrax_Depth_Rtt_Name, _def_Hydrax_Depth_Reflection_Rtt_Name, + _def_Hydrax_API_Rtt_Name, _def_Hydrax_GPU_Normal_Map_Rtt_Name}; + + for (int k = 0; k < 6; k++) + { + mPlanes[k] = static_cast(NULL); + mTextures[k].setNull(); + mRttOptions[k].Name = RttNames[k]; + mRttOptions[k].Size_ = Size(0); + mRttOptions[k].NumberOfChannels_ = NOC_3; + mRttOptions[k].BitsPerChannel_ = BPC_8; + } + + mReflectionListener.mRttManager = this; + mReflectionListener.mCReflectionQueueListener.mRttManager = this; + mReflectionListener.mCReflectionQueueListener.mActive = false; + mRefractionListener.mRttManager = this; + mDepthListener.mRttManager = this; + mDepthReflectionListener.mRttManager = this; + mDepthReflectionListener.mRttManager = this; + mGPUNormalMapListener.mRttManager = this; + } + + RttManager::~RttManager() + { + removeAll(); + } + + void RttManager::initialize(const RttType &Rtt) + { + if (!mPlanesSceneNode) + { + mPlanesSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + mHydrax->getSceneManager()->addRenderQueueListener(&mReflectionListener.mCReflectionQueueListener); + } + + switch (Rtt) + { + case RTT_REFLECTION: + { + const Ogre::Vector3 &WC = mHydrax->getWaterColor(); + + bool RenderSkyBox = !mHydrax->_isCurrentFrameUnderwater(); + + _initializeRtt(Rtt, Ogre::Vector3::UNIT_Y, Ogre::ColourValue(WC.x, WC.y, WC.z), RenderSkyBox, &mReflectionListener); + } + break; + + case RTT_REFRACTION: + { + const Ogre::Vector3 &WC = mHydrax->getWaterColor(); + + bool RenderSkyBox = mHydrax->_isCurrentFrameUnderwater(); + + _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue(WC.x, WC.y, WC.z), RenderSkyBox, + &mRefractionListener); + } + break; + + case RTT_DEPTH: + { + _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue::Black, false, &mDepthListener, "HydraxDepth", + false); + } + break; + + case RTT_DEPTH_REFLECTION: + { + _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue::Black, false, &mDepthReflectionListener, + "HydraxDepth", false); + } + break; + + case RTT_GPU_NORMAL_MAP: + { + _initializeRtt(Rtt, Ogre::Vector3::NEGATIVE_UNIT_Y, Ogre::ColourValue(0.5, 1, 0.5), false, &mGPUNormalMapListener, "", + false); + } + break; + } + } + + void RttManager::remove(const RttType &Rtt) + { + Ogre::TexturePtr &Tex = mTextures[Rtt]; + + if (!Tex.isNull()) + { + Ogre::RenderTarget *RT = Tex->getBuffer()->getRenderTarget(); RT->removeAllListeners(); RT->removeAllViewports(); - Ogre::TextureManager::getSingleton().remove(mRttOptions[Rtt].Name); - Ogre::MeshManager::getSingleton().remove(mRttOptions[Rtt].Name + "ClipPlane"); - - Tex.setNull(); - delete mPlanes[Rtt]; - mPlanes[Rtt] = static_cast(NULL); - } - - // Check it to avoid any possible problem(texture initializated by createTextureUnit(Name..)) - if (Ogre::TextureManager::getSingleton().resourceExists(mRttOptions[Rtt].Name)) - { - Ogre::TextureManager::getSingleton().remove(mRttOptions[Rtt].Name); - } - } - - void RttManager::removeAll() - { - for (int k = 0; k < 6; k++) - { - remove(static_cast(k)); - } - - if (mPlanesSceneNode) - { - mPlanesSceneNode->detachAllObjects(); + Ogre::TextureManager::getSingleton().remove(mRttOptions[Rtt].Name); + Ogre::MeshManager::getSingleton().remove(mRttOptions[Rtt].Name + "ClipPlane"); + + Tex.setNull(); + delete mPlanes[Rtt]; + mPlanes[Rtt] = static_cast(NULL); + } + + // Check it to avoid any possible problem(texture initializated by createTextureUnit(Name..)) + if (Ogre::TextureManager::getSingleton().resourceExists(mRttOptions[Rtt].Name)) + { Ogre::TextureManager::getSingleton().remove(mRttOptions[Rtt].Name); } + } + + void RttManager::removeAll() + { + for (int k = 0; k < 6; k++) + { + remove(static_cast(k)); + } + + if (mPlanesSceneNode) + { + mPlanesSceneNode->detachAllObjects(); mPlanesSceneNode->getParentSceneNode()->removeAndDestroyChild(mPlanesSceneNode); - mPlanesSceneNode = 0; - } - } - - void RttManager::_initializeRtt(const RttType& Rtt, const Ogre::Vector3& PlaneNormal, - const Ogre::ColourValue& BackgroundColour, const bool& RenderSky, - Ogre::RenderTargetListener* RTListener, const Ogre::String& MaterialScheme, - const bool& ShadowsEnabled) - { - remove(Rtt); - - mPlanes[Rtt] = new Ogre::MovablePlane(mRttOptions[Rtt].Name + "Plane"); - - mPlanes[Rtt]->d = 0; - mPlanes[Rtt]->normal = PlaneNormal; - - Ogre::MeshManager::getSingleton(). - createPlane(mRttOptions[Rtt].Name + "ClipPlane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - *mPlanes[Rtt], - mHydrax->getMesh()->getSize().Width,mHydrax->getMesh()->getSize().Height, // PG grid.. <-- look into - 10,10, true, 1,5,5, Ogre::Vector3::UNIT_Z); - - mPlanes[Rtt]->setCastShadows(false); - mPlanesSceneNode->attachObject(mPlanes[Rtt]); - - Size TSize = mRttOptions[Rtt].Size_; - - if (TSize.Width == 0 || TSize.Height == 0) - { - TSize.Width = mHydrax->getViewport()->getActualWidth(); - TSize.Height = mHydrax->getViewport()->getActualHeight(); - } - - mTextures[Rtt] = Ogre::TextureManager::getSingleton() - .createManual(mRttOptions[Rtt].Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - TSize.Width, - TSize.Height, - 0, - getPixelFormat(Rtt), - Ogre::TU_RENDERTARGET); - - Ogre::RenderTarget* RT_Texture = mTextures[Rtt]->getBuffer()->getRenderTarget(); - + mPlanesSceneNode = 0; + } + } + + void RttManager::_initializeRtt(const RttType &Rtt, const Ogre::Vector3 &PlaneNormal, + const Ogre::ColourValue &BackgroundColour, const bool &RenderSky, + Ogre::RenderTargetListener *RTListener, const Ogre::String &MaterialScheme, + const bool &ShadowsEnabled) + { + remove(Rtt); + + mPlanes[Rtt] = new Ogre::MovablePlane(mRttOptions[Rtt].Name + "Plane"); + + mPlanes[Rtt]->d = 0; + mPlanes[Rtt]->normal = PlaneNormal; + + Ogre::MeshManager::getSingleton().createPlane( + mRttOptions[Rtt].Name + "ClipPlane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, *mPlanes[Rtt], + mHydrax->getMesh()->getSize().Width, mHydrax->getMesh()->getSize().Height, // PG grid.. <-- look into + 10, 10, true, 1, 5, 5, Ogre::Vector3::UNIT_Z); + + mPlanes[Rtt]->setCastShadows(false); + mPlanesSceneNode->attachObject(mPlanes[Rtt]); + + Size TSize = mRttOptions[Rtt].Size_; + + if (TSize.Width == 0 || TSize.Height == 0) + { + TSize.Width = mHydrax->getViewport()->getActualWidth(); + TSize.Height = mHydrax->getViewport()->getActualHeight(); + } + + mTextures[Rtt] = Ogre::TextureManager::getSingleton().createManual( + mRttOptions[Rtt].Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, TSize.Width, + TSize.Height, 0, getPixelFormat(Rtt), Ogre::TU_RENDERTARGET); + + Ogre::RenderTarget *RT_Texture = mTextures[Rtt]->getBuffer()->getRenderTarget(); + Ogre::Viewport *RT_Texture_Viewport = RT_Texture->addViewport(mHydrax->getCamera()); RT_Texture_Viewport->setClearEveryFrame(true); RT_Texture_Viewport->setBackgroundColour(BackgroundColour); RT_Texture_Viewport->setOverlaysEnabled(false); - RT_Texture_Viewport->setShadowsEnabled(ShadowsEnabled); - if (MaterialScheme != "") - { - RT_Texture_Viewport->setMaterialScheme(MaterialScheme); - } + RT_Texture_Viewport->setShadowsEnabled(ShadowsEnabled); + if (MaterialScheme != "") { RT_Texture_Viewport->setMaterialScheme(MaterialScheme); } RT_Texture_Viewport->setSkiesEnabled(RenderSky); RT_Texture->addListener(RTListener); - } - - void RttManager::setTextureSize(const RttType& Rtt, const Size& S) - { - mRttOptions[static_cast(Rtt)].Size_ = S; - - if (!getTexture(Rtt).isNull()) - { - initialize(Rtt); - - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); - - if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER); - - if (mHydrax->_isCurrentFrameUnderwater()) - { - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER_COMPOSITOR); - } - } - } - } - - void RttManager::setTexturesSize(const Size& S) - { - bool ReloadMaterialsNeeded = false; - - for(int k = 0; k < 5; k++) - { - mRttOptions[static_cast(k)].Size_ = S; - - if (!getTexture(static_cast(k)).isNull()) - { - initialize(static_cast(k)); - - ReloadMaterialsNeeded = true; - } - } - - if (ReloadMaterialsNeeded) - { - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); - - if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER); - - if (mHydrax->_isCurrentFrameUnderwater()) - { - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER_COMPOSITOR); - } - } - } - } - - const Ogre::PixelFormat RttManager::getPixelFormat(const RttType& Rtt) const - { - switch (mRttOptions[Rtt].NumberOfChannels_) - { - // One channel (R) - case NOC_1 : - { - switch (mRttOptions[Rtt].BitsPerChannel_) - { - // 8 bits - case BPC_8 : - { - return Ogre::PF_L8; - } - break; - - // 16 bits - case BPC_16 : - { - return Ogre::PF_FLOAT16_R; - } - break; - - // 32 bits - case BPC_32 : - { - return Ogre::PF_FLOAT32_R; - } - break; - } - } - break; - - // Two channels (RG) - case NOC_2 : - { - switch (mRttOptions[Rtt].BitsPerChannel_) - { - // 8 bits - case BPC_8 : - { - //... - } - break; - - // 16 bits - case BPC_16 : - { - return Ogre::PF_FLOAT16_GR; - } - break; - - // 32 bits - case BPC_32 : - { - return Ogre::PF_FLOAT32_GR; - } - break; - } - } - break; - - // Three channels (RGB) - case NOC_3 : - { - switch (mRttOptions[Rtt].BitsPerChannel_) - { - // 8 bits - case BPC_8 : - { - return Ogre::PF_B8G8R8; - } - break; - - // 16 bits - case BPC_16 : - { - return Ogre::PF_FLOAT16_RGB; - } - break; - - // 32 bits - case BPC_32 : - { - return Ogre::PF_FLOAT32_RGB; - } - break; - } - } - break; - - // Four channels (RGBA) - case NOC_4 : - { - switch (mRttOptions[Rtt].BitsPerChannel_) - { - // 8 bits - case BPC_8 : - { - return Ogre::PF_B8G8R8A8; - } - break; - - // 16 bits - case BPC_16 : - { - return Ogre::PF_FLOAT16_RGBA; - } - break; - - // 32 bits - case BPC_32 : - { - return Ogre::PF_FLOAT32_RGBA; - } - break; - } - } - break; - - } - - // >= than needed - return Ogre::PF_FLOAT32_RGBA; - } - - /// ------------------------------------------------------------------------------- - - void RttManager::CReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + } + + void RttManager::setTextureSize(const RttType &Rtt, const Size &S) + { + mRttOptions[static_cast(Rtt)].Size_ = S; + + if (!getTexture(Rtt).isNull()) + { + initialize(Rtt); + + mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); + + if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER); + + if (mHydrax->_isCurrentFrameUnderwater()) + { mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER_COMPOSITOR); } + } + } + } + + void RttManager::setTexturesSize(const Size &S) + { + bool ReloadMaterialsNeeded = false; + + for (int k = 0; k < 5; k++) + { + mRttOptions[static_cast(k)].Size_ = S; + + if (!getTexture(static_cast(k)).isNull()) + { + initialize(static_cast(k)); + + ReloadMaterialsNeeded = true; + } + } + + if (ReloadMaterialsNeeded) + { + mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); + + if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER); + + if (mHydrax->_isCurrentFrameUnderwater()) + { mHydrax->getMaterialManager()->reload(MaterialManager::MAT_UNDERWATER_COMPOSITOR); } + } + } + } + + const Ogre::PixelFormat RttManager::getPixelFormat(const RttType &Rtt) const + { + switch (mRttOptions[Rtt].NumberOfChannels_) + { + // One channel (R) + case NOC_1: + { + switch (mRttOptions[Rtt].BitsPerChannel_) + { + // 8 bits + case BPC_8: + { + return Ogre::PF_L8; + } + break; + + // 16 bits + case BPC_16: + { + return Ogre::PF_FLOAT16_R; + } + break; + + // 32 bits + case BPC_32: + { + return Ogre::PF_FLOAT32_R; + } + break; + } + } + break; + + // Two channels (RG) + case NOC_2: + { + switch (mRttOptions[Rtt].BitsPerChannel_) + { + // 8 bits + case BPC_8: + { + //... + } + break; + + // 16 bits + case BPC_16: + { + return Ogre::PF_FLOAT16_GR; + } + break; + + // 32 bits + case BPC_32: + { + return Ogre::PF_FLOAT32_GR; + } + break; + } + } + break; + + // Three channels (RGB) + case NOC_3: + { + switch (mRttOptions[Rtt].BitsPerChannel_) + { + // 8 bits + case BPC_8: + { + return Ogre::PF_B8G8R8; + } + break; + + // 16 bits + case BPC_16: + { + return Ogre::PF_FLOAT16_RGB; + } + break; + + // 32 bits + case BPC_32: + { + return Ogre::PF_FLOAT32_RGB; + } + break; + } + } + break; + + // Four channels (RGBA) + case NOC_4: + { + switch (mRttOptions[Rtt].BitsPerChannel_) + { + // 8 bits + case BPC_8: + { + return Ogre::PF_B8G8R8A8; + } + break; + + // 16 bits + case BPC_16: + { + return Ogre::PF_FLOAT16_RGBA; + } + break; + + // 32 bits + case BPC_32: + { + return Ogre::PF_FLOAT32_RGBA; + } + break; + } + } + break; + } + + // >= than needed + return Ogre::PF_FLOAT32_RGBA; + } + + /// ------------------------------------------------------------------------------- + + void RttManager::CReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; - mCReflectionQueueListener.mActive = true; + mCReflectionQueueListener.mActive = true; mHydrax->getMesh()->getEntity()->setVisible(false); - - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - } - else - { - mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0,+mHydrax->getPlanesError(),0); - } + + if (mHydrax->_isCurrentFrameUnderwater()) + { mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); } + else + { + mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0, +mHydrax->getPlanesError(), 0); + } bool IsInUnderwaterError = false; - // Underwater - if ( mHydrax->_isCurrentFrameUnderwater() && - (mHydrax->getCamera()->getDerivedPosition().y > mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->getPosition().y)) - { - mCameraPlaneDiff = 0; - IsInUnderwaterError = true; - } - // Overwater - else if ((!mHydrax->_isCurrentFrameUnderwater()) && - (mHydrax->getCamera()->getDerivedPosition().y < mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->getPosition().y)) - { - mCameraPlaneDiff = mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->getPosition().y-mHydrax->getCamera()->getDerivedPosition().y+mRttManager->mReflectionDisplacementError; - mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0,-mCameraPlaneDiff,0); - } - else - { - mCameraPlaneDiff = 0; - } - - if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_REFLECTION]->normal = -mRttManager->mPlanes[RTT_REFLECTION]->normal; - } - } + // Underwater + if (mHydrax->_isCurrentFrameUnderwater() && (mHydrax->getCamera()->getDerivedPosition().y > + mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->getPosition().y)) + { + mCameraPlaneDiff = 0; + IsInUnderwaterError = true; + } + // Overwater + else if ((!mHydrax->_isCurrentFrameUnderwater()) && + (mHydrax->getCamera()->getDerivedPosition().y < + mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->getPosition().y)) + { + mCameraPlaneDiff = mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->getPosition().y - + mHydrax->getCamera()->getDerivedPosition().y + mRttManager->mReflectionDisplacementError; + mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0, -mCameraPlaneDiff, 0); + } + else + { + mCameraPlaneDiff = 0; + } + + if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + if (mHydrax->_isCurrentFrameUnderwater()) + { mRttManager->mPlanes[RTT_REFLECTION]->normal = -mRttManager->mPlanes[RTT_REFLECTION]->normal; } + } mHydrax->getCamera()->enableReflection(mRttManager->mPlanes[RTT_REFLECTION]); - if (IsInUnderwaterError) - { - mCReflectionQueueListener.mActive = false; - } - else - { - mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_REFLECTION]); - } + if (IsInUnderwaterError) { mCReflectionQueueListener.mActive = false; } + else + { + mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_REFLECTION]); + } } - void RttManager::CReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; mHydrax->getMesh()->getEntity()->setVisible(true); - if (mCameraPlaneDiff != 0) - { - mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0,mCameraPlaneDiff,0); - } + if (mCameraPlaneDiff != 0) { mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0, mCameraPlaneDiff, 0); } if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0,mHydrax->getPlanesError(),0); - } - else - { - mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - } + { mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0, mHydrax->getPlanesError(), 0); } + else + { + mRttManager->mPlanes[RTT_REFLECTION]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); + } mHydrax->getCamera()->disableReflection(); mHydrax->getCamera()->disableCustomNearClipPlane(); - if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) - { - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_REFLECTION]->normal = -mRttManager->mPlanes[RTT_REFLECTION]->normal; - } - } + if (mHydrax->isComponent(HYDRAX_COMPONENT_UNDERWATER)) + { + if (mHydrax->_isCurrentFrameUnderwater()) + { mRttManager->mPlanes[RTT_REFLECTION]->normal = -mRttManager->mPlanes[RTT_REFLECTION]->normal; } + } - mCReflectionQueueListener.mActive = false; + mCReflectionQueueListener.mActive = false; } - void RttManager::CReflectionListener::CReflectionQueueListener::renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool + void RttManager::CReflectionListener::CReflectionQueueListener::renderQueueStarted(Ogre::uint8 queueGroupId, + const Ogre::String &invocation, + bool - &skipThisInvocation) - { - if ((queueGroupId == Ogre::RENDER_QUEUE_SKIES_EARLY || queueGroupId == Ogre::RENDER_QUEUE_SKIES_LATE || queueGroupId == + &skipThisInvocation) + { + if ((queueGroupId == Ogre::RENDER_QUEUE_SKIES_EARLY || queueGroupId == Ogre::RENDER_QUEUE_SKIES_LATE || + queueGroupId == - (Ogre::RENDER_QUEUE_SKIES_EARLY + 2)) - && mActive) - { - mRttManager->mHydrax->getCamera()->disableCustomNearClipPlane(); - Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mRttManager->mHydrax->getCamera()->getProjectionMatrixRS()); - } - } + (Ogre::RENDER_QUEUE_SKIES_EARLY + 2)) && + mActive) + { + mRttManager->mHydrax->getCamera()->disableCustomNearClipPlane(); + Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix( + mRttManager->mHydrax->getCamera()->getProjectionMatrixRS()); + } + } - void RttManager::CReflectionListener::CReflectionQueueListener::renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool + void RttManager::CReflectionListener::CReflectionQueueListener::renderQueueEnded(Ogre::uint8 queueGroupId, + const Ogre::String &invocation, + bool - &skipThisInvocation) - { - if ((queueGroupId == Ogre::RENDER_QUEUE_SKIES_EARLY || queueGroupId == Ogre::RENDER_QUEUE_SKIES_LATE || queueGroupId == + &skipThisInvocation) + { + if ((queueGroupId == Ogre::RENDER_QUEUE_SKIES_EARLY || queueGroupId == Ogre::RENDER_QUEUE_SKIES_LATE || + queueGroupId == - (Ogre::RENDER_QUEUE_SKIES_EARLY + 2)) - && mActive) - { - mRttManager->mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_REFLECTION]); - Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mRttManager->mHydrax->getCamera()->getProjectionMatrixRS()); - } - } + (Ogre::RENDER_QUEUE_SKIES_EARLY + 2)) && + mActive) + { + mRttManager->mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_REFLECTION]); + Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix( + mRttManager->mHydrax->getCamera()->getProjectionMatrixRS()); + } + } - void RttManager::CRefractionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CRefractionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; mHydrax->getMesh()->getEntity()->setVisible(false); - - if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) - { - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_REFRACTION]->normal = -mRttManager->mPlanes[RTT_REFRACTION]->normal; - mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - } - else - { - mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0,mHydrax->getPlanesError(),0); - } + + if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) + { + if (mHydrax->_isCurrentFrameUnderwater()) + { + mRttManager->mPlanes[RTT_REFRACTION]->normal = -mRttManager->mPlanes[RTT_REFRACTION]->normal; + mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); + } + else + { + mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0, mHydrax->getPlanesError(), 0); + } mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_REFRACTION]); - } + } } - void RttManager::CRefractionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CRefractionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; mHydrax->getMesh()->getEntity()->setVisible(true); - if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) - { - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_REFRACTION]->normal = -mRttManager->mPlanes[RTT_REFRACTION]->normal; - mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0,+mHydrax->getPlanesError(),0); - } - else - { - mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - } + if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) + { + if (mHydrax->_isCurrentFrameUnderwater()) + { + mRttManager->mPlanes[RTT_REFRACTION]->normal = -mRttManager->mPlanes[RTT_REFRACTION]->normal; + mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0, +mHydrax->getPlanesError(), 0); + } + else + { + mRttManager->mPlanes[RTT_REFRACTION]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); + } mHydrax->getCamera()->disableCustomNearClipPlane(); - } + } } - void RttManager::CDepthListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CDepthListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; - Ogre::SceneManager::MovableObjectIterator EntityIterator = - mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); - Ogre::Entity* CurrentEntity; - unsigned int k; + Ogre::SceneManager::MovableObjectIterator EntityIterator = mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); + Ogre::Entity * CurrentEntity; + unsigned int k; mMaterials.empty(); while (EntityIterator.hasMoreElements()) { - CurrentEntity = static_cast(EntityIterator.peekNextValue()); + CurrentEntity = static_cast(EntityIterator.peekNextValue()); - for(k = 0; k < CurrentEntity->getNumSubEntities(); k++) - { - mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName()); + for (k = 0; k < CurrentEntity->getNumSubEntities(); k++) + { + mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName()); - CurrentEntity->getSubEntity(k)->setMaterialName(mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_DEPTH)->getName()); - } + CurrentEntity->getSubEntity(k)->setMaterialName( + mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_DEPTH)->getName()); + } EntityIterator.moveNext(); } - if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) - { - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_DEPTH]->normal = -mRttManager->mPlanes[RTT_DEPTH]->normal; - mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - } - else - { - mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0,mHydrax->getPlanesError(),0); - mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_DEPTH]); - } - } - - if (mHydrax->_isCurrentFrameUnderwater()) - { + if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) + { + if (mHydrax->_isCurrentFrameUnderwater()) + { + mRttManager->mPlanes[RTT_DEPTH]->normal = -mRttManager->mPlanes[RTT_DEPTH]->normal; + mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); + } + else + { + mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0, mHydrax->getPlanesError(), 0); + mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_DEPTH]); + } + } + + if (mHydrax->_isCurrentFrameUnderwater()) + { mHydrax->getMesh()->getEntity()->setVisible(true); - mHydrax->getMesh()->getEntity()->setMaterialName( - mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_SIMPLE_RED)-> - getName()); - mHydrax->getMesh()->getEntity()->setRenderQueueGroup(Ogre::RENDER_QUEUE_SKIES_EARLY); - mHydrax->getGodRaysManager()->setVisible(true); - } - else - { - mHydrax->getMesh()->getEntity()->setVisible(false); - } + mHydrax->getMesh()->getEntity()->setMaterialName( + mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_SIMPLE_RED)->getName()); + mHydrax->getMesh()->getEntity()->setRenderQueueGroup(Ogre::RENDER_QUEUE_SKIES_EARLY); + mHydrax->getGodRaysManager()->setVisible(true); + } + else + { + mHydrax->getMesh()->getEntity()->setVisible(false); + } } - void RttManager::CDepthListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CDepthListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; - Ogre::SceneManager::MovableObjectIterator EntityIterator = - mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); - Ogre::Entity* CurrentEntity; - unsigned int k; + Ogre::SceneManager::MovableObjectIterator EntityIterator = mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); + Ogre::Entity * CurrentEntity; + unsigned int k; while (EntityIterator.hasMoreElements()) { - CurrentEntity = static_cast(EntityIterator.peekNextValue()); + CurrentEntity = static_cast(EntityIterator.peekNextValue()); - for(k = 0; k < CurrentEntity->getNumSubEntities(); k++) - { - CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front()); + for (k = 0; k < CurrentEntity->getNumSubEntities(); k++) + { + CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front()); - mMaterials.pop(); - } + mMaterials.pop(); + } EntityIterator.moveNext(); } mHydrax->getMesh()->getEntity()->setVisible(true); - mHydrax->getGodRaysManager()->setVisible(false); - mHydrax->getMesh()->getEntity()->setRenderQueueGroup(Ogre::RENDER_QUEUE_1); + mHydrax->getGodRaysManager()->setVisible(false); + mHydrax->getMesh()->getEntity()->setRenderQueueGroup(Ogre::RENDER_QUEUE_1); if (Ogre::Math::Abs(mHydrax->getPosition().y - mHydrax->getCamera()->getDerivedPosition().y) > mHydrax->getPlanesError()) - { - if (mHydrax->_isCurrentFrameUnderwater()) - { - mRttManager->mPlanes[RTT_DEPTH]->normal = -mRttManager->mPlanes[RTT_DEPTH]->normal; - mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0,+mHydrax->getPlanesError(),0); - } - else - { - mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - } + { + if (mHydrax->_isCurrentFrameUnderwater()) + { + mRttManager->mPlanes[RTT_DEPTH]->normal = -mRttManager->mPlanes[RTT_DEPTH]->normal; + mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0, +mHydrax->getPlanesError(), 0); + } + else + { + mRttManager->mPlanes[RTT_DEPTH]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); + } mHydrax->getCamera()->disableCustomNearClipPlane(); - } + } } - void RttManager::CDepthReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CDepthReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; - mHydrax->getMesh()->getEntity()->setVisible(false); + mHydrax->getMesh()->getEntity()->setVisible(false); - Ogre::SceneManager::MovableObjectIterator EntityIterator = - mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); - Ogre::Entity* CurrentEntity; - unsigned int k; + Ogre::SceneManager::MovableObjectIterator EntityIterator = mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); + Ogre::Entity * CurrentEntity; + unsigned int k; mMaterials.empty(); while (EntityIterator.hasMoreElements()) { - CurrentEntity = static_cast(EntityIterator.peekNextValue()); + CurrentEntity = static_cast(EntityIterator.peekNextValue()); - for(k = 0; k < CurrentEntity->getNumSubEntities(); k++) - { - mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName()); + for (k = 0; k < CurrentEntity->getNumSubEntities(); k++) + { + mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName()); - CurrentEntity->getSubEntity(k)->setMaterialName(mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_DEPTH)->getName()); - } + CurrentEntity->getSubEntity(k)->setMaterialName( + mHydrax->getMaterialManager()->getMaterial(MaterialManager::MAT_DEPTH)->getName()); + } EntityIterator.moveNext(); } - mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->translate(0,-mHydrax->getPlanesError(),0); - + mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->translate(0, -mHydrax->getPlanesError(), 0); + bool IsInUnderwaterError = false; - if (mHydrax->getCamera()->getDerivedPosition().y > mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->getPosition().y) - { - mCameraPlaneDiff = 0; - IsInUnderwaterError = true; - } - else - { - mCameraPlaneDiff = 0; - } + if (mHydrax->getCamera()->getDerivedPosition().y > + mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->getPosition().y) + { + mCameraPlaneDiff = 0; + IsInUnderwaterError = true; + } + else + { + mCameraPlaneDiff = 0; + } mHydrax->getCamera()->enableReflection(mRttManager->mPlanes[RTT_DEPTH_REFLECTION]); - if (!IsInUnderwaterError) - { - mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_DEPTH_REFLECTION]); - } + if (!IsInUnderwaterError) { mHydrax->getCamera()->enableCustomNearClipPlane(mRttManager->mPlanes[RTT_DEPTH_REFLECTION]); } } - void RttManager::CDepthReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CDepthReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - Hydrax *mHydrax = mRttManager->mHydrax; + Hydrax *mHydrax = mRttManager->mHydrax; - Ogre::SceneManager::MovableObjectIterator EntityIterator = - mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); - Ogre::Entity* CurrentEntity; - unsigned int k; + Ogre::SceneManager::MovableObjectIterator EntityIterator = mHydrax->getSceneManager()->getMovableObjectIterator("Entity"); + Ogre::Entity * CurrentEntity; + unsigned int k; while (EntityIterator.hasMoreElements()) { - CurrentEntity = static_cast(EntityIterator.peekNextValue()); + CurrentEntity = static_cast(EntityIterator.peekNextValue()); - for(k = 0; k < CurrentEntity->getNumSubEntities(); k++) - { - CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front()); + for (k = 0; k < CurrentEntity->getNumSubEntities(); k++) + { + CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front()); - mMaterials.pop(); - } + mMaterials.pop(); + } EntityIterator.moveNext(); } mHydrax->getMesh()->getEntity()->setVisible(true); - if (mCameraPlaneDiff != 0) - { - mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->translate(0,mCameraPlaneDiff,0); - } - - mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->translate(0,mHydrax->getPlanesError(),0); + if (mCameraPlaneDiff != 0) + { mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->translate(0, mCameraPlaneDiff, 0); } + + mRttManager->mPlanes[RTT_DEPTH_REFLECTION]->getParentNode()->translate(0, mHydrax->getPlanesError(), 0); mHydrax->getCamera()->disableReflection(); mHydrax->getCamera()->disableCustomNearClipPlane(); } - void RttManager::CGPUNormalMapListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CGPUNormalMapListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - mOldMaterialName = mRttManager->mHydrax->getMesh()->getMaterialName(); - mRttManager->mHydrax->getMesh()->setMaterialName(mRttManager->mHydrax->getGPUNormalMapManager()->getNormalMapMaterial()->getName()); + mOldMaterialName = mRttManager->mHydrax->getMesh()->getMaterialName(); + mRttManager->mHydrax->getMesh()->setMaterialName( + mRttManager->mHydrax->getGPUNormalMapManager()->getNormalMapMaterial()->getName()); - Ogre::SceneManager *mSceneMgr = mRttManager->mHydrax->getSceneManager(); + Ogre::SceneManager *mSceneMgr = mRttManager->mHydrax->getSceneManager(); - // Render only the Hydrax mesh(Ogre::RENDER_QUEUE_1) - mSceneMgr->clearSpecialCaseRenderQueues(); + // Render only the Hydrax mesh(Ogre::RENDER_QUEUE_1) + mSceneMgr->clearSpecialCaseRenderQueues(); mSceneMgr->addSpecialCaseRenderQueue(Ogre::RENDER_QUEUE_1); mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_INCLUDE); } - void RttManager::CGPUNormalMapListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + void RttManager::CGPUNormalMapListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { - mRttManager->mHydrax->getMesh()->setMaterialName(mOldMaterialName); + mRttManager->mHydrax->getMesh()->setMaterialName(mOldMaterialName); - Ogre::SceneManager *mSceneMgr = mRttManager->mHydrax->getSceneManager(); + Ogre::SceneManager *mSceneMgr = mRttManager->mHydrax->getSceneManager(); - // Render all - mSceneMgr->clearSpecialCaseRenderQueues(); - mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); + // Render all + mSceneMgr->clearSpecialCaseRenderQueues(); + mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); } -} +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/RttManager.h b/source/main/gfx/hydrax/RttManager.h index 1bab78ced6..8f5931688c 100644 --- a/source/main/gfx/hydrax/RttManager.h +++ b/source/main/gfx/hydrax/RttManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,492 +25,482 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_RttManager_H_ #define _Hydrax_RttManager_H_ -#include "Prerequisites.h" - #include "Enums.h" #include "Help.h" +#include "Prerequisites.h" namespace Hydrax { - class Hydrax; - - /** Rtt's manager class - */ - class RttManager - { - public: - /** Rtt enumeration - */ - enum RttType - { - RTT_REFLECTION = 0, - RTT_REFRACTION = 1, - RTT_DEPTH = 2, - RTT_DEPTH_REFLECTION = 3, - RTT_DEPTH_AIP = 4, - RTT_GPU_NORMAL_MAP = 5 - }; - - /** Bits per channel - */ - enum BitsPerChannel - { - BPC_8 = 8, - BPC_16 = 16, - BPC_32 = 32 - }; - - /** Number of channels - */ - enum NumberOfChannels - { - NOC_1 = 1, - NOC_2 = 2, - NOC_3 = 3, - NOC_4 = 4 - }; - - /** Rtt options struct - */ - struct RttOptions - { - /// Texture names - Ogre::String Name; - /// Size; Size(0,0) to get main viewport size - Size Size_; - /// Number of channels - NumberOfChannels NumberOfChannels_; - /// Bits per channel - BitsPerChannel BitsPerChannel_; - }; - - /** Rtt Listener class - */ - class RttListener - { - public: - /** Funtion that is called before the Rtt will render - @param Rtt Rtt type - @remarks We've to override it - */ - virtual void preRenderTargetUpdate(const RttType& Rtt){}; - - /** Funtion that is called after the Rtt will render - @param Rtt Rtt type - @remarks We've to override it - */ - virtual void postRenderTargetUpdate(const RttType& Rtt){}; - }; - - /** Constructor - @param h Hydrax parent pointer - */ - RttManager(Hydrax *h); - - /** Destructor - */ - ~RttManager(); - - /** Initialize a RTT - @param Rtt Rtt to initialize - @remarks If the RTT is already created, it will be recreated. - */ - void initialize(const RttType& Rtt); - - /** Removes a RTT - @param Rtt Rtt to remove - */ - void remove(const RttType& Rtt); - - /** Remove all RttManager resources - @remarks After calling removeAll(), calling initialize(...) is allowed. - */ - void removeAll(); - - /** Get RTT texture name - @param Rtt Rtt type - @return Rtt texture name - */ - inline const Ogre::String& getRttName(RttType Rtt) const - { - return mRttOptions[static_cast(Rtt)].Name; - } - - /** Get Rtt texture - @param Rtt Rtt type - @return Rtt texture - */ - inline Ogre::TexturePtr getTexture(RttType Rtt) - { - return mTextures[static_cast(Rtt)]; - } - - /** Get planes scene node - @return Planes scene node - */ - inline Ogre::SceneNode* getPlanesSceneNode() - { - return mPlanesSceneNode; - } - - /** Get Rtt plane - @param Rtt Rtt type - @return Rtt plane - */ - inline Ogre::MovablePlane* getPlane(RttType Rtt) - { - return mPlanes[static_cast(Rtt)]; - } - - /** Get Rtt texture size - @param Rtt Rtt type - @return Rtt texture size - */ - inline const Size& getTextureSize(const RttType& Rtt) const - { - return mRttOptions[static_cast(Rtt)].Size_; - } - - /** Set Rtt texture size - @param Rtt Rtt type - @param S New texture size (0,0 -> get main viewport size) - */ - void setTextureSize(const RttType& Rtt, const Size& S); - - /** Set Rtt textures size - @param S New texture size (0,0 -> get main viewport size) - */ - void setTexturesSize(const Size& S); - - /** Get pixel format - @param Rtt Rtt type - @return Rtt pixel format - */ - const Ogre::PixelFormat getPixelFormat(const RttType& Rtt) const; - - /** Set number of channels - @Rtt Rtt type - @NOC Number of channels - */ - inline void setNumberOfChannels(const RttType& Rtt, const NumberOfChannels& NOC) - { - mRttOptions[Rtt].NumberOfChannels_ = NOC; - - if (!getTexture(Rtt).isNull()) - { - initialize(Rtt); - } - } - - /** Get number of channels - @Rtt Rtt type - @return Number of channels - */ - inline const NumberOfChannels& getNumberOfChannels(const RttType& Rtt) const - { - return mRttOptions[Rtt].NumberOfChannels_; - } - - /** Set bits per channel - @Rtt Rtt type - @BPC Bits per channel - */ - inline void setBitsPerChannel(const RttType& Rtt, const BitsPerChannel& BPC) - { - mRttOptions[Rtt].BitsPerChannel_ = BPC; - - if (!getTexture(Rtt).isNull()) - { - initialize(Rtt); - } - } - - /** Get bits per channels - @Rtt Rtt type - @return Bits per channel - */ - inline const BitsPerChannel& getBitsPerChannel(const RttType& Rtt) const - { - return mRttOptions[Rtt].BitsPerChannel_; - } - - /** Get Rtt options - @Rtt Rtt type - @return RttOptions - */ - inline const RttOptions& getRttOptions(const RttType& Rtt) const - { - return mRttOptions[Rtt]; - } - - /** Set reflection displacement error - @param ReflectionDisplacementError Range [0.05, ~2], increase if you experiment - reflection issues when the camera is near to the water. - */ - void setReflectionDisplacementError(const Ogre::Real& ReflectionDisplacementError) - { - mReflectionDisplacementError = ReflectionDisplacementError; - } - - /** Get reflection displacement error - @return Reflection displacement error - */ - inline const Ogre::Real& getReflectionDisplacementError() const - { - return mReflectionDisplacementError; - } - - /** Set disable reflection custom near clip plane render queues - @param DisableReflectionCustomNearClipPlaneRenderQueues Disable reflection custom near clip plane render queues - */ - inline void setDisableReflectionCustomNearCliplPlaneRenderQueues(const std::vector& DisableReflectionCustomNearClipPlaneRenderQueues) - { - mDisableReflectionCustomNearClipPlaneRenderQueues = DisableReflectionCustomNearClipPlaneRenderQueues; - } - - /** Get disable reflection custom near clip plane render queues - @return Disable reflection custom near clip plane render queues - */ - inline const std::vector& getDisableReflectionCustomNearClipPlaneRenderQueues() - { - return mDisableReflectionCustomNearClipPlaneRenderQueues; - } - - /** Add Rtt listener - @param l Rtt listener - */ - inline void addRttListener(RttListener *l) - { - mRttListeners.push_back(l); - } - - /** Remove Rtt listener - @param l Rtt listener to be removed - @param releaseMemory delete Rtt listener pointer? - */ - void removeRttListener(RttListener *l, const bool& releaseMemory = true); - - /** Remove all Rtt listeners - @param releaseMemory delete Rtt listeners pointers? - */ - void removeAllRttListeners(const bool& releaseMemory = true); - - private: - /** RttManager::CRefractionListener class - */ - class CRefractionListener : public Ogre::RenderTargetListener - { - public: - /// Rtt manager pointer - RttManager* mRttManager; - - /// Camera.y - Plane.y difference - Ogre::Real mCameraPlaneDiff; - - /** Funtion that is called before the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - /** Funtion that is called after the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - }; - - /** RttManager::CReflectionListener class - */ - class CReflectionListener : public Ogre::RenderTargetListener - { - public: - /** RttManager::CReflectionListener::CReflectionQueueListener class - Used for avoid near clip plane clipping during the reflection Rtt - */ - class CReflectionQueueListener : public Ogre::RenderQueueListener - { - public: - /** Called at the start of the queue - */ - void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); - - /** Called on the end of the queue - */ - void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) ; - - /// Rtt manager pointer - RttManager* mRttManager; - /// Is the reflection Rtt active? - bool mActive; - }; - - /// CReflectionQueueListener - CReflectionQueueListener mCReflectionQueueListener; - - /// Rtt manager pointer - RttManager* mRttManager; - - /// Camera.y - Plane.y difference - Ogre::Real mCameraPlaneDiff; - - /** Funtion that is called before the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - /** Funtion that is called after the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - }; - - /** RttManager::CDepthListener class - */ - class CDepthListener : public Ogre::RenderTargetListener - { - public: - /// Rtt manager pointer - RttManager* mRttManager; - - /// std::string to store entity's original materials name - std::queue mMaterials; - - /// Camera.y - Plane.y difference - Ogre::Real mCameraPlaneDiff; - - /** Funtion that is called before the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - /** Funtion that is called after the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - }; - - /** RttManager::CDepthReflectionListener class - */ - class CDepthReflectionListener : public Ogre::RenderTargetListener - { - public: - /// Rtt manager pointer - RttManager* mRttManager; - - /// std::string to store entity's original materials name - std::queue mMaterials; - - /// Camera.y - Plane.y difference - Ogre::Real mCameraPlaneDiff; - - /** Funtion that is called before the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - /** Funtion that is called after the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - }; - - /** RttManager::CGPUNormalMapListener class - */ - class CGPUNormalMapListener : public Ogre::RenderTargetListener - { - public: - /// Rtt manager pointer - RttManager* mRttManager; - - /// Old Hydrax mesh material name - Ogre::String mOldMaterialName; - - /** Funtion that is called before the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - /** Funtion that is called after the Rtt will render - @param evt Ogre RenderTargetEvent - @remarks We've to override it - */ - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - }; - - /** Initialize the Rtt - @param Rtt Rtt type - @param PlaneNormal Rtt plane normal - @param BackgroundColour Background colour - @param RenderSky True for sky rendering and false for not - @param RTListener Render target listener - @param MaterialScheme Ogre::String("") for none - @param ShadowsEnabled Enable shadows in this RTT - */ - void _initializeRtt(const RttType& Rtt, const Ogre::Vector3& PlaneNormal, - const Ogre::ColourValue& BackgroundColour, const bool& RenderSky, - Ogre::RenderTargetListener* RTListener, const Ogre::String& MaterialScheme = "", - const bool& ShadowsEnabled = true); - - /** Find a render queue in a render queue list - @param l Render queue list - @param rq Render queue to find - @return true If the render queue to find is in the list, false if not - */ - inline const bool _isRenderQueueInList(const std::vector& l, const Ogre::RenderQueueGroupID& rq) - { - for (std::vector::const_iterator i = l.begin(); i != l.end(); i++) - { - if ((*i) == rq) - { - return true; - } - } - - return false; - } - - /** Invoke Rtt Listeners - @param Rtt Rtt type - @param pre true for Pre render target update, false for Post render target update - */ - void _invokeRttListeners(const RttType& Rtt, const bool& pre); - - /// Hydrax parent pointer - Hydrax *mHydrax; + class Hydrax; + + /** Rtt's manager class + */ + class RttManager + { + public: + /** Rtt enumeration + */ + enum RttType + { + RTT_REFLECTION = 0, + RTT_REFRACTION = 1, + RTT_DEPTH = 2, + RTT_DEPTH_REFLECTION = 3, + RTT_DEPTH_AIP = 4, + RTT_GPU_NORMAL_MAP = 5 + }; + + /** Bits per channel + */ + enum BitsPerChannel + { + BPC_8 = 8, + BPC_16 = 16, + BPC_32 = 32 + }; + + /** Number of channels + */ + enum NumberOfChannels + { + NOC_1 = 1, + NOC_2 = 2, + NOC_3 = 3, + NOC_4 = 4 + }; + + /** Rtt options struct + */ + struct RttOptions + { + /// Texture names + Ogre::String Name; + /// Size; Size(0,0) to get main viewport size + Size Size_; + /// Number of channels + NumberOfChannels NumberOfChannels_; + /// Bits per channel + BitsPerChannel BitsPerChannel_; + }; + + /** Rtt Listener class + */ + class RttListener + { + public: + /** Funtion that is called before the Rtt will render + @param Rtt Rtt type + @remarks We've to override it + */ + virtual void preRenderTargetUpdate(const RttType &Rtt){}; + + /** Funtion that is called after the Rtt will render + @param Rtt Rtt type + @remarks We've to override it + */ + virtual void postRenderTargetUpdate(const RttType &Rtt){}; + }; + + /** Constructor + @param h Hydrax parent pointer + */ + RttManager(Hydrax *h); + + /** Destructor + */ + ~RttManager(); + + /** Initialize a RTT + @param Rtt Rtt to initialize + @remarks If the RTT is already created, it will be recreated. + */ + void initialize(const RttType &Rtt); + + /** Removes a RTT + @param Rtt Rtt to remove + */ + void remove(const RttType &Rtt); + + /** Remove all RttManager resources + @remarks After calling removeAll(), calling initialize(...) is allowed. + */ + void removeAll(); + + /** Get RTT texture name + @param Rtt Rtt type + @return Rtt texture name + */ + inline const Ogre::String &getRttName(RttType Rtt) const + { + return mRttOptions[static_cast(Rtt)].Name; + } + + /** Get Rtt texture + @param Rtt Rtt type + @return Rtt texture + */ + inline Ogre::TexturePtr getTexture(RttType Rtt) + { + return mTextures[static_cast(Rtt)]; + } + + /** Get planes scene node + @return Planes scene node + */ + inline Ogre::SceneNode *getPlanesSceneNode() + { + return mPlanesSceneNode; + } + + /** Get Rtt plane + @param Rtt Rtt type + @return Rtt plane + */ + inline Ogre::MovablePlane *getPlane(RttType Rtt) + { + return mPlanes[static_cast(Rtt)]; + } + + /** Get Rtt texture size + @param Rtt Rtt type + @return Rtt texture size + */ + inline const Size &getTextureSize(const RttType &Rtt) const + { + return mRttOptions[static_cast(Rtt)].Size_; + } + + /** Set Rtt texture size + @param Rtt Rtt type + @param S New texture size (0,0 -> get main viewport size) + */ + void setTextureSize(const RttType &Rtt, const Size &S); + + /** Set Rtt textures size + @param S New texture size (0,0 -> get main viewport size) + */ + void setTexturesSize(const Size &S); + + /** Get pixel format + @param Rtt Rtt type + @return Rtt pixel format + */ + const Ogre::PixelFormat getPixelFormat(const RttType &Rtt) const; + + /** Set number of channels + @Rtt Rtt type + @NOC Number of channels + */ + inline void setNumberOfChannels(const RttType &Rtt, const NumberOfChannels &NOC) + { + mRttOptions[Rtt].NumberOfChannels_ = NOC; + + if (!getTexture(Rtt).isNull()) { initialize(Rtt); } + } + + /** Get number of channels + @Rtt Rtt type + @return Number of channels + */ + inline const NumberOfChannels &getNumberOfChannels(const RttType &Rtt) const + { + return mRttOptions[Rtt].NumberOfChannels_; + } + + /** Set bits per channel + @Rtt Rtt type + @BPC Bits per channel + */ + inline void setBitsPerChannel(const RttType &Rtt, const BitsPerChannel &BPC) + { + mRttOptions[Rtt].BitsPerChannel_ = BPC; + + if (!getTexture(Rtt).isNull()) { initialize(Rtt); } + } + + /** Get bits per channels + @Rtt Rtt type + @return Bits per channel + */ + inline const BitsPerChannel &getBitsPerChannel(const RttType &Rtt) const + { + return mRttOptions[Rtt].BitsPerChannel_; + } + + /** Get Rtt options + @Rtt Rtt type + @return RttOptions + */ + inline const RttOptions &getRttOptions(const RttType &Rtt) const + { + return mRttOptions[Rtt]; + } + + /** Set reflection displacement error + @param ReflectionDisplacementError Range [0.05, ~2], increase if you experiment + reflection issues when the camera is near to the water. + */ + void setReflectionDisplacementError(const Ogre::Real &ReflectionDisplacementError) + { + mReflectionDisplacementError = ReflectionDisplacementError; + } + + /** Get reflection displacement error + @return Reflection displacement error + */ + inline const Ogre::Real &getReflectionDisplacementError() const + { + return mReflectionDisplacementError; + } + + /** Set disable reflection custom near clip plane render queues + @param DisableReflectionCustomNearClipPlaneRenderQueues Disable reflection custom near clip plane render queues + */ + inline void setDisableReflectionCustomNearCliplPlaneRenderQueues( + const std::vector &DisableReflectionCustomNearClipPlaneRenderQueues) + { + mDisableReflectionCustomNearClipPlaneRenderQueues = DisableReflectionCustomNearClipPlaneRenderQueues; + } + + /** Get disable reflection custom near clip plane render queues + @return Disable reflection custom near clip plane render queues + */ + inline const std::vector &getDisableReflectionCustomNearClipPlaneRenderQueues() + { + return mDisableReflectionCustomNearClipPlaneRenderQueues; + } + + /** Add Rtt listener + @param l Rtt listener + */ + inline void addRttListener(RttListener *l) + { + mRttListeners.push_back(l); + } + + /** Remove Rtt listener + @param l Rtt listener to be removed + @param releaseMemory delete Rtt listener pointer? + */ + void removeRttListener(RttListener *l, const bool &releaseMemory = true); + + /** Remove all Rtt listeners + @param releaseMemory delete Rtt listeners pointers? + */ + void removeAllRttListeners(const bool &releaseMemory = true); + + private: + /** RttManager::CRefractionListener class + */ + class CRefractionListener : public Ogre::RenderTargetListener + { + public: + /// Rtt manager pointer + RttManager *mRttManager; + + /// Camera.y - Plane.y difference + Ogre::Real mCameraPlaneDiff; + + /** Funtion that is called before the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + + /** Funtion that is called after the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + }; + + /** RttManager::CReflectionListener class + */ + class CReflectionListener : public Ogre::RenderTargetListener + { + public: + /** RttManager::CReflectionListener::CReflectionQueueListener class + Used for avoid near clip plane clipping during the reflection Rtt + */ + class CReflectionQueueListener : public Ogre::RenderQueueListener + { + public: + /** Called at the start of the queue + */ + void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); + + /** Called on the end of the queue + */ + void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); + + /// Rtt manager pointer + RttManager *mRttManager; + /// Is the reflection Rtt active? + bool mActive; + }; + + /// CReflectionQueueListener + CReflectionQueueListener mCReflectionQueueListener; + + /// Rtt manager pointer + RttManager *mRttManager; + + /// Camera.y - Plane.y difference + Ogre::Real mCameraPlaneDiff; + + /** Funtion that is called before the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + + /** Funtion that is called after the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + }; + + /** RttManager::CDepthListener class + */ + class CDepthListener : public Ogre::RenderTargetListener + { + public: + /// Rtt manager pointer + RttManager *mRttManager; + + /// std::string to store entity's original materials name + std::queue mMaterials; + + /// Camera.y - Plane.y difference + Ogre::Real mCameraPlaneDiff; + + /** Funtion that is called before the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + + /** Funtion that is called after the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + }; + + /** RttManager::CDepthReflectionListener class + */ + class CDepthReflectionListener : public Ogre::RenderTargetListener + { + public: + /// Rtt manager pointer + RttManager *mRttManager; + + /// std::string to store entity's original materials name + std::queue mMaterials; + + /// Camera.y - Plane.y difference + Ogre::Real mCameraPlaneDiff; + + /** Funtion that is called before the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + + /** Funtion that is called after the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + }; + + /** RttManager::CGPUNormalMapListener class + */ + class CGPUNormalMapListener : public Ogre::RenderTargetListener + { + public: + /// Rtt manager pointer + RttManager *mRttManager; + + /// Old Hydrax mesh material name + Ogre::String mOldMaterialName; + + /** Funtion that is called before the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + + /** Funtion that is called after the Rtt will render + @param evt Ogre RenderTargetEvent + @remarks We've to override it + */ + void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); + }; + + /** Initialize the Rtt + @param Rtt Rtt type + @param PlaneNormal Rtt plane normal + @param BackgroundColour Background colour + @param RenderSky True for sky rendering and false for not + @param RTListener Render target listener + @param MaterialScheme Ogre::String("") for none + @param ShadowsEnabled Enable shadows in this RTT + */ + void _initializeRtt(const RttType &Rtt, const Ogre::Vector3 &PlaneNormal, const Ogre::ColourValue &BackgroundColour, + const bool &RenderSky, Ogre::RenderTargetListener *RTListener, + const Ogre::String &MaterialScheme = "", const bool &ShadowsEnabled = true); + + /** Find a render queue in a render queue list + @param l Render queue list + @param rq Render queue to find + @return true If the render queue to find is in the list, false if not + */ + inline const bool _isRenderQueueInList(const std::vector &l, const Ogre::RenderQueueGroupID &rq) + { + for (std::vector::const_iterator i = l.begin(); i != l.end(); i++) + { + if ((*i) == rq) { return true; } + } + + return false; + } + + /** Invoke Rtt Listeners + @param Rtt Rtt type + @param pre true for Pre render target update, false for Post render target update + */ + void _invokeRttListeners(const RttType &Rtt, const bool &pre); + + /// Hydrax parent pointer + Hydrax *mHydrax; /// SceneNode to attach our planes Ogre::SceneNode *mPlanesSceneNode; - /// Rtt planes vector - Ogre::MovablePlane *mPlanes[6]; + /// Rtt planes vector + Ogre::MovablePlane *mPlanes[6]; - /// Rtt textures vector - Ogre::TexturePtr mTextures[6]; - /// Rtt options - RttOptions mRttOptions[6]; + /// Rtt textures vector + Ogre::TexturePtr mTextures[6]; + /// Rtt options + RttOptions mRttOptions[6]; - /// Rtt listener objects + /// Rtt listener objects CReflectionListener mReflectionListener; - CRefractionListener mRefractionListener; - CDepthListener mDepthListener; - CDepthReflectionListener mDepthReflectionListener; - CGPUNormalMapListener mGPUNormalMapListener; - - /// Render queues to exclude of the reflection custom near clip plane - std::vector mDisableReflectionCustomNearClipPlaneRenderQueues; - /// Rtt listeners - std::vector mRttListeners; - - /// Reflection displacement error, range [0.01, ~2] - Ogre::Real mReflectionDisplacementError; - }; -}; + CRefractionListener mRefractionListener; + CDepthListener mDepthListener; + CDepthReflectionListener mDepthReflectionListener; + CGPUNormalMapListener mGPUNormalMapListener; + + /// Render queues to exclude of the reflection custom near clip plane + std::vector mDisableReflectionCustomNearClipPlaneRenderQueues; + /// Rtt listeners + std::vector mRttListeners; + + /// Reflection displacement error, range [0.01, ~2] + Ogre::Real mReflectionDisplacementError; + }; +}; // namespace Hydrax #endif diff --git a/source/main/gfx/hydrax/SimpleGrid.cpp b/source/main/gfx/hydrax/SimpleGrid.cpp index 8153f0e68f..d54d3bb293 100644 --- a/source/main/gfx/hydrax/SimpleGrid.cpp +++ b/source/main/gfx/hydrax/SimpleGrid.cpp @@ -24,426 +24,401 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include -namespace Hydrax{namespace Module +namespace Hydrax { - Mesh::VertexType _SG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode& NormalMode) - { - if (NormalMode == MaterialManager::NM_VERTEX) - { - return Mesh::VT_POS_NORM; - } - - // NM_RTT - return Mesh::VT_POS; - } - - Ogre::String _SG_getNormalModeString(const MaterialManager::NormalMode& NormalMode) - { - if (NormalMode == MaterialManager::NM_VERTEX) - { - return "Vertex"; - } - - return "Rtt"; - } - - SimpleGrid::SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode) - : Module("SimpleGrid" + _SG_getNormalModeString(NormalMode), - n, Mesh::Options(256, Size(100), _SG_getVertexTypeFromNormalMode(NormalMode)), NormalMode) - , mHydrax(h) - , mVertices(0) - , mVerticesChoppyBuffer(0) - { - } - - SimpleGrid::SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode, const Options &Options) - : Module("SimpleGrid" + _SG_getNormalModeString(NormalMode), - n, Mesh::Options(Options.Complexity, Size(Options.MeshSize), _SG_getVertexTypeFromNormalMode(NormalMode)), NormalMode) - , mHydrax(h) - , mVertices(0) - , mVerticesChoppyBuffer(0) - { - setOptions(Options); - } - - SimpleGrid::~SimpleGrid() - { - remove(); - - HydraxLOG(getName() + " destroyed."); - } - - void SimpleGrid::setOptions(const Options &Options) - { - mMeshOptions.MeshSize = Options.MeshSize; - mMeshOptions.MeshStrength = Options.Strength; - mMeshOptions.MeshComplexity = Options.Complexity; - - mHydrax->getMesh()->setOptions(mMeshOptions); - mHydrax->_setStrength(Options.Strength); - - if (isCreated()) - { - if (Options.Complexity != mOptions.Complexity || Options.ChoppyWaves != Options.ChoppyWaves) - { - remove(); - mOptions = Options; - create(); - - if (mNormalMode == MaterialManager::NM_RTT) - { - if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) - { - HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); - } - } - - Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); - mHydrax->getMesh()->remove(); - - mHydrax->getMesh()->setOptions(getMeshOptions()); - mHydrax->getMesh()->setMaterialName(MaterialNameTmp); - mHydrax->getMesh()->create(); - - return; - } - - mOptions = Options; - - int v, u; - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(v=0; v(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; - Vertices[v*mOptions.Complexity + u].z = (static_cast(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; - } - } - - if (mOptions.ChoppyWaves && mVerticesChoppyBuffer) - { - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - mVerticesChoppyBuffer[i] = Vertices[i]; - } - } - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(v=0; v(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; - Vertices[v*mOptions.Complexity + u].z = (static_cast(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; - } - } - } - - return; - } - - mOptions = Options; - } - - void SimpleGrid::create() - { - HydraxLOG("Creating " + getName() + " module."); - - Module::create(); - - int v, u; - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - mVertices = new Mesh::POS_NORM_VERTEX[mOptions.Complexity*mOptions.Complexity]; - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(v=0; v(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; - Vertices[v*mOptions.Complexity + u].z = (static_cast(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; - - Vertices[v*mOptions.Complexity + u].nx = 0; - Vertices[v*mOptions.Complexity + u].ny = -1; - Vertices[v*mOptions.Complexity + u].nz = 0; - } - } - - if (mOptions.ChoppyWaves) - { - mVerticesChoppyBuffer = new Mesh::POS_NORM_VERTEX[mOptions.Complexity*mOptions.Complexity]; - - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - mVerticesChoppyBuffer[i] = Vertices[i]; - } - } - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - mVertices = new Mesh::POS_VERTEX[mOptions.Complexity*mOptions.Complexity]; - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(v=0; v(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; - Vertices[v*mOptions.Complexity + u].z = (static_cast(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; - } - } - } - - HydraxLOG(getName() + " created."); - } - - void SimpleGrid::remove() - { - if (!isCreated()) - { - return; - } - - Module::remove(); - - if (mVertices) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - delete [] static_cast(mVertices); - mVertices = 0; - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - delete [] static_cast(mVertices); - mVertices = 0; - } - } - - if (mVerticesChoppyBuffer) - { - delete [] mVerticesChoppyBuffer; - } - } - - void SimpleGrid::saveCfg(Ogre::String &Data) - { - Module::saveCfg(Data); - - Data += CfgFileManager::_getCfgString("SG_Complexity", mOptions.Complexity); - Data += CfgFileManager::_getCfgString("SG_MeshSize", mOptions.MeshSize); - Data += CfgFileManager::_getCfgString("SG_Strength", mOptions.Strength); - Data += CfgFileManager::_getCfgString("SG_Smooth", mOptions.Smooth); - Data += CfgFileManager::_getCfgString("SG_ChoppyWaves", mOptions.ChoppyWaves); - Data += CfgFileManager::_getCfgString("SG_ChoppyStrength", mOptions.ChoppyStrength); Data += "\n"; - } - - bool SimpleGrid::loadCfg(Ogre::ConfigFile &CfgFile) - { - if (!Module::loadCfg(CfgFile)) - { - return false; - } - - setOptions( - Options(CfgFileManager::_getIntValue(CfgFile, "SG_Complexity"), - CfgFileManager::_getSizeValue(CfgFile, "SG_MeshSize"), - CfgFileManager::_getFloatValue(CfgFile, "SG_Strength"), - CfgFileManager::_getBoolValue(CfgFile, "PG_Smooth"), - CfgFileManager::_getBoolValue(CfgFile, "PG_ChoppyWaves"), - CfgFileManager::_getFloatValue(CfgFile, "PG_ChoopyStrength"))); - - return true; - } - - void SimpleGrid::update(const Ogre::Real &timeSinceLastFrame) - { - if (!isCreated()) - { - return; - } - - Module::update(timeSinceLastFrame); - - // Update heigths - - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - if (mOptions.ChoppyWaves) - { - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - Vertices[i] = mVerticesChoppyBuffer[i]; - Vertices[i].y = mNoise->getValue(Vertices[i].x, Vertices[i].z) * mOptions.Strength; - } - } - else - { - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - Vertices[i].y = mNoise->getValue(Vertices[i].x, Vertices[i].z) * mOptions.Strength; - } - } - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - // For object-space to world-space conversion - // RTT normals calculation needs world-space coords - Ogre::Vector3 p = Ogre::Vector3(0,0,0); - Ogre::Affine3 mWorldMatrix; - mWorldMatrix = mHydrax->getMesh()->getEntity()->getParentSceneNode()->_getFullTransform(); - for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) - { - p.x = Vertices[i].x; - p.y = 0; - p.z = Vertices[i].z; - - // Calculate the world-space position - mWorldMatrix*(p); - - Vertices[i].y = mNoise->getValue(p.x, p.z) * mOptions.Strength; - } - } - - // Smooth the heightdata - if (mOptions.Smooth) - { - if (getNormalMode() == MaterialManager::NM_VERTEX) - { - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(int v=1; v<(mOptions.Complexity-1); v++) - { - for(int u=1; u<(mOptions.Complexity-1); u++) - { - Vertices[v*mOptions.Complexity + u].y = - 0.2f * - (Vertices[v *mOptions.Complexity + u ].y + - Vertices[v *mOptions.Complexity + (u+1)].y + - Vertices[v *mOptions.Complexity + (u-1)].y + - Vertices[(v+1)*mOptions.Complexity + u ].y + - Vertices[(v-1)*mOptions.Complexity + u ].y); - } - } - } - else if (getNormalMode() == MaterialManager::NM_RTT) - { - Mesh::POS_VERTEX* Vertices = static_cast(mVertices); - - for(int v=1; v<(mOptions.Complexity-1); v++) - { - for(int u=1; u<(mOptions.Complexity-1); u++) - { - Vertices[v*mOptions.Complexity + u].y = - 0.2f * - (Vertices[v *mOptions.Complexity + u ].y + - Vertices[v *mOptions.Complexity + (u+1)].y + - Vertices[v *mOptions.Complexity + (u-1)].y + - Vertices[(v+1)*mOptions.Complexity + u ].y + - Vertices[(v-1)*mOptions.Complexity + u ].y); - } - } - } - } - - // Update normals - _calculeNormals(); - - // Perform choppy waves - _performChoppyWaves(); - - // Upload geometry changes - mHydrax->getMesh()->updateGeometry(mOptions.Complexity*mOptions.Complexity, mVertices); - } - - void SimpleGrid::_calculeNormals() - { - if (getNormalMode() != MaterialManager::NM_VERTEX) - { - return; - } - - int v, u; - Ogre::Vector3 vec1, vec2, normal; - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(v=1; v<(mOptions.Complexity-1); v++) - { - for(u=1; u<(mOptions.Complexity-1); u++) - { - vec1 = Ogre::Vector3( - Vertices[v*mOptions.Complexity + u + 1].x-Vertices[v*mOptions.Complexity + u - 1].x, - Vertices[v*mOptions.Complexity + u + 1].y-Vertices[v*mOptions.Complexity + u - 1].y, - Vertices[v*mOptions.Complexity + u + 1].z-Vertices[v*mOptions.Complexity + u - 1].z); - - vec2 = Ogre::Vector3( - Vertices[(v+1)*mOptions.Complexity + u].x - Vertices[(v-1)*mOptions.Complexity + u].x, - Vertices[(v+1)*mOptions.Complexity + u].y - Vertices[(v-1)*mOptions.Complexity + u].y, - Vertices[(v+1)*mOptions.Complexity + u].z - Vertices[(v-1)*mOptions.Complexity + u].z); - - normal = vec2.crossProduct(vec1); - - Vertices[v*mOptions.Complexity + u].nx = normal.x; - Vertices[v*mOptions.Complexity + u].ny = normal.y; - Vertices[v*mOptions.Complexity + u].nz = normal.z; - } - } - } - - void SimpleGrid::_performChoppyWaves() - { - if (getNormalMode() != MaterialManager::NM_VERTEX || !mOptions.ChoppyWaves) - { - return; - } - - int v, u, - Underwater = 1; - - if (mHydrax->_isCurrentFrameUnderwater()) - { - Underwater = -1; - } - - Mesh::POS_NORM_VERTEX* Vertices = static_cast(mVertices); - - for(v=1; v<(mOptions.Complexity-1); v++) - { - for(u=1; u<(mOptions.Complexity-1); u++) - { - Vertices[v*mOptions.Complexity + u].x += Vertices[v*mOptions.Complexity + u].nx * mOptions.ChoppyStrength * Underwater; - Vertices[v*mOptions.Complexity + u].z += Vertices[v*mOptions.Complexity + u].nz * mOptions.ChoppyStrength * Underwater; - } - } - } - - float SimpleGrid::getHeigth(const Ogre::Vector2 &Position) - { - if (getNormalMode() != MaterialManager::NM_RTT) - { - Ogre::Vector2 RelativePos = mHydrax->getMesh()->getGridPosition(Position); - - RelativePos.x *= mOptions.MeshSize.Width; - RelativePos.y *= mOptions.MeshSize.Height; - - return mHydrax->getPosition().y + mNoise->getValue(RelativePos.x, RelativePos.y)*mOptions.Strength; - } - else // RTT Normals calculations works with world-space coords - { - return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y)*mOptions.Strength; - } - } -}} + namespace Module + { + Mesh::VertexType _SG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode &NormalMode) + { + if (NormalMode == MaterialManager::NM_VERTEX) { return Mesh::VT_POS_NORM; } + + // NM_RTT + return Mesh::VT_POS; + } + + Ogre::String _SG_getNormalModeString(const MaterialManager::NormalMode &NormalMode) + { + if (NormalMode == MaterialManager::NM_VERTEX) { return "Vertex"; } + + return "Rtt"; + } + + SimpleGrid::SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode) + : Module("SimpleGrid" + _SG_getNormalModeString(NormalMode), n, + Mesh::Options(256, Size(100), _SG_getVertexTypeFromNormalMode(NormalMode)), NormalMode), + mHydrax(h), mVertices(0), mVerticesChoppyBuffer(0) + { + } + + SimpleGrid::SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode, const Options &Options) + : Module("SimpleGrid" + _SG_getNormalModeString(NormalMode), n, + Mesh::Options(Options.Complexity, Size(Options.MeshSize), _SG_getVertexTypeFromNormalMode(NormalMode)), + NormalMode), + mHydrax(h), mVertices(0), mVerticesChoppyBuffer(0) + { + setOptions(Options); + } + + SimpleGrid::~SimpleGrid() + { + remove(); + + HydraxLOG(getName() + " destroyed."); + } + + void SimpleGrid::setOptions(const Options &Options) + { + mMeshOptions.MeshSize = Options.MeshSize; + mMeshOptions.MeshStrength = Options.Strength; + mMeshOptions.MeshComplexity = Options.Complexity; + + mHydrax->getMesh()->setOptions(mMeshOptions); + mHydrax->_setStrength(Options.Strength); + + if (isCreated()) + { + if (Options.Complexity != mOptions.Complexity || Options.ChoppyWaves != Options.ChoppyWaves) + { + remove(); + mOptions = Options; + create(); + + if (mNormalMode == MaterialManager::NM_RTT) + { + if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) + { HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); } + } + + Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); + mHydrax->getMesh()->remove(); + + mHydrax->getMesh()->setOptions(getMeshOptions()); + mHydrax->getMesh()->setMaterialName(MaterialNameTmp); + mHydrax->getMesh()->create(); + + return; + } + + mOptions = Options; + + int v, u; + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (v = 0; v < mOptions.Complexity; v++) + { + for (u = 0; u < mOptions.Complexity; u++) + { + Vertices[v * mOptions.Complexity + u].x = + (static_cast(v) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Width; + Vertices[v * mOptions.Complexity + u].z = + (static_cast(u) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Height; + } + } + + if (mOptions.ChoppyWaves && mVerticesChoppyBuffer) + { + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + mVerticesChoppyBuffer[i] = Vertices[i]; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (v = 0; v < mOptions.Complexity; v++) + { + for (u = 0; u < mOptions.Complexity; u++) + { + Vertices[v * mOptions.Complexity + u].x = + (static_cast(v) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Width; + Vertices[v * mOptions.Complexity + u].z = + (static_cast(u) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Height; + } + } + } + + return; + } + + mOptions = Options; + } + + void SimpleGrid::create() + { + HydraxLOG("Creating " + getName() + " module."); + + Module::create(); + + int v, u; + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + mVertices = new Mesh::POS_NORM_VERTEX[mOptions.Complexity * mOptions.Complexity]; + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (v = 0; v < mOptions.Complexity; v++) + { + for (u = 0; u < mOptions.Complexity; u++) + { + Vertices[v * mOptions.Complexity + u].x = + (static_cast(v) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Width; + Vertices[v * mOptions.Complexity + u].z = + (static_cast(u) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Height; + + Vertices[v * mOptions.Complexity + u].nx = 0; + Vertices[v * mOptions.Complexity + u].ny = -1; + Vertices[v * mOptions.Complexity + u].nz = 0; + } + } + + if (mOptions.ChoppyWaves) + { + mVerticesChoppyBuffer = new Mesh::POS_NORM_VERTEX[mOptions.Complexity * mOptions.Complexity]; + + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + mVerticesChoppyBuffer[i] = Vertices[i]; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + mVertices = new Mesh::POS_VERTEX[mOptions.Complexity * mOptions.Complexity]; + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (v = 0; v < mOptions.Complexity; v++) + { + for (u = 0; u < mOptions.Complexity; u++) + { + Vertices[v * mOptions.Complexity + u].x = + (static_cast(v) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Width; + Vertices[v * mOptions.Complexity + u].z = + (static_cast(u) / (mOptions.Complexity - 1)) * mOptions.MeshSize.Height; + } + } + } + + HydraxLOG(getName() + " created."); + } + + void SimpleGrid::remove() + { + if (!isCreated()) { return; } + + Module::remove(); + + if (mVertices) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + delete[] static_cast(mVertices); + mVertices = 0; + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + delete[] static_cast(mVertices); + mVertices = 0; + } + } + + if (mVerticesChoppyBuffer) { delete[] mVerticesChoppyBuffer; } + } + + void SimpleGrid::saveCfg(Ogre::String &Data) + { + Module::saveCfg(Data); + + Data += CfgFileManager::_getCfgString("SG_Complexity", mOptions.Complexity); + Data += CfgFileManager::_getCfgString("SG_MeshSize", mOptions.MeshSize); + Data += CfgFileManager::_getCfgString("SG_Strength", mOptions.Strength); + Data += CfgFileManager::_getCfgString("SG_Smooth", mOptions.Smooth); + Data += CfgFileManager::_getCfgString("SG_ChoppyWaves", mOptions.ChoppyWaves); + Data += CfgFileManager::_getCfgString("SG_ChoppyStrength", mOptions.ChoppyStrength); + Data += "\n"; + } + + bool SimpleGrid::loadCfg(Ogre::ConfigFile &CfgFile) + { + if (!Module::loadCfg(CfgFile)) { return false; } + + setOptions(Options( + CfgFileManager::_getIntValue(CfgFile, "SG_Complexity"), CfgFileManager::_getSizeValue(CfgFile, "SG_MeshSize"), + CfgFileManager::_getFloatValue(CfgFile, "SG_Strength"), CfgFileManager::_getBoolValue(CfgFile, "PG_Smooth"), + CfgFileManager::_getBoolValue(CfgFile, "PG_ChoppyWaves"), + CfgFileManager::_getFloatValue(CfgFile, "PG_ChoopyStrength"))); + + return true; + } + + void SimpleGrid::update(const Ogre::Real &timeSinceLastFrame) + { + if (!isCreated()) { return; } + + Module::update(timeSinceLastFrame); + + // Update heigths + + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + if (mOptions.ChoppyWaves) + { + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + Vertices[i] = mVerticesChoppyBuffer[i]; + Vertices[i].y = mNoise->getValue(Vertices[i].x, Vertices[i].z) * mOptions.Strength; + } + } + else + { + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + Vertices[i].y = mNoise->getValue(Vertices[i].x, Vertices[i].z) * mOptions.Strength; + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + // For object-space to world-space conversion + // RTT normals calculation needs world-space coords + Ogre::Vector3 p = Ogre::Vector3(0, 0, 0); + Ogre::Affine3 mWorldMatrix; + mWorldMatrix = mHydrax->getMesh()->getEntity()->getParentSceneNode()->_getFullTransform(); + for (int i = 0; i < mOptions.Complexity * mOptions.Complexity; i++) + { + p.x = Vertices[i].x; + p.y = 0; + p.z = Vertices[i].z; + + // Calculate the world-space position + mWorldMatrix *(p); + + Vertices[i].y = mNoise->getValue(p.x, p.z) * mOptions.Strength; + } + } + + // Smooth the heightdata + if (mOptions.Smooth) + { + if (getNormalMode() == MaterialManager::NM_VERTEX) + { + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (int v = 1; v < (mOptions.Complexity - 1); v++) + { + for (int u = 1; u < (mOptions.Complexity - 1); u++) + { + Vertices[v * mOptions.Complexity + u].y = + 0.2f * + (Vertices[v * mOptions.Complexity + u].y + Vertices[v * mOptions.Complexity + (u + 1)].y + + Vertices[v * mOptions.Complexity + (u - 1)].y + Vertices[(v + 1) * mOptions.Complexity + u].y + + Vertices[(v - 1) * mOptions.Complexity + u].y); + } + } + } + else if (getNormalMode() == MaterialManager::NM_RTT) + { + Mesh::POS_VERTEX *Vertices = static_cast(mVertices); + + for (int v = 1; v < (mOptions.Complexity - 1); v++) + { + for (int u = 1; u < (mOptions.Complexity - 1); u++) + { + Vertices[v * mOptions.Complexity + u].y = + 0.2f * + (Vertices[v * mOptions.Complexity + u].y + Vertices[v * mOptions.Complexity + (u + 1)].y + + Vertices[v * mOptions.Complexity + (u - 1)].y + Vertices[(v + 1) * mOptions.Complexity + u].y + + Vertices[(v - 1) * mOptions.Complexity + u].y); + } + } + } + } + + // Update normals + _calculeNormals(); + + // Perform choppy waves + _performChoppyWaves(); + + // Upload geometry changes + mHydrax->getMesh()->updateGeometry(mOptions.Complexity * mOptions.Complexity, mVertices); + } + + void SimpleGrid::_calculeNormals() + { + if (getNormalMode() != MaterialManager::NM_VERTEX) { return; } + + int v, u; + Ogre::Vector3 vec1, vec2, normal; + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (v = 1; v < (mOptions.Complexity - 1); v++) + { + for (u = 1; u < (mOptions.Complexity - 1); u++) + { + vec1 = + Ogre::Vector3(Vertices[v * mOptions.Complexity + u + 1].x - Vertices[v * mOptions.Complexity + u - 1].x, + Vertices[v * mOptions.Complexity + u + 1].y - Vertices[v * mOptions.Complexity + u - 1].y, + Vertices[v * mOptions.Complexity + u + 1].z - Vertices[v * mOptions.Complexity + u - 1].z); + + vec2 = Ogre::Vector3( + Vertices[(v + 1) * mOptions.Complexity + u].x - Vertices[(v - 1) * mOptions.Complexity + u].x, + Vertices[(v + 1) * mOptions.Complexity + u].y - Vertices[(v - 1) * mOptions.Complexity + u].y, + Vertices[(v + 1) * mOptions.Complexity + u].z - Vertices[(v - 1) * mOptions.Complexity + u].z); + + normal = vec2.crossProduct(vec1); + + Vertices[v * mOptions.Complexity + u].nx = normal.x; + Vertices[v * mOptions.Complexity + u].ny = normal.y; + Vertices[v * mOptions.Complexity + u].nz = normal.z; + } + } + } + + void SimpleGrid::_performChoppyWaves() + { + if (getNormalMode() != MaterialManager::NM_VERTEX || !mOptions.ChoppyWaves) { return; } + + int v, u, Underwater = 1; + + if (mHydrax->_isCurrentFrameUnderwater()) { Underwater = -1; } + + Mesh::POS_NORM_VERTEX *Vertices = static_cast(mVertices); + + for (v = 1; v < (mOptions.Complexity - 1); v++) + { + for (u = 1; u < (mOptions.Complexity - 1); u++) + { + Vertices[v * mOptions.Complexity + u].x += + Vertices[v * mOptions.Complexity + u].nx * mOptions.ChoppyStrength * Underwater; + Vertices[v * mOptions.Complexity + u].z += + Vertices[v * mOptions.Complexity + u].nz * mOptions.ChoppyStrength * Underwater; + } + } + } + + float SimpleGrid::getHeigth(const Ogre::Vector2 &Position) + { + if (getNormalMode() != MaterialManager::NM_RTT) + { + Ogre::Vector2 RelativePos = mHydrax->getMesh()->getGridPosition(Position); + + RelativePos.x *= mOptions.MeshSize.Width; + RelativePos.y *= mOptions.MeshSize.Height; + + return mHydrax->getPosition().y + mNoise->getValue(RelativePos.x, RelativePos.y) * mOptions.Strength; + } + else // RTT Normals calculations works with world-space coords + { + return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y) * mOptions.Strength; + } + } + } // namespace Module +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/SimpleGrid.h b/source/main/gfx/hydrax/SimpleGrid.h index 7048ab99a7..ba88719b69 100644 --- a/source/main/gfx/hydrax/SimpleGrid.h +++ b/source/main/gfx/hydrax/SimpleGrid.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,170 +25,154 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_Modules_SimpleGrid_H_ #define _Hydrax_Modules_SimpleGrid_H_ - - #include "Hydrax.h" #include "Mesh.h" #include "Module.h" -namespace Hydrax{ namespace Module +namespace Hydrax { - /** Hydrax simple grid module - */ - class SimpleGrid : public Module - { - public: - /** Struct wich contains Hydrax simple grid module options - */ - struct Options - { - /// Projected grid complexity (N*N) - int Complexity; - /// Size - Size MeshSize; - /// Strength - float Strength; - /// Smooth - bool Smooth; - /// Choppy waves - bool ChoppyWaves; - /// Choppy waves strength - float ChoppyStrength; - - /** Default constructor - */ - Options() - : Complexity(256) - , MeshSize(Size(100)) - , Strength(32.5f) - , Smooth(false) - , ChoppyWaves(true) - , ChoppyStrength(0.065f) - { - } - - /** Constructor - @param _Complexity Projected grid complexity - @param _MeshSize Water mesh size - */ - Options(const int &_Complexity, - const Size &_MeshSize) - : Complexity(_Complexity) - , MeshSize(_MeshSize) - , Strength(32.5f) - , Smooth(false) - , ChoppyWaves(true) - , ChoppyStrength(0.065f) - { - } - - /** Constructor - @param _Complexity Projected grid complexity - @param _MeshSize Water mesh size - @param _Strength Perlin noise strength - @param _Smooth Smooth vertex? - @param _ChoppyWaves Choppy waves enabled? Note: Only with Materialmanager::NM_VERTEX normal mode. - @param _ChoppyStrength Choppy waves strength Note: Only with Materialmanager::NM_VERTEX normal mode. - */ - Options(const int &_Complexity, - const Size &_MeshSize, - const float &_Strength, - const bool &_Smooth, - const bool &_ChoppyWaves, - const float &_ChoppyStrength) - : Complexity(_Complexity) - , MeshSize(_MeshSize) - , Strength(_Strength) - , Smooth(_Smooth) - , ChoppyWaves(_ChoppyWaves) - , ChoppyStrength(_ChoppyStrength) - { - } - }; - - /** Constructor - @param h Hydrax manager pointer - @param n Hydrax noise module - @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT - */ - SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode); - - /** Constructor - @param h Hydrax manager pointer - @param n Hydrax noise module - @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT - @param Options Perlin options - */ - SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode& NormalMode, const Options &Options); - - /** Destructor - */ - ~SimpleGrid(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Set options - @param Options Options - */ - void setOptions(const Options &Options); - - /** Save config - @param Data String reference - */ - void saveCfg(Ogre::String &Data); - - /** Load config - @param CgfFile Ogre::ConfigFile reference - @return True if is the correct module config - */ - bool loadCfg(Ogre::ConfigFile &CfgFile); - - /** Get the current heigth at a especified world-space point - @param Position X/Z World position - @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 - */ - float getHeigth(const Ogre::Vector2 &Position); - - /** Get current options - @return Current options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - private: - /** Calcule current normals - */ - void _calculeNormals(); - - /** Perform choppy waves - */ - void _performChoppyWaves(); - - /// Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX) - void *mVertices; - - /// Use it to store vertex positions when choppy displacement is enabled - Mesh::POS_NORM_VERTEX* mVerticesChoppyBuffer; - - /// Our projected grid options - Options mOptions; - - /// Our Hydrax pointer - Hydrax* mHydrax; - }; -}} + namespace Module + { + /** Hydrax simple grid module + */ + class SimpleGrid : public Module + { + public: + /** Struct wich contains Hydrax simple grid module options + */ + struct Options + { + /// Projected grid complexity (N*N) + int Complexity; + /// Size + Size MeshSize; + /// Strength + float Strength; + /// Smooth + bool Smooth; + /// Choppy waves + bool ChoppyWaves; + /// Choppy waves strength + float ChoppyStrength; + + /** Default constructor + */ + Options() + : Complexity(256), MeshSize(Size(100)), Strength(32.5f), Smooth(false), ChoppyWaves(true), + ChoppyStrength(0.065f) + { + } + + /** Constructor + @param _Complexity Projected grid complexity + @param _MeshSize Water mesh size + */ + Options(const int &_Complexity, const Size &_MeshSize) + : Complexity(_Complexity), MeshSize(_MeshSize), Strength(32.5f), Smooth(false), ChoppyWaves(true), + ChoppyStrength(0.065f) + { + } + + /** Constructor + @param _Complexity Projected grid complexity + @param _MeshSize Water mesh size + @param _Strength Perlin noise strength + @param _Smooth Smooth vertex? + @param _ChoppyWaves Choppy waves enabled? Note: Only with Materialmanager::NM_VERTEX normal mode. + @param _ChoppyStrength Choppy waves strength Note: Only with Materialmanager::NM_VERTEX normal mode. + */ + Options(const int &_Complexity, const Size &_MeshSize, const float &_Strength, const bool &_Smooth, + const bool &_ChoppyWaves, const float &_ChoppyStrength) + : Complexity(_Complexity), MeshSize(_MeshSize), Strength(_Strength), Smooth(_Smooth), + ChoppyWaves(_ChoppyWaves), ChoppyStrength(_ChoppyStrength) + { + } + }; + + /** Constructor + @param h Hydrax manager pointer + @param n Hydrax noise module + @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT + */ + SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode); + + /** Constructor + @param h Hydrax manager pointer + @param n Hydrax noise module + @param NormalMode Switch between MaterialManager::NM_VERTEX and Materialmanager::NM_RTT + @param Options Perlin options + */ + SimpleGrid(Hydrax *h, Noise::Noise *n, const MaterialManager::NormalMode &NormalMode, const Options &Options); + + /** Destructor + */ + ~SimpleGrid(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Set options + @param Options Options + */ + void setOptions(const Options &Options); + + /** Save config + @param Data String reference + */ + void saveCfg(Ogre::String &Data); + + /** Load config + @param CgfFile Ogre::ConfigFile reference + @return True if is the correct module config + */ + bool loadCfg(Ogre::ConfigFile &CfgFile); + + /** Get the current heigth at a especified world-space point + @param Position X/Z World position + @return Heigth at the given position in y-World coordinates, if it's outside of the water return -1 + */ + float getHeigth(const Ogre::Vector2 &Position); + + /** Get current options + @return Current options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + private: + /** Calcule current normals + */ + void _calculeNormals(); + + /** Perform choppy waves + */ + void _performChoppyWaves(); + + /// Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX) + void *mVertices; + + /// Use it to store vertex positions when choppy displacement is enabled + Mesh::POS_NORM_VERTEX *mVerticesChoppyBuffer; + + /// Our projected grid options + Options mOptions; + + /// Our Hydrax pointer + Hydrax *mHydrax; + }; + } // namespace Module +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/TextureManager.cpp b/source/main/gfx/hydrax/TextureManager.cpp index 44ff99f8a0..848e064f99 100644 --- a/source/main/gfx/hydrax/TextureManager.cpp +++ b/source/main/gfx/hydrax/TextureManager.cpp @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -22,93 +22,87 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to -------------------------------------------------------------------------------- */ -#include - #include +#include namespace Hydrax { - TextureManager::TextureManager(Hydrax *h) - : mCreated(false) - , mHydrax(h) - { - for (int k = 0; k < 1; k++) - { - mTextures[k].setNull(); - } + TextureManager::TextureManager(Hydrax *h) : mCreated(false), mHydrax(h) + { + for (int k = 0; k < 1; k++) + { + mTextures[k].setNull(); + } - mTextureNames[0] = "HydraxNormalMap"; - } + mTextureNames[0] = "HydraxNormalMap"; + } - TextureManager::~TextureManager() - { - remove(); - } + TextureManager::~TextureManager() + { + remove(); + } - void TextureManager::create(const Size &Size) - { - remove(); + void TextureManager::create(const Size &Size) + { + remove(); - for (int k = 0; k < 1; k++) - { - _createTexture(mTextures[k], mTextureNames[k], Size); - } + for (int k = 0; k < 1; k++) + { + _createTexture(mTextures[k], mTextureNames[k], Size); + } - mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); + mHydrax->getMaterialManager()->reload(MaterialManager::MAT_WATER); - mCreated = true; - } + mCreated = true; + } - void TextureManager::remove() - { - if (!mCreated) - { - return; - } + void TextureManager::remove() + { + if (!mCreated) { return; } - for (int k = 0; k < 1; k++) - { - Ogre::TextureManager::getSingleton().remove(mTextureNames[k]); - mTextures[k].setNull(); - } + for (int k = 0; k < 1; k++) + { + Ogre::TextureManager::getSingleton().remove(mTextureNames[k]); + mTextures[k].setNull(); + } - mCreated = false; - } + mCreated = false; + } - bool TextureManager::_updateNormalMap(Image &Image) - { - if (!mCreated) - { - HydraxLOG("Error in TextureManager::_updateNormalMap, create() does not called."); + bool TextureManager::_updateNormalMap(Image &Image) + { + if (!mCreated) + { + HydraxLOG("Error in TextureManager::_updateNormalMap, create() does not called."); - return false; - } + return false; + } - if (Image.getType() != Image::TYPE_RGB) - { - HydraxLOG("Error in TextureManager::_updateNormalMap, Image type isn't correct."); + if (Image.getType() != Image::TYPE_RGB) + { + HydraxLOG("Error in TextureManager::_updateNormalMap, Image type isn't correct."); - return false; - } + return false; + } - Ogre::TexturePtr &Texture = getTexture(TEX_NORMAL_ID); + Ogre::TexturePtr &Texture = getTexture(TEX_NORMAL_ID); - Size ImageSize = Image.getSize(); + Size ImageSize = Image.getSize(); - if (Texture->getWidth() != ImageSize.Width || - Texture->getHeight() != ImageSize.Height) - { - HydraxLOG("Error in TextureManager::update, Update size doesn't correspond to " + getTextureName(TEX_NORMAL_ID) + " texture size"); + if (Texture->getWidth() != ImageSize.Width || Texture->getHeight() != ImageSize.Height) + { + HydraxLOG("Error in TextureManager::update, Update size doesn't correspond to " + getTextureName(TEX_NORMAL_ID) + + " texture size"); - return false; - } + return false; + } - Ogre::HardwarePixelBufferSharedPtr pixelBuffer = Texture->getBuffer(); + Ogre::HardwarePixelBufferSharedPtr pixelBuffer = Texture->getBuffer(); pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL); - const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock(); + const Ogre::PixelBox &pixelBox = pixelBuffer->getCurrentLock(); - Ogre::uint8* pDest = static_cast(pixelBox.data); + Ogre::uint8 *pDest = static_cast(pixelBox.data); int x, y; @@ -116,42 +110,37 @@ namespace Hydrax { for (y = 0; y < ImageSize.Height; y++) { - *pDest++ = Image.getValue(x,y,2); // B - *pDest++ = Image.getValue(x,y,1); // G - *pDest++ = Image.getValue(x,y,0); // R - *pDest++ = 255; // A + *pDest++ = Image.getValue(x, y, 2); // B + *pDest++ = Image.getValue(x, y, 1); // G + *pDest++ = Image.getValue(x, y, 0); // R + *pDest++ = 255; // A } } pixelBuffer->unlock(); - return true; - } - - bool TextureManager::_createTexture(Ogre::TexturePtr &Texture, const Ogre::String &Name, const Size &Size) - { - try - { - Ogre::TextureManager::getSingleton().remove(Name); - - Texture = Ogre::TextureManager::getSingleton(). - createManual(Name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - Size.Width, Size.Height, - 0, - Ogre::PF_BYTE_BGRA, - Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); - - Texture->load(); - } - catch (Ogre::Exception &e) - { - HydraxLOG(e.getFullDescription()); - - return false; - } - - return true; - } -} + return true; + } + + bool TextureManager::_createTexture(Ogre::TexturePtr &Texture, const Ogre::String &Name, const Size &Size) + { + try + { + Ogre::TextureManager::getSingleton().remove(Name); + + Texture = Ogre::TextureManager::getSingleton().createManual( + Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, Size.Width, Size.Height, 0, + Ogre::PF_BYTE_BGRA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + + Texture->load(); + } + catch (Ogre::Exception &e) + { + HydraxLOG(e.getFullDescription()); + + return false; + } + + return true; + } +} // namespace Hydrax diff --git a/source/main/gfx/hydrax/TextureManager.h b/source/main/gfx/hydrax/TextureManager.h index 47d58dab58..6c76ee2209 100644 --- a/source/main/gfx/hydrax/TextureManager.h +++ b/source/main/gfx/hydrax/TextureManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,115 +25,111 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _Hydrax_TextureManager_H_ #define _Hydrax_TextureManager_H_ -#include "Prerequisites.h" - #include "Enums.h" #include "Image.h" +#include "Prerequisites.h" namespace Hydrax { - class Hydrax; - - /** Class for manager Normal maps. - */ - class TextureManager - { - public: - /** Textures enumeration - */ - enum TexturesID - { - // Normal map - TEX_NORMAL_ID = 0 - }; - - /** Constructor - @param h Hydrax main pointer - */ - TextureManager(Hydrax* h); - - /** Destructor - */ - ~TextureManager(); - - /** Create height and normal map textures - @param Size Textures's size - */ - void create(const Size &Size); - - /** Remove textures - */ - void remove(); - - /** Update - @param Id Texture's ID - @param Image Update image - @return false if something fails - @remarks If you need to update the texture with another way of data, - get the Ogre::TexturePtr and modify it directly. - Normal image will be Image::Type::TYPE_RGB [0,255] range - */ - inline bool update(const TexturesID &Id, Image &Image) - { - if (Id == TEX_NORMAL_ID) - { - return _updateNormalMap(Image); - } - - return false; - } - - /** Get texture - @param Id Texture Id ( TEX_NORMAL_ID ) - @return Ogre::TexturePtr - */ - inline Ogre::TexturePtr& getTexture(const TexturesID &Id) - { - return mTextures[static_cast(Id)]; - } - - /** Get texture's name - @param Id Texture Id ( TEX_NORMAL_ID ) - @return Texture's name - */ - inline const Ogre::String& getTextureName(const TexturesID &Id) const - { - return mTextureNames[static_cast(Id)]; - } - - private: - /** Create an Ogre::Texture - @param Texture Our Ogre::TexturePtr - @param Name Texture's name - @param Size Texture's size - @return false if there is a problem. - */ - bool _createTexture(Ogre::TexturePtr &Texture, const Ogre::String &Name, const Size &Size); - - /** Get an Ogre::TexturePtr - @param Name Texture's name - @return Our texture - */ - Ogre::TexturePtr _getTexture(const Ogre::String &Name); - - /** Update normal map - @param Image Update image - @return false if something fails - @remarks Image type will be Image::Type::TYPE_RGB - */ + class Hydrax; + + /** Class for manager Normal maps. + */ + class TextureManager + { + public: + /** Textures enumeration + */ + enum TexturesID + { + // Normal map + TEX_NORMAL_ID = 0 + }; + + /** Constructor + @param h Hydrax main pointer + */ + TextureManager(Hydrax *h); + + /** Destructor + */ + ~TextureManager(); + + /** Create height and normal map textures + @param Size Textures's size + */ + void create(const Size &Size); + + /** Remove textures + */ + void remove(); + + /** Update + @param Id Texture's ID + @param Image Update image + @return false if something fails + @remarks If you need to update the texture with another way of data, + get the Ogre::TexturePtr and modify it directly. + Normal image will be Image::Type::TYPE_RGB [0,255] range + */ + inline bool update(const TexturesID &Id, Image &Image) + { + if (Id == TEX_NORMAL_ID) { return _updateNormalMap(Image); } + + return false; + } + + /** Get texture + @param Id Texture Id ( TEX_NORMAL_ID ) + @return Ogre::TexturePtr + */ + inline Ogre::TexturePtr &getTexture(const TexturesID &Id) + { + return mTextures[static_cast(Id)]; + } + + /** Get texture's name + @param Id Texture Id ( TEX_NORMAL_ID ) + @return Texture's name + */ + inline const Ogre::String &getTextureName(const TexturesID &Id) const + { + return mTextureNames[static_cast(Id)]; + } + + private: + /** Create an Ogre::Texture + @param Texture Our Ogre::TexturePtr + @param Name Texture's name + @param Size Texture's size + @return false if there is a problem. + */ + bool _createTexture(Ogre::TexturePtr &Texture, const Ogre::String &Name, const Size &Size); + + /** Get an Ogre::TexturePtr + @param Name Texture's name + @return Our texture + */ + Ogre::TexturePtr _getTexture(const Ogre::String &Name); + + /** Update normal map + @param Image Update image + @return false if something fails + @remarks Image type will be Image::Type::TYPE_RGB + */ bool _updateNormalMap(Image &Image); - /// Our Ogre::TexturePtr array + /// Our Ogre::TexturePtr array Ogre::TexturePtr mTextures[1]; - /// Our Ogre::String array for store texture's names - Ogre::String mTextureNames[1]; + /// Our Ogre::String array for store texture's names + Ogre::String mTextureNames[1]; /// Have been created already called? bool mCreated; - /// Hydrax main pointer - Hydrax *mHydrax; - }; -} + /// Hydrax main pointer + Hydrax *mHydrax; + }; +} // namespace Hydrax #endif \ No newline at end of file diff --git a/source/main/gfx/hydrax/Wave.cpp b/source/main/gfx/hydrax/Wave.cpp index 551d5312d6..1a4c32fb1e 100644 --- a/source/main/gfx/hydrax/Wave.cpp +++ b/source/main/gfx/hydrax/Wave.cpp @@ -35,18 +35,13 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to using namespace Hydrax::Noise; -Wave::Wave(Ogre::Vector2 dir, float A, float T, float p) - : mTime(0) - , mDir(dir) - , mA(A) - , mT(T) - , mP(p) +Wave::Wave(Ogre::Vector2 dir, float A, float T, float p) : mTime(0), mDir(dir), mA(A), mT(T), mP(p) { mDir.normalise(); - mL = 1.5625f*mT*mT; - mC = 1.25f*sqrt(mL); - mF = 2.f*M_PI/mT; - mK = 2.f*M_PI/mL; + mL = 1.5625f * mT * mT; + mC = 1.25f * sqrt(mL); + mF = 2.f * M_PI / mT; + mK = 2.f * M_PI / mL; } Wave::~Wave() @@ -60,6 +55,6 @@ void Wave::update(const Ogre::Real &timeSinceLastFrame) float Wave::getValue(const float &x, const float &y) { - float X = mDir.x*x + mDir.y*y; - return mA * sin(mF*mTime - mK*X + mP); + float X = mDir.x * x + mDir.y * y; + return mA * sin(mF * mTime - mK * X + mP); } diff --git a/source/main/gfx/hydrax/Wave.h b/source/main/gfx/hydrax/Wave.h index 3ffa4b84cb..f04a1746b7 100644 --- a/source/main/gfx/hydrax/Wave.h +++ b/source/main/gfx/hydrax/Wave.h @@ -44,90 +44,109 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to // ---------------------------------------------------------------------------- #include "Perlin.h" -namespace Hydrax{ namespace Noise +namespace Hydrax { - -/** @class Wave Wave.h Noise/Wave/Wave.h - * @brief A wave defined by the direction, amplitude, period, and optionally phase. - */ -class Wave -{ -public: - /** Default constructor - * @param dir Direction of the wave. - * @param A Amplitude of the wave (m). - * @param T Period of the wave (s). - * @param p Phase of the wave (rad). - */ - Wave(Ogre::Vector2 dir, float A, float T, float p=0.f); - - /** Destructor - */ - ~Wave(); - - /** Call it each frame - @param timeSinceLastFrame Time since last frame(delta) - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Get the especified x/y noise value - @param x X Coord - @param y Y Coord - @return Noise value - @remarks range [~-0.2, ~0.2] - */ - float getValue(const float &x, const float &y); - - /** Returns direction of the wave. - * @return Direction. - */ - inline Ogre::Vector2 getDirection() const{return mDir;} - /** Returns amplitude of the wave. - * @return Amplitude. - */ - inline float getAmplitude() const{return mA;} - /** Returns period of the wave. - * @return Period. - */ - inline float getPeriod() const{return mT;} - /** Returns phase of the wave. - * @return Phase. - */ - inline float getPhase() const{return mP;} - /** Returns phase speed of the wave. - * @return Phase speed. - */ - inline float getSpeed() const{return mC;} - /** Returns longitude of the wave. - * @return Wave longitude. - */ - inline float getLongitude() const{return mL;} - -protected: - - -private: - /// Elapsed time - double mTime; - - /// Direction (must be normalised) - Ogre::Vector2 mDir; - /// Amplitude - float mA; - /// Period - float mT; - /// Phase - float mP; - /// Speed (calculated) - float mC; - /// Longitude (calculated) - float mL; - /// Angular frec. - float mF; - /// Dispersion factor - float mK; -}; - -}} // Namespace + namespace Noise + { + + /** @class Wave Wave.h Noise/Wave/Wave.h + * @brief A wave defined by the direction, amplitude, period, and optionally phase. + */ + class Wave + { + public: + /** Default constructor + * @param dir Direction of the wave. + * @param A Amplitude of the wave (m). + * @param T Period of the wave (s). + * @param p Phase of the wave (rad). + */ + Wave(Ogre::Vector2 dir, float A, float T, float p = 0.f); + + /** Destructor + */ + ~Wave(); + + /** Call it each frame + @param timeSinceLastFrame Time since last frame(delta) + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Get the especified x/y noise value + @param x X Coord + @param y Y Coord + @return Noise value + @remarks range [~-0.2, ~0.2] + */ + float getValue(const float &x, const float &y); + + /** Returns direction of the wave. + * @return Direction. + */ + inline Ogre::Vector2 getDirection() const + { + return mDir; + } + /** Returns amplitude of the wave. + * @return Amplitude. + */ + inline float getAmplitude() const + { + return mA; + } + /** Returns period of the wave. + * @return Period. + */ + inline float getPeriod() const + { + return mT; + } + /** Returns phase of the wave. + * @return Phase. + */ + inline float getPhase() const + { + return mP; + } + /** Returns phase speed of the wave. + * @return Phase speed. + */ + inline float getSpeed() const + { + return mC; + } + /** Returns longitude of the wave. + * @return Wave longitude. + */ + inline float getLongitude() const + { + return mL; + } + + protected: + private: + /// Elapsed time + double mTime; + + /// Direction (must be normalised) + Ogre::Vector2 mDir; + /// Amplitude + float mA; + /// Period + float mT; + /// Phase + float mP; + /// Speed (calculated) + float mC; + /// Longitude (calculated) + float mL; + /// Angular frec. + float mF; + /// Dispersion factor + float mK; + }; + + } // namespace Noise +} // namespace Hydrax #endif // WAVE_H_INCLUDED diff --git a/source/main/gfx/particle/ExtinguishableFireAffector.cpp b/source/main/gfx/particle/ExtinguishableFireAffector.cpp index 2a071829ae..bd17ec51b1 100644 --- a/source/main/gfx/particle/ExtinguishableFireAffector.cpp +++ b/source/main/gfx/particle/ExtinguishableFireAffector.cpp @@ -20,242 +20,228 @@ #ifdef USE_ANGELSCRIPT -#include "ExtinguishableFireAffector.h" + #include "ExtinguishableFireAffector.h" -#include -#include -#include -#include + #include "RoRPrerequisites.h" + #include "ScriptEngine.h" -#include "RoRPrerequisites.h" + #include + #include + #include + #include -#include "ScriptEngine.h" - - -namespace Ogre { - -// Instantiate statics -ExtinguishableFireAffector::CmdMiddlePoint ExtinguishableFireAffector::msMiddlePointCmd; -ExtinguishableFireAffector::CmdIntensity ExtinguishableFireAffector::msIntensityCmd; -ExtinguishableFireAffector::CmdMaxIntensity ExtinguishableFireAffector::msMaxIntensityCmd; -ExtinguishableFireAffector::CmdIntensityGrowth ExtinguishableFireAffector::msIntensityGrowthCmd; -ExtinguishableFireAffector::CmdRadius ExtinguishableFireAffector::msRadiusCmd; - -//----------------------------------------------------------------------- -ExtinguishableFireAffector::ExtinguishableFireAffector(ParticleSystem* psys) - : ParticleAffector(psys), mPsys(psys) +namespace Ogre { - mType = "ExtinguishableFire"; - // defaults - mMiddlePoint = Vector3::ZERO; - mRadius = 1.0; - mIntensity = 3000.0; - originalIntensity = mIntensity; - mIntensityGrowth = 10; - mMaxIntensity = 4000.0; - updateIntensityRequired = false; - firstFrame = true; - - // Set up parameters - if (createParamDictionary("ExtinguishableFireAffector")) + // Instantiate statics + ExtinguishableFireAffector::CmdMiddlePoint ExtinguishableFireAffector::msMiddlePointCmd; + ExtinguishableFireAffector::CmdIntensity ExtinguishableFireAffector::msIntensityCmd; + ExtinguishableFireAffector::CmdMaxIntensity ExtinguishableFireAffector::msMaxIntensityCmd; + ExtinguishableFireAffector::CmdIntensityGrowth ExtinguishableFireAffector::msIntensityGrowthCmd; + ExtinguishableFireAffector::CmdRadius ExtinguishableFireAffector::msRadiusCmd; + + //----------------------------------------------------------------------- + ExtinguishableFireAffector::ExtinguishableFireAffector(ParticleSystem *psys) : ParticleAffector(psys), mPsys(psys) { - addBaseParameters(); - // Add extra paramaters - ParamDictionary* dict = getParamDictionary(); - dict->addParameter(ParameterDef("middle_point", - "The middle point of the sphere on which water particles will interact.", - PT_VECTOR3), &msMiddlePointCmd); - dict->addParameter(ParameterDef("intensity", - "The amount of water particles that a fire can withstand before being extinguished.", - PT_REAL), &msIntensityCmd); - dict->addParameter(ParameterDef("max_intensity", - "The maximum intensity the fire can grow to.", - PT_REAL), &msMaxIntensityCmd); - dict->addParameter(ParameterDef("intensity_growth", - "The amount by which the intensity of the fire grows per second.", - PT_REAL), &msMaxIntensityCmd); - dict->addParameter(ParameterDef("radius", - "The radius of the sphere.", - PT_REAL), &msRadiusCmd); - } + mType = "ExtinguishableFire"; + + // defaults + mMiddlePoint = Vector3::ZERO; + mRadius = 1.0; + mIntensity = 3000.0; + originalIntensity = mIntensity; + mIntensityGrowth = 10; + mMaxIntensity = 4000.0; + updateIntensityRequired = false; + firstFrame = true; + + // Set up parameters + if (createParamDictionary("ExtinguishableFireAffector")) + { + addBaseParameters(); + // Add extra paramaters + ParamDictionary *dict = getParamDictionary(); + dict->addParameter(ParameterDef("middle_point", + "The middle point of the sphere on which water particles will interact.", PT_VECTOR3), + &msMiddlePointCmd); + dict->addParameter(ParameterDef("intensity", + "The amount of water particles that a fire can withstand before being extinguished.", + PT_REAL), + &msIntensityCmd); + dict->addParameter(ParameterDef("max_intensity", "The maximum intensity the fire can grow to.", PT_REAL), + &msMaxIntensityCmd); + dict->addParameter( + ParameterDef("intensity_growth", "The amount by which the intensity of the fire grows per second.", PT_REAL), + &msMaxIntensityCmd); + dict->addParameter(ParameterDef("radius", "The radius of the sphere.", PT_REAL), &msRadiusCmd); + } - // predefine objectInstanceName - objectInstanceName = "unknown"; + // predefine objectInstanceName + objectInstanceName = "unknown"; - ScriptEngine::getSingleton().fireEvent(objectInstanceName, mIntensity); -} -//----------------------------------------------------------------------- -ExtinguishableFireAffector::~ExtinguishableFireAffector() -{ - ScriptEngine::getSingleton().fireEvent(objectInstanceName, mIntensity); -} -//----------------------------------------------------------------------- -void ExtinguishableFireAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) -{ - if (firstFrame) - { - originalDimensions = Vector2(pSystem->getDefaultWidth(), pSystem->getDefaultHeight()); - originalIntensity = mIntensity; - firstFrame = false; + ScriptEngine::getSingleton().fireEvent(objectInstanceName, mIntensity); } - - if (mIntensity < 0) + //----------------------------------------------------------------------- + ExtinguishableFireAffector::~ExtinguishableFireAffector() { - // The fire is extinguished (normally, this particleSystem should get deleted by the fire extinguisher, before this can happen) - mPsys->removeAllEmitters(); + ScriptEngine::getSingleton().fireEvent(objectInstanceName, mIntensity); } - else + //----------------------------------------------------------------------- + void ExtinguishableFireAffector::_affectParticles(ParticleSystem *pSystem, Real timeElapsed) { - if (!updateIntensityRequired && mIntensitygetDefaultWidth(), pSystem->getDefaultHeight()); + originalIntensity = mIntensity; + firstFrame = false; } - if (updateIntensityRequired) + if (mIntensity < 0) + { + // The fire is extinguished (normally, this particleSystem should get deleted by the fire extinguisher, before this + // can happen) + mPsys->removeAllEmitters(); + } + else { - // update the fire - mPsys->setDefaultDimensions(originalDimensions.x*mIntensity/originalIntensity, originalDimensions.y*mIntensity/originalIntensity); - updateIntensityRequired = false; - ScriptEngine::getSingleton().fireEvent(objectInstanceName, mIntensity); + if (!updateIntensityRequired && mIntensity < mMaxIntensity) + { + // No water is hitting the fire at the moment, so let's increase the fire intensity a little bit + mIntensity += mIntensityGrowth * timeElapsed; + updateIntensityRequired = true; + } + + if (updateIntensityRequired) + { + // update the fire + mPsys->setDefaultDimensions(originalDimensions.x * mIntensity / originalIntensity, + originalDimensions.y * mIntensity / originalIntensity); + updateIntensityRequired = false; + ScriptEngine::getSingleton().fireEvent(objectInstanceName, mIntensity); + } } } -} -//----------------------------------------------------------------------- -void ExtinguishableFireAffector::setMiddlePoint(const Vector3& pos) -{ - mMiddlePoint = pos; -} -//----------------------------------------------------------------------- -void ExtinguishableFireAffector::setIntensity(Real intensity) -{ - mIntensity = intensity; -} -//----------------------------------------------------------------------- -void ExtinguishableFireAffector::setMaxIntensity(Real intensity) -{ - mMaxIntensity = intensity; -} -//----------------------------------------------------------------------- -void ExtinguishableFireAffector::setIntensityGrowth(Real intensity) -{ - mIntensityGrowth = intensity; -} -//----------------------------------------------------------------------- -void ExtinguishableFireAffector::setRadius(Real radius) -{ - mRadius = radius; -} - -//----------------------------------------------------------------------- -Vector3 ExtinguishableFireAffector::getMiddlePoint(void) const -{ - return mMiddlePoint; -} -//----------------------------------------------------------------------- -Vector3 ExtinguishableFireAffector::getAbsoluteMiddlePoint(void) const -{ - Node* node = mPsys->getParentNode(); - if (!node) return mMiddlePoint; - return node->convertLocalToWorldPosition(mMiddlePoint);; -} -//----------------------------------------------------------------------- -Real ExtinguishableFireAffector::getIntensity(void) const -{ - return mIntensity; -} -//----------------------------------------------------------------------- -Real ExtinguishableFireAffector::getMaxIntensity(void) const -{ - return mMaxIntensity; -} -//----------------------------------------------------------------------- -Real ExtinguishableFireAffector::getIntensityGrowth(void) const -{ - return mIntensityGrowth; -} -//----------------------------------------------------------------------- -Real ExtinguishableFireAffector::getRadius(void) const -{ - return mRadius; -} - -//----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// Command objects -//----------------------------------------------------------------------- -//----------------------------------------------------------------------- -String ExtinguishableFireAffector::CmdMiddlePoint::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getMiddlePoint() ); -} -void ExtinguishableFireAffector::CmdMiddlePoint::doSet(void* target, const String& val) -{ - static_cast(target)->setMiddlePoint( - StringConverter::parseVector3(val)); -} -//----------------------------------------------------------------------- -String ExtinguishableFireAffector::CmdIntensity::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getIntensity() ); - -} -void ExtinguishableFireAffector::CmdIntensity::doSet(void* target, const String& val) -{ - static_cast(target)->setIntensity( - StringConverter::parseReal(val)); -} -//----------------------------------------------------------------------- -String ExtinguishableFireAffector::CmdMaxIntensity::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getMaxIntensity() ); - -} -void ExtinguishableFireAffector::CmdMaxIntensity::doSet(void* target, const String& val) -{ - static_cast(target)->setMaxIntensity( - StringConverter::parseReal(val)); -} -//----------------------------------------------------------------------- -String ExtinguishableFireAffector::CmdIntensityGrowth::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getIntensityGrowth() ); + //----------------------------------------------------------------------- + void ExtinguishableFireAffector::setMiddlePoint(const Vector3 &pos) + { + mMiddlePoint = pos; + } + //----------------------------------------------------------------------- + void ExtinguishableFireAffector::setIntensity(Real intensity) + { + mIntensity = intensity; + } + //----------------------------------------------------------------------- + void ExtinguishableFireAffector::setMaxIntensity(Real intensity) + { + mMaxIntensity = intensity; + } + //----------------------------------------------------------------------- + void ExtinguishableFireAffector::setIntensityGrowth(Real intensity) + { + mIntensityGrowth = intensity; + } + //----------------------------------------------------------------------- + void ExtinguishableFireAffector::setRadius(Real radius) + { + mRadius = radius; + } -} -void ExtinguishableFireAffector::CmdIntensityGrowth::doSet(void* target, const String& val) -{ - static_cast(target)->setIntensityGrowth( - StringConverter::parseReal(val)); -} -//----------------------------------------------------------------------- -String ExtinguishableFireAffector::CmdRadius::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getRadius() ); + //----------------------------------------------------------------------- + Vector3 ExtinguishableFireAffector::getMiddlePoint(void) const + { + return mMiddlePoint; + } + //----------------------------------------------------------------------- + Vector3 ExtinguishableFireAffector::getAbsoluteMiddlePoint(void) const + { + Node *node = mPsys->getParentNode(); + if (!node) return mMiddlePoint; + return node->convertLocalToWorldPosition(mMiddlePoint); + ; + } + //----------------------------------------------------------------------- + Real ExtinguishableFireAffector::getIntensity(void) const + { + return mIntensity; + } + //----------------------------------------------------------------------- + Real ExtinguishableFireAffector::getMaxIntensity(void) const + { + return mMaxIntensity; + } + //----------------------------------------------------------------------- + Real ExtinguishableFireAffector::getIntensityGrowth(void) const + { + return mIntensityGrowth; + } + //----------------------------------------------------------------------- + Real ExtinguishableFireAffector::getRadius(void) const + { + return mRadius; + } -} -void ExtinguishableFireAffector::CmdRadius::doSet(void* target, const String& val) -{ - static_cast(target)->setRadius( - StringConverter::parseReal(val)); -} -//------------------------------------------------------------------------ -bool ExtinguishableFireAffector::isTemplate() const -{ - return !(mPsys->getParentNode()); -} -Real ExtinguishableFireAffector::reduceIntensity(Real amount) -{ - mIntensity -= amount; - updateIntensityRequired = true; - return mIntensity; -} + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // Command objects + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + String ExtinguishableFireAffector::CmdMiddlePoint::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getMiddlePoint()); + } + void ExtinguishableFireAffector::CmdMiddlePoint::doSet(void *target, const String &val) + { + static_cast(target)->setMiddlePoint(StringConverter::parseVector3(val)); + } + //----------------------------------------------------------------------- + String ExtinguishableFireAffector::CmdIntensity::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getIntensity()); + } + void ExtinguishableFireAffector::CmdIntensity::doSet(void *target, const String &val) + { + static_cast(target)->setIntensity(StringConverter::parseReal(val)); + } + //----------------------------------------------------------------------- + String ExtinguishableFireAffector::CmdMaxIntensity::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getMaxIntensity()); + } + void ExtinguishableFireAffector::CmdMaxIntensity::doSet(void *target, const String &val) + { + static_cast(target)->setMaxIntensity(StringConverter::parseReal(val)); + } + //----------------------------------------------------------------------- + String ExtinguishableFireAffector::CmdIntensityGrowth::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getIntensityGrowth()); + } + void ExtinguishableFireAffector::CmdIntensityGrowth::doSet(void *target, const String &val) + { + static_cast(target)->setIntensityGrowth(StringConverter::parseReal(val)); + } + //----------------------------------------------------------------------- + String ExtinguishableFireAffector::CmdRadius::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getRadius()); + } + void ExtinguishableFireAffector::CmdRadius::doSet(void *target, const String &val) + { + static_cast(target)->setRadius(StringConverter::parseReal(val)); + } + //------------------------------------------------------------------------ + bool ExtinguishableFireAffector::isTemplate() const + { + return !(mPsys->getParentNode()); + } + Real ExtinguishableFireAffector::reduceIntensity(Real amount) + { + mIntensity -= amount; + updateIntensityRequired = true; + return mIntensity; + } -} +} // namespace Ogre #endif // USE_ANGELSCRIPT diff --git a/source/main/gfx/particle/ExtinguishableFireAffector.h b/source/main/gfx/particle/ExtinguishableFireAffector.h index 046c78949d..8fef2ef794 100644 --- a/source/main/gfx/particle/ExtinguishableFireAffector.h +++ b/source/main/gfx/particle/ExtinguishableFireAffector.h @@ -22,141 +22,151 @@ #ifdef USE_ANGELSCRIPT -#include -#include -#include - -namespace Ogre { - -/** This class defines a ParticleAffector which deflects particles. -@remarks - This affector (see ParticleAffector) offers a simple (and inaccurate) physical deflection. - All particles which hit the plane are reflected. -@par - The plane is defined by a point (plane_point) and the normal (plane_normal). - In addition it is possible to change the strenght of the recoil by using the bounce parameter. -*/ -class ExtinguishableFireAffector : public ParticleAffector -{ -public: - /** Command object for middle point (see ParamCommand).*/ - class CmdMiddlePoint : public ParamCommand - { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); - }; - - /** Command object for intensity (see ParamCommand).*/ - class CmdIntensity : public ParamCommand - { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); - }; - - /** Command object for maximum intensity (see ParamCommand).*/ - class CmdMaxIntensity : public ParamCommand - { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); - }; + #include + #include + #include - /** Command object for intensity growth (see ParamCommand).*/ - class CmdIntensityGrowth : public ParamCommand - { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); - }; +namespace Ogre +{ - /** Command object for radius (see ParamCommand).*/ - class CmdRadius : public ParamCommand + /** This class defines a ParticleAffector which deflects particles. + @remarks + This affector (see ParticleAffector) offers a simple (and inaccurate) physical deflection. + All particles which hit the plane are reflected. + @par + The plane is defined by a point (plane_point) and the normal (plane_normal). + In addition it is possible to change the strenght of the recoil by using the bounce parameter. + */ + class ExtinguishableFireAffector : public ParticleAffector { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + /** Command object for middle point (see ParamCommand).*/ + class CmdMiddlePoint : public ParamCommand + { + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); + }; + + /** Command object for intensity (see ParamCommand).*/ + class CmdIntensity : public ParamCommand + { + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); + }; + + /** Command object for maximum intensity (see ParamCommand).*/ + class CmdMaxIntensity : public ParamCommand + { + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); + }; + + /** Command object for intensity growth (see ParamCommand).*/ + class CmdIntensityGrowth : public ParamCommand + { + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); + }; + + /** Command object for radius (see ParamCommand).*/ + class CmdRadius : public ParamCommand + { + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); + }; + + /// Default constructor + ExtinguishableFireAffector(ParticleSystem *psys); + + /// Destructor + ~ExtinguishableFireAffector(); + + /** See ParticleAffector. */ + void _affectParticles(ParticleSystem *pSystem, Real timeElapsed); + + /** Sets the sphere middle point. */ + void setMiddlePoint(const Vector3 &pos); + + /** Gets the sphere middle point. */ + Vector3 getMiddlePoint(void) const; + + /** Sets the intensity. */ + void setIntensity(Real intensity); + + /** Gets the intensity */ + Real getIntensity(void) const; + + /** Sets the maximum intensity. */ + void setMaxIntensity(Real intensity); + + /** Gets the maximum intensity */ + Real getMaxIntensity(void) const; + + /** Sets the intensity growth rate. */ + void setIntensityGrowth(Real intensity); + + /** Gets the intensity growth rate*/ + Real getIntensityGrowth(void) const; + + /** Sets the radius for the interaction with the FireExtiniguisher affector. */ + void setRadius(Real radius); + + /** Gets the radius for the interaction with the FireExtiniguisher affector. */ + Real getRadius(void) const; + + bool isTemplate() const; + Vector3 getAbsoluteMiddlePoint(void) const; + Real reduceIntensity(Real amount); + ParticleSystem *getParticleSystem() + { + return mPsys; + }; + + /** Sets the instance name of the parent object for this particle system */ + void setInstanceName(String iname) + { + objectInstanceName = iname; + }; + String getInstanceName() + { + return objectInstanceName; + }; + + /// Command objects + static CmdMiddlePoint msMiddlePointCmd; + static CmdIntensity msIntensityCmd; + static CmdMaxIntensity msMaxIntensityCmd; + static CmdIntensityGrowth msIntensityGrowthCmd; + static CmdRadius msRadiusCmd; + + protected: + /// sphere middle point + Vector3 mMiddlePoint; + + /// radius of the sphere + Real mRadius; + + /// Intensity of the fire + Real mIntensity; + + ParticleSystem *mPsys; + + Real originalIntensity; + bool updateIntensityRequired; + Vector2 originalDimensions; + bool firstFrame; + Real mIntensityGrowth; + Real mMaxIntensity; + + /// The instance name of the parent object + String objectInstanceName; }; - /// Default constructor - ExtinguishableFireAffector(ParticleSystem* psys); - - /// Destructor - ~ExtinguishableFireAffector(); - - /** See ParticleAffector. */ - void _affectParticles(ParticleSystem* pSystem, Real timeElapsed); - - /** Sets the sphere middle point. */ - void setMiddlePoint(const Vector3& pos); - - /** Gets the sphere middle point. */ - Vector3 getMiddlePoint(void) const; - - /** Sets the intensity. */ - void setIntensity(Real intensity); - - /** Gets the intensity */ - Real getIntensity(void) const; - - /** Sets the maximum intensity. */ - void setMaxIntensity(Real intensity); - - /** Gets the maximum intensity */ - Real getMaxIntensity(void) const; - - /** Sets the intensity growth rate. */ - void setIntensityGrowth(Real intensity); - - /** Gets the intensity growth rate*/ - Real getIntensityGrowth(void) const; - - /** Sets the radius for the interaction with the FireExtiniguisher affector. */ - void setRadius(Real radius); - - /** Gets the radius for the interaction with the FireExtiniguisher affector. */ - Real getRadius(void) const; - - bool isTemplate() const; - Vector3 getAbsoluteMiddlePoint(void) const; - Real reduceIntensity(Real amount); - ParticleSystem* getParticleSystem() { return mPsys; }; - - /** Sets the instance name of the parent object for this particle system */ - void setInstanceName(String iname) { objectInstanceName = iname; }; - String getInstanceName() { return objectInstanceName; }; - - /// Command objects - static CmdMiddlePoint msMiddlePointCmd; - static CmdIntensity msIntensityCmd; - static CmdMaxIntensity msMaxIntensityCmd; - static CmdIntensityGrowth msIntensityGrowthCmd; - static CmdRadius msRadiusCmd; - -protected: - /// sphere middle point - Vector3 mMiddlePoint; - - /// radius of the sphere - Real mRadius; - - /// Intensity of the fire - Real mIntensity; - - ParticleSystem* mPsys; - - Real originalIntensity; - bool updateIntensityRequired; - Vector2 originalDimensions; - bool firstFrame; - Real mIntensityGrowth; - Real mMaxIntensity; - - /// The instance name of the parent object - String objectInstanceName; -}; - } // namespace Ogre #endif // USE_ANGELSCRIPT diff --git a/source/main/gfx/particle/ExtinguishableFireAffectorFactory.h b/source/main/gfx/particle/ExtinguishableFireAffectorFactory.h index 0f7d5679ac..0cf808d86d 100644 --- a/source/main/gfx/particle/ExtinguishableFireAffectorFactory.h +++ b/source/main/gfx/particle/ExtinguishableFireAffectorFactory.h @@ -20,32 +20,38 @@ #pragma once -#include -#include - #include "ExtinguishableFireAffector.h" -namespace Ogre { +#include +#include -/** Factory class for DeflectorPlaneAffector. */ -class ExtinguishableFireAffectorFactory : public ParticleAffectorFactory +namespace Ogre { - /** See ParticleAffectorFactory */ - String getName() const { return "ExtinguishableFire"; } - /** See ParticleAffectorFactory */ - Ogre::ParticleAffector* createAffector(Ogre::ParticleSystem* psys) + /** Factory class for DeflectorPlaneAffector. */ + class ExtinguishableFireAffectorFactory : public ParticleAffectorFactory { - Ogre::ParticleAffector* p = OGRE_NEW ExtinguishableFireAffector(psys); - mAffectors.push_back(p); - return p; - } - -public: - - typedef VectorIterator::type> affectorIterator; - - /** Allow external access to the mFactories iterator */ - affectorIterator getAffectorIterator() { return affectorIterator(mAffectors.begin(), mAffectors.end()); } -}; + /** See ParticleAffectorFactory */ + String getName() const + { + return "ExtinguishableFire"; + } + + /** See ParticleAffectorFactory */ + Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys) + { + Ogre::ParticleAffector *p = OGRE_NEW ExtinguishableFireAffector(psys); + mAffectors.push_back(p); + return p; + } + + public: + typedef VectorIterator::type> affectorIterator; + + /** Allow external access to the mFactories iterator */ + affectorIterator getAffectorIterator() + { + return affectorIterator(mAffectors.begin(), mAffectors.end()); + } + }; } // namespace Ogre diff --git a/source/main/gfx/particle/FireExtinguisherAffector.cpp b/source/main/gfx/particle/FireExtinguisherAffector.cpp index b81afb219b..813590bb33 100644 --- a/source/main/gfx/particle/FireExtinguisherAffector.cpp +++ b/source/main/gfx/particle/FireExtinguisherAffector.cpp @@ -20,129 +20,123 @@ #ifdef USE_ANGELSCRIPT -#include "FireExtinguisherAffector.h" + #include "FireExtinguisherAffector.h" -#include "Application.h" + #include "Application.h" + #include "ExtinguishableFireAffectorFactory.h" + #include "RoRPrerequisites.h" -#include -#include -#include -#include -#include + #include + #include + #include + #include -#include "RoRPrerequisites.h" - -#include "ExtinguishableFireAffectorFactory.h" - - -namespace Ogre { - -// Instantiate statics -FireExtinguisherAffector::CmdEffectiveness FireExtinguisherAffector::msEffectivenessCmd; - -//----------------------------------------------------------------------- -FireExtinguisherAffector::FireExtinguisherAffector(ParticleSystem* psys) - : ParticleAffector(psys) +namespace Ogre { - mType = "FireExtinguisher"; - // defaults - mEffectiveness = 1.0; - mEfaf = 0; + // Instantiate statics + FireExtinguisherAffector::CmdEffectiveness FireExtinguisherAffector::msEffectivenessCmd; - // Set up parameters - if (createParamDictionary("FireExtinguisherAffector")) + //----------------------------------------------------------------------- + FireExtinguisherAffector::FireExtinguisherAffector(ParticleSystem *psys) : ParticleAffector(psys) { - addBaseParameters(); - // Add extra paramaters - ParamDictionary* dict = getParamDictionary(); - dict->addParameter(ParameterDef("effectiveness", - "How effective is your fire extinguisher? Anything higher than one is more effective than water while everything lower than one is less effective than water.", - PT_REAL), &msEffectivenessCmd); - } + mType = "FireExtinguisher"; - // get fire affector factory - ParticleSystemManager::ParticleAffectorFactoryIterator pafi = ParticleSystemManager::getSingleton().getAffectorFactoryIterator(); - ParticleAffectorFactory *paf; + // defaults + mEffectiveness = 1.0; + mEfaf = 0; - while(pafi.hasMoreElements()) - { - paf = pafi.getNext(); - if ( paf->getName() == "ExtinguishableFire" ) + // Set up parameters + if (createParamDictionary("FireExtinguisherAffector")) { - mEfaf = (ExtinguishableFireAffectorFactory *)paf; - break; - } - } - if (!mEfaf) LOG("ERROR: Couldn't find an ExtinguishableFireAffectorFactory instance. Was it registered in the content manager?"); -} -//----------------------------------------------------------------------- -void FireExtinguisherAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) -{ - ExtinguishableFireAffectorFactory::affectorIterator affIt = mEfaf->getAffectorIterator(); - ExtinguishableFireAffector* fire; + addBaseParameters(); + // Add extra paramaters + ParamDictionary *dict = getParamDictionary(); + dict->addParameter(ParameterDef("effectiveness", + "How effective is your fire extinguisher? Anything higher than one is more effective " + "than water while everything lower than one is less effective than water.", + PT_REAL), + &msEffectivenessCmd); + } + + // get fire affector factory + ParticleSystemManager::ParticleAffectorFactoryIterator pafi = + ParticleSystemManager::getSingleton().getAffectorFactoryIterator(); + ParticleAffectorFactory *paf; - while(affIt.hasMoreElements()) + while (pafi.hasMoreElements()) + { + paf = pafi.getNext(); + if (paf->getName() == "ExtinguishableFire") + { + mEfaf = (ExtinguishableFireAffectorFactory *)paf; + break; + } + } + if (!mEfaf) + LOG("ERROR: Couldn't find an ExtinguishableFireAffectorFactory instance. Was it registered in the content manager?"); + } + //----------------------------------------------------------------------- + void FireExtinguisherAffector::_affectParticles(ParticleSystem *pSystem, Real timeElapsed) { - fire = (ExtinguishableFireAffector*)affIt.getNext(); + ExtinguishableFireAffectorFactory::affectorIterator affIt = mEfaf->getAffectorIterator(); + ExtinguishableFireAffector * fire; - if (fire->isTemplate()) - continue; + while (affIt.hasMoreElements()) + { + fire = (ExtinguishableFireAffector *)affIt.getNext(); - Real squaredRadius = Math::Pow(fire->getRadius(), 2); - Vector3 middlePoint = fire->getAbsoluteMiddlePoint(); + if (fire->isTemplate()) continue; - ParticleIterator pi = pSystem->_getIterator(); - Particle *p; - int fireHits = 0; - while (!pi.end()) - { - p = pi.getNext(); + Real squaredRadius = Math::Pow(fire->getRadius(), 2); + Vector3 middlePoint = fire->getAbsoluteMiddlePoint(); - if ( middlePoint.squaredDistance(p->mPosition) < squaredRadius ) + ParticleIterator pi = pSystem->_getIterator(); + Particle * p; + int fireHits = 0; + while (!pi.end()) { - // This particle is inside the fire, dispose of it in the next update - p->mTimeToLive = 0; - ++fireHits; + p = pi.getNext(); + + if (middlePoint.squaredDistance(p->mPosition) < squaredRadius) + { + // This particle is inside the fire, dispose of it in the next update + p->mTimeToLive = 0; + ++fireHits; + } + } + if (fireHits > 0) + { + Real intensity = fire->reduceIntensity(fireHits * mEffectiveness); + if (intensity < 0) delete fire->getParticleSystem(); } - } - if (fireHits>0) - { - Real intensity = fire->reduceIntensity(fireHits*mEffectiveness); - if (intensity<0) delete fire->getParticleSystem(); } } -} -//----------------------------------------------------------------------- -void FireExtinguisherAffector::setEffectiveness(Real effectiveness) -{ - mEffectiveness = effectiveness; -} -//----------------------------------------------------------------------- -Real FireExtinguisherAffector::getEffectiveness(void) const -{ - return mEffectiveness; -} - -//----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// Command objects -//----------------------------------------------------------------------- -//----------------------------------------------------------------------- -String FireExtinguisherAffector::CmdEffectiveness::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getEffectiveness() ); + //----------------------------------------------------------------------- + void FireExtinguisherAffector::setEffectiveness(Real effectiveness) + { + mEffectiveness = effectiveness; + } + //----------------------------------------------------------------------- + Real FireExtinguisherAffector::getEffectiveness(void) const + { + return mEffectiveness; + } -} -void FireExtinguisherAffector::CmdEffectiveness::doSet(void* target, const String& val) -{ - static_cast(target)->setEffectiveness( - StringConverter::parseReal(val)); -} + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + // Command objects + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + String FireExtinguisherAffector::CmdEffectiveness::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getEffectiveness()); + } + void FireExtinguisherAffector::CmdEffectiveness::doSet(void *target, const String &val) + { + static_cast(target)->setEffectiveness(StringConverter::parseReal(val)); + } } // namespace Ogre - -#endif //USE_ANGELSCRIPT - +#endif // USE_ANGELSCRIPT diff --git a/source/main/gfx/particle/FireExtinguisherAffector.h b/source/main/gfx/particle/FireExtinguisherAffector.h index 2710b82372..1e2557de28 100644 --- a/source/main/gfx/particle/FireExtinguisherAffector.h +++ b/source/main/gfx/particle/FireExtinguisherAffector.h @@ -22,55 +22,57 @@ #ifdef USE_ANGELSCRIPT -#include -#include + #include "ExtinguishableFireAffectorFactory.h" -#include "ExtinguishableFireAffectorFactory.h" + #include + #include -namespace Ogre { - -/** This class defines a ParticleAffector which deflects particles. -@remarks - This affector (see ParticleAffector) offers a simple (and inaccurate) physical deflection. - All particles which hit the plane are reflected. -@par - The plane is defined by a point (plane_point) and the normal (plane_normal). - In addition it is possible to change the strenght of the recoil by using the bounce parameter. -*/ -class FireExtinguisherAffector : public ParticleAffector +namespace Ogre { -public: - /** Command object for bounce (see ParamCommand).*/ - class CmdEffectiveness : public ParamCommand + + /** This class defines a ParticleAffector which deflects particles. + @remarks + This affector (see ParticleAffector) offers a simple (and inaccurate) physical deflection. + All particles which hit the plane are reflected. + @par + The plane is defined by a point (plane_point) and the normal (plane_normal). + In addition it is possible to change the strenght of the recoil by using the bounce parameter. + */ + class FireExtinguisherAffector : public ParticleAffector { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); - }; + public: + /** Command object for bounce (see ParamCommand).*/ + class CmdEffectiveness : public ParamCommand + { + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); + }; - /// Default constructor - FireExtinguisherAffector(ParticleSystem* psys); + /// Default constructor + FireExtinguisherAffector(ParticleSystem *psys); - /** See ParticleAffector. */ - void _affectParticles(ParticleSystem* pSystem, Real timeElapsed); + /** See ParticleAffector. */ + void _affectParticles(ParticleSystem *pSystem, Real timeElapsed); - /** Sets the bounce value of the deflection. */ - void setEffectiveness(Real effectiveness); + /** Sets the bounce value of the deflection. */ + void setEffectiveness(Real effectiveness); - /** Gets the bounce value of the deflection. */ - Real getEffectiveness(void) const; + /** Gets the bounce value of the deflection. */ + Real getEffectiveness(void) const; - /// Command objects - static CmdEffectiveness msEffectivenessCmd; + /// Command objects + static CmdEffectiveness msEffectivenessCmd; -protected: - // a reference to the extinguishable fire - ExtinguishableFireAffectorFactory* mEfaf; + protected: + // a reference to the extinguishable fire + ExtinguishableFireAffectorFactory *mEfaf; - /// effectiveness factor (1 means as effective as water, everything higher is more effective while anything lower is less effective) - Real mEffectiveness; -}; + /// effectiveness factor (1 means as effective as water, everything higher is more effective while anything lower is less + /// effective) + Real mEffectiveness; + }; } // namespace Ogre -#endif //USE_ANGELSCRIPT +#endif // USE_ANGELSCRIPT diff --git a/source/main/gfx/particle/FireExtinguisherAffectorFactory.h b/source/main/gfx/particle/FireExtinguisherAffectorFactory.h index 08898032ae..1fd0c43562 100644 --- a/source/main/gfx/particle/FireExtinguisherAffectorFactory.h +++ b/source/main/gfx/particle/FireExtinguisherAffectorFactory.h @@ -20,25 +20,28 @@ #pragma once -#include - #include "FireExtinguisherAffector.h" -namespace Ogre { +#include -/** Factory class for DeflectorPlaneAffector. */ -class FireExtinguisherAffectorFactory : public ParticleAffectorFactory +namespace Ogre { - /** See ParticleAffectorFactory */ - String getName() const { return "FireExtinguisher"; } - /** See ParticleAffectorFactory */ - Ogre::ParticleAffector* createAffector(Ogre::ParticleSystem* psys) + /** Factory class for DeflectorPlaneAffector. */ + class FireExtinguisherAffectorFactory : public ParticleAffectorFactory { - Ogre::ParticleAffector* p = OGRE_NEW FireExtinguisherAffector(psys); - mAffectors.push_back(p); - return p; - } -}; + /** See ParticleAffectorFactory */ + String getName() const + { + return "FireExtinguisher"; + } + + /** See ParticleAffectorFactory */ + Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys) + { + Ogre::ParticleAffector *p = OGRE_NEW FireExtinguisherAffector(psys); + mAffectors.push_back(p); + return p; + } + }; } // namespace Ogre - diff --git a/source/main/gfx/particle/OgreParticleCustomParam.h b/source/main/gfx/particle/OgreParticleCustomParam.h index fadf60e2db..ad19cc1ce4 100644 --- a/source/main/gfx/particle/OgreParticleCustomParam.h +++ b/source/main/gfx/particle/OgreParticleCustomParam.h @@ -1,24 +1,25 @@ #pragma once #ifndef __OGRE_PARTICLE_CUSTOM_PARAM_H__ -#define __OGRE_PARTICLE_CUSTOM_PARAM_H__ + #define __OGRE_PARTICLE_CUSTOM_PARAM_H__ -#include + #include -namespace Ogre { -/// custom visual data for shader renderer -class ParticleCustomParam : public ParticleVisualData +namespace Ogre { -public: - ParticleCustomParam() : paramValue(0, 0, 0, 0) + /// custom visual data for shader renderer + class ParticleCustomParam : public ParticleVisualData { - } + public: + ParticleCustomParam() : paramValue(0, 0, 0, 0) + { + } - virtual ~ParticleCustomParam() - { - } + virtual ~ParticleCustomParam() + { + } - Vector4 paramValue; -}; -} + Vector4 paramValue; + }; +} // namespace Ogre #endif // __OGRE_PARTICLE_CUSTOM_PARAM_H__ diff --git a/source/main/gfx/particle/OgreShaderParticleRenderer.cpp b/source/main/gfx/particle/OgreShaderParticleRenderer.cpp index f724ff2d78..2b80b1d1be 100644 --- a/source/main/gfx/particle/OgreShaderParticleRenderer.cpp +++ b/source/main/gfx/particle/OgreShaderParticleRenderer.cpp @@ -1,712 +1,708 @@ #include "OgreShaderParticleRenderer.h" + #include "OgreParticleCustomParam.h" -#include -#include -#include #include #include -#include +#include #include +#include +#include +#include -namespace Ogre { -////////////////////////////////////////////////////////////////////////// - -ShaderParticleRenderer::CmdVertexFormatColour ShaderParticleRenderer::msVertexFmtColour; -ShaderParticleRenderer::CmdVertexFormatTexture ShaderParticleRenderer::msVertexFmtTexture; -ShaderParticleRenderer::CmdVertexFormatSize ShaderParticleRenderer::msVertexFmtSize; -ShaderParticleRenderer::CmdVertexFormatRotation ShaderParticleRenderer::msVertexFmtRotation; -ShaderParticleRenderer::CmdVertexFormatRotationSpeed ShaderParticleRenderer::msVertexFmtRotationSpeed; -ShaderParticleRenderer::CmdVertexFormatDirection ShaderParticleRenderer::msVertexFmtDirection; -ShaderParticleRenderer::CmdVertexFormatTTL ShaderParticleRenderer::msVertexFmtTTL; -ShaderParticleRenderer::CmdVertexFormatTotalTTL ShaderParticleRenderer::msVertexFmtTotalTTL; -ShaderParticleRenderer::CmdVertexFormatTimeFrag ShaderParticleRenderer::msVertexFmtTimeFrag; -ShaderParticleRenderer::CmdVertexFormatTimeFragInv ShaderParticleRenderer::msVertexFmtTimeFragInv; - -////////////////////////////////////////////////////////////////////////// -ShaderParticleRenderer::ShaderParticleRenderer() - : mDefaultParticleSize(1, 1) - , mKeepInLocalSpace(false) - , mParentNode(NULL) - , mParentIsTagPoint(false) - , mSortMode(SM_DISTANCE) - , mLightListUpdated(0) - , mRadius(0.0f) - , mRenderQueueID(RENDER_QUEUE_MAIN) - , mVertexFormatTexture(false) - , mVertexFormatSize(false) - , mVertexFormatRotation(false) - , mVertexFormatRotationSpeed(false) - , mVertexFormatDirection(false) - , mVertexFormatColour(false ) - , mVertexFormatTTL(false) - , mVertexFormatTotalTTL(false) - , mVertexFormatTimeFragment(false) - , mVertexFormatTimeFragmentInv(false) - , mVertexSize(0) -{ - if (createParamDictionary("ShaderParticleRenderer")) - { - ParamDictionary* dict = getParamDictionary(); - dict->addParameter(ParameterDef("diffuse_colour", - "Adds diffuse colour to vertex format (type = float4)", - PT_BOOL), - &msVertexFmtColour); - - dict->addParameter(ParameterDef("texture_coord", - "Adds general texture coordinate to vertex format (type = float2)", - PT_BOOL), - &msVertexFmtTexture); - - dict->addParameter(ParameterDef("particle_size", - "Adds particle size to vertex format (type = float2)", - PT_BOOL), - &msVertexFmtSize); - - dict->addParameter(ParameterDef("particle_rotation", - "Adds particle rotation (in radians) to vertex format (type = float1)" - "note: if particle_rotation_speed present in script, they are packed together as float2", - PT_BOOL), - &msVertexFmtRotation); - - dict->addParameter(ParameterDef("particle_rotation_speed", - "Adds particle rotation speed (in radians/s) to vertex format (type = float1)" - "note: if particle_rotation present in script, they are packed together as float2", - PT_BOOL), - &msVertexFmtRotationSpeed); - - dict->addParameter(ParameterDef("particle_direction", - "Adds particle direction to vertex format (type = float3)" - "note: it represent particle speed", - PT_BOOL), - &msVertexFmtDirection); - - dict->addParameter(ParameterDef("time_to_live", - "Adds particle current time to live to vertex format (type = float1)" - "note: this parameter can be packed with total_time_to_live, time_frag and time_frag_inv", - PT_BOOL), - &msVertexFmtTTL); - - dict->addParameter(ParameterDef("total_time_to_live", - "Adds particle total time to live to vertex format (type = float1)" - "note: this parameter can be packed with time_to_live, time_frag and time_frag_inv", - PT_BOOL), - &msVertexFmtTotalTTL); - - dict->addParameter(ParameterDef("time_frag", - "Adds particle time fragment to vertex format (type = float1), which is ratio between ttl and total ttl" - "note: this parameter can be packed with time_to_live, total_time_to_live and time_frag_inv", - PT_BOOL), - &msVertexFmtTimeFrag); - - dict->addParameter(ParameterDef("time_frag_inv", - "Adds particle inverse time fragment to vertex format (type = float1), which is 1.0f - time_frag" - "note: this parameter can be packed with time_to_live, total_time_to_live and time_frag", - PT_BOOL), - &msVertexFmtTimeFragInv); - } - - mVertexData = OGRE_NEW VertexData; - mIndexData = OGRE_NEW IndexData; - - mTexCoordTable[0] = Vector2(0, 0); - mTexCoordTable[1] = Vector2(1, 0); - mTexCoordTable[2] = Vector2(1, 1); - mTexCoordTable[3] = Vector2(0, 1); -} - -////////////////////////////////////////////////////////////////////////// -ShaderParticleRenderer::~ShaderParticleRenderer() -{ - OGRE_DELETE mVertexData; - OGRE_DELETE mIndexData; -} +namespace Ogre +{ + ////////////////////////////////////////////////////////////////////////// + + ShaderParticleRenderer::CmdVertexFormatColour ShaderParticleRenderer::msVertexFmtColour; + ShaderParticleRenderer::CmdVertexFormatTexture ShaderParticleRenderer::msVertexFmtTexture; + ShaderParticleRenderer::CmdVertexFormatSize ShaderParticleRenderer::msVertexFmtSize; + ShaderParticleRenderer::CmdVertexFormatRotation ShaderParticleRenderer::msVertexFmtRotation; + ShaderParticleRenderer::CmdVertexFormatRotationSpeed ShaderParticleRenderer::msVertexFmtRotationSpeed; + ShaderParticleRenderer::CmdVertexFormatDirection ShaderParticleRenderer::msVertexFmtDirection; + ShaderParticleRenderer::CmdVertexFormatTTL ShaderParticleRenderer::msVertexFmtTTL; + ShaderParticleRenderer::CmdVertexFormatTotalTTL ShaderParticleRenderer::msVertexFmtTotalTTL; + ShaderParticleRenderer::CmdVertexFormatTimeFrag ShaderParticleRenderer::msVertexFmtTimeFrag; + ShaderParticleRenderer::CmdVertexFormatTimeFragInv ShaderParticleRenderer::msVertexFmtTimeFragInv; + + ////////////////////////////////////////////////////////////////////////// + ShaderParticleRenderer::ShaderParticleRenderer() + : mDefaultParticleSize(1, 1), mKeepInLocalSpace(false), mParentNode(NULL), mParentIsTagPoint(false), + mSortMode(SM_DISTANCE), mLightListUpdated(0), mRadius(0.0f), mRenderQueueID(RENDER_QUEUE_MAIN), + mVertexFormatTexture(false), mVertexFormatSize(false), mVertexFormatRotation(false), mVertexFormatRotationSpeed(false), + mVertexFormatDirection(false), mVertexFormatColour(false), mVertexFormatTTL(false), mVertexFormatTotalTTL(false), + mVertexFormatTimeFragment(false), mVertexFormatTimeFragmentInv(false), mVertexSize(0) + { + if (createParamDictionary("ShaderParticleRenderer")) + { + ParamDictionary *dict = getParamDictionary(); + dict->addParameter(ParameterDef("diffuse_colour", "Adds diffuse colour to vertex format (type = float4)", PT_BOOL), + &msVertexFmtColour); + + dict->addParameter( + ParameterDef("texture_coord", "Adds general texture coordinate to vertex format (type = float2)", PT_BOOL), + &msVertexFmtTexture); + + dict->addParameter(ParameterDef("particle_size", "Adds particle size to vertex format (type = float2)", PT_BOOL), + &msVertexFmtSize); + + dict->addParameter( + ParameterDef("particle_rotation", + "Adds particle rotation (in radians) to vertex format (type = float1)" + "note: if particle_rotation_speed present in script, they are packed together as float2", + PT_BOOL), + &msVertexFmtRotation); + + dict->addParameter(ParameterDef("particle_rotation_speed", + "Adds particle rotation speed (in radians/s) to vertex format (type = float1)" + "note: if particle_rotation present in script, they are packed together as float2", + PT_BOOL), + &msVertexFmtRotationSpeed); + + dict->addParameter(ParameterDef("particle_direction", + "Adds particle direction to vertex format (type = float3)" + "note: it represent particle speed", + PT_BOOL), + &msVertexFmtDirection); + + dict->addParameter( + ParameterDef("time_to_live", + "Adds particle current time to live to vertex format (type = float1)" + "note: this parameter can be packed with total_time_to_live, time_frag and time_frag_inv", + PT_BOOL), + &msVertexFmtTTL); + + dict->addParameter(ParameterDef("total_time_to_live", + "Adds particle total time to live to vertex format (type = float1)" + "note: this parameter can be packed with time_to_live, time_frag and time_frag_inv", + PT_BOOL), + &msVertexFmtTotalTTL); + + dict->addParameter( + ParameterDef( + "time_frag", + "Adds particle time fragment to vertex format (type = float1), which is ratio between ttl and total ttl" + "note: this parameter can be packed with time_to_live, total_time_to_live and time_frag_inv", + PT_BOOL), + &msVertexFmtTimeFrag); + + dict->addParameter( + ParameterDef("time_frag_inv", + "Adds particle inverse time fragment to vertex format (type = float1), which is 1.0f - time_frag" + "note: this parameter can be packed with time_to_live, total_time_to_live and time_frag", + PT_BOOL), + &msVertexFmtTimeFragInv); + } -////////////////////////////////////////////////////////////////////////// -const String& ShaderParticleRenderer::getType(void) const -{ - return rendererTypeName; -} + mVertexData = OGRE_NEW VertexData; + mIndexData = OGRE_NEW IndexData; -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_updateRenderQueue(RenderQueue* queue, Ogre::list::type& currentParticles, bool cullIndividually) -{ - // be sure that we have enough space in buffers - if (!allocateBuffers(currentParticles.size())) { - assert(0 && "Cannot allocate buffers"); - return; - } - - // update vertex data - mRadius = 0.0f; - if (!currentParticles.empty()) { - HardwareVertexBufferSharedPtr pVB = mVertexData->vertexBufferBinding->getBuffer(0); - uchar* pDataVB = reinterpret_cast(pVB->lock(HardwareBuffer::HBL_DISCARD)); - for (Ogre::list::type::iterator it=currentParticles.begin(); it!=currentParticles.end(); ++it) { - Particle* pParticle = *it; - addParticle(pDataVB, *pParticle); - pDataVB += 4 * mVertexSize; - - float fDist = (mParentNode != NULL) ? mParentNode->getPosition().distance(pParticle->mPosition) : pParticle->mPosition.length(); - if (fDist > mRadius) - mRadius = fDist; - } - pVB->unlock(); + mTexCoordTable[0] = Vector2(0, 0); + mTexCoordTable[1] = Vector2(1, 0); + mTexCoordTable[2] = Vector2(1, 1); + mTexCoordTable[3] = Vector2(0, 1); } - // setup counts - mVertexData->vertexCount = currentParticles.size() * 4; - mIndexData->indexCount = currentParticles.size() * 6; + ////////////////////////////////////////////////////////////////////////// + ShaderParticleRenderer::~ShaderParticleRenderer() + { + OGRE_DELETE mVertexData; + OGRE_DELETE mIndexData; + } - // update render queue - queue->addRenderable(this, mRenderQueueID); -} + ////////////////////////////////////////////////////////////////////////// + const String &ShaderParticleRenderer::getType(void) const + { + return rendererTypeName; + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::visitRenderables(Renderable::Visitor* visitor, bool debugRenderables) -{ - visitor->visit(this, 0, debugRenderables); -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_updateRenderQueue(RenderQueue *queue, Ogre::list::type ¤tParticles, + bool cullIndividually) + { + // be sure that we have enough space in buffers + if (!allocateBuffers(currentParticles.size())) + { + assert(0 && "Cannot allocate buffers"); + return; + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_setMaterial(MaterialPtr& mat) -{ - mMaterial = mat; -} + // update vertex data + mRadius = 0.0f; + if (!currentParticles.empty()) + { + HardwareVertexBufferSharedPtr pVB = mVertexData->vertexBufferBinding->getBuffer(0); + uchar * pDataVB = reinterpret_cast(pVB->lock(HardwareBuffer::HBL_DISCARD)); + for (Ogre::list::type::iterator it = currentParticles.begin(); it != currentParticles.end(); ++it) + { + Particle *pParticle = *it; + addParticle(pDataVB, *pParticle); + pDataVB += 4 * mVertexSize; -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_notifyCurrentCamera(Camera* cam) -{ -} + float fDist = (mParentNode != NULL) ? mParentNode->getPosition().distance(pParticle->mPosition) + : pParticle->mPosition.length(); + if (fDist > mRadius) mRadius = fDist; + } + pVB->unlock(); + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_notifyParticleRotated(void) -{ - // nothing to do -} + // setup counts + mVertexData->vertexCount = currentParticles.size() * 4; + mIndexData->indexCount = currentParticles.size() * 6; -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_notifyParticleResized(void) -{ - // nothing to do -} + // update render queue + queue->addRenderable(this, mRenderQueueID); + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_notifyParticleQuota(size_t quota) -{ - // nothing to do - hardware buffers will be altered run-time -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::visitRenderables(Renderable::Visitor *visitor, bool debugRenderables) + { + visitor->visit(this, 0, debugRenderables); + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_notifyAttached(Node* parent, bool isTagPoint) -{ - mParentNode = parent; - mParentIsTagPoint = isTagPoint; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_setMaterial(MaterialPtr &mat) + { + mMaterial = mat; + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_notifyDefaultDimensions(Real width, Real height) -{ - mDefaultParticleSize.x = width; - mDefaultParticleSize.y = height; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_notifyCurrentCamera(Camera *cam) + { + } -////////////////////////////////////////////////////////////////////////// -ParticleVisualData* ShaderParticleRenderer::_createVisualData(void) -{ - return OGRE_NEW ParticleCustomParam(); -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_notifyParticleRotated(void) + { + // nothing to do + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::_destroyVisualData(ParticleVisualData* vis) -{ - OGRE_DELETE vis; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_notifyParticleResized(void) + { + // nothing to do + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::setRenderQueueGroup(uint8 queueID) -{ - mRenderQueueID = queueID; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_notifyParticleQuota(size_t quota) + { + // nothing to do - hardware buffers will be altered run-time + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::setKeepParticlesInLocalSpace(bool keepLocal) -{ - mKeepInLocalSpace = keepLocal; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_notifyAttached(Node *parent, bool isTagPoint) + { + mParentNode = parent; + mParentIsTagPoint = isTagPoint; + } -////////////////////////////////////////////////////////////////////////// -SortMode ShaderParticleRenderer::_getSortMode(void) const -{ - return mSortMode; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_notifyDefaultDimensions(Real width, Real height) + { + mDefaultParticleSize.x = width; + mDefaultParticleSize.y = height; + } -////////////////////////////////////////////////////////////////////////// -const MaterialPtr& ShaderParticleRenderer::getMaterial(void) const -{ - return mMaterial; -} + ////////////////////////////////////////////////////////////////////////// + ParticleVisualData *ShaderParticleRenderer::_createVisualData(void) + { + return OGRE_NEW ParticleCustomParam(); + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::getRenderOperation(RenderOperation& op) -{ - assert(mVertexData != NULL); - assert(mIndexData != NULL); - op.vertexData = mVertexData; - op.indexData = mIndexData; - op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; - op.useIndexes = true; - op.srcRenderable = this; -} - -//////////////////////////////////////////////////////////////////////////// -//unsigned short ShaderParticleRenderer::getNumWorldTransforms(void) const -//{ -// if (mKeepInLocalSpace && mParentNode != NULL) -// { -// return mParentNode->getNumWorldTransforms(); -// } else -// { -// return 1; -// } -//} - -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::getWorldTransforms(Matrix4* xform) const -{ - if (mKeepInLocalSpace && mParentNode != NULL) + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::_destroyVisualData(ParticleVisualData *vis) { - *xform = mParentNode->_getFullTransform(); - //mParentNode->getWorldTransforms(xform); - } else + OGRE_DELETE vis; + } + + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::setRenderQueueGroup(uint8 queueID) { - *xform = Matrix4::IDENTITY; + mRenderQueueID = queueID; } -} -////////////////////////////////////////////////////////////////////////// -Real ShaderParticleRenderer::getSquaredViewDepth(const Camera* cam) const -{ - if (mParentNode != NULL) { - return cam->getRealPosition().squaredDistance(mParentNode->getPosition()); - } else { - return 0.0f; + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::setKeepParticlesInLocalSpace(bool keepLocal) + { + mKeepInLocalSpace = keepLocal; } -} -////////////////////////////////////////////////////////////////////////// -const LightList& ShaderParticleRenderer::getLights(void) const -{ - if (mParentNode != NULL) { - // Query from parent entity if exists - if (mParentIsTagPoint) + ////////////////////////////////////////////////////////////////////////// + SortMode ShaderParticleRenderer::_getSortMode(void) const + { + return mSortMode; + } + + ////////////////////////////////////////////////////////////////////////// + const MaterialPtr &ShaderParticleRenderer::getMaterial(void) const + { + return mMaterial; + } + + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::getRenderOperation(RenderOperation &op) + { + assert(mVertexData != NULL); + assert(mIndexData != NULL); + op.vertexData = mVertexData; + op.indexData = mIndexData; + op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; + op.useIndexes = true; + op.srcRenderable = this; + } + + //////////////////////////////////////////////////////////////////////////// + // unsigned short ShaderParticleRenderer::getNumWorldTransforms(void) const + //{ + // if (mKeepInLocalSpace && mParentNode != NULL) + // { + // return mParentNode->getNumWorldTransforms(); + // } else + // { + // return 1; + // } + //} + + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::getWorldTransforms(Matrix4 *xform) const + { + if (mKeepInLocalSpace && mParentNode != NULL) { - TagPoint* tp = static_cast(mParentNode); - return tp->getParentEntity()->queryLights(); + *xform = mParentNode->_getFullTransform(); + // mParentNode->getWorldTransforms(xform); } + else + { + *xform = Matrix4::IDENTITY; + } + } - if (mParentNode) + ////////////////////////////////////////////////////////////////////////// + Real ShaderParticleRenderer::getSquaredViewDepth(const Camera *cam) const + { + if (mParentNode != NULL) { return cam->getRealPosition().squaredDistance(mParentNode->getPosition()); } + else { - SceneNode* sn = static_cast(mParentNode); + return 0.0f; + } + } - // Make sure we only update this only if need. - ulong frame = sn->getCreator()->_getLightsDirtyCounter(); - if (mLightListUpdated != frame) + ////////////////////////////////////////////////////////////////////////// + const LightList &ShaderParticleRenderer::getLights(void) const + { + if (mParentNode != NULL) + { + // Query from parent entity if exists + if (mParentIsTagPoint) + { + TagPoint *tp = static_cast(mParentNode); + return tp->getParentEntity()->queryLights(); + } + + if (mParentNode) + { + SceneNode *sn = static_cast(mParentNode); + + // Make sure we only update this only if need. + ulong frame = sn->getCreator()->_getLightsDirtyCounter(); + if (mLightListUpdated != frame) + { + mLightListUpdated = frame; + sn->findLights(mLightList, mRadius); + } + } + else { - mLightListUpdated = frame; - sn->findLights(mLightList, mRadius); + mLightList.clear(); } } else { mLightList.clear(); } + + return mLightList; } - else + + ////////////////////////////////////////////////////////////////////////// + bool ShaderParticleRenderer::allocateBuffers(size_t iNumParticles) { - mLightList.clear(); - } + // prepare vertex declaration + if (mVertexData->vertexDeclaration->getElementCount() == 0) + { + VertexDeclaration *pDecl = mVertexData->vertexDeclaration; + size_t ofs = 0; + ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_POSITION).getSize(); // position + if (mVertexFormatColour) ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_DIFFUSE).getSize(); // diffuse colour - return mLightList; -} + // other data are stored in vertex as texture coordinates + ushort ix = 0; + if (mVertexFormatTexture) + ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // general texture coord -////////////////////////////////////////////////////////////////////////// -bool ShaderParticleRenderer::allocateBuffers(size_t iNumParticles) -{ - // prepare vertex declaration - if (mVertexData->vertexDeclaration->getElementCount() == 0) { - VertexDeclaration* pDecl = mVertexData->vertexDeclaration; - size_t ofs = 0; - ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_POSITION).getSize(); // position - if (mVertexFormatColour) - ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_DIFFUSE).getSize(); // diffuse colour + if (mVertexFormatSize) + ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle size - // other data are stored in vertex as texture coordinates - ushort ix = 0; - if (mVertexFormatTexture) - ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // general texture coord + if (mVertexFormatRotation || mVertexFormatRotationSpeed) + { + if (mVertexFormatRotation && mVertexFormatRotationSpeed) + ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++) + .getSize(); // current rotation and rotation speed + else + ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++) + .getSize(); // current rotation or rotation speed + } - if (mVertexFormatSize) - ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle size + if (mVertexFormatDirection) + ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++) + .getSize(); // particle direction (as speed) + + // add packed times + size_t iNumTimes = 0; + if (mVertexFormatTTL) iNumTimes++; + if (mVertexFormatTotalTTL) iNumTimes++; + if (mVertexFormatTimeFragment) iNumTimes++; + if (mVertexFormatTimeFragmentInv) iNumTimes++; + switch (iNumTimes) + { + case 1: ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); break; + case 2: ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); break; + case 3: ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); break; + case 4: ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); break; + } - if (mVertexFormatRotation || mVertexFormatRotationSpeed) { - if (mVertexFormatRotation && mVertexFormatRotationSpeed) - ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // current rotation and rotation speed - else - ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); // current rotation or rotation speed - } + // add custom parameters + ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); + assert(ix <= 8); - if (mVertexFormatDirection) - ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle direction (as speed) - - // add packed times - size_t iNumTimes = 0; - if (mVertexFormatTTL) iNumTimes++; - if (mVertexFormatTotalTTL) iNumTimes++; - if (mVertexFormatTimeFragment) iNumTimes++; - if (mVertexFormatTimeFragmentInv) iNumTimes++; - switch(iNumTimes) { - case 1: - ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); - break; - case 2: - ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); - break; - case 3: - ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); - break; - case 4: - ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); - break; + // cache vertex size + mVertexSize = pDecl->getVertexSize(0); } - // add custom parameters - ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); - assert(ix <= 8); + Ogre::HardwareVertexBufferSharedPtr pVB; + if (mVertexData->vertexBufferBinding->isBufferBound(0)) pVB = mVertexData->vertexBufferBinding->getBuffer(0); - // cache vertex size - mVertexSize = pDecl->getVertexSize(0); - } - - Ogre::HardwareVertexBufferSharedPtr pVB; - if (mVertexData->vertexBufferBinding->isBufferBound(0)) - pVB = mVertexData->vertexBufferBinding->getBuffer(0); - - // prepare vertex buffer - if (pVB.isNull() || pVB->getNumVertices() < iNumParticles * 4) { - assert(iNumParticles * 4 < 65536); // we are using 16bit index buffer - pVB = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(mVertexSize, 4 * iNumParticles, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); - if (pVB.isNull()) - return false; - - mVertexData->vertexBufferBinding->setBinding(0, pVB); - } + // prepare vertex buffer + if (pVB.isNull() || pVB->getNumVertices() < iNumParticles * 4) + { + assert(iNumParticles * 4 < 65536); // we are using 16bit index buffer + pVB = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + mVertexSize, 4 * iNumParticles, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + if (pVB.isNull()) return false; - // prepare index buffer - Ogre::HardwareIndexBufferSharedPtr pIB = mIndexData->indexBuffer; - if (pIB.isNull() || pIB->getNumIndexes() < iNumParticles * 6) { - pIB = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, iNumParticles * 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); - if (pIB.isNull()) - return false; + mVertexData->vertexBufferBinding->setBinding(0, pVB); + } - mIndexData->indexBuffer = pIB; + // prepare index buffer + Ogre::HardwareIndexBufferSharedPtr pIB = mIndexData->indexBuffer; + if (pIB.isNull() || pIB->getNumIndexes() < iNumParticles * 6) + { + pIB = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( + Ogre::HardwareIndexBuffer::IT_16BIT, iNumParticles * 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); + if (pIB.isNull()) return false; - // fill - Ogre::uint16* pDataIB = reinterpret_cast(pIB->lock(Ogre::HardwareBuffer::HBL_NORMAL)); - for (Ogre::uint16 k=0; k(iNumParticles); ++k) { - pDataIB[0] = k*4 + 0; - pDataIB[1] = k*4 + 1; - pDataIB[2] = k*4 + 2; + mIndexData->indexBuffer = pIB; - pDataIB[3] = k*4 + 0; - pDataIB[4] = k*4 + 2; - pDataIB[5] = k*4 + 3; - pDataIB += 6; + // fill + Ogre::uint16 *pDataIB = reinterpret_cast(pIB->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + for (Ogre::uint16 k = 0; k < static_cast(iNumParticles); ++k) + { + pDataIB[0] = k * 4 + 0; + pDataIB[1] = k * 4 + 1; + pDataIB[2] = k * 4 + 2; + + pDataIB[3] = k * 4 + 0; + pDataIB[4] = k * 4 + 2; + pDataIB[5] = k * 4 + 3; + pDataIB += 6; + } + pIB->unlock(); } - pIB->unlock(); - } - return true; -} + return true; + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRenderer::addParticle(uint8* pDataVB, const Particle& particle) const -{ - // position - size_t ofs = 0; - for (int k=0; k<4; ++k) { - float* pPosition = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - pPosition[0] = particle.mPosition.x; - pPosition[1] = particle.mPosition.y; - pPosition[2] = particle.mPosition.z; - pPosition[3] = k; - } - ofs += sizeof(float) * 4; - - // diffuse colour - if (mVertexFormatColour) { - for (int k=0; k<4; ++k) { - float* pColour = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - pColour[0] = particle.mColour.r; - pColour[1] = particle.mColour.g; - pColour[2] = particle.mColour.b; - pColour[3] = particle.mColour.a; + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRenderer::addParticle(uint8 *pDataVB, const Particle &particle) const + { + // position + size_t ofs = 0; + for (int k = 0; k < 4; ++k) + { + float *pPosition = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + pPosition[0] = particle.mPosition.x; + pPosition[1] = particle.mPosition.y; + pPosition[2] = particle.mPosition.z; + pPosition[3] = k; } ofs += sizeof(float) * 4; - } - // general texture coordinates - if (mVertexFormatTexture) { - for (int k=0; k<4; ++k) { - float* pTexCoord = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - pTexCoord[0] = mTexCoordTable[k].x; - pTexCoord[1] = mTexCoordTable[k].y; + // diffuse colour + if (mVertexFormatColour) + { + for (int k = 0; k < 4; ++k) + { + float *pColour = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + pColour[0] = particle.mColour.r; + pColour[1] = particle.mColour.g; + pColour[2] = particle.mColour.b; + pColour[3] = particle.mColour.a; + } + ofs += sizeof(float) * 4; } - ofs += sizeof(float) * 2; - } - // particle size - if (mVertexFormatSize) { - float w = mDefaultParticleSize.x; - float h = mDefaultParticleSize.y; - if (particle.hasOwnDimensions()) { - w = particle.getOwnWidth(); - h = particle.getOwnHeight(); + // general texture coordinates + if (mVertexFormatTexture) + { + for (int k = 0; k < 4; ++k) + { + float *pTexCoord = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + pTexCoord[0] = mTexCoordTable[k].x; + pTexCoord[1] = mTexCoordTable[k].y; + } + ofs += sizeof(float) * 2; } - for (int k=0; k<4; ++k) { - float* pSize = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - pSize[0] = w; - pSize[1] = h; + // particle size + if (mVertexFormatSize) + { + float w = mDefaultParticleSize.x; + float h = mDefaultParticleSize.y; + if (particle.hasOwnDimensions()) + { + w = particle.getOwnWidth(); + h = particle.getOwnHeight(); + } + + for (int k = 0; k < 4; ++k) + { + float *pSize = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + pSize[0] = w; + pSize[1] = h; + } + ofs += sizeof(float) * 2; } - ofs += sizeof(float) * 2; - } - // particle rotation - if (mVertexFormatRotation) { - for (int k=0; k<4; ++k) { - float* pRotation = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - *pRotation = particle.mRotation.valueRadians(); + // particle rotation + if (mVertexFormatRotation) + { + for (int k = 0; k < 4; ++k) + { + float *pRotation = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + *pRotation = particle.mRotation.valueRadians(); + } + ofs += sizeof(float); } - ofs += sizeof(float); - } - // particle rotation speed - if (mVertexFormatRotationSpeed) { - for (int k=0; k<4; ++k) { - float* pRotation = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - *pRotation = particle.mRotationSpeed.valueRadians(); + // particle rotation speed + if (mVertexFormatRotationSpeed) + { + for (int k = 0; k < 4; ++k) + { + float *pRotation = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + *pRotation = particle.mRotationSpeed.valueRadians(); + } + ofs += sizeof(float); } - ofs += sizeof(float); - } - // direction - if (mVertexFormatDirection) { - for (int k=0; k<4; ++k) { - float* pDirection = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - pDirection[0] = particle.mDirection.x; - pDirection[1] = particle.mDirection.y; - pDirection[2] = particle.mDirection.z; + // direction + if (mVertexFormatDirection) + { + for (int k = 0; k < 4; ++k) + { + float *pDirection = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + pDirection[0] = particle.mDirection.x; + pDirection[1] = particle.mDirection.y; + pDirection[2] = particle.mDirection.z; + } + ofs += sizeof(float) * 3; } - ofs += sizeof(float) * 3; - } - - // time to live - if (mVertexFormatTTL) { - for (int k=0; k<4; ++k) { - float* pTime = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - *pTime = particle.mTimeToLive; + + // time to live + if (mVertexFormatTTL) + { + for (int k = 0; k < 4; ++k) + { + float *pTime = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + *pTime = particle.mTimeToLive; + } + ofs += sizeof(float); } - ofs += sizeof(float); - } - - // total time to live - if (mVertexFormatTTL) { - for (int k=0; k<4; ++k) { - float* pTime = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - *pTime = particle.mTotalTimeToLive; + + // total time to live + if (mVertexFormatTTL) + { + for (int k = 0; k < 4; ++k) + { + float *pTime = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + *pTime = particle.mTotalTimeToLive; + } + ofs += sizeof(float); } - ofs += sizeof(float); - } - - // time fragment - if (mVertexFormatTimeFragment) { - float fFrag = particle.mTimeToLive / particle.mTotalTimeToLive; - for (int k=0; k<4; ++k) { - float* pTime = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - *pTime = fFrag; + + // time fragment + if (mVertexFormatTimeFragment) + { + float fFrag = particle.mTimeToLive / particle.mTotalTimeToLive; + for (int k = 0; k < 4; ++k) + { + float *pTime = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + *pTime = fFrag; + } + ofs += sizeof(float); } - ofs += sizeof(float); - } - - // inverse time fragment - if (mVertexFormatTimeFragmentInv) { - float fFrag = 1.0f - particle.mTimeToLive / particle.mTotalTimeToLive; - for (int k=0; k<4; ++k) { - float* pTime = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - *pTime = fFrag; + + // inverse time fragment + if (mVertexFormatTimeFragmentInv) + { + float fFrag = 1.0f - particle.mTimeToLive / particle.mTotalTimeToLive; + for (int k = 0; k < 4; ++k) + { + float *pTime = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + *pTime = fFrag; + } + ofs += sizeof(float); } - ofs += sizeof(float); - } - // custom parameter - ParticleCustomParam* pCustom = static_cast(particle.getVisualData()); - const Vector4& customData = pCustom != NULL ? pCustom->paramValue : Vector4::ZERO; - for (int k=0; k<4; ++k) { - float* pParams = reinterpret_cast(pDataVB + k*mVertexSize + ofs); - pParams[0] = customData.x; - pParams[1] = customData.y; - pParams[2] = customData.z; - pParams[3] = customData.w; - } - ofs += sizeof(float) * 4; + // custom parameter + ParticleCustomParam *pCustom = static_cast(particle.getVisualData()); + const Vector4 & customData = pCustom != NULL ? pCustom->paramValue : Vector4::ZERO; + for (int k = 0; k < 4; ++k) + { + float *pParams = reinterpret_cast(pDataVB + k * mVertexSize + ofs); + pParams[0] = customData.x; + pParams[1] = customData.y; + pParams[2] = customData.z; + pParams[3] = customData.w; + } + ofs += sizeof(float) * 4; - // if you see this assert some informations were not added into vertex buffer !!! - assert(ofs == mVertexSize); -} + // if you see this assert some informations were not added into vertex buffer !!! + assert(ofs == mVertexSize); + } -/************************************************************************/ -/* ShaderParticleRendererFactory implementation */ -/************************************************************************/ -const String& ShaderParticleRendererFactory::getType() const -{ - return rendererTypeName; -} + /************************************************************************/ + /* ShaderParticleRendererFactory implementation */ + /************************************************************************/ + const String &ShaderParticleRendererFactory::getType() const + { + return rendererTypeName; + } -////////////////////////////////////////////////////////////////////////// -ParticleSystemRenderer* ShaderParticleRendererFactory::createInstance( const String& name ) -{ - return OGRE_NEW ShaderParticleRenderer(); -} + ////////////////////////////////////////////////////////////////////////// + ParticleSystemRenderer *ShaderParticleRendererFactory::createInstance(const String &name) + { + return OGRE_NEW ShaderParticleRenderer(); + } -////////////////////////////////////////////////////////////////////////// -void ShaderParticleRendererFactory::destroyInstance( ParticleSystemRenderer* inst) -{ - OGRE_DELETE inst; -} + ////////////////////////////////////////////////////////////////////////// + void ShaderParticleRendererFactory::destroyInstance(ParticleSystemRenderer *inst) + { + OGRE_DELETE inst; + } -/************************************************************************/ -/* ParamCommand implementations */ -/************************************************************************/ -String ShaderParticleRenderer::CmdVertexFormatColour::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatColour() ); -} -void ShaderParticleRenderer::CmdVertexFormatColour::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatColour( - StringConverter::parseBool(val)); -} -void ShaderParticleRenderer::setRenderQueueGroupAndPriority(Ogre::uint8,Ogre::ushort) -{ -} + /************************************************************************/ + /* ParamCommand implementations */ + /************************************************************************/ + String ShaderParticleRenderer::CmdVertexFormatColour::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatColour()); + } + void ShaderParticleRenderer::CmdVertexFormatColour::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatColour(StringConverter::parseBool(val)); + } + void ShaderParticleRenderer::setRenderQueueGroupAndPriority(Ogre::uint8, Ogre::ushort) + { + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatTexture::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatTexture() ); -} -void ShaderParticleRenderer::CmdVertexFormatTexture::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatTexture( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatTexture::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatTexture()); + } + void ShaderParticleRenderer::CmdVertexFormatTexture::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatTexture(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatSize::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatSize() ); -} -void ShaderParticleRenderer::CmdVertexFormatSize::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatSize( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatSize::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatSize()); + } + void ShaderParticleRenderer::CmdVertexFormatSize::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatSize(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatRotation::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatRotation() ); -} -void ShaderParticleRenderer::CmdVertexFormatRotation::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatRotation( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatRotation::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatRotation()); + } + void ShaderParticleRenderer::CmdVertexFormatRotation::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatRotation(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatRotationSpeed::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatRotationSpeed() ); -} -void ShaderParticleRenderer::CmdVertexFormatRotationSpeed::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatRotationSpeed( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatRotationSpeed::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatRotationSpeed()); + } + void ShaderParticleRenderer::CmdVertexFormatRotationSpeed::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatRotationSpeed(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatDirection::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatDirection() ); -} -void ShaderParticleRenderer::CmdVertexFormatDirection::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatDirection( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatDirection::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatDirection()); + } + void ShaderParticleRenderer::CmdVertexFormatDirection::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatDirection(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatTTL::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatTTL() ); -} -void ShaderParticleRenderer::CmdVertexFormatTTL::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatTTL( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatTTL::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatTTL()); + } + void ShaderParticleRenderer::CmdVertexFormatTTL::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatTTL(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatTotalTTL::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatTotalTTL() ); -} -void ShaderParticleRenderer::CmdVertexFormatTotalTTL::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatTotalTTL( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatTotalTTL::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatTotalTTL()); + } + void ShaderParticleRenderer::CmdVertexFormatTotalTTL::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatTotalTTL(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatTimeFrag::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatTimeFragment() ); -} -void ShaderParticleRenderer::CmdVertexFormatTimeFrag::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatTimeFragment( - StringConverter::parseBool(val)); -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatTimeFrag::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatTimeFragment()); + } + void ShaderParticleRenderer::CmdVertexFormatTimeFrag::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatTimeFragment(StringConverter::parseBool(val)); + } -////////////////////////////////////////////////////////////////////////// -String ShaderParticleRenderer::CmdVertexFormatTimeFragInv::doGet(const void* target) const -{ - return StringConverter::toString( - static_cast(target)->getVertexFormatTimeFragmentInv() ); -} -void ShaderParticleRenderer::CmdVertexFormatTimeFragInv::doSet(void* target, const String& val) -{ - static_cast(target)->setVertexFormatTimeFragmentInv( - StringConverter::parseBool(val)); -} -} + ////////////////////////////////////////////////////////////////////////// + String ShaderParticleRenderer::CmdVertexFormatTimeFragInv::doGet(const void *target) const + { + return StringConverter::toString(static_cast(target)->getVertexFormatTimeFragmentInv()); + } + void ShaderParticleRenderer::CmdVertexFormatTimeFragInv::doSet(void *target, const String &val) + { + static_cast(target)->setVertexFormatTimeFragmentInv(StringConverter::parseBool(val)); + } +} // namespace Ogre diff --git a/source/main/gfx/particle/OgreShaderParticleRenderer.h b/source/main/gfx/particle/OgreShaderParticleRenderer.h index 16d6eb25ec..a449abb5f2 100644 --- a/source/main/gfx/particle/OgreShaderParticleRenderer.h +++ b/source/main/gfx/particle/OgreShaderParticleRenderer.h @@ -1,12 +1,12 @@ #pragma once #ifndef __OGRE_SHADER_PARTICLE_RENDERER_H__ -#define __OGRE_SHADER_PARTICLE_RENDERER_H__ + #define __OGRE_SHADER_PARTICLE_RENDERER_H__ + #include + #include -#include -#include - -namespace Ogre { +namespace Ogre +{ /** Specialisation of ParticleSystemRenderer to render particles using a custom shaders. @remarks @@ -16,44 +16,46 @@ namespace Ogre { */ class ShaderParticleRenderer : public ParticleSystemRenderer, public Renderable { - protected: + protected: /// rendering data - MaterialPtr mMaterial; ///< material for this renderable - VertexData* mVertexData; - IndexData* mIndexData; - uint8 mRenderQueueID; + MaterialPtr mMaterial; ///< material for this renderable + VertexData *mVertexData; + IndexData * mIndexData; + uint8 mRenderQueueID; /// vertex format for particles - /// * position will be always present in vertex format (don't need to specify) - float4 - w component is vertex index (0-3) + /// * position will be always present in vertex format (don't need to specify) - float4 - w component is vertex index + /// (0-3) /// * following informations will be packed into 1 texture coord: /// mVertexFormatRotation + mVertexFormatRotationSpeed = float2 /// mVertexFormatTTL + mVertexFormatTotalTTL + mVertexFormatTimeFragment + mVertexFormatTimeFragmentInv = float4 /// * mVertexFormatColour will be set as diffuse colour in vertex declaration /// * last tex coord is custom particle parameters defined by emitters (always float4) - bool mVertexFormatColour; ///< particle colour (float4) - bool mVertexFormatTexture; ///< true if particles use texture (float2) - bool mVertexFormatSize; ///< particle size (width and height - float2) - bool mVertexFormatRotation; ///< particle rotation (radians - float1) - bool mVertexFormatRotationSpeed; ///< particle rotation speed (radians/s - float1) - bool mVertexFormatDirection; ///< particle direction (float3) - bool mVertexFormatTTL; ///< particle ttl (float1) - bool mVertexFormatTotalTTL; ///< particle total ttl (float1) - bool mVertexFormatTimeFragment; ///< particle time fragment (ttl / total ttl) (float1) (value 0.0f - 1.0f) - bool mVertexFormatTimeFragmentInv; ///< particle inverse time fragment (1.0f - ttl / total ttl) (float1) (value 0.0f - 1.0f) - size_t mVertexSize; - Vector2 mTexCoordTable[4]; ///< default texture coordinates + bool mVertexFormatColour; ///< particle colour (float4) + bool mVertexFormatTexture; ///< true if particles use texture (float2) + bool mVertexFormatSize; ///< particle size (width and height - float2) + bool mVertexFormatRotation; ///< particle rotation (radians - float1) + bool mVertexFormatRotationSpeed; ///< particle rotation speed (radians/s - float1) + bool mVertexFormatDirection; ///< particle direction (float3) + bool mVertexFormatTTL; ///< particle ttl (float1) + bool mVertexFormatTotalTTL; ///< particle total ttl (float1) + bool mVertexFormatTimeFragment; ///< particle time fragment (ttl / total ttl) (float1) (value 0.0f - 1.0f) + bool mVertexFormatTimeFragmentInv; ///< particle inverse time fragment (1.0f - ttl / total ttl) (float1) (value 0.0f + ///< - 1.0f) + size_t mVertexSize; + Vector2 mTexCoordTable[4]; ///< default texture coordinates /// other informations - Vector2 mDefaultParticleSize; ///< default particle size - Node* mParentNode; ///< parent node for particle system - used for world transformation - SortMode mSortMode; ///< particle sorting - mutable LightList mLightList; ///< light list for renderable - mutable ulong mLightListUpdated; ///< indicator if we need update light list - Real mRadius; ///< maximum distance between particles and parent node - bool mParentIsTagPoint; ///< true if parent node is tag point - bool mKeepInLocalSpace; ///< control transformation matrix for particles - - public: + Vector2 mDefaultParticleSize; ///< default particle size + Node * mParentNode; ///< parent node for particle system - used for world transformation + SortMode mSortMode; ///< particle sorting + mutable LightList mLightList; ///< light list for renderable + mutable ulong mLightListUpdated; ///< indicator if we need update light list + Real mRadius; ///< maximum distance between particles and parent node + bool mParentIsTagPoint; ///< true if parent node is tag point + bool mKeepInLocalSpace; ///< control transformation matrix for particles + + public: ShaderParticleRenderer(); virtual ~ShaderParticleRenderer(); @@ -62,127 +64,188 @@ namespace Ogre { /// diffuse colour class _OgrePrivate CmdVertexFormatColour : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// general texture coord class _OgrePrivate CmdVertexFormatTexture : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// particle size class _OgrePrivate CmdVertexFormatSize : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// rotation class _OgrePrivate CmdVertexFormatRotation : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// rotation speed (rad/s) class _OgrePrivate CmdVertexFormatRotationSpeed : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// direction class _OgrePrivate CmdVertexFormatDirection : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// time-to-live class _OgrePrivate CmdVertexFormatTTL : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// total time-to-live class _OgrePrivate CmdVertexFormatTotalTTL : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// TTL / total_TTL class _OgrePrivate CmdVertexFormatTimeFrag : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; /// 1.0f - TTL / total_TTL class _OgrePrivate CmdVertexFormatTimeFragInv : public ParamCommand { - public: - String doGet(const void* target) const; - void doSet(void* target, const String& val); + public: + String doGet(const void *target) const; + void doSet(void *target, const String &val); }; ////////////////////////////////////////////////////////////////////////// // getters / setters - void setVertexFormatColour(bool bUse) { mVertexFormatColour = bUse; } - bool getVertexFormatColour() const { return mVertexFormatColour; } + void setVertexFormatColour(bool bUse) + { + mVertexFormatColour = bUse; + } + bool getVertexFormatColour() const + { + return mVertexFormatColour; + } - void setVertexFormatTexture(bool bUse) { mVertexFormatTexture = bUse; } - bool getVertexFormatTexture() const { return mVertexFormatTexture; } + void setVertexFormatTexture(bool bUse) + { + mVertexFormatTexture = bUse; + } + bool getVertexFormatTexture() const + { + return mVertexFormatTexture; + } - void setVertexFormatSize(bool bUse) { mVertexFormatSize = bUse; } - bool getVertexFormatSize() const { return mVertexFormatSize; } + void setVertexFormatSize(bool bUse) + { + mVertexFormatSize = bUse; + } + bool getVertexFormatSize() const + { + return mVertexFormatSize; + } - void setVertexFormatRotation(bool bUse) { mVertexFormatRotation = bUse; } - bool getVertexFormatRotation() const { return mVertexFormatRotation; } + void setVertexFormatRotation(bool bUse) + { + mVertexFormatRotation = bUse; + } + bool getVertexFormatRotation() const + { + return mVertexFormatRotation; + } - void setVertexFormatRotationSpeed(bool bUse) { mVertexFormatRotationSpeed = bUse; } - bool getVertexFormatRotationSpeed() const { return mVertexFormatRotationSpeed; } + void setVertexFormatRotationSpeed(bool bUse) + { + mVertexFormatRotationSpeed = bUse; + } + bool getVertexFormatRotationSpeed() const + { + return mVertexFormatRotationSpeed; + } - void setVertexFormatDirection(bool bUse) { mVertexFormatDirection = bUse; } - bool getVertexFormatDirection() const { return mVertexFormatDirection; } + void setVertexFormatDirection(bool bUse) + { + mVertexFormatDirection = bUse; + } + bool getVertexFormatDirection() const + { + return mVertexFormatDirection; + } - void setVertexFormatTTL(bool bUse) { mVertexFormatTTL = bUse; } - bool getVertexFormatTTL() const { return mVertexFormatTTL; } + void setVertexFormatTTL(bool bUse) + { + mVertexFormatTTL = bUse; + } + bool getVertexFormatTTL() const + { + return mVertexFormatTTL; + } - void setVertexFormatTotalTTL(bool bUse) { mVertexFormatTotalTTL = bUse; } - bool getVertexFormatTotalTTL() const { return mVertexFormatTotalTTL; } + void setVertexFormatTotalTTL(bool bUse) + { + mVertexFormatTotalTTL = bUse; + } + bool getVertexFormatTotalTTL() const + { + return mVertexFormatTotalTTL; + } - void setVertexFormatTimeFragment(bool bUse) { mVertexFormatTimeFragment = bUse; } - bool getVertexFormatTimeFragment() const { return mVertexFormatTimeFragment; } + void setVertexFormatTimeFragment(bool bUse) + { + mVertexFormatTimeFragment = bUse; + } + bool getVertexFormatTimeFragment() const + { + return mVertexFormatTimeFragment; + } - void setVertexFormatTimeFragmentInv(bool bUse) { mVertexFormatTimeFragmentInv = bUse; } - bool getVertexFormatTimeFragmentInv() const { return mVertexFormatTimeFragmentInv; } + void setVertexFormatTimeFragmentInv(bool bUse) + { + mVertexFormatTimeFragmentInv = bUse; + } + bool getVertexFormatTimeFragmentInv() const + { + return mVertexFormatTimeFragmentInv; + } ////////////////////////////////////////////////////////////////////////// // ParticleSystemRenderer interface /// @copydoc ParticleSystemRenderer::getType - virtual const String& getType(void) const; + virtual const String &getType(void) const; /// @copydoc ParticleSystemRenderer::_updateRenderQueue - virtual void _updateRenderQueue(RenderQueue* queue, Ogre::list::type& currentParticles, bool cullIndividually); + virtual void _updateRenderQueue(RenderQueue *queue, Ogre::list::type ¤tParticles, + bool cullIndividually); /// @copydoc ParticleSystemRenderer::visitRenderables - virtual void visitRenderables(Renderable::Visitor* visitor, bool debugRenderables = false); + virtual void visitRenderables(Renderable::Visitor *visitor, bool debugRenderables = false); /// @copydoc ParticleSystemRenderer::_setMaterial - virtual void _setMaterial(MaterialPtr& mat); + virtual void _setMaterial(MaterialPtr &mat); /// @copydoc ParticleSystemRenderer::_notifyCurrentCamera - virtual void _notifyCurrentCamera(Camera* cam); + virtual void _notifyCurrentCamera(Camera *cam); /// @copydoc ParticleSystemRenderer::_notifyParticleRotated virtual void _notifyParticleRotated(void); /// @copydoc ParticleSystemRenderer::_notifyParticleResized @@ -190,13 +253,13 @@ namespace Ogre { /// @copydoc ParticleSystemRenderer::_notifyParticleQuota virtual void _notifyParticleQuota(size_t quota); /// @copydoc ParticleSystemRenderer::_notifyAttached - virtual void _notifyAttached(Node* parent, bool isTagPoint = false); + virtual void _notifyAttached(Node *parent, bool isTagPoint = false); /// @copydoc ParticleSystemRenderer::_notifyDefaultDimensions virtual void _notifyDefaultDimensions(Real width, Real height); /// @copydoc ParticleSystemRenderer::_createVisualData - virtual ParticleVisualData* _createVisualData(void); + virtual ParticleVisualData *_createVisualData(void); /// @copydoc ParticleSystemRenderer::_destroyVisualData - virtual void _destroyVisualData(ParticleVisualData* vis); + virtual void _destroyVisualData(ParticleVisualData *vis); /// @copydoc ParticleSystemRenderer::setRenderQueueGroup virtual void setRenderQueueGroup(uint8 queueID); /// @copydoc ParticleSystemRenderer::setKeepParticlesInLocalSpace @@ -207,53 +270,55 @@ namespace Ogre { ////////////////////////////////////////////////////////////////////////// // Ogre::Renderable interface /// @copydoc Renderable::getMaterial - virtual const MaterialPtr& getMaterial(void) const; + virtual const MaterialPtr &getMaterial(void) const; /// @copydoc Renderable::getRenderOperation - virtual void getRenderOperation(RenderOperation& op); + virtual void getRenderOperation(RenderOperation &op); /// @copydoc Renderable::getNumWorldTransforms - //virtual unsigned short getNumWorldTransforms(void) const; + // virtual unsigned short getNumWorldTransforms(void) const; /// @copydoc Renderable::getWorldTransforms - virtual void getWorldTransforms(Matrix4* xform) const; + virtual void getWorldTransforms(Matrix4 *xform) const; /// @copydoc Renderable::getSquaredViewDepth - virtual Real getSquaredViewDepth(const Camera* cam) const; + virtual Real getSquaredViewDepth(const Camera *cam) const; /// @copydoc Renderable::getLights - virtual const LightList& getLights(void) const; + virtual const LightList &getLights(void) const; - private: + private: const String rendererTypeName = "shader"; /// allocate hardware buffers and prepare them for filling particles bool allocateBuffers(size_t iNumParticles); /// add particle to vertex buffer - void addParticle(uint8* pDataVB, const Particle& particle) const; - void setRenderQueueGroupAndPriority(Ogre::uint8,Ogre::ushort); - protected: - static CmdVertexFormatColour msVertexFmtColour; - static CmdVertexFormatTexture msVertexFmtTexture; - static CmdVertexFormatSize msVertexFmtSize; - static CmdVertexFormatRotation msVertexFmtRotation; - static CmdVertexFormatRotationSpeed msVertexFmtRotationSpeed; - static CmdVertexFormatDirection msVertexFmtDirection; - static CmdVertexFormatTTL msVertexFmtTTL; - static CmdVertexFormatTotalTTL msVertexFmtTotalTTL; - static CmdVertexFormatTimeFrag msVertexFmtTimeFrag; - static CmdVertexFormatTimeFragInv msVertexFmtTimeFragInv; + void addParticle(uint8 *pDataVB, const Particle &particle) const; + void setRenderQueueGroupAndPriority(Ogre::uint8, Ogre::ushort); + + protected: + static CmdVertexFormatColour msVertexFmtColour; + static CmdVertexFormatTexture msVertexFmtTexture; + static CmdVertexFormatSize msVertexFmtSize; + static CmdVertexFormatRotation msVertexFmtRotation; + static CmdVertexFormatRotationSpeed msVertexFmtRotationSpeed; + static CmdVertexFormatDirection msVertexFmtDirection; + static CmdVertexFormatTTL msVertexFmtTTL; + static CmdVertexFormatTotalTTL msVertexFmtTotalTTL; + static CmdVertexFormatTimeFrag msVertexFmtTimeFrag; + static CmdVertexFormatTimeFragInv msVertexFmtTimeFragInv; }; /// Factory class for ShaderParticleRenderer class ShaderParticleRendererFactory : public ParticleSystemRendererFactory { - public: + public: /// @copydoc FactoryObj::getType - const String& getType() const; + const String &getType() const; /// @copydoc FactoryObj::createInstance - ParticleSystemRenderer* createInstance( const String& name ); + ParticleSystemRenderer *createInstance(const String &name); /// @copydoc FactoryObj::destroyInstance - void destroyInstance( ParticleSystemRenderer* inst); - private: + void destroyInstance(ParticleSystemRenderer *inst); + + private: const String rendererTypeName = "shader"; }; -} +} // namespace Ogre #endif // __OGRE_SHADER_PARTICLE_RENDERER_H__ diff --git a/source/main/gfx/skyx/AtmosphereManager.cpp b/source/main/gfx/skyx/AtmosphereManager.cpp index 08faf3f3f1..f9492b05af 100644 --- a/source/main/gfx/skyx/AtmosphereManager.cpp +++ b/source/main/gfx/skyx/AtmosphereManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -23,243 +23,228 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "AtmosphereManager.h" -#include "SkyX.h" - #include "GPUManager.h" +#include "SkyX.h" namespace SkyX { - AtmosphereManager::AtmosphereManager(SkyX *s) - : mSkyX(s) - , mOptions(Options()) - { - } - - AtmosphereManager::~AtmosphereManager() - { - } - - void AtmosphereManager::_update(const Options& NewOptions, const bool& ForceToUpdateAll) - { - GPUManager *mGPUManager = mSkyX->getGPUManager(); - - if (NewOptions.InnerRadius != mOptions.InnerRadius || - NewOptions.OuterRadius != mOptions.OuterRadius || - ForceToUpdateAll) - { - mOptions.InnerRadius = NewOptions.InnerRadius; - mOptions.OuterRadius = NewOptions.OuterRadius; - - float Scale = 1.0f / (mOptions.OuterRadius - mOptions.InnerRadius), - ScaleDepth = (mOptions.OuterRadius - mOptions.InnerRadius) / 2.0f, - ScaleOverScaleDepth = Scale / ScaleDepth; - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uInnerRadius", mOptions.InnerRadius); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uCameraPos", Ogre::Vector3(0, mOptions.InnerRadius + (mOptions.OuterRadius-mOptions.InnerRadius)*mOptions.HeightPosition, 0)); - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScale", Scale); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScaleDepth", ScaleDepth); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScaleOverScaleDepth", ScaleOverScaleDepth); - } - - if (NewOptions.HeightPosition != mOptions.HeightPosition || - ForceToUpdateAll) - { - mOptions.HeightPosition = NewOptions.HeightPosition; - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uCameraPos", Ogre::Vector3(0, mOptions.InnerRadius + (mOptions.OuterRadius-mOptions.InnerRadius)*mOptions.HeightPosition, 0)); - } - - if (NewOptions.RayleighMultiplier != mOptions.RayleighMultiplier || - NewOptions.SunIntensity != mOptions.SunIntensity || - ForceToUpdateAll) - { - mOptions.RayleighMultiplier = NewOptions.RayleighMultiplier; - - float Kr4PI = mOptions.RayleighMultiplier * 4.0f * Ogre::Math::PI, - KrESun = mOptions.RayleighMultiplier * mOptions.SunIntensity; + AtmosphereManager::AtmosphereManager(SkyX *s) : mSkyX(s), mOptions(Options()) + { + } + + AtmosphereManager::~AtmosphereManager() + { + } + + void AtmosphereManager::_update(const Options &NewOptions, const bool &ForceToUpdateAll) + { + GPUManager *mGPUManager = mSkyX->getGPUManager(); + + if (NewOptions.InnerRadius != mOptions.InnerRadius || NewOptions.OuterRadius != mOptions.OuterRadius || ForceToUpdateAll) + { + mOptions.InnerRadius = NewOptions.InnerRadius; + mOptions.OuterRadius = NewOptions.OuterRadius; + + float Scale = 1.0f / (mOptions.OuterRadius - mOptions.InnerRadius), + ScaleDepth = (mOptions.OuterRadius - mOptions.InnerRadius) / 2.0f, ScaleOverScaleDepth = Scale / ScaleDepth; + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uInnerRadius", mOptions.InnerRadius); + mGPUManager->setGpuProgramParameter( + GPUManager::GPUP_VERTEX, "uCameraPos", + Ogre::Vector3(0, mOptions.InnerRadius + (mOptions.OuterRadius - mOptions.InnerRadius) * mOptions.HeightPosition, + 0)); + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScale", Scale); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScaleDepth", ScaleDepth); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScaleOverScaleDepth", ScaleOverScaleDepth); + } + + if (NewOptions.HeightPosition != mOptions.HeightPosition || ForceToUpdateAll) + { + mOptions.HeightPosition = NewOptions.HeightPosition; + + mGPUManager->setGpuProgramParameter( + GPUManager::GPUP_VERTEX, "uCameraPos", + Ogre::Vector3(0, mOptions.InnerRadius + (mOptions.OuterRadius - mOptions.InnerRadius) * mOptions.HeightPosition, + 0)); + } + + if (NewOptions.RayleighMultiplier != mOptions.RayleighMultiplier || NewOptions.SunIntensity != mOptions.SunIntensity || + ForceToUpdateAll) + { + mOptions.RayleighMultiplier = NewOptions.RayleighMultiplier; + + float Kr4PI = mOptions.RayleighMultiplier * 4.0f * Ogre::Math::PI, + KrESun = mOptions.RayleighMultiplier * mOptions.SunIntensity; mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKr4PI", Kr4PI); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKrESun", KrESun); - } + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKrESun", KrESun); + } - if (NewOptions.MieMultiplier != mOptions.MieMultiplier || - NewOptions.SunIntensity != mOptions.SunIntensity || - ForceToUpdateAll) - { - mOptions.MieMultiplier = NewOptions.MieMultiplier; + if (NewOptions.MieMultiplier != mOptions.MieMultiplier || NewOptions.SunIntensity != mOptions.SunIntensity || + ForceToUpdateAll) + { + mOptions.MieMultiplier = NewOptions.MieMultiplier; - float Km4PI = mOptions.MieMultiplier * 4.0f * Ogre::Math::PI, - KmESun = mOptions.MieMultiplier * mOptions.SunIntensity; + float Km4PI = mOptions.MieMultiplier * 4.0f * Ogre::Math::PI, KmESun = mOptions.MieMultiplier * mOptions.SunIntensity; mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKm4PI", Km4PI); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKmESun", KmESun, false); - } - - if (NewOptions.NumberOfSamples != mOptions.NumberOfSamples || - ForceToUpdateAll) - { - mOptions.NumberOfSamples = NewOptions.NumberOfSamples; - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uNumberOfSamples", mOptions.NumberOfSamples); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uSamples", static_cast(mOptions.NumberOfSamples)); - } - - if (NewOptions.WaveLength != mOptions.WaveLength || - ForceToUpdateAll) - { - mOptions.WaveLength = NewOptions.WaveLength; - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uInvWaveLength", - Ogre::Vector3(1.0f / Ogre::Math::Pow(mOptions.WaveLength.x, 4.0f), - 1.0f / Ogre::Math::Pow(mOptions.WaveLength.y, 4.0f), - 1.0f / Ogre::Math::Pow(mOptions.WaveLength.z, 4.0f))); - } - - if (NewOptions.G != mOptions.G || - ForceToUpdateAll) - { - mOptions.G = NewOptions.G; - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uG", mOptions.G, false); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uG2", mOptions.G*mOptions.G, false); - } - - if (NewOptions.Exposure != mOptions.Exposure || - ForceToUpdateAll) - { - mOptions.Exposure = NewOptions.Exposure; - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uExposure", mOptions.Exposure); - } - - mSkyX->getCloudsManager()->update(); - } - - const float AtmosphereManager::_scale(const float& cos, const float& uScaleDepth) const - { - float x = 1 - cos; - return uScaleDepth * Ogre::Math::Exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); - } - - const Ogre::Vector3 AtmosphereManager::getColorAt(const Ogre::Vector3& Direction) const - { - /*if (Direction.y < 0) - { - return Ogre::Vector3(0,0,0); - }*/ - - // Parameters - double Scale = 1.0f / (mOptions.OuterRadius - mOptions.InnerRadius), - ScaleDepth = (mOptions.OuterRadius - mOptions.InnerRadius) / 2.0f, - ScaleOverScaleDepth = Scale / ScaleDepth, - Kr4PI = mOptions.RayleighMultiplier * 4.0f * Ogre::Math::PI, - KrESun = mOptions.RayleighMultiplier * mOptions.SunIntensity, - Km4PI = mOptions.MieMultiplier * 4.0f * Ogre::Math::PI, - KmESun = mOptions.MieMultiplier * mOptions.SunIntensity; - - // --- Start vertex program simulation --- - Ogre::Vector3 - uLightDir = mSkyX->getController()->getSunDirection(), - v3Pos = Direction.normalisedCopy(), - uCameraPos = Ogre::Vector3(0, mOptions.InnerRadius + (mOptions.OuterRadius-mOptions.InnerRadius)*mOptions.HeightPosition, 0), - uInvWaveLength = Ogre::Vector3( - 1.0f / Ogre::Math::Pow(mOptions.WaveLength.x, 4.0f), - 1.0f / Ogre::Math::Pow(mOptions.WaveLength.y, 4.0f), - 1.0f / Ogre::Math::Pow(mOptions.WaveLength.z, 4.0f)); - - // Get the ray from the camera to the vertex, and it's length (far point) - v3Pos.y += mOptions.InnerRadius; - Ogre::Vector3 v3Ray = v3Pos - uCameraPos; - double fFar = v3Ray.length(); - v3Ray /= fFar; - - // Calculate the ray's starting position, then calculate its scattering offset - Ogre::Vector3 v3Start = uCameraPos; - double fHeight = uCameraPos.y, - fStartAngle = v3Ray.dotProduct(v3Start) / fHeight, - fDepth = Ogre::Math::Exp(ScaleOverScaleDepth * (mOptions.InnerRadius - uCameraPos.y)), - fStartOffset = fDepth * _scale(fStartAngle, ScaleDepth); - - // Init loop variables - double fSampleLength = fFar /(double)mOptions.NumberOfSamples, - fScaledLength = fSampleLength * Scale, - fHeight_, fDepth_, fLightAngle, fCameraAngle, fScatter; - Ogre::Vector3 v3SampleRay = v3Ray * fSampleLength, - v3SamplePoint = v3Start + v3SampleRay * 0.5f, - color = Ogre::Vector3(0,0,0), v3Attenuate; + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKmESun", KmESun, false); + } + + if (NewOptions.NumberOfSamples != mOptions.NumberOfSamples || ForceToUpdateAll) + { + mOptions.NumberOfSamples = NewOptions.NumberOfSamples; + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uNumberOfSamples", mOptions.NumberOfSamples); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uSamples", + static_cast(mOptions.NumberOfSamples)); + } + + if (NewOptions.WaveLength != mOptions.WaveLength || ForceToUpdateAll) + { + mOptions.WaveLength = NewOptions.WaveLength; + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uInvWaveLength", + Ogre::Vector3(1.0f / Ogre::Math::Pow(mOptions.WaveLength.x, 4.0f), + 1.0f / Ogre::Math::Pow(mOptions.WaveLength.y, 4.0f), + 1.0f / Ogre::Math::Pow(mOptions.WaveLength.z, 4.0f))); + } + + if (NewOptions.G != mOptions.G || ForceToUpdateAll) + { + mOptions.G = NewOptions.G; + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uG", mOptions.G, false); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uG2", mOptions.G * mOptions.G, false); + } + + if (NewOptions.Exposure != mOptions.Exposure || ForceToUpdateAll) + { + mOptions.Exposure = NewOptions.Exposure; + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uExposure", mOptions.Exposure); + } + + mSkyX->getCloudsManager()->update(); + } + + const float AtmosphereManager::_scale(const float &cos, const float &uScaleDepth) const + { + float x = 1 - cos; + return uScaleDepth * Ogre::Math::Exp(-0.00287 + x * (0.459 + x * (3.83 + x * (-6.80 + x * 5.25)))); + } + + const Ogre::Vector3 AtmosphereManager::getColorAt(const Ogre::Vector3 &Direction) const + { + /*if (Direction.y < 0) + { + return Ogre::Vector3(0,0,0); + }*/ + + // Parameters + double Scale = 1.0f / (mOptions.OuterRadius - mOptions.InnerRadius), + ScaleDepth = (mOptions.OuterRadius - mOptions.InnerRadius) / 2.0f, ScaleOverScaleDepth = Scale / ScaleDepth, + Kr4PI = mOptions.RayleighMultiplier * 4.0f * Ogre::Math::PI, + KrESun = mOptions.RayleighMultiplier * mOptions.SunIntensity, + Km4PI = mOptions.MieMultiplier * 4.0f * Ogre::Math::PI, KmESun = mOptions.MieMultiplier * mOptions.SunIntensity; + + // --- Start vertex program simulation --- + Ogre::Vector3 uLightDir = mSkyX->getController()->getSunDirection(), v3Pos = Direction.normalisedCopy(), + uCameraPos = Ogre::Vector3( + 0, mOptions.InnerRadius + (mOptions.OuterRadius - mOptions.InnerRadius) * mOptions.HeightPosition, 0), + uInvWaveLength = Ogre::Vector3(1.0f / Ogre::Math::Pow(mOptions.WaveLength.x, 4.0f), + 1.0f / Ogre::Math::Pow(mOptions.WaveLength.y, 4.0f), + 1.0f / Ogre::Math::Pow(mOptions.WaveLength.z, 4.0f)); + + // Get the ray from the camera to the vertex, and it's length (far point) + v3Pos.y += mOptions.InnerRadius; + Ogre::Vector3 v3Ray = v3Pos - uCameraPos; + double fFar = v3Ray.length(); + v3Ray /= fFar; + + // Calculate the ray's starting position, then calculate its scattering offset + Ogre::Vector3 v3Start = uCameraPos; + double fHeight = uCameraPos.y, fStartAngle = v3Ray.dotProduct(v3Start) / fHeight, + fDepth = Ogre::Math::Exp(ScaleOverScaleDepth * (mOptions.InnerRadius - uCameraPos.y)), + fStartOffset = fDepth * _scale(fStartAngle, ScaleDepth); + + // Init loop variables + double fSampleLength = fFar / (double)mOptions.NumberOfSamples, fScaledLength = fSampleLength * Scale, fHeight_, fDepth_, + fLightAngle, fCameraAngle, fScatter; + Ogre::Vector3 v3SampleRay = v3Ray * fSampleLength, v3SamplePoint = v3Start + v3SampleRay * 0.5f, + color = Ogre::Vector3(0, 0, 0), v3Attenuate; // Loop the ray - for (int i = 0; i < mOptions.NumberOfSamples; i++) - { - fHeight_ = v3SamplePoint.length(); - fDepth_ = Ogre::Math::Exp(ScaleOverScaleDepth * (mOptions.InnerRadius-fHeight_)); - - fLightAngle = uLightDir.dotProduct(v3SamplePoint) / fHeight_; - fCameraAngle = v3Ray.dotProduct(v3SamplePoint) / fHeight_; - - fScatter = (fStartOffset + fDepth*(_scale(fLightAngle, ScaleDepth) - _scale(fCameraAngle, ScaleDepth))); - - v3Attenuate = Ogre::Vector3( - Ogre::Math::Exp(-fScatter * (uInvWaveLength.x * Kr4PI + Km4PI)), - Ogre::Math::Exp(-fScatter * (uInvWaveLength.y * Kr4PI + Km4PI)), - Ogre::Math::Exp(-fScatter * (uInvWaveLength.z * Kr4PI + Km4PI))); - - // Accumulate color - v3Attenuate *= (fDepth_ * fScaledLength); - color += v3Attenuate; - - // Next sample point - v3SamplePoint += v3SampleRay; - } - - // Outputs - Ogre::Vector3 oRayleighColor = color * (uInvWaveLength * KrESun), - oMieColor = color * KmESun, - oDirection = uCameraPos - v3Pos; - - // --- End vertex program simulation --- - // --- Start fragment program simulation --- - - double cos = uLightDir.dotProduct(oDirection) / oDirection.length(), - cos2 = cos*cos, - rayleighPhase = 0.75 * (1.0 + 0.5*cos2), - g2 = mOptions.G*mOptions.G, - miePhase = 1.5f * ((1.0f - g2) / (2.0f + g2)) * - (1.0f + cos2) / Ogre::Math::Pow(1.0f + g2 - 2.0f * mOptions.G * cos, 1.5f); - - Ogre::Vector3 oColor; - - if (mSkyX->getLightingMode() == SkyX::LM_LDR) - { - oColor = Ogre::Vector3( - 1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.x + miePhase * oMieColor.x)), - 1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.y + miePhase * oMieColor.y)), - 1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.z + miePhase * oMieColor.z))); - - // For night rendering - oColor += Ogre::Math::Clamp(((1 - std::max(oColor.x, std::max(oColor.y, oColor.z))*10)), 0, 1) - * (Ogre::Vector3(0.05, 0.05, 0.1) - * (2-0.75f*Ogre::Math::Clamp(-uLightDir.y, 0, 1)) * Ogre::Math::Pow(1-Direction.y, 3)); - } - else - { - oColor = mOptions.Exposure * (rayleighPhase * oRayleighColor + miePhase * oMieColor); - - Ogre::Real nightmult = Ogre::Math::Clamp(((1 - std::max(oColor.x, std::max(oColor.y, oColor.z))*10)), 0, 1); - - // For night rendering - Ogre::Vector3 nightCol = Ogre::Vector3(0.05, 0.05, 0.1) * (2-0.75f*Ogre::Math::Clamp(-uLightDir.y, 0, 1)) * Ogre::Math::Pow(1-Direction.y, 3); - nightCol.x = Ogre::Math::Pow(nightCol.x, 2.2); - nightCol.y = Ogre::Math::Pow(nightCol.y, 2.2); - nightCol.z = Ogre::Math::Pow(nightCol.z, 2.2); - - oColor += nightmult*nightCol; - } - - // --- End fragment program simulation --- - - // Output color - return oColor; - } + for (int i = 0; i < mOptions.NumberOfSamples; i++) + { + fHeight_ = v3SamplePoint.length(); + fDepth_ = Ogre::Math::Exp(ScaleOverScaleDepth * (mOptions.InnerRadius - fHeight_)); + + fLightAngle = uLightDir.dotProduct(v3SamplePoint) / fHeight_; + fCameraAngle = v3Ray.dotProduct(v3SamplePoint) / fHeight_; + + fScatter = (fStartOffset + fDepth * (_scale(fLightAngle, ScaleDepth) - _scale(fCameraAngle, ScaleDepth))); + + v3Attenuate = Ogre::Vector3(Ogre::Math::Exp(-fScatter * (uInvWaveLength.x * Kr4PI + Km4PI)), + Ogre::Math::Exp(-fScatter * (uInvWaveLength.y * Kr4PI + Km4PI)), + Ogre::Math::Exp(-fScatter * (uInvWaveLength.z * Kr4PI + Km4PI))); + + // Accumulate color + v3Attenuate *= (fDepth_ * fScaledLength); + color += v3Attenuate; + + // Next sample point + v3SamplePoint += v3SampleRay; + } + + // Outputs + Ogre::Vector3 oRayleighColor = color * (uInvWaveLength * KrESun), oMieColor = color * KmESun, + oDirection = uCameraPos - v3Pos; + + // --- End vertex program simulation --- + // --- Start fragment program simulation --- + + double cos = uLightDir.dotProduct(oDirection) / oDirection.length(), cos2 = cos * cos, + rayleighPhase = 0.75 * (1.0 + 0.5 * cos2), g2 = mOptions.G * mOptions.G, + miePhase = 1.5f * ((1.0f - g2) / (2.0f + g2)) * (1.0f + cos2) / + Ogre::Math::Pow(1.0f + g2 - 2.0f * mOptions.G * cos, 1.5f); + + Ogre::Vector3 oColor; + + if (mSkyX->getLightingMode() == SkyX::LM_LDR) + { + oColor = Ogre::Vector3( + 1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.x + miePhase * oMieColor.x)), + 1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.y + miePhase * oMieColor.y)), + 1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.z + miePhase * oMieColor.z))); + + // For night rendering + oColor += Ogre::Math::Clamp(((1 - std::max(oColor.x, std::max(oColor.y, oColor.z)) * 10)), 0, 1) * + (Ogre::Vector3(0.05, 0.05, 0.1) * (2 - 0.75f * Ogre::Math::Clamp(-uLightDir.y, 0, 1)) * + Ogre::Math::Pow(1 - Direction.y, 3)); + } + else + { + oColor = mOptions.Exposure * (rayleighPhase * oRayleighColor + miePhase * oMieColor); + + Ogre::Real nightmult = + Ogre::Math::Clamp(((1 - std::max(oColor.x, std::max(oColor.y, oColor.z)) * 10)), 0, 1); + + // For night rendering + Ogre::Vector3 nightCol = Ogre::Vector3(0.05, 0.05, 0.1) * + (2 - 0.75f * Ogre::Math::Clamp(-uLightDir.y, 0, 1)) * + Ogre::Math::Pow(1 - Direction.y, 3); + nightCol.x = Ogre::Math::Pow(nightCol.x, 2.2); + nightCol.y = Ogre::Math::Pow(nightCol.y, 2.2); + nightCol.z = Ogre::Math::Pow(nightCol.z, 2.2); + + oColor += nightmult * nightCol; + } + + // --- End fragment program simulation --- + + // Output color + return oColor; + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/AtmosphereManager.h b/source/main/gfx/skyx/AtmosphereManager.h index 2b1581d3bc..934f75a46b 100644 --- a/source/main/gfx/skyx/AtmosphereManager.h +++ b/source/main/gfx/skyx/AtmosphereManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -28,146 +28,125 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - class SkyX; - - class AtmosphereManager - { - public: - - /** Atmosphere options - */ - struct Options - { - /// Inner atmosphere radius - Ogre::Real InnerRadius; - /// Outer atmosphere radius - Ogre::Real OuterRadius; - /// Height position, in [0, 1] range, 0=InnerRadius, 1=OuterRadius - Ogre::Real HeightPosition; - - /// Rayleigh multiplier - Ogre::Real RayleighMultiplier; - /// Mie multiplier - Ogre::Real MieMultiplier; - /// Sun intensity - Ogre::Real SunIntensity; - - /// WaveLength for RGB channels - Ogre::Vector3 WaveLength; - - /// Phase function - Ogre::Real G; - - /// Exposure coeficient - Ogre::Real Exposure; - - /// Number of samples - int NumberOfSamples; - - /** Default constructor - */ - Options() - : InnerRadius(9.77501f) - , OuterRadius(10.2963f) - , HeightPosition(0.01f) - , RayleighMultiplier(0.0022f) - , MieMultiplier(0.000675f) - , SunIntensity(30) - , WaveLength(Ogre::Vector3(0.57f, 0.54f, 0.44f)) - , G(-0.991f) - , Exposure(2.0f) - , NumberOfSamples(4) - { - } - - /** Constructor + class SkyX; + + class AtmosphereManager + { + public: + /** Atmosphere options + */ + struct Options + { + /// Inner atmosphere radius + Ogre::Real InnerRadius; + /// Outer atmosphere radius + Ogre::Real OuterRadius; + /// Height position, in [0, 1] range, 0=InnerRadius, 1=OuterRadius + Ogre::Real HeightPosition; + + /// Rayleigh multiplier + Ogre::Real RayleighMultiplier; + /// Mie multiplier + Ogre::Real MieMultiplier; + /// Sun intensity + Ogre::Real SunIntensity; + + /// WaveLength for RGB channels + Ogre::Vector3 WaveLength; + + /// Phase function + Ogre::Real G; + + /// Exposure coeficient + Ogre::Real Exposure; + + /// Number of samples + int NumberOfSamples; + + /** Default constructor + */ + Options() + : InnerRadius(9.77501f), OuterRadius(10.2963f), HeightPosition(0.01f), RayleighMultiplier(0.0022f), + MieMultiplier(0.000675f), SunIntensity(30), WaveLength(Ogre::Vector3(0.57f, 0.54f, 0.44f)), G(-0.991f), + Exposure(2.0f), NumberOfSamples(4) + { + } + + /** Constructor @param _InnerRadius Inner atmosphere radius - @param _OuterRadius Outer atmosphere radius - @param _HeightPosition Height position, in [0, 1] range, 0=InnerRadius, 1=OuterRadius - @param _RayleighMultiplier Rayleigh multiplier - @param _MieMultiplier Mie multiplier - @param _SunIntensity Sun intensity - @param _WaveLength Wave length for RGB channels - @param _G Phase function - @param _Exposure Exposure - @param _NumerOfSamples Number of samples - */ - Options(const Ogre::Real& _InnerRadius, - const Ogre::Real& _OuterRadius, - const Ogre::Real& _HeightPosition, - const Ogre::Real& _RayleighMultiplier, - const Ogre::Real& _MieMultiplier, - const Ogre::Real& _SunIntensity, - const Ogre::Vector3& _WaveLength, - const Ogre::Real& _G, - const Ogre::Real& _Exposure, - const int& _NumerOfSamples) - : InnerRadius(_InnerRadius) - , OuterRadius(_OuterRadius) - , HeightPosition(_HeightPosition) - , RayleighMultiplier(_RayleighMultiplier) - , MieMultiplier(_MieMultiplier) - , SunIntensity(_SunIntensity) - , WaveLength(_WaveLength) - , G(_G) - , Exposure(_Exposure) - , NumberOfSamples(_NumerOfSamples) - { - } - }; - - /** Constructor - @param s Parent SkyX pointer - */ - AtmosphereManager(SkyX *s); - - /** Destructor - */ - ~AtmosphereManager(); - - /** Set options - @param _Options New options - */ - inline void setOptions(const Options& _Options) - { - _update(_Options); - } - - /** Get current options - @return Current options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - /** Get current atmosphere color at the given direction - @param Direction *Normalised* direction - @return Atmosphere color at the especified direction - */ - const Ogre::Vector3 getColorAt(const Ogre::Vector3& Direction) const; - - /** Update atmoshpere - @param NewOptions Update only the differences between actual parameters and new ones. - @param ForceToUpdateAll Forces to upload all current parameters to skyx material. - @remarks Current options parameters are updated if needed. - */ - void _update(const Options& NewOptions, const bool& ForceToUpdateAll = false); - - private: - /** Shader scale funtion - @param cos Cos - @param uScaleDepth Scale Depth - @return Scale - */ - const float _scale(const float& cos, const float& uScaleDepth) const; - - /// Our options - Options mOptions; - - /// SkyX parent pointer - SkyX *mSkyX; - }; -} + @param _OuterRadius Outer atmosphere radius + @param _HeightPosition Height position, in [0, 1] range, 0=InnerRadius, 1=OuterRadius + @param _RayleighMultiplier Rayleigh multiplier + @param _MieMultiplier Mie multiplier + @param _SunIntensity Sun intensity + @param _WaveLength Wave length for RGB channels + @param _G Phase function + @param _Exposure Exposure + @param _NumerOfSamples Number of samples + */ + Options(const Ogre::Real &_InnerRadius, const Ogre::Real &_OuterRadius, const Ogre::Real &_HeightPosition, + const Ogre::Real &_RayleighMultiplier, const Ogre::Real &_MieMultiplier, const Ogre::Real &_SunIntensity, + const Ogre::Vector3 &_WaveLength, const Ogre::Real &_G, const Ogre::Real &_Exposure, + const int &_NumerOfSamples) + : InnerRadius(_InnerRadius), OuterRadius(_OuterRadius), HeightPosition(_HeightPosition), + RayleighMultiplier(_RayleighMultiplier), MieMultiplier(_MieMultiplier), SunIntensity(_SunIntensity), + WaveLength(_WaveLength), G(_G), Exposure(_Exposure), NumberOfSamples(_NumerOfSamples) + { + } + }; + + /** Constructor + @param s Parent SkyX pointer + */ + AtmosphereManager(SkyX *s); + + /** Destructor + */ + ~AtmosphereManager(); + + /** Set options + @param _Options New options + */ + inline void setOptions(const Options &_Options) + { + _update(_Options); + } + + /** Get current options + @return Current options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + /** Get current atmosphere color at the given direction + @param Direction *Normalised* direction + @return Atmosphere color at the especified direction + */ + const Ogre::Vector3 getColorAt(const Ogre::Vector3 &Direction) const; + + /** Update atmoshpere + @param NewOptions Update only the differences between actual parameters and new ones. + @param ForceToUpdateAll Forces to upload all current parameters to skyx material. + @remarks Current options parameters are updated if needed. + */ + void _update(const Options &NewOptions, const bool &ForceToUpdateAll = false); + + private: + /** Shader scale funtion + @param cos Cos + @param uScaleDepth Scale Depth + @return Scale + */ + const float _scale(const float &cos, const float &uScaleDepth) const; + + /// Our options + Options mOptions; + + /// SkyX parent pointer + SkyX *mSkyX; + }; +} // namespace SkyX #endif diff --git a/source/main/gfx/skyx/BasicController.cpp b/source/main/gfx/skyx/BasicController.cpp index 6150dffc4c..df4e38db25 100644 --- a/source/main/gfx/skyx/BasicController.cpp +++ b/source/main/gfx/skyx/BasicController.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -25,107 +25,74 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - BasicController::BasicController(const bool& deleteBySkyX) - : Controller(deleteBySkyX) - , mTime(Ogre::Vector3(14.0f, 7.50f, 20.50f)) - , mSunDirection(Ogre::Vector3(0,1,0)) - , mMoonDirection(Ogre::Vector3(0,-1,0)) - , mEastDirection(Ogre::Vector2(0,1)) - , mMoonPhase(0) - { - } - - void BasicController::update(const Ogre::Real& simDeltaTime) - { - mTime.x += simDeltaTime; - - if (mTime.x > 24) - { - mTime.x -= 24; - } - else if (mTime.x < 0) - { - mTime.x += 24; - } - - // 24h day: - // 0______A(Sunrise)_______B(Sunset)______24 - // - - float y, - X = mTime.x, - A = mTime.y, - B = mTime.z, - AB = A+24-B, - AB_ = B-A, - XB = X+24-B; - - if (XB) - { - if (X -0.5f) - { - y *= 2; - } - else - { - y = -(1 + y)*2; - } - } - else - { - y = (X-A)/(B-A); - - if (y < 0.5f) - { - y *= 2; - } - else - { - y = (1 - y)*2; - } - } - - Ogre::Vector2 East = mEastDirection; - - if (X > A && X < B) - { - if (X > (A + AB_/2)) - { - East = -East; - } - } - else - { - if (X<=A) - { - if (XB < (24-AB_)/2) - { - East = -East; - } - } - else - { - if ((X-B) < (24-AB_)/2) - { - East = -East; - } - } - } - - float ydeg = (Ogre::Math::PI/2)*y, - sn = Ogre::Math::Sin(ydeg), - cs = Ogre::Math::Cos(ydeg); - - mSunDirection = Ogre::Vector3(East.x*cs, sn, East.y*cs); - mMoonDirection = -mSunDirection; - } + BasicController::BasicController(const bool &deleteBySkyX) + : Controller(deleteBySkyX), mTime(Ogre::Vector3(14.0f, 7.50f, 20.50f)), mSunDirection(Ogre::Vector3(0, 1, 0)), + mMoonDirection(Ogre::Vector3(0, -1, 0)), mEastDirection(Ogre::Vector2(0, 1)), mMoonPhase(0) + { + } + + void BasicController::update(const Ogre::Real &simDeltaTime) + { + mTime.x += simDeltaTime; + + if (mTime.x > 24) { mTime.x -= 24; } + else if (mTime.x < 0) + { + mTime.x += 24; + } + + // 24h day: + // 0______A(Sunrise)_______B(Sunset)______24 + // + + float y, X = mTime.x, A = mTime.y, B = mTime.z, AB = A + 24 - B, AB_ = B - A, XB = X + 24 - B; + + if (X < A || X > B) + { + if (X < A) { y = -XB / AB; } + else + { + y = -(X - B) / AB; + } + + if (y > -0.5f) { y *= 2; } + else + { + y = -(1 + y) * 2; + } + } + else + { + y = (X - A) / (B - A); + + if (y < 0.5f) { y *= 2; } + else + { + y = (1 - y) * 2; + } + } + + Ogre::Vector2 East = mEastDirection; + + if (X > A && X < B) + { + if (X > (A + AB_ / 2)) { East = -East; } + } + else + { + if (X <= A) + { + if (XB < (24 - AB_) / 2) { East = -East; } + } + else + { + if ((X - B) < (24 - AB_) / 2) { East = -East; } + } + } + + float ydeg = (Ogre::Math::PI / 2) * y, sn = Ogre::Math::Sin(ydeg), cs = Ogre::Math::Cos(ydeg); + + mSunDirection = Ogre::Vector3(East.x * cs, sn, East.y * cs); + mMoonDirection = -mSunDirection; + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/BasicController.h b/source/main/gfx/skyx/BasicController.h index 511bdc07b7..1223aebe42 100644 --- a/source/main/gfx/skyx/BasicController.h +++ b/source/main/gfx/skyx/BasicController.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,107 +24,107 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_BasicController_H_ #define _SkyX_BasicController_H_ -#include "Prerequisites.h" - #include "Controller.h" +#include "Prerequisites.h" namespace SkyX { - /** Basic controller class - */ - class BasicController : public Controller - { - public: - /** Constructor - @param deleteBySkyX true to automatically destroy the controller by SkyX, false otherwise - */ - BasicController(const bool& deleteBySkyX = true); - - /** Update controller - @param simDeltaTime Simulation delta time (It's not the time since last frame, it's the delta simulation time, one - time the time since last frame has been multiplied by the time multiplier) - */ - void update(const Ogre::Real& simDeltaTime); - - /** Set time - @param t Time, where x = time in [0, 24]h range, y = sunrise hour in [0, 24]h range, z = sunset hour in [0, 24] range - */ - inline void setTime(const Ogre::Vector3& t) - { - mTime = t; - update(0); - } - - /** Get time - @return Current time, where x = time in [0, 24]h range, y = sunrise hour in [0, 24]h range, z = sunset hour in [0, 24] range - */ - inline const Ogre::Vector3& getTime() const - { - return mTime; - } - - /** Set eastn direction - @param ed East direction, in X,Z world coords (must be normalized) - */ - inline void setEastDirection(const Ogre::Vector2& ed) - { - mEastDirection = ed; - update(0); - } - - /** Get east direction - @return Current east direction, in X,Z world coords - */ - inline const Ogre::Vector2& getEastDirection() const - { - return mEastDirection; - } - - /** Get sun direction - @return Sun direction, the Earth-to-Sun direction - */ - inline Ogre::Vector3 getSunDirection() - { - return mSunDirection; - } - - /** Get moon direction - @return Moon direction, Earth-to-Moon direction - */ - inline Ogre::Vector3 getMoonDirection() - { - return mMoonDirection; - } - - /** Set moon phase - @param mp Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon - */ - inline void setMoonPhase(const Ogre::Real& mp) - { - mMoonPhase = mp; - } - - /** Get moon phase - @return Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon - */ - inline Ogre::Real getMoonPhase() - { - return mMoonPhase; - } - - private: - /// Time information: x = time in [0, 24]h range, y = sunrise hour in [0, 24]h range, z = sunset hour in [0, 24] range - Ogre::Vector3 mTime; - /// East direction (in X,Z world coords) - Ogre::Vector2 mEastDirection; - - /// Sun direction - Ogre::Vector3 mSunDirection; - /// Moon direction - Ogre::Vector3 mMoonDirection; - /// Moon phase - Ogre::Real mMoonPhase; - }; -} + /** Basic controller class + */ + class BasicController : public Controller + { + public: + /** Constructor + @param deleteBySkyX true to automatically destroy the controller by SkyX, false otherwise + */ + BasicController(const bool &deleteBySkyX = true); + + /** Update controller + @param simDeltaTime Simulation delta time (It's not the time since last frame, it's the delta simulation time, one + time the time since last frame has been multiplied by the time multiplier) + */ + void update(const Ogre::Real &simDeltaTime); + + /** Set time + @param t Time, where x = time in [0, 24]h range, y = sunrise hour in [0, 24]h range, z = sunset hour in [0, 24] range + */ + inline void setTime(const Ogre::Vector3 &t) + { + mTime = t; + update(0); + } + + /** Get time + @return Current time, where x = time in [0, 24]h range, y = sunrise hour in [0, 24]h range, z = sunset hour in [0, 24] + range + */ + inline const Ogre::Vector3 &getTime() const + { + return mTime; + } + + /** Set eastn direction + @param ed East direction, in X,Z world coords (must be normalized) + */ + inline void setEastDirection(const Ogre::Vector2 &ed) + { + mEastDirection = ed; + update(0); + } + + /** Get east direction + @return Current east direction, in X,Z world coords + */ + inline const Ogre::Vector2 &getEastDirection() const + { + return mEastDirection; + } + + /** Get sun direction + @return Sun direction, the Earth-to-Sun direction + */ + inline Ogre::Vector3 getSunDirection() + { + return mSunDirection; + } + + /** Get moon direction + @return Moon direction, Earth-to-Moon direction + */ + inline Ogre::Vector3 getMoonDirection() + { + return mMoonDirection; + } + + /** Set moon phase + @param mp Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon + */ + inline void setMoonPhase(const Ogre::Real &mp) + { + mMoonPhase = mp; + } + + /** Get moon phase + @return Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon + */ + inline Ogre::Real getMoonPhase() + { + return mMoonPhase; + } + + private: + /// Time information: x = time in [0, 24]h range, y = sunrise hour in [0, 24]h range, z = sunset hour in [0, 24] range + Ogre::Vector3 mTime; + /// East direction (in X,Z world coords) + Ogre::Vector2 mEastDirection; + + /// Sun direction + Ogre::Vector3 mSunDirection; + /// Moon direction + Ogre::Vector3 mMoonDirection; + /// Moon phase + Ogre::Real mMoonPhase; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/CloudsManager.cpp b/source/main/gfx/skyx/CloudsManager.cpp index 8a7de3ab84..04a9dab2a0 100644 --- a/source/main/gfx/skyx/CloudsManager.cpp +++ b/source/main/gfx/skyx/CloudsManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -27,293 +27,271 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - /// -------------- CloudLayer ----------------- - CloudLayer::CloudLayer(SkyX *s) - : mSkyX(s) - , mOptions(Options()) - , mCloudLayerPass(0) - { - mAmbientGradient = ColorGradient(); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.95f, 1.0f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.7,0.7,0.65), 0.625f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.55,0.4), 0.5625f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.45,0.3)*0.4, 0.5f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.25,0.25)*0.1, 0.45f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.3)*0.1, 0.35f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.5)*0.15, 0)); - - mSunGradient = ColorGradient(); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.95f, 1.0f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.8, 0.75f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.8,0.75,0.55)*1.3, 0.5625f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*0.75, 0.5f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*0.35, 0.4725f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.5,0.5)*0.15, 0.45f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.25)*0.5, 0.3f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.5,0.5)*0.35, 0.0f)); - } - - CloudLayer::CloudLayer(SkyX *s, const Options& o) - : mSkyX(s) - , mOptions(o) - , mCloudLayerPass(0) - { - mAmbientGradient = ColorGradient(); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.95f, 1.0f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.7,0.7,0.65), 0.625f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.55,0.4), 0.5625f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.45,0.3)*0.4, 0.5f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.25,0.25)*0.1, 0.45f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.3)*0.1, 0.35f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.5)*0.15, 0)); - - mSunGradient = ColorGradient(); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.95f, 1.0f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.8, 0.75f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.8,0.75,0.55)*1.3, 0.5625f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*0.75, 0.5f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*0.35, 0.4725f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.5,0.5)*0.15, 0.45f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.25)*0.5, 0.3f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5,0.5,0.5)*0.35, 0.0f)); - } - - CloudLayer::~CloudLayer() - { - _unregister(); - } - - void CloudLayer::_registerCloudLayer(Ogre::Pass* CloudLayerPass) - { - _unregister(); - - CloudLayerPass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - CloudLayerPass->setCullingMode(Ogre::CULL_NONE); + /// -------------- CloudLayer ----------------- + CloudLayer::CloudLayer(SkyX *s) : mSkyX(s), mOptions(Options()), mCloudLayerPass(0) + { + mAmbientGradient = ColorGradient(); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.95f, 1.0f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.7, 0.7, 0.65), 0.625f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.55, 0.4), 0.5625f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.45, 0.3) * 0.4, 0.5f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.25, 0.25) * 0.1, 0.45f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.3) * 0.1, 0.35f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.5) * 0.15, 0)); + + mSunGradient = ColorGradient(); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.95f, 1.0f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.8, 0.75f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.8, 0.75, 0.55) * 1.3, 0.5625f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 0.75, 0.5f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 0.35, 0.4725f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.5, 0.5) * 0.15, 0.45f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.25) * 0.5, 0.3f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.5, 0.5) * 0.35, 0.0f)); + } + + CloudLayer::CloudLayer(SkyX *s, const Options &o) : mSkyX(s), mOptions(o), mCloudLayerPass(0) + { + mAmbientGradient = ColorGradient(); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.95f, 1.0f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.7, 0.7, 0.65), 0.625f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.55, 0.4), 0.5625f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.45, 0.3) * 0.4, 0.5f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.25, 0.25) * 0.1, 0.45f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.3) * 0.1, 0.35f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.5) * 0.15, 0)); + + mSunGradient = ColorGradient(); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.95f, 1.0f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.8, 0.75f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.8, 0.75, 0.55) * 1.3, 0.5625f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 0.75, 0.5f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 0.35, 0.4725f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.5, 0.5) * 0.15, 0.45f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.25) * 0.5, 0.3f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.5, 0.5, 0.5) * 0.35, 0.0f)); + } + + CloudLayer::~CloudLayer() + { + _unregister(); + } + + void CloudLayer::_registerCloudLayer(Ogre::Pass *CloudLayerPass) + { + _unregister(); + + CloudLayerPass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); + CloudLayerPass->setCullingMode(Ogre::CULL_NONE); CloudLayerPass->setLightingEnabled(false); - CloudLayerPass->setDepthWriteEnabled(false); - - CloudLayerPass->setVertexProgram("SkyX_Clouds_VP"); - if (mSkyX->getLightingMode() == SkyX::LM_LDR) - { - CloudLayerPass->setFragmentProgram("SkyX_Clouds_LDR_FP"); - } - else - { - CloudLayerPass->setFragmentProgram("SkyX_Clouds_HDR_FP"); - } - - // TODO - CloudLayerPass->createTextureUnitState("Clouds.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - CloudLayerPass->createTextureUnitState("CloudsNormal.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - CloudLayerPass->createTextureUnitState("CloudsTile.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); - - mCloudLayerPass = CloudLayerPass; - - _updatePassParameters(); - _updateInternalPassParameters(); - } - - void CloudLayer::_unregister() - { - if (mCloudLayerPass) - { - mCloudLayerPass->getParent()->removePass(mCloudLayerPass->getIndex()); - mCloudLayerPass = static_cast(NULL); - } - } - - void CloudLayer::_updatePassParameters() - { - if (!mCloudLayerPass) - { - return; - } - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uScale", mOptions.Scale); - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uHeight", mOptions.Height); - - float WindDirection_[2] = {mOptions.WindDirection.x, mOptions.WindDirection.y}; - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uWindDirection", WindDirection_, 1, 2); - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uCloudLayerHeightVolume", mOptions.HeightVolume); - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uCloudLayerVolumetricDisplacement", mOptions.VolumetricDisplacement); - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uDetailAttenuation", mOptions.DetailAttenuation); - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uDistanceAttenuation", mOptions.DistanceAttenuation); - } - - void CloudLayer::_updateInternalPassParameters() - { - if (!mCloudLayerPass) - { - return; - } - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uExposure", mSkyX->getAtmosphereManager()->getOptions().Exposure); - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uTime", mSkyX->_getTimeOffset()*mOptions.TimeMultiplier); - /* - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uSunPosition", -mSkyX->getAtmosphereManager()->getSunDirection()*mSkyX->getMeshManager()->getSkydomeRadius()); - - Ogre::Vector3 AmbientColor = Ogre::Vector3::ZERO; - - Ogre::Vector3 SunDir = -mSkyX->getAtmosphereManager()->getSunDirection(); - Ogre::Real Ang = 0; - for (int k = 0; k < 3; k++) - { - Ogre::Vector2 Coords = Ogre::Vector2(Ogre::Math::Cos(Ang), Ogre::Math::Sin(Ang)); - Ang += 2*Ogre::Math::PI/3; - AmbientColor += mSkyX->getAtmosphereManager()->getColorAt(Ogre::Vector3(Coords.x, mOptions.Height/mSkyX->getMeshManager()->getSkydomeRadius(), Coords.y).normalisedCopy()); - } - - AmbientColor /= 3; - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uAmbientLuminosity", AmbientColor*0.75f); - - float Mult = 1.5f; - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uSunColor", Ogre::Vector3( - Ogre::Math::Clamp(AmbientColor.x*Mult, 0, 1), - Ogre::Math::Clamp(AmbientColor.y*Mult, 0, 1), - Ogre::Math::Clamp(AmbientColor.z*Mult, 0, 1))); - */ - - //Ogre::Vector3 SunDir = mSkyX->getAtmosphereManager()->getSunDirection(); - //if (SunDir.y > 0.15f) - //{ - // SunDir = -SunDir; - //} - - // mCloudLayerPass->getFragmentProgramParameters() - // ->setNamedConstant("uSunPosition", -SunDir*mSkyX->getMeshManager()->getSkydomeRadius()); - - float point = (mSkyX->getController()->getSunDirection().y + 1.0f) / 2.0f; - - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uSunColor", mSunGradient.getColor(point)); - mCloudLayerPass->getFragmentProgramParameters() - ->setNamedConstant("uAmbientLuminosity", mAmbientGradient.getColor(point)); - } - - /// ------------- CloudsManager --------------- - CloudsManager::CloudsManager(SkyX *s) - : mSkyX(s) - { - } - - CloudsManager::~CloudsManager() - { - removeAll(); - } - - CloudLayer* CloudsManager::add(const CloudLayer::Options& o) - { - CloudLayer *NewCloudLayer = new CloudLayer(mSkyX, o); - - // TODO - NewCloudLayer->_registerCloudLayer(static_cast( - Ogre::MaterialManager::getSingleton().getByName(mSkyX->getGPUManager()->getSkydomeMaterialName())) - ->getTechnique(0)->createPass()); - - mCloudLayers.push_back(NewCloudLayer); - - bool changeOrder = false; - - // Short layers by height - for (unsigned int k = 0; k < mCloudLayers.size(); k++) - { - if (k+1 < mCloudLayers.size()) - { - if (mCloudLayers.at(k)->getOptions().Height < mCloudLayers.at(k+1)->getOptions().Height) - { - // Swap - CloudLayer* cl = mCloudLayers.at(k); - mCloudLayers.at(k) = mCloudLayers.at(k+1); - mCloudLayers.at(k+1) = cl; - - changeOrder = true; - k = 0; - } - } - } - - if (changeOrder) - { - unregisterAll(); - registerAll(); - } - - return NewCloudLayer; - } - - void CloudsManager::remove(CloudLayer* cl) - { - for(CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + CloudLayerPass->setDepthWriteEnabled(false); + + CloudLayerPass->setVertexProgram("SkyX_Clouds_VP"); + if (mSkyX->getLightingMode() == SkyX::LM_LDR) { CloudLayerPass->setFragmentProgram("SkyX_Clouds_LDR_FP"); } + else + { + CloudLayerPass->setFragmentProgram("SkyX_Clouds_HDR_FP"); + } + + // TODO + CloudLayerPass->createTextureUnitState("Clouds.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + CloudLayerPass->createTextureUnitState("CloudsNormal.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + CloudLayerPass->createTextureUnitState("CloudsTile.png")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); + + mCloudLayerPass = CloudLayerPass; + + _updatePassParameters(); + _updateInternalPassParameters(); + } + + void CloudLayer::_unregister() + { + if (mCloudLayerPass) { - if((*CloudLayersIt) == cl) + mCloudLayerPass->getParent()->removePass(mCloudLayerPass->getIndex()); + mCloudLayerPass = static_cast(NULL); + } + } + + void CloudLayer::_updatePassParameters() + { + if (!mCloudLayerPass) { return; } + + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uScale", mOptions.Scale); + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uHeight", mOptions.Height); + + float WindDirection_[2] = {mOptions.WindDirection.x, mOptions.WindDirection.y}; + + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uWindDirection", WindDirection_, 1, 2); + + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uCloudLayerHeightVolume", mOptions.HeightVolume); + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uCloudLayerVolumetricDisplacement", + mOptions.VolumetricDisplacement); + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uDetailAttenuation", mOptions.DetailAttenuation); + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uDistanceAttenuation", mOptions.DistanceAttenuation); + } + + void CloudLayer::_updateInternalPassParameters() + { + if (!mCloudLayerPass) { return; } + + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uExposure", + mSkyX->getAtmosphereManager()->getOptions().Exposure); + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uTime", + mSkyX->_getTimeOffset() * mOptions.TimeMultiplier); + /* + mCloudLayerPass->getFragmentProgramParameters() + ->setNamedConstant("uSunPosition", + -mSkyX->getAtmosphereManager()->getSunDirection()*mSkyX->getMeshManager()->getSkydomeRadius()); + + Ogre::Vector3 AmbientColor = Ogre::Vector3::ZERO; + + Ogre::Vector3 SunDir = -mSkyX->getAtmosphereManager()->getSunDirection(); + Ogre::Real Ang = 0; + for (int k = 0; k < 3; k++) + { + Ogre::Vector2 Coords = Ogre::Vector2(Ogre::Math::Cos(Ang), Ogre::Math::Sin(Ang)); + Ang += 2*Ogre::Math::PI/3; + AmbientColor += mSkyX->getAtmosphereManager()->getColorAt(Ogre::Vector3(Coords.x, + mOptions.Height/mSkyX->getMeshManager()->getSkydomeRadius(), Coords.y).normalisedCopy()); + } + + AmbientColor /= 3; + + mCloudLayerPass->getFragmentProgramParameters() + ->setNamedConstant("uAmbientLuminosity", AmbientColor*0.75f); + + float Mult = 1.5f; + + mCloudLayerPass->getFragmentProgramParameters() + ->setNamedConstant("uSunColor", Ogre::Vector3( + Ogre::Math::Clamp(AmbientColor.x*Mult, 0, 1), + Ogre::Math::Clamp(AmbientColor.y*Mult, 0, 1), + Ogre::Math::Clamp(AmbientColor.z*Mult, 0, 1))); + */ + + // Ogre::Vector3 SunDir = mSkyX->getAtmosphereManager()->getSunDirection(); + // if (SunDir.y > 0.15f) + //{ + // SunDir = -SunDir; + //} + + // mCloudLayerPass->getFragmentProgramParameters() + // ->setNamedConstant("uSunPosition", -SunDir*mSkyX->getMeshManager()->getSkydomeRadius()); + + float point = (mSkyX->getController()->getSunDirection().y + 1.0f) / 2.0f; + + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uSunColor", mSunGradient.getColor(point)); + mCloudLayerPass->getFragmentProgramParameters()->setNamedConstant("uAmbientLuminosity", mAmbientGradient.getColor(point)); + } + + /// ------------- CloudsManager --------------- + CloudsManager::CloudsManager(SkyX *s) : mSkyX(s) + { + } + + CloudsManager::~CloudsManager() + { + removeAll(); + } + + CloudLayer *CloudsManager::add(const CloudLayer::Options &o) + { + CloudLayer *NewCloudLayer = new CloudLayer(mSkyX, o); + + // TODO + NewCloudLayer->_registerCloudLayer(static_cast(Ogre::MaterialManager::getSingleton().getByName( + mSkyX->getGPUManager()->getSkydomeMaterialName())) + ->getTechnique(0) + ->createPass()); + + mCloudLayers.push_back(NewCloudLayer); + + bool changeOrder = false; + + // Short layers by height + for (unsigned int k = 0; k < mCloudLayers.size(); k++) + { + if (k + 1 < mCloudLayers.size()) { - delete (*CloudLayersIt); - mCloudLayers.erase(CloudLayersIt); - return; + if (mCloudLayers.at(k)->getOptions().Height < mCloudLayers.at(k + 1)->getOptions().Height) + { + // Swap + CloudLayer *cl = mCloudLayers.at(k); + mCloudLayers.at(k) = mCloudLayers.at(k + 1); + mCloudLayers.at(k + 1) = cl; + + changeOrder = true; + k = 0; + } } - } - } + } - void CloudsManager::removeAll() - { - for(CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + if (changeOrder) { - delete (*CloudLayersIt); - } - - mCloudLayers.clear(); - } - - void CloudsManager::registerAll() - { - for(unsigned int k = 0; k < mCloudLayers.size(); k++) - { - mCloudLayers.at(k)->_registerCloudLayer(static_cast( - Ogre::MaterialManager::getSingleton().getByName(mSkyX->getGPUManager()->getSkydomeMaterialName())) - ->getTechnique(0)->createPass()); - } - } - - void CloudsManager::unregister(CloudLayer* cl) - { - for(CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + unregisterAll(); + registerAll(); + } + + return NewCloudLayer; + } + + void CloudsManager::remove(CloudLayer *cl) + { + for (CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) { - if((*CloudLayersIt) == cl) + if ((*CloudLayersIt) == cl) { - (*CloudLayersIt)->_unregister(); + delete (*CloudLayersIt); + mCloudLayers.erase(CloudLayersIt); + return; } - } - } + } + } + + void CloudsManager::removeAll() + { + for (CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + { + delete (*CloudLayersIt); + } + + mCloudLayers.clear(); + } + + void CloudsManager::registerAll() + { + for (unsigned int k = 0; k < mCloudLayers.size(); k++) + { + mCloudLayers.at(k)->_registerCloudLayer( + static_cast( + Ogre::MaterialManager::getSingleton().getByName(mSkyX->getGPUManager()->getSkydomeMaterialName())) + ->getTechnique(0) + ->createPass()); + } + } + + void CloudsManager::unregister(CloudLayer *cl) + { + for (CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + { + if ((*CloudLayersIt) == cl) { (*CloudLayersIt)->_unregister(); } + } + } - void CloudsManager::unregisterAll() - { - for(CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + void CloudsManager::unregisterAll() + { + for (CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) { - (*CloudLayersIt)->_unregister(); - } - } + (*CloudLayersIt)->_unregister(); + } + } - void CloudsManager::update() - { - for(CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) + void CloudsManager::update() + { + for (CloudLayersIt = mCloudLayers.begin(); CloudLayersIt != mCloudLayers.end(); CloudLayersIt++) { - (*CloudLayersIt)->_updateInternalPassParameters(); - } - } + (*CloudLayersIt)->_updateInternalPassParameters(); + } + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/CloudsManager.h b/source/main/gfx/skyx/CloudsManager.h index 7c3b7a3674..6a63462c3e 100644 --- a/source/main/gfx/skyx/CloudsManager.h +++ b/source/main/gfx/skyx/CloudsManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,263 +24,237 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_CloudsManager_H_ #define _SkyX_CloudsManager_H_ -#include "Prerequisites.h" - #include "ColorGradient.h" +#include "Prerequisites.h" namespace SkyX { - class SkyX; - - class CloudLayer - { - public: - /** Cloud layer options - */ - struct Options - { - /// Cloud layer height - Ogre::Real Height; - /// Cloud layer scale - Ogre::Real Scale; - /// Wind direction - Ogre::Vector2 WindDirection; - /// Time multiplier - Ogre::Real TimeMultiplier; - - /// Distance attenuation - Ogre::Real DistanceAttenuation; - /// Detail attenuation - Ogre::Real DetailAttenuation; - /// Cloud layer height volume(For volumetric effects on the gpu) - Ogre::Real HeightVolume; - /// Volumetric displacement(For volumetric effects on the gpu) - Ogre::Real VolumetricDisplacement; - - - /** Default constructor - */ - Options() - : Height(100) - , Scale(0.001f) - , WindDirection(Ogre::Vector2(1,1)) - , TimeMultiplier(0.125f) - , DistanceAttenuation(0.05f) - , DetailAttenuation(1) - , HeightVolume(0.25f) - , VolumetricDisplacement(0.01f) - { - } - - /** Constructor - @param _Height Cloud layer height - @param _Scale Clouds scale - @param _WindDirection Clouds movement direction - @param _TimeMultiplier Time multiplier factor - */ - Options(const Ogre::Real& _Height, - const Ogre::Real& _Scale, - const Ogre::Vector2& _WindDirection, - const Ogre::Real& _TimeMultiplier) - : Height(_Height) - , Scale(_Scale) - , WindDirection(_WindDirection) - , TimeMultiplier(_TimeMultiplier) - , DistanceAttenuation(0.05f) - , DetailAttenuation(1) - , HeightVolume(0.25f) - , VolumetricDisplacement(0.01f) - { - } - - /** Constructor - @param _Height Cloud layer height - @param _Scale Clouds scale - @param _WindDirection Clouds movement direction - @param _TimeMultiplier Time multiplier factor - @param _DistanceAttenuation Distance attenuation - @param _DetailAttenuation Detail attenuation - @param _HeightVolume Height volume(For volumetric effects on the gpu) - @param _VolumetricDisplacement Volumetric displacement(For volumetric effects on the gpu) - - */ - Options(const Ogre::Real& _Height, - const Ogre::Real& _Scale, - const Ogre::Vector2& _WindDirection, - const Ogre::Real& _TimeMultiplier, - const Ogre::Real& _DistanceAttenuation, - const Ogre::Real& _DetailAttenuation, - const Ogre::Real& _HeightVolume, - const Ogre::Real& _VolumetricDisplacement) - : Height(_Height) - , Scale(_Scale) - , WindDirection(_WindDirection) - , TimeMultiplier(_TimeMultiplier) - , DistanceAttenuation(_DistanceAttenuation) - , DetailAttenuation(_DetailAttenuation) - , HeightVolume(_HeightVolume) - , VolumetricDisplacement(_VolumetricDisplacement) - { - } - }; - - - /** Default onstructor - @param s SkyX parent pointer - */ - CloudLayer(SkyX *s); - - /** Constructor - @param s SkyX parent pointer - @param o Cloud layer options - */ - CloudLayer(SkyX *s, const Options& o); - - /** Destructor - */ + class SkyX; + + class CloudLayer + { + public: + /** Cloud layer options + */ + struct Options + { + /// Cloud layer height + Ogre::Real Height; + /// Cloud layer scale + Ogre::Real Scale; + /// Wind direction + Ogre::Vector2 WindDirection; + /// Time multiplier + Ogre::Real TimeMultiplier; + + /// Distance attenuation + Ogre::Real DistanceAttenuation; + /// Detail attenuation + Ogre::Real DetailAttenuation; + /// Cloud layer height volume(For volumetric effects on the gpu) + Ogre::Real HeightVolume; + /// Volumetric displacement(For volumetric effects on the gpu) + Ogre::Real VolumetricDisplacement; + + /** Default constructor + */ + Options() + : Height(100), Scale(0.001f), WindDirection(Ogre::Vector2(1, 1)), TimeMultiplier(0.125f), + DistanceAttenuation(0.05f), DetailAttenuation(1), HeightVolume(0.25f), VolumetricDisplacement(0.01f) + { + } + + /** Constructor + @param _Height Cloud layer height + @param _Scale Clouds scale + @param _WindDirection Clouds movement direction + @param _TimeMultiplier Time multiplier factor + */ + Options(const Ogre::Real &_Height, const Ogre::Real &_Scale, const Ogre::Vector2 &_WindDirection, + const Ogre::Real &_TimeMultiplier) + : Height(_Height), Scale(_Scale), WindDirection(_WindDirection), TimeMultiplier(_TimeMultiplier), + DistanceAttenuation(0.05f), DetailAttenuation(1), HeightVolume(0.25f), VolumetricDisplacement(0.01f) + { + } + + /** Constructor + @param _Height Cloud layer height + @param _Scale Clouds scale + @param _WindDirection Clouds movement direction + @param _TimeMultiplier Time multiplier factor + @param _DistanceAttenuation Distance attenuation + @param _DetailAttenuation Detail attenuation + @param _HeightVolume Height volume(For volumetric effects on the gpu) + @param _VolumetricDisplacement Volumetric displacement(For volumetric effects on the gpu) + + */ + Options(const Ogre::Real &_Height, const Ogre::Real &_Scale, const Ogre::Vector2 &_WindDirection, + const Ogre::Real &_TimeMultiplier, const Ogre::Real &_DistanceAttenuation, + const Ogre::Real &_DetailAttenuation, const Ogre::Real &_HeightVolume, + const Ogre::Real &_VolumetricDisplacement) + : Height(_Height), Scale(_Scale), WindDirection(_WindDirection), TimeMultiplier(_TimeMultiplier), + DistanceAttenuation(_DistanceAttenuation), DetailAttenuation(_DetailAttenuation), HeightVolume(_HeightVolume), + VolumetricDisplacement(_VolumetricDisplacement) + { + } + }; + + /** Default onstructor + @param s SkyX parent pointer + */ + CloudLayer(SkyX *s); + + /** Constructor + @param s SkyX parent pointer + @param o Cloud layer options + */ + CloudLayer(SkyX *s, const Options &o); + + /** Destructor + */ ~CloudLayer(); - /** Set options - @param o New options - */ - inline void setOptions(const Options& o) - { - mOptions = o; - _updatePassParameters(); - } - - /** Get options - @return Cloud layer options - */ - inline const Options& getOptions() const - { - return mOptions; - } - - /** Set ambient gradient - @param AmbientGradient Ambient color gradient - */ - inline void setAmbientGradient(const ColorGradient& AmbientGradient) - { - mAmbientGradient = AmbientGradient; - } - - /** Get ambient color gradient - @return Ambient color gradient - */ - inline const ColorGradient& getAmbientGradient() const - { - return mAmbientGradient; - } - - /** Set sun gradient - @param SunGradient Sun color gradient - */ - inline void setSunGradient(const ColorGradient& SunGradient) - { - mSunGradient = SunGradient; - } - - /** Get sun color gradient - @return Sun color gradient - */ - inline const ColorGradient& getSunGradient() const - { - return mSunGradient; - } - - /** Register layer - @param CloudLayerPass Pass where register the cloud layer - */ - void _registerCloudLayer(Ogre::Pass* CloudLayerPass); - - /** Unregister cloud pass - */ - void _unregister(); - - /** Update internal cloud pass parameters - */ - void _updateInternalPassParameters(); - - private: - /** Update cloud pass parameters - */ - void _updatePassParameters(); - - /// Cloud layer options - Options mOptions; - - /// Ambient and Sun color gradients - ColorGradient mAmbientGradient; - ColorGradient mSunGradient; - - /// Cloud layer pass - Ogre::Pass *mCloudLayerPass; - - /// SkyX parent pointer - SkyX *mSkyX; - }; - - class CloudsManager - { - public: - /** Constructor - @param s SkyX parent pointer - */ - CloudsManager(SkyX *h); - - /** Destructor - */ + /** Set options + @param o New options + */ + inline void setOptions(const Options &o) + { + mOptions = o; + _updatePassParameters(); + } + + /** Get options + @return Cloud layer options + */ + inline const Options &getOptions() const + { + return mOptions; + } + + /** Set ambient gradient + @param AmbientGradient Ambient color gradient + */ + inline void setAmbientGradient(const ColorGradient &AmbientGradient) + { + mAmbientGradient = AmbientGradient; + } + + /** Get ambient color gradient + @return Ambient color gradient + */ + inline const ColorGradient &getAmbientGradient() const + { + return mAmbientGradient; + } + + /** Set sun gradient + @param SunGradient Sun color gradient + */ + inline void setSunGradient(const ColorGradient &SunGradient) + { + mSunGradient = SunGradient; + } + + /** Get sun color gradient + @return Sun color gradient + */ + inline const ColorGradient &getSunGradient() const + { + return mSunGradient; + } + + /** Register layer + @param CloudLayerPass Pass where register the cloud layer + */ + void _registerCloudLayer(Ogre::Pass *CloudLayerPass); + + /** Unregister cloud pass + */ + void _unregister(); + + /** Update internal cloud pass parameters + */ + void _updateInternalPassParameters(); + + private: + /** Update cloud pass parameters + */ + void _updatePassParameters(); + + /// Cloud layer options + Options mOptions; + + /// Ambient and Sun color gradients + ColorGradient mAmbientGradient; + ColorGradient mSunGradient; + + /// Cloud layer pass + Ogre::Pass *mCloudLayerPass; + + /// SkyX parent pointer + SkyX *mSkyX; + }; + + class CloudsManager + { + public: + /** Constructor + @param s SkyX parent pointer + */ + CloudsManager(SkyX *h); + + /** Destructor + */ ~CloudsManager(); - /** Update cloud layers - */ - void update(); - - /** Add a cloud layer - @param o Cloud layer options - @return Cloud layer - */ - CloudLayer* add(const CloudLayer::Options& o); - - /** Remove the specified cloud layer - */ - void remove(CloudLayer *cl); - - /** Remove all cloud layers - */ - void removeAll(); - - /** Register all - */ - void registerAll(); - - /** Unregister cloud layer - @param cl Cloud layer to be unregistered - */ - void unregister(CloudLayer* cl); - - /** Unregister all cloud layers - */ - void unregisterAll(); - - /** Get cloud layers - @return Cloud layers - */ - inline const std::vector& getCloudLayers() const - { - return mCloudLayers; - } - - private: - /// Cloud layers std::vector - std::vector mCloudLayers; - /// Cloud layers iterator - std::vector::iterator CloudLayersIt; - - /// SkyX parent pointer - SkyX *mSkyX; - }; -} + /** Update cloud layers + */ + void update(); + + /** Add a cloud layer + @param o Cloud layer options + @return Cloud layer + */ + CloudLayer *add(const CloudLayer::Options &o); + + /** Remove the specified cloud layer + */ + void remove(CloudLayer *cl); + + /** Remove all cloud layers + */ + void removeAll(); + + /** Register all + */ + void registerAll(); + + /** Unregister cloud layer + @param cl Cloud layer to be unregistered + */ + void unregister(CloudLayer *cl); + + /** Unregister all cloud layers + */ + void unregisterAll(); + + /** Get cloud layers + @return Cloud layers + */ + inline const std::vector &getCloudLayers() const + { + return mCloudLayers; + } + + private: + /// Cloud layers std::vector + std::vector mCloudLayers; + /// Cloud layers iterator + std::vector::iterator CloudLayersIt; + + /// SkyX parent pointer + SkyX *mSkyX; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/ColorGradient.cpp b/source/main/gfx/skyx/ColorGradient.cpp index 5acc220c11..cc0cc1ac21 100644 --- a/source/main/gfx/skyx/ColorGradient.cpp +++ b/source/main/gfx/skyx/ColorGradient.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -25,107 +25,91 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - ColorGradient::ColorGradient() - : mMalFormed(true) - { - } - - ColorGradient::~ColorGradient() - { - } - - const Ogre::Vector3 ColorGradient::getColor(const Ogre::Real& p) const - { - if (mMalFormed) - { - SkyXLOG("Mal-formed ColorGradient"); - return Ogre::Vector3(0,0,0); - } - - if (CFrameVector.size() == 0) - { - return Ogre::Vector3(0,0,0); - } - else if (CFrameVector.size() == 1) - { - return CFrameVector.at(0).first; - } - - std::pair minBound, maxBound; - - // Min value - minBound.first = 0; - minBound.second = -1; - for (unsigned int k = 0; k < CFrameVector.size(); k++) - { - if (CFrameVector.at(k).second < p && CFrameVector.at(k).second > minBound.second) - { - minBound.first = k; - minBound.second = CFrameVector.at(k).second; - } - } - - // Max value - maxBound.first = 0; - maxBound.second = 2; - for (unsigned int k = 0; k < CFrameVector.size(); k++) - { - if (CFrameVector.at(k).second > p && CFrameVector.at(k).second < maxBound.second) - { - maxBound.first = k; - maxBound.second = CFrameVector.at(k).second; - } - } - - float range = maxBound.second - minBound.second, - rangepoint = (p - minBound.second) / range; - - return CFrameVector.at(minBound.first).first*(1-rangepoint) + CFrameVector.at(maxBound.first).first*rangepoint; - } - - const bool ColorGradient::_checkBounds() const - { - std::pair existbounds; - existbounds.first = false; existbounds.second = false; - - for (unsigned int k = 0; k < CFrameVector.size(); k++) - { - if (CFrameVector.at(k).second == 0) - { - // More than one min bound - if (existbounds.first) - { - return false; - } - - existbounds.first = true; - } - - if (CFrameVector.at(k).second < 0 || CFrameVector.at(k).second > 1) - { - return false; - } - } - - for (unsigned int k = 0; k < CFrameVector.size(); k++) - { - if (CFrameVector.at(k).second == 1) - { - // More than one min bound - if (existbounds.second) - { - return false; - } - - existbounds.second = true; - } - } - - if (!existbounds.first || !existbounds.second) - { - return false; - } - - return true; - } + ColorGradient::ColorGradient() : mMalFormed(true) + { + } + + ColorGradient::~ColorGradient() + { + } + + const Ogre::Vector3 ColorGradient::getColor(const Ogre::Real &p) const + { + if (mMalFormed) + { + SkyXLOG("Mal-formed ColorGradient"); + return Ogre::Vector3(0, 0, 0); + } + + if (CFrameVector.size() == 0) { return Ogre::Vector3(0, 0, 0); } + else if (CFrameVector.size() == 1) + { + return CFrameVector.at(0).first; + } + + std::pair minBound, maxBound; + + // Min value + minBound.first = 0; + minBound.second = -1; + for (unsigned int k = 0; k < CFrameVector.size(); k++) + { + if (CFrameVector.at(k).second < p && CFrameVector.at(k).second > minBound.second) + { + minBound.first = k; + minBound.second = CFrameVector.at(k).second; + } + } + + // Max value + maxBound.first = 0; + maxBound.second = 2; + for (unsigned int k = 0; k < CFrameVector.size(); k++) + { + if (CFrameVector.at(k).second > p && CFrameVector.at(k).second < maxBound.second) + { + maxBound.first = k; + maxBound.second = CFrameVector.at(k).second; + } + } + + float range = maxBound.second - minBound.second, rangepoint = (p - minBound.second) / range; + + return CFrameVector.at(minBound.first).first * (1 - rangepoint) + CFrameVector.at(maxBound.first).first * rangepoint; + } + + const bool ColorGradient::_checkBounds() const + { + std::pair existbounds; + existbounds.first = false; + existbounds.second = false; + + for (unsigned int k = 0; k < CFrameVector.size(); k++) + { + if (CFrameVector.at(k).second == 0) + { + // More than one min bound + if (existbounds.first) { return false; } + + existbounds.first = true; + } + + if (CFrameVector.at(k).second < 0 || CFrameVector.at(k).second > 1) { return false; } + } + + for (unsigned int k = 0; k < CFrameVector.size(); k++) + { + if (CFrameVector.at(k).second == 1) + { + // More than one min bound + if (existbounds.second) { return false; } + + existbounds.second = true; + } + } + + if (!existbounds.first || !existbounds.second) { return false; } + + return true; + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/ColorGradient.h b/source/main/gfx/skyx/ColorGradient.h index bc20a65b19..84a9404aba 100644 --- a/source/main/gfx/skyx/ColorGradient.h +++ b/source/main/gfx/skyx/ColorGradient.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -28,58 +28,58 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - class ColorGradient - { - public: - /** Color frame type definition - ColorFrame.first: Colour value - ColorFrame.second: Position in the gradient [0,1] range - */ - typedef std::pair ColorFrame; - - /** Constructor - */ - ColorGradient(); - - /** Destructor - */ - ~ColorGradient(); - - /** Add color frame - @param CFrame Color frame - */ - inline void addCFrame(const ColorFrame& CFrame) - { - CFrameVector.push_back(CFrame); - - mMalFormed = !_checkBounds(); - } - - /** Clear color gradient - */ - inline void clear() - { - CFrameVector.clear(); - } - - /** Get color value - @param p The gradient point in [0,1] range - @return Color at the given gradient position - */ - const Ogre::Vector3 getColor(const Ogre::Real& p) const; - - private: - /** Check bounds - @return false if the Color gradient is mal-formed - */ - const bool _checkBounds() const; - - /// Mal formed color gradient? - bool mMalFormed; - - /// Color frame vector - std::vector CFrameVector; - }; -} + class ColorGradient + { + public: + /** Color frame type definition + ColorFrame.first: Colour value + ColorFrame.second: Position in the gradient [0,1] range + */ + typedef std::pair ColorFrame; + + /** Constructor + */ + ColorGradient(); + + /** Destructor + */ + ~ColorGradient(); + + /** Add color frame + @param CFrame Color frame + */ + inline void addCFrame(const ColorFrame &CFrame) + { + CFrameVector.push_back(CFrame); + + mMalFormed = !_checkBounds(); + } + + /** Clear color gradient + */ + inline void clear() + { + CFrameVector.clear(); + } + + /** Get color value + @param p The gradient point in [0,1] range + @return Color at the given gradient position + */ + const Ogre::Vector3 getColor(const Ogre::Real &p) const; + + private: + /** Check bounds + @return false if the Color gradient is mal-formed + */ + const bool _checkBounds() const; + + /// Mal formed color gradient? + bool mMalFormed; + + /// Color frame vector + std::vector CFrameVector; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/Controller.h b/source/main/gfx/skyx/Controller.h index 74008af6f6..34c59a56fc 100644 --- a/source/main/gfx/skyx/Controller.h +++ b/source/main/gfx/skyx/Controller.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -28,56 +28,59 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - /** Controller base class - */ - class Controller - { - public: - /** Constructor - @param deleteBySkyX true to automatically destroy the controller by SkyX, false otherwise - */ - inline Controller(const bool& deleteBySkyX) - : mDeleteBySkyX(deleteBySkyX) - { - } + /** Controller base class + */ + class Controller + { + public: + /** Constructor + @param deleteBySkyX true to automatically destroy the controller by SkyX, false otherwise + */ + inline Controller(const bool &deleteBySkyX) : mDeleteBySkyX(deleteBySkyX) + { + } - /** Destructor - */ - inline virtual ~Controller(){} + /** Destructor + */ + inline virtual ~Controller() + { + } - /** Update controller - @param simDeltaTime Simulation delta time (It's not the time since last frame, it's the delta simulation time, one - time the time since last frame has been multiplied by the time multiplier) - */ - inline virtual void update(const Ogre::Real& simDeltaTime){} + /** Update controller + @param simDeltaTime Simulation delta time (It's not the time since last frame, it's the delta simulation time, one + time the time since last frame has been multiplied by the time multiplier) + */ + inline virtual void update(const Ogre::Real &simDeltaTime) + { + } - /** Get sun direction - @return Sun direction, the Earth-to-Sun direction - */ - virtual Ogre::Vector3 getSunDirection() = 0; + /** Get sun direction + @return Sun direction, the Earth-to-Sun direction + */ + virtual Ogre::Vector3 getSunDirection() = 0; - /** Get moon direction - @return Moon direction, Earth-to-Moon direction - */ - virtual Ogre::Vector3 getMoonDirection() = 0; + /** Get moon direction + @return Moon direction, Earth-to-Moon direction + */ + virtual Ogre::Vector3 getMoonDirection() = 0; - /** Get moon phase - @return Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon - */ - virtual Ogre::Real getMoonPhase() = 0; + /** Get moon phase + @return Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon + */ + virtual Ogre::Real getMoonPhase() = 0; - /** Must the controller be destroyed by SkyX? - @return true if yes, false if not - */ - inline const bool& getDeleteBySkyX() const - { - return mDeleteBySkyX; - } + /** Must the controller be destroyed by SkyX? + @return true if yes, false if not + */ + inline const bool &getDeleteBySkyX() const + { + return mDeleteBySkyX; + } - private: - /// Must the controller be destroyed by SkyX? - bool mDeleteBySkyX; - }; -} + private: + /// Must the controller be destroyed by SkyX? + bool mDeleteBySkyX; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/GPUManager.cpp b/source/main/gfx/skyx/GPUManager.cpp index f9b2b95871..abe576f12a 100644 --- a/source/main/gfx/skyx/GPUManager.cpp +++ b/source/main/gfx/skyx/GPUManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -27,346 +27,328 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - GPUManager::GPUManager(SkyX *s) - : mSkyX(s) - , mGroundPasses(std::vector()) - { - _notifySkydomeMaterialChanged(); - } - - GPUManager::~GPUManager() - { - } - - void GPUManager::addGroundPass(Ogre::Pass* GroundPass, const Ogre::Real& AtmosphereRadius, const Ogre::SceneBlendType& SBT) - { - GroundPass->setVertexProgram("SkyX_Ground_VP"); - if (mSkyX->getLightingMode() == SkyX::LM_LDR) - { - GroundPass->setFragmentProgram("SkyX_Ground_LDR_FP"); - } - else - { - GroundPass->setFragmentProgram("SkyX_Ground_HDR_FP"); - } - - GroundPass->getVertexProgramParameters()->setNamedConstant("uSkydomeRadius", AtmosphereRadius*10); - - GroundPass->setLightingEnabled(false); - - GroundPass->setDepthCheckEnabled(true); - GroundPass->setDepthWriteEnabled(false); - - GroundPass->setSceneBlending(SBT); - - /// TODO + GPUManager::GPUManager(SkyX *s) : mSkyX(s), mGroundPasses(std::vector()) + { + _notifySkydomeMaterialChanged(); + } + + GPUManager::~GPUManager() + { + } + + void GPUManager::addGroundPass(Ogre::Pass *GroundPass, const Ogre::Real &AtmosphereRadius, const Ogre::SceneBlendType &SBT) + { + GroundPass->setVertexProgram("SkyX_Ground_VP"); + if (mSkyX->getLightingMode() == SkyX::LM_LDR) { GroundPass->setFragmentProgram("SkyX_Ground_LDR_FP"); } + else + { + GroundPass->setFragmentProgram("SkyX_Ground_HDR_FP"); + } + + GroundPass->getVertexProgramParameters()->setNamedConstant("uSkydomeRadius", AtmosphereRadius * 10); + + GroundPass->setLightingEnabled(false); + + GroundPass->setDepthCheckEnabled(true); + GroundPass->setDepthWriteEnabled(false); + + GroundPass->setSceneBlending(SBT); + + /// TODO mGroundPasses.push_back(GroundPass); - mSkyX->getAtmosphereManager()->_update(mSkyX->getAtmosphereManager()->getOptions(), true); - } - - void GPUManager::_updateFP() - { - Ogre::String fp_name = "SkyX_Ground_HDR_FP"; - - if (mSkyX->getLightingMode() == SkyX::LM_LDR) - { - fp_name = "SkyX_Ground_LDR_FP"; - } - - for(unsigned int k = 0; k < mGroundPasses.size(); k++) - { - mGroundPasses.at(k)->setFragmentProgram(fp_name); - } - - bool gammaCorrection = mSkyX->getLightingMode() == SkyX::LM_HDR; - - // SkyX_Starfield.png - static_cast(Ogre::MaterialManager::getSingleton().getByName(getSkydomeMaterialName())) - ->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setHardwareGammaEnabled(gammaCorrection); - - // SkyX_Moon.png and SkyX_MoonHalo.png - static_cast(Ogre::MaterialManager::getSingleton().getByName(getMoonMaterialName())) - ->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setHardwareGammaEnabled(gammaCorrection); - static_cast(Ogre::MaterialManager::getSingleton().getByName(getMoonMaterialName())) - ->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setHardwareGammaEnabled(gammaCorrection); - - _setTextureHWGammaCorrection("SkyX_Starfield.png", gammaCorrection); - _setTextureHWGammaCorrection("SkyX_Moon.png", gammaCorrection); - _setTextureHWGammaCorrection("SkyX_MoonHalo.png", gammaCorrection); - } - - void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const int &Value, const bool& UpdateGroundPasses) - { - if (!mSkyX->getMeshManager()->isCreated()) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - - if (!UpdateGroundPasses) - { - return; - } - - std::vector::iterator PassIt; - - for(PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) - { - if (!(*PassIt)) - { - mGroundPasses.erase(PassIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*PassIt)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*PassIt)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - } - } - - void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Real &Value, const bool& UpdateGroundPasses) - { - if (!mSkyX->getMeshManager()->isCreated()) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - - if (!UpdateGroundPasses) - { - return; - } - - std::vector::iterator PassIt; - - for(PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) - { - if (!(*PassIt)) - { - mGroundPasses.erase(PassIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*PassIt)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*PassIt)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - } - } - - void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector2 &Value, const bool& UpdateGroundPasses) - { - if (!mSkyX->getMeshManager()->isCreated()) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - float Value_[2] = {Value.x, Value.y}; - - Parameters->setNamedConstant(Name, Value_, 1, 2); - - if (!UpdateGroundPasses) - { - return; - } - - std::vector::iterator PassIt; - - for(PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) - { - if (!(*PassIt)) - { - mGroundPasses.erase(PassIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*PassIt)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*PassIt)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value_, 1, 2); - } - } - - void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector3 &Value, const bool& UpdateGroundPasses) - { - if (!mSkyX->getMeshManager()->isCreated()) - { - return; - } - - Ogre::GpuProgramParametersSharedPtr Parameters; - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - - if (!UpdateGroundPasses) - { - return; - } - - std::vector::iterator PassIt; - - for(PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) - { - if (!(*PassIt)) - { - mGroundPasses.erase(PassIt); - continue; - } - - switch (GpuP) - { - case GPUP_VERTEX: - { - Parameters = (*PassIt)->getVertexProgramParameters(); - } - break; - - case GPUP_FRAGMENT: - { - Parameters = (*PassIt)->getFragmentProgramParameters(); - } - break; - } - - Parameters->setNamedConstant(Name, Value); - } - } - - const Ogre::String GPUManager::getSkydomeMaterialName() const - { - Ogre::String starfield = (mSkyX->isStarfieldEnabled()) ? "STARFIELD_" : ""; - - return (mSkyX->getLightingMode() == SkyX::LM_LDR) ? "SkyX_Skydome_" + starfield + "LDR" : "SkyX_Skydome_" + starfield + "HDR"; - } - - void GPUManager::_setTextureHWGammaCorrection(const Ogre::String& n, const bool& g) - { - Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(n); - - if (!tex.isNull()) - { - if (g) - { - if (!tex->isHardwareGammaEnabled()) - { - tex->setHardwareGammaEnabled(true); - tex->reload(); - } - } - else - { - if (tex->isHardwareGammaEnabled()) - { - tex->setHardwareGammaEnabled(false); - tex->reload(); - } - } - } - } + mSkyX->getAtmosphereManager()->_update(mSkyX->getAtmosphereManager()->getOptions(), true); + } + + void GPUManager::_updateFP() + { + Ogre::String fp_name = "SkyX_Ground_HDR_FP"; + + if (mSkyX->getLightingMode() == SkyX::LM_LDR) { fp_name = "SkyX_Ground_LDR_FP"; } + + for (unsigned int k = 0; k < mGroundPasses.size(); k++) + { + mGroundPasses.at(k)->setFragmentProgram(fp_name); + } + + bool gammaCorrection = mSkyX->getLightingMode() == SkyX::LM_HDR; + + // SkyX_Starfield.png + static_cast(Ogre::MaterialManager::getSingleton().getByName(getSkydomeMaterialName())) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0) + ->setHardwareGammaEnabled(gammaCorrection); + + // SkyX_Moon.png and SkyX_MoonHalo.png + static_cast(Ogre::MaterialManager::getSingleton().getByName(getMoonMaterialName())) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0) + ->setHardwareGammaEnabled(gammaCorrection); + static_cast(Ogre::MaterialManager::getSingleton().getByName(getMoonMaterialName())) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(1) + ->setHardwareGammaEnabled(gammaCorrection); + + _setTextureHWGammaCorrection("SkyX_Starfield.png", gammaCorrection); + _setTextureHWGammaCorrection("SkyX_Moon.png", gammaCorrection); + _setTextureHWGammaCorrection("SkyX_MoonHalo.png", gammaCorrection); + } + + void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const int &Value, + const bool &UpdateGroundPasses) + { + if (!mSkyX->getMeshManager()->isCreated()) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + + if (!UpdateGroundPasses) { return; } + + std::vector::iterator PassIt; + + for (PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) + { + if (!(*PassIt)) + { + mGroundPasses.erase(PassIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*PassIt)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*PassIt)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + } + } + + void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Real &Value, + const bool &UpdateGroundPasses) + { + if (!mSkyX->getMeshManager()->isCreated()) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + + if (!UpdateGroundPasses) { return; } + + std::vector::iterator PassIt; + + for (PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) + { + if (!(*PassIt)) + { + mGroundPasses.erase(PassIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*PassIt)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*PassIt)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + } + } + + void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector2 &Value, + const bool &UpdateGroundPasses) + { + if (!mSkyX->getMeshManager()->isCreated()) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + float Value_[2] = {Value.x, Value.y}; + + Parameters->setNamedConstant(Name, Value_, 1, 2); + + if (!UpdateGroundPasses) { return; } + + std::vector::iterator PassIt; + + for (PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) + { + if (!(*PassIt)) + { + mGroundPasses.erase(PassIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*PassIt)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*PassIt)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value_, 1, 2); + } + } + + void GPUManager::setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector3 &Value, + const bool &UpdateGroundPasses) + { + if (!mSkyX->getMeshManager()->isCreated()) { return; } + + Ogre::GpuProgramParametersSharedPtr Parameters; + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = mSkydomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + + if (!UpdateGroundPasses) { return; } + + std::vector::iterator PassIt; + + for (PassIt = mGroundPasses.begin(); PassIt != mGroundPasses.end(); PassIt++) + { + if (!(*PassIt)) + { + mGroundPasses.erase(PassIt); + continue; + } + + switch (GpuP) + { + case GPUP_VERTEX: + { + Parameters = (*PassIt)->getVertexProgramParameters(); + } + break; + + case GPUP_FRAGMENT: + { + Parameters = (*PassIt)->getFragmentProgramParameters(); + } + break; + } + + Parameters->setNamedConstant(Name, Value); + } + } + + const Ogre::String GPUManager::getSkydomeMaterialName() const + { + Ogre::String starfield = (mSkyX->isStarfieldEnabled()) ? "STARFIELD_" : ""; + + return (mSkyX->getLightingMode() == SkyX::LM_LDR) ? "SkyX_Skydome_" + starfield + "LDR" + : "SkyX_Skydome_" + starfield + "HDR"; + } + + void GPUManager::_setTextureHWGammaCorrection(const Ogre::String &n, const bool &g) + { + Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(n); + + if (!tex.isNull()) + { + if (g) + { + if (!tex->isHardwareGammaEnabled()) + { + tex->setHardwareGammaEnabled(true); + tex->reload(); + } + } + else + { + if (tex->isHardwareGammaEnabled()) + { + tex->setHardwareGammaEnabled(false); + tex->reload(); + } + } + } + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/GPUManager.h b/source/main/gfx/skyx/GPUManager.h index 4f29f092af..9685bb79e2 100644 --- a/source/main/gfx/skyx/GPUManager.h +++ b/source/main/gfx/skyx/GPUManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -28,116 +28,122 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - class SkyX; - - class GPUManager - { - public: - /** Gpu program enum - */ - enum GpuProgram - { - // Vertex program - GPUP_VERTEX = 0, - // Fragment program - GPUP_FRAGMENT = 1 - }; - - /** Constructor - @param s Parent SkyX pointer - */ - GPUManager(SkyX *s); - - /** Destructor - */ - ~GPUManager(); - - /** Add ground pass (Use for atmospheric scattering effect on the terrain) - @param GroundPass Ground pass - @param AtmosphereRaidus Atmosphere radius (typically far carmera clip plane) - @param SBT Scene blend type - */ - void addGroundPass(Ogre::Pass* GroundPass, const Ogre::Real& AtmosphereRadius, const Ogre::SceneBlendType& SBT = Ogre::SBT_ADD); - - /** Set gpu program int parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param Name param name - @param Value value - @param UpdateGroundPasses true to update ground passes - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const int &Value, const bool& UpdateGroundPasses = true); - - /** Set gpu program Ogre::Real parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param Name param name - @param Value value - @param UpdateGroundPasses true to update ground passes - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Real &Value, const bool& UpdateGroundPasses = true); - - /** Set gpu program Ogre::Vector2 parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param Name param name - @param Value value - @param UpdateGroundPasses true to update ground passes - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector2 &Value, const bool& UpdateGroundPasses = true); - - /** Set gpu program Ogre::Vector3 parameter - @param GpuP Gpu program type (Vertex/Fragment) - @param Name param name - @param Value value - @param UpdateGroundPasses true to update ground passes - */ - void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector3 &Value, const bool& UpdateGroundPasses = true); - - /** Get skydome material name - @return Skydome material name - */ - const Ogre::String getSkydomeMaterialName() const; - - /** Get moon material name - @return Moon material name - */ - inline const Ogre::String getMoonMaterialName() const - { - return "SkyX_Moon"; - } - - /** Update fragment program materials - @remarks Only for internal use - */ - void _updateFP(); - - /** Notify skydome material changed - @remarks Only for internal use - */ - inline void _notifySkydomeMaterialChanged() - { - mSkydomeMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName(getSkydomeMaterialName())); - - if (mSkydomeMaterial.isNull()) - { - SkyXLOG("Error in SkyX::GPUManager: '" + getSkydomeMaterialName() + "' material not found"); - return; - } - } - - private: - /** Set texture HW gamma correction - @param n Texture name - @param g True to enable gamma correction, false to disable it - */ - void _setTextureHWGammaCorrection(const Ogre::String& n, const bool& g); - - /// Skydome material - Ogre::MaterialPtr mSkydomeMaterial; - /// Ground pass vector - std::vector mGroundPasses; - - /// SkyX parent pointer - SkyX *mSkyX; - }; -} + class SkyX; + + class GPUManager + { + public: + /** Gpu program enum + */ + enum GpuProgram + { + // Vertex program + GPUP_VERTEX = 0, + // Fragment program + GPUP_FRAGMENT = 1 + }; + + /** Constructor + @param s Parent SkyX pointer + */ + GPUManager(SkyX *s); + + /** Destructor + */ + ~GPUManager(); + + /** Add ground pass (Use for atmospheric scattering effect on the terrain) + @param GroundPass Ground pass + @param AtmosphereRaidus Atmosphere radius (typically far carmera clip plane) + @param SBT Scene blend type + */ + void addGroundPass(Ogre::Pass *GroundPass, const Ogre::Real &AtmosphereRadius, + const Ogre::SceneBlendType &SBT = Ogre::SBT_ADD); + + /** Set gpu program int parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param Name param name + @param Value value + @param UpdateGroundPasses true to update ground passes + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const int &Value, + const bool &UpdateGroundPasses = true); + + /** Set gpu program Ogre::Real parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param Name param name + @param Value value + @param UpdateGroundPasses true to update ground passes + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Real &Value, + const bool &UpdateGroundPasses = true); + + /** Set gpu program Ogre::Vector2 parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param Name param name + @param Value value + @param UpdateGroundPasses true to update ground passes + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector2 &Value, + const bool &UpdateGroundPasses = true); + + /** Set gpu program Ogre::Vector3 parameter + @param GpuP Gpu program type (Vertex/Fragment) + @param Name param name + @param Value value + @param UpdateGroundPasses true to update ground passes + */ + void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const Ogre::Vector3 &Value, + const bool &UpdateGroundPasses = true); + + /** Get skydome material name + @return Skydome material name + */ + const Ogre::String getSkydomeMaterialName() const; + + /** Get moon material name + @return Moon material name + */ + inline const Ogre::String getMoonMaterialName() const + { + return "SkyX_Moon"; + } + + /** Update fragment program materials + @remarks Only for internal use + */ + void _updateFP(); + + /** Notify skydome material changed + @remarks Only for internal use + */ + inline void _notifySkydomeMaterialChanged() + { + mSkydomeMaterial = + static_cast(Ogre::MaterialManager::getSingleton().getByName(getSkydomeMaterialName())); + + if (mSkydomeMaterial.isNull()) + { + SkyXLOG("Error in SkyX::GPUManager: '" + getSkydomeMaterialName() + "' material not found"); + return; + } + } + + private: + /** Set texture HW gamma correction + @param n Texture name + @param g True to enable gamma correction, false to disable it + */ + void _setTextureHWGammaCorrection(const Ogre::String &n, const bool &g); + + /// Skydome material + Ogre::MaterialPtr mSkydomeMaterial; + /// Ground pass vector + std::vector mGroundPasses; + + /// SkyX parent pointer + SkyX *mSkyX; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/MeshManager.cpp b/source/main/gfx/skyx/MeshManager.cpp index 08dd7e55bf..df790f75b2 100644 --- a/source/main/gfx/skyx/MeshManager.cpp +++ b/source/main/gfx/skyx/MeshManager.cpp @@ -27,345 +27,308 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - MeshManager::MeshManager(SkyX *s) - : mSkyX(s) - , mCreated(false) - , mMesh(static_cast(0)) - , mSubMesh(0) - , mEntity(0) - , mVertexBuffer() - , mVertices(0) - , mIndexBuffer() - , mSceneNode(0) - , mSteps(70) - , mCircles(95) - , mUnderHorizonCircles(12) - , mUnderHorizonFading(true) - , mUnderHorizonFadingExponent(0.75) - , mUnderHorizonFadingMultiplier(2) - , mRadiusMultiplier(0.95f) - , mMaterialName("_NULL_") - { - } - - MeshManager::~MeshManager() - { - remove(); - } - - void MeshManager::remove() - { - if (!mCreated) - { - return; - } - - mSceneNode->detachAllObjects(); - mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); - mSceneNode = 0; - - Ogre::MeshManager::getSingleton().remove("SkyXMesh"); - mSkyX->getSceneManager()->destroyEntity(mEntity); - - mMesh.setNull(); - mSubMesh = 0; - mEntity = 0; - mVertexBuffer.setNull(); - mIndexBuffer.setNull(); - mMaterialName = "_NULL_"; - - delete [] mVertices; - - mCreated = false; - } - - void MeshManager::create() - { - if (mCreated) - { - return; - } - - // Create mesh and submesh - mMesh = Ogre::MeshManager::getSingleton().createManual("SkyXMesh", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - mSubMesh = mMesh->createSubMesh(); + MeshManager::MeshManager(SkyX *s) + : mSkyX(s), mCreated(false), mMesh(static_cast(0)), mSubMesh(0), mEntity(0), mVertexBuffer(), mVertices(0), + mIndexBuffer(), mSceneNode(0), mSteps(70), mCircles(95), mUnderHorizonCircles(12), mUnderHorizonFading(true), + mUnderHorizonFadingExponent(0.75), mUnderHorizonFadingMultiplier(2), mRadiusMultiplier(0.95f), mMaterialName("_NULL_") + { + } + + MeshManager::~MeshManager() + { + remove(); + } + + void MeshManager::remove() + { + if (!mCreated) { return; } + + mSceneNode->detachAllObjects(); + mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); + mSceneNode = 0; + + Ogre::MeshManager::getSingleton().remove("SkyXMesh"); + mSkyX->getSceneManager()->destroyEntity(mEntity); + + mMesh.setNull(); + mSubMesh = 0; + mEntity = 0; + mVertexBuffer.setNull(); + mIndexBuffer.setNull(); + mMaterialName = "_NULL_"; + + delete[] mVertices; + + mCreated = false; + } + + void MeshManager::create() + { + if (mCreated) { return; } + + // Create mesh and submesh + mMesh = + Ogre::MeshManager::getSingleton().createManual("SkyXMesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + mSubMesh = mMesh->createSubMesh(); mSubMesh->useSharedVertices = false; - // Create mesh geometry - _createGeometry(); + // Create mesh geometry + _createGeometry(); - // Build edge list - mMesh->buildEdgeList(); + // Build edge list + mMesh->buildEdgeList(); - // End mesh creation + // End mesh creation mMesh->load(); mMesh->touch(); mEntity = mSkyX->getSceneManager()->createEntity("SkyXMeshEnt", "SkyXMesh"); mEntity->setMaterialName(mMaterialName); - mEntity->setCastShadows(false); - mEntity->setRenderQueueGroup(mSkyX->getRenderQueueGroups().skydome); + mEntity->setCastShadows(false); + mEntity->setRenderQueueGroup(mSkyX->getRenderQueueGroups().skydome); - mSceneNode = mSkyX->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - mSceneNode->showBoundingBox(false); + mSceneNode = mSkyX->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + mSceneNode->showBoundingBox(false); mSceneNode->attachObject(mEntity); - mCreated = true; - } + mCreated = true; + } - void MeshManager::updateGeometry(Ogre::Camera* cam) - { - if (!mCreated) - { - return; - } + void MeshManager::updateGeometry(Ogre::Camera *cam) + { + if (!mCreated) { return; } - float Radius = getSkydomeRadius(cam); + float Radius = getSkydomeRadius(cam); - mVertices[0].x = 0; mVertices[0].z = 0; mVertices[0].y = Radius; - mVertices[0].nx = 0; mVertices[0].nz = 0; mVertices[0].ny = 1; - mVertices[0].u = 4; mVertices[0].v = 4; - mVertices[0].o = 1; + mVertices[0].x = 0; + mVertices[0].z = 0; + mVertices[0].y = Radius; + mVertices[0].nx = 0; + mVertices[0].nz = 0; + mVertices[0].ny = 1; + mVertices[0].u = 4; + mVertices[0].v = 4; + mVertices[0].o = 1; - float AngleStep = (Ogre::Math::PI/2) / (mCircles-mUnderHorizonCircles); + float AngleStep = (Ogre::Math::PI / 2) / (mCircles - mUnderHorizonCircles); - float r, uvr, c, s, h; - float currentPhiAngle, currentTethaAngle; - int x, y; + float r, uvr, c, s, h; + float currentPhiAngle, currentTethaAngle; + int x, y; - // Above-horizon - for(y=0;y(y+1)/(mCircles-mUnderHorizonCircles); + uvr = static_cast(y + 1) / (mCircles - mUnderHorizonCircles); - for(x=0;x(y+1)/(mCircles-mUnderHorizonCircles); - - op = Ogre::Math::Clamp(Ogre::Math::Pow(static_cast(mCircles-y-1) / mUnderHorizonCircles, mUnderHorizonFadingExponent)*mUnderHorizonFadingMultiplier, 0, 1); - - for(x=0;x - writeData(0, - mVertexBuffer->getSizeInBytes(), - mVertices, - true); - - // Update bounds - Ogre::AxisAlignedBox meshBounds = - Ogre::AxisAlignedBox(-Radius, 0, -Radius, - Radius, Radius, Radius); - - mMesh->_setBounds(meshBounds); - mSceneNode->_updateBounds(); - } - - void MeshManager::_createGeometry() - { - int numVertices = mSteps * mCircles + 1; - int numEle = 6 * mSteps * (mCircles-1) + 3 * mSteps; - - // Vertex buffers - mSubMesh->vertexData = new Ogre::VertexData(); - mSubMesh->vertexData->vertexStart = 0; - mSubMesh->vertexData->vertexCount = numVertices; - - Ogre::VertexDeclaration* vdecl = mSubMesh->vertexData->vertexDeclaration; - Ogre::VertexBufferBinding* vbind = mSubMesh->vertexData->vertexBufferBinding; - - size_t offset = 0; - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES, 0); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); - vdecl->addElement(0, offset, Ogre::VET_FLOAT1, Ogre::VES_TEXTURE_COORDINATES, 2); - - mVertexBuffer = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(VERTEX), - numVertices, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - - vbind->setBinding(0, mVertexBuffer); - - unsigned short *indexbuffer = new unsigned short[numEle]; - - for (int k = 0; k < mSteps; k++) - { - indexbuffer[k*3] = 0; - indexbuffer[k*3+1] = k+1; - - if (k != mSteps-1) - { - indexbuffer[k*3+2] = k+2; - } - else - { - indexbuffer[k*3+2] = 1; - } - } - - unsigned short *twoface; - - for(int y=0; y - writeData(0, - mIndexBuffer->getSizeInBytes(), - indexbuffer, - true); - - delete []indexbuffer; - - // Set index buffer for this submesh - mSubMesh->indexData->indexBuffer = mIndexBuffer; - mSubMesh->indexData->indexStart = 0; - mSubMesh->indexData->indexCount = numEle; - - // Create our internal buffer for manipulations - mVertices = new VERTEX[1+mSteps * mCircles]; - } - - void MeshManager::setGeometryParameters(const int &Steps, const int &Circles) - { - mSteps = Steps; - mCircles = Circles; - - if (mCreated) - { - remove(); - create(); - } - } - - void MeshManager::setUnderHorizonParams(const int& UnderHorizonCircles, const bool& UnderHorizonFading, const Ogre::Real& UnderHorizonFadingExponent, const Ogre::Real& UnderHorizonFadingMultiplier) - { - bool needToRecreate = (mUnderHorizonCircles != UnderHorizonCircles); - - mUnderHorizonCircles = UnderHorizonCircles; - mUnderHorizonFading = UnderHorizonFading; - mUnderHorizonFadingExponent = UnderHorizonFadingExponent; - mUnderHorizonFadingMultiplier = UnderHorizonFadingMultiplier; - - if (needToRecreate) - { - remove(); - create(); - } - } - - void MeshManager::setMaterialName(const Ogre::String& MaterialName) - { - mMaterialName = MaterialName; - - if (mCreated) - { - mEntity->setMaterialName(MaterialName); - } - } - - const float MeshManager::getSkydomeRadius(Ogre::Camera* c) const - { - float cameraFarClipDistance = c->getFarClipDistance(); - - if (!cameraFarClipDistance) - { - cameraFarClipDistance = mSkyX->getInfiniteCameraFarClipDistance(); - } - - return cameraFarClipDistance*mRadiusMultiplier; - } -} + // Under-horizon + for (y = mCircles - mUnderHorizonCircles; y < mCircles; y++) + { + currentTethaAngle = Ogre::Math::PI / 2 - AngleStep * (y + 1); + + r = Ogre::Math::Cos(currentTethaAngle); + h = Ogre::Math::Sin(currentTethaAngle); + + uvr = static_cast(y + 1) / (mCircles - mUnderHorizonCircles); + + op = Ogre::Math::Clamp( + Ogre::Math::Pow(static_cast(mCircles - y - 1) / mUnderHorizonCircles, mUnderHorizonFadingExponent) * + mUnderHorizonFadingMultiplier, + 0, 1); + + for (x = 0; x < mSteps; x++) + { + currentPhiAngle = Ogre::Math::TWO_PI * x / mSteps; + + c = Ogre::Math::Cos(currentPhiAngle) * r; + s = Ogre::Math::Sin(currentPhiAngle) * r; + + mVertices[1 + y * mSteps + x].x = c * Radius; + mVertices[1 + y * mSteps + x].z = s * Radius; + mVertices[1 + y * mSteps + x].y = h * Radius; + + mVertices[1 + y * mSteps + x].nx = c; + mVertices[1 + y * mSteps + x].nz = s; + mVertices[1 + y * mSteps + x].ny = h; + + mVertices[1 + y * mSteps + x].u = (1 + c * uvr / r) * 4; + mVertices[1 + y * mSteps + x].v = (1 + s * uvr / r) * 4; + + mVertices[1 + y * mSteps + x].o = op; + } + } + + // Update data + mVertexBuffer->writeData(0, mVertexBuffer->getSizeInBytes(), mVertices, true); + + // Update bounds + Ogre::AxisAlignedBox meshBounds = Ogre::AxisAlignedBox(-Radius, 0, -Radius, Radius, Radius, Radius); + + mMesh->_setBounds(meshBounds); + mSceneNode->_updateBounds(); + } + + void MeshManager::_createGeometry() + { + int numVertices = mSteps * mCircles + 1; + int numEle = 6 * mSteps * (mCircles - 1) + 3 * mSteps; + + // Vertex buffers + mSubMesh->vertexData = new Ogre::VertexData(); + mSubMesh->vertexData->vertexStart = 0; + mSubMesh->vertexData->vertexCount = numVertices; + + Ogre::VertexDeclaration * vdecl = mSubMesh->vertexData->vertexDeclaration; + Ogre::VertexBufferBinding *vbind = mSubMesh->vertexData->vertexBufferBinding; + + size_t offset = 0; + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES, 0); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); + vdecl->addElement(0, offset, Ogre::VET_FLOAT1, Ogre::VES_TEXTURE_COORDINATES, 2); + + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(VERTEX), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + + vbind->setBinding(0, mVertexBuffer); + + unsigned short *indexbuffer = new unsigned short[numEle]; + + for (int k = 0; k < mSteps; k++) + { + indexbuffer[k * 3] = 0; + indexbuffer[k * 3 + 1] = k + 1; + + if (k != mSteps - 1) { indexbuffer[k * 3 + 2] = k + 2; } + else + { + indexbuffer[k * 3 + 2] = 1; + } + } + + unsigned short *twoface; + + for (int y = 0; y < mCircles - 1; y++) + { + for (int x = 0; x < mSteps; x++) + { + twoface = indexbuffer + (y * mSteps + x) * 6 + 3 * mSteps; + + int p0 = 1 + y * mSteps + x; + int p1 = 1 + y * mSteps + x + 1; + int p2 = 1 + (y + 1) * mSteps + x; + int p3 = 1 + (y + 1) * mSteps + x + 1; + + if (x == mSteps - 1) + { + p1 -= x + 1; + p3 -= x + 1; + } + + // First triangle + twoface[2] = p0; + twoface[1] = p1; + twoface[0] = p2; + + // Second triangle + twoface[5] = p1; + twoface[4] = p3; + twoface[3] = p2; + } + } + + // Prepare buffer for indices + mIndexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, numEle, + Ogre::HardwareBuffer::HBU_STATIC, true); + + mIndexBuffer->writeData(0, mIndexBuffer->getSizeInBytes(), indexbuffer, true); + + delete[] indexbuffer; + + // Set index buffer for this submesh + mSubMesh->indexData->indexBuffer = mIndexBuffer; + mSubMesh->indexData->indexStart = 0; + mSubMesh->indexData->indexCount = numEle; + + // Create our internal buffer for manipulations + mVertices = new VERTEX[1 + mSteps * mCircles]; + } + + void MeshManager::setGeometryParameters(const int &Steps, const int &Circles) + { + mSteps = Steps; + mCircles = Circles; + + if (mCreated) + { + remove(); + create(); + } + } + + void MeshManager::setUnderHorizonParams(const int &UnderHorizonCircles, const bool &UnderHorizonFading, + const Ogre::Real &UnderHorizonFadingExponent, + const Ogre::Real &UnderHorizonFadingMultiplier) + { + bool needToRecreate = (mUnderHorizonCircles != UnderHorizonCircles); + + mUnderHorizonCircles = UnderHorizonCircles; + mUnderHorizonFading = UnderHorizonFading; + mUnderHorizonFadingExponent = UnderHorizonFadingExponent; + mUnderHorizonFadingMultiplier = UnderHorizonFadingMultiplier; + + if (needToRecreate) + { + remove(); + create(); + } + } + + void MeshManager::setMaterialName(const Ogre::String &MaterialName) + { + mMaterialName = MaterialName; + + if (mCreated) { mEntity->setMaterialName(MaterialName); } + } + + const float MeshManager::getSkydomeRadius(Ogre::Camera *c) const + { + float cameraFarClipDistance = c->getFarClipDistance(); + + if (!cameraFarClipDistance) { cameraFarClipDistance = mSkyX->getInfiniteCameraFarClipDistance(); } + + return cameraFarClipDistance * mRadiusMultiplier; + } +} // namespace SkyX diff --git a/source/main/gfx/skyx/MeshManager.h b/source/main/gfx/skyx/MeshManager.h index 20beadc695..3d1240dcf1 100644 --- a/source/main/gfx/skyx/MeshManager.h +++ b/source/main/gfx/skyx/MeshManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -28,49 +28,49 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - class SkyX; - - class MeshManager - { - public: - /** Vertex struct - */ - struct VERTEX - { - // Position - float x, y, z, - // Normalized position - nx, ny, nz, - // Texture coords - u, v, - // Opacity - o; - }; - - /** Constructor - @param s Parent SkyX pointer - */ - MeshManager(SkyX *s); - - /** Destructor - */ - ~MeshManager(); - - /** Create our water mesh, geometry, entity, etc... + class SkyX; + + class MeshManager + { + public: + /** Vertex struct + */ + struct VERTEX + { + // Position + float x, y, z, + // Normalized position + nx, ny, nz, + // Texture coords + u, v, + // Opacity + o; + }; + + /** Constructor + @param s Parent SkyX pointer + */ + MeshManager(SkyX *s); + + /** Destructor + */ + ~MeshManager(); + + /** Create our water mesh, geometry, entity, etc... @remarks Call it after setMaterialName() */ void create(); - /** Remove all resources - */ - void remove(); + /** Remove all resources + */ + void remove(); - /** Update geometry - @param cam Camera - */ - void updateGeometry(Ogre::Camera* cam); + /** Update geometry + @param cam Camera + */ + void updateGeometry(Ogre::Camera *cam); - /** Get mesh + /** Get mesh @return Mesh */ inline Ogre::MeshPtr getMesh() @@ -81,7 +81,7 @@ namespace SkyX /** Get sub mesh @return Sub mesh */ - inline Ogre::SubMesh* getSubMesh() + inline Ogre::SubMesh *getSubMesh() { return mSubMesh; } @@ -89,7 +89,7 @@ namespace SkyX /** Get entity @return Entity */ - inline Ogre::Entity* getEntity() + inline Ogre::Entity *getEntity() { return mEntity; } @@ -97,17 +97,17 @@ namespace SkyX /** Get material name @return Material name */ - inline const Ogre::String& getMaterialName() const + inline const Ogre::String &getMaterialName() const { return mMaterialName; } - /** Set mesh material + /** Set mesh material @param MaterialName The material name */ void setMaterialName(const Ogre::String &MaterialName); - /** Get hardware vertex buffer reference + /** Get hardware vertex buffer reference @return Ogre::HardwareVertexBufferSharedPtr reference */ inline Ogre::HardwareVertexBufferSharedPtr &getHardwareVertexBuffer() @@ -115,122 +115,124 @@ namespace SkyX return mVertexBuffer; } - /** Get hardware index buffer reference - @return Ogre::HardwareIndexBufferSharedPtr reference - */ - inline Ogre::HardwareIndexBufferSharedPtr &getHardwareIndexBuffer() - { - return mIndexBuffer; - } - - /** Get the Ogre::SceneNode pointer where Hydrax mesh is attached - @return Ogre::SceneNode* - */ - inline Ogre::SceneNode* getSceneNode() - { - return mSceneNode; - } - - /** Is _createGeometry() called? - @return true if created() have been already called - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Set geometry parameters - @param Steps Sphere number of steps - @param Circles Spehere number of circes - */ - void setGeometryParameters(const int& Steps, const int& Circles); - - /** Get number of steps - @return Number of steps - */ - inline const int& getSteps() const - { - return mSteps; - } - - /** Get number of circles - @return Number of circles - */ - inline const int& getCircles() const - { - return mCircles; - } - - /** Set under-horizon rendering params - @remarks In an ideal situation, you only must see the avobe horizon sky due to the fact that the terrain/water - must be 'infinite' and the under-horizont sky part is hide. - But, infinite terrain/water is not always implemented in games and 3d apps in general, so... in order to - get a good-looking sky, SkyX provides an approach to render realistic under-horizont sky. - @param UnderHorizonCircles Number of circles of SkyX::MeshManager::mCircles reserved for the under-horizont geometry part, - 0 means not under-horizon rendering - @param UnderHorizonFading true/false to fade or not the under-horizon sky - @param UnderHorizonFadingExponent Exponent of the fading, pow(vertex_angle, exp), 1=linear - @param UnderHorizonFadingMultiplier Fading multiplier, opacity = saturate(pow(opacity,fading_exp)*fading_multiplier) - */ - void setUnderHorizonParams(const int& UnderHorizonCircles = 15, const bool& UnderHorizonFading = true, const Ogre::Real& UnderHorizonFadingExponent = 1, const Ogre::Real& UnderHorizonFadingMultiplier = 2); - - /** Get under-horizon circles - @return Under-horizon circles - */ - inline const int& getUnderHorizonCircles() const - { - return mUnderHorizonCircles; - } - - /** Get under-horizon fading - @return Under-horizon fading - */ - inline const bool& getUnderHorizonFading() const - { - return mUnderHorizonFading; - } - - /** Get under-horizon exponent fading - @return under-horizon exponent fading - */ - inline const Ogre::Real& getUnderHorizonFadingExponent() const - { - return mUnderHorizonFadingExponent; - } - - /** Get under-horizon fading multiplier - @return Under-horizon fading multiplier - */ - inline const Ogre::Real& getUnderHorizonFadingMultiplier() const - { - return mUnderHorizonFadingMultiplier; - } - - /** Set radius multiplier - @param RadiusMultiplier Radius multiplier - @remarks Radius multiplier in [0,1] range - Radius = CameraFarClipDistance * RadiusMultiplier - */ - inline void setRadiusMultiplier(const Ogre::Real& RadiusMultiplier) - { - mRadiusMultiplier = RadiusMultiplier; - } - - /** Get skydome radius - @param c Camera - @return Skydome radius relative to the given camera - */ - const float getSkydomeRadius(Ogre::Camera* c) const; - - private: - /** Create geometry - */ - void _createGeometry(); - - /// Has been create() already called? - bool mCreated; - - /// Ogre::MeshPtr + /** Get hardware index buffer reference + @return Ogre::HardwareIndexBufferSharedPtr reference + */ + inline Ogre::HardwareIndexBufferSharedPtr &getHardwareIndexBuffer() + { + return mIndexBuffer; + } + + /** Get the Ogre::SceneNode pointer where Hydrax mesh is attached + @return Ogre::SceneNode* + */ + inline Ogre::SceneNode *getSceneNode() + { + return mSceneNode; + } + + /** Is _createGeometry() called? + @return true if created() have been already called + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Set geometry parameters + @param Steps Sphere number of steps + @param Circles Spehere number of circes + */ + void setGeometryParameters(const int &Steps, const int &Circles); + + /** Get number of steps + @return Number of steps + */ + inline const int &getSteps() const + { + return mSteps; + } + + /** Get number of circles + @return Number of circles + */ + inline const int &getCircles() const + { + return mCircles; + } + + /** Set under-horizon rendering params + @remarks In an ideal situation, you only must see the avobe horizon sky due to the fact that the terrain/water + must be 'infinite' and the under-horizont sky part is hide. + But, infinite terrain/water is not always implemented in games and 3d apps in general, so... in order to + get a good-looking sky, SkyX provides an approach to render realistic under-horizont sky. + @param UnderHorizonCircles Number of circles of SkyX::MeshManager::mCircles reserved for the under-horizont geometry + part, 0 means not under-horizon rendering + @param UnderHorizonFading true/false to fade or not the under-horizon sky + @param UnderHorizonFadingExponent Exponent of the fading, pow(vertex_angle, exp), 1=linear + @param UnderHorizonFadingMultiplier Fading multiplier, opacity = saturate(pow(opacity,fading_exp)*fading_multiplier) + */ + void setUnderHorizonParams(const int &UnderHorizonCircles = 15, const bool &UnderHorizonFading = true, + const Ogre::Real &UnderHorizonFadingExponent = 1, + const Ogre::Real &UnderHorizonFadingMultiplier = 2); + + /** Get under-horizon circles + @return Under-horizon circles + */ + inline const int &getUnderHorizonCircles() const + { + return mUnderHorizonCircles; + } + + /** Get under-horizon fading + @return Under-horizon fading + */ + inline const bool &getUnderHorizonFading() const + { + return mUnderHorizonFading; + } + + /** Get under-horizon exponent fading + @return under-horizon exponent fading + */ + inline const Ogre::Real &getUnderHorizonFadingExponent() const + { + return mUnderHorizonFadingExponent; + } + + /** Get under-horizon fading multiplier + @return Under-horizon fading multiplier + */ + inline const Ogre::Real &getUnderHorizonFadingMultiplier() const + { + return mUnderHorizonFadingMultiplier; + } + + /** Set radius multiplier + @param RadiusMultiplier Radius multiplier + @remarks Radius multiplier in [0,1] range + Radius = CameraFarClipDistance * RadiusMultiplier + */ + inline void setRadiusMultiplier(const Ogre::Real &RadiusMultiplier) + { + mRadiusMultiplier = RadiusMultiplier; + } + + /** Get skydome radius + @param c Camera + @return Skydome radius relative to the given camera + */ + const float getSkydomeRadius(Ogre::Camera *c) const; + + private: + /** Create geometry + */ + void _createGeometry(); + + /// Has been create() already called? + bool mCreated; + + /// Ogre::MeshPtr Ogre::MeshPtr mMesh; /// Ogre::Submesh pointer Ogre::SubMesh *mSubMesh; @@ -240,37 +242,37 @@ namespace SkyX /// Vertex buffer Ogre::HardwareVertexBufferSharedPtr mVertexBuffer; /// Index buffer - Ogre::HardwareIndexBufferSharedPtr mIndexBuffer; + Ogre::HardwareIndexBufferSharedPtr mIndexBuffer; - /// Vertices - VERTEX* mVertices; + /// Vertices + VERTEX *mVertices; - /// Circles - int mCircles; - /// Steps - int mSteps; + /// Circles + int mCircles; + /// Steps + int mSteps; - /// Under-horizon rendering - int mUnderHorizonCircles; - /// Under-horizon fading - bool mUnderHorizonFading; - /// Under-horizon exponent fading (1=linear fading) - Ogre::Real mUnderHorizonFadingExponent; - /// Under-horizon fading multiplier: opacity = saturate(pow(opacity,fading_exp)*fading_multiplier) - Ogre::Real mUnderHorizonFadingMultiplier; + /// Under-horizon rendering + int mUnderHorizonCircles; + /// Under-horizon fading + bool mUnderHorizonFading; + /// Under-horizon exponent fading (1=linear fading) + Ogre::Real mUnderHorizonFadingExponent; + /// Under-horizon fading multiplier: opacity = saturate(pow(opacity,fading_exp)*fading_multiplier) + Ogre::Real mUnderHorizonFadingMultiplier; - /// Radius multiplier - Ogre::Real mRadiusMultiplier; + /// Radius multiplier + Ogre::Real mRadiusMultiplier; - /// Ogre::SceneNode pointer - Ogre::SceneNode* mSceneNode; + /// Ogre::SceneNode pointer + Ogre::SceneNode *mSceneNode; /// Material name Ogre::String mMaterialName; - /// Main SkyX pointer - SkyX* mSkyX; - }; -} + /// Main SkyX pointer + SkyX *mSkyX; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/MoonManager.cpp b/source/main/gfx/skyx/MoonManager.cpp index 7f03045365..14740b5ab2 100644 --- a/source/main/gfx/skyx/MoonManager.cpp +++ b/source/main/gfx/skyx/MoonManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -27,286 +27,263 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - MoonManager::MoonManager(SkyX *s) - : mSkyX(s) - , mMoonBillboard(0) - , mMoonSceneNode(0) - , mCreated(false) - , mMoonSize(0.225f) - , mMoonHaloIntensity(0.4f) - , mMoonHaloStrength(0.9f) - , mMoonMaterial(Ogre::MaterialPtr()) - { - } - - MoonManager::~MoonManager() - { - remove(); - } - - void MoonManager::create() - { - if (mCreated) - { - return; - } - - mMoonMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_Moon")); - - if (mMoonMaterial.isNull()) - { - SkyXLOG("Error while creating SkyX::MoonManager, material not found"); - return; - } - - mMoonSceneNode = mSkyX->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - - mMoonBillboard = mSkyX->getSceneManager()->createBillboardSet("SkyXMoonBillboardSet", 1); + MoonManager::MoonManager(SkyX *s) + : mSkyX(s), mMoonBillboard(0), mMoonSceneNode(0), mCreated(false), mMoonSize(0.225f), mMoonHaloIntensity(0.4f), + mMoonHaloStrength(0.9f), mMoonMaterial(Ogre::MaterialPtr()) + { + } + + MoonManager::~MoonManager() + { + remove(); + } + + void MoonManager::create() + { + if (mCreated) { return; } + + mMoonMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_Moon")); + + if (mMoonMaterial.isNull()) + { + SkyXLOG("Error while creating SkyX::MoonManager, material not found"); + return; + } + + mMoonSceneNode = mSkyX->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + + mMoonBillboard = mSkyX->getSceneManager()->createBillboardSet("SkyXMoonBillboardSet", 1); mMoonBillboard->setMaterialName(mSkyX->getGPUManager()->getMoonMaterialName()); - mMoonBillboard->setBillboardType(Ogre::BBT_ORIENTED_COMMON); - mMoonBillboard->setRenderQueueGroup(mSkyX->getRenderQueueGroups().skydome+1); - mMoonBillboard->setCastShadows(false); - - mMoonBillboard->createBillboard(Ogre::Vector3(0,0,0)); - - mMoonSceneNode->attachObject(mMoonBillboard); - - mCreated = true; - } - - void MoonManager::remove() - { - if (!mCreated) - { - return; - } - - mMoonSceneNode->detachAllObjects(); - mMoonSceneNode->getParentSceneNode()->removeAndDestroyChild(mMoonSceneNode); - mMoonSceneNode = 0; - - mSkyX->getSceneManager()->destroyBillboardSet(mMoonBillboard); - mMoonBillboard = 0; - - mMoonMaterial.setNull(); - - mCreated = false; - } - - void MoonManager::updateMoonPhase(const Ogre::Real& phase) - { - Ogre::Real center = 0, radius = 0, radius_add = 0, interpolation = 0, halo_flip = 0; - - Ogre::Vector3 halo1, halo2; - - // [-1, 0] - if (phase < 0) - { - // [-1, -0.5] - if (phase < -0.5) - { - center = (1+phase)/2; - radius = 0.25; - - interpolation = center*4; - - if (interpolation < 1.0f/3) - { - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.25, 0.5, (1-interpolation)*interpolation); - halo2 = Ogre::Vector3(0.25, 0.5, interpolation); - } - else if (interpolation < 2.0f/3) - { - interpolation -= 1.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.25, 0.5, 1-interpolation); - halo2 = Ogre::Vector3(0.0, 0.5, interpolation); - } - else - { - interpolation -= 2.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.0, 0.5, 1-interpolation); - halo2 = Ogre::Vector3(0.75, 0.0, interpolation); - } - - radius_add = 0.1*center/(0.25001-center); - - radius += radius_add; - center += radius_add; - } - // [-0.5, 0] - else - { - center = (-phase)/2; - radius = 0.25; - - interpolation = 1-center*4; - - if (interpolation < 1.0f/3) - { - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.75, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.5, 0.0, interpolation); - } - else if (interpolation < 2.0f/3) - { - interpolation -= 1.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.5, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.25, 0.0, interpolation); - } - else - { - interpolation -= 2.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.25, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.00, 0.0, interpolation); - } - - radius_add = 0.1*center/(0.25001-center); - - radius += radius_add; - center += radius_add; - - radius = -radius; - center = -center; - } - } - // [0, 1] - else - { - halo_flip = 1; - - // [0, 0.5] - if (phase < 0.5) - { - center = phase/2; - radius = 0.25; - - interpolation = center*4; - - if (interpolation < 1.0f/3) - { - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.00, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.25, 0.0, interpolation); - } - else if (interpolation < 2.0f/3) - { - interpolation -= 1.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.25, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.5, 0.0, interpolation); - } - else - { - interpolation -= 2.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.5, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.75, 0.0, interpolation); - } - - radius_add = 0.1*center/(0.25001-center); - - radius += radius_add; - center += radius_add; - - radius = -radius; - center = center; - } - // [0.5, 1] - else - { - center = (1-phase)/2; - radius = 0.25; - - interpolation = 1-center*4; - - if (interpolation < 1.0f/3) - { - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.75, 0.0, 1-interpolation); - halo2 = Ogre::Vector3(0.0, 0.5, interpolation); - } - else if (interpolation < 2.0f/3) - { - interpolation -= 1.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.0, 0.5, 1-interpolation); - halo2 = Ogre::Vector3(0.25, 0.5, interpolation); - } - else - { - interpolation -= 2.0f/3; - interpolation /= 1.0f/3; - halo1 = Ogre::Vector3(0.25, 0.5, 1-interpolation); - halo2 = Ogre::Vector3(0.25, 0.5, (1-interpolation)*interpolation); - } - - radius_add = 0.1*center/(0.25001-center); - - radius += radius_add; - center += radius_add; - - center = -center; - } - } - - mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonPhase", Ogre::Vector3(radius, center + 0.5f, mMoonHaloStrength)); - - halo1.z *= mMoonHaloIntensity; - halo2.z *= mMoonHaloIntensity; - - mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonHalo1", halo1); - mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonHalo2", halo2); - mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonHaloFlip", halo_flip); - } - - void MoonManager::updateGeometry(Ogre::Camera* c) - { - if (!mCreated) - { - return; - } - - float radius = mSkyX->getMeshManager()->getSkydomeRadius(c)*0.95f, - size = radius*mMoonSize; - - mMoonBillboard->setCommonDirection((mSkyX->getController()->getMoonDirection()).normalisedCopy().perpendicular()); - - Ogre::Vector3 moonRelativePos = mSkyX->getController()->getMoonDirection()* - Ogre::Math::Cos(Ogre::Math::ASin((size/2)/radius))*radius; - - mMoonSceneNode->setPosition(c->getDerivedPosition() + moonRelativePos); - - if (moonRelativePos.y < -size/2) - { - mMoonSceneNode->setVisible(false); - } - else - { - mMoonSceneNode->setVisible(mSkyX->isVisible()); - - mMoonMaterial->getTechnique(0)->getPass(0) - ->getVertexProgramParameters()->setNamedConstant("uSkydomeCenter", c->getDerivedPosition()); - } - - if (mMoonBillboard->getBoundingBox().getMaximum().x != size) - { - _updateMoonBounds(c); - } - } - - void MoonManager::_updateMoonBounds(Ogre::Camera* c) - { - float radius = mSkyX->getMeshManager()->getSkydomeRadius(c)*0.95f, - size = radius*mMoonSize; - - mMoonBillboard->setDefaultDimensions(size, size); - mMoonBillboard->setBounds(Ogre::AxisAlignedBox(-size/2, -size/2, -size/2, - size/2, size/2, size/2), 1); - mMoonSceneNode->_updateBounds(); - } -} + mMoonBillboard->setBillboardType(Ogre::BBT_ORIENTED_COMMON); + mMoonBillboard->setRenderQueueGroup(mSkyX->getRenderQueueGroups().skydome + 1); + mMoonBillboard->setCastShadows(false); + + mMoonBillboard->createBillboard(Ogre::Vector3(0, 0, 0)); + + mMoonSceneNode->attachObject(mMoonBillboard); + + mCreated = true; + } + + void MoonManager::remove() + { + if (!mCreated) { return; } + + mMoonSceneNode->detachAllObjects(); + mMoonSceneNode->getParentSceneNode()->removeAndDestroyChild(mMoonSceneNode); + mMoonSceneNode = 0; + + mSkyX->getSceneManager()->destroyBillboardSet(mMoonBillboard); + mMoonBillboard = 0; + + mMoonMaterial.setNull(); + + mCreated = false; + } + + void MoonManager::updateMoonPhase(const Ogre::Real &phase) + { + Ogre::Real center = 0, radius = 0, radius_add = 0, interpolation = 0, halo_flip = 0; + + Ogre::Vector3 halo1, halo2; + + // [-1, 0] + if (phase < 0) + { + // [-1, -0.5] + if (phase < -0.5) + { + center = (1 + phase) / 2; + radius = 0.25; + + interpolation = center * 4; + + if (interpolation < 1.0f / 3) + { + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.25, 0.5, (1 - interpolation) * interpolation); + halo2 = Ogre::Vector3(0.25, 0.5, interpolation); + } + else if (interpolation < 2.0f / 3) + { + interpolation -= 1.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.25, 0.5, 1 - interpolation); + halo2 = Ogre::Vector3(0.0, 0.5, interpolation); + } + else + { + interpolation -= 2.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.0, 0.5, 1 - interpolation); + halo2 = Ogre::Vector3(0.75, 0.0, interpolation); + } + + radius_add = 0.1 * center / (0.25001 - center); + + radius += radius_add; + center += radius_add; + } + // [-0.5, 0] + else + { + center = (-phase) / 2; + radius = 0.25; + + interpolation = 1 - center * 4; + + if (interpolation < 1.0f / 3) + { + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.75, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.5, 0.0, interpolation); + } + else if (interpolation < 2.0f / 3) + { + interpolation -= 1.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.5, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.25, 0.0, interpolation); + } + else + { + interpolation -= 2.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.25, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.00, 0.0, interpolation); + } + + radius_add = 0.1 * center / (0.25001 - center); + + radius += radius_add; + center += radius_add; + + radius = -radius; + center = -center; + } + } + // [0, 1] + else + { + halo_flip = 1; + + // [0, 0.5] + if (phase < 0.5) + { + center = phase / 2; + radius = 0.25; + + interpolation = center * 4; + + if (interpolation < 1.0f / 3) + { + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.00, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.25, 0.0, interpolation); + } + else if (interpolation < 2.0f / 3) + { + interpolation -= 1.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.25, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.5, 0.0, interpolation); + } + else + { + interpolation -= 2.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.5, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.75, 0.0, interpolation); + } + + radius_add = 0.1 * center / (0.25001 - center); + + radius += radius_add; + center += radius_add; + + radius = -radius; + center = center; + } + // [0.5, 1] + else + { + center = (1 - phase) / 2; + radius = 0.25; + + interpolation = 1 - center * 4; + + if (interpolation < 1.0f / 3) + { + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.75, 0.0, 1 - interpolation); + halo2 = Ogre::Vector3(0.0, 0.5, interpolation); + } + else if (interpolation < 2.0f / 3) + { + interpolation -= 1.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.0, 0.5, 1 - interpolation); + halo2 = Ogre::Vector3(0.25, 0.5, interpolation); + } + else + { + interpolation -= 2.0f / 3; + interpolation /= 1.0f / 3; + halo1 = Ogre::Vector3(0.25, 0.5, 1 - interpolation); + halo2 = Ogre::Vector3(0.25, 0.5, (1 - interpolation) * interpolation); + } + + radius_add = 0.1 * center / (0.25001 - center); + + radius += radius_add; + center += radius_add; + + center = -center; + } + } + + mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uMoonPhase", Ogre::Vector3(radius, center + 0.5f, mMoonHaloStrength)); + + halo1.z *= mMoonHaloIntensity; + halo2.z *= mMoonHaloIntensity; + + mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonHalo1", halo1); + mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonHalo2", halo2); + mMoonMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uMoonHaloFlip", halo_flip); + } + + void MoonManager::updateGeometry(Ogre::Camera *c) + { + if (!mCreated) { return; } + + float radius = mSkyX->getMeshManager()->getSkydomeRadius(c) * 0.95f, size = radius * mMoonSize; + + mMoonBillboard->setCommonDirection((mSkyX->getController()->getMoonDirection()).normalisedCopy().perpendicular()); + + Ogre::Vector3 moonRelativePos = + mSkyX->getController()->getMoonDirection() * Ogre::Math::Cos(Ogre::Math::ASin((size / 2) / radius)) * radius; + + mMoonSceneNode->setPosition(c->getDerivedPosition() + moonRelativePos); + + if (moonRelativePos.y < -size / 2) { mMoonSceneNode->setVisible(false); } + else + { + mMoonSceneNode->setVisible(mSkyX->isVisible()); + + mMoonMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters()->setNamedConstant("uSkydomeCenter", + c->getDerivedPosition()); + } + + if (mMoonBillboard->getBoundingBox().getMaximum().x != size) { _updateMoonBounds(c); } + } + + void MoonManager::_updateMoonBounds(Ogre::Camera *c) + { + float radius = mSkyX->getMeshManager()->getSkydomeRadius(c) * 0.95f, size = radius * mMoonSize; + + mMoonBillboard->setDefaultDimensions(size, size); + mMoonBillboard->setBounds(Ogre::AxisAlignedBox(-size / 2, -size / 2, -size / 2, size / 2, size / 2, size / 2), 1); + mMoonSceneNode->_updateBounds(); + } +} // namespace SkyX diff --git a/source/main/gfx/skyx/MoonManager.h b/source/main/gfx/skyx/MoonManager.h index 9962b9b704..45a8301491 100644 --- a/source/main/gfx/skyx/MoonManager.h +++ b/source/main/gfx/skyx/MoonManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -28,137 +28,137 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - class SkyX; - - class MoonManager - { - public: - /** Constructor - @param s Parent SkyX pointer - */ - MoonManager(SkyX *s); - - /** Destructor - */ - ~MoonManager(); - - /** Create all resources - */ - void create(); - - /** Remove all resources - */ - void remove(); - - /** Update moon phase - @param phase Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon - */ - void updateMoonPhase(const Ogre::Real& phase); - - /** Update geometry - @param c Camera - */ - void updateGeometry(Ogre::Camera* c); - - /** Get moon billboard - @return Moon billboard - */ - inline Ogre::BillboardSet* getMoonBillboard() - { - return mMoonBillboard; - } - - /** Get moon scene node - @return Moon scene node - */ - inline Ogre::SceneNode* getMoonSceneNode() - { - return mMoonSceneNode; - } - - /** Set moon size - @param MoonSize Moon size - */ - inline void setMoonSize(const Ogre::Real& MoonSize) - { - mMoonSize = MoonSize; - } - - /** Get moon size - @return Moon size - */ - inline const Ogre::Real& getMoonSize() const - { - return mMoonSize; - } - - /** Set moon halo intensity - @param MoonHaloIntensity Moon halo intensity - */ - inline void setMoonHaloIntensity(const Ogre::Real& MoonHaloIntensity) - { - mMoonHaloIntensity = MoonHaloIntensity; - } - - /** Get moon halo intensity - @return Moon halo intensity - */ - inline const Ogre::Real& getMoonHaloIntensity() const - { - return mMoonHaloIntensity; - } - - /** Set moon halo strength - @param MoonHaloStrength Moon halo strength (linear/exponential fading) - */ - inline void setMoonHaloStrength(const Ogre::Real& MoonHaloStrength) - { - mMoonHaloStrength = MoonHaloStrength; - } - - /** Get moon halo strength - @return Moon halo strength (linear/exponential fading) - */ - inline const Ogre::Real& getMoonHaloStrength() const - { - return mMoonHaloStrength; - } - - /** Is moon manager created? - @return true if yes, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - private: - /** Update moon bounds - @param c Camera - */ - void _updateMoonBounds(Ogre::Camera* c); - - /// Moon billboard - Ogre::BillboardSet* mMoonBillboard; - /// Moon scene node - Ogre::SceneNode* mMoonSceneNode; - - /// Is moon manager created? - bool mCreated; - - /// Moon size - Ogre::Real mMoonSize; - /// Moon halo intensity - Ogre::Real mMoonHaloIntensity; - /// Moon halo strength - Ogre::Real mMoonHaloStrength; - - /// Moon material - Ogre::MaterialPtr mMoonMaterial; - - /// SkyX parent pointer - SkyX *mSkyX; - }; -} + class SkyX; + + class MoonManager + { + public: + /** Constructor + @param s Parent SkyX pointer + */ + MoonManager(SkyX *s); + + /** Destructor + */ + ~MoonManager(); + + /** Create all resources + */ + void create(); + + /** Remove all resources + */ + void remove(); + + /** Update moon phase + @param phase Moon phase in [-1,1] range, where -1 means fully covered Moon, 0 clear Moon and 1 fully covered Moon + */ + void updateMoonPhase(const Ogre::Real &phase); + + /** Update geometry + @param c Camera + */ + void updateGeometry(Ogre::Camera *c); + + /** Get moon billboard + @return Moon billboard + */ + inline Ogre::BillboardSet *getMoonBillboard() + { + return mMoonBillboard; + } + + /** Get moon scene node + @return Moon scene node + */ + inline Ogre::SceneNode *getMoonSceneNode() + { + return mMoonSceneNode; + } + + /** Set moon size + @param MoonSize Moon size + */ + inline void setMoonSize(const Ogre::Real &MoonSize) + { + mMoonSize = MoonSize; + } + + /** Get moon size + @return Moon size + */ + inline const Ogre::Real &getMoonSize() const + { + return mMoonSize; + } + + /** Set moon halo intensity + @param MoonHaloIntensity Moon halo intensity + */ + inline void setMoonHaloIntensity(const Ogre::Real &MoonHaloIntensity) + { + mMoonHaloIntensity = MoonHaloIntensity; + } + + /** Get moon halo intensity + @return Moon halo intensity + */ + inline const Ogre::Real &getMoonHaloIntensity() const + { + return mMoonHaloIntensity; + } + + /** Set moon halo strength + @param MoonHaloStrength Moon halo strength (linear/exponential fading) + */ + inline void setMoonHaloStrength(const Ogre::Real &MoonHaloStrength) + { + mMoonHaloStrength = MoonHaloStrength; + } + + /** Get moon halo strength + @return Moon halo strength (linear/exponential fading) + */ + inline const Ogre::Real &getMoonHaloStrength() const + { + return mMoonHaloStrength; + } + + /** Is moon manager created? + @return true if yes, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + private: + /** Update moon bounds + @param c Camera + */ + void _updateMoonBounds(Ogre::Camera *c); + + /// Moon billboard + Ogre::BillboardSet *mMoonBillboard; + /// Moon scene node + Ogre::SceneNode *mMoonSceneNode; + + /// Is moon manager created? + bool mCreated; + + /// Moon size + Ogre::Real mMoonSize; + /// Moon halo intensity + Ogre::Real mMoonHaloIntensity; + /// Moon halo strength + Ogre::Real mMoonHaloStrength; + + /// Moon material + Ogre::MaterialPtr mMoonMaterial; + + /// SkyX parent pointer + SkyX *mSkyX; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/Prerequisites.h b/source/main/gfx/skyx/Prerequisites.h index cab0b6a5f3..085b2816bd 100644 --- a/source/main/gfx/skyx/Prerequisites.h +++ b/source/main/gfx/skyx/Prerequisites.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,8 +24,8 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_Prerequisites_H_ #define _SkyX_Prerequisites_H_ -#pragma warning (disable:4244) // conversion from 'xxx' to 'yyy', possible loss of data -#pragma warning (disable:4355) // 'this' : used in base member initializer list +#pragma warning(disable : 4244) // conversion from 'xxx' to 'yyy', possible loss of data +#pragma warning(disable : 4355) // 'this' : used in base member initializer list /// Include external headers #include diff --git a/source/main/gfx/skyx/SCfgFileManager.cpp b/source/main/gfx/skyx/SCfgFileManager.cpp index 5ab5c7b1f6..7cd0ad9df2 100644 --- a/source/main/gfx/skyx/SCfgFileManager.cpp +++ b/source/main/gfx/skyx/SCfgFileManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -23,213 +23,194 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to */ #include "SCfgFileManager.h" + #include "SkyX.h" namespace SkyX { - CfgFileManager::CfgFileManager(SkyX* s, BasicController *c, Ogre::Camera *d) - : mSkyX(s), mController(c), mCamera(d) - { - } - - CfgFileManager::~CfgFileManager() - { - } - - const bool CfgFileManager::load(const Ogre::String& File) const - { - std::pair CfgFileResult; - _loadCfgFile(File, CfgFileResult); - - if (!CfgFileResult.first) - { - return false; - } - - Ogre::ConfigFile &CfgFile = CfgFileResult.second; - - if (!_checkVersion(CfgFile)) - { - return false; - } - - - mSkyX->setTimeMultiplier(_getFloatValue(CfgFile, "TimeMultiplier")); - mController->setTime(_getVector3Value(CfgFile, "Time")); - mController->setMoonPhase(_getFloatValue(CfgFile, "MoonPhase")); - - mSkyX->getAtmosphereManager()->setOptions( - AtmosphereManager::Options( - _getFloatValue(CfgFile, "_InnerRadius"), - _getFloatValue(CfgFile, "_OuterRadius"), - _getFloatValue(CfgFile, "_HeightPosition"), - _getFloatValue(CfgFile, "_RayleighMultiplier"), - _getFloatValue(CfgFile, "_MieMultiplier"), - _getFloatValue(CfgFile, "_SunIntensity"), - _getVector3Value(CfgFile, "_WaveLength"), - _getFloatValue(CfgFile, "_G"), - _getFloatValue(CfgFile, "_Exposure"), - _getFloatValue(CfgFile, "_NumerOfSamples") - )); - - // Layered clouds - if (_getBoolValue(CfgFile, "layeredclouds") && !_getBoolValue(CfgFile, "volClouds")) - { - // Create layer cloud - if (mSkyX->getCloudsManager()->getCloudLayers().empty()) - { - mSkyX->getCloudsManager()->add(CloudLayer::Options( - _getFloatValue(CfgFile, "lHeight"), - _getFloatValue(CfgFile, "Scale"), - _getVector2Value(CfgFile, "WindDirection"), - _getFloatValue(CfgFile, "TimeMultiplier"), - _getFloatValue(CfgFile, "DistanceAttenuation"), - _getFloatValue(CfgFile, "DetailAttenuation"), - _getFloatValue(CfgFile, "HeightVolume"), - _getFloatValue(CfgFile, "VolumetricDisplacement") - )); - } - } - else - { - mSkyX->getVCloudsManager()->setWindSpeed(_getFloatValue(CfgFile, "WindSpeed")); - mSkyX->getVCloudsManager()->setAutoupdate(_getBoolValue(CfgFile, "AutoUpdate")); - mSkyX->getVCloudsManager()->setHeight(_getVector2Value(CfgFile, "vHeight")); - - VClouds::VClouds* vclouds = mSkyX->getVCloudsManager()->getVClouds(); - - vclouds->setWindDirection(_getDegreeValue(CfgFile, "WindDirection")); - - vclouds->setAmbientColor(_getVector3Value(CfgFile, "AmbientColor")); - vclouds->setLightResponse(_getVector4Value(CfgFile, "LightResponse")); - vclouds->setAmbientFactors(_getVector4Value(CfgFile, "AmbientFactors")); - vclouds->setWheater(_getVector2Value(CfgFile, "Wheater").x, _getVector2Value(CfgFile, "Wheater").y, _getBoolValue(CfgFile, "DelayedResponse")); - - // Create VClouds - if (!mSkyX->getVCloudsManager()->isCreated()) - { - // SkyX::MeshManager::getSkydomeRadius(...) works for both finite and infinite(=0) camera far clip distances - mSkyX->getVCloudsManager()->create(mSkyX->getMeshManager()->getSkydomeRadius(mCamera)); - } - - vclouds->getLightningManager()->setEnabled(_getBoolValue(CfgFile, "lightnings")); - - if (vclouds->getLightningManager()->isEnabled()) - { - vclouds->getLightningManager()->setAverageLightningApparitionTime(_getFloatValue(CfgFile, "AverageLightningApparitionTime")); - vclouds->getLightningManager()->setLightningColor(_getVector3Value(CfgFile, "LightningColor")); - vclouds->getLightningManager()->setLightningTimeMultiplier(_getFloatValue(CfgFile, "LightningTimeMultiplier")); - } - } - return true; - } - - const bool CfgFileManager::save(const Ogre::String& File, const Ogre::String& Path) const - { - Ogre::String Data = - "#SkyX cfg file.\n\n"; - - Data += "#SkyX version field\n"; - Data += _getVersionCfgString(); - - return _saveToFile(Data, File, Path); - } - - const bool CfgFileManager::_saveToFile(const Ogre::String& Data, const Ogre::String& File, const Ogre::String& Path) const - { - FILE *DestinationFile = fopen((Path+"/"+File).c_str(), "w"); - - if (!DestinationFile) - { - return false; - } - - fprintf(DestinationFile, "%s", Data.c_str()); - fclose(DestinationFile); - - SkyXLOG(File + " saved in " + Path + " ."); - - return true; - } - - const void CfgFileManager::_loadCfgFile(const Ogre::String& File, std::pair &Result) const - { - try - { - Result.second.load(Ogre::ResourceGroupManager::getSingleton().openResource(File, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)); - Result.first = true; - - } catch(...) - { - SkyXLOG("CfgFileManager::_getCfgFile(...): " + File + " not found in any resource group."); - Result.first = false; - } - - SkyXLOG(File + " loaded."); - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const int &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Real &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const bool &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector2 &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + Ogre::StringConverter::toString(Value.y) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector3 &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + Ogre::StringConverter::toString(Value.y) + "x" + Ogre::StringConverter::toString(Value.z) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector4 &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + Ogre::StringConverter::toString(Value.y) + "x" + Ogre::StringConverter::toString(Value.z) + "x" + Ogre::StringConverter::toString(Value.w) + "\n"; - } - - Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Degree &Value) - { - return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; - } - - bool CfgFileManager::_isStringInList(const Ogre::StringVector &List, const Ogre::String &Find) - { - for (unsigned int k = 0; k < List.size(); k++) - { - if (List[k] == Find) - { - return true; - } - } - - return false; - } - - const Ogre::String CfgFileManager::_getVersionCfgString() const - { - return "SkyXVersion=" + - // Major - Ogre::StringConverter::toString(SKYX_VERSION_MAJOR)+"." + - // Minor - Ogre::StringConverter::toString(SKYX_VERSION_MINOR) + "." + - // Patch - Ogre::StringConverter::toString(SKYX_VERSION_PATCH) + "\n\n"; - } - - const bool CfgFileManager::_checkVersion(Ogre::ConfigFile& CfgFile) const - { - // accept any + CfgFileManager::CfgFileManager(SkyX *s, BasicController *c, Ogre::Camera *d) : mSkyX(s), mController(c), mCamera(d) + { + } + + CfgFileManager::~CfgFileManager() + { + } + + const bool CfgFileManager::load(const Ogre::String &File) const + { + std::pair CfgFileResult; + _loadCfgFile(File, CfgFileResult); + + if (!CfgFileResult.first) { return false; } + + Ogre::ConfigFile &CfgFile = CfgFileResult.second; + + if (!_checkVersion(CfgFile)) { return false; } + + mSkyX->setTimeMultiplier(_getFloatValue(CfgFile, "TimeMultiplier")); + mController->setTime(_getVector3Value(CfgFile, "Time")); + mController->setMoonPhase(_getFloatValue(CfgFile, "MoonPhase")); + + mSkyX->getAtmosphereManager()->setOptions( + AtmosphereManager::Options(_getFloatValue(CfgFile, "_InnerRadius"), _getFloatValue(CfgFile, "_OuterRadius"), + _getFloatValue(CfgFile, "_HeightPosition"), _getFloatValue(CfgFile, "_RayleighMultiplier"), + _getFloatValue(CfgFile, "_MieMultiplier"), _getFloatValue(CfgFile, "_SunIntensity"), + _getVector3Value(CfgFile, "_WaveLength"), _getFloatValue(CfgFile, "_G"), + _getFloatValue(CfgFile, "_Exposure"), _getFloatValue(CfgFile, "_NumerOfSamples"))); + + // Layered clouds + if (_getBoolValue(CfgFile, "layeredclouds") && !_getBoolValue(CfgFile, "volClouds")) + { + // Create layer cloud + if (mSkyX->getCloudsManager()->getCloudLayers().empty()) + { + mSkyX->getCloudsManager()->add(CloudLayer::Options( + _getFloatValue(CfgFile, "lHeight"), _getFloatValue(CfgFile, "Scale"), + _getVector2Value(CfgFile, "WindDirection"), _getFloatValue(CfgFile, "TimeMultiplier"), + _getFloatValue(CfgFile, "DistanceAttenuation"), _getFloatValue(CfgFile, "DetailAttenuation"), + _getFloatValue(CfgFile, "HeightVolume"), _getFloatValue(CfgFile, "VolumetricDisplacement"))); + } + } + else + { + mSkyX->getVCloudsManager()->setWindSpeed(_getFloatValue(CfgFile, "WindSpeed")); + mSkyX->getVCloudsManager()->setAutoupdate(_getBoolValue(CfgFile, "AutoUpdate")); + mSkyX->getVCloudsManager()->setHeight(_getVector2Value(CfgFile, "vHeight")); + + VClouds::VClouds *vclouds = mSkyX->getVCloudsManager()->getVClouds(); + + vclouds->setWindDirection(_getDegreeValue(CfgFile, "WindDirection")); + + vclouds->setAmbientColor(_getVector3Value(CfgFile, "AmbientColor")); + vclouds->setLightResponse(_getVector4Value(CfgFile, "LightResponse")); + vclouds->setAmbientFactors(_getVector4Value(CfgFile, "AmbientFactors")); + vclouds->setWheater(_getVector2Value(CfgFile, "Wheater").x, _getVector2Value(CfgFile, "Wheater").y, + _getBoolValue(CfgFile, "DelayedResponse")); + + // Create VClouds + if (!mSkyX->getVCloudsManager()->isCreated()) + { + // SkyX::MeshManager::getSkydomeRadius(...) works for both finite and infinite(=0) camera far clip distances + mSkyX->getVCloudsManager()->create(mSkyX->getMeshManager()->getSkydomeRadius(mCamera)); + } + + vclouds->getLightningManager()->setEnabled(_getBoolValue(CfgFile, "lightnings")); + + if (vclouds->getLightningManager()->isEnabled()) + { + vclouds->getLightningManager()->setAverageLightningApparitionTime( + _getFloatValue(CfgFile, "AverageLightningApparitionTime")); + vclouds->getLightningManager()->setLightningColor(_getVector3Value(CfgFile, "LightningColor")); + vclouds->getLightningManager()->setLightningTimeMultiplier(_getFloatValue(CfgFile, "LightningTimeMultiplier")); + } + } + return true; + } + + const bool CfgFileManager::save(const Ogre::String &File, const Ogre::String &Path) const + { + Ogre::String Data = "#SkyX cfg file.\n\n"; + + Data += "#SkyX version field\n"; + Data += _getVersionCfgString(); + + return _saveToFile(Data, File, Path); + } + + const bool CfgFileManager::_saveToFile(const Ogre::String &Data, const Ogre::String &File, const Ogre::String &Path) const + { + FILE *DestinationFile = fopen((Path + "/" + File).c_str(), "w"); + + if (!DestinationFile) { return false; } + + fprintf(DestinationFile, "%s", Data.c_str()); + fclose(DestinationFile); + + SkyXLOG(File + " saved in " + Path + " ."); + + return true; + } + + const void CfgFileManager::_loadCfgFile(const Ogre::String &File, std::pair &Result) const + { + try + { + Result.second.load(Ogre::ResourceGroupManager::getSingleton().openResource( + File, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)); + Result.first = true; + } + catch (...) + { + SkyXLOG("CfgFileManager::_getCfgFile(...): " + File + " not found in any resource group."); + Result.first = false; + } + + SkyXLOG(File + " loaded."); + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const int &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Real &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const bool &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector2 &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + + Ogre::StringConverter::toString(Value.y) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector3 &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + + Ogre::StringConverter::toString(Value.y) + "x" + Ogre::StringConverter::toString(Value.z) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Vector4 &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value.x) + "x" + + Ogre::StringConverter::toString(Value.y) + "x" + Ogre::StringConverter::toString(Value.z) + "x" + + Ogre::StringConverter::toString(Value.w) + "\n"; + } + + Ogre::String CfgFileManager::_getCfgString(const Ogre::String &Name, const Ogre::Degree &Value) + { + return "" + Name + "=" + Ogre::StringConverter::toString(Value) + "\n"; + } + + bool CfgFileManager::_isStringInList(const Ogre::StringVector &List, const Ogre::String &Find) + { + for (unsigned int k = 0; k < List.size(); k++) + { + if (List[k] == Find) { return true; } + } + + return false; + } + + const Ogre::String CfgFileManager::_getVersionCfgString() const + { + return "SkyXVersion=" + + // Major + Ogre::StringConverter::toString(SKYX_VERSION_MAJOR) + "." + + // Minor + Ogre::StringConverter::toString(SKYX_VERSION_MINOR) + "." + + // Patch + Ogre::StringConverter::toString(SKYX_VERSION_PATCH) + "\n\n"; + } + + const bool CfgFileManager::_checkVersion(Ogre::ConfigFile &CfgFile) const + { + // accept any #if 0 if(CfgFile.getSetting("HydraxVersion") != ( // Major @@ -244,112 +225,89 @@ namespace SkyX return false; } #endif // 0 - return true; - } - - int CfgFileManager::_getIntValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return 0; - } - else - { - return Ogre::StringConverter::parseInt(Value); - } - } - - Ogre::Real CfgFileManager::_getFloatValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return 0; - } - else - { - return Ogre::StringConverter::parseReal(Value); - } - } - - bool CfgFileManager::_getBoolValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return false; - } - else - { - return Ogre::StringConverter::parseBool(Value); - } - } - - Ogre::Vector2 CfgFileManager::_getVector2Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Ogre::Vector2(0,0); - } - else - { - return Ogre::Vector2(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1])); - } - } - - Ogre::Vector3 CfgFileManager::_getVector3Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Ogre::Vector3(0,0,0); - } - else - { - return Ogre::Vector3(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[2])); - } - } - - Ogre::Vector4 CfgFileManager::_getVector4Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Ogre::Vector4(0, 0, 0, 0); - } - else - { - return Ogre::Vector4( - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[2]), - Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[3]) - ); - } - } - - Ogre::Degree CfgFileManager::_getDegreeValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name) - { - Ogre::String Value = CfgFile.getSetting("" + Name); - - if (Value == "") - { - return Ogre::Degree(0); - } - else - { - return Ogre::Degree(Ogre::StringConverter::parseReal(Value)); - } - } -} + return true; + } + + int CfgFileManager::_getIntValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return 0; } + else + { + return Ogre::StringConverter::parseInt(Value); + } + } + + Ogre::Real CfgFileManager::_getFloatValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return 0; } + else + { + return Ogre::StringConverter::parseReal(Value); + } + } + + bool CfgFileManager::_getBoolValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return false; } + else + { + return Ogre::StringConverter::parseBool(Value); + } + } + + Ogre::Vector2 CfgFileManager::_getVector2Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Ogre::Vector2(0, 0); } + else + { + return Ogre::Vector2(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1])); + } + } + + Ogre::Vector3 CfgFileManager::_getVector3Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Ogre::Vector3(0, 0, 0); } + else + { + return Ogre::Vector3(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[2])); + } + } + + Ogre::Vector4 CfgFileManager::_getVector4Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Ogre::Vector4(0, 0, 0, 0); } + else + { + return Ogre::Vector4(Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[0]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[1]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[2]), + Ogre::StringConverter::parseReal(Ogre::StringUtil::split(Value, "x")[3])); + } + } + + Ogre::Degree CfgFileManager::_getDegreeValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name) + { + Ogre::String Value = CfgFile.getSetting("" + Name); + + if (Value == "") { return Ogre::Degree(0); } + else + { + return Ogre::Degree(Ogre::StringConverter::parseReal(Value)); + } + } +} // namespace SkyX diff --git a/source/main/gfx/skyx/SCfgFileManager.h b/source/main/gfx/skyx/SCfgFileManager.h index b8d4e4ec89..d31e98542a 100644 --- a/source/main/gfx/skyx/SCfgFileManager.h +++ b/source/main/gfx/skyx/SCfgFileManager.h @@ -3,7 +3,7 @@ This source file is part of Hydrax. Visit --- -Copyright (C) 2008 Xavier Verguín González +Copyright (C) 2008 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under @@ -25,164 +25,164 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_CfgFileManager_H_ #define _SkyX_CfgFileManager_H_ -#include "Prerequisites.h" - #include "Help.h" +#include "Prerequisites.h" namespace SkyX { - class SkyX; - class BasicController; - - /** Config file manager. - Class to load/save all Hydrax options from/to a config file - */ - class CfgFileManager - { - public: - /** Constructor - @param h Hydrax parent pointer - */ - CfgFileManager(SkyX *s, BasicController *c, Ogre::Camera* d); - - /** Destructor - */ + class SkyX; + class BasicController; + + /** Config file manager. + Class to load/save all Hydrax options from/to a config file + */ + class CfgFileManager + { + public: + /** Constructor + @param h Hydrax parent pointer + */ + CfgFileManager(SkyX *s, BasicController *c, Ogre::Camera *d); + + /** Destructor + */ ~CfgFileManager(); - /** Load hydrax cfg file - @param File File name - @return false if an error has been ocurred(Check the log file in this case). - */ - const bool load(const Ogre::String& File) const; - - /** Save current hydrax config to a file - @param File Destination file name - @param Path File path - @return false if an error has been ocurred(Check the log file in this case). - */ - const bool save(const Ogre::String& File, const Ogre::String& Path = "") const; - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return int cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const int& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Ogre::Real cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Ogre::Real& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return bool cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const bool& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Ogre::Vector2 cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Ogre::Vector2& Value); - - /** Get the cfg string - @param Name Parameter name - @param Value Parameter value - @return Ogre::Vector3 cfg string - */ - static Ogre::String _getCfgString(const Ogre::String& Name, const Ogre::Vector3& Value); - - static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Vector4 &Value); - - static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Degree &Value); - - /** Get int value - @param CfgFile Config file - @param Name Parameter name - @return int value - @remarks if the parameter isn't found or the data type is not an int value, return 0 as default - */ - static int _getIntValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get float value - @param CfgFile Config file - @param Name Parameter name - @return float value - @remarks if the parameter isn't found or the data type is not a float value, return 0 as default - */ - static Ogre::Real _getFloatValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get bool value - @param CfgFile Config file - @param Name Parameter name - @return bool value - @remarks if the parameter isn't found or the data type is not a bool value, return false as default - */ - static bool _getBoolValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get vector2 value - @param CfgFile Config file - @param Name Parameter name - @return vector2 value - @remarks if the parameter isn't found or the data type is not an int value, returns (0,0) as default - */ - static Ogre::Vector2 _getVector2Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Get vector3 value - @param CfgFile Config file - @param Name Parameter name - @return vector3 value - @remarks if the parameter isn't found or the data type is not an int value, returns (0,0,0) as default - */ - static Ogre::Vector3 _getVector3Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - static Ogre::Vector4 _getVector4Value(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - static Ogre::Degree _getDegreeValue(Ogre::ConfigFile& CfgFile, const Ogre::String Name); - - /** Check is a std::vector contains a specified Ogre::String - @param List String list - @param Find String to find - @return true if it's contained, false if not - */ - static bool _isStringInList(const Ogre::StringVector &List, const Ogre::String &Find); - - private: - /** Save a string in file - @param Data Data - @param File Destination file - @param Path File path - @return false if an error has ocurred - */ - const bool _saveToFile(const Ogre::String& Data, const Ogre::String& File, const Ogre::String& Path) const; - - /** Load a cfg file in an Ogre::ConfigFile - @param File File name - @param Result, std::pair First: False if the file isn't in the Hydrax resource group, Second: Ogre::ConfigFile - */ - const void _loadCfgFile(const Ogre::String& File, std::pair &Result) const; - - /** Get hydrax version cfg string - @return Hydrax version cfg string - */ - const Ogre::String _getVersionCfgString() const; - - /** Check hydrax version cfg file - @param CfgFile Config file - @return true if it's the same version, false if not. - */ - const bool _checkVersion(Ogre::ConfigFile& CfgFile) const; - - /// Hydrax parent pointer - SkyX* mSkyX; - BasicController* mController; - Ogre::Camera *mCamera; - }; -}; + /** Load hydrax cfg file + @param File File name + @return false if an error has been ocurred(Check the log file in this case). + */ + const bool load(const Ogre::String &File) const; + + /** Save current hydrax config to a file + @param File Destination file name + @param Path File path + @return false if an error has been ocurred(Check the log file in this case). + */ + const bool save(const Ogre::String &File, const Ogre::String &Path = "") const; + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return int cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const int &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Ogre::Real cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Real &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return bool cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const bool &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Ogre::Vector2 cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Vector2 &Value); + + /** Get the cfg string + @param Name Parameter name + @param Value Parameter value + @return Ogre::Vector3 cfg string + */ + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Vector3 &Value); + + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Vector4 &Value); + + static Ogre::String _getCfgString(const Ogre::String &Name, const Ogre::Degree &Value); + + /** Get int value + @param CfgFile Config file + @param Name Parameter name + @return int value + @remarks if the parameter isn't found or the data type is not an int value, return 0 as default + */ + static int _getIntValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get float value + @param CfgFile Config file + @param Name Parameter name + @return float value + @remarks if the parameter isn't found or the data type is not a float value, return 0 as default + */ + static Ogre::Real _getFloatValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get bool value + @param CfgFile Config file + @param Name Parameter name + @return bool value + @remarks if the parameter isn't found or the data type is not a bool value, return false as default + */ + static bool _getBoolValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get vector2 value + @param CfgFile Config file + @param Name Parameter name + @return vector2 value + @remarks if the parameter isn't found or the data type is not an int value, returns (0,0) as default + */ + static Ogre::Vector2 _getVector2Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Get vector3 value + @param CfgFile Config file + @param Name Parameter name + @return vector3 value + @remarks if the parameter isn't found or the data type is not an int value, returns (0,0,0) as default + */ + static Ogre::Vector3 _getVector3Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + static Ogre::Vector4 _getVector4Value(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + static Ogre::Degree _getDegreeValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name); + + /** Check is a std::vector contains a specified Ogre::String + @param List String list + @param Find String to find + @return true if it's contained, false if not + */ + static bool _isStringInList(const Ogre::StringVector &List, const Ogre::String &Find); + + private: + /** Save a string in file + @param Data Data + @param File Destination file + @param Path File path + @return false if an error has ocurred + */ + const bool _saveToFile(const Ogre::String &Data, const Ogre::String &File, const Ogre::String &Path) const; + + /** Load a cfg file in an Ogre::ConfigFile + @param File File name + @param Result, std::pair First: False if the file isn't in the Hydrax resource group, Second: + Ogre::ConfigFile + */ + const void _loadCfgFile(const Ogre::String &File, std::pair &Result) const; + + /** Get hydrax version cfg string + @return Hydrax version cfg string + */ + const Ogre::String _getVersionCfgString() const; + + /** Check hydrax version cfg file + @param CfgFile Config file + @return true if it's the same version, false if not. + */ + const bool _checkVersion(Ogre::ConfigFile &CfgFile) const; + + /// Hydrax parent pointer + SkyX * mSkyX; + BasicController *mController; + Ogre::Camera * mCamera; + }; +}; // namespace SkyX #endif diff --git a/source/main/gfx/skyx/SkyX.cpp b/source/main/gfx/skyx/SkyX.cpp index bdc685ede3..a1b2055f7b 100644 --- a/source/main/gfx/skyx/SkyX.cpp +++ b/source/main/gfx/skyx/SkyX.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -21,254 +21,203 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to -------------------------------------------------------------------------------- */ -#pragma warning(disable:4355) +#pragma warning(disable : 4355) #include "SkyX.h" namespace SkyX { - SkyX::SkyX(Ogre::SceneManager* sm, Controller* c) - : Ogre::FrameListener() - , Ogre::RenderTargetListener() - , mSceneManager(sm) - , mController(c) - , mCamera(0) - , mMeshManager(new MeshManager(this)) - , mAtmosphereManager(new AtmosphereManager(this)) - , mGPUManager(new GPUManager(this)) - , mMoonManager(new MoonManager(this)) - , mCloudsManager(new CloudsManager(this)) - , mRenderQueueGroups(RenderQueueGroups(Ogre::RENDER_QUEUE_SKIES_EARLY, Ogre::RENDER_QUEUE_3, Ogre::RENDER_QUEUE_4, Ogre::RENDER_QUEUE_2)) - , mCreated(false) - , mLastCameraPosition(Ogre::Vector3(0,0,0)) - , mLastCameraFarClipDistance(-1) - , mInfiniteCameraFarClipDistance(100000) - , mVisible(true) - , mLightingMode(LM_LDR) - , mStarfield(true) - , mTimeMultiplier(0.1f) - , mTimeOffset(0.0f) - { - // Need to be instanced here, when SkyX::mSceneManager is valid - mVCloudsManager = new VCloudsManager(this); - } - - SkyX::~SkyX() - { - remove(); - - delete mMeshManager; - delete mAtmosphereManager; - delete mGPUManager; - delete mMoonManager; - delete mCloudsManager; - delete mVCloudsManager; - - if (mCfgFileManager) - delete mCfgFileManager; - - if (mController->getDeleteBySkyX()) - { - delete mController; - } - } - - void SkyX::create() - { - if (mCreated) - { - return; - } - - mGPUManager->_notifySkydomeMaterialChanged(); - - mMeshManager->create(); - mMeshManager->setMaterialName(mGPUManager->getSkydomeMaterialName()); - - mAtmosphereManager->_update(mAtmosphereManager->getOptions(), true); - - if (mStarfield) - { - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uTime", mTimeOffset*0.5f, false); - } - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uLightDir", mController->getSunDirection()); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uLightDir", mController->getSunDirection()); - - mMoonManager->create(); - - setVisible(mVisible); - - mLastCameraPosition = Ogre::Vector3(0,0,0); - mLastCameraFarClipDistance = -1; - - mCreated = true; - } - - void SkyX::remove() - { - if (!mCreated) - { - return; - } - - mCloudsManager->removeAll(); - mMeshManager->remove(); - mMoonManager->remove(); - mVCloudsManager->remove(); - - mCamera = 0; - - mCreated = false; - } - - void SkyX::update(const Ogre::Real& timeSinceLastFrame) - { - if (!mCreated) - { - return; - } - - if (mTimeMultiplier != 0) - { - float timemultiplied = timeSinceLastFrame * mTimeMultiplier; - - mTimeOffset += timemultiplied; - - mController->update(timemultiplied); - - if (mStarfield) - { - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uTime", mTimeOffset*0.5f, false); - } - } - - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uLightDir", mController->getSunDirection()); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uLightDir", mController->getSunDirection()); - - mMoonManager->updateMoonPhase(mController->getMoonPhase()); - mCloudsManager->update(); - mVCloudsManager->update(timeSinceLastFrame); - } + SkyX::SkyX(Ogre::SceneManager *sm, Controller *c) + : Ogre::FrameListener(), Ogre::RenderTargetListener(), mSceneManager(sm), mController(c), mCamera(0), + mMeshManager(new MeshManager(this)), mAtmosphereManager(new AtmosphereManager(this)), mGPUManager(new GPUManager(this)), + mMoonManager(new MoonManager(this)), mCloudsManager(new CloudsManager(this)), + mRenderQueueGroups(RenderQueueGroups(Ogre::RENDER_QUEUE_SKIES_EARLY, Ogre::RENDER_QUEUE_3, Ogre::RENDER_QUEUE_4, + Ogre::RENDER_QUEUE_2)), + mCreated(false), mLastCameraPosition(Ogre::Vector3(0, 0, 0)), mLastCameraFarClipDistance(-1), + mInfiniteCameraFarClipDistance(100000), mVisible(true), mLightingMode(LM_LDR), mStarfield(true), mTimeMultiplier(0.1f), + mTimeOffset(0.0f) + { + // Need to be instanced here, when SkyX::mSceneManager is valid + mVCloudsManager = new VCloudsManager(this); + } - void SkyX::notifyCameraRender(Ogre::Camera* c) - { - if (!mCreated) - { - return; - } + SkyX::~SkyX() + { + remove(); - mCamera = c; - - if (mLastCameraPosition != c->getDerivedPosition()) - { - mMeshManager->getSceneNode()->setPosition(mCamera->getDerivedPosition()); + delete mMeshManager; + delete mAtmosphereManager; + delete mGPUManager; + delete mMoonManager; + delete mCloudsManager; + delete mVCloudsManager; - mLastCameraPosition = mCamera->getDerivedPosition(); - } + if (mCfgFileManager) delete mCfgFileManager; - if (mLastCameraFarClipDistance != c->getFarClipDistance()) - { - mMeshManager->updateGeometry(c); + if (mController->getDeleteBySkyX()) { delete mController; } + } - mLastCameraFarClipDistance = mCamera->getFarClipDistance(); - } + void SkyX::create() + { + if (mCreated) { return; } - mMoonManager->updateGeometry(c); + mGPUManager->_notifySkydomeMaterialChanged(); - mVCloudsManager->notifyCameraRender(c); - } + mMeshManager->create(); + mMeshManager->setMaterialName(mGPUManager->getSkydomeMaterialName()); - void SkyX::setVisible(const bool& visible) - { - mVisible = visible; + mAtmosphereManager->_update(mAtmosphereManager->getOptions(), true); - if (!mCreated) - { - return; - } - - mMeshManager->getSceneNode()->setVisible(mVisible); - mMoonManager->getMoonSceneNode()->setVisible(mVisible); + if (mStarfield) { mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uTime", mTimeOffset * 0.5f, false); } - if (mVCloudsManager->isCreated()) - { - mVCloudsManager->getVClouds()->setVisible(mVisible); - } - } + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uLightDir", mController->getSunDirection()); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uLightDir", mController->getSunDirection()); - void SkyX::setRenderQueueGroups(const RenderQueueGroups& rqg) - { - mRenderQueueGroups = rqg; - - mVCloudsManager->getVClouds()->setRenderQueueGroups( - VClouds::VClouds::RenderQueueGroups(mRenderQueueGroups.vclouds, mRenderQueueGroups.vcloudsLightningsUnder, mRenderQueueGroups.vcloudsLightningsOver)); - - if (!mCreated) - { - return; - } - - mMeshManager->getEntity()->setRenderQueueGroup(mRenderQueueGroups.skydome); - mMoonManager->getMoonBillboard()->setRenderQueueGroup(mRenderQueueGroups.skydome+1); - } - - void SkyX::setLightingMode(const LightingMode& lm) - { - mLightingMode = lm; + mMoonManager->create(); - if (!mCreated) - { - return; - } - - mGPUManager->_notifySkydomeMaterialChanged(); - - // Update skydome material - mMeshManager->setMaterialName(mGPUManager->getSkydomeMaterialName()); - // Update layered clouds material - mCloudsManager->registerAll(); - // Update ground passes materials and update textures gamma correction - mGPUManager->_updateFP(); - - // Update parameters - mAtmosphereManager->_update(mAtmosphereManager->getOptions(), true); - } - - void SkyX::setStarfieldEnabled(const bool& Enabled) - { - mStarfield = Enabled; - - if (!mCreated) - { - return; - } - - mGPUManager->_notifySkydomeMaterialChanged(); - - // Update skydome material - mMeshManager->setMaterialName(mGPUManager->getSkydomeMaterialName()); - - // Update parameters - mAtmosphereManager->_update(mAtmosphereManager->getOptions(), true); - - if (mStarfield) - { - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uTime", mTimeOffset*0.5f, false); - } + setVisible(mVisible); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uLightDir", mController->getSunDirection()); - mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uLightDir", mController->getSunDirection()); - } + mLastCameraPosition = Ogre::Vector3(0, 0, 0); + mLastCameraFarClipDistance = -1; - bool SkyX::frameStarted(const Ogre::FrameEvent& e) - { - update(e.timeSinceLastFrame); - return true; - } + mCreated = true; + } - void SkyX::preViewportUpdate(const Ogre::RenderTargetViewportEvent& evt) - { - notifyCameraRender(evt.source->getCamera()); - } + void SkyX::remove() + { + if (!mCreated) { return; } + + mCloudsManager->removeAll(); + mMeshManager->remove(); + mMoonManager->remove(); + mVCloudsManager->remove(); + + mCamera = 0; + + mCreated = false; + } + + void SkyX::update(const Ogre::Real &timeSinceLastFrame) + { + if (!mCreated) { return; } + + if (mTimeMultiplier != 0) + { + float timemultiplied = timeSinceLastFrame * mTimeMultiplier; + + mTimeOffset += timemultiplied; + + mController->update(timemultiplied); + + if (mStarfield) + { mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uTime", mTimeOffset * 0.5f, false); } + } + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uLightDir", mController->getSunDirection()); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uLightDir", mController->getSunDirection()); + + mMoonManager->updateMoonPhase(mController->getMoonPhase()); + mCloudsManager->update(); + mVCloudsManager->update(timeSinceLastFrame); + } + + void SkyX::notifyCameraRender(Ogre::Camera *c) + { + if (!mCreated) { return; } + + mCamera = c; + + if (mLastCameraPosition != c->getDerivedPosition()) + { + mMeshManager->getSceneNode()->setPosition(mCamera->getDerivedPosition()); + + mLastCameraPosition = mCamera->getDerivedPosition(); + } + + if (mLastCameraFarClipDistance != c->getFarClipDistance()) + { + mMeshManager->updateGeometry(c); + + mLastCameraFarClipDistance = mCamera->getFarClipDistance(); + } + + mMoonManager->updateGeometry(c); + + mVCloudsManager->notifyCameraRender(c); + } + + void SkyX::setVisible(const bool &visible) + { + mVisible = visible; + + if (!mCreated) { return; } + + mMeshManager->getSceneNode()->setVisible(mVisible); + mMoonManager->getMoonSceneNode()->setVisible(mVisible); + + if (mVCloudsManager->isCreated()) { mVCloudsManager->getVClouds()->setVisible(mVisible); } + } + + void SkyX::setRenderQueueGroups(const RenderQueueGroups &rqg) + { + mRenderQueueGroups = rqg; + + mVCloudsManager->getVClouds()->setRenderQueueGroups(VClouds::VClouds::RenderQueueGroups( + mRenderQueueGroups.vclouds, mRenderQueueGroups.vcloudsLightningsUnder, mRenderQueueGroups.vcloudsLightningsOver)); + + if (!mCreated) { return; } + + mMeshManager->getEntity()->setRenderQueueGroup(mRenderQueueGroups.skydome); + mMoonManager->getMoonBillboard()->setRenderQueueGroup(mRenderQueueGroups.skydome + 1); + } + + void SkyX::setLightingMode(const LightingMode &lm) + { + mLightingMode = lm; + + if (!mCreated) { return; } + + mGPUManager->_notifySkydomeMaterialChanged(); + + // Update skydome material + mMeshManager->setMaterialName(mGPUManager->getSkydomeMaterialName()); + // Update layered clouds material + mCloudsManager->registerAll(); + // Update ground passes materials and update textures gamma correction + mGPUManager->_updateFP(); + + // Update parameters + mAtmosphereManager->_update(mAtmosphereManager->getOptions(), true); + } + + void SkyX::setStarfieldEnabled(const bool &Enabled) + { + mStarfield = Enabled; + + if (!mCreated) { return; } + + mGPUManager->_notifySkydomeMaterialChanged(); + + // Update skydome material + mMeshManager->setMaterialName(mGPUManager->getSkydomeMaterialName()); + + // Update parameters + mAtmosphereManager->_update(mAtmosphereManager->getOptions(), true); + + if (mStarfield) { mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uTime", mTimeOffset * 0.5f, false); } + + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uLightDir", mController->getSunDirection()); + mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uLightDir", mController->getSunDirection()); + } + + bool SkyX::frameStarted(const Ogre::FrameEvent &e) + { + update(e.timeSinceLastFrame); + return true; + } + + void SkyX::preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) + { + notifyCameraRender(evt.source->getCamera()); + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/SkyX.h b/source/main/gfx/skyx/SkyX.h index 0716c3f5c1..1f602308a8 100644 --- a/source/main/gfx/skyx/SkyX.h +++ b/source/main/gfx/skyx/SkyX.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,386 +24,383 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_SkyX_H_ #define _SkyX_SkyX_H_ -#include "Prerequisites.h" - -#include "MeshManager.h" #include "AtmosphereManager.h" -#include "GPUManager.h" -#include "MoonManager.h" +#include "BasicController.h" #include "CloudsManager.h" #include "ColorGradient.h" #include "Controller.h" -#include "BasicController.h" -#include "VCloudsManager.h" -#include "VClouds/VClouds.h" -#include "VClouds/GeometryManager.h" -#include "VClouds/GeometryBlock.h" -#include "VClouds/FastFakeRandom.h" -#include "VClouds/Ellipsoid.h" -#include "VClouds/DataManager.h" +#include "GPUManager.h" +#include "MeshManager.h" +#include "MoonManager.h" +#include "Prerequisites.h" #include "SCfgFileManager.h" +#include "VClouds/DataManager.h" +#include "VClouds/Ellipsoid.h" +#include "VClouds/FastFakeRandom.h" +#include "VClouds/GeometryBlock.h" +#include "VClouds/GeometryManager.h" +#include "VClouds/VClouds.h" +#include "VCloudsManager.h" namespace SkyX { - /** SkyX class - Create simple and beautiful skies! - @remarks How to update SkyX: - Updating SkyX is a very easy task that can be done manually or automatically by using listeners. - There're two update steps in SkyX: per-frame update and per-camera update, and the order is very - important. - The per-frame update must be performed at first: SkyX::update(...), after that and before each - camera render operation SkyX::notifyCameraRender(...) must be invoked. - Both updates can be automatically performed by using listeners: the Ogre::FrameListener is used - for the per-frame udpate, and the Ogre::RenderTargetListener is used for the per-camera update. - For more information have a look to sample projects. - + /** SkyX class + Create simple and beautiful skies! + @remarks How to update SkyX: + Updating SkyX is a very easy task that can be done manually or automatically by using listeners. + There're two update steps in SkyX: per-frame update and per-camera update, and the order is very + important. + The per-frame update must be performed at first: SkyX::update(...), after that and before each + camera render operation SkyX::notifyCameraRender(...) must be invoked. + Both updates can be automatically performed by using listeners: the Ogre::FrameListener is used + for the per-frame udpate, and the Ogre::RenderTargetListener is used for the per-camera update. + For more information have a look to sample projects. + */ - class SkyX : public Ogre::FrameListener, public Ogre::RenderTargetListener - { - public: - /** Render queue groups - */ - struct RenderQueueGroups - { - /** Constructor - @param s Skydome render queue group (Note: Moon = skydome_render_queue+1) - @param vc VClouds render queue group - @param vclu VClouds lightnings render queue group (when the camera is under the cloud field) - @param vclo VClouds lightnings render queue group (when the camera is over the cloud field) - */ - inline RenderQueueGroups(const Ogre::uint8& s, const Ogre::uint8& vc, const Ogre::uint8& vclu, const Ogre::uint8& vclo) - : skydome(s), vclouds(vc), vcloudsLightningsUnder(vclu), vcloudsLightningsOver(vclo) - { - } - - /// Skydome render queue group (Note: Moon = skydome_render_queue+1) - Ogre::uint8 skydome; - /// VClouds render queue group - Ogre::uint8 vclouds; - /// VClouds lightnings render queue group (when the camera is under the cloud field) - Ogre::uint8 vcloudsLightningsUnder; - /// VClouds lightnings render queue group (when the camera is over the cloud field) - Ogre::uint8 vcloudsLightningsOver; - }; - - /** Lighting mode enumeration - SkyX is designed for true HDR rendering, but there is a big number of applications - which don't use HDR rendering, due to this fact a little exponential tone-mapping - algoritm is applied to SkyX materials if LM_LDR is selected. (See: AtmosphereManager::Options::Exposure) - Select LM_HDR if your app is designed for true HDR rendering. In HDR mode, we assume you're ussing a - full linear rendering pipeline, so all textures are gamma corrected if needed. - */ - enum LightingMode - { - /// Low dynamic range - LM_LDR = 0, - /// High dynamic range - LM_HDR = 1 - }; - - /** Contructor - @param sm Ogre Scene manager - @param c SkyX controller - */ - SkyX(Ogre::SceneManager* sm, Controller* c); - - /** Destructor - */ - ~SkyX(); - - /** Create SkyX + class SkyX : public Ogre::FrameListener, public Ogre::RenderTargetListener + { + public: + /** Render queue groups + */ + struct RenderQueueGroups + { + /** Constructor + @param s Skydome render queue group (Note: Moon = skydome_render_queue+1) + @param vc VClouds render queue group + @param vclu VClouds lightnings render queue group (when the camera is under the cloud field) + @param vclo VClouds lightnings render queue group (when the camera is over the cloud field) + */ + inline RenderQueueGroups(const Ogre::uint8 &s, const Ogre::uint8 &vc, const Ogre::uint8 &vclu, + const Ogre::uint8 &vclo) + : skydome(s), vclouds(vc), vcloudsLightningsUnder(vclu), vcloudsLightningsOver(vclo) + { + } + + /// Skydome render queue group (Note: Moon = skydome_render_queue+1) + Ogre::uint8 skydome; + /// VClouds render queue group + Ogre::uint8 vclouds; + /// VClouds lightnings render queue group (when the camera is under the cloud field) + Ogre::uint8 vcloudsLightningsUnder; + /// VClouds lightnings render queue group (when the camera is over the cloud field) + Ogre::uint8 vcloudsLightningsOver; + }; + + /** Lighting mode enumeration + SkyX is designed for true HDR rendering, but there is a big number of applications + which don't use HDR rendering, due to this fact a little exponential tone-mapping + algoritm is applied to SkyX materials if LM_LDR is selected. (See: AtmosphereManager::Options::Exposure) + Select LM_HDR if your app is designed for true HDR rendering. In HDR mode, we assume you're ussing a + full linear rendering pipeline, so all textures are gamma corrected if needed. + */ + enum LightingMode + { + /// Low dynamic range + LM_LDR = 0, + /// High dynamic range + LM_HDR = 1 + }; + + /** Contructor + @param sm Ogre Scene manager + @param c SkyX controller + */ + SkyX(Ogre::SceneManager *sm, Controller *c); + + /** Destructor + */ + ~SkyX(); + + /** Create SkyX */ void create(); - /** Remove SkyX (free resources) - */ - void remove(); + /** Remove SkyX (free resources) + */ + void remove(); /** Update (to be invoked per frame) - @param timeSinceLastFrame Time elapsed since last frame + @param timeSinceLastFrame Time elapsed since last frame @remarks Invoke this function only one time per frame. - Per-frame update must be performed before per-camera updates through SkyX::notifyCameraRender(...) - Also it's possible to use listeners, making all this process transparent, - just register SkyX in ogre root through Ogre::Root::addFrameListener(...) + Per-frame update must be performed before per-camera updates through SkyX::notifyCameraRender(...) + Also it's possible to use listeners, making all this process transparent, + just register SkyX in ogre root through Ogre::Root::addFrameListener(...) */ void update(const Ogre::Real &timeSinceLastFrame); - /** Notify camera render (to be invoked per camera and per frame) - @param c Camera - @remarks Invoke this method manually before the camera render operation - Per-camera updates must be performed after the per-frame update through SkyX::update(...) - Also it's possible to use listeners, making all this process transparent, - just register SkyX in your render target through Ogre::RenderTarget::addListener(...) - */ - void notifyCameraRender(Ogre::Camera* c); - - /** Is SkyX created? - @return true if yes, false if not - */ - inline const bool isCreated() const - { - return mCreated; - } - - /** Set visible - @param visible true to set SkyX visible, false to hide it - */ - void setVisible(const bool& visible); - - /** Is SkyX visible? - @return true if SkyX is visible, false otherwise - */ - inline const bool& isVisible() const - { - return mVisible; - } - - /** Set time multiplier - @param TimeMultiplier Time multiplier - @remarks The time multiplier can be a negative number, 0 will disable auto-updating - For setting a custom time of day, check: AtmosphereManager::Options::Time - */ - inline void setTimeMultiplier(const Ogre::Real& TimeMultiplier) - { - mTimeMultiplier = TimeMultiplier; - mVCloudsManager->_updateWindSpeedConfig(); - } - - /** Get time multiplier - @return Time multiplier - */ - inline const Ogre::Real& getTimeMultiplier() const - { - return mTimeMultiplier; - } - - /** Get mesh manager - @return Mesh manager pointer - */ - inline MeshManager* getMeshManager() - { - return mMeshManager; - } - - /** Get atmosphere manager - @return Atmosphere manager pointer - */ - inline AtmosphereManager* getAtmosphereManager() - { - return mAtmosphereManager; - } - - /** Get GPU manager - @return Atmosphere manager pointer - */ - inline GPUManager* getGPUManager() - { - return mGPUManager; - } - - /** Get moon manager - @return Moon manager - */ - inline MoonManager* getMoonManager() - { - return mMoonManager; - } - - /** Get clouds manager - @return Clouds manager - */ - inline CloudsManager* getCloudsManager() - { - return mCloudsManager; - } - - /** Get volumetric clouds manager - @return Volumetric clouds manager - */ - inline VCloudsManager* getVCloudsManager() - { - return mVCloudsManager; - } - - /** Set controller - @param c Controller - */ - inline void setController(Controller* c) - { - if (mController->getDeleteBySkyX()) - { - delete mController; - } - - mController = c; - } - - /** Get current controller - @return Current controller - */ - inline Controller* getController() const - { - return mController; - } - - /** Set render queue groups - @param rqg Render queue groups - */ - void setRenderQueueGroups(const RenderQueueGroups& rqg); - - /** Get render queue groups - @return Current render queue groups - */ - inline const RenderQueueGroups& getRenderQueueGroups() const - { - return mRenderQueueGroups; - } - - /** Set lighting mode - @param lm Lighting mode - @remarks SkyX is designed for true HDR rendering, but there're a lot of applications - that doesn't use HDR rendering, due to this a little exponential tone-mapping - algoritm is applied to SkyX materials if LM_LDR is selected. (See: AtmosphereManager::Options::Exposure) - Select LM_HDR if your app is designed for true HDR rendering. In HDR mode, we assume you're ussing a - full linear rendering pipeline, so all textures are gamma corrected if needed. - */ - void setLightingMode(const LightingMode& lm); - - /** Get lighting mode - @return Lighting mode - */ - inline const LightingMode& getLightingMode() const - { - return mLightingMode; - } - - /** Set the starfield enabled/disabled - @param Enabled true for starfield, false for not - */ - void setStarfieldEnabled(const bool& Enabled); - - /** Is the starfield enable? - @return true if the starfield is enabled, false if it isn't - */ - inline const bool& isStarfieldEnabled() const - { - return mStarfield; - } - - /** Set infinite camera far clip distance - @param d Infinite camera far clip distance - @remarks SkyX needs a finite camera far clip distance in order to builds its geometry. Since Ogre allows infinite far clip - camera distances (camearFarClipDistance = 0) you'll need to manually provide a far clip distance if you're using - an infinite camera far clip distance. - */ - inline void setInfiniteCameraFarClipDistance(const Ogre::Real& d) - { - mInfiniteCameraFarClipDistance = d; - } - - /** Get infinite cmaera far clip distance - @return Infinite camera far clip distance - */ - inline const Ogre::Real& getInfiniteCameraFarClipDistance() const - { - return mInfiniteCameraFarClipDistance; - } - - /** Get scene manager - @return Ogre scene manager - */ - inline Ogre::SceneManager* getSceneManager() - { - return mSceneManager; - } - - /** Get current rendering camera - @return Current rendering camera - */ - inline Ogre::Camera* getCamera() - { + /** Notify camera render (to be invoked per camera and per frame) + @param c Camera + @remarks Invoke this method manually before the camera render operation + Per-camera updates must be performed after the per-frame update through SkyX::update(...) + Also it's possible to use listeners, making all this process transparent, + just register SkyX in your render target through Ogre::RenderTarget::addListener(...) + */ + void notifyCameraRender(Ogre::Camera *c); + + /** Is SkyX created? + @return true if yes, false if not + */ + inline const bool isCreated() const + { + return mCreated; + } + + /** Set visible + @param visible true to set SkyX visible, false to hide it + */ + void setVisible(const bool &visible); + + /** Is SkyX visible? + @return true if SkyX is visible, false otherwise + */ + inline const bool &isVisible() const + { + return mVisible; + } + + /** Set time multiplier + @param TimeMultiplier Time multiplier + @remarks The time multiplier can be a negative number, 0 will disable auto-updating + For setting a custom time of day, check: AtmosphereManager::Options::Time + */ + inline void setTimeMultiplier(const Ogre::Real &TimeMultiplier) + { + mTimeMultiplier = TimeMultiplier; + mVCloudsManager->_updateWindSpeedConfig(); + } + + /** Get time multiplier + @return Time multiplier + */ + inline const Ogre::Real &getTimeMultiplier() const + { + return mTimeMultiplier; + } + + /** Get mesh manager + @return Mesh manager pointer + */ + inline MeshManager *getMeshManager() + { + return mMeshManager; + } + + /** Get atmosphere manager + @return Atmosphere manager pointer + */ + inline AtmosphereManager *getAtmosphereManager() + { + return mAtmosphereManager; + } + + /** Get GPU manager + @return Atmosphere manager pointer + */ + inline GPUManager *getGPUManager() + { + return mGPUManager; + } + + /** Get moon manager + @return Moon manager + */ + inline MoonManager *getMoonManager() + { + return mMoonManager; + } + + /** Get clouds manager + @return Clouds manager + */ + inline CloudsManager *getCloudsManager() + { + return mCloudsManager; + } + + /** Get volumetric clouds manager + @return Volumetric clouds manager + */ + inline VCloudsManager *getVCloudsManager() + { + return mVCloudsManager; + } + + /** Set controller + @param c Controller + */ + inline void setController(Controller *c) + { + if (mController->getDeleteBySkyX()) { delete mController; } + + mController = c; + } + + /** Get current controller + @return Current controller + */ + inline Controller *getController() const + { + return mController; + } + + /** Set render queue groups + @param rqg Render queue groups + */ + void setRenderQueueGroups(const RenderQueueGroups &rqg); + + /** Get render queue groups + @return Current render queue groups + */ + inline const RenderQueueGroups &getRenderQueueGroups() const + { + return mRenderQueueGroups; + } + + /** Set lighting mode + @param lm Lighting mode + @remarks SkyX is designed for true HDR rendering, but there're a lot of applications + that doesn't use HDR rendering, due to this a little exponential tone-mapping + algoritm is applied to SkyX materials if LM_LDR is selected. (See: AtmosphereManager::Options::Exposure) + Select LM_HDR if your app is designed for true HDR rendering. In HDR mode, we assume you're ussing a + full linear rendering pipeline, so all textures are gamma corrected if needed. + */ + void setLightingMode(const LightingMode &lm); + + /** Get lighting mode + @return Lighting mode + */ + inline const LightingMode &getLightingMode() const + { + return mLightingMode; + } + + /** Set the starfield enabled/disabled + @param Enabled true for starfield, false for not + */ + void setStarfieldEnabled(const bool &Enabled); + + /** Is the starfield enable? + @return true if the starfield is enabled, false if it isn't + */ + inline const bool &isStarfieldEnabled() const + { + return mStarfield; + } + + /** Set infinite camera far clip distance + @param d Infinite camera far clip distance + @remarks SkyX needs a finite camera far clip distance in order to builds its geometry. Since Ogre allows infinite far + clip camera distances (camearFarClipDistance = 0) you'll need to manually provide a far clip distance if you're using + an infinite camera far clip distance. + */ + inline void setInfiniteCameraFarClipDistance(const Ogre::Real &d) + { + mInfiniteCameraFarClipDistance = d; + } + + /** Get infinite cmaera far clip distance + @return Infinite camera far clip distance + */ + inline const Ogre::Real &getInfiniteCameraFarClipDistance() const + { + return mInfiniteCameraFarClipDistance; + } + + /** Get scene manager + @return Ogre scene manager + */ + inline Ogre::SceneManager *getSceneManager() + { + return mSceneManager; + } + + /** Get current rendering camera + @return Current rendering camera + */ + inline Ogre::Camera *getCamera() + { return mCamera; - } - - /** Frame started - @param evt Frame event - */ - bool frameStarted(const Ogre::FrameEvent& evt); - - /** Fired before update a render target viewport - @param evt Render target viewport event - */ - void preViewportUpdate(const Ogre::RenderTargetViewportEvent& evt); - - /** Get time offset - @return Time offset - @remarks Only for internal use - */ - inline const Ogre::Real& _getTimeOffset() const - { - return mTimeOffset; - } - - inline CfgFileManager* getCfgFileManager() - { - return mCfgFileManager; - } - - inline const bool loadCfg(const Ogre::String &File) const - { - return mCfgFileManager->load(File); - } - - private: - /// Is SkyX created? - bool mCreated; - - /// Mesh manager - MeshManager* mMeshManager; - /// Atmosphere manager - AtmosphereManager* mAtmosphereManager; - /// GPU manager - GPUManager* mGPUManager; - /// Moon manager - MoonManager* mMoonManager; - /// Clouds manager - CloudsManager* mCloudsManager; - /// Volumetric clouds manager - VCloudsManager* mVCloudsManager; - - /// Controller - Controller* mController; - - /// Render queue groups - RenderQueueGroups mRenderQueueGroups; - - /// Scene manager + } + + /** Frame started + @param evt Frame event + */ + bool frameStarted(const Ogre::FrameEvent &evt); + + /** Fired before update a render target viewport + @param evt Render target viewport event + */ + void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt); + + /** Get time offset + @return Time offset + @remarks Only for internal use + */ + inline const Ogre::Real &_getTimeOffset() const + { + return mTimeOffset; + } + + inline CfgFileManager *getCfgFileManager() + { + return mCfgFileManager; + } + + inline const bool loadCfg(const Ogre::String &File) const + { + return mCfgFileManager->load(File); + } + + private: + /// Is SkyX created? + bool mCreated; + + /// Mesh manager + MeshManager *mMeshManager; + /// Atmosphere manager + AtmosphereManager *mAtmosphereManager; + /// GPU manager + GPUManager *mGPUManager; + /// Moon manager + MoonManager *mMoonManager; + /// Clouds manager + CloudsManager *mCloudsManager; + /// Volumetric clouds manager + VCloudsManager *mVCloudsManager; + + /// Controller + Controller *mController; + + /// Render queue groups + RenderQueueGroups mRenderQueueGroups; + + /// Scene manager Ogre::SceneManager *mSceneManager; - /// Current rendering camera - Ogre::Camera* mCamera; - - /// Last camera position - Ogre::Vector3 mLastCameraPosition; - /// Last camera far clip distance - Ogre::Real mLastCameraFarClipDistance; - /// Infinite camera far clip distance - Ogre::Real mInfiniteCameraFarClipDistance; - - /// Is SkyX visible? - bool mVisible; - - /// Lighting mode - LightingMode mLightingMode; - /// Enable starfield? - bool mStarfield; - - /// Time multiplier - Ogre::Real mTimeMultiplier; - /// Time offset - Ogre::Real mTimeOffset; - - CfgFileManager *mCfgFileManager; - }; -} + /// Current rendering camera + Ogre::Camera *mCamera; + + /// Last camera position + Ogre::Vector3 mLastCameraPosition; + /// Last camera far clip distance + Ogre::Real mLastCameraFarClipDistance; + /// Infinite camera far clip distance + Ogre::Real mInfiniteCameraFarClipDistance; + + /// Is SkyX visible? + bool mVisible; + + /// Lighting mode + LightingMode mLightingMode; + /// Enable starfield? + bool mStarfield; + + /// Time multiplier + Ogre::Real mTimeMultiplier; + /// Time offset + Ogre::Real mTimeOffset; + + CfgFileManager *mCfgFileManager; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/DataManager.cpp b/source/main/gfx/skyx/VClouds/DataManager.cpp index cad7d19ddd..4c5f05637f 100644 --- a/source/main/gfx/skyx/VClouds/DataManager.cpp +++ b/source/main/gfx/skyx/VClouds/DataManager.cpp @@ -23,598 +23,586 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "DataManager.h" -#include "VClouds.h" #include "Ellipsoid.h" +#include "VClouds.h" -namespace SkyX { namespace VClouds +namespace SkyX { - DataManager::DataManager(VClouds *vc) - : mVClouds(vc) - , mCellsCurrent(0) - , mCellsTmp(0) - , mFFRandom(0) - , mNx(0), mNy(0), mNz(0) - , mCurrentTransition(0) - , mUpdateTime(10.0f) - , mStep(0), mXStart(0), mXEnd(0) - , mMaxNumberOfClouds(250) - , mVolTexToUpdate(true) - , mCreated(false) - { - for (int k = 0; k < 2; k++) - { - mVolTextures[k].setNull(); - } - } - - DataManager::~DataManager() - { - remove(); - } - - void DataManager::remove() - { - if (!mCreated) - { - return; - } - - for (int k = 0; k < 2; k++) - { - Ogre::TextureManager::getSingleton().remove(mVolTextures[k]->getName()); - mVolTextures[k].setNull(); - } - - _delete3DCellArray(mCellsCurrent, mNx, mNy); - _delete3DCellArray(mCellsTmp, mNx, mNy); - - delete mFFRandom; - - mNx = mNy = mNz = 0; - - mCreated = false; - } - - void DataManager::update(const Ogre::Real &timeSinceLastFrame) - { - if (mVolTexToUpdate) - { - mCurrentTransition += timeSinceLastFrame; - - mXEnd = static_cast((mCurrentTransition / mUpdateTime)*4*mNx); - if (mXEnd > 4*mNx) - { - mXEnd = 4*mNx; - } - - if (mXEnd/mNx != mXStart/mNx) - { - for (int k = mStep; k <= mXEnd/mNx; k++) - { - _performCalculations(mNx, mNy, mNz, k, mXStart%mNx, (mXEnd/mNx != k) ? mNx : mXEnd%mNx); - mXStart = 0; - } - } - else - { - if (mXStart != mXEnd) - { - _performCalculations(mNx, mNy, mNz, mXEnd/mNx, mXStart%mNx, mXEnd%mNx); - } - } - - mStep = mXEnd/mNx; - mXStart = mXEnd; - - if (mCurrentTransition >= mUpdateTime) - { - _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); - - mCurrentTransition = mUpdateTime; - mVolTexToUpdate = !mVolTexToUpdate; - mStep = mXStart = mXEnd = 0; - } - } - else - { - mCurrentTransition -= timeSinceLastFrame; - - mXEnd = static_cast(((mUpdateTime-mCurrentTransition) / mUpdateTime)*4*mNx); - if (mXEnd < 0) - { - mXEnd = 0; - } - - if (mXEnd/mNx != mXStart/mNx) - { - for (int k = mStep; k <= mXEnd/mNx; k++) - { - _performCalculations(mNx, mNy, mNz, k, mXStart%mNx, (mXEnd/mNx != k) ? mNx : mXEnd%mNx); - mXStart = 0; - } - } - else - { - if (mXStart != mXEnd) - { - _performCalculations(mNx, mNy, mNz, mXEnd/mNx, mXStart%mNx, mXEnd%mNx); - } - } - - mStep = mXEnd/mNx; - mXStart = mXEnd; - - if (mCurrentTransition <= 0) - { - _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); - - mCurrentTransition = 0; - mVolTexToUpdate = !mVolTexToUpdate; - mStep = mXStart = mXEnd = 0; - } - } - } - - void DataManager::create(const int &nx, const int &ny, const int &nz) - { - remove(); - - mNx = nx; mNy = ny; mNz = nz; - - mFFRandom = new FastFakeRandom(1024, 0, 1); - - _initData(nx, ny, nz); - - for (int k = 0; k < 2; k++) - { - _createVolTexture(static_cast(k), nx, ny, nz); - } - - _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); - _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); - - mCreated = true; - } - - void DataManager::forceToUpdateData() - { - // Finish current update process - _performCalculations(mNx, mNy, mNz, mStep, mXStart%mNx, mNx); - for (int k = mStep+1; k < 4; k++) - { - _performCalculations(mNx, mNy, mNz, k, 0, mNx); - } - mStep = mXStart = mXEnd = 0; - - if (mVolTexToUpdate) - { - _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); - mCurrentTransition = mUpdateTime; - } - else - { - _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); - mCurrentTransition = 0; - } - - mVolTexToUpdate = !mVolTexToUpdate; - } - - void DataManager::_initData(const int& nx, const int& ny, const int& nz) - { - mCellsCurrent = _create3DCellArray(nx, ny, nz); - mCellsTmp = _create3DCellArray(nx, ny, nz, false); - } - - DataManager::Cell *** DataManager::_create3DCellArray(const int& nx, const int& ny, const int& nz, const bool& init) - { - Cell ***c = new Cell** [nx]; - - int u, v, w; - - for (u = 0; u < nx; u++) - { - c[u] = new Cell* [ny]; - - for (v = 0; v < ny; v++) - { - c[u][v] = new Cell[nz]; - } - } - - if (!init) - { - return c; - } - - for (u = 0; u < nx; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 1; w < nz; w++) - { - c[u][v][w].act = false; - c[u][v][w].cld = false; - c[u][v][w].hum = false; - - c[u][v][w].pact = 0; - c[u][v][w].pext = 1; - c[u][v][w].phum = 0; - - c[u][v][w].dens = 0.0f; - c[u][v][w].light = 1.0f; - } - } - } - - return c; - } - - void DataManager::_delete3DCellArray(Cell ***c, const int& nx, const int& ny) - { - int u, v; - - for (u = 0; u < nx; u++) - { - for (v = 0; v < ny; v++) - { - delete [] c[u][v]; - } - - delete [] c[u]; - } - - delete [] c; - } - - void DataManager::_copy3DCellArraysData(Cell ***src, Cell ***dest, const int& nx, const int& ny, const int& nz) - { - int u, v, w; - - for (u = 0; u < nx; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 0; w < nz; w++) - { - dest[u][v][w].act = src[u][v][w].act; - dest[u][v][w].cld = src[u][v][w].cld; - dest[u][v][w].hum = src[u][v][w].hum; - - dest[u][v][w].pact = src[u][v][w].pact; - dest[u][v][w].pext = src[u][v][w].pext; - dest[u][v][w].phum = src[u][v][w].phum; - - dest[u][v][w].dens = src[u][v][w].dens; - dest[u][v][w].light = src[u][v][w].light; - } - } - } - } - - void DataManager::setWheater(const float& Humidity, const float& AverageCloudsSize, const bool& delayedResponse) - { - int numberofclouds = static_cast(Humidity * mMaxNumberOfClouds); - Ogre::Vector3 maxcloudsize = AverageCloudsSize*Ogre::Vector3(mNx/14, mNy/14, static_cast(static_cast(mNz)/2.75)); - - // Update old clouds with new parameters - Ogre::Vector3 currentdimensions, currentPosition; - std::vector::const_iterator mEllipsoidsIt; - - for(mEllipsoidsIt = mEllipsoids.begin(); mEllipsoidsIt != mEllipsoids.end(); mEllipsoidsIt++) - { - // Update size - currentdimensions = (*mEllipsoidsIt)->getDimensions(); - - if (currentdimensions.x / maxcloudsize.x < 0.5 || currentdimensions.x / maxcloudsize.x > 2) - { - currentdimensions.x = maxcloudsize.x + Ogre::Math::RangeRandom(-0.2,0.2)*maxcloudsize.x; - } - if (currentdimensions.y / maxcloudsize.y < 0.5 || currentdimensions.y / maxcloudsize.y > 2) - { - currentdimensions.y = maxcloudsize.y + Ogre::Math::RangeRandom(-0.2,0.2)*maxcloudsize.y; - } - if (currentdimensions.z / maxcloudsize.z < 0.5 || currentdimensions.z / maxcloudsize.z > 2) - { - currentdimensions.z = maxcloudsize.z + Ogre::Math::RangeRandom(-0.2,0.15)*maxcloudsize.z; - } - - (*mEllipsoidsIt)->setDimensions(currentdimensions); - - // Update position - currentPosition = (*mEllipsoidsIt)->getPosition(); - (*mEllipsoidsIt)->setPosition(Ogre::Vector3(currentPosition.x,currentPosition.y,static_cast(Ogre::Math::RangeRandom(currentdimensions.z+2,mNz-currentdimensions.z-2)))); - } - - // Remove some clouds if needed - while (static_cast(numberofclouds) < mEllipsoids.size()) - { - mEllipsoids.pop_back(); - } - - // Add new clouds if needed - Ogre::Vector3 newclouddimensions; - while (static_cast(numberofclouds) > mEllipsoids.size()) - { - newclouddimensions = maxcloudsize*Ogre::Vector3(Ogre::Math::RangeRandom(0.5, 2), Ogre::Math::RangeRandom(0.5, 2), Ogre::Math::RangeRandom(0.75, 1)); - addEllipsoid(new Ellipsoid(newclouddimensions.x, newclouddimensions.y, newclouddimensions.z, mNx, mNy, mNz, (int)Ogre::Math::RangeRandom(0, mNx), (int)Ogre::Math::RangeRandom(0, mNy), static_cast(Ogre::Math::RangeRandom(newclouddimensions.z+2,mNz-newclouddimensions.z-2)), Ogre::Math::RangeRandom(1,5.0f)), false); - } - - _updateProbabilities(mCellsCurrent, mNx, mNy, mNz, delayedResponse); - - if (!delayedResponse) - { - for (int k = 0; k < 4; k++) - { - _performCalculations(mNx, mNy, mNz, k, 0, mNx); - } - mStep = mXStart = mXEnd = 0; - - _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); - _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); - } - } - - void DataManager::addEllipsoid(Ellipsoid *e, const bool& UpdateProbabilities) - { - mEllipsoids.push_back(e); - - if (UpdateProbabilities) - { - e->updateProbabilities(mCellsCurrent,mNx,mNy,mNz); - } - } - - void DataManager::_clearProbabilities(Cell*** c, const int& nx, const int& ny, const int& nz, const bool& clearData) - { - int u, v, w; - - for (u = 0; u < nx; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 0; w < nz; w++) - { - c[u][v][w].pact = 0; - c[u][v][w].pext = 1; - c[u][v][w].phum = 0; - - if (clearData) - { - c[u][v][w].act = false; - c[u][v][w].cld = false; - c[u][v][w].hum = false; - - c[u][v][w].dens = 0; - c[u][v][w].light = 0; - } - } - } - } - } - - void DataManager::_updateProbabilities(Cell*** c, const int& nx, const int& ny, const int& nz, const bool& delayedResponse) - { - _clearProbabilities(c,nx,ny,nz,!delayedResponse); - - std::vector::const_iterator mEllipsoidsIt; - - for(mEllipsoidsIt = mEllipsoids.begin(); mEllipsoidsIt != mEllipsoids.end(); mEllipsoidsIt++) - { - (*mEllipsoidsIt)->updateProbabilities(c,nx,ny,nz,delayedResponse); - } - } - - const Ogre::Real DataManager::_getLightAbsorcionAt(Cell*** c, const int& nx, const int& ny, const int& nz, const int& x, const int& y, const int& z, const Ogre::Vector3& d, const float& att) const - { - Ogre::Real step = 1, factor = 1; - Ogre::Vector3 pos = Ogre::Vector3(x, y, z); - bool outOfBounds = false; - int u, v, uu, vv, - current_iteration = 0, max_iterations = 8; - - while(!outOfBounds) - { - if ( (int)pos.z >= nz || (int)pos.z < 0 || factor <= 0 || current_iteration >= max_iterations) - { - outOfBounds = true; - } - else - { - u = (int)pos.x; v = (int)pos.y; - - uu = (u<0) ? (u + nx) : u; if (u>=nx) { uu-= nx; } - vv = (v<0) ? (v + ny) : v; if (v>=ny) { vv-= ny; } - - factor -= c[uu][vv][(int)pos.z].dens*att*(1-static_cast(current_iteration)/max_iterations); - pos += step*(-d); - - current_iteration++; - } - } - - return Ogre::Math::Clamp(factor,0,1); - } - - void DataManager::_performCalculations(const int& nx, const int& ny, const int& nz, const int& step, const int& xStart, const int& xEnd) - { - int u, v, w; - - switch (step) - { - case 0: - { - for (u = xStart; u < xEnd; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 0; w < nz; w++) - { - // ti+1 ti - mCellsCurrent[u][v][w].hum = mCellsCurrent[u][v][w].hum || (mFFRandom->get() < mCellsCurrent[u][v][w].phum); - mCellsCurrent[u][v][w].cld = mCellsCurrent[u][v][w].cld && (mFFRandom->get() > mCellsCurrent[u][v][w].pext); - mCellsCurrent[u][v][w].act = mCellsCurrent[u][v][w].act || (mFFRandom->get() < mCellsCurrent[u][v][w].pact); - - // Copy act in the temporal buffer, for _fact(...) - mCellsTmp[u][v][w].act = mCellsCurrent[u][v][w].act; - } - } - } - } - break; - case 1: - { - for (u = xStart; u < xEnd; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 0; w < nz; w++) - { - // ti+1 ti - mCellsCurrent[u][v][w].hum = mCellsCurrent[u][v][w].hum && !mCellsCurrent[u][v][w].act; - mCellsCurrent[u][v][w].cld = mCellsCurrent[u][v][w].cld || mCellsCurrent[u][v][w].act; - mCellsCurrent[u][v][w].act = !mCellsCurrent[u][v][w].act && mCellsCurrent[u][v][w].hum && _fact(mCellsTmp, nx, ny, nz, u,v,w); - } - } - } - } - break; - case 2: - { - // Continous density - for (u = xStart; u < xEnd; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 0; w < nz; w++) - { - mCellsCurrent[u][v][w].dens = _getDensityAt(mCellsCurrent, nx, ny, nz, u,v,w, 1/*TODOOOO!!!*/, 1.15f); - // mCellsCurrent[u][v][w].dens = _getDensityAt(mCellsCurrent,u,v,w); - } - } - } - } - break; - case 3: - { - // Light scattering - Ogre::Vector3 SunDir = Ogre::Vector3(mVClouds->getSunDirection().x, mVClouds->getSunDirection().z, mVClouds->getSunDirection().y); - - for (u = xStart; u < xEnd; u++) - { - for (v = 0; v < ny; v++) - { - for (w = 0; w < nz; w++) - { - mCellsCurrent[u][v][w].light = _getLightAbsorcionAt(mCellsCurrent, nx, ny, nz, u,v,w, SunDir, 0.15f/*TODO!!!!*/); - } - } - } - } - break; - } - } - - const bool DataManager::_fact(Cell ***c, const int& nx, const int& ny, const int& nz, const int& x, const int& y, const int& z) const - { - bool i1m, j1m, k1m, - i1r, j1r, k1r, - i2r, i2m, j2r, j2m, k2r; - - i1m = ((x+1)>=nx) ? c[0][y][z].act : c[x+1][y][z].act; - j1m = ((y+1)>=ny) ? c[x][0][z].act : c[x][y+1][z].act; - k1m = ((z+1)>=nz) ? false : c[x][y][z+1].act; - - i1r = ((x-1)<0) ? c[nx-1][y][z].act : c[x-1][y][z].act; - j1r = ((y-1)<0) ? c[x][ny-1][z].act : c[x][y-1][z].act; - k1r = ((z-1)<0) ? false : c[x][y][z-1].act; - - i2r = ((x-2)<0) ? c[nx-2][y][z].act : c[x-2][y][z].act; - j2r = ((y-2)<0) ? c[x][ny-2][z].act : c[x][y-2][z].act; - k2r = ((z-2)<0) ? false : c[x][y][z-2].act; - - i2m = ((x+2)>=nx) ? c[1][y][z].act : c[x+2][y][z].act; - j2m = ((y+2)>=ny) ? c[x][1][z].act : c[x][y+2][z].act; - - return i1m || j1m || k1m || i1r || j1r || k1r || i2r || i2m || j2r || j2m || k2r; - } - - const float DataManager::_getDensityAt(Cell ***c, const int& nx, const int& ny, const int& nz, const int& x, const int& y, const int& z, const int& r, const float& strength) const - { - int zr = ((z-r)<0) ? 0 : z-r, - zm = ((z+r)>=nz) ? nz : z+r, - u, uu, v, vv, w, - clouds = 0, div = 0; - - for (u = x-r; u <= x+r; u++) - { - for (v = y-r; v <= y+r; v++) - { - for (w = zr; w < zm; w++) - { - // x/y Seamless! - uu = (u<0) ? (u + nx) : u; if (u>=nx) { uu-= nx; } - vv = (v<0) ? (v + ny) : v; if (v>=ny) { vv-= ny; } - - clouds += c[uu][vv][w].cld ? 1 : 0; - div++; - } - } - } - - return Ogre::Math::Clamp(strength*((float)clouds)/div, 0, 1); - } - - const float DataManager::_getDensityAt(Cell ***c, const int& x, const int& y, const int& z) const - { - return c[x][y][z].cld ? 1.0f : 0.0f; - } - - void DataManager::_createVolTexture(const VolTextureId& TexId, const int& nx, const int& ny, const int& nz) - { - mVolTextures[static_cast(TexId)] - = Ogre::TextureManager::getSingleton(). - createManual("_SkyX_VolCloudsData"+Ogre::StringConverter::toString(TexId), - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_3D, - nx, ny, nz, 0, - Ogre::PF_BYTE_RGBA); - - mVolTextures[static_cast(TexId)]->load(); - - static_cast( - Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds")) - ->getTechnique(0)->getPass(0)->getTextureUnitState(static_cast(TexId)) - ->setTextureName("_SkyX_VolCloudsData"+Ogre::StringConverter::toString(TexId), Ogre::TEX_TYPE_3D); - static_cast( - Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds_Lightning")) - ->getTechnique(0)->getPass(0)->getTextureUnitState(static_cast(TexId)) - ->setTextureName("_SkyX_VolCloudsData"+Ogre::StringConverter::toString(TexId), Ogre::TEX_TYPE_3D); - } - - void DataManager::_updateVolTextureData(Cell ***c, const VolTextureId& TexId, const int& nx, const int& ny, const int& nz) - { - Ogre::HardwarePixelBufferSharedPtr buffer = mVolTextures[TexId]->getBuffer(0,0); - - buffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); - const Ogre::PixelBox &pb = buffer->getCurrentLock(); - - Ogre::uint32 *pbptr = reinterpret_cast(pb.data); - size_t x, y, z; - - for (z = pb.front; z < pb.back; z++) + namespace VClouds + { + DataManager::DataManager(VClouds *vc) + : mVClouds(vc), mCellsCurrent(0), mCellsTmp(0), mFFRandom(0), mNx(0), mNy(0), mNz(0), mCurrentTransition(0), + mUpdateTime(10.0f), mStep(0), mXStart(0), mXEnd(0), mMaxNumberOfClouds(250), mVolTexToUpdate(true), mCreated(false) + { + for (int k = 0; k < 2; k++) + { + mVolTextures[k].setNull(); + } + } + + DataManager::~DataManager() + { + remove(); + } + + void DataManager::remove() + { + if (!mCreated) { return; } + + for (int k = 0; k < 2; k++) + { + Ogre::TextureManager::getSingleton().remove(mVolTextures[k]->getName()); + mVolTextures[k].setNull(); + } + + _delete3DCellArray(mCellsCurrent, mNx, mNy); + _delete3DCellArray(mCellsTmp, mNx, mNy); + + delete mFFRandom; + + mNx = mNy = mNz = 0; + + mCreated = false; + } + + void DataManager::update(const Ogre::Real &timeSinceLastFrame) + { + if (mVolTexToUpdate) + { + mCurrentTransition += timeSinceLastFrame; + + mXEnd = static_cast((mCurrentTransition / mUpdateTime) * 4 * mNx); + if (mXEnd > 4 * mNx) { mXEnd = 4 * mNx; } + + if (mXEnd / mNx != mXStart / mNx) + { + for (int k = mStep; k <= mXEnd / mNx; k++) + { + _performCalculations(mNx, mNy, mNz, k, mXStart % mNx, (mXEnd / mNx != k) ? mNx : mXEnd % mNx); + mXStart = 0; + } + } + else + { + if (mXStart != mXEnd) { _performCalculations(mNx, mNy, mNz, mXEnd / mNx, mXStart % mNx, mXEnd % mNx); } + } + + mStep = mXEnd / mNx; + mXStart = mXEnd; + + if (mCurrentTransition >= mUpdateTime) + { + _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); + + mCurrentTransition = mUpdateTime; + mVolTexToUpdate = !mVolTexToUpdate; + mStep = mXStart = mXEnd = 0; + } + } + else + { + mCurrentTransition -= timeSinceLastFrame; + + mXEnd = static_cast(((mUpdateTime - mCurrentTransition) / mUpdateTime) * 4 * mNx); + if (mXEnd < 0) { mXEnd = 0; } + + if (mXEnd / mNx != mXStart / mNx) + { + for (int k = mStep; k <= mXEnd / mNx; k++) + { + _performCalculations(mNx, mNy, mNz, k, mXStart % mNx, (mXEnd / mNx != k) ? mNx : mXEnd % mNx); + mXStart = 0; + } + } + else + { + if (mXStart != mXEnd) { _performCalculations(mNx, mNy, mNz, mXEnd / mNx, mXStart % mNx, mXEnd % mNx); } + } + + mStep = mXEnd / mNx; + mXStart = mXEnd; + + if (mCurrentTransition <= 0) + { + _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); + + mCurrentTransition = 0; + mVolTexToUpdate = !mVolTexToUpdate; + mStep = mXStart = mXEnd = 0; + } + } + } + + void DataManager::create(const int &nx, const int &ny, const int &nz) + { + remove(); + + mNx = nx; + mNy = ny; + mNz = nz; + + mFFRandom = new FastFakeRandom(1024, 0, 1); + + _initData(nx, ny, nz); + + for (int k = 0; k < 2; k++) + { + _createVolTexture(static_cast(k), nx, ny, nz); + } + + _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); + _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); + + mCreated = true; + } + + void DataManager::forceToUpdateData() + { + // Finish current update process + _performCalculations(mNx, mNy, mNz, mStep, mXStart % mNx, mNx); + for (int k = mStep + 1; k < 4; k++) + { + _performCalculations(mNx, mNy, mNz, k, 0, mNx); + } + mStep = mXStart = mXEnd = 0; + + if (mVolTexToUpdate) + { + _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); + mCurrentTransition = mUpdateTime; + } + else + { + _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); + mCurrentTransition = 0; + } + + mVolTexToUpdate = !mVolTexToUpdate; + } + + void DataManager::_initData(const int &nx, const int &ny, const int &nz) + { + mCellsCurrent = _create3DCellArray(nx, ny, nz); + mCellsTmp = _create3DCellArray(nx, ny, nz, false); + } + + DataManager::Cell ***DataManager::_create3DCellArray(const int &nx, const int &ny, const int &nz, const bool &init) + { + Cell ***c = new Cell **[nx]; + + int u, v, w; + + for (u = 0; u < nx; u++) + { + c[u] = new Cell *[ny]; + + for (v = 0; v < ny; v++) + { + c[u][v] = new Cell[nz]; + } + } + + if (!init) { return c; } + + for (u = 0; u < nx; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 1; w < nz; w++) + { + c[u][v][w].act = false; + c[u][v][w].cld = false; + c[u][v][w].hum = false; + + c[u][v][w].pact = 0; + c[u][v][w].pext = 1; + c[u][v][w].phum = 0; + + c[u][v][w].dens = 0.0f; + c[u][v][w].light = 1.0f; + } + } + } + + return c; + } + + void DataManager::_delete3DCellArray(Cell ***c, const int &nx, const int &ny) + { + int u, v; + + for (u = 0; u < nx; u++) + { + for (v = 0; v < ny; v++) + { + delete[] c[u][v]; + } + + delete[] c[u]; + } + + delete[] c; + } + + void DataManager::_copy3DCellArraysData(Cell ***src, Cell ***dest, const int &nx, const int &ny, const int &nz) + { + int u, v, w; + + for (u = 0; u < nx; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 0; w < nz; w++) + { + dest[u][v][w].act = src[u][v][w].act; + dest[u][v][w].cld = src[u][v][w].cld; + dest[u][v][w].hum = src[u][v][w].hum; + + dest[u][v][w].pact = src[u][v][w].pact; + dest[u][v][w].pext = src[u][v][w].pext; + dest[u][v][w].phum = src[u][v][w].phum; + + dest[u][v][w].dens = src[u][v][w].dens; + dest[u][v][w].light = src[u][v][w].light; + } + } + } + } + + void DataManager::setWheater(const float &Humidity, const float &AverageCloudsSize, const bool &delayedResponse) + { + int numberofclouds = static_cast(Humidity * mMaxNumberOfClouds); + Ogre::Vector3 maxcloudsize = + AverageCloudsSize * Ogre::Vector3(mNx / 14, mNy / 14, static_cast(static_cast(mNz) / 2.75)); + + // Update old clouds with new parameters + Ogre::Vector3 currentdimensions, currentPosition; + std::vector::const_iterator mEllipsoidsIt; + + for (mEllipsoidsIt = mEllipsoids.begin(); mEllipsoidsIt != mEllipsoids.end(); mEllipsoidsIt++) + { + // Update size + currentdimensions = (*mEllipsoidsIt)->getDimensions(); + + if (currentdimensions.x / maxcloudsize.x < 0.5 || currentdimensions.x / maxcloudsize.x > 2) + { currentdimensions.x = maxcloudsize.x + Ogre::Math::RangeRandom(-0.2, 0.2) * maxcloudsize.x; } + if (currentdimensions.y / maxcloudsize.y < 0.5 || currentdimensions.y / maxcloudsize.y > 2) + { currentdimensions.y = maxcloudsize.y + Ogre::Math::RangeRandom(-0.2, 0.2) * maxcloudsize.y; } + if (currentdimensions.z / maxcloudsize.z < 0.5 || currentdimensions.z / maxcloudsize.z > 2) + { currentdimensions.z = maxcloudsize.z + Ogre::Math::RangeRandom(-0.2, 0.15) * maxcloudsize.z; } + + (*mEllipsoidsIt)->setDimensions(currentdimensions); + + // Update position + currentPosition = (*mEllipsoidsIt)->getPosition(); + (*mEllipsoidsIt) + ->setPosition(Ogre::Vector3( + currentPosition.x, currentPosition.y, + static_cast(Ogre::Math::RangeRandom(currentdimensions.z + 2, mNz - currentdimensions.z - 2)))); + } + + // Remove some clouds if needed + while (static_cast(numberofclouds) < mEllipsoids.size()) + { + mEllipsoids.pop_back(); + } + + // Add new clouds if needed + Ogre::Vector3 newclouddimensions; + while (static_cast(numberofclouds) > mEllipsoids.size()) + { + newclouddimensions = + maxcloudsize * Ogre::Vector3(Ogre::Math::RangeRandom(0.5, 2), Ogre::Math::RangeRandom(0.5, 2), + Ogre::Math::RangeRandom(0.75, 1)); + addEllipsoid(new Ellipsoid(newclouddimensions.x, newclouddimensions.y, newclouddimensions.z, mNx, mNy, mNz, + (int)Ogre::Math::RangeRandom(0, mNx), (int)Ogre::Math::RangeRandom(0, mNy), + static_cast( + Ogre::Math::RangeRandom(newclouddimensions.z + 2, mNz - newclouddimensions.z - 2)), + Ogre::Math::RangeRandom(1, 5.0f)), + false); + } + + _updateProbabilities(mCellsCurrent, mNx, mNy, mNz, delayedResponse); + + if (!delayedResponse) + { + for (int k = 0; k < 4; k++) + { + _performCalculations(mNx, mNy, mNz, k, 0, mNx); + } + mStep = mXStart = mXEnd = 0; + + _updateVolTextureData(mCellsCurrent, VOL_TEX0, mNx, mNy, mNz); + _updateVolTextureData(mCellsCurrent, VOL_TEX1, mNx, mNy, mNz); + } + } + + void DataManager::addEllipsoid(Ellipsoid *e, const bool &UpdateProbabilities) + { + mEllipsoids.push_back(e); + + if (UpdateProbabilities) { e->updateProbabilities(mCellsCurrent, mNx, mNy, mNz); } + } + + void DataManager::_clearProbabilities(Cell ***c, const int &nx, const int &ny, const int &nz, const bool &clearData) + { + int u, v, w; + + for (u = 0; u < nx; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 0; w < nz; w++) + { + c[u][v][w].pact = 0; + c[u][v][w].pext = 1; + c[u][v][w].phum = 0; + + if (clearData) + { + c[u][v][w].act = false; + c[u][v][w].cld = false; + c[u][v][w].hum = false; + + c[u][v][w].dens = 0; + c[u][v][w].light = 0; + } + } + } + } + } + + void DataManager::_updateProbabilities(Cell ***c, const int &nx, const int &ny, const int &nz, + const bool &delayedResponse) + { + _clearProbabilities(c, nx, ny, nz, !delayedResponse); + + std::vector::const_iterator mEllipsoidsIt; + + for (mEllipsoidsIt = mEllipsoids.begin(); mEllipsoidsIt != mEllipsoids.end(); mEllipsoidsIt++) + { + (*mEllipsoidsIt)->updateProbabilities(c, nx, ny, nz, delayedResponse); + } + } + + const Ogre::Real DataManager::_getLightAbsorcionAt(Cell ***c, const int &nx, const int &ny, const int &nz, const int &x, + const int &y, const int &z, const Ogre::Vector3 &d, + const float &att) const + { + Ogre::Real step = 1, factor = 1; + Ogre::Vector3 pos = Ogre::Vector3(x, y, z); + bool outOfBounds = false; + int u, v, uu, vv, current_iteration = 0, max_iterations = 8; + + while (!outOfBounds) + { + if ((int)pos.z >= nz || (int)pos.z < 0 || factor <= 0 || current_iteration >= max_iterations) + { outOfBounds = true; } + else + { + u = (int)pos.x; + v = (int)pos.y; + + uu = (u < 0) ? (u + nx) : u; + if (u >= nx) { uu -= nx; } + vv = (v < 0) ? (v + ny) : v; + if (v >= ny) { vv -= ny; } + + factor -= c[uu][vv][(int)pos.z].dens * att * (1 - static_cast(current_iteration) / max_iterations); + pos += step * (-d); + + current_iteration++; + } + } + + return Ogre::Math::Clamp(factor, 0, 1); + } + + void DataManager::_performCalculations(const int &nx, const int &ny, const int &nz, const int &step, const int &xStart, + const int &xEnd) + { + int u, v, w; + + switch (step) + { + case 0: + { + for (u = xStart; u < xEnd; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 0; w < nz; w++) + { + // ti+1 ti + mCellsCurrent[u][v][w].hum = + mCellsCurrent[u][v][w].hum || (mFFRandom->get() < mCellsCurrent[u][v][w].phum); + mCellsCurrent[u][v][w].cld = + mCellsCurrent[u][v][w].cld && (mFFRandom->get() > mCellsCurrent[u][v][w].pext); + mCellsCurrent[u][v][w].act = + mCellsCurrent[u][v][w].act || (mFFRandom->get() < mCellsCurrent[u][v][w].pact); + + // Copy act in the temporal buffer, for _fact(...) + mCellsTmp[u][v][w].act = mCellsCurrent[u][v][w].act; + } + } + } + } + break; + case 1: + { + for (u = xStart; u < xEnd; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 0; w < nz; w++) + { + // ti+1 ti + mCellsCurrent[u][v][w].hum = mCellsCurrent[u][v][w].hum && !mCellsCurrent[u][v][w].act; + mCellsCurrent[u][v][w].cld = mCellsCurrent[u][v][w].cld || mCellsCurrent[u][v][w].act; + mCellsCurrent[u][v][w].act = !mCellsCurrent[u][v][w].act && mCellsCurrent[u][v][w].hum && + _fact(mCellsTmp, nx, ny, nz, u, v, w); + } + } + } + } + break; + case 2: + { + // Continous density + for (u = xStart; u < xEnd; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 0; w < nz; w++) + { + mCellsCurrent[u][v][w].dens = + _getDensityAt(mCellsCurrent, nx, ny, nz, u, v, w, 1 /*TODOOOO!!!*/, 1.15f); + // mCellsCurrent[u][v][w].dens = _getDensityAt(mCellsCurrent,u,v,w); + } + } + } + } + break; + case 3: + { + // Light scattering + Ogre::Vector3 SunDir = + Ogre::Vector3(mVClouds->getSunDirection().x, mVClouds->getSunDirection().z, mVClouds->getSunDirection().y); + + for (u = xStart; u < xEnd; u++) + { + for (v = 0; v < ny; v++) + { + for (w = 0; w < nz; w++) + { + mCellsCurrent[u][v][w].light = + _getLightAbsorcionAt(mCellsCurrent, nx, ny, nz, u, v, w, SunDir, 0.15f /*TODO!!!!*/); + } + } + } + } + break; + } + } + + const bool DataManager::_fact(Cell ***c, const int &nx, const int &ny, const int &nz, const int &x, const int &y, + const int &z) const + { + bool i1m, j1m, k1m, i1r, j1r, k1r, i2r, i2m, j2r, j2m, k2r; + + i1m = ((x + 1) >= nx) ? c[0][y][z].act : c[x + 1][y][z].act; + j1m = ((y + 1) >= ny) ? c[x][0][z].act : c[x][y + 1][z].act; + k1m = ((z + 1) >= nz) ? false : c[x][y][z + 1].act; + + i1r = ((x - 1) < 0) ? c[nx - 1][y][z].act : c[x - 1][y][z].act; + j1r = ((y - 1) < 0) ? c[x][ny - 1][z].act : c[x][y - 1][z].act; + k1r = ((z - 1) < 0) ? false : c[x][y][z - 1].act; + + i2r = ((x - 2) < 0) ? c[nx - 2][y][z].act : c[x - 2][y][z].act; + j2r = ((y - 2) < 0) ? c[x][ny - 2][z].act : c[x][y - 2][z].act; + k2r = ((z - 2) < 0) ? false : c[x][y][z - 2].act; + + i2m = ((x + 2) >= nx) ? c[1][y][z].act : c[x + 2][y][z].act; + j2m = ((y + 2) >= ny) ? c[x][1][z].act : c[x][y + 2][z].act; + + return i1m || j1m || k1m || i1r || j1r || k1r || i2r || i2m || j2r || j2m || k2r; + } + + const float DataManager::_getDensityAt(Cell ***c, const int &nx, const int &ny, const int &nz, const int &x, const int &y, + const int &z, const int &r, const float &strength) const + { + int zr = ((z - r) < 0) ? 0 : z - r, zm = ((z + r) >= nz) ? nz : z + r, u, uu, v, vv, w, clouds = 0, div = 0; + + for (u = x - r; u <= x + r; u++) + { + for (v = y - r; v <= y + r; v++) + { + for (w = zr; w < zm; w++) + { + // x/y Seamless! + uu = (u < 0) ? (u + nx) : u; + if (u >= nx) { uu -= nx; } + vv = (v < 0) ? (v + ny) : v; + if (v >= ny) { vv -= ny; } + + clouds += c[uu][vv][w].cld ? 1 : 0; + div++; + } + } + } + + return Ogre::Math::Clamp(strength * ((float)clouds) / div, 0, 1); + } + + const float DataManager::_getDensityAt(Cell ***c, const int &x, const int &y, const int &z) const + { + return c[x][y][z].cld ? 1.0f : 0.0f; + } + + void DataManager::_createVolTexture(const VolTextureId &TexId, const int &nx, const int &ny, const int &nz) + { + mVolTextures[static_cast(TexId)] = Ogre::TextureManager::getSingleton().createManual( + "_SkyX_VolCloudsData" + Ogre::StringConverter::toString(TexId), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_3D, nx, ny, nz, 0, Ogre::PF_BYTE_RGBA); + + mVolTextures[static_cast(TexId)]->load(); + + static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds")) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(static_cast(TexId)) + ->setTextureName("_SkyX_VolCloudsData" + Ogre::StringConverter::toString(TexId), Ogre::TEX_TYPE_3D); + static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds_Lightning")) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(static_cast(TexId)) + ->setTextureName("_SkyX_VolCloudsData" + Ogre::StringConverter::toString(TexId), Ogre::TEX_TYPE_3D); + } + + void DataManager::_updateVolTextureData(Cell ***c, const VolTextureId &TexId, const int &nx, const int &ny, const int &nz) + { + Ogre::HardwarePixelBufferSharedPtr buffer = mVolTextures[TexId]->getBuffer(0, 0); + + buffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); + const Ogre::PixelBox &pb = buffer->getCurrentLock(); + + Ogre::uint32 *pbptr = reinterpret_cast(pb.data); + size_t x, y, z; + + for (z = pb.front; z < pb.back; z++) { for (y = pb.top; y < pb.bottom; y++) { for (x = pb.left; x < pb.right; x++) { - Ogre::PixelUtil::packColour (c[x][y][z].dens/* TODO!!!! */, c[x][y][z].light, 0, 0, pb.format, &pbptr[x]); + Ogre::PixelUtil::packColour(c[x][y][z].dens /* TODO!!!! */, c[x][y][z].light, 0, 0, pb.format, &pbptr[x]); } pbptr += pb.rowPitch; } - pbptr += pb.getSliceSkip (); + pbptr += pb.getSliceSkip(); } - buffer->unlock(); - } -}} \ No newline at end of file + buffer->unlock(); + } + } // namespace VClouds +} \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/DataManager.h b/source/main/gfx/skyx/VClouds/DataManager.h index fa7f7dd6a1..98e59658f4 100644 --- a/source/main/gfx/skyx/VClouds/DataManager.h +++ b/source/main/gfx/skyx/VClouds/DataManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,280 +24,287 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_VClouds_DataManager_H_ #define _SkyX_VClouds_DataManager_H_ -#include "Prerequisites.h" - #include "FastFakeRandom.h" +#include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class VClouds; - class Ellipsoid; - - class DataManager - { - public: - /** Cell struct - */ - struct Cell - { - /// Humidity, phase and cloud - bool hum, act, cld; - - /// Probabilities - float phum, pext, pact; - - /// Continous density - float dens; - - /// Light absorcion - float light; - }; - - /** Volumetric textures enumeration - */ - enum VolTextureId - { - VOL_TEX0 = 0, - VOL_TEX1 = 1 - }; - - /** Constructor - @param vc VClouds parent pointer - */ - DataManager(VClouds *vc); - - /** Destructor - */ - ~DataManager(); - - /** Create - @param nx X complexity - @param ny Y complexity - @param nz Z complexity - */ - void create(const int& nx, const int& ny, const int& nz); - - /** Update - @param timeSinceLastFrame Time elapsed since last frame - */ - void update(const Ogre::Real &timeSinceLastFrame); - - /** Remove - */ - void remove(); - - /** Has been create(...) already called? - @return true if created() have been already called - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Set update time - @param UpdateTime Time elapsed between data calculations, a little freeze could be experimented during these calculations on old CPU's - */ - inline void setUpdateTime(const float& UpdateTime) - { - mUpdateTime = UpdateTime; - } - - /** Get update time - @return Update time - */ - inline const Ogre::Real& getUpdateTime() const - { - return mUpdateTime; - } - - /** Get current interpolation factor - @return Interpolation factor - @remarks Only for internal use - */ - inline const Ogre::Real _getInterpolation() const - { - return mCurrentTransition/mUpdateTime; - } - - /** Set wheater parameters - Use this funtion to update the cloud field parameters, you'll get a smart and smooth transition from your old - setting to your new ones. - @param Humidity Humidity, in other words: the percentage of clouds in [0,1] range. - @param AverageCloudsSize Average clouds size, for example: if previous wheater clouds size parameter was very different from new one(i.e: more little) - only the old biggest clouds are going to be keept and the little ones are going to be replaced - @param delayedResponse false to change wheather conditions over several updates, true to change it at the moment - */ - void setWheater(const float& Humidity, const float& AverageCloudsSize, const bool& delayedResponse = true); - - /** Add ellipsoid: clouds are modelled as ellipsoids in our simulation approach, so.. different kind of clouds - can be modelled with ellipsoids compositions. - @param e Ellipsoid - @param UpdateProbabilities Update probabilities? - */ - void addEllipsoid(Ellipsoid *e, const bool& UpdateProbabilities = true); - - /** Forces the data manager to calculate the next step right now - */ - void forceToUpdateData(); - - private: - - /** Initialize data - @param nx X complexity - @param ny Y complexity - @param nz Z complexity - */ - void _initData(const int& nx, const int& ny, const int& nz); - - /** Create tridimensional cell array - @param nx X size - @param ny Y size - @param nz Z size - @param init Initialize values - @return Cell 3d pointer - */ - Cell *** _create3DCellArray(const int& nx, const int& ny, const int& nz, const bool& init = true); - - /** Delete tridimensional cell array - @param c Cell pointer to be deleted - @param nx X size - @param ny Y size - */ - void _delete3DCellArray(Cell ***c, const int& nx, const int& ny); - - /** Copy 3d cells arrays data - @param src Source - @param dest Dest - @param nx X size - @param ny Y size - @param nz Z size - */ - void _copy3DCellArraysData(Cell ***src, Cell ***dest, const int& nx, const int& ny, const int& nz); - - /** Perform celullar automata simulation - @param nx X size - @param ny Y size - @param nz Z size - @param step Calculation step. Valid steps are 0,1,2,3. - @param xStart x start cell (included) - @param xEnd x end cell (not included, until xEnd-1) - */ - void _performCalculations(const int& nx, const int& ny, const int& nz, const int& step, const int& xStart, const int& xEnd); - - /** Update volumetric texture data - @param c Cells data - @param TexId Texture Id - @param nx X size - @param ny Y size - @param nz Z size - */ - void _updateVolTextureData(Cell ***c, const VolTextureId& TexId, const int& nx, const int& ny, const int& nz); - - /** Get continous density at a point - @param c Cells data - @param nx X size - @param ny Y size - @param nz Z size - @param x x Coord - @param y y Coord - @param z z Coord - @param r Radius - @param sgtrength Strength - */ - const float _getDensityAt(Cell ***c, const int& nx, const int& ny, const int& nz, const int& x, const int& y, const int& z, const int& r, const float& strength) const; - - /** Get discrete density at a point - @param c Cells data - @param x x Coord - @param y y Coord - @param z z Coord - */ - const float _getDensityAt(Cell ***c, const int& x, const int& y, const int& z) const; - - /** Fact funtion - @param c Cells data - @param nx X size - @param ny Y size - @param nz Z size - @param x x Coord - @param y y Coord - @param z z Coord - */ - const bool _fact(Cell ***c, const int& nx, const int& ny, const int& nz, const int& x, const int& y, const int& z) const; - - /** Clear probabilities - @param c Cells data - @param nx X size - @param ny Y size - @param nz Z size - @param clearData Clear data? - */ - void _clearProbabilities(Cell*** c, const int& nx, const int& ny, const int& nz, const bool& clearData); - - /** Update probabilities based from the Ellipsoid vector - @param c Cells data - @param nx X size - @param ny Y size - @param nz Z size - @param delayedResponse false to change wheather conditions over several updates, true to change it at the moment - */ - void _updateProbabilities(Cell*** c, const int& nx, const int& ny, const int& nz, const bool& delayedResponse); - - /** Get light absorcion factor at a point - @param c Cells data - @param nx X size - @param ny Y size - @param nz Z size - @param x x Coord - @param y y Coord - @param z z Coord - @param d Light direction - @param att Attenuation factor - */ - const Ogre::Real _getLightAbsorcionAt(Cell*** c, const int& nx, const int& ny, const int& nz, const int& x, const int& y, const int& z, const Ogre::Vector3& d, const float& att) const; - - /** Create volumetric texture - @param TexId Texture Id - @param nx X size - @param ny Y size - @param nz Z size - */ - void _createVolTexture(const VolTextureId& TexId, const int& nx, const int& ny, const int& nz); - - /// Simulation data - Cell ***mCellsCurrent, - ***mCellsTmp; - - /// Current transition - float mCurrentTransition; - /// Update time - float mUpdateTime; - /// Current calculation state - int mStep, mXStart, mXEnd; - - /// Complexities - int mNx, mNy, mNz; - - /// Volumetric textures array - Ogre::TexturePtr mVolTextures[2]; - /// Current texture - bool mVolTexToUpdate; - - /// Has been create(...) already called? - bool mCreated; - - /// Fast fake random - FastFakeRandom *mFFRandom; - - /// Max number of clouds(Ellipsoids) - int mMaxNumberOfClouds; - /// Ellipsoids - std::vector mEllipsoids; - - /// SkyX parent pointer - VClouds *mVClouds; - }; - -}} +namespace SkyX +{ + namespace VClouds + { + + class VClouds; + class Ellipsoid; + + class DataManager + { + public: + /** Cell struct + */ + struct Cell + { + /// Humidity, phase and cloud + bool hum, act, cld; + + /// Probabilities + float phum, pext, pact; + + /// Continous density + float dens; + + /// Light absorcion + float light; + }; + + /** Volumetric textures enumeration + */ + enum VolTextureId + { + VOL_TEX0 = 0, + VOL_TEX1 = 1 + }; + + /** Constructor + @param vc VClouds parent pointer + */ + DataManager(VClouds *vc); + + /** Destructor + */ + ~DataManager(); + + /** Create + @param nx X complexity + @param ny Y complexity + @param nz Z complexity + */ + void create(const int &nx, const int &ny, const int &nz); + + /** Update + @param timeSinceLastFrame Time elapsed since last frame + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Remove + */ + void remove(); + + /** Has been create(...) already called? + @return true if created() have been already called + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Set update time + @param UpdateTime Time elapsed between data calculations, a little freeze could be experimented during these + calculations on old CPU's + */ + inline void setUpdateTime(const float &UpdateTime) + { + mUpdateTime = UpdateTime; + } + + /** Get update time + @return Update time + */ + inline const Ogre::Real &getUpdateTime() const + { + return mUpdateTime; + } + + /** Get current interpolation factor + @return Interpolation factor + @remarks Only for internal use + */ + inline const Ogre::Real _getInterpolation() const + { + return mCurrentTransition / mUpdateTime; + } + + /** Set wheater parameters + Use this funtion to update the cloud field parameters, you'll get a smart and smooth transition from your old + setting to your new ones. + @param Humidity Humidity, in other words: the percentage of clouds in [0,1] range. + @param AverageCloudsSize Average clouds size, for example: if previous wheater clouds size parameter was very + different from new one(i.e: more little) only the old biggest clouds are going to be keept and the little ones are + going to be replaced + @param delayedResponse false to change wheather conditions over several updates, true to change it at the moment + */ + void setWheater(const float &Humidity, const float &AverageCloudsSize, const bool &delayedResponse = true); + + /** Add ellipsoid: clouds are modelled as ellipsoids in our simulation approach, so.. different kind of clouds + can be modelled with ellipsoids compositions. + @param e Ellipsoid + @param UpdateProbabilities Update probabilities? + */ + void addEllipsoid(Ellipsoid *e, const bool &UpdateProbabilities = true); + + /** Forces the data manager to calculate the next step right now + */ + void forceToUpdateData(); + + private: + /** Initialize data + @param nx X complexity + @param ny Y complexity + @param nz Z complexity + */ + void _initData(const int &nx, const int &ny, const int &nz); + + /** Create tridimensional cell array + @param nx X size + @param ny Y size + @param nz Z size + @param init Initialize values + @return Cell 3d pointer + */ + Cell ***_create3DCellArray(const int &nx, const int &ny, const int &nz, const bool &init = true); + + /** Delete tridimensional cell array + @param c Cell pointer to be deleted + @param nx X size + @param ny Y size + */ + void _delete3DCellArray(Cell ***c, const int &nx, const int &ny); + + /** Copy 3d cells arrays data + @param src Source + @param dest Dest + @param nx X size + @param ny Y size + @param nz Z size + */ + void _copy3DCellArraysData(Cell ***src, Cell ***dest, const int &nx, const int &ny, const int &nz); + + /** Perform celullar automata simulation + @param nx X size + @param ny Y size + @param nz Z size + @param step Calculation step. Valid steps are 0,1,2,3. + @param xStart x start cell (included) + @param xEnd x end cell (not included, until xEnd-1) + */ + void _performCalculations(const int &nx, const int &ny, const int &nz, const int &step, const int &xStart, + const int &xEnd); + + /** Update volumetric texture data + @param c Cells data + @param TexId Texture Id + @param nx X size + @param ny Y size + @param nz Z size + */ + void _updateVolTextureData(Cell ***c, const VolTextureId &TexId, const int &nx, const int &ny, const int &nz); + + /** Get continous density at a point + @param c Cells data + @param nx X size + @param ny Y size + @param nz Z size + @param x x Coord + @param y y Coord + @param z z Coord + @param r Radius + @param sgtrength Strength + */ + const float _getDensityAt(Cell ***c, const int &nx, const int &ny, const int &nz, const int &x, const int &y, + const int &z, const int &r, const float &strength) const; + + /** Get discrete density at a point + @param c Cells data + @param x x Coord + @param y y Coord + @param z z Coord + */ + const float _getDensityAt(Cell ***c, const int &x, const int &y, const int &z) const; + + /** Fact funtion + @param c Cells data + @param nx X size + @param ny Y size + @param nz Z size + @param x x Coord + @param y y Coord + @param z z Coord + */ + const bool _fact(Cell ***c, const int &nx, const int &ny, const int &nz, const int &x, const int &y, + const int &z) const; + + /** Clear probabilities + @param c Cells data + @param nx X size + @param ny Y size + @param nz Z size + @param clearData Clear data? + */ + void _clearProbabilities(Cell ***c, const int &nx, const int &ny, const int &nz, const bool &clearData); + + /** Update probabilities based from the Ellipsoid vector + @param c Cells data + @param nx X size + @param ny Y size + @param nz Z size + @param delayedResponse false to change wheather conditions over several updates, true to change it at the moment + */ + void _updateProbabilities(Cell ***c, const int &nx, const int &ny, const int &nz, const bool &delayedResponse); + + /** Get light absorcion factor at a point + @param c Cells data + @param nx X size + @param ny Y size + @param nz Z size + @param x x Coord + @param y y Coord + @param z z Coord + @param d Light direction + @param att Attenuation factor + */ + const Ogre::Real _getLightAbsorcionAt(Cell ***c, const int &nx, const int &ny, const int &nz, const int &x, + const int &y, const int &z, const Ogre::Vector3 &d, const float &att) const; + + /** Create volumetric texture + @param TexId Texture Id + @param nx X size + @param ny Y size + @param nz Z size + */ + void _createVolTexture(const VolTextureId &TexId, const int &nx, const int &ny, const int &nz); + + /// Simulation data + Cell ***mCellsCurrent, ***mCellsTmp; + + /// Current transition + float mCurrentTransition; + /// Update time + float mUpdateTime; + /// Current calculation state + int mStep, mXStart, mXEnd; + + /// Complexities + int mNx, mNy, mNz; + + /// Volumetric textures array + Ogre::TexturePtr mVolTextures[2]; + /// Current texture + bool mVolTexToUpdate; + + /// Has been create(...) already called? + bool mCreated; + + /// Fast fake random + FastFakeRandom *mFFRandom; + + /// Max number of clouds(Ellipsoids) + int mMaxNumberOfClouds; + /// Ellipsoids + std::vector mEllipsoids; + + /// SkyX parent pointer + VClouds *mVClouds; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/Ellipsoid.cpp b/source/main/gfx/skyx/VClouds/Ellipsoid.cpp index cd55e19140..024b62e91f 100644 --- a/source/main/gfx/skyx/VClouds/Ellipsoid.cpp +++ b/source/main/gfx/skyx/VClouds/Ellipsoid.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -23,122 +23,113 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "Ellipsoid.h" -namespace SkyX { namespace VClouds +namespace SkyX { - - Ellipsoid::Ellipsoid( - const int &a, const int &b, const int &c, - const int &nx, const int &ny, const int &nz, - const int &x, const int &y, const int &z, - const Ogre::Real& Density) - : mA(a), mB(b), mC(c) - , mA2(Ogre::Math::Pow(a, 2)), mB2(Ogre::Math::Pow(b, 2)), mC2(Ogre::Math::Pow(c, 2)) - , mNx(nx), mNy(ny), mNz(nz) - , mX(x), mY(y), mZ(z) - , mDensity(Density) - { - } - - Ellipsoid::~Ellipsoid() - { - } - - const float Ellipsoid::_getLength(const int &x, const int &y, const int &z) const - { - if (x == mX && y == mY && z == mZ) - { - return 0.0f; - } - - // x^2 y^2 z^2 - // / + / + / = 1 (Ellipsoid ecuation) - // a^2 b^2 c^2 - // - // maxradatdir = lambda (Xo, Yo, Zo) = lambda; where Xo, Yo and Zo are the components of the normaliced direction vector - // - // => lambda^2 = 1 / ( EllipsoidEcuation...) - // - // => lambda = sqrt (...) => maxradatdir = lambda - - Ogre::Vector3 Direction = Ogre::Vector3(x-mX, y-mY, z-mZ), - DirectionNormalized = Direction.normalisedCopy(); - - Ogre::Real a = Ogre::Math::Pow(DirectionNormalized.x, 2) / mA2 + - Ogre::Math::Pow(DirectionNormalized.y, 2) / mB2 + - Ogre::Math::Pow(DirectionNormalized.z, 2) / mC2, - - lambda = 1.0f / Ogre::Math::Sqrt(a); - - return Ogre::Math::Clamp(Direction.length() / lambda, 0, 1); - } - - const Ogre::Vector3 Ellipsoid::getProbabilities(const int& x, const int& y, const int& z) const - { - float density = Ogre::Math::Pow(1-_getLength(x, y, z), 1.0f/mDensity); - - return Ogre::Vector3(density, 1-density, density); - } - - void Ellipsoid::updateProbabilities(DataManager::Cell ***c, const int &nx, const int &ny, const int &nz, const bool& delayedResponse) - { - int u, v, w, uu, vv; - - float length; - - for (u = mX-mA; u < mX+mA; u++) - { - uu = (u<0) ? (u + nx) : u; if (u>=nx) { uu-= nx; } - - for (v = mY-mB; v < mY+mB; v++) - { - vv = (v<0) ? (v + ny) : v; if (v>=ny) { vv-= ny; } - - for (w = mZ-mC; w < mZ+mC; w++) - { - length = _getLength(u, v, w); - - if (length < 1) - { - c[uu][vv][w].phum = 0.005f; - c[uu][vv][w].pext = 0.05f; - c[uu][vv][w].pact = 0.01f; - - if (!delayedResponse) - { - c[uu][vv][w].cld = Ogre::Math::RangeRandom(0,1) > length ? true : false; - } - } - } - } - } - } - - void Ellipsoid::move(const int& Ax, const int& Ay, const int& Az) - { - mX += Ax; mY += Ay; mZ += Az; - } - - const bool Ellipsoid::isOutOfCells() const - { - if ( (mX+mA) >= mNx || (mX-mA) < 0 || - (mY+mB) >= mNy || (mY-mB) < 0 || - (mZ+mZ) >= mNz || (mZ-mZ) < 0 ) - { - return true; - } - - return false; - } - - void Ellipsoid::setDimensions(const Ogre::Vector3& Dimensions) - { - mA = Dimensions.x; - mB = Dimensions.y; - mC = Dimensions.z; - - mA2 = Ogre::Math::Pow(mA, 2); - mB2 = Ogre::Math::Pow(mB, 2); - mC2 = Ogre::Math::Pow(mC, 2); - } - -}} \ No newline at end of file + namespace VClouds + { + + Ellipsoid::Ellipsoid(const int &a, const int &b, const int &c, const int &nx, const int &ny, const int &nz, const int &x, + const int &y, const int &z, const Ogre::Real &Density) + : mA(a), mB(b), mC(c), mA2(Ogre::Math::Pow(a, 2)), mB2(Ogre::Math::Pow(b, 2)), mC2(Ogre::Math::Pow(c, 2)), mNx(nx), + mNy(ny), mNz(nz), mX(x), mY(y), mZ(z), mDensity(Density) + { + } + + Ellipsoid::~Ellipsoid() + { + } + + const float Ellipsoid::_getLength(const int &x, const int &y, const int &z) const + { + if (x == mX && y == mY && z == mZ) { return 0.0f; } + + // x^2 y^2 z^2 + // / + / + / = 1 (Ellipsoid ecuation) + // a^2 b^2 c^2 + // + // maxradatdir = lambda (Xo, Yo, Zo) = lambda; where Xo, Yo and Zo are the components of the normaliced direction + // vector + // + // => lambda^2 = 1 / ( EllipsoidEcuation...) + // + // => lambda = sqrt (...) => maxradatdir = lambda + + Ogre::Vector3 Direction = Ogre::Vector3(x - mX, y - mY, z - mZ), DirectionNormalized = Direction.normalisedCopy(); + + Ogre::Real a = Ogre::Math::Pow(DirectionNormalized.x, 2) / mA2 + Ogre::Math::Pow(DirectionNormalized.y, 2) / mB2 + + Ogre::Math::Pow(DirectionNormalized.z, 2) / mC2, + + lambda = 1.0f / Ogre::Math::Sqrt(a); + + return Ogre::Math::Clamp(Direction.length() / lambda, 0, 1); + } + + const Ogre::Vector3 Ellipsoid::getProbabilities(const int &x, const int &y, const int &z) const + { + float density = Ogre::Math::Pow(1 - _getLength(x, y, z), 1.0f / mDensity); + + return Ogre::Vector3(density, 1 - density, density); + } + + void Ellipsoid::updateProbabilities(DataManager::Cell ***c, const int &nx, const int &ny, const int &nz, + const bool &delayedResponse) + { + int u, v, w, uu, vv; + + float length; + + for (u = mX - mA; u < mX + mA; u++) + { + uu = (u < 0) ? (u + nx) : u; + if (u >= nx) { uu -= nx; } + + for (v = mY - mB; v < mY + mB; v++) + { + vv = (v < 0) ? (v + ny) : v; + if (v >= ny) { vv -= ny; } + + for (w = mZ - mC; w < mZ + mC; w++) + { + length = _getLength(u, v, w); + + if (length < 1) + { + c[uu][vv][w].phum = 0.005f; + c[uu][vv][w].pext = 0.05f; + c[uu][vv][w].pact = 0.01f; + + if (!delayedResponse) { c[uu][vv][w].cld = Ogre::Math::RangeRandom(0, 1) > length ? true : false; } + } + } + } + } + } + + void Ellipsoid::move(const int &Ax, const int &Ay, const int &Az) + { + mX += Ax; + mY += Ay; + mZ += Az; + } + + const bool Ellipsoid::isOutOfCells() const + { + if ((mX + mA) >= mNx || (mX - mA) < 0 || (mY + mB) >= mNy || (mY - mB) < 0 || (mZ + mZ) >= mNz || (mZ - mZ) < 0) + { return true; } + + return false; + } + + void Ellipsoid::setDimensions(const Ogre::Vector3 &Dimensions) + { + mA = Dimensions.x; + mB = Dimensions.y; + mC = Dimensions.z; + + mA2 = Ogre::Math::Pow(mA, 2); + mB2 = Ogre::Math::Pow(mB, 2); + mC2 = Ogre::Math::Pow(mC, 2); + } + + } // namespace VClouds +} \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/Ellipsoid.h b/source/main/gfx/skyx/VClouds/Ellipsoid.h index 9df00e1459..e979a14a40 100644 --- a/source/main/gfx/skyx/VClouds/Ellipsoid.h +++ b/source/main/gfx/skyx/VClouds/Ellipsoid.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,122 +24,124 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_VClouds_Ellipsoid_H_ #define _SkyX_VClouds_Ellipsoid_H_ -#include "Prerequisites.h" - #include "DataManager.h" +#include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - /** Ellipsoid class - x^2 y^2 z^2 - / + / + / = 1 - a^2 b^2 c^2 - */ - class Ellipsoid - { - public: - /** Constructor - @param a A constant - @param b B constant - @param c C constant - @param nx X size - @param ny Y size - @param nz Z size - @param x x Coord (position) - @param y y Coord (position) - @param z z Coord (position) - @param Density Cloud density - */ - Ellipsoid(const int& a, const int& b, const int& c, - const int& nx, const int& ny, const int& nz, - const int& x, const int& y, const int& z, - const Ogre::Real& DynLibManager = 1.0f); - - /** Destructor - */ - ~Ellipsoid(); - - /** Move the ellipsoid - @param Ax x increment - @param Ay y increment - @param Az z increment - */ - void move(const int& Ax, const int& Ay, const int& Az); - - /** Get probabilities at a point - @param x x Coord - @param y y Coord - @param z z Coord - @return Probabilities (Hum, Ext, Act) - */ - const Ogre::Vector3 getProbabilities(const int& x, const int& y, const int& z) const; - - /** Update probabilities - @param c Cells - @param nx X complexity - @param ny Y complexity - @param nz Z complexity - @param delayedResponse true to get a delayed response, updating only probabilities, false to also set clouds - */ - void updateProbabilities(DataManager::Cell ***c, const int &nx, const int &ny, const int &nz, const bool& delayedResponse = true); - - /** Determines if the ellipsoid is out of the cells domain and needs to be removed - */ - const bool isOutOfCells() const; - - /** Get dimensions - @return Ellipsoid dimensions - */ - inline const Ogre::Vector3 getDimensions() const - { - return Ogre::Vector3(mA, mB, mC); - } - - /** Get position - @return Position - */ - inline const Ogre::Vector3 getPosition() const - { - return Ogre::Vector3(mX, mY, mZ); - } - - /** Set dimensions - @param Dimensions New dimensions - */ - void setDimensions(const Ogre::Vector3& Dimensions); - - /** Set position - @param Position New position - */ - inline void setPosition(const Ogre::Vector3& Position) - { - mX = Position.x; - mY = Position.y; - mZ = Position.z; - } - - private: - /** Get length - @param x x Coord - @param y y Coord - @param z z Coord - @return [0,1] range where 0 is the center of the ellipsoid and 1 the superfice - */ - const float _getLength(const int& x, const int& y, const int& z) const; - - /// Ellipsoid parameters - int mA, mB, mC, mA2, mB2, mC2; - - /// Position - int mX, mY, mZ; - - /// Cells size - int mNx, mNy, mNz; - - /// Cloud density - Ogre::Real mDensity; - }; - -}} +namespace SkyX +{ + namespace VClouds + { + + /** Ellipsoid class + x^2 y^2 z^2 + / + / + / = 1 + a^2 b^2 c^2 + */ + class Ellipsoid + { + public: + /** Constructor + @param a A constant + @param b B constant + @param c C constant + @param nx X size + @param ny Y size + @param nz Z size + @param x x Coord (position) + @param y y Coord (position) + @param z z Coord (position) + @param Density Cloud density + */ + Ellipsoid(const int &a, const int &b, const int &c, const int &nx, const int &ny, const int &nz, const int &x, + const int &y, const int &z, const Ogre::Real &DynLibManager = 1.0f); + + /** Destructor + */ + ~Ellipsoid(); + + /** Move the ellipsoid + @param Ax x increment + @param Ay y increment + @param Az z increment + */ + void move(const int &Ax, const int &Ay, const int &Az); + + /** Get probabilities at a point + @param x x Coord + @param y y Coord + @param z z Coord + @return Probabilities (Hum, Ext, Act) + */ + const Ogre::Vector3 getProbabilities(const int &x, const int &y, const int &z) const; + + /** Update probabilities + @param c Cells + @param nx X complexity + @param ny Y complexity + @param nz Z complexity + @param delayedResponse true to get a delayed response, updating only probabilities, false to also set clouds + */ + void updateProbabilities(DataManager::Cell ***c, const int &nx, const int &ny, const int &nz, + const bool &delayedResponse = true); + + /** Determines if the ellipsoid is out of the cells domain and needs to be removed + */ + const bool isOutOfCells() const; + + /** Get dimensions + @return Ellipsoid dimensions + */ + inline const Ogre::Vector3 getDimensions() const + { + return Ogre::Vector3(mA, mB, mC); + } + + /** Get position + @return Position + */ + inline const Ogre::Vector3 getPosition() const + { + return Ogre::Vector3(mX, mY, mZ); + } + + /** Set dimensions + @param Dimensions New dimensions + */ + void setDimensions(const Ogre::Vector3 &Dimensions); + + /** Set position + @param Position New position + */ + inline void setPosition(const Ogre::Vector3 &Position) + { + mX = Position.x; + mY = Position.y; + mZ = Position.z; + } + + private: + /** Get length + @param x x Coord + @param y y Coord + @param z z Coord + @return [0,1] range where 0 is the center of the ellipsoid and 1 the superfice + */ + const float _getLength(const int &x, const int &y, const int &z) const; + + /// Ellipsoid parameters + int mA, mB, mC, mA2, mB2, mC2; + + /// Position + int mX, mY, mZ; + + /// Cells size + int mNx, mNy, mNz; + + /// Cloud density + Ogre::Real mDensity; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/FastFakeRandom.cpp b/source/main/gfx/skyx/VClouds/FastFakeRandom.cpp index 4f0d1e8f63..5001fbf662 100644 --- a/source/main/gfx/skyx/VClouds/FastFakeRandom.cpp +++ b/source/main/gfx/skyx/VClouds/FastFakeRandom.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -23,30 +23,32 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "FastFakeRandom.h" -namespace SkyX { namespace VClouds +namespace SkyX { - FastFakeRandom::FastFakeRandom(const int &n, const Ogre::Real &min, const Ogre::Real &max) - : mCapacity(n) - , mIndex(-1) - { - mData = new float[n]; - - for (int k = 0; k < n; k++) - { - mData[k] = Ogre::Math::RangeRandom(min, max); - } - } - - FastFakeRandom::~FastFakeRandom() - { - delete [] mData; - } - - float& FastFakeRandom::get() - { - mIndex ++; if (mIndex >= mCapacity) {mIndex = 0;} - - return mData[mIndex]; - } - -}} \ No newline at end of file + namespace VClouds + { + FastFakeRandom::FastFakeRandom(const int &n, const Ogre::Real &min, const Ogre::Real &max) : mCapacity(n), mIndex(-1) + { + mData = new float[n]; + + for (int k = 0; k < n; k++) + { + mData[k] = Ogre::Math::RangeRandom(min, max); + } + } + + FastFakeRandom::~FastFakeRandom() + { + delete[] mData; + } + + float &FastFakeRandom::get() + { + mIndex++; + if (mIndex >= mCapacity) { mIndex = 0; } + + return mData[mIndex]; + } + + } // namespace VClouds +} \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/FastFakeRandom.h b/source/main/gfx/skyx/VClouds/FastFakeRandom.h index cbca80b150..a69e827069 100644 --- a/source/main/gfx/skyx/VClouds/FastFakeRandom.h +++ b/source/main/gfx/skyx/VClouds/FastFakeRandom.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -26,36 +26,39 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class FastFakeRandom - { - public: - /** Constructor - @param n Capacity - @param min Min value - @param max Max value - */ - FastFakeRandom(const int& n, const Ogre::Real& min, const Ogre::Real& max); - - /** Destructor - */ - ~FastFakeRandom(); - - /** Get random number - */ - float& get(); - - private: - /// Data pointer - float *mData; - /// Capacity - int mCapacity; - /// Index - int mIndex; - - }; - -}} +namespace SkyX +{ + namespace VClouds + { + + class FastFakeRandom + { + public: + /** Constructor + @param n Capacity + @param min Min value + @param max Max value + */ + FastFakeRandom(const int &n, const Ogre::Real &min, const Ogre::Real &max); + + /** Destructor + */ + ~FastFakeRandom(); + + /** Get random number + */ + float &get(); + + private: + /// Data pointer + float *mData; + /// Capacity + int mCapacity; + /// Index + int mIndex; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/GeometryBlock.cpp b/source/main/gfx/skyx/VClouds/GeometryBlock.cpp index f6a62688cc..c12068481b 100644 --- a/source/main/gfx/skyx/VClouds/GeometryBlock.cpp +++ b/source/main/gfx/skyx/VClouds/GeometryBlock.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -25,542 +25,487 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "VClouds.h" -namespace SkyX { namespace VClouds +namespace SkyX { - GeometryBlock::GeometryBlock(VClouds* vc, - const float& Height, const Ogre::Radian& Alpha, const Ogre::Radian& Beta, - const float& Radius, const Ogre::Radian& Phi, const int& Na, - const int& Nb, const int& Nc, const int& A, - const int& B, const int& C, const int& Position) - : mVClouds(vc) - , mCreated(false) - , mSubMesh(0) - , mEntity(0) - , mVertices(0) - , mNumberOfTriangles(0) - , mVertexCount(0) - , mHeight(Height) - , mAlpha(Alpha) - , mBeta(Beta) - , mRadius(Radius) - , mPhi(Phi) - , mNa(Na) , mNb(Nb) , mNc(Nc) - , mA(A) , mB(B) , mC(C) - , mPosition(Position) - , mDisplacement(Ogre::Vector3(0,0,0)) - , mWorldOffset(Ogre::Vector2(0,0)) - , mCamera(0) - , mDistance(Ogre::Vector3(0,0,0)) - , mLastFallingDistance(0) - { - _calculateDataSize(); - } - - GeometryBlock::~GeometryBlock() - { - remove(); - } - - void GeometryBlock::create() - { - remove(); - - // Create mesh and submesh - mMesh = Ogre::MeshManager::getSingleton().createManual("_SkyX_VClouds_Block" + Ogre::StringConverter::toString(mPosition), - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - mSubMesh = mMesh->createSubMesh(); - mSubMesh->useSharedVertices = false; - - // Create mesh geometry - _createGeometry(); - - // Build edge list - mMesh->buildEdgeList(); - - // End mesh creation - mMesh->load(); - mMesh->touch(); - - // Create entity - mEntity = mVClouds->getSceneManager()->createEntity("_SkyX_VClouds_BlockEnt" + Ogre::StringConverter::toString(mPosition), "_SkyX_VClouds_Block" + Ogre::StringConverter::toString(mPosition)); - mEntity->setMaterialName("SkyX_VolClouds"); - mEntity->setCastShadows(false); - mEntity->setRenderQueueGroup(mVClouds->getRenderQueueGroups().vclouds); - - // Set bounds - mMesh->_setBounds(_buildAABox(mLastFallingDistance)); - - mCreated = true; - } - - void GeometryBlock::remove() - { - if (!mCreated) - { - return; - } - - Ogre::MeshManager::getSingleton().remove(mMesh->getName()); - mVClouds->getSceneManager()->destroyEntity(mEntity); - - mMesh.setNull(); - mSubMesh = 0; - mEntity = 0; - mVertexBuffer.setNull(); - mIndexBuffer.setNull(); - - delete [] mVertices; - - mCreated = false; - } - - const Ogre::AxisAlignedBox GeometryBlock::_buildAABox(const float& fd) const - { - Ogre::Vector2 Center = Ogre::Vector2(0,0); - Ogre::Vector2 V1 = mRadius*Ogre::Vector2(Ogre::Math::Cos(mPhi*mPosition), Ogre::Math::Sin(mPhi*mPosition)); - Ogre::Vector2 V2 = mRadius*Ogre::Vector2(Ogre::Math::Cos(mPhi*(mPosition+1)), Ogre::Math::Sin(mPhi*(mPosition+1))); - - Ogre::Vector2 Max = Ogre::Vector2(std::max(std::max(V1.x, V2.x), Center.x), std::max(std::max(V1.y, V2.y), Center.y) ); - Ogre::Vector2 Min = Ogre::Vector2(std::min(std::min(V1.x, V2.x), Center.x), std::min(std::min(V1.y, V2.y), Center.y) ); - - return Ogre::AxisAlignedBox( - // Min x,y,z - Min.x, -std::max(fd,0), Min.y, - // Max x,y,z - Max.x, mHeight - std::min(fd,0), Max.y); - } - - void GeometryBlock::_calculateDataSize() - { - mVertexCount = 7*mNa + 6*mNb + 4*mNc; - mNumberOfTriangles = 5*mNa + 4*mNb + 2*mNc; - - mV2Cos = Ogre::Vector2(Ogre::Math::Cos(mPosition*mPhi), Ogre::Math::Cos((mPosition+1)*mPhi)); - mV2Sin = Ogre::Vector2(Ogre::Math::Sin(mPosition*mPhi), Ogre::Math::Sin((mPosition+1)*mPhi)); - - mBetaSin = Ogre::Math::Sin(Ogre::Math::PI-mBeta.valueRadians()); - mAlphaSin = Ogre::Math::Sin(Ogre::Math::PI-mAlpha.valueRadians()); - } - - void GeometryBlock::_createGeometry() - { - // Vertex buffers - mSubMesh->vertexData = new Ogre::VertexData(); - mSubMesh->vertexData->vertexStart = 0; - mSubMesh->vertexData->vertexCount = mVertexCount; - - Ogre::VertexDeclaration* vdecl = mSubMesh->vertexData->vertexDeclaration; - Ogre::VertexBufferBinding* vbind = mSubMesh->vertexData->vertexBufferBinding; - - size_t offset = 0; - // Position - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - // 3D coords - vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES, 0); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); - // Noise coords - vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1); - offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); - // Opacity - vdecl->addElement(0, offset, Ogre::VET_FLOAT1, Ogre::VES_TEXTURE_COORDINATES, 2); - - mVertexBuffer = Ogre::HardwareBufferManager::getSingleton(). - createVertexBuffer(sizeof(VERTEX), - mVertexCount, - Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); - - vbind->setBinding(0, mVertexBuffer); - - unsigned short *indexbuffer = new unsigned short[mNumberOfTriangles*3]; - - int IndexOffset = 0; - int VertexOffset = 0; - - // C - for (int k = 0; k < mNc; k++) - { - // First triangle - indexbuffer[IndexOffset] = VertexOffset; - indexbuffer[IndexOffset+1] = VertexOffset+1; - indexbuffer[IndexOffset+2] = VertexOffset+3; - - // Second triangle - indexbuffer[IndexOffset+3] = VertexOffset; - indexbuffer[IndexOffset+4] = VertexOffset+3; - indexbuffer[IndexOffset+5] = VertexOffset+2; - - IndexOffset += 6; - VertexOffset += 4; - } - - // B - for (int k = 0; k < mNb; k++) - { - // First triangle - indexbuffer[IndexOffset] = VertexOffset; - indexbuffer[IndexOffset+1] = VertexOffset+1; - indexbuffer[IndexOffset+2] = VertexOffset+3; - - // Second triangle - indexbuffer[IndexOffset+3] = VertexOffset; - indexbuffer[IndexOffset+4] = VertexOffset+3; - indexbuffer[IndexOffset+5] = VertexOffset+2; - - // Third triangle - indexbuffer[IndexOffset+6] = VertexOffset+2; - indexbuffer[IndexOffset+7] = VertexOffset+3; - indexbuffer[IndexOffset+8] = VertexOffset+5; - - // Fourth triangle - indexbuffer[IndexOffset+9] = VertexOffset+2; - indexbuffer[IndexOffset+10] = VertexOffset+5; - indexbuffer[IndexOffset+11] = VertexOffset+4; - - IndexOffset += 12; - VertexOffset += 6; - } - - // A - for (int k = 0; k < mNa; k++) - { - // First triangle - indexbuffer[IndexOffset] = VertexOffset; - indexbuffer[IndexOffset+1] = VertexOffset+1; - indexbuffer[IndexOffset+2] = VertexOffset+3; - - // Second triangle - indexbuffer[IndexOffset+3] = VertexOffset; - indexbuffer[IndexOffset+4] = VertexOffset+3; - indexbuffer[IndexOffset+5] = VertexOffset+2; - - // Third triangle - indexbuffer[IndexOffset+6] = VertexOffset+2; - indexbuffer[IndexOffset+7] = VertexOffset+3; - indexbuffer[IndexOffset+8] = VertexOffset+5; - - // Fourth triangle - indexbuffer[IndexOffset+9] = VertexOffset+2; - indexbuffer[IndexOffset+10] = VertexOffset+5; - indexbuffer[IndexOffset+11] = VertexOffset+4; - - // Fifth triangle - indexbuffer[IndexOffset+12] = VertexOffset+4; - indexbuffer[IndexOffset+13] = VertexOffset+5; - indexbuffer[IndexOffset+14] = VertexOffset+6; - - IndexOffset += 15; - VertexOffset += 7; - } - - // Prepare buffer for indices - mIndexBuffer = - Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( - Ogre::HardwareIndexBuffer::IT_16BIT, - mNumberOfTriangles*3, - Ogre::HardwareBuffer::HBU_STATIC, true); - - mIndexBuffer-> - writeData(0, - mIndexBuffer->getSizeInBytes(), - indexbuffer, - true); - - delete []indexbuffer; - - // Set index buffer for this submesh - mSubMesh->indexData->indexBuffer = mIndexBuffer; - mSubMesh->indexData->indexStart = 0; - mSubMesh->indexData->indexCount = mNumberOfTriangles*3; - - // Create our internal buffer for manipulations - mVertices = new VERTEX[mVertexCount]; - } - - void GeometryBlock::updateGeometry(Ogre::Camera* c, const Ogre::Vector3& displacement, const Ogre::Vector3& distance) - { - if (!mCreated) - { - return; - } - - mDisplacement = displacement; - - float fallingDistance = mVClouds->getDistanceFallingParams().x*(mEntity->getParentSceneNode()->_getDerivedPosition().y-c->getDerivedPosition().y); - - if (mVClouds->getDistanceFallingParams().y > 0) // -1 means no max falling - { - if (fallingDistance > 0) - { - if (fallingDistance > mVClouds->getDistanceFallingParams().y) - { - fallingDistance = mVClouds->getDistanceFallingParams().y; - } - } - else - { - if (-fallingDistance > mVClouds->getDistanceFallingParams().y) - { - fallingDistance = -mVClouds->getDistanceFallingParams().y; - } - } - } - - if (fallingDistance != mLastFallingDistance) - { - mLastFallingDistance = fallingDistance; - mMesh->_setBounds(_buildAABox(mLastFallingDistance)); - } - - if (isInFrustum(c)) - { - mCamera = c; - mDistance = distance; - _updateGeometry(); - } - } - - void GeometryBlock::_updateGeometry() - { - // Update zone C - for (int k = 0; k < mNc; k++) - { - _updateZoneCSlice(k); - } - - // Update zone B - for (int k = 0; k < mNb; k++) - { - _updateZoneBSlice(k); - } - - // Update zone A - for (int k = 0; k < mNa; k++) - { - _updateZoneASlice(k); - } - - // Upload changes - mVertexBuffer-> - writeData(0, - mVertexBuffer->getSizeInBytes(), - mVertices, - true); - } - - void GeometryBlock::_updateZoneCSlice(const int& n) - { - int VertexOffset = n*4; - - // TODO, calculate constants by zone, not by slice - float Radius = mB+((mC-mB)/mNc)*(mNc-n); - - Radius += mDisplacement.z; - - float opacity = 1; - - if (n == 0) - { - opacity = 1 - mDisplacement.z/((mC-mB)/mNc); - } - else if (n == mNc-1) - { - opacity = mDisplacement.z/((mC-mB)/mNc); - } - - Ogre::Vector2 x1 = Radius*mV2Cos, - x2 = Radius*mBetaSin*mV2Cos, - z1 = Radius*mV2Sin, - z2 = Radius*mBetaSin*mV2Sin; - - Ogre::Vector3 or0 = Ogre::Vector3(x1.x, 0, z1.x), - or1 = Ogre::Vector3(x1.y, 0, z1.y); - - float y0 = Radius*Ogre::Math::Sin(mAlpha), - d = Ogre::Vector2(x1.x - x2.x, z1.x - z2.x).length(), - ang = Ogre::Math::ATan(y0/d).valueRadians(), - hip = mHeight / Ogre::Math::Sin(ang); - - // Vertex 0 - _setVertexData(VertexOffset, or0, opacity); - // Vertex 1 - _setVertexData(VertexOffset+1, or1, opacity); - // Vertex 2 - _setVertexData(VertexOffset+2, or0+(Ogre::Vector3(x2.x, y0, z2.x)-or0).normalisedCopy()*hip, opacity); - // Vertex 3 - _setVertexData(VertexOffset+3, or1+(Ogre::Vector3(x2.y, y0, z2.y)-or1).normalisedCopy()*hip, opacity); - } - - void GeometryBlock::_updateZoneBSlice(const int& n) - { - int VertexOffset = mNc*4 + n*6; - - // TODO - float Radius = mA+((mB-mA)/mNb)*(mNb-n); - - Radius += mDisplacement.y; - - float opacity = 1; - - if (n == 0) - { - opacity = 1-mDisplacement.y/((mB-mA)/mNb); - } - else if (n == mNb-1) - { - opacity = mDisplacement.y/((mB-mA)/mNb); - } - - Ogre::Vector2 x1 = Radius*mV2Cos, - x2 = Radius*mBetaSin*mV2Cos, - z1 = Radius*mV2Sin, - z2 = Radius*mBetaSin*mV2Sin; - - float y0 = Radius*Ogre::Math::Sin(mAlpha); - - // Vertex 0 - _setVertexData(VertexOffset, Ogre::Vector3(x1.x, 0, z1.x), opacity); - // Vertex 1 - _setVertexData(VertexOffset+1, Ogre::Vector3(x1.y, 0, z1.y), opacity); - // Vertex 2 - _setVertexData(VertexOffset+2, Ogre::Vector3(x2.x, y0, z2.x), opacity); - // Vertex 3 - _setVertexData(VertexOffset+3, Ogre::Vector3(x2.y, y0, z2.y), opacity); - - Ogre::Vector2 x3 = Radius*mAlphaSin*mV2Cos, - z3 = Radius*mAlphaSin*mV2Sin; - - Ogre::Vector3 or0 = Ogre::Vector3(x2.x, y0, z2.x), - or1 = Ogre::Vector3(x2.y, y0, z2.y); - - float y1 = Radius*Ogre::Math::Sin(mBeta), - y3 = y1-y0, - d = Ogre::Vector2(x3.x - x2.x, z3.x - z2.x).length(), - ang = Ogre::Math::ATan(y3/d).valueRadians(), - hip = (mHeight-y0) / Ogre::Math::Sin(ang); - - // Vertex 4 - _setVertexData(VertexOffset+4, or0 + (Ogre::Vector3(x3.x, y1, z3.x)-or0).normalisedCopy()*hip, opacity); - // Vertex 5 - _setVertexData(VertexOffset+5, or1 + (Ogre::Vector3(x3.y, y1, z3.y)-or1).normalisedCopy()*hip, opacity); - } - - void GeometryBlock::_updateZoneASlice(const int& n) - { - int VertexOffset = mNc*4 + mNb*6 +n*7; - - // TODO - float Radius = (mA/mNa)*(mNa-n); - - Radius += mDisplacement.x; - - float opacity = (n == 0) ? (1-mDisplacement.x/(mA/mNa)) : 1.0f; - - Ogre::Vector2 x1 = Radius*mV2Cos, - x2 = Radius*mBetaSin*mV2Cos, - z1 = Radius*mV2Sin, - z2 = Radius*mBetaSin*mV2Sin; - - float y0 = Radius*Ogre::Math::Sin(mAlpha); - - // Vertex 0 - _setVertexData(VertexOffset, Ogre::Vector3(x1.x, 0, z1.x), opacity); - // Vertex 1 - _setVertexData(VertexOffset+1, Ogre::Vector3(x1.y, 0, z1.y), opacity); - // Vertex 2 - _setVertexData(VertexOffset+2, Ogre::Vector3(x2.x, y0, z2.x), opacity); - // Vertex 3 - _setVertexData(VertexOffset+3, Ogre::Vector3(x2.y, y0, z2.y), opacity); - - Ogre::Vector2 x3 = Radius*mAlphaSin*mV2Cos, - z3 = Radius*mAlphaSin*mV2Sin; - - float y1 = Radius*Ogre::Math::Sin(mBeta); - - // Vertex 4 - _setVertexData(VertexOffset+4, Ogre::Vector3(x3.x, y1, z3.x), opacity); - // Vertex 5 - _setVertexData(VertexOffset+5, Ogre::Vector3(x3.y, y1, z3.y), opacity); - - // Vertex 6 - _setVertexData(VertexOffset+6, Ogre::Vector3(0, Radius, 0), opacity); - } - - void GeometryBlock::_setVertexData(const int& index, const Ogre::Vector3& p, const float& o) - { - float yDist = -mDistance.y; - float fallingDistance = mVClouds->getDistanceFallingParams().x*yDist*(Ogre::Vector2(p.x,p.z).length()/mRadius); - - if (mVClouds->getDistanceFallingParams().y > 0) // -1 means no max falling - { - if (fallingDistance > 0) - { - if (fallingDistance > mVClouds->getDistanceFallingParams().y) - { - fallingDistance = mVClouds->getDistanceFallingParams().y; - } - } - else - { - if (-fallingDistance > mVClouds->getDistanceFallingParams().y) - { - fallingDistance = -mVClouds->getDistanceFallingParams().y; - } - } - } - - fallingDistance *= Ogre::Math::Sign(yDist); - - // Position - mVertices[index].x = p.x; - if (yDist < -mHeight/2) - { - // Over-cloud - mVertices[index].y = mHeight - p.y; - } - else // Under-cloud - { - mVertices[index].y = p.y - fallingDistance; - } - mVertices[index].z = p.z; - - // 3D coords (Z-UP) - float scale = mVClouds->getCloudFieldScale()/mRadius; - mVertices[index].xc = (p.x+mWorldOffset.x)*scale; - mVertices[index].yc = (p.z+mWorldOffset.y)*scale; - mVertices[index].zc = Ogre::Math::Clamp(p.y/mHeight, 0, 1); - if (yDist < -mHeight/2) - { - // Over-cloud - mVertices[index].zc = 1.0f - mVertices[index].zc; - } - - // Noise coords - float noise_scale = mVClouds->getNoiseScale()/mRadius; - float xz_length_radius = Ogre::Vector2(p.x,p.z).length() / mRadius; - Ogre::Vector3 origin = Ogre::Vector3(0,-(mEntity->getParentSceneNode()->_getDerivedPosition().y-mCamera->getDerivedPosition().y) -mRadius*(0.5f+0.5f*Ogre::Vector2(p.x,p.z).length()/mRadius),0); - Ogre::Vector3 dir = (p-origin).normalisedCopy(); - float hip = Ogre::Math::Sqrt(Ogre::Math::Pow(xz_length_radius * mRadius, 2) + Ogre::Math::Pow(origin.y, 2)); - Ogre::Vector3 uv = dir*hip; // Only x/z, += origin doesn't need - mVertices[index].u = (uv.x+mWorldOffset.x)*noise_scale; - mVertices[index].v = (uv.z+mWorldOffset.y)*noise_scale; - - // Opacity - float dist = (mDistance - Ogre::Vector3(p.x, p.y - fallingDistance, p.z)).length(); - float att = Ogre::Math::Clamp((dist-mA/3.25f)/(mA/3.25f),0.0f,1.0f); - mVertices[index].o = o * att * mVClouds->getGlobalOpacity(); - } - - const bool GeometryBlock::isInFrustum(Ogre::Camera *c) const - { - if (!mCreated) - { - return false; - } - - // TODO: Use a world bounding box for each geometry zone, this way the - // culling is going to be more acurrated and the geometry falling is going to be culled - // when the falling factor is bigger than 1. - return c->isVisible(mEntity->getParentSceneNode()->_getWorldAABB()); - } -}} \ No newline at end of file + namespace VClouds + { + GeometryBlock::GeometryBlock(VClouds *vc, const float &Height, const Ogre::Radian &Alpha, const Ogre::Radian &Beta, + const float &Radius, const Ogre::Radian &Phi, const int &Na, const int &Nb, const int &Nc, + const int &A, const int &B, const int &C, const int &Position) + : mVClouds(vc), mCreated(false), mSubMesh(0), mEntity(0), mVertices(0), mNumberOfTriangles(0), mVertexCount(0), + mHeight(Height), mAlpha(Alpha), mBeta(Beta), mRadius(Radius), mPhi(Phi), mNa(Na), mNb(Nb), mNc(Nc), mA(A), mB(B), + mC(C), mPosition(Position), mDisplacement(Ogre::Vector3(0, 0, 0)), mWorldOffset(Ogre::Vector2(0, 0)), mCamera(0), + mDistance(Ogre::Vector3(0, 0, 0)), mLastFallingDistance(0) + { + _calculateDataSize(); + } + + GeometryBlock::~GeometryBlock() + { + remove(); + } + + void GeometryBlock::create() + { + remove(); + + // Create mesh and submesh + mMesh = + Ogre::MeshManager::getSingleton().createManual("_SkyX_VClouds_Block" + Ogre::StringConverter::toString(mPosition), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + mSubMesh = mMesh->createSubMesh(); + mSubMesh->useSharedVertices = false; + + // Create mesh geometry + _createGeometry(); + + // Build edge list + mMesh->buildEdgeList(); + + // End mesh creation + mMesh->load(); + mMesh->touch(); + + // Create entity + mEntity = + mVClouds->getSceneManager()->createEntity("_SkyX_VClouds_BlockEnt" + Ogre::StringConverter::toString(mPosition), + "_SkyX_VClouds_Block" + Ogre::StringConverter::toString(mPosition)); + mEntity->setMaterialName("SkyX_VolClouds"); + mEntity->setCastShadows(false); + mEntity->setRenderQueueGroup(mVClouds->getRenderQueueGroups().vclouds); + + // Set bounds + mMesh->_setBounds(_buildAABox(mLastFallingDistance)); + + mCreated = true; + } + + void GeometryBlock::remove() + { + if (!mCreated) { return; } + + Ogre::MeshManager::getSingleton().remove(mMesh->getName()); + mVClouds->getSceneManager()->destroyEntity(mEntity); + + mMesh.setNull(); + mSubMesh = 0; + mEntity = 0; + mVertexBuffer.setNull(); + mIndexBuffer.setNull(); + + delete[] mVertices; + + mCreated = false; + } + + const Ogre::AxisAlignedBox GeometryBlock::_buildAABox(const float &fd) const + { + Ogre::Vector2 Center = Ogre::Vector2(0, 0); + Ogre::Vector2 V1 = mRadius * Ogre::Vector2(Ogre::Math::Cos(mPhi * mPosition), Ogre::Math::Sin(mPhi * mPosition)); + Ogre::Vector2 V2 = + mRadius * Ogre::Vector2(Ogre::Math::Cos(mPhi * (mPosition + 1)), Ogre::Math::Sin(mPhi * (mPosition + 1))); + + Ogre::Vector2 Max = Ogre::Vector2(std::max(std::max(V1.x, V2.x), Center.x), + std::max(std::max(V1.y, V2.y), Center.y)); + Ogre::Vector2 Min = Ogre::Vector2(std::min(std::min(V1.x, V2.x), Center.x), + std::min(std::min(V1.y, V2.y), Center.y)); + + return Ogre::AxisAlignedBox( + // Min x,y,z + Min.x, -std::max(fd, 0), Min.y, + // Max x,y,z + Max.x, mHeight - std::min(fd, 0), Max.y); + } + + void GeometryBlock::_calculateDataSize() + { + mVertexCount = 7 * mNa + 6 * mNb + 4 * mNc; + mNumberOfTriangles = 5 * mNa + 4 * mNb + 2 * mNc; + + mV2Cos = Ogre::Vector2(Ogre::Math::Cos(mPosition * mPhi), Ogre::Math::Cos((mPosition + 1) * mPhi)); + mV2Sin = Ogre::Vector2(Ogre::Math::Sin(mPosition * mPhi), Ogre::Math::Sin((mPosition + 1) * mPhi)); + + mBetaSin = Ogre::Math::Sin(Ogre::Math::PI - mBeta.valueRadians()); + mAlphaSin = Ogre::Math::Sin(Ogre::Math::PI - mAlpha.valueRadians()); + } + + void GeometryBlock::_createGeometry() + { + // Vertex buffers + mSubMesh->vertexData = new Ogre::VertexData(); + mSubMesh->vertexData->vertexStart = 0; + mSubMesh->vertexData->vertexCount = mVertexCount; + + Ogre::VertexDeclaration * vdecl = mSubMesh->vertexData->vertexDeclaration; + Ogre::VertexBufferBinding *vbind = mSubMesh->vertexData->vertexBufferBinding; + + size_t offset = 0; + // Position + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + // 3D coords + vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES, 0); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); + // Noise coords + vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); + // Opacity + vdecl->addElement(0, offset, Ogre::VET_FLOAT1, Ogre::VES_TEXTURE_COORDINATES, 2); + + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + sizeof(VERTEX), mVertexCount, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + + vbind->setBinding(0, mVertexBuffer); + + unsigned short *indexbuffer = new unsigned short[mNumberOfTriangles * 3]; + + int IndexOffset = 0; + int VertexOffset = 0; + + // C + for (int k = 0; k < mNc; k++) + { + // First triangle + indexbuffer[IndexOffset] = VertexOffset; + indexbuffer[IndexOffset + 1] = VertexOffset + 1; + indexbuffer[IndexOffset + 2] = VertexOffset + 3; + + // Second triangle + indexbuffer[IndexOffset + 3] = VertexOffset; + indexbuffer[IndexOffset + 4] = VertexOffset + 3; + indexbuffer[IndexOffset + 5] = VertexOffset + 2; + + IndexOffset += 6; + VertexOffset += 4; + } + + // B + for (int k = 0; k < mNb; k++) + { + // First triangle + indexbuffer[IndexOffset] = VertexOffset; + indexbuffer[IndexOffset + 1] = VertexOffset + 1; + indexbuffer[IndexOffset + 2] = VertexOffset + 3; + + // Second triangle + indexbuffer[IndexOffset + 3] = VertexOffset; + indexbuffer[IndexOffset + 4] = VertexOffset + 3; + indexbuffer[IndexOffset + 5] = VertexOffset + 2; + + // Third triangle + indexbuffer[IndexOffset + 6] = VertexOffset + 2; + indexbuffer[IndexOffset + 7] = VertexOffset + 3; + indexbuffer[IndexOffset + 8] = VertexOffset + 5; + + // Fourth triangle + indexbuffer[IndexOffset + 9] = VertexOffset + 2; + indexbuffer[IndexOffset + 10] = VertexOffset + 5; + indexbuffer[IndexOffset + 11] = VertexOffset + 4; + + IndexOffset += 12; + VertexOffset += 6; + } + + // A + for (int k = 0; k < mNa; k++) + { + // First triangle + indexbuffer[IndexOffset] = VertexOffset; + indexbuffer[IndexOffset + 1] = VertexOffset + 1; + indexbuffer[IndexOffset + 2] = VertexOffset + 3; + + // Second triangle + indexbuffer[IndexOffset + 3] = VertexOffset; + indexbuffer[IndexOffset + 4] = VertexOffset + 3; + indexbuffer[IndexOffset + 5] = VertexOffset + 2; + + // Third triangle + indexbuffer[IndexOffset + 6] = VertexOffset + 2; + indexbuffer[IndexOffset + 7] = VertexOffset + 3; + indexbuffer[IndexOffset + 8] = VertexOffset + 5; + + // Fourth triangle + indexbuffer[IndexOffset + 9] = VertexOffset + 2; + indexbuffer[IndexOffset + 10] = VertexOffset + 5; + indexbuffer[IndexOffset + 11] = VertexOffset + 4; + + // Fifth triangle + indexbuffer[IndexOffset + 12] = VertexOffset + 4; + indexbuffer[IndexOffset + 13] = VertexOffset + 5; + indexbuffer[IndexOffset + 14] = VertexOffset + 6; + + IndexOffset += 15; + VertexOffset += 7; + } + + // Prepare buffer for indices + mIndexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( + Ogre::HardwareIndexBuffer::IT_16BIT, mNumberOfTriangles * 3, Ogre::HardwareBuffer::HBU_STATIC, true); + + mIndexBuffer->writeData(0, mIndexBuffer->getSizeInBytes(), indexbuffer, true); + + delete[] indexbuffer; + + // Set index buffer for this submesh + mSubMesh->indexData->indexBuffer = mIndexBuffer; + mSubMesh->indexData->indexStart = 0; + mSubMesh->indexData->indexCount = mNumberOfTriangles * 3; + + // Create our internal buffer for manipulations + mVertices = new VERTEX[mVertexCount]; + } + + void GeometryBlock::updateGeometry(Ogre::Camera *c, const Ogre::Vector3 &displacement, const Ogre::Vector3 &distance) + { + if (!mCreated) { return; } + + mDisplacement = displacement; + + float fallingDistance = mVClouds->getDistanceFallingParams().x * + (mEntity->getParentSceneNode()->_getDerivedPosition().y - c->getDerivedPosition().y); + + if (mVClouds->getDistanceFallingParams().y > 0) // -1 means no max falling + { + if (fallingDistance > 0) + { + if (fallingDistance > mVClouds->getDistanceFallingParams().y) + { fallingDistance = mVClouds->getDistanceFallingParams().y; } + } + else + { + if (-fallingDistance > mVClouds->getDistanceFallingParams().y) + { fallingDistance = -mVClouds->getDistanceFallingParams().y; } + } + } + + if (fallingDistance != mLastFallingDistance) + { + mLastFallingDistance = fallingDistance; + mMesh->_setBounds(_buildAABox(mLastFallingDistance)); + } + + if (isInFrustum(c)) + { + mCamera = c; + mDistance = distance; + _updateGeometry(); + } + } + + void GeometryBlock::_updateGeometry() + { + // Update zone C + for (int k = 0; k < mNc; k++) + { + _updateZoneCSlice(k); + } + + // Update zone B + for (int k = 0; k < mNb; k++) + { + _updateZoneBSlice(k); + } + + // Update zone A + for (int k = 0; k < mNa; k++) + { + _updateZoneASlice(k); + } + + // Upload changes + mVertexBuffer->writeData(0, mVertexBuffer->getSizeInBytes(), mVertices, true); + } + + void GeometryBlock::_updateZoneCSlice(const int &n) + { + int VertexOffset = n * 4; + + // TODO, calculate constants by zone, not by slice + float Radius = mB + ((mC - mB) / mNc) * (mNc - n); + + Radius += mDisplacement.z; + + float opacity = 1; + + if (n == 0) { opacity = 1 - mDisplacement.z / ((mC - mB) / mNc); } + else if (n == mNc - 1) + { + opacity = mDisplacement.z / ((mC - mB) / mNc); + } + + Ogre::Vector2 x1 = Radius * mV2Cos, x2 = Radius * mBetaSin * mV2Cos, z1 = Radius * mV2Sin, + z2 = Radius * mBetaSin * mV2Sin; + + Ogre::Vector3 or0 = Ogre::Vector3(x1.x, 0, z1.x), or1 = Ogre::Vector3(x1.y, 0, z1.y); + + float y0 = Radius * Ogre::Math::Sin(mAlpha), d = Ogre::Vector2(x1.x - x2.x, z1.x - z2.x).length(), + ang = Ogre::Math::ATan(y0 / d).valueRadians(), hip = mHeight / Ogre::Math::Sin(ang); + + // Vertex 0 + _setVertexData(VertexOffset, or0, opacity); + // Vertex 1 + _setVertexData(VertexOffset + 1, or1, opacity); + // Vertex 2 + _setVertexData(VertexOffset + 2, or0 + (Ogre::Vector3(x2.x, y0, z2.x) - or0).normalisedCopy() * hip, opacity); + // Vertex 3 + _setVertexData(VertexOffset + 3, or1 + (Ogre::Vector3(x2.y, y0, z2.y) - or1).normalisedCopy() * hip, opacity); + } + + void GeometryBlock::_updateZoneBSlice(const int &n) + { + int VertexOffset = mNc * 4 + n * 6; + + // TODO + float Radius = mA + ((mB - mA) / mNb) * (mNb - n); + + Radius += mDisplacement.y; + + float opacity = 1; + + if (n == 0) { opacity = 1 - mDisplacement.y / ((mB - mA) / mNb); } + else if (n == mNb - 1) + { + opacity = mDisplacement.y / ((mB - mA) / mNb); + } + + Ogre::Vector2 x1 = Radius * mV2Cos, x2 = Radius * mBetaSin * mV2Cos, z1 = Radius * mV2Sin, + z2 = Radius * mBetaSin * mV2Sin; + + float y0 = Radius * Ogre::Math::Sin(mAlpha); + + // Vertex 0 + _setVertexData(VertexOffset, Ogre::Vector3(x1.x, 0, z1.x), opacity); + // Vertex 1 + _setVertexData(VertexOffset + 1, Ogre::Vector3(x1.y, 0, z1.y), opacity); + // Vertex 2 + _setVertexData(VertexOffset + 2, Ogre::Vector3(x2.x, y0, z2.x), opacity); + // Vertex 3 + _setVertexData(VertexOffset + 3, Ogre::Vector3(x2.y, y0, z2.y), opacity); + + Ogre::Vector2 x3 = Radius * mAlphaSin * mV2Cos, z3 = Radius * mAlphaSin * mV2Sin; + + Ogre::Vector3 or0 = Ogre::Vector3(x2.x, y0, z2.x), or1 = Ogre::Vector3(x2.y, y0, z2.y); + + float y1 = Radius * Ogre::Math::Sin(mBeta), y3 = y1 - y0, d = Ogre::Vector2(x3.x - x2.x, z3.x - z2.x).length(), + ang = Ogre::Math::ATan(y3 / d).valueRadians(), hip = (mHeight - y0) / Ogre::Math::Sin(ang); + + // Vertex 4 + _setVertexData(VertexOffset + 4, or0 + (Ogre::Vector3(x3.x, y1, z3.x) - or0).normalisedCopy() * hip, opacity); + // Vertex 5 + _setVertexData(VertexOffset + 5, or1 + (Ogre::Vector3(x3.y, y1, z3.y) - or1).normalisedCopy() * hip, opacity); + } + + void GeometryBlock::_updateZoneASlice(const int &n) + { + int VertexOffset = mNc * 4 + mNb * 6 + n * 7; + + // TODO + float Radius = (mA / mNa) * (mNa - n); + + Radius += mDisplacement.x; + + float opacity = (n == 0) ? (1 - mDisplacement.x / (mA / mNa)) : 1.0f; + + Ogre::Vector2 x1 = Radius * mV2Cos, x2 = Radius * mBetaSin * mV2Cos, z1 = Radius * mV2Sin, + z2 = Radius * mBetaSin * mV2Sin; + + float y0 = Radius * Ogre::Math::Sin(mAlpha); + + // Vertex 0 + _setVertexData(VertexOffset, Ogre::Vector3(x1.x, 0, z1.x), opacity); + // Vertex 1 + _setVertexData(VertexOffset + 1, Ogre::Vector3(x1.y, 0, z1.y), opacity); + // Vertex 2 + _setVertexData(VertexOffset + 2, Ogre::Vector3(x2.x, y0, z2.x), opacity); + // Vertex 3 + _setVertexData(VertexOffset + 3, Ogre::Vector3(x2.y, y0, z2.y), opacity); + + Ogre::Vector2 x3 = Radius * mAlphaSin * mV2Cos, z3 = Radius * mAlphaSin * mV2Sin; + + float y1 = Radius * Ogre::Math::Sin(mBeta); + + // Vertex 4 + _setVertexData(VertexOffset + 4, Ogre::Vector3(x3.x, y1, z3.x), opacity); + // Vertex 5 + _setVertexData(VertexOffset + 5, Ogre::Vector3(x3.y, y1, z3.y), opacity); + + // Vertex 6 + _setVertexData(VertexOffset + 6, Ogre::Vector3(0, Radius, 0), opacity); + } + + void GeometryBlock::_setVertexData(const int &index, const Ogre::Vector3 &p, const float &o) + { + float yDist = -mDistance.y; + float fallingDistance = mVClouds->getDistanceFallingParams().x * yDist * (Ogre::Vector2(p.x, p.z).length() / mRadius); + + if (mVClouds->getDistanceFallingParams().y > 0) // -1 means no max falling + { + if (fallingDistance > 0) + { + if (fallingDistance > mVClouds->getDistanceFallingParams().y) + { fallingDistance = mVClouds->getDistanceFallingParams().y; } + } + else + { + if (-fallingDistance > mVClouds->getDistanceFallingParams().y) + { fallingDistance = -mVClouds->getDistanceFallingParams().y; } + } + } + + fallingDistance *= Ogre::Math::Sign(yDist); + + // Position + mVertices[index].x = p.x; + if (yDist < -mHeight / 2) + { + // Over-cloud + mVertices[index].y = mHeight - p.y; + } + else // Under-cloud + { + mVertices[index].y = p.y - fallingDistance; + } + mVertices[index].z = p.z; + + // 3D coords (Z-UP) + float scale = mVClouds->getCloudFieldScale() / mRadius; + mVertices[index].xc = (p.x + mWorldOffset.x) * scale; + mVertices[index].yc = (p.z + mWorldOffset.y) * scale; + mVertices[index].zc = Ogre::Math::Clamp(p.y / mHeight, 0, 1); + if (yDist < -mHeight / 2) + { + // Over-cloud + mVertices[index].zc = 1.0f - mVertices[index].zc; + } + + // Noise coords + float noise_scale = mVClouds->getNoiseScale() / mRadius; + float xz_length_radius = Ogre::Vector2(p.x, p.z).length() / mRadius; + Ogre::Vector3 origin = + Ogre::Vector3(0, + -(mEntity->getParentSceneNode()->_getDerivedPosition().y - mCamera->getDerivedPosition().y) - + mRadius * (0.5f + 0.5f * Ogre::Vector2(p.x, p.z).length() / mRadius), + 0); + Ogre::Vector3 dir = (p - origin).normalisedCopy(); + float hip = Ogre::Math::Sqrt(Ogre::Math::Pow(xz_length_radius * mRadius, 2) + Ogre::Math::Pow(origin.y, 2)); + Ogre::Vector3 uv = dir * hip; // Only x/z, += origin doesn't need + mVertices[index].u = (uv.x + mWorldOffset.x) * noise_scale; + mVertices[index].v = (uv.z + mWorldOffset.y) * noise_scale; + + // Opacity + float dist = (mDistance - Ogre::Vector3(p.x, p.y - fallingDistance, p.z)).length(); + float att = Ogre::Math::Clamp((dist - mA / 3.25f) / (mA / 3.25f), 0.0f, 1.0f); + mVertices[index].o = o * att * mVClouds->getGlobalOpacity(); + } + + const bool GeometryBlock::isInFrustum(Ogre::Camera *c) const + { + if (!mCreated) { return false; } + + // TODO: Use a world bounding box for each geometry zone, this way the + // culling is going to be more acurrated and the geometry falling is going to be culled + // when the falling factor is bigger than 1. + return c->isVisible(mEntity->getParentSceneNode()->_getWorldAABB()); + } + } // namespace VClouds +} \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/GeometryBlock.h b/source/main/gfx/skyx/VClouds/GeometryBlock.h index 9b9523f506..917df97bf0 100644 --- a/source/main/gfx/skyx/VClouds/GeometryBlock.h +++ b/source/main/gfx/skyx/VClouds/GeometryBlock.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -26,230 +26,231 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class VClouds; - - class GeometryBlock - { - public: - /** Vertex struct - */ - struct VERTEX - { // Position - float x,y,z, - // 3D Coords - xc, yc, zc, - // Noise coords - u, v, - // Opacity - o; - }; - - /** Constructor - @param vc VClouds pointer - @param Height Field height (in woorld coordinates) - @param Alpha Alpha angle - @param Beta Beta angle - @param Radius Total radius - @param Phi Actimutal angle - @param Na Number of slices in A zone - @param Nb Number of slices in B zone - @param Nc Number of slices in C zone - @param A A radius - @param B B radius - @param C C radius - */ - GeometryBlock(VClouds *vc, - const float& Height, const Ogre::Radian& Alpha, const Ogre::Radian& Beta, - const float& Radius, const Ogre::Radian& Phi, const int& Na, - const int& Nb, const int& Nc, const int& A, - const int& B, const int& C, const int& Position); - - /** Destructor - */ - ~GeometryBlock(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Update geometry - @param c Camera - @param displacement Current offset in world units per zone - @param distance Current camera to cloud field distance - */ - void updateGeometry(Ogre::Camera* c, const Ogre::Vector3& displacement, const Ogre::Vector3& distance); - - /** Has been create() already called? - @return true if created() have been already called, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Get mesh - @return Mesh - */ - inline Ogre::MeshPtr getMesh() - { - return mMesh; - } - - /** Get sub mesh - @return Sub mesh - */ - inline Ogre::SubMesh* getSubMesh() - { - return mSubMesh; - } +namespace SkyX +{ + namespace VClouds + { - /** Get entity - @return Entity - */ - inline Ogre::Entity* getEntity() - { - return mEntity; - } + class VClouds; - /** Get hardware vertex buffer reference - @return Ogre::HardwareVertexBufferSharedPtr reference - */ - inline Ogre::HardwareVertexBufferSharedPtr &getHardwareVertexBuffer() + class GeometryBlock { - return mVertexBuffer; - } - - /** Get hardware index buffer reference - @return Ogre::HardwareIndexBufferSharedPtr reference - */ - inline Ogre::HardwareIndexBufferSharedPtr &getHardwareIndexBuffer() - { - return mIndexBuffer; - } - - /** Set world offset - @param WorldOffset World offset - */ - inline void setWorldOffset(const Ogre::Vector2& WorldOffset) - { - mWorldOffset = WorldOffset; - } - - /** Is the geometry block inside the camera frustum? - @param c Camera - @return true if yes, false if not - */ - const bool isInFrustum(Ogre::Camera *c) const; - - private: - /** Build axis aligned box - @param fd Falling distance (Positive values for falling geometry, negative for reverse falling geometry) - */ - const Ogre::AxisAlignedBox _buildAABox(const float& fd) const; - - /** Calculate data size - */ - void _calculateDataSize(); - - /** Create geometry - */ - void _createGeometry(); - - /** Update geometry - */ - void _updateGeometry(); - - /** Update zone C slice - @param n Number of slice - */ - void _updateZoneCSlice(const int& n); - - /** Update zone B slice - @param n Number of slice - */ - void _updateZoneBSlice(const int& n); - - /** Update zone A slice - @param n Number of slice - */ - void _updateZoneASlice(const int& n); - - /** Set vertex data - @param index Vertex index - @param o Slice opacity - @param p Position - */ - void _setVertexData(const int& index, const Ogre::Vector3& p, const float& o); - - /// Has been create() already called? - bool mCreated; - - /// Ogre::MeshPtr - Ogre::MeshPtr mMesh; - /// Ogre::Submesh pointer - Ogre::SubMesh *mSubMesh; - /// Ogre::Entity pointer - Ogre::Entity *mEntity; - - /// Vertex buffer - Ogre::HardwareVertexBufferSharedPtr mVertexBuffer; - /// Index buffer - Ogre::HardwareIndexBufferSharedPtr mIndexBuffer; - - /// Vertices pointer - VERTEX *mVertices; - - /// Current number of triangles - int mNumberOfTriangles; - /// Vertex count - int mVertexCount; - - /// Height - float mHeight; - /// Angles - Ogre::Radian mAlpha, mBeta; - /// Radius - float mRadius; - /// Acimutal angle - Ogre::Radian mPhi; - /// Number of slices per geometry zone - int mNa, mNb, mNc; - /// A, B and C radius - float mA, mB, mC; - /// Number of block(Position) - int mPosition; - - /// Precomputed Cos/Sin vectors - Ogre::Vector2 mV2Cos; - Ogre::Vector2 mV2Sin; - /// PI - Beta, PI - Alpha Sin - float mBetaSin; - float mAlphaSin; - - /// Displacement - Ogre::Vector3 mDisplacement; - /// World coords offset - Ogre::Vector2 mWorldOffset; - - /// VClouds pointer - VClouds *mVClouds; - /// Current rendering camera - Ogre::Camera* mCamera; - - /// Current distance - Ogre::Vector3 mDistance; - - /// Last falling distance - float mLastFallingDistance; - }; - - -}} + public: + /** Vertex struct + */ + struct VERTEX + { // Position + float x, y, z, + // 3D Coords + xc, yc, zc, + // Noise coords + u, v, + // Opacity + o; + }; + + /** Constructor + @param vc VClouds pointer + @param Height Field height (in woorld coordinates) + @param Alpha Alpha angle + @param Beta Beta angle + @param Radius Total radius + @param Phi Actimutal angle + @param Na Number of slices in A zone + @param Nb Number of slices in B zone + @param Nc Number of slices in C zone + @param A A radius + @param B B radius + @param C C radius + */ + GeometryBlock(VClouds *vc, const float &Height, const Ogre::Radian &Alpha, const Ogre::Radian &Beta, + const float &Radius, const Ogre::Radian &Phi, const int &Na, const int &Nb, const int &Nc, const int &A, + const int &B, const int &C, const int &Position); + + /** Destructor + */ + ~GeometryBlock(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Update geometry + @param c Camera + @param displacement Current offset in world units per zone + @param distance Current camera to cloud field distance + */ + void updateGeometry(Ogre::Camera *c, const Ogre::Vector3 &displacement, const Ogre::Vector3 &distance); + + /** Has been create() already called? + @return true if created() have been already called, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Get mesh + @return Mesh + */ + inline Ogre::MeshPtr getMesh() + { + return mMesh; + } + + /** Get sub mesh + @return Sub mesh + */ + inline Ogre::SubMesh *getSubMesh() + { + return mSubMesh; + } + + /** Get entity + @return Entity + */ + inline Ogre::Entity *getEntity() + { + return mEntity; + } + + /** Get hardware vertex buffer reference + @return Ogre::HardwareVertexBufferSharedPtr reference + */ + inline Ogre::HardwareVertexBufferSharedPtr &getHardwareVertexBuffer() + { + return mVertexBuffer; + } + + /** Get hardware index buffer reference + @return Ogre::HardwareIndexBufferSharedPtr reference + */ + inline Ogre::HardwareIndexBufferSharedPtr &getHardwareIndexBuffer() + { + return mIndexBuffer; + } + + /** Set world offset + @param WorldOffset World offset + */ + inline void setWorldOffset(const Ogre::Vector2 &WorldOffset) + { + mWorldOffset = WorldOffset; + } + + /** Is the geometry block inside the camera frustum? + @param c Camera + @return true if yes, false if not + */ + const bool isInFrustum(Ogre::Camera *c) const; + + private: + /** Build axis aligned box + @param fd Falling distance (Positive values for falling geometry, negative for reverse falling geometry) + */ + const Ogre::AxisAlignedBox _buildAABox(const float &fd) const; + + /** Calculate data size + */ + void _calculateDataSize(); + + /** Create geometry + */ + void _createGeometry(); + + /** Update geometry + */ + void _updateGeometry(); + + /** Update zone C slice + @param n Number of slice + */ + void _updateZoneCSlice(const int &n); + + /** Update zone B slice + @param n Number of slice + */ + void _updateZoneBSlice(const int &n); + + /** Update zone A slice + @param n Number of slice + */ + void _updateZoneASlice(const int &n); + + /** Set vertex data + @param index Vertex index + @param o Slice opacity + @param p Position + */ + void _setVertexData(const int &index, const Ogre::Vector3 &p, const float &o); + + /// Has been create() already called? + bool mCreated; + + /// Ogre::MeshPtr + Ogre::MeshPtr mMesh; + /// Ogre::Submesh pointer + Ogre::SubMesh *mSubMesh; + /// Ogre::Entity pointer + Ogre::Entity *mEntity; + + /// Vertex buffer + Ogre::HardwareVertexBufferSharedPtr mVertexBuffer; + /// Index buffer + Ogre::HardwareIndexBufferSharedPtr mIndexBuffer; + + /// Vertices pointer + VERTEX *mVertices; + + /// Current number of triangles + int mNumberOfTriangles; + /// Vertex count + int mVertexCount; + + /// Height + float mHeight; + /// Angles + Ogre::Radian mAlpha, mBeta; + /// Radius + float mRadius; + /// Acimutal angle + Ogre::Radian mPhi; + /// Number of slices per geometry zone + int mNa, mNb, mNc; + /// A, B and C radius + float mA, mB, mC; + /// Number of block(Position) + int mPosition; + + /// Precomputed Cos/Sin vectors + Ogre::Vector2 mV2Cos; + Ogre::Vector2 mV2Sin; + /// PI - Beta, PI - Alpha Sin + float mBetaSin; + float mAlphaSin; + + /// Displacement + Ogre::Vector3 mDisplacement; + /// World coords offset + Ogre::Vector2 mWorldOffset; + + /// VClouds pointer + VClouds *mVClouds; + /// Current rendering camera + Ogre::Camera *mCamera; + + /// Current distance + Ogre::Vector3 mDistance; + + /// Last falling distance + float mLastFallingDistance; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/GeometryManager.cpp b/source/main/gfx/skyx/VClouds/GeometryManager.cpp index 0d4fd5c0c7..2570fe5439 100644 --- a/source/main/gfx/skyx/VClouds/GeometryManager.cpp +++ b/source/main/gfx/skyx/VClouds/GeometryManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -25,180 +25,171 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "VClouds.h" -namespace SkyX { namespace VClouds +namespace SkyX { - - GeometryManager::GeometryManager(VClouds* vc) - : mVClouds(vc) - , mCreated(false) - , mHeight(Ogre::Vector2()) - , mRadius(0) - , mAlpha(0) - , mBeta(0) - , mPhi(0) - , mNumberOfBlocks(0) - , mNa(0), mNb(0), mNc(0) - , mA(0), mB(0), mC(0) - , mWorldOffset(Ogre::Vector2(0,0)) - , mCurrentDistance(Ogre::Vector3(0,0,0)) - { - } - - GeometryManager::~GeometryManager() - { - remove(); - } - - void GeometryManager::create(const Ogre::Vector2& Height, const float& Radius, - const Ogre::Radian& Alpha, const Ogre::Radian& Beta, - const int& NumberOfBlocks, const int& Na, const int& Nb, const int& Nc) - { - remove(); - - mHeight = Height; - mRadius = Radius; - mAlpha = Alpha; - mBeta = Beta; - mPhi = Ogre::Math::TWO_PI / NumberOfBlocks; - mNumberOfBlocks = NumberOfBlocks; - mNa = Na; mNb = Nb; mNc = Nc; - - mSceneNode = mVClouds->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - _createGeometry(); - - mCreated = true; - } - - void GeometryManager::remove() - { - if (!mCreated) - { - return; - } - - mSceneNode->detachAllObjects(); - mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); - mSceneNode = 0; - - for (int k = 0; k < mNumberOfBlocks; k++) - { - delete mGeometryBlocks.at(k); - mGeometryBlocks.at(k) = 0; - } - - mGeometryBlocks.clear(); - - mCreated = false; - } - - void GeometryManager::update(const Ogre::Real& timeSinceLastFrame) - { - if (!mCreated) - { - return; - } - - mWorldOffset += mVClouds->getWindDirectionV2() * mVClouds->getWindSpeed() * timeSinceLastFrame; - } - - void GeometryManager::updateGeometry(Ogre::Camera* c, const Ogre::Real& timeSinceLastCameraFrame) - { - if (!mCreated) - { - return; - } - - mSceneNode->setPosition(mVClouds->getCamera()->getDerivedPosition().x, mHeight.x, mVClouds->getCamera()->getDerivedPosition().z); - mSceneNode->_update(false, false); - - _updateGeometry(c, timeSinceLastCameraFrame); - } - - void GeometryManager::_setMaterialName(const Ogre::String& mn) - { - for(Ogre::uint32 k = 0; k < mGeometryBlocks.size(); k++) - { - mGeometryBlocks.at(k)->getEntity()->setMaterialName(mn); - } - } - - void GeometryManager::_updateRenderQueueGroup(const Ogre::uint8& rqg) - { - for(Ogre::uint32 k = 0; k < mGeometryBlocks.size(); k++) - { - mGeometryBlocks.at(k)->getEntity()->setRenderQueueGroup(rqg); - } - } - - void GeometryManager::_createGeometry() - { - mA = mHeight.y / Ogre::Math::Cos(Ogre::Math::PI/2-mBeta.valueRadians()); - mB = mHeight.y / Ogre::Math::Cos(Ogre::Math::PI/2-mAlpha.valueRadians()); - mC = mRadius; - - for (int k = 0; k < mNumberOfBlocks; k++) - { - mGeometryBlocks.push_back(new GeometryBlock(mVClouds, mHeight.y, mAlpha, mBeta, mRadius, mPhi, mNa, mNb, mNc, mA, mB, mC, k)); - mGeometryBlocks.at(k)->create(); - // Each geometry block must be in a different scene node, See: GeometryBlock::isInFrustum(Ogre::Camera *c) - Ogre::SceneNode *sn = mSceneNode->createChildSceneNode(); - sn->attachObject(mGeometryBlocks.at(k)->getEntity()); - } - } - - void GeometryManager::_updateGeometry(Ogre::Camera* c, const Ogre::Real& timeSinceLastFrame) - { - // Look for current camera data - std::vector& camerasData = mVClouds->_getCamerasData(); - std::vector::iterator currentCameraDataIt; - - for (currentCameraDataIt = camerasData.begin(); currentCameraDataIt != camerasData.end(); currentCameraDataIt++) - { - if ((*currentCameraDataIt).camera == c) - { - break; - } - } - - std::vector::reference currentCameraData = (*currentCameraDataIt); - - // Calculate wind offset - Ogre::Vector2 CameraDirection = Ogre::Vector2(c->getDerivedDirection().x, c->getDerivedDirection().z); - float offset = - CameraDirection.dotProduct(mVClouds->getWindDirectionV2()) * mVClouds->getWindSpeed() * timeSinceLastFrame; - - // Calculate camera offset - Ogre::Vector2 CameraOffset = Ogre::Vector2(c->getDerivedPosition().x - currentCameraData.lastPosition.x, c->getDerivedPosition().z - currentCameraData.lastPosition.z); - offset -= CameraOffset.dotProduct(CameraDirection); - - // Update camera data - currentCameraData.cameraOffset += CameraOffset; - currentCameraData.lastPosition = c->getDerivedPosition(); - - // Update geometry displacement - currentCameraData.geometryDisplacement += Ogre::Vector3(offset); - - if (currentCameraData.geometryDisplacement.z < 0 || currentCameraData.geometryDisplacement.z > (mC-mB)/mNc) - { - currentCameraData.geometryDisplacement.z -= ((mC-mB)/mNc)*Ogre::Math::IFloor((currentCameraData.geometryDisplacement.z)/((mC-mB)/mNc)); - } - - if (currentCameraData.geometryDisplacement.y < 0 || currentCameraData.geometryDisplacement.y > (mB-mA)/mNb) - { - currentCameraData.geometryDisplacement.y -= ((mB-mA)/mNb)*Ogre::Math::IFloor((currentCameraData.geometryDisplacement.y)/((mB-mA)/mNb)); - } - - if (currentCameraData.geometryDisplacement.x < 0 || currentCameraData.geometryDisplacement.x > mA/mNa) - { - currentCameraData.geometryDisplacement.x -= (mA/mNa)*Ogre::Math::IFloor((currentCameraData.geometryDisplacement.x)/(mA/mNa)); - } - - // Check under/over cloud rendering - mCurrentDistance = c->getDerivedPosition()-mSceneNode->_getDerivedPosition(); - - for (int k = 0; k < mNumberOfBlocks; k++) - { - mGeometryBlocks.at(k)->setWorldOffset(mWorldOffset + currentCameraData.cameraOffset); - mGeometryBlocks.at(k)->updateGeometry(c, currentCameraData.geometryDisplacement, mCurrentDistance); - } - } -}} + namespace VClouds + { + + GeometryManager::GeometryManager(VClouds *vc) + : mVClouds(vc), mCreated(false), mHeight(Ogre::Vector2()), mRadius(0), mAlpha(0), mBeta(0), mPhi(0), + mNumberOfBlocks(0), mNa(0), mNb(0), mNc(0), mA(0), mB(0), mC(0), mWorldOffset(Ogre::Vector2(0, 0)), + mCurrentDistance(Ogre::Vector3(0, 0, 0)) + { + } + + GeometryManager::~GeometryManager() + { + remove(); + } + + void GeometryManager::create(const Ogre::Vector2 &Height, const float &Radius, const Ogre::Radian &Alpha, + const Ogre::Radian &Beta, const int &NumberOfBlocks, const int &Na, const int &Nb, + const int &Nc) + { + remove(); + + mHeight = Height; + mRadius = Radius; + mAlpha = Alpha; + mBeta = Beta; + mPhi = Ogre::Math::TWO_PI / NumberOfBlocks; + mNumberOfBlocks = NumberOfBlocks; + mNa = Na; + mNb = Nb; + mNc = Nc; + + mSceneNode = mVClouds->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + _createGeometry(); + + mCreated = true; + } + + void GeometryManager::remove() + { + if (!mCreated) { return; } + + mSceneNode->detachAllObjects(); + mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode); + mSceneNode = 0; + + for (int k = 0; k < mNumberOfBlocks; k++) + { + delete mGeometryBlocks.at(k); + mGeometryBlocks.at(k) = 0; + } + + mGeometryBlocks.clear(); + + mCreated = false; + } + + void GeometryManager::update(const Ogre::Real &timeSinceLastFrame) + { + if (!mCreated) { return; } + + mWorldOffset += mVClouds->getWindDirectionV2() * mVClouds->getWindSpeed() * timeSinceLastFrame; + } + + void GeometryManager::updateGeometry(Ogre::Camera *c, const Ogre::Real &timeSinceLastCameraFrame) + { + if (!mCreated) { return; } + + mSceneNode->setPosition(mVClouds->getCamera()->getDerivedPosition().x, mHeight.x, + mVClouds->getCamera()->getDerivedPosition().z); + mSceneNode->_update(false, false); + + _updateGeometry(c, timeSinceLastCameraFrame); + } + + void GeometryManager::_setMaterialName(const Ogre::String &mn) + { + for (Ogre::uint32 k = 0; k < mGeometryBlocks.size(); k++) + { + mGeometryBlocks.at(k)->getEntity()->setMaterialName(mn); + } + } + + void GeometryManager::_updateRenderQueueGroup(const Ogre::uint8 &rqg) + { + for (Ogre::uint32 k = 0; k < mGeometryBlocks.size(); k++) + { + mGeometryBlocks.at(k)->getEntity()->setRenderQueueGroup(rqg); + } + } + + void GeometryManager::_createGeometry() + { + mA = mHeight.y / Ogre::Math::Cos(Ogre::Math::PI / 2 - mBeta.valueRadians()); + mB = mHeight.y / Ogre::Math::Cos(Ogre::Math::PI / 2 - mAlpha.valueRadians()); + mC = mRadius; + + for (int k = 0; k < mNumberOfBlocks; k++) + { + mGeometryBlocks.push_back( + new GeometryBlock(mVClouds, mHeight.y, mAlpha, mBeta, mRadius, mPhi, mNa, mNb, mNc, mA, mB, mC, k)); + mGeometryBlocks.at(k)->create(); + // Each geometry block must be in a different scene node, See: GeometryBlock::isInFrustum(Ogre::Camera *c) + Ogre::SceneNode *sn = mSceneNode->createChildSceneNode(); + sn->attachObject(mGeometryBlocks.at(k)->getEntity()); + } + } + + void GeometryManager::_updateGeometry(Ogre::Camera *c, const Ogre::Real &timeSinceLastFrame) + { + // Look for current camera data + std::vector & camerasData = mVClouds->_getCamerasData(); + std::vector::iterator currentCameraDataIt; + + for (currentCameraDataIt = camerasData.begin(); currentCameraDataIt != camerasData.end(); currentCameraDataIt++) + { + if ((*currentCameraDataIt).camera == c) { break; } + } + + std::vector::reference currentCameraData = (*currentCameraDataIt); + + // Calculate wind offset + Ogre::Vector2 CameraDirection = Ogre::Vector2(c->getDerivedDirection().x, c->getDerivedDirection().z); + float offset = + -CameraDirection.dotProduct(mVClouds->getWindDirectionV2()) * mVClouds->getWindSpeed() * timeSinceLastFrame; + + // Calculate camera offset + Ogre::Vector2 CameraOffset = Ogre::Vector2(c->getDerivedPosition().x - currentCameraData.lastPosition.x, + c->getDerivedPosition().z - currentCameraData.lastPosition.z); + offset -= CameraOffset.dotProduct(CameraDirection); + + // Update camera data + currentCameraData.cameraOffset += CameraOffset; + currentCameraData.lastPosition = c->getDerivedPosition(); + + // Update geometry displacement + currentCameraData.geometryDisplacement += Ogre::Vector3(offset); + + if (currentCameraData.geometryDisplacement.z < 0 || currentCameraData.geometryDisplacement.z > (mC - mB) / mNc) + { + currentCameraData.geometryDisplacement.z -= + ((mC - mB) / mNc) * Ogre::Math::IFloor((currentCameraData.geometryDisplacement.z) / ((mC - mB) / mNc)); + } + + if (currentCameraData.geometryDisplacement.y < 0 || currentCameraData.geometryDisplacement.y > (mB - mA) / mNb) + { + currentCameraData.geometryDisplacement.y -= + ((mB - mA) / mNb) * Ogre::Math::IFloor((currentCameraData.geometryDisplacement.y) / ((mB - mA) / mNb)); + } + + if (currentCameraData.geometryDisplacement.x < 0 || currentCameraData.geometryDisplacement.x > mA / mNa) + { + currentCameraData.geometryDisplacement.x -= + (mA / mNa) * Ogre::Math::IFloor((currentCameraData.geometryDisplacement.x) / (mA / mNa)); + } + + // Check under/over cloud rendering + mCurrentDistance = c->getDerivedPosition() - mSceneNode->_getDerivedPosition(); + + for (int k = 0; k < mNumberOfBlocks; k++) + { + mGeometryBlocks.at(k)->setWorldOffset(mWorldOffset + currentCameraData.cameraOffset); + mGeometryBlocks.at(k)->updateGeometry(c, currentCameraData.geometryDisplacement, mCurrentDistance); + } + } + } // namespace VClouds +} // namespace SkyX diff --git a/source/main/gfx/skyx/VClouds/GeometryManager.h b/source/main/gfx/skyx/VClouds/GeometryManager.h index 65a8ffa3db..0c84051b6b 100644 --- a/source/main/gfx/skyx/VClouds/GeometryManager.h +++ b/source/main/gfx/skyx/VClouds/GeometryManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,146 +24,147 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_VClouds_GeometryManager_H_ #define _SkyX_VClouds_GeometryManager_H_ -#include "Prerequisites.h" - #include "GeometryBlock.h" +#include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class VClouds; - - class GeometryManager - { - public: - /** Constructor - @param vc VClouds pointer - */ - GeometryManager(VClouds* vc); - - /** Destructor - */ - ~GeometryManager(); - - /** Create - @param Height x = Field altitude, y: Field height (both in world coordinates) - @param Radius Radius - @param Alpha Alpha angle - @param Beta Beta angle - @param NumberOfBlocks Number of geometry blocks - @param Na Number of slices in A zone - @param Nb Number of slices in B zone - @param Nc Number of slices in C zone - */ - void create(const Ogre::Vector2& Height, const float& Radius, - const Ogre::Radian& Alpha, const Ogre::Radian& Beta, - const int& NumberOfBlocks, const int& Na, const int& Nb, const int& Nc); - - /** Remove - */ - void remove(); - - /** Update, to be invoked per frame - @param timeSinceLastFrame Time since last frame - */ - void update(const Ogre::Real& timeSinceLastFrame); - - /** Update geoemtry - @param c Camera - @param timeSinceLastCameraFrame Time since last CAMERA frame - */ - void updateGeometry(Ogre::Camera* c, const Ogre::Real& timeSinceLastCameraFrame); - - /** Has been create() already called? - @return true if created() have been already called, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Get scene node - @return Scene node - */ - inline Ogre::SceneNode* getSceneNode() - { - return mSceneNode; - } - - /** Get height (x = Altitude over the camera, y: Field height (both in world coordinates)) - @return Height (x = Altitude over the camera, y: Field height (both in world coordinates)) - */ - inline const Ogre::Vector2 getHeight() const - { - return mHeight; - } - - /** Set material name - @param mn Material name - @remarks Only for internal use - */ - void _setMaterialName(const Ogre::String& mn); - - /** Update render queue group - @param rqg Render queue group - @remarks Only for internal use. Use VClouds::setRenderQueueGroups(...) instead. - */ - void _updateRenderQueueGroup(const Ogre::uint8& rqg); - - /** Get current camera to cloud field distance - @return Current camera to cloud field distance - @remarks Only for internal use - */ - inline const Ogre::Vector3 _getCurrentDistance() const - { - return mCurrentDistance; - } - - private: - /** Create geometry - */ - void _createGeometry(); - - /** Update geometry - @param c Camera - @param timeSinceLastFrame Time since last frame - */ - void _updateGeometry(Ogre::Camera* c, const Ogre::Real& timeSinceLastFrame); - - /// Has been create() already called? - bool mCreated; - - /// Height: x = Altitude over the camera, y: Field height (both in world coordinates) - Ogre::Vector2 mHeight; - /// Angles - Ogre::Radian mAlpha, mBeta; - /// Radius - float mRadius; - /// Azimutal angle per block - Ogre::Radian mPhi; - /// Number of blocks - int mNumberOfBlocks; - /// Number of slices per geometry zone - int mNa, mNb, mNc; - /// A, B and C radius - float mA, mB, mC; - - /// World coords offset - Ogre::Vector2 mWorldOffset; - - /// Geometry blocks - std::vector mGeometryBlocks; - - /// Scene node - Ogre::SceneNode *mSceneNode; - - /// Current camera-clouds distance - Ogre::Vector3 mCurrentDistance; - - /// VClouds pointer - VClouds *mVClouds; - }; - - -}} +namespace SkyX +{ + namespace VClouds + { + + class VClouds; + + class GeometryManager + { + public: + /** Constructor + @param vc VClouds pointer + */ + GeometryManager(VClouds *vc); + + /** Destructor + */ + ~GeometryManager(); + + /** Create + @param Height x = Field altitude, y: Field height (both in world coordinates) + @param Radius Radius + @param Alpha Alpha angle + @param Beta Beta angle + @param NumberOfBlocks Number of geometry blocks + @param Na Number of slices in A zone + @param Nb Number of slices in B zone + @param Nc Number of slices in C zone + */ + void create(const Ogre::Vector2 &Height, const float &Radius, const Ogre::Radian &Alpha, const Ogre::Radian &Beta, + const int &NumberOfBlocks, const int &Na, const int &Nb, const int &Nc); + + /** Remove + */ + void remove(); + + /** Update, to be invoked per frame + @param timeSinceLastFrame Time since last frame + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Update geoemtry + @param c Camera + @param timeSinceLastCameraFrame Time since last CAMERA frame + */ + void updateGeometry(Ogre::Camera *c, const Ogre::Real &timeSinceLastCameraFrame); + + /** Has been create() already called? + @return true if created() have been already called, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Get scene node + @return Scene node + */ + inline Ogre::SceneNode *getSceneNode() + { + return mSceneNode; + } + + /** Get height (x = Altitude over the camera, y: Field height (both in world coordinates)) + @return Height (x = Altitude over the camera, y: Field height (both in world coordinates)) + */ + inline const Ogre::Vector2 getHeight() const + { + return mHeight; + } + + /** Set material name + @param mn Material name + @remarks Only for internal use + */ + void _setMaterialName(const Ogre::String &mn); + + /** Update render queue group + @param rqg Render queue group + @remarks Only for internal use. Use VClouds::setRenderQueueGroups(...) instead. + */ + void _updateRenderQueueGroup(const Ogre::uint8 &rqg); + + /** Get current camera to cloud field distance + @return Current camera to cloud field distance + @remarks Only for internal use + */ + inline const Ogre::Vector3 _getCurrentDistance() const + { + return mCurrentDistance; + } + + private: + /** Create geometry + */ + void _createGeometry(); + + /** Update geometry + @param c Camera + @param timeSinceLastFrame Time since last frame + */ + void _updateGeometry(Ogre::Camera *c, const Ogre::Real &timeSinceLastFrame); + + /// Has been create() already called? + bool mCreated; + + /// Height: x = Altitude over the camera, y: Field height (both in world coordinates) + Ogre::Vector2 mHeight; + /// Angles + Ogre::Radian mAlpha, mBeta; + /// Radius + float mRadius; + /// Azimutal angle per block + Ogre::Radian mPhi; + /// Number of blocks + int mNumberOfBlocks; + /// Number of slices per geometry zone + int mNa, mNb, mNc; + /// A, B and C radius + float mA, mB, mC; + + /// World coords offset + Ogre::Vector2 mWorldOffset; + + /// Geometry blocks + std::vector mGeometryBlocks; + + /// Scene node + Ogre::SceneNode *mSceneNode; + + /// Current camera-clouds distance + Ogre::Vector3 mCurrentDistance; + + /// VClouds pointer + VClouds *mVClouds; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/Lightning.cpp b/source/main/gfx/skyx/VClouds/Lightning.cpp index 17381577a1..7db7bea03f 100644 --- a/source/main/gfx/skyx/VClouds/Lightning.cpp +++ b/source/main/gfx/skyx/VClouds/Lightning.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -23,250 +23,236 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "Lightning.h" -namespace SkyX { namespace VClouds +namespace SkyX { - Lightning::Lightning(Ogre::SceneManager* sm, Ogre::SceneNode* sn, const Ogre::Vector3& orig, const Ogre::Vector3& dir, - const Ogre::Real& l, const Ogre::uint32& d, const Ogre::uint32& rec, const Ogre::Real& tm, const Ogre::Real& wm, const Ogre::Vector2& b) - : mOrigin(orig) - , mDirection(dir) - , mLength(l) - , mRealLength(0) - , mDivisions(d) - , mRecursivity(rec) - , mTime(0) - , mTimeMultiplier(tm) - , mIntensity(0) - , mWidthMultiplier(wm) - , mBounds(b) - , mAngleRange(Ogre::Vector2(Ogre::Math::RangeRandom(0.3,0.5), Ogre::Math::RangeRandom(0.6,0.8))) - , mTimeMultipliers(Ogre::Vector3(Ogre::Math::RangeRandom(1.75,4.25), Ogre::Math::RangeRandom(0.4,1.25f), Ogre::Math::RangeRandom(0.2,1.0f))) - , mSegments(std::vector()) - , mChildren(std::vector()) - , mBillboardSet(0) - , mSceneManager(sm) - , mSceneNode(sn) - , mCreated(false) - , mFinished(false) - { - } - - Lightning::~Lightning() - { - remove(); - } - - void Lightning::create() - { - remove(); - - Ogre::Vector3 current, last = mOrigin; - - // Create ray segments - for(Ogre::uint32 k = 1; k < mDivisions+1; k++) - { - Ogre::Vector3 current = mOrigin + mDirection*mLength*(static_cast(k)/mDivisions); - - current += (mLength/(mDivisions*3))*Ogre::Vector3( - Ogre::Math::RangeRandom(-1, 1), Ogre::Math::RangeRandom(-1, 1), Ogre::Math::RangeRandom(-1, 1)); - - mSegments.push_back(Segment(last, current)); - - mRealLength += (current-last).length(); - - last = current; - } - - // Create the associated billboard set - mBillboardSet = mSceneManager->createBillboardSet(); - mBillboardSet->setMaterialName("SkyX_Lightning"); - mBillboardSet->setBillboardType(Ogre::BBT_ORIENTED_SELF); - - Ogre::Real width = mWidthMultiplier*3*(static_cast(mRecursivity)/4+1)*Ogre::Math::RangeRandom(0.5f, 2.5f-mRecursivity/3); - - // Create the associated billboard for each segment - Ogre::Real delta; - Ogre::Vector2 bounds; - Ogre::Billboard* bb; - for(Ogre::uint32 k = 0; k < mSegments.size(); k++) - { - delta = 1.0f / mSegments.size(); - bounds = Ogre::Vector2(k*delta,(k+1)*delta); - - bounds = Ogre::Vector2(mBounds.x, mBounds.x) + bounds*(mBounds.y-mBounds.x); - - bb = mBillboardSet->createBillboard((mSegments.at(k).a+mSegments.at(k).b)/2); - bb->setDimensions(width, (mSegments.at(k).a-mSegments.at(k).b).length()); - bb->setColour(Ogre::ColourValue(0,bounds.x,bounds.y)); - bb->mDirection = (mSegments.at(k).a-mSegments.at(k).b).normalisedCopy(); - - bb = mBillboardSet->createBillboard(mSegments.at(k).a + (mSegments.at(k).a-mSegments.at(k).b).normalisedCopy()*width/2); - bb->setDimensions(width, width); - bb->setColour(Ogre::ColourValue(1,bounds.x,bounds.x)); - bb->mDirection = (mSegments.at(k).a-mSegments.at(k).b).normalisedCopy(); - - bb = mBillboardSet->createBillboard(mSegments.at(k).b - (mSegments.at(k).a-mSegments.at(k).b).normalisedCopy()*width/2); - bb->setDimensions(width, width); - bb->setColour(Ogre::ColourValue(1,bounds.y,bounds.y)); - bb->mDirection = -(mSegments.at(k).a-mSegments.at(k).b).normalisedCopy(); - - width *= 1-(1.0f/(mRecursivity*mRecursivity+1.0f))*(1.0f/mSegments.size()); - } - - mBillboardSet->_updateBounds(); - - mSceneNode->attachObject(mBillboardSet); - - mBillboardSet->setCustomParameter(0, Ogre::Vector4(1,0,0,0)); - - // Ramifications - if (mRecursivity > 0) - { - Ogre::Real angle; - Ogre::Vector3 dir; - Ogre::Real lengthMult; - for (Ogre::uint32 k = 0; k < mDivisions-1; k++) - { - angle = (mSegments.at(k).b-mSegments.at(k).a).normalisedCopy().dotProduct( - ((mSegments.at(k+1).b-mSegments.at(k+1).a).normalisedCopy())); - - if (angle < Ogre::Math::RangeRandom(mAngleRange.x, mAngleRange.y)) - { - dir = (mSegments.at(k).b-mSegments.at(k).a).normalisedCopy(); - dir.x *= Ogre::Math::RangeRandom(0.8f, 1.2f); - dir.y *= Ogre::Math::RangeRandom(0.8f, 1.2f); - dir.z *= Ogre::Math::RangeRandom(0.8f, 1.2f); - dir.normalise(); - - delta = 1.0f / mSegments.size(); - bounds = Ogre::Vector2(mBounds.x+(mBounds.y-mBounds.x)*(k+1)*delta,1); - - lengthMult = Ogre::Math::RangeRandom(0.1f, 0.7f); - - Lightning* lightning = new Lightning(mSceneManager, mSceneNode, mSegments.at(k).b, dir, lengthMult*mLength, 2+mDivisions*lengthMult, mRecursivity-1, mTimeMultiplier, mWidthMultiplier, bounds); - lightning->create(); - - mChildren.push_back(lightning); - } - } - } - - mCreated = true; - } - - void Lightning::remove() - { - if (!mCreated) - { - return; - } - - mSceneNode->detachObject(mBillboardSet); - mSceneManager->destroyBillboardSet(mBillboardSet); - - mSegments.clear(); - - for(Ogre::uint32 k = 0; k < mChildren.size(); k++) - { - delete mChildren.at(k); - } - - mChildren.clear(); - - mFinished = false; - - mCreated = false; - } - - void Lightning::update(Ogre::Real timeSinceLastFrame) - { - if (!mCreated) - { - return; - } - - timeSinceLastFrame *= mTimeMultiplier; - - // mTime timeline: (Note: Time multipliers are random) - // 0.0 -> 1.2 : Ray creation(fordward effect) + Big flash - // 1.2 -> 2.0 : Sinus flashing pattern - // 2.0 -> 3.0 Ray fading - - Ogre::Real alpha = 0.5f; - Ogre::Real maxAlpha = 1.5f; - - if (mTime < 1) - { - mTime += timeSinceLastFrame*mTimeMultipliers.x; - - if (mTime > 2) mTime = 1.5f; // Prevent big changes - - if (mTime > 0.8f) // Big flash start - { - alpha += (mTime-0.8f)*(maxAlpha/0.2f); - } - } - else if (mTime > 1 && mTime < 2) - { - mTime += timeSinceLastFrame*mTimeMultipliers.y; - - if (mTime > 3) mTime = 2.5f; // Prevent big changes - - if (mTime < 1.2f) // Big flash end - { - alpha += (0.2f-(mTime-1.0f))*(maxAlpha/0.2f); - } - else // Sinus flashing pattern - { - alpha += Ogre::Math::Abs(Ogre::Math::Sin((mTime-1.2f)*1.5f*mTimeMultipliers.x)); - } - } - else if (mTime > 2) // Ray fading - { - mTime += timeSinceLastFrame*mTimeMultipliers.z; - - if (mTime > 3) - { - mTime = 3; // Prevent big changes - mFinished = true; - } - - alpha += Ogre::Math::Abs(Ogre::Math::Sin((2-1.2f)*1.5f*mTimeMultipliers.x)); - alpha *= 3.0f-mTime; - } - - mIntensity = alpha; - - _updateData(alpha, mTime > 1 ? 1 : mTime, mTime); - } - - void Lightning::_updateRenderQueueGroup(const Ogre::uint8& rqg) - { - mBillboardSet->setRenderQueueGroup(rqg); - - for(Ogre::uint32 k = 0; k < mChildren.size(); k++) - { - mChildren.at(k)->_updateRenderQueueGroup(rqg); - } - } - - void Lightning::_updateData(const Ogre::Real& alpha, const Ogre::Real& currentPos, const Ogre::Real& parentTime) - { - Ogre::Vector4 params = Ogre::Vector4(alpha,currentPos,(3-mRecursivity)*0.075f+(mBounds.x*1.5f+0.2f)*0.85f,0); - - if (parentTime > 1 && parentTime < 2.2f) - { - params.z *= Ogre::Math::Clamp(1.5-parentTime,0.2f,1); - } - else if (parentTime > 2.2f) - { - params.z *= Ogre::Math::Clamp((-2.2f+parentTime)*1.25f,0.2f,1); - } - - mBillboardSet->setCustomParameter(0, params); - - for(Ogre::uint32 k = 0; k < mChildren.size(); k++) - { - mChildren.at(k)->_updateData(alpha*0.75f, currentPos, parentTime); - } - } -}} \ No newline at end of file + namespace VClouds + { + Lightning::Lightning(Ogre::SceneManager *sm, Ogre::SceneNode *sn, const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, + const Ogre::Real &l, const Ogre::uint32 &d, const Ogre::uint32 &rec, const Ogre::Real &tm, + const Ogre::Real &wm, const Ogre::Vector2 &b) + : mOrigin(orig), mDirection(dir), mLength(l), mRealLength(0), mDivisions(d), mRecursivity(rec), mTime(0), + mTimeMultiplier(tm), mIntensity(0), mWidthMultiplier(wm), mBounds(b), + mAngleRange(Ogre::Vector2(Ogre::Math::RangeRandom(0.3, 0.5), Ogre::Math::RangeRandom(0.6, 0.8))), + mTimeMultipliers(Ogre::Vector3(Ogre::Math::RangeRandom(1.75, 4.25), Ogre::Math::RangeRandom(0.4, 1.25f), + Ogre::Math::RangeRandom(0.2, 1.0f))), + mSegments(std::vector()), mChildren(std::vector()), mBillboardSet(0), + mSceneManager(sm), mSceneNode(sn), mCreated(false), mFinished(false) + { + } + + Lightning::~Lightning() + { + remove(); + } + + void Lightning::create() + { + remove(); + + Ogre::Vector3 current, last = mOrigin; + + // Create ray segments + for (Ogre::uint32 k = 1; k < mDivisions + 1; k++) + { + Ogre::Vector3 current = mOrigin + mDirection * mLength * (static_cast(k) / mDivisions); + + current += + (mLength / (mDivisions * 3)) * + Ogre::Vector3(Ogre::Math::RangeRandom(-1, 1), Ogre::Math::RangeRandom(-1, 1), Ogre::Math::RangeRandom(-1, 1)); + + mSegments.push_back(Segment(last, current)); + + mRealLength += (current - last).length(); + + last = current; + } + + // Create the associated billboard set + mBillboardSet = mSceneManager->createBillboardSet(); + mBillboardSet->setMaterialName("SkyX_Lightning"); + mBillboardSet->setBillboardType(Ogre::BBT_ORIENTED_SELF); + + Ogre::Real width = mWidthMultiplier * 3 * (static_cast(mRecursivity) / 4 + 1) * + Ogre::Math::RangeRandom(0.5f, 2.5f - mRecursivity / 3); + + // Create the associated billboard for each segment + Ogre::Real delta; + Ogre::Vector2 bounds; + Ogre::Billboard *bb; + for (Ogre::uint32 k = 0; k < mSegments.size(); k++) + { + delta = 1.0f / mSegments.size(); + bounds = Ogre::Vector2(k * delta, (k + 1) * delta); + + bounds = Ogre::Vector2(mBounds.x, mBounds.x) + bounds * (mBounds.y - mBounds.x); + + bb = mBillboardSet->createBillboard((mSegments.at(k).a + mSegments.at(k).b) / 2); + bb->setDimensions(width, (mSegments.at(k).a - mSegments.at(k).b).length()); + bb->setColour(Ogre::ColourValue(0, bounds.x, bounds.y)); + bb->mDirection = (mSegments.at(k).a - mSegments.at(k).b).normalisedCopy(); + + bb = mBillboardSet->createBillboard(mSegments.at(k).a + + (mSegments.at(k).a - mSegments.at(k).b).normalisedCopy() * width / 2); + bb->setDimensions(width, width); + bb->setColour(Ogre::ColourValue(1, bounds.x, bounds.x)); + bb->mDirection = (mSegments.at(k).a - mSegments.at(k).b).normalisedCopy(); + + bb = mBillboardSet->createBillboard(mSegments.at(k).b - + (mSegments.at(k).a - mSegments.at(k).b).normalisedCopy() * width / 2); + bb->setDimensions(width, width); + bb->setColour(Ogre::ColourValue(1, bounds.y, bounds.y)); + bb->mDirection = -(mSegments.at(k).a - mSegments.at(k).b).normalisedCopy(); + + width *= 1 - (1.0f / (mRecursivity * mRecursivity + 1.0f)) * (1.0f / mSegments.size()); + } + + mBillboardSet->_updateBounds(); + + mSceneNode->attachObject(mBillboardSet); + + mBillboardSet->setCustomParameter(0, Ogre::Vector4(1, 0, 0, 0)); + + // Ramifications + if (mRecursivity > 0) + { + Ogre::Real angle; + Ogre::Vector3 dir; + Ogre::Real lengthMult; + for (Ogre::uint32 k = 0; k < mDivisions - 1; k++) + { + angle = (mSegments.at(k).b - mSegments.at(k).a) + .normalisedCopy() + .dotProduct(((mSegments.at(k + 1).b - mSegments.at(k + 1).a).normalisedCopy())); + + if (angle < Ogre::Math::RangeRandom(mAngleRange.x, mAngleRange.y)) + { + dir = (mSegments.at(k).b - mSegments.at(k).a).normalisedCopy(); + dir.x *= Ogre::Math::RangeRandom(0.8f, 1.2f); + dir.y *= Ogre::Math::RangeRandom(0.8f, 1.2f); + dir.z *= Ogre::Math::RangeRandom(0.8f, 1.2f); + dir.normalise(); + + delta = 1.0f / mSegments.size(); + bounds = Ogre::Vector2(mBounds.x + (mBounds.y - mBounds.x) * (k + 1) * delta, 1); + + lengthMult = Ogre::Math::RangeRandom(0.1f, 0.7f); + + Lightning *lightning = new Lightning(mSceneManager, mSceneNode, mSegments.at(k).b, dir, + lengthMult * mLength, 2 + mDivisions * lengthMult, mRecursivity - 1, + mTimeMultiplier, mWidthMultiplier, bounds); + lightning->create(); + + mChildren.push_back(lightning); + } + } + } + + mCreated = true; + } + + void Lightning::remove() + { + if (!mCreated) { return; } + + mSceneNode->detachObject(mBillboardSet); + mSceneManager->destroyBillboardSet(mBillboardSet); + + mSegments.clear(); + + for (Ogre::uint32 k = 0; k < mChildren.size(); k++) + { + delete mChildren.at(k); + } + + mChildren.clear(); + + mFinished = false; + + mCreated = false; + } + + void Lightning::update(Ogre::Real timeSinceLastFrame) + { + if (!mCreated) { return; } + + timeSinceLastFrame *= mTimeMultiplier; + + // mTime timeline: (Note: Time multipliers are random) + // 0.0 -> 1.2 : Ray creation(fordward effect) + Big flash + // 1.2 -> 2.0 : Sinus flashing pattern + // 2.0 -> 3.0 Ray fading + + Ogre::Real alpha = 0.5f; + Ogre::Real maxAlpha = 1.5f; + + if (mTime < 1) + { + mTime += timeSinceLastFrame * mTimeMultipliers.x; + + if (mTime > 2) mTime = 1.5f; // Prevent big changes + + if (mTime > 0.8f) // Big flash start + { alpha += (mTime - 0.8f) * (maxAlpha / 0.2f); } + } + else if (mTime > 1 && mTime < 2) + { + mTime += timeSinceLastFrame * mTimeMultipliers.y; + + if (mTime > 3) mTime = 2.5f; // Prevent big changes + + if (mTime < 1.2f) // Big flash end + { alpha += (0.2f - (mTime - 1.0f)) * (maxAlpha / 0.2f); } + else // Sinus flashing pattern + { + alpha += Ogre::Math::Abs(Ogre::Math::Sin((mTime - 1.2f) * 1.5f * mTimeMultipliers.x)); + } + } + else if (mTime > 2) // Ray fading + { + mTime += timeSinceLastFrame * mTimeMultipliers.z; + + if (mTime > 3) + { + mTime = 3; // Prevent big changes + mFinished = true; + } + + alpha += Ogre::Math::Abs(Ogre::Math::Sin((2 - 1.2f) * 1.5f * mTimeMultipliers.x)); + alpha *= 3.0f - mTime; + } + + mIntensity = alpha; + + _updateData(alpha, mTime > 1 ? 1 : mTime, mTime); + } + + void Lightning::_updateRenderQueueGroup(const Ogre::uint8 &rqg) + { + mBillboardSet->setRenderQueueGroup(rqg); + + for (Ogre::uint32 k = 0; k < mChildren.size(); k++) + { + mChildren.at(k)->_updateRenderQueueGroup(rqg); + } + } + + void Lightning::_updateData(const Ogre::Real &alpha, const Ogre::Real ¤tPos, const Ogre::Real &parentTime) + { + Ogre::Vector4 params = + Ogre::Vector4(alpha, currentPos, (3 - mRecursivity) * 0.075f + (mBounds.x * 1.5f + 0.2f) * 0.85f, 0); + + if (parentTime > 1 && parentTime < 2.2f) { params.z *= Ogre::Math::Clamp(1.5 - parentTime, 0.2f, 1); } + else if (parentTime > 2.2f) + { + params.z *= Ogre::Math::Clamp((-2.2f + parentTime) * 1.25f, 0.2f, 1); + } + + mBillboardSet->setCustomParameter(0, params); + + for (Ogre::uint32 k = 0; k < mChildren.size(); k++) + { + mChildren.at(k)->_updateData(alpha * 0.75f, currentPos, parentTime); + } + } + } // namespace VClouds +} \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/Lightning.h b/source/main/gfx/skyx/VClouds/Lightning.h index d42fadf095..ee55837d93 100644 --- a/source/main/gfx/skyx/VClouds/Lightning.h +++ b/source/main/gfx/skyx/VClouds/Lightning.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -26,182 +26,183 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class Lightning - { - public: - /** Segment struct - */ - struct Segment - { - public: - /** Default constructor - */ - Segment() - : a(Ogre::Vector3()) - , b(Ogre::Vector3()) - { - } - - /** Constructor - @param a_ First segment point (Start) - @param b_ Second segment point (End) - */ - Segment(const Ogre::Vector3& a_, const Ogre::Vector3& b_) - : a(a_) - , b(b_) - { - } - - /// Segment start - Ogre::Vector3 a; - /// Segment end - Ogre::Vector3 b; - }; - - /** Constructor - @param sm Scene manager - @param sn Scene node - @param orig Lighting origin - @param dir Lighting direction - @param l Lighting lenth - @param d Divisions - @param rec Recursivity level - @param tm Time multiplier - @param wm Width multiplier - @param b Bounds - */ - Lightning(Ogre::SceneManager* sm, Ogre::SceneNode* sn, const Ogre::Vector3& orig, const Ogre::Vector3& dir, const Ogre::Real& l, - const Ogre::uint32& d, const Ogre::uint32& rec, const Ogre::Real& tm, const Ogre::Real& wm, const Ogre::Vector2& b = Ogre::Vector2(0,1)); - - /** Destructor - */ - ~Lightning(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Update - @param timeSinceLastFrame Time since last frame - */ - void update(Ogre::Real timeSinceLastFrame); - - /** Get ray direction - @return Ray direction - */ - inline const Ogre::Vector3& getDirection() const - { - return mDirection; - } - - /** Get ray length - @return Ray length - */ - inline const Ogre::Real& getLength() const - { - return mLength; - } - - /** Get lightning intensity - @return Lightning intensity - */ - inline const Ogre::Real& getIntensity() const - { - return mIntensity; - } - - /** Get billboard set - @return Billboard set - */ - inline Ogre::BillboardSet* getBillboardSet() const - { - return mBillboardSet; - } - - /** Get scene node - @return Scene node - */ - inline Ogre::SceneNode* getSceneNode() const - { - return mSceneNode; - } - - /** Has the ray finished? - @return true if the ray has finished, false otherwise - */ - inline const bool& isFinished() const - { - return mFinished; - } - - /** Update render queue group - @param rqg Render queue group - @remarks Only for internal use. Use VClouds::setRenderQueueGroups(...) instead. - */ - void _updateRenderQueueGroup(const Ogre::uint8& rqg); - - private: - /** Update data - @param alpha Alpha - @param currentPos Current position - @param parentTime Parent time - */ - void _updateData(const Ogre::Real& alpha, const Ogre::Real& currentPos, const Ogre::Real& parentTime); - - /// Ray origin - Ogre::Vector3 mOrigin; - /// Ray direction - Ogre::Vector3 mDirection; - /// Ray length - Ogre::Real mLength; - - /// Real ray length (total segments length amount) - Ogre::Real mRealLength; - /// Number of divisions - Ogre::uint32 mDivisions; - /// Recursivity level - Ogre::uint32 mRecursivity; - /// Width multiplier - Ogre::Real mWidthMultiplier; - /// Ray bounds (for internal visual calculations) - Ogre::Vector2 mBounds; - /// Angle range (Little values -> Less derivations, bigger values -> More derivations) - Ogre::Vector2 mAngleRange; - - /// Current elapsed time - Ogre::Real mTime; - /// Global time multiplier - Ogre::Real mTimeMultiplier; - /// Per step time multipliers - Ogre::Vector3 mTimeMultipliers; - - /// Lightning intensity - Ogre::Real mIntensity; - - /// Segments - std::vector mSegments; - /// Children lightnings - std::vector mChildren; - - /// Billboard set - Ogre::BillboardSet* mBillboardSet; - /// Scene manager - Ogre::SceneManager* mSceneManager; - /// Scene node - Ogre::SceneNode* mSceneNode; - - /// Has been create() already called? - bool mCreated; - /// Has the ray finished? - bool mFinished; - }; - -}} +namespace SkyX +{ + namespace VClouds + { + + class Lightning + { + public: + /** Segment struct + */ + struct Segment + { + public: + /** Default constructor + */ + Segment() : a(Ogre::Vector3()), b(Ogre::Vector3()) + { + } + + /** Constructor + @param a_ First segment point (Start) + @param b_ Second segment point (End) + */ + Segment(const Ogre::Vector3 &a_, const Ogre::Vector3 &b_) : a(a_), b(b_) + { + } + + /// Segment start + Ogre::Vector3 a; + /// Segment end + Ogre::Vector3 b; + }; + + /** Constructor + @param sm Scene manager + @param sn Scene node + @param orig Lighting origin + @param dir Lighting direction + @param l Lighting lenth + @param d Divisions + @param rec Recursivity level + @param tm Time multiplier + @param wm Width multiplier + @param b Bounds + */ + Lightning(Ogre::SceneManager *sm, Ogre::SceneNode *sn, const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, + const Ogre::Real &l, const Ogre::uint32 &d, const Ogre::uint32 &rec, const Ogre::Real &tm, + const Ogre::Real &wm, const Ogre::Vector2 &b = Ogre::Vector2(0, 1)); + + /** Destructor + */ + ~Lightning(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Update + @param timeSinceLastFrame Time since last frame + */ + void update(Ogre::Real timeSinceLastFrame); + + /** Get ray direction + @return Ray direction + */ + inline const Ogre::Vector3 &getDirection() const + { + return mDirection; + } + + /** Get ray length + @return Ray length + */ + inline const Ogre::Real &getLength() const + { + return mLength; + } + + /** Get lightning intensity + @return Lightning intensity + */ + inline const Ogre::Real &getIntensity() const + { + return mIntensity; + } + + /** Get billboard set + @return Billboard set + */ + inline Ogre::BillboardSet *getBillboardSet() const + { + return mBillboardSet; + } + + /** Get scene node + @return Scene node + */ + inline Ogre::SceneNode *getSceneNode() const + { + return mSceneNode; + } + + /** Has the ray finished? + @return true if the ray has finished, false otherwise + */ + inline const bool &isFinished() const + { + return mFinished; + } + + /** Update render queue group + @param rqg Render queue group + @remarks Only for internal use. Use VClouds::setRenderQueueGroups(...) instead. + */ + void _updateRenderQueueGroup(const Ogre::uint8 &rqg); + + private: + /** Update data + @param alpha Alpha + @param currentPos Current position + @param parentTime Parent time + */ + void _updateData(const Ogre::Real &alpha, const Ogre::Real ¤tPos, const Ogre::Real &parentTime); + + /// Ray origin + Ogre::Vector3 mOrigin; + /// Ray direction + Ogre::Vector3 mDirection; + /// Ray length + Ogre::Real mLength; + + /// Real ray length (total segments length amount) + Ogre::Real mRealLength; + /// Number of divisions + Ogre::uint32 mDivisions; + /// Recursivity level + Ogre::uint32 mRecursivity; + /// Width multiplier + Ogre::Real mWidthMultiplier; + /// Ray bounds (for internal visual calculations) + Ogre::Vector2 mBounds; + /// Angle range (Little values -> Less derivations, bigger values -> More derivations) + Ogre::Vector2 mAngleRange; + + /// Current elapsed time + Ogre::Real mTime; + /// Global time multiplier + Ogre::Real mTimeMultiplier; + /// Per step time multipliers + Ogre::Vector3 mTimeMultipliers; + + /// Lightning intensity + Ogre::Real mIntensity; + + /// Segments + std::vector mSegments; + /// Children lightnings + std::vector mChildren; + + /// Billboard set + Ogre::BillboardSet *mBillboardSet; + /// Scene manager + Ogre::SceneManager *mSceneManager; + /// Scene node + Ogre::SceneNode *mSceneNode; + + /// Has been create() already called? + bool mCreated; + /// Has the ray finished? + bool mFinished; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/LightningManager.cpp b/source/main/gfx/skyx/VClouds/LightningManager.cpp index a0332586d9..26d1f88608 100644 --- a/source/main/gfx/skyx/VClouds/LightningManager.cpp +++ b/source/main/gfx/skyx/VClouds/LightningManager.cpp @@ -26,289 +26,303 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "VClouds.h" #include "skyx/Prerequisites.h" -namespace SkyX { namespace VClouds +namespace SkyX { - - LightningManager::LightningManager(VClouds* vc) - : mVClouds(vc) - , mLightnings(std::vector()) - , mSceneNodes(std::vector()) - , mEnabled(false) - , mLightningColor(Ogre::Vector3(1,0.925f,0.85f)) - , mLightningTimeMultiplier(2.0f) - , mAverageLightningApparitionTime(1.5f) - , mRemainingTime(1.5f) - , mVolCloudsLightningMaterial(Ogre::MaterialPtr()) - , mLightningMaterial(Ogre::MaterialPtr()) - , mListeners(std::vector()) - , mCreated(false) - { - } - - LightningManager::~LightningManager() - { - remove(); - } - - void LightningManager::create() - { - remove(); - - mVolCloudsLightningMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds_Lightning")); - mLightningMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_Lightning")); - - if (mLightningMaterial.isNull()) - { - SkyXLOG("Error while creating SkyX::VClouds::LightningManager, material not found"); - return; - } - - if (mEnabled) - { - mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds_Lightning"); - } - else - { - mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds"); - } - - mCreated = true; - - setLightningColor(mLightningColor); - } - - void LightningManager::remove() - { - if (!mCreated) - { - return; - } - - for(Ogre::uint32 k = 0; k < mLightnings.size(); k++) - { - delete mLightnings.at(k); - - mVClouds->getSceneManager()->destroySceneNode(mSceneNodes.at(k)); - } - - mLightnings.clear(); - mSceneNodes.clear(); - - removeListeners(); - - mVolCloudsLightningMaterial.setNull(); - mLightningMaterial.setNull(); - - mCreated = false; - } - - void LightningManager::update(const Ogre::Real& timeSinceLastFrame) - { - if (!mCreated) - { - return; - } - - if (mEnabled) - { - mRemainingTime -= timeSinceLastFrame; - - if (mRemainingTime <= 0) - { - mRemainingTime = Ogre::Math::RangeRandom(0, 2*mAverageLightningApparitionTime); - - // Select a random camera to place the lightning - if (!mVClouds->_getCamerasData().empty()) - { - Ogre::Camera* c = mVClouds->_getCamerasData().at(mVClouds->_getCamerasData().size()*0.999).camera; - - Ogre::Real prob = Ogre::Math::RangeRandom(0,1); - - // Cloud-to-ground - if (prob < 0.5) - { - addLightning( - // Ray position - Ogre::Vector3(c->getDerivedPosition().x + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5), mVClouds->getGeometrySettings().Height.x + 0.2*mVClouds->getGeometrySettings().Height.y, c->getDerivedPosition().z + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5)), - // Ray direction - Ogre::Vector3(0,-1,0), - // Ray length - mVClouds->getGeometrySettings().Height.x + 0.1*mVClouds->getGeometrySettings().Height.y); - } - // Cloud-to-cloud - else if (prob < 0.7) - { - addLightning( - // Ray position - Ogre::Vector3(c->getDerivedPosition().x + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5), mVClouds->getGeometrySettings().Height.x + 0.2*mVClouds->getGeometrySettings().Height.y, c->getDerivedPosition().z + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5)), - // Ray direction - Ogre::Vector3(Ogre::Math::RangeRandom(-1,1),Ogre::Math::RangeRandom(-0.1,0.1),Ogre::Math::RangeRandom(-1,1)).normalisedCopy(), - // Ray length - Ogre::Math::RangeRandom(0.5,1.5f)*0.2*mVClouds->getGeometrySettings().Height.y); - } - // Cloud-to-ground + cloud-to-cloud - else - { - addLightning( - // Ray position - Ogre::Vector3(c->getDerivedPosition().x + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5), mVClouds->getGeometrySettings().Height.x + 0.2*mVClouds->getGeometrySettings().Height.y, c->getDerivedPosition().z + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5)), - // Ray direction - Ogre::Vector3(0,-1,0), - // Ray length - mVClouds->getGeometrySettings().Height.x + 0.1*mVClouds->getGeometrySettings().Height.y); - - addLightning( - // Ray position - Ogre::Vector3(c->getDerivedPosition().x + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5), mVClouds->getGeometrySettings().Height.x + 0.2*mVClouds->getGeometrySettings().Height.y, c->getDerivedPosition().z + Ogre::Math::RangeRandom(-c->getFarClipDistance()*0.5,c->getFarClipDistance()*0.5)/Ogre::Math::RangeRandom(1,5)), - // Ray direction - Ogre::Vector3(Ogre::Math::RangeRandom(-1,1),Ogre::Math::RangeRandom(-0.1,0.1),Ogre::Math::RangeRandom(-1,1)).normalisedCopy(), - // Ray length - Ogre::Math::RangeRandom(0.5,1.5f)*0.2*mVClouds->getGeometrySettings().Height.y); - } - - updateMaterial(); - } - } - } - - for(std::vector::iterator it = mLightnings.begin(); it != mLightnings.end();) - { - if ((*it)->isFinished()) - { - Ogre::SceneNode* sn = (*it)->getSceneNode(); - - delete (*it); - it = mLightnings.erase(it); - - // Remove the associated scene node - for(std::vector::iterator it2 = mSceneNodes.begin(); it2 != mSceneNodes.end(); it2++) - { - if ((*it2) == sn) - { - sn->getParentSceneNode()->removeAndDestroyChild(sn); - mSceneNodes.erase(it2); - break; - } - } - } - else - { - (*it)->update(timeSinceLastFrame); - it++; - } - } - } - - Lightning* LightningManager::addLightning(const Ogre::Vector3& p, const Ogre::Vector3& d, const Ogre::Real l, const Ogre::uint32& div) - { - if (!mCreated || mLightnings.size() == 3) - { - return static_cast(NULL); - } - - Ogre::SceneNode* sn = mVClouds->getSceneManager()->getRootSceneNode()->createChildSceneNode(); - sn->setPosition(p); - - Lightning* lightning = new Lightning(mVClouds->getSceneManager(), sn, Ogre::Vector3(0,0,0), d, l, div, 3, mLightningTimeMultiplier, mVClouds->getGeometrySettings().Radius/9500); - lightning->create(); - lightning->_updateRenderQueueGroup( - mVClouds->getGeometryManager()->_getCurrentDistance().y < mVClouds->getGeometryManager()->getHeight().y/2 ? - mVClouds->getRenderQueueGroups().vcloudsLightningsUnder : mVClouds->getRenderQueueGroups().vcloudsLightningsOver); - lightning->getBillboardSet()->setVisible(mVClouds->isVisible()); - - mSceneNodes.push_back(sn); - mLightnings.push_back(lightning); - - for(Ogre::uint32 k = 0; k < mListeners.size(); k++) - { - mListeners.at(k)->lightningAdded(lightning); - } - - return lightning; - } - - void LightningManager::updateMaterial() - { - Ogre::Vector3 pos; - - for(Ogre::uint32 k = 0; k < 3; k++) - { - if (k < mLightnings.size()) - { - pos = mVClouds->getGeometryManager()->getSceneNode()->_getFullTransform().inverse() * mSceneNodes.at(k)->_getDerivedPosition(); - - mVolCloudsLightningMaterial-> - getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightning" + Ogre::StringConverter::toString(k), - Ogre::Vector4(pos.x, pos.y, pos.z, mLightnings.at(k)->getIntensity())); - } - else - { - mVolCloudsLightningMaterial-> - getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightning" + Ogre::StringConverter::toString(k), - Ogre::Vector4(0,0,0,0)); - } - } - } - - void LightningManager::setLightningColor(const Ogre::Vector3& c) - { - mLightningColor = c; - - if (!mCreated) - { - return; - } - - mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uLightningColor", mLightningColor); - - mLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uColor", mLightningColor); - } - - void LightningManager::removeListener(Listener* listener) - { - for(std::vector::iterator it = mListeners.begin(); it != mListeners.end(); it++) - { - if ((*it) == listener) - { - mListeners.erase(it); - return; - } - } - } - - void LightningManager::setEnabled(const bool& enable) - { - mEnabled = enable; - - if (mCreated) - { - if (mEnabled) - { - mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds_Lightning"); - } - else - { - mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds"); - } - } - } - - void LightningManager::_updateRenderQueueGroup(const Ogre::uint8& rqg) - { - for(Ogre::uint32 k = 0; k < mLightnings.size(); k++) - { - mLightnings.at(k)->_updateRenderQueueGroup(rqg); - } - } - - void LightningManager::_setVisible(const bool& v) - { - for(Ogre::uint32 k = 0; k < mLightnings.size(); k++) - { - mLightnings.at(k)->getBillboardSet()->setVisible(v); - } - } - -}} + namespace VClouds + { + + LightningManager::LightningManager(VClouds *vc) + : mVClouds(vc), mLightnings(std::vector()), mSceneNodes(std::vector()), + mEnabled(false), mLightningColor(Ogre::Vector3(1, 0.925f, 0.85f)), mLightningTimeMultiplier(2.0f), + mAverageLightningApparitionTime(1.5f), mRemainingTime(1.5f), mVolCloudsLightningMaterial(Ogre::MaterialPtr()), + mLightningMaterial(Ogre::MaterialPtr()), mListeners(std::vector()), mCreated(false) + { + } + + LightningManager::~LightningManager() + { + remove(); + } + + void LightningManager::create() + { + remove(); + + mVolCloudsLightningMaterial = + static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds_Lightning")); + mLightningMaterial = + static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_Lightning")); + + if (mLightningMaterial.isNull()) + { + SkyXLOG("Error while creating SkyX::VClouds::LightningManager, material not found"); + return; + } + + if (mEnabled) { mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds_Lightning"); } + else + { + mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds"); + } + + mCreated = true; + + setLightningColor(mLightningColor); + } + + void LightningManager::remove() + { + if (!mCreated) { return; } + + for (Ogre::uint32 k = 0; k < mLightnings.size(); k++) + { + delete mLightnings.at(k); + + mVClouds->getSceneManager()->destroySceneNode(mSceneNodes.at(k)); + } + + mLightnings.clear(); + mSceneNodes.clear(); + + removeListeners(); + + mVolCloudsLightningMaterial.setNull(); + mLightningMaterial.setNull(); + + mCreated = false; + } + + void LightningManager::update(const Ogre::Real &timeSinceLastFrame) + { + if (!mCreated) { return; } + + if (mEnabled) + { + mRemainingTime -= timeSinceLastFrame; + + if (mRemainingTime <= 0) + { + mRemainingTime = Ogre::Math::RangeRandom(0, 2 * mAverageLightningApparitionTime); + + // Select a random camera to place the lightning + if (!mVClouds->_getCamerasData().empty()) + { + Ogre::Camera *c = mVClouds->_getCamerasData().at(mVClouds->_getCamerasData().size() * 0.999).camera; + + Ogre::Real prob = Ogre::Math::RangeRandom(0, 1); + + // Cloud-to-ground + if (prob < 0.5) + { + addLightning( + // Ray position + Ogre::Vector3( + c->getDerivedPosition().x + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5), + mVClouds->getGeometrySettings().Height.x + 0.2 * mVClouds->getGeometrySettings().Height.y, + c->getDerivedPosition().z + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5)), + // Ray direction + Ogre::Vector3(0, -1, 0), + // Ray length + mVClouds->getGeometrySettings().Height.x + 0.1 * mVClouds->getGeometrySettings().Height.y); + } + // Cloud-to-cloud + else if (prob < 0.7) + { + addLightning( + // Ray position + Ogre::Vector3( + c->getDerivedPosition().x + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5), + mVClouds->getGeometrySettings().Height.x + 0.2 * mVClouds->getGeometrySettings().Height.y, + c->getDerivedPosition().z + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5)), + // Ray direction + Ogre::Vector3(Ogre::Math::RangeRandom(-1, 1), Ogre::Math::RangeRandom(-0.1, 0.1), + Ogre::Math::RangeRandom(-1, 1)) + .normalisedCopy(), + // Ray length + Ogre::Math::RangeRandom(0.5, 1.5f) * 0.2 * mVClouds->getGeometrySettings().Height.y); + } + // Cloud-to-ground + cloud-to-cloud + else + { + addLightning( + // Ray position + Ogre::Vector3( + c->getDerivedPosition().x + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5), + mVClouds->getGeometrySettings().Height.x + 0.2 * mVClouds->getGeometrySettings().Height.y, + c->getDerivedPosition().z + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5)), + // Ray direction + Ogre::Vector3(0, -1, 0), + // Ray length + mVClouds->getGeometrySettings().Height.x + 0.1 * mVClouds->getGeometrySettings().Height.y); + + addLightning( + // Ray position + Ogre::Vector3( + c->getDerivedPosition().x + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5), + mVClouds->getGeometrySettings().Height.x + 0.2 * mVClouds->getGeometrySettings().Height.y, + c->getDerivedPosition().z + + Ogre::Math::RangeRandom(-c->getFarClipDistance() * 0.5, c->getFarClipDistance() * 0.5) / + Ogre::Math::RangeRandom(1, 5)), + // Ray direction + Ogre::Vector3(Ogre::Math::RangeRandom(-1, 1), Ogre::Math::RangeRandom(-0.1, 0.1), + Ogre::Math::RangeRandom(-1, 1)) + .normalisedCopy(), + // Ray length + Ogre::Math::RangeRandom(0.5, 1.5f) * 0.2 * mVClouds->getGeometrySettings().Height.y); + } + + updateMaterial(); + } + } + } + + for (std::vector::iterator it = mLightnings.begin(); it != mLightnings.end();) + { + if ((*it)->isFinished()) + { + Ogre::SceneNode *sn = (*it)->getSceneNode(); + + delete (*it); + it = mLightnings.erase(it); + + // Remove the associated scene node + for (std::vector::iterator it2 = mSceneNodes.begin(); it2 != mSceneNodes.end(); it2++) + { + if ((*it2) == sn) + { + sn->getParentSceneNode()->removeAndDestroyChild(sn); + mSceneNodes.erase(it2); + break; + } + } + } + else + { + (*it)->update(timeSinceLastFrame); + it++; + } + } + } + + Lightning *LightningManager::addLightning(const Ogre::Vector3 &p, const Ogre::Vector3 &d, const Ogre::Real l, + const Ogre::uint32 &div) + { + if (!mCreated || mLightnings.size() == 3) { return static_cast(NULL); } + + Ogre::SceneNode *sn = mVClouds->getSceneManager()->getRootSceneNode()->createChildSceneNode(); + sn->setPosition(p); + + Lightning *lightning = new Lightning(mVClouds->getSceneManager(), sn, Ogre::Vector3(0, 0, 0), d, l, div, 3, + mLightningTimeMultiplier, mVClouds->getGeometrySettings().Radius / 9500); + lightning->create(); + lightning->_updateRenderQueueGroup(mVClouds->getGeometryManager()->_getCurrentDistance().y < + mVClouds->getGeometryManager()->getHeight().y / 2 + ? mVClouds->getRenderQueueGroups().vcloudsLightningsUnder + : mVClouds->getRenderQueueGroups().vcloudsLightningsOver); + lightning->getBillboardSet()->setVisible(mVClouds->isVisible()); + + mSceneNodes.push_back(sn); + mLightnings.push_back(lightning); + + for (Ogre::uint32 k = 0; k < mListeners.size(); k++) + { + mListeners.at(k)->lightningAdded(lightning); + } + + return lightning; + } + + void LightningManager::updateMaterial() + { + Ogre::Vector3 pos; + + for (Ogre::uint32 k = 0; k < 3; k++) + { + if (k < mLightnings.size()) + { + pos = mVClouds->getGeometryManager()->getSceneNode()->_getFullTransform().inverse() * + mSceneNodes.at(k)->_getDerivedPosition(); + + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uLightning" + Ogre::StringConverter::toString(k), + Ogre::Vector4(pos.x, pos.y, pos.z, mLightnings.at(k)->getIntensity())); + } + else + { + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uLightning" + Ogre::StringConverter::toString(k), Ogre::Vector4(0, 0, 0, 0)); + } + } + } + + void LightningManager::setLightningColor(const Ogre::Vector3 &c) + { + mLightningColor = c; + + if (!mCreated) { return; } + + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uLightningColor", mLightningColor); + + mLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uColor", + mLightningColor); + } + + void LightningManager::removeListener(Listener *listener) + { + for (std::vector::iterator it = mListeners.begin(); it != mListeners.end(); it++) + { + if ((*it) == listener) + { + mListeners.erase(it); + return; + } + } + } + + void LightningManager::setEnabled(const bool &enable) + { + mEnabled = enable; + + if (mCreated) + { + if (mEnabled) { mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds_Lightning"); } + else + { + mVClouds->getGeometryManager()->_setMaterialName("SkyX_VolClouds"); + } + } + } + + void LightningManager::_updateRenderQueueGroup(const Ogre::uint8 &rqg) + { + for (Ogre::uint32 k = 0; k < mLightnings.size(); k++) + { + mLightnings.at(k)->_updateRenderQueueGroup(rqg); + } + } + + void LightningManager::_setVisible(const bool &v) + { + for (Ogre::uint32 k = 0; k < mLightnings.size(); k++) + { + mLightnings.at(k)->getBillboardSet()->setVisible(v); + } + } + + } // namespace VClouds +} // namespace SkyX diff --git a/source/main/gfx/skyx/VClouds/LightningManager.h b/source/main/gfx/skyx/VClouds/LightningManager.h index 0e49b8c2f8..57c15e29f0 100644 --- a/source/main/gfx/skyx/VClouds/LightningManager.h +++ b/source/main/gfx/skyx/VClouds/LightningManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,212 +24,219 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_VClouds_LightningManager_H_ #define _SkyX_VClouds_LightningManager_H_ -#include "Prerequisites.h" - #include "Lightning.h" +#include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class VClouds; - - class LightningManager - { - public: - /** Listener class - */ - class Listener - { - public: - /** Lightning added - @param l Lightning that has been added - @remarks Useful when, for example, the app needs to known when a Lightning has been created (by manually - invoking LightningManager::addLightning(...) or automatically based on the lightning creation - probabilities) in order to play a sound, etc. - The lightning position is accessible through Lightning::getSceneNode()->getPosition(). - */ - inline virtual void lightningAdded(Lightning* l){} - }; - - /** Constructor - @param vc VClouds pointer - */ - LightningManager(VClouds* vc); - - /** Destructor - */ - ~LightningManager(); - - /** Create - */ - void create(); - - /** Remove - */ - void remove(); - - /** Update, to be invoked per frame - @param timeSinceLastFrame Time since last frame - */ - void update(const Ogre::Real& timeSinceLastFrame); - - /** Add lightning - @param p Lightning position - @param d Lightning direction - @param l Lightning length - @return The lightning or null in error case (the max number of simultaneous lightnings is 3) - @remarks The lightning will be automatically destroyed one time it'll be finished, so the returned ptr will not - be available one time the lightning will have disappeared - */ - Lightning* addLightning(const Ogre::Vector3& p, const Ogre::Vector3& d, const Ogre::Real l, const Ogre::uint32& div = static_cast(Ogre::Math::RangeRandom(12, 30))); - - /** Update material - @remarks To be invoked before each camera rendering process - */ - void updateMaterial(); - - /** Add listener - @param listener Listener - */ - inline void addListener(Listener* listener) - { - mListeners.push_back(listener); - } - - /** Remove listener - @param listener Listener to be removed - */ - void removeListener(Listener* listener); - - /** Remove listeners - */ - inline void removeListeners() - { - mListeners.clear(); - } - - /** Get listeners - @return Listeners - */ - inline const std::vector& getListeners() const - { - return mListeners; - } - - /** Enable or disable the lightning system - @param enable true to enable the lightning system, false otherwise - */ - void setEnabled(const bool& enable); - - /** Get whether the lightning system is enabled or not - @return true if the lightning system is enabled, false otherwise - @remarks Even if the lightning system is disabled, you'll be able to manually add lightnings trhough LightningManager::addLightning(...) - */ - inline const bool& isEnabled() const - { - return mEnabled; - } - - /** Set lightning color - @param c Lightning color - */ - void setLightningColor(const Ogre::Vector3& c); - - /** Get lightning color - @return Lightning color - */ - inline const Ogre::Vector3& getLightningColor() const - { - return mLightningColor; - } - - /** Set lightning time multiplier - @param c Lightning time multiplier - @remarks Changes applies to new lightnings, not to existing ones - */ - void setLightningTimeMultiplier(const Ogre::Real& m) - { - mLightningTimeMultiplier = m; - } - - /** Set lightning time multiplier - @return Lightning time multiplier - */ - inline const Ogre::Real& getLightningTimeMultiplier() const - { - return mLightningTimeMultiplier; - } - - /** Set average lightning apparition time - @param alat Average lightning apparition time - */ - inline void setAverageLightningApparitionTime(const Ogre::Real& alat) - { - mAverageLightningApparitionTime = alat; - mRemainingTime = alat; - } - - /** Get average lightning apparition time - @return Average lightning apparition time - */ - inline const Ogre::Real& getAverageLightningApparitionTime() const - { - return mAverageLightningApparitionTime; - } - - /** Has been create() already called? - @return true if created() have been already called, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Update render queue group - @param rqg Render queue group - @remarks Only for internal use. Use VClouds::setRenderQueueGroups(...) instead. - */ - void _updateRenderQueueGroup(const Ogre::uint8& rqg); - - /** Set visible - @param v Visible? - @remarks Only for internal use. Use VClouds::setVisible(...) instead. - */ - void _setVisible(const bool& v); - - private: - /// Lightnings - std::vector mLightnings; - /// Scene nodes - std::vector mSceneNodes; - - /// Is the lightning system enabled? - bool mEnabled; - - /// Lightning color - Ogre::Vector3 mLightningColor; - /// Lightning time multiplier - Ogre::Real mLightningTimeMultiplier; - - /// Average lightning apparition time (in seconds) - Ogre::Real mAverageLightningApparitionTime; - /// Remaining time for next lightning - Ogre::Real mRemainingTime; - - /// Vol. clouds + lightning material - Ogre::MaterialPtr mVolCloudsLightningMaterial; - /// Lightning material - Ogre::MaterialPtr mLightningMaterial; - - /// Listeners - std::vector mListeners; - - /// Has been create() already called? - bool mCreated; - - /// VClouds pointer - VClouds *mVClouds; - }; - -}} +namespace SkyX +{ + namespace VClouds + { + + class VClouds; + + class LightningManager + { + public: + /** Listener class + */ + class Listener + { + public: + /** Lightning added + @param l Lightning that has been added + @remarks Useful when, for example, the app needs to known when a Lightning has been created (by manually + invoking LightningManager::addLightning(...) or automatically based on the lightning creation + probabilities) in order to play a sound, etc. + The lightning position is accessible through Lightning::getSceneNode()->getPosition(). + */ + inline virtual void lightningAdded(Lightning *l) + { + } + }; + + /** Constructor + @param vc VClouds pointer + */ + LightningManager(VClouds *vc); + + /** Destructor + */ + ~LightningManager(); + + /** Create + */ + void create(); + + /** Remove + */ + void remove(); + + /** Update, to be invoked per frame + @param timeSinceLastFrame Time since last frame + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Add lightning + @param p Lightning position + @param d Lightning direction + @param l Lightning length + @return The lightning or null in error case (the max number of simultaneous lightnings is 3) + @remarks The lightning will be automatically destroyed one time it'll be finished, so the returned ptr will not + be available one time the lightning will have disappeared + */ + Lightning *addLightning(const Ogre::Vector3 &p, const Ogre::Vector3 &d, const Ogre::Real l, + const Ogre::uint32 &div = static_cast(Ogre::Math::RangeRandom(12, 30))); + + /** Update material + @remarks To be invoked before each camera rendering process + */ + void updateMaterial(); + + /** Add listener + @param listener Listener + */ + inline void addListener(Listener *listener) + { + mListeners.push_back(listener); + } + + /** Remove listener + @param listener Listener to be removed + */ + void removeListener(Listener *listener); + + /** Remove listeners + */ + inline void removeListeners() + { + mListeners.clear(); + } + + /** Get listeners + @return Listeners + */ + inline const std::vector &getListeners() const + { + return mListeners; + } + + /** Enable or disable the lightning system + @param enable true to enable the lightning system, false otherwise + */ + void setEnabled(const bool &enable); + + /** Get whether the lightning system is enabled or not + @return true if the lightning system is enabled, false otherwise + @remarks Even if the lightning system is disabled, you'll be able to manually add lightnings trhough + LightningManager::addLightning(...) + */ + inline const bool &isEnabled() const + { + return mEnabled; + } + + /** Set lightning color + @param c Lightning color + */ + void setLightningColor(const Ogre::Vector3 &c); + + /** Get lightning color + @return Lightning color + */ + inline const Ogre::Vector3 &getLightningColor() const + { + return mLightningColor; + } + + /** Set lightning time multiplier + @param c Lightning time multiplier + @remarks Changes applies to new lightnings, not to existing ones + */ + void setLightningTimeMultiplier(const Ogre::Real &m) + { + mLightningTimeMultiplier = m; + } + + /** Set lightning time multiplier + @return Lightning time multiplier + */ + inline const Ogre::Real &getLightningTimeMultiplier() const + { + return mLightningTimeMultiplier; + } + + /** Set average lightning apparition time + @param alat Average lightning apparition time + */ + inline void setAverageLightningApparitionTime(const Ogre::Real &alat) + { + mAverageLightningApparitionTime = alat; + mRemainingTime = alat; + } + + /** Get average lightning apparition time + @return Average lightning apparition time + */ + inline const Ogre::Real &getAverageLightningApparitionTime() const + { + return mAverageLightningApparitionTime; + } + + /** Has been create() already called? + @return true if created() have been already called, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Update render queue group + @param rqg Render queue group + @remarks Only for internal use. Use VClouds::setRenderQueueGroups(...) instead. + */ + void _updateRenderQueueGroup(const Ogre::uint8 &rqg); + + /** Set visible + @param v Visible? + @remarks Only for internal use. Use VClouds::setVisible(...) instead. + */ + void _setVisible(const bool &v); + + private: + /// Lightnings + std::vector mLightnings; + /// Scene nodes + std::vector mSceneNodes; + + /// Is the lightning system enabled? + bool mEnabled; + + /// Lightning color + Ogre::Vector3 mLightningColor; + /// Lightning time multiplier + Ogre::Real mLightningTimeMultiplier; + + /// Average lightning apparition time (in seconds) + Ogre::Real mAverageLightningApparitionTime; + /// Remaining time for next lightning + Ogre::Real mRemainingTime; + + /// Vol. clouds + lightning material + Ogre::MaterialPtr mVolCloudsLightningMaterial; + /// Lightning material + Ogre::MaterialPtr mLightningMaterial; + + /// Listeners + std::vector mListeners; + + /// Has been create() already called? + bool mCreated; + + /// VClouds pointer + VClouds *mVClouds; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VClouds/VClouds.cpp b/source/main/gfx/skyx/VClouds/VClouds.cpp index ab5abdff6b..7b4ce7752b 100644 --- a/source/main/gfx/skyx/VClouds/VClouds.cpp +++ b/source/main/gfx/skyx/VClouds/VClouds.cpp @@ -25,306 +25,267 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #include "gfx/skyx/SkyX.h" -namespace SkyX { namespace VClouds +namespace SkyX { - VClouds::VClouds(Ogre::SceneManager *sm) - : mSceneManager(sm) - , mCamera(0) - , mCreated(false) - , mGeometrySettings(GeometrySettings()) - , mDistanceFallingParams(Ogre::Vector2(1,-1)) - , mRenderQueueGroups(RenderQueueGroups(Ogre::RENDER_QUEUE_MAIN, Ogre::RENDER_QUEUE_9, Ogre::RENDER_QUEUE_4)) - , mWindDirection(Ogre::Degree(0)) - , mWindSpeed(80.0f) - , mWheater(Ogre::Vector2(0.5f, 1.0f)) - , mDelayedResponse(false) - , mSunDirection(Ogre::Vector3(0,-1,0)) - , mSunColor(Ogre::Vector3(1,1,1)) - , mAmbientColor(Ogre::Vector3(0.63f,0.63f,0.7f)) - , mLightResponse(Ogre::Vector4(0.25f,0.2f,1.0f,0.1f)) - , mAmbientFactors(Ogre::Vector4(0.45f,0.3f,0.6f,1)) - , mGlobalOpacity(1.0f) - , mCloudFieldScale(1.0f) - , mNoiseScale(4.2f) - , mVisible(true) - , mDataManager(new DataManager(this)) - , mGeometryManager(new GeometryManager(this)) - , mLightningManager(new LightningManager(this)) - , mCamerasData(std::vector()) - , mVolCloudsMaterial(Ogre::MaterialPtr()) - , mVolCloudsLightningMaterial(Ogre::MaterialPtr()) - { - } - - VClouds::~VClouds() - { - remove(); - - delete mDataManager; - delete mGeometryManager; - delete mLightningManager; - } - - void VClouds::create() - { - remove(); - - mVolCloudsMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds")); - mVolCloudsLightningMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds_Lightning")); - - if (mVolCloudsMaterial.isNull() || mVolCloudsLightningMaterial.isNull()) - { - SkyXLOG("Error while creating SkyX::VClouds::VClouds, materials are not found"); - return; - } - - // Data manager - mDataManager->create(128,128,20); - - // Geometry manager - mGeometryManager->create(mGeometrySettings.Height, mGeometrySettings.Radius, mGeometrySettings.Alpha, - mGeometrySettings.Beta, mGeometrySettings.NumberOfBlocks, mGeometrySettings.Na, mGeometrySettings.Nb, mGeometrySettings.Nc); - - mGeometryManager->getSceneNode()->setVisible(mVisible); - - mVolCloudsMaterial - ->getTechnique(0)->getPass(0)->getVertexProgramParameters()->setNamedConstant("uRadius", mGeometrySettings.Radius); - mVolCloudsLightningMaterial-> - getTechnique(0)->getPass(0)->getVertexProgramParameters()->setNamedConstant("uRadius", mGeometrySettings.Radius); - - // Lightning manager - mLightningManager->create(); - - mCreated = true; - - // Update material parameters - setSunColor(mSunColor); - setAmbientColor(mAmbientColor); - setLightResponse(mLightResponse); - setAmbientFactors(mAmbientFactors); - - // Set current wheater - setWheater(mWheater.x, mWheater.y, mDelayedResponse); - } - - void VClouds::create(const GeometrySettings& gs) - { - // Update geometry settings - mGeometrySettings = gs; - - create(); - } - - void VClouds::create(const Ogre::Vector2& Height, const float& Radius) - { - // Update geometry params - mGeometrySettings.Height = Height; - mGeometrySettings.Radius = Radius; - - create(); - } - - void VClouds::remove() - { - if (!mCreated) - { - return; - } - - mDataManager->remove(); - mGeometryManager->remove(); - mLightningManager->remove(); - - mCamera = 0; - mCamerasData.clear(); - - mVolCloudsMaterial.setNull(); - mVolCloudsLightningMaterial.setNull(); - - mCreated = false; - } - - void VClouds::update(const Ogre::Real& timeSinceLastFrame) - { - if (!mCreated) - { - return; - } - - mDataManager->update(timeSinceLastFrame); - mGeometryManager->update(timeSinceLastFrame); - mLightningManager->update(timeSinceLastFrame); - - if (mLightningManager->isEnabled()) - { - mVolCloudsLightningMaterial-> - getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uInterpolation", mDataManager->_getInterpolation()); - mVolCloudsLightningMaterial-> - getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uSunDirection", -mSunDirection); - } - else - { - mVolCloudsMaterial-> - getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uInterpolation", mDataManager->_getInterpolation()); - mVolCloudsMaterial-> - getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uSunDirection", -mSunDirection); - } - } - - void VClouds::notifyCameraRender(Ogre::Camera* c, const Ogre::Real& timeSinceLastCameraFrame) - { - if (!mCreated) - { - return; - } - - mCamera = c; - - // Check if the camera is registered - bool isRegistered = false; - for (Ogre::uint32 k = 0; k < mCamerasData.size(); k++) - { - if (mCamerasData.at(k).camera == c) - { - isRegistered = true; - break; - } - } - - if (!isRegistered) - { - mCamerasData.push_back(CameraData(c)); - SkyXLOG("VClouds warning: unregistered camera registered, manual unregistering is needed before camera destruction"); - } - - mGeometryManager->updateGeometry(c, timeSinceLastCameraFrame); - mLightningManager->updateMaterial(); - - mLightningManager->_updateRenderQueueGroup(mGeometryManager->_getCurrentDistance().y < mGeometryManager->getHeight().y/2 ? - mRenderQueueGroups.vcloudsLightningsUnder : mRenderQueueGroups.vcloudsLightningsOver); - } - - void VClouds::registerCamera(Ogre::Camera* c) - { - for (Ogre::uint32 k = 0; k < mCamerasData.size(); k++) - { - if (mCamerasData.at(k).camera == c) - { - return; - } - } - - mCamerasData.push_back(CameraData(c)); - } - - void VClouds::unregisterCamera(Ogre::Camera* c) - { - for (std::vector::iterator it = mCamerasData.begin(); it != mCamerasData.end(); it++) - { - if ((*it).camera == c) - { - mCamerasData.erase(it); - return; - } - } - } - - void VClouds::setVisible(const bool& visible) - { - mVisible = visible; - - if (!mCreated) - { - return; - } - - mGeometryManager->getSceneNode()->setVisible(mVisible); - mLightningManager->_setVisible(mVisible); - } - - void VClouds::setRenderQueueGroups(const RenderQueueGroups& rqg) - { - mRenderQueueGroups = rqg; - - if (!mCreated) - { - return; - } - - mGeometryManager->_updateRenderQueueGroup(rqg.vclouds); - } - - void VClouds::setSunColor(const Ogre::Vector3& SunColor) - { - mSunColor = SunColor; - - if (!mCreated) - { - return; - } - - mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uSunColor", mSunColor); - mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uSunColor", mSunColor); - } - - void VClouds::setAmbientColor(const Ogre::Vector3& AmbientColor) - { - mAmbientColor = AmbientColor; - - if (!mCreated) - { - return; - } - - mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uAmbientColor", mAmbientColor); - mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uAmbientColor", mAmbientColor); - } - - void VClouds::setLightResponse(const Ogre::Vector4& LightResponse) - { - mLightResponse = LightResponse; - - if (!mCreated) - { - return; - } - - mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uLightResponse", mLightResponse); - mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uLightResponse", mLightResponse); - } - - void VClouds::setAmbientFactors(const Ogre::Vector4& AmbientFactors) - { - mAmbientFactors = AmbientFactors; - - if (!mCreated) - { - return; - } - - mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uAmbientFactors", mAmbientFactors); - mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters() - ->setNamedConstant("uAmbientFactors", mAmbientFactors); - } - - void VClouds::setWheater(const float& Humidity, const float& AverageCloudsSize, const bool& DelayedResponse) - { - mWheater = Ogre::Vector2(Humidity, AverageCloudsSize); - mDelayedResponse = DelayedResponse; - - if (!mCreated) - { - return; - } - - mDataManager->setWheater(mWheater.x, mWheater.y, mDelayedResponse); - } - -}} + namespace VClouds + { + VClouds::VClouds(Ogre::SceneManager *sm) + : mSceneManager(sm), mCamera(0), mCreated(false), mGeometrySettings(GeometrySettings()), + mDistanceFallingParams(Ogre::Vector2(1, -1)), + mRenderQueueGroups(RenderQueueGroups(Ogre::RENDER_QUEUE_MAIN, Ogre::RENDER_QUEUE_9, Ogre::RENDER_QUEUE_4)), + mWindDirection(Ogre::Degree(0)), mWindSpeed(80.0f), mWheater(Ogre::Vector2(0.5f, 1.0f)), mDelayedResponse(false), + mSunDirection(Ogre::Vector3(0, -1, 0)), mSunColor(Ogre::Vector3(1, 1, 1)), + mAmbientColor(Ogre::Vector3(0.63f, 0.63f, 0.7f)), mLightResponse(Ogre::Vector4(0.25f, 0.2f, 1.0f, 0.1f)), + mAmbientFactors(Ogre::Vector4(0.45f, 0.3f, 0.6f, 1)), mGlobalOpacity(1.0f), mCloudFieldScale(1.0f), + mNoiseScale(4.2f), mVisible(true), mDataManager(new DataManager(this)), mGeometryManager(new GeometryManager(this)), + mLightningManager(new LightningManager(this)), mCamerasData(std::vector()), + mVolCloudsMaterial(Ogre::MaterialPtr()), mVolCloudsLightningMaterial(Ogre::MaterialPtr()) + { + } + + VClouds::~VClouds() + { + remove(); + + delete mDataManager; + delete mGeometryManager; + delete mLightningManager; + } + + void VClouds::create() + { + remove(); + + mVolCloudsMaterial = + static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds")); + mVolCloudsLightningMaterial = + static_cast(Ogre::MaterialManager::getSingleton().getByName("SkyX_VolClouds_Lightning")); + + if (mVolCloudsMaterial.isNull() || mVolCloudsLightningMaterial.isNull()) + { + SkyXLOG("Error while creating SkyX::VClouds::VClouds, materials are not found"); + return; + } + + // Data manager + mDataManager->create(128, 128, 20); + + // Geometry manager + mGeometryManager->create(mGeometrySettings.Height, mGeometrySettings.Radius, mGeometrySettings.Alpha, + mGeometrySettings.Beta, mGeometrySettings.NumberOfBlocks, mGeometrySettings.Na, + mGeometrySettings.Nb, mGeometrySettings.Nc); + + mGeometryManager->getSceneNode()->setVisible(mVisible); + + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters()->setNamedConstant( + "uRadius", mGeometrySettings.Radius); + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters()->setNamedConstant( + "uRadius", mGeometrySettings.Radius); + + // Lightning manager + mLightningManager->create(); + + mCreated = true; + + // Update material parameters + setSunColor(mSunColor); + setAmbientColor(mAmbientColor); + setLightResponse(mLightResponse); + setAmbientFactors(mAmbientFactors); + + // Set current wheater + setWheater(mWheater.x, mWheater.y, mDelayedResponse); + } + + void VClouds::create(const GeometrySettings &gs) + { + // Update geometry settings + mGeometrySettings = gs; + + create(); + } + + void VClouds::create(const Ogre::Vector2 &Height, const float &Radius) + { + // Update geometry params + mGeometrySettings.Height = Height; + mGeometrySettings.Radius = Radius; + + create(); + } + + void VClouds::remove() + { + if (!mCreated) { return; } + + mDataManager->remove(); + mGeometryManager->remove(); + mLightningManager->remove(); + + mCamera = 0; + mCamerasData.clear(); + + mVolCloudsMaterial.setNull(); + mVolCloudsLightningMaterial.setNull(); + + mCreated = false; + } + + void VClouds::update(const Ogre::Real &timeSinceLastFrame) + { + if (!mCreated) { return; } + + mDataManager->update(timeSinceLastFrame); + mGeometryManager->update(timeSinceLastFrame); + mLightningManager->update(timeSinceLastFrame); + + if (mLightningManager->isEnabled()) + { + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uInterpolation", mDataManager->_getInterpolation()); + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uSunDirection", -mSunDirection); + } + else + { + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uInterpolation", mDataManager->_getInterpolation()); + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uSunDirection", + -mSunDirection); + } + } + + void VClouds::notifyCameraRender(Ogre::Camera *c, const Ogre::Real &timeSinceLastCameraFrame) + { + if (!mCreated) { return; } + + mCamera = c; + + // Check if the camera is registered + bool isRegistered = false; + for (Ogre::uint32 k = 0; k < mCamerasData.size(); k++) + { + if (mCamerasData.at(k).camera == c) + { + isRegistered = true; + break; + } + } + + if (!isRegistered) + { + mCamerasData.push_back(CameraData(c)); + SkyXLOG( + "VClouds warning: unregistered camera registered, manual unregistering is needed before camera destruction"); + } + + mGeometryManager->updateGeometry(c, timeSinceLastCameraFrame); + mLightningManager->updateMaterial(); + + mLightningManager->_updateRenderQueueGroup(mGeometryManager->_getCurrentDistance().y < + mGeometryManager->getHeight().y / 2 + ? mRenderQueueGroups.vcloudsLightningsUnder + : mRenderQueueGroups.vcloudsLightningsOver); + } + + void VClouds::registerCamera(Ogre::Camera *c) + { + for (Ogre::uint32 k = 0; k < mCamerasData.size(); k++) + { + if (mCamerasData.at(k).camera == c) { return; } + } + + mCamerasData.push_back(CameraData(c)); + } + + void VClouds::unregisterCamera(Ogre::Camera *c) + { + for (std::vector::iterator it = mCamerasData.begin(); it != mCamerasData.end(); it++) + { + if ((*it).camera == c) + { + mCamerasData.erase(it); + return; + } + } + } + + void VClouds::setVisible(const bool &visible) + { + mVisible = visible; + + if (!mCreated) { return; } + + mGeometryManager->getSceneNode()->setVisible(mVisible); + mLightningManager->_setVisible(mVisible); + } + + void VClouds::setRenderQueueGroups(const RenderQueueGroups &rqg) + { + mRenderQueueGroups = rqg; + + if (!mCreated) { return; } + + mGeometryManager->_updateRenderQueueGroup(rqg.vclouds); + } + + void VClouds::setSunColor(const Ogre::Vector3 &SunColor) + { + mSunColor = SunColor; + + if (!mCreated) { return; } + + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uSunColor", + mSunColor); + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uSunColor", mSunColor); + } + + void VClouds::setAmbientColor(const Ogre::Vector3 &AmbientColor) + { + mAmbientColor = AmbientColor; + + if (!mCreated) { return; } + + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uAmbientColor", + mAmbientColor); + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uAmbientColor", mAmbientColor); + } + + void VClouds::setLightResponse(const Ogre::Vector4 &LightResponse) + { + mLightResponse = LightResponse; + + if (!mCreated) { return; } + + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightResponse", + mLightResponse); + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uLightResponse", mLightResponse); + } + + void VClouds::setAmbientFactors(const Ogre::Vector4 &AmbientFactors) + { + mAmbientFactors = AmbientFactors; + + if (!mCreated) { return; } + + mVolCloudsMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uAmbientFactors", + mAmbientFactors); + mVolCloudsLightningMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + "uAmbientFactors", mAmbientFactors); + } + + void VClouds::setWheater(const float &Humidity, const float &AverageCloudsSize, const bool &DelayedResponse) + { + mWheater = Ogre::Vector2(Humidity, AverageCloudsSize); + mDelayedResponse = DelayedResponse; + + if (!mCreated) { return; } + + mDataManager->setWheater(mWheater.x, mWheater.y, mDelayedResponse); + } + + } // namespace VClouds +} // namespace SkyX diff --git a/source/main/gfx/skyx/VClouds/VClouds.h b/source/main/gfx/skyx/VClouds/VClouds.h index c122b79d7b..032088af28 100644 --- a/source/main/gfx/skyx/VClouds/VClouds.h +++ b/source/main/gfx/skyx/VClouds/VClouds.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,559 +24,550 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_VClouds_VClouds_H_ #define _SkyX_VClouds_VClouds_H_ -#include "Prerequisites.h" - #include "DataManager.h" #include "GeometryManager.h" #include "LightningManager.h" +#include "Prerequisites.h" -namespace SkyX { namespace VClouds{ - - class VClouds - { - public: - /** Render queue groups - */ - struct RenderQueueGroups - { - /** Constructor - @param vc VClouds render queue group - @param vclu VClouds lightnings render queue group (when the camera is under the cloud field) - @param vclo VClouds lightnings render queue group (when the camera is over the cloud field) - */ - inline RenderQueueGroups(const Ogre::uint8& vc, const Ogre::uint8& vclu, const Ogre::uint8& vclo) - : vclouds(vc), vcloudsLightningsUnder(vclu), vcloudsLightningsOver(vclo) - { - } - - /// VClouds render queue group - Ogre::uint8 vclouds; - /// VClouds lightnings render queue group (when the camera is under the cloud field) - Ogre::uint8 vcloudsLightningsUnder; - /// VClouds lightnings render queue group (when the camera is over the cloud field) - Ogre::uint8 vcloudsLightningsOver; - }; - - /** Geometry settings - */ - struct GeometrySettings - { - /// Height: x = Altitude over the camera, y: Field height (both in world coordinates) - Ogre::Vector2 Height; - /// Angles - Ogre::Radian Alpha, Beta; - /// Radius - float Radius; - /// Number of blocks - int NumberOfBlocks; - /// Number of slices per geometry zone - int Na, Nb, Nc; - - /** Default constructor - */ - GeometrySettings() - : Height(Ogre::Vector2(10,50)) - , Alpha(Ogre::Degree(12)), Beta(Ogre::Degree(40)) - , Radius(100) - , NumberOfBlocks(12) - , Na(10), Nb(8), Nc(6) - { - } - - /** Constructor - @param _Height x = Cloud field y-coord start, y: Field height (both in world coordinates) - @param _Radius Radius - @param _Alpha Alpha angle - @param _Beta Beta angle - @param _NumberOfBlocks Number of geometry blocks - @param _Na Number of slices in A zone - @param _Nb Number of slices in B zone - @param _Nc Number of slices in C zone - */ - GeometrySettings(const Ogre::Vector2& _Height, const float& _Radius, - const Ogre::Radian& _Alpha = Ogre::Degree(12), const Ogre::Radian& _Beta = Ogre::Degree(40), - const int& _NumberOfBlocks = 12, const int& _Na = 10, const int& _Nb = 8, const int& _Nc = 6) - : Height(_Height) - , Alpha(_Alpha), Beta(_Beta) - , Radius(_Radius) - , NumberOfBlocks(_NumberOfBlocks) - , Na(_Na), Nb(_Nb), Nc(_Nc) - { - } - }; - - /** Camera data struct - */ - struct CameraData - { - public: - /** Default constructor - */ - inline CameraData() - : camera(0) - , lastPosition(Ogre::Vector3(0,0,0)) - , cameraOffset(Ogre::Vector2(0,0)) - , geometryDisplacement(Ogre::Vector3(0,0,0)) - { - } - - /** Constructor - @param c Camera - */ - inline CameraData(Ogre::Camera* c) - : camera(c) - , lastPosition(c->getDerivedPosition()) - , cameraOffset(Ogre::Vector2(0,0)) - , geometryDisplacement(Ogre::Vector3(0,0,0)) - { - } - - /// Camera - Ogre::Camera* camera; - /// Last camera position - Ogre::Vector3 lastPosition; - /// Camera offset - Ogre::Vector2 cameraOffset; - /// Geometry displacement - Ogre::Vector3 geometryDisplacement; - }; - - /** Simple constructor - @param sm Scene manager - */ - VClouds(Ogre::SceneManager *sm); - - /** Destructor - */ - ~VClouds(); - - /** Create - */ - void create(); - - /** Create - @param gs Geometry settings - */ - void create(const GeometrySettings& gs); - - /** Create - @param Height x = Cloud field y-coord start, y: Field height (both in world coordinates) - @param Radius Radius - */ - void create(const Ogre::Vector2& Height, const float& Radius); - - /** Remove - */ - void remove(); - - /** Update, to be invoked per frame - @param timeSinceLastFrame Time since last frame - */ - void update(const Ogre::Real& timeSinceLastFrame); - - /** Notify camera render, to be invoked per-camera and per-frame - @param c Rendering camera - @param timeSinceLastCameraFrame Time since last CAMERA frame - */ - void notifyCameraRender(Ogre::Camera* c, const Ogre::Real& timeSinceLastCameraFrame); - - /** Register camera - @param c Camera - @remarks If a rendering camera is used(in notifyCameraRender(...)) without having registered it before, - all will work as expected but a warning will be logged since the user should manually unregister - the camera one time it'll be remove - */ - void registerCamera(Ogre::Camera* c); - - /** Unregister camera - @param c Camera - @remarks After having used a camera (i.e. before removing the camera), the user should manually unregister it - */ - void unregisterCamera(Ogre::Camera* c); - - /** Has been create() already called? - @return true if created() have been already called, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Set geometry settings - @param GeometrySettings Geometry settings - @remarks Set geometry settings before call create(...) - */ - inline void setGeometrySettings(const GeometrySettings& gs) - { - mGeometrySettings = gs; - } - - /** Get geometry settings - @return Geometry settings - */ - inline const GeometrySettings& getGeometrySettings() const - { - return mGeometrySettings; - } - - /** Set distance falling params - @param DistanceFallingParams - DistanceFallingParams.x = Distance falling factor (How much the cloud field geometry falls with the distance) - Remember that the geometry falling is relative to the distance(height) between the camera - and the cloud field. Typical range is [0, ~2] 0 = no falling - DistanceFallingParams.y = Max falling (in world coords), useful when , i.e., you've water and you want to go in. - That param will allow you to avoid the cloud field geometry falls into the ocean. - -1 means not max falling. (default) - @remarks See GoemetryBlock::_setVertexData(...) for more info - */ - inline void setDistanceFallingParams(const Ogre::Vector2& DistanceFallingParams) - { - mDistanceFallingParams = DistanceFallingParams; - } - - /** Get distance falling params - @return DistanceFallingParams.x = Distance falling factor (How much the cloud field geometry falls with the distance) - Remember that the geometry falling is relative to the distance(height) between the camera - and the cloud field. - Typical range is [0, ~2] 0 = no falling - DistanceFallingParams.y = Max falling (in world coords), useful when , i.e., you've water and you want to go in. - That param will allow you to avoid the cloud field geometry falls into the ocean. - -1 means not max falling. (default) - @remarks See GoemetryBlock::_setVertexData(...) for more info - */ - inline const Ogre::Vector2& getDistanceFallingParams() const - { - return mDistanceFallingParams; - } - - /** Set render queue groups - @param rqg Render queue groups - */ - void setRenderQueueGroups(const RenderQueueGroups& rqg); - - /** Get render queue groups - @return Current render queue groups - */ - inline const RenderQueueGroups& getRenderQueueGroups() const - { - return mRenderQueueGroups; - } - - /** Set wind direction - @param WindDirection Wind direction - */ - inline void setWindDirection(const Ogre::Radian& WindDirection) - { - mWindDirection = WindDirection; - } - - /** Get wind direction - @return Wind direction - */ - inline const Ogre::Radian& getWindDirection() const - { - return mWindDirection; - } - - /** Get wind direction as a Vector2 - @return Wind direction - */ - inline const Ogre::Vector2 getWindDirectionV2() const - { - return Ogre::Vector2(Ogre::Math::Cos(mWindDirection), Ogre::Math::Sin(mWindDirection)); - } - - /** Set wind speed - @param WindSpeed Wind speed - */ - inline void setWindSpeed(const float& WindSpeed) - { - mWindSpeed = WindSpeed; - } - - /** Get wind speed - @return Wind speed - */ - inline const float& getWindSpeed() const - { - return mWindSpeed; - } - - /** Set sun direction - @param SunDirection Sun direction - */ - inline void setSunDirection(const Ogre::Vector3& SunDirection) - { - mSunDirection = SunDirection; - } - - /** Get sun direction - @return Sun direction - */ - inline const Ogre::Vector3& getSunDirection() const - { - return mSunDirection; - } - - /** Set sun color - @param SunColor Sun color - */ - void setSunColor(const Ogre::Vector3& SunColor); - - /** Get sun color - @return Sun color - */ - inline const Ogre::Vector3& getSunColor() const - { - return mSunColor; - } - - /** Set ambient color - @param AmbientColor Ambient color - */ - void setAmbientColor(const Ogre::Vector3& AmbientColor); - - /** Get Ambient color - @return Ambient color - */ - inline const Ogre::Vector3& getAmbientColor() const - { - return mAmbientColor; - } - - /** Set light response - @param LightResponse - x - Sun light power - y - Sun beta multiplier - z - Ambient color multiplier - w - Distance attenuation - */ - void setLightResponse(const Ogre::Vector4& LightResponse); - - /** Get light response - @return Light response - */ - inline const Ogre::Vector4& getLightResponse() const - { - return mLightResponse; - } - - /** Set ambient factors - @param AmbientFactors x - constant, y - linear, z - cuadratic, w - cubic - */ - void setAmbientFactors(const Ogre::Vector4& AmbientFactors); - - /** Get ambient factors - @return Ambient factors - */ - inline const Ogre::Vector4& getAmbientFactors() const - { - return mAmbientFactors; - } - - /** Set global opacity - @param GlobalOpacity Global opacity: [0,1] range 0->Transparent cloud field - */ - inline void setGlobalOpacity(const Ogre::Real& GlobalOpacity) - { - mGlobalOpacity = GlobalOpacity; - } - - /** Get global opacity - @return Global opacity - */ - inline const Ogre::Real& getGlobalOpacity() const - { - return mGlobalOpacity; - } - - /** Set cloud field scale - @param CloudFieldScale Cloud field scale - */ - inline void setCloudFieldScale(const Ogre::Real& CloudFieldScale) - { - mCloudFieldScale = CloudFieldScale; - } - - /** Get cloud field scale - @return Cloud field scale - */ - inline const Ogre::Real& getCloudFieldScale() const - { - return mCloudFieldScale; - } - - /** Set noise scale - @param NoiseScale Noise scale - */ - inline void setNoiseScale(const Ogre::Real& NoiseScale) - { - mNoiseScale = NoiseScale; - } - - /** Get noise scale - @return Noise scale - */ - inline const Ogre::Real& getNoiseScale() const - { - return mNoiseScale; - } - - /** Set wheater parameters - Use this funtion to update the cloud field parameters, you'll get a smart and smooth transition from your old - setting to your new ones. - @param Humidity Humidity, in other words: the percentage of clouds in [0,1] range. - @param AverageCloudsSize Average clouds size, for example: if previous wheater clouds size parameter was very different from new one(i.e: more little) - only the old biggest clouds are going to be keept and the little ones are going to be replaced - @param DelayedResponse false to change wheather conditions over several updates, true to change it at the moment - */ - void setWheater(const float& Humidity, const float& AverageCloudsSize, const bool& DelayedResponse); - - /** Get wheater - @return Wheater parameters: x = Humidity, y = Average clouds size, both un [0,1] range - */ - inline const Ogre::Vector2& getWheater() const - { - return mWheater; - } - - /** Set visible - @param visible true to set VClouds visible, false to hide it - */ - void setVisible(const bool& visible); - - /** Is VClouds visible? - @return true if VClouds is visible, false otherwise - */ - inline const bool& isVisible() const - { - return mVisible; - } - - /** Get scene manager - @return Ogre::SceneManager pointer - */ - inline Ogre::SceneManager* getSceneManager() - { - return mSceneManager; - } - - /** Get current rendering camera - @return Current rendering camera - */ - inline Ogre::Camera* getCamera() - { - return mCamera; - } - - /** Get data manager - @return Data manager - */ - inline DataManager* getDataManager() - { - return mDataManager; - } - - /** Get geometry manager - @return Geometry manager - */ - inline GeometryManager* getGeometryManager() - { - return mGeometryManager; - } - - /** Get lightning manager - @return Lightning manager - */ - inline LightningManager* getLightningManager() - { - return mLightningManager; - } - - /** Get cameras data - @return Cameras data - @remarks Only for internal use - */ - inline std::vector& _getCamerasData() - { - return mCamerasData; - } - - private: - /// Has been create(...) already called? - bool mCreated; - - /// Geometry settings - GeometrySettings mGeometrySettings; - - /// Geometry distance falling params - Ogre::Vector2 mDistanceFallingParams; - - /// Render queue groups - RenderQueueGroups mRenderQueueGroups; - - /// Wind direction - Ogre::Radian mWindDirection; - /// Wind speed - float mWindSpeed; - - /// Wheater parameters: x = Humidity, y = Average clouds size, both un [0,1] range - Ogre::Vector2 mWheater; - /// Delayed response (This param is stored to allow the user call setWheater(...) before create() ) - bool mDelayedResponse; - - /// Sun direction - Ogre::Vector3 mSunDirection; - - /// Sun color - Ogre::Vector3 mSunColor; - /// Ambient color - Ogre::Vector3 mAmbientColor; - - /** Light response: - x - Sun light power - y - Sun beta multiplier - z - Ambient color multiplier - w - Distance attenuation - */ - Ogre::Vector4 mLightResponse; - /** Ambient factors - x - constant, y - linear, z - cuadratic, w - cubic - */ - Ogre::Vector4 mAmbientFactors; - - /// Global opacity - float mGlobalOpacity; - - /// Cloud field scale - float mCloudFieldScale; - /// Noise scale - float mNoiseScale; - - /// Is VClouds visible? - bool mVisible; - - /// Data manager - DataManager *mDataManager; - /// Geometry manager - GeometryManager *mGeometryManager; - /// Lightning manager - LightningManager *mLightningManager; - - /// Ogre::SceneManager pointer - Ogre::SceneManager *mSceneManager; - /// Current rendering camera - Ogre::Camera* mCamera; - - /// Vol. clouds material - Ogre::MaterialPtr mVolCloudsMaterial; - /// Vol. clouds + lightning material - Ogre::MaterialPtr mVolCloudsLightningMaterial; - - /// Cameras data - std::vector mCamerasData; - }; - -}} +namespace SkyX +{ + namespace VClouds + { + + class VClouds + { + public: + /** Render queue groups + */ + struct RenderQueueGroups + { + /** Constructor + @param vc VClouds render queue group + @param vclu VClouds lightnings render queue group (when the camera is under the cloud field) + @param vclo VClouds lightnings render queue group (when the camera is over the cloud field) + */ + inline RenderQueueGroups(const Ogre::uint8 &vc, const Ogre::uint8 &vclu, const Ogre::uint8 &vclo) + : vclouds(vc), vcloudsLightningsUnder(vclu), vcloudsLightningsOver(vclo) + { + } + + /// VClouds render queue group + Ogre::uint8 vclouds; + /// VClouds lightnings render queue group (when the camera is under the cloud field) + Ogre::uint8 vcloudsLightningsUnder; + /// VClouds lightnings render queue group (when the camera is over the cloud field) + Ogre::uint8 vcloudsLightningsOver; + }; + + /** Geometry settings + */ + struct GeometrySettings + { + /// Height: x = Altitude over the camera, y: Field height (both in world coordinates) + Ogre::Vector2 Height; + /// Angles + Ogre::Radian Alpha, Beta; + /// Radius + float Radius; + /// Number of blocks + int NumberOfBlocks; + /// Number of slices per geometry zone + int Na, Nb, Nc; + + /** Default constructor + */ + GeometrySettings() + : Height(Ogre::Vector2(10, 50)), Alpha(Ogre::Degree(12)), Beta(Ogre::Degree(40)), Radius(100), + NumberOfBlocks(12), Na(10), Nb(8), Nc(6) + { + } + + /** Constructor + @param _Height x = Cloud field y-coord start, y: Field height (both in world coordinates) + @param _Radius Radius + @param _Alpha Alpha angle + @param _Beta Beta angle + @param _NumberOfBlocks Number of geometry blocks + @param _Na Number of slices in A zone + @param _Nb Number of slices in B zone + @param _Nc Number of slices in C zone + */ + GeometrySettings(const Ogre::Vector2 &_Height, const float &_Radius, + const Ogre::Radian &_Alpha = Ogre::Degree(12), const Ogre::Radian &_Beta = Ogre::Degree(40), + const int &_NumberOfBlocks = 12, const int &_Na = 10, const int &_Nb = 8, const int &_Nc = 6) + : Height(_Height), Alpha(_Alpha), Beta(_Beta), Radius(_Radius), NumberOfBlocks(_NumberOfBlocks), Na(_Na), + Nb(_Nb), Nc(_Nc) + { + } + }; + + /** Camera data struct + */ + struct CameraData + { + public: + /** Default constructor + */ + inline CameraData() + : camera(0), lastPosition(Ogre::Vector3(0, 0, 0)), cameraOffset(Ogre::Vector2(0, 0)), + geometryDisplacement(Ogre::Vector3(0, 0, 0)) + { + } + + /** Constructor + @param c Camera + */ + inline CameraData(Ogre::Camera *c) + : camera(c), lastPosition(c->getDerivedPosition()), cameraOffset(Ogre::Vector2(0, 0)), + geometryDisplacement(Ogre::Vector3(0, 0, 0)) + { + } + + /// Camera + Ogre::Camera *camera; + /// Last camera position + Ogre::Vector3 lastPosition; + /// Camera offset + Ogre::Vector2 cameraOffset; + /// Geometry displacement + Ogre::Vector3 geometryDisplacement; + }; + + /** Simple constructor + @param sm Scene manager + */ + VClouds(Ogre::SceneManager *sm); + + /** Destructor + */ + ~VClouds(); + + /** Create + */ + void create(); + + /** Create + @param gs Geometry settings + */ + void create(const GeometrySettings &gs); + + /** Create + @param Height x = Cloud field y-coord start, y: Field height (both in world coordinates) + @param Radius Radius + */ + void create(const Ogre::Vector2 &Height, const float &Radius); + + /** Remove + */ + void remove(); + + /** Update, to be invoked per frame + @param timeSinceLastFrame Time since last frame + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Notify camera render, to be invoked per-camera and per-frame + @param c Rendering camera + @param timeSinceLastCameraFrame Time since last CAMERA frame + */ + void notifyCameraRender(Ogre::Camera *c, const Ogre::Real &timeSinceLastCameraFrame); + + /** Register camera + @param c Camera + @remarks If a rendering camera is used(in notifyCameraRender(...)) without having registered it before, + all will work as expected but a warning will be logged since the user should manually unregister + the camera one time it'll be remove + */ + void registerCamera(Ogre::Camera *c); + + /** Unregister camera + @param c Camera + @remarks After having used a camera (i.e. before removing the camera), the user should manually unregister it + */ + void unregisterCamera(Ogre::Camera *c); + + /** Has been create() already called? + @return true if created() have been already called, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Set geometry settings + @param GeometrySettings Geometry settings + @remarks Set geometry settings before call create(...) + */ + inline void setGeometrySettings(const GeometrySettings &gs) + { + mGeometrySettings = gs; + } + + /** Get geometry settings + @return Geometry settings + */ + inline const GeometrySettings &getGeometrySettings() const + { + return mGeometrySettings; + } + + /** Set distance falling params + @param DistanceFallingParams + DistanceFallingParams.x = Distance falling factor (How much the cloud field geometry falls with the + distance) Remember that the geometry falling is relative to the distance(height) between the camera and the cloud + field. Typical range is [0, ~2] 0 = no falling DistanceFallingParams.y = Max falling (in world coords), useful when + , i.e., you've water and you want to go in. That param will allow you to avoid the cloud field geometry falls into + the ocean. -1 means not max falling. (default) + @remarks See GoemetryBlock::_setVertexData(...) for more info + */ + inline void setDistanceFallingParams(const Ogre::Vector2 &DistanceFallingParams) + { + mDistanceFallingParams = DistanceFallingParams; + } + + /** Get distance falling params + @return DistanceFallingParams.x = Distance falling factor (How much the cloud field geometry falls with the + distance) Remember that the geometry falling is relative to the distance(height) between the camera and the cloud + field. Typical range is [0, ~2] 0 = no falling DistanceFallingParams.y = Max falling (in world coords), useful when + , i.e., you've water and you want to go in. That param will allow you to avoid the cloud field geometry falls into + the ocean. -1 means not max falling. (default) + @remarks See GoemetryBlock::_setVertexData(...) for more info + */ + inline const Ogre::Vector2 &getDistanceFallingParams() const + { + return mDistanceFallingParams; + } + + /** Set render queue groups + @param rqg Render queue groups + */ + void setRenderQueueGroups(const RenderQueueGroups &rqg); + + /** Get render queue groups + @return Current render queue groups + */ + inline const RenderQueueGroups &getRenderQueueGroups() const + { + return mRenderQueueGroups; + } + + /** Set wind direction + @param WindDirection Wind direction + */ + inline void setWindDirection(const Ogre::Radian &WindDirection) + { + mWindDirection = WindDirection; + } + + /** Get wind direction + @return Wind direction + */ + inline const Ogre::Radian &getWindDirection() const + { + return mWindDirection; + } + + /** Get wind direction as a Vector2 + @return Wind direction + */ + inline const Ogre::Vector2 getWindDirectionV2() const + { + return Ogre::Vector2(Ogre::Math::Cos(mWindDirection), Ogre::Math::Sin(mWindDirection)); + } + + /** Set wind speed + @param WindSpeed Wind speed + */ + inline void setWindSpeed(const float &WindSpeed) + { + mWindSpeed = WindSpeed; + } + + /** Get wind speed + @return Wind speed + */ + inline const float &getWindSpeed() const + { + return mWindSpeed; + } + + /** Set sun direction + @param SunDirection Sun direction + */ + inline void setSunDirection(const Ogre::Vector3 &SunDirection) + { + mSunDirection = SunDirection; + } + + /** Get sun direction + @return Sun direction + */ + inline const Ogre::Vector3 &getSunDirection() const + { + return mSunDirection; + } + + /** Set sun color + @param SunColor Sun color + */ + void setSunColor(const Ogre::Vector3 &SunColor); + + /** Get sun color + @return Sun color + */ + inline const Ogre::Vector3 &getSunColor() const + { + return mSunColor; + } + + /** Set ambient color + @param AmbientColor Ambient color + */ + void setAmbientColor(const Ogre::Vector3 &AmbientColor); + + /** Get Ambient color + @return Ambient color + */ + inline const Ogre::Vector3 &getAmbientColor() const + { + return mAmbientColor; + } + + /** Set light response + @param LightResponse + x - Sun light power + y - Sun beta multiplier + z - Ambient color multiplier + w - Distance attenuation + */ + void setLightResponse(const Ogre::Vector4 &LightResponse); + + /** Get light response + @return Light response + */ + inline const Ogre::Vector4 &getLightResponse() const + { + return mLightResponse; + } + + /** Set ambient factors + @param AmbientFactors x - constant, y - linear, z - cuadratic, w - cubic + */ + void setAmbientFactors(const Ogre::Vector4 &AmbientFactors); + + /** Get ambient factors + @return Ambient factors + */ + inline const Ogre::Vector4 &getAmbientFactors() const + { + return mAmbientFactors; + } + + /** Set global opacity + @param GlobalOpacity Global opacity: [0,1] range 0->Transparent cloud field + */ + inline void setGlobalOpacity(const Ogre::Real &GlobalOpacity) + { + mGlobalOpacity = GlobalOpacity; + } + + /** Get global opacity + @return Global opacity + */ + inline const Ogre::Real &getGlobalOpacity() const + { + return mGlobalOpacity; + } + + /** Set cloud field scale + @param CloudFieldScale Cloud field scale + */ + inline void setCloudFieldScale(const Ogre::Real &CloudFieldScale) + { + mCloudFieldScale = CloudFieldScale; + } + + /** Get cloud field scale + @return Cloud field scale + */ + inline const Ogre::Real &getCloudFieldScale() const + { + return mCloudFieldScale; + } + + /** Set noise scale + @param NoiseScale Noise scale + */ + inline void setNoiseScale(const Ogre::Real &NoiseScale) + { + mNoiseScale = NoiseScale; + } + + /** Get noise scale + @return Noise scale + */ + inline const Ogre::Real &getNoiseScale() const + { + return mNoiseScale; + } + + /** Set wheater parameters + Use this funtion to update the cloud field parameters, you'll get a smart and smooth transition from your old + setting to your new ones. + @param Humidity Humidity, in other words: the percentage of clouds in [0,1] range. + @param AverageCloudsSize Average clouds size, for example: if previous wheater clouds size parameter was very + different from new one(i.e: more little) only the old biggest clouds are going to be keept and the little ones are + going to be replaced + @param DelayedResponse false to change wheather conditions over several updates, true to change it at the moment + */ + void setWheater(const float &Humidity, const float &AverageCloudsSize, const bool &DelayedResponse); + + /** Get wheater + @return Wheater parameters: x = Humidity, y = Average clouds size, both un [0,1] range + */ + inline const Ogre::Vector2 &getWheater() const + { + return mWheater; + } + + /** Set visible + @param visible true to set VClouds visible, false to hide it + */ + void setVisible(const bool &visible); + + /** Is VClouds visible? + @return true if VClouds is visible, false otherwise + */ + inline const bool &isVisible() const + { + return mVisible; + } + + /** Get scene manager + @return Ogre::SceneManager pointer + */ + inline Ogre::SceneManager *getSceneManager() + { + return mSceneManager; + } + + /** Get current rendering camera + @return Current rendering camera + */ + inline Ogre::Camera *getCamera() + { + return mCamera; + } + + /** Get data manager + @return Data manager + */ + inline DataManager *getDataManager() + { + return mDataManager; + } + + /** Get geometry manager + @return Geometry manager + */ + inline GeometryManager *getGeometryManager() + { + return mGeometryManager; + } + + /** Get lightning manager + @return Lightning manager + */ + inline LightningManager *getLightningManager() + { + return mLightningManager; + } + + /** Get cameras data + @return Cameras data + @remarks Only for internal use + */ + inline std::vector &_getCamerasData() + { + return mCamerasData; + } + + private: + /// Has been create(...) already called? + bool mCreated; + + /// Geometry settings + GeometrySettings mGeometrySettings; + + /// Geometry distance falling params + Ogre::Vector2 mDistanceFallingParams; + + /// Render queue groups + RenderQueueGroups mRenderQueueGroups; + + /// Wind direction + Ogre::Radian mWindDirection; + /// Wind speed + float mWindSpeed; + + /// Wheater parameters: x = Humidity, y = Average clouds size, both un [0,1] range + Ogre::Vector2 mWheater; + /// Delayed response (This param is stored to allow the user call setWheater(...) before create() ) + bool mDelayedResponse; + + /// Sun direction + Ogre::Vector3 mSunDirection; + + /// Sun color + Ogre::Vector3 mSunColor; + /// Ambient color + Ogre::Vector3 mAmbientColor; + + /** Light response: + x - Sun light power + y - Sun beta multiplier + z - Ambient color multiplier + w - Distance attenuation + */ + Ogre::Vector4 mLightResponse; + /** Ambient factors + x - constant, y - linear, z - cuadratic, w - cubic + */ + Ogre::Vector4 mAmbientFactors; + + /// Global opacity + float mGlobalOpacity; + + /// Cloud field scale + float mCloudFieldScale; + /// Noise scale + float mNoiseScale; + + /// Is VClouds visible? + bool mVisible; + + /// Data manager + DataManager *mDataManager; + /// Geometry manager + GeometryManager *mGeometryManager; + /// Lightning manager + LightningManager *mLightningManager; + + /// Ogre::SceneManager pointer + Ogre::SceneManager *mSceneManager; + /// Current rendering camera + Ogre::Camera *mCamera; + + /// Vol. clouds material + Ogre::MaterialPtr mVolCloudsMaterial; + /// Vol. clouds + lightning material + Ogre::MaterialPtr mVolCloudsLightningMaterial; + + /// Cameras data + std::vector mCamerasData; + }; + + } // namespace VClouds +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gfx/skyx/VCloudsManager.cpp b/source/main/gfx/skyx/VCloudsManager.cpp index c2a2c4d883..0610044e67 100644 --- a/source/main/gfx/skyx/VCloudsManager.cpp +++ b/source/main/gfx/skyx/VCloudsManager.cpp @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -27,136 +27,111 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to namespace SkyX { - VCloudsManager::VCloudsManager(SkyX *s) - : mSkyX(s) - , mVClouds(0) - , mHeight(Ogre::Vector2(-1, -1)) - , mWindSpeed(800.0f) - , mAutoupdate(true) - , mCreated(false) - , mCurrentTimeSinceLastFrame(0) - { - mVClouds = new VClouds::VClouds(mSkyX->getSceneManager()); - mVClouds->setRenderQueueGroups( - VClouds::VClouds::RenderQueueGroups(mSkyX->getRenderQueueGroups().vclouds, mSkyX->getRenderQueueGroups().vcloudsLightningsUnder, mSkyX->getRenderQueueGroups().vcloudsLightningsOver)); - - mAmbientGradient = ColorGradient(); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.9f, 1.0f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.7,0.7,0.65), 0.625f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.55,0.4)*0.5, 0.5625f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.55,0.4)*0.25, 0.475f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.45,0.3)*0.2, 0.4f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.3)*0.2, 0.325f)); - mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2,0.2,0.3)*0.15, 0)); - - mSunGradient = ColorGradient(); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.9f, 1.0f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1,1,1)*0.8, 0.75f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.8,0.75,0.55)*1.3, 0.5625f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*1.5, 0.5f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*0.6, 0.4725f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6,0.5,0.2)*0.4, 0.45f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.0,0.0,0.0), 0.4125f)); // Sun-Moon threshold - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.25,0.25,0.25), 0.25f)); - mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.4,0.4,0.4), 0.0f)); - } - - VCloudsManager::~VCloudsManager() - { - remove(); - - delete mVClouds; - } - - void VCloudsManager::create(const Ogre::Real& radius) - { - if (mCreated) - { - return; - } - - Ogre::Real selectedRadius = radius < 0 ? mVClouds->getGeometrySettings().Radius : radius; - - // Use default options if the user haven't set any specific Height parameters - Ogre::Vector2 defaultheight = Ogre::Vector2(selectedRadius*0.025f, selectedRadius*0.1f); - Ogre::Vector2 height = (mHeight.x == -1 || mHeight.y == -1) ? defaultheight : mHeight; - - _setLightParameters(); - mVClouds->create(height, selectedRadius); - - mCreated = true; - - _updateWindSpeedConfig(); - } - - void VCloudsManager::update(const Ogre::Real& timeSinceLastFrame) - { - if (!mCreated) - { - return; - } - - mCurrentTimeSinceLastFrame = timeSinceLastFrame; - - _setLightParameters(); - - mVClouds->update(timeSinceLastFrame); - } - - void VCloudsManager::notifyCameraRender(Ogre::Camera* c) - { - if (!mCreated) - { - return; - } - - mVClouds->notifyCameraRender(c, mCurrentTimeSinceLastFrame); - } - - void VCloudsManager::remove() - { - if (!mCreated) - { - return; - } - - mVClouds->remove(); - - mCreated = false; - } - - void VCloudsManager::_setLightParameters() - { - Ogre::Vector3 SunDir = -mSkyX->getController()->getSunDirection(); - - // Moon - if (SunDir.y > 0.175f) - { - SunDir = -mSkyX->getController()->getMoonDirection(); - } - - mVClouds->setSunDirection(SunDir); - - float point = (mSkyX->getController()->getSunDirection().y + 1.0f) / 2.0f; - - mVClouds->setAmbientColor(mAmbientGradient.getColor(point)); - mVClouds->setSunColor(mSunGradient.getColor(point)); - } - - void VCloudsManager::_updateWindSpeedConfig() - { - if (!mCreated) - { - return; - } - - if (mAutoupdate) - { - mVClouds->setWindSpeed(mSkyX->getTimeMultiplier() * mWindSpeed); - } - else - { - mVClouds->setWindSpeed(mWindSpeed); - } - } + VCloudsManager::VCloudsManager(SkyX *s) + : mSkyX(s), mVClouds(0), mHeight(Ogre::Vector2(-1, -1)), mWindSpeed(800.0f), mAutoupdate(true), mCreated(false), + mCurrentTimeSinceLastFrame(0) + { + mVClouds = new VClouds::VClouds(mSkyX->getSceneManager()); + mVClouds->setRenderQueueGroups(VClouds::VClouds::RenderQueueGroups(mSkyX->getRenderQueueGroups().vclouds, + mSkyX->getRenderQueueGroups().vcloudsLightningsUnder, + mSkyX->getRenderQueueGroups().vcloudsLightningsOver)); + + mAmbientGradient = ColorGradient(); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.9f, 1.0f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.7, 0.7, 0.65), 0.625f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.55, 0.4) * 0.5, 0.5625f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.55, 0.4) * 0.25, 0.475f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.45, 0.3) * 0.2, 0.4f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.3) * 0.2, 0.325f)); + mAmbientGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.2, 0.2, 0.3) * 0.15, 0)); + + mSunGradient = ColorGradient(); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.9f, 1.0f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(1, 1, 1) * 0.8, 0.75f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.8, 0.75, 0.55) * 1.3, 0.5625f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 1.5, 0.5f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 0.6, 0.4725f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.6, 0.5, 0.2) * 0.4, 0.45f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.0, 0.0, 0.0), 0.4125f)); // Sun-Moon threshold + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.25, 0.25, 0.25), 0.25f)); + mSunGradient.addCFrame(ColorGradient::ColorFrame(Ogre::Vector3(0.4, 0.4, 0.4), 0.0f)); + } + + VCloudsManager::~VCloudsManager() + { + remove(); + + delete mVClouds; + } + + void VCloudsManager::create(const Ogre::Real &radius) + { + if (mCreated) { return; } + + Ogre::Real selectedRadius = radius < 0 ? mVClouds->getGeometrySettings().Radius : radius; + + // Use default options if the user haven't set any specific Height parameters + Ogre::Vector2 defaultheight = Ogre::Vector2(selectedRadius * 0.025f, selectedRadius * 0.1f); + Ogre::Vector2 height = (mHeight.x == -1 || mHeight.y == -1) ? defaultheight : mHeight; + + _setLightParameters(); + mVClouds->create(height, selectedRadius); + + mCreated = true; + + _updateWindSpeedConfig(); + } + + void VCloudsManager::update(const Ogre::Real &timeSinceLastFrame) + { + if (!mCreated) { return; } + + mCurrentTimeSinceLastFrame = timeSinceLastFrame; + + _setLightParameters(); + + mVClouds->update(timeSinceLastFrame); + } + + void VCloudsManager::notifyCameraRender(Ogre::Camera *c) + { + if (!mCreated) { return; } + + mVClouds->notifyCameraRender(c, mCurrentTimeSinceLastFrame); + } + + void VCloudsManager::remove() + { + if (!mCreated) { return; } + + mVClouds->remove(); + + mCreated = false; + } + + void VCloudsManager::_setLightParameters() + { + Ogre::Vector3 SunDir = -mSkyX->getController()->getSunDirection(); + + // Moon + if (SunDir.y > 0.175f) { SunDir = -mSkyX->getController()->getMoonDirection(); } + + mVClouds->setSunDirection(SunDir); + + float point = (mSkyX->getController()->getSunDirection().y + 1.0f) / 2.0f; + + mVClouds->setAmbientColor(mAmbientGradient.getColor(point)); + mVClouds->setSunColor(mSunGradient.getColor(point)); + } + + void VCloudsManager::_updateWindSpeedConfig() + { + if (!mCreated) { return; } + + if (mAutoupdate) { mVClouds->setWindSpeed(mSkyX->getTimeMultiplier() * mWindSpeed); } + else + { + mVClouds->setWindSpeed(mWindSpeed); + } + } } \ No newline at end of file diff --git a/source/main/gfx/skyx/VCloudsManager.h b/source/main/gfx/skyx/VCloudsManager.h index 2544c1422f..9aa994aafb 100644 --- a/source/main/gfx/skyx/VCloudsManager.h +++ b/source/main/gfx/skyx/VCloudsManager.h @@ -3,7 +3,7 @@ This source file is part of SkyX. Visit http://www.paradise-studios.net/products/skyx/ -Copyright (C) 2009-2012 Xavier Verguín González +Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -24,182 +24,181 @@ Place - Suite 330, Boston, MA 02111-1307, USA, or go to #ifndef _SkyX_VCloudsManager_H_ #define _SkyX_VCloudsManager_H_ +#include "ColorGradient.h" #include "Prerequisites.h" - #include "VClouds/VClouds.h" -#include "ColorGradient.h" namespace SkyX { - class SkyX; - - class VCloudsManager - { - public: - /** Constructor - @param s Parent SkyX pointer - */ - VCloudsManager(SkyX *s); - - /** Destructor - */ - ~VCloudsManager(); - - /** Create all resources - @param radius Volumetric cloud field radius, -1 to use current VClouds::mGeometrySettings::Radius - */ - void create(const Ogre::Real& radius = -1); - - /** Update - @param timeSinceLastFrame Time since last frame - */ - void update(const Ogre::Real& timeSinceLastFrame); - - /** Notify camera render, to be invoked per-camera and per-frame - @param c Rendering camera - @remarks The VClouds system needs the CAMERA time since last frame, so here we assume that all render targets - are being updated one time per frame(in other words, all render targets are being updated at the same rate) - */ - void notifyCameraRender(Ogre::Camera* c); - - /** Remove all resources - */ - void remove(); - - /** Set ambient gradient - @param AmbientGradient Ambient color gradient - */ - inline void setAmbientGradient(const ColorGradient& AmbientGradient) - { - mAmbientGradient = AmbientGradient; - } - - /** Get ambient color gradient - @return Ambient color gradient - */ - inline const ColorGradient& getAmbientGradient() const - { - return mAmbientGradient; - } - - /** Set sun gradient - @param SunGradient Sun color gradient - */ - inline void setSunGradient(const ColorGradient& SunGradient) - { - mSunGradient = SunGradient; - } - - /** Get sun color gradient - @return Sun color gradient - */ - inline const ColorGradient& getSunGradient() const - { - return mSunGradient; - } - - /** Set height parameters - @param Height x = Cloud field y-coord start, y: Field height (both in world coordinates) - @remarks Call it before create(), for now... - For autocalculated height based on the radius length set (-1,-1) as height params - */ - inline void setHeight(const Ogre::Vector2& Height) - { - mHeight = Height; - } - - /** Get height parameters - @return Height: x = Cloud field y-coord start, y: Field height (both in world coordinates) - */ - inline const Ogre::Vector2& getHeight() const - { - return mHeight; - } - - /** Set autoupdate - @Autoupdate true if you want to update volumetric clouds wind depending of the SkyX time multiplier - @remarks You can use VClouds->setWindSpeed(..) for different winds speeds - */ - inline void setAutoupdate(const bool& Autoupdate) - { - mAutoupdate = Autoupdate; - _updateWindSpeedConfig(); - } - - /** Get autoupdate - @return true if you want to update volumetric clouds wind depending of the SkyX time multiplier - */ - inline const bool& getAutoupdate() const - { - return mAutoupdate; - } - - /** Set wind speed - @param WindSpeed Wind speed - */ - inline void setWindSpeed(const Ogre::Real& WindSpeed) - { - mWindSpeed = WindSpeed; - _updateWindSpeedConfig(); - } - - /** Get wind speed - @return Wind speed - */ - inline const Ogre::Real& getWindSpeed() const - { - return mWindSpeed; - } - - /** Get VClouds - */ - inline VClouds::VClouds* getVClouds() - { - return mVClouds; - } - - /** Is moon manager created? - @return true if yes, false if not - */ - inline const bool& isCreated() const - { - return mCreated; - } - - /** Update wind speed config - @remarks Only for internal use - */ - void _updateWindSpeedConfig(); - - private: - /** Set light parameters - */ - void _setLightParameters(); - - /// Ambient and Sun color gradients - ColorGradient mAmbientGradient; - ColorGradient mSunGradient; - - /// VClouds pointer - VClouds::VClouds* mVClouds; - - /// Height parameters, x = Cloud field y-coord start, y: Field height (both in world coordinates) - Ogre::Vector2 mHeight; - - /// Autoupdate wind speed depending of skyx time multiplier? - bool mAutoupdate; - /// Wind speed - Ogre::Real mWindSpeed; - - /// Is vclouds manager created? - bool mCreated; - - /// Current time since last frame - Ogre::Real mCurrentTimeSinceLastFrame; - - /// SkyX parent pointer - SkyX *mSkyX; - }; -} + class SkyX; + + class VCloudsManager + { + public: + /** Constructor + @param s Parent SkyX pointer + */ + VCloudsManager(SkyX *s); + + /** Destructor + */ + ~VCloudsManager(); + + /** Create all resources + @param radius Volumetric cloud field radius, -1 to use current VClouds::mGeometrySettings::Radius + */ + void create(const Ogre::Real &radius = -1); + + /** Update + @param timeSinceLastFrame Time since last frame + */ + void update(const Ogre::Real &timeSinceLastFrame); + + /** Notify camera render, to be invoked per-camera and per-frame + @param c Rendering camera + @remarks The VClouds system needs the CAMERA time since last frame, so here we assume that all render targets + are being updated one time per frame(in other words, all render targets are being updated at the same rate) + */ + void notifyCameraRender(Ogre::Camera *c); + + /** Remove all resources + */ + void remove(); + + /** Set ambient gradient + @param AmbientGradient Ambient color gradient + */ + inline void setAmbientGradient(const ColorGradient &AmbientGradient) + { + mAmbientGradient = AmbientGradient; + } + + /** Get ambient color gradient + @return Ambient color gradient + */ + inline const ColorGradient &getAmbientGradient() const + { + return mAmbientGradient; + } + + /** Set sun gradient + @param SunGradient Sun color gradient + */ + inline void setSunGradient(const ColorGradient &SunGradient) + { + mSunGradient = SunGradient; + } + + /** Get sun color gradient + @return Sun color gradient + */ + inline const ColorGradient &getSunGradient() const + { + return mSunGradient; + } + + /** Set height parameters + @param Height x = Cloud field y-coord start, y: Field height (both in world coordinates) + @remarks Call it before create(), for now... + For autocalculated height based on the radius length set (-1,-1) as height params + */ + inline void setHeight(const Ogre::Vector2 &Height) + { + mHeight = Height; + } + + /** Get height parameters + @return Height: x = Cloud field y-coord start, y: Field height (both in world coordinates) + */ + inline const Ogre::Vector2 &getHeight() const + { + return mHeight; + } + + /** Set autoupdate + @Autoupdate true if you want to update volumetric clouds wind depending of the SkyX time multiplier + @remarks You can use VClouds->setWindSpeed(..) for different winds speeds + */ + inline void setAutoupdate(const bool &Autoupdate) + { + mAutoupdate = Autoupdate; + _updateWindSpeedConfig(); + } + + /** Get autoupdate + @return true if you want to update volumetric clouds wind depending of the SkyX time multiplier + */ + inline const bool &getAutoupdate() const + { + return mAutoupdate; + } + + /** Set wind speed + @param WindSpeed Wind speed + */ + inline void setWindSpeed(const Ogre::Real &WindSpeed) + { + mWindSpeed = WindSpeed; + _updateWindSpeedConfig(); + } + + /** Get wind speed + @return Wind speed + */ + inline const Ogre::Real &getWindSpeed() const + { + return mWindSpeed; + } + + /** Get VClouds + */ + inline VClouds::VClouds *getVClouds() + { + return mVClouds; + } + + /** Is moon manager created? + @return true if yes, false if not + */ + inline const bool &isCreated() const + { + return mCreated; + } + + /** Update wind speed config + @remarks Only for internal use + */ + void _updateWindSpeedConfig(); + + private: + /** Set light parameters + */ + void _setLightParameters(); + + /// Ambient and Sun color gradients + ColorGradient mAmbientGradient; + ColorGradient mSunGradient; + + /// VClouds pointer + VClouds::VClouds *mVClouds; + + /// Height parameters, x = Cloud field y-coord start, y: Field height (both in world coordinates) + Ogre::Vector2 mHeight; + + /// Autoupdate wind speed depending of skyx time multiplier? + bool mAutoupdate; + /// Wind speed + Ogre::Real mWindSpeed; + + /// Is vclouds manager created? + bool mCreated; + + /// Current time since last frame + Ogre::Real mCurrentTimeSinceLastFrame; + + /// SkyX parent pointer + SkyX *mSkyX; + }; +} // namespace SkyX #endif \ No newline at end of file diff --git a/source/main/gui/DashBoardManager.cpp b/source/main/gui/DashBoardManager.cpp index 05efcdaecb..49a33950c4 100644 --- a/source/main/gui/DashBoardManager.cpp +++ b/source/main/gui/DashBoardManager.cpp @@ -22,7 +22,6 @@ /// @author Thomas Fischer thomas{AT}thomasfischer{DOT}biz /// @date 19th of October 2011 - #include "DashBoardManager.h" #include "Application.h" @@ -38,80 +37,80 @@ DashBoardManager::DashBoardManager(void) : visible(true), free_dashboard(0) memset(&dashboards, 0, sizeof(dashboards)); // init data - INITDATA(DD_ENGINE_RPM , DC_FLOAT, "rpm"); - INITDATA(DD_ENGINE_SPEEDO_KPH , DC_FLOAT, "speedo_kph"); - INITDATA(DD_ENGINE_SPEEDO_MPH , DC_FLOAT, "speedo_mph"); - INITDATA(DD_ENGINE_TURBO , DC_FLOAT, "engine_turbo"); - INITDATA(DD_ENGINE_IGNITION , DC_BOOL , "engine_ignition"); - INITDATA(DD_ENGINE_BATTERY , DC_BOOL , "engine_battery"); - INITDATA(DD_ENGINE_CLUTCH_WARNING , DC_BOOL , "engine_clutch_warning"); - INITDATA(DD_ENGINE_GEAR , DC_INT , "engine_gear"); - INITDATA(DD_ENGINE_NUM_GEAR , DC_INT , "engine_num_gear"); - INITDATA(DD_ENGINE_GEAR_STRING , DC_CHAR , "engine_gear_string"); - INITDATA(DD_ENGINE_AUTOGEAR_STRING , DC_CHAR , "engine_autogear_string"); - INITDATA(DD_ENGINE_AUTO_GEAR , DC_INT , "engine_auto_gear"); - INITDATA(DD_ENGINE_CLUTCH , DC_FLOAT, "engine_clutch"); - INITDATA(DD_BRAKE , DC_FLOAT, "brake"); - INITDATA(DD_ACCELERATOR , DC_FLOAT, "accelerator"); - INITDATA(DD_ROLL , DC_FLOAT, "roll"); - INITDATA(DD_ROLL_CORR , DC_FLOAT, "roll_corr"); - INITDATA(DD_ROLL_CORR_ACTIVE , DC_BOOL , "roll_corr_active"); - INITDATA(DD_PITCH , DC_FLOAT, "pitch"); - INITDATA(DD_PARKINGBRAKE , DC_BOOL , "parkingbrake"); - INITDATA(DD_LOCKED , DC_BOOL , "locked"); - INITDATA(DD_LOW_PRESSURE , DC_BOOL , "low_pressure"); - INITDATA(DD_LIGHTS , DC_BOOL , "lights"); - INITDATA(DD_TRACTIONCONTROL_MODE , DC_INT , "tractioncontrol_mode"); - INITDATA(DD_ANTILOCKBRAKE_MODE , DC_INT , "antilockbrake_mode"); - INITDATA(DD_TIES_MODE , DC_INT , "ties_mode"); - INITDATA(DD_SCREW_THROTTLE_0 , DC_FLOAT, "screw_throttle_0"); - INITDATA(DD_SCREW_THROTTLE_1 , DC_FLOAT, "screw_throttle_1"); - INITDATA(DD_SCREW_THROTTLE_2 , DC_FLOAT, "screw_throttle_2"); - INITDATA(DD_SCREW_THROTTLE_3 , DC_FLOAT, "screw_throttle_3"); - INITDATA(DD_SCREW_THROTTLE_4 , DC_FLOAT, "screw_throttle_4"); - INITDATA(DD_SCREW_THROTTLE_5 , DC_FLOAT, "screw_throttle_5"); - INITDATA(DD_SCREW_STEER_0 , DC_FLOAT, "screw_steer_0"); - INITDATA(DD_SCREW_STEER_1 , DC_FLOAT, "screw_steer_1"); - INITDATA(DD_SCREW_STEER_2 , DC_FLOAT, "screw_steer_2"); - INITDATA(DD_SCREW_STEER_3 , DC_FLOAT, "screw_steer_3"); - INITDATA(DD_SCREW_STEER_4 , DC_FLOAT, "screw_steer_4"); - INITDATA(DD_SCREW_STEER_5 , DC_FLOAT, "screw_steer_5"); - INITDATA(DD_WATER_DEPTH , DC_FLOAT, "water_depth"); - INITDATA(DD_WATER_SPEED , DC_FLOAT, "water_speed"); - INITDATA(DD_AEROENGINE_THROTTLE_0 , DC_FLOAT, "aeroengine_throttle_0"); - INITDATA(DD_AEROENGINE_THROTTLE_1 , DC_FLOAT, "aeroengine_throttle_1"); - INITDATA(DD_AEROENGINE_THROTTLE_2 , DC_FLOAT, "aeroengine_throttle_2"); - INITDATA(DD_AEROENGINE_THROTTLE_3 , DC_FLOAT, "aeroengine_throttle_3"); - INITDATA(DD_AEROENGINE_THROTTLE_4 , DC_FLOAT, "aeroengine_throttle_4"); - INITDATA(DD_AEROENGINE_THROTTLE_5 , DC_FLOAT, "aeroengine_throttle_5"); - INITDATA(DD_AEROENGINE_FAILED_0 , DC_BOOL , "aeroengine_failed_0"); - INITDATA(DD_AEROENGINE_FAILED_1 , DC_BOOL , "aeroengine_failed_1"); - INITDATA(DD_AEROENGINE_FAILED_2 , DC_BOOL , "aeroengine_failed_2"); - INITDATA(DD_AEROENGINE_FAILED_3 , DC_BOOL , "aeroengine_failed_3"); - INITDATA(DD_AEROENGINE_FAILED_4 , DC_BOOL , "aeroengine_failed_4"); - INITDATA(DD_AEROENGINE_FAILED_5 , DC_BOOL , "aeroengine_failed_5"); - INITDATA(DD_AEROENGINE_RPM_0 , DC_FLOAT, "aeroengine_rpm_0"); - INITDATA(DD_AEROENGINE_RPM_1 , DC_FLOAT, "aeroengine_rpm_1"); - INITDATA(DD_AEROENGINE_RPM_2 , DC_FLOAT, "aeroengine_rpm_2"); - INITDATA(DD_AEROENGINE_RPM_3 , DC_FLOAT, "aeroengine_rpm_3"); - INITDATA(DD_AEROENGINE_RPM_4 , DC_FLOAT, "aeroengine_rpm_4"); - INITDATA(DD_AEROENGINE_RPM_5 , DC_FLOAT, "aeroengine_rpm_5"); - INITDATA(DD_AIRSPEED , DC_FLOAT, "airspeed"); - INITDATA(DD_WING_AOA_0 , DC_FLOAT, "wing_aoa_0"); - INITDATA(DD_WING_AOA_1 , DC_FLOAT, "wing_aoa_1"); - INITDATA(DD_WING_AOA_2 , DC_FLOAT, "wing_aoa_2"); - INITDATA(DD_WING_AOA_3 , DC_FLOAT, "wing_aoa_3"); - INITDATA(DD_WING_AOA_4 , DC_FLOAT, "wing_aoa_4"); - INITDATA(DD_WING_AOA_5 , DC_FLOAT, "wing_aoa_5"); - INITDATA(DD_ALTITUDE , DC_FLOAT, "altitude"); - INITDATA(DD_ALTITUDE_STRING , DC_CHAR , "altitude_string"); - INITDATA(DD_EDITOR_NODE_INFO , DC_CHAR , "editor_node_info"); - - INITDATA(DD_ODOMETER_TOTAL , DC_FLOAT, "odometer_total"); - INITDATA(DD_ODOMETER_USER , DC_FLOAT, "odometer_user"); - - INITDATA(DD_SIGNAL_TURNLEFT , DC_BOOL, "signal_turnleft"); - INITDATA(DD_SIGNAL_TURNRIGHT , DC_BOOL, "signal_turnright"); + INITDATA(DD_ENGINE_RPM, DC_FLOAT, "rpm"); + INITDATA(DD_ENGINE_SPEEDO_KPH, DC_FLOAT, "speedo_kph"); + INITDATA(DD_ENGINE_SPEEDO_MPH, DC_FLOAT, "speedo_mph"); + INITDATA(DD_ENGINE_TURBO, DC_FLOAT, "engine_turbo"); + INITDATA(DD_ENGINE_IGNITION, DC_BOOL, "engine_ignition"); + INITDATA(DD_ENGINE_BATTERY, DC_BOOL, "engine_battery"); + INITDATA(DD_ENGINE_CLUTCH_WARNING, DC_BOOL, "engine_clutch_warning"); + INITDATA(DD_ENGINE_GEAR, DC_INT, "engine_gear"); + INITDATA(DD_ENGINE_NUM_GEAR, DC_INT, "engine_num_gear"); + INITDATA(DD_ENGINE_GEAR_STRING, DC_CHAR, "engine_gear_string"); + INITDATA(DD_ENGINE_AUTOGEAR_STRING, DC_CHAR, "engine_autogear_string"); + INITDATA(DD_ENGINE_AUTO_GEAR, DC_INT, "engine_auto_gear"); + INITDATA(DD_ENGINE_CLUTCH, DC_FLOAT, "engine_clutch"); + INITDATA(DD_BRAKE, DC_FLOAT, "brake"); + INITDATA(DD_ACCELERATOR, DC_FLOAT, "accelerator"); + INITDATA(DD_ROLL, DC_FLOAT, "roll"); + INITDATA(DD_ROLL_CORR, DC_FLOAT, "roll_corr"); + INITDATA(DD_ROLL_CORR_ACTIVE, DC_BOOL, "roll_corr_active"); + INITDATA(DD_PITCH, DC_FLOAT, "pitch"); + INITDATA(DD_PARKINGBRAKE, DC_BOOL, "parkingbrake"); + INITDATA(DD_LOCKED, DC_BOOL, "locked"); + INITDATA(DD_LOW_PRESSURE, DC_BOOL, "low_pressure"); + INITDATA(DD_LIGHTS, DC_BOOL, "lights"); + INITDATA(DD_TRACTIONCONTROL_MODE, DC_INT, "tractioncontrol_mode"); + INITDATA(DD_ANTILOCKBRAKE_MODE, DC_INT, "antilockbrake_mode"); + INITDATA(DD_TIES_MODE, DC_INT, "ties_mode"); + INITDATA(DD_SCREW_THROTTLE_0, DC_FLOAT, "screw_throttle_0"); + INITDATA(DD_SCREW_THROTTLE_1, DC_FLOAT, "screw_throttle_1"); + INITDATA(DD_SCREW_THROTTLE_2, DC_FLOAT, "screw_throttle_2"); + INITDATA(DD_SCREW_THROTTLE_3, DC_FLOAT, "screw_throttle_3"); + INITDATA(DD_SCREW_THROTTLE_4, DC_FLOAT, "screw_throttle_4"); + INITDATA(DD_SCREW_THROTTLE_5, DC_FLOAT, "screw_throttle_5"); + INITDATA(DD_SCREW_STEER_0, DC_FLOAT, "screw_steer_0"); + INITDATA(DD_SCREW_STEER_1, DC_FLOAT, "screw_steer_1"); + INITDATA(DD_SCREW_STEER_2, DC_FLOAT, "screw_steer_2"); + INITDATA(DD_SCREW_STEER_3, DC_FLOAT, "screw_steer_3"); + INITDATA(DD_SCREW_STEER_4, DC_FLOAT, "screw_steer_4"); + INITDATA(DD_SCREW_STEER_5, DC_FLOAT, "screw_steer_5"); + INITDATA(DD_WATER_DEPTH, DC_FLOAT, "water_depth"); + INITDATA(DD_WATER_SPEED, DC_FLOAT, "water_speed"); + INITDATA(DD_AEROENGINE_THROTTLE_0, DC_FLOAT, "aeroengine_throttle_0"); + INITDATA(DD_AEROENGINE_THROTTLE_1, DC_FLOAT, "aeroengine_throttle_1"); + INITDATA(DD_AEROENGINE_THROTTLE_2, DC_FLOAT, "aeroengine_throttle_2"); + INITDATA(DD_AEROENGINE_THROTTLE_3, DC_FLOAT, "aeroengine_throttle_3"); + INITDATA(DD_AEROENGINE_THROTTLE_4, DC_FLOAT, "aeroengine_throttle_4"); + INITDATA(DD_AEROENGINE_THROTTLE_5, DC_FLOAT, "aeroengine_throttle_5"); + INITDATA(DD_AEROENGINE_FAILED_0, DC_BOOL, "aeroengine_failed_0"); + INITDATA(DD_AEROENGINE_FAILED_1, DC_BOOL, "aeroengine_failed_1"); + INITDATA(DD_AEROENGINE_FAILED_2, DC_BOOL, "aeroengine_failed_2"); + INITDATA(DD_AEROENGINE_FAILED_3, DC_BOOL, "aeroengine_failed_3"); + INITDATA(DD_AEROENGINE_FAILED_4, DC_BOOL, "aeroengine_failed_4"); + INITDATA(DD_AEROENGINE_FAILED_5, DC_BOOL, "aeroengine_failed_5"); + INITDATA(DD_AEROENGINE_RPM_0, DC_FLOAT, "aeroengine_rpm_0"); + INITDATA(DD_AEROENGINE_RPM_1, DC_FLOAT, "aeroengine_rpm_1"); + INITDATA(DD_AEROENGINE_RPM_2, DC_FLOAT, "aeroengine_rpm_2"); + INITDATA(DD_AEROENGINE_RPM_3, DC_FLOAT, "aeroengine_rpm_3"); + INITDATA(DD_AEROENGINE_RPM_4, DC_FLOAT, "aeroengine_rpm_4"); + INITDATA(DD_AEROENGINE_RPM_5, DC_FLOAT, "aeroengine_rpm_5"); + INITDATA(DD_AIRSPEED, DC_FLOAT, "airspeed"); + INITDATA(DD_WING_AOA_0, DC_FLOAT, "wing_aoa_0"); + INITDATA(DD_WING_AOA_1, DC_FLOAT, "wing_aoa_1"); + INITDATA(DD_WING_AOA_2, DC_FLOAT, "wing_aoa_2"); + INITDATA(DD_WING_AOA_3, DC_FLOAT, "wing_aoa_3"); + INITDATA(DD_WING_AOA_4, DC_FLOAT, "wing_aoa_4"); + INITDATA(DD_WING_AOA_5, DC_FLOAT, "wing_aoa_5"); + INITDATA(DD_ALTITUDE, DC_FLOAT, "altitude"); + INITDATA(DD_ALTITUDE_STRING, DC_CHAR, "altitude_string"); + INITDATA(DD_EDITOR_NODE_INFO, DC_CHAR, "editor_node_info"); + + INITDATA(DD_ODOMETER_TOTAL, DC_FLOAT, "odometer_total"); + INITDATA(DD_ODOMETER_USER, DC_FLOAT, "odometer_user"); + + INITDATA(DD_SIGNAL_TURNLEFT, DC_BOOL, "signal_turnleft"); + INITDATA(DD_SIGNAL_TURNRIGHT, DC_BOOL, "signal_turnright"); // load dash fonts MyGUI::ResourceManager::getInstance().load("MyGUI_FontsDash.xml"); } @@ -121,21 +120,19 @@ DashBoardManager::~DashBoardManager(void) // free all objects for (int i = 0; i < free_dashboard; i++) { - if (!dashboards[i]) - continue; + if (!dashboards[i]) continue; - delete(dashboards[i]); + delete (dashboards[i]); dashboards[i] = 0; } } -int DashBoardManager::getLinkIDForName(Ogre::String& str) +int DashBoardManager::getLinkIDForName(Ogre::String &str) { - const char* s = str.c_str(); + const char *s = str.c_str(); for (int i = 0; i < DD_MAX; i++) { - if (!strcmp(data[i].name, s)) - return i; + if (!strcmp(data[i].name, s)) return i; } return -1; } @@ -148,7 +145,7 @@ int DashBoardManager::loadDashBoard(Ogre::String filename, bool textureLayer) return 1; } - DashBoard* d = new DashBoard(this, filename, textureLayer); + DashBoard *d = new DashBoard(this, filename, textureLayer); d->setVisible(true); dashboards[free_dashboard] = d; @@ -157,7 +154,7 @@ int DashBoardManager::loadDashBoard(Ogre::String filename, bool textureLayer) return 0; } -void DashBoardManager::update(float& dt) +void DashBoardManager::update(float &dt) { // TODO: improve logic: only update visible dashboards for (int i = 0; i < free_dashboard; i++) @@ -178,12 +175,9 @@ float DashBoardManager::getNumeric(size_t key) { switch (data[key].type) { - case DC_BOOL: - return data[key].data.value_bool ? 1.0f : 0.0f; - case(DC_INT): - return (float)data[key].data.value_int; - case(DC_FLOAT): - return data[key].data.value_float; + case DC_BOOL: return data[key].data.value_bool ? 1.0f : 0.0f; + case (DC_INT): return (float)data[key].data.value_int; + case (DC_FLOAT): return data[key].data.value_float; } return 0; } @@ -193,8 +187,7 @@ void DashBoardManager::setVisible(bool visibility) visible = visibility; for (int i = 0; i < free_dashboard; i++) { - if (!dashboards[i]->getIsTextureLayer()) - dashboards[i]->setVisible(visibility); + if (!dashboards[i]->getIsTextureLayer()) dashboards[i]->setVisible(visibility); } } @@ -202,8 +195,7 @@ void DashBoardManager::setVisible3d(bool visibility) { for (int i = 0; i < free_dashboard; i++) { - if (dashboards[i]->getIsTextureLayer()) - dashboards[i]->setVisible(visibility, false); + if (dashboards[i]->getIsTextureLayer()) dashboards[i]->setVisible(visibility, false); } } @@ -211,22 +203,21 @@ void DashBoardManager::windowResized() { for (int i = 0; i < free_dashboard; i++) { - if (dashboards[i]) - dashboards[i]->windowResized(); + if (dashboards[i]) dashboards[i]->windowResized(); } } // DASHBOARD class below -DashBoard::DashBoard(DashBoardManager* manager, Ogre::String filename, bool _textureLayer) : manager(manager), filename(filename), free_controls(0), visible(false), mainWidget(nullptr), textureLayer(_textureLayer) +DashBoard::DashBoard(DashBoardManager *manager, Ogre::String filename, bool _textureLayer) + : manager(manager), filename(filename), free_controls(0), visible(false), mainWidget(nullptr), textureLayer(_textureLayer) { // use 'this' class pointer to make layout unique prefix = MyGUI::utility::toString(this, "_"); memset(&controls, 0, sizeof(controls)); loadLayout(filename); // hide first - if (mainWidget) - mainWidget->setVisible(false); + if (mainWidget) mainWidget->setVisible(false); } DashBoard::~DashBoard() @@ -245,7 +236,7 @@ void DashBoard::updateFeatures() } } -void DashBoard::update(float& dt) +void DashBoard::update(float &dt) { // walk all controls and animate them for (int i = 0; i < free_controls; i++) @@ -256,10 +247,11 @@ void DashBoard::update(float& dt) // get the value float val = manager->getNumeric(controls[i].linkID); // calculate the angle - float angle = (val - controls[i].vmin) * (controls[i].wmax - controls[i].wmin) / (controls[i].vmax - controls[i].vmin) + controls[i].wmin; + float angle = + (val - controls[i].vmin) * (controls[i].wmax - controls[i].wmin) / (controls[i].vmax - controls[i].vmin) + + controls[i].wmin; - if (fabs(val - controls[i].last) < 0.02f) - continue; + if (fabs(val - controls[i].last) < 0.02f) continue; controls[i].last = val; @@ -279,27 +271,23 @@ void DashBoard::update(float& dt) if (controls[i].condition == CONDITION_GREATER) { float val = manager->getNumeric(controls[i].linkID); - state = (val > controls[i].conditionArgument); + state = (val > controls[i].conditionArgument); } else if (controls[i].condition == CONDITION_LESSER) { float val = manager->getNumeric(controls[i].linkID); - state = (val < controls[i].conditionArgument); + state = (val < controls[i].conditionArgument); } else { state = (manager->getNumeric(controls[i].linkID) > 0); } - if (state == controls[i].lastState) - continue; + if (state == controls[i].lastState) continue; controls[i].lastState = state; // switch states - if (state) - { - controls[i].img->setImageTexture(String(controls[i].texture) + "-on.png"); - } + if (state) { controls[i].img->setImageTexture(String(controls[i].texture) + "-on.png"); } else { controls[i].img->setImageTexture(String(controls[i].texture) + "-off.png"); @@ -311,8 +299,7 @@ void DashBoard::update(float& dt) String fn = String(controls[i].texture) + String("-") + TOSTRING((int)val) + String(".png"); - if (fabs(val - controls[i].last) < 0.2f) - continue; + if (fabs(val - controls[i].last) < 0.2f) continue; controls[i].last = val; controls[i].img->setImageTexture(fn); @@ -321,11 +308,12 @@ void DashBoard::update(float& dt) { float val = manager->getNumeric(controls[i].linkID); - if (fabs(val - controls[i].last) < 0.2f) - continue; + if (fabs(val - controls[i].last) < 0.2f) continue; controls[i].last = val; - float scale = (val - controls[i].vmin) * (controls[i].wmax - controls[i].wmin) / (controls[i].vmax - controls[i].vmin) + controls[i].wmin; + float scale = + (val - controls[i].vmin) * (controls[i].wmax - controls[i].wmin) / (controls[i].vmax - controls[i].vmin) + + controls[i].wmin; if (controls[i].direction == DIRECTION_UP) { controls[i].widget->setPosition(controls[i].initialPosition.left, controls[i].initialPosition.top - scale); @@ -351,11 +339,12 @@ void DashBoard::update(float& dt) { float val = manager->getNumeric(controls[i].linkID); - if (fabs(val - controls[i].last) < 0.2f) - continue; + if (fabs(val - controls[i].last) < 0.2f) continue; controls[i].last = val; - float translation = (val - controls[i].vmin) * (controls[i].wmax - controls[i].wmin) / (controls[i].vmax - controls[i].vmin) + controls[i].wmin; + float translation = + (val - controls[i].vmin) * (controls[i].wmax - controls[i].wmin) / (controls[i].vmax - controls[i].vmin) + + controls[i].wmin; if (controls[i].direction == DIRECTION_UP) controls[i].widget->setPosition(controls[i].initialPosition.left, controls[i].initialPosition.top - translation); else if (controls[i].direction == DIRECTION_DOWN) @@ -369,25 +358,18 @@ void DashBoard::update(float& dt) { float val = manager->getNumeric(controls[i].linkID); - if (fabs(val - controls[i].last) < 0.2f) - continue; + if (fabs(val - controls[i].last) < 0.2f) continue; controls[i].last = val; MyGUI::UString s; - if (strlen(controls[i].format) == 0) - { - s = Ogre::StringConverter::toString(val); - } + if (strlen(controls[i].format) == 0) { s = Ogre::StringConverter::toString(val); } else { char tmp[1024] = ""; sprintf(tmp, controls[i].format, val); // Detect and eliminate negative zero (-0) on output - if (strcmp(tmp, controls[i].format_neg_zero) == 0) - { - sprintf(tmp, controls[i].format, 0.f); - } + if (strcmp(tmp, controls[i].format_neg_zero) == 0) { sprintf(tmp, controls[i].format, 0.f); } s = MyGUI::UString(tmp); } @@ -396,7 +378,7 @@ void DashBoard::update(float& dt) } else if (controls[i].animationType == ANIM_TEXTSTRING) { - char* val = manager->getChar(controls[i].linkID); + char *val = manager->getChar(controls[i].linkID); controls[i].txt->setCaption(MyGUI::UString(val)); } } @@ -404,15 +386,13 @@ void DashBoard::update(float& dt) void DashBoard::windowResized() { - if (!mainWidget) - return; + if (!mainWidget) return; mainWidget->setPosition(0, 0); if (textureLayer) { // texture layers are independent from the screen size, but rather from the layer texture size TexturePtr tex = TextureManager::getSingleton().getByName("RTTTexture1"); - if (!tex.isNull()) - mainWidget->setSize(tex->getWidth(), tex->getHeight()); + if (!tex.isNull()) mainWidget->setSize(tex->getWidth(), tex->getHeight()); } else { @@ -423,9 +403,9 @@ void DashBoard::windowResized() void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) { - std::string name = w->getName(); - std::string anim = w->getUserString("anim"); - std::string debug = w->getUserString("debug"); + std::string name = w->getName(); + std::string anim = w->getUserString("anim"); + std::string debug = w->getUserString("debug"); std::string linkArgs = w->getUserString("link"); // make it unclickable @@ -462,13 +442,12 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) layoutLink_t ctrl; memset(&ctrl, 0, sizeof(ctrl)); - if (!name.empty()) - strncpy(ctrl.name, name.c_str(), 255); - ctrl.widget = w; - ctrl.initialSize = w->getSize(); + if (!name.empty()) strncpy(ctrl.name, name.c_str(), 255); + ctrl.widget = w; + ctrl.initialSize = w->getSize(); ctrl.initialPosition = w->getPosition(); - ctrl.last = 1337.1337f; // force update - ctrl.lastState = true; + ctrl.last = 1337.1337f; // force update + ctrl.lastState = true; // establish the link { @@ -477,7 +456,7 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) String linkName = ""; if (linkArgs.empty()) { - LOG("Dashboard ("+filename+"/"+name+"): empty Link"); + LOG("Dashboard (" + filename + "/" + name + "): empty Link"); return; } // conditional checks @@ -487,13 +466,13 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) Ogre::StringVector args = Ogre::StringUtil::split(linkArgs, ">"); if (args.size() == 2) { - linkName = args[0]; + linkName = args[0]; ctrl.conditionArgument = StringConverter::parseReal(args[1]); - ctrl.condition = CONDITION_GREATER; + ctrl.condition = CONDITION_GREATER; } else { - LOG("Dashboard ("+filename+"/"+name+"): error in conditional Link: " + linkArgs); + LOG("Dashboard (" + filename + "/" + name + "): error in conditional Link: " + linkArgs); return; } } @@ -502,28 +481,28 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) Ogre::StringVector args = Ogre::StringUtil::split(linkArgs, "<"); if (args.size() == 2) { - linkName = args[0]; + linkName = args[0]; ctrl.conditionArgument = StringConverter::parseReal(args[1]); - ctrl.condition = CONDITION_LESSER; + ctrl.condition = CONDITION_LESSER; } else { - LOG("Dashboard ("+filename+"/"+name+"): error in conditional Link: " + linkArgs); + LOG("Dashboard (" + filename + "/" + name + "): error in conditional Link: " + linkArgs); return; } } else { - ctrl.condition = CONDITION_NONE; + ctrl.condition = CONDITION_NONE; ctrl.conditionArgument = 0; - linkName = linkArgs; + linkName = linkArgs; } // now try to get the enum id for it int linkID = manager->getLinkIDForName(linkName); if (linkID < 0) { - LOG("Dashboard ("+filename+"/"+name+"): unknown Link: " + linkName); + LOG("Dashboard (" + filename + "/" + name + "): unknown Link: " + linkName); return; } @@ -537,12 +516,10 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) ctrl.vmax = StringConverter::parseReal(w->getUserString("vmax")); String texture = w->getUserString("texture"); - if (!texture.empty()) - strncpy(ctrl.texture, texture.c_str(), 255); + if (!texture.empty()) strncpy(ctrl.texture, texture.c_str(), 255); String format = w->getUserString("format"); - if (!format.empty()) - strncpy(ctrl.format, format.c_str(), 255); + if (!format.empty()) strncpy(ctrl.format, format.c_str(), 255); String direction = w->getUserString("direction"); if (direction == "right") @@ -555,7 +532,7 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) ctrl.direction = DIRECTION_UP; else if (!direction.empty()) { - LOG("Dashboard ("+filename+"/"+name+"): unknown direction: " + direction); + LOG("Dashboard (" + filename + "/" + name + "): unknown direction: " + direction); return; } // then specializations @@ -579,12 +556,12 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) } catch (...) { - LOG("Dashboard ("+filename+"/"+name+"): Rotating controls must use the RotatingSkin"); + LOG("Dashboard (" + filename + "/" + name + "): Rotating controls must use the RotatingSkin"); return; } if (!ctrl.rotImg) { - LOG("Dashboard ("+filename+"/"+name+"): error loading rotation control"); + LOG("Dashboard (" + filename + "/" + name + "): error loading rotation control"); return; } @@ -596,7 +573,7 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) ctrl.animationType = ANIM_SCALE; if (ctrl.direction == DIRECTION_NONE) { - LOG("Dashboard ("+filename+"/"+name+"): direction empty: scale needs a direction"); + LOG("Dashboard (" + filename + "/" + name + "): direction empty: scale needs a direction"); return; } } @@ -605,17 +582,17 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) ctrl.animationType = ANIM_TRANSLATE; if (ctrl.direction == DIRECTION_NONE) { - LOG("Dashboard ("+filename+"/"+name+"): direction empty: translate needs a direction"); + LOG("Dashboard (" + filename + "/" + name + "): direction empty: translate needs a direction"); return; } } else if (anim == "series") { ctrl.animationType = ANIM_SERIES; - ctrl.img = (MyGUI::ImageBox *)w; //w->getSubWidgetMain()->castType(); + ctrl.img = (MyGUI::ImageBox *)w; // w->getSubWidgetMain()->castType(); if (!ctrl.img) { - LOG("Dashboard ("+filename+"/"+name+"): error loading series control"); + LOG("Dashboard (" + filename + "/" + name + "): error loading series control"); return; } } @@ -630,7 +607,7 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) } catch (...) { - LOG("Dashboard ("+filename+"/"+name+"): textcolor controls must use the TextBox Control"); + LOG("Dashboard (" + filename + "/" + name + "): textcolor controls must use the TextBox Control"); return; } } @@ -643,17 +620,14 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) } catch (...) { - LOG("Dashboard ("+filename+"/"+name+"): Lamp controls must use the ImageBox Control"); + LOG("Dashboard (" + filename + "/" + name + "): Lamp controls must use the ImageBox Control"); return; } ctrl.animationType = ANIM_TEXTFORMAT; // Prepare for eliminating negative zero (-0.0) display // Must be done on string-level because -0.001 with format "%1.0f" would still produce "-0" - if (std::strlen(ctrl.format)) - { - std::snprintf(ctrl.format_neg_zero, 255, ctrl.format, -0.f); - } + if (std::strlen(ctrl.format)) { std::snprintf(ctrl.format_neg_zero, 255, ctrl.format, -0.f); } } else if (anim == "textstring") { @@ -664,7 +638,7 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) } catch (...) { - LOG("Dashboard ("+filename+"/"+name+"): Lamp controls must use the ImageBox Control"); + LOG("Dashboard (" + filename + "/" + name + "): Lamp controls must use the ImageBox Control"); return; } ctrl.animationType = ANIM_TEXTSTRING; @@ -686,10 +660,10 @@ void DashBoard::loadLayoutRecursive(MyGUI::WidgetPtr w) } */ ctrl.animationType = ANIM_LAMP; - ctrl.img = (MyGUI::ImageBox *)w; //w->getSubWidgetMain()->castType(); + ctrl.img = (MyGUI::ImageBox *)w; // w->getSubWidgetMain()->castType(); if (!ctrl.img) { - LOG("Dashboard ("+filename+"/"+name+"): error loading Lamp control"); + LOG("Dashboard (" + filename + "/" + name + "): error loading Lamp control"); return; } } @@ -721,8 +695,7 @@ void DashBoard::loadLayout(Ogre::String filename) } // if this thing should be rendered to texture, relocate the main window to the RTT layer - if (textureLayer && mainWidget) - mainWidget->detachFromWidget("RTTLayer1"); + if (textureLayer && mainWidget) mainWidget->detachFromWidget("RTTLayer1"); } void DashBoard::setVisible(bool v, bool smooth) diff --git a/source/main/gui/DashBoardManager.h b/source/main/gui/DashBoardManager.h index f8a080acbd..9a7a4cf7ba 100644 --- a/source/main/gui/DashBoardManager.h +++ b/source/main/gui/DashBoardManager.h @@ -25,29 +25,26 @@ #pragma once - #include "RoRPrerequisites.h" #include - #include // TODO: Clean up this header #define DD_MAXCHAR 255 -#define DD_MAX_SCREWPROP 6 +#define DD_MAX_SCREWPROP 6 #define DD_MAX_AEROENGINE 6 -#define DD_MAX_WING 6 -#define MAX_DASH 6 +#define DD_MAX_WING 6 +#define MAX_DASH 6 -#define MAX_CONTROLS 1024 +#define MAX_CONTROLS 1024 -typedef union dataContainer_t -{ - bool value_bool; - int value_int; +typedef union dataContainer_t { + bool value_bool; + int value_int; float value_float; - char value_char[DD_MAXCHAR]; + char value_char[DD_MAXCHAR]; } dataContainer_t; enum @@ -61,10 +58,10 @@ enum typedef struct dashData_t { - char type; // DC_* + char type; // DC_* dataContainer_t data; - bool enabled; - const char* name; // char string of name + bool enabled; + const char * name; // char string of name dashData_t() : type(DC_INVALID), name("") { @@ -72,7 +69,7 @@ typedef struct dashData_t enabled = false; } - dashData_t(char type, const char* name) : type(type), name(name) + dashData_t(char type, const char *name) : type(type), name(name) { memset(&data, 0, sizeof(data)); enabled = true; @@ -84,14 +81,14 @@ typedef struct dashData_t enum { DD_ENGINE_RPM, - DD_ENGINE_SPEEDO_KPH, /// speedo in kilometer per hour - DD_ENGINE_SPEEDO_MPH, /// speedo in miles per hour - DD_ENGINE_TURBO, /// turbo gauge + DD_ENGINE_SPEEDO_KPH, /// speedo in kilometer per hour + DD_ENGINE_SPEEDO_MPH, /// speedo in miles per hour + DD_ENGINE_TURBO, /// turbo gauge DD_ENGINE_IGNITION, - DD_ENGINE_BATTERY, /// battery lamp - DD_ENGINE_CLUTCH_WARNING, /// clutch warning lamp + DD_ENGINE_BATTERY, /// battery lamp + DD_ENGINE_CLUTCH_WARNING, /// clutch warning lamp - DD_ENGINE_GEAR, /// current gear + DD_ENGINE_GEAR, /// current gear DD_ENGINE_NUM_GEAR, DD_ENGINE_GEAR_STRING, /// string like "/" DD_ENGINE_AUTOGEAR_STRING, /// string like "P R N G" @@ -99,20 +96,20 @@ enum DD_ENGINE_CLUTCH, // the engines clutch - DD_BRAKE, // the brake application in % 0-1 + DD_BRAKE, // the brake application in % 0-1 DD_ACCELERATOR, // accelerator pedal in %, 0-1 - DD_ROLL, // roll of the chassis - DD_ROLL_CORR, // correction roll of the chassis + DD_ROLL, // roll of the chassis + DD_ROLL_CORR, // correction roll of the chassis DD_ROLL_CORR_ACTIVE, // correction rolling active DD_PITCH, /// chassis pitch DD_PARKINGBRAKE, /// parking brake status - DD_LOCKED, /// locked lamp + DD_LOCKED, /// locked lamp DD_LOW_PRESSURE, /// low pressure - DD_LIGHTS, /// lights on + DD_LIGHTS, /// lights on DD_TRACTIONCONTROL_MODE, DD_ANTILOCKBRAKE_MODE, @@ -184,71 +181,117 @@ enum // this class is NOT intended to be thread safe - performance is required class DashBoardManager : public ZeroedMemoryAllocator { -public: + public: DashBoardManager(void); ~DashBoardManager(void); // Getter / Setter - inline bool _getBool(size_t key) { return data[key].data.value_bool; }; - inline int _getInt(size_t key) { return data[key].data.value_int; }; - inline float _getFloat(size_t key) { return data[key].data.value_float; }; + inline bool _getBool(size_t key) + { + return data[key].data.value_bool; + }; + inline int _getInt(size_t key) + { + return data[key].data.value_int; + }; + inline float _getFloat(size_t key) + { + return data[key].data.value_float; + }; inline float getNumeric(size_t key); - inline char* getChar(size_t key) { return data[key].data.value_char; }; - inline bool getEnabled(size_t key) { return data[key].enabled; }; + inline char *getChar(size_t key) + { + return data[key].data.value_char; + }; + inline bool getEnabled(size_t key) + { + return data[key].enabled; + }; - inline void setBool(size_t key, bool& val) { data[key].data.value_bool = val; }; - inline void setInt(size_t key, int& val) { data[key].data.value_int = val; }; - inline void setFloat(size_t key, float& val) { data[key].data.value_float = val; }; - inline void setChar(size_t key, const char* val) { strncpy(data[key].data.value_char, val, DD_MAXCHAR); }; + inline void setBool(size_t key, bool &val) + { + data[key].data.value_bool = val; + }; + inline void setInt(size_t key, int &val) + { + data[key].data.value_int = val; + }; + inline void setFloat(size_t key, float &val) + { + data[key].data.value_float = val; + }; + inline void setChar(size_t key, const char *val) + { + strncpy(data[key].data.value_char, val, DD_MAXCHAR); + }; - inline void setEnabled(size_t key, bool val) { data[key].enabled = val; }; + inline void setEnabled(size_t key, bool val) + { + data[key].enabled = val; + }; - inline int getDataType(size_t key) { return data[key].type; }; + inline int getDataType(size_t key) + { + return data[key].type; + }; - int getLinkIDForName(Ogre::String& str); + int getLinkIDForName(Ogre::String &str); int loadDashBoard(Ogre::String filename, bool textureLayer); - void update(float& dt); + void update(float &dt); void updateFeatures(); - bool WasDashboardLoaded() const { return (free_dashboard > 0); }; + bool WasDashboardLoaded() const + { + return (free_dashboard > 0); + }; void setVisible(bool visibility); void setVisible3d(bool visibility); - bool getVisible() { return visible; }; + bool getVisible() + { + return visible; + }; void windowResized(); -protected: - bool visible; + + protected: + bool visible; dashData_t data[DD_MAX]; - DashBoard* dashboards[MAX_DASH]; - int free_dashboard; + DashBoard *dashboards[MAX_DASH]; + int free_dashboard; }; class DashBoard : public ZeroedMemoryAllocator { - //friend class DashBoardManager; -public: - DashBoard(DashBoardManager* manager, Ogre::String filename, bool textureLayer); + // friend class DashBoardManager; + public: + DashBoard(DashBoardManager *manager, Ogre::String filename, bool textureLayer); ~DashBoard(); void setVisible(bool visible, bool smooth = true); - bool getVisible() { return visible; }; + bool getVisible() + { + return visible; + }; - bool getIsTextureLayer() { return textureLayer; } + bool getIsTextureLayer() + { + return textureLayer; + } - void update(float& dt); + void update(float &dt); void updateFeatures(); void windowResized(); -protected: - DashBoardManager* manager; - Ogre::String filename; + protected: + DashBoardManager * manager; + Ogre::String filename; MyGUI::VectorWidgetPtr widgets; - MyGUI::WindowPtr mainWidget; - bool visible, textureLayer; - std::string prefix; + MyGUI::WindowPtr mainWidget; + bool visible, textureLayer; + std::string prefix; enum { @@ -282,34 +325,35 @@ class DashBoard : public ZeroedMemoryAllocator // linking attributes typedef struct layoutLink_t { - int linkID; // DD_* + int linkID; // DD_* char animationType; // ANIM_* float wmin; // rotation/offset whatever (widget min/max) float wmax; float vmin; // value min/max float vmax; - int condition; // CONDITION_* + int condition; // CONDITION_* float conditionArgument; - char direction; // DIRECTION_* - char format[255]; // string format - char texture[255]; // texture filename - char name[255]; // widget name - char format_neg_zero[255]; //!< Test for undesired '-0.0' on display. Only for link type "format". Empty if not applicable. - - MyGUI::Widget* widget; - MyGUI::RotatingSkin* rotImg; - MyGUI::ImageBox* img; - MyGUI::TextBox* txt; - MyGUI::IntSize initialSize; - MyGUI::IntPoint initialPosition; + char direction; // DIRECTION_* + char format[255]; // string format + char texture[255]; // texture filename + char name[255]; // widget name + char + format_neg_zero[255]; //!< Test for undesired '-0.0' on display. Only for link type "format". Empty if not applicable. + + MyGUI::Widget * widget; + MyGUI::RotatingSkin *rotImg; + MyGUI::ImageBox * img; + MyGUI::TextBox * txt; + MyGUI::IntSize initialSize; + MyGUI::IntPoint initialPosition; float last; - bool lastState; + bool lastState; } layoutLink_t; - void loadLayout(Ogre::String filename); - void loadLayoutRecursive(MyGUI::WidgetPtr ptr); + void loadLayout(Ogre::String filename); + void loadLayoutRecursive(MyGUI::WidgetPtr ptr); layoutLink_t controls[MAX_CONTROLS]; - int free_controls; + int free_controls; }; diff --git a/source/main/gui/GUIInputManager.cpp b/source/main/gui/GUIInputManager.cpp index 5329aa17cb..bd234c8e71 100644 --- a/source/main/gui/GUIInputManager.cpp +++ b/source/main/gui/GUIInputManager.cpp @@ -20,22 +20,21 @@ #include #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 -#include + #include #endif -#include "GUIInputManager.h" - #include "Application.h" +#include "GUIInputManager.h" #include "GUIManager.h" -#include "GUI_TopMenubar.h" -#include "GUI_GameMainMenu.h" // TODO: remove this hack ~ only_a_ptr, 02/2017 +#include "GUI_GameMainMenu.h" // TODO: remove this hack ~ only_a_ptr, 02/2017 #include "GUI_GamePauseMenu.h" // TODO: remove this hack ~ only_a_ptr, 02/2017 +#include "GUI_TopMenubar.h" #include "OverlayWrapper.h" #include "RoRFrameListener.h" // SimController #include "SceneMouse.h" -#include #include +#include #include #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 @@ -44,17 +43,15 @@ MyGUI::Char translateWin32Text(MyGUI::KeyCode kc) static WCHAR deadKey = 0; BYTE keyState[256]; - HKL layout = GetKeyboardLayout(0); - if (GetKeyboardState(keyState) == 0) - return 0; + HKL layout = GetKeyboardLayout(0); + if (GetKeyboardState(keyState) == 0) return 0; - int code = *((int*)&kc); - unsigned int vk = MapVirtualKeyEx((UINT)code, 3, layout); - if (vk == 0) - return 0; + int code = *((int *)&kc); + unsigned int vk = MapVirtualKeyEx((UINT)code, 3, layout); + if (vk == 0) return 0; WCHAR buff[3] = {0, 0, 0}; - int ascii = ToUnicodeEx(vk, (UINT)code, keyState, buff, 3, 0, layout); + int ascii = ToUnicodeEx(vk, (UINT)code, keyState, buff, 3, 0, layout); if (ascii == 1 && deadKey != '\0') { // A dead key is stored and we have just converted a character key @@ -63,8 +60,7 @@ MyGUI::Char translateWin32Text(MyGUI::KeyCode kc) WCHAR out[3]; deadKey = '\0'; - if (FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3)) - return out[0]; + if (FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3)) return out[0]; } else if (ascii == 1) { @@ -94,9 +90,7 @@ MyGUI::Char translateWin32Text(MyGUI::KeyCode kc) case 0xB8: // Cedilla: � deadKey = 0x327; break; - default: - deadKey = buff[0]; - break; + default: deadKey = buff[0]; break; } } @@ -104,13 +98,8 @@ MyGUI::Char translateWin32Text(MyGUI::KeyCode kc) } #endif -GUIInputManager::GUIInputManager() : - height(0) - , m_last_mousemove_time(0) - , mCursorX(0) - , mCursorY(0) - , width(0) - , m_is_cursor_supressed(false) +GUIInputManager::GUIInputManager() + : height(0), m_last_mousemove_time(0), mCursorX(0), mCursorY(0), width(0), m_is_cursor_supressed(false) { m_last_mousemove_time = new Ogre::Timer(); } @@ -119,16 +108,15 @@ GUIInputManager::~GUIInputManager() { } -bool GUIInputManager::mouseMoved(const OIS::MouseEvent& _arg) +bool GUIInputManager::mouseMoved(const OIS::MouseEvent &_arg) { this->WakeUpGUI(); RoR::App::GetGuiManager()->GetImGui().InjectMouseMoved(_arg); - if (RoR::App::sim_state.GetActive() == RoR::SimState::RUNNING && RoR::App::GetGuiManager()->IsVisible_TopMenubar()) // dirty hack to block imgui handled input events - { - return true; - } + if (RoR::App::sim_state.GetActive() == RoR::SimState::RUNNING && + RoR::App::GetGuiManager()->IsVisible_TopMenubar()) // dirty hack to block imgui handled input events + { return true; } if (RoR::App::sim_state.GetActive() == RoR::SimState::PAUSED) { @@ -144,12 +132,10 @@ bool GUIInputManager::mouseMoved(const OIS::MouseEvent& _arg) if (handled) { - MyGUI::Widget* w = MyGUI::InputManager::getInstance().getMouseFocusWidget(); + MyGUI::Widget *w = MyGUI::InputManager::getInstance().getMouseFocusWidget(); // hack for console, we want to use the mouse through that control - if (w && w->getName().substr(0, 7) == "Console") - handled = false; - if (w && w->getUserString("interactive") == "0") - handled = false; + if (w && w->getName().substr(0, 7) == "Console") handled = false; + if (w && w->getUserString("interactive") == "0") handled = false; } if (!handled && RoR::App::GetOverlayWrapper() != nullptr) @@ -160,7 +146,8 @@ bool GUIInputManager::mouseMoved(const OIS::MouseEvent& _arg) if (!handled) { - if (RoR::App::GetSimController() != nullptr) // TODO: Fix this hack. Main menu should not use the same input handler as simulation ~ only_a_ptr, 08/2018 + if (RoR::App::GetSimController() != + nullptr) // TODO: Fix this hack. Main menu should not use the same input handler as simulation ~ only_a_ptr, 08/2018 { // not handled by gui bool fixed = RoR::App::GetSimController()->GetSceneMouse().mouseMoved(_arg); @@ -180,7 +167,7 @@ bool GUIInputManager::mouseMoved(const OIS::MouseEvent& _arg) return true; } -bool GUIInputManager::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool GUIInputManager::mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { this->WakeUpGUI(); @@ -194,12 +181,10 @@ bool GUIInputManager::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButton if (handled) { - MyGUI::Widget* w = MyGUI::InputManager::getInstance().getMouseFocusWidget(); + MyGUI::Widget *w = MyGUI::InputManager::getInstance().getMouseFocusWidget(); // hack for console, we want to use the mouse through that control - if (w && w->getName().substr(0, 7) == "Console") - handled = false; - if (w && w->getUserString("interactive") == "0") - handled = false; + if (w && w->getName().substr(0, 7) == "Console") handled = false; + if (w && w->getUserString("interactive") == "0") handled = false; } if (!handled && RoR::App::GetOverlayWrapper()) @@ -209,14 +194,12 @@ bool GUIInputManager::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButton } // TODO: Fix this hack. Main menu should not use the same input handler as simulation ~ only_a_ptr, 08/2018 - if (!handled && (RoR::App::GetSimController() != nullptr)) - { - RoR::App::GetSimController()->GetSceneMouse().mousePressed(_arg, _id); - } + if (!handled && (RoR::App::GetSimController() != nullptr)) + { RoR::App::GetSimController()->GetSceneMouse().mousePressed(_arg, _id); } return handled; } -bool GUIInputManager::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool GUIInputManager::mouseReleased(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { this->WakeUpGUI(); @@ -227,12 +210,10 @@ bool GUIInputManager::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButto if (handled) { - MyGUI::Widget* w = MyGUI::InputManager::getInstance().getMouseFocusWidget(); + MyGUI::Widget *w = MyGUI::InputManager::getInstance().getMouseFocusWidget(); // hack for console, we want to use the mouse through that control - if (w && w->getName().substr(0, 7) == "Console") - handled = false; - if (w && w->getUserString("interactive") == "0") - handled = false; + if (w && w->getName().substr(0, 7) == "Console") handled = false; + if (w && w->getUserString("interactive") == "0") handled = false; } if (!handled && RoR::App::GetOverlayWrapper()) @@ -242,32 +223,25 @@ bool GUIInputManager::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButto } if (!handled && (RoR::App::GetSimController() != nullptr)) - { - RoR::App::GetSimController()->GetSceneMouse().mouseReleased(_arg, _id); - } + { RoR::App::GetSimController()->GetSceneMouse().mouseReleased(_arg, _id); } return handled; } -bool GUIInputManager::keyPressed(const OIS::KeyEvent& _arg) +bool GUIInputManager::keyPressed(const OIS::KeyEvent &_arg) { RoR::App::GetGuiManager()->GetImGui().InjectKeyPressed(_arg); - if (RoR::App::sim_state.GetActive() == RoR::SimState::RUNNING && - RoR::App::GetGuiManager()->IsVisible_TopMenubar() || RoR::App::GetGuiManager()->IsVisible_NodeBeamUtils()) // dirty hack to block imgui handled input events + if (RoR::App::sim_state.GetActive() == RoR::SimState::RUNNING && RoR::App::GetGuiManager()->IsVisible_TopMenubar() || + RoR::App::GetGuiManager()->IsVisible_NodeBeamUtils()) // dirty hack to block imgui handled input events { - if (_arg.key == OIS::KC_RETURN) - { - return true; - } + if (_arg.key == OIS::KC_RETURN) { return true; } } - if (RoR::App::GetGuiManager()->IsVisible_GameMainMenu()) // Special hacky handling of main-menu key control. TODO: Remove this!~ only_a_ptr, 06/2017 + if (RoR::App::GetGuiManager()->IsVisible_GameMainMenu()) // Special hacky handling of main-menu key control. TODO: Remove + // this!~ only_a_ptr, 06/2017 { - if (_arg.key == OIS::KC_UP) - { - RoR::App::GetGuiManager()->GetMainMenu()->KeyUpPressed(); - } - else if (_arg.key == OIS::KC_DOWN) + if (_arg.key == OIS::KC_UP) { RoR::App::GetGuiManager()->GetMainMenu()->KeyUpPressed(); } + else if (_arg.key == OIS::KC_DOWN) { RoR::App::GetGuiManager()->GetMainMenu()->KeyDownPressed(); } @@ -276,13 +250,11 @@ bool GUIInputManager::keyPressed(const OIS::KeyEvent& _arg) RoR::App::GetGuiManager()->GetMainMenu()->EnterKeyPressed(); } } - if (RoR::App::sim_state.GetActive() == RoR::SimState::PAUSED) // Special hacky handling of pause-menu key control. TODO: Remove this!~ only_a_ptr, 06/2017 + if (RoR::App::sim_state.GetActive() == + RoR::SimState::PAUSED) // Special hacky handling of pause-menu key control. TODO: Remove this!~ only_a_ptr, 06/2017 { - if (_arg.key == OIS::KC_UP) - { - RoR::App::GetGuiManager()->GetPauseMenu()->KeyUpPressed(); - } - else if (_arg.key == OIS::KC_DOWN) + if (_arg.key == OIS::KC_UP) { RoR::App::GetGuiManager()->GetPauseMenu()->KeyUpPressed(); } + else if (_arg.key == OIS::KC_DOWN) { RoR::App::GetGuiManager()->GetPauseMenu()->KeyDownPressed(); } @@ -292,14 +264,14 @@ bool GUIInputManager::keyPressed(const OIS::KeyEvent& _arg) } } - MyGUI::Char text = (MyGUI::Char)_arg.text; - MyGUI::KeyCode key = MyGUI::KeyCode::Enum(_arg.key); - int scan_code = MYGUI_GET_SCANCODE(key); + MyGUI::Char text = (MyGUI::Char)_arg.text; + MyGUI::KeyCode key = MyGUI::KeyCode::Enum(_arg.key); + int scan_code = MYGUI_GET_SCANCODE(key); if (scan_code > 70 && scan_code < 84) { static MyGUI::Char nums[13] = {55, 56, 57, 45, 52, 53, 54, 43, 49, 50, 51, 48, 46}; - text = nums[scan_code - 71]; + text = nums[scan_code - 71]; } else if (key == MyGUI::KeyCode::Divide) { @@ -317,31 +289,24 @@ bool GUIInputManager::keyPressed(const OIS::KeyEvent& _arg) if (handled) { - MyGUI::Widget* w = MyGUI::InputManager::getInstance().getKeyFocusWidget(); + MyGUI::Widget *w = MyGUI::InputManager::getInstance().getKeyFocusWidget(); // hack for console, we want to use the mouse through that control - if (w && w->getName().substr(0, 7) == "Console" && w->getName() != "ConsoleInput") - handled = false; + if (w && w->getName().substr(0, 7) == "Console" && w->getName() != "ConsoleInput") handled = false; } - if (!handled) - { - RoR::App::GetSimController()->GetSceneMouse().keyPressed(_arg); - } + if (!handled) { RoR::App::GetSimController()->GetSceneMouse().keyPressed(_arg); } return handled; } -bool GUIInputManager::keyReleased(const OIS::KeyEvent& _arg) +bool GUIInputManager::keyReleased(const OIS::KeyEvent &_arg) { RoR::App::GetGuiManager()->GetImGui().InjectKeyReleased(_arg); - if (RoR::App::sim_state.GetActive() == RoR::SimState::RUNNING && - RoR::App::GetGuiManager()->IsVisible_TopMenubar() || RoR::App::GetGuiManager()->IsVisible_NodeBeamUtils()) // dirty hack to block imgui handled input events + if (RoR::App::sim_state.GetActive() == RoR::SimState::RUNNING && RoR::App::GetGuiManager()->IsVisible_TopMenubar() || + RoR::App::GetGuiManager()->IsVisible_NodeBeamUtils()) // dirty hack to block imgui handled input events { - if (_arg.key == OIS::KC_RETURN) - { - return true; - } + if (_arg.key == OIS::KC_RETURN) { return true; } } // fallback, handle by GUI, then by RoR::SceneMouse @@ -349,23 +314,19 @@ bool GUIInputManager::keyReleased(const OIS::KeyEvent& _arg) if (handled) { - MyGUI::Widget* w = MyGUI::InputManager::getInstance().getKeyFocusWidget(); + MyGUI::Widget *w = MyGUI::InputManager::getInstance().getKeyFocusWidget(); // hack for console, we want to use the mouse through that control - if (w && w->getName().substr(0, 7) == "Console" && w->getName() != "ConsoleInput") - handled = false; + if (w && w->getName().substr(0, 7) == "Console" && w->getName() != "ConsoleInput") handled = false; } - if (!handled) - { - RoR::App::GetSimController()->GetSceneMouse().keyReleased(_arg); - } + if (!handled) { RoR::App::GetSimController()->GetSceneMouse().keyReleased(_arg); } return handled; } void GUIInputManager::setInputViewSize(int _width, int _height) { - this->width = _width; + this->width = _width; this->height = _height; checkPosition(); @@ -396,9 +357,7 @@ void GUIInputManager::WakeUpGUI() { m_last_mousemove_time->reset(); if (!m_is_cursor_supressed) - { - RoR::App::GetGuiManager()->SetMouseCursorVisibility(RoR::GUIManager::MouseCursorVisibility::VISIBLE); - } + { RoR::App::GetGuiManager()->SetMouseCursorVisibility(RoR::GUIManager::MouseCursorVisibility::VISIBLE); } } void GUIInputManager::SupressCursor(bool do_supress) diff --git a/source/main/gui/GUIInputManager.h b/source/main/gui/GUIInputManager.h index 41941f692c..4561a34987 100644 --- a/source/main/gui/GUIInputManager.h +++ b/source/main/gui/GUIInputManager.h @@ -20,7 +20,6 @@ #pragma once - #include "RoRPrerequisites.h" #include @@ -30,8 +29,7 @@ class GUIInputManager { friend class InputEngine; -public: - + public: GUIInputManager(); virtual ~GUIInputManager(); @@ -39,25 +37,26 @@ class GUIInputManager void setMousePosition(int _x, int _y); - float getLastMouseMoveTime() { return m_last_mousemove_time->getMilliseconds(); }; + float getLastMouseMoveTime() + { + return m_last_mousemove_time->getMilliseconds(); + }; void SupressCursor(bool do_supress); -protected: - - virtual bool mouseMoved(const OIS::MouseEvent& _arg); - virtual bool mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - virtual bool mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - virtual bool keyPressed(const OIS::KeyEvent& _arg); - virtual bool keyReleased(const OIS::KeyEvent& _arg); + protected: + virtual bool mouseMoved(const OIS::MouseEvent &_arg); + virtual bool mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + virtual bool mouseReleased(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + virtual bool keyPressed(const OIS::KeyEvent &_arg); + virtual bool keyReleased(const OIS::KeyEvent &_arg); void checkPosition(); -private: - - int mCursorX, mCursorY, width, height; - bool m_is_cursor_supressed; ///< True if cursor was manually hidden. - Ogre::Timer* m_last_mousemove_time; + private: + int mCursorX, mCursorY, width, height; + bool m_is_cursor_supressed; ///< True if cursor was manually hidden. + Ogre::Timer *m_last_mousemove_time; void WakeUpGUI(); }; diff --git a/source/main/gui/GUIManager.cpp b/source/main/gui/GUIManager.cpp index 5cd7067b56..e90b28317b 100644 --- a/source/main/gui/GUIManager.cpp +++ b/source/main/gui/GUIManager.cpp @@ -36,20 +36,20 @@ #include "RTTLayer.h" #include "TerrainManager.h" -//Managed GUI panels +// Managed GUI panels #include "GUI_DebugOptions.h" #include "GUI_FrictionSettings.h" -#include "GUI_GameMainMenu.h" #include "GUI_GameAbout.h" +#include "GUI_GameChatBox.h" #include "GUI_GameConsole.h" +#include "GUI_GameMainMenu.h" #include "GUI_GamePauseMenu.h" -#include "GUI_GameChatBox.h" #include "GUI_GameSettings.h" #include "GUI_LoadingWindow.h" +#include "GUI_MainSelector.h" #include "GUI_MessageBox.h" -#include "GUI_MultiplayerSelector.h" #include "GUI_MultiplayerClientList.h" -#include "GUI_MainSelector.h" +#include "GUI_MultiplayerSelector.h" #include "GUI_NodeBeamUtils.h" #include "GUI_RigSpawnerReportWindow.h" #include "GUI_SimUtils.h" @@ -62,494 +62,578 @@ #define RESOURCE_FILENAME "MyGUI_Core.xml" -namespace RoR { - -struct GuiManagerImpl +namespace RoR { - GuiManagerImpl(): - mygui(nullptr), - mygui_platform(nullptr) - {} - - GUI::GameMainMenu panel_GameMainMenu; - GUI::GameAbout panel_GameAbout; - GUI::GamePauseMenu panel_GamePauseMenu; - GUI::GameSettings panel_GameSettings; - GUI::DebugOptions panel_DebugOptions; - GUI::SimUtils panel_SimUtils; - GUI::MessageBoxDialog panel_MessageBox; - GUI::MultiplayerSelector panel_MultiplayerSelector; - GUI::MainSelector panel_MainSelector; - GUI::GameChatBox panel_ChatBox; - GUI::ActorSpawnerReportWindow panel_SpawnerReport; - GUI::VehicleDescription panel_VehicleDescription; - GUI::MpClientList panel_MpClientList; - GUI::FrictionSettings panel_FrictionSettings; - GUI::TextureToolWindow panel_TextureToolWindow; - GUI::NodeBeamUtils panel_NodeBeamUtils; - GUI::LoadingWindow panel_LoadingWindow; - GUI::TopMenubar panel_TopMenubar; - RoR::Console panel_GameConsole; - - MyGUI::Gui* mygui; - MyGUI::OgrePlatform* mygui_platform; -}; - -GUIManager::GuiTheme::GuiTheme(): - in_progress_text_color(1.f, 0.832031f, 0.f, 1.f), - no_entries_text_color(0.7f, 0.7f, 0.7f, 1.f), - error_text_color(1.f, 0.175439f, 0.175439f, 1.f), - selected_entry_text_color(.9f, 0.7f, 0.05f, 1.f) -{ - try - { - //Setup custom font - Str<500> font_path; - font_path << App::sys_process_dir.GetActive() << PATH_SLASH << "languages" << PATH_SLASH << "Roboto-Medium.ttf"; - ImFontConfig font_config; - font_config.OversampleH = 1; - font_config.OversampleV = 1; - font_config.PixelSnapH = true; - default_font = ImGui::GetIO().Fonts->AddFontFromFileTTF(font_path, 16, &font_config); - assert(default_font); - } - catch (...) - { - LOG("Failed to load font: Roboto-Medium.ttf"); - } - -} - -void GUIManager::SetVisible_GameMainMenu (bool v) { m_impl->panel_GameMainMenu .SetVisible(v); } -void GUIManager::SetVisible_GameAbout (bool v) { m_impl->panel_GameAbout .SetVisible(v); } -void GUIManager::SetVisible_DebugOptions (bool v) { m_impl->panel_DebugOptions .SetVisible(v); } -void GUIManager::SetVisible_MultiplayerSelector (bool v) { m_impl->panel_MultiplayerSelector.SetVisible(v); } -void GUIManager::SetVisible_ChatBox (bool v) { m_impl->panel_ChatBox .SetVisible(v); } -void GUIManager::SetVisible_SpawnerReport (bool v) { m_impl->panel_SpawnerReport .SetVisible(v); } -void GUIManager::SetVisible_VehicleDescription (bool v) { m_impl->panel_VehicleDescription .SetVisible(v); } -void GUIManager::SetVisible_MpClientList (bool v) { m_impl->panel_MpClientList .SetVisible(v); } -void GUIManager::SetVisible_FrictionSettings (bool v) { m_impl->panel_FrictionSettings .SetVisible(v); } -void GUIManager::SetVisible_TextureToolWindow (bool v) { m_impl->panel_TextureToolWindow .SetVisible(v); } -void GUIManager::SetVisible_LoadingWindow (bool v) { m_impl->panel_LoadingWindow .SetVisible(v); } -void GUIManager::SetVisible_Console (bool v) { m_impl->panel_GameConsole .SetVisible(v); } -void GUIManager::SetVisible_GameSettings (bool v) { m_impl->panel_GameSettings .SetVisible(v); } -void GUIManager::SetVisible_NodeBeamUtils (bool v) { m_impl->panel_NodeBeamUtils .SetVisible(v); } - -bool GUIManager::IsVisible_GameMainMenu () { return m_impl->panel_GameMainMenu .IsVisible(); } -bool GUIManager::IsVisible_GameAbout () { return m_impl->panel_GameAbout .IsVisible(); } -bool GUIManager::IsVisible_DebugOptions () { return m_impl->panel_DebugOptions .IsVisible(); } -bool GUIManager::IsVisible_MultiplayerSelector () { return m_impl->panel_MultiplayerSelector.IsVisible(); } -bool GUIManager::IsVisible_MainSelector () { return m_impl->panel_MainSelector .IsVisible(); } -bool GUIManager::IsVisible_ChatBox () { return m_impl->panel_ChatBox .IsVisible(); } -bool GUIManager::IsVisible_SpawnerReport () { return m_impl->panel_SpawnerReport .IsVisible(); } -bool GUIManager::IsVisible_VehicleDescription () { return m_impl->panel_VehicleDescription .IsVisible(); } -bool GUIManager::IsVisible_MpClientList () { return m_impl->panel_MpClientList .IsVisible(); } -bool GUIManager::IsVisible_FrictionSettings () { return m_impl->panel_FrictionSettings .IsVisible(); } -bool GUIManager::IsVisible_TextureToolWindow () { return m_impl->panel_TextureToolWindow .IsVisible(); } -bool GUIManager::IsVisible_LoadingWindow () { return m_impl->panel_LoadingWindow .IsVisible(); } -bool GUIManager::IsVisible_Console () { return m_impl->panel_GameConsole .IsVisible(); } -bool GUIManager::IsVisible_GameSettings () { return m_impl->panel_GameSettings .IsVisible(); } -bool GUIManager::IsVisible_TopMenubar () { return m_impl->panel_TopMenubar .IsVisible(); } -bool GUIManager::IsVisible_NodeBeamUtils () { return m_impl->panel_NodeBeamUtils .IsVisible(); } - -// GUI GetInstance*() -Console* GUIManager::GetConsole() { return &m_impl->panel_GameConsole ; } -GUI::MainSelector* GUIManager::GetMainSelector() { return &m_impl->panel_MainSelector ; } -GUI::GameMainMenu* GUIManager::GetMainMenu() { return &m_impl->panel_GameMainMenu ; } -GUI::GamePauseMenu* GUIManager::GetPauseMenu() { return &m_impl->panel_GamePauseMenu ; } -GUI::LoadingWindow* GUIManager::GetLoadingWindow() { return &m_impl->panel_LoadingWindow ; } -GUI::MpClientList* GUIManager::GetMpClientList() { return &m_impl->panel_MpClientList ; } -GUI::MultiplayerSelector* GUIManager::GetMpSelector() { return &m_impl->panel_MultiplayerSelector ; } -GUI::FrictionSettings* GUIManager::GetFrictionSettings() { return &m_impl->panel_FrictionSettings ; } -GUI::SimUtils* GUIManager::GetSimUtils() { return &m_impl->panel_SimUtils ; } -GUI::TopMenubar* GUIManager::GetTopMenubar() { return &m_impl->panel_TopMenubar ; } - -GUIManager::GUIManager() : - m_renderwindow_closed(false), - m_impl(nullptr) -{ - RoR::App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(this); - OgreBites::WindowEventUtilities::addWindowEventListener(RoR::App::GetOgreSubsystem()->GetRenderWindow(), this); - - std::string gui_logpath = PathCombine(App::sys_logs_dir.GetActive(), "MyGUI.log"); - auto mygui_platform = new MyGUI::OgrePlatform(); - mygui_platform->initialise( - RoR::App::GetOgreSubsystem()->GetRenderWindow(), - gEnv->sceneManager, - Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, - gui_logpath); // use cache resource group so preview images are working - auto mygui = new MyGUI::Gui(); - // empty init - mygui->initialise(""); + struct GuiManagerImpl + { + GuiManagerImpl() : mygui(nullptr), mygui_platform(nullptr) + { + } - // add layer factory - MyGUI::FactoryManager::getInstance().registerFactory("Layer"); + GUI::GameMainMenu panel_GameMainMenu; + GUI::GameAbout panel_GameAbout; + GUI::GamePauseMenu panel_GamePauseMenu; + GUI::GameSettings panel_GameSettings; + GUI::DebugOptions panel_DebugOptions; + GUI::SimUtils panel_SimUtils; + GUI::MessageBoxDialog panel_MessageBox; + GUI::MultiplayerSelector panel_MultiplayerSelector; + GUI::MainSelector panel_MainSelector; + GUI::GameChatBox panel_ChatBox; + GUI::ActorSpawnerReportWindow panel_SpawnerReport; + GUI::VehicleDescription panel_VehicleDescription; + GUI::MpClientList panel_MpClientList; + GUI::FrictionSettings panel_FrictionSettings; + GUI::TextureToolWindow panel_TextureToolWindow; + GUI::NodeBeamUtils panel_NodeBeamUtils; + GUI::LoadingWindow panel_LoadingWindow; + GUI::TopMenubar panel_TopMenubar; + RoR::Console panel_GameConsole; + + MyGUI::Gui * mygui; + MyGUI::OgrePlatform *mygui_platform; + }; + + GUIManager::GuiTheme::GuiTheme() + : in_progress_text_color(1.f, 0.832031f, 0.f, 1.f), no_entries_text_color(0.7f, 0.7f, 0.7f, 1.f), + error_text_color(1.f, 0.175439f, 0.175439f, 1.f), selected_entry_text_color(.9f, 0.7f, 0.05f, 1.f) + { + try + { + // Setup custom font + Str<500> font_path; + font_path << App::sys_process_dir.GetActive() << PATH_SLASH << "languages" << PATH_SLASH << "Roboto-Medium.ttf"; + ImFontConfig font_config; + font_config.OversampleH = 1; + font_config.OversampleV = 1; + font_config.PixelSnapH = true; + default_font = ImGui::GetIO().Fonts->AddFontFromFileTTF(font_path, 16, &font_config); + assert(default_font); + } + catch (...) + { + LOG("Failed to load font: Roboto-Medium.ttf"); + } + } - // then load the actual config - MyGUI::ResourceManager::getInstance().load(RESOURCE_FILENAME); + void GUIManager::SetVisible_GameMainMenu(bool v) + { + m_impl->panel_GameMainMenu.SetVisible(v); + } + void GUIManager::SetVisible_GameAbout(bool v) + { + m_impl->panel_GameAbout.SetVisible(v); + } + void GUIManager::SetVisible_DebugOptions(bool v) + { + m_impl->panel_DebugOptions.SetVisible(v); + } + void GUIManager::SetVisible_MultiplayerSelector(bool v) + { + m_impl->panel_MultiplayerSelector.SetVisible(v); + } + void GUIManager::SetVisible_ChatBox(bool v) + { + m_impl->panel_ChatBox.SetVisible(v); + } + void GUIManager::SetVisible_SpawnerReport(bool v) + { + m_impl->panel_SpawnerReport.SetVisible(v); + } + void GUIManager::SetVisible_VehicleDescription(bool v) + { + m_impl->panel_VehicleDescription.SetVisible(v); + } + void GUIManager::SetVisible_MpClientList(bool v) + { + m_impl->panel_MpClientList.SetVisible(v); + } + void GUIManager::SetVisible_FrictionSettings(bool v) + { + m_impl->panel_FrictionSettings.SetVisible(v); + } + void GUIManager::SetVisible_TextureToolWindow(bool v) + { + m_impl->panel_TextureToolWindow.SetVisible(v); + } + void GUIManager::SetVisible_LoadingWindow(bool v) + { + m_impl->panel_LoadingWindow.SetVisible(v); + } + void GUIManager::SetVisible_Console(bool v) + { + m_impl->panel_GameConsole.SetVisible(v); + } + void GUIManager::SetVisible_GameSettings(bool v) + { + m_impl->panel_GameSettings.SetVisible(v); + } + void GUIManager::SetVisible_NodeBeamUtils(bool v) + { + m_impl->panel_NodeBeamUtils.SetVisible(v); + } - MyGUI::ResourceManager::getInstance().load("MyGUI_FontsEnglish.xml"); + bool GUIManager::IsVisible_GameMainMenu() + { + return m_impl->panel_GameMainMenu.IsVisible(); + } + bool GUIManager::IsVisible_GameAbout() + { + return m_impl->panel_GameAbout.IsVisible(); + } + bool GUIManager::IsVisible_DebugOptions() + { + return m_impl->panel_DebugOptions.IsVisible(); + } + bool GUIManager::IsVisible_MultiplayerSelector() + { + return m_impl->panel_MultiplayerSelector.IsVisible(); + } + bool GUIManager::IsVisible_MainSelector() + { + return m_impl->panel_MainSelector.IsVisible(); + } + bool GUIManager::IsVisible_ChatBox() + { + return m_impl->panel_ChatBox.IsVisible(); + } + bool GUIManager::IsVisible_SpawnerReport() + { + return m_impl->panel_SpawnerReport.IsVisible(); + } + bool GUIManager::IsVisible_VehicleDescription() + { + return m_impl->panel_VehicleDescription.IsVisible(); + } + bool GUIManager::IsVisible_MpClientList() + { + return m_impl->panel_MpClientList.IsVisible(); + } + bool GUIManager::IsVisible_FrictionSettings() + { + return m_impl->panel_FrictionSettings.IsVisible(); + } + bool GUIManager::IsVisible_TextureToolWindow() + { + return m_impl->panel_TextureToolWindow.IsVisible(); + } + bool GUIManager::IsVisible_LoadingWindow() + { + return m_impl->panel_LoadingWindow.IsVisible(); + } + bool GUIManager::IsVisible_Console() + { + return m_impl->panel_GameConsole.IsVisible(); + } + bool GUIManager::IsVisible_GameSettings() + { + return m_impl->panel_GameSettings.IsVisible(); + } + bool GUIManager::IsVisible_TopMenubar() + { + return m_impl->panel_TopMenubar.IsVisible(); + } + bool GUIManager::IsVisible_NodeBeamUtils() + { + return m_impl->panel_NodeBeamUtils.IsVisible(); + } - m_impl = new GuiManagerImpl(); - m_impl->mygui_platform = mygui_platform; - m_impl->mygui = mygui; - MyGUI::PointerManager::getInstance().setVisible(false); // RoR is using mouse cursor drawn by DearIMGUI. + // GUI GetInstance*() + Console *GUIManager::GetConsole() + { + return &m_impl->panel_GameConsole; + } + GUI::MainSelector *GUIManager::GetMainSelector() + { + return &m_impl->panel_MainSelector; + } + GUI::GameMainMenu *GUIManager::GetMainMenu() + { + return &m_impl->panel_GameMainMenu; + } + GUI::GamePauseMenu *GUIManager::GetPauseMenu() + { + return &m_impl->panel_GamePauseMenu; + } + GUI::LoadingWindow *GUIManager::GetLoadingWindow() + { + return &m_impl->panel_LoadingWindow; + } + GUI::MpClientList *GUIManager::GetMpClientList() + { + return &m_impl->panel_MpClientList; + } + GUI::MultiplayerSelector *GUIManager::GetMpSelector() + { + return &m_impl->panel_MultiplayerSelector; + } + GUI::FrictionSettings *GUIManager::GetFrictionSettings() + { + return &m_impl->panel_FrictionSettings; + } + GUI::SimUtils *GUIManager::GetSimUtils() + { + return &m_impl->panel_SimUtils; + } + GUI::TopMenubar *GUIManager::GetTopMenubar() + { + return &m_impl->panel_TopMenubar; + } -#ifdef _WIN32 - MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &GUIManager::eventRequestTag); -#endif // _WIN32 - windowResized(RoR::App::GetOgreSubsystem()->GetRenderWindow()); + GUIManager::GUIManager() : m_renderwindow_closed(false), m_impl(nullptr) + { + RoR::App::GetOgreSubsystem()->GetOgreRoot()->addFrameListener(this); + OgreBites::WindowEventUtilities::addWindowEventListener(RoR::App::GetOgreSubsystem()->GetRenderWindow(), this); - this->SetupImGui(); -} + std::string gui_logpath = PathCombine(App::sys_logs_dir.GetActive(), "MyGUI.log"); + auto mygui_platform = new MyGUI::OgrePlatform(); + mygui_platform->initialise(RoR::App::GetOgreSubsystem()->GetRenderWindow(), gEnv->sceneManager, + Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, + gui_logpath); // use cache resource group so preview images are working + auto mygui = new MyGUI::Gui(); -GUIManager::~GUIManager() -{ - delete m_impl; -} + // empty init + mygui->initialise(""); -void GUIManager::UnfocusGui() -{ - MyGUI::InputManager::getInstance().resetKeyFocusWidget(); - MyGUI::InputManager::getInstance().resetMouseCaptureWidget(); -} + // add layer factory + MyGUI::FactoryManager::getInstance().registerFactory("Layer"); -void GUIManager::ShutdownMyGUI() -{ - if (m_impl->mygui) - { - m_impl->mygui->shutdown(); - delete m_impl->mygui; - m_impl->mygui = nullptr; - } + // then load the actual config + MyGUI::ResourceManager::getInstance().load(RESOURCE_FILENAME); - if (m_impl->mygui_platform) - { - m_impl->mygui_platform->shutdown(); - delete m_impl->mygui_platform; - m_impl->mygui_platform = nullptr; - } + MyGUI::ResourceManager::getInstance().load("MyGUI_FontsEnglish.xml"); - delete m_impl; -} + m_impl = new GuiManagerImpl(); + m_impl->mygui_platform = mygui_platform; + m_impl->mygui = mygui; + MyGUI::PointerManager::getInstance().setVisible(false); // RoR is using mouse cursor drawn by DearIMGUI. -bool GUIManager::frameStarted(const Ogre::FrameEvent& evt) -{ - if (m_renderwindow_closed) return false; - if (!m_impl->mygui) return true; +#ifdef _WIN32 + MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &GUIManager::eventRequestTag); +#endif // _WIN32 + windowResized(RoR::App::GetOgreSubsystem()->GetRenderWindow()); + this->SetupImGui(); + } - // now hide the mouse cursor if not used since a long time - if (getLastMouseMoveTime() > 5000) + GUIManager::~GUIManager() { - App::GetGuiManager()->SetMouseCursorVisibility(GUIManager::MouseCursorVisibility::HIDDEN); + delete m_impl; } - return true; -} - -bool GUIManager::frameEnded(const Ogre::FrameEvent& evt) -{ - return true; -}; + void GUIManager::UnfocusGui() + { + MyGUI::InputManager::getInstance().resetKeyFocusWidget(); + MyGUI::InputManager::getInstance().resetMouseCaptureWidget(); + } -void GUIManager::DrawSimulationGui(float dt) -{ - m_impl->panel_SimUtils.FrameStepSimGui(dt); - if (App::app_state.GetActive() == AppState::SIMULATION) + void GUIManager::ShutdownMyGUI() { - m_impl->panel_TopMenubar.Update(); + if (m_impl->mygui) + { + m_impl->mygui->shutdown(); + delete m_impl->mygui; + m_impl->mygui = nullptr; + } - if (App::sim_state.GetActive() == SimState::PAUSED) + if (m_impl->mygui_platform) { - m_impl->panel_GamePauseMenu.Draw(); + m_impl->mygui_platform->shutdown(); + delete m_impl->mygui_platform; + m_impl->mygui_platform = nullptr; } - } - if (m_impl->panel_NodeBeamUtils.IsVisible()) - { - m_impl->panel_NodeBeamUtils.Draw(); + delete m_impl; } - if (m_impl->panel_MessageBox.IsVisible()) + bool GUIManager::frameStarted(const Ogre::FrameEvent &evt) { - m_impl->panel_MessageBox.Draw(); - } -}; + if (m_renderwindow_closed) return false; + if (!m_impl->mygui) return true; -void GUIManager::PushNotification(Ogre::String Title, Ogre::UTFString text) -{ - m_impl->panel_SimUtils.PushNotification(Title, text); -} + // now hide the mouse cursor if not used since a long time + if (getLastMouseMoveTime() > 5000) + { App::GetGuiManager()->SetMouseCursorVisibility(GUIManager::MouseCursorVisibility::HIDDEN); } -void GUIManager::HideNotification() -{ - m_impl->panel_SimUtils.HideNotificationBox(); -} + return true; + } -void GUIManager::windowResized(Ogre::RenderWindow* rw) -{ - int width = (int)rw->getWidth(); - int height = (int)rw->getHeight(); - setInputViewSize(width, height); + bool GUIManager::frameEnded(const Ogre::FrameEvent &evt) + { + return true; + }; + + void GUIManager::DrawSimulationGui(float dt) + { + m_impl->panel_SimUtils.FrameStepSimGui(dt); + if (App::app_state.GetActive() == AppState::SIMULATION) + { + m_impl->panel_TopMenubar.Update(); -} + if (App::sim_state.GetActive() == SimState::PAUSED) { m_impl->panel_GamePauseMenu.Draw(); } + } -void GUIManager::windowClosed(Ogre::RenderWindow* rw) -{ - m_renderwindow_closed = true; -} + if (m_impl->panel_NodeBeamUtils.IsVisible()) { m_impl->panel_NodeBeamUtils.Draw(); } -void GUIManager::eventRequestTag(const MyGUI::UString& _tag, MyGUI::UString& _result) -{ - _result = MyGUI::LanguageManager::getInstance().getTag(_tag); -} + if (m_impl->panel_MessageBox.IsVisible()) { m_impl->panel_MessageBox.Draw(); } + }; -Ogre::String GUIManager::getRandomWallpaperImage() -{ - using namespace Ogre; - FileInfoListPtr files = ResourceGroupManager::getSingleton().findResourceFileInfo("Wallpapers", "*.jpg", false); - if (files.isNull() || files->empty()) + void GUIManager::PushNotification(Ogre::String Title, Ogre::UTFString text) { - files = ResourceGroupManager::getSingleton().findResourceFileInfo("Wallpapers", "*.png", false); - if (files.isNull() || files->empty()) - return ""; + m_impl->panel_SimUtils.PushNotification(Title, text); } - srand ( time(NULL) ); - int num = 0; - for (int i = 0; isize()); + void GUIManager::HideNotification() + { + m_impl->panel_SimUtils.HideNotificationBox(); + } - return files->at(num).filename; -} + void GUIManager::windowResized(Ogre::RenderWindow *rw) + { + int width = (int)rw->getWidth(); + int height = (int)rw->getHeight(); + setInputViewSize(width, height); + } -void GUIManager::SetSceneManagerForGuiRendering(Ogre::SceneManager* scene_manager) -{ - m_impl->mygui_platform->getRenderManagerPtr()->setSceneManager(scene_manager); -} + void GUIManager::windowClosed(Ogre::RenderWindow *rw) + { + m_renderwindow_closed = true; + } -void GUIManager::UpdateSimUtils(float dt, Actor *truck) -{ - if (m_impl->panel_SimUtils.IsBaseVisible()) //Better to update only when it's visible. + void GUIManager::eventRequestTag(const MyGUI::UString &_tag, MyGUI::UString &_result) { - m_impl->panel_SimUtils.UpdateStats(dt, truck); + _result = MyGUI::LanguageManager::getInstance().getTag(_tag); } -} -void GUIManager::AddRigLoadingReport(std::string const & vehicle_name, std::string const & text, int num_errors, int num_warnings, int num_other) -{ - m_impl->panel_SpawnerReport.SetRigLoadingReport(vehicle_name, text, num_errors, num_warnings, num_other); -} + Ogre::String GUIManager::getRandomWallpaperImage() + { + using namespace Ogre; + FileInfoListPtr files = ResourceGroupManager::getSingleton().findResourceFileInfo("Wallpapers", "*.jpg", false); + if (files.isNull() || files->empty()) + { + files = ResourceGroupManager::getSingleton().findResourceFileInfo("Wallpapers", "*.png", false); + if (files.isNull() || files->empty()) return ""; + } + srand(time(NULL)); -void GUIManager::CenterSpawnerReportWindow() -{ - m_impl->panel_SpawnerReport.CenterToScreen(); -} + int num = 0; + for (int i = 0; i < Math::RangeRandom(0, 10); i++) + num = Math::RangeRandom(0, files->size()); -void GUIManager::pushMessageChatBox(Ogre::String txt) -{ - m_impl->panel_ChatBox.pushMsg(txt); -} + return files->at(num).filename; + } -void GUIManager::hideGUI(bool hidden) -{ - if (hidden) + void GUIManager::SetSceneManagerForGuiRendering(Ogre::SceneManager *scene_manager) { - m_impl->panel_SimUtils.HideNotificationBox(); - m_impl->panel_SimUtils.SetFPSBoxVisible(false); - m_impl->panel_SimUtils.SetActorInfoBoxVisible(false); - m_impl->panel_ChatBox.Hide(); + m_impl->mygui_platform->getRenderManagerPtr()->setSceneManager(scene_manager); } - m_impl->panel_SimUtils.DisableNotifications(hidden); -} - -void GUIManager::FrictionSettingsUpdateCollisions() -{ - App::GetGuiManager()->GetFrictionSettings()->setCollisions(gEnv->collisions); -} -void GUIManager::SetMouseCursorVisibility(MouseCursorVisibility visi) -{ - switch (visi) + void GUIManager::UpdateSimUtils(float dt, Actor *truck) { - case MouseCursorVisibility::VISIBLE: - ImGui::GetIO().MouseDrawCursor = true; - this->SupressCursor(false); - return; - - case MouseCursorVisibility::HIDDEN: - ImGui::GetIO().MouseDrawCursor = false; - return; + if (m_impl->panel_SimUtils.IsBaseVisible()) // Better to update only when it's visible. + { m_impl->panel_SimUtils.UpdateStats(dt, truck); } + } - case MouseCursorVisibility::SUPRESSED: - ImGui::GetIO().MouseDrawCursor = false; - this->SupressCursor(true); - return; + void GUIManager::AddRigLoadingReport(std::string const &vehicle_name, std::string const &text, int num_errors, + int num_warnings, int num_other) + { + m_impl->panel_SpawnerReport.SetRigLoadingReport(vehicle_name, text, num_errors, num_warnings, num_other); } -} -void GUIManager::ReflectGameState() -{ - const auto app_state = App::app_state.GetActive(); - const auto mp_state = App::mp_state.GetActive(); - if (app_state == AppState::MAIN_MENU) + void GUIManager::CenterSpawnerReportWindow() { - m_impl->panel_GameMainMenu .SetVisible(!m_impl->panel_MainSelector.IsVisible()); + m_impl->panel_SpawnerReport.CenterToScreen(); + } - m_impl->panel_ChatBox .SetVisible(false); - m_impl->panel_DebugOptions .SetVisible(false); - m_impl->panel_FrictionSettings .SetVisible(false); - m_impl->panel_TextureToolWindow .SetVisible(false); - m_impl->panel_VehicleDescription .SetVisible(false); - m_impl->panel_SpawnerReport .SetVisible(false); - m_impl->panel_SimUtils .SetBaseVisible(false); - m_impl->panel_MpClientList .SetVisible(mp_state == MpState::CONNECTED); - return; + void GUIManager::pushMessageChatBox(Ogre::String txt) + { + m_impl->panel_ChatBox.pushMsg(txt); } - if (app_state == AppState::SIMULATION) + + void GUIManager::hideGUI(bool hidden) { - m_impl->panel_SimUtils .SetBaseVisible(true); - m_impl->panel_GameMainMenu .SetVisible(false); - return; + if (hidden) + { + m_impl->panel_SimUtils.HideNotificationBox(); + m_impl->panel_SimUtils.SetFPSBoxVisible(false); + m_impl->panel_SimUtils.SetActorInfoBoxVisible(false); + m_impl->panel_ChatBox.Hide(); + } + m_impl->panel_SimUtils.DisableNotifications(hidden); } -} -void GUIManager::NewImGuiFrame(float dt) -{ - // Update screen size - int left, top, width, height; - gEnv->mainCamera->getViewport()->getActualDimensions(left, top, width, height); // output params + void GUIManager::FrictionSettingsUpdateCollisions() + { + App::GetGuiManager()->GetFrictionSettings()->setCollisions(gEnv->collisions); + } - // Read keyboard modifiers inputs - OIS::Keyboard* kb = App::GetInputEngine()->GetOisKeyboard(); - bool ctrl = kb->isKeyDown(OIS::KC_LCONTROL); - bool shift = kb->isKeyDown(OIS::KC_LSHIFT); - bool alt = kb->isKeyDown(OIS::KC_LMENU); + void GUIManager::SetMouseCursorVisibility(MouseCursorVisibility visi) + { + switch (visi) + { + case MouseCursorVisibility::VISIBLE: + ImGui::GetIO().MouseDrawCursor = true; + this->SupressCursor(false); + return; - // Call IMGUI - m_imgui.NewFrame(dt, static_cast(width), static_cast(height), ctrl, alt, shift); -} + case MouseCursorVisibility::HIDDEN: ImGui::GetIO().MouseDrawCursor = false; return; -void GUIManager::SetupImGui() -{ - ImGuiIO& io = ImGui::GetIO(); - io.IniFilename = nullptr; // Disable 'imgui.ini' - we don't need to persist window positions. - - m_imgui.Init(gEnv->sceneManager); - // Colors - ImGuiStyle& style = ImGui::GetStyle(); - style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - style.Colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f); - style.Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - style.Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 1.00f); - style.Colors[ImGuiCol_Border] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - style.Colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.78f, 0.39f, 0.00f, 0.99f); - style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.98f); - style.Colors[ImGuiCol_TitleBg] = ImVec4(0.57f, 0.31f, 0.00f, 1.00f); - style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 1.00f); - style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.74f, 0.44f, 0.00f, 1.00f); - style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.16f, 0.16f, 0.16f, 0.99f); - style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.29f, 1.00f); - style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.78f, 0.39f, 0.00f, 0.99f); - style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1.00f, 0.50f, 0.00f, 0.99f); - style.Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); - style.Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); - style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); - style.Colors[ImGuiCol_Button] = ImVec4(0.26f, 0.26f, 0.25f, 1.00f); - style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.78f, 0.39f, 0.00f, 0.98f); - style.Colors[ImGuiCol_ButtonActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); - style.Colors[ImGuiCol_Header] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.57f, 0.30f, 0.00f, 1.00f); - style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.78f, 0.39f, 0.00f, 1.00f); - style.Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - style.Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f); - style.Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f); - style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.22f, 0.22f, 0.21f, 1.00f); - style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.39f, 0.00f, 1.00f); - style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); - style.Colors[ImGuiCol_CloseButton] = ImVec4(0.55f, 0.27f, 0.09f, 1.00f); - style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.86f, 0.43f, 0.00f, 1.00f); - style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); - style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 1.00f); - style.Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - // Styles - style.WindowPadding = ImVec2(10.f, 10.f); - style.FrameRounding = 2.f; - style.WindowRounding = 4.f; - style.WindowTitleAlign = ImVec2(0.5f, 0.5f); - style.ItemSpacing = ImVec2(5.f, 5.f); - style.GrabRounding = 3.f; - style.ChildWindowRounding = 4.f; -} - -void GUIManager::DrawMainMenuGui() -{ - if (m_impl->panel_MultiplayerSelector.IsVisible()) - { - m_impl->panel_MultiplayerSelector.Draw(); + case MouseCursorVisibility::SUPRESSED: + ImGui::GetIO().MouseDrawCursor = false; + this->SupressCursor(true); + return; + } } - if (m_impl->panel_GameMainMenu.IsVisible()) + void GUIManager::ReflectGameState() { - m_impl->panel_GameMainMenu.Draw(); + const auto app_state = App::app_state.GetActive(); + const auto mp_state = App::mp_state.GetActive(); + if (app_state == AppState::MAIN_MENU) + { + m_impl->panel_GameMainMenu.SetVisible(!m_impl->panel_MainSelector.IsVisible()); + + m_impl->panel_ChatBox.SetVisible(false); + m_impl->panel_DebugOptions.SetVisible(false); + m_impl->panel_FrictionSettings.SetVisible(false); + m_impl->panel_TextureToolWindow.SetVisible(false); + m_impl->panel_VehicleDescription.SetVisible(false); + m_impl->panel_SpawnerReport.SetVisible(false); + m_impl->panel_SimUtils.SetBaseVisible(false); + m_impl->panel_MpClientList.SetVisible(mp_state == MpState::CONNECTED); + return; + } + if (app_state == AppState::SIMULATION) + { + m_impl->panel_SimUtils.SetBaseVisible(true); + m_impl->panel_GameMainMenu.SetVisible(false); + return; + } } - if (App::mp_state.GetActive() == MpState::CONNECTING) + void GUIManager::NewImGuiFrame(float dt) { - this->DrawMpConnectingStatusBox(); + // Update screen size + int left, top, width, height; + gEnv->mainCamera->getViewport()->getActualDimensions(left, top, width, height); // output params + + // Read keyboard modifiers inputs + OIS::Keyboard *kb = App::GetInputEngine()->GetOisKeyboard(); + bool ctrl = kb->isKeyDown(OIS::KC_LCONTROL); + bool shift = kb->isKeyDown(OIS::KC_LSHIFT); + bool alt = kb->isKeyDown(OIS::KC_LMENU); + + // Call IMGUI + m_imgui.NewFrame(dt, static_cast(width), static_cast(height), ctrl, alt, shift); } - if (m_impl->panel_GameSettings.IsVisible()) + void GUIManager::SetupImGui() { - m_impl->panel_GameSettings.Draw(); + ImGuiIO &io = ImGui::GetIO(); + io.IniFilename = nullptr; // Disable 'imgui.ini' - we don't need to persist window positions. + + m_imgui.Init(gEnv->sceneManager); + // Colors + ImGuiStyle &style = ImGui::GetStyle(); + style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); + style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f); + style.Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + style.Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 1.00f); + style.Colors[ImGuiCol_Border] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); + style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + style.Colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); + style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.78f, 0.39f, 0.00f, 0.99f); + style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.98f); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.57f, 0.31f, 0.00f, 1.00f); + style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 1.00f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.74f, 0.44f, 0.00f, 1.00f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); + style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.16f, 0.16f, 0.16f, 0.99f); + style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.29f, 1.00f); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.78f, 0.39f, 0.00f, 0.99f); + style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1.00f, 0.50f, 0.00f, 0.99f); + style.Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); + style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); + style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); + style.Colors[ImGuiCol_Button] = ImVec4(0.26f, 0.26f, 0.25f, 1.00f); + style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.78f, 0.39f, 0.00f, 0.98f); + style.Colors[ImGuiCol_ButtonActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); + style.Colors[ImGuiCol_Header] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); + style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.57f, 0.30f, 0.00f, 1.00f); + style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.78f, 0.39f, 0.00f, 1.00f); + style.Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + style.Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f); + style.Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f); + style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.22f, 0.22f, 0.21f, 1.00f); + style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.39f, 0.00f, 1.00f); + style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); + style.Colors[ImGuiCol_CloseButton] = ImVec4(0.55f, 0.27f, 0.09f, 1.00f); + style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.86f, 0.43f, 0.00f, 1.00f); + style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(1.00f, 0.48f, 0.00f, 1.00f); + style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 1.00f); + style.Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); + // Styles + style.WindowPadding = ImVec2(10.f, 10.f); + style.FrameRounding = 2.f; + style.WindowRounding = 4.f; + style.WindowTitleAlign = ImVec2(0.5f, 0.5f); + style.ItemSpacing = ImVec2(5.f, 5.f); + style.GrabRounding = 3.f; + style.ChildWindowRounding = 4.f; } - if (m_impl->panel_MessageBox.IsVisible()) + void GUIManager::DrawMainMenuGui() { - m_impl->panel_MessageBox.Draw(); - } -} + if (m_impl->panel_MultiplayerSelector.IsVisible()) { m_impl->panel_MultiplayerSelector.Draw(); } -void GUIManager::DrawMpConnectingStatusBox() -{ - static float spin_counter=0.f; + if (m_impl->panel_GameMainMenu.IsVisible()) { m_impl->panel_GameMainMenu.Draw(); } - const ImVec2 spin_size(20.f, 20.f); - const float spin_column_w(50.f); - const int win_flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoInputs - | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar; + if (App::mp_state.GetActive() == MpState::CONNECTING) { this->DrawMpConnectingStatusBox(); } - ImGui::SetNextWindowPosCenter(); - ImGui::Begin("Connecting to MP server...", nullptr, win_flags); - ImGui::Columns(2); - ImGui::SetColumnOffset(1, spin_column_w); + if (m_impl->panel_GameSettings.IsVisible()) { m_impl->panel_GameSettings.Draw(); } - ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(5.f, 7.f)); // NOTE: Hand aligned; I failed calculate the positioning here ~ only_a_ptr, 10/2017 - DrawImGuiSpinner(spin_counter, spin_size); + if (m_impl->panel_MessageBox.IsVisible()) { m_impl->panel_MessageBox.Draw(); } + } - ImGui::NextColumn(); - // HACK: The trailing space is a workaround for a scissoring issue in OGRE/DearIMGUI integration. ~ only_a_ptr, 10/2017 - ImGui::Text("Joining [%s:%d] ", App::mp_server_host.GetActive(), App::mp_server_port.GetActive()); + void GUIManager::DrawMpConnectingStatusBox() + { + static float spin_counter = 0.f; + + const ImVec2 spin_size(20.f, 20.f); + const float spin_column_w(50.f); + const int win_flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoInputs | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar; + + ImGui::SetNextWindowPosCenter(); + ImGui::Begin("Connecting to MP server...", nullptr, win_flags); + ImGui::Columns(2); + ImGui::SetColumnOffset(1, spin_column_w); + + ImGui::SetCursorPos( + ImGui::GetCursorPos() + + ImVec2(5.f, 7.f)); // NOTE: Hand aligned; I failed calculate the positioning here ~ only_a_ptr, 10/2017 + DrawImGuiSpinner(spin_counter, spin_size); + + ImGui::NextColumn(); + // HACK: The trailing space is a workaround for a scissoring issue in OGRE/DearIMGUI integration. ~ only_a_ptr, 10/2017 + ImGui::Text("Joining [%s:%d] ", App::mp_server_host.GetActive(), App::mp_server_port.GetActive()); #ifdef USE_SOCKETW - ImGui::TextDisabled("%s", m_net_connect_status.c_str()); + ImGui::TextDisabled("%s", m_net_connect_status.c_str()); #endif - ImGui::End(); -} + ImGui::End(); + } -void GUIManager::ShowMessageBox(const char* title, const char* text, bool allow_close, const char* btn1_text, const char* btn2_text) -{ - m_impl->panel_MessageBox.Show(title, text, allow_close, btn1_text, btn2_text); -} + void GUIManager::ShowMessageBox(const char *title, const char *text, bool allow_close, const char *btn1_text, + const char *btn2_text) + { + m_impl->panel_MessageBox.Show(title, text, allow_close, btn1_text, btn2_text); + } } // namespace RoR diff --git a/source/main/gui/GUIManager.h b/source/main/gui/GUIManager.h index eb99780af5..120d6cf677 100644 --- a/source/main/gui/GUIManager.h +++ b/source/main/gui/GUIManager.h @@ -29,137 +29,147 @@ #include "RoRPrerequisites.h" #include -#include #include +#include -namespace RoR { - -class GUIManager : - public GUIInputManager - , public Ogre::FrameListener - , public Ogre::WindowEventListener - , public ZeroedMemoryAllocator +namespace RoR { -public: - struct GuiTheme + class GUIManager : public GUIInputManager, + public Ogre::FrameListener, + public Ogre::WindowEventListener, + public ZeroedMemoryAllocator { - GuiTheme(); - - ImVec4 in_progress_text_color; - ImVec4 no_entries_text_color; - ImVec4 error_text_color; - ImVec4 selected_entry_text_color; - - ImFont* default_font; + public: + struct GuiTheme + { + GuiTheme(); + + ImVec4 in_progress_text_color; + ImVec4 no_entries_text_color; + ImVec4 error_text_color; + ImVec4 selected_entry_text_color; + + ImFont *default_font; + }; + + // NOTE: RoR's mouse cursor management is a mess - cursor is hidden/revealed ad-hoc in the code (originally by calling + // `MyGUI::PointerManager::setVisible()`); this enum+API cleans it up a bit ~ only_a_ptr, 09/2017 + enum class MouseCursorVisibility + { + VISIBLE, ///< Visible, will be auto-hidden if not moving for a while. + HIDDEN, ///< Hidden as inactive, will re-appear the moment user moves mouse. + SUPRESSED, ///< Hidden manually, will not re-appear until explicitly set VISIBLE. + }; + + GUIManager(); + ~GUIManager(); + + // GUI SetVisible*() + void SetVisible_GameMainMenu(bool visible); + void SetVisible_GameAbout(bool visible); + void SetVisible_GameSettings(bool visible); + void SetVisible_DebugOptions(bool visible); + void SetVisible_MultiplayerSelector(bool visible); + void SetVisible_ChatBox(bool visible); + void SetVisible_SpawnerReport(bool visible); + void SetVisible_VehicleDescription(bool visible); + void SetVisible_MpClientList(bool visible); + void SetVisible_FrictionSettings(bool visible); + void SetVisible_TextureToolWindow(bool visible); + void SetVisible_NodeBeamUtils(bool visible); + void SetVisible_LoadingWindow(bool visible); + void SetVisible_Console(bool visible); + + // GUI IsVisible*() + bool IsVisible_GameMainMenu(); + bool IsVisible_GameAbout(); + bool IsVisible_GameSettings(); + bool IsVisible_TopMenubar(); + bool IsVisible_DebugOptions(); + bool IsVisible_MessageBox(); + bool IsVisible_MultiplayerSelector(); + bool IsVisible_MpClientList(); + bool IsVisible_MainSelector(); + bool IsVisible_ChatBox(); + bool IsVisible_SpawnerReport(); + bool IsVisible_VehicleDescription(); + bool IsVisible_FrictionSettings(); + bool IsVisible_TextureToolWindow(); + bool IsVisible_NodeBeamUtils(); + bool IsVisible_LoadingWindow(); + bool IsVisible_Console(); + + // GUI GetInstance*() + Console * GetConsole(); + GUI::MainSelector * GetMainSelector(); + GUI::GameMainMenu * GetMainMenu(); + GUI::GamePauseMenu * GetPauseMenu(); + GUI::LoadingWindow * GetLoadingWindow(); + GUI::MpClientList * GetMpClientList(); + GUI::MultiplayerSelector *GetMpSelector(); + GUI::FrictionSettings * GetFrictionSettings(); + GUI::SimUtils * GetSimUtils(); + GUI::TopMenubar * GetTopMenubar(); + + // GUI manipulation + void pushMessageChatBox(Ogre::String txt); + void ShowMessageBox(const char *title, const char *text, bool allow_close = true, const char *btn1_text = "OK", + const char *btn2_text = nullptr); + void UnfocusGui(); + void PushNotification(Ogre::String Title, Ogre::UTFString text); + void HideNotification(); + void CenterSpawnerReportWindow(); + + void UpdateSimUtils(float dt, Actor *truck); + void NewImGuiFrame(float dt); + void DrawMainMenuGui(); + void DrawSimulationGui(float dt); + + void SetMpConnectingStatusMsg(std::string const &msg) + { + m_net_connect_status = msg; + } + void DrawMpConnectingStatusBox(); + void hideGUI(bool visible); + + void windowResized(Ogre::RenderWindow *rw); + + void SetSceneManagerForGuiRendering(Ogre::SceneManager *scene_manager); + + void FrictionSettingsUpdateCollisions(); + void ShutdownMyGUI(); + void ReflectGameState(); + void SetMouseCursorVisibility(MouseCursorVisibility visi); + + virtual void AddRigLoadingReport(std::string const &vehicle_name, std::string const &text, int num_errors, + int num_warnings, int num_other); + + static Ogre::String getRandomWallpaperImage(); + + inline OgreImGui &GetImGui() + { + return m_imgui; + } + inline GuiTheme &GetTheme() + { + return m_theme; + } + + private: + void SetupImGui(); + + virtual bool frameStarted(const Ogre::FrameEvent &_evt); + virtual bool frameEnded(const Ogre::FrameEvent &_evt); + virtual void windowClosed(Ogre::RenderWindow *rw); + + void eventRequestTag(const MyGUI::UString &_tag, MyGUI::UString &_result); + + GuiManagerImpl *m_impl; + bool m_renderwindow_closed; + OgreImGui m_imgui; + GuiTheme m_theme; + std::string m_net_connect_status; }; - // NOTE: RoR's mouse cursor management is a mess - cursor is hidden/revealed ad-hoc in the code (originally by calling `MyGUI::PointerManager::setVisible()`); this enum+API cleans it up a bit ~ only_a_ptr, 09/2017 - enum class MouseCursorVisibility - { - VISIBLE, ///< Visible, will be auto-hidden if not moving for a while. - HIDDEN, ///< Hidden as inactive, will re-appear the moment user moves mouse. - SUPRESSED, ///< Hidden manually, will not re-appear until explicitly set VISIBLE. - }; - - GUIManager(); - ~GUIManager(); - - // GUI SetVisible*() - void SetVisible_GameMainMenu (bool visible); - void SetVisible_GameAbout (bool visible); - void SetVisible_GameSettings (bool visible); - void SetVisible_DebugOptions (bool visible); - void SetVisible_MultiplayerSelector (bool visible); - void SetVisible_ChatBox (bool visible); - void SetVisible_SpawnerReport (bool visible); - void SetVisible_VehicleDescription (bool visible); - void SetVisible_MpClientList (bool visible); - void SetVisible_FrictionSettings (bool visible); - void SetVisible_TextureToolWindow (bool visible); - void SetVisible_NodeBeamUtils (bool visible); - void SetVisible_LoadingWindow (bool visible); - void SetVisible_Console (bool visible); - - // GUI IsVisible*() - bool IsVisible_GameMainMenu (); - bool IsVisible_GameAbout (); - bool IsVisible_GameSettings (); - bool IsVisible_TopMenubar (); - bool IsVisible_DebugOptions (); - bool IsVisible_MessageBox (); - bool IsVisible_MultiplayerSelector (); - bool IsVisible_MpClientList (); - bool IsVisible_MainSelector (); - bool IsVisible_ChatBox (); - bool IsVisible_SpawnerReport (); - bool IsVisible_VehicleDescription (); - bool IsVisible_FrictionSettings (); - bool IsVisible_TextureToolWindow (); - bool IsVisible_NodeBeamUtils (); - bool IsVisible_LoadingWindow (); - bool IsVisible_Console (); - - // GUI GetInstance*() - Console* GetConsole(); - GUI::MainSelector* GetMainSelector(); - GUI::GameMainMenu* GetMainMenu(); - GUI::GamePauseMenu* GetPauseMenu(); - GUI::LoadingWindow* GetLoadingWindow(); - GUI::MpClientList* GetMpClientList(); - GUI::MultiplayerSelector* GetMpSelector(); - GUI::FrictionSettings* GetFrictionSettings(); - GUI::SimUtils* GetSimUtils(); - GUI::TopMenubar* GetTopMenubar(); - - // GUI manipulation - void pushMessageChatBox(Ogre::String txt); - void ShowMessageBox(const char* title, const char* text, bool allow_close = true, const char* btn1_text = "OK", const char* btn2_text = nullptr); - void UnfocusGui(); - void PushNotification(Ogre::String Title, Ogre::UTFString text); - void HideNotification(); - void CenterSpawnerReportWindow(); - - void UpdateSimUtils(float dt, Actor* truck); - void NewImGuiFrame(float dt); - void DrawMainMenuGui(); - void DrawSimulationGui(float dt); - - void SetMpConnectingStatusMsg(std::string const & msg) { m_net_connect_status = msg; } - void DrawMpConnectingStatusBox(); - void hideGUI(bool visible); - - void windowResized(Ogre::RenderWindow* rw); - - void SetSceneManagerForGuiRendering(Ogre::SceneManager* scene_manager); - - void FrictionSettingsUpdateCollisions(); - void ShutdownMyGUI(); - void ReflectGameState(); - void SetMouseCursorVisibility(MouseCursorVisibility visi); - - virtual void AddRigLoadingReport(std::string const& vehicle_name, std::string const& text, int num_errors, int num_warnings, int num_other); - - static Ogre::String getRandomWallpaperImage(); - - inline OgreImGui& GetImGui() { return m_imgui; } - inline GuiTheme& GetTheme() { return m_theme; } - - -private: - void SetupImGui(); - - virtual bool frameStarted(const Ogre::FrameEvent& _evt); - virtual bool frameEnded(const Ogre::FrameEvent& _evt); - virtual void windowClosed(Ogre::RenderWindow* rw); - - void eventRequestTag(const MyGUI::UString& _tag, MyGUI::UString& _result); - - GuiManagerImpl* m_impl; - bool m_renderwindow_closed; - OgreImGui m_imgui; - GuiTheme m_theme; - std::string m_net_connect_status; -}; - } // namespace RoR diff --git a/source/main/gui/GUIUtils.cpp b/source/main/gui/GUIUtils.cpp index 7fbd5af8f5..c4c2d97a45 100644 --- a/source/main/gui/GUIUtils.cpp +++ b/source/main/gui/GUIUtils.cpp @@ -19,26 +19,24 @@ #include "GUIUtils.h" -void RoR::DrawImGuiSpinner(float& counter, const ImVec2 size, const float spacing, const float step_sec) +void RoR::DrawImGuiSpinner(float &counter, const ImVec2 size, const float spacing, const float step_sec) { // Hardcoded to 4 segments, counter is reset after full round (4 steps) // -------------------------------------------------------------------- - const ImU32 COLORS[] = { ImColor(255,255,255,255), ImColor(210,210,210,255), ImColor(120,120,120,255), ImColor(60,60,60,255) }; + const ImU32 COLORS[] = {ImColor(255, 255, 255, 255), ImColor(210, 210, 210, 255), ImColor(120, 120, 120, 255), + ImColor(60, 60, 60, 255)}; // Update counter, determine coloring counter += ImGui::GetIO().DeltaTime; int color_start = 0; // Index to GUI_SPINNER_COLORS array for the top middle segment (segment 0) - while (counter > (step_sec*4.f)) + while (counter > (step_sec * 4.f)) { - counter -= (step_sec*4.f); + counter -= (step_sec * 4.f); } - if (counter > (step_sec*3.f)) - { - color_start = 3; - } - else if (counter > (step_sec*2.f)) + if (counter > (step_sec * 3.f)) { color_start = 3; } + else if (counter > (step_sec * 2.f)) { color_start = 2; } @@ -48,37 +46,39 @@ void RoR::DrawImGuiSpinner(float& counter, const ImVec2 size, const float spacin } // Draw segments - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - const ImVec2 pos = ImGui::GetCursorScreenPos(); - const float left = pos.x; - const float top = pos.y; - const float right = pos.x + size.x; - const float bottom = pos.y + size.y; - const float mid_x = pos.x + (size.x / 2.f); - const float mid_y = pos.y + (size.y / 2.f); - - // NOTE: Enter vertices in clockwise order, otherwise anti-aliasing doesn't work and polygon is rasterized larger! -- Observed under OpenGL2 / OGRE 1.9 + ImDrawList * draw_list = ImGui::GetWindowDrawList(); + const ImVec2 pos = ImGui::GetCursorScreenPos(); + const float left = pos.x; + const float top = pos.y; + const float right = pos.x + size.x; + const float bottom = pos.y + size.y; + const float mid_x = pos.x + (size.x / 2.f); + const float mid_y = pos.y + (size.y / 2.f); + + // NOTE: Enter vertices in clockwise order, otherwise anti-aliasing doesn't work and polygon is rasterized larger! -- Observed + // under OpenGL2 / OGRE 1.9 // Top triangle, vertices: mid, left, right - draw_list->AddTriangleFilled(ImVec2(mid_x, mid_y-spacing), ImVec2(left + spacing, top), ImVec2(right - spacing, top), COLORS[color_start]); + draw_list->AddTriangleFilled(ImVec2(mid_x, mid_y - spacing), ImVec2(left + spacing, top), ImVec2(right - spacing, top), + COLORS[color_start]); // Right triangle, vertices: mid, top, bottom - draw_list->AddTriangleFilled(ImVec2(mid_x+spacing, mid_y), ImVec2(right, top + spacing), ImVec2(right, bottom - spacing), COLORS[(color_start+3)%4]); + draw_list->AddTriangleFilled(ImVec2(mid_x + spacing, mid_y), ImVec2(right, top + spacing), ImVec2(right, bottom - spacing), + COLORS[(color_start + 3) % 4]); // Bottom triangle, vertices: mid, right, left - draw_list->AddTriangleFilled(ImVec2(mid_x, mid_y+spacing), ImVec2(right - spacing, bottom), ImVec2(left + spacing, bottom), COLORS[(color_start+2)%4]); + draw_list->AddTriangleFilled(ImVec2(mid_x, mid_y + spacing), ImVec2(right - spacing, bottom), ImVec2(left + spacing, bottom), + COLORS[(color_start + 2) % 4]); // Left triangle, vertices: mid, bottom, top - draw_list->AddTriangleFilled(ImVec2(mid_x-spacing, mid_y), ImVec2(left, bottom - spacing), ImVec2(left, top + spacing), COLORS[(color_start+1)%4]); + draw_list->AddTriangleFilled(ImVec2(mid_x - spacing, mid_y), ImVec2(left, bottom - spacing), ImVec2(left, top + spacing), + COLORS[(color_start + 1) % 4]); } -void RoR::DrawGCheckbox(GVarPod_A& gvar, const char* label) +void RoR::DrawGCheckbox(GVarPod_A &gvar, const char *label) { bool val = gvar.GetActive(); - if (ImGui::Checkbox(label, &val)) - { - gvar.SetActive(val); - } + if (ImGui::Checkbox(label, &val)) { gvar.SetActive(val); } } -void RoR::DrawGCheckbox(GVarPod_APS& gvar, const char* label) +void RoR::DrawGCheckbox(GVarPod_APS &gvar, const char *label) { bool val = gvar.GetStored(); if (ImGui::Checkbox(label, &val)) @@ -88,52 +88,37 @@ void RoR::DrawGCheckbox(GVarPod_APS& gvar, const char* label) } } -void RoR::DrawGIntCheck(GVarPod_A& gvar, const char* label) +void RoR::DrawGIntCheck(GVarPod_A &gvar, const char *label) { bool val = (gvar.GetActive() != 0); - if (ImGui::Checkbox(label, &val)) - { - gvar.SetActive(val ? 1 : 0); - } + if (ImGui::Checkbox(label, &val)) { gvar.SetActive(val ? 1 : 0); } } -void RoR::DrawGIntBox(GVarPod_A& gvar, const char* label) +void RoR::DrawGIntBox(GVarPod_A &gvar, const char *label) { int val = gvar.GetActive(); - if (ImGui::InputInt(label, &val, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue)) - { - gvar.SetActive(val); - } + if (ImGui::InputInt(label, &val, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue)) { gvar.SetActive(val); } } -void RoR::DrawGIntSlider(GVarPod_A& gvar, const char* label, int v_min, int v_max) +void RoR::DrawGIntSlider(GVarPod_A &gvar, const char *label, int v_min, int v_max) { int val = gvar.GetActive(); - if (ImGui::SliderInt(label, &val, v_min, v_max)) - { - gvar.SetActive(val); - } + if (ImGui::SliderInt(label, &val, v_min, v_max)) { gvar.SetActive(val); } } -void RoR::DrawGFloatSlider(GVarPod_A& gvar, const char* label, float v_min, float v_max) +void RoR::DrawGFloatSlider(GVarPod_A &gvar, const char *label, float v_min, float v_max) { float val = gvar.GetActive(); - if (ImGui::SliderFloat(label, &val, v_min, v_max, "%.2f")) - { - gvar.SetActive(val); - } + if (ImGui::SliderFloat(label, &val, v_min, v_max, "%.2f")) { gvar.SetActive(val); } } -void RoR::DrawGFloatBox(GVarPod_A& gvar, const char* label) +void RoR::DrawGFloatBox(GVarPod_A &gvar, const char *label) { float fval = gvar.GetActive(); - if (ImGui::InputFloat(label, &fval, 0.f, 0.f, -1, ImGuiInputTextFlags_EnterReturnsTrue)) - { - gvar.SetActive(fval); - } + if (ImGui::InputFloat(label, &fval, 0.f, 0.f, -1, ImGuiInputTextFlags_EnterReturnsTrue)) { gvar.SetActive(fval); } } -void RoR::DrawGFloatBox(GVarPod_APS& gvar, const char* label) +void RoR::DrawGFloatBox(GVarPod_APS &gvar, const char *label) { float fval = gvar.GetActive(); if (ImGui::InputFloat(label, &fval, 0.f, 0.f, -1, ImGuiInputTextFlags_EnterReturnsTrue)) diff --git a/source/main/gui/GUIUtils.h b/source/main/gui/GUIUtils.h index 4314b7e3b4..48de064bd9 100644 --- a/source/main/gui/GUIUtils.h +++ b/source/main/gui/GUIUtils.h @@ -22,75 +22,58 @@ #include "Application.h" #include "GUIManager.h" -namespace RoR { +namespace RoR +{ -/// Draws animated loading spinner -void DrawImGuiSpinner( - float& counter, const ImVec2 size = ImVec2(16.f, 16.f), - const float spacing = 2.f, const float step_sec = 0.15f); + /// Draws animated loading spinner + void DrawImGuiSpinner(float &counter, const ImVec2 size = ImVec2(16.f, 16.f), const float spacing = 2.f, + const float step_sec = 0.15f); -void DrawGCheckbox(GVarPod_A& gvar, const char* label); + void DrawGCheckbox(GVarPod_A &gvar, const char *label); -void DrawGCheckbox(GVarPod_APS& gvar, const char* label); + void DrawGCheckbox(GVarPod_APS &gvar, const char *label); -void DrawGIntCheck(GVarPod_A& gvar, const char* label); + void DrawGIntCheck(GVarPod_A &gvar, const char *label); -void DrawGIntBox(GVarPod_A& gvar, const char* label); + void DrawGIntBox(GVarPod_A &gvar, const char *label); -void DrawGIntSlider(GVarPod_A& gvar, const char* label, int v_min, int v_max); + void DrawGIntSlider(GVarPod_A &gvar, const char *label, int v_min, int v_max); -void DrawGFloatSlider(GVarPod_A& gvar, const char* label, float v_min, float v_max); + void DrawGFloatSlider(GVarPod_A &gvar, const char *label, float v_min, float v_max); -void DrawGFloatBox(GVarPod_A& gvar, const char* label); + void DrawGFloatBox(GVarPod_A &gvar, const char *label); -void DrawGFloatBox(GVarPod_APS& gvar, const char* label); + void DrawGFloatBox(GVarPod_APS &gvar, const char *label); -template -void DrawGTextEdit(GVarStr_A& gvar, const char* label, Str& buf) -{ - if (ImGui::InputText(label, buf.GetBuffer(), buf.GetCapacity(), ImGuiInputTextFlags_EnterReturnsTrue)) - { - gvar.SetActive(buf.GetBuffer()); - } - if (ImGui::IsItemActive()) + template void DrawGTextEdit(GVarStr_A &gvar, const char *label, Str &buf) { - ImGui::TextDisabled("(hit Enter key to submit)"); - } - else - { - buf.Assign(gvar.GetActive()); + if (ImGui::InputText(label, buf.GetBuffer(), buf.GetCapacity(), ImGuiInputTextFlags_EnterReturnsTrue)) + { gvar.SetActive(buf.GetBuffer()); } + if (ImGui::IsItemActive()) { ImGui::TextDisabled("(hit Enter key to submit)"); } + else + { + buf.Assign(gvar.GetActive()); + } } -} -template -void DrawGTextEdit(GVarStr_APS& gvar, const char* label, Str& buf, bool update_active) -{ - if (ImGui::InputText(label, buf.GetBuffer(), buf.GetCapacity(), ImGuiInputTextFlags_EnterReturnsTrue)) + template void DrawGTextEdit(GVarStr_APS &gvar, const char *label, Str &buf, bool update_active) { - if (update_active) + if (ImGui::InputText(label, buf.GetBuffer(), buf.GetCapacity(), ImGuiInputTextFlags_EnterReturnsTrue)) { - gvar.SetActive(buf.GetBuffer()); + if (update_active) { gvar.SetActive(buf.GetBuffer()); } + gvar.SetStored(buf.GetBuffer()); + } + if (ImGui::IsItemActive()) { ImGui::TextDisabled("(hit Enter key to submit)"); } + else + { + buf.Assign(gvar.GetStored()); } - gvar.SetStored(buf.GetBuffer()); - } - if (ImGui::IsItemActive()) - { - ImGui::TextDisabled("(hit Enter key to submit)"); - } - else - { - buf.Assign(gvar.GetStored()); } -} -template -void DrawGCombo(GVarEnum_A& gvar, const char* label, const char* values) -{ - int selection = static_cast(gvar.GetActive()); - if (ImGui::Combo(label, &selection, values)) + template void DrawGCombo(GVarEnum_A &gvar, const char *label, const char *values) { - gvar.SetActive(static_cast(selection)); + int selection = static_cast(gvar.GetActive()); + if (ImGui::Combo(label, &selection, values)) { gvar.SetActive(static_cast(selection)); } } -} } // namespace RoR diff --git a/source/main/gui/OverlayWrapper.cpp b/source/main/gui/OverlayWrapper.cpp index c69f8627f9..da3214a7cc 100644 --- a/source/main/gui/OverlayWrapper.cpp +++ b/source/main/gui/OverlayWrapper.cpp @@ -23,20 +23,16 @@ /// @author Thomas Fischer /// @date 6th of May 2010 -#include -#include -#include -#include #include "OverlayWrapper.h" #include "AeroEngine.h" #include "Application.h" #include "AutoPilot.h" #include "Beam.h" +#include "BeamEngine.h" #include "BeamFactory.h" #include "Character.h" #include "DashBoardManager.h" -#include "BeamEngine.h" #include "ErrorUtils.h" #include "FlexAirfoil.h" #include "GfxActor.h" @@ -51,15 +47,17 @@ #include "TurboProp.h" #include "Utils.h" +#include +#include +#include +#include + using namespace Ogre; bool g_is_scaled = false; -OverlayWrapper::OverlayWrapper(): - m_direction_arrow_node(nullptr), - mTimeUntilNextToggle(0), - m_dashboard_visible(false), - m_visible_overlays(0) +OverlayWrapper::OverlayWrapper() + : m_direction_arrow_node(nullptr), mTimeUntilNextToggle(0), m_dashboard_visible(false), m_visible_overlays(0) { win = RoR::App::GetOgreSubsystem()->GetRenderWindow(); init(); @@ -72,37 +70,34 @@ OverlayWrapper::~OverlayWrapper() HideDirectionOverlay(); } -void OverlayWrapper::resizePanel(OverlayElement* oe) +void OverlayWrapper::resizePanel(OverlayElement *oe) { - if (g_is_scaled) - return; + if (g_is_scaled) return; oe->setHeight(oe->getHeight() * (Real)win->getWidth() / (Real)win->getHeight()); oe->setTop(oe->getTop() * (Real)win->getWidth() / (Real)win->getHeight()); } -void OverlayWrapper::reposPanel(OverlayElement* oe) +void OverlayWrapper::reposPanel(OverlayElement *oe) { - if (g_is_scaled) - return; + if (g_is_scaled) return; oe->setTop(oe->getTop() * (Real)win->getWidth() / (Real)win->getHeight()); } -void OverlayWrapper::placeNeedle(SceneNode* node, float x, float y, float len) -{/**(Real)win->getHeight()/(Real)win->getWidth()*/ +void OverlayWrapper::placeNeedle(SceneNode *node, float x, float y, float len) +{ /**(Real)win->getHeight()/(Real)win->getWidth()*/ node->setPosition((x - 640.0) / 444.0, (512 - y) / 444.0, -2.0); node->setScale(0.0025, 0.007 * len, 0.007); } -Overlay* OverlayWrapper::loadOverlay(String name, bool autoResizeRation) +Overlay *OverlayWrapper::loadOverlay(String name, bool autoResizeRation) { - Overlay* o = OverlayManager::getSingleton().getByName(name); - if (!o) - return NULL; + Overlay *o = OverlayManager::getSingleton().getByName(name); + if (!o) return NULL; if (autoResizeRation) { struct LoadedOverlay lo; - lo.o = o; + lo.o = o; lo.orgScaleX = o->getScaleX(); lo.orgScaleY = o->getScaleY(); @@ -112,7 +107,7 @@ Overlay* OverlayWrapper::loadOverlay(String name, bool autoResizeRation) return o; } -void OverlayWrapper::resizeOverlay(LoadedOverlay& lo) +void OverlayWrapper::resizeOverlay(LoadedOverlay &lo) { // enforce 4:3 for overlays float w = win->getWidth(); @@ -120,8 +115,7 @@ void OverlayWrapper::resizeOverlay(LoadedOverlay& lo) float s = (4.0f / 3.0f) / (w / h); // window is higher than wide - if (s > 1) - s = (3.0f / 4.0f) / (h / w); + if (s > 1) s = (3.0f / 4.0f) / (h / w); // originals lo.o->setScale(lo.orgScaleX, lo.orgScaleY); @@ -140,12 +134,12 @@ void OverlayWrapper::windowResized() } } -OverlayElement* OverlayWrapper::loadOverlayElement(String name) +OverlayElement *OverlayWrapper::loadOverlayElement(String name) { return OverlayManager::getSingleton().getOverlayElement(name); } -Ogre::TextureUnitState* GetTexUnit(Ogre::String material_name) // Internal helper +Ogre::TextureUnitState *GetTexUnit(Ogre::String material_name) // Internal helper { return MaterialManager::getSingleton().getByName(material_name)->getTechnique(0)->getPass(0)->getTextureUnitState(0); } @@ -155,13 +149,14 @@ int OverlayWrapper::init() m_direction_arrow_overlay = loadOverlay("tracks/DirectionArrow", false); try { - directionArrowText = (TextAreaOverlayElement*)loadOverlayElement("tracks/DirectionArrow/Text"); + directionArrowText = (TextAreaOverlayElement *)loadOverlayElement("tracks/DirectionArrow/Text"); } catch (...) { - ErrorUtils::ShowError("Resources not found!", "please ensure that your installation is complete and the resources are installed properly. If this error persists please re-install RoR."); + ErrorUtils::ShowError("Resources not found!", "please ensure that your installation is complete and the resources are " + "installed properly. If this error persists please re-install RoR."); } - directionArrowDistance = (TextAreaOverlayElement*)loadOverlayElement("tracks/DirectionArrow/Distance"); + directionArrowDistance = (TextAreaOverlayElement *)loadOverlayElement("tracks/DirectionArrow/Distance"); // openGL fix m_direction_arrow_overlay->show(); @@ -169,18 +164,16 @@ int OverlayWrapper::init() m_debug_fps_memory_overlay = loadOverlay("Core/DebugOverlay", false); - OverlayElement* vere = loadOverlayElement("Core/RoRVersionString"); - if (vere) - vere->setCaption("Rigs of Rods version " + String(ROR_VERSION_STRING)); + OverlayElement *vere = loadOverlayElement("Core/RoRVersionString"); + if (vere) vere->setCaption("Rigs of Rods version " + String(ROR_VERSION_STRING)); - m_machine_dashboard_overlay = loadOverlay("tracks/MachineDashboardOverlay"); - m_aerial_dashboard.dash_overlay = loadOverlay("tracks/AirDashboardOverlay", false); + m_machine_dashboard_overlay = loadOverlay("tracks/MachineDashboardOverlay"); + m_aerial_dashboard.dash_overlay = loadOverlay("tracks/AirDashboardOverlay", false); m_aerial_dashboard.needles_overlay = loadOverlay("tracks/AirNeedlesOverlay", false); - m_marine_dashboard_overlay = loadOverlay("tracks/BoatDashboardOverlay"); + m_marine_dashboard_overlay = loadOverlay("tracks/BoatDashboardOverlay"); m_marine_dashboard_needles_overlay = loadOverlay("tracks/BoatNeedlesOverlay"); - - //adjust dashboard size for screen ratio + // adjust dashboard size for screen ratio resizePanel(loadOverlayElement("tracks/pressureo")); resizePanel(loadOverlayElement("tracks/pressureneedle")); MaterialPtr m = MaterialManager::getSingleton().getByName("tracks/pressureneedle_mat"); @@ -198,7 +191,7 @@ int OverlayWrapper::init() resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/airdashbar")); resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/airdashfiller")); - OverlayElement* tempoe; + OverlayElement *tempoe; resizePanel(tempoe = OverlayManager::getSingleton().getOverlayElement("tracks/thrusttrack1")); resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/thrusttrack2")); @@ -210,17 +203,17 @@ int OverlayWrapper::init() resizePanel(m_aerial_dashboard.engines[2].thr_element = loadOverlayElement("tracks/thrust3")); resizePanel(m_aerial_dashboard.engines[3].thr_element = loadOverlayElement("tracks/thrust4")); - thrtop = 1.0f + tempoe->getTop() + m_aerial_dashboard.engines[0].thr_element->getHeight() * 0.5f; + thrtop = 1.0f + tempoe->getTop() + m_aerial_dashboard.engines[0].thr_element->getHeight() * 0.5f; thrheight = tempoe->getHeight() - m_aerial_dashboard.engines[0].thr_element->getHeight() * 2.0f; throffset = m_aerial_dashboard.engines[0].thr_element->getHeight() * 0.5f; - m_aerial_dashboard.thrust_track_top = thrtop; + m_aerial_dashboard.thrust_track_top = thrtop; m_aerial_dashboard.thrust_track_height = thrheight; - m_aerial_dashboard.engines[0].engfire_element = loadOverlayElement("tracks/engfire1"); - m_aerial_dashboard.engines[1].engfire_element = loadOverlayElement("tracks/engfire2"); - m_aerial_dashboard.engines[2].engfire_element = loadOverlayElement("tracks/engfire3"); - m_aerial_dashboard.engines[3].engfire_element = loadOverlayElement("tracks/engfire4"); + m_aerial_dashboard.engines[0].engfire_element = loadOverlayElement("tracks/engfire1"); + m_aerial_dashboard.engines[1].engfire_element = loadOverlayElement("tracks/engfire2"); + m_aerial_dashboard.engines[2].engfire_element = loadOverlayElement("tracks/engfire3"); + m_aerial_dashboard.engines[3].engfire_element = loadOverlayElement("tracks/engfire4"); m_aerial_dashboard.engines[0].engstart_element = loadOverlayElement("tracks/engstart1"); m_aerial_dashboard.engines[1].engstart_element = loadOverlayElement("tracks/engstart2"); m_aerial_dashboard.engines[2].engstart_element = loadOverlayElement("tracks/engstart3"); @@ -241,8 +234,8 @@ int OverlayWrapper::init() resizePanel(loadOverlayElement("tracks/vvi")); resizePanel(loadOverlayElement("tracks/altimeter")); resizePanel(loadOverlayElement("tracks/altimeter_val")); - m_aerial_dashboard.alt_value_textarea = (TextAreaOverlayElement*)loadOverlayElement("tracks/altimeter_val"); - boat_depth_value_taoe = (TextAreaOverlayElement*)loadOverlayElement("tracks/boatdepthmeter_val"); + m_aerial_dashboard.alt_value_textarea = (TextAreaOverlayElement *)loadOverlayElement("tracks/altimeter_val"); + boat_depth_value_taoe = (TextAreaOverlayElement *)loadOverlayElement("tracks/boatdepthmeter_val"); resizePanel(loadOverlayElement("tracks/adi-tape")); resizePanel(loadOverlayElement("tracks/adi")); resizePanel(loadOverlayElement("tracks/adi-bugs")); @@ -255,10 +248,10 @@ int OverlayWrapper::init() resizePanel(loadOverlayElement("tracks/hsi-v")); resizePanel(loadOverlayElement("tracks/hsi-h")); m_aerial_dashboard.hsirosetexture = GetTexUnit("tracks/hsi-rose"); - m_aerial_dashboard.hsibugtexture = GetTexUnit("tracks/hsi-bug"); - m_aerial_dashboard.hsivtexture = GetTexUnit("tracks/hsi-v"); - m_aerial_dashboard.hsihtexture = GetTexUnit("tracks/hsi-h"); - //autopilot + m_aerial_dashboard.hsibugtexture = GetTexUnit("tracks/hsi-bug"); + m_aerial_dashboard.hsivtexture = GetTexUnit("tracks/hsi-v"); + m_aerial_dashboard.hsihtexture = GetTexUnit("tracks/hsi-h"); + // autopilot reposPanel(loadOverlayElement("tracks/ap_hdg_pack")); reposPanel(loadOverlayElement("tracks/ap_wlv_but")); reposPanel(loadOverlayElement("tracks/ap_nav_but")); @@ -280,14 +273,14 @@ int OverlayWrapper::init() m_aerial_dashboard.gpws.Setup("tracks/ap_gpws_but", "tracks/gpws-on", "tracks/gpws-off"); m_aerial_dashboard.brks.Setup("tracks/ap_brks_but", "tracks/brks-on", "tracks/brks-off"); - //boat + // boat resizePanel(loadOverlayElement("tracks/boatdashbar")); resizePanel(loadOverlayElement("tracks/boatdashfiller")); resizePanel(loadOverlayElement("tracks/boatthrusttrack1")); resizePanel(loadOverlayElement("tracks/boatthrusttrack2")); - //resizePanel(boatmapo=loadOverlayElement("tracks/boatmap")); - //resizePanel(boatmapdot=loadOverlayElement("tracks/boatreddot")); + // resizePanel(boatmapo=loadOverlayElement("tracks/boatmap")); + // resizePanel(boatmapdot=loadOverlayElement("tracks/boatreddot")); resizePanel(bthro1 = loadOverlayElement("tracks/boatthrust1")); resizePanel(bthro2 = loadOverlayElement("tracks/boatthrust2")); @@ -296,12 +289,24 @@ int OverlayWrapper::init() resizePanel(loadOverlayElement("tracks/boatsteer")); resizePanel(loadOverlayElement("tracks/boatspeedneedle")); resizePanel(loadOverlayElement("tracks/boatsteer/fg")); - boatspeedtexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/boatspeedneedle_mat")))->getTechnique(0)->getPass(0)->getTextureUnitState(0); - boatsteertexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/boatsteer/fg_mat")))->getTechnique(0)->getPass(0)->getTextureUnitState(0); - - //prepare needles - speedotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/speedoneedle_mat")))->getTechnique(0)->getPass(0)->getTextureUnitState(0); // Needed for dashboard-prop - tachotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/tachoneedle_mat"))) ->getTechnique(0)->getPass(0)->getTextureUnitState(0); // Needed for dashboard-prop + boatspeedtexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/boatspeedneedle_mat"))) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0); + boatsteertexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/boatsteer/fg_mat"))) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0); + + // prepare needles + speedotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/speedoneedle_mat"))) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0); // Needed for dashboard-prop + tachotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/tachoneedle_mat"))) + ->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0); // Needed for dashboard-prop resizePanel(loadOverlayElement("tracks/airspeedneedle")); m_aerial_dashboard.airspeedtexture = GetTexUnit("tracks/airspeedneedle_mat"); @@ -342,27 +347,27 @@ int OverlayWrapper::init() resizePanel(loadOverlayElement("tracks/airtorque4needle")); m_aerial_dashboard.engines[3].torque_texture = GetTexUnit("tracks/airtorque4needle_mat"); - guiGear = loadOverlayElement("tracks/Gear"); + guiGear = loadOverlayElement("tracks/Gear"); guiGear3D = loadOverlayElement("tracks/3DGear"); - guiAuto[0] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearR"); - guiAuto[1] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearN"); - guiAuto[2] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearD"); - guiAuto[3] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGear2"); - guiAuto[4] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGear1"); + guiAuto[0] = (TextAreaOverlayElement *)loadOverlayElement("tracks/AGearR"); + guiAuto[1] = (TextAreaOverlayElement *)loadOverlayElement("tracks/AGearN"); + guiAuto[2] = (TextAreaOverlayElement *)loadOverlayElement("tracks/AGearD"); + guiAuto[3] = (TextAreaOverlayElement *)loadOverlayElement("tracks/AGear2"); + guiAuto[4] = (TextAreaOverlayElement *)loadOverlayElement("tracks/AGear1"); - guiAuto3D[0] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGearR"); - guiAuto3D[1] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGearN"); - guiAuto3D[2] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGearD"); - guiAuto3D[3] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGear2"); - guiAuto3D[4] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGear1"); + guiAuto3D[0] = (TextAreaOverlayElement *)loadOverlayElement("tracks/3DAGearR"); + guiAuto3D[1] = (TextAreaOverlayElement *)loadOverlayElement("tracks/3DAGearN"); + guiAuto3D[2] = (TextAreaOverlayElement *)loadOverlayElement("tracks/3DAGearD"); + guiAuto3D[3] = (TextAreaOverlayElement *)loadOverlayElement("tracks/3DAGear2"); + guiAuto3D[4] = (TextAreaOverlayElement *)loadOverlayElement("tracks/3DAGear1"); - m_truck_pressure_overlay = loadOverlay("tracks/PressureOverlay"); + m_truck_pressure_overlay = loadOverlay("tracks/PressureOverlay"); m_truck_pressure_needle_overlay = loadOverlay("tracks/PressureNeedleOverlay"); m_racing_overlay = loadOverlay("tracks/Racing", false); - laptime = (TextAreaOverlayElement*)loadOverlayElement("tracks/Racing/LapTime"); - bestlaptime = (TextAreaOverlayElement*)loadOverlayElement("tracks/Racing/BestLapTime"); + laptime = (TextAreaOverlayElement *)loadOverlayElement("tracks/Racing/LapTime"); + bestlaptime = (TextAreaOverlayElement *)loadOverlayElement("tracks/Racing/BestLapTime"); g_is_scaled = true; @@ -371,14 +376,12 @@ int OverlayWrapper::init() void OverlayWrapper::update(float dt) { - if (mTimeUntilNextToggle > 0) - mTimeUntilNextToggle -= dt; + if (mTimeUntilNextToggle > 0) mTimeUntilNextToggle -= dt; } void OverlayWrapper::showDebugOverlay(int mode) { - if (!m_debug_fps_memory_overlay) - return; + if (!m_debug_fps_memory_overlay) return; if (mode > 0) { @@ -411,12 +414,12 @@ void OverlayWrapper::showPressureOverlay(bool show) } } -void OverlayWrapper::ToggleDashboardOverlays(Actor* actor) +void OverlayWrapper::ToggleDashboardOverlays(Actor *actor) { showDashboardOverlays(!m_dashboard_visible, actor); } -void OverlayWrapper::showDashboardOverlays(bool show, Actor* actor) +void OverlayWrapper::showDashboardOverlays(bool show, Actor *actor) { m_dashboard_visible = show; @@ -460,63 +463,77 @@ void OverlayWrapper::showDashboardOverlays(bool show, Actor* actor) void OverlayWrapper::updateStats(bool detailed) { - static UTFString currFps = _L("Current FPS: "); - static UTFString avgFps = _L("Average FPS: "); - static UTFString bestFps = _L("Best FPS: "); - static UTFString worstFps = _L("Worst FPS: "); - static UTFString tris = _L("Triangle Count: "); - const RenderTarget::FrameStats& stats = win->getStatistics(); + static UTFString currFps = _L("Current FPS: "); + static UTFString avgFps = _L("Average FPS: "); + static UTFString bestFps = _L("Best FPS: "); + static UTFString worstFps = _L("Worst FPS: "); + static UTFString tris = _L("Triangle Count: "); + const RenderTarget::FrameStats &stats = win->getStatistics(); // update stats when necessary try { - OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps"); - OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps"); - OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps"); - OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps"); + OverlayElement *guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps"); + OverlayElement *guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps"); + OverlayElement *guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps"); + OverlayElement *guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps"); guiAvg->setCaption(avgFps + TOUTFSTRING(stats.avgFPS)); guiCurr->setCaption(currFps + TOUTFSTRING(stats.lastFPS)); guiBest->setCaption(bestFps + TOUTFSTRING(stats.bestFPS) + U(" ") + TOUTFSTRING(stats.bestFrameTime) + U(" ms")); guiWorst->setCaption(worstFps + TOUTFSTRING(stats.worstFPS) + U(" ") + TOUTFSTRING(stats.worstFrameTime) + U(" ms")); - OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris"); - UTFString triss = tris + TOUTFSTRING(stats.triangleCount); + OverlayElement *guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris"); + UTFString triss = tris + TOUTFSTRING(stats.triangleCount); if (stats.triangleCount > 1000000) - triss = tris + TOUTFSTRING(stats.triangleCount/1000000.0f) + U(" M"); + triss = tris + TOUTFSTRING(stats.triangleCount / 1000000.0f) + U(" M"); else if (stats.triangleCount > 1000) - triss = tris + TOUTFSTRING(stats.triangleCount/1000.0f) + U(" k"); + triss = tris + TOUTFSTRING(stats.triangleCount / 1000.0f) + U(" k"); guiTris->setCaption(triss); // create some memory texts UTFString memoryText; if (TextureManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Textures: ") + formatBytes(TextureManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(TextureManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Textures: ") + formatBytes(TextureManager::getSingleton().getMemoryUsage()) + U(" / ") + + formatBytes(TextureManager::getSingleton().getMemoryBudget()) + U("\n"); if (CompositorManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Compositors: ") + formatBytes(CompositorManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(CompositorManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Compositors: ") + formatBytes(CompositorManager::getSingleton().getMemoryUsage()) + + U(" / ") + formatBytes(CompositorManager::getSingleton().getMemoryBudget()) + U("\n"); if (FontManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Fonts: ") + formatBytes(FontManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(FontManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Fonts: ") + formatBytes(FontManager::getSingleton().getMemoryUsage()) + U(" / ") + + formatBytes(FontManager::getSingleton().getMemoryBudget()) + U("\n"); if (GpuProgramManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("GPU Program: ") + formatBytes(GpuProgramManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(GpuProgramManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("GPU Program: ") + formatBytes(GpuProgramManager::getSingleton().getMemoryUsage()) + + U(" / ") + formatBytes(GpuProgramManager::getSingleton().getMemoryBudget()) + U("\n"); if (HighLevelGpuProgramManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("HL GPU Program: ") + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("HL GPU Program: ") + + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryUsage()) + U(" / ") + + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryBudget()) + U("\n"); if (MaterialManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + + U(" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + U("\n"); if (MeshManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Meshes: ") + formatBytes(MeshManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(MeshManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Meshes: ") + formatBytes(MeshManager::getSingleton().getMemoryUsage()) + U(" / ") + + formatBytes(MeshManager::getSingleton().getMemoryBudget()) + U("\n"); if (SkeletonManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Skeletons: ") + formatBytes(SkeletonManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(SkeletonManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Skeletons: ") + formatBytes(SkeletonManager::getSingleton().getMemoryUsage()) + + U(" / ") + formatBytes(SkeletonManager::getSingleton().getMemoryBudget()) + U("\n"); if (MaterialManager::getSingleton().getMemoryUsage() > 1) - memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + U(" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + U("\n"); + memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + + U(" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + U("\n"); memoryText = memoryText + U("\n"); - OverlayElement* memoryDbg = OverlayManager::getSingleton().getOverlayElement("Core/MemoryText"); + OverlayElement *memoryDbg = OverlayManager::getSingleton().getOverlayElement("Core/MemoryText"); memoryDbg->setCaption(memoryText); - float sumMem = TextureManager::getSingleton().getMemoryUsage() + CompositorManager::getSingleton().getMemoryUsage() + FontManager::getSingleton().getMemoryUsage() + GpuProgramManager::getSingleton().getMemoryUsage() + HighLevelGpuProgramManager::getSingleton().getMemoryUsage() + MaterialManager::getSingleton().getMemoryUsage() + MeshManager::getSingleton().getMemoryUsage() + SkeletonManager::getSingleton().getMemoryUsage() + MaterialManager::getSingleton().getMemoryUsage(); + float sumMem = TextureManager::getSingleton().getMemoryUsage() + CompositorManager::getSingleton().getMemoryUsage() + + FontManager::getSingleton().getMemoryUsage() + GpuProgramManager::getSingleton().getMemoryUsage() + + HighLevelGpuProgramManager::getSingleton().getMemoryUsage() + + MaterialManager::getSingleton().getMemoryUsage() + MeshManager::getSingleton().getMemoryUsage() + + SkeletonManager::getSingleton().getMemoryUsage() + MaterialManager::getSingleton().getMemoryUsage(); String sumMemoryText = _L("Memory (Ogre): ") + formatBytes(sumMem) + U("\n"); - OverlayElement* memorySumDbg = OverlayManager::getSingleton().getOverlayElement("Core/CurrMemory"); + OverlayElement *memorySumDbg = OverlayManager::getSingleton().getOverlayElement("Core/CurrMemory"); memorySumDbg->setCaption(sumMemoryText); } catch (...) @@ -525,17 +542,15 @@ void OverlayWrapper::updateStats(bool detailed) } } -bool OverlayWrapper::mouseMoved(const OIS::MouseEvent& _arg) +bool OverlayWrapper::mouseMoved(const OIS::MouseEvent &_arg) { - if (!m_aerial_dashboard.needles_overlay->isVisible()) - return false; - bool res = false; - const OIS::MouseState ms = _arg.state; - - Actor* player_actor = RoR::App::GetSimController()->GetPlayerActor(); + if (!m_aerial_dashboard.needles_overlay->isVisible()) return false; + bool res = false; + const OIS::MouseState ms = _arg.state; + + Actor *player_actor = RoR::App::GetSimController()->GetPlayerActor(); - if (!player_actor) - return res; + if (!player_actor) return res; float mouseX = ms.X.abs / (float)ms.width; float mouseY = ms.Y.abs / (float)ms.height; @@ -546,17 +561,15 @@ bool OverlayWrapper::mouseMoved(const OIS::MouseEvent& _arg) { const int num_engines = std::min(4, player_actor->ar_num_aeroengines); - OverlayElement* element = m_aerial_dashboard.needles_overlay->findElementAt(mouseX, mouseY); + OverlayElement *element = m_aerial_dashboard.needles_overlay->findElementAt(mouseX, mouseY); if (element) { - res = true; + res = true; float thr_value = 1.0f - ((mouseY - thrtop - throffset) / thrheight); for (int i = 0; i < num_engines; ++i) { if (element == m_aerial_dashboard.engines[i].thr_element) - { - player_actor->ar_aeroengines[i]->setThrottle(thr_value); - } + { player_actor->ar_aeroengines[i]->setThrottle(thr_value); } } } @@ -566,14 +579,11 @@ bool OverlayWrapper::mouseMoved(const OIS::MouseEvent& _arg) res = true; for (int i = 0; i < num_engines; ++i) { - if (element == m_aerial_dashboard.engines[i].engstart_element) - { - player_actor->ar_aeroengines[i]->flipStart(); - } + if (element == m_aerial_dashboard.engines[i].engstart_element) { player_actor->ar_aeroengines[i]->flipStart(); } } if (player_actor->ar_autopilot && mTimeUntilNextToggle <= 0) { - //heading group + // heading group if (element == m_aerial_dashboard.hdg.element) { mTimeUntilNextToggle = 0.2; @@ -589,7 +599,7 @@ bool OverlayWrapper::mouseMoved(const OIS::MouseEvent& _arg) mTimeUntilNextToggle = 0.2; player_actor->ar_autopilot->toggleHeading(Autopilot::HEADING_NAV); } - //altitude group + // altitude group if (element == m_aerial_dashboard.alt.element) { mTimeUntilNextToggle = 0.2; @@ -600,25 +610,25 @@ bool OverlayWrapper::mouseMoved(const OIS::MouseEvent& _arg) mTimeUntilNextToggle = 0.2; player_actor->ar_autopilot->toggleAlt(Autopilot::ALT_VS); } - //IAS + // IAS if (element == m_aerial_dashboard.ias.element) { mTimeUntilNextToggle = 0.2; player_actor->ar_autopilot->toggleIAS(); } - //GPWS + // GPWS if (element == m_aerial_dashboard.gpws.element) { mTimeUntilNextToggle = 0.2; player_actor->ar_autopilot->toggleGPWS(); } - //BRKS + // BRKS if (element == m_aerial_dashboard.brks.element) { mTimeUntilNextToggle = 0.2; player_actor->ToggleParkingBrake(); } - //trims + // trims if (element == m_aerial_dashboard.hdg_trim.up_button) { mTimeUntilNextToggle = 0.1; @@ -665,12 +675,12 @@ bool OverlayWrapper::mouseMoved(const OIS::MouseEvent& _arg) return res; } -bool OverlayWrapper::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool OverlayWrapper::mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { return mouseMoved(_arg); } -bool OverlayWrapper::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id) +bool OverlayWrapper::mouseReleased(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id) { return mouseMoved(_arg); } @@ -680,7 +690,7 @@ void OverlayWrapper::SetupDirectionArrow() if (RoR::App::GetOverlayWrapper() != nullptr) { // setup direction arrow - Ogre::Entity* arrow_entity = gEnv->sceneManager->createEntity("arrow2.mesh"); + Ogre::Entity *arrow_entity = gEnv->sceneManager->createEntity("arrow2.mesh"); arrow_entity->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY); // Add entity to the scene node @@ -694,14 +704,12 @@ void OverlayWrapper::SetupDirectionArrow() } } -void OverlayWrapper::UpdateDirectionArrowHud(RoR::GfxActor* player_vehicle, Ogre::Vector3 point_to, Ogre::Vector3 character_pos) +void OverlayWrapper::UpdateDirectionArrowHud(RoR::GfxActor *player_vehicle, Ogre::Vector3 point_to, Ogre::Vector3 character_pos) { m_direction_arrow_node->lookAt(point_to, Node::TS_WORLD, Vector3::UNIT_Y); Real distance = 0.0f; if (player_vehicle != nullptr && player_vehicle->GetSimDataBuffer().simbuf_live_local) - { - distance = player_vehicle->GetSimDataBuffer().simbuf_pos.distance(point_to); - } + { distance = player_vehicle->GetSimDataBuffer().simbuf_pos.distance(point_to); } else if (gEnv->player) { distance = character_pos.distance(point_to); @@ -718,7 +726,7 @@ void OverlayWrapper::HideDirectionOverlay() BITMASK_SET_0(m_visible_overlays, VisibleOverlays::DIRECTION_ARROW); } -void OverlayWrapper::ShowDirectionOverlay(Ogre::String const& caption) +void OverlayWrapper::ShowDirectionOverlay(Ogre::String const &caption) { m_direction_arrow_overlay->show(); directionArrowText->setCaption(caption); @@ -727,21 +735,21 @@ void OverlayWrapper::ShowDirectionOverlay(Ogre::String const& caption) BITMASK_SET_1(m_visible_overlays, VisibleOverlays::DIRECTION_ARROW); } -void OverlayWrapper::UpdatePressureTexture(RoR::GfxActor* ga) +void OverlayWrapper::UpdatePressureTexture(RoR::GfxActor *ga) { const float pressure = ga->GetSimDataBuffer().simbuf_tyre_pressure; - Real angle = 135.0 - pressure * 2.7; + Real angle = 135.0 - pressure * 2.7; pressuretexture->setTextureRotate(Degree(angle)); } -void OverlayWrapper::UpdateLandVehicleHUD(RoR::GfxActor* ga) +void OverlayWrapper::UpdateLandVehicleHUD(RoR::GfxActor *ga) { // gears int vehicle_getgear = ga->GetSimDataBuffer().simbuf_gear; if (vehicle_getgear > 0) { size_t numgears = ga->GetAttributes().xa_num_gears; - String gearstr = TOSTRING(vehicle_getgear) + "/" + TOSTRING(numgears); + String gearstr = TOSTRING(vehicle_getgear) + "/" + TOSTRING(numgears); guiGear->setCaption(gearstr); guiGear3D->setCaption(gearstr); } @@ -756,7 +764,7 @@ void OverlayWrapper::UpdateLandVehicleHUD(RoR::GfxActor* ga) guiGear3D->setCaption("R"); } - //autogears + // autogears int cg = ga->GetSimDataBuffer().simbuf_autoshift; for (int i = 0; i < 5; i++) { @@ -798,56 +806,54 @@ void OverlayWrapper::UpdateLandVehicleHUD(RoR::GfxActor* ga) // speedo / calculate speed Real guiSpeedFactor = 7.0 * (140.0 / ga->GetAttributes().xa_speedo_highest_kph); - Real angle = 140 - fabs(ga->GetSimDataBuffer().simbuf_wheel_speed * guiSpeedFactor); - angle = std::max(-140.0f, angle); + Real angle = 140 - fabs(ga->GetSimDataBuffer().simbuf_wheel_speed * guiSpeedFactor); + angle = std::max(-140.0f, angle); speedotexture->setTextureRotate(Degree(angle)); // calculate tach stuff Real tachoFactor = 0.072; if (ga->GetAttributes().xa_speedo_use_engine_max_rpm) - { - tachoFactor = 0.072 * (3500 / ga->GetAttributes().xa_engine_max_rpm); - } + { tachoFactor = 0.072 * (3500 / ga->GetAttributes().xa_engine_max_rpm); } angle = 126.0 - fabs(ga->GetSimDataBuffer().simbuf_engine_rpm * tachoFactor); angle = std::max(-120.0f, angle); angle = std::min(angle, 121.0f); tachotexture->setTextureRotate(Degree(angle)); } -void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor* gfx_actor) +void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor *gfx_actor) { - RoR::GfxActor::SimBuffer& simbuf = gfx_actor->GetSimDataBuffer(); - RoR::GfxActor::NodeData* nodes = gfx_actor->GetSimNodeBuffer(); - RoR::GfxActor::Attributes& attr = gfx_actor->GetAttributes(); + RoR::GfxActor::SimBuffer & simbuf = gfx_actor->GetSimDataBuffer(); + RoR::GfxActor::NodeData * nodes = gfx_actor->GetSimNodeBuffer(); + RoR::GfxActor::Attributes &attr = gfx_actor->GetAttributes(); - auto const& simbuf_ae = simbuf.simbuf_aeroengines; - int num_ae = static_cast( simbuf_ae.size() ); + auto const &simbuf_ae = simbuf.simbuf_aeroengines; + int num_ae = static_cast(simbuf_ae.size()); - //throttles + // throttles m_aerial_dashboard.SetThrottle(0, true, simbuf_ae[0].simbuf_ae_throttle); m_aerial_dashboard.SetThrottle(1, (num_ae > 1), (num_ae > 1) ? simbuf_ae[1].simbuf_ae_throttle : 0.f); m_aerial_dashboard.SetThrottle(2, (num_ae > 2), (num_ae > 2) ? simbuf_ae[2].simbuf_ae_throttle : 0.f); m_aerial_dashboard.SetThrottle(3, (num_ae > 3), (num_ae > 3) ? simbuf_ae[3].simbuf_ae_throttle : 0.f); - //fire + // fire m_aerial_dashboard.SetEngineFailed(0, simbuf_ae[0].simbuf_ae_failed); m_aerial_dashboard.SetEngineFailed(1, num_ae > 1 && simbuf_ae[1].simbuf_ae_failed); m_aerial_dashboard.SetEngineFailed(2, num_ae > 2 && simbuf_ae[2].simbuf_ae_failed); m_aerial_dashboard.SetEngineFailed(3, num_ae > 3 && simbuf_ae[3].simbuf_ae_failed); - //airspeed - float angle = 0.0; + // airspeed + float angle = 0.0; float ground_speed_kt = simbuf.simbuf_node0_velo.length() * 1.9438; // 1.943 = m/s in knots/s - //tropospheric model valid up to 11.000m (33.000ft) + // tropospheric model valid up to 11.000m (33.000ft) float altitude = nodes[0].AbsPosition.y; - //float sea_level_temperature=273.15+15.0; //in Kelvin - float sea_level_pressure = 101325; //in Pa - //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin - float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa - float airdensity = airpressure * 0.0000120896;//1.225 at sea level + // float sea_level_temperature=273.15+15.0; //in Kelvin + float sea_level_pressure = 101325; // in Pa + // float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin + float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896; // 1.225 at sea level - float kt = ground_speed_kt * sqrt(airdensity / 1.225); //KIAS + float kt = ground_speed_kt * sqrt(airdensity / 1.225); // KIAS if (kt > 23.0) { if (kt < 50.0) @@ -863,11 +869,9 @@ void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor* gfx_actor) // AOA angle = simbuf.simbuf_wing4_aoa; - if (kt < 10.0) - angle = 0; + if (kt < 10.0) angle = 0; float absangle = angle; - if (absangle < 0) - absangle = -absangle; + if (absangle < 0) absangle = -absangle; const int actor_id = gfx_actor->GetActorId(); SOUND_MODULATE(actor_id, SS_MOD_AOA, absangle); @@ -876,10 +880,8 @@ void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor* gfx_actor) else SOUND_STOP(actor_id, SS_TRIG_AOA); - if (angle > 25.0) - angle = 25.0; - if (angle < -25.0) - angle = -25.0; + if (angle > 25.0) angle = 25.0; + if (angle < -25.0) angle = -25.0; m_aerial_dashboard.aoatexture->setTextureRotate(Degree(-angle * 4.7 + 90.0)); // altimeter @@ -889,27 +891,26 @@ void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor* gfx_actor) sprintf(altc, "%03u", (int)(nodes[0].AbsPosition.y / 30.48)); m_aerial_dashboard.alt_value_textarea->setCaption(altc); - //adi - //roll + // adi + // roll Vector3 rollv = nodes[attr.xa_camera0_pos_node].AbsPosition - nodes[attr.xa_camera0_roll_node].AbsPosition; rollv.normalise(); float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y)); - //pitch - Vector3 dirv = simbuf.simbuf_direction; - float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y)); - Vector3 upv = dirv.crossProduct(-rollv); - if (upv.y < 0) - rollangle = 3.14159 - rollangle; + // pitch + Vector3 dirv = simbuf.simbuf_direction; + float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y)); + Vector3 upv = dirv.crossProduct(-rollv); + if (upv.y < 0) rollangle = 3.14159 - rollangle; m_aerial_dashboard.adibugstexture->setTextureRotate(Radian(-rollangle)); m_aerial_dashboard.aditapetexture->setTextureVScroll(-pitchangle * 0.25); m_aerial_dashboard.aditapetexture->setTextureRotate(Radian(-rollangle)); - //hsi + // hsi float dirangle = atan2(dirv.dotProduct(Vector3::UNIT_X), dirv.dotProduct(-Vector3::UNIT_Z)); m_aerial_dashboard.hsirosetexture->setTextureRotate(Radian(dirangle)); - //autopilot + // autopilot m_aerial_dashboard.hsibugtexture->setTextureRotate(Radian(dirangle) - Degree(simbuf.simbuf_ap_heading_value)); float vdev = 0; @@ -919,70 +920,64 @@ void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor* gfx_actor) vdev = simbuf.simbuf_ap_ils_vdev; hdev = simbuf.simbuf_ap_ils_hdev; } - if (hdev > 15) - hdev = 15; - if (hdev < -15) - hdev = -15; + if (hdev > 15) hdev = 15; + if (hdev < -15) hdev = -15; m_aerial_dashboard.hsivtexture->setTextureUScroll(-hdev * 0.02); - if (vdev > 15) - vdev = 15; - if (vdev < -15) - vdev = -15; + if (vdev > 15) vdev = 15; + if (vdev < -15) vdev = -15; m_aerial_dashboard.hsihtexture->setTextureVScroll(-vdev * 0.02); - //vvi + // vvi float vvi = simbuf.simbuf_node0_velo.y * 196.85; - if (vvi < 1000.0 && vvi > -1000.0) - angle = vvi * 0.047; - if (vvi > 1000.0 && vvi < 6000.0) - angle = 47.0 + (vvi - 1000.0) * 0.01175; - if (vvi > 6000.0) - angle = 105.75; - if (vvi < -1000.0 && vvi > -6000.0) - angle = -47.0 + (vvi + 1000.0) * 0.01175; - if (vvi < -6000.0) - angle = -105.75; + if (vvi < 1000.0 && vvi > -1000.0) angle = vvi * 0.047; + if (vvi > 1000.0 && vvi < 6000.0) angle = 47.0 + (vvi - 1000.0) * 0.01175; + if (vvi > 6000.0) angle = 105.75; + if (vvi < -1000.0 && vvi > -6000.0) angle = -47.0 + (vvi + 1000.0) * 0.01175; + if (vvi < -6000.0) angle = -105.75; m_aerial_dashboard.vvitexture->setTextureRotate(Degree(-angle + 90.0)); - //rpm + // rpm m_aerial_dashboard.SetEngineRpm(0, simbuf_ae[0].simbuf_ae_rpmpc); m_aerial_dashboard.SetEngineRpm(1, (num_ae > 1) ? simbuf_ae[1].simbuf_ae_rpmpc : 0.f); m_aerial_dashboard.SetEngineRpm(2, (num_ae > 2) ? simbuf_ae[2].simbuf_ae_rpmpc : 0.f); m_aerial_dashboard.SetEngineRpm(3, (num_ae > 3) ? simbuf_ae[3].simbuf_ae_rpmpc : 0.f); - //turboprops - pitch + // turboprops - pitch m_aerial_dashboard.SetEnginePitch(0, (simbuf_ae[0].simbuf_ae_turboprop) ? simbuf_ae[0].simbuf_tp_aepitch : 0.f); m_aerial_dashboard.SetEnginePitch(1, (num_ae > 1 && simbuf_ae[1].simbuf_ae_turboprop) ? simbuf_ae[1].simbuf_tp_aepitch : 0.f); m_aerial_dashboard.SetEnginePitch(2, (num_ae > 2 && simbuf_ae[2].simbuf_ae_turboprop) ? simbuf_ae[2].simbuf_tp_aepitch : 0.f); m_aerial_dashboard.SetEnginePitch(3, (num_ae > 3 && simbuf_ae[3].simbuf_ae_turboprop) ? simbuf_ae[3].simbuf_tp_aepitch : 0.f); - //turboprops - torque + // turboprops - torque m_aerial_dashboard.SetEngineTorque(0, (simbuf_ae[0].simbuf_ae_turboprop) ? simbuf_ae[0].simbuf_tp_aetorque : 0.f); - m_aerial_dashboard.SetEngineTorque(1, (num_ae > 1 && simbuf_ae[1].simbuf_ae_turboprop) ? simbuf_ae[1].simbuf_tp_aetorque : 0.f); - m_aerial_dashboard.SetEngineTorque(2, (num_ae > 2 && simbuf_ae[2].simbuf_ae_turboprop) ? simbuf_ae[2].simbuf_tp_aetorque : 0.f); - m_aerial_dashboard.SetEngineTorque(3, (num_ae > 3 && simbuf_ae[3].simbuf_ae_turboprop) ? simbuf_ae[3].simbuf_tp_aetorque : 0.f); - - //starters + m_aerial_dashboard.SetEngineTorque(1, + (num_ae > 1 && simbuf_ae[1].simbuf_ae_turboprop) ? simbuf_ae[1].simbuf_tp_aetorque : 0.f); + m_aerial_dashboard.SetEngineTorque(2, + (num_ae > 2 && simbuf_ae[2].simbuf_ae_turboprop) ? simbuf_ae[2].simbuf_tp_aetorque : 0.f); + m_aerial_dashboard.SetEngineTorque(3, + (num_ae > 3 && simbuf_ae[3].simbuf_ae_turboprop) ? simbuf_ae[3].simbuf_tp_aetorque : 0.f); + + // starters m_aerial_dashboard.SetIgnition(0, true, simbuf_ae[0].simbuf_ae_ignition); m_aerial_dashboard.SetIgnition(1, num_ae > 1, num_ae > 1 && simbuf_ae[1].simbuf_ae_ignition); m_aerial_dashboard.SetIgnition(2, num_ae > 2, num_ae > 2 && simbuf_ae[2].simbuf_ae_ignition); m_aerial_dashboard.SetIgnition(3, num_ae > 3, num_ae > 3 && simbuf_ae[3].simbuf_ae_ignition); - //autopilot - heading + // autopilot - heading m_aerial_dashboard.hdg.SetActive(simbuf.simbuf_ap_heading_mode == Autopilot::HEADING_FIXED); m_aerial_dashboard.wlv.SetActive(simbuf.simbuf_ap_heading_mode == Autopilot::HEADING_WLV); m_aerial_dashboard.nav.SetActive(simbuf.simbuf_ap_heading_mode == Autopilot::HEADING_NAV); - //autopilot - altitude + // autopilot - altitude m_aerial_dashboard.alt.SetActive(simbuf.simbuf_ap_alt_mode == Autopilot::ALT_FIXED); m_aerial_dashboard.vs.SetActive(simbuf.simbuf_ap_alt_mode == Autopilot::ALT_VS); - //autopilot - other buttons + // autopilot - other buttons m_aerial_dashboard.ias.SetActive(simbuf.simbuf_ap_ias_mode); m_aerial_dashboard.gpws.SetActive(simbuf.simbuf_ap_gpws_mode); m_aerial_dashboard.brks.SetActive(simbuf.simbuf_parking_brake); - //autopilot - trims + // autopilot - trims m_aerial_dashboard.hdg_trim.DisplayFormat("%.3u", simbuf.simbuf_ap_heading_value); m_aerial_dashboard.alt_trim.DisplayFormat("%i00", simbuf.simbuf_ap_alt_value / 100); m_aerial_dashboard.ias_trim.DisplayFormat("%.3u", simbuf.simbuf_ap_ias_value); @@ -994,18 +989,16 @@ void OverlayWrapper::UpdateAerialHUD(RoR::GfxActor* gfx_actor) m_aerial_dashboard.vs_trim.DisplayFormat("+%i00", simbuf.simbuf_ap_vs_value / 100); } -void OverlayWrapper::UpdateMarineHUD(Actor* vehicle) +void OverlayWrapper::UpdateMarineHUD(Actor *vehicle) { // throttles bthro1->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[0]->getThrottle() / 2.0) - 1.0); if (vehicle->ar_num_screwprops > 1) - { - bthro2->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[1]->getThrottle() / 2.0) - 1.0); - } + { bthro2->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[1]->getThrottle() / 2.0) - 1.0); } // depth - char tmp[50] = ""; - float height = vehicle->GetHeightAboveGround(); + char tmp[50] = ""; + float height = vehicle->GetHeightAboveGround(); if (height > 0.1 && height < 99.9) { sprintf(tmp, "%2.1f", height); @@ -1017,10 +1010,10 @@ void OverlayWrapper::UpdateMarineHUD(Actor* vehicle) } // water speed - Vector3 cam_dir = vehicle->getDirection(); + Vector3 cam_dir = vehicle->getDirection(); Vector3 velocity = vehicle->ar_nodes[vehicle->ar_main_camera_node_pos].Velocity; - float kt = cam_dir.dotProduct(velocity) * 1.9438; - float angle = kt * 4.2; + float kt = cam_dir.dotProduct(velocity) * 1.9438; + float angle = kt * 4.2; boatspeedtexture->setTextureRotate(Degree(-angle)); boatsteertexture->setTextureRotate(Degree(vehicle->ar_screwprops[0]->getRudder() * 170)); } @@ -1037,7 +1030,7 @@ void OverlayWrapper::HideRacingOverlay() BITMASK_SET_0(m_visible_overlays, VisibleOverlays::RACING); } -void OverlayWrapper::TemporarilyHideAllOverlays(Actor* current_vehicle) +void OverlayWrapper::TemporarilyHideAllOverlays(Actor *current_vehicle) { m_racing_overlay->hide(); m_direction_arrow_overlay->hide(); @@ -1046,12 +1039,9 @@ void OverlayWrapper::TemporarilyHideAllOverlays(Actor* current_vehicle) showDashboardOverlays(false, current_vehicle); } -void OverlayWrapper::RestoreOverlaysVisibility(Actor* current_vehicle) +void OverlayWrapper::RestoreOverlaysVisibility(Actor *current_vehicle) { - if (BITMASK_IS_1(m_visible_overlays, VisibleOverlays::RACING)) - { - m_racing_overlay->show(); - } + if (BITMASK_IS_1(m_visible_overlays, VisibleOverlays::RACING)) { m_racing_overlay->show(); } else if (BITMASK_IS_1(m_visible_overlays, VisibleOverlays::DIRECTION_ARROW)) { m_direction_arrow_overlay->show(); @@ -1064,15 +1054,15 @@ void OverlayWrapper::RestoreOverlaysVisibility(Actor* current_vehicle) showDashboardOverlays(!RoR::App::GetSimController()->IsGUIHidden(), current_vehicle); } -void OverlayWrapper::UpdateRacingGui(RoR::GfxScene* gs) +void OverlayWrapper::UpdateRacingGui(RoR::GfxScene *gs) { - float time = gs->GetSimDataBuffer().simbuf_race_time; - UTFString txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100); + float time = gs->GetSimDataBuffer().simbuf_race_time; + UTFString txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100); this->laptime->setCaption(txt); if (gs->GetSimDataBuffer().simbuf_race_best_time > 0.0f) { time = gs->GetSimDataBuffer().simbuf_race_best_time; - txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100); + txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100); this->bestlaptime->setCaption(txt); this->bestlaptime->show(); } @@ -1081,12 +1071,9 @@ void OverlayWrapper::UpdateRacingGui(RoR::GfxScene* gs) this->bestlaptime->hide(); } - float time_diff = gs->GetSimDataBuffer().simbuf_race_time_diff; - Ogre::ColourValue colour = Ogre::ColourValue::White; - if (time_diff > 0.0f) - { - colour = ColourValue(0.8, 0.0, 0.0); - } + float time_diff = gs->GetSimDataBuffer().simbuf_race_time_diff; + Ogre::ColourValue colour = Ogre::ColourValue::White; + if (time_diff > 0.0f) { colour = ColourValue(0.8, 0.0, 0.0); } else if (time_diff < 0.0f) { colour = ColourValue(0.0, 0.8, 0.0); @@ -1100,8 +1087,7 @@ void AeroDashOverlay::SetThrottle(int engine, bool visible, float value) if (visible) { engines[engine].thr_element->show(); - engines[engine].thr_element->setTop( - thrust_track_top + thrust_track_height * (1.0 - value) - 1.0); + engines[engine].thr_element->setTop(thrust_track_top + thrust_track_height * (1.0 - value) - 1.0); } else { @@ -1111,8 +1097,7 @@ void AeroDashOverlay::SetThrottle(int engine, bool visible, float value) void AeroDashOverlay::SetEngineFailed(int engine, bool value) { - engines[engine].engfire_element->setMaterialName( - value ? "tracks/engfire-on" : "tracks/engfire-off"); + engines[engine].engfire_element->setMaterialName(value ? "tracks/engfire-on" : "tracks/engfire-off"); } void AeroDashOverlay::SetEngineRpm(int engine, float pcent) @@ -1149,8 +1134,7 @@ void AeroDashOverlay::SetIgnition(int engine, bool visible, bool ignited) if (visible) { engines[engine].engstart_element->show(); - engines[engine].engstart_element->setMaterialName( - ignited ? "tracks/engstart-on" : "tracks/engstart-off"); + engines[engine].engstart_element->setMaterialName(ignited ? "tracks/engstart-on" : "tracks/engstart-off"); } else { @@ -1163,27 +1147,27 @@ void AeroSwitchOverlay::SetActive(bool value) element->setMaterial(value ? on_material : off_material); } -void AeroSwitchOverlay::Setup(std::string const & elem_name, std::string const & mat_on, std::string const & mat_off) +void AeroSwitchOverlay::Setup(std::string const &elem_name, std::string const &mat_on, std::string const &mat_off) { - element = Ogre::OverlayManager::getSingleton().getOverlayElement(elem_name); - on_material = Ogre::MaterialManager::getSingleton().getByName(mat_on); + element = Ogre::OverlayManager::getSingleton().getOverlayElement(elem_name); + on_material = Ogre::MaterialManager::getSingleton().getByName(mat_on); off_material = Ogre::MaterialManager::getSingleton().getByName(mat_off); } -void AeroTrimOverlay::Setup(std::string const & up, std::string const & dn, std::string const & disp) +void AeroTrimOverlay::Setup(std::string const &up, std::string const &dn, std::string const &disp) { - display = Ogre::OverlayManager::getSingleton().getOverlayElement(disp); + display = Ogre::OverlayManager::getSingleton().getOverlayElement(disp); up_button = Ogre::OverlayManager::getSingleton().getOverlayElement(up); dn_button = Ogre::OverlayManager::getSingleton().getOverlayElement(dn); } -void AeroTrimOverlay::DisplayFormat(const char* fmt, ...) +void AeroTrimOverlay::DisplayFormat(const char *fmt, ...) { char buffer[500] = {}; va_list args; va_start(args, fmt); - vsprintf(buffer, fmt, args); + vsprintf(buffer, fmt, args); va_end(args); display->setCaption(buffer); diff --git a/source/main/gui/OverlayWrapper.h b/source/main/gui/OverlayWrapper.h index 6ca6f9a63b..c8c06dc70a 100644 --- a/source/main/gui/OverlayWrapper.h +++ b/source/main/gui/OverlayWrapper.h @@ -19,24 +19,22 @@ along with Rigs of Rods. If not, see . */ - /// @file /// @author Thomas Fischer /// @date 6th of May 2010 - #pragma once #include "RoRPrerequisites.h" -#include #include +#include struct AeroEngineOverlay { - Ogre::OverlayElement *thr_element; - Ogre::OverlayElement *engfire_element; - Ogre::OverlayElement *engstart_element; + Ogre::OverlayElement * thr_element; + Ogre::OverlayElement * engfire_element; + Ogre::OverlayElement * engstart_element; Ogre::TextureUnitState *rpm_texture; Ogre::TextureUnitState *pitch_texture; Ogre::TextureUnitState *torque_texture; @@ -44,18 +42,18 @@ struct AeroEngineOverlay struct AeroSwitchOverlay { - void Setup(std::string const & elem_name, std::string const & mat_on, std::string const & mat_off); + void Setup(std::string const &elem_name, std::string const &mat_on, std::string const &mat_off); void SetActive(bool value); Ogre::OverlayElement *element; - Ogre::MaterialPtr on_material; - Ogre::MaterialPtr off_material; + Ogre::MaterialPtr on_material; + Ogre::MaterialPtr off_material; }; struct AeroTrimOverlay { - void Setup(std::string const & up, std::string const & dn, std::string const & disp); - void DisplayFormat(const char* fmt, ...); + void Setup(std::string const &up, std::string const &dn, std::string const &disp); + void DisplayFormat(const char *fmt, ...); Ogre::OverlayElement *up_button; Ogre::OverlayElement *dn_button; @@ -76,17 +74,17 @@ struct AeroDashOverlay Ogre::Overlay *dash_overlay; Ogre::Overlay *needles_overlay; - Ogre::TextureUnitState *adibugstexture; - Ogre::TextureUnitState *aditapetexture; - Ogre::TextureUnitState *hsirosetexture; - Ogre::TextureUnitState *hsibugtexture; - Ogre::TextureUnitState *hsivtexture; - Ogre::TextureUnitState *hsihtexture; - Ogre::TextureUnitState *airspeedtexture; - Ogre::TextureUnitState *altimetertexture; - Ogre::TextureUnitState *vvitexture; - Ogre::TextureUnitState *aoatexture; - Ogre::TextAreaOverlayElement* alt_value_textarea; + Ogre::TextureUnitState * adibugstexture; + Ogre::TextureUnitState * aditapetexture; + Ogre::TextureUnitState * hsirosetexture; + Ogre::TextureUnitState * hsibugtexture; + Ogre::TextureUnitState * hsivtexture; + Ogre::TextureUnitState * hsihtexture; + Ogre::TextureUnitState * airspeedtexture; + Ogre::TextureUnitState * altimetertexture; + Ogre::TextureUnitState * vvitexture; + Ogre::TextureUnitState * aoatexture; + Ogre::TextAreaOverlayElement *alt_value_textarea; AeroSwitchOverlay hdg; AeroSwitchOverlay wlv; @@ -111,15 +109,14 @@ class OverlayWrapper : public ZeroedMemoryAllocator friend class SimController; friend class RoR::MainMenu; -public: - + public: OverlayWrapper(); ~OverlayWrapper(); struct LoadedOverlay { - float orgScaleX; - float orgScaleY; + float orgScaleX; + float orgScaleY; Ogre::Overlay *o; }; @@ -130,28 +127,31 @@ class OverlayWrapper : public ZeroedMemoryAllocator void showPressureOverlay(bool show); void windowResized(); - void resizeOverlay(LoadedOverlay & overlay); + void resizeOverlay(LoadedOverlay &overlay); - bool mouseMoved(const OIS::MouseEvent& _arg); - bool mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); - bool mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id); + bool mouseMoved(const OIS::MouseEvent &_arg); + bool mousePressed(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); + bool mouseReleased(const OIS::MouseEvent &_arg, OIS::MouseButtonID _id); float mTimeUntilNextToggle; void SetupDirectionArrow(); - void UpdateDirectionArrowHud(RoR::GfxActor* player_vehicle, Ogre::Vector3 point_to, Ogre::Vector3 character_pos); + void UpdateDirectionArrowHud(RoR::GfxActor *player_vehicle, Ogre::Vector3 point_to, Ogre::Vector3 character_pos); void HideDirectionOverlay(); - void ShowDirectionOverlay(Ogre::String const & caption); - bool IsDirectionArrowVisible() const { return BITMASK_IS_1(m_visible_overlays, VisibleOverlays::DIRECTION_ARROW); } + void ShowDirectionOverlay(Ogre::String const &caption); + bool IsDirectionArrowVisible() const + { + return BITMASK_IS_1(m_visible_overlays, VisibleOverlays::DIRECTION_ARROW); + } - void UpdatePressureTexture(RoR::GfxActor* ga); + void UpdatePressureTexture(RoR::GfxActor *ga); - void UpdateLandVehicleHUD(RoR::GfxActor* ga); - void UpdateAerialHUD(RoR::GfxActor* ga); - void UpdateMarineHUD(Actor * vehicle); + void UpdateLandVehicleHUD(RoR::GfxActor *ga); + void UpdateAerialHUD(RoR::GfxActor *ga); + void UpdateMarineHUD(Actor *vehicle); void ShowRacingOverlay(); void HideRacingOverlay(); - void UpdateRacingGui(RoR::GfxScene* gs); + void UpdateRacingGui(RoR::GfxScene *gs); /// Hides all overlays, but doesn't change visibility flags (for further restoring). void TemporarilyHideAllOverlays(Actor *current_vehicle); @@ -159,30 +159,29 @@ class OverlayWrapper : public ZeroedMemoryAllocator /// Shows all overlays flagged as "visible". void RestoreOverlaysVisibility(Actor *current_vehicle); -protected: - - /// RoR needs to temporarily hide all overlays when player enters editor. + protected: + /// RoR needs to temporarily hide all overlays when player enters editor. /// However, OGRE only provides per-overlay show() and hide() functionality. /// Thus, an external state must be kept to restore overlays after exiting the editor. struct VisibleOverlays { - static const int DIRECTION_ARROW = BITMASK(1); - static const int DEBUG_FPS_MEMORY = BITMASK(2); - static const int RACING = BITMASK(4); - static const int TRUCK_TIRE_PRESSURE_OVERLAY = BITMASK(5); + static const int DIRECTION_ARROW = BITMASK(1); + static const int DEBUG_FPS_MEMORY = BITMASK(2); + static const int RACING = BITMASK(4); + static const int TRUCK_TIRE_PRESSURE_OVERLAY = BITMASK(5); }; - int init(); + int init(); void update(float dt); void resizePanel(Ogre::OverlayElement *oe); void reposPanel(Ogre::OverlayElement *oe); void placeNeedle(Ogre::SceneNode *node, float x, float y, float len); - void updateStats(bool detailed=false); + void updateStats(bool detailed = false); - Ogre::Overlay *loadOverlay(Ogre::String name, bool autoResizeRation=true); + Ogre::Overlay * loadOverlay(Ogre::String name, bool autoResizeRation = true); Ogre::OverlayElement *loadOverlayElement(Ogre::String name); - Ogre::RenderWindow* win; + Ogre::RenderWindow *win; bool m_dashboard_visible; @@ -190,7 +189,7 @@ class OverlayWrapper : public ZeroedMemoryAllocator // Overlays // ------------------------------------------------------------- - unsigned int m_visible_overlays; + unsigned int m_visible_overlays; Ogre::Overlay *m_truck_pressure_overlay; Ogre::Overlay *m_truck_pressure_needle_overlay; @@ -212,24 +211,24 @@ class OverlayWrapper : public ZeroedMemoryAllocator // ------------------------------------------------------------- // Truck - Ogre::OverlayElement* guiGear; //!< truck - Ogre::OverlayElement* guiGear3D; //!< truck + Ogre::OverlayElement *guiGear; //!< truck + Ogre::OverlayElement *guiGear3D; //!< truck // Marine overlay elements Ogre::OverlayElement *bthro1; Ogre::OverlayElement *bthro2; // Truck - Ogre::TextAreaOverlayElement* guiAuto[5]; - Ogre::TextAreaOverlayElement* guiAuto3D[5]; + Ogre::TextAreaOverlayElement *guiAuto[5]; + Ogre::TextAreaOverlayElement *guiAuto3D[5]; // Truck (racing overlay) - Ogre::TextAreaOverlayElement* laptime; - Ogre::TextAreaOverlayElement* bestlaptime; - Ogre::TextAreaOverlayElement* directionArrowText; - Ogre::TextAreaOverlayElement* directionArrowDistance; + Ogre::TextAreaOverlayElement *laptime; + Ogre::TextAreaOverlayElement *bestlaptime; + Ogre::TextAreaOverlayElement *directionArrowText; + Ogre::TextAreaOverlayElement *directionArrowDistance; - Ogre::TextAreaOverlayElement* boat_depth_value_taoe; //!< Marine + Ogre::TextAreaOverlayElement *boat_depth_value_taoe; //!< Marine // truck Ogre::TextureUnitState *speedotexture; // Needed for dashboard prop @@ -248,7 +247,7 @@ class OverlayWrapper : public ZeroedMemoryAllocator float throffset; // Truck racing overlay - Ogre::SceneNode* m_direction_arrow_node; + Ogre::SceneNode *m_direction_arrow_node; std::vector m_loaded_overlays; }; diff --git a/source/main/gui/RTTLayer.cpp b/source/main/gui/RTTLayer.cpp index 6942ca30ef..1f14d0ed22 100644 --- a/source/main/gui/RTTLayer.cpp +++ b/source/main/gui/RTTLayer.cpp @@ -1,99 +1,97 @@ // based on the MyGUI UnitTests -#include "MyGUI_LayerItem.h" #include "RTTLayer.h" + #include "MyGUI_Enumerator.h" #include "MyGUI_FactoryManager.h" -#include "MyGUI_RenderManager.h" #include "MyGUI_Gui.h" +#include "MyGUI_LayerItem.h" #include "MyGUI_LayerNode.h" +#include "MyGUI_RenderManager.h" -namespace MyGUI { - -RTTLayer::RTTLayer() : - mTexture(nullptr), - mOutOfDate(false) +namespace MyGUI { -} -RTTLayer::~RTTLayer() -{ - if (mTexture) + RTTLayer::RTTLayer() : mTexture(nullptr), mOutOfDate(false) { - MyGUI::RenderManager::getInstance().destroyTexture(mTexture); - mTexture = nullptr; } -} - -void RTTLayer::deserialization(xml::ElementPtr _node, Version _version) -{ - Base::deserialization(_node, _version); - MyGUI::xml::ElementEnumerator propert = _node->getElementEnumerator(); - while (propert.next("Property")) + RTTLayer::~RTTLayer() { - const std::string& key = propert->findAttribute("key"); - const std::string& value = propert->findAttribute("value"); - if (key == "TextureSize") - setTextureSize(utility::parseValue(value)); - if (key == "TextureName") - setTextureName(value); + if (mTexture) + { + MyGUI::RenderManager::getInstance().destroyTexture(mTexture); + mTexture = nullptr; + } } -} -void RTTLayer::renderToTarget(IRenderTarget* _target, bool _update) -{ - bool outOfDate = mOutOfDate || isOutOfDate(); + void RTTLayer::deserialization(xml::ElementPtr _node, Version _version) + { + Base::deserialization(_node, _version); + + MyGUI::xml::ElementEnumerator propert = _node->getElementEnumerator(); + while (propert.next("Property")) + { + const std::string &key = propert->findAttribute("key"); + const std::string &value = propert->findAttribute("value"); + if (key == "TextureSize") setTextureSize(utility::parseValue(value)); + if (key == "TextureName") setTextureName(value); + } + } - if (outOfDate || _update) + void RTTLayer::renderToTarget(IRenderTarget *_target, bool _update) { - MyGUI::IRenderTarget* target = mTexture->getRenderTarget(); - if (target != nullptr) + bool outOfDate = mOutOfDate || isOutOfDate(); + + if (outOfDate || _update) { - target->begin(); + MyGUI::IRenderTarget *target = mTexture->getRenderTarget(); + if (target != nullptr) + { + target->begin(); - for (VectorILayerNode::iterator iter = mChildItems.begin(); iter != mChildItems.end(); ++iter) - (*iter)->renderToTarget(target, _update); + for (VectorILayerNode::iterator iter = mChildItems.begin(); iter != mChildItems.end(); ++iter) + (*iter)->renderToTarget(target, _update); - target->end(); + target->end(); + } } - } - - mOutOfDate = false; -} -void RTTLayer::setTextureSize(const IntSize& _size) -{ - if (mTextureSize == _size) - return; + mOutOfDate = false; + } - mTextureSize = _size; - if (mTexture) + void RTTLayer::setTextureSize(const IntSize &_size) { - MyGUI::RenderManager::getInstance().destroyTexture(mTexture); - mTexture = nullptr; - } + if (mTextureSize == _size) return; - MYGUI_ASSERT(mTextureSize.width * mTextureSize.height, "RTTLayer texture size must have non-zero width and height"); - std::string name = mTextureName.empty() ? MyGUI::utility::toString((size_t)this, getClassTypeName()) : mTextureName; - mTexture = MyGUI::RenderManager::getInstance().createTexture(name); - mTexture->createManual(mTextureSize.width, mTextureSize.height, MyGUI::TextureUsage::RenderTarget, MyGUI::PixelFormat::R8G8B8A8); + mTextureSize = _size; + if (mTexture) + { + MyGUI::RenderManager::getInstance().destroyTexture(mTexture); + mTexture = nullptr; + } - mOutOfDate = true; -} + MYGUI_ASSERT(mTextureSize.width * mTextureSize.height, "RTTLayer texture size must have non-zero width and height"); + std::string name = mTextureName.empty() ? MyGUI::utility::toString((size_t)this, getClassTypeName()) : mTextureName; + mTexture = MyGUI::RenderManager::getInstance().createTexture(name); + mTexture->createManual(mTextureSize.width, mTextureSize.height, MyGUI::TextureUsage::RenderTarget, + MyGUI::PixelFormat::R8G8B8A8); -void RTTLayer::setTextureName(const std::string& _name) -{ - mTextureName = _name; + mOutOfDate = true; + } - if (mTexture != nullptr) + void RTTLayer::setTextureName(const std::string &_name) { - IntSize size = mTextureSize; - mTextureSize.clear(); - setTextureSize(size); - } + mTextureName = _name; - mOutOfDate = true; -} + if (mTexture != nullptr) + { + IntSize size = mTextureSize; + mTextureSize.clear(); + setTextureSize(size); + } + + mOutOfDate = true; + } } // namespace MyGUI diff --git a/source/main/gui/RTTLayer.h b/source/main/gui/RTTLayer.h index 670f2b8738..671521a465 100644 --- a/source/main/gui/RTTLayer.h +++ b/source/main/gui/RTTLayer.h @@ -2,32 +2,32 @@ #pragma once +#include "MyGUI_OverlappedLayer.h" #include "MyGUI_Prerequest.h" #include "MyGUI_Types.h" -#include "MyGUI_OverlappedLayer.h" -namespace MyGUI { - -class RTTLayer : - public OverlappedLayer +namespace MyGUI { - MYGUI_RTTI_DERIVED( RTTLayer ) -public: - RTTLayer(); - virtual ~RTTLayer(); + class RTTLayer : public OverlappedLayer + { + MYGUI_RTTI_DERIVED(RTTLayer) + + public: + RTTLayer(); + virtual ~RTTLayer(); - virtual void deserialization(xml::ElementPtr _node, Version _version); - virtual void renderToTarget(IRenderTarget* _target, bool _update); + virtual void deserialization(xml::ElementPtr _node, Version _version); + virtual void renderToTarget(IRenderTarget *_target, bool _update); - void setTextureSize(const IntSize& _size); - void setTextureName(const std::string& _name); + void setTextureSize(const IntSize &_size); + void setTextureName(const std::string &_name); -private: - MyGUI::ITexture* mTexture; - IntSize mTextureSize; - std::string mTextureName; - bool mOutOfDate; -}; + private: + MyGUI::ITexture *mTexture; + IntSize mTextureSize; + std::string mTextureName; + bool mOutOfDate; + }; } // namespace MyGUI diff --git a/source/main/gui/imgui/OgreImGui.cpp b/source/main/gui/imgui/OgreImGui.cpp index 1805b91f43..ea47cf2d64 100644 --- a/source/main/gui/imgui/OgreImGui.cpp +++ b/source/main/gui/imgui/OgreImGui.cpp @@ -25,99 +25,90 @@ #include "OgreImGui.h" -#include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include -#include -#include +#include -void OgreImGui::Init(Ogre::SceneManager* scenemgr) +void OgreImGui::Init(Ogre::SceneManager *scenemgr) { - mSceneMgr = scenemgr; - ImGuiIO& io = ImGui::GetIO(); + mSceneMgr = scenemgr; + ImGuiIO &io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = OIS::KC_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. - io.KeyMap[ImGuiKey_LeftArrow] = OIS::KC_LEFT; + io.KeyMap[ImGuiKey_Tab] = OIS::KC_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array + // that we will update during the application lifetime. + io.KeyMap[ImGuiKey_LeftArrow] = OIS::KC_LEFT; io.KeyMap[ImGuiKey_RightArrow] = OIS::KC_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = OIS::KC_UP; - io.KeyMap[ImGuiKey_DownArrow] = OIS::KC_DOWN; - io.KeyMap[ImGuiKey_PageUp] = OIS::KC_PGUP; - io.KeyMap[ImGuiKey_PageDown] = OIS::KC_PGDOWN; - io.KeyMap[ImGuiKey_Home] = OIS::KC_HOME; - io.KeyMap[ImGuiKey_End] = OIS::KC_END; - io.KeyMap[ImGuiKey_Delete] = OIS::KC_DELETE; - io.KeyMap[ImGuiKey_Backspace] = OIS::KC_BACK; - io.KeyMap[ImGuiKey_Enter] = OIS::KC_RETURN; - io.KeyMap[ImGuiKey_Escape] = OIS::KC_ESCAPE; - io.KeyMap[ImGuiKey_A] = OIS::KC_A; - io.KeyMap[ImGuiKey_C] = OIS::KC_C; - io.KeyMap[ImGuiKey_V] = OIS::KC_V; - io.KeyMap[ImGuiKey_X] = OIS::KC_X; - io.KeyMap[ImGuiKey_Y] = OIS::KC_Y; - io.KeyMap[ImGuiKey_Z] = OIS::KC_Z; + io.KeyMap[ImGuiKey_UpArrow] = OIS::KC_UP; + io.KeyMap[ImGuiKey_DownArrow] = OIS::KC_DOWN; + io.KeyMap[ImGuiKey_PageUp] = OIS::KC_PGUP; + io.KeyMap[ImGuiKey_PageDown] = OIS::KC_PGDOWN; + io.KeyMap[ImGuiKey_Home] = OIS::KC_HOME; + io.KeyMap[ImGuiKey_End] = OIS::KC_END; + io.KeyMap[ImGuiKey_Delete] = OIS::KC_DELETE; + io.KeyMap[ImGuiKey_Backspace] = OIS::KC_BACK; + io.KeyMap[ImGuiKey_Enter] = OIS::KC_RETURN; + io.KeyMap[ImGuiKey_Escape] = OIS::KC_ESCAPE; + io.KeyMap[ImGuiKey_A] = OIS::KC_A; + io.KeyMap[ImGuiKey_C] = OIS::KC_C; + io.KeyMap[ImGuiKey_V] = OIS::KC_V; + io.KeyMap[ImGuiKey_X] = OIS::KC_X; + io.KeyMap[ImGuiKey_Y] = OIS::KC_Y; + io.KeyMap[ImGuiKey_Z] = OIS::KC_Z; createFontTexture(); createMaterial(); } -//Inherhited from OIS::MouseListener -void OgreImGui::InjectMouseMoved( const OIS::MouseEvent &arg ) +// Inherhited from OIS::MouseListener +void OgreImGui::InjectMouseMoved(const OIS::MouseEvent &arg) { - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); io.MousePos.x = arg.state.X.abs; io.MousePos.y = arg.state.Y.abs; - io.MouseWheel = Ogre::Math::Clamp((float)arg.state.Z.rel, -1/3.f, 1/3.f); + io.MouseWheel = Ogre::Math::Clamp((float)arg.state.Z.rel, -1 / 3.f, 1 / 3.f); } -void OgreImGui::InjectMousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) +void OgreImGui::InjectMousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) { - ImGuiIO& io = ImGui::GetIO(); - if (id<5) - { - io.MouseDown[id] = true; - } + ImGuiIO &io = ImGui::GetIO(); + if (id < 5) { io.MouseDown[id] = true; } } -void OgreImGui::InjectMouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) +void OgreImGui::InjectMouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id) { - ImGuiIO& io = ImGui::GetIO(); - if (id<5) - { - io.MouseDown[id] = false; - } + ImGuiIO &io = ImGui::GetIO(); + if (id < 5) { io.MouseDown[id] = false; } } // Inherhited from OIS::KeyListener -void OgreImGui::InjectKeyPressed( const OIS::KeyEvent &arg ) +void OgreImGui::InjectKeyPressed(const OIS::KeyEvent &arg) { - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); io.KeysDown[arg.key] = true; - if (arg.text>0) - { - io.AddInputCharacter((unsigned short)arg.text); - } + if (arg.text > 0) { io.AddInputCharacter((unsigned short)arg.text); } } -void OgreImGui::InjectKeyReleased( const OIS::KeyEvent &arg ) +void OgreImGui::InjectKeyReleased(const OIS::KeyEvent &arg) { - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); io.KeysDown[arg.key] = false; } @@ -126,20 +117,19 @@ void OgreImGui::Render() // Construct projection matrix, taking texel offset corrections in account (important for DirectX9) // See also: // - OGRE-API specific hint: http://www.ogre3d.org/forums/viewtopic.php?f=5&p=536881#p536881 - // - IMGUI Dx9 demo solution: https://github.com/ocornut/imgui/blob/master/examples/directx9_example/imgui_impl_dx9.cpp#L127-L138 - ImGuiIO& io = ImGui::GetIO(); - Ogre::RenderSystem* renderSys = Ogre::Root::getSingletonPtr()->getRenderSystem(); - const float texelOffsetX = renderSys->getHorizontalTexelOffset(); - const float texelOffsetY = renderSys->getVerticalTexelOffset(); - const float L = texelOffsetX; - const float R = io.DisplaySize.x + texelOffsetX; - const float T = texelOffsetY; - const float B = io.DisplaySize.y + texelOffsetY; - - Ogre::Matrix4 projMatrix( 2.0f/(R-L), 0.0f, 0.0f, (L+R)/(L-R), - 0.0f, -2.0f/(B-T), 0.0f, (T+B)/(B-T), - 0.0f, 0.0f, -1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + // - IMGUI Dx9 demo solution: + // https://github.com/ocornut/imgui/blob/master/examples/directx9_example/imgui_impl_dx9.cpp#L127-L138 + ImGuiIO & io = ImGui::GetIO(); + Ogre::RenderSystem *renderSys = Ogre::Root::getSingletonPtr()->getRenderSystem(); + const float texelOffsetX = renderSys->getHorizontalTexelOffset(); + const float texelOffsetY = renderSys->getVerticalTexelOffset(); + const float L = texelOffsetX; + const float R = io.DisplaySize.x + texelOffsetX; + const float T = texelOffsetY; + const float B = io.DisplaySize.y + texelOffsetY; + + Ogre::Matrix4 projMatrix(2.0f / (R - L), 0.0f, 0.0f, (L + R) / (L - R), 0.0f, -2.0f / (B - T), 0.0f, (T + B) / (B - T), 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); mPass->getVertexProgramParameters()->setNamedConstant("ProjectionMatrix", projMatrix); @@ -147,26 +137,28 @@ void OgreImGui::Render() /// Adopted from https://bitbucket.org/ChaosCreator/imgui-ogre2.1-binding /// ... Commentary on OGRE forums: http://www.ogre3d.org/forums/viewtopic.php?f=5&t=89081#p531059 ImGui::Render(); - ImDrawData* draw_data = ImGui::GetDrawData(); - int vpWidth = 2000; // Dummy viewport size - int vpHeight = 2000; - Ogre::Viewport* vp = renderSys->_getViewport(); - if (vp != nullptr) // Viewport is sometimes 'null' on Windows/Dx9 right after game startup or map load - probably related to switching Ogre::Camera-s ~ only_a_ptr, 01/2018 + ImDrawData * draw_data = ImGui::GetDrawData(); + int vpWidth = 2000; // Dummy viewport size + int vpHeight = 2000; + Ogre::Viewport *vp = renderSys->_getViewport(); + if (vp != nullptr) // Viewport is sometimes 'null' on Windows/Dx9 right after game startup or map load - probably related to + // switching Ogre::Camera-s ~ only_a_ptr, 01/2018 { vpWidth = vp->getActualWidth(); vpHeight = vp->getActualHeight(); } for (int i = 0; i < draw_data->CmdListsCount; ++i) { - const ImDrawList* draw_list = draw_data->CmdLists[i]; - unsigned int startIdx = 0; + const ImDrawList *draw_list = draw_data->CmdLists[i]; + unsigned int startIdx = 0; for (int j = 0; j < draw_list->CmdBuffer.Size; ++j) { // Create a renderable and fill it's buffers - ImGUIRenderable renderable; + ImGUIRenderable renderable; const ImDrawCmd *drawCmd = &draw_list->CmdBuffer[j]; - renderable.updateVertexData(draw_list->VtxBuffer.Data, &draw_list->IdxBuffer.Data[startIdx], draw_list->VtxBuffer.Size, drawCmd->ElemCount); + renderable.updateVertexData(draw_list->VtxBuffer.Data, &draw_list->IdxBuffer.Data[startIdx], + draw_list->VtxBuffer.Size, drawCmd->ElemCount); // Set scissoring int scLeft = static_cast(drawCmd->ClipRect.x); // Obtain bounds @@ -174,9 +166,9 @@ void OgreImGui::Render() int scRight = static_cast(drawCmd->ClipRect.z); int scBottom = static_cast(drawCmd->ClipRect.w); - scLeft = scLeft < 0 ? 0 : (scLeft > vpWidth ? vpWidth : scLeft); // Clamp bounds to viewport dimensions - scRight = scRight < 0 ? 0 : (scRight > vpWidth ? vpWidth : scRight); - scTop = scTop < 0 ? 0 : (scTop > vpHeight ? vpHeight : scTop); + scLeft = scLeft < 0 ? 0 : (scLeft > vpWidth ? vpWidth : scLeft); // Clamp bounds to viewport dimensions + scRight = scRight < 0 ? 0 : (scRight > vpWidth ? vpWidth : scRight); + scTop = scTop < 0 ? 0 : (scTop > vpHeight ? vpHeight : scTop); scBottom = scBottom < 0 ? 0 : (scBottom > vpHeight ? vpHeight : scBottom); renderSys->setScissorTest(true, scLeft, scTop, scRight, scBottom); @@ -193,155 +185,144 @@ void OgreImGui::Render() void OgreImGui::createMaterial() { - static const char* vertexShaderSrcD3D11 = - { - "cbuffer vertexBuffer : register(b0) \n" - "{\n" - "float4x4 ProjectionMatrix; \n" - "};\n" - "struct VS_INPUT\n" - "{\n" - "float2 pos : POSITION;\n" - "float4 col : COLOR0;\n" - "float2 uv : TEXCOORD0;\n" - "};\n" - "struct PS_INPUT\n" - "{\n" - "float4 pos : SV_POSITION;\n" - "float4 col : COLOR0;\n" - "float2 uv : TEXCOORD0;\n" - "};\n" - "PS_INPUT main(VS_INPUT input)\n" - "{\n" - "PS_INPUT output;\n" - "output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\n" - "output.col = input.col;\n" - "output.uv = input.uv;\n" - "return output;\n" - "}" - }; - - static const char* pixelShaderSrcD3D11 = - { - "struct PS_INPUT\n" - "{\n" - "float4 pos : SV_POSITION;\n" - "float4 col : COLOR0;\n" - "float2 uv : TEXCOORD0;\n" - "};\n" - "sampler sampler0;\n" - "Texture2D texture0;\n" - "\n" - "float4 main(PS_INPUT input) : SV_Target\n" - "{\n" - "float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \n" - "return out_col; \n" - "}" - }; - - static const char* vertexShaderSrcD3D9 = - { - "uniform float4x4 ProjectionMatrix; \n" - "struct VS_INPUT\n" - "{\n" - "float2 pos : POSITION;\n" - "float4 col : COLOR0;\n" - "float2 uv : TEXCOORD0;\n" - "};\n" - "struct PS_INPUT\n" - "{\n" - "float4 pos : POSITION;\n" - "float4 col : COLOR0;\n" - "float2 uv : TEXCOORD0;\n" - "};\n" - "PS_INPUT main(VS_INPUT input)\n" - "{\n" - "PS_INPUT output;\n" - "output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\n" - "output.col = input.col;\n" - "output.uv = input.uv;\n" - "return output;\n" - "}" - }; - - static const char* pixelShaderSrcSrcD3D9 = - { - "struct PS_INPUT\n" - "{\n" - "float4 pos : SV_POSITION;\n" - "float4 col : COLOR0;\n" - "float2 uv : TEXCOORD0;\n" - "};\n" - "sampler2D sampler0;\n" - "\n" - "float4 main(PS_INPUT input) : SV_Target\n" - "{\n" - "float4 out_col = input.col.bgra * tex2D(sampler0, input.uv); \n" - "return out_col; \n" - "}" - }; - - static const char* vertexShaderSrcGLSL = - { // See https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#OpenGL_and_GLSL_versions - "#version 130\n" - "uniform mat4 ProjectionMatrix; \n" - "in vec2 vertex;\n" - "in vec2 uv0;\n" - "in vec4 colour;\n" - "out vec2 Texcoord;\n" - "out vec4 col;\n" - "void main()\n" - "{\n" - "gl_Position = ProjectionMatrix* vec4(vertex.xy, 0.f, 1.f);\n" - "Texcoord = uv0;\n" - "col = colour;\n" - "}" - }; - - static const char* pixelShaderSrcGLSL = - { // See https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#OpenGL_and_GLSL_versions - "#version 130\n" - "in vec2 Texcoord;\n" - "in vec4 col;\n" - "uniform sampler2D sampler0;\n" - "out vec4 out_col;\n" - "void main()\n" - "{\n" - "out_col = col * texture(sampler0, Texcoord); \n" - "}" - }; - - //create the default shadows material - Ogre::HighLevelGpuProgramManager& mgr = Ogre::HighLevelGpuProgramManager::getSingleton(); + static const char *vertexShaderSrcD3D11 = {"cbuffer vertexBuffer : register(b0) \n" + "{\n" + "float4x4 ProjectionMatrix; \n" + "};\n" + "struct VS_INPUT\n" + "{\n" + "float2 pos : POSITION;\n" + "float4 col : COLOR0;\n" + "float2 uv : TEXCOORD0;\n" + "};\n" + "struct PS_INPUT\n" + "{\n" + "float4 pos : SV_POSITION;\n" + "float4 col : COLOR0;\n" + "float2 uv : TEXCOORD0;\n" + "};\n" + "PS_INPUT main(VS_INPUT input)\n" + "{\n" + "PS_INPUT output;\n" + "output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\n" + "output.col = input.col;\n" + "output.uv = input.uv;\n" + "return output;\n" + "}"}; + + static const char *pixelShaderSrcD3D11 = {"struct PS_INPUT\n" + "{\n" + "float4 pos : SV_POSITION;\n" + "float4 col : COLOR0;\n" + "float2 uv : TEXCOORD0;\n" + "};\n" + "sampler sampler0;\n" + "Texture2D texture0;\n" + "\n" + "float4 main(PS_INPUT input) : SV_Target\n" + "{\n" + "float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \n" + "return out_col; \n" + "}"}; + + static const char *vertexShaderSrcD3D9 = {"uniform float4x4 ProjectionMatrix; \n" + "struct VS_INPUT\n" + "{\n" + "float2 pos : POSITION;\n" + "float4 col : COLOR0;\n" + "float2 uv : TEXCOORD0;\n" + "};\n" + "struct PS_INPUT\n" + "{\n" + "float4 pos : POSITION;\n" + "float4 col : COLOR0;\n" + "float2 uv : TEXCOORD0;\n" + "};\n" + "PS_INPUT main(VS_INPUT input)\n" + "{\n" + "PS_INPUT output;\n" + "output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\n" + "output.col = input.col;\n" + "output.uv = input.uv;\n" + "return output;\n" + "}"}; + + static const char *pixelShaderSrcSrcD3D9 = {"struct PS_INPUT\n" + "{\n" + "float4 pos : SV_POSITION;\n" + "float4 col : COLOR0;\n" + "float2 uv : TEXCOORD0;\n" + "};\n" + "sampler2D sampler0;\n" + "\n" + "float4 main(PS_INPUT input) : SV_Target\n" + "{\n" + "float4 out_col = input.col.bgra * tex2D(sampler0, input.uv); \n" + "return out_col; \n" + "}"}; + + static const char *vertexShaderSrcGLSL = { + // See https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#OpenGL_and_GLSL_versions + "#version 130\n" + "uniform mat4 ProjectionMatrix; \n" + "in vec2 vertex;\n" + "in vec2 uv0;\n" + "in vec4 colour;\n" + "out vec2 Texcoord;\n" + "out vec4 col;\n" + "void main()\n" + "{\n" + "gl_Position = ProjectionMatrix* vec4(vertex.xy, 0.f, 1.f);\n" + "Texcoord = uv0;\n" + "col = colour;\n" + "}"}; + + static const char *pixelShaderSrcGLSL = { + // See https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#OpenGL_and_GLSL_versions + "#version 130\n" + "in vec2 Texcoord;\n" + "in vec4 col;\n" + "uniform sampler2D sampler0;\n" + "out vec4 out_col;\n" + "void main()\n" + "{\n" + "out_col = col * texture(sampler0, Texcoord); \n" + "}"}; + + // create the default shadows material + Ogre::HighLevelGpuProgramManager &mgr = Ogre::HighLevelGpuProgramManager::getSingleton(); Ogre::HighLevelGpuProgramPtr vertexShaderUnified = mgr.getByName("imgui/VP"); - Ogre::HighLevelGpuProgramPtr pixelShaderUnified = mgr.getByName("imgui/FP"); - + Ogre::HighLevelGpuProgramPtr pixelShaderUnified = mgr.getByName("imgui/FP"); + Ogre::HighLevelGpuProgramPtr vertexShaderD3D11 = mgr.getByName("imgui/VP/D3D11"); - Ogre::HighLevelGpuProgramPtr pixelShaderD3D11 = mgr.getByName("imgui/FP/D3D11"); + Ogre::HighLevelGpuProgramPtr pixelShaderD3D11 = mgr.getByName("imgui/FP/D3D11"); Ogre::HighLevelGpuProgramPtr vertexShaderD3D9 = mgr.getByName("imgui/VP/D3D9"); - Ogre::HighLevelGpuProgramPtr pixelShaderD3D9 = mgr.getByName("imgui/FP/D3D9"); + Ogre::HighLevelGpuProgramPtr pixelShaderD3D9 = mgr.getByName("imgui/FP/D3D9"); Ogre::HighLevelGpuProgramPtr vertexShaderGL = mgr.getByName("imgui/VP/GL130"); - Ogre::HighLevelGpuProgramPtr pixelShaderGL = mgr.getByName("imgui/FP/GL130"); + Ogre::HighLevelGpuProgramPtr pixelShaderGL = mgr.getByName("imgui/FP/GL130"); if (vertexShaderUnified.isNull()) { - vertexShaderUnified = mgr.createProgram("imgui/VP",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,"unified",Ogre::GPT_VERTEX_PROGRAM); + vertexShaderUnified = mgr.createProgram("imgui/VP", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "unified", + Ogre::GPT_VERTEX_PROGRAM); } if (pixelShaderUnified.isNull()) { - pixelShaderUnified = mgr.createProgram("imgui/FP",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,"unified",Ogre::GPT_FRAGMENT_PROGRAM); + pixelShaderUnified = mgr.createProgram("imgui/FP", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "unified", + Ogre::GPT_FRAGMENT_PROGRAM); } - Ogre::UnifiedHighLevelGpuProgram* vertexShaderPtr = static_cast(vertexShaderUnified.get()); - Ogre::UnifiedHighLevelGpuProgram* pixelShaderPtr = static_cast(pixelShaderUnified.get()); + Ogre::UnifiedHighLevelGpuProgram *vertexShaderPtr = + static_cast(vertexShaderUnified.get()); + Ogre::UnifiedHighLevelGpuProgram *pixelShaderPtr = static_cast(pixelShaderUnified.get()); if (vertexShaderD3D11.isNull()) { - vertexShaderD3D11 = mgr.createProgram("imgui/VP/D3D11", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", Ogre::GPT_VERTEX_PROGRAM); + vertexShaderD3D11 = mgr.createProgram("imgui/VP/D3D11", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", + Ogre::GPT_VERTEX_PROGRAM); vertexShaderD3D11->setParameter("target", "vs_4_0"); vertexShaderD3D11->setParameter("entry_point", "main"); vertexShaderD3D11->setSource(vertexShaderSrcD3D11); @@ -352,8 +333,8 @@ void OgreImGui::createMaterial() if (pixelShaderD3D11.isNull()) { - pixelShaderD3D11 = mgr.createProgram("imgui/FP/D3D11", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", Ogre::GPT_FRAGMENT_PROGRAM); + pixelShaderD3D11 = mgr.createProgram("imgui/FP/D3D11", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", + Ogre::GPT_FRAGMENT_PROGRAM); pixelShaderD3D11->setParameter("target", "ps_4_0"); pixelShaderD3D11->setParameter("entry_point", "main"); pixelShaderD3D11->setSource(pixelShaderSrcD3D11); @@ -364,8 +345,8 @@ void OgreImGui::createMaterial() if (vertexShaderD3D9.isNull()) { - vertexShaderD3D9 = mgr.createProgram("imgui/VP/D3D9", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", Ogre::GPT_VERTEX_PROGRAM); + vertexShaderD3D9 = mgr.createProgram("imgui/VP/D3D9", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", + Ogre::GPT_VERTEX_PROGRAM); vertexShaderD3D9->setParameter("target", "vs_2_0"); vertexShaderD3D9->setParameter("entry_point", "main"); vertexShaderD3D9->setSource(vertexShaderSrcD3D9); @@ -376,8 +357,8 @@ void OgreImGui::createMaterial() if (pixelShaderD3D9.isNull()) { - pixelShaderD3D9 = mgr.createProgram("imgui/FP/D3D9", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", Ogre::GPT_FRAGMENT_PROGRAM); + pixelShaderD3D9 = mgr.createProgram("imgui/FP/D3D9", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", + Ogre::GPT_FRAGMENT_PROGRAM); pixelShaderD3D9->setParameter("target", "ps_2_0"); pixelShaderD3D9->setParameter("entry_point", "main"); pixelShaderD3D9->setSource(pixelShaderSrcSrcD3D9); @@ -388,8 +369,8 @@ void OgreImGui::createMaterial() if (vertexShaderGL.isNull()) { - vertexShaderGL = mgr.createProgram("imgui/VP/GL130", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsl", Ogre::GPT_VERTEX_PROGRAM); + vertexShaderGL = mgr.createProgram("imgui/VP/GL130", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", + Ogre::GPT_VERTEX_PROGRAM); vertexShaderGL->setSource(vertexShaderSrcGLSL); vertexShaderGL->load(); vertexShaderPtr->addDelegateProgram(vertexShaderGL->getName()); @@ -397,16 +378,17 @@ void OgreImGui::createMaterial() if (pixelShaderGL.isNull()) { - pixelShaderGL = mgr.createProgram("imgui/FP/GL130", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsl", Ogre::GPT_FRAGMENT_PROGRAM); + pixelShaderGL = mgr.createProgram("imgui/FP/GL130", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", + Ogre::GPT_FRAGMENT_PROGRAM); pixelShaderGL->setSource(pixelShaderSrcGLSL); pixelShaderGL->load(); - pixelShaderGL->setParameter("sampler0","int 0"); + pixelShaderGL->setParameter("sampler0", "int 0"); pixelShaderPtr->addDelegateProgram(pixelShaderGL->getName()); } - Ogre::MaterialPtr imguiMaterial = Ogre::MaterialManager::getSingleton().create("imgui/material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + Ogre::MaterialPtr imguiMaterial = + Ogre::MaterialManager::getSingleton().create("imgui/material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mPass = imguiMaterial->getTechnique(0)->getPass(0); mPass->setFragmentProgram("imgui/FP"); mPass->setVertexProgram("imgui/VP"); @@ -414,8 +396,9 @@ void OgreImGui::createMaterial() mPass->setDepthFunction(Ogre::CMPF_ALWAYS_PASS); mPass->setLightingEnabled(false); mPass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - mPass->setSeparateSceneBlendingOperation(Ogre::SBO_ADD,Ogre::SBO_ADD); - mPass->setSeparateSceneBlending(Ogre::SBF_SOURCE_ALPHA,Ogre::SBF_ONE_MINUS_SOURCE_ALPHA,Ogre::SBF_ONE_MINUS_SOURCE_ALPHA,Ogre::SBF_ZERO); + mPass->setSeparateSceneBlendingOperation(Ogre::SBO_ADD, Ogre::SBO_ADD); + mPass->setSeparateSceneBlending(Ogre::SBF_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA, + Ogre::SBF_ZERO); mPass->createTextureUnitState()->setTextureName("ImguiFontTex"); } @@ -423,19 +406,22 @@ void OgreImGui::createMaterial() void OgreImGui::createFontTexture() { // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; + ImGuiIO & io = ImGui::GetIO(); + unsigned char *pixels; + int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - mFontTex = Ogre::TextureManager::getSingleton().createManual("ImguiFontTex",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,Ogre::TEX_TYPE_2D,width,height,1,1,Ogre::PF_BYTE_RGBA); + mFontTex = + Ogre::TextureManager::getSingleton().createManual("ImguiFontTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, width, height, 1, 1, Ogre::PF_BYTE_RGBA); // Lock texture for writing - const Ogre::PixelBox & lockBox = mFontTex->getBuffer()->lock(Ogre::Box(0, 0, width, height), Ogre::HardwareBuffer::HBL_DISCARD); + const Ogre::PixelBox &lockBox = + mFontTex->getBuffer()->lock(Ogre::Box(0, 0, width, height), Ogre::HardwareBuffer::HBL_DISCARD); // Copy texture to ImGui size_t texDepth = Ogre::PixelUtil::getNumElemBytes(lockBox.format); - memcpy(lockBox.data,pixels, width*height*texDepth); + memcpy(lockBox.data, pixels, width * height * texDepth); // Unlock mFontTex->getBuffer()->unlock(); @@ -443,13 +429,13 @@ void OgreImGui::createFontTexture() void OgreImGui::NewFrame(float deltaTime, float displayWidth, float displayHeight, bool ctrl, bool alt, bool shift) { - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); io.DeltaTime = deltaTime; - // Read keyboard modifiers inputs - io.KeyCtrl = ctrl; + // Read keyboard modifiers inputs + io.KeyCtrl = ctrl; io.KeyShift = shift; - io.KeyAlt = alt; + io.KeyAlt = alt; io.KeySuper = false; // Setup display size (every frame to accommodate for window resizing) @@ -459,49 +445,46 @@ void OgreImGui::NewFrame(float deltaTime, float displayWidth, float displayHeigh ImGui::NewFrame(); } -// -------------------------- ImGui Renderable ------------------------------ // +// -------------------------- ImGui Renderable ------------------------------ // - OgreImGui::ImGUIRenderable::ImGUIRenderable(): - mVertexBufferSize(5000), - mIndexBufferSize(10000) +OgreImGui::ImGUIRenderable::ImGUIRenderable() : mVertexBufferSize(5000), mIndexBufferSize(10000) { this->initImGUIRenderable(); - //By default we want ImGUIRenderables to still work in wireframe mode - this->setPolygonModeOverrideable( false ); + // By default we want ImGUIRenderables to still work in wireframe mode + this->setPolygonModeOverrideable(false); } void OgreImGui::ImGUIRenderable::initImGUIRenderable(void) { // use identity projection and view matrices - mUseIdentityProjection = true; - mUseIdentityView = true; + mUseIdentityProjection = true; + mUseIdentityView = true; mRenderOp.vertexData = OGRE_NEW Ogre::VertexData(); - mRenderOp.indexData = OGRE_NEW Ogre::IndexData(); + mRenderOp.indexData = OGRE_NEW Ogre::IndexData(); mRenderOp.vertexData->vertexCount = 0; mRenderOp.vertexData->vertexStart = 0; - mRenderOp.indexData->indexCount = 0; - mRenderOp.indexData->indexStart = 0; - mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; - mRenderOp.useIndexes = true; + mRenderOp.indexData->indexCount = 0; + mRenderOp.indexData->indexStart = 0; + mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; + mRenderOp.useIndexes = true; mRenderOp.useGlobalInstancingVertexBufferIsAvailable = false; - Ogre::VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; - + Ogre::VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; + // vertex declaration size_t offset = 0; - decl->addElement(0,offset,Ogre::VET_FLOAT2,Ogre::VES_POSITION); - offset += Ogre::VertexElement::getTypeSize( Ogre::VET_FLOAT2 ); - decl->addElement(0,offset,Ogre::VET_FLOAT2,Ogre::VES_TEXTURE_COORDINATES,0); - offset += Ogre::VertexElement::getTypeSize( Ogre::VET_FLOAT2 ); - decl->addElement(0,offset,Ogre::VET_COLOUR,Ogre::VES_DIFFUSE); - - - // set basic white material - this->setMaterial( "imgui/material" ); + decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_POSITION); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); + decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0); + offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); + decl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); + + // set basic white material + this->setMaterial("imgui/material"); } OgreImGui::ImGUIRenderable::~ImGUIRenderable() @@ -511,82 +494,81 @@ OgreImGui::ImGUIRenderable::~ImGUIRenderable() mMaterial.setNull(); } -void OgreImGui::ImGUIRenderable::setMaterial( const Ogre::String& matName ) +void OgreImGui::ImGUIRenderable::setMaterial(const Ogre::String &matName) { - mMaterial = Ogre::MaterialManager::getSingleton().getByName( matName ); - if ( !mMaterial.isNull() ) - { - return; - } - + mMaterial = Ogre::MaterialManager::getSingleton().getByName(matName); + if (!mMaterial.isNull()) { return; } + // Won't load twice anyway mMaterial->load(); } -void OgreImGui::ImGUIRenderable::setMaterial(const Ogre::MaterialPtr & material) +void OgreImGui::ImGUIRenderable::setMaterial(const Ogre::MaterialPtr &material) { mMaterial = material; } -const Ogre::MaterialPtr& OgreImGui::ImGUIRenderable::getMaterial(void) const +const Ogre::MaterialPtr &OgreImGui::ImGUIRenderable::getMaterial(void) const { return mMaterial; } -/// @author https://bitbucket.org/ChaosCreator/imgui-ogre2.1-binding/src/8f1a01db510f543a987c3c16859d0a33400d9097/ImguiRenderable.cpp?at=master&fileviewer=file-view-default +/// @author +/// https://bitbucket.org/ChaosCreator/imgui-ogre2.1-binding/src/8f1a01db510f543a987c3c16859d0a33400d9097/ImguiRenderable.cpp?at=master&fileviewer=file-view-default /// Commentary on OGRE forums: http://www.ogre3d.org/forums/viewtopic.php?f=5&t=89081#p531059 -void OgreImGui::ImGUIRenderable::updateVertexData(const ImDrawVert* vtxBuf, const ImDrawIdx* idxBuf, unsigned int vtxCount, unsigned int idxCount) +void OgreImGui::ImGUIRenderable::updateVertexData(const ImDrawVert *vtxBuf, const ImDrawIdx *idxBuf, unsigned int vtxCount, + unsigned int idxCount) { - Ogre::VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; + Ogre::VertexBufferBinding *bind = mRenderOp.vertexData->vertexBufferBinding; if (bind->getBindings().empty() || mVertexBufferSize != vtxCount) { mVertexBufferSize = vtxCount; - bind->setBinding(0, Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(sizeof(ImDrawVert), mVertexBufferSize, Ogre::HardwareBuffer::HBU_WRITE_ONLY)); + bind->setBinding(0, Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(sizeof(ImDrawVert), mVertexBufferSize, + Ogre::HardwareBuffer::HBU_WRITE_ONLY)); } if (mRenderOp.indexData->indexBuffer.isNull() || mIndexBufferSize != idxCount) { mIndexBufferSize = idxCount; - mRenderOp.indexData->indexBuffer = - Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, mIndexBufferSize, Ogre::HardwareBuffer::HBU_WRITE_ONLY); + mRenderOp.indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( + Ogre::HardwareIndexBuffer::IT_16BIT, mIndexBufferSize, Ogre::HardwareBuffer::HBU_WRITE_ONLY); } // Copy all vertices - ImDrawVert* vtxDst = (ImDrawVert*)(bind->getBuffer(0)->lock(Ogre::HardwareBuffer::HBL_DISCARD)); - ImDrawIdx* idxDst = (ImDrawIdx*)(mRenderOp.indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); + ImDrawVert *vtxDst = (ImDrawVert *)(bind->getBuffer(0)->lock(Ogre::HardwareBuffer::HBL_DISCARD)); + ImDrawIdx * idxDst = (ImDrawIdx *)(mRenderOp.indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); memcpy(vtxDst, vtxBuf, mVertexBufferSize * sizeof(ImDrawVert)); memcpy(idxDst, idxBuf, mIndexBufferSize * sizeof(ImDrawIdx)); mRenderOp.vertexData->vertexStart = 0; mRenderOp.vertexData->vertexCount = vtxCount; - mRenderOp.indexData->indexStart = 0; - mRenderOp.indexData->indexCount = idxCount; - + mRenderOp.indexData->indexStart = 0; + mRenderOp.indexData->indexCount = idxCount; bind->getBuffer(0)->unlock(); mRenderOp.indexData->indexBuffer->unlock(); } -void OgreImGui::ImGUIRenderable::getWorldTransforms( Ogre::Matrix4* xform ) const +void OgreImGui::ImGUIRenderable::getWorldTransforms(Ogre::Matrix4 *xform) const { *xform = Ogre::Matrix4::IDENTITY; } -void OgreImGui::ImGUIRenderable::getRenderOperation(Ogre::RenderOperation& op) +void OgreImGui::ImGUIRenderable::getRenderOperation(Ogre::RenderOperation &op) { op = mRenderOp; } -const Ogre::LightList& OgreImGui::ImGUIRenderable::getLights(void) const +const Ogre::LightList &OgreImGui::ImGUIRenderable::getLights(void) const { static const Ogre::LightList light_list; return light_list; } -bool OgreImGui::frameRenderingQueued(const Ogre::FrameEvent& evt) +bool OgreImGui::frameRenderingQueued(const Ogre::FrameEvent &evt) { this->Render(); return true; diff --git a/source/main/gui/imgui/OgreImGui.h b/source/main/gui/imgui/OgreImGui.h index a3baf8a66a..f8515b7835 100644 --- a/source/main/gui/imgui/OgreImGui.h +++ b/source/main/gui/imgui/OgreImGui.h @@ -25,29 +25,67 @@ #pragma once -#include -#include -#include -#include -#include +#include "OgreRenderable.h" +#include +#include +#include #include +#include #include +#include #include -#include "OgreRenderable.h" -#include +#include // DearIMGUI math functions, copypasted from -static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); } -static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); } -static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); } -static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); } -static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); } -static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); } -static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } -static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } -static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } -static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } +static inline ImVec2 operator*(const ImVec2 &lhs, const float rhs) +{ + return ImVec2(lhs.x * rhs, lhs.y * rhs); +} +static inline ImVec2 operator/(const ImVec2 &lhs, const float rhs) +{ + return ImVec2(lhs.x / rhs, lhs.y / rhs); +} +static inline ImVec2 operator+(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); +} +static inline ImVec2 operator-(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); +} +static inline ImVec2 operator*(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); +} +static inline ImVec2 operator/(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); +} +static inline ImVec2 &operator+=(ImVec2 &lhs, const ImVec2 &rhs) +{ + lhs.x += rhs.x; + lhs.y += rhs.y; + return lhs; +} +static inline ImVec2 &operator-=(ImVec2 &lhs, const ImVec2 &rhs) +{ + lhs.x -= rhs.x; + lhs.y -= rhs.y; + return lhs; +} +static inline ImVec2 &operator*=(ImVec2 &lhs, const float rhs) +{ + lhs.x *= rhs; + lhs.y *= rhs; + return lhs; +} +static inline ImVec2 &operator/=(ImVec2 &lhs, const float rhs) +{ + lhs.x /= rhs; + lhs.y /= rhs; + return lhs; +} /// DearIMGUI rendering for OGRE engine; Usage: /// 1. Call `Init()` after OGRE was started @@ -55,58 +93,62 @@ static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) /// 3. Use `Inject*()` functions to handle inputs. /// 4. Use any ImGui*() functions to create your GUI. /// 5. Call `Render()` to render the GUI; alternatively register the class as frame listener for automated rendering. -class OgreImGui: public Ogre::FrameListener +class OgreImGui : public Ogre::FrameListener { -public: - OgreImGui(): mSceneMgr(nullptr) {} + public: + OgreImGui() : mSceneMgr(nullptr) + { + } - void Init(Ogre::SceneManager* scenemgr); + void Init(Ogre::SceneManager *scenemgr); void NewFrame(float deltaTime, float vpWidth, float vpHeight, bool ctrl, bool alt, bool shift); void Render(); // Input-injecting functions - void InjectMouseMoved( const OIS::MouseEvent &arg ); - void InjectMousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ); - void InjectMouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ); - void InjectKeyPressed( const OIS::KeyEvent &arg ); - void InjectKeyReleased( const OIS::KeyEvent &arg ); + void InjectMouseMoved(const OIS::MouseEvent &arg); + void InjectMousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id); + void InjectMouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id); + void InjectKeyPressed(const OIS::KeyEvent &arg); + void InjectKeyReleased(const OIS::KeyEvent &arg); // Ogre::FrameListener interface - virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt) override; - -private: + virtual bool frameRenderingQueued(const Ogre::FrameEvent &evt) override; + private: class ImGUIRenderable : public Ogre::Renderable { - public: + public: ImGUIRenderable(); virtual ~ImGUIRenderable(); - void updateVertexData(const ImDrawVert* vtxBuf, const ImDrawIdx* idxBuf, unsigned int vtxCount, unsigned int idxCount); - Ogre::Real getSquaredViewDepth(const Ogre::Camera* cam) const { (void)cam; return 0; } + void updateVertexData(const ImDrawVert *vtxBuf, const ImDrawIdx *idxBuf, unsigned int vtxCount, unsigned int idxCount); + Ogre::Real getSquaredViewDepth(const Ogre::Camera *cam) const + { + (void)cam; + return 0; + } - void setMaterial( const Ogre::String& matName ); - void setMaterial(const Ogre::MaterialPtr & material); - virtual const Ogre::MaterialPtr& getMaterial(void) const override; - virtual void getWorldTransforms( Ogre::Matrix4* xform ) const override; - virtual void getRenderOperation( Ogre::RenderOperation& op ) override; - virtual const Ogre::LightList& getLights(void) const override; + void setMaterial(const Ogre::String &matName); + void setMaterial(const Ogre::MaterialPtr &material); + virtual const Ogre::MaterialPtr &getMaterial(void) const override; + virtual void getWorldTransforms(Ogre::Matrix4 *xform) const override; + virtual void getRenderOperation(Ogre::RenderOperation &op) override; + virtual const Ogre::LightList & getLights(void) const override; int mVertexBufferSize; int mIndexBufferSize; - private: + private: void initImGUIRenderable(void); - Ogre::MaterialPtr mMaterial; + Ogre::MaterialPtr mMaterial; Ogre::RenderOperation mRenderOp; }; void createFontTexture(); void createMaterial(); - Ogre::Pass* mPass; - Ogre::TexturePtr mFontTex; - Ogre::SceneManager* mSceneMgr; - + Ogre::Pass * mPass; + Ogre::TexturePtr mFontTex; + Ogre::SceneManager *mSceneMgr; }; diff --git a/source/main/gui/imgui/imconfig.h b/source/main/gui/imgui/imconfig.h index 1daa254066..adca5ab955 100644 --- a/source/main/gui/imgui/imconfig.h +++ b/source/main/gui/imgui/imconfig.h @@ -20,8 +20,8 @@ //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS -//---- Don't implement help and test window functionality (ShowUserGuide()/ShowStyleEditor()/ShowTestWindow() methods will be empty) -//#define IMGUI_DISABLE_TEST_WINDOWS +//---- Don't implement help and test window functionality (ShowUserGuide()/ShowStyleEditor()/ShowTestWindow() methods will be +// empty) #define IMGUI_DISABLE_TEST_WINDOWS //---- Don't define obsolete functions names //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -54,4 +54,3 @@ namespace ImGui void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL); } */ - diff --git a/source/main/gui/imgui/imgui.cpp b/source/main/gui/imgui/imgui.cpp index 5b1d4f2281..7eecddb06c 100644 --- a/source/main/gui/imgui/imgui.cpp +++ b/source/main/gui/imgui/imgui.cpp @@ -23,7 +23,8 @@ - What is ImTextureID and how do I display an image? - I integrated ImGui in my engine and the text or lines are blurry.. - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs. + - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of +labels/IDs. - How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application? - How can I load a different font than the default? - How can I easily use icons in my application? @@ -44,13 +45,15 @@ - minimize setup and maintenance - minimize state storage on user side - portable, minimize dependencies, run on target (consoles, phones, etc.) - - efficient runtime (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything) + - efficient runtime (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. +- but a typical frame won't allocate anything) - read about immediate-mode gui principles @ http://mollyrocket.com/861, http://mollyrocket.com/forums/index.html Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: - doesn't look fancy, doesn't animate - limited layout features, intricate layouts are typically crafted in code - - occasionally uses statically sized buffers for string manipulations - won't crash, but some very long pieces of text may be clipped. functions like ImGui::TextUnformatted() don't have such restriction. + - occasionally uses statically sized buffers for string manipulations - won't crash, but some very long pieces of text may be +clipped. functions like ImGui::TextUnformatted() don't have such restriction. END-USER GUIDE @@ -80,11 +83,13 @@ ================ - read the FAQ below this section! - - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. + - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less +data retention on your side, no state duplication, less sync, less bugs. - call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - see examples/ folder for standalone sample applications. Prefer reading examples/opengl2_example/ first as it is the simplest. you may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme). + - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more +compact UI or a different color scheme). - getting started: - init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'. @@ -93,11 +98,14 @@ 1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input' 2/ call ImGui::NewFrame() as early as you can! 3/ use any ImGui function you want between NewFrame() and Render() - 4/ call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your RenderDrawListFn handler that you set in the IO structure. - (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) + 4/ call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your RenderDrawListFn +handler that you set in the IO structure. (if you don't need to render, you still need to call Render() and ignore the callback, +or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) - all rendering information are stored into command-lists until ImGui::Render() is called. - - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - - effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. + - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that +you provide. + - effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs +"render" phases of your own application. - refer to the examples applications in the examples/ folder for instruction on how to setup your code. - a typical application skeleton may be: @@ -106,7 +114,8 @@ io.DisplaySize.x = 1920.0f; io.DisplaySize.y = 1280.0f; io.IniFilename = "imgui.ini"; - io.RenderDrawListsFn = my_render_function; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data. + io.RenderDrawListsFn = my_render_function; // Setup a render function, or set to NULL and call GetDrawData() after +Render() to access the render data. // TODO: Fill others settings of the io structure // Load texture atlas @@ -133,16 +142,17 @@ ImGui::NewFrame(); // 3) most of your application code here - MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); - MyGameRender(); // may use any ImGui functions + MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); +ImGui::End(); MyGameRender(); // may use any ImGui functions // 4) render & swap video buffers ImGui::Render(); SwapBuffers(); } - - You can read back 'io.WantCaptureMouse', 'io.WantCaptureKeybord' etc. flags from the IO structure to tell how ImGui intends to use your - inputs and to know if you should share them or hide them from the rest of your application. Read the FAQ below for more information. + - You can read back 'io.WantCaptureMouse', 'io.WantCaptureKeybord' etc. flags from the IO structure to tell how ImGui intends +to use your inputs and to know if you should share them or hide them from the rest of your application. Read the FAQ below for +more information. API BREAKING CHANGES @@ -153,42 +163,68 @@ Also read releases logs https://github.com/ocornut/imgui/releases for more details. - 2017/05/01 (1.50) - Renamed ImDrawList::PathFill() to ImDrawList::PathFillConvex() for clarity. - - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild(). - - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. - - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. - - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. - - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. - If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. - However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. - This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. - ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) + - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions +as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same +child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing +string to BeginChild(). + - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass +io.ClipboardUserData to it. + - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for +horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. + - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. +This was sort of always the intent and hopefully breakage should be minimal. + - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background +(ImGuiCol_WindowBg color) anymore. If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not +affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact +that we don't draw a WindowBg background behind the title bar. This helper function will convert an old TitleBg/TitleBgActive +color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. ImVec4 ConvertTitleBgCol(const +ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; - return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); + return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + +title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); } - If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. - - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). + If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as +TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. + - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now +using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. - - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). - - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. + - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool +display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the +"default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). + - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool +intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at +logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside +style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were +previously using ImGuiCol_WindowBg. (ref github issue #337) + - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection +function (will obsolete). + - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using +DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. + - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 +over that width. if you had manual pixel-perfect alignment in place it might affect you. - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. - - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position. - GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side. - GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out! + - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor +position. GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but +take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from +the window left side. GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the +scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out! - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize - - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project. - - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason - - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure. - you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text. - - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost. - this necessary change will break your rendering function! the fix should be very easy. sorry for that :( - - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. + - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to +your project. + - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for +no justifiable reason + - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of +ImFontAtlas::AddFont** functions to the ImFontConfig structure. you need to render your textured triangles with bilinear filtering +to benefit from sub-pixel positioning of text. + - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to +get anti-aliasing for a marginal cost. this necessary change will break your rendering function! the fix should be very easy. +sorry for that :( + - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to +update your copy and you can ignore the rest. - the signature of the io.RenderDrawListsFn handler has changed! ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) became: @@ -202,34 +238,53 @@ ImDrawCmd 'clip_rect' -> 'ClipRect' ImDrawCmd 'user_callback' -> 'UserCallback' ImDrawCmd 'texture_id' -> 'TextureId' - - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. - - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! - - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade! + - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 +triangles using indices from the index buffer. + - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to +de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! + - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please +upgrade! - 2015/07/10 (1.43) - changed SameLine() parameters from int to float. - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete). - - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. - - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence - - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry! - - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). - - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete). - - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. - - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened. - - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). + - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling +functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. + - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a +difference when texture have transparence + - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override +should have been rarely be used. Sorry! + - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will +obsolete). + - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline +redirection function (will obsolete). + - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. +Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. + - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the +open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup +is opened. + - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already +the same). - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50. - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API - - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. - - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. - - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50. - - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing + - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general +ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. + - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or +Inputfloat() instead. + - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to +GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50. + - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to +ImGuiStyleVar_IndentSpacing - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50. - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing) - - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50. + - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function +until 1.50. - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once. - - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now. + - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, +return 0 for now. - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing() - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused) - - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. + - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with +actual pointer storage functions. - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. this sequence: @@ -243,17 +298,21 @@ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // io.Fonts->TexID = (your_texture_identifier); - you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. - it is now recommended that you sample the font texture with bilinear interpolation. - (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. - (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) - (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets - - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver) - - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph) + you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal +needs. it is now recommended that you sample the font texture with bilinear interpolation. (1.30) - added texture identifier in +ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. (1.30) - removed +IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) (1.30) - removed ImGui::IsItemFocused() in favor of +ImGui::IsItemActive() which handles all widgets + - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, +ImGuiSetCondition_FirstUseEver) + - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, +FontFallbackGlyph) - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered() - - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly) - - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity) + - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl +(more IDE friendly) + - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for +simplicity) - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale() - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically) @@ -279,40 +338,42 @@ stb_textedit.h stb_truetype.h Don't overwrite imconfig.h if you have made modification to your copy. - Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a function, search for its name - in the code, there will likely be a comment about it. Please report any issue to the GitHub page! + Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a +function, search for its name in the code, there will likely be a comment about it. Please report any issue to the GitHub page! Q: What is ImTextureID and how do I display an image? A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. - ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry! - It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc. - At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render. - Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing. - (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!) - To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions. - ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. - It is your responsibility to get textures uploaded to your GPU. + ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the +void* to carry! It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material +(cast MyMaterial* to void*), etc. At the end of the chain, your renderer takes this void* to cast it back into whatever it needs +to select a current texture to render. Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is +treating ImTextureID as a different thing. (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer +into a void*, just cast it to void*, don't take it's address!) To display a custom image/texture within an ImGui window, you may +use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions. ImGui will generate the geometry and draw calls using +the ImTextureID that you passed and which your renderer can use. It is your responsibility to get textures uploaded to your GPU. Q: I integrated ImGui in my engine and the text or lines are blurry.. A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). + A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as +(x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) A: Yes. A primer on the use of labels/IDs in ImGui.. - Elements that are not clickable, such as Text() items don't need an ID. - - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget). - to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. + - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is +the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a +pointer. Button("OK"); // Label = "OK", ID = hash of "OK" Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" - - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows - or in two different locations of a tree. + - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two +different windows or in two different locations of a tree. - If you have a same ID twice in the same location, you'll have a conflict: @@ -321,8 +382,8 @@ Fear not! this is easy to solve and there are many ways to solve it! - - When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases. - use "##" to pass a complement to the ID that won't be visible to the end-user: + - When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the +simpler collision cases. use "##" to pass a complement to the ID that won't be visible to the end-user: Button("Play"); // Label = "Play", ID = hash of "Play" Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) @@ -333,8 +394,8 @@ Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!) - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels. - For example you may want to include varying information in a window title bar (and windows are uniquely identified by their ID.. obviously) - Use "###" to pass a label that isn't part of ID: + For example you may want to include varying information in a window title bar (and windows are uniquely identified by their +ID.. obviously) Use "###" to pass a label that isn't part of ID: Button("Hello###ID"; // Label = "Hello", ID = hash of "ID" Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above) @@ -344,7 +405,8 @@ - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window. This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements. - You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the ID stack! + You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the +ID stack! for (int i = 0; i < 100; i++) { @@ -390,16 +452,20 @@ - When working with trees, ID are used to preserve the open/close state of each tree node. Depending on your use cases you may want to use strings, indices or pointers as ID. - e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. - e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! + e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve +your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as +ID will preserve the node open/closed state differently. experiment and see what makes more sense! Q: How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application? - A: You can read the 'io.WantCaptureXXX' flags in the ImGuiIO structure. Preferably read them after calling ImGui::NewFrame() to avoid those flags lagging by one frame, but either should be fine. - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an on-screen keyboard, if available. - ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is a more accurate and complete than testing for ImGui::IsMouseHoveringAnyWindow(). - (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantcaptureKeyboard=false'. - Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) + A: You can read the 'io.WantCaptureXXX' flags in the ImGuiIO structure. Preferably read them after calling ImGui::NewFrame() to +avoid those flags lagging by one frame, but either should be fine. When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags +are set you may want to discard/hide the inputs from the rest of your application. When 'io.WantInputsCharacters' is set to may +want to notify your OS to popup an on-screen keyboard, if available. ImGui is tracking dragging and widget activity that may occur +outside the boundary of a window, so 'io.WantCaptureMouse' is a more accurate and complete than testing for +ImGui::IsMouseHoveringAnyWindow(). (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' +event that your application receive will typically have 'io.WantcaptureKeyboard=false'. Depending on your application logic it may +or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the +corresponding key-ups.) Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF file you want: @@ -409,8 +475,8 @@ io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() Q: How can I easily use icons in my application? - A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings. - Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions. + A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to +icons within your strings. Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions. Q: How can I load multiple fonts? A: Use the font atlas to pack them into a single texture: @@ -437,27 +503,33 @@ config.MergeMode = true; io.Fonts->AddFontDefault(); io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font - io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs + io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge +japanese glyphs Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. - All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will not work. - In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. + A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. + All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 +for Japanese or CP-1251 for Cyrillic) will not work. In C++11 you can encode a string literal in UTF-8 by using the u8"hello" +syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. You can also try to remap +your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems +reading/editing your source code. - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); // Load Japanese characters - io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - io.ImeWindowHandle = MY_HWND; // To input using Microsoft IME, give ImGui the hwnd of your application + io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); // Load Japanese +characters io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() io.ImeWindowHandle = MY_HWND; // To input using Microsoft +IME, give ImGui the hwnd of your application - As for text input, depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. + As for text input, depends on you passing the right character code to io.AddInputCharacter(). The example applications do +that. Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, - then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. + A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs +flag, zero background alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. + - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly +add custom UI in the middle of a deep nested inner loop in your code. - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug" - - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) + - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. +this is also useful to set yourself in the context of another window (to get/set other settings) - tip: you can call Render() multiple times (e.g for VR renders). - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui! @@ -465,15 +537,20 @@ ISSUES & TODO-LIST ================== Issue numbers (#) refer to github issues listed at https://github.com/ocornut/imgui/issues - The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point it usually moves to the github) + The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point it usually moves +to the github) - doc: add a proper documentation+regression testing system (#435) - - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass. - - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis) (#690) - - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify. + - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the +global window list. perhaps a lightweight explicit cleanup pass. + - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used +for a single axis) (#690) + - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to +end-user. clarify. - window: allow resizing of child windows (possibly given min/max for each axis?) - window: background options for child windows, border option (disable rounding) - - window: add a way to clear an existing window instead of appending (e.g. for tooltip override using a consistent api rather than the deferred tooltip) + - window: add a way to clear an existing window instead of appending (e.g. for tooltip override using a consistent api rather +than the deferred tooltip) - window: resizing from any sides? + mouse cursor directives for app. !- window: begin with *p_open == false should return false. - window: get size/pos helpers given names (see discussion in #249) @@ -482,28 +559,38 @@ - window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later. - window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic. - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - - draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). + - draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical +non-scrolling window or non-overflowing column would merge with previous command). !- scrolling: allow immediately effective change of scroll if we haven't appended items yet - splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319) - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. - widgets: clean up widgets internal toward exposing everything. - widgets: add disabled and read-only modes (#211) - main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them. -!- main: make it so that a frame with no window registered won't refocus every window on subsequent frames (~bump LastFrameActive of all windows). - - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes - - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode? +!- main: make it so that a frame with no window registered won't refocus every window on subsequent frames (~bump LastFrameActive +of all windows). + - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also +effectively IsHovered() region sometimes differs from hot region, e.g tree nodes + - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of +the TreeNode? - input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile. - input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541) - input text: expose CursorPos in char filter event (#816) - - input text: flag to disable live update of the user buffer (also applies to float/int text input) + - input text: flag to disable live update of the user buffer (also applies to float/int text input) - input text: resize behavior - field could stretch when being edited? hover tooltip shows more text? - input text: add ImGuiInputTextFlags_EnterToApply? (off #218) - - input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725) - - input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc). - - input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200) + - input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text +replacement during edition (#725) + - input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to +clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large +text (e.g TextUnformatted could clip and log separately, etc). + - input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow +up on #200) - input text multi-line: line numbers? status bar? (follow up on #200) - - input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725) - - input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position. + - input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal +behavior). namely, the change of buffer can create a scrollbar glitch (#725) + - input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel +position. - input number: optional range min/max for Input*() functions - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled) - input number: use mouse wheel to step up/down @@ -511,7 +598,8 @@ - button: provide a button that looks framed. - text: proper alignment options - image/image button: misalignment on padded/bordered button? - - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that? + - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even +thou they are different parameters ordering could be more consistent. can we fix that? - layout: horizontal layout helper (#97) - layout: horizontal flow until no space left (#404) - layout: more generic alignment state (left/right/centered) for single items? @@ -526,15 +614,18 @@ - columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets) - combo: sparse combo boxes (via function call?) / iterators - combo: contents should extends to fit label if combo widget is small - - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203) + - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox +(pr #203) - listbox: multiple selection - listbox: user may want to initial scroll to focus on the one selected value? - listbox: keyboard navigation. - listbox: scrolling should track modified selection. -!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402) +!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite +fishy needs improvement! (#331, #402) - popups: add variant using global identifier similar to Begin/End (#402) - popups: border options. richer api like BeginChild() perhaps? (#197) - - tooltip: tooltip that doesn't fit in entire screen seems to lose their "last preferred button" and may teleport when moving mouse + - tooltip: tooltip that doesn't fit in entire screen seems to lose their "last preferred button" and may teleport when moving +mouse - menus: local shortcuts, global shortcuts (#456, #126) - menus: icons - menus: menubars: some sort of priority / effect of main menu-bar on desktop size? @@ -548,9 +639,11 @@ - pie menus patterns (#434) - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) + - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple +plots) - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) - - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID) + - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - +probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID) - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt() - slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). - slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate. @@ -568,36 +661,45 @@ - settings: write more decent code to allow saving/loading new fields - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file - style: add window shadows. - - style/optimization: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. + - style/optimization: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of +rounding. - style: color-box not always square? - - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc. + - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other +settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc. - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation). - style: global scale setting. - style: WindowPadding needs to be EVEN needs the 0.5 multiplier probably have a subtle effect on clip rectangle - text: simple markup language for color change? - font: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier. - - font: small opt: for monospace font (like the defalt one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance + - font: small opt: for monospace font (like the defalt one) we can trim IndexXAdvance as long as trailing value is == +FallbackXAdvance - font: add support for kerning, probably optional. perhaps default to (32..128)^2 matrix ~ 36KB then hash fallback. - - font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize) + - font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going +through ImGui::CalcTextSize) - font: fix AddRemapChar() to work before font has been built. - log: LogButtons() options for specifying depth and/or hiding depth slider - log: have more control over the log scope (e.g. stop logging when leaving current tree node scope) - log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard) - - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs. + - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is +commented because it fails with multiple Begin/End pairs. - filters: set a current filter that tree node can automatically query to hide themselves - filters: handle wildcards (with implicit leading/trailing *), regexps - - shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus) + - shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use +(button=activate, input=focus) !- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing - keyboard: full keyboard navigation and focus. (#323) - - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) + - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets +restored (#622) + - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next +frame) - input: rework IO system to be able to pass actual ordered/timestamped events. (~#335, #71) - input: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style). - input: support track pad style scrolling & slider edit. - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? - misc: provide HoveredTime and ActivatedTime to ease the creation of animations. - - style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438) + - style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in +HSV space? (#438) - style editor: color child window height expressed in multiple of line height. - remote: make a system like RemoteImGui first-class citizen/project (#75) - drawlist: move Font, FontSize, FontTexUvWhitePixel inside ImDrawList and make it self-contained (apart from drawing settings?) @@ -606,13 +708,14 @@ - examples: window minimize, maximize (#583) - optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335) - optimization: use another hash function than crc32, e.g. FNV1a - - optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)? + - optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between +clip rectangle don't overlap)? - optimization: turn some the various stack vectors into statically-sized arrays - optimization: better clipping for multi-component widgets */ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS #endif #include "imgui.h" @@ -620,103 +723,120 @@ #define IMGUI_DEFINE_PLACEMENT_NEW #include "imgui_internal.h" -#include // toupper, isprint -#include // NULL, malloc, free, qsort, atoi -#include // vsnprintf, sscanf, printf -#include // INT_MIN, INT_MAX +#include // toupper, isprint +#include // INT_MIN, INT_MAX +#include // vsnprintf, sscanf, printf +#include // NULL, malloc, free, qsort, atoi #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t + #include // intptr_t #else -#include // intptr_t + #include // intptr_t #endif #ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen + #pragma warning(disable : 4127) // condition expression is constant + #pragma warning(disable : 4505) // unreferenced local function has been removed (stb stuff) + #pragma warning( \ + disable : 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif // Clang warnings with -Weverything #ifdef __clang__ -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. -#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. -#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. -#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // -#pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' // + #pragma clang diagnostic ignored \ + "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. + #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing + // and comparing against same constants (typically 0.0f) is ok. + #pragma clang diagnostic ignored \ + "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to + // vsnformat(). yes, user passing incorrect format strings can crash the code. + #pragma clang diagnostic ignored \ + "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order + // is undefined. if MemFree() leads to users code that has been disabled before exit it might + // cause problems. ImGui coding style welcomes static/globals. + #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // + // similar to above, not sure what the exact difference it. + #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // + #pragma clang diagnostic ignored \ + "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would + // lead to casting every %p arg to void*. probably enabled by -pedantic. + #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' // #elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size -#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers + #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used + #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size + #pragma GCC diagnostic ignored \ + "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' + #pragma GCC diagnostic ignored \ + "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function + #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value + #pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers #endif //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- -static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL); - -static void PushMultiItemsWidths(int components, float w_full = 0.0f); -static float GetDraggedColumnOffset(int column_index); - -static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); - -static ImFont* GetDefaultFont(); -static void SetCurrentFont(ImFont* font); -static void SetCurrentWindow(ImGuiWindow* window); -static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); -static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond); -static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond); -static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiSetCond cond); -static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); -static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); -static inline bool IsWindowContentHoverable(ImGuiWindow* window); -static void ClearSetNextWindowData(); -static void CheckStacksSize(ImGuiWindow* window, bool write); -static void Scrollbar(ImGuiWindow* window, bool horizontal); - -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window); -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window); - -static ImGuiIniData* FindWindowSettings(const char* name); -static ImGuiIniData* AddWindowSettings(const char* name); -static void LoadIniSettingsFromDisk(const char* ini_filename); -static void SaveIniSettingsToDisk(const char* ini_filename); -static void MarkIniSettingsDirty(); - -static void PushColumnClipRect(int column_index = -1); -static ImRect GetVisibleRect(); - -static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags); -static void CloseInactivePopups(); -static void ClosePopupToLevel(int remaining); -static void ClosePopup(ImGuiID id); -static bool IsPopupOpen(ImGuiID id); -static ImGuiWindow* GetFrontMostModalRootWindow(); -static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid); - -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data); -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); -static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); - -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size); -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size); -static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2); -static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); +static void LogRenderedText(const ImVec2 &ref_pos, const char *text, const char *text_end = NULL); + +static void PushMultiItemsWidths(int components, float w_full = 0.0f); +static float GetDraggedColumnOffset(int column_index); + +static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); + +static ImFont * GetDefaultFont(); +static void SetCurrentFont(ImFont *font); +static void SetCurrentWindow(ImGuiWindow *window); +static void SetWindowScrollY(ImGuiWindow *window, float new_scroll_y); +static void SetWindowPos(ImGuiWindow *window, const ImVec2 &pos, ImGuiSetCond cond); +static void SetWindowSize(ImGuiWindow *window, const ImVec2 &size, ImGuiSetCond cond); +static void SetWindowCollapsed(ImGuiWindow *window, bool collapsed, ImGuiSetCond cond); +static ImGuiWindow *FindHoveredWindow(ImVec2 pos, bool excluding_childs); +static ImGuiWindow *CreateNewWindow(const char *name, ImVec2 size, ImGuiWindowFlags flags); +static inline bool IsWindowContentHoverable(ImGuiWindow *window); +static void ClearSetNextWindowData(); +static void CheckStacksSize(ImGuiWindow *window, bool write); +static void Scrollbar(ImGuiWindow *window, bool horizontal); + +static void AddDrawListToRenderList(ImVector &out_render_list, ImDrawList *draw_list); +static void AddWindowToRenderList(ImVector &out_render_list, ImGuiWindow *window); +static void AddWindowToSortedBuffer(ImVector &out_sorted_windows, ImGuiWindow *window); + +static ImGuiIniData *FindWindowSettings(const char *name); +static ImGuiIniData *AddWindowSettings(const char *name); +static void LoadIniSettingsFromDisk(const char *ini_filename); +static void SaveIniSettingsToDisk(const char *ini_filename); +static void MarkIniSettingsDirty(); + +static void PushColumnClipRect(int column_index = -1); +static ImRect GetVisibleRect(); + +static bool BeginPopupEx(const char *str_id, ImGuiWindowFlags extra_flags); +static void CloseInactivePopups(); +static void ClosePopupToLevel(int remaining); +static void ClosePopup(ImGuiID id); +static bool IsPopupOpen(ImGuiID id); +static ImGuiWindow *GetFrontMostModalRootWindow(); +static ImVec2 FindBestPopupWindowPos(const ImVec2 &base_pos, const ImVec2 &size, int *last_dir, const ImRect &rect_to_avoid); + +static bool InputTextFilterCharacter(unsigned int *p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, + void *user_data); +static int InputTextCalcTextLenAndLineCount(const char *text_begin, const char **out_text_end); +static ImVec2 InputTextCalcTextSizeW(const ImWchar *text_begin, const ImWchar *text_end, const ImWchar **remaining = NULL, + ImVec2 *out_offset = NULL, bool stop_on_new_line = false); + +static inline void DataTypeFormatString(ImGuiDataType data_type, void *data_ptr, const char *display_format, char *buf, + int buf_size); +static inline void DataTypeFormatString(ImGuiDataType data_type, void *data_ptr, int decimal_precision, char *buf, int buf_size); +static void DataTypeApplyOp(ImGuiDataType data_type, int op, void *value1, const void *value2); +static bool DataTypeApplyOpFromText(const char *buf, const char *initial_value_buf, ImGuiDataType data_type, void *data_ptr, + const char *scalar_format); //----------------------------------------------------------------------------- // Platform dependent default implementations //----------------------------------------------------------------------------- -static const char* GetClipboardTextFn_DefaultImpl(void* user_data); -static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text); -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); +static const char *GetClipboardTextFn_DefaultImpl(void *user_data); +static void SetClipboardTextFn_DefaultImpl(void *user_data, const char *text); +static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); //----------------------------------------------------------------------------- // Context @@ -724,16 +844,19 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); // Default font atlas storage . // New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable. -static ImFontAtlas GImDefaultFontAtlas; +static ImFontAtlas GImDefaultFontAtlas; // Default context storage + current context pointer. -// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext() -// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by: -// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts) -// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 +// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling +// ImGui::SetCurrentContext() ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N +// threads to access N different contexts, you might work around it by: +// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number +// of contexts) +// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim +// to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 #ifndef GImGui -static ImGuiContext GImDefaultContext; -ImGuiContext* GImGui = &GImDefaultContext; +static ImGuiContext GImDefaultContext; +ImGuiContext * GImGui = &GImDefaultContext; #endif //----------------------------------------------------------------------------- @@ -742,73 +865,81 @@ ImGuiContext* GImGui = &GImDefaultContext; ImGuiStyle::ImGuiStyle() { - Alpha = 1.0f; // Global alpha applies to everything in ImGui - WindowPadding = ImVec2(8,8); // Padding within a window - WindowMinSize = ImVec2(32,32); // Minimum window size - WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows - WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows - FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) - FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). - ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines - ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) - TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns - ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar - ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar - GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar - GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. - ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. - DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. - DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. - AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. - AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - - Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); - Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); - Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); - Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input - Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); - Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); - Colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); - Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); - Colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); - Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); - Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); - Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); - Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); - Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); - Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); - Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); - Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); - Colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f); - Colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f); - Colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); - Colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); - Colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); - Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); - Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f); - Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); - Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f); - Colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f); - Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f); - Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); - Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + Alpha = 1.0f; // Global alpha applies to everything in ImGui + WindowPadding = ImVec2(8, 8); // Padding within a window + WindowMinSize = ImVec2(32, 32); // Minimum window size + WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows + WindowTitleAlign = ImVec2(0.0f, 0.5f); // Alignment for title bar text + ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows + FramePadding = ImVec2(4, 3); // Padding within a framed rectangle (used by most widgets) + FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). + ItemSpacing = ImVec2(8, 4); // Horizontal and vertical spacing between widgets/lines + ItemInnerSpacing = ImVec2( + 4, 4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) + TouchExtraPadding = ImVec2( + 0, + 0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we + // don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! + IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). + ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns + ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar + ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar + GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar + GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. + ButtonTextAlign = ImVec2(0.5f, 0.5f); // Alignment of button text when button is larger than text. + DisplayWindowPadding = ImVec2(22, 22); // Window positions are clamped to be visible within the display area by at least this + // amount. Only covers regular windows. + DisplaySafeAreaPadding = ImVec2(4, 4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area + // padding. Covers popups/tooltips as well regular windows. + AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. + AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more + // polygons), increase to reduce quality. + + Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); + Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); + Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); + Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); + Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_FrameBg] = + ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input + Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); + Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); + Colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); + Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); + Colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); + Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); + Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); + Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); + Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); + Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); + Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); + Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); + Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); + Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); + Colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f); + Colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f); + Colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); + Colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); + Colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); + Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); + Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f); + Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f); + Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); + Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); + Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f); + Colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f); + Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f); + Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); + Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); + Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } ImGuiIO::ImGuiIO() @@ -816,20 +947,20 @@ ImGuiIO::ImGuiIO() // Most fields are initialized with zero memset(this, 0, sizeof(*this)); - DisplaySize = ImVec2(-1.0f, -1.0f); - DeltaTime = 1.0f/60.0f; - IniSavingRate = 5.0f; - IniFilename = "imgui.ini"; - LogFilename = "imgui_log.txt"; - Fonts = &GImDefaultFontAtlas; - FontGlobalScale = 1.0f; - FontDefault = NULL; + DisplaySize = ImVec2(-1.0f, -1.0f); + DeltaTime = 1.0f / 60.0f; + IniSavingRate = 5.0f; + IniFilename = "imgui.ini"; + LogFilename = "imgui_log.txt"; + Fonts = &GImDefaultFontAtlas; + FontGlobalScale = 1.0f; + FontDefault = NULL; DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - MousePos = ImVec2(-1,-1); - MousePosPrev = ImVec2(-1,-1); - MouseDoubleClickTime = 0.30f; + MousePos = ImVec2(-1, -1); + MousePosPrev = ImVec2(-1, -1); + MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; - MouseDragThreshold = 6.0f; + MouseDragThreshold = 6.0f; for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) @@ -837,16 +968,16 @@ ImGuiIO::ImGuiIO() for (int i = 0; i < ImGuiKey_COUNT; i++) KeyMap[i] = -1; KeyRepeatDelay = 0.250f; - KeyRepeatRate = 0.050f; - UserData = NULL; + KeyRepeatRate = 0.050f; + UserData = NULL; // User functions - RenderDrawListsFn = NULL; - MemAllocFn = malloc; - MemFreeFn = free; - GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations - SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; - ClipboardUserData = NULL; + RenderDrawListsFn = NULL; + MemAllocFn = malloc; + MemFreeFn = free; + GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations + SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; + ClipboardUserData = NULL; ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; // Set OS X style defaults based on __APPLE__ compile time flag @@ -863,16 +994,16 @@ void ImGuiIO::AddInputCharacter(ImWchar c) const int n = ImStrlenW(InputCharacters); if (n + 1 < IM_ARRAYSIZE(InputCharacters)) { - InputCharacters[n] = c; - InputCharacters[n+1] = '\0'; + InputCharacters[n] = c; + InputCharacters[n + 1] = '\0'; } } -void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) +void ImGuiIO::AddInputCharactersUTF8(const char *utf8_chars) { // We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar); - ImWchar wchars[wchars_buf_len]; + ImWchar wchars[wchars_buf_len]; ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL); for (int i = 0; i < wchars_buf_len && wchars[i] != 0; i++) AddInputCharacter(wchars[i]); @@ -882,17 +1013,17 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) // HELPERS //----------------------------------------------------------------------------- -#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose -#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 +#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL)*255.0f + ((_VAL) >= 0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose +#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. #ifdef _WIN32 -#define IM_NEWLINE "\r\n" + #define IM_NEWLINE "\r\n" #else -#define IM_NEWLINE "\n" + #define IM_NEWLINE "\n" #endif -bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c) +bool ImIsPointInTriangle(const ImVec2 &p, const ImVec2 &a, const ImVec2 &b, const ImVec2 &c) { bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f; bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f; @@ -900,101 +1031,106 @@ bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, cons return ((b1 == b2) && (b2 == b3)); } -int ImStricmp(const char* str1, const char* str2) +int ImStricmp(const char *str1, const char *str2) { int d; - while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } + while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) + { + str1++; + str2++; + } return d; } -int ImStrnicmp(const char* str1, const char* str2, int count) +int ImStrnicmp(const char *str1, const char *str2, int count) { int d = 0; - while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; } + while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) + { + str1++; + str2++; + count--; + } return d; } -void ImStrncpy(char* dst, const char* src, int count) +void ImStrncpy(char *dst, const char *src, int count) { if (count < 1) return; strncpy(dst, src, (size_t)count); - dst[count-1] = 0; + dst[count - 1] = 0; } -char* ImStrdup(const char *str) +char *ImStrdup(const char *str) { - size_t len = strlen(str) + 1; - void* buff = ImGui::MemAlloc(len); - return (char*)memcpy(buff, (const void*)str, len); + size_t len = strlen(str) + 1; + void * buff = ImGui::MemAlloc(len); + return (char *)memcpy(buff, (const void *)str, len); } -int ImStrlenW(const ImWchar* str) +int ImStrlenW(const ImWchar *str) { int n = 0; - while (*str++) n++; + while (*str++) + n++; return n; } -const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line +const ImWchar *ImStrbolW(const ImWchar *buf_mid_line, const ImWchar *buf_begin) // find beginning-of-line { while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') buf_mid_line--; return buf_mid_line; } -const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end) +const char *ImStristr(const char *haystack, const char *haystack_end, const char *needle, const char *needle_end) { - if (!needle_end) - needle_end = needle + strlen(needle); + if (!needle_end) needle_end = needle + strlen(needle); const char un0 = (char)toupper(*needle); while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) { if (toupper(*haystack) == un0) { - const char* b = needle + 1; - for (const char* a = haystack + 1; b < needle_end; a++, b++) - if (toupper(*a) != toupper(*b)) - break; - if (b == needle_end) - return haystack; + const char *b = needle + 1; + for (const char *a = haystack + 1; b < needle_end; a++, b++) + if (toupper(*a) != toupper(*b)) break; + if (b == needle_end) return haystack; } haystack++; } return NULL; } - -// MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). -// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. -int ImFormatString(char* buf, int buf_size, const char* fmt, ...) +// MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). +// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct +// it at compile time sounds like a pandora can of worm. +int ImFormatString(char *buf, int buf_size, const char *fmt, ...) { IM_ASSERT(buf_size > 0); va_list args; va_start(args, fmt); int w = vsnprintf(buf, buf_size, fmt, args); va_end(args); - if (w == -1 || w >= buf_size) - w = buf_size - 1; + if (w == -1 || w >= buf_size) w = buf_size - 1; buf[w] = 0; return w; } -int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) +int ImFormatStringV(char *buf, int buf_size, const char *fmt, va_list args) { IM_ASSERT(buf_size > 0); int w = vsnprintf(buf, buf_size, fmt, args); - if (w == -1 || w >= buf_size) - w = buf_size - 1; + if (w == -1 || w >= buf_size) w = buf_size - 1; buf[w] = 0; return w; } // Pass data_size==0 for zero-terminated strings // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImU32 ImHash(const void* data, int data_size, ImU32 seed) +ImU32 ImHash(const void *data, int data_size, ImU32 seed) { - static ImU32 crc32_lut[256] = { 0 }; + static ImU32 crc32_lut[256] = {0}; if (!crc32_lut[1]) { const ImU32 polynomial = 0xEDB88320; @@ -1007,9 +1143,9 @@ ImU32 ImHash(const void* data, int data_size, ImU32 seed) } } - seed = ~seed; - ImU32 crc = seed; - const unsigned char* current = (const unsigned char*)data; + seed = ~seed; + ImU32 crc = seed; + const unsigned char *current = (const unsigned char *)data; if (data_size > 0) { @@ -1026,8 +1162,7 @@ ImU32 ImHash(const void* data, int data_size, ImU32 seed) // Because this syntax is rarely used we are optimizing for the common case. // - If we reach ### in the string we discard the hash so far and reset to the seed. // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller. - if (c == '#' && current[0] == '#' && current[1] == '#') - crc = seed; + if (c == '#' && current[0] == '#' && current[1] == '#') crc = seed; crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; } } @@ -1041,20 +1176,20 @@ ImU32 ImHash(const void* data, int data_size, ImU32 seed) // Convert UTF-8 to 32-bits character, process single character input. // Based on stb_from_utf8() from github.com/nothings/stb/ // We handle UTF-8 decoding error by skipping forward. -int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) +int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, const char *in_text_end) { - unsigned int c = (unsigned int)-1; - const unsigned char* str = (const unsigned char*)in_text; + unsigned int c = (unsigned int)-1; + const unsigned char *str = (const unsigned char *)in_text; if (!(*str & 0x80)) { - c = (unsigned int)(*str++); + c = (unsigned int)(*str++); *out_char = c; return 1; } if ((*str & 0xe0) == 0xc0) { *out_char = 0xFFFD; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 2) return 1; + if (in_text_end && in_text_end - (const char *)str < 2) return 1; if (*str < 0xc2) return 2; c = (unsigned int)((*str++ & 0x1f) << 6); if ((*str & 0xc0) != 0x80) return 2; @@ -1065,7 +1200,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* if ((*str & 0xf0) == 0xe0) { *out_char = 0xFFFD; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 3) return 1; + if (in_text_end && in_text_end - (const char *)str < 3) return 1; if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3; if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below c = (unsigned int)((*str++ & 0x0f) << 12); @@ -1079,7 +1214,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* if ((*str & 0xf8) == 0xf0) { *out_char = 0xFFFD; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 4) return 1; + if (in_text_end && in_text_end - (const char *)str < 4) return 1; if (*str > 0xf4) return 4; if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4; if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below @@ -1099,42 +1234,38 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* return 0; } -int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) +int ImTextStrFromUtf8(ImWchar *buf, int buf_size, const char *in_text, const char *in_text_end, const char **in_text_remaining) { - ImWchar* buf_out = buf; - ImWchar* buf_end = buf + buf_size; - while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text) + ImWchar *buf_out = buf; + ImWchar *buf_end = buf + buf_size; + while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c; in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); - if (c == 0) - break; - if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes + if (c == 0) break; + if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes *buf_out++ = (ImWchar)c; } *buf_out = 0; - if (in_text_remaining) - *in_text_remaining = in_text; + if (in_text_remaining) *in_text_remaining = in_text; return (int)(buf_out - buf); } -int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) +int ImTextCountCharsFromUtf8(const char *in_text, const char *in_text_end) { int char_count = 0; while ((!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c; in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); - if (c == 0) - break; - if (c < 0x10000) - char_count++; + if (c == 0) break; + if (c < 0x10000) char_count++; } return char_count; } // Based on stb_to_utf8() from github.com/nothings/stb/ -static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) +static inline int ImTextCharToUtf8(char *buf, int buf_size, unsigned int c) { if (c < 0x80) { @@ -1148,25 +1279,22 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) buf[1] = (char)(0x80 + (c & 0x3f)); return 2; } - if (c >= 0xdc00 && c < 0xe000) - { - return 0; - } + if (c >= 0xdc00 && c < 0xe000) { return 0; } if (c >= 0xd800 && c < 0xdc00) { if (buf_size < 4) return 0; buf[0] = (char)(0xf0 + (c >> 18)); buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); - buf[3] = (char)(0x80 + ((c ) & 0x3f)); + buf[3] = (char)(0x80 + ((c)&0x3f)); return 4; } - //else if (c < 0x10000) + // else if (c < 0x10000) { if (buf_size < 3) return 0; buf[0] = (char)(0xe0 + (c >> 12)); - buf[1] = (char)(0x80 + ((c>> 6) & 0x3f)); - buf[2] = (char)(0x80 + ((c ) & 0x3f)); + buf[1] = (char)(0x80 + ((c >> 6) & 0x3f)); + buf[2] = (char)(0x80 + ((c)&0x3f)); return 3; } } @@ -1180,23 +1308,23 @@ static inline int ImTextCountUtf8BytesFromChar(unsigned int c) return 3; } -int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end) +int ImTextStrToUtf8(char *buf, int buf_size, const ImWchar *in_text, const ImWchar *in_text_end) { - char* buf_out = buf; - const char* buf_end = buf + buf_size; - while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text) + char * buf_out = buf; + const char *buf_end = buf + buf_size; + while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c = (unsigned int)(*in_text++); if (c < 0x80) *buf_out++ = (char)c; else - buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c); + buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c); } *buf_out = 0; return (int)(buf_out - buf); } -int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) +int ImTextCountUtf8BytesFromStr(const ImWchar *in_text, const ImWchar *in_text_end) { int bytes_count = 0; while ((!in_text_end || in_text < in_text_end) && *in_text) @@ -1212,63 +1340,64 @@ int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_e ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) { - float s = 1.0f/255.0f; - return ImVec4( - ((in >> IM_COL32_R_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); + float s = 1.0f / 255.0f; + return ImVec4(((in >> IM_COL32_R_SHIFT) & 0xFF) * s, ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); } -ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) +ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4 &in) { ImU32 out; - out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT; + out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT; out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT; out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT; out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT; return out; } -ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) -{ - ImVec4 c = GImGui->Style.Colors[idx]; - c.w *= GImGui->Style.Alpha * alpha_mul; - return ColorConvertFloat4ToU32(c); +ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) +{ + ImVec4 c = GImGui->Style.Colors[idx]; + c.w *= GImGui->Style.Alpha * alpha_mul; + return ColorConvertFloat4ToU32(c); } -ImU32 ImGui::GetColorU32(const ImVec4& col) -{ - ImVec4 c = col; - c.w *= GImGui->Style.Alpha; - return ColorConvertFloat4ToU32(c); +ImU32 ImGui::GetColorU32(const ImVec4 &col) +{ + ImVec4 c = col; + c.w *= GImGui->Style.Alpha; + return ColorConvertFloat4ToU32(c); } // Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592 // Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv -void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v) +void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float &out_h, float &out_s, float &out_v) { float K = 0.f; if (g < b) { - const float tmp = g; g = b; b = tmp; - K = -1.f; + const float tmp = g; + g = b; + b = tmp; + K = -1.f; } if (r < g) { - const float tmp = r; r = g; g = tmp; - K = -2.f / 6.f - K; + const float tmp = r; + r = g; + g = tmp; + K = -2.f / 6.f - K; } const float chroma = r - (g < b ? g : b); - out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f)); - out_s = chroma / (r + 1e-20f); - out_v = r; + out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f)); + out_s = chroma / (r + 1e-20f); + out_v = r; } // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 // also http://en.wikipedia.org/wiki/HSL_and_HSV -void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b) +void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float &out_r, float &out_g, float &out_b) { if (s == 0.0f) { @@ -1277,7 +1406,7 @@ void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& return; } - h = fmodf(h, 1.0f) / (60.0f/360.0f); + h = fmodf(h, 1.0f) / (60.0f / 360.0f); int i = (int)h; float f = h - (float)i; float p = v * (1.0f - s); @@ -1286,26 +1415,52 @@ void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& switch (i) { - case 0: out_r = v; out_g = t; out_b = p; break; - case 1: out_r = q; out_g = v; out_b = p; break; - case 2: out_r = p; out_g = v; out_b = t; break; - case 3: out_r = p; out_g = q; out_b = v; break; - case 4: out_r = t; out_g = p; out_b = v; break; - case 5: default: out_r = v; out_g = p; out_b = q; break; + case 0: + out_r = v; + out_g = t; + out_b = p; + break; + case 1: + out_r = q; + out_g = v; + out_b = p; + break; + case 2: + out_r = p; + out_g = v; + out_b = t; + break; + case 3: + out_r = p; + out_g = q; + out_b = v; + break; + case 4: + out_r = t; + out_g = p; + out_b = v; + break; + case 5: + default: + out_r = v; + out_g = p; + out_b = q; + break; } } -FILE* ImFileOpen(const char* filename, const char* mode) +FILE *ImFileOpen(const char *filename, const char *mode) { #if defined(_WIN32) && !defined(__CYGWIN__) - // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can) - const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; - const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; + // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to + // wchar format (using a single allocation, because we can) + const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; + const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; ImVector buf; buf.resize(filename_wsize + mode_wsize); ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL); ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL); - return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]); + return _wfopen((wchar_t *)&buf[0], (wchar_t *)&buf[filename_wsize]); #else return fopen(filename, mode); #endif @@ -1313,15 +1468,13 @@ FILE* ImFileOpen(const char* filename, const char* mode) // Load file content into memory // Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree() -void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size, int padding_bytes) +void *ImFileLoadToMemory(const char *filename, const char *file_open_mode, int *out_file_size, int padding_bytes) { IM_ASSERT(filename && file_open_mode); - if (out_file_size) - *out_file_size = 0; + if (out_file_size) *out_file_size = 0; - FILE* f; - if ((f = ImFileOpen(filename, file_open_mode)) == NULL) - return NULL; + FILE *f; + if ((f = ImFileOpen(filename, file_open_mode)) == NULL) return NULL; long file_size_signed; if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) @@ -1330,8 +1483,8 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* return NULL; } - int file_size = (int)file_size_signed; - void* file_data = ImGui::MemAlloc(file_size + padding_bytes); + int file_size = (int)file_size_signed; + void *file_data = ImGui::MemAlloc(file_size + padding_bytes); if (file_data == NULL) { fclose(f); @@ -1343,12 +1496,10 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* ImGui::MemFree(file_data); return NULL; } - if (padding_bytes > 0) - memset((void *)(((char*)file_data) + file_size), 0, padding_bytes); + if (padding_bytes > 0) memset((void *)(((char *)file_data) + file_size), 0, padding_bytes); fclose(f); - if (out_file_size) - *out_file_size = file_size; + if (out_file_size) *out_file_size = file_size; return file_data; } @@ -1364,15 +1515,15 @@ void ImGuiStorage::Clear() } // std::lower_bound but without the bullshit -static ImVector::iterator LowerBound(ImVector& data, ImGuiID key) +static ImVector::iterator LowerBound(ImVector &data, ImGuiID key) { ImVector::iterator first = data.begin(); - ImVector::iterator last = data.end(); - int count = (int)(last - first); + ImVector::iterator last = data.end(); + int count = (int)(last - first); while (count > 0) { - int count2 = count / 2; - ImVector::iterator mid = first + count2; + int count2 = count / 2; + ImVector::iterator mid = first + count2; if (mid->key < key) { first = ++mid; @@ -1388,9 +1539,8 @@ static ImVector::iterator LowerBound(ImVector::iterator it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return default_val; + ImVector::iterator it = LowerBound(const_cast &>(Data), key); + if (it == Data.end() || it->key != key) return default_val; return it->val_i; } @@ -1401,51 +1551,48 @@ bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const { - ImVector::iterator it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return default_val; + ImVector::iterator it = LowerBound(const_cast &>(Data), key); + if (it == Data.end() || it->key != key) return default_val; return it->val_f; } -void* ImGuiStorage::GetVoidPtr(ImGuiID key) const +void *ImGuiStorage::GetVoidPtr(ImGuiID key) const { - ImVector::iterator it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return NULL; + ImVector::iterator it = LowerBound(const_cast &>(Data), key); + if (it == Data.end() || it->key != key) return NULL; return it->val_p; } -// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. -int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) +// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function +// invalidates the pointer. +int *ImGuiStorage::GetIntRef(ImGuiID key, int default_val) { ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); + if (it == Data.end() || it->key != key) it = Data.insert(it, Pair(key, default_val)); return &it->val_i; } -bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) +bool *ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) { - return (bool*)GetIntRef(key, default_val ? 1 : 0); + return (bool *)GetIntRef(key, default_val ? 1 : 0); } -float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) +float *ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); + if (it == Data.end() || it->key != key) it = Data.insert(it, Pair(key, default_val)); return &it->val_f; } -void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) +void **ImGuiStorage::GetVoidPtrRef(ImGuiID key, void *default_val) { ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); + if (it == Data.end() || it->key != key) it = Data.insert(it, Pair(key, default_val)); return &it->val_p; } -// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) +// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on +// explicit interaction (maximum one a frame) void ImGuiStorage::SetInt(ImGuiID key, int val) { ImVector::iterator it = LowerBound(Data, key); @@ -1473,7 +1620,7 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val) it->val_f = val; } -void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) +void ImGuiStorage::SetVoidPtr(ImGuiID key, void *val) { ImVector::iterator it = LowerBound(Data, key); if (it == Data.end() || it->key != key) @@ -1495,7 +1642,7 @@ void ImGuiStorage::SetAllInt(int v) //----------------------------------------------------------------------------- // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) +ImGuiTextFilter::ImGuiTextFilter(const char *default_filter) { if (default_filter) { @@ -1505,27 +1652,24 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) else { InputBuf[0] = 0; - CountGrep = 0; + CountGrep = 0; } } -bool ImGuiTextFilter::Draw(const char* label, float width) +bool ImGuiTextFilter::Draw(const char *label, float width) { - if (width != 0.0f) - ImGui::PushItemWidth(width); + if (width != 0.0f) ImGui::PushItemWidth(width); bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf)); - if (width != 0.0f) - ImGui::PopItemWidth(); - if (value_changed) - Build(); + if (width != 0.0f) ImGui::PopItemWidth(); + if (value_changed) Build(); return value_changed; } -void ImGuiTextFilter::TextRange::split(char separator, ImVector& out) +void ImGuiTextFilter::TextRange::split(char separator, ImVector &out) { out.resize(0); - const char* wb = b; - const char* we = wb; + const char *wb = b; + const char *we = wb; while (we < e) { if (*we == separator) @@ -1535,57 +1679,48 @@ void ImGuiTextFilter::TextRange::split(char separator, ImVector& out) } we++; } - if (wb != we) - out.push_back(TextRange(wb, we)); + if (wb != we) out.push_back(TextRange(wb, we)); } void ImGuiTextFilter::Build() { Filters.resize(0); - TextRange input_range(InputBuf, InputBuf+strlen(InputBuf)); + TextRange input_range(InputBuf, InputBuf + strlen(InputBuf)); input_range.split(',', Filters); CountGrep = 0; for (int i = 0; i != Filters.Size; i++) { Filters[i].trim_blanks(); - if (Filters[i].empty()) - continue; - if (Filters[i].front() != '-') - CountGrep += 1; + if (Filters[i].empty()) continue; + if (Filters[i].front() != '-') CountGrep += 1; } } -bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const +bool ImGuiTextFilter::PassFilter(const char *text, const char *text_end) const { - if (Filters.empty()) - return true; + if (Filters.empty()) return true; - if (text == NULL) - text = ""; + if (text == NULL) text = ""; for (int i = 0; i != Filters.Size; i++) { - const TextRange& f = Filters[i]; - if (f.empty()) - continue; + const TextRange &f = Filters[i]; + if (f.empty()) continue; if (f.front() == '-') { // Subtract - if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL) - return false; + if (ImStristr(text, text_end, f.begin() + 1, f.end()) != NULL) return false; } else { // Grep - if (ImStristr(text, text_end, f.begin(), f.end()) != NULL) - return true; + if (ImStristr(text, text_end, f.begin(), f.end()) != NULL) return true; } } // Implicit * grep - if (CountGrep == 0) - return true; + if (CountGrep == 0) return true; return false; } @@ -1597,18 +1732,17 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const // On some platform vsnprintf() takes va_list by reference and modifies it. // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. #ifndef va_copy -#define va_copy(dest, src) (dest = src) + #define va_copy(dest, src) (dest = src) #endif // Helper: Text buffer for logging/accumulating text -void ImGuiTextBuffer::appendv(const char* fmt, va_list args) +void ImGuiTextBuffer::appendv(const char *fmt, va_list args) { va_list args_copy; va_copy(args_copy, args); - int len = vsnprintf(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. - if (len <= 0) - return; + int len = vsnprintf(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. + if (len <= 0) return; const int write_off = Buf.Size; const int needed_sz = write_off + len; @@ -1619,10 +1753,10 @@ void ImGuiTextBuffer::appendv(const char* fmt, va_list args) } Buf.resize(needed_sz); - ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args_copy); + ImFormatStringV(&Buf[write_off] - 1, len + 1, fmt, args_copy); } -void ImGuiTextBuffer::append(const char* fmt, ...) +void ImGuiTextBuffer::append(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -1636,7 +1770,7 @@ void ImGuiTextBuffer::append(const char* fmt, ...) ImGuiSimpleColumns::ImGuiSimpleColumns() { - Count = 0; + Count = 0; Spacing = Width = NextWidth = 0.0f; memset(Pos, 0, sizeof(Pos)); memset(NextWidths, 0, sizeof(NextWidths)); @@ -1647,12 +1781,11 @@ void ImGuiSimpleColumns::Update(int count, float spacing, bool clear) IM_ASSERT(Count <= IM_ARRAYSIZE(Pos)); Count = count; Width = NextWidth = 0.0f; - Spacing = spacing; + Spacing = spacing; if (clear) memset(NextWidths, 0, sizeof(NextWidths)); for (int i = 0; i < Count; i++) { - if (i > 0 && NextWidths[i] > 0.0f) - Width += Spacing; + if (i > 0 && NextWidths[i] > 0.0f) Width += Spacing; Pos[i] = (float)(int)Width; Width += NextWidths[i]; NextWidths[i] = 0.0f; @@ -1661,7 +1794,7 @@ void ImGuiSimpleColumns::Update(int count, float spacing, bool clear) float ImGuiSimpleColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double { - NextWidth = 0.0f; + NextWidth = 0.0f; NextWidths[0] = ImMax(NextWidths[0], w0); NextWidths[1] = ImMax(NextWidths[1], w1); NextWidths[2] = ImMax(NextWidths[2], w2); @@ -1681,25 +1814,32 @@ float ImGuiSimpleColumns::CalcExtraSpace(float avail_w) static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) { - // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. - // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. Consider moving within SetCursorXXX functions? + // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. + // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same + // issue. Consider moving within SetCursorXXX functions? ImGui::SetCursorPosY(pos_y); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. - window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. + ImGuiWindow *window = ImGui::GetCurrentWindow(); + window->DC.CursorPosPrevLine.y = + window->DC.CursorPos.y - + line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. + window->DC.PrevLineHeight = + (line_height - + GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the + // clipper have a fourth step to let user process and display the last item in their list. if (window->DC.ColumnsCount > 1) - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + window->DC.ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 // Use case B: Begin() called from constructor with items_height>0 -// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. +// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is +// why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. void ImGuiListClipper::Begin(int count, float items_height) { - StartPosY = ImGui::GetCursorPosY(); + StartPosY = ImGui::GetCursorPosY(); ItemsHeight = items_height; - ItemsCount = count; - StepNo = 0; + ItemsCount = count; + StepNo = 0; DisplayEnd = DisplayStart = -1; if (ItemsHeight > 0.0f) { @@ -1712,48 +1852,56 @@ void ImGuiListClipper::Begin(int count, float items_height) void ImGuiListClipper::End() { - if (ItemsCount < 0) - return; - // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. + if (ItemsCount < 0) return; + // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to + // just seek at the end and not assert/crash the user. if (ItemsCount < INT_MAX) SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor ItemsCount = -1; - StepNo = 3; + StepNo = 3; } bool ImGuiListClipper::Step() { if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems) { - ItemsCount = -1; - return false; + ItemsCount = -1; + return false; } - if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height. + if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can + // measure the element height. { DisplayStart = 0; - DisplayEnd = 1; - StartPosY = ImGui::GetCursorPosY(); - StepNo = 1; + DisplayEnd = 1; + StartPosY = ImGui::GetCursorPosY(); + StepNo = 1; return true; } - if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. + if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, + // and position the cursor before the first element. { - if (ItemsCount == 1) { ItemsCount = -1; return false; } + if (ItemsCount == 1) + { + ItemsCount = -1; + return false; + } float items_height = ImGui::GetCursorPosY() - StartPosY; - IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically - Begin(ItemsCount-1, items_height); + IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically + Begin(ItemsCount - 1, items_height); DisplayStart++; DisplayEnd++; StepNo = 3; return true; } - if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3. + if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user + // still call Step(). Does nothing and switch to Step 3. { IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0); StepNo = 3; return true; } - if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. + if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element + // DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. End(); return false; } @@ -1762,48 +1910,49 @@ bool ImGuiListClipper::Step() // ImGuiWindow //----------------------------------------------------------------------------- -ImGuiWindow::ImGuiWindow(const char* name) +ImGuiWindow::ImGuiWindow(const char *name) { Name = ImStrdup(name); - ID = ImHash(name, 0); + ID = ImHash(name, 0); IDStack.push_back(ID); MoveId = GetID("#MOVE"); - Flags = 0; + Flags = 0; IndexWithinParent = 0; PosFloat = Pos = ImVec2(0.0f, 0.0f); Size = SizeFull = ImVec2(0.0f, 0.0f); SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); - WindowPadding = ImVec2(0.0f, 0.0f); - Scroll = ImVec2(0.0f, 0.0f); - ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); - ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); + WindowPadding = ImVec2(0.0f, 0.0f); + Scroll = ImVec2(0.0f, 0.0f); + ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); + ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); ScrollbarX = ScrollbarY = false; - ScrollbarSizes = ImVec2(0.0f, 0.0f); - BorderSize = 0.0f; + ScrollbarSizes = ImVec2(0.0f, 0.0f); + BorderSize = 0.0f; Active = WasActive = false; - Accessed = false; - Collapsed = false; - SkipItems = false; - BeginCount = 0; - PopupId = 0; + Accessed = false; + Collapsed = false; + SkipItems = false; + BeginCount = 0; + PopupId = 0; AutoFitFramesX = AutoFitFramesY = -1; - AutoFitOnlyGrows = false; - AutoPosLastDirection = -1; - HiddenFrames = 0; - SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; + AutoFitOnlyGrows = false; + AutoPosLastDirection = -1; + HiddenFrames = 0; + SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = + ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; SetWindowPosCenterWanted = false; - LastFrameActive = -1; + LastFrameActive = -1; ItemWidthDefault = 0.0f; - FontWindowScale = 1.0f; + FontWindowScale = 1.0f; - DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList)); + DrawList = (ImDrawList *)ImGui::MemAlloc(sizeof(ImDrawList)); IM_PLACEMENT_NEW(DrawList) ImDrawList(); DrawList->_OwnerName = Name; - RootWindow = NULL; - RootNonPopupWindow = NULL; - ParentWindow = NULL; + RootWindow = NULL; + RootNonPopupWindow = NULL; + ParentWindow = NULL; FocusIdxAllCounter = FocusIdxTabCounter = -1; FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; @@ -1819,23 +1968,23 @@ ImGuiWindow::~ImGuiWindow() Name = NULL; } -ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) +ImGuiID ImGuiWindow::GetID(const char *str, const char *str_end) { ImGuiID seed = IDStack.back(); - ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed); + ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed); ImGui::KeepAliveID(id); return id; } -ImGuiID ImGuiWindow::GetID(const void* ptr) +ImGuiID ImGuiWindow::GetID(const void *ptr) { ImGuiID seed = IDStack.back(); - ImGuiID id = ImHash(&ptr, sizeof(void*), seed); + ImGuiID id = ImHash(&ptr, sizeof(void *), seed); ImGui::KeepAliveID(id); return id; } -ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) +ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char *str, const char *str_end) { ImGuiID seed = IDStack.back(); return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); @@ -1845,29 +1994,27 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) // Internal API exposed in imgui_internal.h //----------------------------------------------------------------------------- -static void SetCurrentWindow(ImGuiWindow* window) +static void SetCurrentWindow(ImGuiWindow *window) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; g.CurrentWindow = window; - if (window) - g.FontSize = window->CalcFontSize(); + if (window) g.FontSize = window->CalcFontSize(); } -ImGuiWindow* ImGui::GetParentWindow() +ImGuiWindow *ImGui::GetParentWindow() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } -void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) +void ImGui::SetActiveID(ImGuiID id, ImGuiWindow *window) { - ImGuiContext& g = *GImGui; - g.ActiveId = id; - g.ActiveIdAllowOverlap = false; + ImGuiContext &g = *GImGui; + g.ActiveId = id; + g.ActiveIdAllowOverlap = false; g.ActiveIdIsJustActivated = true; - if (id) - g.ActiveIdIsAlive = true; + if (id) g.ActiveIdIsAlive = true; g.ActiveIdWindow = window; } @@ -1878,60 +2025,59 @@ void ImGui::ClearActiveID() void ImGui::SetHoveredID(ImGuiID id) { - ImGuiContext& g = *GImGui; - g.HoveredId = id; + ImGuiContext &g = *GImGui; + g.HoveredId = id; g.HoveredIdAllowOverlap = false; } void ImGui::KeepAliveID(ImGuiID id) { - ImGuiContext& g = *GImGui; - if (g.ActiveId == id) - g.ActiveIdIsAlive = true; + ImGuiContext &g = *GImGui; + if (g.ActiveId == id) g.ActiveIdIsAlive = true; } // Advance cursor given item size for layout. -void ImGui::ItemSize(const ImVec2& size, float text_offset_y) +void ImGui::ItemSize(const ImVec2 &size, float text_offset_y) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; // Always align ourselves on pixel boundaries - ImGuiContext& g = *GImGui; - const float line_height = ImMax(window->DC.CurrentLineHeight, size.y); - const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y); - window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); - window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y)); - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); - - //window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // Debug - - window->DC.PrevLineHeight = line_height; + ImGuiContext &g = *GImGui; + const float line_height = ImMax(window->DC.CurrentLineHeight, size.y); + const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y); + window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); + window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), + (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y)); + window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); + window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); + + // window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // Debug + + window->DC.PrevLineHeight = line_height; window->DC.PrevLineTextBaseOffset = text_base_offset; window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f; } -void ImGui::ItemSize(const ImRect& bb, float text_offset_y) +void ImGui::ItemSize(const ImRect &bb, float text_offset_y) { ItemSize(bb.GetSize(), text_offset_y); } // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface -// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). -bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) +// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to +// ItemAdd(). +bool ImGui::ItemAdd(const ImRect &bb, const ImGuiID *id) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.LastItemId = id ? *id : 0; - window->DC.LastItemRect = bb; + ImGuiWindow *window = GetCurrentWindow(); + window->DC.LastItemId = id ? *id : 0; + window->DC.LastItemRect = bb; window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; - if (IsClippedEx(bb, id, false)) - return false; + if (IsClippedEx(bb, id, false)) return false; // This is a sensible default, but widgets are free to override it after calling ItemAdd() - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (IsMouseHoveringRect(bb.Min, bb.Max)) { // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) @@ -1939,68 +2085,64 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) window->DC.LastItemHoveredRect = true; if (g.HoveredRootWindow == window->RootWindow) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) - if (IsWindowContentHoverable(window)) - window->DC.LastItemHoveredAndUsable = true; + if (IsWindowContentHoverable(window)) window->DC.LastItemHoveredAndUsable = true; } return true; } -bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged) +bool ImGui::IsClippedEx(const ImRect &bb, const ImGuiID *id, bool clip_even_when_logged) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindowRead(); if (!bb.Overlaps(window->ClipRect)) if (!id || *id != GImGui->ActiveId) - if (clip_even_when_logged || !g.LogEnabled) - return true; + if (clip_even_when_logged || !g.LogEnabled) return true; return false; } -// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. -bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) +// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different +// logic. +bool ImGui::IsHovered(const ImRect &bb, ImGuiID id, bool flatten_childs) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(g.HoveredRootWindow)) - return true; + if (IsWindowContentHoverable(g.HoveredRootWindow)) return true; } return false; } -bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop) +bool ImGui::FocusableItemRegister(ImGuiWindow *window, bool is_active, bool tab_stop) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus; window->FocusIdxAllCounter++; - if (allow_keyboard_focus) - window->FocusIdxTabCounter++; + if (allow_keyboard_focus) window->FocusIdxTabCounter++; // Process keyboard input at this point: TAB, Shift-TAB switch focus // We can always TAB out of a widget that doesn't allow tabbing in. - if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab)) + if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && + IsKeyPressedMap(ImGuiKey_Tab)) { // Modulo on index will be applied at the end of frame once we've got the total counter of items. window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); } - if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) - return true; + if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) return true; if (allow_keyboard_focus) - if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) - return true; + if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) return true; return false; } -void ImGui::FocusableItemUnregister(ImGuiWindow* window) +void ImGui::FocusableItemUnregister(ImGuiWindow *window) { window->FocusIdxAllCounter--; window->FocusIdxTabCounter--; @@ -2008,10 +2150,9 @@ void ImGui::FocusableItemUnregister(ImGuiWindow* window) ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y) { - ImGuiContext& g = *GImGui; - ImVec2 content_max; - if (size.x < 0.0f || size.y < 0.0f) - content_max = g.CurrentWindow->Pos + GetContentRegionMax(); + ImGuiContext &g = *GImGui; + ImVec2 content_max; + if (size.x < 0.0f || size.y < 0.0f) content_max = g.CurrentWindow->Pos + GetContentRegionMax(); if (size.x <= 0.0f) size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x; if (size.y <= 0.0f) @@ -2019,12 +2160,11 @@ ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y) return size; } -float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) +float ImGui::CalcWrapWidthForPos(const ImVec2 &pos, float wrap_pos_x) { - if (wrap_pos_x < 0.0f) - return 0.0f; + if (wrap_pos_x < 0.0f) return 0.0f; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); if (wrap_pos_x == 0.0f) wrap_pos_x = GetContentRegionMax().x + window->Pos.x; else if (wrap_pos_x > 0.0f) @@ -2035,42 +2175,42 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) //----------------------------------------------------------------------------- -void* ImGui::MemAlloc(size_t sz) +void *ImGui::MemAlloc(size_t sz) { GImGui->IO.MetricsAllocs++; return GImGui->IO.MemAllocFn(sz); } -void ImGui::MemFree(void* ptr) +void ImGui::MemFree(void *ptr) { if (ptr) GImGui->IO.MetricsAllocs--; return GImGui->IO.MemFreeFn(ptr); } -const char* ImGui::GetClipboardText() +const char *ImGui::GetClipboardText() { return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : ""; } -void ImGui::SetClipboardText(const char* text) +void ImGui::SetClipboardText(const char *text) { - if (GImGui->IO.SetClipboardTextFn) - GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text); + if (GImGui->IO.SetClipboardTextFn) GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text); } -const char* ImGui::GetVersion() +const char *ImGui::GetVersion() { return IMGUI_VERSION; } // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself -// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module -ImGuiContext* ImGui::GetCurrentContext() +// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will +// point to the static data within its module +ImGuiContext *ImGui::GetCurrentContext() { return GImGui; } -void ImGui::SetCurrentContext(ImGuiContext* ctx) +void ImGui::SetCurrentContext(ImGuiContext *ctx) { #ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this. @@ -2079,37 +2219,36 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx) #endif } -ImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)) +ImGuiContext *ImGui::CreateContext(void *(*malloc_fn)(size_t), void (*free_fn)(void *)) { if (!malloc_fn) malloc_fn = malloc; - ImGuiContext* ctx = (ImGuiContext*)malloc_fn(sizeof(ImGuiContext)); + ImGuiContext *ctx = (ImGuiContext *)malloc_fn(sizeof(ImGuiContext)); IM_PLACEMENT_NEW(ctx) ImGuiContext(); ctx->IO.MemAllocFn = malloc_fn; - ctx->IO.MemFreeFn = free_fn ? free_fn : free; + ctx->IO.MemFreeFn = free_fn ? free_fn : free; return ctx; } -void ImGui::DestroyContext(ImGuiContext* ctx) +void ImGui::DestroyContext(ImGuiContext *ctx) { - void (*free_fn)(void*) = ctx->IO.MemFreeFn; + void (*free_fn)(void *) = ctx->IO.MemFreeFn; ctx->~ImGuiContext(); free_fn(ctx); - if (GImGui == ctx) - SetCurrentContext(NULL); + if (GImGui == ctx) SetCurrentContext(NULL); } -ImGuiIO& ImGui::GetIO() +ImGuiIO &ImGui::GetIO() { return GImGui->IO; } -ImGuiStyle& ImGui::GetStyle() +ImGuiStyle &ImGui::GetStyle() { return GImGui->Style; } // Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() -ImDrawData* ImGui::GetDrawData() +ImDrawData *ImGui::GetDrawData() { return GImGui->RenderDrawData.Valid ? &GImGui->RenderDrawData : NULL; } @@ -2126,19 +2265,21 @@ int ImGui::GetFrameCount() void ImGui::NewFrame() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; // Check user data - IM_ASSERT(g.IO.DeltaTime >= 0.0f); // Need a positive DeltaTime (zero is tolerated but will cause some timing issues) + IM_ASSERT(g.IO.DeltaTime >= 0.0f); // Need a positive DeltaTime (zero is tolerated but will cause some timing issues) IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f); - IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? - IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? - IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid style setting + IM_ASSERT(g.IO.Fonts->Fonts.Size > + 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? + IM_ASSERT(g.IO.Fonts->Fonts[0] + ->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? + IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid style setting if (!g.Initialized) { // Initialize on first frame - g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); + g.LogClipboard = (ImGuiTextBuffer *)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer(); IM_ASSERT(g.Settings.empty()); @@ -2157,63 +2298,68 @@ void ImGui::NewFrame() g.OverlayDrawList.PushClipRectFullScreen(); // Mark rendering data as invalid to prevent user who may have a handle on it to use it - g.RenderDrawData.Valid = false; - g.RenderDrawData.CmdLists = NULL; + g.RenderDrawData.Valid = false; + g.RenderDrawData.CmdLists = NULL; g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; // Update inputs state - if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) - g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); - if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta + if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); + if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || + (g.IO.MousePosPrev.x < 0 && + g.IO.MousePosPrev.y < + 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta g.IO.MouseDelta = ImVec2(0.0f, 0.0f); else g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; g.IO.MousePosPrev = g.IO.MousePos; for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) { - g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; - g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; + g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; + g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; - g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; + g.IO.MouseDownDuration[i] = + g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; g.IO.MouseDoubleClicked[i] = false; if (g.IO.MouseClicked[i]) { if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime) { - if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) + if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < + g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) g.IO.MouseDoubleClicked[i] = true; - g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click + g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click } else { g.IO.MouseClickedTime[i] = g.Time; } - g.IO.MouseClickedPos[i] = g.IO.MousePos; + g.IO.MouseClickedPos[i] = g.IO.MousePos; g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; } else if (g.IO.MouseDown[i]) { - g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); + g.IO.MouseDragMaxDistanceSqr[i] = + ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); } } memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) - g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; + g.IO.KeysDownDuration[i] = + g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; // Calculate frame-rate for the user, as a purely luxurious feature g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; - g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); + g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); // Clear reference to active widget if the widget isn't alive anymore g.HoveredIdPreviousFrame = g.HoveredId; - g.HoveredId = 0; - g.HoveredIdAllowOverlap = false; - if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) - ClearActiveID(); - g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdIsAlive = false; + g.HoveredId = 0; + g.HoveredIdAllowOverlap = false; + if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) ClearActiveID(); + g.ActiveIdPreviousFrame = g.ActiveId; + g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. @@ -2227,7 +2373,8 @@ void ImGui::NewFrame() if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovedWindow->PosFloat += g.IO.MouseDelta; - if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings) && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) + if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings) && + (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) MarkIniSettingsDirty(); } FocusWindow(g.MovedWindow); @@ -2235,13 +2382,13 @@ void ImGui::NewFrame() else { ClearActiveID(); - g.MovedWindow = NULL; + g.MovedWindow = NULL; g.MovedWindowMoveId = 0; } } else { - g.MovedWindow = NULL; + g.MovedWindow = NULL; g.MovedWindowMoveId = 0; } @@ -2249,25 +2396,24 @@ void ImGui::NewFrame() if (g.SettingsDirtyTimer > 0.0f) { g.SettingsDirtyTimer -= g.IO.DeltaTime; - if (g.SettingsDirtyTimer <= 0.0f) - SaveIniSettingsToDisk(g.IO.IniFilename); + if (g.SettingsDirtyTimer <= 0.0f) SaveIniSettingsToDisk(g.IO.IniFilename); } - // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow + // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive + // HoveredRootWindow from HoveredWindow g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false); if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow)) g.HoveredRootWindow = g.HoveredWindow->RootWindow; else g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true); - if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) + if (ImGuiWindow *modal_window = GetFrontMostModalRootWindow()) { g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); - ImGuiWindow* window = g.HoveredRootWindow; + ImGuiWindow *window = g.HoveredRootWindow; while (window && window != modal_window) window = window->ParentWindow; - if (!window) - g.HoveredRootWindow = g.HoveredWindow = NULL; + if (!window) g.HoveredRootWindow = g.HoveredWindow = NULL; } else { @@ -2275,13 +2421,13 @@ void ImGui::NewFrame() } // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application. - // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership. - int mouse_earliest_button_down = -1; - bool mouse_any_down = false; + // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to + // track click ownership. + int mouse_earliest_button_down = -1; + bool mouse_any_down = false; for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) { - if (g.IO.MouseClicked[i]) - g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); + if (g.IO.MouseClicked[i]) g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); mouse_any_down |= g.IO.MouseDown[i]; if (g.IO.MouseDown[i]) if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i]) @@ -2291,28 +2437,28 @@ void ImGui::NewFrame() if (g.CaptureMouseNextFrame != -1) g.IO.WantCaptureMouse = (g.CaptureMouseNextFrame != 0); else - g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty()); + g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || + (!g.OpenPopupStack.empty()); g.IO.WantCaptureKeyboard = (g.CaptureKeyboardNextFrame != -1) ? (g.CaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); - g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); - g.MouseCursor = ImGuiMouseCursor_Arrow; + g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); + g.MouseCursor = ImGuiMouseCursor_Arrow; g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = -1; g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. - if (!mouse_avail_to_imgui) - g.HoveredWindow = g.HoveredRootWindow = NULL; + if (!mouse_avail_to_imgui) g.HoveredWindow = g.HoveredRootWindow = NULL; // Scale & Scrolling if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed) { - ImGuiWindow* window = g.HoveredWindow; + ImGuiWindow *window = g.HoveredWindow; if (g.IO.KeyCtrl) { if (g.IO.FontAllowUserScaling) { // Zoom / Scale window - float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - float scale = new_font_scale / window->FontWindowScale; + float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); + float scale = new_font_scale / window->FontWindowScale; window->FontWindowScale = new_font_scale; const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; @@ -2331,22 +2477,23 @@ void ImGui::NewFrame() } // Pressing TAB activate widget focus - // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. + // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard + // focus. if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false)) g.FocusedWindow->FocusIdxTabRequestNext = 0; // Mark all windows as not visible for (int i = 0; i != g.Windows.Size; i++) { - ImGuiWindow* window = g.Windows[i]; - window->WasActive = window->Active; - window->Active = false; - window->Accessed = false; + ImGuiWindow *window = g.Windows[i]; + window->WasActive = window->Active; + window->Active = false; + window->Accessed = false; } // Closing the focused window restore focus to the first active root window in descending z-order if (g.FocusedWindow && !g.FocusedWindow->WasActive) - for (int i = g.Windows.Size-1; i >= 0; i--) + for (int i = g.Windows.Size - 1; i >= 0; i--) if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) { FocusWindow(g.Windows[i]); @@ -2360,22 +2507,23 @@ void ImGui::NewFrame() CloseInactivePopups(); // Create implicit window - we will only render it if the user has added something to it. - ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiSetCond_FirstUseEver); ImGui::Begin("Debug"); } -// NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations. +// NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap +// allocations. void ImGui::Shutdown() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; - // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) + // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen + // if we never called NewFrame) if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. g.IO.Fonts->Clear(); // Cleanup of other data are conditional on actually having used ImGui. - if (!g.Initialized) - return; + if (!g.Initialized) return; SaveIniSettingsToDisk(g.IO.IniFilename); @@ -2388,11 +2536,11 @@ void ImGui::Shutdown() g.WindowsSortBuffer.clear(); g.CurrentWindow = NULL; g.CurrentWindowStack.clear(); - g.FocusedWindow = NULL; - g.HoveredWindow = NULL; + g.FocusedWindow = NULL; + g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; - g.ActiveIdWindow = NULL; - g.MovedWindow = NULL; + g.ActiveIdWindow = NULL; + g.MovedWindow = NULL; for (int i = 0; i < g.Settings.Size; i++) ImGui::MemFree(g.Settings[i].Name); g.Settings.clear(); @@ -2401,7 +2549,7 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - g.SetNextWindowSizeConstraintCallback = NULL; + g.SetNextWindowSizeConstraintCallback = NULL; g.SetNextWindowSizeConstraintCallbackUserData = NULL; for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].clear(); @@ -2430,64 +2578,60 @@ void ImGui::Shutdown() g.Initialized = false; } -static ImGuiIniData* FindWindowSettings(const char* name) +static ImGuiIniData *FindWindowSettings(const char *name) { - ImGuiContext& g = *GImGui; - ImGuiID id = ImHash(name, 0); + ImGuiContext &g = *GImGui; + ImGuiID id = ImHash(name, 0); for (int i = 0; i != g.Settings.Size; i++) { - ImGuiIniData* ini = &g.Settings[i]; - if (ini->Id == id) - return ini; + ImGuiIniData *ini = &g.Settings[i]; + if (ini->Id == id) return ini; } return NULL; } -static ImGuiIniData* AddWindowSettings(const char* name) +static ImGuiIniData *AddWindowSettings(const char *name) { GImGui->Settings.resize(GImGui->Settings.Size + 1); - ImGuiIniData* ini = &GImGui->Settings.back(); - ini->Name = ImStrdup(name); - ini->Id = ImHash(name, 0); - ini->Collapsed = false; - ini->Pos = ImVec2(FLT_MAX,FLT_MAX); - ini->Size = ImVec2(0,0); + ImGuiIniData *ini = &GImGui->Settings.back(); + ini->Name = ImStrdup(name); + ini->Id = ImHash(name, 0); + ini->Collapsed = false; + ini->Pos = ImVec2(FLT_MAX, FLT_MAX); + ini->Size = ImVec2(0, 0); return ini; } // Zero-tolerance, poor-man .ini parsing // FIXME: Write something less rubbish -static void LoadIniSettingsFromDisk(const char* ini_filename) +static void LoadIniSettingsFromDisk(const char *ini_filename) { - ImGuiContext& g = *GImGui; - if (!ini_filename) - return; + ImGuiContext &g = *GImGui; + if (!ini_filename) return; - int file_size; - char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_size, 1); - if (!file_data) - return; + int file_size; + char *file_data = (char *)ImFileLoadToMemory(ini_filename, "rb", &file_size, 1); + if (!file_data) return; - ImGuiIniData* settings = NULL; - const char* buf_end = file_data + file_size; - for (const char* line_start = file_data; line_start < buf_end; ) + ImGuiIniData *settings = NULL; + const char * buf_end = file_data + file_size; + for (const char *line_start = file_data; line_start < buf_end;) { - const char* line_end = line_start; + const char *line_end = line_start; while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') line_end++; if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']') { char name[64]; - ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", (int)(line_end-line_start-2), line_start+1); + ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", (int)(line_end - line_start - 2), line_start + 1); settings = FindWindowSettings(name); - if (!settings) - settings = AddWindowSettings(name); + if (!settings) settings = AddWindowSettings(name); } else if (settings) { float x, y; - int i; + int i; if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y); else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2) @@ -2496,43 +2640,40 @@ static void LoadIniSettingsFromDisk(const char* ini_filename) settings->Collapsed = (i != 0); } - line_start = line_end+1; + line_start = line_end + 1; } ImGui::MemFree(file_data); } -static void SaveIniSettingsToDisk(const char* ini_filename) +static void SaveIniSettingsToDisk(const char *ini_filename) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; g.SettingsDirtyTimer = 0.0f; - if (!ini_filename) - return; + if (!ini_filename) return; // Gather data from windows that were active during this session for (int i = 0; i != g.Windows.Size; i++) { - ImGuiWindow* window = g.Windows[i]; - if (window->Flags & ImGuiWindowFlags_NoSavedSettings) - continue; - ImGuiIniData* settings = FindWindowSettings(window->Name); - settings->Pos = window->Pos; - settings->Size = window->SizeFull; - settings->Collapsed = window->Collapsed; + ImGuiWindow *window = g.Windows[i]; + if (window->Flags & ImGuiWindowFlags_NoSavedSettings) continue; + ImGuiIniData *settings = FindWindowSettings(window->Name); + settings->Pos = window->Pos; + settings->Size = window->SizeFull; + settings->Collapsed = window->Collapsed; } // Write .ini file // If a window wasn't opened in this session we preserve its settings - FILE* f = ImFileOpen(ini_filename, "wt"); - if (!f) - return; + FILE *f = ImFileOpen(ini_filename, "wt"); + if (!f) return; for (int i = 0; i != g.Settings.Size; i++) { - const ImGuiIniData* settings = &g.Settings[i]; - if (settings->Pos.x == FLT_MAX) - continue; - const char* name = settings->Name; - if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() + const ImGuiIniData *settings = &g.Settings[i]; + if (settings->Pos.x == FLT_MAX) continue; + const char *name = settings->Name; + if (const char *p = + strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() name = p; fprintf(f, "[%s]\n", name); fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); @@ -2546,54 +2687,46 @@ static void SaveIniSettingsToDisk(const char* ini_filename) static void MarkIniSettingsDirty() { - ImGuiContext& g = *GImGui; - if (g.SettingsDirtyTimer <= 0.0f) - g.SettingsDirtyTimer = g.IO.IniSavingRate; + ImGuiContext &g = *GImGui; + if (g.SettingsDirtyTimer <= 0.0f) g.SettingsDirtyTimer = g.IO.IniSavingRate; } // FIXME: Add a more explicit sort order in the window structure. -static int ChildWindowComparer(const void* lhs, const void* rhs) -{ - const ImGuiWindow* a = *(const ImGuiWindow**)lhs; - const ImGuiWindow* b = *(const ImGuiWindow**)rhs; - if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) - return d; - if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) - return d; - if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox)) - return d; +static int ChildWindowComparer(const void *lhs, const void *rhs) +{ + const ImGuiWindow *a = *(const ImGuiWindow **)lhs; + const ImGuiWindow *b = *(const ImGuiWindow **)rhs; + if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) return d; + if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) return d; + if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox)) return d; return (a->IndexWithinParent - b->IndexWithinParent); } -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window) +static void AddWindowToSortedBuffer(ImVector &out_sorted_windows, ImGuiWindow *window) { out_sorted_windows.push_back(window); if (window->Active) { int count = window->DC.ChildWindows.Size; - if (count > 1) - qsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer); + if (count > 1) qsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow *), ChildWindowComparer); for (int i = 0; i < count; i++) { - ImGuiWindow* child = window->DC.ChildWindows[i]; - if (child->Active) - AddWindowToSortedBuffer(out_sorted_windows, child); + ImGuiWindow *child = window->DC.ChildWindows[i]; + if (child->Active) AddWindowToSortedBuffer(out_sorted_windows, child); } } } -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list) +static void AddDrawListToRenderList(ImVector &out_render_list, ImDrawList *draw_list) { - if (draw_list->CmdBuffer.empty()) - return; + if (draw_list->CmdBuffer.empty()) return; // Remove trailing command if unused - ImDrawCmd& last_cmd = draw_list->CmdBuffer.back(); + ImDrawCmd &last_cmd = draw_list->CmdBuffer.back(); if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL) { draw_list->CmdBuffer.pop_back(); - if (draw_list->CmdBuffer.empty()) - return; + if (draw_list->CmdBuffer.empty()) return; } // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. @@ -2602,49 +2735,54 @@ static void AddDrawListToRenderList(ImVector& out_render_list, ImDr IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) - // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - + // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to + // put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render + // accordingly. + IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= + ((int64_t)1L << (sizeof(ImDrawIdx) * 8))); // Too many vertices in same ImDrawList. See comment above. + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; } -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window) +static void AddWindowToRenderList(ImVector &out_render_list, ImGuiWindow *window) { AddDrawListToRenderList(out_render_list, window->DrawList); for (int i = 0; i < window->DC.ChildWindows.Size; i++) { - ImGuiWindow* child = window->DC.ChildWindows[i]; + ImGuiWindow *child = window->DC.ChildWindows[i]; if (!child->Active) // clipped children may have been marked not active continue; - if ((child->Flags & ImGuiWindowFlags_Popup) && child->HiddenFrames > 0) - continue; + if ((child->Flags & ImGuiWindowFlags_Popup) && child->HiddenFrames > 0) continue; AddWindowToRenderList(out_render_list, child); } } -// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. -void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) +// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. +// (int)(max.x-min.x) in user's render produce correct result. +void ImGui::PushClipRect(const ImVec2 &clip_rect_min, const ImVec2 &clip_rect_max, bool intersect_with_current_clip_rect) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect); window->ClipRect = window->DrawList->_ClipRectStack.back(); } void ImGui::PopClipRect() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DrawList->PopClipRect(); window->ClipRect = window->DrawList->_ClipRectStack.back(); } -// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. +// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will +// be very minimal. void ImGui::EndFrame() { - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() - IM_ASSERT(g.FrameCountEnded != g.FrameCount); // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again + ImGuiContext &g = *GImGui; + IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.FrameCountEnded != + g.FrameCount); // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again // Render tooltip if (g.Tooltip[0]) @@ -2662,9 +2800,8 @@ void ImGui::EndFrame() } // Hide implicit "Debug" window if it hasn't been used - IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls - if (g.CurrentWindow && !g.CurrentWindow->Accessed) - g.CurrentWindow->Active = false; + IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls + if (g.CurrentWindow && !g.CurrentWindow->Accessed) g.CurrentWindow->Active = false; ImGui::End(); // Click to focus window and start moving (after we're done with all our widgets) @@ -2677,7 +2814,7 @@ void ImGui::EndFrame() FocusWindow(g.HoveredWindow); if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) { - g.MovedWindow = g.HoveredWindow; + g.MovedWindow = g.HoveredWindow; g.MovedWindowMoveId = g.HoveredRootWindow->MoveId; SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); } @@ -2696,12 +2833,12 @@ void ImGui::EndFrame() g.WindowsSortBuffer.reserve(g.Windows.Size); for (int i = 0; i != g.Windows.Size; i++) { - ImGuiWindow* window = g.Windows[i]; - if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it + ImGuiWindow *window = g.Windows[i]; + if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it continue; AddWindowToSortedBuffer(g.WindowsSortBuffer, window); } - IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong + IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong g.Windows.swap(g.WindowsSortBuffer); // Clear Input data for next frame @@ -2713,15 +2850,15 @@ void ImGui::EndFrame() void ImGui::Render() { - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + ImGuiContext &g = *GImGui; + IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() - if (g.FrameCountEnded != g.FrameCount) - ImGui::EndFrame(); + if (g.FrameCountEnded != g.FrameCount) ImGui::EndFrame(); g.FrameCountRendered = g.FrameCount; // Skip render altogether if alpha is 0.0 - // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false. + // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the + // first place, or consistently respond to Begin() returning false. if (g.Style.Alpha > 0.0f) { // Gather windows to render @@ -2730,7 +2867,7 @@ void ImGui::Render() g.RenderDrawLists[i].resize(0); for (int i = 0; i != g.Windows.Size; i++) { - ImGuiWindow* window = g.Windows[i]; + ImGuiWindow *window = g.Windows[i]; if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) { // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. @@ -2745,55 +2882,55 @@ void ImGui::Render() } // Flatten layers - int n = g.RenderDrawLists[0].Size; + int n = g.RenderDrawLists[0].Size; int flattened_size = n; for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) flattened_size += g.RenderDrawLists[i].Size; g.RenderDrawLists[0].resize(flattened_size); for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) { - ImVector& layer = g.RenderDrawLists[i]; - if (layer.empty()) - continue; - memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); + ImVector &layer = g.RenderDrawLists[i]; + if (layer.empty()) continue; + memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList *)); n += layer.Size; } // Draw software mouse cursor if requested if (g.IO.MouseDrawCursor) { - const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor]; - const ImVec2 pos = g.IO.MousePos - cursor_data.HotOffset; - const ImVec2 size = cursor_data.Size; - const ImTextureID tex_id = g.IO.Fonts->TexID; + const ImGuiMouseCursorData &cursor_data = g.MouseCursorData[g.MouseCursor]; + const ImVec2 pos = g.IO.MousePos - cursor_data.HotOffset; + const ImVec2 size = cursor_data.Size; + const ImTextureID tex_id = g.IO.Fonts->TexID; g.OverlayDrawList.PushTextureID(tex_id); - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,255)); // Black border - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], IM_COL32(255,255,255,255)); // White fill + g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(1, 0), pos + ImVec2(1, 0) + size, cursor_data.TexUvMin[1], + cursor_data.TexUvMax[1], IM_COL32(0, 0, 0, 48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(2, 0), pos + ImVec2(2, 0) + size, cursor_data.TexUvMin[1], + cursor_data.TexUvMax[1], IM_COL32(0, 0, 0, 48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], + IM_COL32(0, 0, 0, 255)); // Black border + g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], + IM_COL32(255, 255, 255, 255)); // White fill g.OverlayDrawList.PopTextureID(); } - if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList); + if (!g.OverlayDrawList.VtxBuffer.empty()) AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList); // Setup draw data - g.RenderDrawData.Valid = true; - g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL; + g.RenderDrawData.Valid = true; + g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL; g.RenderDrawData.CmdListsCount = g.RenderDrawLists[0].Size; g.RenderDrawData.TotalVtxCount = g.IO.MetricsRenderVertices; g.RenderDrawData.TotalIdxCount = g.IO.MetricsRenderIndices; // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() - if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) - g.IO.RenderDrawListsFn(&g.RenderDrawData); + if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) g.IO.RenderDrawListsFn(&g.RenderDrawData); } } -const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) +const char *ImGui::FindRenderedTextEnd(const char *text, const char *text_end) { - const char* text_display_end = text; - if (!text_end) - text_end = (const char*)-1; + const char *text_display_end = text; + if (!text_end) text_end = (const char *)-1; while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) text_display_end++; @@ -2801,18 +2938,14 @@ const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) } // Pass text data straight to log (without being displayed) -void ImGui::LogText(const char* fmt, ...) +void ImGui::LogText(const char *fmt, ...) { - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; + ImGuiContext &g = *GImGui; + if (!g.LogEnabled) return; va_list args; va_start(args, fmt); - if (g.LogFile) - { - vfprintf(g.LogFile, fmt, args); - } + if (g.LogFile) { vfprintf(g.LogFile, fmt, args); } else { g.LogClipboard->appendv(fmt, args); @@ -2822,72 +2955,66 @@ void ImGui::LogText(const char* fmt, ...) // Internal version that takes a position to decide on newline placement and pad items according to their depth. // We split text into individual lines to add current tree level padding -static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end) +static void LogRenderedText(const ImVec2 &ref_pos, const char *text, const char *text_end) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = ImGui::GetCurrentWindowRead(); - if (!text_end) - text_end = ImGui::FindRenderedTextEnd(text, text_end); + if (!text_end) text_end = ImGui::FindRenderedTextEnd(text, text_end); - const bool log_new_line = ref_pos.y > window->DC.LogLinePosY+1; - window->DC.LogLinePosY = ref_pos.y; + const bool log_new_line = ref_pos.y > window->DC.LogLinePosY + 1; + window->DC.LogLinePosY = ref_pos.y; - const char* text_remaining = text; - if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth + const char *text_remaining = text; + if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth g.LogStartDepth = window->DC.TreeDepth; const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth); for (;;) { - // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry. - const char* line_end = text_remaining; + // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log + // entry. + const char *line_end = text_remaining; while (line_end < text_end) if (*line_end == '\n') break; else line_end++; - if (line_end >= text_end) - line_end = NULL; + if (line_end >= text_end) line_end = NULL; const bool is_first_line = (text == text_remaining); - bool is_last_line = false; + bool is_last_line = false; if (line_end == NULL) { is_last_line = true; - line_end = text_end; + line_end = text_end; } - if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0)) + if (line_end != NULL && !(is_last_line && (line_end - text_remaining) == 0)) { const int char_count = (int)(line_end - text_remaining); if (log_new_line || !is_first_line) - ImGui::LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); + ImGui::LogText(IM_NEWLINE "%*s%.*s", tree_depth * 4, "", char_count, text_remaining); else ImGui::LogText(" %.*s", char_count, text_remaining); } - if (is_last_line) - break; + if (is_last_line) break; text_remaining = line_end + 1; } } // Internal ImGui functions to render text // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() -void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) +void ImGui::RenderText(ImVec2 pos, const char *text, const char *text_end, bool hide_text_after_hash) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); // Hide anything after a '##' string - const char* text_display_end; - if (hide_text_after_hash) - { - text_display_end = FindRenderedTextEnd(text, text_end); - } + const char *text_display_end; + if (hide_text_after_hash) { text_display_end = FindRenderedTextEnd(text, text_end); } else { - if (!text_end) - text_end = text + strlen(text); // FIXME-OPT + if (!text_end) text_end = text + strlen(text); // FIXME-OPT text_display_end = text_end; } @@ -2895,52 +3022,51 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool if (text_len > 0) { window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); - if (g.LogEnabled) - LogRenderedText(pos, text, text_display_end); + if (g.LogEnabled) LogRenderedText(pos, text, text_display_end); } } -void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) +void ImGui::RenderTextWrapped(ImVec2 pos, const char *text, const char *text_end, float wrap_width) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); - if (!text_end) - text_end = text + strlen(text); // FIXME-OPT + if (!text_end) text_end = text + strlen(text); // FIXME-OPT const int text_len = (int)(text_end - text); if (text_len > 0) { window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); - if (g.LogEnabled) - LogRenderedText(pos, text, text_end); + if (g.LogEnabled) LogRenderedText(pos, text, text_end); } } // Default clip_rect uses (pos_min,pos_max) -// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges) -void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) +// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle +// edges) +void ImGui::RenderTextClipped(const ImVec2 &pos_min, const ImVec2 &pos_max, const char *text, const char *text_end, + const ImVec2 *text_size_if_known, const ImVec2 &align, const ImRect *clip_rect) { // Hide anything after a '##' string - const char* text_display_end = FindRenderedTextEnd(text, text_end); - const int text_len = (int)(text_display_end - text); - if (text_len == 0) - return; + const char *text_display_end = FindRenderedTextEnd(text, text_end); + const int text_len = (int)(text_display_end - text); + if (text_len == 0) return; - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); // Perform CPU side clipping for single clipped element to avoid using scissor state - ImVec2 pos = pos_min; + ImVec2 pos = pos_min; const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); - const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min; - const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max; - bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); + const ImVec2 *clip_min = clip_rect ? &clip_rect->Min : &pos_min; + const ImVec2 *clip_max = clip_rect ? &clip_rect->Max : &pos_max; + bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y); - // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment. + // Align whole block. We should defer that to the better rendering function when we'll have support for individual line + // alignment. if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x); if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y); @@ -2948,25 +3074,25 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons if (need_clipping) { ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, + &fine_clip_rect); } else { window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); } - if (g.LogEnabled) - LogRenderedText(pos, text, text_display_end); + if (g.LogEnabled) LogRenderedText(pos, text, text_display_end); } // Render a rectangle shaped with optional rounding and borders void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); if (border && (window->Flags & ImGuiWindowFlags_ShowBorders)) { - window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding); + window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding); window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding); } } @@ -2974,26 +3100,26 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, // Render a triangle to denote expanded/collapsed state void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); - const float h = g.FontSize * 1.00f; - const float r = h * 0.40f * scale; - ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale); + const float h = g.FontSize * 1.00f; + const float r = h * 0.40f * scale; + ImVec2 center = p_min + ImVec2(h * 0.50f, h * 0.50f * scale); ImVec2 a, b, c; if (is_open) { - center.y -= r*0.25f; - a = center + ImVec2(0,1)*r; - b = center + ImVec2(-0.866f,-0.5f)*r; - c = center + ImVec2(0.866f,-0.5f)*r; + center.y -= r * 0.25f; + a = center + ImVec2(0, 1) * r; + b = center + ImVec2(-0.866f, -0.5f) * r; + c = center + ImVec2(0.866f, -0.5f) * r; } else { - a = center + ImVec2(1,0)*r; - b = center + ImVec2(-0.500f,0.866f)*r; - c = center + ImVec2(-0.500f,-0.866f)*r; + a = center + ImVec2(1, 0) * r; + b = center + ImVec2(-0.500f, 0.866f) * r; + c = center + ImVec2(-0.500f, -0.866f) * r; } window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text)); @@ -3001,22 +3127,23 @@ void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale) void ImGui::RenderBullet(ImVec2 pos) { - ImGuiWindow* window = GetCurrentWindow(); - window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8); + ImGuiWindow *window = GetCurrentWindow(); + window->DrawList->AddCircleFilled(pos, GImGui->FontSize * 0.20f, GetColorU32(ImGuiCol_Text), 8); } void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); ImVec2 a, b, c; - float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f); - float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f); - a.x = pos.x + 0.5f + start_x; - b.x = a.x + rem_third; - c.x = a.x + rem_third * 3.0f; - b.y = pos.y - 1.0f + (float)(int)(g.Font->Ascent * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y); + float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f); + float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f); + a.x = pos.x + 0.5f + start_x; + b.x = a.x + rem_third; + c.x = a.x + rem_third * 3.0f; + b.y = pos.y - 1.0f + (float)(int)(g.Font->Ascent * (g.FontSize / g.Font->FontSize) + 0.5f) + + (float)(int)(g.Font->DisplayOffset.y); a.y = b.y - rem_third; c.y = b.y - rem_third * 2.0f; @@ -3028,44 +3155,42 @@ void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. // CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize) -ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) +ImVec2 ImGui::CalcTextSize(const char *text, const char *text_end, bool hide_text_after_double_hash, float wrap_width) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; - const char* text_display_end; + const char *text_display_end; if (hide_text_after_double_hash) - text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string + text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string else text_display_end = text_end; - ImFont* font = g.Font; + ImFont * font = g.Font; const float font_size = g.FontSize; - if (text == text_display_end) - return ImVec2(0.0f, font_size); + if (text == text_display_end) return ImVec2(0.0f, font_size); ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field) - const float font_scale = font_size / font->FontSize; + const float font_scale = font_size / font->FontSize; const float character_spacing_x = 1.0f * font_scale; - if (text_size.x > 0.0f) - text_size.x -= character_spacing_x; + if (text_size.x > 0.0f) text_size.x -= character_spacing_x; text_size.x = (float)(int)(text_size.x + 0.95f); return text_size; } // Helper to calculate coarse clipping of large list of evenly sized items. -// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. -// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX -void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) +// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use +// this sort of pattern. NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX +void ImGui::CalcListClipping(int items_count, float items_height, int *out_items_display_start, int *out_items_display_end) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindowRead(); if (g.LogEnabled) { // If logging is active, do not perform any clipping *out_items_display_start = 0; - *out_items_display_end = items_count; + *out_items_display_end = items_count; return; } if (window->SkipItems) @@ -3074,34 +3199,33 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items return; } - const ImVec2 pos = window->DC.CursorPos; - int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); - int end = (int)((window->ClipRect.Max.y - pos.y) / items_height); - start = ImClamp(start, 0, items_count); - end = ImClamp(end + 1, start, items_count); + const ImVec2 pos = window->DC.CursorPos; + int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); + int end = (int)((window->ClipRect.Max.y - pos.y) / items_height); + start = ImClamp(start, 0, items_count); + end = ImClamp(end + 1, start, items_count); *out_items_display_start = start; - *out_items_display_end = end; + *out_items_display_end = end; } // Find window given position, search front-to-back -// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. -static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) +// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() +// and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before +// the next Begin(). Moving window thankfully isn't affected. +static ImGuiWindow *FindHoveredWindow(ImVec2 pos, bool excluding_childs) { - ImGuiContext& g = *GImGui; - for (int i = g.Windows.Size-1; i >= 0; i--) + ImGuiContext &g = *GImGui; + for (int i = g.Windows.Size - 1; i >= 0; i--) { - ImGuiWindow* window = g.Windows[i]; - if (!window->Active) - continue; - if (window->Flags & ImGuiWindowFlags_NoInputs) - continue; - if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0) - continue; + ImGuiWindow *window = g.Windows[i]; + if (!window->Active) continue; + if (window->Flags & ImGuiWindowFlags_NoInputs) continue; + if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0) continue; // Using the clipped AABB so a child window will typically be clipped by its parent. - ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding); - if (bb.Contains(pos)) - return window; + ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, + window->WindowRectClipped.Max + g.Style.TouchExtraPadding); + if (bb.Contains(pos)) return window; } return NULL; } @@ -3109,15 +3233,14 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) // Test if mouse cursor is hovering given rectangle // NB- Rectangle is clipped by our current clip setting // NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding) -bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip) +bool ImGui::IsMouseHoveringRect(const ImVec2 &r_min, const ImVec2 &r_max, bool clip) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindowRead(); // Clip ImRect rect_clipped(r_min, r_max); - if (clip) - rect_clipped.Clip(window->ClipRect); + if (clip) rect_clipped.Clip(window->ClipRect); // Expand for touch input const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); @@ -3126,17 +3249,17 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c bool ImGui::IsMouseHoveringWindow() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.HoveredWindow == g.CurrentWindow; } bool ImGui::IsMouseHoveringAnyWindow() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.HoveredWindow != NULL; } -bool ImGui::IsPosHoveringAnyWindow(const ImVec2& pos) +bool ImGui::IsPosHoveringAnyWindow(const ImVec2 &pos) { return FindHoveredWindow(pos, false) != NULL; } @@ -3162,52 +3285,47 @@ bool ImGui::IsKeyDown(int key_index) bool ImGui::IsKeyPressed(int key_index, bool repeat) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (key_index < 0) return false; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); const float t = g.IO.KeysDownDuration[key_index]; - if (t == 0.0f) - return true; + if (t == 0.0f) return true; if (repeat && t > g.IO.KeyRepeatDelay) { float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; - if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) - return true; + if ((fmodf(t - delay, rate) > rate * 0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate * 0.5f)) return true; } return false; } bool ImGui::IsKeyReleased(int key_index) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (key_index < 0) return false; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - if (g.IO.KeysDownDurationPrev[key_index] >= 0.0f && !g.IO.KeysDown[key_index]) - return true; + if (g.IO.KeysDownDurationPrev[key_index] >= 0.0f && !g.IO.KeysDown[key_index]) return true; return false; } bool ImGui::IsMouseDown(int button) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDown[button]; } bool ImGui::IsMouseClicked(int button, bool repeat) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); const float t = g.IO.MouseDownDuration[button]; - if (t == 0.0f) - return true; + if (t == 0.0f) return true; if (repeat && t > g.IO.KeyRepeatDelay) { float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; - if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) - return true; + if ((fmodf(t - delay, rate) > rate * 0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate * 0.5f)) return true; } return false; @@ -3215,26 +3333,24 @@ bool ImGui::IsMouseClicked(int button, bool repeat) bool ImGui::IsMouseReleased(int button) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseReleased[button]; } bool ImGui::IsMouseDoubleClicked(int button) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDoubleClicked[button]; } bool ImGui::IsMouseDragging(int button, float lock_threshold) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (!g.IO.MouseDown[button]) - return false; - if (lock_threshold < 0.0f) - lock_threshold = g.IO.MouseDragThreshold; + if (!g.IO.MouseDown[button]) return false; + if (lock_threshold < 0.0f) lock_threshold = g.IO.MouseDragThreshold; return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; } @@ -3246,27 +3362,26 @@ ImVec2 ImGui::GetMousePos() // NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() { - ImGuiContext& g = *GImGui; - if (g.CurrentPopupStack.Size > 0) - return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; + ImGuiContext &g = *GImGui; + if (g.CurrentPopupStack.Size > 0) return g.OpenPopupStack[g.CurrentPopupStack.Size - 1].MousePosOnOpen; return g.IO.MousePos; } ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (lock_threshold < 0.0f) - lock_threshold = g.IO.MouseDragThreshold; + if (lock_threshold < 0.0f) lock_threshold = g.IO.MouseDragThreshold; if (g.IO.MouseDown[button]) if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold) - return g.IO.MousePos - g.IO.MouseClickedPos[button]; // Assume we can only get active with left-mouse button (at the moment). + return g.IO.MousePos - + g.IO.MouseClickedPos[button]; // Assume we can only get active with left-mouse button (at the moment). return ImVec2(0.0f, 0.0f); } void ImGui::ResetMouseDragDelta(int button) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr g.IO.MouseClickedPos[button] = g.IO.MousePos; @@ -3294,22 +3409,22 @@ void ImGui::CaptureMouseFromApp(bool capture) bool ImGui::IsItemHovered() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.LastItemHoveredAndUsable; } bool ImGui::IsItemHoveredRect() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.LastItemHoveredRect; } bool ImGui::IsItemActive() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (g.ActiveId) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return g.ActiveId == window->DC.LastItemId; } return false; @@ -3332,55 +3447,55 @@ bool ImGui::IsAnyItemActive() bool ImGui::IsItemVisible() { - ImGuiWindow* window = GetCurrentWindowRead(); - ImRect r(window->ClipRect); + ImGuiWindow *window = GetCurrentWindowRead(); + ImRect r(window->ClipRect); return r.Overlaps(window->DC.LastItemRect); } -// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. +// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes +// priority. void ImGui::SetItemAllowOverlap() { - ImGuiContext& g = *GImGui; - if (g.HoveredId == g.CurrentWindow->DC.LastItemId) - g.HoveredIdAllowOverlap = true; - if (g.ActiveId == g.CurrentWindow->DC.LastItemId) - g.ActiveIdAllowOverlap = true; + ImGuiContext &g = *GImGui; + if (g.HoveredId == g.CurrentWindow->DC.LastItemId) g.HoveredIdAllowOverlap = true; + if (g.ActiveId == g.CurrentWindow->DC.LastItemId) g.ActiveIdAllowOverlap = true; } ImVec2 ImGui::GetItemRectMin() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.LastItemRect.Min; } ImVec2 ImGui::GetItemRectMax() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.LastItemRect.Max; } ImVec2 ImGui::GetItemRectSize() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.LastItemRect.GetSize(); } -ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, float outward) +ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2 &pos, bool on_edge, float outward) { - ImGuiWindow* window = GetCurrentWindowRead(); - ImRect rect = window->DC.LastItemRect; + ImGuiWindow *window = GetCurrentWindowRead(); + ImRect rect = window->DC.LastItemRect; rect.Expand(outward); return rect.GetClosestPoint(pos, on_edge); } -// Tooltip is stored and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous value. -void ImGui::SetTooltipV(const char* fmt, va_list args) +// Tooltip is stored and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous +// value. +void ImGui::SetTooltipV(const char *fmt, va_list args) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args); } -void ImGui::SetTooltip(const char* fmt, ...) +void ImGui::SetTooltip(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -3390,7 +3505,7 @@ void ImGui::SetTooltip(const char* fmt, ...) static ImRect GetVisibleRect() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y) return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax); return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); @@ -3398,52 +3513,55 @@ static ImRect GetVisibleRect() void ImGui::BeginTooltip() { - ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; + ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; ImGui::Begin("##Tooltip", NULL, flags); } void ImGui::EndTooltip() { - IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls + IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls ImGui::End(); } static bool IsPopupOpen(ImGuiID id) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == id; } // Mark popup as open (toggle toward open state). -// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. -// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). -// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) -void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetID(str_id); - int current_stack_size = g.CurrentPopupStack.Size; - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) +// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a +// BeginPopup()/EndPopup() block. Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be +// at the same level). One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of +// ImGuiPopupRef to NULL) +void ImGui::OpenPopupEx(const char *str_id, bool reopen_existing) +{ + ImGuiContext &g = *GImGui; + ImGuiWindow * window = g.CurrentWindow; + ImGuiID id = window->GetID(str_id); + int current_stack_size = g.CurrentPopupStack.Size; + ImGuiPopupRef popup_ref = ImGuiPopupRef( + id, window, window->GetID("##menus"), + g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) { - g.OpenPopupStack.resize(current_stack_size+1); + g.OpenPopupStack.resize(current_stack_size + 1); g.OpenPopupStack[current_stack_size] = popup_ref; } } -void ImGui::OpenPopup(const char* str_id) +void ImGui::OpenPopup(const char *str_id) { ImGui::OpenPopupEx(str_id, false); } static void CloseInactivePopups() { - ImGuiContext& g = *GImGui; - if (g.OpenPopupStack.empty()) - return; + ImGuiContext &g = *GImGui; + if (g.OpenPopupStack.empty()) return; // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. // Don't close our own child popup windows @@ -3452,39 +3570,35 @@ static void CloseInactivePopups() { for (n = 0; n < g.OpenPopupStack.Size; n++) { - ImGuiPopupRef& popup = g.OpenPopupStack[n]; - if (!popup.Window) - continue; + ImGuiPopupRef &popup = g.OpenPopupStack[n]; + if (!popup.Window) continue; IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); - if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) - continue; + if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) continue; bool has_focus = false; for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.FocusedWindow->RootWindow); - if (!has_focus) - break; + if (!has_focus) break; } } - if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a useful breakpoint on the line below + if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a useful breakpoint on the line below g.OpenPopupStack.resize(n); } -static ImGuiWindow* GetFrontMostModalRootWindow() +static ImGuiWindow *GetFrontMostModalRootWindow() { - ImGuiContext& g = *GImGui; - for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) - if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window) - if (front_most_popup->Flags & ImGuiWindowFlags_Modal) - return front_most_popup; + ImGuiContext &g = *GImGui; + for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--) + if (ImGuiWindow *front_most_popup = g.OpenPopupStack.Data[n].Window) + if (front_most_popup->Flags & ImGuiWindowFlags_Modal) return front_most_popup; return NULL; } static void ClosePopupToLevel(int remaining) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (remaining > 0) - ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window); + ImGui::FocusWindow(g.OpenPopupStack[remaining - 1].Window); else ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow); g.OpenPopupStack.resize(remaining); @@ -3492,36 +3606,37 @@ static void ClosePopupToLevel(int remaining) static void ClosePopup(ImGuiID id) { - if (!IsPopupOpen(id)) - return; - ImGuiContext& g = *GImGui; + if (!IsPopupOpen(id)) return; + ImGuiContext &g = *GImGui; ClosePopupToLevel(g.OpenPopupStack.Size - 1); } // Close the popup we have begin-ed into. void ImGui::CloseCurrentPopup() { - ImGuiContext& g = *GImGui; - int popup_idx = g.CurrentPopupStack.Size - 1; - if (popup_idx < 0 || popup_idx > g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) + ImGuiContext &g = *GImGui; + int popup_idx = g.CurrentPopupStack.Size - 1; + if (popup_idx < 0 || popup_idx > g.OpenPopupStack.Size || + g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) return; - while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) + while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && + (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) popup_idx--; ClosePopupToLevel(popup_idx); } static inline void ClearSetNextWindowData() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0; g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false; } -static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) +static bool BeginPopupEx(const char *str_id, ImGuiWindowFlags extra_flags) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiID id = window->GetID(str_id); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = g.CurrentWindow; + const ImGuiID id = window->GetID(str_id); if (!IsPopupOpen(id)) { ClearSetNextWindowData(); // We behave like Begin() and need to consume those values @@ -3529,26 +3644,26 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) } ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; + ImGuiWindowFlags flags = extra_flags | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; char name[20]; if (flags & ImGuiWindowFlags_ChildMenu) - ImFormatString(name, IM_ARRAYSIZE(name), "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth + ImFormatString(name, IM_ARRAYSIZE(name), "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, IM_ARRAYSIZE(name), "##popup_%08x", id); // Not recycling, so we can close/open during the same frame bool is_open = ImGui::Begin(name, NULL, flags); - if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; + if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; if (!is_open) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) ImGui::EndPopup(); return is_open; } -bool ImGui::BeginPopup(const char* str_id) +bool ImGui::BeginPopup(const char *str_id) { - if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance + if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance { ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; @@ -3556,24 +3671,25 @@ bool ImGui::BeginPopup(const char* str_id) return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders); } -bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags) +bool ImGui::BeginPopupModal(const char *name, bool *p_open, ImGuiWindowFlags extra_flags) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiID id = window->GetID(name); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = g.CurrentWindow; + const ImGuiID id = window->GetID(name); if (!IsPopupOpen(id)) { ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; } - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; + ImGuiWindowFlags flags = extra_flags | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoSavedSettings; bool is_open = ImGui::Begin(name, p_open, flags); - if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + if (!is_open || + (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); - if (is_open) - ClosePopup(id); + if (is_open) ClosePopup(id); return false; } @@ -3582,67 +3698,65 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext void ImGui::EndPopup() { - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls + ImGuiWindow *window = GetCurrentWindow(); + IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls IM_ASSERT(GImGui->CurrentPopupStack.Size > 0); ImGui::End(); - if (!(window->Flags & ImGuiWindowFlags_Modal)) - ImGui::PopStyleVar(); + if (!(window->Flags & ImGuiWindowFlags_Modal)) ImGui::PopStyleVar(); } // This is a helper to handle the most simple case of associating one named popup to one given widget. -// 1. If you have many possible popups (for different "instances" of a same widget, or for wholly different widgets), you may be better off handling -// this yourself so you can store data relative to the widget that opened the popup instead of choosing different popup identifiers. -// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() with IsItemHoveredRect() +// 1. If you have many possible popups (for different "instances" of a same widget, or for wholly different widgets), you may be +// better off handling +// this yourself so you can store data relative to the widget that opened the popup instead of choosing different popup +// identifiers. +// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() +// with IsItemHoveredRect() // and passing true to the OpenPopupEx(). -// Because: hovering an item in a window below the popup won't normally trigger is hovering behavior/coloring. The pattern of ignoring the fact that -// the item isn't interactable (because it is blocked by the active popup) may useful in some situation when e.g. large canvas as one item, content of menu -// driven by click position. -bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) +// Because: hovering an item in a window below the popup won't normally trigger is hovering behavior/coloring. The pattern of +// ignoring the fact that the item isn't interactable (because it is blocked by the active popup) may useful in some situation +// when e.g. large canvas as one item, content of menu driven by click position. +bool ImGui::BeginPopupContextItem(const char *str_id, int mouse_button) { - if (IsItemHovered() && IsMouseClicked(mouse_button)) - OpenPopupEx(str_id, false); + if (IsItemHovered() && IsMouseClicked(mouse_button)) OpenPopupEx(str_id, false); return BeginPopup(str_id); } -bool ImGui::BeginPopupContextWindow(bool also_over_items, const char* str_id, int mouse_button) +bool ImGui::BeginPopupContextWindow(bool also_over_items, const char *str_id, int mouse_button) { if (!str_id) str_id = "window_context_menu"; if (IsMouseHoveringWindow() && IsMouseClicked(mouse_button)) - if (also_over_items || !IsAnyItemHovered()) - OpenPopupEx(str_id, true); + if (also_over_items || !IsAnyItemHovered()) OpenPopupEx(str_id, true); return BeginPopup(str_id); } -bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) +bool ImGui::BeginPopupContextVoid(const char *str_id, int mouse_button) { if (!str_id) str_id = "void_context_menu"; - if (!IsMouseHoveringAnyWindow() && IsMouseClicked(mouse_button)) - OpenPopupEx(str_id, true); + if (!IsMouseHoveringAnyWindow() && IsMouseClicked(mouse_button)) OpenPopupEx(str_id, true); return BeginPopup(str_id); } -static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) +static bool BeginChildEx(const char *name, ImGuiID id, const ImVec2 &size_arg, bool border, ImGuiWindowFlags extra_flags) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); - ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; + ImGuiWindow * window = ImGui::GetCurrentWindow(); + ImGuiWindowFlags flags = + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow; const ImVec2 content_avail = ImGui::GetContentRegionAvail(); - ImVec2 size = ImFloor(size_arg); + ImVec2 size = ImFloor(size_arg); if (size.x <= 0.0f) { - if (size.x == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitX; - size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) + if (size.x == 0.0f) flags |= ImGuiWindowFlags_ChildWindowAutoFitX; + size.x = ImMax(content_avail.x, 4.0f) - + fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) } if (size.y <= 0.0f) { - if (size.y == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitY; + if (size.y == 0.0f) flags |= ImGuiWindowFlags_ChildWindowAutoFitY; size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y); } - if (border) - flags |= ImGuiWindowFlags_ShowBorders; + if (border) flags |= ImGuiWindowFlags_ShowBorders; flags |= extra_flags; char title[256]; @@ -3653,40 +3767,37 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); - if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - ImGui::GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; + if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) ImGui::GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; return ret; } -bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) +bool ImGui::BeginChild(const char *str_id, const ImVec2 &size_arg, bool border, ImGuiWindowFlags extra_flags) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags); } -bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) +bool ImGui::BeginChild(ImGuiID id, const ImVec2 &size_arg, bool border, ImGuiWindowFlags extra_flags) { return BeginChildEx(NULL, id, size_arg, border, extra_flags); } void ImGui::EndChild() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); - IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss - if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1) - { - ImGui::End(); - } + IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss + if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1) { ImGui::End(); } else { - // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting. + // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into + // automatic size-fitting. ImVec2 sz = GetWindowSize(); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f + if (window->Flags & + ImGuiWindowFlags_ChildWindowAutoFitX) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f sz.x = ImMax(4.0f, sz.x); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) - sz.y = ImMax(4.0f, sz.y); + if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) sz.y = ImMax(4.0f, sz.y); ImGui::End(); @@ -3698,14 +3809,15 @@ void ImGui::EndChild() } // Helper to create a child window / scrolling region that looks like a normal widget frame. -bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags) +bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2 &size, ImGuiWindowFlags extra_flags) { - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); - return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); + return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); } void ImGui::EndChildFrame() @@ -3716,65 +3828,110 @@ void ImGui::EndChildFrame() } // Save and compare stack sizes on Begin()/End() to detect usage errors -static void CheckStacksSize(ImGuiWindow* window, bool write) -{ - // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) - ImGuiContext& g = *GImGui; - int* p_backup = &window->DC.StackSizesBackup[0]; - { int current = window->IDStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop() - { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup() - { int current = g.CurrentPopupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup() - { int current = g.ColorModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // Too few or too many PopStyleColor() - { int current = g.StyleModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // Too few or too many PopStyleVar() - { int current = g.FontStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushFont/PopFont Mismatch!"); p_backup++; } // Too few or too many PopFont() +static void CheckStacksSize(ImGuiWindow *window, bool write) +{ + // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to + // conveniently push once and not pop (they are cleared on Begin) + ImGuiContext &g = *GImGui; + int * p_backup = &window->DC.StackSizesBackup[0]; + { + int current = window->IDStack.Size; + if (write) + *p_backup = current; + else + IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); + p_backup++; + } // Too few or too many PopID()/TreePop() + { + int current = window->DC.GroupStack.Size; + if (write) + *p_backup = current; + else + IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); + p_backup++; + } // Too few or too many EndGroup() + { + int current = g.CurrentPopupStack.Size; + if (write) + *p_backup = current; + else + IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); + p_backup++; + } // Too few or too many EndMenu()/EndPopup() + { + int current = g.ColorModifiers.Size; + if (write) + *p_backup = current; + else + IM_ASSERT(*p_backup == current && "PushStyleColor/PopStyleColor Mismatch!"); + p_backup++; + } // Too few or too many PopStyleColor() + { + int current = g.StyleModifiers.Size; + if (write) + *p_backup = current; + else + IM_ASSERT(*p_backup == current && "PushStyleVar/PopStyleVar Mismatch!"); + p_backup++; + } // Too few or too many PopStyleVar() + { + int current = g.FontStack.Size; + if (write) + *p_backup = current; + else + IM_ASSERT(*p_backup == current && "PushFont/PopFont Mismatch!"); + p_backup++; + } // Too few or too many PopFont() IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); } -static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& r_inner) +static ImVec2 FindBestPopupWindowPos(const ImVec2 &base_pos, const ImVec2 &size, int *last_dir, const ImRect &r_inner) { - const ImGuiStyle& style = GImGui->Style; + const ImGuiStyle &style = GImGui->Style; - // Clamp into visible area while not overlapping the cursor. Safety padding is optional if our popup size won't fit without it. + // Clamp into visible area while not overlapping the cursor. Safety padding is optional if our popup size won't fit without + // it. ImVec2 safe_padding = style.DisplaySafeAreaPadding; ImRect r_outer(GetVisibleRect()); - r_outer.Reduce(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? safe_padding.y : 0.0f)); + r_outer.Reduce(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x * 2) ? safe_padding.x : 0.0f, + (size.y - r_outer.GetHeight() > safe_padding.y * 2) ? safe_padding.y : 0.0f)); ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size); - for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++) // Last, Right, down, up, left. (Favor last used direction). + for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++) // Last, Right, down, up, left. (Favor last used direction). { const int dir = (n == -1) ? *last_dir : n; - ImRect rect(dir == 0 ? r_inner.Max.x : r_outer.Min.x, dir == 1 ? r_inner.Max.y : r_outer.Min.y, dir == 3 ? r_inner.Min.x : r_outer.Max.x, dir == 2 ? r_inner.Min.y : r_outer.Max.y); - if (rect.GetWidth() < size.x || rect.GetHeight() < size.y) - continue; + ImRect rect(dir == 0 ? r_inner.Max.x : r_outer.Min.x, dir == 1 ? r_inner.Max.y : r_outer.Min.y, + dir == 3 ? r_inner.Min.x : r_outer.Max.x, dir == 2 ? r_inner.Min.y : r_outer.Max.y); + if (rect.GetWidth() < size.x || rect.GetHeight() < size.y) continue; *last_dir = dir; - return ImVec2(dir == 0 ? r_inner.Max.x : dir == 3 ? r_inner.Min.x - size.x : base_pos_clamped.x, dir == 1 ? r_inner.Max.y : dir == 2 ? r_inner.Min.y - size.y : base_pos_clamped.y); + return ImVec2(dir == 0 ? r_inner.Max.x : dir == 3 ? r_inner.Min.x - size.x : base_pos_clamped.x, + dir == 1 ? r_inner.Max.y : dir == 2 ? r_inner.Min.y - size.y : base_pos_clamped.y); } // Fallback, try to keep within display - *last_dir = -1; + *last_dir = -1; ImVec2 pos = base_pos; - pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); - pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); + pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); + pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); return pos; } -ImGuiWindow* ImGui::FindWindowByName(const char* name) +ImGuiWindow *ImGui::FindWindowByName(const char *name) { // FIXME-OPT: Store sorted hashes -> pointers so we can do a bissection in a contiguous block - ImGuiContext& g = *GImGui; - ImGuiID id = ImHash(name, 0); + ImGuiContext &g = *GImGui; + ImGuiID id = ImHash(name, 0); for (int i = 0; i < g.Windows.Size; i++) - if (g.Windows[i]->ID == id) - return g.Windows[i]; + if (g.Windows[i]->ID == id) return g.Windows[i]; return NULL; } -static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags) +static ImGuiWindow *CreateNewWindow(const char *name, ImVec2 size, ImGuiWindowFlags flags) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; // Create window the first time - ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow)); + ImGuiWindow *window = (ImGuiWindow *)ImGui::MemAlloc(sizeof(ImGuiWindow)); IM_PLACEMENT_NEW(window) ImGuiWindow(name); window->Flags = flags; @@ -3786,15 +3943,13 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl else { // Retrieve settings from .ini file - // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. + // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a + // window. window->PosFloat = ImVec2(60, 60); - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); - ImGuiIniData* settings = FindWindowSettings(name); - if (!settings) - { - settings = AddWindowSettings(name); - } + ImGuiIniData *settings = FindWindowSettings(name); + if (!settings) { settings = AddWindowSettings(name); } else { window->SetWindowPosAllowFlags &= ~ImGuiSetCond_FirstUseEver; @@ -3804,27 +3959,24 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl if (settings->Pos.x != FLT_MAX) { - window->PosFloat = settings->Pos; - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->PosFloat = settings->Pos; + window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); window->Collapsed = settings->Collapsed; } - if (ImLengthSqr(settings->Size) > 0.00001f && !(flags & ImGuiWindowFlags_NoResize)) - size = settings->Size; + if (ImLengthSqr(settings->Size) > 0.00001f && !(flags & ImGuiWindowFlags_NoResize)) size = settings->Size; window->Size = window->SizeFull = size; } if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) { window->AutoFitFramesX = window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = false; + window->AutoFitOnlyGrows = false; } else { - if (window->Size.x <= 0.0f) - window->AutoFitFramesX = 2; - if (window->Size.y <= 0.0f) - window->AutoFitFramesY = 2; + if (window->Size.x <= 0.0f) window->AutoFitFramesX = 2; + if (window->Size.y <= 0.0f) window->AutoFitFramesY = 2; window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); } @@ -3835,20 +3987,20 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl return window; } -static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size) +static void ApplySizeFullWithConstraint(ImGuiWindow *window, ImVec2 new_size) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (g.SetNextWindowSizeConstraint) { // Using -1,-1 on either X/Y axis to preserve the current size. - ImRect cr = g.SetNextWindowSizeConstraintRect; + ImRect cr = g.SetNextWindowSizeConstraintRect; new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; if (g.SetNextWindowSizeConstraintCallback) { ImGuiSizeConstraintCallbackData data; - data.UserData = g.SetNextWindowSizeConstraintCallbackUserData; - data.Pos = window->Pos; + data.UserData = g.SetNextWindowSizeConstraintCallbackUserData; + data.Pos = window->Pos; data.CurrentSize = window->SizeFull; data.DesiredSize = new_size; g.SetNextWindowSizeConstraintCallback(&data); @@ -3861,40 +4013,47 @@ static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size) } // Push a new ImGui window to add widgets to. -// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. +// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without +// explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. -// - 'size_on_first_use' for a regular window denote the initial size for first-time creation (no saved data) and isn't that useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation. -// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). -// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. -// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. -// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. -// - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiSetCond_FirstUseEver) prior to calling Begin(). -bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) +// - 'size_on_first_use' for a regular window denote the initial size for first-time creation (no saved data) and isn't that +// useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation. +// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information +// to the .ini file). +// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See +// documentation at the top of this file. +// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false +// is returned. +// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to +// false when the button is pressed. +// - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiSetCond_FirstUseEver) prior to calling +// Begin(). +bool ImGui::Begin(const char *name, bool *p_open, ImGuiWindowFlags flags) { return ImGui::Begin(name, p_open, ImVec2(0.f, 0.f), -1.0f, flags); } -bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) +bool ImGui::Begin(const char *name, bool *p_open, const ImVec2 &size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) { - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - IM_ASSERT(name != NULL); // Window name required - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() - IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + IM_ASSERT(name != NULL); // Window name required + IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.FrameCountEnded != + g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet - if (flags & ImGuiWindowFlags_NoInputs) - flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; + if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; // Find or create - bool window_is_new = false; - ImGuiWindow* window = FindWindowByName(name); + bool window_is_new = false; + ImGuiWindow *window = FindWindowByName(name); if (!window) { - window = CreateNewWindow(name, size_on_first_use, flags); + window = CreateNewWindow(name, size_on_first_use, flags); window_is_new = true; } - const int current_frame = ImGui::GetFrameCount(); + const int current_frame = ImGui::GetFrameCount(); const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); if (first_begin_of_the_frame) window->Flags = (ImGuiWindowFlags)flags; @@ -3902,16 +4061,18 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us flags = window->Flags; // Add to stack - ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL; + ImGuiWindow *parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL; g.CurrentWindowStack.push_back(window); SetCurrentWindow(window); CheckStacksSize(window, true); IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - bool window_was_active = (window->LastFrameActive == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + bool window_was_active = + (window->LastFrameActive == + current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) { - ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; + ImGuiPopupRef &popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; window_was_active &= (window->PopupId == popup_ref.PopupId); window_was_active &= (window == popup_ref.Window); popup_ref.Window = window; @@ -3925,19 +4086,21 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bool window_pos_set_by_api = false, window_size_set_by_api = false; if (g.SetNextWindowPosCond) { - const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that. + const ImVec2 backup_cursor_pos = + window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that. if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; - if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) + if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX, -FLT_MAX)) < 0.001f) { - window->SetWindowPosCenterWanted = true; // May be processed on the next frame if this is our first frame and we are measuring size + window->SetWindowPosCenterWanted = + true; // May be processed on the next frame if this is our first frame and we are measuring size window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); } else { SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond); } - window->DC.CursorPos = backup_cursor_pos; + window->DC.CursorPos = backup_cursor_pos; g.SetNextWindowPosCond = 0; } if (g.SetNextWindowSizeCond) @@ -3949,7 +4112,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } if (g.SetNextWindowContentSizeCond) { - window->SizeContentsExplicit = g.SetNextWindowContentSizeVal; + window->SizeContentsExplicit = g.SetNextWindowContentSizeVal; g.SetNextWindowContentSizeCond = 0; } else if (first_begin_of_the_frame) @@ -3958,7 +4121,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } if (g.SetNextWindowCollapsedCond) { - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing; + if (!window_was_active || window_appearing_after_being_hidden) + window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing; SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); g.SetNextWindowCollapsedCond = 0; } @@ -3971,30 +4135,29 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Update known root window (if we are a child window, otherwise window == window->RootWindow) int root_idx, root_non_popup_idx; for (root_idx = g.CurrentWindowStack.Size - 1; root_idx > 0; root_idx--) - if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow)) - break; + if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow)) break; for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--) - if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) - break; + if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) break; window->ParentWindow = parent_window; - window->RootWindow = g.CurrentWindowStack[root_idx]; - window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. + window->RootWindow = g.CurrentWindowStack[root_idx]; + window->RootNonPopupWindow = + g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { - window->Active = true; + window->Active = true; window->IndexWithinParent = 0; - window->BeginCount = 0; - window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); - window->LastFrameActive = current_frame; + window->BeginCount = 0; + window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX); + window->LastFrameActive = current_frame; window->IDStack.resize(1); // Clear draw list, setup texture, outer clipping rectangle window->DrawList->Clear(); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); ImRect fullscreen_rect(GetVisibleRect()); - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup))) + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); else PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); @@ -4003,20 +4166,20 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = -1; - if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.IO.MousePos; + if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) window->PosFloat = g.IO.MousePos; } // Collapse window by double-clicking on title bar - // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing + // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and + // drawing if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) { ImRect title_bar_rect = window->TitleBarRect(); - if (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) + if (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && + g.IO.MouseDoubleClicked[0]) { window->Collapsed = !window->Collapsed; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkIniSettingsDirty(); FocusWindow(window); } } @@ -4028,25 +4191,33 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // SIZE // Save contents size from last frame for auto-fitting (unless explicitly specified) - window->SizeContents.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x)); - window->SizeContents.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y)); + window->SizeContents.x = + (float)(int)((window->SizeContentsExplicit.x != 0.0f) + ? window->SizeContentsExplicit.x + : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x)); + window->SizeContents.y = + (float)(int)((window->SizeContentsExplicit.y != 0.0f) + ? window->SizeContentsExplicit.y + : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y)); // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) - if (window->HiddenFrames > 0) - window->HiddenFrames--; + if (window->HiddenFrames > 0) window->HiddenFrames--; if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_active) { window->HiddenFrames = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) { - if (!window_size_set_by_api) - window->Size = window->SizeFull = ImVec2(0.f, 0.f); + if (!window_size_set_by_api) window->Size = window->SizeFull = ImVec2(0.f, 0.f); window->SizeContents = ImVec2(0.f, 0.f); } } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && + !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | + ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) + ? ImVec2(0, 0) + : style.WindowPadding; // Calculate auto-fit size ImVec2 size_auto_fit; @@ -4057,10 +4228,13 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } else { - size_auto_fit = ImClamp(window->SizeContents + window->WindowPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding)); + size_auto_fit = ImClamp(window->SizeContents + window->WindowPadding, style.WindowMinSize, + ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding)); - // Handling case of auto fit window not fitting in screen on one axis, we are growing auto fit size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding. - if (size_auto_fit.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)) + // Handling case of auto fit window not fitting in screen on one axis, we are growing auto fit size on the other axis + // to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding. + if (size_auto_fit.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && + (flags & ImGuiWindowFlags_HorizontalScrollbar)) size_auto_fit.y += style.ScrollbarSize; if (size_auto_fit.y < window->SizeContents.y && !(flags & ImGuiWindowFlags_NoScrollbar)) size_auto_fit.x += style.ScrollbarSize; @@ -4079,10 +4253,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } else { - if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window_size_set_by_api) - { - window->SizeFull = size_auto_fit; - } + if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window_size_set_by_api) { window->SizeFull = size_auto_fit; } else if ((window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) && !window_size_set_by_api) { // Auto-fit only grows during the first few frames @@ -4090,15 +4261,14 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; if (window->AutoFitFramesY > 0) window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkIniSettingsDirty(); } } // Apply minimum/maximum window size constraints and final size ApplySizeFullWithConstraint(window, window->SizeFull); window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; - + // POSITION // Position child window @@ -4110,7 +4280,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) { window->Pos = window->PosFloat = parent_window->DC.CursorPos; - window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin(). + window->Size = window->SizeFull = + size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided + // by user passed via BeginChild()->Begin(). } bool window_pos_center = false; @@ -4123,38 +4295,54 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } else if (flags & ImGuiWindowFlags_ChildMenu) { - // Child menus typically request _any_ position within the parent menu item, and then our FindBestPopupWindowPos() function will move the new menu outside the parent bounds. - // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. + // Child menus typically request _any_ position within the parent menu item, and then our FindBestPopupWindowPos() + // function will move the new menu outside the parent bounds. This is how we end up with child menus appearing + // (most-commonly) on the right of the parent menu. IM_ASSERT(window_pos_set_by_api); - float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value). + float horizontal_overlap = + style.ItemSpacing + .x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is + // hard-coded to style.ItemSpacing.x, may need to introduce another style value). ImRect rect_to_avoid; if (parent_window->DC.MenuBarAppending) - rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); + rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, + parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); else - rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); - window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); + rect_to_avoid = ImRect( + parent_window->Pos.x + horizontal_overlap, -FLT_MAX, + parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); + window->PosFloat = + FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); } else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_appearing_after_being_hidden) { ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); - window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); + window->PosFloat = + FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); } // Position tooltip (always follows mouse) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) { - ImRect rect_to_avoid(g.IO.MousePos.x - 16, g.IO.MousePos.y - 8, g.IO.MousePos.x + 24, g.IO.MousePos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? + ImRect rect_to_avoid(g.IO.MousePos.x - 16, g.IO.MousePos.y - 8, g.IO.MousePos.x + 24, + g.IO.MousePos.y + + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? window->PosFloat = FindBestPopupWindowPos(g.IO.MousePos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == -1) - window->PosFloat = g.IO.MousePos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. + window->PosFloat = + g.IO.MousePos + ImVec2(2, 2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all + // cost even if it means that part of the tooltip won't be visible. } // Clamp position so it stays visible if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) { - if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. + if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && + g.IO.DisplaySize.x > 0.0f && + g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager + // reports zero-sized window when initializing or minimizing. { - ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); + ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); window->PosFloat = ImMax(window->PosFloat + window->Size, padding) - window->Size; window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding); } @@ -4168,80 +4356,97 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); // Prepare for focus requests - window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1); - window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1); + window->FocusIdxAllRequestCurrent = + (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) + ? INT_MAX + : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter + 1)) % (window->FocusIdxAllCounter + 1); + window->FocusIdxTabRequestCurrent = + (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) + ? INT_MAX + : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter + 1)) % (window->FocusIdxTabCounter + 1); window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1; window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX; // Apply scrolling if (window->ScrollTarget.x < FLT_MAX) { - window->Scroll.x = window->ScrollTarget.x; + window->Scroll.x = window->ScrollTarget.x; window->ScrollTarget.x = FLT_MAX; } if (window->ScrollTarget.y < FLT_MAX) { float center_ratio = window->ScrollTargetCenterRatio.y; - window->Scroll.y = window->ScrollTarget.y - ((1.0f - center_ratio) * (window->TitleBarHeight() + window->MenuBarHeight())) - (center_ratio * window->SizeFull.y); + window->Scroll.y = window->ScrollTarget.y - + ((1.0f - center_ratio) * (window->TitleBarHeight() + window->MenuBarHeight())) - + (center_ratio * window->SizeFull.y); window->ScrollTarget.y = FLT_MAX; } window->Scroll = ImMax(window->Scroll, ImVec2(0.0f, 0.0f)); if (!window->Collapsed && !window->SkipItems) - window->Scroll = ImMin(window->Scroll, ImMax(ImVec2(0.0f, 0.0f), window->SizeContents - window->SizeFull + window->ScrollbarSizes)); + window->Scroll = ImMin(window->Scroll, + ImMax(ImVec2(0.0f, 0.0f), window->SizeContents - window->SizeFull + window->ScrollbarSizes)); // Modal window darkens what is behind them if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) - window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, + GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); // Draw window + handle manual resize - ImRect title_bar_rect = window->TitleBarRect(); + ImRect title_bar_rect = window->TitleBarRect(); const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; if (window->Collapsed) { // Draw title bar only - RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); + RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, + window_rounding); } else { - ImU32 resize_col = 0; + ImU32 resize_col = 0; const float resize_corner_size = ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) + if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && + !(flags & ImGuiWindowFlags_NoResize)) { // Manual resize - const ImVec2 br = window->Rect().GetBR(); - const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); + const ImVec2 br = window->Rect().GetBR(); + const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); const ImGuiID resize_id = window->GetID("#RESIZE"); - bool hovered, held; + bool hovered, held; ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds); - resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); + resize_col = + GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; + if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) { // Manual auto-fit when double-clicking ApplySizeFullWithConstraint(window, size_auto_fit); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkIniSettingsDirty(); ClearActiveID(); } else if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + ApplySizeFullWithConstraint(window, + (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); + if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkIniSettingsDirty(); } - window->Size = window->SizeFull; + window->Size = window->SizeFull; title_bar_rect = window->TitleBarRect(); } // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); - window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); + window->ScrollbarY = + (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || + ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || + ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - + window->WindowPadding.x) && + !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarSizes = + ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background, Default Alpha @@ -4253,15 +4458,22 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) bg_color_idx = ImGuiCol_ChildWindowBg; ImVec4 bg_color = style.Colors[bg_color_idx]; - if (bg_alpha >= 0.0f) - bg_color.w = bg_alpha; + if (bg_alpha >= 0.0f) bg_color.w = bg_alpha; bg_color.w *= style.Alpha; if (bg_color.w > 0.0f) - window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BottomLeft|ImGuiCorner_BottomRight); + window->DrawList->AddRectFilled( + window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, + ColorConvertFloat4ToU32(bg_color), window_rounding, + (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BottomLeft | ImGuiCorner_BottomRight); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); + window->DrawList->AddRectFilled( + title_bar_rect.GetTL(), title_bar_rect.GetBR(), + GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) + ? ImGuiCol_TitleBgActive + : ImGuiCol_TitleBg), + window_rounding, ImGuiCorner_TopLeft | ImGuiCorner_TopRight); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) @@ -4269,14 +4481,14 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us ImRect menu_bar_rect = window->MenuBarRect(); if (flags & ImGuiWindowFlags_ShowBorders) window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border)); - window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); + window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), + (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, + ImGuiCorner_TopLeft | ImGuiCorner_TopRight); } // Scrollbars - if (window->ScrollbarX) - Scrollbar(window, true); - if (window->ScrollbarY) - Scrollbar(window, false); + if (window->ScrollbarX) Scrollbar(window, true); + if (window->ScrollbarY) Scrollbar(window, false); // Render resize grip // (after the input handling so we don't have a frame of latency) @@ -4285,67 +4497,77 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const ImVec2 br = window->Rect().GetBR(); window->DrawList->PathLineTo(br + ImVec2(-resize_corner_size, -window->BorderSize)); window->DrawList->PathLineTo(br + ImVec2(-window->BorderSize, -resize_corner_size)); - window->DrawList->PathArcToFast(ImVec2(br.x - window_rounding - window->BorderSize, br.y - window_rounding - window->BorderSize), window_rounding, 0, 3); + window->DrawList->PathArcToFast( + ImVec2(br.x - window_rounding - window->BorderSize, br.y - window_rounding - window->BorderSize), + window_rounding, 0, 3); window->DrawList->PathFillConvex(resize_col); } // Borders if (flags & ImGuiWindowFlags_ShowBorders) { - window->DrawList->AddRect(window->Pos+ImVec2(1,1), window->Pos+window->Size+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), window_rounding); - window->DrawList->AddRect(window->Pos, window->Pos+window->Size, GetColorU32(ImGuiCol_Border), window_rounding); + window->DrawList->AddRect(window->Pos + ImVec2(1, 1), window->Pos + window->Size + ImVec2(1, 1), + GetColorU32(ImGuiCol_BorderShadow), window_rounding); + window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), window_rounding); if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddLine(title_bar_rect.GetBL()+ImVec2(1,0), title_bar_rect.GetBR()-ImVec2(1,0), GetColorU32(ImGuiCol_Border)); + window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(1, 0), title_bar_rect.GetBR() - ImVec2(1, 0), + GetColorU32(ImGuiCol_Border)); } } // Update ContentsRegionMax. All the variable it depends on are set above in this function. window->ContentsRegionRect.Min.x = -window->Scroll.x + window->WindowPadding.x; - window->ContentsRegionRect.Min.y = -window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); - window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x)); - window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y)); + window->ContentsRegionRect.Min.y = + -window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); + window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x + : (window->Size.x - window->ScrollbarSizes.x)); + window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y + : (window->Size.y - window->ScrollbarSizes.y)); // Setup drawing context - window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; - window->DC.GroupOffsetX = 0.0f; + window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; + window->DC.GroupOffsetX = 0.0f; window->DC.ColumnsOffsetX = 0.0f; - window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y); - window->DC.CursorPos = window->DC.CursorStartPos; + window->DC.CursorStartPos = + window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, + window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y); + window->DC.CursorPos = window->DC.CursorStartPos; window->DC.CursorPosPrevLine = window->DC.CursorPos; - window->DC.CursorMaxPos = window->DC.CursorStartPos; + window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; - window->DC.MenuBarAppending = false; + window->DC.MenuBarAppending = false; window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x); - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; window->DC.ChildWindows.resize(0); - window->DC.LayoutType = ImGuiLayoutType_Vertical; - window->DC.ItemWidth = window->ItemWidthDefault; - window->DC.TextWrapPos = -1.0f; // disabled + window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.ItemWidth = window->ItemWidthDefault; + window->DC.TextWrapPos = -1.0f; // disabled window->DC.AllowKeyboardFocus = true; - window->DC.ButtonRepeat = false; + window->DC.ButtonRepeat = false; window->DC.ItemWidthStack.resize(0); window->DC.AllowKeyboardFocusStack.resize(0); window->DC.ButtonRepeatStack.resize(0); window->DC.TextWrapPosStack.resize(0); - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; + window->DC.ColumnsCurrent = 0; + window->DC.ColumnsCount = 1; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY; - window->DC.TreeDepth = 0; - window->DC.StateStorage = &window->StateStorage; + window->DC.TreeDepth = 0; + window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); window->DC.ColorEditMode = ImGuiColorEditMode_UserSelect; window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_active); - if (window->AutoFitFramesX > 0) - window->AutoFitFramesX--; - if (window->AutoFitFramesY > 0) - window->AutoFitFramesY--; + if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; + if (window->AutoFitFramesY > 0) window->AutoFitFramesY--; - // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) + // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference + // rectangle can start around there) if (!window_was_active && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) - if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) + if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) FocusWindow(window); // Title bar @@ -4354,7 +4576,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (p_open != NULL) { const float pad = 2.0f; - const float rad = (window->TitleBarHeight() - pad*2.0f) * 0.5f; + const float rad = (window->TitleBarHeight() - pad * 2.0f) * 0.5f; if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad)) *p_open = false; } @@ -4364,11 +4586,16 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f); ImVec2 text_min = window->Pos; - ImVec2 text_max = window->Pos + ImVec2(window->Size.x, style.FramePadding.y*2 + text_size.y); + ImVec2 text_max = window->Pos + ImVec2(window->Size.x, style.FramePadding.y * 2 + text_size.y); ImRect clip_rect; - clip_rect.Max = ImVec2(window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton() - float pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0 ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; - float pad_right = (p_open != NULL) ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; + clip_rect.Max = + ImVec2(window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), + text_max.y); // Match the size of CloseWindowButton() + float pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0 + ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) + : style.FramePadding.x; + float pad_right = + (p_open != NULL) ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; if (style.WindowTitleAlign.x > 0.0f) pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x); text_min.x += pad_left; text_max.x -= pad_right; @@ -4381,8 +4608,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->WindowRectClipped.Clip(window->ClipRect); // Pressing CTRL+C while holding on a window copy its content to the clipboard - // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. - // Maybe we can support CTRL+C on every element? + // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to + // work that out and add better logging scope. Maybe we can support CTRL+C on every element? /* if (g.ActiveId == move_id) if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) @@ -4394,17 +4621,17 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); - const float border_size = window->BorderSize; - ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. - clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + const float border_size = window->BorderSize; + ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x * 0.5f))); clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size); - clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - + ImMax(border_size, ImFloor(window->WindowPadding.x * 0.5f))); clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size); PushClipRect(clip_rect.Min, clip_rect.Max, true); // Clear 'accessed' flag last thing - if (first_begin_of_the_frame) - window->Accessed = false; + if (first_begin_of_the_frame) window->Accessed = false; window->BeginCount++; g.SetNextWindowSizeConstraint = false; @@ -4416,15 +4643,14 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->Collapsed = parent_window && parent_window->Collapsed; if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - window->Collapsed |= (window->WindowRectClipped.Min.x >= window->WindowRectClipped.Max.x || window->WindowRectClipped.Min.y >= window->WindowRectClipped.Max.y); + window->Collapsed |= (window->WindowRectClipped.Min.x >= window->WindowRectClipped.Max.x || + window->WindowRectClipped.Min.y >= window->WindowRectClipped.Max.y); // We also hide the window from rendering because we've already added its border to the command list. // (we could perform the check earlier in the function but it is simpler at this point) - if (window->Collapsed) - window->Active = false; + if (window->Collapsed) window->Active = false; } - if (style.Alpha <= 0.0f) - window->Active = false; + if (style.Alpha <= 0.0f) window->Active = false; // Return false if we don't intend to display anything to allow user to perform an early out optimization window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0; @@ -4433,84 +4659,93 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us void ImGui::End() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + ImGuiContext &g = *GImGui; + ImGuiWindow * window = g.CurrentWindow; if (window->DC.ColumnsCount != 1) // close columns set if any is open Columns(1, "#CLOSECOLUMNS"); - PopClipRect(); // inner window clip rectangle + PopClipRect(); // inner window clip rectangle // Stop logging - if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging + if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging LogFinish(); // Pop // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin(). g.CurrentWindowStack.pop_back(); - if (window->Flags & ImGuiWindowFlags_Popup) - g.CurrentPopupStack.pop_back(); + if (window->Flags & ImGuiWindowFlags_Popup) g.CurrentPopupStack.pop_back(); CheckStacksSize(window, false); SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); } // Vertical scrollbar // The entire piece of code below is rather confusing because: -// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) -// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar +// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking +// inside the grab) +// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a +// scrollbar // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. -static void Scrollbar(ImGuiWindow* window, bool horizontal) +static void Scrollbar(ImGuiWindow *window, bool horizontal) { - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); // Render background - bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX); - float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f; - const ImRect window_rect = window->Rect(); - const float border_size = window->BorderSize; - ImRect bb = horizontal - ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) - : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); + bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX); + float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f; + const ImRect window_rect = window->Rect(); + const float border_size = window->BorderSize; + ImRect bb = horizontal ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, + window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) + : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, + window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); if (!horizontal) bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); - if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f) - return; + if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f) return; float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; - int window_rounding_corners; + int window_rounding_corners; if (horizontal) window_rounding_corners = ImGuiCorner_BottomLeft | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); else - window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); - window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); - bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); + window_rounding_corners = + (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight + : 0) | + (other_scrollbar ? 0 : ImGuiCorner_BottomRight); + window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, + window_rounding_corners); + bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), + ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main axis of the scrollbar - float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); - float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y; - float win_size_avail_v = (horizontal ? window->Size.x : window->Size.y) - other_scrollbar_size_w; + float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); + float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y; + float win_size_avail_v = (horizontal ? window->Size.x : window->Size.y) - other_scrollbar_size_w; float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y; // The grabable box size generally represent the amount visible (vs the total scrollable amount) // But we maintain a minimum size in pixel to allow for the user to still aim inside. - const float grab_h_pixels = ImMin(ImMax(scrollbar_size_v * ImSaturate(win_size_avail_v / ImMax(win_size_contents_v, win_size_avail_v)), style.GrabMinSize), scrollbar_size_v); + const float grab_h_pixels = ImMin( + ImMax(scrollbar_size_v * ImSaturate(win_size_avail_v / ImMax(win_size_contents_v, win_size_avail_v)), style.GrabMinSize), + scrollbar_size_v); const float grab_h_norm = grab_h_pixels / scrollbar_size_v; // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). - bool held = false; - bool hovered = false; + bool held = false; + bool hovered = false; const bool previously_held = (g.ActiveId == id); ImGui::ButtonBehavior(bb, id, &hovered, &held); - float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); + float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); float scroll_ratio = ImSaturate(scroll_v / scroll_max); - float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; + float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; if (held && grab_h_norm < 1.0f) { - float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y; - float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y; + float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y; + float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + float *click_delta_to_grab_center_v = + horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y; // Click position in scrollbar normalized space (0.0f->1.0f) const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); @@ -4521,20 +4756,20 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) { // On initial click calculate the distance between mouse and the center of the grab if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm) - { - *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; - } + { *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; } else { - seek_absolute = true; + seek_absolute = true; *click_delta_to_grab_center_v = 0.0f; } } // Apply scroll - // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position - const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm)); - scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); + // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before + // setting up our starting position + const float scroll_v_norm = + ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); + scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max); //(win_size_contents_v - win_size_v)); if (horizontal) window->Scroll.x = scroll_v; else @@ -4542,45 +4777,46 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) // Update values for rendering scroll_ratio = ImSaturate(scroll_v / scroll_max); - grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; + grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Update distance to grab now that we have seeked and saturated - if (seek_absolute) - *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; + if (seek_absolute) *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; } // Render - const ImU32 grab_col = ImGui::GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); + const ImU32 grab_col = ImGui::GetColorU32(held ? ImGuiCol_ScrollbarGrabActive + : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); if (horizontal) - window->DrawList->AddRectFilled(ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y), ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y), grab_col, style.ScrollbarRounding); + window->DrawList->AddRectFilled(ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y), + ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y), grab_col, + style.ScrollbarRounding); else - window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels), grab_col, style.ScrollbarRounding); + window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm)), + ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels), grab_col, + style.ScrollbarRounding); } // Moving window to front of display (which happens to be back of our sorted list) -void ImGui::FocusWindow(ImGuiWindow* window) +void ImGui::FocusWindow(ImGuiWindow *window) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing. g.FocusedWindow = window; // Passing NULL allow to disable keyboard focus - if (!window) - return; + if (!window) return; // And move its root window to the top of the pile - if (window->RootWindow) - window = window->RootWindow; + if (window->RootWindow) window = window->RootWindow; // Steal focus on active widgets - if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it.. - if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window) - ClearActiveID(); + if (window->Flags & + ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it.. + if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window) ClearActiveID(); // Bring to front - if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window) - return; + if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window) return; for (int i = 0; i < g.Windows.Size; i++) if (g.Windows[i] == window) { @@ -4592,76 +4828,77 @@ void ImGui::FocusWindow(ImGuiWindow* window) void ImGui::PushItemWidth(float item_width) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); } static void PushMultiItemsWidths(int components, float w_full) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); - const ImGuiStyle& style = GImGui->Style; - if (w_full <= 0.0f) - w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + ImGuiWindow * window = ImGui::GetCurrentWindow(); + const ImGuiStyle &style = GImGui->Style; + if (w_full <= 0.0f) w_full = ImGui::CalcItemWidth(); + const float w_item_one = + ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); window->DC.ItemWidthStack.push_back(w_item_last); - for (int i = 0; i < components-1; i++) + for (int i = 0; i < components - 1; i++) window->DC.ItemWidthStack.push_back(w_item_one); window->DC.ItemWidth = window->DC.ItemWidthStack.back(); } void ImGui::PopItemWidth() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.ItemWidthStack.pop_back(); window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back(); } float ImGui::CalcItemWidth() { - ImGuiWindow* window = GetCurrentWindowRead(); - float w = window->DC.ItemWidth; + ImGuiWindow *window = GetCurrentWindowRead(); + float w = window->DC.ItemWidth; if (w < 0.0f) { - // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well. + // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used + // (we add 2 frame padding to it), but we could move that responsibility to the widget as well. float width_to_right_edge = GetContentRegionAvail().x; - w = ImMax(1.0f, width_to_right_edge + w); + w = ImMax(1.0f, width_to_right_edge + w); } w = (float)(int)w; return w; } -static ImFont* GetDefaultFont() +static ImFont *GetDefaultFont() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } -static void SetCurrentFont(ImFont* font) +static void SetCurrentFont(ImFont *font) { - ImGuiContext& g = *GImGui; - IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? + ImGuiContext &g = *GImGui; + IM_ASSERT(font && + font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? IM_ASSERT(font->Scale > 0.0f); - g.Font = font; - g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale; - g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; + g.Font = font; + g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale; + g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel; } -void ImGui::PushFont(ImFont* font) +void ImGui::PushFont(ImFont *font) { - ImGuiContext& g = *GImGui; - if (!font) - font = GetDefaultFont(); + ImGuiContext &g = *GImGui; + if (!font) font = GetDefaultFont(); SetCurrentFont(font); g.FontStack.push_back(font); g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID); } -void ImGui::PopFont() +void ImGui::PopFont() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; g.CurrentWindow->DrawList->PopTextureID(); g.FontStack.pop_back(); SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); @@ -4669,51 +4906,51 @@ void ImGui::PopFont() void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.AllowKeyboardFocus = allow_keyboard_focus; window->DC.AllowKeyboardFocusStack.push_back(allow_keyboard_focus); } void ImGui::PopAllowKeyboardFocus() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.AllowKeyboardFocusStack.pop_back(); window->DC.AllowKeyboardFocus = window->DC.AllowKeyboardFocusStack.empty() ? true : window->DC.AllowKeyboardFocusStack.back(); } void ImGui::PushButtonRepeat(bool repeat) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.ButtonRepeat = repeat; window->DC.ButtonRepeatStack.push_back(repeat); } void ImGui::PopButtonRepeat() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.ButtonRepeatStack.pop_back(); window->DC.ButtonRepeat = window->DC.ButtonRepeatStack.empty() ? false : window->DC.ButtonRepeatStack.back(); } void ImGui::PushTextWrapPos(float wrap_pos_x) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.TextWrapPos = wrap_pos_x; window->DC.TextWrapPosStack.push_back(wrap_pos_x); } void ImGui::PopTextWrapPos() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.TextWrapPosStack.pop_back(); window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back(); } -void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) +void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4 &col) { - ImGuiContext& g = *GImGui; - ImGuiColMod backup; - backup.Col = idx; + ImGuiContext &g = *GImGui; + ImGuiColMod backup; + backup.Col = idx; backup.BackupValue = g.Style.Colors[idx]; g.ColorModifiers.push_back(backup); g.Style.Colors[idx] = col; @@ -4721,10 +4958,10 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) void ImGui::PopStyleColor(int count) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; while (count > 0) { - ImGuiColMod& backup = g.ColorModifiers.back(); + ImGuiColMod &backup = g.ColorModifiers.back(); g.Style.Colors[backup.Col] = backup.BackupValue; g.ColorModifiers.pop_back(); count--; @@ -4733,28 +4970,30 @@ void ImGui::PopStyleColor(int count) struct ImGuiStyleVarInfo { - ImGuiDataType Type; - ImU32 Offset; - void* GetVarPtr() const { return (void*)((unsigned char*)&GImGui->Style + Offset); } + ImGuiDataType Type; + ImU32 Offset; + void * GetVarPtr() const + { + return (void *)((unsigned char *)&GImGui->Style + Offset); + } }; -static const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] = -{ - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildWindowRounding) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, +static const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] = { + {ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha)}, + {ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding)}, + {ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding)}, + {ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize)}, + {ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildWindowRounding)}, + {ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding)}, + {ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding)}, + {ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing)}, + {ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing)}, + {ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing)}, + {ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize)}, + {ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign)}, }; -static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) +static const ImGuiStyleVarInfo *GetStyleVarInfo(ImGuiStyleVar idx) { IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_Count_); return &GStyleVarInfo[idx]; @@ -4762,10 +5001,10 @@ static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); + const ImGuiStyleVarInfo *var_info = GetStyleVarInfo(idx); if (var_info->Type == ImGuiDataType_Float) { - float* pvar = (float*)var_info->GetVarPtr(); + float *pvar = (float *)var_info->GetVarPtr(); GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); *pvar = val; return; @@ -4773,12 +5012,12 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) IM_ASSERT(0); // Called function with wrong-type? Variable is not a float. } -void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) +void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2 &val) { - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); + const ImGuiStyleVarInfo *var_info = GetStyleVarInfo(idx); if (var_info->Type == ImGuiDataType_Float2) { - ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(); + ImVec2 *pvar = (ImVec2 *)var_info->GetVarPtr(); GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); *pvar = val; return; @@ -4788,20 +5027,23 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) void ImGui::PopStyleVar(int count) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; while (count > 0) { - ImGuiStyleMod& backup = g.StyleModifiers.back(); - const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); - if (info->Type == ImGuiDataType_Float) (*(float*)info->GetVarPtr()) = backup.BackupFloat[0]; - else if (info->Type == ImGuiDataType_Float2) (*(ImVec2*)info->GetVarPtr()) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]); - else if (info->Type == ImGuiDataType_Int) (*(int*)info->GetVarPtr()) = backup.BackupInt[0]; + ImGuiStyleMod & backup = g.StyleModifiers.back(); + const ImGuiStyleVarInfo *info = GetStyleVarInfo(backup.VarIdx); + if (info->Type == ImGuiDataType_Float) + (*(float *)info->GetVarPtr()) = backup.BackupFloat[0]; + else if (info->Type == ImGuiDataType_Float2) + (*(ImVec2 *)info->GetVarPtr()) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]); + else if (info->Type == ImGuiDataType_Int) + (*(int *)info->GetVarPtr()) = backup.BackupInt[0]; g.StyleModifiers.pop_back(); count--; } } -const char* ImGui::GetStyleColName(ImGuiCol idx) +const char *ImGui::GetStyleColName(ImGuiCol idx) { // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; switch (idx) @@ -4856,141 +5098,139 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) bool ImGui::IsWindowHovered() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow); } bool ImGui::IsWindowFocused() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FocusedWindow == g.CurrentWindow; } bool ImGui::IsRootWindowFocused() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FocusedWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildFocused() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildHovered() { - ImGuiContext& g = *GImGui; - return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow); + ImGuiContext &g = *GImGui; + return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && + IsWindowContentHoverable(g.HoveredRootWindow); } float ImGui::GetWindowWidth() { - ImGuiWindow* window = GImGui->CurrentWindow; + ImGuiWindow *window = GImGui->CurrentWindow; return window->Size.x; } float ImGui::GetWindowHeight() { - ImGuiWindow* window = GImGui->CurrentWindow; + ImGuiWindow *window = GImGui->CurrentWindow; return window->Size.y; } ImVec2 ImGui::GetWindowPos() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + ImGuiContext &g = *GImGui; + ImGuiWindow * window = g.CurrentWindow; return window->Pos; } -static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) +static void SetWindowScrollY(ImGuiWindow *window, float new_scroll_y) { window->DC.CursorMaxPos.y += window->Scroll.y; window->Scroll.y = new_scroll_y; window->DC.CursorMaxPos.y -= window->Scroll.y; } -static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond) +static void SetWindowPos(ImGuiWindow *window, const ImVec2 &pos, ImGuiSetCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowPosAllowFlags & cond) == 0) - return; + if (cond && (window->SetWindowPosAllowFlags & cond) == 0) return; window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); window->SetWindowPosCenterWanted = false; // Set const ImVec2 old_pos = window->Pos; - window->PosFloat = pos; - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); - window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor - window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected. + window->PosFloat = pos; + window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a + // bad idea - will smear) let's at least offset the cursor + window->DC.CursorMaxPos += + (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected. } -void ImGui::SetWindowPos(const ImVec2& pos, ImGuiSetCond cond) +void ImGui::SetWindowPos(const ImVec2 &pos, ImGuiSetCond cond) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); SetWindowPos(window, pos, cond); } -void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond) +void ImGui::SetWindowPos(const char *name, const ImVec2 &pos, ImGuiSetCond cond) { - if (ImGuiWindow* window = FindWindowByName(name)) - SetWindowPos(window, pos, cond); + if (ImGuiWindow *window = FindWindowByName(name)) SetWindowPos(window, pos, cond); } ImVec2 ImGui::GetWindowSize() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->Size; } -static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond) +static void SetWindowSize(ImGuiWindow *window, const ImVec2 &size, ImGuiSetCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) - return; + if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) return; window->SetWindowSizeAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); // Set if (size.x > 0.0f) { window->AutoFitFramesX = 0; - window->SizeFull.x = size.x; + window->SizeFull.x = size.x; } else { - window->AutoFitFramesX = 2; + window->AutoFitFramesX = 2; window->AutoFitOnlyGrows = false; } if (size.y > 0.0f) { window->AutoFitFramesY = 0; - window->SizeFull.y = size.y; + window->SizeFull.y = size.y; } else { - window->AutoFitFramesY = 2; + window->AutoFitFramesY = 2; window->AutoFitOnlyGrows = false; } } -void ImGui::SetWindowSize(const ImVec2& size, ImGuiSetCond cond) +void ImGui::SetWindowSize(const ImVec2 &size, ImGuiSetCond cond) { SetWindowSize(GImGui->CurrentWindow, size, cond); } -void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond) +void ImGui::SetWindowSize(const char *name, const ImVec2 &size, ImGuiSetCond cond) { - ImGuiWindow* window = FindWindowByName(name); - if (window) - SetWindowSize(window, size, cond); + ImGuiWindow *window = FindWindowByName(name); + if (window) SetWindowSize(window, size, cond); } -static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiSetCond cond) +static void SetWindowCollapsed(ImGuiWindow *window, bool collapsed, ImGuiSetCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) - return; + if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) return; window->SetWindowCollapsedAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); // Set @@ -5007,11 +5247,10 @@ bool ImGui::IsWindowCollapsed() return GImGui->CurrentWindow->Collapsed; } -void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond) +void ImGui::SetWindowCollapsed(const char *name, bool collapsed, ImGuiSetCond cond) { - ImGuiWindow* window = FindWindowByName(name); - if (window) - SetWindowCollapsed(window, collapsed, cond); + ImGuiWindow *window = FindWindowByName(name); + if (window) SetWindowCollapsed(window, collapsed, cond); } void ImGui::SetWindowFocus() @@ -5019,12 +5258,11 @@ void ImGui::SetWindowFocus() FocusWindow(GImGui->CurrentWindow); } -void ImGui::SetWindowFocus(const char* name) +void ImGui::SetWindowFocus(const char *name) { if (name) { - if (ImGuiWindow* window = FindWindowByName(name)) - FocusWindow(window); + if (ImGuiWindow *window = FindWindowByName(name)) FocusWindow(window); } else { @@ -5032,76 +5270,76 @@ void ImGui::SetWindowFocus(const char* name) } } -void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond) +void ImGui::SetNextWindowPos(const ImVec2 &pos, ImGuiSetCond cond) { - ImGuiContext& g = *GImGui; - g.SetNextWindowPosVal = pos; + ImGuiContext &g = *GImGui; + g.SetNextWindowPosVal = pos; g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::SetNextWindowPosCenter(ImGuiSetCond cond) { - ImGuiContext& g = *GImGui; - g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX); + ImGuiContext &g = *GImGui; + g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX); g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; } -void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond) +void ImGui::SetNextWindowSize(const ImVec2 &size, ImGuiSetCond cond) { - ImGuiContext& g = *GImGui; - g.SetNextWindowSizeVal = size; + ImGuiContext &g = *GImGui; + g.SetNextWindowSizeVal = size; g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always; } -void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) +void ImGui::SetNextWindowSizeConstraints(const ImVec2 &size_min, const ImVec2 &size_max, + ImGuiSizeConstraintCallback custom_callback, void *custom_callback_user_data) { - ImGuiContext& g = *GImGui; - g.SetNextWindowSizeConstraint = true; - g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max); - g.SetNextWindowSizeConstraintCallback = custom_callback; + ImGuiContext &g = *GImGui; + g.SetNextWindowSizeConstraint = true; + g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max); + g.SetNextWindowSizeConstraintCallback = custom_callback; g.SetNextWindowSizeConstraintCallbackUserData = custom_callback_user_data; } -void ImGui::SetNextWindowContentSize(const ImVec2& size) +void ImGui::SetNextWindowContentSize(const ImVec2 &size) { - ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = size; + ImGuiContext &g = *GImGui; + g.SetNextWindowContentSizeVal = size; g.SetNextWindowContentSizeCond = ImGuiSetCond_Always; } void ImGui::SetNextWindowContentWidth(float width) { - ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = ImVec2(width, g.SetNextWindowContentSizeCond ? g.SetNextWindowContentSizeVal.y : 0.0f); + ImGuiContext &g = *GImGui; + g.SetNextWindowContentSizeVal = ImVec2(width, g.SetNextWindowContentSizeCond ? g.SetNextWindowContentSizeVal.y : 0.0f); g.SetNextWindowContentSizeCond = ImGuiSetCond_Always; } void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond) { - ImGuiContext& g = *GImGui; - g.SetNextWindowCollapsedVal = collapsed; + ImGuiContext &g = *GImGui; + g.SetNextWindowCollapsedVal = collapsed; g.SetNextWindowCollapsedCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::SetNextWindowFocus() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; g.SetNextWindowFocus = true; } // In window space (not screen space!) ImVec2 ImGui::GetContentRegionMax() { - ImGuiWindow* window = GetCurrentWindowRead(); - ImVec2 mx = window->ContentsRegionRect.Max; - if (window->DC.ColumnsCount != 1) - mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; + ImGuiWindow *window = GetCurrentWindowRead(); + ImVec2 mx = window->ContentsRegionRect.Max; + if (window->DC.ColumnsCount != 1) mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; return mx; } ImVec2 ImGui::GetContentRegionAvail() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return GetContentRegionMax() - (window->DC.CursorPos - window->Pos); } @@ -5113,47 +5351,47 @@ float ImGui::GetContentRegionAvailWidth() // In window space (not screen space!) ImVec2 ImGui::GetWindowContentRegionMin() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->ContentsRegionRect.Min; } ImVec2 ImGui::GetWindowContentRegionMax() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->ContentsRegionRect.Max; } float ImGui::GetWindowContentRegionWidth() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->ContentsRegionRect.Max.x - window->ContentsRegionRect.Min.x; } float ImGui::GetTextLineHeight() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FontSize; } float ImGui::GetTextLineHeightWithSpacing() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FontSize + g.Style.ItemSpacing.y; } float ImGui::GetItemsLineHeightWithSpacing() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; } -ImDrawList* ImGui::GetWindowDrawList() +ImDrawList *ImGui::GetWindowDrawList() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); return window->DrawList; } -ImFont* ImGui::GetFont() +ImFont *ImGui::GetFont() { return GImGui->Font; } @@ -5170,69 +5408,70 @@ ImVec2 ImGui::GetFontTexUvWhitePixel() void ImGui::SetWindowFontScale(float scale) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); window->FontWindowScale = scale; - g.FontSize = window->CalcFontSize(); + g.FontSize = window->CalcFontSize(); } -// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. -// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'. +// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is +// more convenient. Conversion happens as we pass the value to user, but it makes our naming convention confusing because +// GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'. ImVec2 ImGui::GetCursorPos() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.CursorPos - window->Pos + window->Scroll; } float ImGui::GetCursorPosX() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x; } float ImGui::GetCursorPosY() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y; } -void ImGui::SetCursorPos(const ImVec2& local_pos) +void ImGui::SetCursorPos(const ImVec2 &local_pos) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = window->Pos - window->Scroll + local_pos; + ImGuiWindow *window = GetCurrentWindow(); + window->DC.CursorPos = window->Pos - window->Scroll + local_pos; window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); } void ImGui::SetCursorPosX(float x) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; + ImGuiWindow *window = GetCurrentWindow(); + window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x); } void ImGui::SetCursorPosY(float y) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; + ImGuiWindow *window = GetCurrentWindow(); + window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); } ImVec2 ImGui::GetCursorStartPos() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.CursorStartPos - window->Pos; } ImVec2 ImGui::GetCursorScreenPos() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.CursorPos; } -void ImGui::SetCursorScreenPos(const ImVec2& screen_pos) +void ImGui::SetCursorScreenPos(const ImVec2 &screen_pos) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = screen_pos; + ImGuiWindow *window = GetCurrentWindow(); + window->DC.CursorPos = screen_pos; window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); } @@ -5248,37 +5487,40 @@ float ImGui::GetScrollY() float ImGui::GetScrollMaxX() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->SizeContents.x - window->SizeFull.x - window->ScrollbarSizes.x; } float ImGui::GetScrollMaxY() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->SizeContents.y - window->SizeFull.y - window->ScrollbarSizes.y; } void ImGui::SetScrollX(float scroll_x) { - ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTarget.x = scroll_x; + ImGuiWindow *window = GetCurrentWindow(); + window->ScrollTarget.x = scroll_x; window->ScrollTargetCenterRatio.x = 0.0f; } void ImGui::SetScrollY(float scroll_y) { - ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY + ImGuiWindow *window = GetCurrentWindow(); + window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY window->ScrollTargetCenterRatio.y = 0.0f; } void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); window->ScrollTarget.y = (float)(int)(pos_y + window->Scroll.y); - if (center_y_ratio <= 0.0f && window->ScrollTarget.y <= window->WindowPadding.y) // Minor hack to make "scroll to top" take account of WindowPadding, else it would scroll to (WindowPadding.y - ItemSpacing.y) + if (center_y_ratio <= 0.0f && + window->ScrollTarget.y <= window->WindowPadding.y) // Minor hack to make "scroll to top" take account of WindowPadding, + // else it would scroll to (WindowPadding.y - ItemSpacing.y) window->ScrollTarget.y = 0.0f; window->ScrollTargetCenterRatio.y = center_y_ratio; } @@ -5286,42 +5528,43 @@ void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio) // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. void ImGui::SetScrollHere(float center_y_ratio) { - ImGuiWindow* window = GetCurrentWindow(); - float target_y = window->DC.CursorPosPrevLine.y + (window->DC.PrevLineHeight * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. + ImGuiWindow *window = GetCurrentWindow(); + float target_y = window->DC.CursorPosPrevLine.y + (window->DC.PrevLineHeight * center_y_ratio) + + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * + 2.0f); // Precisely aim above, in the middle or below the last line. SetScrollFromPosY(target_y - window->Pos.y, center_y_ratio); } void ImGui::SetKeyboardFocusHere(int offset) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset; window->FocusIdxTabRequestNext = INT_MAX; } -void ImGui::SetStateStorage(ImGuiStorage* tree) +void ImGui::SetStateStorage(ImGuiStorage *tree) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.StateStorage = tree ? tree : &window->StateStorage; } -ImGuiStorage* ImGui::GetStateStorage() +ImGuiStorage *ImGui::GetStateStorage() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.StateStorage; } -void ImGui::TextV(const char* fmt, va_list args) +void ImGui::TextV(const char *fmt, va_list args) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; - const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + ImGuiContext &g = *GImGui; + const char * text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); TextUnformatted(g.TempBuffer, text_end); } -void ImGui::Text(const char* fmt, ...) +void ImGui::Text(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -5329,14 +5572,14 @@ void ImGui::Text(const char* fmt, ...) va_end(args); } -void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) +void ImGui::TextColoredV(const ImVec4 &col, const char *fmt, va_list args) { PushStyleColor(ImGuiCol_Text, col); TextV(fmt, args); PopStyleColor(); } -void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) +void ImGui::TextColored(const ImVec4 &col, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -5344,14 +5587,14 @@ void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) va_end(args); } -void ImGui::TextDisabledV(const char* fmt, va_list args) +void ImGui::TextDisabledV(const char *fmt, va_list args) { PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]); TextV(fmt, args); PopStyleColor(); } -void ImGui::TextDisabled(const char* fmt, ...) +void ImGui::TextDisabled(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -5359,15 +5602,15 @@ void ImGui::TextDisabled(const char* fmt, ...) va_end(args); } -void ImGui::TextWrappedV(const char* fmt, va_list args) +void ImGui::TextWrappedV(const char *fmt, va_list args) { - bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position is one ia already set + bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position is one ia already set if (need_wrap) PushTextWrapPos(0.0f); TextV(fmt, args); if (need_wrap) PopTextWrapPos(); } -void ImGui::TextWrapped(const char* fmt, ...) +void ImGui::TextWrapped(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -5375,31 +5618,30 @@ void ImGui::TextWrapped(const char* fmt, ...) va_end(args); } -void ImGui::TextUnformatted(const char* text, const char* text_end) +void ImGui::TextUnformatted(const char *text, const char *text_end) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; IM_ASSERT(text != NULL); - const char* text_begin = text; - if (text_end == NULL) - text_end = text + strlen(text); // FIXME-OPT + const char *text_begin = text; + if (text_end == NULL) text_end = text + strlen(text); // FIXME-OPT - const float wrap_pos_x = window->DC.TextWrapPos; - const bool wrap_enabled = wrap_pos_x >= 0.0f; + const float wrap_pos_x = window->DC.TextWrapPos; + const bool wrap_enabled = wrap_pos_x >= 0.0f; if (text_end - text > 2000 && !wrap_enabled) { // Long text! // Perform manual coarse clipping to optimize for long multi-line text - // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. - // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. - const char* line = text; - const float line_height = GetTextLineHeight(); - const ImVec2 text_pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrentLineTextBaseOffset); - const ImRect clip_rect = window->ClipRect; - ImVec2 text_size(0,0); + // From this point we will only compute the width of lines that are visible. Optimization only available when + // word-wrapping is disabled. We also don't vertically center the text within the line full height, which is unlikely to + // matter because we are likely the biggest and only item on the line. + const char * line = text; + const float line_height = GetTextLineHeight(); + const ImVec2 text_pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrentLineTextBaseOffset); + const ImRect clip_rect = window->ClipRect; + ImVec2 text_size(0, 0); if (text_pos.y <= clip_rect.Max.y) { @@ -5414,9 +5656,8 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) int lines_skipped = 0; while (line < text_end && lines_skipped < lines_skippable) { - const char* line_end = strchr(line, '\n'); - if (!line_end) - line_end = text_end; + const char *line_end = strchr(line, '\n'); + if (!line_end) line_end = text_end; line = line_end + 1; lines_skipped++; } @@ -5430,15 +5671,13 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); while (line < text_end) { - const char* line_end = strchr(line, '\n'); - if (IsClippedEx(line_rect, NULL, false)) - break; + const char *line_end = strchr(line, '\n'); + if (IsClippedEx(line_rect, NULL, false)) break; const ImVec2 line_size = CalcTextSize(line, line_end, false); - text_size.x = ImMax(text_size.x, line_size.x); + text_size.x = ImMax(text_size.x, line_size.x); RenderText(pos, line, line_end, false); - if (!line_end) - line_end = text_end; + if (!line_end) line_end = text_end; line = line_end + 1; line_rect.Min.y += line_height; line_rect.Max.y += line_height; @@ -5449,9 +5688,8 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) int lines_skipped = 0; while (line < text_end) { - const char* line_end = strchr(line, '\n'); - if (!line_end) - line_end = text_end; + const char *line_end = strchr(line, '\n'); + if (!line_end) line_end = text_end; line = line_end + 1; lines_skipped++; } @@ -5467,15 +5705,14 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) } else { - const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; - const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); + const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; + const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); // Account of baseline offset ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset); ImRect bb(text_pos, text_pos + text_size); ItemSize(text_size); - if (!ItemAdd(bb, NULL)) - return; + if (!ItemAdd(bb, NULL)) return; // Render (we don't hide text after ## in this end-user function) RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width); @@ -5484,43 +5721,43 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) void ImGui::AlignFirstTextHeightToWidgets() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; // Declare a dummy item size to that upcoming items that are smaller will center-align on the newly expanded line height. - ImGuiContext& g = *GImGui; - ItemSize(ImVec2(0, g.FontSize + g.Style.FramePadding.y*2), g.Style.FramePadding.y); + ImGuiContext &g = *GImGui; + ItemSize(ImVec2(0, g.FontSize + g.Style.FramePadding.y * 2), g.Style.FramePadding.y); SameLine(0, 0); } // Add a label+text combo aligned to other label+value widgets -void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) +void ImGui::LabelTextV(const char *label, const char *fmt, va_list args) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float w = CalcItemWidth(); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2)); - const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size); + const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2)); + const ImRect total_bb(window->DC.CursorPos, + window->DC.CursorPos + + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y * 2) + + label_size); ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, NULL)) - return; + if (!ItemAdd(total_bb, NULL)) return; // Render - const char* value_text_begin = &g.TempBuffer[0]; - const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f)); + const char *value_text_begin = &g.TempBuffer[0]; + const char *value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f, 0.5f)); if (label_size.x > 0.0f) RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label); } -void ImGui::LabelText(const char* label, const char* fmt, ...) +void ImGui::LabelText(const char *label, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -5528,22 +5765,23 @@ void ImGui::LabelText(const char* label, const char* fmt, ...) va_end(args); } -static inline bool IsWindowContentHoverable(ImGuiWindow* window) +static inline bool IsWindowContentHoverable(ImGuiWindow *window) { // An active popup disable hovering on other windows (apart from its own children) - ImGuiContext& g = *GImGui; - if (ImGuiWindow* focused_window = g.FocusedWindow) - if (ImGuiWindow* focused_root_window = focused_window->RootWindow) - if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) + ImGuiContext &g = *GImGui; + if (ImGuiWindow *focused_window = g.FocusedWindow) + if (ImGuiWindow *focused_root_window = focused_window->RootWindow) + if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && + focused_root_window != window->RootWindow) return false; return true; } -bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) +bool ImGui::ButtonBehavior(const ImRect &bb, ImGuiID id, bool *out_hovered, bool *out_held, ImGuiButtonFlags flags) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); if (flags & ImGuiButtonFlags_Disabled) { @@ -5553,7 +5791,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool return false; } - if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) + if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | + ImGuiButtonFlags_PressedOnDoubleClick)) == 0) flags |= ImGuiButtonFlags_PressedOnClickRelease; bool pressed = false; @@ -5564,9 +5803,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat - // PressedOnClickRelease | * | .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds - // PressedOnClick | | .. - // PressedOnRelease | | .. (NOT on release) + // PressedOnClickRelease | * | .. (NOT on release) <-- MOST COMMON! (*) only + // if both click/release were over bounds PressedOnClick | | .. PressedOnRelease | | .. (NOT on release) // PressedOnDoubleClick | | .. if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { @@ -5574,7 +5813,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool FocusWindow(window); g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } - if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) + if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || + ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { pressed = true; ClearActiveID(); @@ -5582,14 +5822,17 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) { - if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + if (!((flags & ImGuiButtonFlags_Repeat) && + g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps pressed = true; ClearActiveID(); } - // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). - // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. - if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true)) + // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). + // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer + // RepeatDelay/RepeatRate settings. + if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && + IsMouseClicked(0, true)) pressed = true; } } @@ -5597,21 +5840,21 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool bool held = false; if (g.ActiveId == id) { - if (g.IO.MouseDown[0]) - { - held = true; - } + if (g.IO.MouseDown[0]) { held = true; } else { if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) - if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + if (!((flags & ImGuiButtonFlags_Repeat) && + g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps pressed = true; ClearActiveID(); } } - // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where + // a later submitted widget overlaps a previous one. + if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && + (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) hovered = pressed = held = false; if (out_hovered) *out_hovered = hovered; @@ -5620,26 +5863,27 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool return pressed; } -bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) +bool ImGui::ButtonEx(const char *label, const ImVec2 &size_arg, ImGuiButtonFlags flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 pos = window->DC.CursorPos; - if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) + if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && + style.FramePadding.y < + window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text + // baseline matches (bit hacky, since it shouldn't be a flag) pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y; ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); const ImRect bb(pos, pos + size); ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(bb, &id)) - return false; + if (!ItemAdd(bb, &id)) return false; if (window->DC.ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; bool hovered, held; @@ -5648,45 +5892,44 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); + RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, + &bb); // Automatically close popups - //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) + // if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) // CloseCurrentPopup(); return pressed; } -bool ImGui::Button(const char* label, const ImVec2& size_arg) +bool ImGui::Button(const char *label, const ImVec2 &size_arg) { return ButtonEx(label, size_arg, 0); } // Small buttons fits within text without additional vertical spacing. -bool ImGui::SmallButton(const char* label) +bool ImGui::SmallButton(const char *label) { - ImGuiContext& g = *GImGui; - float backup_padding_y = g.Style.FramePadding.y; - g.Style.FramePadding.y = 0.0f; - bool pressed = ButtonEx(label, ImVec2(0,0), ImGuiButtonFlags_AlignTextBaseLine); - g.Style.FramePadding.y = backup_padding_y; + ImGuiContext &g = *GImGui; + float backup_padding_y = g.Style.FramePadding.y; + g.Style.FramePadding.y = 0.0f; + bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine); + g.Style.FramePadding.y = backup_padding_y; return pressed; } // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) -bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) +bool ImGui::InvisibleButton(const char *str_id, const ImVec2 &size_arg) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - const ImGuiID id = window->GetID(str_id); - ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + const ImGuiID id = window->GetID(str_id); + ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(bb); - if (!ItemAdd(bb, &id)) - return false; + if (!ItemAdd(bb, &id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); @@ -5695,47 +5938,49 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) } // Upper-right button to close a window. -bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) +bool ImGui::CloseButton(ImGuiID id, const ImVec2 &pos, float radius) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); - const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); + const ImRect bb(pos - ImVec2(radius, radius), pos + ImVec2(radius, radius)); bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); // Render - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive + : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); const ImVec2 center = bb.GetCenter(); window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12); const float cross_extent = (radius * 0.7071f) - 1.0f; if (hovered) { - window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); - window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); + window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), + GetColorU32(ImGuiCol_Text)); + window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), + GetColorU32(ImGuiCol_Text)); } return pressed; } -void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) +void ImGui::Image(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0, const ImVec2 &uv1, const ImVec4 &tint_col, + const ImVec4 &border_col) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - if (border_col.w > 0.0f) - bb.Max += ImVec2(2,2); + if (border_col.w > 0.0f) bb.Max += ImVec2(2, 2); ItemSize(bb); - if (!ItemAdd(bb, NULL)) - return; + if (!ItemAdd(bb, NULL)) return; if (border_col.w > 0.0f) { window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); - window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, GetColorU32(tint_col)); + window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, + GetColorU32(tint_col)); } else { @@ -5747,14 +5992,14 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& // frame_padding = 0: no framing // frame_padding > 0: set framing size // The color used are the button colors. -bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) +bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, + const ImVec4 &bg_col, const ImVec4 &tint_col) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; // Default to using texture ID as ID. User can still push string/integer prefixes. // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV. @@ -5763,11 +6008,10 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I PopID(); const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding; - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2); const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size); ItemSize(bb); - if (!ItemAdd(bb, &id)) - return false; + if (!ItemAdd(bb, &id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); @@ -5775,8 +6019,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding)); - if (bg_col.w > 0.0f) - window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); + if (bg_col.w > 0.0f) window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col)); return pressed; @@ -5785,31 +6028,27 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I // Start logging ImGui output to TTY void ImGui::LogToTTY(int max_depth) { - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + if (g.LogEnabled) return; + ImGuiWindow *window = GetCurrentWindowRead(); - g.LogEnabled = true; - g.LogFile = stdout; + g.LogEnabled = true; + g.LogFile = stdout; g.LogStartDepth = window->DC.TreeDepth; - if (max_depth >= 0) - g.LogAutoExpandMaxDepth = max_depth; + if (max_depth >= 0) g.LogAutoExpandMaxDepth = max_depth; } // Start logging ImGui output to given file -void ImGui::LogToFile(int max_depth, const char* filename) +void ImGui::LogToFile(int max_depth, const char *filename) { - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + if (g.LogEnabled) return; + ImGuiWindow *window = GetCurrentWindowRead(); if (!filename) { filename = g.IO.LogFilename; - if (!filename) - return; + if (!filename) return; } g.LogFile = ImFileOpen(filename, "ab"); @@ -5818,32 +6057,28 @@ void ImGui::LogToFile(int max_depth, const char* filename) IM_ASSERT(g.LogFile != NULL); // Consider this an error return; } - g.LogEnabled = true; + g.LogEnabled = true; g.LogStartDepth = window->DC.TreeDepth; - if (max_depth >= 0) - g.LogAutoExpandMaxDepth = max_depth; + if (max_depth >= 0) g.LogAutoExpandMaxDepth = max_depth; } // Start logging ImGui output to clipboard void ImGui::LogToClipboard(int max_depth) { - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext &g = *GImGui; + if (g.LogEnabled) return; + ImGuiWindow *window = GetCurrentWindowRead(); - g.LogEnabled = true; - g.LogFile = NULL; + g.LogEnabled = true; + g.LogFile = NULL; g.LogStartDepth = window->DC.TreeDepth; - if (max_depth >= 0) - g.LogAutoExpandMaxDepth = max_depth; + if (max_depth >= 0) g.LogAutoExpandMaxDepth = max_depth; } void ImGui::LogFinish() { - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; + ImGuiContext &g = *GImGui; + if (!g.LogEnabled) return; LogText(IM_NEWLINE); g.LogEnabled = false; @@ -5865,12 +6100,15 @@ void ImGui::LogFinish() // Helper to display logging buttons void ImGui::LogButtons() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; PushID("LogButtons"); - const bool log_to_tty = Button("Log To TTY"); SameLine(); - const bool log_to_file = Button("Log To File"); SameLine(); - const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); + const bool log_to_tty = Button("Log To TTY"); + SameLine(); + const bool log_to_file = Button("Log To File"); + SameLine(); + const bool log_to_clipboard = Button("Log To Clipboard"); + SameLine(); PushItemWidth(80.0f); PushAllowKeyboardFocus(false); SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL); @@ -5879,23 +6117,19 @@ void ImGui::LogButtons() PopID(); // Start logging at the end of the function so that the buttons don't appear in the log - if (log_to_tty) - LogToTTY(g.LogAutoExpandMaxDepth); - if (log_to_file) - LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename); - if (log_to_clipboard) - LogToClipboard(g.LogAutoExpandMaxDepth); + if (log_to_tty) LogToTTY(g.LogAutoExpandMaxDepth); + if (log_to_file) LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename); + if (log_to_clipboard) LogToClipboard(g.LogAutoExpandMaxDepth); } bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { - if (flags & ImGuiTreeNodeFlags_Leaf) - return true; + if (flags & ImGuiTreeNodeFlags_Leaf) return true; // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiStorage* storage = window->DC.StateStorage; + ImGuiContext &g = *GImGui; + ImGuiWindow * window = g.CurrentWindow; + ImGuiStorage *storage = window->DC.StateStorage; bool is_open; if (g.SetNextTreeNodeOpenCond != 0) @@ -5907,7 +6141,8 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) } else { - // We treat ImGuiSetCondition_Once and ImGuiSetCondition_FirstUseEver the same because tree node state are not saved persistently. + // We treat ImGuiSetCondition_Once and ImGuiSetCondition_FirstUseEver the same because tree node state are not saved + // persistently. const int stored_value = storage->GetInt(id, -1); if (stored_value == -1) { @@ -5934,44 +6169,46 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) return is_open; } -bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) +bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char *label, const char *label_end) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; - const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; + const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); - if (!label_end) - label_end = FindRenderedTextEnd(label); + if (!label_end) label_end = FindRenderedTextEnd(label); const ImVec2 label_size = CalcTextSize(label, label_end, false); // We vertically grow up to current line height up the typical widget height. - const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it - const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); - ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); + const float text_base_offset_y = + ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it + const float frame_height = + ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); + ImRect bb = + ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); if (display_frame) { // Framed header expand a little outside the default padding - bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1; - bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; + bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f) - 1; + bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f) - 1; } - const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing - const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser + const float text_offset_x = (g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2)); // Collapser arrow width + Spacing + const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapser ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing - // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not) - const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); + // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the + // content or not) + const ImRect interact_bb = + display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x * 2, bb.Max.y); bool is_open = TreeNodeBehaviorIsOpen(id, flags); if (!ItemAdd(interact_bb, &id)) { - if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushRawID(id); + if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); return is_open; } @@ -5980,25 +6217,25 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnDoubleClick .............. double-click anywhere to open // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); + ImGuiButtonFlags button_flags = + ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) - button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); + button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | + ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) { bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)); - if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) - toggled |= g.IO.MouseDoubleClicked[0]; + if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) toggled |= g.IO.MouseDoubleClicked[0]; if (toggled) { is_open = !is_open; window->DC.StateStorage->SetInt(id, is_open); } } - if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) - SetItemAllowOverlap(); + if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) SetItemAllowOverlap(); // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); @@ -6010,12 +6247,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f); if (g.LogEnabled) { - // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. + // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make + // sure the ## aren't stripped out here. const char log_prefix[] = "\n##"; const char log_suffix[] = "##"; - LogRenderedText(text_pos, log_prefix, log_prefix+3); + LogRenderedText(text_pos, log_prefix, log_prefix + 3); RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); - LogRenderedText(text_pos, log_suffix+1, log_suffix+3); + LogRenderedText(text_pos, log_suffix + 1, log_suffix + 3); } else { @@ -6025,99 +6263,100 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l else { // Unframed typed for tree nodes - if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) - RenderFrame(bb.Min, bb.Max, col, false); + if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) RenderFrame(bb.Min, bb.Max, col, false); if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); + RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize * 0.50f + text_base_offset_y)); else if (!(flags & ImGuiTreeNodeFlags_Leaf)) - RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f); - if (g.LogEnabled) - LogRenderedText(text_pos, ">"); + RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize * 0.15f + text_base_offset_y), is_open, 0.70f); + if (g.LogEnabled) LogRenderedText(text_pos, ">"); RenderText(text_pos, label, label_end, false); } - if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushRawID(id); + if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); return is_open; } -// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). -// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). -bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) +// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the +// ImGuiTreeNodeFlags_NoTreePushOnOpen flag). This is basically the same as calling TreeNodeEx(label, +// ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen). You can remove the _NoTreePushOnOpen flag if you +// want behavior closer to normal TreeNode(). +bool ImGui::CollapsingHeader(const char *label, ImGuiTreeNodeFlags flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label); + return TreeNodeBehavior(window->GetID(label), + flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label); } -bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags) +bool ImGui::CollapsingHeader(const char *label, bool *p_open, ImGuiTreeNodeFlags flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - if (p_open && !*p_open) - return false; + if (p_open && !*p_open) return false; - ImGuiID id = window->GetID(label); - bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); + ImGuiID id = window->GetID(label); + bool is_open = TreeNodeBehavior(id, + flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | + (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), + label); if (p_open) { - // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. - ImGuiContext& g = *GImGui; - float button_sz = g.FontSize * 0.5f; - if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) + // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons + // on title bars, headers, etc. + ImGuiContext &g = *GImGui; + float button_sz = g.FontSize * 0.5f; + if (CloseButton(window->GetID((void *)(intptr_t)(id + 1)), + ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, + window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), + button_sz)) *p_open = false; } return is_open; } -bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) +bool ImGui::TreeNodeEx(const char *label, ImGuiTreeNodeFlags flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; return TreeNodeBehavior(window->GetID(label), flags, label, NULL); } -bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) +bool ImGui::TreeNodeExV(const char *str_id, ImGuiTreeNodeFlags flags, const char *fmt, va_list args) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + ImGuiContext &g = *GImGui; + const char * label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end); } -bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) +bool ImGui::TreeNodeExV(const void *ptr_id, ImGuiTreeNodeFlags flags, const char *fmt, va_list args) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + ImGuiContext &g = *GImGui; + const char * label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end); } -bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) +bool ImGui::TreeNodeV(const char *str_id, const char *fmt, va_list args) { return TreeNodeExV(str_id, 0, fmt, args); } -bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) +bool ImGui::TreeNodeV(const void *ptr_id, const char *fmt, va_list args) { return TreeNodeExV(ptr_id, 0, fmt, args); } -bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +bool ImGui::TreeNodeEx(const char *str_id, ImGuiTreeNodeFlags flags, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -6126,7 +6365,7 @@ bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* return is_open; } -bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +bool ImGui::TreeNodeEx(const void *ptr_id, ImGuiTreeNodeFlags flags, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -6135,7 +6374,7 @@ bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* return is_open; } -bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) +bool ImGui::TreeNode(const char *str_id, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -6144,7 +6383,7 @@ bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) return is_open; } -bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) +bool ImGui::TreeNode(const void *ptr_id, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -6153,128 +6392,127 @@ bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) return is_open; } -bool ImGui::TreeNode(const char* label) +bool ImGui::TreeNode(const char *label) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; return TreeNodeBehavior(window->GetID(label), 0, label, NULL); } void ImGui::TreeAdvanceToLabelPos() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing(); } // Horizontal distance preceding label when using TreeNode() or Bullet() float ImGui::GetTreeNodeToLabelSpacing() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; return g.FontSize + (g.Style.FramePadding.x * 2.0f); } void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond) { - ImGuiContext& g = *GImGui; - g.SetNextTreeNodeOpenVal = is_open; + ImGuiContext &g = *GImGui; + g.SetNextTreeNodeOpenVal = is_open; g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiSetCond_Always; } -void ImGui::PushID(const char* str_id) +void ImGui::PushID(const char *str_id) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->IDStack.push_back(window->GetID(str_id)); } -void ImGui::PushID(const char* str_id_begin, const char* str_id_end) +void ImGui::PushID(const char *str_id_begin, const char *str_id_end) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->IDStack.push_back(window->GetID(str_id_begin, str_id_end)); } -void ImGui::PushID(const void* ptr_id) +void ImGui::PushID(const void *ptr_id) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->IDStack.push_back(window->GetID(ptr_id)); } void ImGui::PushID(int int_id) { - const void* ptr_id = (void*)(intptr_t)int_id; - ImGuiWindow* window = GetCurrentWindow(); + const void * ptr_id = (void *)(intptr_t)int_id; + ImGuiWindow *window = GetCurrentWindow(); window->IDStack.push_back(window->GetID(ptr_id)); } void ImGui::PopID() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->IDStack.pop_back(); } -ImGuiID ImGui::GetID(const char* str_id) +ImGuiID ImGui::GetID(const char *str_id) { return GImGui->CurrentWindow->GetID(str_id); } -ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) +ImGuiID ImGui::GetID(const char *str_id_begin, const char *str_id_end) { return GImGui->CurrentWindow->GetID(str_id_begin, str_id_end); } -ImGuiID ImGui::GetID(const void* ptr_id) +ImGuiID ImGui::GetID(const void *ptr_id) { return GImGui->CurrentWindow->GetID(ptr_id); } void ImGui::Bullet() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); ItemSize(bb); if (!ItemAdd(bb, NULL)) { - SameLine(0, style.FramePadding.x*2); + SameLine(0, style.FramePadding.x * 2); return; } // Render and stay on same line - RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); - SameLine(0, style.FramePadding.x*2); + RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f)); + SameLine(0, style.FramePadding.x * 2); } // Text with a little bullet aligned to the typical tree node. -void ImGui::BulletTextV(const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - const char* text_begin = g.TempBuffer; - const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); - const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it - const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding +void ImGui::BulletTextV(const char *fmt, va_list args) +{ + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; + + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + + const char * text_begin = g.TempBuffer; + const char * text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); + const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it + const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize); + const ImRect bb(window->DC.CursorPos, + window->DC.CursorPos + + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), + ImMax(line_height, label_size.y))); // Empty text doesn't add padding ItemSize(bb); - if (!ItemAdd(bb, NULL)) - return; + if (!ItemAdd(bb, NULL)) return; // Render - RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); - RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false); + RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f)); + RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, text_base_offset_y), text_begin, text_end, false); } -void ImGui::BulletText(const char* fmt, ...) +void ImGui::BulletText(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -6282,52 +6520,56 @@ void ImGui::BulletText(const char* fmt, ...) va_end(args); } -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size) +static inline void DataTypeFormatString(ImGuiDataType data_type, void *data_ptr, const char *display_format, char *buf, + int buf_size) { if (data_type == ImGuiDataType_Int) - ImFormatString(buf, buf_size, display_format, *(int*)data_ptr); + ImFormatString(buf, buf_size, display_format, *(int *)data_ptr); else if (data_type == ImGuiDataType_Float) - ImFormatString(buf, buf_size, display_format, *(float*)data_ptr); + ImFormatString(buf, buf_size, display_format, *(float *)data_ptr); } -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size) +static inline void DataTypeFormatString(ImGuiDataType data_type, void *data_ptr, int decimal_precision, char *buf, int buf_size) { if (data_type == ImGuiDataType_Int) { if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%d", *(int*)data_ptr); + ImFormatString(buf, buf_size, "%d", *(int *)data_ptr); else - ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(int*)data_ptr); + ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(int *)data_ptr); } else if (data_type == ImGuiDataType_Float) { if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%f", *(float*)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits? + ImFormatString(buf, buf_size, "%f", + *(float *)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it + // is a float, while hiding non-significant digits? else - ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float*)data_ptr); + ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float *)data_ptr); } } -static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2)// Store into value1 +static void DataTypeApplyOp(ImGuiDataType data_type, int op, void *value1, const void *value2) // Store into value1 { if (data_type == ImGuiDataType_Int) { if (op == '+') - *(int*)value1 = *(int*)value1 + *(const int*)value2; + *(int *)value1 = *(int *)value1 + *(const int *)value2; else if (op == '-') - *(int*)value1 = *(int*)value1 - *(const int*)value2; + *(int *)value1 = *(int *)value1 - *(const int *)value2; } else if (data_type == ImGuiDataType_Float) { if (op == '+') - *(float*)value1 = *(float*)value1 + *(const float*)value2; + *(float *)value1 = *(float *)value1 + *(const float *)value2; else if (op == '-') - *(float*)value1 = *(float*)value1 - *(const float*)value2; + *(float *)value1 = *(float *)value1 - *(const float *)value2; } } // User can input math operators (e.g. +100) to edit a numerical values. -static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format) +static bool DataTypeApplyOpFromText(const char *buf, const char *initial_value_buf, ImGuiDataType data_type, void *data_ptr, + const char *scalar_format) { while (ImCharIsSpace(*buf)) buf++; @@ -6345,44 +6587,61 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b { op = 0; } - if (!buf[0]) - return false; + if (!buf[0]) return false; if (data_type == ImGuiDataType_Int) { - if (!scalar_format) - scalar_format = "%d"; - int* v = (int*)data_ptr; + if (!scalar_format) scalar_format = "%d"; + int * v = (int *)data_ptr; const int old_v = *v; - int arg0 = *v; - if (op && sscanf(initial_value_buf, scalar_format, &arg0) < 1) - return false; + int arg0 = *v; + if (op && sscanf(initial_value_buf, scalar_format, &arg0) < 1) return false; - // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision + // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer + // so we can fit big integers (e.g. 2000000003) past float precision float arg1 = 0.0f; - if (op == '+') { if (sscanf(buf, "%f", &arg1) == 1) *v = (int)(arg0 + arg1); } // Add (use "+-" to subtract) - else if (op == '*') { if (sscanf(buf, "%f", &arg1) == 1) *v = (int)(arg0 * arg1); } // Multiply - else if (op == '/') { if (sscanf(buf, "%f", &arg1) == 1 && arg1 != 0.0f) *v = (int)(arg0 / arg1); }// Divide - else { if (sscanf(buf, scalar_format, &arg0) == 1) *v = arg0; } // Assign constant + if (op == '+') + { + if (sscanf(buf, "%f", &arg1) == 1) *v = (int)(arg0 + arg1); + } // Add (use "+-" to subtract) + else if (op == '*') + { + if (sscanf(buf, "%f", &arg1) == 1) *v = (int)(arg0 * arg1); + } // Multiply + else if (op == '/') + { + if (sscanf(buf, "%f", &arg1) == 1 && arg1 != 0.0f) *v = (int)(arg0 / arg1); + } // Divide + else + { + if (sscanf(buf, scalar_format, &arg0) == 1) *v = arg0; + } // Assign constant return (old_v != *v); } else if (data_type == ImGuiDataType_Float) { // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in - scalar_format = "%f"; - float* v = (float*)data_ptr; + scalar_format = "%f"; + float * v = (float *)data_ptr; const float old_v = *v; - float arg0 = *v; - if (op && sscanf(initial_value_buf, scalar_format, &arg0) < 1) - return false; + float arg0 = *v; + if (op && sscanf(initial_value_buf, scalar_format, &arg0) < 1) return false; float arg1 = 0.0f; - if (sscanf(buf, scalar_format, &arg1) < 1) - return false; - if (op == '+') { *v = arg0 + arg1; } // Add (use "+-" to subtract) - else if (op == '*') { *v = arg0 * arg1; } // Multiply - else if (op == '/') { if (arg1 != 0.0f) *v = arg0 / arg1; } // Divide - else { *v = arg1; } // Assign constant + if (sscanf(buf, scalar_format, &arg1) < 1) return false; + if (op == '+') { *v = arg0 + arg1; } // Add (use "+-" to subtract) + else if (op == '*') + { + *v = arg0 * arg1; + } // Multiply + else if (op == '/') + { + if (arg1 != 0.0f) *v = arg0 / arg1; + } // Divide + else + { + *v = arg1; + } // Assign constant return (old_v != *v); } @@ -6390,10 +6649,11 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b } // Create text input in place of a slider (when CTRL+Clicking on slider) -bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision) +bool ImGui::InputScalarAsWidgetReplacement(const ImRect &aabb, const char *label, ImGuiDataType data_type, void *data_ptr, + ImGuiID id, int decimal_precision) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) SetActiveID(g.ScalarAsInputTextId, window); @@ -6402,11 +6662,13 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label char buf[32]; DataTypeFormatString(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf)); - bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); + bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), + ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); if (g.ScalarAsInputTextId == 0) { // First frame - IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) + IM_ASSERT(g.ActiveId == + id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) g.ScalarAsInputTextId = g.ActiveId; SetHoveredID(id); } @@ -6421,20 +6683,23 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label } // Parse display precision back from the display format string -int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) +int ImGui::ParseFormatPrecision(const char *fmt, int default_precision) { int precision = default_precision; while ((fmt = strchr(fmt, '%')) != NULL) { fmt++; - if (fmt[0] == '%') { fmt++; continue; } // Ignore "%%" + if (fmt[0] == '%') + { + fmt++; + continue; + } // Ignore "%%" while (*fmt >= '0' && *fmt <= '9') fmt++; if (*fmt == '.') { precision = atoi(fmt + 1); - if (precision < 0 || precision > 10) - precision = default_precision; + if (precision < 0 || precision > 10) precision = default_precision; } break; } @@ -6446,12 +6711,14 @@ float ImGui::RoundScalar(float value, int decimal_precision) // Round past decimal precision // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 // FIXME: Investigate better rounding methods - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; - float min_step = (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); - bool negative = value < 0.0f; - value = fabsf(value); + static const float min_steps[10] = {1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, + 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f}; + float min_step = (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] + : powf(10.0f, (float)-decimal_precision); + bool negative = value < 0.0f; + value = fabsf(value); float remainder = fmodf(value, min_step); - if (remainder <= min_step*0.5f) + if (remainder <= min_step * 0.5f) value -= remainder; else value += (min_step - remainder); @@ -6460,22 +6727,21 @@ float ImGui::RoundScalar(float value, int decimal_precision) static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos) { - if (v_min == v_max) - return 0.0f; + if (v_min == v_max) return 0.0f; - const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); - const float v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); + const bool is_non_linear = (power < 1.0f - 0.00001f) || (power > 1.0f + 0.00001f); + const float v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); if (is_non_linear) { if (v_clamped < 0.0f) { - const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); - return (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; + const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f, v_max) - v_min); + return (1.0f - powf(f, 1.0f / power)) * linear_zero_pos; } else { - const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); - return linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); + const float f = (v_clamped - ImMax(0.0f, v_min)) / (v_max - ImMax(0.0f, v_min)); + return linear_zero_pos + powf(f, 1.0f / power) * (1.0f - linear_zero_pos); } } @@ -6483,37 +6749,40 @@ static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float return (v_clamped - v_min) / (v_max - v_min); } -bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags) +bool ImGui::SliderBehavior(const ImRect &frame_bb, ImGuiID id, float *v, float v_min, float v_max, float power, + int decimal_precision, ImGuiSliderFlags flags) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); + const ImGuiStyle &style = g.Style; // Draw frame RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); + const bool is_non_linear = (power < 1.0f - 0.00001f) || (power > 1.0f + 0.00001f); const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; const float grab_padding = 2.0f; - const float slider_sz = is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f); + const float slider_sz = + is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f); float grab_sz; if (decimal_precision > 0) grab_sz = ImMin(style.GrabMinSize, slider_sz); else - grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit - const float slider_usable_sz = slider_sz - grab_sz; - const float slider_usable_pos_min = (is_horizontal ? frame_bb.Min.x : frame_bb.Min.y) + grab_padding + grab_sz*0.5f; - const float slider_usable_pos_max = (is_horizontal ? frame_bb.Max.x : frame_bb.Max.y) - grab_padding - grab_sz*0.5f; + grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), + slider_sz); // Integer sliders, if possible have the grab size represent 1 unit + const float slider_usable_sz = slider_sz - grab_sz; + const float slider_usable_pos_min = (is_horizontal ? frame_bb.Min.x : frame_bb.Min.y) + grab_padding + grab_sz * 0.5f; + const float slider_usable_pos_max = (is_horizontal ? frame_bb.Max.x : frame_bb.Max.y) - grab_padding - grab_sz * 0.5f; // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f - float linear_zero_pos = 0.0f; // 0.0->1.0f + float linear_zero_pos = 0.0f; // 0.0->1.0f if (v_min * v_max < 0.0f) { // Different sign - const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power); - const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power); - linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0); + const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f / power); + const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f / power); + linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0); } else { @@ -6528,9 +6797,10 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v if (g.IO.MouseDown[0]) { const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; - if (!is_horizontal) - clicked_t = 1.0f - clicked_t; + float clicked_t = (slider_usable_sz > 0.0f) + ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) + : 0.0f; + if (!is_horizontal) clicked_t = 1.0f - clicked_t; float new_value; if (is_non_linear) @@ -6539,9 +6809,9 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v if (clicked_t < linear_zero_pos) { // Negative: rescale to the negative range before powering - float a = 1.0f - (clicked_t / linear_zero_pos); - a = powf(a, power); - new_value = ImLerp(ImMin(v_max,0.0f), v_min, a); + float a = 1.0f - (clicked_t / linear_zero_pos); + a = powf(a, power); + new_value = ImLerp(ImMin(v_max, 0.0f), v_min, a); } else { @@ -6551,8 +6821,8 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos); else a = clicked_t; - a = powf(a, power); - new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); + a = powf(a, power); + new_value = ImLerp(ImMax(v_min, 0.0f), v_max, a); } } else @@ -6565,7 +6835,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v new_value = RoundScalar(new_value, decimal_precision); if (*v != new_value) { - *v = new_value; + *v = new_value; value_changed = true; } } @@ -6579,15 +6849,18 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v float grab_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); // Draw - if (!is_horizontal) - grab_t = 1.0f - grab_t; + if (!is_horizontal) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); - ImRect grab_bb; + ImRect grab_bb; if (is_horizontal) - grab_bb = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + grab_padding), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - grab_padding)); + grab_bb = ImRect(ImVec2(grab_pos - grab_sz * 0.5f, frame_bb.Min.y + grab_padding), + ImVec2(grab_pos + grab_sz * 0.5f, frame_bb.Max.y - grab_padding)); else - grab_bb = ImRect(ImVec2(frame_bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f)); - window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); + grab_bb = ImRect(ImVec2(frame_bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f), + ImVec2(frame_bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f)); + window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, + GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), + style.GrabRounding); return value_changed; } @@ -6597,20 +6870,20 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v // "%.3f" 1.234 // "%5.2f secs" 01.23 secs // "Gold: %.0f" Gold: 1 -bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat(const char *label, float *v, float v_min, float v_max, const char *display_format, float power) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); + const ImRect total_bb(frame_bb.Min, + frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); // NB- we don't call ItemSize() yet because we may turn into a text edit box below if (!ItemAdd(total_bb, &id)) @@ -6620,15 +6893,13 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c } const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); + if (hovered) SetHoveredID(id); - if (!display_format) - display_format = "%.3f"; + if (!display_format) display_format = "%.3f"; int decimal_precision = ParseFormatPrecision(display_format, 3); // Tabbing or CTRL-clicking on Slider turns it into an input box - bool start_text_input = false; + bool start_text_input = false; const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) { @@ -6637,7 +6908,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (tab_focus_requested || g.IO.KeyCtrl) { - start_text_input = true; + start_text_input = true; g.ScalarAsInputTextId = 0; } } @@ -6650,9 +6921,9 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); + char value_buf[64]; + const char *value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); @@ -6660,30 +6931,28 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c return value_changed; } -bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format, float power) +bool ImGui::VSliderFloat(const char *label, const ImVec2 &size, float *v, float v_min, float v_max, const char *display_format, + float power) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); - const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + const ImRect bb(frame_bb.Min, + frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(frame_bb, &id)) - return false; + if (!ItemAdd(frame_bb, &id)) return false; const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); + if (hovered) SetHoveredID(id); - if (!display_format) - display_format = "%.3f"; + if (!display_format) display_format = "%.3f"; int decimal_precision = ParseFormatPrecision(display_format, 3); if (hovered && g.IO.MouseClicked[0]) @@ -6697,52 +6966,51 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding - char value_buf[64]; - char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f)); + char value_buf[64]; + char *value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, + ImVec2(0.5f, 0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); return value_changed; } -bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max) +bool ImGui::SliderAngle(const char *label, float *v_rad, float v_degrees_min, float v_degrees_max) { - float v_deg = (*v_rad) * 360.0f / (2*IM_PI); - bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); - *v_rad = v_deg * (2*IM_PI) / 360.0f; + float v_deg = (*v_rad) * 360.0f / (2 * IM_PI); + bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); + *v_rad = v_deg * (2 * IM_PI) / 360.0f; return value_changed; } -bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt(const char *label, int *v, int v_min, int v_max, const char *display_format) { - if (!display_format) - display_format = "%.0f"; - float v_f = (float)*v; - bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); - *v = (int)v_f; + if (!display_format) display_format = "%.0f"; + float v_f = (float)*v; + bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); + *v = (int)v_f; return value_changed; } -bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format) +bool ImGui::VSliderInt(const char *label, const ImVec2 &size, int *v, int v_min, int v_max, const char *display_format) { - if (!display_format) - display_format = "%.0f"; - float v_f = (float)*v; - bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); - *v = (int)v_f; + if (!display_format) display_format = "%.0f"; + float v_f = (float)*v; + bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); + *v = (int)v_f; return value_changed; } // Add multiple sliders on 1 line for compact edition of multiple components -bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloatN(const char *label, float *v, int components, float v_min, float v_max, const char *display_format, + float power) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - bool value_changed = false; + ImGuiContext &g = *GImGui; + bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components); @@ -6762,29 +7030,28 @@ bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_mi return value_changed; } -bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat2(const char *label, float v[2], float v_min, float v_max, const char *display_format, float power) { return SliderFloatN(label, v, 2, v_min, v_max, display_format, power); } -bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat3(const char *label, float v[3], float v_min, float v_max, const char *display_format, float power) { return SliderFloatN(label, v, 3, v_min, v_max, display_format, power); } -bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat4(const char *label, float v[4], float v_min, float v_max, const char *display_format, float power) { return SliderFloatN(label, v, 4, v_min, v_max, display_format, power); } -bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format) +bool ImGui::SliderIntN(const char *label, int *v, int components, int v_min, int v_max, const char *display_format) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - bool value_changed = false; + ImGuiContext &g = *GImGui; + bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components); @@ -6804,28 +7071,30 @@ bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int return value_changed; } -bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt2(const char *label, int v[2], int v_min, int v_max, const char *display_format) { return SliderIntN(label, v, 2, v_min, v_max, display_format); } -bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt3(const char *label, int v[3], int v_min, int v_max, const char *display_format) { return SliderIntN(label, v, 3, v_min, v_max, display_format); } -bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt4(const char *label, int v[4], int v_min, int v_max, const char *display_format) { return SliderIntN(label, v, 4, v_min, v_max, display_format); } -bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) +bool ImGui::DragBehavior(const ImRect &frame_bb, ImGuiID id, float *v, float v_speed, float v_min, float v_max, + int decimal_precision, float power) { - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = + GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); bool value_changed = false; @@ -6838,32 +7107,30 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (g.ActiveIdIsJustActivated) { // Lock current value on click - g.DragCurrentValue = *v; + g.DragCurrentValue = *v; g.DragLastMouseDelta = ImVec2(0.f, 0.f); } - float v_cur = g.DragCurrentValue; + float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) { float speed = v_speed; if (speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) speed = (v_max - v_min) * g.DragSpeedDefaultRatio; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - speed = speed * g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - speed = speed * g.DragSpeedScaleSlow; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) speed = speed * g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) speed = speed * g.DragSpeedScaleSlow; float delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; if (fabsf(power - 1.0f) > 0.001f) { // Logarithmic curve on both side of 0.0 - float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; + float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; - float v1 = powf(v0_abs, 1.0f / power) + (delta * v0_sign); - float v1_abs = v1 >= 0.0f ? v1 : -v1; - float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line - v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign + float v1 = powf(v0_abs, 1.0f / power) + (delta * v0_sign); + float v1_abs = v1 >= 0.0f ? v1 : -v1; + float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line + v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign } else { @@ -6872,8 +7139,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s g.DragLastMouseDelta.x = mouse_drag_delta.x; // Clamp - if (v_min < v_max) - v_cur = ImClamp(v_cur, v_min, v_max); + if (v_min < v_max) v_cur = ImClamp(v_cur, v_min, v_max); g.DragCurrentValue = v_cur; } @@ -6881,7 +7147,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s v_cur = RoundScalar(v_cur, decimal_precision); if (*v != v_cur) { - *v = v_cur; + *v = v_cur; value_changed = true; } } @@ -6894,21 +7160,22 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s return value_changed; } -bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat(const char *label, float *v, float v_speed, float v_min, float v_max, const char *display_format, + float power) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + const ImRect total_bb(frame_bb.Min, + frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); // NB- we don't call ItemSize() yet because we may turn into a text edit box below if (!ItemAdd(total_bb, &id)) @@ -6918,15 +7185,13 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f } const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); + if (hovered) SetHoveredID(id); - if (!display_format) - display_format = "%.3f"; + if (!display_format) display_format = "%.3f"; int decimal_precision = ParseFormatPrecision(display_format, 3); // Tabbing or CTRL-clicking on Drag turns it into an input box - bool start_text_input = false; + bool start_text_input = false; const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] | g.IO.MouseDoubleClicked[0]))) { @@ -6935,7 +7200,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0]) { - start_text_input = true; + start_text_input = true; g.ScalarAsInputTextId = 0; } } @@ -6947,24 +7212,23 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f const bool value_changed = DragBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); + char value_buf[64]; + const char *value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); + if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); return value_changed; } -bool ImGui::DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloatN(const char *label, float *v, int components, float v_speed, float v_min, float v_max, + const char *display_format, float power) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - bool value_changed = false; + ImGuiContext &g = *GImGui; + bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components); @@ -6984,36 +7248,42 @@ bool ImGui::DragFloatN(const char* label, float* v, int components, float v_spee return value_changed; } -bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat2(const char *label, float v[2], float v_speed, float v_min, float v_max, const char *display_format, + float power) { return DragFloatN(label, v, 2, v_speed, v_min, v_max, display_format, power); } -bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat3(const char *label, float v[3], float v_speed, float v_min, float v_max, const char *display_format, + float power) { return DragFloatN(label, v, 3, v_speed, v_min, v_max, display_format, power); } -bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat4(const char *label, float v[4], float v_speed, float v_min, float v_max, const char *display_format, + float power) { return DragFloatN(label, v, 4, v_speed, v_min, v_max, display_format, power); } -bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* display_format, const char* display_format_max, float power) +bool ImGui::DragFloatRange2(const char *label, float *v_current_min, float *v_current_max, float v_speed, float v_min, + float v_max, const char *display_format, const char *display_format_max, float power) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; PushID(label); BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power); + bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, + (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power); + value_changed |= + DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), + (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); @@ -7025,24 +7295,22 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu } // NB: v_speed is float to allow adjusting the drag speed with more precision -bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt(const char *label, int *v, float v_speed, int v_min, int v_max, const char *display_format) { - if (!display_format) - display_format = "%.0f"; - float v_f = (float)*v; - bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); - *v = (int)v_f; + if (!display_format) display_format = "%.0f"; + float v_f = (float)*v; + bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); + *v = (int)v_f; return value_changed; } -bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragIntN(const char *label, int *v, int components, float v_speed, int v_min, int v_max, const char *display_format) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - bool value_changed = false; + ImGuiContext &g = *GImGui; + bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components); @@ -7062,36 +7330,38 @@ bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, i return value_changed; } -bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt2(const char *label, int v[2], float v_speed, int v_min, int v_max, const char *display_format) { return DragIntN(label, v, 2, v_speed, v_min, v_max, display_format); } -bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt3(const char *label, int v[3], float v_speed, int v_min, int v_max, const char *display_format) { return DragIntN(label, v, 3, v_speed, v_min, v_max, display_format); } -bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt4(const char *label, int v[4], float v_speed, int v_min, int v_max, const char *display_format) { return DragIntN(label, v, 4, v_speed, v_min, v_max, display_format); } -bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* display_format, const char* display_format_max) +bool ImGui::DragIntRange2(const char *label, int *v_current_min, int *v_current_max, float v_speed, int v_min, int v_max, + const char *display_format, const char *display_format_max) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; PushID(label); BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); + bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, + (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); + value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), + (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); @@ -7102,27 +7372,26 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_ return value_changed; } -void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +void ImGui::PlotEx(ImGuiPlotType plot_type, const char *label, float (*values_getter)(void *data, int idx), void *data, + int values_count, int values_offset, const char *overlay_text, float scale_min, float scale_max, + ImVec2 graph_size) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; const ImVec2 label_size = CalcTextSize(label, NULL, true); - if (graph_size.x == 0.0f) - graph_size.x = CalcItemWidth(); - if (graph_size.y == 0.0f) - graph_size.y = label_size.y + (style.FramePadding.y * 2); + if (graph_size.x == 0.0f) graph_size.x = CalcItemWidth(); + if (graph_size.y == 0.0f) graph_size.y = label_size.y + (style.FramePadding.y * 2); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y)); const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); + const ImRect total_bb(frame_bb.Min, + frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, NULL)) - return; + if (!ItemAdd(total_bb, NULL)) return; // Determine scale from values if not specified if (scale_min == FLT_MAX || scale_max == FLT_MAX) @@ -7132,34 +7401,32 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge for (int i = 0; i < values_count; i++) { const float v = values_getter(data, i); - v_min = ImMin(v_min, v); - v_max = ImMax(v_max, v); + v_min = ImMin(v_min, v); + v_max = ImMax(v_max, v); } - if (scale_min == FLT_MAX) - scale_min = v_min; - if (scale_max == FLT_MAX) - scale_max = v_max; + if (scale_min == FLT_MAX) scale_min = v_min; + if (scale_max == FLT_MAX) scale_max = v_max; } RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); if (values_count > 0) { - int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); + int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); // Tooltip on hover int v_hovered = -1; if (IsHovered(inner_bb, 0)) { - const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); - const int v_idx = (int)(t * item_count); + const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); + const int v_idx = (int)(t * item_count); IM_ASSERT(v_idx >= 0 && v_idx < values_count); const float v0 = values_getter(data, (v_idx + values_offset) % values_count); const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); if (plot_type == ImGuiPlotType_Lines) - SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1); + SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx + 1, v1); else if (plot_type == ImGuiPlotType_Histogram) SetTooltip("%d: %8.4g", v_idx, v0); v_hovered = v_idx; @@ -7167,100 +7434,111 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge const float t_step = 1.0f / (float)res_w; - float v0 = values_getter(data, (0 + values_offset) % values_count); - float t0 = 0.0f; - ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) ); // Point in the normalized space of our target rectangle + float v0 = values_getter(data, (0 + values_offset) % values_count); + float t0 = 0.0f; + ImVec2 tp0 = + ImVec2(t0, 1.0f - ImSaturate((v0 - scale_min) / + (scale_max - scale_min))); // Point in the normalized space of our target rectangle const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram); - const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); + const ImU32 col_hovered = + GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); for (int n = 0; n < res_w; n++) { - const float t1 = t0 + t_step; - const int v1_idx = (int)(t0 * item_count + 0.5f); + const float t1 = t0 + t_step; + const int v1_idx = (int)(t0 * item_count + 0.5f); IM_ASSERT(v1_idx >= 0 && v1_idx < values_count); - const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); - const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) ); + const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); + const ImVec2 tp1 = ImVec2(t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min))); - // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. + // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to + // save a bit of CPU. ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f)); if (plot_type == ImGuiPlotType_Lines) - { - window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); - } + { window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); } else if (plot_type == ImGuiPlotType_Histogram) { - if (pos1.x >= pos0.x + 2.0f) - pos1.x -= 1.0f; + if (pos1.x >= pos0.x + 2.0f) pos1.x -= 1.0f; window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); } - t0 = t1; + t0 = t1; tp0 = tp1; } } // Text overlay if (overlay_text) - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f)); + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, + ImVec2(0.5f, 0.0f)); - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); + if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); } struct ImGuiPlotArrayGetterData { - const float* Values; - int Stride; + const float *Values; + int Stride; - ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; } + ImGuiPlotArrayGetterData(const float *values, int stride) + { + Values = values; + Stride = stride; + } }; -static float Plot_ArrayGetter(void* data, int idx) +static float Plot_ArrayGetter(void *data, int idx) { - ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data; - const float v = *(float*)(void*)((unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); + ImGuiPlotArrayGetterData *plot_data = (ImGuiPlotArrayGetterData *)data; + const float v = *(float *)(void *)((unsigned char *)plot_data->Values + (size_t)idx * plot_data->Stride); return v; } -void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) +void ImGui::PlotLines(const char *label, const float *values, int values_count, int values_offset, const char *overlay_text, + float scale_min, float scale_max, ImVec2 graph_size, int stride) { ImGuiPlotArrayGetterData data(values, stride); - PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); + PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void *)&data, values_count, values_offset, overlay_text, scale_min, + scale_max, graph_size); } -void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +void ImGui::PlotLines(const char *label, float (*values_getter)(void *data, int idx), void *data, int values_count, + int values_offset, const char *overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { - PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); + PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, + graph_size); } -void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) +void ImGui::PlotHistogram(const char *label, const float *values, int values_count, int values_offset, const char *overlay_text, + float scale_min, float scale_max, ImVec2 graph_size, int stride) { ImGuiPlotArrayGetterData data(values, stride); - PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); + PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void *)&data, values_count, values_offset, overlay_text, scale_min, + scale_max, graph_size); } -void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +void ImGui::PlotHistogram(const char *label, float (*values_getter)(void *data, int idx), void *data, int values_count, + int values_offset, const char *overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { - PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); + PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, + graph_size); } // size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size -void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) +void ImGui::ProgressBar(float fraction, const ImVec2 &size_arg, const char *overlay) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; ImVec2 pos = window->DC.CursorPos; - ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f)); + ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f)); ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(bb, NULL)) - return; + if (!ItemAdd(bb, NULL)) return; // Render fraction = ImSaturate(fraction); @@ -7273,66 +7551,68 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over char overlay_buf[32]; if (!overlay) { - ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f); + ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f); overlay = overlay_buf; } ImVec2 overlay_size = CalcTextSize(overlay, NULL); if (overlay_size.x > 0.0f) - RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb); + RenderTextClipped( + ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), + bb.Min.y), + bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb); } -bool ImGui::Checkbox(const char* label, bool* v) +bool ImGui::Checkbox(const char *label, bool *v) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); + const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y * 2, + label_size.y + style.FramePadding.y * 2)); ItemSize(check_bb, style.FramePadding.y); ImRect total_bb = check_bb; - if (label_size.x > 0) - SameLine(0, style.ItemInnerSpacing.x); - const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size); + if (label_size.x > 0) SameLine(0, style.ItemInnerSpacing.x); + const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), + window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size); if (label_size.x > 0) { ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max)); } - if (!ItemAdd(total_bb, &id)) - return false; + if (!ItemAdd(total_bb, &id)) return false; bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) - *v = !(*v); + if (pressed) *v = !(*v); - RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + RenderFrame(check_bb.Min, check_bb.Max, + GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), + true, style.FrameRounding); if (*v) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); - const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); - window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), style.FrameRounding); + const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); + window->DrawList->AddRectFilled(check_bb.Min + ImVec2(pad, pad), check_bb.Max - ImVec2(pad, pad), + GetColorU32(ImGuiCol_CheckMark), style.FrameRounding); } - if (g.LogEnabled) - LogRenderedText(text_bb.GetTL(), *v ? "[x]" : "[ ]"); - if (label_size.x > 0.0f) - RenderText(text_bb.GetTL(), label); + if (g.LogEnabled) LogRenderedText(text_bb.GetTL(), *v ? "[x]" : "[ ]"); + if (label_size.x > 0.0f) RenderText(text_bb.GetTL(), label); return pressed; } -bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) +bool ImGui::CheckboxFlags(const char *label, unsigned int *flags, unsigned int flags_value) { - bool v = ((*flags & flags_value) == flags_value); + bool v = ((*flags & flags_value) == flags_value); bool pressed = Checkbox(label, &v); if (pressed) { @@ -7345,97 +7625,92 @@ bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int f return pressed; } -bool ImGui::RadioButton(const char* label, bool active) +bool ImGui::RadioButton(const char *label, bool active) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1)); + const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y * 2 - 1, + label_size.y + style.FramePadding.y * 2 - 1)); ItemSize(check_bb, style.FramePadding.y); ImRect total_bb = check_bb; - if (label_size.x > 0) - SameLine(0, style.ItemInnerSpacing.x); - const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size); + if (label_size.x > 0) SameLine(0, style.ItemInnerSpacing.x); + const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), + window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size); if (label_size.x > 0) { ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); total_bb.Add(text_bb); } - if (!ItemAdd(total_bb, &id)) - return false; + if (!ItemAdd(total_bb, &id)) return false; - ImVec2 center = check_bb.GetCenter(); - center.x = (float)(int)center.x + 0.5f; - center.y = (float)(int)center.y + 0.5f; + ImVec2 center = check_bb.GetCenter(); + center.x = (float)(int)center.x + 0.5f; + center.y = (float)(int)center.y + 0.5f; const float radius = check_bb.GetHeight() * 0.5f; bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); + window->DrawList->AddCircleFilled( + center, radius, + GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); if (active) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); - const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); - window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16); + const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); + window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16); } if (window->Flags & ImGuiWindowFlags_ShowBorders) { - window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16); + window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16); window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16); } - if (g.LogEnabled) - LogRenderedText(text_bb.GetTL(), active ? "(x)" : "( )"); - if (label_size.x > 0.0f) - RenderText(text_bb.GetTL(), label); + if (g.LogEnabled) LogRenderedText(text_bb.GetTL(), active ? "(x)" : "( )"); + if (label_size.x > 0.0f) RenderText(text_bb.GetTL(), label); return pressed; } -bool ImGui::RadioButton(const char* label, int* v, int v_button) +bool ImGui::RadioButton(const char *label, int *v, int v_button) { const bool pressed = RadioButton(label, *v == v_button); - if (pressed) - { - *v = v_button; - } + if (pressed) { *v = v_button; } return pressed; } -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) +static int InputTextCalcTextLenAndLineCount(const char *text_begin, const char **out_text_end) { - int line_count = 0; - const char* s = text_begin; + int line_count = 0; + const char *s = text_begin; while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding - if (c == '\n') - line_count++; + if (c == '\n') line_count++; s--; - if (s[0] != '\n' && s[0] != '\r') - line_count++; + if (s[0] != '\n' && s[0] != '\r') line_count++; *out_text_end = s; return line_count; } -static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line) +static ImVec2 InputTextCalcTextSizeW(const ImWchar *text_begin, const ImWchar *text_end, const ImWchar **remaining, + ImVec2 *out_offset, bool stop_on_new_line) { - ImFont* font = GImGui->Font; + ImFont * font = GImGui->Font; const float line_height = GImGui->FontSize; - const float scale = line_height / font->FontSize; + const float scale = line_height / font->FontSize; - ImVec2 text_size = ImVec2(0,0); - float line_width = 0.0f; + ImVec2 text_size = ImVec2(0, 0); + float line_width = 0.0f; - const ImWchar* s = text_begin; + const ImWchar *s = text_begin; while (s < text_end) { unsigned int c = (unsigned int)(*s++); @@ -7444,125 +7719,165 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t text_size.x = ImMax(text_size.x, line_width); text_size.y += line_height; line_width = 0.0f; - if (stop_on_new_line) - break; + if (stop_on_new_line) break; continue; } - if (c == '\r') - continue; + if (c == '\r') continue; const float char_width = font->GetCharAdvance((unsigned short)c) * scale; line_width += char_width; } - if (text_size.x < line_width) - text_size.x = line_width; + if (text_size.x < line_width) text_size.x = line_width; if (out_offset) - *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n + *out_offset = + ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n - if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n + if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n text_size.y += line_height; - if (remaining) - *remaining = s; + if (remaining) *remaining = s; return text_size; } -// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar) +// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText +// converts between UTF-8 and wchar) namespace ImGuiStb { -static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; } -static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->Text[idx]; } -static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->Text[line_start_idx+char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); } -static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; } -static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; -static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx) -{ - const ImWchar* text = obj->Text.Data; - const ImWchar* text_remaining = NULL; - const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true); - r->x0 = 0.0f; - r->x1 = size.x; - r->baseline_y_delta = size.y; - r->ymin = 0.0f; - r->ymax = size.y; - r->num_chars = (int)(text_remaining - (text + line_start_idx)); -} - -static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } -static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } -#ifdef __APPLE__ // FIXME: Move setting to IO structure -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } -static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } + static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING *obj) + { + return obj->CurLenW; + } + static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING *obj, int idx) + { + return obj->Text[idx]; + } + static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING *obj, int line_start_idx, int char_idx) + { + ImWchar c = obj->Text[line_start_idx + char_idx]; + if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; + return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); + } + static int STB_TEXTEDIT_KEYTOTEXT(int key) + { + return key >= 0x10000 ? 0 : key; + } + static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; + static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow *r, STB_TEXTEDIT_STRING *obj, int line_start_idx) + { + const ImWchar *text = obj->Text.Data; + const ImWchar *text_remaining = NULL; + const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true); + r->x0 = 0.0f; + r->x1 = size.x; + r->baseline_y_delta = size.y; + r->ymin = 0.0f; + r->ymax = size.y; + r->num_chars = (int)(text_remaining - (text + line_start_idx)); + } + + static bool is_separator(unsigned int c) + { + return ImCharIsSpace(c) || c == ',' || c == ';' || c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || + c == '|'; + } + static int is_word_boundary_from_right(STB_TEXTEDIT_STRING *obj, int idx) + { + return idx > 0 ? (is_separator(obj->Text[idx - 1]) && !is_separator(obj->Text[idx])) : 1; + } + static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING *obj, int idx) + { + idx--; + while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) + idx--; + return idx < 0 ? 0 : idx; + } +#ifdef __APPLE__ // FIXME: Move setting to IO structure + static int is_word_boundary_from_left(STB_TEXTEDIT_STRING *obj, int idx) + { + return idx > 0 ? (!is_separator(obj->Text[idx - 1]) && is_separator(obj->Text[idx])) : 1; + } + static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING *obj, int idx) + { + idx++; + int len = obj->CurLenW; + while (idx < len && !is_word_boundary_from_left(obj, idx)) + idx++; + return idx > len ? len : idx; + } #else -static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } + static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING *obj, int idx) + { + idx++; + int len = obj->CurLenW; + while (idx < len && !is_word_boundary_from_right(obj, idx)) + idx++; + return idx > len ? len : idx; + } #endif -#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h -#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL +#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h +#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL -static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) -{ - ImWchar* dst = obj->Text.Data + pos; + static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING *obj, int pos, int n) + { + ImWchar *dst = obj->Text.Data + pos; - // We maintain our buffer length in both UTF-8 and wchar formats - obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); - obj->CurLenW -= n; + // We maintain our buffer length in both UTF-8 and wchar formats + obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); + obj->CurLenW -= n; - // Offset remaining text - const ImWchar* src = obj->Text.Data + pos + n; - while (ImWchar c = *src++) - *dst++ = c; - *dst = '\0'; -} + // Offset remaining text + const ImWchar *src = obj->Text.Data + pos + n; + while (ImWchar c = *src++) + *dst++ = c; + *dst = '\0'; + } -static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len) -{ - const int text_len = obj->CurLenW; - IM_ASSERT(pos <= text_len); - if (new_text_len + text_len + 1 > obj->Text.Size) - return false; + static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING *obj, int pos, const ImWchar *new_text, int new_text_len) + { + const int text_len = obj->CurLenW; + IM_ASSERT(pos <= text_len); + if (new_text_len + text_len + 1 > obj->Text.Size) return false; - const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len); - if (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA) - return false; + const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len); + if (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA) return false; - ImWchar* text = obj->Text.Data; - if (pos != text_len) - memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar)); - memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar)); + ImWchar *text = obj->Text.Data; + if (pos != text_len) memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar)); + memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar)); - obj->CurLenW += new_text_len; - obj->CurLenA += new_text_len_utf8; - obj->Text[obj->CurLenW] = '\0'; + obj->CurLenW += new_text_len; + obj->CurLenA += new_text_len_utf8; + obj->Text[obj->CurLenW] = '\0'; - return true; -} + return true; + } -// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) -#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left -#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right -#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up -#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down -#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line -#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line -#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text -#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text -#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor -#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor -#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo -#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo -#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word -#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word -#define STB_TEXTEDIT_K_SHIFT 0x20000 +// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their +// STB_TEXTEDIT_K_* symbols) +#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left +#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right +#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up +#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down +#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line +#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line +#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text +#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text +#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor +#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor +#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo +#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo +#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word +#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word +#define STB_TEXTEDIT_K_SHIFT 0x20000 #define STB_TEXTEDIT_IMPLEMENTATION #include "stb_textedit.h" -} +} // namespace ImGuiStb void ImGuiTextEditState::OnKeyPressed(int key) { @@ -7577,8 +7892,8 @@ void ImGuiTextEditState::OnKeyPressed(int key) void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count) { IM_ASSERT(pos + bytes_count <= BufTextLen); - char* dst = Buf + pos; - const char* src = Buf + pos + bytes_count; + char * dst = Buf + pos; + const char *src = Buf + pos + bytes_count; while (char c = *src++) *dst++ = c; *dst = '\0'; @@ -7588,30 +7903,28 @@ void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count) else if (CursorPos >= pos) CursorPos = pos; SelectionStart = SelectionEnd = CursorPos; - BufDirty = true; + BufDirty = true; BufTextLen -= bytes_count; } -void ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end) +void ImGuiTextEditCallbackData::InsertChars(int pos, const char *new_text, const char *new_text_end) { const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text); - if (new_text_len + BufTextLen + 1 >= BufSize) - return; + if (new_text_len + BufTextLen + 1 >= BufSize) return; - if (BufTextLen != pos) - memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos)); + if (BufTextLen != pos) memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos)); memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char)); Buf[BufTextLen + new_text_len] = '\0'; - if (CursorPos >= pos) - CursorPos += new_text_len; + if (CursorPos >= pos) CursorPos += new_text_len; SelectionStart = SelectionEnd = CursorPos; - BufDirty = true; + BufDirty = true; BufTextLen += new_text_len; } // Return false to discard a character. -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +static bool InputTextFilterCharacter(unsigned int *p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, + void *user_data) { unsigned int c = *p_char; @@ -7620,30 +7933,27 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f bool pass = false; pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); - if (!pass) - return false; + if (!pass) return false; } - if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys. + if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX + // seems to send private characters for special keys like arrow keys. return false; - if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank)) + if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | + ImGuiInputTextFlags_CharsNoBlank)) { if (flags & ImGuiInputTextFlags_CharsDecimal) - if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/')) - return false; + if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/')) return false; if (flags & ImGuiInputTextFlags_CharsHexadecimal) - if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) - return false; + if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) return false; if (flags & ImGuiInputTextFlags_CharsUppercase) - if (c >= 'a' && c <= 'z') - *p_char = (c += (unsigned int)('A'-'a')); + if (c >= 'a' && c <= 'z') *p_char = (c += (unsigned int)('A' - 'a')); if (flags & ImGuiInputTextFlags_CharsNoBlank) - if (ImCharIsSpace(c)) - return false; + if (ImCharIsSpace(c)) return false; } if (flags & ImGuiInputTextFlags_CallbackCharFilter) @@ -7652,47 +7962,52 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; callback_data.EventChar = (ImWchar)c; - callback_data.Flags = flags; - callback_data.UserData = user_data; - if (callback(&callback_data) != 0) - return false; + callback_data.Flags = flags; + callback_data.UserData = user_data; + if (callback(&callback_data) != 0) return false; *p_char = callback_data.EventChar; - if (!callback_data.EventChar) - return false; + if (!callback_data.EventChar) return false; } return true; } // Edit a string of text -// NB: when active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while active has no effect. -// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188 -bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +// NB: when active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while active has no +// effect. +// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle +// stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188 +bool ImGui::InputTextEx(const char *label, char *buf, int buf_size, const ImVec2 &size_arg, ImGuiInputTextFlags flags, + ImGuiTextEditCallback callback, void *user_data) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) - IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) + IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && + (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) + IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && + (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) - ImGuiContext& g = *GImGui; - const ImGuiIO& io = g.IO; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiIO & io = g.IO; + const ImGuiStyle &style = g.Style; const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; - const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; - const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; + const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; + const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn BeginGroup(); - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); - - ImGuiWindow* draw_window = window; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), + (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); + const ImRect total_bb(frame_bb.Min, + frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); + + ImGuiWindow *draw_window = window; if (is_multiline) { if (!BeginChildFrame(id, frame_bb.GetSize())) @@ -7707,33 +8022,35 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else { ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, &id)) - return false; + if (!ItemAdd(total_bb, &id)) return false; } // Password pushes a temporary font with only a fallback glyph if (is_password) { - const ImFont::Glyph* glyph = g.Font->FindGlyph('*'); - ImFont* password_font = &g.InputTextPasswordFont; - password_font->FontSize = g.Font->FontSize; - password_font->Scale = g.Font->Scale; - password_font->DisplayOffset = g.Font->DisplayOffset; - password_font->Ascent = g.Font->Ascent; - password_font->Descent = g.Font->Descent; - password_font->ContainerAtlas = g.Font->ContainerAtlas; - password_font->FallbackGlyph = glyph; - password_font->FallbackXAdvance = glyph->XAdvance; + const ImFont::Glyph *glyph = g.Font->FindGlyph('*'); + ImFont * password_font = &g.InputTextPasswordFont; + password_font->FontSize = g.Font->FontSize; + password_font->Scale = g.Font->Scale; + password_font->DisplayOffset = g.Font->DisplayOffset; + password_font->Ascent = g.Font->Ascent; + password_font->Descent = g.Font->Descent; + password_font->ContainerAtlas = g.Font->ContainerAtlas; + password_font->FallbackGlyph = glyph; + password_font->FallbackXAdvance = glyph->XAdvance; IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexXAdvance.empty() && password_font->IndexLookup.empty()); PushFont(password_font); } // NB: we are only allowed to access 'edit_state' if we are the active widget. - ImGuiTextEditState& edit_state = g.InputTextState; + ImGuiTextEditState &edit_state = g.InputTextState; - const bool focus_requested = FocusableItemRegister(window, g.ActiveId == id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing + const bool focus_requested = + FocusableItemRegister(window, g.ActiveId == id, + (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) == + 0); // Using completion callback disable keyboard tabbing const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); - const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; + const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; const bool hovered = IsHovered(frame_bb, id); if (hovered) @@ -7741,8 +8058,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 SetHoveredID(id); g.MouseCursor = ImGuiMouseCursor_TextInput; } - const bool user_clicked = hovered && io.MouseClicked[0]; - const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); + const bool user_clicked = hovered && io.MouseClicked[0]; + const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && + g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0; if (focus_requested || user_clicked || user_scrolled) @@ -7753,16 +8071,20 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) const int prev_len_w = edit_state.CurLenW; - edit_state.Text.resize(buf_size+1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash. - edit_state.InitialText.resize(buf_size+1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash. + edit_state.Text.resize( + buf_size + 1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash. + edit_state.InitialText.resize(buf_size + + 1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash. ImStrncpy(edit_state.InitialText.Data, buf, edit_state.InitialText.Size); - const char* buf_end = NULL; - edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); - edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8. + const char *buf_end = NULL; + edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); + edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not + // UTF-8 aware. Here we'll cut off malformed UTF-8. edit_state.CursorAnimReset(); // Preserve cursor position and undo/redo stack if we come back to same widget - // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and edit_state.Text (wchar). + // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and + // edit_state.Text (wchar). const bool recycle_state = (edit_state.Id == id) && (prev_len_w == edit_state.CurLenW); if (recycle_state) { @@ -7772,16 +8094,13 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } else { - edit_state.Id = id; + edit_state.Id = id; edit_state.ScrollX = 0.0f; stb_textedit_initialize_state(&edit_state.StbState, !is_multiline); - if (!is_multiline && focus_requested_by_code) - select_all = true; + if (!is_multiline && focus_requested_by_code) select_all = true; } - if (flags & ImGuiInputTextFlags_AlwaysInsertMode) - edit_state.StbState.insert_mode = true; - if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl))) - select_all = true; + if (flags & ImGuiInputTextFlags_AlwaysInsertMode) edit_state.StbState.insert_mode = true; + if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl))) select_all = true; } SetActiveID(id, window); FocusWindow(window); @@ -7789,8 +8108,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (io.MouseClicked[0]) { // Release focus when we click outside - if (g.ActiveId == id) - ClearActiveID(); + if (g.ActiveId == id) ClearActiveID(); } bool value_changed = false; @@ -7801,24 +8119,26 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (!is_editable && !g.ActiveIdIsJustActivated) { // When read-only we always use the live data passed to the function - edit_state.Text.resize(buf_size+1); - const char* buf_end = NULL; - edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); - edit_state.CurLenA = (int)(buf_end - buf); + edit_state.Text.resize(buf_size + 1); + const char *buf_end = NULL; + edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); + edit_state.CurLenA = (int)(buf_end - buf); edit_state.CursorClamp(); } edit_state.BufSizeA = buf_size; - // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. - // Down the line we should have a cleaner library-wide concept of Selected vs Active. + // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the + // widget. Down the line we should have a cleaner library-wide concept of Selected vs Active. g.ActiveIdAllowOverlap = !io.MouseDown[0]; // Edit in progress const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; - const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f)); + const float mouse_y = + (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize * 0.5f)); - const bool osx_double_click_selects_words = io.OSXBehaviors; // OS X style: Double click selects by word instead of selecting whole text + const bool osx_double_click_selects_words = + io.OSXBehaviors; // OS X style: Double click selects by word instead of selecting whole text if (select_all || (hovered && !osx_double_click_selects_words && io.MouseDoubleClicked[0])) { edit_state.SelectAll(); @@ -7841,21 +8161,20 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 edit_state.CursorAnimReset(); edit_state.CursorFollow = true; } - if (edit_state.SelectedAllMouseLock && !io.MouseDown[0]) - edit_state.SelectedAllMouseLock = false; + if (edit_state.SelectedAllMouseLock && !io.MouseDown[0]) edit_state.SelectedAllMouseLock = false; if (io.InputCharacters[0]) { // Process text input (before we check for Return because using some IME will effectively send a Return?) - // We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - to input certain characters. + // We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - + // to input certain characters. if (!(io.KeyCtrl && !io.KeyAlt) && is_editable) { for (int n = 0; n < IM_ARRAYSIZE(io.InputCharacters) && io.InputCharacters[n]; n++) if (unsigned int c = (unsigned int)io.InputCharacters[n]) { // Insert character if they pass filtering - if (!InputTextFilterCharacter(&c, flags, callback, user_data)) - continue; + if (!InputTextFilterCharacter(&c, flags, callback, user_data)) continue; edit_state.OnKeyPressed((int)c); } } @@ -7865,25 +8184,63 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } // Handle various key-presses - bool cancel_edit = false; - const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); - const bool is_shortcut_key_only = (io.OSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl - const bool is_wordmove_key_down = io.OSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl - const bool is_startend_key_down = io.OSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End - - if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } + bool cancel_edit = false; + const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); + const bool is_shortcut_key_only = (io.OSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && + !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl + const bool is_wordmove_key_down = + io.OSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl + const bool is_startend_key_down = io.OSXBehaviors && io.KeySuper && !io.KeyCtrl && + !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End + + if (IsKeyPressedMap(ImGuiKey_LeftArrow)) + { + edit_state.OnKeyPressed((is_startend_key_down + ? STB_TEXTEDIT_K_LINESTART + : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | + k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_RightArrow)) + { + edit_state.OnKeyPressed((is_startend_key_down + ? STB_TEXTEDIT_K_LINEEND + : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | + k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) + { + if (io.KeyCtrl) + SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); + else + edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) + { + if (io.KeyCtrl) + SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); + else + edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_Home)) + { + edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_End)) + { + edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) + { + edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); + } else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) { if (!edit_state.HasSelection()) { - if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT); - else if (io.OSXBehaviors && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT); + if (is_wordmove_key_down) + edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT); + else if (io.OSXBehaviors && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) + edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT); } edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } @@ -7898,33 +8255,52 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (is_editable) { unsigned int c = '\n'; // Insert new line - if (InputTextFilterCharacter(&c, flags, callback, user_data)) - edit_state.OnKeyPressed((int)c); + if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } } - else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && !io.KeyAlt && is_editable) + else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && + !io.KeyAlt && is_editable) { unsigned int c = '\t'; // Insert TAB - if (InputTextFilterCharacter(&c, flags, callback, user_data)) - edit_state.OnKeyPressed((int)c); + if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } - else if (IsKeyPressedMap(ImGuiKey_Escape)) { ClearActiveID(); cancel_edit = true; } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } - else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection())) + else if (IsKeyPressedMap(ImGuiKey_Escape)) + { + ClearActiveID(); + cancel_edit = true; + } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) + { + edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); + edit_state.ClearSelection(); + } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) + { + edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); + edit_state.ClearSelection(); + } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) + { + edit_state.SelectAll(); + edit_state.CursorFollow = true; + } + else if (is_shortcut_key_only && !is_password && + ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && + (!is_multiline || edit_state.HasSelection())) { // Cut, Copy const bool cut = IsKeyPressedMap(ImGuiKey_X); - if (cut && !edit_state.HasSelection()) - edit_state.SelectAll(); + if (cut && !edit_state.HasSelection()) edit_state.SelectAll(); if (io.SetClipboardTextFn) { - const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; - const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW; - edit_state.TempTextBuffer.resize((ie-ib) * 4 + 1); - ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data+ib, edit_state.Text.Data+ie); + const int ib = + edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; + const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) + : edit_state.CurLenW; + edit_state.TempTextBuffer.resize((ie - ib) * 4 + 1); + ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data + ib, + edit_state.Text.Data + ie); SetClipboardText(edit_state.TempTextBuffer.Data); } @@ -7937,20 +8313,18 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V) && is_editable) { // Paste - if (const char* clipboard = GetClipboardText()) + if (const char *clipboard = GetClipboardText()) { // Filter pasted buffer - const int clipboard_len = (int)strlen(clipboard); - ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar)); - int clipboard_filtered_len = 0; - for (const char* s = clipboard; *s; ) + const int clipboard_len = (int)strlen(clipboard); + ImWchar * clipboard_filtered = (ImWchar *)ImGui::MemAlloc((clipboard_len + 1) * sizeof(ImWchar)); + int clipboard_filtered_len = 0; + for (const char *s = clipboard; *s;) { unsigned int c; s += ImTextCharFromUtf8(&c, s, NULL); - if (c == 0) - break; - if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, user_data)) - continue; + if (c == 0) break; + if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, user_data)) continue; clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; } clipboard_filtered[clipboard_filtered_len] = 0; @@ -7975,9 +8349,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else { // Apply new value immediately - copy modified buffer back - // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer + // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of + // the input buffer // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect. - // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks. + // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit + // callbacks. if (is_editable) { edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4); @@ -7985,27 +8361,29 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } // User callback - if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0) + if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | + ImGuiInputTextFlags_CallbackAlways)) != 0) { IM_ASSERT(callback != NULL); - // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment. + // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard + // TABBING at the moment. ImGuiInputTextFlags event_flag = 0; - ImGuiKey event_key = ImGuiKey_COUNT; + ImGuiKey event_key = ImGuiKey_COUNT; if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab)) { event_flag = ImGuiInputTextFlags_CallbackCompletion; - event_key = ImGuiKey_Tab; + event_key = ImGuiKey_Tab; } else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow)) { event_flag = ImGuiInputTextFlags_CallbackHistory; - event_key = ImGuiKey_UpArrow; + event_key = ImGuiKey_UpArrow; } else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow)) { event_flag = ImGuiInputTextFlags_CallbackHistory; - event_key = ImGuiKey_DownArrow; + event_key = ImGuiKey_DownArrow; } else if (flags & ImGuiInputTextFlags_CallbackAlways) event_flag = ImGuiInputTextFlags_CallbackAlways; @@ -8015,37 +8393,51 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 ImGuiTextEditCallbackData callback_data; memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); callback_data.EventFlag = event_flag; - callback_data.Flags = flags; - callback_data.UserData = user_data; - callback_data.ReadOnly = !is_editable; + callback_data.Flags = flags; + callback_data.UserData = user_data; + callback_data.ReadOnly = !is_editable; - callback_data.EventKey = event_key; - callback_data.Buf = edit_state.TempTextBuffer.Data; + callback_data.EventKey = event_key; + callback_data.Buf = edit_state.TempTextBuffer.Data; callback_data.BufTextLen = edit_state.CurLenA; - callback_data.BufSize = edit_state.BufSizeA; - callback_data.BufDirty = false; - - // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) - ImWchar* text = edit_state.Text.Data; - const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor); - const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start); - const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end); + callback_data.BufSize = edit_state.BufSizeA; + callback_data.BufDirty = false; + + // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch + // the ImWchar buffer, see https://github.com/nothings/stb/issues/188) + ImWchar * text = edit_state.Text.Data; + const int utf8_cursor_pos = callback_data.CursorPos = + ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor); + const int utf8_selection_start = callback_data.SelectionStart = + ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start); + const int utf8_selection_end = callback_data.SelectionEnd = + ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end); // Call user code callback(&callback_data); // Read back what user may have modified - IM_ASSERT(callback_data.Buf == edit_state.TempTextBuffer.Data); // Invalid to modify those fields + IM_ASSERT(callback_data.Buf == edit_state.TempTextBuffer.Data); // Invalid to modify those fields IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA); IM_ASSERT(callback_data.Flags == flags); - if (callback_data.CursorPos != utf8_cursor_pos) edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); - if (callback_data.SelectionStart != utf8_selection_start) edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); - if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); + if (callback_data.CursorPos != utf8_cursor_pos) + edit_state.StbState.cursor = + ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); + if (callback_data.SelectionStart != utf8_selection_start) + edit_state.StbState.select_start = + ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); + if (callback_data.SelectionEnd != utf8_selection_end) + edit_state.StbState.select_end = + ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); if (callback_data.BufDirty) { - IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! - edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, callback_data.Buf, NULL); - edit_state.CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() + IM_ASSERT(callback_data.BufTextLen == + (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! + edit_state.CurLenW = + ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, callback_data.Buf, NULL); + edit_state.CurLenA = + callback_data + .BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() edit_state.CursorAnimReset(); } } @@ -8061,36 +8453,41 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } // Render - // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. - const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; - - if (!is_multiline) - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - - const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size - ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; - ImVec2 text_size(0.f, 0.f); - const bool is_currently_scrolling = (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetIDNoKeepAlive("#SCROLLY")); + // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. + // We set buf to NULL to prevent accidental usage from now on. + const char *buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; + buf = NULL; + + if (!is_multiline) RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + + const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, + frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size + ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; + ImVec2 text_size(0.f, 0.f); + const bool is_currently_scrolling = + (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetIDNoKeepAlive("#SCROLLY")); if (g.ActiveId == id || is_currently_scrolling) { edit_state.CursorAnim += io.DeltaTime; // This is going to be messy. We need to: // - Display the text (this alone can be more easily clipped) - // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation) + // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position + // calculation) // - Measure text height (for scrollbar) - // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) + // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large + // amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. - const ImWchar* text_begin = edit_state.Text.Data; - ImVec2 cursor_offset, select_start_offset; + const ImWchar *text_begin = edit_state.Text.Data; + ImVec2 cursor_offset, select_start_offset; { // Count lines + find lines numbers straddling 'cursor' and 'select_start' position. - const ImWchar* searches_input_ptr[2]; - searches_input_ptr[0] = text_begin + edit_state.StbState.cursor; - searches_input_ptr[1] = NULL; - int searches_remaining = 1; - int searches_result_line_number[2] = { -1, -999 }; + const ImWchar *searches_input_ptr[2]; + searches_input_ptr[0] = text_begin + edit_state.StbState.cursor; + searches_input_ptr[1] = NULL; + int searches_remaining = 1; + int searches_result_line_number[2] = {-1, -999}; if (edit_state.StbState.select_start != edit_state.StbState.select_end) { searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); @@ -8099,15 +8496,24 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } // Iterate all lines to find our line numbers - // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. + // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining + // counter. searches_remaining += is_multiline ? 1 : 0; int line_count = 0; - for (const ImWchar* s = text_begin; *s != 0; s++) + for (const ImWchar *s = text_begin; *s != 0; s++) if (*s == '\n') { line_count++; - if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } - if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } + if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) + { + searches_result_line_number[0] = line_count; + if (--searches_remaining <= 0) break; + } + if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) + { + searches_result_line_number[1] = line_count; + if (--searches_remaining <= 0) break; + } } line_count++; if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; @@ -8118,13 +8524,13 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 cursor_offset.y = searches_result_line_number[0] * g.FontSize; if (searches_result_line_number[1] >= 0) { - select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; + select_start_offset.x = + InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; select_start_offset.y = searches_result_line_number[1] * g.FontSize; } // Calculate text height - if (is_multiline) - text_size = ImVec2(size.x, line_count * g.FontSize); + if (is_multiline) text_size = ImVec2(size.x, line_count * g.FontSize); } // Scroll @@ -8152,68 +8558,74 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); else if (cursor_offset.y - size.y >= scroll_y) scroll_y = cursor_offset.y - size.y; - draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // To avoid a frame of lag + draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // To avoid a frame of lag draw_window->Scroll.y = scroll_y; - render_pos.y = draw_window->DC.CursorPos.y; + render_pos.y = draw_window->DC.CursorPos.y; } } - edit_state.CursorFollow = false; + edit_state.CursorFollow = false; const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f); // Draw selection if (edit_state.StbState.select_start != edit_state.StbState.select_end) { - const ImWchar* text_selected_begin = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); - const ImWchar* text_selected_end = text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end); - - float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. - float bg_offy_dn = is_multiline ? 0.0f : 2.0f; - ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg); - ImVec2 rect_pos = render_pos + select_start_offset - render_scroll; - for (const ImWchar* p = text_selected_begin; p < text_selected_end; ) + const ImWchar *text_selected_begin = + text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); + const ImWchar *text_selected_end = + text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end); + + float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play + // so well with multi-line selection. + float bg_offy_dn = is_multiline ? 0.0f : 2.0f; + ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg); + ImVec2 rect_pos = render_pos + select_start_offset - render_scroll; + for (const ImWchar *p = text_selected_begin; p < text_selected_end;) { - if (rect_pos.y > clip_rect.w + g.FontSize) - break; + if (rect_pos.y > clip_rect.w + g.FontSize) break; if (rect_pos.y < clip_rect.y) { while (p < text_selected_end) - if (*p++ == '\n') - break; + if (*p++ == '\n') break; } else { ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); - if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * 0.50f); // So we can see selected empty lines - ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); + if (rect_size.x <= 0.0f) + rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * + 0.50f); // So we can see selected empty lines + ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn)); rect.Clip(clip_rect); - if (rect.Overlaps(clip_rect)) - draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); + if (rect.Overlaps(clip_rect)) draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); } rect_pos.x = render_pos.x - render_scroll.x; rect_pos.y += g.FontSize; } } - draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect); + draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, + buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect); // Draw blinking cursor - bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; + bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll; - ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f); + ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, + cursor_screen_pos.y - 1.5f); if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); - // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) - if (is_editable) - g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize); + // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an + // extra nicety.) + if (is_editable) g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize); } else { // Render text only - const char* buf_end = NULL; + const char *buf_end = NULL; if (is_multiline) - text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width - draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, is_multiline ? NULL : &clip_rect); + text_size = + ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width + draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, + is_multiline ? NULL : &clip_rect); } if (is_multiline) @@ -8223,12 +8635,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 EndGroup(); } - if (is_password) - PopFont(); + if (is_password) PopFont(); // Log as text - if (g.LogEnabled && !is_password) - LogRenderedText(render_pos, buf_display, NULL); + if (g.LogEnabled && !is_password) LogRenderedText(render_pos, buf_display, NULL); if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); @@ -8239,43 +8649,46 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 return value_changed; } -bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +bool ImGui::InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, + void *user_data) { IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() - return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data); + return InputTextEx(label, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); } -bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +bool ImGui::InputTextMultiline(const char *label, char *buf, size_t buf_size, const ImVec2 &size, ImGuiInputTextFlags flags, + ImGuiTextEditCallback callback, void *user_data) { return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } -// NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "display_format" argument) -bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags) +// NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions +// "display_format" argument) +bool ImGui::InputScalarEx(const char *label, ImGuiDataType data_type, void *data_ptr, void *step_ptr, void *step_fast_ptr, + const char *scalar_format, ImGuiInputTextFlags extra_flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImVec2 label_size = CalcTextSize(label, NULL, true); BeginGroup(); PushID(label); - const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding*2.0f; - if (step_ptr) - PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); + const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding * 2.0f; + if (step_ptr) PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x) * 2)); char buf[64]; DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf)); bool value_changed = false; - if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal)) - extra_flags |= ImGuiInputTextFlags_CharsDecimal; + if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal)) extra_flags |= ImGuiInputTextFlags_CharsDecimal; extra_flags |= ImGuiInputTextFlags_AutoSelectAll; - if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view - value_changed = DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, scalar_format); + if (InputText("", buf, IM_ARRAYSIZE(buf), + extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view + value_changed = + DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, scalar_format); // Step buttons if (step_ptr) @@ -8307,31 +8720,35 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data return value_changed; } -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat(const char *label, float *v, float step, float step_fast, int decimal_precision, + ImGuiInputTextFlags extra_flags) { char display_format[16]; if (decimal_precision < 0) - strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1 + strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a + // float, while hiding non-significant digits? %f doesn't have a minimum of 1 else ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision); - return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags); + return InputScalarEx(label, ImGuiDataType_Float, (void *)v, (void *)(step > 0.0f ? &step : NULL), + (void *)(step_fast > 0.0f ? &step_fast : NULL), display_format, extra_flags); } -bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt(const char *label, int *v, int step, int step_fast, ImGuiInputTextFlags extra_flags) { - // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. - const char* scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), scalar_format, extra_flags); + // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own + // data, if you want to handle prefixes. + const char *scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; + return InputScalarEx(label, ImGuiDataType_Int, (void *)v, (void *)(step > 0.0f ? &step : NULL), + (void *)(step_fast > 0.0f ? &step_fast : NULL), scalar_format, extra_flags); } -bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloatN(const char *label, float *v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - bool value_changed = false; + ImGuiContext &g = *GImGui; + bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components); @@ -8352,29 +8769,28 @@ bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal return value_changed; } -bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat2(const char *label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) { return InputFloatN(label, v, 2, decimal_precision, extra_flags); } -bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat3(const char *label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) { return InputFloatN(label, v, 3, decimal_precision, extra_flags); } -bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat4(const char *label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) { return InputFloatN(label, v, 4, decimal_precision, extra_flags); } -bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags) +bool ImGui::InputIntN(const char *label, int *v, int components, ImGuiInputTextFlags extra_flags) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - bool value_changed = false; + ImGuiContext &g = *GImGui; + bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components); @@ -8395,104 +8811,103 @@ bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextF return value_changed; } -bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt2(const char *label, int v[2], ImGuiInputTextFlags extra_flags) { return InputIntN(label, v, 2, extra_flags); } -bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt3(const char *label, int v[3], ImGuiInputTextFlags extra_flags) { return InputIntN(label, v, 3, extra_flags); } -bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt4(const char *label, int v[4], ImGuiInputTextFlags extra_flags) { return InputIntN(label, v, 4, extra_flags); } -static bool Items_ArrayGetter(void* data, int idx, const char** out_text) +static bool Items_ArrayGetter(void *data, int idx, const char **out_text) { - const char* const* items = (const char* const*)data; - if (out_text) - *out_text = items[idx]; + const char *const *items = (const char *const *)data; + if (out_text) *out_text = items[idx]; return true; } -static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) +static bool Items_SingleStringGetter(void *data, int idx, const char **out_text) { // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited. - const char* items_separated_by_zeros = (const char*)data; - int items_count = 0; - const char* p = items_separated_by_zeros; + const char *items_separated_by_zeros = (const char *)data; + int items_count = 0; + const char *p = items_separated_by_zeros; while (*p) { - if (idx == items_count) - break; + if (idx == items_count) break; p += strlen(p) + 1; items_count++; } - if (!*p) - return false; - if (out_text) - *out_text = p; + if (!*p) return false; + if (out_text) *out_text = p; return true; } // Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items) +bool ImGui::Combo(const char *label, int *current_item, const char *const *items, int items_count, int height_in_items) { - const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); + const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void *)items, items_count, height_in_items); return value_changed; } // Combo box helper allowing to pass all items in a single string. -bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) +bool ImGui::Combo(const char *label, int *current_item, const char *items_separated_by_zeros, int height_in_items) { - int items_count = 0; - const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open + int items_count = 0; + const char *p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open while (*p) { p += strlen(p) + 1; items_count++; } - bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); + bool value_changed = + Combo(label, current_item, Items_SingleStringGetter, (void *)items_separated_by_zeros, items_count, height_in_items); return value_changed; } // Combo box function. -bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) +bool ImGui::Combo(const char *label, int *current_item, bool (*items_getter)(void *, int, const char **), void *data, + int items_count, int height_in_items) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); + const ImRect total_bb(frame_bb.Min, + frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, &id)) - return false; + if (!ItemAdd(total_bb, &id)) return false; - const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f); - const bool hovered = IsHovered(frame_bb, id); - bool popup_open = IsPopupOpen(id); - bool popup_opened_now = false; + const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f); + const bool hovered = IsHovered(frame_bb, id); + bool popup_open = IsPopupOpen(id); + bool popup_opened_now = false; const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING - RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); + RenderFrame(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, + GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, + style.FrameRounding); // FIXME-ROUNDING + RenderCollapseTriangle(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y) + style.FramePadding, true); if (*current_item >= 0 && *current_item < items_count) { - const char* item_text; + const char *item_text; if (items_getter(data, *current_item, &item_text)) - RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, item_text, NULL, NULL, ImVec2(0.0f,0.0f)); + RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, item_text, NULL, NULL, ImVec2(0.0f, 0.0f)); } if (label_size.x > 0) @@ -8504,10 +8919,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (g.IO.MouseClicked[0]) { ClearActiveID(); - if (IsPopupOpen(id)) - { - ClosePopup(id); - } + if (IsPopupOpen(id)) { ClosePopup(id); } else { FocusWindow(window); @@ -8521,15 +8933,16 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (IsPopupOpen(id)) { // Size default to hold ~7 items - if (height_in_items < 0) - height_in_items = 7; + if (height_in_items < 0) height_in_items = 7; - float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); + float popup_height = + (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); float popup_y1 = frame_bb.Max.y; float popup_y2 = ImClamp(popup_y1 + popup_height, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y); if ((popup_y2 - popup_y1) < ImMin(popup_height, frame_bb.Min.y - style.DisplaySafeAreaPadding.y)) { - // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement) + // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We + // have similar code in Begin() for popup placement) popup_y1 = ImClamp(frame_bb.Min.y - popup_height, style.DisplaySafeAreaPadding.y, frame_bb.Min.y); popup_y2 = frame_bb.Min.y; } @@ -8538,26 +8951,25 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi SetNextWindowSize(popup_rect.GetSize()); PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); - const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); + const ImGuiWindowFlags flags = + ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); if (BeginPopupEx(label, flags)) { // Display items Spacing(); for (int i = 0; i < items_count; i++) { - PushID((void*)(intptr_t)i); - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; + PushID((void *)(intptr_t)i); + const bool item_selected = (i == *current_item); + const char *item_text; + if (!items_getter(data, i, &item_text)) item_text = "*Unknown item*"; if (Selectable(item_text, item_selected)) { ClearActiveID(); value_changed = true; *current_item = i; } - if (item_selected && popup_opened_now) - SetScrollHere(); + if (item_selected && popup_opened_now) SetScrollHere(); PopID(); } EndPopup(); @@ -8569,34 +8981,32 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi // Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image. // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID. -bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +bool ImGui::Selectable(const char *label, bool selected, ImGuiSelectableFlags flags, const ImVec2 &size_arg) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) - PopClipRect(); + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) PopClipRect(); - ImGuiID id = window->GetID(label); - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); - ImVec2 pos = window->DC.CursorPos; + ImGuiID id = window->GetID(label); + ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); + ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrentLineTextBaseOffset; ImRect bb(pos, pos + size); ItemSize(bb); // Fill horizontal space. ImVec2 window_padding = window->WindowPadding; - float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x; - float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x); - ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y); + float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x; + float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x); + ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, + size_arg.y != 0.0f ? size_arg.y : size.y); ImRect bb_with_spacing(pos, pos + size_draw); - if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth)) - bb_with_spacing.Max.x += window_padding.x; + if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth)) bb_with_spacing.Max.x += window_padding.x; // Selectables are tightly packed together, we extend the box to cover spacing between selectable. float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f); @@ -8609,25 +9019,26 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bb_with_spacing.Max.y += spacing_D; if (!ItemAdd(bb_with_spacing, &id)) { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) - PushColumnClipRect(); + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) PushColumnClipRect(); return false; } ImGuiButtonFlags button_flags = 0; if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick; - if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnClick|ImGuiButtonFlags_PressedOnRelease; + if (flags & ImGuiSelectableFlags_MenuItem) + button_flags |= ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease; if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; - if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; + if (flags & ImGuiSelectableFlags_AllowDoubleClick) + button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; bool hovered, held; bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, button_flags); - if (flags & ImGuiSelectableFlags_Disabled) - selected = false; + if (flags & ImGuiSelectableFlags_Disabled) selected = false; // Render if (hovered || selected) { - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + const ImU32 col = + GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); } @@ -8638,7 +9049,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl } if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderTextClipped(bb.Min, bb_with_spacing.Max, label, NULL, &label_size, ImVec2(0.0f,0.0f)); + RenderTextClipped(bb.Min, bb_with_spacing.Max, label, NULL, &label_size, ImVec2(0.0f, 0.0f)); if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups @@ -8647,7 +9058,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl return pressed; } -bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +bool ImGui::Selectable(const char *label, bool *p_selected, ImGuiSelectableFlags flags, const ImVec2 &size_arg) { if (Selectable(label, *p_selected, flags, size_arg)) { @@ -8659,18 +9070,18 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags // Helper to calculate the size of a listbox and display a label on the right. // Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label "##empty" -bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) +bool ImGui::ListBoxHeader(const char *label, const ImVec2 &size_arg) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - const ImGuiStyle& style = GetStyle(); - const ImGuiID id = GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImGuiStyle &style = GetStyle(); + const ImGuiID id = GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); - // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); + // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at + // scrollbar. + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); @@ -8684,16 +9095,17 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) return true; } -bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items) +bool ImGui::ListBoxHeader(const char *label, int items_count, int height_in_items) { - // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. - // However we don't add +0.40f if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size. - // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution. - if (height_in_items < 0) - height_in_items = ImMin(items_count, 7); + // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at + // scrollbar. However we don't add +0.40f if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic + // list of items will make the widget resize occasionally when it crosses that size. I am expecting that someone will come and + // complain about this behavior in a remote future, then we can advise on a better solution. + if (height_in_items < 0) height_in_items = ImMin(items_count, 7); float height_in_items_f = height_in_items < items_count ? (height_in_items + 0.40f) : (height_in_items + 0.00f); - // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). + // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also + // enforce that by passing a flag to BeginChild(). ImVec2 size; size.x = 0.0f; size.y = GetTextLineHeightWithSpacing() * height_in_items_f + GetStyle().ItemSpacing.y; @@ -8702,9 +9114,9 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item void ImGui::ListBoxFooter() { - ImGuiWindow* parent_window = GetParentWindow(); - const ImRect bb = parent_window->DC.LastItemRect; - const ImGuiStyle& style = GetStyle(); + ImGuiWindow * parent_window = GetParentWindow(); + const ImRect bb = parent_window->DC.LastItemRect; + const ImGuiStyle &style = GetStyle(); EndChildFrame(); @@ -8716,27 +9128,27 @@ void ImGui::ListBoxFooter() EndGroup(); } -bool ImGui::ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_items) +bool ImGui::ListBox(const char *label, int *current_item, const char *const *items, int items_count, int height_items) { - const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); + const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void *)items, items_count, height_items); return value_changed; } -bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) +bool ImGui::ListBox(const char *label, int *current_item, bool (*items_getter)(void *, int, const char **), void *data, + int items_count, int height_in_items) { - if (!ListBoxHeader(label, items_count, height_in_items)) - return false; + if (!ListBoxHeader(label, items_count, height_in_items)) return false; - // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. - bool value_changed = false; + // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a + // custom version of ListBox() in your code without using the clipper. + bool value_changed = false; ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; + const bool item_selected = (i == *current_item); + const char *item_text; + if (!items_getter(data, i, &item_text)) item_text = "*Unknown item*"; PushID(i); if (Selectable(item_text, item_selected)) @@ -8750,20 +9162,23 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v return value_changed; } -bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) +bool ImGui::MenuItem(const char *label, const char *shortcut, bool selected, bool enabled) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - ImVec2 pos = window->DC.CursorPos; - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); - float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); + ImGuiContext &g = *GImGui; + ImVec2 pos = window->DC.CursorPos; + ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); + float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, + (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - bool pressed = Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f)); + bool pressed = Selectable(label, false, + ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | + (enabled ? 0 : ImGuiSelectableFlags_Disabled), + ImVec2(w, 0.0f)); if (shortcut_size.x > 0.0f) { PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); @@ -8772,17 +9187,17 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo } if (selected) - RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled)); + RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), + GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled)); return pressed; } -bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) +bool ImGui::MenuItem(const char *label, const char *shortcut, bool *p_selected, bool enabled) { if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) { - if (p_selected) - *p_selected = !*p_selected; + if (p_selected) *p_selected = !*p_selected; return true; } return false; @@ -8790,13 +9205,15 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool ImGui::BeginMainMenuBar() { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; SetNextWindowPos(ImVec2(0.0f, 0.0f)); SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.FontBaseSize + g.Style.FramePadding.y * 2.0f)); PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); - if (!Begin("##MainMenuBar", NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_MenuBar) - || !BeginMenuBar()) + PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); + if (!Begin("##MainMenuBar", NULL, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar) || + !BeginMenuBar()) { End(); PopStyleVar(2); @@ -8815,19 +9232,18 @@ void ImGui::EndMainMenuBar() bool ImGui::BeginMenuBar() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - if (!(window->Flags & ImGuiWindowFlags_MenuBar)) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; + if (!(window->Flags & ImGuiWindowFlags_MenuBar)) return false; IM_ASSERT(!window->DC.MenuBarAppending); BeginGroup(); // Save position PushID("##menubar"); ImRect rect = window->MenuBarRect(); - PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false); - window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); - window->DC.LayoutType = ImGuiLayoutType_Horizontal; + PushClipRect(ImVec2(ImFloor(rect.Min.x + 0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), + ImVec2(ImFloor(rect.Max.x + 0.5f), ImFloor(rect.Max.y + 0.5f)), false); + window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y); // + g.Style.FramePadding.y); + window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.MenuBarAppending = true; AlignFirstTextHeightToWidgets(); return true; @@ -8835,41 +9251,41 @@ bool ImGui::BeginMenuBar() void ImGui::EndMenuBar() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); IM_ASSERT(window->DC.MenuBarAppending); PopClipRect(); PopID(); - window->DC.MenuBarOffsetX = window->DC.CursorPos.x - window->MenuBarRect().Min.x; + window->DC.MenuBarOffsetX = window->DC.CursorPos.x - window->MenuBarRect().Min.x; window->DC.GroupStack.back().AdvanceCursor = false; EndGroup(); - window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.MenuBarAppending = false; } -bool ImGui::BeginMenu(const char* label, bool enabled) +bool ImGui::BeginMenu(const char *label, bool enabled) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGuiWindow* backed_focused_window = g.FocusedWindow; + ImVec2 label_size = CalcTextSize(label, NULL, true); + ImGuiWindow *backed_focused_window = g.FocusedWindow; bool pressed; - bool menu_is_open = IsPopupOpen(id); - bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); - if (menuset_is_open) - g.FocusedWindow = window; - - // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestPopupWindowPos). + bool menu_is_open = IsPopupOpen(id); + bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && + (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && + g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); + if (menuset_is_open) g.FocusedWindow = window; + + // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using + // FindBestPopupWindowPos). ImVec2 popup_pos, pos = window->DC.CursorPos; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { @@ -8877,7 +9293,10 @@ bool ImGui::BeginMenu(const char* label, bool enabled) window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); float w = label_size.x; - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + pressed = Selectable(label, menu_is_open, + ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | + (!enabled ? ImGuiSelectableFlags_Disabled : 0), + ImVec2(w, 0.0f)); PopStyleVar(); SameLine(); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); @@ -8887,40 +9306,50 @@ bool ImGui::BeginMenu(const char* label, bool enabled) popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + pressed = Selectable(label, menu_is_open, + ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | + ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), + ImVec2(w, 0.0f)); if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); RenderCollapseTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), false); if (!enabled) PopStyleColor(); } bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); - if (menuset_is_open) - g.FocusedWindow = backed_focused_window; + if (menuset_is_open) g.FocusedWindow = backed_focused_window; bool want_open = false, want_close = false; - if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels + // more reactive. bool moving_within_opened_triangle = false; - if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) + if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && + g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { - if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) + if (ImGuiWindow *next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) { ImRect next_window_rect = next_window->Rect(); - ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; - ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR(); - ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR(); - float extra = ImClamp(fabsf(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. - ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues - tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale? - tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f); + ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; + ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR(); + ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR(); + float extra = ImClamp(fabsf(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. + ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues + tb.y = + ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias + // toward large sub-menus // FIXME: Multiply by fb_scale? + tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f); moving_within_opened_triangle = ImIsPointInTriangle(g.IO.MousePos, ta, tb, tc); - //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); window->DrawList->PopClipRect(); // Debug + // window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, + // moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); + // window->DrawList->PopClipRect(); + // // Debug } } - want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); - want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); + want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && + g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); + want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); } else if (menu_is_open && pressed && menuset_is_open) // menu-bar: click open menu to close { @@ -8929,10 +9358,10 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others want_open = true; - if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' + if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if + // (BeginMenu("options", has_object)) { ..use object.. }' want_close = true; - if (want_close && IsPopupOpen(id)) - ClosePopupToLevel(GImGui->CurrentPopupStack.Size); + if (want_close && IsPopupOpen(id)) ClosePopupToLevel(GImGui->CurrentPopupStack.Size); if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) { @@ -8942,14 +9371,17 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } menu_is_open |= want_open; - if (want_open) - OpenPopup(label); + if (want_open) OpenPopup(label); if (menu_is_open) { SetNextWindowPos(popup_pos, ImGuiSetCond_Always); - ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); - menu_is_open = BeginPopupEx(label, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + ImGuiWindowFlags flags = + ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) + ? ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_ChildWindow + : ImGuiWindowFlags_ChildMenu); + menu_is_open = BeginPopupEx( + label, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } return menu_is_open; @@ -8962,70 +9394,70 @@ void ImGui::EndMenu() // A little colored square. Return true when clicked. // FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. -bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_border) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID("#colorbutton"); - const float square_size = g.FontSize; - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(square_size + style.FramePadding.y*2, square_size + (small_height ? 0 : style.FramePadding.y*2))); +bool ImGui::ColorButton(const ImVec4 &col, bool small_height, bool outline_border) +{ + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; + + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID("#colorbutton"); + const float square_size = g.FontSize; + const ImRect bb(window->DC.CursorPos, + window->DC.CursorPos + ImVec2(square_size + style.FramePadding.y * 2, + square_size + (small_height ? 0 : style.FramePadding.y * 2))); ItemSize(bb, small_height ? 0.0f : style.FramePadding.y); - if (!ItemAdd(bb, &id)) - return false; + if (!ItemAdd(bb, &id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); if (hovered) - SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8_SAT(col.x), IM_F32_TO_INT8_SAT(col.y), IM_F32_TO_INT8_SAT(col.z), IM_F32_TO_INT8_SAT(col.w)); + SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8_SAT(col.x), + IM_F32_TO_INT8_SAT(col.y), IM_F32_TO_INT8_SAT(col.z), IM_F32_TO_INT8_SAT(col.w)); return pressed; } -bool ImGui::ColorEdit3(const char* label, float col[3]) +bool ImGui::ColorEdit3(const char *label, float col[3]) { float col4[4]; - col4[0] = col[0]; - col4[1] = col[1]; - col4[2] = col[2]; - col4[3] = 1.0f; + col4[0] = col[0]; + col4[1] = col[1]; + col4[2] = col[2]; + col4[3] = 1.0f; const bool value_changed = ColorEdit4(label, col4, false); - col[0] = col4[0]; - col[1] = col4[1]; - col[2] = col4[2]; + col[0] = col4[0]; + col[1] = col4[1]; + col[2] = col4[2]; return value_changed; } // Edit colors components (each component in 0.0f..1.0f range // Use CTRL-Click to input value and TAB to go to next item. -bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) +bool ImGui::ColorEdit4(const char *label, float col[4], bool alpha) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return false; - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w_full = CalcItemWidth(); - const float square_sz = (g.FontSize + style.FramePadding.y * 2.0f); + ImGuiContext & g = *GImGui; + const ImGuiStyle &style = g.Style; + const ImGuiID id = window->GetID(label); + const float w_full = CalcItemWidth(); + const float square_sz = (g.FontSize + style.FramePadding.y * 2.0f); ImGuiColorEditMode edit_mode = window->DC.ColorEditMode; if (edit_mode == ImGuiColorEditMode_UserSelect || edit_mode == ImGuiColorEditMode_UserSelectShowButton) edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3; - float f[4] = { col[0], col[1], col[2], col[3] }; - if (edit_mode == ImGuiColorEditMode_HSV) - ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); + float f[4] = {col[0], col[1], col[2], col[3]}; + if (edit_mode == ImGuiColorEditMode_HSV) ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; + int i[4] = {IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), + IM_F32_TO_INT8_UNBOUND(f[3])}; - int components = alpha ? 4 : 3; + int components = alpha ? 4 : 3; bool value_changed = false; BeginGroup(); @@ -9036,60 +9468,59 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) { case ImGuiColorEditMode_RGB: case ImGuiColorEditMode_HSV: + { + // RGB/HSV 0..255 Sliders + const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x); + const float w_item_one = + ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); + const float w_item_last = + ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); + + const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); + const char * ids[4] = {"##X", "##Y", "##Z", "##W"}; + const char * fmt_table[3][4] = {{"%3.0f", "%3.0f", "%3.0f", "%3.0f"}, + {"R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f"}, + {"H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f"}}; + const char **fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; + + PushItemWidth(w_item_one); + for (int n = 0; n < components; n++) { - // RGB/HSV 0..255 Sliders - const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x); - const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); - - const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); - const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; - const char* fmt_table[3][4] = - { - { "%3.0f", "%3.0f", "%3.0f", "%3.0f" }, - { "R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f" }, - { "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" } - }; - const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; - - PushItemWidth(w_item_one); - for (int n = 0; n < components; n++) - { - if (n > 0) - SameLine(0, style.ItemInnerSpacing.x); - if (n + 1 == components) - PushItemWidth(w_item_last); - value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]); - } - PopItemWidth(); - PopItemWidth(); + if (n > 0) SameLine(0, style.ItemInnerSpacing.x); + if (n + 1 == components) PushItemWidth(w_item_last); + value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]); } - break; + PopItemWidth(); + PopItemWidth(); + } + break; case ImGuiColorEditMode_HEX: + { + // RGB Hexadecimal Input + const float w_slider_all = w_full - square_sz; + char buf[64]; + if (alpha) + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", i[0], i[1], i[2], i[3]); + else + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); + PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); + if (InputText("##Text", buf, IM_ARRAYSIZE(buf), + ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) { - // RGB Hexadecimal Input - const float w_slider_all = w_full - square_sz; - char buf[64]; + value_changed |= true; + char *p = buf; + while (*p == '#' || ImCharIsSpace(*p)) + p++; + i[0] = i[1] = i[2] = i[3] = 0; if (alpha) - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", i[0], i[1], i[2], i[3]); + sscanf(p, "%02X%02X%02X%02X", (unsigned int *)&i[0], (unsigned int *)&i[1], (unsigned int *)&i[2], + (unsigned int *)&i[3]); // Treat at unsigned (%X is unsigned) else - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); - PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); - if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) - { - value_changed |= true; - char* p = buf; - while (*p == '#' || ImCharIsSpace(*p)) - p++; - i[0] = i[1] = i[2] = i[3] = 0; - if (alpha) - sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) - else - sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); - } - PopItemWidth(); + sscanf(p, "%02X%02X%02X", (unsigned int *)&i[0], (unsigned int *)&i[1], (unsigned int *)&i[2]); } - break; + PopItemWidth(); + } + break; } SameLine(0, style.ItemInnerSpacing.x); @@ -9100,17 +9531,18 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) // Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here if (IsItemHovered()) - SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8_SAT(col[0]), IM_F32_TO_INT8_SAT(col[1]), IM_F32_TO_INT8_SAT(col[2]), IM_F32_TO_INT8_SAT(col[3])); + SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8_SAT(col[0]), + IM_F32_TO_INT8_SAT(col[1]), IM_F32_TO_INT8_SAT(col[2]), IM_F32_TO_INT8_SAT(col[3])); if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) { SameLine(0, style.ItemInnerSpacing.x); - const char* button_titles[3] = { "RGB", "HSV", "HEX" }; - if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups)) + const char *button_titles[3] = {"RGB", "HSV", "HEX"}; + if (ButtonEx(button_titles[edit_mode], ImVec2(0, 0), ImGuiButtonFlags_DontClosePopups)) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! } - const char* label_display_end = FindRenderedTextEnd(label); + const char *label_display_end = FindRenderedTextEnd(label); if (label != label_display_end) { SameLine(0, (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) ? -1.0f : style.ItemInnerSpacing.x); @@ -9120,16 +9552,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) // Convert back for (int n = 0; n < 4; n++) f[n] = i[n] / 255.0f; - if (edit_mode == 1) - ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); + if (edit_mode == 1) ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); if (value_changed) { col[0] = f[0]; col[1] = f[1]; col[2] = f[2]; - if (alpha) - col[3] = f[3]; + if (alpha) col[3] = f[3]; } PopID(); @@ -9140,39 +9570,35 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) void ImGui::ColorEditMode(ImGuiColorEditMode mode) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.ColorEditMode = mode; } // Horizontal separating line. void ImGui::Separator() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - if (window->DC.ColumnsCount > 1) - PopClipRect(); + if (window->DC.ColumnsCount > 1) PopClipRect(); float x1 = window->Pos.x; float x2 = window->Pos.x + window->Size.x; - if (!window->DC.GroupStack.empty()) - x1 += window->DC.IndentX; + if (!window->DC.GroupStack.empty()) x1 += window->DC.IndentX; - const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f)); - ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. + const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + 1.0f)); + ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't + // provide height to not alter layout. if (!ItemAdd(bb, NULL)) { - if (window->DC.ColumnsCount > 1) - PushColumnClipRect(); + if (window->DC.ColumnsCount > 1) PushColumnClipRect(); return; } - window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Border)); + window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Border)); - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - LogText(IM_NEWLINE "--------------------------------"); + ImGuiContext &g = *GImGui; + if (g.LogEnabled) LogText(IM_NEWLINE "--------------------------------"); if (window->DC.ColumnsCount > 1) { @@ -9183,98 +9609,101 @@ void ImGui::Separator() void ImGui::Spacing() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - ItemSize(ImVec2(0,0)); + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; + ItemSize(ImVec2(0, 0)); } -void ImGui::Dummy(const ImVec2& size) +void ImGui::Dummy(const ImVec2 &size) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(bb); ItemAdd(bb, NULL); } -bool ImGui::IsRectVisible(const ImVec2& size) +bool ImGui::IsRectVisible(const ImVec2 &size) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); } -bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) +bool ImGui::IsRectVisible(const ImVec2 &rect_min, const ImVec2 &rect_max) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); } -// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) +// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout +// primitives such as SameLine() on whole group, etc.) void ImGui::BeginGroup() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1); - ImGuiGroupData& group_data = window->DC.GroupStack.back(); - group_data.BackupCursorPos = window->DC.CursorPos; - group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; - group_data.BackupIndentX = window->DC.IndentX; - group_data.BackupGroupOffsetX = window->DC.GroupOffsetX; - group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight; + ImGuiGroupData &group_data = window->DC.GroupStack.back(); + group_data.BackupCursorPos = window->DC.CursorPos; + group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; + group_data.BackupIndentX = window->DC.IndentX; + group_data.BackupGroupOffsetX = window->DC.GroupOffsetX; + group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight; group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset; - group_data.BackupLogLinePosY = window->DC.LogLinePosY; - group_data.BackupActiveIdIsAlive = GImGui->ActiveIdIsAlive; - group_data.AdvanceCursor = true; + group_data.BackupLogLinePosY = window->DC.LogLinePosY; + group_data.BackupActiveIdIsAlive = GImGui->ActiveIdIsAlive; + group_data.AdvanceCursor = true; - window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX; - window->DC.IndentX = window->DC.GroupOffsetX; - window->DC.CursorMaxPos = window->DC.CursorPos; + window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX; + window->DC.IndentX = window->DC.GroupOffsetX; + window->DC.CursorMaxPos = window->DC.CursorPos; window->DC.CurrentLineHeight = 0.0f; - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; } void ImGui::EndGroup() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); - IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls + IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls - ImGuiGroupData& group_data = window->DC.GroupStack.back(); + ImGuiGroupData &group_data = window->DC.GroupStack.back(); ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos); - group_bb.Max.y -= g.Style.ItemSpacing.y; // Cancel out last vertical spacing because we are adding one ourselves. + group_bb.Max.y -= g.Style.ItemSpacing.y; // Cancel out last vertical spacing because we are adding one ourselves. group_bb.Max = ImMax(group_bb.Min, group_bb.Max); - window->DC.CursorPos = group_data.BackupCursorPos; - window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); - window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight; + window->DC.CursorPos = group_data.BackupCursorPos; + window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); + window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight; window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset; - window->DC.IndentX = group_data.BackupIndentX; - window->DC.GroupOffsetX = group_data.BackupGroupOffsetX; - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; + window->DC.IndentX = group_data.BackupIndentX; + window->DC.GroupOffsetX = group_data.BackupGroupOffsetX; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; if (group_data.AdvanceCursor) { - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. + window->DC.CurrentLineTextBaseOffset = + ImMax(window->DC.PrevLineTextBaseOffset, + group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first + // line* of the group but it is hard to obtain now. ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset); ItemAdd(group_bb, NULL); } - // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will function on the entire group. - // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but if you search for LastItemId you'll notice it is only used in that context. - const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow); - if (active_id_within_group) - window->DC.LastItemId = g.ActiveId; + // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will + // function on the entire group. It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', + // but if you search for LastItemId you'll notice it is only used in that context. + const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && + g.ActiveIdWindow->RootWindow == window->RootWindow); + if (active_id_within_group) window->DC.LastItemId = g.ActiveId; if (active_id_within_group && g.HoveredId == g.ActiveId) window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = true; window->DC.GroupStack.pop_back(); - //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // Debug + // window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // Debug } // Gets back to previous line and continue with horizontal layout @@ -9284,15 +9713,15 @@ void ImGui::EndGroup() // spacing_w >= 0 : enforce spacing amount void ImGui::SameLine(float pos_x, float spacing_w) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (pos_x != 0.0f) { if (spacing_w < 0.0f) spacing_w = 0.0f; - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffsetX + window->DC.ColumnsOffsetX; + window->DC.CursorPos.x = + window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffsetX + window->DC.ColumnsOffsetX; window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; } else @@ -9301,28 +9730,27 @@ void ImGui::SameLine(float pos_x, float spacing_w) window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; } - window->DC.CurrentLineHeight = window->DC.PrevLineHeight; + window->DC.CurrentLineHeight = window->DC.PrevLineHeight; window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; } void ImGui::NewLine() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - if (window->DC.CurrentLineHeight > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. - ItemSize(ImVec2(0,0)); + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems) return; + if (window->DC.CurrentLineHeight > + 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. + ItemSize(ImVec2(0, 0)); else ItemSize(ImVec2(0.0f, GImGui->FontSize)); } void ImGui::NextColumn() { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.ColumnsCount <= 1) - return; + ImGuiWindow *window = GetCurrentWindow(); + if (window->SkipItems || window->DC.ColumnsCount <= 1) return; - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; PopItemWidth(); PopClipRect(); @@ -9335,72 +9763,72 @@ void ImGui::NextColumn() } else { - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsOffsetX = 0.0f; + window->DC.ColumnsCurrent = 0; + window->DC.ColumnsOffsetX = 0.0f; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY; window->DrawList->ChannelsSetCurrent(0); } - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = window->DC.ColumnsCellMinY; - window->DC.CurrentLineHeight = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); + window->DC.CursorPos.y = window->DC.ColumnsCellMinY; + window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; PushColumnClipRect(); - PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup + PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup } int ImGui::GetColumnIndex() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.ColumnsCurrent; } int ImGui::GetColumnsCount() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow *window = GetCurrentWindowRead(); return window->DC.ColumnsCount; } static float GetDraggedColumnOffset(int column_index) { - // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing - // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. - ImGuiContext& g = *GImGui; - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); - IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. + // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an + // auto-resizing window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute + // positioning. + ImGuiContext &g = *GImGui; + ImGuiWindow * window = ImGui::GetCurrentWindowRead(); + IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your + // columns and another widgets. IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; - x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(column_index+1)-g.Style.ColumnsMinSpacing); + x = ImClamp(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing, + ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); return (float)(int)x; } float ImGui::GetColumnOffset(int column_index) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindowRead(); + if (column_index < 0) column_index = window->DC.ColumnsCurrent; if (g.ActiveId) { const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - if (g.ActiveId == column_id) - return GetDraggedColumnOffset(column_index); + if (g.ActiveId == column_id) return GetDraggedColumnOffset(column_index); } IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = window->DC.ColumnsData[column_index].OffsetNorm; + const float t = window->DC.ColumnsData[column_index].OffsetNorm; const float x_offset = window->DC.ColumnsMinX + t * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); return (float)(int)x_offset; } void ImGui::SetColumnOffset(int column_index, float offset) { - ImGuiWindow* window = GetCurrentWindow(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiWindow *window = GetCurrentWindow(); + if (column_index < 0) column_index = window->DC.ColumnsCurrent; IM_ASSERT(column_index < window->DC.ColumnsData.Size); const float t = (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); @@ -9412,70 +9840,66 @@ void ImGui::SetColumnOffset(int column_index, float offset) float ImGui::GetColumnWidth(int column_index) { - ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiWindow *window = GetCurrentWindowRead(); + if (column_index < 0) column_index = window->DC.ColumnsCurrent; - float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index); + float w = GetColumnOffset(column_index + 1) - GetColumnOffset(column_index); return w; } static void PushColumnClipRect(int column_index) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiWindow *window = ImGui::GetCurrentWindow(); + if (column_index < 0) column_index = window->DC.ColumnsCurrent; float x1 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index) - 1.0f); - float x2 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1.0f); - ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true); + float x2 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index + 1) - 1.0f); + ImGui::PushClipRect(ImVec2(x1, -FLT_MAX), ImVec2(x2, +FLT_MAX), true); } -void ImGui::Columns(int columns_count, const char* id, bool border) +void ImGui::Columns(int columns_count, const char *id, bool border) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); if (window->DC.ColumnsCount != 1) { - if (window->DC.ColumnsCurrent != 0) - ItemSize(ImVec2(0,0)); // Advance to column 0 + if (window->DC.ColumnsCurrent != 0) ItemSize(ImVec2(0, 0)); // Advance to column 0 PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; + window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; } // Draw columns borders and handle resize at the time of "closing" a columns set - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && !window->SkipItems) + if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && + !window->SkipItems) { const float y1 = window->DC.ColumnsStartPosY; const float y2 = window->DC.CursorPos.y; for (int i = 1; i < window->DC.ColumnsCount; i++) { - float x = window->Pos.x + GetColumnOffset(i); + float x = window->Pos.x + GetColumnOffset(i); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const ImRect column_rect(ImVec2(x-4,y1),ImVec2(x+4,y2)); - if (IsClippedEx(column_rect, &column_id, false)) - continue; + const ImRect column_rect(ImVec2(x - 4, y1), ImVec2(x + 4, y2)); + if (IsClippedEx(column_rect, &column_id, false)) continue; bool hovered, held; ButtonBehavior(column_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; // Draw before resize so our items positioning are in sync with the line being drawn const ImU32 col = GetColorU32(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1+1.0f), ImVec2(xi, y2), col); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); if (held) { if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) + g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) x = GetDraggedColumnOffset(i); SetColumnOffset(i, x); } @@ -9489,16 +9913,18 @@ void ImGui::Columns(int columns_count, const char* id, bool border) PopID(); // Set state for first column - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = columns_count; + window->DC.ColumnsCurrent = 0; + window->DC.ColumnsCount = columns_count; window->DC.ColumnsShowBorders = border; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; - window->DC.ColumnsMinX = window->DC.IndentX; // Lock our horizontal range - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + window->DC.ColumnsMinX = window->DC.IndentX; // Lock our horizontal range + window->DC.ColumnsMaxX = + content_region_width - window->Scroll.x - + ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize); // - window->WindowPadding().x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; - window->DC.ColumnsOffsetX = 0.0f; + window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); if (window->DC.ColumnsCount != 1) @@ -9510,7 +9936,9 @@ void ImGui::Columns(int columns_count, const char* id, bool border) const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); KeepAliveID(column_id); const float default_t = column_index / (float)window->DC.ColumnsCount; - const float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) + const float t = window->DC.StateStorage->GetFloat( + column_id, + default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) window->DC.ColumnsData[column_index].OffsetNorm = t; } window->DrawList->ChannelsSplit(window->DC.ColumnsCount); @@ -9525,39 +9953,39 @@ void ImGui::Columns(int columns_count, const char* id, bool border) void ImGui::Indent(float indent_w) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); window->DC.IndentX += (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; } void ImGui::Unindent(float indent_w) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext &g = *GImGui; + ImGuiWindow * window = GetCurrentWindow(); window->DC.IndentX -= (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; } -void ImGui::TreePush(const char* str_id) +void ImGui::TreePush(const char *str_id) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); Indent(); window->DC.TreeDepth++; PushID(str_id ? str_id : "#TreePush"); } -void ImGui::TreePush(const void* ptr_id) +void ImGui::TreePush(const void *ptr_id) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); Indent(); window->DC.TreeDepth++; - PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); + PushID(ptr_id ? ptr_id : (const void *)"#TreePush"); } void ImGui::TreePushRawID(ImGuiID id) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); Indent(); window->DC.TreeDepth++; window->IDStack.push_back(id); @@ -9565,28 +9993,28 @@ void ImGui::TreePushRawID(ImGuiID id) void ImGui::TreePop() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow *window = GetCurrentWindow(); Unindent(); window->DC.TreeDepth--; PopID(); } -void ImGui::Value(const char* prefix, bool b) +void ImGui::Value(const char *prefix, bool b) { Text("%s: %s", prefix, (b ? "true" : "false")); } -void ImGui::Value(const char* prefix, int v) +void ImGui::Value(const char *prefix, int v) { Text("%s: %d", prefix, v); } -void ImGui::Value(const char* prefix, unsigned int v) +void ImGui::Value(const char *prefix, unsigned int v) { Text("%s: %d", prefix, v); } -void ImGui::Value(const char* prefix, float v, const char* float_format) +void ImGui::Value(const char *prefix, float v, const char *float_format) { if (float_format) { @@ -9601,14 +10029,14 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) } // FIXME: May want to remove those helpers? -void ImGui::ValueColor(const char* prefix, const ImVec4& v) +void ImGui::ValueColor(const char *prefix, const ImVec4 &v) { Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w); SameLine(); ColorButton(v, true); } -void ImGui::ValueColor(const char* prefix, ImU32 v) +void ImGui::ValueColor(const char *prefix, ImU32 v) { Text("%s: %08X", prefix, v); SameLine(); @@ -9619,29 +10047,28 @@ void ImGui::ValueColor(const char* prefix, ImU32 v) // PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- -#if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS)) -#undef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#include +#if defined(_WIN32) && !defined(_WINDOWS_) && \ + (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS)) + #undef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #include #endif // Win32 API clipboard implementation #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) -#ifdef _MSC_VER -#pragma comment(lib, "user32") -#endif + #ifdef _MSC_VER + #pragma comment(lib, "user32") + #endif -static const char* GetClipboardTextFn_DefaultImpl(void*) +static const char *GetClipboardTextFn_DefaultImpl(void *) { static ImVector buf_local; buf_local.clear(); - if (!OpenClipboard(NULL)) - return NULL; + if (!OpenClipboard(NULL)) return NULL; HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); - if (wbuf_handle == NULL) - return NULL; - if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle)) + if (wbuf_handle == NULL) return NULL; + if (ImWchar *wbuf_global = (ImWchar *)GlobalLock(wbuf_handle)) { int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1; buf_local.resize(buf_len); @@ -9652,15 +10079,13 @@ static const char* GetClipboardTextFn_DefaultImpl(void*) return buf_local.Data; } -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) +static void SetClipboardTextFn_DefaultImpl(void *, const char *text) { - if (!OpenClipboard(NULL)) - return; + if (!OpenClipboard(NULL)) return; const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; - HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); - if (wbuf_handle == NULL) - return; - ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); + HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); + if (wbuf_handle == NULL) return; + ImWchar *wbuf_global = (ImWchar *)GlobalLock(wbuf_handle); ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); GlobalUnlock(wbuf_handle); EmptyClipboard(); @@ -9671,22 +10096,22 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) #else // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers -static const char* GetClipboardTextFn_DefaultImpl(void*) +static const char *GetClipboardTextFn_DefaultImpl(void *) { return GImGui->PrivateClipboard; } // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) +static void SetClipboardTextFn_DefaultImpl(void *, const char *text) { - ImGuiContext& g = *GImGui; + ImGuiContext &g = *GImGui; if (g.PrivateClipboard) { ImGui::MemFree(g.PrivateClipboard); g.PrivateClipboard = NULL; } - const char* text_end = text + strlen(text); - g.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1); + const char *text_end = text + strlen(text); + g.PrivateClipboard = (char *)ImGui::MemAlloc((size_t)(text_end - text) + 1); memcpy(g.PrivateClipboard, text, (size_t)(text_end - text)); g.PrivateClipboard[(int)(text_end - text)] = 0; } @@ -9696,10 +10121,10 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) // Win32 API IME support (for Asian languages, etc.) #if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS) -#include -#ifdef _MSC_VER -#pragma comment(lib, "imm32") -#endif + #include + #ifdef _MSC_VER + #pragma comment(lib, "imm32") + #endif static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) { @@ -9710,14 +10135,16 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) COMPOSITIONFORM cf; cf.ptCurrentPos.x = x; cf.ptCurrentPos.y = y; - cf.dwStyle = CFS_FORCE_POSITION; + cf.dwStyle = CFS_FORCE_POSITION; ImmSetCompositionWindow(himc, &cf); } } #else -static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} +static void ImeSetInputScreenPosFn_DefaultImpl(int, int) +{ +} #endif @@ -9725,13 +10152,14 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} // HELP //----------------------------------------------------------------------------- -void ImGui::ShowMetricsWindow(bool* p_open) +void ImGui::ShowMetricsWindow(bool *p_open) { if (ImGui::Begin("ImGui Metrics", p_open)) { ImGui::Text("ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); + ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, + ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects); @@ -9739,57 +10167,71 @@ void ImGui::ShowMetricsWindow(bool* p_open) struct Funcs { - static void NodeDrawList(ImDrawList* draw_list, const char* label) + static void NodeDrawList(ImDrawList *draw_list, const char *label) { - bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); + bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, + draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, + draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); if (draw_list == ImGui::GetWindowDrawList()) { ImGui::SameLine(); - ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) + ImGui::TextColored(ImColor(255, 100, 100), + "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the + // data double-buffered) if (node_open) ImGui::TreePop(); return; } - if (!node_open) - return; + if (!node_open) return; - ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list + ImDrawList *overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list overlay_draw_list->PushClipRectFullScreen(); int elem_offset = 0; - for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) + for (const ImDrawCmd *pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); + elem_offset += pcmd->ElemCount, pcmd++) { if (pcmd->UserCallback) { ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); continue; } - ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + ImDrawIdx *idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + bool pcmd_node_open = + ImGui::TreeNode((void *)(pcmd - draw_list->CmdBuffer.begin()), + "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, + draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, + pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); if (show_clip_rects && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; ImRect vtxs_rect; for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); - clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); - vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255)); + clip_rect.Floor(); + overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255, 255, 0, 255)); + vtxs_rect.Floor(); + overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255, 0, 255, 255)); } - if (!pcmd_node_open) - continue; - ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + if (!pcmd_node_open) continue; + ImGuiListClipper clipper(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to + // save CPU, only items that may be visible. while (clipper.Step()) - for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) + for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart * 3; + prim < clipper.DisplayEnd; prim++) { - char buf[300], *buf_p = buf; + char buf[300], *buf_p = buf; ImVec2 triangles_pos[3]; for (int n = 0; n < 3; n++, vtx_i++) { - ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; + ImDrawVert &v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; triangles_pos[n] = v.pos; - buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", + (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) - overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle + overlay_draw_list->AddPolyline( + triangles_pos, 3, IM_COL32(255, 255, 0, 255), true, 1.0f, + false); // Add triangle without AA, more readable for large-thin triangle } ImGui::TreePop(); } @@ -9797,22 +10239,23 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } - static void NodeWindows(ImVector& windows, const char* label) + static void NodeWindows(ImVector &windows, const char *label) { - if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) - return; + if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) return; for (int i = 0; i < windows.Size; i++) Funcs::NodeWindow(windows[i], "Window"); ImGui::TreePop(); } - static void NodeWindow(ImGuiWindow* window, const char* label) + static void NodeWindow(ImGuiWindow *window, const char *label) { - if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) + if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, + window)) return; NodeDrawList(window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f)", window->Pos.x, window->Pos.y); - ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); + ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, + window->SizeContents.x, window->SizeContents.y); ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); @@ -9821,7 +10264,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; - ImGuiContext& g = *GImGui; // Access private state + ImGuiContext &g = *GImGui; // Access private state Funcs::NodeWindows(g.Windows, "Windows"); if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.RenderDrawLists[0].Size)) { @@ -9833,8 +10276,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) { for (int i = 0; i < g.OpenPopupStack.Size; i++) { - ImGuiWindow* window = g.OpenPopupStack[i].Window; - ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); + ImGuiWindow *window = g.OpenPopupStack[i].Window; + ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", + window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", + window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); } ImGui::TreePop(); } @@ -9843,7 +10288,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); - ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, + g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may + // see current frame information or not ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); ImGui::TreePop(); } @@ -9854,9 +10301,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) //----------------------------------------------------------------------------- // Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed. -// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github. +// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from +// imgui_internal.h add it or request it on the github. #ifdef IMGUI_INCLUDE_IMGUI_USER_INL -#include "imgui_user.inl" + #include "imgui_user.inl" #endif //----------------------------------------------------------------------------- diff --git a/source/main/gui/imgui/imgui.h b/source/main/gui/imgui/imgui.h index 310f757db8..96e25598d8 100644 --- a/source/main/gui/imgui/imgui.h +++ b/source/main/gui/imgui/imgui.h @@ -9,64 +9,68 @@ #pragma once #if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H) -#include "imconfig.h" // User-editable configuration file + #include "imconfig.h" // User-editable configuration file #endif -#include // FLT_MAX -#include // va_list -#include // ptrdiff_t, NULL -#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#include -#define IMGUI_VERSION "1.50 WIP" +#include // FLT_MAX +#include // va_list +#include // ptrdiff_t, NULL +#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp +#include +#define IMGUI_VERSION "1.50 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API -#define IMGUI_API + #define IMGUI_API #endif // Define assertion handler. #ifndef IM_ASSERT -#include -#define IM_ASSERT(_EXPR) assert(_EXPR) + #include + #define IM_ASSERT(_EXPR) assert(_EXPR) #endif // Some compilers support applying printf-style warnings to user functions. #if defined(__clang__) || defined(__GNUC__) -#define IM_PRINTFARGS(FMT) __attribute__((format(printf, FMT, (FMT+1)))) + #define IM_PRINTFARGS(FMT) __attribute__((format(printf, FMT, (FMT + 1)))) #else -#define IM_PRINTFARGS(FMT) + #define IM_PRINTFARGS(FMT) #endif #if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wold-style-cast" #endif // Forward declarations -struct ImDrawChannel; // Temporary storage for outputting drawing commands out of order, used by ImDrawList::ChannelsSplit() -struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call) -struct ImDrawData; // All draw command lists required to render the frame -struct ImDrawList; // A single draw command list (generally one per window) -struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) -struct ImFont; // Runtime data for a single font within a parent ImFontAtlas -struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF font loader -struct ImFontConfig; // Configuration data when adding a font or merging fonts -struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 -struct ImGuiIO; // Main configuration and I/O between your application and ImGui -struct ImGuiOnceUponAFrame; // Simple helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro -struct ImGuiStorage; // Simple custom key value storage -struct ImGuiStyle; // Runtime data for styling/colors -struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -struct ImGuiTextBuffer; // Text buffer for logging/accumulating text -struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use) -struct ImGuiSizeConstraintCallbackData;// Structure used to constraint window size in custom ways when using custom ImGuiSizeConstraintCallback (rare/advanced use) -struct ImGuiListClipper; // Helper to manually clip large list of items -struct ImGuiContext; // ImGui context (opaque) +struct ImDrawChannel; // Temporary storage for outputting drawing commands out of order, used by ImDrawList::ChannelsSplit() +struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call) +struct ImDrawData; // All draw command lists required to render the frame +struct ImDrawList; // A single draw command list (generally one per window) +struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) +struct ImFont; // Runtime data for a single font within a parent ImFontAtlas +struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF font loader +struct ImFontConfig; // Configuration data when adding a font or merging fonts +struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 +struct ImGuiIO; // Main configuration and I/O between your application and ImGui +struct ImGuiOnceUponAFrame; // Simple helper for running a block of code not more than once a frame, used by + // IMGUI_ONCE_UPON_A_FRAME macro +struct ImGuiStorage; // Simple custom key value storage +struct ImGuiStyle; // Runtime data for styling/colors +struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" +struct ImGuiTextBuffer; // Text buffer for logging/accumulating text +struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced + // use) +struct ImGuiSizeConstraintCallbackData; // Structure used to constraint window size in custom ways when using custom + // ImGuiSizeConstraintCallback (rare/advanced use) +struct ImGuiListClipper; // Helper to manually clip large list of items +struct ImGuiContext; // ImGui context (opaque) // Typedefs and Enumerations (declared as int for compatibility and to not pollute the top of this file) -typedef unsigned int ImU32; // 32-bit unsigned integer (typically used to store packed colors) -typedef unsigned int ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) +typedef unsigned int ImU32; // 32-bit unsigned integer (typically used to store packed colors) +typedef unsigned int ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) typedef unsigned short ImWchar; // character for keyboard input/display -typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) +typedef void * ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about + // ImTextureID in imgui.cpp) typedef int ImGuiCol; // a color identifier for styling // enum ImGuiCol_ typedef int ImGuiStyleVar; // a variable identifier for styling // enum ImGuiStyleVar_ typedef int ImGuiKey; // a key identifier (ImGui-side enum) // enum ImGuiKey_ @@ -78,18 +82,27 @@ typedef int ImGuiInputTextFlags; // flags for InputText*() // e typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); -typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); +typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData *data); // Others helpers at bottom of the file: // class ImVector<> // Lightweight std::vector like class. -// IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times) +// IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested +// code that runs multiple times) struct ImVec2 { float x, y; - ImVec2() { x = y = 0.0f; } - ImVec2(float _x, float _y) { x = _x; y = _y; } -#ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. + ImVec2() + { + x = y = 0.0f; + } + ImVec2(float _x, float _y) + { + x = _x; + y = _y; + } +#ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math + // types and ImVec2. IM_VEC2_CLASS_EXTRA #endif }; @@ -97,9 +110,19 @@ struct ImVec2 struct ImVec4 { float x, y, z, w; - ImVec4() { x = y = z = w = 0.0f; } - ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } -#ifdef IM_VEC4_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec4. + ImVec4() + { + x = y = z = w = 0.0f; + } + ImVec4(float _x, float _y, float _z, float _w) + { + x = _x; + y = _y; + z = _z; + w = _w; + } +#ifdef IM_VEC4_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math + // types and ImVec4. IM_VEC4_CLASS_EXTRA #endif }; @@ -109,367 +132,599 @@ struct ImVec4 namespace ImGui { // Main - IMGUI_API ImGuiIO& GetIO(); - IMGUI_API ImGuiStyle& GetStyle(); - IMGUI_API ImDrawData* GetDrawData(); // same value as passed to your io.RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() - IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until NewFrame()/Render(). - IMGUI_API void Render(); // ends the ImGui frame, finalize rendering data, then call your io.RenderDrawListsFn() function if set. - IMGUI_API void Shutdown(); - IMGUI_API void ShowUserGuide(); // help block - IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // style editor block. you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) - IMGUI_API void ShowTestWindow(bool* p_open = NULL); // test window demonstrating ImGui features - IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // metrics window for debugging ImGui (browse draw commands, individual vertices, window list, etc.) + IMGUI_API ImGuiIO &GetIO(); + IMGUI_API ImGuiStyle &GetStyle(); + IMGUI_API ImDrawData *GetDrawData(); // same value as passed to your io.RenderDrawListsFn() function. valid after Render() and + // until the next call to NewFrame() + IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until NewFrame()/Render(). + IMGUI_API void Render(); // ends the ImGui frame, finalize rendering data, then call your io.RenderDrawListsFn() function if + // set. + IMGUI_API void Shutdown(); + IMGUI_API void ShowUserGuide(); // help block + IMGUI_API void ShowStyleEditor( + ImGuiStyle *ref = NULL); // style editor block. you can pass in a reference ImGuiStyle structure to + // compare to, revert to and save to (else it uses the default style) + IMGUI_API void ShowTestWindow(bool *p_open = NULL); // test window demonstrating ImGui features + IMGUI_API void ShowMetricsWindow( + bool *p_open = NULL); // metrics window for debugging ImGui (browse draw commands, individual vertices, window list, etc.) // Window - IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. - IMGUI_API void End(); // finish appending to current window, pop it off the window stack. - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). - IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " - IMGUI_API void EndChild(); - IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API float GetContentRegionAvailWidth(); // - IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates - IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates - IMGUI_API float GetWindowContentRegionWidth(); // - IMGUI_API ImDrawList* GetWindowDrawList(); // get rendering command-list if you want to append your own draw primitives - IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList api) - IMGUI_API ImVec2 GetWindowSize(); // get current window size - IMGUI_API float GetWindowWidth(); - IMGUI_API float GetWindowHeight(); - IMGUI_API bool IsWindowCollapsed(); - IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows - - IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() - IMGUI_API void SetNextWindowPosCenter(ImGuiSetCond cond = 0); // set next window position to be centered on screen. call before Begin() - IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() - IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. - IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() - IMGUI_API void SetNextWindowContentWidth(float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() - IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() - IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() - IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. - IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. - IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). - IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). - IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond = 0); // set named window position. - IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. - IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0); // set named window collapsed state - IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. - - IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] - IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] - IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X - IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y - IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] - IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] - IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. - IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use negative 'offset' to access previous widgets. - IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) - IMGUI_API ImGuiStorage* GetStateStorage(); + IMGUI_API bool Begin( + const char *name, bool *p_open = NULL, + ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false + // when window is collapsed, so you can early out in your code. 'bool* p_open' creates a + // widget on the upper-right to close the window (which sets your bool to false). + IMGUI_API bool Begin( + const char *name, bool *p_open, const ImVec2 &size_on_first_use, float bg_alpha = -1.0f, + ImGuiWindowFlags flags = + 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() + // instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first + // time EVER the window is created and probably not what you want! might obsolete this API eventually. + IMGUI_API void End(); // finish appending to current window, pop it off the window stack. + IMGUI_API bool BeginChild( + const char *str_id, const ImVec2 &size = ImVec2(0, 0), bool border = false, + ImGuiWindowFlags extra_flags = + 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus + // abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). + IMGUI_API bool BeginChild(ImGuiID id, const ImVec2 &size = ImVec2(0, 0), bool border = false, + ImGuiWindowFlags extra_flags = 0); // " + IMGUI_API void EndChild(); + IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or + // current column boundaries), in windows coordinates + IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() + IMGUI_API float GetContentRegionAvailWidth(); // + IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates + IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override + // with SetNextWindowContentSize(), in window coordinates + IMGUI_API float GetWindowContentRegionWidth(); // + IMGUI_API ImDrawList *GetWindowDrawList(); // get rendering command-list if you want to append your own draw primitives + IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via + // the DrawList api) + IMGUI_API ImVec2 GetWindowSize(); // get current window size + IMGUI_API float GetWindowWidth(); + IMGUI_API float GetWindowHeight(); + IMGUI_API bool IsWindowCollapsed(); + IMGUI_API void SetWindowFontScale( + float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows + + IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() + IMGUI_API void SetNextWindowPosCenter( + ImGuiSetCond cond = 0); // set next window position to be centered on screen. call before Begin() + IMGUI_API void SetNextWindowSize( + const ImVec2 &size, + ImGuiSetCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() + IMGUI_API void SetNextWindowSizeConstraints( + const ImVec2 &size_min, const ImVec2 &size_max, ImGuiSizeConstraintCallback custom_callback = NULL, + void *custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current + // size. Use callback to apply non-trivial programmatic constraints. + IMGUI_API void SetNextWindowContentSize( + const ImVec2 &size); // set next window content size (enforce the range of scrollbars). + // set axis to 0.0f to leave it automatic. call before Begin() + IMGUI_API void SetNextWindowContentWidth( + float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() + IMGUI_API void SetNextWindowCollapsed(bool collapsed, + ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() + IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() + IMGUI_API void SetWindowPos( + const ImVec2 &pos, ImGuiSetCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). + // prefer using SetNextWindowPos(), as this may incur tearing and side-effects. + IMGUI_API void SetWindowSize(const ImVec2 &size, + ImGuiSetCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). + // set to ImVec2(0,0) to force an auto-fit. prefer using + // SetNextWindowSize(), as this may incur tearing and minor side-effects. + IMGUI_API void SetWindowCollapsed( + bool collapsed, + ImGuiSetCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). + IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using + // SetNextWindowFocus(). + IMGUI_API void SetWindowPos(const char *name, const ImVec2 &pos, ImGuiSetCond cond = 0); // set named window position. + IMGUI_API void SetWindowSize( + const char *name, const ImVec2 &size, + ImGuiSetCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. + IMGUI_API void SetWindowCollapsed(const char *name, bool collapsed, + ImGuiSetCond cond = 0); // set named window collapsed state + IMGUI_API void SetWindowFocus(const char *name); // set named window to be focused / front-most. use NULL to remove focus. + + IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] + IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] + IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X + IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y + IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] + IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] + IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. + // center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. + IMGUI_API void SetScrollFromPosY( + float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or + // GetCursorStartPos()+offset to get valid positions. + IMGUI_API void SetKeyboardFocusHere( + int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple + // component widget. Use negative 'offset' to access previous widgets. + IMGUI_API void SetStateStorage(ImGuiStorage *tree); // replace tree state storage with our own (if you want to manipulate it + // yourself, typically clear subsection of it) + IMGUI_API ImGuiStorage *GetStateStorage(); // Parameters stacks (shared) - IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font - IMGUI_API void PopFont(); - IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); - IMGUI_API void PopStyleColor(int count = 1); - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); - IMGUI_API void PopStyleVar(int count = 1); - IMGUI_API ImFont* GetFont(); // get current font - IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied - IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API - IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier - IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied + IMGUI_API void PushFont(ImFont *font); // use NULL as a shortcut to push default font + IMGUI_API void PopFont(); + IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4 &col); + IMGUI_API void PopStyleColor(int count = 1); + IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); + IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2 &val); + IMGUI_API void PopStyleVar(int count = 1); + IMGUI_API ImFont *GetFont(); // get current font + IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied + IMGUI_API ImVec2 + GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API + IMGUI_API ImU32 GetColorU32( + ImGuiCol idx, + float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier + IMGUI_API ImU32 GetColorU32(const ImVec4 &col); // retrieve given color with style alpha applied // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) - IMGUI_API void PopItemWidth(); - IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position - IMGUI_API void PushTextWrapPos(float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space - IMGUI_API void PopTextWrapPos(); - IMGUI_API void PushAllowKeyboardFocus(bool v); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets - IMGUI_API void PopAllowKeyboardFocus(); - IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (uses io.KeyRepeatDelay/io.KeyRepeatRate for now). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. - IMGUI_API void PopButtonRepeat(); + IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to + // ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the + // right of window (so -1.0f always align width to the right side) + IMGUI_API void PopItemWidth(); + IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position + IMGUI_API void PushTextWrapPos( + float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or + // column); > 0.0f: wrap at 'wrap_pos_x' position in window local space + IMGUI_API void PopTextWrapPos(); + IMGUI_API void PushAllowKeyboardFocus( + bool v); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets + IMGUI_API void PopAllowKeyboardFocus(); + IMGUI_API void PushButtonRepeat( + bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (uses + // io.KeyRepeatDelay/io.KeyRepeatRate for now). Note that you can call IsItemActive() after any Button() to + // tell if the button is held in the current frame. + IMGUI_API void PopButtonRepeat(); // Cursor / Layout - IMGUI_API void Separator(); // horizontal line - IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally - IMGUI_API void NewLine(); // undo a SameLine() - IMGUI_API void Spacing(); // add vertical spacing - IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size - IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if >0 - IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if >0 - IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) - IMGUI_API void EndGroup(); - IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position - IMGUI_API float GetCursorPosX(); // " - IMGUI_API float GetCursorPosY(); // " - IMGUI_API void SetCursorPos(const ImVec2& local_pos); // " - IMGUI_API void SetCursorPosX(float x); // " - IMGUI_API void SetCursorPosY(float y); // " - IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) - IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] - IMGUI_API void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets - IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() - IMGUI_API float GetTextLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of text == GetWindowFontSize() + GetStyle().ItemSpacing.y - IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y + IMGUI_API void Separator(); // horizontal line + IMGUI_API void SameLine(float pos_x = 0.0f, + float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally + IMGUI_API void NewLine(); // undo a SameLine() + IMGUI_API void Spacing(); // add vertical spacing + IMGUI_API void Dummy(const ImVec2 &size); // add a dummy item of given size + IMGUI_API void Indent( + float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if >0 + IMGUI_API void Unindent( + float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if >0 + IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use + // IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) + IMGUI_API void EndGroup(); + IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position + IMGUI_API float GetCursorPosX(); // " + IMGUI_API float GetCursorPosY(); // " + IMGUI_API void SetCursorPos(const ImVec2 &local_pos); // " + IMGUI_API void SetCursorPosX(float x); // " + IMGUI_API void SetCursorPosY(float y); // " + IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work + // with ImDrawList API) + IMGUI_API void SetCursorScreenPos(const ImVec2 &pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] + IMGUI_API void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to + // vertically lower it to match subsequent (bigger) widgets + IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() + IMGUI_API float GetTextLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of text == + // GetWindowFontSize() + // + GetStyle().ItemSpacing.y + IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height + // widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + + // GetStyle().ItemSpacing.y // Columns // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1). - IMGUI_API void NextColumn(); // next column - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column - IMGUI_API float GetColumnWidth(int column_index = -1); // column width (== GetColumnOffset(GetColumnIndex()+1) - GetColumnOffset(GetColumnOffset()) - IMGUI_API int GetColumnsCount(); // number of columns (what was passed to Columns()) + IMGUI_API void Columns(int count = 1, const char *id = NULL, + bool border = true); // setup number of columns. use an identifier to distinguish multiple column sets. + // close with Columns(1). + IMGUI_API void NextColumn(); // next column + IMGUI_API int GetColumnIndex(); // get current column index + IMGUI_API float GetColumnOffset( + int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to + // use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not + // resizable unless you call this + IMGUI_API void SetColumnOffset(int column_index, + float offset_x); // set position of column line (in pixels, from the left side of + // the contents region). pass -1 to use current column + IMGUI_API float GetColumnWidth( + int column_index = -1); // column width (== GetColumnOffset(GetColumnIndex()+1) - GetColumnOffset(GetColumnOffset()) + IMGUI_API int GetColumnsCount(); // number of columns (what was passed to Columns()) // ID scopes // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. - // You can also use the "##foobar" syntax within widget label to distinguish them from each others. Read "A primer on the use of labels/IDs" in the FAQ for more details. - IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack! - IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); - IMGUI_API void PushID(const void* ptr_id); - IMGUI_API void PushID(int int_id); - IMGUI_API void PopID(); - IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). useful if you want to query into ImGuiStorage yourself. otherwise rarely needed - IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); - IMGUI_API ImGuiID GetID(const void* ptr_id); + // You can also use the "##foobar" syntax within widget label to distinguish them from each others. Read "A primer on the use + // of labels/IDs" in the FAQ for more details. + IMGUI_API void PushID(const char *str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack! + IMGUI_API void PushID(const char *str_id_begin, const char *str_id_end); + IMGUI_API void PushID(const void *ptr_id); + IMGUI_API void PushID(int int_id); + IMGUI_API void PopID(); + IMGUI_API ImGuiID GetID(const char *str_id); // calculate unique ID (hash of whole ID stack + given parameter). useful if you + // want to query into ImGuiStorage yourself. otherwise rarely needed + IMGUI_API ImGuiID GetID(const char *str_id_begin, const char *str_id_end); + IMGUI_API ImGuiID GetID(const void *ptr_id); // Widgets - IMGUI_API void Text(const char* fmt, ...) IM_PRINTFARGS(1); - IMGUI_API void TextV(const char* fmt, va_list args); - IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_PRINTFARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args); - IMGUI_API void TextDisabled(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextDisabledV(const char* fmt, va_list args); - IMGUI_API void TextWrapped(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). - IMGUI_API void TextWrappedV(const char* fmt, va_list args); - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, recommended for long chunks of text - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets - IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args); - IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses - IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for Bullet()+Text() - IMGUI_API void BulletTextV(const char* fmt, va_list args); - IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button - IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) - IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); - IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); - IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding - IMGUI_API bool Checkbox(const char* label, bool* v); - IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); - IMGUI_API bool RadioButton(const char* label, bool active); - IMGUI_API bool RadioButton(const char* label, int* v, int v_button); - IMGUI_API bool Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); - IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0 - IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ColorButton(const ImVec4& col, bool small_height = false, bool outline_border = true); - IMGUI_API bool ColorEdit3(const char* label, float col[3]); // Hint: 'float col[3]' function argument is same as 'float* col'. You can pass address of first element out of a contiguous set, e.g. &myvector.x - IMGUI_API bool ColorEdit4(const char* label, float col[4], bool show_alpha = true); // " - IMGUI_API void ColorEditMode(ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and will be obsoleted/replaced. - IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); - IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); - IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); - IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); - IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL); - - // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) - // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, remember than a 'float v[3]' function argument is the same as 'float* v'. You can pass address of your first element out of a contiguous set, e.g. &myvector.x - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound - IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", const char* display_format_max = NULL, float power = 1.0f); - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_min >= v_max we have no bound - IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f", const char* display_format_max = NULL); + IMGUI_API void Text(const char *fmt, ...) IM_PRINTFARGS(1); + IMGUI_API void TextV(const char *fmt, va_list args); + IMGUI_API void TextColored(const ImVec4 &col, const char *fmt, ...) + IM_PRINTFARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextColoredV(const ImVec4 &col, const char *fmt, va_list args); + IMGUI_API void TextDisabled(const char *fmt, ...) IM_PRINTFARGS( + 1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextDisabledV(const char *fmt, va_list args); + IMGUI_API void TextWrapped(const char *fmt, ...) + IM_PRINTFARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on + // an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a + // size using SetNextWindowSize(). + IMGUI_API void TextWrappedV(const char *fmt, va_list args); + IMGUI_API void TextUnformatted( + const char *text, + const char *text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy + // done to any bounded stack buffer, recommended for long chunks of text + IMGUI_API void LabelText(const char *label, const char *fmt, ...) + IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets + IMGUI_API void LabelTextV(const char *label, const char *fmt, va_list args); + IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by + // GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses + IMGUI_API void BulletText(const char *fmt, ...) IM_PRINTFARGS(1); // shortcut for Bullet()+Text() + IMGUI_API void BulletTextV(const char *fmt, va_list args); + IMGUI_API bool Button(const char *label, const ImVec2 &size = ImVec2(0, 0)); // button + IMGUI_API bool SmallButton(const char *label); // button with FramePadding=(0,0) + IMGUI_API bool InvisibleButton(const char *str_id, const ImVec2 &size); + IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0 = ImVec2(0, 0), + const ImVec2 &uv1 = ImVec2(1, 1), const ImVec4 &tint_col = ImVec4(1, 1, 1, 1), + const ImVec4 &border_col = ImVec4(0, 0, 0, 0)); + IMGUI_API bool ImageButton( + ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0 = ImVec2(0, 0), const ImVec2 &uv1 = ImVec2(1, 1), + int frame_padding = -1, const ImVec4 &bg_col = ImVec4(0, 0, 0, 0), + const ImVec4 &tint_col = ImVec4(1, 1, 1, 1)); // <0 frame_padding uses default frame padding settings. 0 for no padding + IMGUI_API bool Checkbox(const char *label, bool *v); + IMGUI_API bool CheckboxFlags(const char *label, unsigned int *flags, unsigned int flags_value); + IMGUI_API bool RadioButton(const char *label, bool active); + IMGUI_API bool RadioButton(const char *label, int *v, int v_button); + IMGUI_API bool Combo(const char *label, int *current_item, const char *const *items, int items_count, + int height_in_items = -1); + IMGUI_API bool Combo(const char *label, int *current_item, const char *items_separated_by_zeros, + int height_in_items = -1); // separate items with \0, end item-list with \0\0 + IMGUI_API bool Combo(const char *label, int *current_item, bool (*items_getter)(void *data, int idx, const char **out_text), + void *data, int items_count, int height_in_items = -1); + IMGUI_API bool ColorButton(const ImVec4 &col, bool small_height = false, bool outline_border = true); + IMGUI_API bool ColorEdit3(const char *label, + float col[3]); // Hint: 'float col[3]' function argument is same as 'float* col'. You can pass + // address of first element out of a contiguous set, e.g. &myvector.x + IMGUI_API bool ColorEdit4(const char *label, float col[4], bool show_alpha = true); // " + IMGUI_API void ColorEditMode( + ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and will be obsoleted/replaced. + IMGUI_API void PlotLines(const char *label, const float *values, int values_count, int values_offset = 0, + const char *overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, + ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); + IMGUI_API void PlotLines(const char *label, float (*values_getter)(void *data, int idx), void *data, int values_count, + int values_offset = 0, const char *overlay_text = NULL, float scale_min = FLT_MAX, + float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + IMGUI_API void PlotHistogram(const char *label, const float *values, int values_count, int values_offset = 0, + const char *overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, + ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); + IMGUI_API void PlotHistogram(const char *label, float (*values_getter)(void *data, int idx), void *data, int values_count, + int values_offset = 0, const char *overlay_text = NULL, float scale_min = FLT_MAX, + float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + IMGUI_API void ProgressBar(float fraction, const ImVec2 &size_arg = ImVec2(-1, 0), const char *overlay = NULL); + + // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go + // off-bounds) For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, remember than a 'float v[3]' + // function argument is the same as 'float* v'. You can pass address of your first element out of a contiguous set, e.g. + // &myvector.x + IMGUI_API bool DragFloat(const char *label, float *v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, + const char *display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound + IMGUI_API bool DragFloat2(const char *label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, + const char *display_format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloat3(const char *label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, + const char *display_format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloat4(const char *label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, + const char *display_format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloatRange2(const char *label, float *v_current_min, float *v_current_max, float v_speed = 1.0f, + float v_min = 0.0f, float v_max = 0.0f, const char *display_format = "%.3f", + const char *display_format_max = NULL, float power = 1.0f); + IMGUI_API bool DragInt(const char *label, int *v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, + const char *display_format = "%.0f"); // If v_min >= v_max we have no bound + IMGUI_API bool DragInt2(const char *label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, + const char *display_format = "%.0f"); + IMGUI_API bool DragInt3(const char *label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, + const char *display_format = "%.0f"); + IMGUI_API bool DragInt4(const char *label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, + const char *display_format = "%.0f"); + IMGUI_API bool DragIntRange2(const char *label, int *v_current_min, int *v_current_max, float v_speed = 1.0f, int v_min = 0, + int v_max = 0, const char *display_format = "%.0f", const char *display_format_max = NULL); // Widgets: Input with Keyboard - IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); - - // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go off-bounds) - IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders - IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); - IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); + IMGUI_API bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags = 0, + ImGuiTextEditCallback callback = NULL, void *user_data = NULL); + IMGUI_API bool InputTextMultiline(const char *label, char *buf, size_t buf_size, const ImVec2 &size = ImVec2(0, 0), + ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, + void *user_data = NULL); + IMGUI_API bool InputFloat(const char *label, float *v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, + ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat2(const char *label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat3(const char *label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat4(const char *label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt(const char *label, int *v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt2(const char *label, int v[2], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt3(const char *label, int v[3], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt4(const char *label, int v[4], ImGuiInputTextFlags extra_flags = 0); + + // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go + // off-bounds) + IMGUI_API bool SliderFloat(const char *label, float *v, float v_min, float v_max, const char *display_format = "%.3f", + float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use + // power!=1.0 for logarithmic sliders + IMGUI_API bool SliderFloat2(const char *label, float v[2], float v_min, float v_max, const char *display_format = "%.3f", + float power = 1.0f); + IMGUI_API bool SliderFloat3(const char *label, float v[3], float v_min, float v_max, const char *display_format = "%.3f", + float power = 1.0f); + IMGUI_API bool SliderFloat4(const char *label, float v[4], float v_min, float v_max, const char *display_format = "%.3f", + float power = 1.0f); + IMGUI_API bool SliderAngle(const char *label, float *v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); + IMGUI_API bool SliderInt(const char *label, int *v, int v_min, int v_max, const char *display_format = "%.0f"); + IMGUI_API bool SliderInt2(const char *label, int v[2], int v_min, int v_max, const char *display_format = "%.0f"); + IMGUI_API bool SliderInt3(const char *label, int v[3], int v_min, int v_max, const char *display_format = "%.0f"); + IMGUI_API bool SliderInt4(const char *label, int v[4], int v_min, int v_max, const char *display_format = "%.0f"); + IMGUI_API bool VSliderFloat(const char *label, const ImVec2 &size, float *v, float v_min, float v_max, + const char *display_format = "%.3f", float power = 1.0f); + IMGUI_API bool VSliderInt(const char *label, const ImVec2 &size, int *v, int v_min, int v_max, + const char *display_format = "%.0f"); // Widgets: Trees - IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). - IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // " - IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // " - IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // " - IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); - IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); - IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); - IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); - IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); - IMGUI_API void TreePush(const char* str_id = NULL); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose - IMGUI_API void TreePush(const void* ptr_id = NULL); // " - IMGUI_API void TreePop(); // ~ Unindent()+PopId() - IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() - IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode - IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. - IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). - IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header + IMGUI_API bool TreeNode(const char *label); // if returning 'true' the node is open and the tree id is pushed into the id + // stack. user is responsible for calling TreePop(). + IMGUI_API bool TreeNode(const char *str_id, const char *fmt, ...) + IM_PRINTFARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() + // you can use Bullet(). + IMGUI_API bool TreeNode(const void *ptr_id, const char *fmt, ...) IM_PRINTFARGS(2); // " + IMGUI_API bool TreeNodeV(const char *str_id, const char *fmt, va_list args); // " + IMGUI_API bool TreeNodeV(const void *ptr_id, const char *fmt, va_list args); // " + IMGUI_API bool TreeNodeEx(const char *label, ImGuiTreeNodeFlags flags = 0); + IMGUI_API bool TreeNodeEx(const char *str_id, ImGuiTreeNodeFlags flags, const char *fmt, ...) IM_PRINTFARGS(3); + IMGUI_API bool TreeNodeEx(const void *ptr_id, ImGuiTreeNodeFlags flags, const char *fmt, ...) IM_PRINTFARGS(3); + IMGUI_API bool TreeNodeExV(const char *str_id, ImGuiTreeNodeFlags flags, const char *fmt, va_list args); + IMGUI_API bool TreeNodeExV(const void *ptr_id, ImGuiTreeNodeFlags flags, const char *fmt, va_list args); + IMGUI_API void TreePush(const char *str_id = NULL); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, + // but you can call Push/Pop yourself for layout purpose + IMGUI_API void TreePush(const void *ptr_id = NULL); // " + IMGUI_API void TreePop(); // ~ Unindent()+PopId() + IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() + IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == + // (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode + IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. + IMGUI_API bool CollapsingHeader(const char * label, + ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor + // push on ID stack. user doesn't have to call TreePop(). + IMGUI_API bool CollapsingHeader(const char *label, bool *p_open, + ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close + // button on upper right of the header // Widgets: Selectable / Lists - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height - IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); - IMGUI_API bool ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); - IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. - IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " - IMGUI_API void ListBoxFooter(); // terminate the scrolling region - - // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) - IMGUI_API void Value(const char* prefix, bool b); - IMGUI_API void Value(const char* prefix, int v); - IMGUI_API void Value(const char* prefix, unsigned int v); - IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); - IMGUI_API void ValueColor(const char* prefix, const ImVec4& v); - IMGUI_API void ValueColor(const char* prefix, ImU32 v); + IMGUI_API bool Selectable(const char *label, bool selected = false, ImGuiSelectableFlags flags = 0, + const ImVec2 &size = ImVec2(0, 0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. + // size.y==0.0: use label height, size.y>0.0: specify height + IMGUI_API bool Selectable(const char *label, bool *p_selected, ImGuiSelectableFlags flags = 0, + const ImVec2 &size = ImVec2(0, 0)); + IMGUI_API bool ListBox(const char *label, int *current_item, const char *const *items, int items_count, + int height_in_items = -1); + IMGUI_API bool ListBox(const char *label, int *current_item, bool (*items_getter)(void *data, int idx, const char **out_text), + void *data, int items_count, int height_in_items = -1); + IMGUI_API bool ListBoxHeader(const char * label, + const ImVec2 &size = ImVec2(0, + 0)); // use if you want to reimplement ListBox() will custom data or + // interactions. make sure to call ListBoxFooter() afterwards. + IMGUI_API bool ListBoxHeader(const char *label, int items_count, int height_in_items = -1); // " + IMGUI_API void ListBoxFooter(); // terminate the scrolling region + + // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your + // types. you can add functions to the ImGui namespace) + IMGUI_API void Value(const char *prefix, bool b); + IMGUI_API void Value(const char *prefix, int v); + IMGUI_API void Value(const char *prefix, unsigned int v); + IMGUI_API void Value(const char *prefix, float v, const char *float_format = NULL); + IMGUI_API void ValueColor(const char *prefix, const ImVec4 &v); + IMGUI_API void ValueColor(const char *prefix, ImU32 v); // Tooltips - IMGUI_API void SetTooltip(const char* fmt, ...) IM_PRINTFARGS(1); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). last call wins - IMGUI_API void SetTooltipV(const char* fmt, va_list args); - IMGUI_API void BeginTooltip(); // use to create full-featured tooltip windows that aren't just text - IMGUI_API void EndTooltip(); + IMGUI_API void SetTooltip(const char *fmt, ...) + IM_PRINTFARGS(1); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). last call wins + IMGUI_API void SetTooltipV(const char *fmt, va_list args); + IMGUI_API void BeginTooltip(); // use to create full-featured tooltip windows that aren't just text + IMGUI_API void EndTooltip(); // Menus - IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. only call EndMainMenuBar() if this returns true! - IMGUI_API void EndMainMenuBar(); - IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set). only call EndMenuBar() if this returns true! - IMGUI_API void EndMenuBar(); - IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! - IMGUI_API void EndMenu(); - IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment - IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL + IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. only call EndMainMenuBar() if this returns + // true! + IMGUI_API void EndMainMenuBar(); + IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set). only call + // EndMenuBar() if this returns true! + IMGUI_API void EndMenuBar(); + IMGUI_API bool BeginMenu(const char *label, + bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! + IMGUI_API void EndMenu(); + IMGUI_API bool MenuItem(const char *label, const char *shortcut = NULL, bool selected = false, + bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not + // processed by ImGui at the moment + IMGUI_API bool MenuItem(const char *label, const char *shortcut, bool *p_selected, + bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL // Popups - IMGUI_API void OpenPopup(const char* str_id); // mark popup as open. popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). - IMGUI_API bool BeginPopup(const char* str_id); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! - IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (block interactions behind the modal window, can't close the modal window by clicking outside) - IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item. read comments in .cpp! - IMGUI_API bool BeginPopupContextWindow(bool also_over_items = true, const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (no window). - IMGUI_API void EndPopup(); - IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. - - // Logging: all text output from interface is redirected to tty/file/clipboard. By default, tree nodes are automatically opened during logging. - IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty - IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file - IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard - IMGUI_API void LogFinish(); // stop logging (close file, etc.) - IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard - IMGUI_API void LogText(const char* fmt, ...) IM_PRINTFARGS(1); // pass text data straight to log (without being displayed) + IMGUI_API void OpenPopup( + const char *str_id); // mark popup as open. popups are closed when user click outside, or activate a pressable item, or + // CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. popup identifiers are + // relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). + IMGUI_API bool BeginPopup(const char *str_id); // return true if the popup is open, and you can start outputting to it. only + // call EndPopup() if BeginPopup() returned true! + IMGUI_API bool BeginPopupModal(const char *name, bool *p_open = NULL, + ImGuiWindowFlags extra_flags = 0); // modal dialog (block interactions behind the modal window, + // can't close the modal window by clicking outside) + IMGUI_API bool BeginPopupContextItem( + const char *str_id, + int mouse_button = 1); // helper to open and begin popup when clicked on last item. read comments in .cpp! + IMGUI_API bool BeginPopupContextWindow( + bool also_over_items = true, const char *str_id = NULL, + int mouse_button = 1); // helper to open and begin popup when clicked on current window. + IMGUI_API bool BeginPopupContextVoid( + const char *str_id = NULL, + int mouse_button = 1); // helper to open and begin popup when clicked in void (no window). + IMGUI_API void EndPopup(); + IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable + // automatically close the current popup. + + // Logging: all text output from interface is redirected to tty/file/clipboard. By default, tree nodes are automatically + // opened during logging. + IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty + IMGUI_API void LogToFile(int max_depth = -1, const char *filename = NULL); // start logging to file + IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard + IMGUI_API void LogFinish(); // stop logging (close file, etc.) + IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard + IMGUI_API void LogText(const char *fmt, ...) IM_PRINTFARGS(1); // pass text data straight to log (without being displayed) // Clipping - IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); - IMGUI_API void PopClipRect(); + IMGUI_API void PushClipRect(const ImVec2 &clip_rect_min, const ImVec2 &clip_rect_max, bool intersect_with_current_clip_rect); + IMGUI_API void PopClipRect(); // Utilities - IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? - IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this - IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) - IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) - IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) - IMGUI_API bool IsAnyItemHovered(); - IMGUI_API bool IsAnyItemActive(); - IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space - IMGUI_API ImVec2 GetItemRectMax(); // " - IMGUI_API ImVec2 GetItemRectSize(); // " - IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) - IMGUI_API bool IsWindowFocused(); // is current window focused - IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) - IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused - IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) - IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. - IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. - IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window - IMGUI_API float GetTime(); - IMGUI_API int GetFrameCount(); - IMGUI_API const char* GetStyleColName(ImGuiCol idx); - IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f); // utility to find the closest point the last item bounding rectangle edge. useful to visually link items - IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); - IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame - IMGUI_API void EndChildFrame(); - - IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); - IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); - IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); - IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); + IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? + IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked + // by popup while we are hovering this + IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't + // interact will always return false) + IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) + IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) + IMGUI_API bool IsAnyItemHovered(); + IMGUI_API bool IsAnyItemActive(); + IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space + IMGUI_API ImVec2 GetItemRectMax(); // " + IMGUI_API ImVec2 GetItemRectSize(); // " + IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with + // invisible buttons, selectables, etc. to catch unused area. + IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child + // windows from each others) + IMGUI_API bool IsWindowFocused(); // is current window focused + IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) + IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) + // focused + IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) + // hovered and hoverable (not blocked by a popup) + IMGUI_API bool IsRectVisible( + const ImVec2 &size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. + IMGUI_API bool IsRectVisible(const ImVec2 &rect_min, + const ImVec2 &rect_max); // test if rectangle (in screen space) is visible / not clipped. to + // perform coarse clipping on user's side. + IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2 &pos); // is given position hovering any active imgui window + IMGUI_API float GetTime(); + IMGUI_API int GetFrameCount(); + IMGUI_API const char *GetStyleColName(ImGuiCol idx); + IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2 &pos, bool on_edge = false, + float outward = +0.0f); // utility to find the closest point the last item bounding + // rectangle edge. useful to visually link items + IMGUI_API ImVec2 CalcTextSize(const char *text, const char *text_end = NULL, bool hide_text_after_double_hash = false, + float wrap_width = -1.0f); + IMGUI_API void CalcListClipping( + int items_count, float items_height, int *out_items_display_start, + int *out_items_display_end); // calculate coarse clipping for large list of evenly sized items. + // Prefer using the ImGuiListClipper higher-level helper if you can. + + IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2 &size, + ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that + // looks like a normal widget frame + IMGUI_API void EndChildFrame(); + + IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); + IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4 &in); + IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float &out_h, float &out_s, float &out_v); + IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float &out_r, float &out_g, float &out_b); // Inputs - IMGUI_API int GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] - IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each entry, uses your own indices! - IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate - IMGUI_API bool IsKeyReleased(int key_index); // " - IMGUI_API bool IsMouseDown(int button); // is mouse button held - IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) - IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. - IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) - IMGUI_API bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current window). disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) - IMGUI_API bool IsMouseHoveringAnyWindow(); // is mouse hovering any visible window - IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. - IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold - IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls - IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into - IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold - IMGUI_API void ResetMouseDragDelta(int button = 0); // - IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you - IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type - IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application handle). e.g. force capture keyboard when your widget is being hovered. - IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application handle). + IMGUI_API int GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] + IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each + // entry, uses your own indices! + IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. + // if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate + IMGUI_API bool IsKeyReleased(int key_index); // " + IMGUI_API bool IsMouseDown(int button); // is mouse button held + IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) + IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in + // IsMouseClicked(). uses io.MouseDoubleClickTime. + IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) + IMGUI_API bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current + // window). disregarding of any consideration of being blocked by a popup. (unlike + // IsWindowHovered() this will return true even if the window is blocked because of a + // popup) + IMGUI_API bool IsMouseHoveringAnyWindow(); // is mouse hovering any visible window + IMGUI_API bool IsMouseHoveringRect( + const ImVec2 &r_min, const ImVec2 &r_max, + bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. + // disregarding of consideration of focus/window ordering/blocked by a popup. + IMGUI_API bool IsMouseDragging( + int button = 0, + float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls + IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we + // have BeginPopup() into + IMGUI_API ImVec2 GetMouseDragDelta( + int button = 0, + float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API void ResetMouseDragDelta(int button = 0); // + IMGUI_API ImGuiMouseCursor + GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before + // Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you + IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type + IMGUI_API void CaptureKeyboardFromApp( + bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your + // application handle). e.g. force capture keyboard when your widget is being hovered. + IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag + // is entirely left for your application handle). // Helpers functions to access functions pointers in ImGui::GetIO() - IMGUI_API void* MemAlloc(size_t sz); - IMGUI_API void MemFree(void* ptr); - IMGUI_API const char* GetClipboardText(); - IMGUI_API void SetClipboardText(const char* text); - - // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. - // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. - IMGUI_API const char* GetVersion(); - IMGUI_API ImGuiContext* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); - IMGUI_API void DestroyContext(ImGuiContext* ctx); - IMGUI_API ImGuiContext* GetCurrentContext(); - IMGUI_API void SetCurrentContext(ImGuiContext* ctx); - - // Obsolete (will be removed) + IMGUI_API void * MemAlloc(size_t sz); + IMGUI_API void MemFree(void *ptr); + IMGUI_API const char *GetClipboardText(); + IMGUI_API void SetClipboardText(const char *text); + + // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default + // context created and active by default. All contexts share a same ImFontAtlas by default. If you want different font atlas, + // you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. + IMGUI_API const char *GetVersion(); + IMGUI_API ImGuiContext *CreateContext(void *(*malloc_fn)(size_t) = NULL, void (*free_fn)(void *) = NULL); + IMGUI_API void DestroyContext(ImGuiContext *ctx); + IMGUI_API ImGuiContext *GetCurrentContext(); + IMGUI_API void SetCurrentContext(ImGuiContext *ctx); + +// Obsolete (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ - static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ - static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ - static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETE 1.42+ - static inline bool GetWindowCollapsed() { return ImGui::IsWindowCollapsed(); } // OBSOLETE 1.39+ - static inline bool IsRectClipped(const ImVec2& size) { return !IsRectVisible(size); } // OBSOLETE 1.39+ + static inline bool CollapsingHeader(const char *label, const char *str_id, bool framed = true, bool default_open = false) + { + (void)str_id; + (void)framed; + ImGuiTreeNodeFlags default_open_flags = 1 << 5; + return CollapsingHeader(label, (default_open ? default_open_flags : 0)); + } // OBSOLETE 1.49+ + static inline ImFont *GetWindowFont() + { + return GetFont(); + } // OBSOLETE 1.48+ + static inline float GetWindowFontSize() + { + return GetFontSize(); + } // OBSOLETE 1.48+ + static inline void SetScrollPosHere() + { + SetScrollHere(); + } // OBSOLETE 1.42+ + static inline bool GetWindowCollapsed() + { + return ImGui::IsWindowCollapsed(); + } // OBSOLETE 1.39+ + static inline bool IsRectClipped(const ImVec2 &size) + { + return !IsRectVisible(size); + } // OBSOLETE 1.39+ #endif } // namespace ImGui @@ -478,93 +733,106 @@ namespace ImGui enum ImGuiWindowFlags_ { // Default: 0 - ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar - ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip - ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window - ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically) - ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel - ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it - ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame - ImGuiWindowFlags_ShowBorders = 1 << 7, // Show borders around windows and items - ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file - ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs - ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. - ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state - ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) - ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) - ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) - // [Internal] - ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitY = 1 << 22, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() - ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip() - ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup() - ImGuiWindowFlags_Modal = 1 << 26, // Don't use! For internal use by BeginPopupModal() - ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() + ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar + ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip + ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window + ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically) + ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel + ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it + ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame + ImGuiWindowFlags_ShowBorders = 1 << 7, // Show borders around windows and items + ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file + ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs + ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar + ImGuiWindowFlags_HorizontalScrollbar = + 1 + << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); + // prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. + ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state + ImGuiWindowFlags_NoBringToFrontOnFocus = + 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) + ImGuiWindowFlags_AlwaysVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) + ImGuiWindowFlags_AlwaysHorizontalScrollbar = 1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysUseWindowPadding = + 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child + // windows, because more convenient) [Internal] + ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() + ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() + ImGuiWindowFlags_ChildWindowAutoFitY = 1 << 22, // Don't use! For internal use by BeginChild() + ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() + ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip() + ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup() + ImGuiWindowFlags_Modal = 1 << 26, // Don't use! For internal use by BeginPopupModal() + ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() }; // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { // Default: 0 - ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ - ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef - ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z - ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs - ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus - ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to when the value was modified) - ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Call user function on pressing TAB (for completion handling) - ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Call user function on pressing Up/Down arrows (for history handling) - ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Call user function every time. User code may query cursor position, modify text buffer. - ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 to discard character. - ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field - ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter). - ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally - ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode - ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode - ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' - // [Internal] - ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() + ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ + ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef + ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z + ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs + ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus + ImGuiInputTextFlags_EnterReturnsTrue = + 1 << 5, // Return 'true' when Enter is pressed (as opposed to when the value was modified) + ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Call user function on pressing TAB (for completion handling) + ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Call user function on pressing Up/Down arrows (for history handling) + ImGuiInputTextFlags_CallbackAlways = + 1 << 8, // Call user function every time. User code may query cursor position, modify text buffer. + ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Call user function to filter character. Modify data->EventChar to + // replace/filter input, or return 1 to discard character. + ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field + ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter + // (default is opposite: unfocus with Ctrl+Enter, add line with Enter). + ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally + ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode + ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode + ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' + // [Internal] + ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; // Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() enum ImGuiTreeNodeFlags_ { - ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected - ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) - ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one - ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack - ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) - ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open - ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node - ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. - ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). - ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible - ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog + ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected + ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) + ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one + ImGuiTreeNodeFlags_NoTreePushOnOpen = + 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack + ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by + // default logging will automatically open tree nodes) + ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open + ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node + ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick + // is also set, single-click arrow or double-click all box to open. + ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). + ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow + // ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed + // ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just + // open and contents is not visible + ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; // Flags for ImGui::Selectable() enum ImGuiSelectableFlags_ { // Default: 0 - ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window - ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) - ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too + ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window + ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) + ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too }; // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array enum ImGuiKey_ { - ImGuiKey_Tab, // for tabbing through fields - ImGuiKey_LeftArrow, // for text edit - ImGuiKey_RightArrow,// for text edit - ImGuiKey_UpArrow, // for text edit - ImGuiKey_DownArrow, // for text edit + ImGuiKey_Tab, // for tabbing through fields + ImGuiKey_LeftArrow, // for text edit + ImGuiKey_RightArrow, // for text edit + ImGuiKey_UpArrow, // for text edit + ImGuiKey_DownArrow, // for text edit ImGuiKey_PageUp, ImGuiKey_PageDown, ImGuiKey_Home, // for text edit @@ -587,12 +855,12 @@ enum ImGuiCol_ { ImGuiCol_Text, ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, // Background of normal windows - ImGuiCol_ChildWindowBg, // Background of child windows - ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows + ImGuiCol_WindowBg, // Background of normal windows + ImGuiCol_ChildWindowBg, // Background of child windows + ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows ImGuiCol_Border, ImGuiCol_BorderShadow, - ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input + ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive, ImGuiCol_TitleBg, @@ -627,7 +895,7 @@ enum ImGuiCol_ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active + ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT }; @@ -654,24 +922,24 @@ enum ImGuiStyleVar_ // FIXME-OBSOLETE: Will be replaced by future color/picker api enum ImGuiColorEditMode_ { - ImGuiColorEditMode_UserSelect = -2, + ImGuiColorEditMode_UserSelect = -2, ImGuiColorEditMode_UserSelectShowButton = -1, - ImGuiColorEditMode_RGB = 0, - ImGuiColorEditMode_HSV = 1, - ImGuiColorEditMode_HEX = 2 + ImGuiColorEditMode_RGB = 0, + ImGuiColorEditMode_HSV = 1, + ImGuiColorEditMode_HEX = 2 }; // Enumeration for GetMouseCursor() enum ImGuiMouseCursor_ { - ImGuiMouseCursor_None = -1, + ImGuiMouseCursor_None = -1, ImGuiMouseCursor_Arrow = 0, - ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. - ImGuiMouseCursor_Move, // Unused - ImGuiMouseCursor_ResizeNS, // Unused - ImGuiMouseCursor_ResizeEW, // When hovering over a column - ImGuiMouseCursor_ResizeNESW, // Unused - ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window + ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. + ImGuiMouseCursor_Move, // Unused + ImGuiMouseCursor_ResizeNS, // Unused + ImGuiMouseCursor_ResizeEW, // When hovering over a column + ImGuiMouseCursor_ResizeNESW, // Unused + ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Count_ }; @@ -679,38 +947,45 @@ enum ImGuiMouseCursor_ // All those functions treat 0 as a shortcut to ImGuiSetCond_Always enum ImGuiSetCond_ { - ImGuiSetCond_Always = 1 << 0, // Set the variable - ImGuiSetCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call with succeed) - ImGuiSetCond_FirstUseEver = 1 << 2, // Set the variable if the window has no saved data (if doesn't exist in the .ini file) - ImGuiSetCond_Appearing = 1 << 3 // Set the variable if the window is appearing after being hidden/inactive (or the first time) + ImGuiSetCond_Always = 1 << 0, // Set the variable + ImGuiSetCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call with succeed) + ImGuiSetCond_FirstUseEver = 1 << 2, // Set the variable if the window has no saved data (if doesn't exist in the .ini file) + ImGuiSetCond_Appearing = 1 << 3 // Set the variable if the window is appearing after being hidden/inactive (or the first time) }; struct ImGuiStyle { - float Alpha; // Global alpha applies to everything in ImGui - ImVec2 WindowPadding; // Padding within a window - ImVec2 WindowMinSize; // Minimum window size - float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows - ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. - float ChildWindowRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows - ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets) - float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). - ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines - ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) - ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - float ColumnsMinSpacing; // Minimum horizontal spacing between two columns - float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar - float ScrollbarRounding; // Radius of grab corners for scrollbar - float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. - float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. - ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered. - ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. - ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. - bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. - bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - float CurveTessellationTol; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - ImVec4 Colors[ImGuiCol_COUNT]; + float Alpha; // Global alpha applies to everything in ImGui + ImVec2 WindowPadding; // Padding within a window + ImVec2 WindowMinSize; // Minimum window size + float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows + ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. + float ChildWindowRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows + ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets) + float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). + ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines + ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and + // its label) + ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. + // Unfortunately we don't sort widgets so priority on overlap will always be given to the first + // widget. So don't grow this too much! + float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). + float ColumnsMinSpacing; // Minimum horizontal spacing between two columns + float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar + float ScrollbarRounding; // Radius of grab corners for scrollbar + float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. + float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. + ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for + // horizontally+vertically centered. + ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. + // Only covers regular windows. + ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. + // Covers popups/tooltips as well regular windows. + bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. + bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + float CurveTessellationTol; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), + // increase to reduce quality. + ImVec4 Colors[ImGuiCol_COUNT]; IMGUI_API ImGuiStyle(); }; @@ -723,29 +998,37 @@ struct ImGuiIO // Settings (fill once) // Default value: //------------------------------------------------------------------ - ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. - float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. - float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. - const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. - const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). - float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. - float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. - float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging - int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array - float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). - float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. - void* UserData; // = NULL // Store your own data for retrieval by callbacks. - - ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. - float FontGlobalScale; // = 1.0f // Global scale all fonts - bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. - ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. - ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui. - ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. - ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize + ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. + float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. + float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. + const char *IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. + const char *LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is + // specified). + float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. + float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. + float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging + int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array + float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for + // buttons in Repeat mode, etc.). + float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. + void *UserData; // = NULL // Store your own data for retrieval by callbacks. + + ImFontAtlas *Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. + // Output to Fonts array. + float FontGlobalScale; // = 1.0f // Global scale all fonts + bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. + ImFont *FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. + ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are + // different from framebuffer coordinates. User storage only, presently not used by ImGui. + ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set + // DisplayVisibleMin/Max to the visible area. + ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize // Advanced/subtle behaviors - bool OSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl + bool OSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts + // using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double + // click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead + // of Ctrl //------------------------------------------------------------------ // User Functions @@ -754,136 +1037,252 @@ struct ImGuiIO // Rendering function, will be called in Render(). // Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer. // See example applications if you are unsure of how to implement this. - void (*RenderDrawListsFn)(ImDrawData* data); + void (*RenderDrawListsFn)(ImDrawData *data); // Optional: access OS clipboard - // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) - const char* (*GetClipboardTextFn)(void* user_data); - void (*SetClipboardTextFn)(void* user_data, const char* text); - void* ClipboardUserData; + // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on + // other architectures) + const char *(*GetClipboardTextFn)(void *user_data); + void (*SetClipboardTextFn)(void *user_data, const char *text); + void *ClipboardUserData; // Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. // (default to posix malloc/free) - void* (*MemAllocFn)(size_t sz); - void (*MemFreeFn)(void* ptr); + void *(*MemAllocFn)(size_t sz); + void (*MemFreeFn)(void *ptr); - // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows) - // (default to use native imm32 api on Windows) - void (*ImeSetInputScreenPosFn)(int x, int y); - void* ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning. + // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using + // Japanese/Chinese IME in Windows) (default to use native imm32 api on Windows) + void (*ImeSetInputScreenPosFn)(int x, int y); + void *ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning. //------------------------------------------------------------------ // Input - Fill before calling NewFrame() //------------------------------------------------------------------ - ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) - bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. - bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). - bool KeyCtrl; // Keyboard modifier pressed: Control - bool KeyShift; // Keyboard modifier pressed: Shift - bool KeyAlt; // Keyboard modifier pressed: Alt - bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows - bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) - ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. + ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button + // (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being + // used by your application + available to user as a convenience via IsMouse** API. + float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. + bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). + bool KeyCtrl; // Keyboard modifier pressed: Control + bool KeyShift; // Keyboard modifier pressed: Shift + bool KeyAlt; // Keyboard modifier pressed: Alt + bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows + bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) + ImWchar InputCharacters[16 + 1]; // List of characters input (translated by user from keypress+keyboard state). Fill using + // AddInputCharacter() helper. // Functions - IMGUI_API void AddInputCharacter(ImWchar c); // Add new character into InputCharacters[] - IMGUI_API void AddInputCharactersUTF8(const char* utf8_chars); // Add new characters into InputCharacters[] from an UTF-8 string - inline void ClearInputCharacters() { InputCharacters[0] = 0; } // Clear the text input buffer manually + IMGUI_API void AddInputCharacter(ImWchar c); // Add new character into InputCharacters[] + IMGUI_API void AddInputCharactersUTF8( + const char *utf8_chars); // Add new characters into InputCharacters[] from an UTF-8 string + inline void ClearInputCharacters() + { + InputCharacters[0] = 0; + } // Clear the text input buffer manually //------------------------------------------------------------------ // Output - Retrieve after calling NewFrame() //------------------------------------------------------------------ - bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input). Use to hide mouse from the rest of your application - bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input). Use to hide keyboard from the rest of your application - bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. Use to activate on screen keyboard if your system needs one - float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames - int MetricsAllocs; // Number of active memory allocations - int MetricsRenderVertices; // Vertices output during last call to Render() - int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 - int MetricsActiveWindows; // Number of visible root windows (exclude child windows) - ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are negative, so a disappearing/reappearing mouse won't have a huge delta for one frame. + bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input). Use to hide + // mouse from the rest of your application + bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input). Use to hide keyboard from the rest of + // your application + bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. Use + // to activate on screen keyboard if your system needs one + float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation + // based on IO.DeltaTime over 120 frames + int MetricsAllocs; // Number of active memory allocations + int MetricsRenderVertices; // Vertices output during last call to Render() + int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 + int MetricsActiveWindows; // Number of visible root windows (exclude child windows) + ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are negative, so a + // disappearing/reappearing mouse won't have a huge delta for one frame. //------------------------------------------------------------------ // [Private] ImGui will maintain those fields. Forward compatibility not guaranteed! //------------------------------------------------------------------ - ImVec2 MousePosPrev; // Previous mouse position temporary storage (nb: not for public use, set to MousePos in NewFrame()) - bool MouseClicked[5]; // Mouse button went from !Down to Down - ImVec2 MouseClickedPos[5]; // Position at time of clicking - float MouseClickedTime[5]; // Time of last click (used to figure out double-click) - bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? - bool MouseReleased[5]; // Mouse button went from Down to !Down - bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds. - float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) - float MouseDownDurationPrev[5]; // Previous time the mouse button has been down - float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the click point - float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) - float KeysDownDurationPrev[512]; // Previous duration the key has been down - - IMGUI_API ImGuiIO(); + ImVec2 MousePosPrev; // Previous mouse position temporary storage (nb: not for public use, set to MousePos in NewFrame()) + bool MouseClicked[5]; // Mouse button went from !Down to Down + ImVec2 MouseClickedPos[5]; // Position at time of clicking + float MouseClickedTime[5]; // Time of last click (used to figure out double-click) + bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? + bool MouseReleased[5]; // Mouse button went from Down to !Down + bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if + // click started outside ImGui bounds. + float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) + float MouseDownDurationPrev[5]; // Previous time the mouse button has been down + float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the click point + float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) + float KeysDownDurationPrev[512]; // Previous duration the key has been down + + IMGUI_API ImGuiIO(); }; //----------------------------------------------------------------------------- // Helpers //----------------------------------------------------------------------------- -// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). -// Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code! -template -class ImVector +// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is +// absurdly slow, so let's bypass it so our code runs fast in debug). Our implementation does NOT call c++ constructors because we +// don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code! +template class ImVector { -public: - int Size; - int Capacity; - T* Data; + public: + int Size; + int Capacity; + T * Data; - typedef T value_type; - typedef value_type* iterator; - typedef const value_type* const_iterator; + typedef T value_type; + typedef value_type * iterator; + typedef const value_type *const_iterator; - ImVector() { Size = Capacity = 0; Data = NULL; } - ~ImVector() { if (Data) ImGui::MemFree(Data); } + ImVector() + { + Size = Capacity = 0; + Data = NULL; + } + ~ImVector() + { + if (Data) ImGui::MemFree(Data); + } - inline bool empty() const { return Size == 0; } - inline int size() const { return Size; } - inline int capacity() const { return Capacity; } + inline bool empty() const + { + return Size == 0; + } + inline int size() const + { + return Size; + } + inline int capacity() const + { + return Capacity; + } - inline value_type& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; } - inline const value_type& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; } + inline value_type &operator[](int i) + { + IM_ASSERT(i < Size); + return Data[i]; + } + inline const value_type &operator[](int i) const + { + IM_ASSERT(i < Size); + return Data[i]; + } - inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } } - inline iterator begin() { return Data; } - inline const_iterator begin() const { return Data; } - inline iterator end() { return Data + Size; } - inline const_iterator end() const { return Data + Size; } - inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; } - inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; } - inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; } - inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; } - inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } + inline void clear() + { + if (Data) + { + Size = Capacity = 0; + ImGui::MemFree(Data); + Data = NULL; + } + } + inline iterator begin() + { + return Data; + } + inline const_iterator begin() const + { + return Data; + } + inline iterator end() + { + return Data + Size; + } + inline const_iterator end() const + { + return Data + Size; + } + inline value_type &front() + { + IM_ASSERT(Size > 0); + return Data[0]; + } + inline const value_type &front() const + { + IM_ASSERT(Size > 0); + return Data[0]; + } + inline value_type &back() + { + IM_ASSERT(Size > 0); + return Data[Size - 1]; + } + inline const value_type &back() const + { + IM_ASSERT(Size > 0); + return Data[Size - 1]; + } + inline void swap(ImVector &rhs) + { + int rhs_size = rhs.Size; + rhs.Size = Size; + Size = rhs_size; + int rhs_cap = rhs.Capacity; + rhs.Capacity = Capacity; + Capacity = rhs_cap; + value_type *rhs_data = rhs.Data; + rhs.Data = Data; + Data = rhs_data; + } - inline int _grow_capacity(int new_size) { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > new_size ? new_capacity : new_size; } + inline int _grow_capacity(int new_size) + { + int new_capacity = Capacity ? (Capacity + Capacity / 2) : 8; + return new_capacity > new_size ? new_capacity : new_size; + } - inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void reserve(int new_capacity) + inline void resize(int new_size) + { + if (new_size > Capacity) reserve(_grow_capacity(new_size)); + Size = new_size; + } + inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; - T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); - if (Data) - memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); + T *new_data = (value_type *)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); + if (Data) memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); ImGui::MemFree(Data); - Data = new_data; + Data = new_data; Capacity = new_capacity; } - inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; } - inline void pop_back() { IM_ASSERT(Size > 0); Size--; } + inline void push_back(const value_type &v) + { + if (Size == Capacity) reserve(_grow_capacity(Size + 1)); + Data[Size++] = v; + } + inline void pop_back() + { + IM_ASSERT(Size > 0); + Size--; + } - inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } - inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } + inline iterator erase(const_iterator it) + { + IM_ASSERT(it >= Data && it < Data + Size); + const ptrdiff_t off = it - Data; + memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); + Size--; + return Data + off; + } + inline iterator insert(const_iterator it, const value_type &v) + { + IM_ASSERT(it >= Data && it <= Data + Size); + const ptrdiff_t off = it - Data; + if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); + if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); + Data[off] = v; + Size++; + return Data + off; + } }; // Helper: execute a block of code at maximum once a frame @@ -894,12 +1293,23 @@ class ImVector // // code block will be executed one per frame // } // Attention! the macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces. -#define IMGUI_ONCE_UPON_A_FRAME static ImGuiOnceUponAFrame imgui_oaf##__LINE__; if (imgui_oaf##__LINE__) +#define IMGUI_ONCE_UPON_A_FRAME \ + static ImGuiOnceUponAFrame imgui_oaf##__LINE__; \ + if (imgui_oaf##__LINE__) struct ImGuiOnceUponAFrame { - ImGuiOnceUponAFrame() { RefFrame = -1; } + ImGuiOnceUponAFrame() + { + RefFrame = -1; + } mutable int RefFrame; - operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } + operator bool() const + { + int current_frame = ImGui::GetFrameCount(); + if (RefFrame == current_frame) return false; + RefFrame = current_frame; + return true; + } }; // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" @@ -907,48 +1317,110 @@ struct ImGuiTextFilter { struct TextRange { - const char* b; - const char* e; - - TextRange() { b = e = NULL; } - TextRange(const char* _b, const char* _e) { b = _b; e = _e; } - const char* begin() const { return b; } - const char* end() const { return e; } - bool empty() const { return b == e; } - char front() const { return *b; } - static bool is_blank(char c) { return c == ' ' || c == '\t'; } - void trim_blanks() { while (b < e && is_blank(*b)) b++; while (e > b && is_blank(*(e-1))) e--; } - IMGUI_API void split(char separator, ImVector& out); + const char *b; + const char *e; + + TextRange() + { + b = e = NULL; + } + TextRange(const char *_b, const char *_e) + { + b = _b; + e = _e; + } + const char *begin() const + { + return b; + } + const char *end() const + { + return e; + } + bool empty() const + { + return b == e; + } + char front() const + { + return *b; + } + static bool is_blank(char c) + { + return c == ' ' || c == '\t'; + } + void trim_blanks() + { + while (b < e && is_blank(*b)) + b++; + while (e > b && is_blank(*(e - 1))) + e--; + } + IMGUI_API void split(char separator, ImVector &out); }; char InputBuf[256]; ImVector Filters; int CountGrep; - ImGuiTextFilter(const char* default_filter = ""); - ~ImGuiTextFilter() {} - void Clear() { InputBuf[0] = 0; Build(); } - bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build - bool PassFilter(const char* text, const char* text_end = NULL) const; - bool IsActive() const { return !Filters.empty(); } - IMGUI_API void Build(); + ImGuiTextFilter(const char *default_filter = ""); + ~ImGuiTextFilter() + { + } + void Clear() + { + InputBuf[0] = 0; + Build(); + } + bool Draw(const char *label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build + bool PassFilter(const char *text, const char *text_end = NULL) const; + bool IsActive() const + { + return !Filters.empty(); + } + IMGUI_API void Build(); }; // Helper: Text buffer for logging/accumulating text struct ImGuiTextBuffer { - ImVector Buf; - - ImGuiTextBuffer() { Buf.push_back(0); } - inline char operator[](int i) { return Buf.Data[i]; } - const char* begin() const { return &Buf.front(); } - const char* end() const { return &Buf.back(); } // Buf is zero-terminated, so end() will point on the zero-terminator - int size() const { return Buf.Size - 1; } - bool empty() { return Buf.Size <= 1; } - void clear() { Buf.clear(); Buf.push_back(0); } - const char* c_str() const { return Buf.Data; } - IMGUI_API void append(const char* fmt, ...) IM_PRINTFARGS(2); - IMGUI_API void appendv(const char* fmt, va_list args); + ImVector Buf; + + ImGuiTextBuffer() + { + Buf.push_back(0); + } + inline char operator[](int i) + { + return Buf.Data[i]; + } + const char *begin() const + { + return &Buf.front(); + } + const char *end() const + { + return &Buf.back(); + } // Buf is zero-terminated, so end() will point on the zero-terminator + int size() const + { + return Buf.Size - 1; + } + bool empty() + { + return Buf.Size <= 1; + } + void clear() + { + Buf.clear(); + Buf.push_back(0); + } + const char *c_str() const + { + return Buf.Data; + } + IMGUI_API void append(const char *fmt, ...) IM_PRINTFARGS(2); + IMGUI_API void appendv(const char *fmt, va_list args); }; // Helper: Simple Key->value storage @@ -956,7 +1428,8 @@ struct ImGuiTextBuffer // We use it to e.g. store collapse state for a tree (Int 0/1), store color edit options. // You can use it as custom user storage for temporary values. // Declare your own storage if: -// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). +// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their +// state). // - You want to store custom debug data easily without adding or editing structures in your code. // Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. struct ImGuiStorage @@ -964,168 +1437,264 @@ struct ImGuiStorage struct Pair { ImGuiID key; - union { int val_i; float val_f; void* val_p; }; - Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } - Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } - Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } + union { + int val_i; + float val_f; + void *val_p; + }; + Pair(ImGuiID _key, int _val_i) + { + key = _key; + val_i = _val_i; + } + Pair(ImGuiID _key, float _val_f) + { + key = _key; + val_f = _val_f; + } + Pair(ImGuiID _key, void *_val_p) + { + key = _key; + val_p = _val_p; + } }; - ImVector Data; + ImVector Data; // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) // - Set***() functions find pair, insertion on demand if missing. // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair. - IMGUI_API void Clear(); - IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; - IMGUI_API void SetInt(ImGuiID key, int val); - IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; - IMGUI_API void SetBool(ImGuiID key, bool val); - IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; - IMGUI_API void SetFloat(ImGuiID key, float val); - IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL - IMGUI_API void SetVoidPtr(ImGuiID key, void* val); + IMGUI_API void Clear(); + IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; + IMGUI_API void SetInt(ImGuiID key, int val); + IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; + IMGUI_API void SetBool(ImGuiID key, bool val); + IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; + IMGUI_API void SetFloat(ImGuiID key, float val); + IMGUI_API void *GetVoidPtr(ImGuiID key) const; // default_val is NULL + IMGUI_API void SetVoidPtr(ImGuiID key, void *val); // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. - // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. - // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct) + // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() + // function invalidates the pointer. + // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if + // you can't modify existing struct) // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; - IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); - IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false); - IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); - IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); + IMGUI_API int * GetIntRef(ImGuiID key, int default_val = 0); + IMGUI_API bool * GetBoolRef(ImGuiID key, bool default_val = false); + IMGUI_API float *GetFloatRef(ImGuiID key, float default_val = 0.0f); + IMGUI_API void **GetVoidPtrRef(ImGuiID key, void *default_val = NULL); // Use on your own storage if you know only integer are being stored (open/close all tree nodes) - IMGUI_API void SetAllInt(int val); + IMGUI_API void SetAllInt(int val); }; -// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered. +// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding +// callback is triggered. struct ImGuiTextEditCallbackData { - ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only - ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only - void* UserData; // What user passed to InputText() // Read-only - bool ReadOnly; // Read-only mode // Read-only + ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only + ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only + void * UserData; // What user passed to InputText() // Read-only + bool ReadOnly; // Read-only mode // Read-only // CharFilter event: - ImWchar EventChar; // Character input // Read-write (replace character or set to zero) + ImWchar EventChar; // Character input // Read-write (replace character or set to zero) // Completion,History,Always events: // If you modify the buffer contents make sure you update 'BufTextLen' and set 'BufDirty' to true. - ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only - char* Buf; // Current text buffer // Read-write (pointed data only, can't replace the actual pointer) - int BufTextLen; // Current text length in bytes // Read-write - int BufSize; // Maximum text length in bytes // Read-only - bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write - int CursorPos; // // Read-write - int SelectionStart; // // Read-write (== to SelectionEnd when no selection) - int SelectionEnd; // // Read-write + ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only + char * Buf; // Current text buffer // Read-write (pointed data only, can't replace the actual pointer) + int BufTextLen; // Current text length in bytes // Read-write + int BufSize; // Maximum text length in bytes // Read-only + bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write + int CursorPos; // // Read-write + int SelectionStart; // // Read-write (== to SelectionEnd when no selection) + int SelectionEnd; // // Read-write // NB: Helper functions for text manipulation. Calling those function loses selection. - IMGUI_API void DeleteChars(int pos, int bytes_count); - IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL); - bool HasSelection() const { return SelectionStart != SelectionEnd; } + IMGUI_API void DeleteChars(int pos, int bytes_count); + IMGUI_API void InsertChars(int pos, const char *text, const char *text_end = NULL); + bool HasSelection() const + { + return SelectionStart != SelectionEnd; + } }; -// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). -// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. +// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the +// next Begin(). NB: For basic min/max size constraint on each axis you don't need to use the callback! The +// SetNextWindowSizeConstraints() parameters are enough. struct ImGuiSizeConstraintCallbackData { - void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() - ImVec2 Pos; // Read-only. Window position, for reference. - ImVec2 CurrentSize; // Read-only. Current window size. - ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. + void * UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() + ImVec2 Pos; // Read-only. Window position, for reference. + ImVec2 CurrentSize; // Read-only. Current window size. + ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. }; // Helpers macros to generate 32-bits encoded colors #ifdef IMGUI_USE_BGRA_PACKED_COLOR -#define IM_COL32_R_SHIFT 16 -#define IM_COL32_G_SHIFT 8 -#define IM_COL32_B_SHIFT 0 -#define IM_COL32_A_SHIFT 24 -#define IM_COL32_A_MASK 0xFF000000 + #define IM_COL32_R_SHIFT 16 + #define IM_COL32_G_SHIFT 8 + #define IM_COL32_B_SHIFT 0 + #define IM_COL32_A_SHIFT 24 + #define IM_COL32_A_MASK 0xFF000000 #else -#define IM_COL32_R_SHIFT 0 -#define IM_COL32_G_SHIFT 8 -#define IM_COL32_B_SHIFT 16 -#define IM_COL32_A_SHIFT 24 -#define IM_COL32_A_MASK 0xFF000000 + #define IM_COL32_R_SHIFT 0 + #define IM_COL32_G_SHIFT 8 + #define IM_COL32_B_SHIFT 16 + #define IM_COL32_A_SHIFT 24 + #define IM_COL32_A_MASK 0xFF000000 #endif -#define IM_COL32(R,G,B,A) (((ImU32)(A)<>IM_COL32_R_SHIFT)&0xFF) * sc; Value.y = (float)((rgba>>IM_COL32_G_SHIFT)&0xFF) * sc; Value.z = (float)((rgba>>IM_COL32_B_SHIFT)&0xFF) * sc; Value.w = (float)((rgba>>IM_COL32_A_SHIFT)&0xFF) * sc; } - ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; } - ImColor(const ImVec4& col) { Value = col; } - inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } - inline operator ImVec4() const { return Value; } + ImColor() + { + Value.x = Value.y = Value.z = Value.w = 0.0f; + } + ImColor(int r, int g, int b, int a = 255) + { + float sc = 1.0f / 255.0f; + Value.x = (float)r * sc; + Value.y = (float)g * sc; + Value.z = (float)b * sc; + Value.w = (float)a * sc; + } + ImColor(ImU32 rgba) + { + float sc = 1.0f / 255.0f; + Value.x = (float)((rgba >> IM_COL32_R_SHIFT) & 0xFF) * sc; + Value.y = (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * sc; + Value.z = (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * sc; + Value.w = (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * sc; + } + ImColor(float r, float g, float b, float a = 1.0f) + { + Value.x = r; + Value.y = g; + Value.z = b; + Value.w = a; + } + ImColor(const ImVec4 &col) + { + Value = col; + } + inline operator ImU32() const + { + return ImGui::ColorConvertFloat4ToU32(Value); + } + inline operator ImVec4() const + { + return Value; + } - inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; } + inline void SetHSV(float h, float s, float v, float a = 1.0f) + { + ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); + Value.w = a; + } - static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); } + static ImColor HSV(float h, float s, float v, float a = 1.0f) + { + float r, g, b; + ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); + return ImColor(r, g, b, a); + } }; // Helper: Manually clip large list of items. -// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all. -// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. -// ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null. -// Usage: +// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping +// based on visibility to save yourself from processing those items at all. The clipper calculates the range of visible items and +// advance the cursor to compensate for the non-visible items we have skipped. ImGui already clip items based on their bounds but +// it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission +// cost null. Usage: // ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced. // while (clipper.Step()) // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) // ImGui::Text("line number %d", i); -// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor). -// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. -// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.) -// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. +// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element +// height (step skipped if we passed a known height as second arg to constructor). +// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the +// cursor before the first element. +// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does +// nothing and switch to Step 3.) +// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the +// cursor to the end of the list and then returns 'false' to end the loop. struct ImGuiListClipper { - float StartPosY; - float ItemsHeight; - int ItemsCount, StepNo, DisplayStart, DisplayEnd; - - // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). - // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing(). - // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step(). - ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). - ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false. - - IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. - IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. - IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. + float StartPosY; + float ItemsHeight; + int ItemsCount, StepNo, DisplayStart, DisplayEnd; + + // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which + // case the cursor won't be advanced in the final step). items_height: Use -1.0f to be calculated automatically on first step. + // Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or + // GetItemsLineHeightWithSpacing(). If you don't specify an items_height, you NEED to call Step(). If you specify items_height + // you may call the old Begin()/End() api directly, but prefer calling Step(). + ImGuiListClipper(int items_count = -1, float items_height = -1.0f) + { + Begin(items_count, items_height); + } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). + ~ImGuiListClipper() + { + IM_ASSERT(ItemsCount == -1); + } // Assert if user forgot to call End() or Step() until false. + + IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw + // those items. + IMGUI_API void Begin( + int items_count, + float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. + IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. }; //----------------------------------------------------------------------------- // Draw List -// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. +// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of +// ImDrawList. //----------------------------------------------------------------------------- // Draw callbacks for advanced uses. -// NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that) -// Draw callback may be useful for example, A) Change your GPU render state, B) render a complex 3D scene inside a UI element (without an intermediate texture/render target), etc. -// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()' -typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); +// NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke +// into the draw list for that) Draw callback may be useful for example, A) Change your GPU render state, B) render a complex 3D +// scene inside a UI element (without an intermediate texture/render target), etc. The expected behavior from your rendering +// function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()' +typedef void (*ImDrawCallback)(const ImDrawList *parent_list, const ImDrawCmd *cmd); // Typically, 1 command = 1 gpu draw call (unless command is a callback) struct ImDrawCmd { - unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. - ImVec4 ClipRect; // Clipping rectangle (x1, y1, x2, y2) - ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. - ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. - void* UserCallbackData; // The draw callback code can access this. - - ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } + unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee + // ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. + ImVec4 ClipRect; // Clipping rectangle (x1, y1, x2, y2) + ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() + // functions. Ignore if never using images or multiple fonts atlas. + ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will + // be set normally. + void *UserCallbackData; // The draw callback code can access this. + + ImDrawCmd() + { + ElemCount = 0; + ClipRect.x = ClipRect.y = -8192.0f; + ClipRect.z = ClipRect.w = +8192.0f; + TextureId = NULL; + UserCallback = NULL; + UserCallbackData = NULL; + } }; // Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h) @@ -1137,146 +1706,232 @@ typedef unsigned short ImDrawIdx; #ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { - ImVec2 pos; - ImVec2 uv; - ImU32 col; + ImVec2 pos; + ImVec2 uv; + ImU32 col; }; #else // You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h -// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine. -// The type has to be described within the macro (you can either declare the struct or use a typedef) +// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields +// as needed to simplify integration in your engine. The type has to be described within the macro (you can either declare the +// struct or use a typedef) IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; #endif -// Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each column can be batched together. -// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered. +// Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each +// column can be batched together. You can also use them to simulate drawing layers and submit primitives in a different order +// than how they will be rendered. struct ImDrawChannel { - ImVector CmdBuffer; - ImVector IdxBuffer; + ImVector CmdBuffer; + ImVector IdxBuffer; }; // Draw command list -// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. -// At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged in the future. -// If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives. -// You can interleave normal ImGui:: calls and adding primitives to the current draw list. -// All positions are in screen coordinates (0,0=top-left, 1 pixel per unit). Primitives are always added to the list and not culled (culling is done at render time and at a higher-level by ImGui:: functions). +// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed +// to your ImGuiIO::RenderDrawListFn function for rendering. At the moment, each ImGui window contains its own ImDrawList but they +// could potentially be merged in the future. If you want to add custom rendering within a window, you can use +// ImGui::GetWindowDrawList() to access the current draw list and add your own primitives. You can interleave normal ImGui:: calls +// and adding primitives to the current draw list. All positions are in screen coordinates (0,0=top-left, 1 pixel per unit). +// Primitives are always added to the list and not culled (culling is done at render time and at a higher-level by ImGui:: +// functions). struct ImDrawList { // This is what you have to render - ImVector CmdBuffer; // Commands. Typically 1 command = 1 gpu draw call. - ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those - ImVector VtxBuffer; // Vertex buffer. + ImVector CmdBuffer; // Commands. Typically 1 command = 1 gpu draw call. + ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those + ImVector VtxBuffer; // Vertex buffer. // [Internal, used while building lists] - const char* _OwnerName; // Pointer to owner window's name for debugging - unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size - ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) - ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) - ImVector _ClipRectStack; // [Internal] - ImVector _TextureIdStack; // [Internal] - ImVector _Path; // [Internal] current path building - int _ChannelsCurrent; // [Internal] current channel number (0) - int _ChannelsCount; // [Internal] number of active channels (1+) - ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size) - - ImDrawList() { _OwnerName = NULL; Clear(); } - ~ImDrawList() { ClearFreeMemory(); } - IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) - IMGUI_API void PushClipRectFullScreen(); - IMGUI_API void PopClipRect(); - IMGUI_API void PushTextureID(const ImTextureID& texture_id); - IMGUI_API void PopTextureID(); + const char * _OwnerName; // Pointer to owner window's name for debugging + unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size + ImDrawVert * _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> + // operators too much) + ImDrawIdx *_IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> + // operators too much) + ImVector _ClipRectStack; // [Internal] + ImVector _TextureIdStack; // [Internal] + ImVector _Path; // [Internal] current path building + int _ChannelsCurrent; // [Internal] current channel number (0) + int _ChannelsCount; // [Internal] number of active channels (1+) + ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be + // smaller than _Channels.Size) + + ImDrawList() + { + _OwnerName = NULL; + Clear(); + } + ~ImDrawList() + { + ClearFreeMemory(); + } + IMGUI_API void PushClipRect( + ImVec2 clip_rect_min, ImVec2 clip_rect_max, + bool intersect_with_current_clip_rect = + false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse + // clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) + IMGUI_API void PushClipRectFullScreen(); + IMGUI_API void PopClipRect(); + IMGUI_API void PushTextureID(const ImTextureID &texture_id); + IMGUI_API void PopTextureID(); // Primitives - IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0, float thickness = 1.0f); // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding to which corner to round - IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0); // a: upper-left, b: lower-right - IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); - IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col); - IMGUI_API void AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col); - IMGUI_API void AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); - IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12); - IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); - IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); - IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = 0xFFFFFFFF); - IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = 0xFFFFFFFF); - IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased); - IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased); - IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); + IMGUI_API void AddLine(const ImVec2 &a, const ImVec2 &b, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddRect(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0, + float thickness = 1.0f); // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding + // to which corner to round + IMGUI_API void AddRectFilled(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding = 0.0f, + int rounding_corners_flags = ~0); // a: upper-left, b: lower-right + IMGUI_API void AddRectFilledMultiColor(const ImVec2 &a, const ImVec2 &b, ImU32 col_upr_left, ImU32 col_upr_right, + ImU32 col_bot_right, ImU32 col_bot_left); + IMGUI_API void AddQuad(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddQuadFilled(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, ImU32 col); + IMGUI_API void AddTriangle(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddTriangleFilled(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col); + IMGUI_API void AddCircle(const ImVec2 ¢re, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); + IMGUI_API void AddCircleFilled(const ImVec2 ¢re, float radius, ImU32 col, int num_segments = 12); + IMGUI_API void AddText(const ImVec2 &pos, ImU32 col, const char *text_begin, const char *text_end = NULL); + IMGUI_API void AddText(const ImFont *font, float font_size, const ImVec2 &pos, ImU32 col, const char *text_begin, + const char *text_end = NULL, float wrap_width = 0.0f, const ImVec4 *cpu_fine_clip_rect = NULL); + IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2 &a, const ImVec2 &b, const ImVec2 &uv_a = ImVec2(0, 0), + const ImVec2 &uv_b = ImVec2(1, 1), ImU32 col = 0xFFFFFFFF); + IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, + const ImVec2 &uv_a = ImVec2(0, 0), const ImVec2 &uv_b = ImVec2(1, 0), + const ImVec2 &uv_c = ImVec2(1, 1), const ImVec2 &uv_d = ImVec2(0, 1), ImU32 col = 0xFFFFFFFF); + IMGUI_API void AddPolyline(const ImVec2 *points, const int num_points, ImU32 col, bool closed, float thickness, + bool anti_aliased); + IMGUI_API void AddConvexPolyFilled(const ImVec2 *points, const int num_points, ImU32 col, bool anti_aliased); + IMGUI_API void AddBezierCurve(const ImVec2 &pos0, const ImVec2 &cp0, const ImVec2 &cp1, const ImVec2 &pos1, ImU32 col, + float thickness, int num_segments = 0); // Stateful path API, add points then finish with PathFill() or PathStroke() - inline void PathClear() { _Path.resize(0); } - inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } - inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } - inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } - IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); - IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle - IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); - IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ~0); // rounding_corners_flags: 4-bits corresponding to which corner to round + inline void PathClear() + { + _Path.resize(0); + } + inline void PathLineTo(const ImVec2 &pos) + { + _Path.push_back(pos); + } + inline void PathLineToMergeDuplicate(const ImVec2 &pos) + { + if (_Path.Size == 0 || memcmp(&_Path[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); + } + inline void PathFillConvex(ImU32 col) + { + AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); + PathClear(); + } + inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) + { + AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); + PathClear(); + } + IMGUI_API void PathArcTo(const ImVec2 ¢re, float radius, float a_min, float a_max, int num_segments = 10); + IMGUI_API void PathArcToFast(const ImVec2 ¢re, float radius, int a_min_of_12, + int a_max_of_12); // Use precomputed angles for a 12 steps circle + IMGUI_API void PathBezierCurveTo(const ImVec2 &p1, const ImVec2 &p2, const ImVec2 &p3, int num_segments = 0); + IMGUI_API void PathRect( + const ImVec2 &rect_min, const ImVec2 &rect_max, float rounding = 0.0f, + int rounding_corners_flags = ~0); // rounding_corners_flags: 4-bits corresponding to which corner to round // Channels - // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives) - // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end) - IMGUI_API void ChannelsSplit(int channels_count); - IMGUI_API void ChannelsMerge(); - IMGUI_API void ChannelsSetCurrent(int channel_index); + // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before + // background primitives) + // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to + // append into separate channels then merge at the end) + IMGUI_API void ChannelsSplit(int channels_count); + IMGUI_API void ChannelsMerge(); + IMGUI_API void ChannelsSetCurrent(int channel_index); // Advanced - IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. - IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible + IMGUI_API void AddCallback(ImDrawCallback callback, + void *callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and + // call the function instead of rendering triangles. + IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent + // rendering / blending). Otherwise primitives are merged into the same draw-call as much as + // possible // Internal helpers // NB: all primitives needs to be reserved via PrimReserve() beforehand! - IMGUI_API void Clear(); - IMGUI_API void ClearFreeMemory(); - IMGUI_API void PrimReserve(int idx_count, int vtx_count); - IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles) - IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col); - IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col); - inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col){ _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; } - inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; } - inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } - IMGUI_API void UpdateClipRect(); - IMGUI_API void UpdateTextureID(); + IMGUI_API void Clear(); + IMGUI_API void ClearFreeMemory(); + IMGUI_API void PrimReserve(int idx_count, int vtx_count); + IMGUI_API void PrimRect(const ImVec2 &a, const ImVec2 &b, ImU32 col); // Axis aligned rectangle (composed of two triangles) + IMGUI_API void PrimRectUV(const ImVec2 &a, const ImVec2 &b, const ImVec2 &uv_a, const ImVec2 &uv_b, ImU32 col); + IMGUI_API void PrimQuadUV(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, const ImVec2 &uv_a, + const ImVec2 &uv_b, const ImVec2 &uv_c, const ImVec2 &uv_d, ImU32 col); + inline void PrimWriteVtx(const ImVec2 &pos, const ImVec2 &uv, ImU32 col) + { + _VtxWritePtr->pos = pos; + _VtxWritePtr->uv = uv; + _VtxWritePtr->col = col; + _VtxWritePtr++; + _VtxCurrentIdx++; + } + inline void PrimWriteIdx(ImDrawIdx idx) + { + *_IdxWritePtr = idx; + _IdxWritePtr++; + } + inline void PrimVtx(const ImVec2 &pos, const ImVec2 &uv, ImU32 col) + { + PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); + PrimWriteVtx(pos, uv, col); + } + IMGUI_API void UpdateClipRect(); + IMGUI_API void UpdateTextureID(); }; // All draw data to render an ImGui frame struct ImDrawData { - bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. - ImDrawList** CmdLists; - int CmdListsCount; - int TotalVtxCount; // For convenience, sum of all cmd_lists vtx_buffer.Size - int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size + bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. + ImDrawList **CmdLists; + int CmdListsCount; + int TotalVtxCount; // For convenience, sum of all cmd_lists vtx_buffer.Size + int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size // Functions - ImDrawData() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; } - IMGUI_API void DeIndexAllBuffers(); // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! - IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. + ImDrawData() + { + Valid = false; + CmdLists = NULL; + CmdListsCount = TotalVtxCount = TotalIdxCount = 0; + } + IMGUI_API void DeIndexAllBuffers(); // For backward compatibility: convert all buffers from indexed to de-indexed, in case you + // cannot render indexed. Note: this is slow and most likely a waste of resources. Always + // prefer indexed rendering! + IMGUI_API void ScaleClipRects(const ImVec2 &sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final + // output buffer is at a different scale than ImGui expects, or if there is a + // difference between your window resolution and framebuffer resolution. }; struct ImFontConfig { - void* FontData; // // TTF data - int FontDataSize; // // TTF data size - bool FontDataOwnedByAtlas; // true // TTF data ownership taken by the container ImFontAtlas (will delete memory itself). Set to true - int FontNo; // 0 // Index of font within TTF file - float SizePixels; // // Size in pixels for rasterizer - int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. - bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. - ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs - const ImWchar* GlyphRanges; // // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. - bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). - bool MergeGlyphCenterV; // false // When merging (multiple ImFontInput for one ImFont), vertically center new glyphs instead of aligning their baseline + void *FontData; // // TTF data + int FontDataSize; // // TTF data size + bool FontDataOwnedByAtlas; // true // TTF data ownership taken by the container ImFontAtlas (will delete memory itself). + // Set to true + int FontNo; // 0 // Index of font within TTF file + float SizePixels; // // Size in pixels for rasterizer + int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel + // positions on the Y axis. + bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font + // with the default font. If enabled, you can set OversampleH/V to 1. + ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs + const ImWchar + *GlyphRanges; // // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, + // zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. + bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII + // font + icons + Japanese glyphs). + bool MergeGlyphCenterV; // false // When merging (multiple ImFontInput for one ImFont), vertically center new glyphs + // instead of aligning their baseline // [Internal] - char Name[32]; // Name (strictly for debugging) - ImFont* DstFont; + char Name[32]; // Name (strictly for debugging) + ImFont *DstFont; IMGUI_API ImFontConfig(); }; @@ -1287,57 +1942,78 @@ struct ImFontConfig // 1. (Optional) Call AddFont*** functions. If you don't call any, the default font will be loaded for you. // 2. Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. // 3. Upload the pixels data into a texture within your graphics system. -// 4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during rendering to identify the texture. +// 4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during +// rendering to identify the texture. // 5. Call ClearTexData() to free textures memory on the heap. -// NB: If you use a 'glyph_ranges' array you need to make sure that your array persist up until the ImFont is cleared. We only copy the pointer, not the data. +// NB: If you use a 'glyph_ranges' array you need to make sure that your array persist up until the ImFont is cleared. We only +// copy the pointer, not the data. struct ImFontAtlas { IMGUI_API ImFontAtlas(); IMGUI_API ~ImFontAtlas(); - IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg); - IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); - IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() - IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_ttf_data' still owned by caller. Compress with binary_to_compressed_c.cpp - IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_ttf_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 paramaeter - IMGUI_API void ClearTexData(); // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics memory. - IMGUI_API void ClearInputData(); // Clear the input TTF data (inc sizes, glyph ranges) - IMGUI_API void ClearFonts(); // Clear the ImGui-side font data (glyphs storage, UV coordinates) - IMGUI_API void Clear(); // Clear all + IMGUI_API ImFont *AddFont(const ImFontConfig *font_cfg); + IMGUI_API ImFont *AddFontDefault(const ImFontConfig *font_cfg = NULL); + IMGUI_API ImFont *AddFontFromFileTTF(const char *filename, float size_pixels, const ImFontConfig *font_cfg = NULL, + const ImWchar *glyph_ranges = NULL); + IMGUI_API ImFont *AddFontFromMemoryTTF( + void *ttf_data, int ttf_size, float size_pixels, const ImFontConfig *font_cfg = NULL, + const ImWchar *glyph_ranges = NULL); // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() + IMGUI_API ImFont *AddFontFromMemoryCompressedTTF( + const void *compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig *font_cfg = NULL, + const ImWchar *glyph_ranges = + NULL); // 'compressed_ttf_data' still owned by caller. Compress with binary_to_compressed_c.cpp + IMGUI_API ImFont *AddFontFromMemoryCompressedBase85TTF( + const char *compressed_ttf_data_base85, float size_pixels, const ImFontConfig *font_cfg = NULL, + const ImWchar *glyph_ranges = NULL); // 'compressed_ttf_data_base85' still owned by caller. Compress with + // binary_to_compressed_c.cpp with -base85 paramaeter + IMGUI_API void ClearTexData(); // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics + // memory. + IMGUI_API void ClearInputData(); // Clear the input TTF data (inc sizes, glyph ranges) + IMGUI_API void ClearFonts(); // Clear the ImGui-side font data (glyphs storage, UV coordinates) + IMGUI_API void Clear(); // Clear all // Retrieve texture data // User is in charge of copying the pixels into graphics memory, then call SetTextureUserID() - // After loading the texture into your graphic system, store your texture handle in 'TexID' (ignore if you aren't using multiple fonts nor images) - // RGBA32 format is provided for convenience and high compatibility, but note that all RGB pixels are white, so 75% of the memory is wasted. - // Pitch = Width * BytesPerPixels - IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel - IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel - void SetTexID(void* id) { TexID = id; } + // After loading the texture into your graphic system, store your texture handle in 'TexID' (ignore if you aren't using + // multiple fonts nor images) RGBA32 format is provided for convenience and high compatibility, but note that all RGB pixels + // are white, so 75% of the memory is wasted. Pitch = Width * BytesPerPixels + IMGUI_API void GetTexDataAsAlpha8(unsigned char **out_pixels, int *out_width, int *out_height, + int *out_bytes_per_pixel = NULL); // 1 byte per-pixel + IMGUI_API void GetTexDataAsRGBA32(unsigned char **out_pixels, int *out_width, int *out_height, + int *out_bytes_per_pixel = NULL); // 4 bytes-per-pixel + void SetTexID(void *id) + { + TexID = id; + } // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) // NB: Make sure that your string are UTF-8 and NOT in your local code page. See FAQ for details. - IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin - IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters - IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs - IMGUI_API const ImWchar* GetGlyphRangesChinese(); // Japanese + full set of about 21000 CJK Unified Ideographs - IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters - IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters + IMGUI_API const ImWchar *GetGlyphRangesDefault(); // Basic Latin, Extended Latin + IMGUI_API const ImWchar *GetGlyphRangesKorean(); // Default + Korean characters + IMGUI_API const ImWchar *GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs + IMGUI_API const ImWchar *GetGlyphRangesChinese(); // Japanese + full set of about 21000 CJK Unified Ideographs + IMGUI_API const ImWchar *GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters + IMGUI_API const ImWchar *GetGlyphRangesThai(); // Default + Thai characters // Members // (Access texture data via GetTexData*() calls which will setup a default font for you.) - void* TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It ia passed back to you during rendering. - unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight - unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 - int TexWidth; // Texture width calculated during Build(). - int TexHeight; // Texture height calculated during Build(). - int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. - ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel - ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. + void *TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It ia passed back to + // you during rendering. + unsigned char *TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight + unsigned int + *TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 + int TexWidth; // Texture width calculated during Build(). + int TexHeight; // Texture height calculated during Build(). + int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your + // graphics API have texture size restrictions you may want to increase texture width to decrease height. + ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel + ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling + // ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. // Private - ImVector ConfigData; // Internal data - IMGUI_API bool Build(); // Build pixels data. This is automatically for you by the GetTexData*** functions. - IMGUI_API void RenderCustomTexData(int pass, void* rects); + ImVector ConfigData; // Internal data + IMGUI_API bool Build(); // Build pixels data. This is automatically for you by the GetTexData*** functions. + IMGUI_API void RenderCustomTexData(int pass, void *rects); }; // Font runtime data and rendering @@ -1346,57 +2022,72 @@ struct ImFont { struct Glyph { - ImWchar Codepoint; - float XAdvance; - float X0, Y0, X1, Y1; - float U0, V0, U1, V1; // Texture coordinates + ImWchar Codepoint; + float XAdvance; + float X0, Y0, X1, Y1; + float U0, V0, U1, V1; // Texture coordinates }; // Members: Hot ~62/78 bytes - float FontSize; // // Height of characters, set during loading (don't change after loading) - float Scale; // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale() - ImVec2 DisplayOffset; // = (0.f,1.f) // Offset font rendering by xx pixels - ImVector Glyphs; // // All glyphs. - ImVector IndexXAdvance; // // Sparse. Glyphs->XAdvance in a directly indexable way (more cache-friendly, for CalcTextSize functions which are often bottleneck in large UI). - ImVector IndexLookup; // // Sparse. Index glyphs by Unicode code-point. - const Glyph* FallbackGlyph; // == FindGlyph(FontFallbackChar) - float FallbackXAdvance; // == FallbackGlyph->XAdvance - ImWchar FallbackChar; // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() + float FontSize; // // Height of characters, set during loading (don't change after loading) + float Scale; // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with + // SetFontScale() + ImVec2 DisplayOffset; // = (0.f,1.f) // Offset font rendering by xx pixels + ImVector Glyphs; // // All glyphs. + ImVector IndexXAdvance; // // Sparse. Glyphs->XAdvance in a directly indexable way (more cache-friendly, + // for CalcTextSize functions which are often bottleneck in large UI). + ImVector IndexLookup; // // Sparse. Index glyphs by Unicode code-point. + const Glyph * FallbackGlyph; // == FindGlyph(FontFallbackChar) + float FallbackXAdvance; // == FallbackGlyph->XAdvance + ImWchar FallbackChar; // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() // Members: Cold ~18/26 bytes - short ConfigDataCount; // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. - ImFontConfig* ConfigData; // // Pointer within ContainerAtlas->ConfigData - ImFontAtlas* ContainerAtlas; // // What we has been loaded into - float Ascent, Descent; // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] - int MetricsTotalSurface;// // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + short ConfigDataCount; // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging + // multiple font sources into one ImFont. + ImFontConfig *ConfigData; // // Pointer within ContainerAtlas->ConfigData + ImFontAtlas * ContainerAtlas; // // What we has been loaded into + float Ascent, Descent; // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + int MetricsTotalSurface; // // Total surface in pixels to get an idea of the font rasterization/texture cost (not + // exact, we approximate the cost of padding between glyphs) // Methods IMGUI_API ImFont(); IMGUI_API ~ImFont(); - IMGUI_API void Clear(); - IMGUI_API void BuildLookupTable(); - IMGUI_API const Glyph* FindGlyph(ImWchar c) const; - IMGUI_API void SetFallbackChar(ImWchar c); - float GetCharAdvance(ImWchar c) const { return ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] : FallbackXAdvance; } - bool IsLoaded() const { return ContainerAtlas != NULL; } + IMGUI_API void Clear(); + IMGUI_API void BuildLookupTable(); + IMGUI_API const Glyph *FindGlyph(ImWchar c) const; + IMGUI_API void SetFallbackChar(ImWchar c); + float GetCharAdvance(ImWchar c) const + { + return ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] : FallbackXAdvance; + } + bool IsLoaded() const + { + return ContainerAtlas != NULL; + } // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. - IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 - IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; - IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const; - IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const; + IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char *text_begin, + const char *text_end = NULL, const char **remaining = NULL) const; // utf8 + IMGUI_API const char *CalcWordWrapPositionA(float scale, const char *text, const char *text_end, float wrap_width) const; + IMGUI_API void RenderChar(ImDrawList *draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const; + IMGUI_API void RenderText(ImDrawList *draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4 &clip_rect, + const char *text_begin, const char *text_end, float wrap_width = 0.0f, + bool cpu_fine_clip = false) const; // Private - IMGUI_API void GrowIndex(int new_size); - IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. + IMGUI_API void GrowIndex(int new_size); + IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, + bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. + // Currently needs to be called AFTER fonts have been built. }; #if defined(__clang__) -#pragma clang diagnostic pop + #pragma clang diagnostic pop #endif // Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) #ifdef IMGUI_INCLUDE_IMGUI_USER_H -#include "imgui_user.h" + #include "imgui_user.h" #endif diff --git a/source/main/gui/imgui/imgui_demo.cpp b/source/main/gui/imgui/imgui_demo.cpp index b503146c17..5cd88aeadf 100644 --- a/source/main/gui/imgui/imgui_demo.cpp +++ b/source/main/gui/imgui/imgui_demo.cpp @@ -5,55 +5,66 @@ // Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to. // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow(). // During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui. -// Removing this file from your project is hindering your access to documentation, likely leading you to poorer usage of the library. +// Removing this file from your project is hindering your access to documentation, likely leading you to poorer usage of the +// library. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS #endif #include "imgui.h" -#include // toupper, isprint -#include // sqrtf, powf, cosf, sinf, floorf, ceilf -#include // vsnprintf, sscanf, printf -#include // NULL, malloc, free, qsort, atoi + +#include // toupper, isprint +#include // sqrtf, powf, cosf, sinf, floorf, ceilf +#include // vsnprintf, sscanf, printf +#include // NULL, malloc, free, qsort, atoi #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t + #include // intptr_t #else -#include // intptr_t + #include // intptr_t #endif #ifdef _MSC_VER -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf + #pragma warning( \ + disable : 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen + #define snprintf _snprintf #endif #ifdef __clang__ -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code) -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' -#pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal -#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // -#endif + #pragma clang diagnostic ignored \ + "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. + #pragma clang diagnostic ignored \ + "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo + // code (so user can copy & paste the code) + #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' + #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal + #pragma clang diagnostic ignored \ + "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order + // is undefined. if MemFree() leads to users code that has been disabled before exit it might + // cause problems. ImGui coding style welcomes static/globals. + #if __has_warning("-Wreserved-id-macro") + #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // + #endif #elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size -#pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#if (__GNUC__ >= 6) -#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on github. -#endif + #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size + #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) + #pragma GCC diagnostic ignored \ + "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function + #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value + #if (__GNUC__ >= 6) + #pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // + // GCC 6.0+ only. See #883 on github. + #endif #endif // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. #ifdef _WIN32 -#define IM_NEWLINE "\r\n" + #define IM_NEWLINE "\r\n" #else -#define IM_NEWLINE "\n" + #define IM_NEWLINE "\n" #endif -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*_ARR))) +#define IM_MAX(_A, _B) (((_A) >= (_B)) ? (_A) : (_B)) //----------------------------------------------------------------------------- // DEMO CODE @@ -61,20 +72,20 @@ #ifndef IMGUI_DISABLE_TEST_WINDOWS -static void ShowExampleAppConsole(bool* p_open); -static void ShowExampleAppLog(bool* p_open); -static void ShowExampleAppLayout(bool* p_open); -static void ShowExampleAppPropertyEditor(bool* p_open); -static void ShowExampleAppLongText(bool* p_open); -static void ShowExampleAppAutoResize(bool* p_open); -static void ShowExampleAppConstrainedResize(bool* p_open); -static void ShowExampleAppFixedOverlay(bool* p_open); -static void ShowExampleAppManipulatingWindowTitle(bool* p_open); -static void ShowExampleAppCustomRendering(bool* p_open); +static void ShowExampleAppConsole(bool *p_open); +static void ShowExampleAppLog(bool *p_open); +static void ShowExampleAppLayout(bool *p_open); +static void ShowExampleAppPropertyEditor(bool *p_open); +static void ShowExampleAppLongText(bool *p_open); +static void ShowExampleAppAutoResize(bool *p_open); +static void ShowExampleAppConstrainedResize(bool *p_open); +static void ShowExampleAppFixedOverlay(bool *p_open); +static void ShowExampleAppManipulatingWindowTitle(bool *p_open); +static void ShowExampleAppCustomRendering(bool *p_open); static void ShowExampleAppMainMenuBar(); static void ShowExampleMenuFile(); -static void ShowHelpMarker(const char* desc) +static void ShowHelpMarker(const char *desc) { ImGui::TextDisabled("(?)"); if (ImGui::IsItemHovered()) @@ -93,41 +104,39 @@ void ImGui::ShowUserGuide() ImGui::BulletText("Click and drag on lower right corner to resize window."); ImGui::BulletText("Click and drag on any empty space to move window."); ImGui::BulletText("Mouse Wheel to scroll."); - if (ImGui::GetIO().FontAllowUserScaling) - ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); + if (ImGui::GetIO().FontAllowUserScaling) ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); ImGui::BulletText("CTRL+Click on a slider or drag box to input text."); - ImGui::BulletText( - "While editing text:\n" - "- Hold SHIFT or use mouse to select text\n" - "- CTRL+Left/Right to word jump\n" - "- CTRL+A or double-click to select all\n" - "- CTRL+X,CTRL+C,CTRL+V clipboard\n" - "- CTRL+Z,CTRL+Y undo/redo\n" - "- ESCAPE to revert\n" - "- You can apply arithmetic operators +,*,/ on numerical values.\n" - " Use +- to subtract.\n"); + ImGui::BulletText("While editing text:\n" + "- Hold SHIFT or use mouse to select text\n" + "- CTRL+Left/Right to word jump\n" + "- CTRL+A or double-click to select all\n" + "- CTRL+X,CTRL+C,CTRL+V clipboard\n" + "- CTRL+Z,CTRL+Y undo/redo\n" + "- ESCAPE to revert\n" + "- You can apply arithmetic operators +,*,/ on numerical values.\n" + " Use +- to subtract.\n"); } // Demonstrate most ImGui features (big function!) -void ImGui::ShowTestWindow(bool* p_open) +void ImGui::ShowTestWindow(bool *p_open) { // Examples apps - static bool show_app_main_menu_bar = false; - static bool show_app_console = false; - static bool show_app_log = false; - static bool show_app_layout = false; - static bool show_app_property_editor = false; - static bool show_app_long_text = false; - static bool show_app_auto_resize = false; - static bool show_app_constrained_resize = false; - static bool show_app_fixed_overlay = false; + static bool show_app_main_menu_bar = false; + static bool show_app_console = false; + static bool show_app_log = false; + static bool show_app_layout = false; + static bool show_app_property_editor = false; + static bool show_app_long_text = false; + static bool show_app_auto_resize = false; + static bool show_app_constrained_resize = false; + static bool show_app_fixed_overlay = false; static bool show_app_manipulating_window_title = false; - static bool show_app_custom_rendering = false; - static bool show_app_style_editor = false; + static bool show_app_custom_rendering = false; + static bool show_app_style_editor = false; static bool show_app_metrics = false; - static bool show_app_about = false; + static bool show_app_about = false; if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); if (show_app_console) ShowExampleAppConsole(&show_app_console); @@ -142,7 +151,12 @@ void ImGui::ShowTestWindow(bool* p_open) if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics); - if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } + if (show_app_style_editor) + { + ImGui::Begin("Style Editor", &show_app_style_editor); + ImGui::ShowStyleEditor(); + ImGui::End(); + } if (show_app_about) { ImGui::Begin("About ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); @@ -153,24 +167,24 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::End(); } - static bool no_titlebar = false; - static bool no_border = true; - static bool no_resize = false; - static bool no_move = false; + static bool no_titlebar = false; + static bool no_border = true; + static bool no_resize = false; + static bool no_move = false; static bool no_scrollbar = false; - static bool no_collapse = false; - static bool no_menu = false; + static bool no_collapse = false; + static bool no_menu = false; // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; - if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; - if (!no_border) window_flags |= ImGuiWindowFlags_ShowBorders; - if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; - if (no_move) window_flags |= ImGuiWindowFlags_NoMove; + if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; + if (!no_border) window_flags |= ImGuiWindowFlags_ShowBorders; + if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; + if (no_move) window_flags |= ImGuiWindowFlags_NoMove; if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; - if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; - if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); + if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; + if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; + ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) { // Early out if the window is collapsed, as an optimization. @@ -178,8 +192,8 @@ void ImGui::ShowTestWindow(bool* p_open) return; } - //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels - ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels + // ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels + ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels ImGui::Text("Dear ImGui says hello."); @@ -219,17 +233,22 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Spacing(); if (ImGui::CollapsingHeader("Help")) { - ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code for programming reference.\n\nUser Guide:"); + ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code for " + "programming reference.\n\nUser Guide:"); ImGui::ShowUserGuide(); } if (ImGui::CollapsingHeader("Window options")) { - ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150); - ImGui::Checkbox("No border", &no_border); ImGui::SameLine(300); + ImGui::Checkbox("No titlebar", &no_titlebar); + ImGui::SameLine(150); + ImGui::Checkbox("No border", &no_border); + ImGui::SameLine(300); ImGui::Checkbox("No resize", &no_resize); - ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150); - ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300); + ImGui::Checkbox("No move", &no_move); + ImGui::SameLine(150); + ImGui::Checkbox("No scrollbar", &no_scrollbar); + ImGui::SameLine(300); ImGui::Checkbox("No collapse", &no_collapse); ImGui::Checkbox("No menu", &no_menu); @@ -241,7 +260,9 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Logging")) { - ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output."); + ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a " + "block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output " + "directly to the log without a visual output."); ImGui::LogButtons(); ImGui::TreePop(); } @@ -254,10 +275,10 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Basic trees")) { for (int i = 0; i < 5; i++) - if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) + if (ImGui::TreeNode((void *)(intptr_t)i, "Child %d", i)) { ImGui::Text("blah blah"); - ImGui::SameLine(); + ImGui::SameLine(); if (ImGui::SmallButton("print")) printf("Child %d pressed", i); ImGui::TreePop(); } @@ -266,26 +287,31 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Advanced, with Selectable nodes")) { - ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); + ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to " + "toggle, click on arrows or double-click to open."); static bool align_label_with_current_x_position = false; ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position); ImGui::Text("Hello!"); - if (align_label_with_current_x_position) - ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); - - static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. - int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. - ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. + if (align_label_with_current_x_position) ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); + + static int selection_mask = + (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state + // inside or outside your objects in whatever format you see fit. + int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the + // loop. May be a pointer to your own node type, etc. + ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, + ImGui::GetFontSize() * 3); // Increase spacing to differentiate leaves from expanded contents. for (int i = 0; i < 6; i++) { - // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. - ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0); + // Disable the default open on single-click behavior and pass in Selected flag according to our selection + // state. + ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | + ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0); if (i < 3) { // Node - bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); - if (ImGui::IsItemClicked()) - node_clicked = i; + bool node_open = ImGui::TreeNodeEx((void *)(intptr_t)i, node_flags, "Selectable Node %d", i); + if (ImGui::IsItemClicked()) node_clicked = i; if (node_open) { ImGui::Text("Blah blah\nBlah Blah"); @@ -294,23 +320,26 @@ void ImGui::ShowTestWindow(bool* p_open) } else { - // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Selectable Leaf %d", i); - if (ImGui::IsItemClicked()) - node_clicked = i; + // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use + // BulletText() or TreeAdvanceToLabelPos()+Text(). + ImGui::TreeNodeEx((void *)(intptr_t)i, + node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, + "Selectable Leaf %d", i); + if (ImGui::IsItemClicked()) node_clicked = i; } } if (node_clicked != -1) { - // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. + // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the + // clicking-frame. if (ImGui::GetIO().KeyCtrl) - selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection - selection_mask = (1 << node_clicked); // Click to single-select + selection_mask ^= (1 << node_clicked); // CTRL+click to toggle + else // if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this + // commented bit preserve selection when clicking on item that is part of the selection + selection_mask = (1 << node_clicked); // Click to single-select } ImGui::PopStyleVar(); - if (align_label_with_current_x_position) - ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); + if (align_label_with_current_x_position) ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); ImGui::TreePop(); } ImGui::TreePop(); @@ -337,16 +366,18 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::BulletText("Bullet point 1"); ImGui::BulletText("Bullet point 2\nOn multiple lines"); - ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); - ImGui::Bullet(); ImGui::SmallButton("Button"); + ImGui::Bullet(); + ImGui::Text("Bullet point 3 (two calls)"); + ImGui::Bullet(); + ImGui::SmallButton("Button"); ImGui::TreePop(); } if (ImGui::TreeNode("Colored Text")) { // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. - ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink"); - ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow"); + ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink"); + ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow"); ImGui::TextDisabled("Disabled"); ImGui::TreePop(); } @@ -354,7 +385,8 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Word Wrapping")) { // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility. - ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages."); + ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for " + "text wrapping follows simple rules suitable for English and possibly other languages."); ImGui::Spacing(); static float wrap_width = 200.0f; @@ -362,18 +394,24 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("Test paragraph 1:"); ImVec2 pos = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255)); + ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), + ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), + IM_COL32(255, 0, 255, 255)); ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); - ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width); - ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255)); + ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character " + "word. The quick brown fox jumps over the lazy dog.", + wrap_width); + ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255)); ImGui::PopTextWrapPos(); ImGui::Text("Test paragraph 2:"); pos = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255)); + ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), + ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), + IM_COL32(255, 0, 255, 255)); ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh"); - ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255)); + ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255)); ImGui::PopTextWrapPos(); ImGui::TreePop(); @@ -382,12 +420,15 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("UTF-8 Text")) { // UTF-8 test with Japanese characters - // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html) - // Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature') - // However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with hexadecimal constants. - // In your own application be reasonable and use UTF-8 in source or retrieve the data from file system! - // Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application. - ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges."); + // (needs a suitable font, try Arial Unicode or M+ fonts + // http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html) Most compiler appears to support UTF-8 in + // source code (with Visual Studio you need to save your file as 'UTF-8 without signature') However for the sake for + // maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the + // string with hexadecimal constants. In your own application be reasonable and use UTF-8 in source or retrieve the + // data from file system! Note that characters values are preserved even if the font cannot be displayed, so you can + // safely copy & paste garbled characters into another application. + ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. " + "Call io.Font->LoadFromFileTTF() manually to load extra character ranges."); ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; @@ -397,24 +438,35 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Images")) { - ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!"); - ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos(); - float tex_w = (float)ImGui::GetIO().Fonts->TexWidth; - float tex_h = (float)ImGui::GetIO().Fonts->TexHeight; - ImTextureID tex_id = ImGui::GetIO().Fonts->TexID; + ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this " + "demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture " + "data. Hover the texture for a zoomed view!"); + ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos(); + float tex_w = (float)ImGui::GetIO().Fonts->TexWidth; + float tex_h = (float)ImGui::GetIO().Fonts->TexHeight; + ImTextureID tex_id = ImGui::GetIO().Fonts->TexID; ImGui::Text("%.0fx%.0f", tex_w, tex_h); - ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); + ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), + ImColor(255, 255, 255, 128)); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); float focus_sz = 32.0f; - float focus_x = ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > tex_w - focus_sz) focus_x = tex_w - focus_sz; - float focus_y = ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > tex_h - focus_sz) focus_y = tex_h - focus_sz; + float focus_x = ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f; + if (focus_x < 0.0f) + focus_x = 0.0f; + else if (focus_x > tex_w - focus_sz) + focus_x = tex_w - focus_sz; + float focus_y = ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f; + if (focus_y < 0.0f) + focus_y = 0.0f; + else if (focus_y > tex_h - focus_sz) + focus_y = tex_h - focus_sz; ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y); ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz); ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h); ImVec2 uv1 = ImVec2((focus_x + focus_sz) / tex_w, (focus_y + focus_sz) / tex_h); - ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128)); + ImGui::Image(tex_id, ImVec2(128, 128), uv0, uv1, ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128)); ImGui::EndTooltip(); } ImGui::TextWrapped("And now some textured buttons.."); @@ -422,8 +474,9 @@ void ImGui::ShowTestWindow(bool* p_open) for (int i = 0; i < 8; i++) { ImGui::PushID(i); - int frame_padding = -1 + i; // -1 = uses default padding - if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding, ImColor(0,0,0,255))) + int frame_padding = -1 + i; // -1 = uses default padding + if (ImGui::ImageButton(tex_id, ImVec2(32, 32), ImVec2(0, 0), ImVec2(32.0f / tex_w, 32 / tex_h), frame_padding, + ImColor(0, 0, 0, 255))) pressed_count += 1; ImGui::PopID(); ImGui::SameLine(); @@ -437,31 +490,37 @@ void ImGui::ShowTestWindow(bool* p_open) { if (ImGui::TreeNode("Basic")) { - static bool selected[4] = { false, true, false, false }; + static bool selected[4] = {false, true, false, false}; ImGui::Selectable("1. I am selectable", &selected[0]); ImGui::Selectable("2. I am selectable", &selected[1]); ImGui::Text("3. I am not selectable"); ImGui::Selectable("4. I am selectable", &selected[2]); if (ImGui::Selectable("5. I am double clickable", selected[3], ImGuiSelectableFlags_AllowDoubleClick)) - if (ImGui::IsMouseDoubleClicked(0)) - selected[3] = !selected[3]; + if (ImGui::IsMouseDoubleClicked(0)) selected[3] = !selected[3]; ImGui::TreePop(); } if (ImGui::TreeNode("Rendering more text into the same block")) { - static bool selected[3] = { false, false, false }; - ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); - ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes"); - ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); + static bool selected[3] = {false, false, false}; + ImGui::Selectable("main.c", &selected[0]); + ImGui::SameLine(300); + ImGui::Text(" 2,345 bytes"); + ImGui::Selectable("Hello.cpp", &selected[1]); + ImGui::SameLine(300); + ImGui::Text("12,345 bytes"); + ImGui::Selectable("Hello.h", &selected[2]); + ImGui::SameLine(300); + ImGui::Text(" 2,345 bytes"); ImGui::TreePop(); } if (ImGui::TreeNode("In columns")) { ImGui::Columns(3, NULL, false); - static bool selected[16] = { 0 }; + static bool selected[16] = {0}; for (int i = 0; i < 16; i++) { - char label[32]; sprintf(label, "Item %d", i); + char label[32]; + sprintf(label, "Item %d", i); if (ImGui::Selectable(label, &selected[i])) {} ImGui::NextColumn(); } @@ -470,11 +529,12 @@ void ImGui::ShowTestWindow(bool* p_open) } if (ImGui::TreeNode("Grid")) { - static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true }; + static bool selected[16] = {true, false, false, false, false, true, false, false, + false, false, true, false, false, false, false, true}; for (int i = 0; i < 16; i++) { ImGui::PushID(i); - if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50))) + if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50, 50))) { int x = i % 4, y = i / 4; if (x > 0) selected[i - 1] ^= 1; @@ -492,18 +552,33 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Filtered Text Input")) { - static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); - static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); - static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); - static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); - static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); - struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } }; - static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); + static char buf1[64] = ""; + ImGui::InputText("default", buf1, 64); + static char buf2[64] = ""; + ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); + static char buf3[64] = ""; + ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); + static char buf4[64] = ""; + ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); + static char buf5[64] = ""; + ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); + struct TextFilters + { + static int FilterImGuiLetters(ImGuiTextEditCallbackData *data) + { + if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; + return 1; + } + }; + static char buf6[64] = ""; + ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, + TextFilters::FilterImGuiLetters); ImGui::Text("Password input"); static char bufpass[64] = "password123"; ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank); - ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); + ImGui::SameLine(); + ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank); ImGui::TreePop(); @@ -511,28 +586,32 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Multi-line Text Input")) { - static bool read_only = false; - static char text[1024*16] = - "/*\n" - " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" - " the hexadecimal encoding of one offending instruction,\n" - " more formally, the invalid operand with locked CMPXCHG8B\n" - " instruction bug, is a design flaw in the majority of\n" - " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" - " processors (all in the P5 microarchitecture).\n" - "*/\n\n" - "label:\n" - "\tlock cmpxchg8b eax\n"; - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + static bool read_only = false; + static char text[1024 * 16] = "/*\n" + " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" + " the hexadecimal encoding of one offending instruction,\n" + " more formally, the invalid operand with locked CMPXCHG8B\n" + " instruction bug, is a design flaw in the majority of\n" + " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" + " processors (all in the P5 microarchitecture).\n" + "*/\n\n" + "label:\n" + "\tlock cmpxchg8b eax\n"; + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::Checkbox("Read-only", &read_only); ImGui::PopStyleVar(); - ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0)); + ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), + ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0)); ImGui::TreePop(); } - static bool a=false; - if (ImGui::Button("Button")) { printf("Clicked\n"); a ^= 1; } + static bool a = false; + if (ImGui::Button("Button")) + { + printf("Clicked\n"); + a ^= 1; + } if (a) { ImGui::SameLine(); @@ -543,8 +622,10 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Checkbox("checkbox", &check); static int e = 0; - ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine(); - ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine(); + ImGui::RadioButton("radio a", &e, 0); + ImGui::SameLine(); + ImGui::RadioButton("radio b", &e, 1); + ImGui::SameLine(); ImGui::RadioButton("radio c", &e, 2); // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. @@ -552,17 +633,16 @@ void ImGui::ShowTestWindow(bool* p_open) { if (i > 0) ImGui::SameLine(); ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i/7.0f, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(i/7.0f, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(i/7.0f, 0.8f, 0.8f)); + ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i / 7.0f, 0.6f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(i / 7.0f, 0.7f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(i / 7.0f, 0.8f, 0.8f)); ImGui::Button("Click"); ImGui::PopStyleColor(3); ImGui::PopID(); } ImGui::Text("Hover over me"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip"); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("I am a tooltip"); ImGui::SameLine(); ImGui::Text("- or me"); @@ -570,13 +650,13 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::BeginTooltip(); ImGui::Text("I am a fancy tooltip"); - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; + static float arr[] = {0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f}; ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr)); ImGui::EndTooltip(); } // Testing IMGUI_ONCE_UPON_A_FRAME macro - //for (int i = 0; i < 5; i++) + // for (int i = 0; i < 5; i++) //{ // IMGUI_ONCE_UPON_A_FRAME // { @@ -589,74 +669,91 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::LabelText("label", "Value"); static int item = 1; - ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo) + ImGui::Combo( + "combo", &item, + "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo) - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" }; - static int item2 = -1; - ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that. + const char *items[] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK"}; + static int item2 = -1; + ImGui::Combo("combo scroll", &item2, items, + IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no + // need to create/copy an array just for that. { - static char str0[128] = "Hello, world!"; - static int i0=123; - static float f0=0.001f; + static char str0[128] = "Hello, world!"; + static int i0 = 123; + static float f0 = 0.001f; ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); - ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n"); + ImGui::SameLine(); + ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" + "CTRL+Left/Right to word jump.\n" + "CTRL+A or double-click to select all.\n" + "CTRL+X,CTRL+C,CTRL+V clipboard.\n" + "CTRL+Z,CTRL+Y undo/redo.\n" + "ESCAPE to revert.\n"); ImGui::InputInt("input int", &i0); - ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n"); + ImGui::SameLine(); + ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result " + "becomes [ 200 ]\nUse +- to subtract.\n"); ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); - static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; + static float vec4a[4] = {0.10f, 0.20f, 0.30f, 0.44f}; ImGui::InputFloat3("input float3", vec4a); } { - static int i1=50, i2=42; + static int i1 = 50, i2 = 42; ImGui::DragInt("drag int", &i1, 1); - ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value."); + ImGui::SameLine(); + ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to " + "input value."); ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%"); - static float f1=1.00f, f2=0.0067f; + static float f1 = 1.00f, f2 = 0.0067f; ImGui::DragFloat("drag float", &f1, 0.005f); ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns"); } { - static int i1=0; + static int i1 = 0; ImGui::SliderInt("slider int", &i1, -1, 3); - ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value."); + ImGui::SameLine(); + ShowHelpMarker("CTRL+click to input value."); - static float f1=0.123f, f2=0.0f; + static float f1 = 0.123f, f2 = 0.0f; ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f); static float angle = 0.0f; ImGui::SliderAngle("slider angle", &angle); } - static float col1[3] = { 1.0f,0.0f,0.2f }; - static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; + static float col1[3] = {1.0f, 0.0f, 0.2f}; + static float col2[4] = {0.4f, 0.7f, 0.0f, 0.5f}; ImGui::ColorEdit3("color 1", col1); - ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n"); + ImGui::SameLine(); + ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n"); ImGui::ColorEdit4("color 2", col2); - const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; - static int listbox_item_current = 1; + const char *listbox_items[] = {"Apple", "Banana", "Cherry", "Kiwi", "Mango", + "Orange", "Pineapple", "Strawberry", "Watermelon"}; + static int listbox_item_current = 1; ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4); - //static int listbox_item_current2 = 2; - //ImGui::PushItemWidth(-1); - //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); - //ImGui::PopItemWidth(); + // static int listbox_item_current2 = 2; + // ImGui::PushItemWidth(-1); + // ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); + // ImGui::PopItemWidth(); if (ImGui::TreeNode("Range Widgets")) { ImGui::Unindent(); static float begin = 10, end = 90; - static int begin_i = 100, end_i = 1000; + static int begin_i = 100, end_i = 1000; ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%"); ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units"); @@ -668,8 +765,8 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::Unindent(); - static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - static int vec4i[4] = { 1, 5, 100, 255 }; + static float vec4f[4] = {0.10f, 0.20f, 0.30f, 0.44f}; + static int vec4i[4] = {1, 5, 100, 255}; ImGui::InputFloat2("input float2", vec4f); ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f); @@ -705,22 +802,21 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing)); static int int_value = 0; - ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5); + ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5); ImGui::SameLine(); - static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; + static float values[7] = {0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f}; ImGui::PushID("set1"); for (int i = 0; i < 7; i++) { if (i > 0) ImGui::SameLine(); ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(i/7.0f, 0.6f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(i/7.0f, 0.7f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f)); - ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values[i]); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i / 7.0f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(i / 7.0f, 0.6f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(i / 7.0f, 0.7f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i / 7.0f, 0.9f, 0.9f)); + ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, ""); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) ImGui::SetTooltip("%.3f", values[i]); ImGui::PopStyleColor(4); ImGui::PopID(); } @@ -728,19 +824,18 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SameLine(); ImGui::PushID("set2"); - static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; - const int rows = 3; - const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows); + static float values2[4] = {0.20f, 0.80f, 0.40f, 0.25f}; + const int rows = 3; + const ImVec2 small_slider_size(18, (160.0f - (rows - 1) * spacing) / rows); for (int nx = 0; nx < 4; nx++) { if (nx > 0) ImGui::SameLine(); ImGui::BeginGroup(); for (int ny = 0; ny < rows; ny++) { - ImGui::PushID(nx*rows+ny); + ImGui::PushID(nx * rows + ny); ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values2[nx]); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) ImGui::SetTooltip("%.3f", values2[nx]); ImGui::PopID(); } ImGui::EndGroup(); @@ -754,7 +849,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (i > 0) ImGui::SameLine(); ImGui::PushID(i); ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); - ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); + ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); ImGui::PopStyleVar(); ImGui::PopID(); } @@ -771,42 +866,52 @@ void ImGui::ShowTestWindow(bool* p_open) static bool animate = true; ImGui::Checkbox("Animate", &animate); - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; + static float arr[] = {0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f}; ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); // Create a dummy array of contiguous float values to plot - // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter. - static float values[90] = { 0 }; - static int values_offset = 0; + // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the + // sizeof() of your structure in the Stride parameter. + static float values[90] = {0}; + static int values_offset = 0; if (animate) { static float refresh_time = ImGui::GetTime(); // Create dummy data at fixed 60 hz rate for the demo - for (; ImGui::GetTime() > refresh_time + 1.0f/60.0f; refresh_time += 1.0f/60.0f) + for (; ImGui::GetTime() > refresh_time + 1.0f / 60.0f; refresh_time += 1.0f / 60.0f) { - static float phase = 0.0f; + static float phase = 0.0f; values[values_offset] = cosf(phase); - values_offset = (values_offset+1) % IM_ARRAYSIZE(values); - phase += 0.10f*values_offset; + values_offset = (values_offset + 1) % IM_ARRAYSIZE(values); + phase += 0.10f * values_offset; } } - ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); - ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80)); + ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0, 80)); + ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80)); // Use functions to generate output - // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count. + // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and + // user provide sample rate/count. struct Funcs { - static float Sin(void*, int i) { return sinf(i * 0.1f); } - static float Saw(void*, int i) { return (i & 1) ? 1.0f : 0.0f; } + static float Sin(void *, int i) + { + return sinf(i * 0.1f); + } + static float Saw(void *, int i) + { + return (i & 1) ? 1.0f : 0.0f; + } }; static int func_type = 0, display_count = 70; ImGui::Separator(); - ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth(); + ImGui::PushItemWidth(100); + ImGui::Combo("func", &func_type, "Sin\0Saw\0"); + ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::SliderInt("Sample count", &display_count, 1, 400); - float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; - ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80)); - ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80)); + float (*func)(void *, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; + ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); + ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); ImGui::Separator(); // Animate a simple progress bar @@ -814,19 +919,28 @@ void ImGui::ShowTestWindow(bool* p_open) if (animate) { progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; - if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } - if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } + if (progress >= +1.1f) + { + progress = +1.1f; + progress_dir *= -1.0f; + } + if (progress <= -0.1f) + { + progress = -0.1f; + progress_dir *= -1.0f; + } } - // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. - ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); + // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. + // ImVec2(0.0f,0.0f) uses ItemWidth. + ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f)); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::Text("Progress Bar"); float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress; - char buf[32]; - sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753); - ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf); + char buf[32]; + sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753); + ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf); } if (ImGui::CollapsingHeader("Layout")) @@ -834,35 +948,33 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Child regions")) { ImGui::Text("Without border"); - static int line = 50; - bool goto_line = ImGui::Button("Goto"); + static int line = 50; + bool goto_line = ImGui::Button("Goto"); ImGui::SameLine(); ImGui::PushItemWidth(100); goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); ImGui::PopItemWidth(); - ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 300), false, + ImGuiWindowFlags_HorizontalScrollbar); for (int i = 0; i < 100; i++) { ImGui::Text("%04d: scrollable region", i); - if (goto_line && line == i) - ImGui::SetScrollHere(); + if (goto_line && line == i) ImGui::SetScrollHere(); } - if (goto_line && line >= 100) - ImGui::SetScrollHere(); + if (goto_line && line >= 100) ImGui::SetScrollHere(); ImGui::EndChild(); ImGui::SameLine(); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f); - ImGui::BeginChild("Sub2", ImVec2(0,300), true); + ImGui::BeginChild("Sub2", ImVec2(0, 300), true); ImGui::Text("With border"); ImGui::Columns(2); for (int i = 0; i < 100; i++) { - if (i == 50) - ImGui::NextColumn(); + if (i == 50) ImGui::NextColumn(); char buf[32]; - sprintf(buf, "%08x", i*5731); + sprintf(buf, "%08x", i * 5731); ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); } ImGui::EndChild(); @@ -875,31 +987,36 @@ void ImGui::ShowTestWindow(bool* p_open) { static float f = 0.0f; ImGui::Text("PushItemWidth(100)"); - ImGui::SameLine(); ShowHelpMarker("Fixed width."); + ImGui::SameLine(); + ShowHelpMarker("Fixed width."); ImGui::PushItemWidth(100); ImGui::DragFloat("float##1", &f); ImGui::PopItemWidth(); ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)"); - ImGui::SameLine(); ShowHelpMarker("Half of window width."); + ImGui::SameLine(); + ShowHelpMarker("Half of window width."); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f); ImGui::DragFloat("float##2", &f); ImGui::PopItemWidth(); ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)"); - ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); + ImGui::SameLine(); + ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f); ImGui::DragFloat("float##3", &f); ImGui::PopItemWidth(); ImGui::Text("PushItemWidth(-100)"); - ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100"); + ImGui::SameLine(); + ShowHelpMarker("Align to right edge minus 100"); ImGui::PushItemWidth(-100); ImGui::DragFloat("float##4", &f); ImGui::PopItemWidth(); ImGui::Text("PushItemWidth(-1)"); - ImGui::SameLine(); ShowHelpMarker("Align to right edge"); + ImGui::SameLine(); + ShowHelpMarker("Align to right edge"); ImGui::PushItemWidth(-1); ImGui::DragFloat("float##5", &f); ImGui::PopItemWidth(); @@ -912,68 +1029,87 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)"); // Text - ImGui::Text("Two items: Hello"); ImGui::SameLine(); - ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); + ImGui::Text("Two items: Hello"); + ImGui::SameLine(); + ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor"); // Adjust spacing - ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20); - ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); + ImGui::Text("More spacing: Hello"); + ImGui::SameLine(0, 20); + ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor"); // Button ImGui::AlignFirstTextHeightToWidgets(); - ImGui::Text("Normal buttons"); ImGui::SameLine(); - ImGui::Button("Banana"); ImGui::SameLine(); - ImGui::Button("Apple"); ImGui::SameLine(); + ImGui::Text("Normal buttons"); + ImGui::SameLine(); + ImGui::Button("Banana"); + ImGui::SameLine(); + ImGui::Button("Apple"); + ImGui::SameLine(); ImGui::Button("Corniflower"); // Button - ImGui::Text("Small buttons"); ImGui::SameLine(); - ImGui::SmallButton("Like this one"); ImGui::SameLine(); + ImGui::Text("Small buttons"); + ImGui::SameLine(); + ImGui::SmallButton("Like this one"); + ImGui::SameLine(); ImGui::Text("can fit within a text block."); // Aligned to arbitrary position. Easy/cheap column. ImGui::Text("Aligned"); - ImGui::SameLine(150); ImGui::Text("x=150"); - ImGui::SameLine(300); ImGui::Text("x=300"); + ImGui::SameLine(150); + ImGui::Text("x=150"); + ImGui::SameLine(300); + ImGui::Text("x=300"); ImGui::Text("Aligned"); - ImGui::SameLine(150); ImGui::SmallButton("x=150"); - ImGui::SameLine(300); ImGui::SmallButton("x=300"); + ImGui::SameLine(150); + ImGui::SmallButton("x=150"); + ImGui::SameLine(300); + ImGui::SmallButton("x=300"); // Checkbox - static bool c1=false,c2=false,c3=false,c4=false; - ImGui::Checkbox("My", &c1); ImGui::SameLine(); - ImGui::Checkbox("Tailor", &c2); ImGui::SameLine(); - ImGui::Checkbox("Is", &c3); ImGui::SameLine(); + static bool c1 = false, c2 = false, c3 = false, c4 = false; + ImGui::Checkbox("My", &c1); + ImGui::SameLine(); + ImGui::Checkbox("Tailor", &c2); + ImGui::SameLine(); + ImGui::Checkbox("Is", &c3); + ImGui::SameLine(); ImGui::Checkbox("Rich", &c4); // Various - static float f0=1.0f, f1=2.0f, f2=3.0f; + static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f; ImGui::PushItemWidth(80); - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" }; - static int item = -1; - ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine(); - ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Z", &f2, 0.0f,5.0f); + const char *items[] = {"AAAA", "BBBB", "CCCC", "DDDD"}; + static int item = -1; + ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); + ImGui::SameLine(); + ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); + ImGui::SameLine(); + ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); + ImGui::SameLine(); + ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f); ImGui::PopItemWidth(); ImGui::PushItemWidth(80); ImGui::Text("Lists:"); - static int selection[4] = { 0, 1, 2, 3 }; + static int selection[4] = {0, 1, 2, 3}; for (int i = 0; i < 4; i++) { if (i > 0) ImGui::SameLine(); ImGui::PushID(i); ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); ImGui::PopID(); - //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); + // if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); } ImGui::PopItemWidth(); // Dummy - ImVec2 sz(30,30); - ImGui::Button("A", sz); ImGui::SameLine(); - ImGui::Dummy(sz); ImGui::SameLine(); + ImVec2 sz(30, 30); + ImGui::Button("A", sz); + ImGui::SameLine(); + ImGui::Dummy(sz); + ImGui::SameLine(); ImGui::Button("B", sz); ImGui::TreePop(); @@ -981,7 +1117,9 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Groups")) { - ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)"); + ImGui::TextWrapped( + "(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. " + "EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)"); ImGui::BeginGroup(); { ImGui::BeginGroup(); @@ -993,20 +1131,19 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Button("CCC"); ImGui::Button("DDD"); ImGui::EndGroup(); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("Group hovered"); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Group hovered"); ImGui::SameLine(); ImGui::Button("EEE"); ImGui::EndGroup(); } // Capture the group size and create widgets using the same size - ImVec2 size = ImGui::GetItemRectSize(); - const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f }; + ImVec2 size = ImGui::GetItemRectSize(); + const float values[5] = {0.5f, 0.20f, 0.80f, 0.60f, 0.25f}; ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size); - ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y)); + ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y)); ImGui::SameLine(); - ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y)); + ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y)); ImGui::EndGroup(); ImGui::SameLine(); @@ -1023,45 +1160,74 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Text Baseline Alignment")) { - ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)"); + ImGui::TextWrapped( + "(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines " + "only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)"); - ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("One\nTwo\nThree"); + ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); + ImGui::SameLine(); ImGui::Text("Banana"); - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); + ImGui::SameLine(); ImGui::Text("One\nTwo\nThree"); - ImGui::Button("HOP##1"); ImGui::SameLine(); - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Button("HOP##1"); + ImGui::SameLine(); + ImGui::Text("Banana"); + ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); + ImGui::SameLine(); ImGui::Text("Banana"); - ImGui::Button("HOP##2"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Button("HOP##2"); + ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); + ImGui::SameLine(); ImGui::Text("Banana"); - ImGui::Button("TEST##1"); ImGui::SameLine(); - ImGui::Text("TEST"); ImGui::SameLine(); + ImGui::Button("TEST##1"); + ImGui::SameLine(); + ImGui::Text("TEST"); + ImGui::SameLine(); ImGui::SmallButton("TEST##2"); ImGui::AlignFirstTextHeightToWidgets(); // If your line starts with text, call this to align it to upcoming widgets. - ImGui::Text("Text aligned to Widget"); ImGui::SameLine(); - ImGui::Button("Widget##1"); ImGui::SameLine(); - ImGui::Text("Widget"); ImGui::SameLine(); + ImGui::Text("Text aligned to Widget"); + ImGui::SameLine(); + ImGui::Button("Widget##1"); + ImGui::SameLine(); + ImGui::Text("Widget"); + ImGui::SameLine(); ImGui::SmallButton("Widget##2"); // Tree const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; ImGui::Button("Button##1"); ImGui::SameLine(0.0f, spacing); - if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + if (ImGui::TreeNode("Node##1")) + { + for (int i = 0; i < 6; i++) + ImGui::BulletText("Item %d..", i); + ImGui::TreePop(); + } // Dummy tree data - ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). - bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); - if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with + // upcoming widget. Otherwise you can use SmallButton (smaller fit). + bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need + // to do it before we add child content. + ImGui::SameLine(0.0f, spacing); + ImGui::Button("Button##2"); + if (node_open) + { + for (int i = 0; i < 6; i++) + ImGui::BulletText("Item %d..", i); + ImGui::TreePop(); + } // Dummy tree data // Bullet ImGui::Button("Button##3"); @@ -1070,7 +1236,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::AlignFirstTextHeightToWidgets(); ImGui::BulletText("Node"); - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); + ImGui::SameLine(0.0f, spacing); + ImGui::Button("Button##4"); ImGui::TreePop(); } @@ -1078,13 +1245,15 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Scrolling")) { ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)"); - static bool track = true; - static int track_line = 50, scroll_to_px = 200; + static bool track = true; + static int track_line = 50, scroll_to_px = 200; ImGui::Checkbox("Track", &track); ImGui::PushItemWidth(100); - ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line %.0f"); + ImGui::SameLine(130); + track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line %.0f"); bool scroll_to = ImGui::Button("Scroll To"); - ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px"); + ImGui::SameLine(130); + scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px"); ImGui::PopItemWidth(); if (scroll_to) track = false; @@ -1093,14 +1262,13 @@ void ImGui::ShowTestWindow(bool* p_open) if (i > 0) ImGui::SameLine(); ImGui::BeginGroup(); ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom"); - ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true); - if (scroll_to) - ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f); + ImGui::BeginChild(ImGui::GetID((void *)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true); + if (scroll_to) ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f); for (int line = 0; line < 100; line++) { if (track && line == track_line) { - ImGui::TextColored(ImColor(255,255,0), "Line %d", line); + ImGui::TextColored(ImColor(255, 255, 0), "Line %d", line); ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom } else @@ -1116,25 +1284,34 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Horizontal Scrolling")) { - ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag."); - ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin()."); + ImGui::Bullet(); + ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the " + "ImGuiWindowFlags_HorizontalScrollbar flag."); + ImGui::Bullet(); + ImGui::TextWrapped( + "You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin()."); static int lines = 7; ImGui::SliderInt("Lines", &lines, 1, 15); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); - ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing() * 7 + 30), true, + ImGuiWindowFlags_HorizontalScrollbar); for (int line = 0; line < lines; line++) { - // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off - // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API) + // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to + // create your own time line for a real application you may be better off manipulating the cursor position + // yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use + // the lower-level ImDrawList API) int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3); for (int n = 0; n < num_buttons; n++) { if (n > 0) ImGui::SameLine(); ImGui::PushID(n + line * 1000); - char num_buf[16]; - const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf); - float hue = n*0.05f; + char num_buf[16]; + const char *label = (!(n % 15)) + ? "FizzBuzz" + : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf); + float hue = n * 0.05f; ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(hue, 0.6f, 0.6f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(hue, 0.7f, 0.7f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(hue, 0.8f, 0.8f)); @@ -1146,12 +1323,17 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::EndChild(); ImGui::PopStyleVar(2); float scroll_x_delta = 0.0f; - ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; - ImGui::SameLine(); ImGui::Text("Scroll from code"); ImGui::SameLine(); - ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; + ImGui::SmallButton("<<"); + if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; + ImGui::SameLine(); + ImGui::Text("Scroll from code"); + ImGui::SameLine(); + ImGui::SmallButton(">>"); + if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; if (scroll_x_delta != 0.0f) { - ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window) + ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of + // another window (here we are already out of your child window) ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta); ImGui::End(); } @@ -1161,15 +1343,23 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Clipping")) { static ImVec2 size(100, 100), offset(50, 20); - ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost."); - ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f"); + ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. " + "Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The " + "system is designed to try minimizing both execution and CPU/GPU rendering cost."); + ImGui::DragFloat2("size", (float *)&size, 0.5f, 0.0f, 200.0f, "%.0f"); ImGui::TextWrapped("(Click and drag)"); ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y); + ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); ImGui::InvisibleButton("##dummy", size); - if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; } - ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255)); - ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); + if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) + { + offset.x += ImGui::GetIO().MouseDelta.x; + offset.y += ImGui::GetIO().MouseDelta.y; + } + ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), ImColor(90, 90, 120, 255)); + ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize() * 2.0f, + ImVec2(pos.x + offset.x, pos.y + offset.y), ImColor(255, 255, 255, 255), + "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); ImGui::TreePop(); } } @@ -1178,16 +1368,17 @@ void ImGui::ShowTestWindow(bool* p_open) { if (ImGui::TreeNode("Popups")) { - ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); + ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking " + "outside the popup closes it."); - static int selected_fish = -1; - const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; - static bool toggles[] = { true, false, false, false, false }; + static int selected_fish = -1; + const char *names[] = {"Bream", "Haddock", "Mackerel", "Pollock", "Tilefish"}; + static bool toggles[] = {true, false, false, false, false}; // Simple selection popup - // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label) - if (ImGui::Button("Select..")) - ImGui::OpenPopup("select"); + // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" + // operator to preserve a constant ID with a variable label) + if (ImGui::Button("Select..")) ImGui::OpenPopup("select"); ImGui::SameLine(); ImGui::Text(selected_fish == -1 ? "" : names[selected_fish]); if (ImGui::BeginPopup("select")) @@ -1195,14 +1386,12 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("Aquarium"); ImGui::Separator(); for (int i = 0; i < IM_ARRAYSIZE(names); i++) - if (ImGui::Selectable(names[i])) - selected_fish = i; + if (ImGui::Selectable(names[i])) selected_fish = i; ImGui::EndPopup(); } // Showing a menu with toggles - if (ImGui::Button("Toggle..")) - ImGui::OpenPopup("toggle"); + if (ImGui::Button("Toggle..")) ImGui::OpenPopup("toggle"); if (ImGui::BeginPopup("toggle")) { for (int i = 0; i < IM_ARRAYSIZE(names); i++) @@ -1215,11 +1404,9 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Separator(); ImGui::Text("Tooltip here"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip over a popup"); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("I am a tooltip over a popup"); - if (ImGui::Button("Stacked Popup")) - ImGui::OpenPopup("another popup"); + if (ImGui::Button("Stacked Popup")) ImGui::OpenPopup("another popup"); if (ImGui::BeginPopup("another popup")) { for (int i = 0; i < IM_ARRAYSIZE(names); i++) @@ -1234,8 +1421,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::EndPopup(); } - if (ImGui::Button("Popup Menu..")) - ImGui::OpenPopup("FilePopup"); + if (ImGui::Button("Popup Menu..")) ImGui::OpenPopup("FilePopup"); if (ImGui::BeginPopup("FilePopup")) { ShowExampleMenuFile(); @@ -1243,11 +1429,14 @@ void ImGui::ShowTestWindow(bool* p_open) } ImGui::Spacing(); - ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); + ImGui::TextWrapped( + "Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); ImGui::Separator(); - // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above. - // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here - // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus. + // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of + // the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block to make them two + // different menusets. If we don't, opening any popup above and hovering our menu here would open it. This is because + // once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior + // for regular menus. ImGui::PushID("foo"); ImGui::MenuItem("Menu item", "CTRL+M"); if (ImGui::BeginMenu("Menu inside a regular window")) @@ -1277,12 +1466,12 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::BeginPopupContextItem("color context menu")) { ImGui::Text("Edit color"); - ImGui::ColorEdit3("##edit", (float*)&color); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); + ImGui::ColorEdit3("##edit", (float *)&color); + if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); } - ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); + ImGui::SameLine(); + ImGui::Text("(<-- right-click here)"); ImGui::TreePop(); } @@ -1291,45 +1480,40 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window."); - if (ImGui::Button("Delete..")) - ImGui::OpenPopup("Delete?"); + if (ImGui::Button("Delete..")) ImGui::OpenPopup("Delete?"); if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); ImGui::Separator(); - //static int dummy_i = 0; - //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0"); + // static int dummy_i = 0; + // ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0"); static bool dont_ask_me_next_time = false; - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); ImGui::PopStyleVar(); - if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } ImGui::SameLine(); - if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); } - if (ImGui::Button("Stacked modals..")) - ImGui::OpenPopup("Stacked 1"); + if (ImGui::Button("Stacked modals..")) ImGui::OpenPopup("Stacked 1"); if (ImGui::BeginPopupModal("Stacked 1")) { ImGui::Text("Hello from Stacked The First"); - if (ImGui::Button("Another one..")) - ImGui::OpenPopup("Stacked 2"); + if (ImGui::Button("Another one..")) ImGui::OpenPopup("Stacked 2"); if (ImGui::BeginPopupModal("Stacked 2")) { ImGui::Text("Hello from Stacked The Second"); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); + if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); } - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); + if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); } @@ -1343,14 +1527,14 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Basic")) { ImGui::Text("Without border:"); - ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border + ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border ImGui::Separator(); for (int n = 0; n < 14; n++) { char label[32]; sprintf(label, "Item %d", n); if (ImGui::Selectable(label)) {} - //if (ImGui::Button(label, ImVec2(-1,0))) {} + // if (ImGui::Button(label, ImVec2(-1,0))) {} ImGui::NextColumn(); } ImGui::Columns(1); @@ -1359,24 +1543,30 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("With border:"); ImGui::Columns(4, "mycolumns"); // 4-ways, with border ImGui::Separator(); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Text("Flags"); ImGui::NextColumn(); + ImGui::Text("ID"); + ImGui::NextColumn(); + ImGui::Text("Name"); + ImGui::NextColumn(); + ImGui::Text("Path"); + ImGui::NextColumn(); + ImGui::Text("Flags"); + ImGui::NextColumn(); ImGui::Separator(); - const char* names[3] = { "One", "Two", "Three" }; - const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; - static int selected = -1; + const char *names[3] = {"One", "Two", "Three"}; + const char *paths[3] = {"/path/one", "/path/two", "/path/three"}; + static int selected = -1; for (int i = 0; i < 3; i++) { char label[32]; sprintf(label, "%04d", i); - if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) - selected = i; + if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) selected = i; + ImGui::NextColumn(); + ImGui::Text(names[i]); + ImGui::NextColumn(); + ImGui::Text(paths[i]); + ImGui::NextColumn(); + ImGui::Text("...."); ImGui::NextColumn(); - ImGui::Text(names[i]); ImGui::NextColumn(); - ImGui::Text(paths[i]); ImGui::NextColumn(); - ImGui::Text("...."); ImGui::NextColumn(); } ImGui::Columns(1); ImGui::Separator(); @@ -1432,9 +1622,12 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); + ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); + ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); + ImGui::NextColumn(); ImGui::Columns(1); ImGui::Separator(); ImGui::TreePop(); @@ -1466,7 +1659,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (h_borders) ImGui::Separator(); for (int i = 0; i < 8; i++) { - ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i); + ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i); ImGui::NextColumn(); } ImGui::Columns(1); @@ -1475,13 +1668,24 @@ void ImGui::ShowTestWindow(bool* p_open) } bool node_open = ImGui::TreeNode("Tree within single cell"); - ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell."); + ImGui::SameLine(); + ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell."); if (node_open) { ImGui::Columns(2, "tree items"); ImGui::Separator(); - if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn(); - if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn(); + if (ImGui::TreeNode("Hello")) + { + ImGui::BulletText("Sailor"); + ImGui::TreePop(); + } + ImGui::NextColumn(); + if (ImGui::TreeNode("Bonjour")) + { + ImGui::BulletText("Marin"); + ImGui::TreePop(); + } + ImGui::NextColumn(); ImGui::Columns(1); ImGui::Separator(); ImGui::TreePop(); @@ -1497,10 +1701,9 @@ void ImGui::ShowTestWindow(bool* p_open) " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" " \"-xxx\" hide lines containing \"xxx\""); filter.Draw(); - const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; + const char *lines[] = {"aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world"}; for (int i = 0; i < IM_ARRAYSIZE(lines); i++) - if (filter.PassFilter(lines[i])) - ImGui::BulletText("%s", lines[i]); + if (filter.PassFilter(lines[i])) ImGui::BulletText("%s", lines[i]); } if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus")) @@ -1514,7 +1717,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::InputText("3", buf, IM_ARRAYSIZE(buf)); ImGui::PushAllowKeyboardFocus(false); ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf)); - //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets."); + // ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain + // widgets."); ImGui::PopAllowKeyboardFocus(); ImGui::InputText("5", buf, IM_ARRAYSIZE(buf)); ImGui::TreePop(); @@ -1522,11 +1726,13 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Focus from code")) { - bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine(); - bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine(); - bool focus_3 = ImGui::Button("Focus on 3"); - int has_focus = 0; - static char buf[128] = "click on a button to set focus"; + bool focus_1 = ImGui::Button("Focus on 1"); + ImGui::SameLine(); + bool focus_2 = ImGui::Button("Focus on 2"); + ImGui::SameLine(); + bool focus_3 = ImGui::Button("Focus on 3"); + int has_focus = 0; + static char buf[128] = "click on a button to set focus"; if (focus_1) ImGui::SetKeyboardFocusHere(); ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); @@ -1556,61 +1762,107 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::IsItemActive()) { // Draw a line between the button and the mouse cursor - ImDrawList* draw_list = ImGui::GetWindowDrawList(); + ImDrawList *draw_list = ImGui::GetWindowDrawList(); draw_list->PushClipRectFullScreen(); - draw_list->AddLine(ImGui::CalcItemRectClosestPoint(ImGui::GetIO().MousePos, true, -2.0f), ImGui::GetIO().MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); + draw_list->AddLine(ImGui::CalcItemRectClosestPoint(ImGui::GetIO().MousePos, true, -2.0f), ImGui::GetIO().MousePos, + ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); draw_list->PopClipRect(); - ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); + ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); - ImVec2 mouse_delta = ImGui::GetIO().MouseDelta; - ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y); + ImVec2 mouse_delta = ImGui::GetIO().MouseDelta; + ImGui::SameLine(); + ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, + value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y); } ImGui::TreePop(); } if (ImGui::TreeNode("Keyboard & Mouse State")) { - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y); - ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } - ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse down:"); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) + if (io.MouseDownDuration[i] >= 0.0f) + { + ImGui::SameLine(); + ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); + } + ImGui::Text("Mouse clicked:"); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) + if (ImGui::IsMouseClicked(i)) + { + ImGui::SameLine(); + ImGui::Text("b%d", i); + } + ImGui::Text("Mouse dbl-clicked:"); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) + if (ImGui::IsMouseDoubleClicked(i)) + { + ImGui::SameLine(); + ImGui::Text("b%d", i); + } + ImGui::Text("Mouse released:"); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) + if (ImGui::IsMouseReleased(i)) + { + ImGui::SameLine(); + ImGui::Text("b%d", i); + } ImGui::Text("MouseWheel: %.1f", io.MouseWheel); - ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } - ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); + ImGui::Text("Keys down:"); + for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) + if (io.KeysDownDuration[i] >= 0.0f) + { + ImGui::SameLine(); + ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); + } + ImGui::Text("Keys pressed:"); + for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) + if (ImGui::IsKeyPressed(i)) + { + ImGui::SameLine(); + ImGui::Text("%d", i); + } + ImGui::Text("Keys release:"); + for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) + if (ImGui::IsKeyReleased(i)) + { + ImGui::SameLine(); + ImGui::Text("%d", i); + } + ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", + io.KeySuper ? "SUPER " : ""); ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); ImGui::Text("WantTextInput: %s", io.WantTextInput ? "true" : "false"); ImGui::Button("Hovering me sets the\nkeyboard capture flag"); - if (ImGui::IsItemHovered()) - ImGui::CaptureKeyboardFromApp(true); + if (ImGui::IsItemHovered()) ImGui::CaptureKeyboardFromApp(true); ImGui::SameLine(); ImGui::Button("Holding me clears the\nthe keyboard capture flag"); - if (ImGui::IsItemActive()) - ImGui::CaptureKeyboardFromApp(false); + if (ImGui::IsItemActive()) ImGui::CaptureKeyboardFromApp(false); ImGui::TreePop(); } if (ImGui::TreeNode("Mouse cursors")) { - ImGui::TextWrapped("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. You can also set io.MouseDrawCursor to ask ImGui to render the cursor for you in software."); + ImGui::TextWrapped( + "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. You can " + "also set io.MouseDrawCursor to ask ImGui to render the cursor for you in software."); ImGui::Checkbox("io.MouseDrawCursor", &ImGui::GetIO().MouseDrawCursor); ImGui::Text("Hover to see mouse cursors:"); for (int i = 0; i < ImGuiMouseCursor_Count_; i++) { char label[32]; sprintf(label, "Mouse cursor %d", i); - ImGui::Bullet(); ImGui::Selectable(label, false); - if (ImGui::IsItemHovered()) - ImGui::SetMouseCursor(i); + ImGui::Bullet(); + ImGui::Selectable(label, false); + if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(i); } ImGui::TreePop(); } @@ -1619,20 +1871,19 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::End(); } -void ImGui::ShowStyleEditor(ImGuiStyle* ref) +void ImGui::ShowStyleEditor(ImGuiStyle *ref) { - ImGuiStyle& style = ImGui::GetStyle(); + ImGuiStyle &style = ImGui::GetStyle(); - // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to the default style) + // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to the default + // style) const ImGuiStyle default_style; // Default style - if (ImGui::Button("Revert Style")) - style = ref ? *ref : default_style; + if (ImGui::Button("Revert Style")) style = ref ? *ref : default_style; if (ref) { ImGui::SameLine(); - if (ImGui::Button("Save Style")) - *ref = style; + if (ImGui::Button("Save Style")) *ref = style; } ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.55f); @@ -1644,35 +1895,39 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::PushItemWidth(100); ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; - ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. + ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, + "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But + // application code could have a toggle to switch between zero and non-zero. ImGui::PopItemWidth(); ImGui::TreePop(); } if (ImGui::TreeNode("Settings")) { - ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("WindowPadding", (float *)&style.WindowPadding, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 16.0f, "%.0f"); ImGui::SliderFloat("ChildWindowRounding", &style.ChildWindowRounding, 0.0f, 16.0f, "%.0f"); - ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("FramePadding", (float *)&style.FramePadding, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 16.0f, "%.0f"); - ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); + ImGui::SliderFloat2("ItemSpacing", (float *)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("ItemInnerSpacing", (float *)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("TouchExtraPadding", (float *)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f"); ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f"); ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 16.0f, "%.0f"); ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f"); ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 16.0f, "%.0f"); ImGui::Text("Alignment"); - ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); - ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content."); + ImGui::SliderFloat2("WindowTitleAlign", (float *)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat2("ButtonTextAlign", (float *)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); + ImGui::SameLine(); + ShowHelpMarker("Alignment applies when a button is larger than its text content."); ImGui::TreePop(); } if (ImGui::TreeNode("Colors")) { - static int output_dest = 0; + static int output_dest = 0; static bool output_only_modified = false; if (ImGui::Button("Copy Colors")) { @@ -1683,15 +1938,21 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::LogText("ImGuiStyle& style = ImGui::GetStyle();" IM_NEWLINE); for (int i = 0; i < ImGuiCol_COUNT; i++) { - const ImVec4& col = style.Colors[i]; - const char* name = ImGui::GetStyleColName(i); - if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) - ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 22 - (int)strlen(name), "", col.x, col.y, col.z, col.w); + const ImVec4 &col = style.Colors[i]; + const char * name = ImGui::GetStyleColName(i); + if (!output_only_modified || + memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) + ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, + 22 - (int)strlen(name), "", col.x, col.y, col.z, col.w); } ImGui::LogFinish(); } - ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth(); - ImGui::SameLine(); ImGui::Checkbox("Only Modified Fields", &output_only_modified); + ImGui::SameLine(); + ImGui::PushItemWidth(120); + ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + ImGui::Checkbox("Only Modified Fields", &output_only_modified); static ImGuiColorEditMode edit_mode = ImGuiColorEditMode_RGB; ImGui::RadioButton("RGB", &edit_mode, ImGuiColorEditMode_RGB); @@ -1699,7 +1960,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::RadioButton("HSV", &edit_mode, ImGuiColorEditMode_HSV); ImGui::SameLine(); ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX); - //ImGui::Text("Tip: Click on colored square to change edit mode."); + // ImGui::Text("Tip: Click on colored square to change edit mode."); static ImGuiTextFilter filter; filter.Draw("Filter colors", 200); @@ -1709,15 +1970,19 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::ColorEditMode(edit_mode); for (int i = 0; i < ImGuiCol_COUNT; i++) { - const char* name = ImGui::GetStyleColName(i); - if (!filter.PassFilter(name)) - continue; + const char *name = ImGui::GetStyleColName(i); + if (!filter.PassFilter(name)) continue; ImGui::PushID(i); - ImGui::ColorEdit4(name, (float*)&style.Colors[i], true); + ImGui::ColorEdit4(name, (float *)&style.Colors[i], true); if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) { - ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : default_style.Colors[i]; - if (ref) { ImGui::SameLine(); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; } + ImGui::SameLine(); + if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : default_style.Colors[i]; + if (ref) + { + ImGui::SameLine(); + if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; + } } ImGui::PopID(); } @@ -1729,62 +1994,81 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size)) { - ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); - ImFontAtlas* atlas = ImGui::GetIO().Fonts; + ImGui::SameLine(); + ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); + ImFontAtlas *atlas = ImGui::GetIO().Fonts; if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) { - ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); + ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), + ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128)); ImGui::TreePop(); } ImGui::PushItemWidth(100); for (int i = 0; i < atlas->Fonts.Size; i++) { - ImFont* font = atlas->Fonts[i]; - ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size); - ImGui::TreePush((void*)(intptr_t)i); - ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font; + ImFont *font = atlas->Fonts[i]; + ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", + font->FontSize, font->Glyphs.Size); + ImGui::TreePush((void *)(intptr_t)i); + ImGui::SameLine(); + if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font; ImGui::PushFont(font); ImGui::Text("The quick brown fox jumps over the lazy dog"); ImGui::PopFont(); if (ImGui::TreeNode("Details")) { - ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font - ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); + ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font + ImGui::SameLine(); + ShowHelpMarker( + "Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps " + "at a given size at the time of building the atlas. You may oversample them to get some flexibility with " + "scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: " + "the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); - ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((int)font->MetricsTotalSurface), (int)sqrtf((int)font->MetricsTotalSurface)); + ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, + (int)sqrtf((int)font->MetricsTotalSurface), (int)sqrtf((int)font->MetricsTotalSurface)); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) { - ImFontConfig* cfg = &font->ConfigData[config_i]; - ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); + ImFontConfig *cfg = &font->ConfigData[config_i]; + ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, + cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); } if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { // Display all glyphs of the fonts in separate pages of 256 characters - const ImFont::Glyph* glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior. + const ImFont::Glyph *glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL + // on fallback, which isn't the default behavior. font->FallbackGlyph = NULL; for (int base = 0; base < 0x10000; base += 256) { int count = 0; for (int n = 0; n < 256; n++) count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0; - if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph")) + if (count > 0 && ImGui::TreeNode((void *)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, + count, count > 1 ? "glyphs" : "glyph")) { - float cell_spacing = style.ItemSpacing.y; - ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1); - ImVec2 base_pos = ImGui::GetCursorScreenPos(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); + float cell_spacing = style.ItemSpacing.y; + ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1); + ImVec2 base_pos = ImGui::GetCursorScreenPos(); + ImDrawList *draw_list = ImGui::GetWindowDrawList(); for (int n = 0; n < 256; n++) { - ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing)); - ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y); - const ImFont::Glyph* glyph = font->FindGlyph((ImWchar)(base+n));; - draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); - font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. + ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), + base_pos.y + (n / 16) * (cell_size.y + cell_spacing)); + ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y); + const ImFont::Glyph *glyph = font->FindGlyph((ImWchar)(base + n)); + ; + draw_list->AddRect(cell_p1, cell_p2, + glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50)); + font->RenderChar( + draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), + (ImWchar)(base + n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 + // conversion functions available to generate a string. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) { ImGui::BeginTooltip(); - ImGui::Text("Codepoint: U+%04X", base+n); + ImGui::Text("Codepoint: U+%04X", base + n); ImGui::Separator(); ImGui::Text("XAdvance+1: %.1f", glyph->XAdvance); ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1); @@ -1827,7 +2111,7 @@ static void ShowExampleAppMainMenuBar() if (ImGui::BeginMenu("Edit")) { if (ImGui::MenuItem("Undo", "CTRL+Z")) {} - if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item + if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item ImGui::Separator(); if (ImGui::MenuItem("Cut", "CTRL+X")) {} if (ImGui::MenuItem("Copy", "CTRL+C")) {} @@ -1873,7 +2157,7 @@ static void ShowExampleMenuFile() ImGui::Text("Scrolling Text %d", i); ImGui::EndChild(); static float f = 0.5f; - static int n = 0; + static int n = 0; ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); ImGui::InputFloat("Input", &f, 0.1f); ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); @@ -1886,15 +2170,13 @@ static void ShowExampleMenuFile() ImGui::EndMenu(); } if (ImGui::BeginMenu("Disabled", false)) // Disabled - { - IM_ASSERT(0); - } + { IM_ASSERT(0); } if (ImGui::MenuItem("Checked", NULL, true)) {} if (ImGui::MenuItem("Quit", "Alt+F4")) {} } // Demonstrate creating a window which gets auto-resized according to its content. -static void ShowExampleAppAutoResize(bool* p_open) +static void ShowExampleAppAutoResize(bool *p_open) { if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize)) { @@ -1903,56 +2185,68 @@ static void ShowExampleAppAutoResize(bool* p_open) } static int lines = 10; - ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop."); + ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the " + "window size to\noutput your content because that would create a feedback loop."); ImGui::SliderInt("Number of lines", &lines, 1, 20); for (int i = 0; i < lines; i++) - ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally + ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally ImGui::End(); } // Demonstrate creating a window with custom resize constraints. -static void ShowExampleAppConstrainedResize(bool* p_open) +static void ShowExampleAppConstrainedResize(bool *p_open) { struct CustomConstraints // Helper functions to demonstrate programmatic constraints { - static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } - static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } + static void Square(ImGuiSizeConstraintCallbackData *data) + { + data->DesiredSize = + ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); + } + static void Step(ImGuiSizeConstraintCallbackData *data) + { + float step = (float)(int)(intptr_t)data->UserData; + data->DesiredSize = + ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); + } }; static int type = 0; - if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only - if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only + if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only + if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 - if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 - if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square - if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step + if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 + if (type == 4) + ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square + if (type == 5) + ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, + (void *)100); // Fixed Step if (ImGui::Begin("Example: Constrained Resize", p_open)) { - const char* desc[] = - { - "Resize vertical only", - "Resize horizontal only", - "Width > 100, Height > 100", - "Width 300-400", - "Custom: Always Square", - "Custom: Fixed Steps (100)", + const char *desc[] = { + "Resize vertical only", "Resize horizontal only", "Width > 100, Height > 100", + "Width 300-400", "Custom: Always Square", "Custom: Fixed Steps (100)", }; - ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); - if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200,200)); ImGui::SameLine(); - if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500,500)); ImGui::SameLine(); - if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800,200)); - for (int i = 0; i < 10; i++) + ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); + if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200, 200)); + ImGui::SameLine(); + if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500, 500)); + ImGui::SameLine(); + if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800, 200)); + for (int i = 0; i < 10; i++) ImGui::Text("Hello, sailor! Making this line long enough for the example."); } ImGui::End(); } // Demonstrate creating a simple static window with no decoration. -static void ShowExampleAppFixedOverlay(bool* p_open) +static void ShowExampleAppFixedOverlay(bool *p_open) { - ImGui::SetNextWindowPos(ImVec2(10,10)); - if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) + ImGui::SetNextWindowPos(ImVec2(10, 10)); + if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0, 0), 0.3f, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoSavedSettings)) { ImGui::End(); return; @@ -1964,97 +2258,123 @@ static void ShowExampleAppFixedOverlay(bool* p_open) } // Demonstrate using "##" and "###" in identifiers to manipulate ID generation. -// Read section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." about ID. -static void ShowExampleAppManipulatingWindowTitle(bool*) +// Read section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the +// purpose of labels/IDs." about ID. +static void ShowExampleAppManipulatingWindowTitle(bool *) { // By default, Windows are uniquely identified by their title. // You can use the "##" and "###" markers to manipulate the display/ID. // Using "##" to display same title but have unique identifier. - ImGui::SetNextWindowPos(ImVec2(100,100), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiSetCond_FirstUseEver); ImGui::Begin("Same title as another window##1"); ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique."); ImGui::End(); - ImGui::SetNextWindowPos(ImVec2(100,200), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiSetCond_FirstUseEver); ImGui::Begin("Same title as another window##2"); ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique."); ImGui::End(); // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" char buf[128]; - sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand()); - ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiSetCond_FirstUseEver); + sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], rand()); + ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiSetCond_FirstUseEver); ImGui::Begin(buf); ImGui::Text("This window has a changing title."); ImGui::End(); } -// Demonstrate using the low-level ImDrawList to draw custom shapes. -static void ShowExampleAppCustomRendering(bool* p_open) +// Demonstrate using the low-level ImDrawList to draw custom shapes. +static void ShowExampleAppCustomRendering(bool *p_open) { - ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin("Example: Custom rendering", p_open)) { ImGui::End(); return; } - // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc. - // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4. - // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types) - // In this example we are not using the maths operators! - ImDrawList* draw_list = ImGui::GetWindowDrawList(); + // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded + // operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and + // ImVec2/ImVec4. ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid + // messing with your types) In this example we are not using the maths operators! + ImDrawList *draw_list = ImGui::GetWindowDrawList(); // Primitives ImGui::Text("Primitives"); - static float sz = 36.0f; - static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f); + static float sz = 36.0f; + static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); ImGui::ColorEdit3("Color", &col.x); { - const ImVec2 p = ImGui::GetCursorScreenPos(); - const ImU32 col32 = ImColor(col); - float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f; + const ImVec2 p = ImGui::GetCursorScreenPos(); + const ImU32 col32 = ImColor(col); + float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f; for (int n = 0; n < 2; n++) { float thickness = (n == 0) ? 1.0f : 4.0f; - draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ~0, thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ~0, thickness); x += sz+spacing; - draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, thickness); x += spacing; - draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, thickness); + draw_list->AddCircle(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col32, 20, thickness); + x += sz + spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 0.0f, ~0, thickness); + x += sz + spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ~0, thickness); + x += sz + spacing; + draw_list->AddTriangle(ImVec2(x + sz * 0.5f, y), ImVec2(x + sz, y + sz - 0.5f), ImVec2(x, y + sz - 0.5f), col32, + thickness); + x += sz + spacing; + draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col32, thickness); + x += sz + spacing; + draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, thickness); + x += sz + spacing; + draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col32, thickness); + x += spacing; + draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), + ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz), col32, thickness); x = p.x + 4; - y += sz+spacing; - } - draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing; - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing; - draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing; - draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0)); - ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3)); + y += sz + spacing; + } + draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col32, 32); + x += sz + spacing; + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32); + x += sz + spacing; + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f); + x += sz + spacing; + draw_list->AddTriangleFilled(ImVec2(x + sz * 0.5f, y), ImVec2(x + sz, y + sz - 0.5f), ImVec2(x, y + sz - 0.5f), col32); + x += sz + spacing; + draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), ImColor(0, 0, 0), ImColor(255, 0, 0), + ImColor(255, 255, 0), ImColor(0, 255, 0)); + ImGui::Dummy(ImVec2((sz + spacing) * 8, (sz + spacing) * 3)); } ImGui::Separator(); { static ImVector points; - static bool adding_line = false; + static bool adding_line = false; ImGui::Text("Canvas example"); if (ImGui::Button("Clear")) points.clear(); - if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } } + if (points.Size >= 2) + { + ImGui::SameLine(); + if (ImGui::Button("Undo")) + { + points.pop_back(); + points.pop_back(); + } + } ImGui::Text("Left-click and drag to add lines,\nRight-click to undo"); // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered() - // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos(). - // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max). - ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! - ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available + // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() + // and SetCursorPos(). If you only use the ImDrawList API, you can notify the owner window of its extends by using + // SetCursorPos(max). + ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! + ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available if (canvas_size.x < 50.0f) canvas_size.x = 50.0f; if (canvas_size.y < 50.0f) canvas_size.y = 50.0f; - draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(50,50,50), ImColor(50,50,60), ImColor(60,60,70), ImColor(50,50,60)); - draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255)); + draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), + ImColor(50, 50, 50), ImColor(50, 50, 60), ImColor(60, 60, 70), ImColor(50, 50, 60)); + draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), + ImColor(255, 255, 255)); bool adding_preview = false; ImGui::InvisibleButton("canvas", canvas_size); @@ -2063,8 +2383,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) { adding_preview = true; points.push_back(mouse_pos_in_canvas); - if (!ImGui::GetIO().MouseDown[0]) - adding_line = adding_preview = false; + if (!ImGui::GetIO().MouseDown[0]) adding_line = adding_preview = false; } if (ImGui::IsItemHovered()) { @@ -2080,12 +2399,15 @@ static void ShowExampleAppCustomRendering(bool* p_open) points.pop_back(); } } - draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.) + draw_list->PushClipRect(canvas_pos, + ImVec2(canvas_pos.x + canvas_size.x, + canvas_pos.y + canvas_size.y)); // clip lines within the canvas (if we resize it, etc.) for (int i = 0; i < points.Size - 1; i += 2) - draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), IM_COL32(255,255,0,255), 2.0f); + draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), + ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), + 2.0f); draw_list->PopClipRect(); - if (adding_preview) - points.pop_back(); + if (adding_preview) points.pop_back(); } ImGui::End(); } @@ -2094,12 +2416,12 @@ static void ShowExampleAppCustomRendering(bool* p_open) // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions. struct ExampleAppConsole { - char InputBuf[256]; - ImVector Items; - bool ScrollToBottom; - ImVector History; - int HistoryPos; // -1: new line, 0..History.Size-1 browsing history. - ImVector Commands; + char InputBuf[256]; + ImVector Items; + bool ScrollToBottom; + ImVector History; + int HistoryPos; // -1: new line, 0..History.Size-1 browsing history. + ImVector Commands; ExampleAppConsole() { @@ -2109,7 +2431,8 @@ struct ExampleAppConsole Commands.push_back("HELP"); Commands.push_back("HISTORY"); Commands.push_back("CLEAR"); - Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches. + Commands.push_back( + "CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches. AddLog("Welcome to ImGui!"); } ~ExampleAppConsole() @@ -2120,11 +2443,35 @@ struct ExampleAppConsole } // Portable helpers - static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; } - static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; } - static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); } + static int Stricmp(const char *str1, const char *str2) + { + int d; + while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) + { + str1++; + str2++; + } + return d; + } + static int Strnicmp(const char *str1, const char *str2, int n) + { + int d = 0; + while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) + { + str1++; + str2++; + n--; + } + return d; + } + static char *Strdup(const char *str) + { + size_t len = strlen(str) + 1; + void * buff = malloc(len); + return (char *)memcpy(buff, (const void *)str, len); + } - void ClearLog() + void ClearLog() { for (int i = 0; i < Items.Size; i++) free(Items[i]); @@ -2132,108 +2479,130 @@ struct ExampleAppConsole ScrollToBottom = true; } - void AddLog(const char* fmt, ...) IM_PRINTFARGS(2) + void AddLog(const char *fmt, ...) IM_PRINTFARGS(2) { - char buf[1024]; + char buf[1024]; va_list args; va_start(args, fmt); vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); - buf[IM_ARRAYSIZE(buf)-1] = 0; + buf[IM_ARRAYSIZE(buf) - 1] = 0; va_end(args); Items.push_back(Strdup(buf)); ScrollToBottom = true; } - void Draw(const char* title, bool* p_open) + void Draw(const char *title, bool *p_open) { - ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin(title, p_open)) { ImGui::End(); return; } - ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc."); + ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate " + "implementation may want to store entries along with extra data such as timestamp, emitter, etc."); ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion."); // TODO: display items starting from the bottom - if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); - if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); - if (ImGui::SmallButton("Clear")) ClearLog(); ImGui::SameLine(); + if (ImGui::SmallButton("Add Dummy Text")) + { + AddLog("%d some text", Items.Size); + AddLog("some more text"); + AddLog("display very important message here!"); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); + ImGui::SameLine(); + if (ImGui::SmallButton("Clear")) ClearLog(); + ImGui::SameLine(); if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true; - //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } + // static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } ImGui::Separator(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); static ImGuiTextFilter filter; filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); ImGui::PopStyleVar(); ImGui::Separator(); - ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing()), false, + ImGuiWindowFlags_HorizontalScrollbar); if (ImGui::BeginPopupContextWindow()) { if (ImGui::Selectable("Clear")) ClearLog(); ImGui::EndPopup(); } - // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end()); - // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items. - // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements. - // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with: + // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text + // you can use ImGui::TextUnformatted(log.begin(), log.end()); NB- if you have thousands of entries this approach may be + // too inefficient and may require user-side clipping to only process visible items. You can seek and display only the + // lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random + // access to the elements. To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with: // ImGuiListClipper clipper(Items.Size); // while (clipper.Step()) // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list. - // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter, - // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code! - // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list. - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing + // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap + // random-access' property. We would need random-access on the post-filtered list. A typical application wanting coarse + // clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this + // array when user changes the filter, and appending newly elements as they are inserted. This is left as a task to the + // user until we can manage to improve this example code! If your items are of variable size you may want to implement + // code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into + // your list. + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing for (int i = 0; i < Items.Size; i++) { - const char* item = Items[i]; - if (!filter.PassFilter(item)) - continue; - ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text. - if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f); - else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f); + const char *item = Items[i]; + if (!filter.PassFilter(item)) continue; + ImVec4 col = + ImVec4(1.0f, 1.0f, 1.0f, + 1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text. + if (strstr(item, "[error]")) + col = ImColor(1.0f, 0.4f, 0.4f, 1.0f); + else if (strncmp(item, "# ", 2) == 0) + col = ImColor(1.0f, 0.78f, 0.58f, 1.0f); ImGui::PushStyleColor(ImGuiCol_Text, col); ImGui::TextUnformatted(item); ImGui::PopStyleColor(); } - if (ScrollToBottom) - ImGui::SetScrollHere(); + if (ScrollToBottom) ImGui::SetScrollHere(); ScrollToBottom = false; ImGui::PopStyleVar(); ImGui::EndChild(); ImGui::Separator(); // Command-line - if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this)) - { - char* input_end = InputBuf+strlen(InputBuf); - while (input_end > InputBuf && input_end[-1] == ' ') input_end--; *input_end = 0; - if (InputBuf[0]) - ExecCommand(InputBuf); + if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), + ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | + ImGuiInputTextFlags_CallbackHistory, + &TextEditCallbackStub, (void *)this)) + { + char *input_end = InputBuf + strlen(InputBuf); + while (input_end > InputBuf && input_end[-1] == ' ') + input_end--; + *input_end = 0; + if (InputBuf[0]) ExecCommand(InputBuf); strcpy(InputBuf, ""); } // Demonstrate keeping auto focus on the input box - if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) + if (ImGui::IsItemHovered() || + (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget ImGui::End(); } - void ExecCommand(const char* command_line) + void ExecCommand(const char *command_line) { AddLog("# %s\n", command_line); - // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal. + // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or + // optimal. HistoryPos = -1; - for (int i = History.Size-1; i >= 0; i--) + for (int i = History.Size - 1; i >= 0; i--) if (Stricmp(History[i], command_line) == 0) { free(History[i]); @@ -2243,10 +2612,7 @@ struct ExampleAppConsole History.push_back(Strdup(command_line)); // Process command - if (Stricmp(command_line, "CLEAR") == 0) - { - ClearLog(); - } + if (Stricmp(command_line, "CLEAR") == 0) { ClearLog(); } else if (Stricmp(command_line, "HELP") == 0) { AddLog("Commands:"); @@ -2264,113 +2630,112 @@ struct ExampleAppConsole } } - static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks + static int TextEditCallbackStub( + ImGuiTextEditCallbackData *data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks { - ExampleAppConsole* console = (ExampleAppConsole*)data->UserData; + ExampleAppConsole *console = (ExampleAppConsole *)data->UserData; return console->TextEditCallback(data); } - int TextEditCallback(ImGuiTextEditCallbackData* data) + int TextEditCallback(ImGuiTextEditCallbackData *data) { - //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd); + // AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd); switch (data->EventFlag) { case ImGuiInputTextFlags_CallbackCompletion: - { - // Example of TEXT COMPLETION + { + // Example of TEXT COMPLETION - // Locate beginning of current word - const char* word_end = data->Buf + data->CursorPos; - const char* word_start = word_end; - while (word_start > data->Buf) - { - const char c = word_start[-1]; - if (c == ' ' || c == '\t' || c == ',' || c == ';') - break; - word_start--; - } + // Locate beginning of current word + const char *word_end = data->Buf + data->CursorPos; + const char *word_start = word_end; + while (word_start > data->Buf) + { + const char c = word_start[-1]; + if (c == ' ' || c == '\t' || c == ',' || c == ';') break; + word_start--; + } - // Build a list of candidates - ImVector candidates; - for (int i = 0; i < Commands.Size; i++) - if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0) - candidates.push_back(Commands[i]); + // Build a list of candidates + ImVector candidates; + for (int i = 0; i < Commands.Size; i++) + if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0) candidates.push_back(Commands[i]); - if (candidates.Size == 0) - { - // No match - AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start); - } - else if (candidates.Size == 1) + if (candidates.Size == 0) + { + // No match + AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start); + } + else if (candidates.Size == 1) + { + // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing + data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start)); + data->InsertChars(data->CursorPos, candidates[0]); + data->InsertChars(data->CursorPos, " "); + } + else + { + // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and + // "CLASSIFY" + int match_len = (int)(word_end - word_start); + for (;;) { - // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing - data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start)); - data->InsertChars(data->CursorPos, candidates[0]); - data->InsertChars(data->CursorPos, " "); + int c = 0; + bool all_candidates_matches = true; + for (int i = 0; i < candidates.Size && all_candidates_matches; i++) + if (i == 0) + c = toupper(candidates[i][match_len]); + else if (c == 0 || c != toupper(candidates[i][match_len])) + all_candidates_matches = false; + if (!all_candidates_matches) break; + match_len++; } - else - { - // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY" - int match_len = (int)(word_end - word_start); - for (;;) - { - int c = 0; - bool all_candidates_matches = true; - for (int i = 0; i < candidates.Size && all_candidates_matches; i++) - if (i == 0) - c = toupper(candidates[i][match_len]); - else if (c == 0 || c != toupper(candidates[i][match_len])) - all_candidates_matches = false; - if (!all_candidates_matches) - break; - match_len++; - } - if (match_len > 0) - { - data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start)); - data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len); - } - - // List matches - AddLog("Possible matches:\n"); - for (int i = 0; i < candidates.Size; i++) - AddLog("- %s\n", candidates[i]); + if (match_len > 0) + { + data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start)); + data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len); } - break; + // List matches + AddLog("Possible matches:\n"); + for (int i = 0; i < candidates.Size; i++) + AddLog("- %s\n", candidates[i]); } + + break; + } case ImGuiInputTextFlags_CallbackHistory: + { + // Example of HISTORY + const int prev_history_pos = HistoryPos; + if (data->EventKey == ImGuiKey_UpArrow) { - // Example of HISTORY - const int prev_history_pos = HistoryPos; - if (data->EventKey == ImGuiKey_UpArrow) - { - if (HistoryPos == -1) - HistoryPos = History.Size - 1; - else if (HistoryPos > 0) - HistoryPos--; - } - else if (data->EventKey == ImGuiKey_DownArrow) - { - if (HistoryPos != -1) - if (++HistoryPos >= History.Size) - HistoryPos = -1; - } + if (HistoryPos == -1) + HistoryPos = History.Size - 1; + else if (HistoryPos > 0) + HistoryPos--; + } + else if (data->EventKey == ImGuiKey_DownArrow) + { + if (HistoryPos != -1) + if (++HistoryPos >= History.Size) HistoryPos = -1; + } - // A better implementation would preserve the data on the current input line along with cursor position. - if (prev_history_pos != HistoryPos) - { - data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : ""); - data->BufDirty = true; - } + // A better implementation would preserve the data on the current input line along with cursor position. + if (prev_history_pos != HistoryPos) + { + data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = + (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : ""); + data->BufDirty = true; } } + } return 0; } }; -static void ShowExampleAppConsole(bool* p_open) +static void ShowExampleAppConsole(bool *p_open) { static ExampleAppConsole console; console.Draw("Example: Console", p_open); @@ -2382,29 +2747,32 @@ static void ShowExampleAppConsole(bool* p_open) // my_log.Draw("title"); struct ExampleAppLog { - ImGuiTextBuffer Buf; - ImGuiTextFilter Filter; - ImVector LineOffsets; // Index to lines offset - bool ScrollToBottom; + ImGuiTextBuffer Buf; + ImGuiTextFilter Filter; + ImVector LineOffsets; // Index to lines offset + bool ScrollToBottom; - void Clear() { Buf.clear(); LineOffsets.clear(); } + void Clear() + { + Buf.clear(); + LineOffsets.clear(); + } - void AddLog(const char* fmt, ...) IM_PRINTFARGS(2) + void AddLog(const char *fmt, ...) IM_PRINTFARGS(2) { - int old_size = Buf.size(); + int old_size = Buf.size(); va_list args; va_start(args, fmt); Buf.appendv(fmt, args); va_end(args); for (int new_size = Buf.size(); old_size < new_size; old_size++) - if (Buf[old_size] == '\n') - LineOffsets.push_back(old_size); + if (Buf[old_size] == '\n') LineOffsets.push_back(old_size); ScrollToBottom = true; } - void Draw(const char* title, bool* p_open = NULL) + void Draw(const char *title, bool *p_open = NULL) { - ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiSetCond_FirstUseEver); ImGui::Begin(title, p_open); if (ImGui::Button("Clear")) Clear(); ImGui::SameLine(); @@ -2412,18 +2780,17 @@ struct ExampleAppLog ImGui::SameLine(); Filter.Draw("Filter", -100.0f); ImGui::Separator(); - ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); if (copy) ImGui::LogToClipboard(); if (Filter.IsActive()) { - const char* buf_begin = Buf.begin(); - const char* line = buf_begin; + const char *buf_begin = Buf.begin(); + const char *line = buf_begin; for (int line_no = 0; line != NULL; line_no++) { - const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL; - if (Filter.PassFilter(line, line_end)) - ImGui::TextUnformatted(line, line_end); + const char *line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL; + if (Filter.PassFilter(line, line_end)) ImGui::TextUnformatted(line, line_end); line = line_end && line_end[1] ? line_end + 1 : NULL; } } @@ -2432,8 +2799,7 @@ struct ExampleAppLog ImGui::TextUnformatted(Buf.begin()); } - if (ScrollToBottom) - ImGui::SetScrollHere(1.0f); + if (ScrollToBottom) ImGui::SetScrollHere(1.0f); ScrollToBottom = false; ImGui::EndChild(); ImGui::End(); @@ -2441,16 +2807,16 @@ struct ExampleAppLog }; // Demonstrate creating a simple log window with basic filtering. -static void ShowExampleAppLog(bool* p_open) +static void ShowExampleAppLog(bool *p_open) { static ExampleAppLog log; // Demo fill static float last_time = -1.0f; - float time = ImGui::GetTime(); + float time = ImGui::GetTime(); if (time - last_time >= 0.3f) { - const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" }; + const char *random_words[] = {"system", "info", "warning", "error", "fatal", "notice", "log"}; log.AddLog("[%s] Hello, time is %.1f, rand() %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand()); last_time = time; } @@ -2459,7 +2825,7 @@ static void ShowExampleAppLog(bool* p_open) } // Demonstrate create a window with multiple child windows. -static void ShowExampleAppLayout(bool* p_open) +static void ShowExampleAppLayout(bool *p_open) { ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiSetCond_FirstUseEver); if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar)) @@ -2481,51 +2847,54 @@ static void ShowExampleAppLayout(bool* p_open) { char label[128]; sprintf(label, "MyObject %d", i); - if (ImGui::Selectable(label, selected == i)) - selected = i; + if (ImGui::Selectable(label, selected == i)) selected = i; } ImGui::EndChild(); ImGui::SameLine(); // right ImGui::BeginGroup(); - ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us - ImGui::Text("MyObject: %d", selected); - ImGui::Separator(); - ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); - ImGui::EndChild(); - ImGui::BeginChild("buttons"); - if (ImGui::Button("Revert")) {} - ImGui::SameLine(); - if (ImGui::Button("Save")) {} - ImGui::EndChild(); + ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us + ImGui::Text("MyObject: %d", selected); + ImGui::Separator(); + ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore " + "et dolore magna aliqua. "); + ImGui::EndChild(); + ImGui::BeginChild("buttons"); + if (ImGui::Button("Revert")) {} + ImGui::SameLine(); + if (ImGui::Button("Save")) {} + ImGui::EndChild(); ImGui::EndGroup(); } ImGui::End(); } // Demonstrate create a simple property editor. -static void ShowExampleAppPropertyEditor(bool* p_open) +static void ShowExampleAppPropertyEditor(bool *p_open) { - ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin("Example: Property editor", p_open)) { ImGui::End(); return; } - ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API."); + ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are " + "dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor " + "horizontally instead of using the Columns() API."); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); ImGui::Columns(2); ImGui::Separator(); struct funcs { - static void ShowDummyObject(const char* prefix, int uid) + static void ShowDummyObject(const char *prefix, int uid) { - ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. - ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. + ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. + ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add + // vertical spacing to make the tree lines equal high. bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); ImGui::NextColumn(); ImGui::AlignFirstTextHeightToWidgets(); @@ -2533,19 +2902,16 @@ static void ShowExampleAppPropertyEditor(bool* p_open) ImGui::NextColumn(); if (node_open) { - static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; + static float dummy_members[8] = {0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f}; for (int i = 0; i < 8; i++) { ImGui::PushID(i); // Use field index as identifier. - if (i < 2) - { - ShowDummyObject("Child", 424242); - } + if (i < 2) { ShowDummyObject("Child", 424242); } else { ImGui::AlignFirstTextHeightToWidgets(); // Here we use a Selectable (instead of Text) to highlight on hover - //ImGui::Text("Field_%d", i); + // ImGui::Text("Field_%d", i); char label[32]; sprintf(label, "Field_%d", i); ImGui::Bullet(); @@ -2578,27 +2944,33 @@ static void ShowExampleAppPropertyEditor(bool* p_open) } // Demonstrate/test rendering huge amount of text, and the incidence of clipping. -static void ShowExampleAppLongText(bool* p_open) +static void ShowExampleAppLongText(bool *p_open) { - ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin("Example: Long text display", p_open)) { ImGui::End(); return; } - static int test_type = 0; + static int test_type = 0; static ImGuiTextBuffer log; - static int lines = 0; + static int lines = 0; ImGui::Text("Printing unusually long amount of text."); - ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0"); + ImGui::Combo( + "Test type", &test_type, + "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0"); ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); - if (ImGui::Button("Clear")) { log.clear(); lines = 0; } + if (ImGui::Button("Clear")) + { + log.clear(); + lines = 0; + } ImGui::SameLine(); if (ImGui::Button("Add 1000 lines")) { for (int i = 0; i < 1000; i++) - log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i); + log.append("%i The quick brown fox jumps over the lazy dog\n", lines + i); lines += 1000; } ImGui::BeginChild("Log"); @@ -2609,19 +2981,19 @@ static void ShowExampleAppLongText(bool* p_open) ImGui::TextUnformatted(log.begin(), log.end()); break; case 1: - { - // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); - ImGuiListClipper clipper(lines); - while (clipper.Step()) - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); - ImGui::PopStyleVar(); - break; - } + { + // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); + ImGuiListClipper clipper(lines); + while (clipper.Step()) + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); + ImGui::PopStyleVar(); + break; + } case 2: // Multiple calls to Text(), not clipped (slow) - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); for (int i = 0; i < lines; i++) ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); ImGui::PopStyleVar(); @@ -2634,8 +3006,14 @@ static void ShowExampleAppLongText(bool* p_open) // End of Demo code #else -void ImGui::ShowTestWindow(bool*) {} -void ImGui::ShowUserGuide() {} -void ImGui::ShowStyleEditor(ImGuiStyle*) {} +void ImGui::ShowTestWindow(bool *) +{ +} +void ImGui::ShowUserGuide() +{ +} +void ImGui::ShowStyleEditor(ImGuiStyle *) +{ +} #endif diff --git a/source/main/gui/imgui/imgui_draw.cpp b/source/main/gui/imgui/imgui_draw.cpp index fa7cac529a..a6ede487d3 100644 --- a/source/main/gui/imgui/imgui_draw.cpp +++ b/source/main/gui/imgui/imgui_draw.cpp @@ -9,7 +9,7 @@ // - Default font data #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS #endif #include "imgui.h" @@ -17,36 +17,41 @@ #define IMGUI_DEFINE_PLACEMENT_NEW #include "imgui_internal.h" -#include // vsnprintf, sscanf, printf +#include // vsnprintf, sscanf, printf #if !defined(alloca) -#ifdef _WIN32 -#include // alloca -#elif (defined(__FreeBSD__) || defined(FreeBSD_kernel) || defined(__DragonFly__)) && !defined(__GLIBC__) -#include // alloca. FreeBSD uses stdlib.h unless GLIBC -#else -#include // alloca -#endif + #ifdef _WIN32 + #include // alloca + #elif (defined(__FreeBSD__) || defined(FreeBSD_kernel) || defined(__DragonFly__)) && !defined(__GLIBC__) + #include // alloca. FreeBSD uses stdlib.h unless GLIBC + #else + #include // alloca + #endif #endif #ifdef _MSC_VER -#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf + #pragma warning(disable : 4505) // unreferenced local function has been removed (stb stuff) + #pragma warning( \ + disable : 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen + #define snprintf _snprintf #endif #ifdef __clang__ -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. -#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // -#endif + #pragma clang diagnostic ignored \ + "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. + #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing + // and comparing against same constants ok. + #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // + // similar to above, not sure what the exact difference it. + #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // + #if __has_warning("-Wreserved-id-macro") + #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // + #endif #elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers + #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used + #pragma GCC diagnostic ignored \ + "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function + #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value + #pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers #endif //------------------------------------------------------------------------- @@ -63,50 +68,52 @@ namespace IMGUI_STB_NAMESPACE #endif #ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration + #pragma warning(push) + #pragma warning(disable : 4456) // declaration of 'xx' hides previous local declaration #endif #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wunused-function" -#pragma clang diagnostic ignored "-Wmissing-prototypes" + #pragma clang diagnostic push + #pragma clang diagnostic ignored \ + "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. + #pragma clang diagnostic ignored "-Wunused-function" + #pragma clang diagnostic ignored "-Wmissing-prototypes" #endif #ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored \ + "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] #endif -#define STBRP_ASSERT(x) IM_ASSERT(x) +#define STBRP_ASSERT(x) IM_ASSERT(x) #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION -#define STBRP_STATIC -#define STB_RECT_PACK_IMPLEMENTATION + #define STBRP_STATIC + #define STB_RECT_PACK_IMPLEMENTATION #endif #include "stb_rect_pack.h" -#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x)) -#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x)) -#define STBTT_assert(x) IM_ASSERT(x) +#define STBTT_malloc(x, u) ((void)(u), ImGui::MemAlloc(x)) +#define STBTT_free(x, u) ((void)(u), ImGui::MemFree(x)) +#define STBTT_assert(x) IM_ASSERT(x) #ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION -#define STBTT_STATIC -#define STB_TRUETYPE_IMPLEMENTATION + #define STBTT_STATIC + #define STB_TRUETYPE_IMPLEMENTATION #else -#define STBTT_DEF extern + #define STBTT_DEF extern #endif #include "stb_truetype.h" #ifdef __GNUC__ -#pragma GCC diagnostic pop + #pragma GCC diagnostic pop #endif #ifdef __clang__ -#pragma clang diagnostic pop + #pragma clang diagnostic pop #endif #ifdef _MSC_VER -#pragma warning (pop) + #pragma warning(pop) #endif #ifdef IMGUI_STB_NAMESPACE @@ -118,7 +125,8 @@ using namespace IMGUI_STB_NAMESPACE; // ImDrawList //----------------------------------------------------------------------------- -static const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift +static const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, + +8192.0f); // Large values that are easy to encode in a few bits+shift void ImDrawList::Clear() { @@ -126,13 +134,13 @@ void ImDrawList::Clear() IdxBuffer.resize(0); VtxBuffer.resize(0); _VtxCurrentIdx = 0; - _VtxWritePtr = NULL; - _IdxWritePtr = NULL; + _VtxWritePtr = NULL; + _IdxWritePtr = NULL; _ClipRectStack.resize(0); _TextureIdStack.resize(0); _Path.resize(0); _ChannelsCurrent = 0; - _ChannelsCount = 1; + _ChannelsCount = 1; // NB: Do not clear channels so our allocations are re-used after the first frame. } @@ -142,16 +150,17 @@ void ImDrawList::ClearFreeMemory() IdxBuffer.clear(); VtxBuffer.clear(); _VtxCurrentIdx = 0; - _VtxWritePtr = NULL; - _IdxWritePtr = NULL; + _VtxWritePtr = NULL; + _IdxWritePtr = NULL; _ClipRectStack.clear(); _TextureIdStack.clear(); _Path.clear(); _ChannelsCurrent = 0; - _ChannelsCount = 1; + _ChannelsCount = 1; for (int i = 0; i < _Channels.Size; i++) { - if (i == 0) memset(&_Channels[0], 0, sizeof(_Channels[0])); // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again + if (i == 0) + memset(&_Channels[0], 0, sizeof(_Channels[0])); // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again _Channels[i].CmdBuffer.clear(); _Channels[i].IdxBuffer.clear(); } @@ -159,49 +168,52 @@ void ImDrawList::ClearFreeMemory() } // Use macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug mode -#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : GNullClipRect) -#define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL) +#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size - 1] : GNullClipRect) +#define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size - 1] : NULL) void ImDrawList::AddDrawCmd() { ImDrawCmd draw_cmd; - draw_cmd.ClipRect = GetCurrentClipRect(); + draw_cmd.ClipRect = GetCurrentClipRect(); draw_cmd.TextureId = GetCurrentTextureId(); IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w); CmdBuffer.push_back(draw_cmd); } -void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) +void ImDrawList::AddCallback(ImDrawCallback callback, void *callback_data) { - ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL; + ImDrawCmd *current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL; if (!current_cmd || current_cmd->ElemCount != 0 || current_cmd->UserCallback != NULL) { AddDrawCmd(); current_cmd = &CmdBuffer.back(); } - current_cmd->UserCallback = callback; + current_cmd->UserCallback = callback; current_cmd->UserCallbackData = callback_data; AddDrawCmd(); // Force a new command after us (see comment below) } -// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack. -// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only. +// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any +// check so we always have a command ready in the stack. The cost of figuring out if a new command has to be added or if we can +// merge is paid in those Update** functions only. void ImDrawList::UpdateClipRect() { // If current command is used with different settings we need to add a new command const ImVec4 curr_clip_rect = GetCurrentClipRect(); - ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size-1] : NULL; - if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL) + ImDrawCmd * curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size - 1] : NULL; + if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || + curr_cmd->UserCallback != NULL) { AddDrawCmd(); return; } // Try to merge with previous command if it matches, else use current command - ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL; - if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL) + ImDrawCmd *prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL; + if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && + prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL) CmdBuffer.pop_back(); else curr_cmd->ClipRect = curr_clip_rect; @@ -211,7 +223,7 @@ void ImDrawList::UpdateTextureID() { // If current command is used with different settings we need to add a new command const ImTextureID curr_texture_id = GetCurrentTextureId(); - ImDrawCmd* curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL; + ImDrawCmd * curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL; if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL) { AddDrawCmd(); @@ -219,8 +231,9 @@ void ImDrawList::UpdateTextureID() } // Try to merge with previous command if it matches, else use current command - ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL; - if (prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL) + ImDrawCmd *prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL; + if (prev_cmd && prev_cmd->TextureId == curr_texture_id && + memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL) CmdBuffer.pop_back(); else curr_cmd->TextureId = curr_texture_id; @@ -229,13 +242,14 @@ void ImDrawList::UpdateTextureID() #undef GetCurrentClipRect #undef GetCurrentTextureId -// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) +// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using +// higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect) { ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y); if (intersect_with_current_clip_rect && _ClipRectStack.Size) { - ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size-1]; + ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size - 1]; if (cr.x < current.x) cr.x = current.x; if (cr.y < current.y) cr.y = current.y; if (cr.z > current.z) cr.z = current.z; @@ -251,7 +265,8 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_ void ImDrawList::PushClipRectFullScreen() { PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w)); - //PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here? + // PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext + // from here? } void ImDrawList::PopClipRect() @@ -261,7 +276,7 @@ void ImDrawList::PopClipRect() UpdateClipRect(); } -void ImDrawList::PushTextureID(const ImTextureID& texture_id) +void ImDrawList::PushTextureID(const ImTextureID &texture_id) { _TextureIdStack.push_back(texture_id); UpdateTextureID(); @@ -278,20 +293,17 @@ void ImDrawList::ChannelsSplit(int channels_count) { IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1); int old_channels_count = _Channels.Size; - if (old_channels_count < channels_count) - _Channels.resize(channels_count); + if (old_channels_count < channels_count) _Channels.resize(channels_count); _ChannelsCount = channels_count; // _Channels[] (24 bytes each) hold storage that we'll swap with this->_CmdBuffer/_IdxBuffer - // The content of _Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to. - // When we switch to the next channel, we'll copy _CmdBuffer/_IdxBuffer into _Channels[0] and then _Channels[1] into _CmdBuffer/_IdxBuffer + // The content of _Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't + // strictly need to. When we switch to the next channel, we'll copy _CmdBuffer/_IdxBuffer into _Channels[0] and then + // _Channels[1] into _CmdBuffer/_IdxBuffer memset(&_Channels[0], 0, sizeof(ImDrawChannel)); for (int i = 1; i < channels_count; i++) { - if (i >= old_channels_count) - { - IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel(); - } + if (i >= old_channels_count) { IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel(); } else { _Channels[i].CmdBuffer.resize(0); @@ -300,7 +312,7 @@ void ImDrawList::ChannelsSplit(int channels_count) if (_Channels[i].CmdBuffer.Size == 0) { ImDrawCmd draw_cmd; - draw_cmd.ClipRect = _ClipRectStack.back(); + draw_cmd.ClipRect = _ClipRectStack.back(); draw_cmd.TextureId = _TextureIdStack.back(); _Channels[i].CmdBuffer.push_back(draw_cmd); } @@ -309,33 +321,39 @@ void ImDrawList::ChannelsSplit(int channels_count) void ImDrawList::ChannelsMerge() { - // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use. - if (_ChannelsCount <= 1) - return; + // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all + // sub-buffers ready for use. + if (_ChannelsCount <= 1) return; ChannelsSetCurrent(0); - if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0) - CmdBuffer.pop_back(); + if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0) CmdBuffer.pop_back(); int new_cmd_buffer_count = 0, new_idx_buffer_count = 0; for (int i = 1; i < _ChannelsCount; i++) { - ImDrawChannel& ch = _Channels[i]; - if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0) - ch.CmdBuffer.pop_back(); + ImDrawChannel &ch = _Channels[i]; + if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0) ch.CmdBuffer.pop_back(); new_cmd_buffer_count += ch.CmdBuffer.Size; new_idx_buffer_count += ch.IdxBuffer.Size; } CmdBuffer.resize(CmdBuffer.Size + new_cmd_buffer_count); IdxBuffer.resize(IdxBuffer.Size + new_idx_buffer_count); - ImDrawCmd* cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count; - _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count; + ImDrawCmd *cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count; + _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count; for (int i = 1; i < _ChannelsCount; i++) { - ImDrawChannel& ch = _Channels[i]; - if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } - if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; } + ImDrawChannel &ch = _Channels[i]; + if (int sz = ch.CmdBuffer.Size) + { + memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); + cmd_write += sz; + } + if (int sz = ch.IdxBuffer.Size) + { + memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); + _IdxWritePtr += sz; + } } AddDrawCmd(); _ChannelsCount = 1; @@ -356,7 +374,7 @@ void ImDrawList::ChannelsSetCurrent(int idx) // NB: this can be called with negative count for removing primitives (as long as the result does not underflow) void ImDrawList::PrimReserve(int idx_count, int vtx_count) { - ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1]; + ImDrawCmd &draw_cmd = CmdBuffer.Data[CmdBuffer.Size - 1]; draw_cmd.ElemCount += idx_count; int vtx_buffer_size = VtxBuffer.Size; @@ -369,110 +387,145 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) } // Fully unrolled with inline call to keep our debug builds decently fast. -void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) -{ - ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel); - ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; - _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); - _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; +void ImDrawList::PrimRect(const ImVec2 &a, const ImVec2 &c, ImU32 col) +{ + ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel); + ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; + _IdxWritePtr[0] = idx; + _IdxWritePtr[1] = (ImDrawIdx)(idx + 1); + _IdxWritePtr[2] = (ImDrawIdx)(idx + 2); + _IdxWritePtr[3] = idx; + _IdxWritePtr[4] = (ImDrawIdx)(idx + 2); + _IdxWritePtr[5] = (ImDrawIdx)(idx + 3); + _VtxWritePtr[0].pos = a; + _VtxWritePtr[0].uv = uv; + _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos = b; + _VtxWritePtr[1].uv = uv; + _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos = c; + _VtxWritePtr[2].uv = uv; + _VtxWritePtr[2].col = col; + _VtxWritePtr[3].pos = d; + _VtxWritePtr[3].uv = uv; + _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; _IdxWritePtr += 6; } -void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col) -{ - ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y); - ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; - _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); - _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; +void ImDrawList::PrimRectUV(const ImVec2 &a, const ImVec2 &c, const ImVec2 &uv_a, const ImVec2 &uv_c, ImU32 col) +{ + ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y); + ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; + _IdxWritePtr[0] = idx; + _IdxWritePtr[1] = (ImDrawIdx)(idx + 1); + _IdxWritePtr[2] = (ImDrawIdx)(idx + 2); + _IdxWritePtr[3] = idx; + _IdxWritePtr[4] = (ImDrawIdx)(idx + 2); + _IdxWritePtr[5] = (ImDrawIdx)(idx + 3); + _VtxWritePtr[0].pos = a; + _VtxWritePtr[0].uv = uv_a; + _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos = b; + _VtxWritePtr[1].uv = uv_b; + _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos = c; + _VtxWritePtr[2].uv = uv_c; + _VtxWritePtr[2].col = col; + _VtxWritePtr[3].pos = d; + _VtxWritePtr[3].uv = uv_d; + _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; _IdxWritePtr += 6; } -void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col) -{ - ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; - _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); - _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; +void ImDrawList::PrimQuadUV(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, const ImVec2 &uv_a, + const ImVec2 &uv_b, const ImVec2 &uv_c, const ImVec2 &uv_d, ImU32 col) +{ + ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; + _IdxWritePtr[0] = idx; + _IdxWritePtr[1] = (ImDrawIdx)(idx + 1); + _IdxWritePtr[2] = (ImDrawIdx)(idx + 2); + _IdxWritePtr[3] = idx; + _IdxWritePtr[4] = (ImDrawIdx)(idx + 2); + _IdxWritePtr[5] = (ImDrawIdx)(idx + 3); + _VtxWritePtr[0].pos = a; + _VtxWritePtr[0].uv = uv_a; + _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos = b; + _VtxWritePtr[1].uv = uv_b; + _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos = c; + _VtxWritePtr[2].uv = uv_c; + _VtxWritePtr[2].col = col; + _VtxWritePtr[3].pos = d; + _VtxWritePtr[3].uv = uv_d; + _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; _IdxWritePtr += 6; } // TODO: Thickness anti-aliased lines cap are missing their AA fringe. -void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness, bool anti_aliased) +void ImDrawList::AddPolyline(const ImVec2 *points, const int points_count, ImU32 col, bool closed, float thickness, + bool anti_aliased) { - if (points_count < 2) - return; + if (points_count < 2) return; const ImVec2 uv = GImGui->FontTexUvWhitePixel; anti_aliased &= GImGui->Style.AntiAliasedLines; - //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug + // if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug int count = points_count; - if (!closed) - count = points_count-1; + if (!closed) count = points_count - 1; const bool thick_line = thickness > 1.0f; if (anti_aliased) { // Anti-aliased stroke - const float AA_SIZE = 1.0f; - const ImU32 col_trans = col & IM_COL32(255,255,255,0); + const float AA_SIZE = 1.0f; + const ImU32 col_trans = col & IM_COL32(255, 255, 255, 0); - const int idx_count = thick_line ? count*18 : count*12; - const int vtx_count = thick_line ? points_count*4 : points_count*3; + const int idx_count = thick_line ? count * 18 : count * 12; + const int vtx_count = thick_line ? points_count * 4 : points_count * 3; PrimReserve(idx_count, vtx_count); // Temporary buffer - ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2)); - ImVec2* temp_points = temp_normals + points_count; + ImVec2 *temp_normals = (ImVec2 *)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2)); + ImVec2 *temp_points = temp_normals + points_count; for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; - ImVec2 diff = points[i2] - points[i1]; + const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; + ImVec2 diff = points[i2] - points[i1]; diff *= ImInvLength(diff, 1.0f); temp_normals[i1].x = diff.y; temp_normals[i1].y = -diff.x; } - if (!closed) - temp_normals[points_count-1] = temp_normals[points_count-2]; + if (!closed) temp_normals[points_count - 1] = temp_normals[points_count - 2]; if (!thick_line) { if (!closed) { - temp_points[0] = points[0] + temp_normals[0] * AA_SIZE; - temp_points[1] = points[0] - temp_normals[0] * AA_SIZE; - temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * AA_SIZE; - temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE; + temp_points[0] = points[0] + temp_normals[0] * AA_SIZE; + temp_points[1] = points[0] - temp_normals[0] * AA_SIZE; + temp_points[(points_count - 1) * 2 + 0] = points[points_count - 1] + temp_normals[points_count - 1] * AA_SIZE; + temp_points[(points_count - 1) * 2 + 1] = points[points_count - 1] - temp_normals[points_count - 1] * AA_SIZE; } // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. unsigned int idx1 = _VtxCurrentIdx; for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; - unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+3; + const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; + unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 3; // Average normals - ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f; - float dmr2 = dm.x*dm.x + dm.y*dm.y; + ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f; + float dmr2 = dm.x * dm.x + dm.y * dm.y; if (dmr2 > 0.000001f) { float scale = 1.0f / dmr2; @@ -480,14 +533,22 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 dm *= scale; } dm *= AA_SIZE; - temp_points[i2*2+0] = points[i2] + dm; - temp_points[i2*2+1] = points[i2] - dm; + temp_points[i2 * 2 + 0] = points[i2] + dm; + temp_points[i2 * 2 + 1] = points[i2] - dm; // Add indexes - _IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2); - _IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0); - _IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0); - _IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10]= (ImDrawIdx)(idx2+0); _IdxWritePtr[11]= (ImDrawIdx)(idx2+1); + _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); + _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); + _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); + _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); + _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); + _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); + _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); + _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); + _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); + _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); + _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); + _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr += 12; idx1 = idx2; @@ -496,9 +557,15 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 // Add vertexes for (int i = 0; i < points_count; i++) { - _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; - _VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col_trans; + _VtxWritePtr[0].pos = points[i]; + _VtxWritePtr[0].uv = uv; + _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos = temp_points[i * 2 + 0]; + _VtxWritePtr[1].uv = uv; + _VtxWritePtr[1].col = col_trans; + _VtxWritePtr[2].pos = temp_points[i * 2 + 1]; + _VtxWritePtr[2].uv = uv; + _VtxWritePtr[2].col = col_trans; _VtxWritePtr += 3; } } @@ -511,42 +578,58 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness); temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness); temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE); - temp_points[(points_count-1)*4+0] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE); - temp_points[(points_count-1)*4+1] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness); - temp_points[(points_count-1)*4+2] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness); - temp_points[(points_count-1)*4+3] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE); + temp_points[(points_count - 1) * 4 + 0] = + points[points_count - 1] + temp_normals[points_count - 1] * (half_inner_thickness + AA_SIZE); + temp_points[(points_count - 1) * 4 + 1] = + points[points_count - 1] + temp_normals[points_count - 1] * (half_inner_thickness); + temp_points[(points_count - 1) * 4 + 2] = + points[points_count - 1] - temp_normals[points_count - 1] * (half_inner_thickness); + temp_points[(points_count - 1) * 4 + 3] = + points[points_count - 1] - temp_normals[points_count - 1] * (half_inner_thickness + AA_SIZE); } // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. unsigned int idx1 = _VtxCurrentIdx; for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; - unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+4; + const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; + unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 4; // Average normals - ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f; - float dmr2 = dm.x*dm.x + dm.y*dm.y; + ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f; + float dmr2 = dm.x * dm.x + dm.y * dm.y; if (dmr2 > 0.000001f) { float scale = 1.0f / dmr2; if (scale > 100.0f) scale = 100.0f; dm *= scale; } - ImVec2 dm_out = dm * (half_inner_thickness + AA_SIZE); - ImVec2 dm_in = dm * half_inner_thickness; - temp_points[i2*4+0] = points[i2] + dm_out; - temp_points[i2*4+1] = points[i2] + dm_in; - temp_points[i2*4+2] = points[i2] - dm_in; - temp_points[i2*4+3] = points[i2] - dm_out; + ImVec2 dm_out = dm * (half_inner_thickness + AA_SIZE); + ImVec2 dm_in = dm * half_inner_thickness; + temp_points[i2 * 4 + 0] = points[i2] + dm_out; + temp_points[i2 * 4 + 1] = points[i2] + dm_in; + temp_points[i2 * 4 + 2] = points[i2] - dm_in; + temp_points[i2 * 4 + 3] = points[i2] - dm_out; // Add indexes - _IdxWritePtr[0] = (ImDrawIdx)(idx2+1); _IdxWritePtr[1] = (ImDrawIdx)(idx1+1); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2); - _IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+1); - _IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0); - _IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10] = (ImDrawIdx)(idx2+0); _IdxWritePtr[11] = (ImDrawIdx)(idx2+1); - _IdxWritePtr[12] = (ImDrawIdx)(idx2+2); _IdxWritePtr[13] = (ImDrawIdx)(idx1+2); _IdxWritePtr[14] = (ImDrawIdx)(idx1+3); - _IdxWritePtr[15] = (ImDrawIdx)(idx1+3); _IdxWritePtr[16] = (ImDrawIdx)(idx2+3); _IdxWritePtr[17] = (ImDrawIdx)(idx2+2); + _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 1); + _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 1); + _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); + _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); + _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); + _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 1); + _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); + _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); + _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); + _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); + _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); + _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); + _IdxWritePtr[12] = (ImDrawIdx)(idx2 + 2); + _IdxWritePtr[13] = (ImDrawIdx)(idx1 + 2); + _IdxWritePtr[14] = (ImDrawIdx)(idx1 + 3); + _IdxWritePtr[15] = (ImDrawIdx)(idx1 + 3); + _IdxWritePtr[16] = (ImDrawIdx)(idx2 + 3); + _IdxWritePtr[17] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr += 18; idx1 = idx2; @@ -555,10 +638,18 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 // Add vertexes for (int i = 0; i < points_count; i++) { - _VtxWritePtr[0].pos = temp_points[i*4+0]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col_trans; - _VtxWritePtr[1].pos = temp_points[i*4+1]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = temp_points[i*4+2]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = temp_points[i*4+3]; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col_trans; + _VtxWritePtr[0].pos = temp_points[i * 4 + 0]; + _VtxWritePtr[0].uv = uv; + _VtxWritePtr[0].col = col_trans; + _VtxWritePtr[1].pos = temp_points[i * 4 + 1]; + _VtxWritePtr[1].uv = uv; + _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos = temp_points[i * 4 + 2]; + _VtxWritePtr[2].uv = uv; + _VtxWritePtr[2].col = col; + _VtxWritePtr[3].pos = temp_points[i * 4 + 3]; + _VtxWritePtr[3].uv = uv; + _VtxWritePtr[3].col = col_trans; _VtxWritePtr += 4; } } @@ -567,77 +658,95 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 else { // Non Anti-aliased Stroke - const int idx_count = count*6; - const int vtx_count = count*4; // FIXME-OPT: Not sharing edges + const int idx_count = count * 6; + const int vtx_count = count * 4; // FIXME-OPT: Not sharing edges PrimReserve(idx_count, vtx_count); for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; - const ImVec2& p1 = points[i1]; - const ImVec2& p2 = points[i2]; - ImVec2 diff = p2 - p1; + const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; + const ImVec2 &p1 = points[i1]; + const ImVec2 &p2 = points[i2]; + ImVec2 diff = p2 - p1; diff *= ImInvLength(diff, 1.0f); - const float dx = diff.x * (thickness * 0.5f); - const float dy = diff.y * (thickness * 0.5f); - _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; + const float dx = diff.x * (thickness * 0.5f); + const float dy = diff.y * (thickness * 0.5f); + _VtxWritePtr[0].pos.x = p1.x + dy; + _VtxWritePtr[0].pos.y = p1.y - dx; + _VtxWritePtr[0].uv = uv; + _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos.x = p2.x + dy; + _VtxWritePtr[1].pos.y = p2.y - dx; + _VtxWritePtr[1].uv = uv; + _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos.x = p2.x - dy; + _VtxWritePtr[2].pos.y = p2.y + dx; + _VtxWritePtr[2].uv = uv; + _VtxWritePtr[2].col = col; + _VtxWritePtr[3].pos.x = p1.x - dy; + _VtxWritePtr[3].pos.y = p1.y + dx; + _VtxWritePtr[3].uv = uv; + _VtxWritePtr[3].col = col; _VtxWritePtr += 4; - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); - _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); + _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); + _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2); + _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); + _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2); + _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3); _IdxWritePtr += 6; _VtxCurrentIdx += 4; } } } -void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased) +void ImDrawList::AddConvexPolyFilled(const ImVec2 *points, const int points_count, ImU32 col, bool anti_aliased) { const ImVec2 uv = GImGui->FontTexUvWhitePixel; anti_aliased &= GImGui->Style.AntiAliasedShapes; - //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug + // if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug if (anti_aliased) { // Anti-aliased Fill - const float AA_SIZE = 1.0f; - const ImU32 col_trans = col & IM_COL32(255,255,255,0); - const int idx_count = (points_count-2)*3 + points_count*6; - const int vtx_count = (points_count*2); + const float AA_SIZE = 1.0f; + const ImU32 col_trans = col & IM_COL32(255, 255, 255, 0); + const int idx_count = (points_count - 2) * 3 + points_count * 6; + const int vtx_count = (points_count * 2); PrimReserve(idx_count, vtx_count); // Add indexes for fill unsigned int vtx_inner_idx = _VtxCurrentIdx; - unsigned int vtx_outer_idx = _VtxCurrentIdx+1; + unsigned int vtx_outer_idx = _VtxCurrentIdx + 1; for (int i = 2; i < points_count; i++) { - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+((i-1)<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx+(i<<1)); + _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); + _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + ((i - 1) << 1)); + _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (i << 1)); _IdxWritePtr += 3; } // Compute normals - ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); - for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) + ImVec2 *temp_normals = (ImVec2 *)alloca(points_count * sizeof(ImVec2)); + for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) { - const ImVec2& p0 = points[i0]; - const ImVec2& p1 = points[i1]; - ImVec2 diff = p1 - p0; + const ImVec2 &p0 = points[i0]; + const ImVec2 &p1 = points[i1]; + ImVec2 diff = p1 - p0; diff *= ImInvLength(diff, 1.0f); temp_normals[i0].x = diff.y; temp_normals[i0].y = -diff.x; } - for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) + for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) { // Average normals - const ImVec2& n0 = temp_normals[i0]; - const ImVec2& n1 = temp_normals[i1]; - ImVec2 dm = (n0 + n1) * 0.5f; - float dmr2 = dm.x*dm.x + dm.y*dm.y; + const ImVec2 &n0 = temp_normals[i0]; + const ImVec2 &n1 = temp_normals[i1]; + ImVec2 dm = (n0 + n1) * 0.5f; + float dmr2 = dm.x * dm.x + dm.y * dm.y; if (dmr2 > 0.000001f) { float scale = 1.0f / dmr2; @@ -647,13 +756,21 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun dm *= AA_SIZE * 0.5f; // Add vertices - _VtxWritePtr[0].pos = (points[i1] - dm); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner - _VtxWritePtr[1].pos = (points[i1] + dm); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer + _VtxWritePtr[0].pos = (points[i1] - dm); + _VtxWritePtr[0].uv = uv; + _VtxWritePtr[0].col = col; // Inner + _VtxWritePtr[1].pos = (points[i1] + dm); + _VtxWritePtr[1].uv = uv; + _VtxWritePtr[1].col = col_trans; // Outer _VtxWritePtr += 2; // Add indexes for fringes - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+(i0<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); - _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx+(i1<<1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); + _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); + _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); + _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); + _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); + _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); + _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr += 6; } _VtxCurrentIdx += (ImDrawIdx)vtx_count; @@ -661,33 +778,37 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun else { // Non Anti-aliased Fill - const int idx_count = (points_count-2)*3; + const int idx_count = (points_count - 2) * 3; const int vtx_count = points_count; PrimReserve(idx_count, vtx_count); for (int i = 0; i < vtx_count; i++) { - _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; + _VtxWritePtr[0].pos = points[i]; + _VtxWritePtr[0].uv = uv; + _VtxWritePtr[0].col = col; _VtxWritePtr++; } for (int i = 2; i < points_count; i++) { - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i); + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); + _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + i - 1); + _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + i); _IdxWritePtr += 3; } _VtxCurrentIdx += (ImDrawIdx)vtx_count; } } -void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int amin, int amax) +void ImDrawList::PathArcToFast(const ImVec2 ¢re, float radius, int amin, int amax) { static ImVec2 circle_vtx[12]; - static bool circle_vtx_builds = false; - const int circle_vtx_count = IM_ARRAYSIZE(circle_vtx); + static bool circle_vtx_builds = false; + const int circle_vtx_count = IM_ARRAYSIZE(circle_vtx); if (!circle_vtx_builds) { for (int i = 0; i < circle_vtx_count; i++) { - const float a = ((float)i / (float)circle_vtx_count) * 2*IM_PI; + const float a = ((float)i / (float)circle_vtx_count) * 2 * IM_PI; circle_vtx[i].x = cosf(a); circle_vtx[i].y = sinf(a); } @@ -695,25 +816,21 @@ void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int amin, int } if (amin > amax) return; - if (radius == 0.0f) - { - _Path.push_back(centre); - } + if (radius == 0.0f) { _Path.push_back(centre); } else { _Path.reserve(_Path.Size + (amax - amin + 1)); for (int a = amin; a <= amax; a++) { - const ImVec2& c = circle_vtx[a % circle_vtx_count]; + const ImVec2 &c = circle_vtx[a % circle_vtx_count]; _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); } } } -void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float amax, int num_segments) +void ImDrawList::PathArcTo(const ImVec2 ¢re, float radius, float amin, float amax, int num_segments) { - if (radius == 0.0f) - _Path.push_back(centre); + if (radius == 0.0f) _Path.push_back(centre); _Path.reserve(_Path.Size + (num_segments + 1)); for (int i = 0; i <= num_segments; i++) { @@ -722,33 +839,31 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float } } -static void PathBezierToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) +static void PathBezierToCasteljau(ImVector *path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, + float y4, float tess_tol, int level) { float dx = x4 - x1; float dy = y4 - y1; float d2 = ((x2 - x4) * dy - (y2 - y4) * dx); float d3 = ((x3 - x4) * dy - (y3 - y4) * dx); - d2 = (d2 >= 0) ? d2 : -d2; - d3 = (d3 >= 0) ? d3 : -d3; - if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy)) - { - path->push_back(ImVec2(x4, y4)); - } + d2 = (d2 >= 0) ? d2 : -d2; + d3 = (d3 >= 0) ? d3 : -d3; + if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy)) { path->push_back(ImVec2(x4, y4)); } else if (level < 10) { - float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f; - float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f; - float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f; - float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f; - float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f; - float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f; - - PathBezierToCasteljau(path, x1,y1, x12,y12, x123,y123, x1234,y1234, tess_tol, level+1); - PathBezierToCasteljau(path, x1234,y1234, x234,y234, x34,y34, x4,y4, tess_tol, level+1); + float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f; + float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f; + float x34 = (x3 + x4) * 0.5f, y34 = (y3 + y4) * 0.5f; + float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f; + float x234 = (x23 + x34) * 0.5f, y234 = (y23 + y34) * 0.5f; + float x1234 = (x123 + x234) * 0.5f, y1234 = (y123 + y234) * 0.5f; + + PathBezierToCasteljau(path, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1); + PathBezierToCasteljau(path, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1); } } -void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments) +void ImDrawList::PathBezierCurveTo(const ImVec2 &p2, const ImVec2 &p3, const ImVec2 &p4, int num_segments) { ImVec2 p1 = _Path.back(); if (num_segments == 0) @@ -761,29 +876,33 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV float t_step = 1.0f / (float)num_segments; for (int i_step = 1; i_step <= num_segments; i_step++) { - float t = t_step * i_step; - float u = 1.0f - t; - float w1 = u*u*u; - float w2 = 3*u*u*t; - float w3 = 3*u*t*t; - float w4 = t*t*t; - _Path.push_back(ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y)); + float t = t_step * i_step; + float u = 1.0f - t; + float w1 = u * u * u; + float w2 = 3 * u * u * t; + float w3 = 3 * u * t * t; + float w4 = t * t * t; + _Path.push_back(ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x, w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y)); } } } -void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners) +void ImDrawList::PathRect(const ImVec2 &a, const ImVec2 &b, float rounding, int rounding_corners) { float r = rounding; - r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ) - 1.0f); - r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ) - 1.0f); + r = ImMin(r, fabsf(b.x - a.x) * + (((rounding_corners & (1 | 2)) == (1 | 2)) || ((rounding_corners & (4 | 8)) == (4 | 8)) ? 0.5f : 1.0f) - + 1.0f); + r = ImMin(r, fabsf(b.y - a.y) * + (((rounding_corners & (1 | 8)) == (1 | 8)) || ((rounding_corners & (2 | 4)) == (2 | 4)) ? 0.5f : 1.0f) - + 1.0f); if (r <= 0.0f || rounding_corners == 0) { PathLineTo(a); - PathLineTo(ImVec2(b.x,a.y)); + PathLineTo(ImVec2(b.x, a.y)); PathLineTo(b); - PathLineTo(ImVec2(a.x,b.y)); + PathLineTo(ImVec2(a.x, b.y)); } else { @@ -791,35 +910,32 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int const float r1 = (rounding_corners & 2) ? r : 0.0f; const float r2 = (rounding_corners & 4) ? r : 0.0f; const float r3 = (rounding_corners & 8) ? r : 0.0f; - PathArcToFast(ImVec2(a.x+r0,a.y+r0), r0, 6, 9); - PathArcToFast(ImVec2(b.x-r1,a.y+r1), r1, 9, 12); - PathArcToFast(ImVec2(b.x-r2,b.y-r2), r2, 0, 3); - PathArcToFast(ImVec2(a.x+r3,b.y-r3), r3, 3, 6); + PathArcToFast(ImVec2(a.x + r0, a.y + r0), r0, 6, 9); + PathArcToFast(ImVec2(b.x - r1, a.y + r1), r1, 9, 12); + PathArcToFast(ImVec2(b.x - r2, b.y - r2), r2, 0, 3); + PathArcToFast(ImVec2(a.x + r3, b.y - r3), r3, 3, 6); } } -void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness) +void ImDrawList::AddLine(const ImVec2 &a, const ImVec2 &b, ImU32 col, float thickness) { - if ((col & IM_COL32_A_MASK) == 0) - return; - PathLineTo(a + ImVec2(0.5f,0.5f)); - PathLineTo(b + ImVec2(0.5f,0.5f)); + if ((col & IM_COL32_A_MASK) == 0) return; + PathLineTo(a + ImVec2(0.5f, 0.5f)); + PathLineTo(b + ImVec2(0.5f, 0.5f)); PathStroke(col, false, thickness); } // a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly. -void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness) +void ImDrawList::AddRect(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding, int rounding_corners_flags, float thickness) { - if ((col & IM_COL32_A_MASK) == 0) - return; - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners_flags); + if ((col & IM_COL32_A_MASK) == 0) return; + PathRect(a + ImVec2(0.5f, 0.5f), b - ImVec2(0.5f, 0.5f), rounding, rounding_corners_flags); PathStroke(col, true, thickness); } -void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags) +void ImDrawList::AddRectFilled(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding, int rounding_corners_flags) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; if (rounding > 0.0f) { PathRect(a, b, rounding, rounding_corners_flags); @@ -832,25 +948,28 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa } } -void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left) +void ImDrawList::AddRectFilledMultiColor(const ImVec2 &a, const ImVec2 &c, ImU32 col_upr_left, ImU32 col_upr_right, + ImU32 col_bot_right, ImU32 col_bot_left) { - if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) - return; + if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) return; const ImVec2 uv = GImGui->FontTexUvWhitePixel; PrimReserve(6, 4); - PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); - PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3)); + PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); + PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1)); + PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); + PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); + PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); + PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3)); PrimWriteVtx(a, uv, col_upr_left); PrimWriteVtx(ImVec2(c.x, a.y), uv, col_upr_right); PrimWriteVtx(c, uv, col_bot_right); PrimWriteVtx(ImVec2(a.x, c.y), uv, col_bot_left); } -void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness) +void ImDrawList::AddQuad(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, ImU32 col, float thickness) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(a); PathLineTo(b); @@ -859,10 +978,9 @@ void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, cons PathStroke(col, true, thickness); } -void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col) +void ImDrawList::AddQuadFilled(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, ImU32 col) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(a); PathLineTo(b); @@ -871,10 +989,9 @@ void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c PathFillConvex(col); } -void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness) +void ImDrawList::AddTriangle(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col, float thickness) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(a); PathLineTo(b); @@ -882,10 +999,9 @@ void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, PathStroke(col, true, thickness); } -void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col) +void ImDrawList::AddTriangleFilled(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(a); PathLineTo(b); @@ -893,54 +1009,50 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec PathFillConvex(col); } -void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness) +void ImDrawList::AddCircle(const ImVec2 ¢re, float radius, ImU32 col, int num_segments, float thickness) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; - const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments); + const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments; + PathArcTo(centre, radius - 0.5f, 0.0f, a_max, num_segments); PathStroke(col, true, thickness); } -void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments) +void ImDrawList::AddCircleFilled(const ImVec2 ¢re, float radius, ImU32 col, int num_segments) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; - const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; + const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(centre, radius, 0.0f, a_max, num_segments); PathFillConvex(col); } -void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments) +void ImDrawList::AddBezierCurve(const ImVec2 &pos0, const ImVec2 &cp0, const ImVec2 &cp1, const ImVec2 &pos1, ImU32 col, + float thickness, int num_segments) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(pos0); PathBezierCurveTo(cp0, cp1, pos1, num_segments); PathStroke(col, false, thickness); } -void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) +void ImDrawList::AddText(const ImFont *font, float font_size, const ImVec2 &pos, ImU32 col, const char *text_begin, + const char *text_end, float wrap_width, const ImVec4 *cpu_fine_clip_rect) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; - if (text_end == NULL) - text_end = text_begin + strlen(text_begin); - if (text_begin == text_end) - return; + if (text_end == NULL) text_end = text_begin + strlen(text_begin); + if (text_begin == text_end) return; - // Note: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it is just SO useful. - // Might just move Font/FontSize to ImDrawList? - if (font == NULL) - font = GImGui->Font; - if (font_size == 0.0f) - font_size = GImGui->FontSize; + // Note: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it + // is just SO useful. Might just move Font/FontSize to ImDrawList? + if (font == NULL) font = GImGui->Font; + if (font_size == 0.0f) font_size = GImGui->FontSize; - IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. + IM_ASSERT( + font->ContainerAtlas->TexID == + _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. ImVec4 clip_rect = _ClipRectStack.back(); if (cpu_fine_clip_rect) @@ -953,58 +1065,54 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL); } -void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) +void ImDrawList::AddText(const ImVec2 &pos, ImU32 col, const char *text_begin, const char *text_end) { AddText(GImGui->Font, GImGui->FontSize, pos, col, text_begin, text_end); } -void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col) +void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2 &a, const ImVec2 &b, const ImVec2 &uv_a, const ImVec2 &uv_b, + ImU32 col) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; // FIXME-OPT: This is wasting draw calls. const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back(); - if (push_texture_id) - PushTextureID(user_texture_id); + if (push_texture_id) PushTextureID(user_texture_id); PrimReserve(6, 4); PrimRectUV(a, b, uv_a, uv_b, col); - if (push_texture_id) - PopTextureID(); + if (push_texture_id) PopTextureID(); } -void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col) +void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &d, + const ImVec2 &uv_a, const ImVec2 &uv_b, const ImVec2 &uv_c, const ImVec2 &uv_d, ImU32 col) { - if ((col & IM_COL32_A_MASK) == 0) - return; + if ((col & IM_COL32_A_MASK) == 0) return; const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back(); - if (push_texture_id) - PushTextureID(user_texture_id); + if (push_texture_id) PushTextureID(user_texture_id); PrimReserve(6, 4); PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col); - if (push_texture_id) - PopTextureID(); + if (push_texture_id) PopTextureID(); } //----------------------------------------------------------------------------- // ImDrawData //----------------------------------------------------------------------------- -// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! +// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is +// slow and most likely a waste of resources. Always prefer indexed rendering! void ImDrawData::DeIndexAllBuffers() { ImVector new_vtx_buffer; TotalVtxCount = TotalIdxCount = 0; for (int i = 0; i < CmdListsCount; i++) { - ImDrawList* cmd_list = CmdLists[i]; - if (cmd_list->IdxBuffer.empty()) - continue; + ImDrawList *cmd_list = CmdLists[i]; + if (cmd_list->IdxBuffer.empty()) continue; new_vtx_buffer.resize(cmd_list->IdxBuffer.Size); for (int j = 0; j < cmd_list->IdxBuffer.Size; j++) new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]]; @@ -1014,16 +1122,18 @@ void ImDrawData::DeIndexAllBuffers() } } -// Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. -void ImDrawData::ScaleClipRects(const ImVec2& scale) +// Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui +// expects, or if there is a difference between your window resolution and framebuffer resolution. +void ImDrawData::ScaleClipRects(const ImVec2 &scale) { for (int i = 0; i < CmdListsCount; i++) { - ImDrawList* cmd_list = CmdLists[i]; + ImDrawList *cmd_list = CmdLists[i]; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { - ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i]; - cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, cmd->ClipRect.w * scale.y); + ImDrawCmd *cmd = &cmd_list->CmdBuffer[cmd_i]; + cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, + cmd->ClipRect.w * scale.y); } } } @@ -1034,29 +1144,29 @@ void ImDrawData::ScaleClipRects(const ImVec2& scale) ImFontConfig::ImFontConfig() { - FontData = NULL; - FontDataSize = 0; + FontData = NULL; + FontDataSize = 0; FontDataOwnedByAtlas = true; - FontNo = 0; - SizePixels = 0.0f; - OversampleH = 3; - OversampleV = 1; - PixelSnapH = false; - GlyphExtraSpacing = ImVec2(0.0f, 0.0f); - GlyphRanges = NULL; - MergeMode = false; - MergeGlyphCenterV = false; - DstFont = NULL; + FontNo = 0; + SizePixels = 0.0f; + OversampleH = 3; + OversampleV = 1; + PixelSnapH = false; + GlyphExtraSpacing = ImVec2(0.0f, 0.0f); + GlyphRanges = NULL; + MergeMode = false; + MergeGlyphCenterV = false; + DstFont = NULL; memset(Name, 0, sizeof(Name)); } ImFontAtlas::ImFontAtlas() { - TexID = NULL; + TexID = NULL; TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; TexWidth = TexHeight = TexDesiredWidth = 0; - TexUvWhitePixel = ImVec2(0, 0); + TexUvWhitePixel = ImVec2(0, 0); } ImFontAtlas::~ImFontAtlas() @@ -1064,7 +1174,7 @@ ImFontAtlas::~ImFontAtlas() Clear(); } -void ImFontAtlas::ClearInputData() +void ImFontAtlas::ClearInputData() { for (int i = 0; i < ConfigData.Size; i++) if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas) @@ -1077,23 +1187,21 @@ void ImFontAtlas::ClearInputData() for (int i = 0; i < Fonts.Size; i++) if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size) { - Fonts[i]->ConfigData = NULL; + Fonts[i]->ConfigData = NULL; Fonts[i]->ConfigDataCount = 0; } ConfigData.clear(); } -void ImFontAtlas::ClearTexData() +void ImFontAtlas::ClearTexData() { - if (TexPixelsAlpha8) - ImGui::MemFree(TexPixelsAlpha8); - if (TexPixelsRGBA32) - ImGui::MemFree(TexPixelsRGBA32); + if (TexPixelsAlpha8) ImGui::MemFree(TexPixelsAlpha8); + if (TexPixelsRGBA32) ImGui::MemFree(TexPixelsRGBA32); TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; } -void ImFontAtlas::ClearFonts() +void ImFontAtlas::ClearFonts() { for (int i = 0; i < Fonts.Size; i++) { @@ -1103,20 +1211,19 @@ void ImFontAtlas::ClearFonts() Fonts.clear(); } -void ImFontAtlas::Clear() +void ImFontAtlas::Clear() { ClearInputData(); ClearTexData(); ClearFonts(); } -void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) +void ImFontAtlas::GetTexDataAsAlpha8(unsigned char **out_pixels, int *out_width, int *out_height, int *out_bytes_per_pixel) { // Build atlas on demand if (TexPixelsAlpha8 == NULL) { - if (ConfigData.empty()) - AddFontDefault(); + if (ConfigData.empty()) AddFontDefault(); Build(); } @@ -1126,28 +1233,28 @@ void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_wid if (out_bytes_per_pixel) *out_bytes_per_pixel = 1; } -void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) +void ImFontAtlas::GetTexDataAsRGBA32(unsigned char **out_pixels, int *out_width, int *out_height, int *out_bytes_per_pixel) { // Convert to RGBA32 format on demand // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp if (!TexPixelsRGBA32) { - unsigned char* pixels; + unsigned char *pixels; GetTexDataAsAlpha8(&pixels, NULL, NULL); - TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4)); - const unsigned char* src = pixels; - unsigned int* dst = TexPixelsRGBA32; + TexPixelsRGBA32 = (unsigned int *)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4)); + const unsigned char *src = pixels; + unsigned int * dst = TexPixelsRGBA32; for (int n = TexWidth * TexHeight; n > 0; n--) *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); } - *out_pixels = (unsigned char*)TexPixelsRGBA32; + *out_pixels = (unsigned char *)TexPixelsRGBA32; if (out_width) *out_width = TexWidth; if (out_height) *out_height = TexHeight; if (out_bytes_per_pixel) *out_bytes_per_pixel = 4; } -ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) +ImFont *ImFontAtlas::AddFont(const ImFontConfig *font_cfg) { IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); IM_ASSERT(font_cfg->SizePixels > 0.0f); @@ -1155,22 +1262,22 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) // Create new font if (!font_cfg->MergeMode) { - ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont)); + ImFont *font = (ImFont *)ImGui::MemAlloc(sizeof(ImFont)); IM_PLACEMENT_NEW(font) ImFont(); Fonts.push_back(font); } else { - IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use ImGui::AddFontDefault() to add the default imgui font. + IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use + // ImGui::AddFontDefault() to add the default imgui font. } ConfigData.push_back(*font_cfg); - ImFontConfig& new_font_cfg = ConfigData.back(); - if (!new_font_cfg.DstFont) - new_font_cfg.DstFont = Fonts.back(); + ImFontConfig &new_font_cfg = ConfigData.back(); + if (!new_font_cfg.DstFont) new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) { - new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize); + new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize); new_font_cfg.FontDataOwnedByAtlas = true; memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); } @@ -1183,39 +1290,48 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) // Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder) static unsigned int stb_decompress_length(unsigned char *input); static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length); -static const char* GetDefaultCompressedFontDataTTFBase85(); -static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } -static void Decode85(const unsigned char* src, unsigned char* dst) +static const char * GetDefaultCompressedFontDataTTFBase85(); +static unsigned int Decode85Byte(char c) +{ + return c >= '\\' ? c - 36 : c - 35; +} +static void Decode85(const unsigned char *src, unsigned char *dst) { while (*src) { - unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4])))); - dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness. + unsigned int tmp = + Decode85Byte(src[0]) + + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4])))); + dst[0] = ((tmp >> 0) & 0xFF); + dst[1] = ((tmp >> 8) & 0xFF); + dst[2] = ((tmp >> 16) & 0xFF); + dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness. src += 5; dst += 4; } } // Load embedded ProggyClean.ttf at size 13, disable oversampling -ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) +ImFont *ImFontAtlas::AddFontDefault(const ImFontConfig *font_cfg_template) { ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); if (!font_cfg_template) { font_cfg.OversampleH = font_cfg.OversampleV = 1; - font_cfg.PixelSnapH = true; + font_cfg.PixelSnapH = true; } if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "ProggyClean.ttf, 13px"); - const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, 13.0f, &font_cfg, GetGlyphRangesDefault()); + const char *ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); + ImFont * font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, 13.0f, &font_cfg, GetGlyphRangesDefault()); return font; } -ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) +ImFont *ImFontAtlas::AddFontFromFileTTF(const char *filename, float size_pixels, const ImFontConfig *font_cfg_template, + const ImWchar *glyph_ranges) { - int data_size = 0; - void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0); + int data_size = 0; + void *data = ImFileLoadToMemory(filename, "rb", &data_size, 0); if (!data) { IM_ASSERT(0); // Could not load file. @@ -1225,31 +1341,33 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, if (font_cfg.Name[0] == '\0') { // Store a short copy of filename into into the font name for convenience - const char* p; + const char *p; for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); } return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges); } -// NBM Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build(). -ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) +// NBM Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer +// will be deleted after Build(). +ImFont *ImFontAtlas::AddFontFromMemoryTTF(void *ttf_data, int ttf_size, float size_pixels, const ImFontConfig *font_cfg_template, + const ImWchar *glyph_ranges) { ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); - font_cfg.FontData = ttf_data; + font_cfg.FontData = ttf_data; font_cfg.FontDataSize = ttf_size; - font_cfg.SizePixels = size_pixels; - if (glyph_ranges) - font_cfg.GlyphRanges = glyph_ranges; + font_cfg.SizePixels = size_pixels; + if (glyph_ranges) font_cfg.GlyphRanges = glyph_ranges; return AddFont(&font_cfg); } -ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) +ImFont *ImFontAtlas::AddFontFromMemoryCompressedTTF(const void *compressed_ttf_data, int compressed_ttf_size, float size_pixels, + const ImFontConfig *font_cfg_template, const ImWchar *glyph_ranges) { - const unsigned int buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data); - unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); - stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); + const unsigned int buf_decompressed_size = stb_decompress_length((unsigned char *)compressed_ttf_data); + unsigned char * buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); + stb_decompress(buf_decompressed_data, (unsigned char *)compressed_ttf_data, (unsigned int)compressed_ttf_size); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); @@ -1257,63 +1375,67 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges); } -ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) +ImFont *ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char *compressed_ttf_data_base85, float size_pixels, + const ImFontConfig *font_cfg, const ImWchar *glyph_ranges) { - int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4; - void* compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size); - Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf); - ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); + int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4; + void *compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size); + Decode85((const unsigned char *)compressed_ttf_data_base85, (unsigned char *)compressed_ttf); + ImFont *font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); ImGui::MemFree(compressed_ttf); return font; } -bool ImFontAtlas::Build() +bool ImFontAtlas::Build() { IM_ASSERT(ConfigData.Size > 0); - TexID = NULL; + TexID = NULL; TexWidth = TexHeight = 0; - TexUvWhitePixel = ImVec2(0, 0); + TexUvWhitePixel = ImVec2(0, 0); ClearTexData(); struct ImFontTempBuildData { - stbtt_fontinfo FontInfo; - stbrp_rect* Rects; - stbtt_pack_range* Ranges; - int RangesCount; + stbtt_fontinfo FontInfo; + stbrp_rect * Rects; + stbtt_pack_range *Ranges; + int RangesCount; }; - ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)ConfigData.Size * sizeof(ImFontTempBuildData)); + ImFontTempBuildData *tmp_array = + (ImFontTempBuildData *)ImGui::MemAlloc((size_t)ConfigData.Size * sizeof(ImFontTempBuildData)); // Initialize font information early (so we can error without any cleanup) + count glyphs - int total_glyph_count = 0; + int total_glyph_count = 0; int total_glyph_range_count = 0; for (int input_i = 0; input_i < ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; - ImFontTempBuildData& tmp = tmp_array[input_i]; + ImFontConfig & cfg = ConfigData[input_i]; + ImFontTempBuildData &tmp = tmp_array[input_i]; IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == this)); - const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); + const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char *)cfg.FontData, cfg.FontNo); IM_ASSERT(font_offset >= 0); - if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) - return false; + if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char *)cfg.FontData, font_offset)) return false; // Count glyphs - if (!cfg.GlyphRanges) - cfg.GlyphRanges = GetGlyphRangesDefault(); - for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) + if (!cfg.GlyphRanges) cfg.GlyphRanges = GetGlyphRangesDefault(); + for (const ImWchar *in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) { total_glyph_count += (in_range[1] - in_range[0]) + 1; total_glyph_range_count++; } } - // Start packing. We need a known width for the skyline algorithm. Using a cheap heuristic here to decide of width. User can override TexDesiredWidth if they wish. - // After packing is done, width shouldn't matter much, but some API/GPU have texture size limitations and increasing width can decrease height. - TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyph_count > 4000) ? 4096 : (total_glyph_count > 2000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512; - TexHeight = 0; - const int max_tex_height = 1024*32; + // Start packing. We need a known width for the skyline algorithm. Using a cheap heuristic here to decide of width. User can + // override TexDesiredWidth if they wish. After packing is done, width shouldn't matter much, but some API/GPU have texture + // size limitations and increasing width can decrease height. + TexWidth = + (TexDesiredWidth > 0) + ? TexDesiredWidth + : (total_glyph_count > 4000) ? 4096 : (total_glyph_count > 2000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512; + TexHeight = 0; + const int max_tex_height = 1024 * 32; stbtt_pack_context spc; stbtt_PackBegin(&spc, NULL, TexWidth, max_tex_height, 0, 1, NULL); @@ -1321,45 +1443,45 @@ bool ImFontAtlas::Build() ImVector extra_rects; RenderCustomTexData(0, &extra_rects); stbtt_PackSetOversampling(&spc, 1, 1); - stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rects[0], extra_rects.Size); + stbrp_pack_rects((stbrp_context *)spc.pack_info, &extra_rects[0], extra_rects.Size); for (int i = 0; i < extra_rects.Size; i++) - if (extra_rects[i].was_packed) - TexHeight = ImMax(TexHeight, extra_rects[i].y + extra_rects[i].h); + if (extra_rects[i].was_packed) TexHeight = ImMax(TexHeight, extra_rects[i].y + extra_rects[i].h); // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) - int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0; - stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyph_count * sizeof(stbtt_packedchar)); - stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect)); - stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range)); + int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0; + stbtt_packedchar *buf_packedchars = (stbtt_packedchar *)ImGui::MemAlloc(total_glyph_count * sizeof(stbtt_packedchar)); + stbrp_rect * buf_rects = (stbrp_rect *)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect)); + stbtt_pack_range *buf_ranges = (stbtt_pack_range *)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range)); memset(buf_packedchars, 0, total_glyph_count * sizeof(stbtt_packedchar)); - memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect)); // Unnecessary but let's clear this for the sake of sanity. + memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect)); // Unnecessary but let's clear this for the sake of sanity. memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range)); - // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point) + // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture + // at this point) for (int input_i = 0; input_i < ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; - ImFontTempBuildData& tmp = tmp_array[input_i]; + ImFontConfig & cfg = ConfigData[input_i]; + ImFontTempBuildData &tmp = tmp_array[input_i]; // Setup ranges - int glyph_count = 0; + int glyph_count = 0; int glyph_ranges_count = 0; - for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) + for (const ImWchar *in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) { glyph_count += (in_range[1] - in_range[0]) + 1; glyph_ranges_count++; } - tmp.Ranges = buf_ranges + buf_ranges_n; + tmp.Ranges = buf_ranges + buf_ranges_n; tmp.RangesCount = glyph_ranges_count; buf_ranges_n += glyph_ranges_count; for (int i = 0; i < glyph_ranges_count; i++) { - const ImWchar* in_range = &cfg.GlyphRanges[i * 2]; - stbtt_pack_range& range = tmp.Ranges[i]; - range.font_size = cfg.SizePixels; + const ImWchar * in_range = &cfg.GlyphRanges[i * 2]; + stbtt_pack_range &range = tmp.Ranges[i]; + range.font_size = cfg.SizePixels; range.first_unicode_codepoint_in_range = in_range[0]; - range.num_chars = (in_range[1] - in_range[0]) + 1; - range.chardata_for_range = buf_packedchars + buf_packedchars_n; + range.num_chars = (in_range[1] - in_range[0]) + 1; + range.chardata_for_range = buf_packedchars + buf_packedchars_n; buf_packedchars_n += range.num_chars; } @@ -1368,20 +1490,19 @@ bool ImFontAtlas::Build() buf_rects_n += glyph_count; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); - stbrp_pack_rects((stbrp_context*)spc.pack_info, tmp.Rects, n); + stbrp_pack_rects((stbrp_context *)spc.pack_info, tmp.Rects, n); // Extend texture height for (int i = 0; i < n; i++) - if (tmp.Rects[i].was_packed) - TexHeight = ImMax(TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); + if (tmp.Rects[i].was_packed) TexHeight = ImMax(TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); } IM_ASSERT(buf_rects_n == total_glyph_count); IM_ASSERT(buf_packedchars_n == total_glyph_count); IM_ASSERT(buf_ranges_n == total_glyph_range_count); // Create texture - TexHeight = ImUpperPowerOfTwo(TexHeight); - TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(TexWidth * TexHeight); + TexHeight = ImUpperPowerOfTwo(TexHeight); + TexPixelsAlpha8 = (unsigned char *)ImGui::MemAlloc(TexWidth * TexHeight); memset(TexPixelsAlpha8, 0, TexWidth * TexHeight); spc.pixels = TexPixelsAlpha8; spc.height = TexHeight; @@ -1389,8 +1510,8 @@ bool ImFontAtlas::Build() // Second pass: render characters for (int input_i = 0; input_i < ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; - ImFontTempBuildData& tmp = tmp_array[input_i]; + ImFontConfig & cfg = ConfigData[input_i]; + ImFontTempBuildData &tmp = tmp_array[input_i]; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); tmp.Rects = NULL; @@ -1404,59 +1525,66 @@ bool ImFontAtlas::Build() // Third pass: setup ImFont and glyphs for runtime for (int input_i = 0; input_i < ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; - ImFontTempBuildData& tmp = tmp_array[input_i]; - ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true) + ImFontConfig & cfg = ConfigData[input_i]; + ImFontTempBuildData &tmp = tmp_array[input_i]; + ImFont * dst_font = + cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true) float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels); - int unscaled_ascent, unscaled_descent, unscaled_line_gap; + int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); - float ascent = unscaled_ascent * font_scale; + float ascent = unscaled_ascent * font_scale; float descent = unscaled_descent * font_scale; if (!cfg.MergeMode) { - dst_font->ContainerAtlas = this; - dst_font->ConfigData = &cfg; + dst_font->ContainerAtlas = this; + dst_font->ConfigData = &cfg; dst_font->ConfigDataCount = 0; - dst_font->FontSize = cfg.SizePixels; - dst_font->Ascent = ascent; - dst_font->Descent = descent; + dst_font->FontSize = cfg.SizePixels; + dst_font->Ascent = ascent; + dst_font->Descent = descent; dst_font->Glyphs.resize(0); dst_font->MetricsTotalSurface = 0; } dst_font->ConfigDataCount++; float off_y = (cfg.MergeMode && cfg.MergeGlyphCenterV) ? (ascent - dst_font->Ascent) * 0.5f : 0.0f; - dst_font->FallbackGlyph = NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() + dst_font->FallbackGlyph = + NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() for (int i = 0; i < tmp.RangesCount; i++) { - stbtt_pack_range& range = tmp.Ranges[i]; + stbtt_pack_range &range = tmp.Ranges[i]; for (int char_idx = 0; char_idx < range.num_chars; char_idx += 1) { - const stbtt_packedchar& pc = range.chardata_for_range[char_idx]; - if (!pc.x0 && !pc.x1 && !pc.y0 && !pc.y1) - continue; + const stbtt_packedchar &pc = range.chardata_for_range[char_idx]; + if (!pc.x0 && !pc.x1 && !pc.y0 && !pc.y1) continue; const int codepoint = range.first_unicode_codepoint_in_range + char_idx; - if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint)) - continue; + if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint)) continue; stbtt_aligned_quad q; - float dummy_x = 0.0f, dummy_y = 0.0f; + float dummy_x = 0.0f, dummy_y = 0.0f; stbtt_GetPackedQuad(range.chardata_for_range, TexWidth, TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0); dst_font->Glyphs.resize(dst_font->Glyphs.Size + 1); - ImFont::Glyph& glyph = dst_font->Glyphs.back(); - glyph.Codepoint = (ImWchar)codepoint; - glyph.X0 = q.x0; glyph.Y0 = q.y0; glyph.X1 = q.x1; glyph.Y1 = q.y1; - glyph.U0 = q.s0; glyph.V0 = q.t0; glyph.U1 = q.s1; glyph.V1 = q.t1; + ImFont::Glyph &glyph = dst_font->Glyphs.back(); + glyph.Codepoint = (ImWchar)codepoint; + glyph.X0 = q.x0; + glyph.Y0 = q.y0; + glyph.X1 = q.x1; + glyph.Y1 = q.y1; + glyph.U0 = q.s0; + glyph.V0 = q.t0; + glyph.U1 = q.s1; + glyph.V1 = q.t1; glyph.Y0 += (float)(int)(dst_font->Ascent + off_y + 0.5f); glyph.Y1 += (float)(int)(dst_font->Ascent + off_y + 0.5f); - glyph.XAdvance = (pc.xadvance + cfg.GlyphExtraSpacing.x); // Bake spacing into XAdvance - if (cfg.PixelSnapH) - glyph.XAdvance = (float)(int)(glyph.XAdvance + 0.5f); - dst_font->MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * TexHeight + 1.99f); // +1 to account for average padding, +0.99 to round + glyph.XAdvance = (pc.xadvance + cfg.GlyphExtraSpacing.x); // Bake spacing into XAdvance + if (cfg.PixelSnapH) glyph.XAdvance = (float)(int)(glyph.XAdvance + 0.5f); + dst_font->MetricsTotalSurface += + (int)((glyph.U1 - glyph.U0) * TexWidth + 1.99f) * + (int)((glyph.V1 - glyph.V0) * TexHeight + 1.99f); // +1 to account for average padding, +0.99 to round } } cfg.DstFont->BuildLookupTable(); @@ -1473,14 +1601,13 @@ bool ImFontAtlas::Build() return true; } -void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) +void ImFontAtlas::RenderCustomTexData(int pass, void *p_rects) { // A work of art lies ahead! (. = white layer, X = black layer, others are blank) // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. - const int TEX_DATA_W = 90; - const int TEX_DATA_H = 27; - const char texture_data[TEX_DATA_W*TEX_DATA_H+1] = - { + const int TEX_DATA_W = 90; + const int TEX_DATA_H = 27; + const char texture_data[TEX_DATA_W * TEX_DATA_H + 1] = { "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" "..- -X.....X- X.X - X.X -X.....X - X.....X" "--- -XXX.XXX- X...X - X...X -X....X - X....X" @@ -1507,28 +1634,27 @@ void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) " ----------------------------------- X...XXXXXXXXXXXXX...X - " " - X..X X..X - " " - X.X X.X - " - " - XX XX - " - }; + " - XX XX - "}; - ImVector& rects = *(ImVector*)p_rects; + ImVector &rects = *(ImVector *)p_rects; if (pass == 0) { // Request rectangles stbrp_rect r; memset(&r, 0, sizeof(r)); - r.w = (TEX_DATA_W*2)+1; - r.h = TEX_DATA_H+1; + r.w = (TEX_DATA_W * 2) + 1; + r.h = TEX_DATA_H + 1; rects.push_back(r); } else if (pass == 1) { // Render/copy pixels - const stbrp_rect& r = rects[0]; + const stbrp_rect &r = rects[0]; for (int y = 0, n = 0; y < TEX_DATA_H; y++) for (int x = 0; x < TEX_DATA_W; x++, n++) { - const int offset0 = (int)(r.x + x) + (int)(r.y + y) * TexWidth; - const int offset1 = offset0 + 1 + TEX_DATA_W; + const int offset0 = (int)(r.x + x) + (int)(r.y + y) * TexWidth; + const int offset1 = offset0 + 1 + TEX_DATA_W; TexPixelsAlpha8[offset0] = texture_data[n] == '.' ? 0xFF : 0x00; TexPixelsAlpha8[offset1] = texture_data[n] == 'X' ? 0xFF : 0x00; } @@ -1536,50 +1662,48 @@ void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) TexUvWhitePixel = ImVec2((r.x + 0.5f) * tex_uv_scale.x, (r.y + 0.5f) * tex_uv_scale.y); // Setup mouse cursors - const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] = - { + const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] = { // Pos ........ Size ......... Offset ...... - { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow - { ImVec2(13,0), ImVec2(7,16), ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput - { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move - { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS - { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW - { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW - { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE + {ImVec2(0, 3), ImVec2(12, 19), ImVec2(0, 0)}, // ImGuiMouseCursor_Arrow + {ImVec2(13, 0), ImVec2(7, 16), ImVec2(4, 8)}, // ImGuiMouseCursor_TextInput + {ImVec2(31, 0), ImVec2(23, 23), ImVec2(11, 11)}, // ImGuiMouseCursor_Move + {ImVec2(21, 0), ImVec2(9, 23), ImVec2(5, 11)}, // ImGuiMouseCursor_ResizeNS + {ImVec2(55, 18), ImVec2(23, 9), ImVec2(11, 5)}, // ImGuiMouseCursor_ResizeEW + {ImVec2(73, 0), ImVec2(17, 17), ImVec2(9, 9)}, // ImGuiMouseCursor_ResizeNESW + {ImVec2(55, 0), ImVec2(17, 17), ImVec2(9, 9)}, // ImGuiMouseCursor_ResizeNWSE }; for (int type = 0; type < ImGuiMouseCursor_Count_; type++) { - ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type]; - ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.x, (float)r.y); - const ImVec2 size = cursor_datas[type][1]; - cursor_data.Type = type; - cursor_data.Size = size; - cursor_data.HotOffset = cursor_datas[type][2]; - cursor_data.TexUvMin[0] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; - pos.x += TEX_DATA_W+1; - cursor_data.TexUvMin[1] = (pos) * tex_uv_scale; + ImGuiMouseCursorData &cursor_data = GImGui->MouseCursorData[type]; + ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.x, (float)r.y); + const ImVec2 size = cursor_datas[type][1]; + cursor_data.Type = type; + cursor_data.Size = size; + cursor_data.HotOffset = cursor_datas[type][2]; + cursor_data.TexUvMin[0] = (pos)*tex_uv_scale; + cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; + pos.x += TEX_DATA_W + 1; + cursor_data.TexUvMin[1] = (pos)*tex_uv_scale; cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale; } } } // Retrieve list of range (2 int per range, values are inclusive) -const ImWchar* ImFontAtlas::GetGlyphRangesDefault() +const ImWchar *ImFontAtlas::GetGlyphRangesDefault() { - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement + static const ImWchar ranges[] = { + 0x0020, + 0x00FF, // Basic Latin + Latin Supplement 0, }; return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesKorean() +const ImWchar *ImFontAtlas::GetGlyphRangesKorean() { - static const ImWchar ranges[] = - { + static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3131, 0x3163, // Korean alphabets 0xAC00, 0xD79D, // Korean characters @@ -1588,10 +1712,9 @@ const ImWchar* ImFontAtlas::GetGlyphRangesKorean() return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesChinese() +const ImWchar *ImFontAtlas::GetGlyphRangesChinese() { - static const ImWchar ranges[] = - { + static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions @@ -1602,72 +1725,108 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChinese() return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() -{ - // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1. - // This encoding helps us reduce the source code size. - static const short offsets_from_0x4E00[] = - { - -1,0,1,3,0,0,0,0,1,0,5,1,1,0,7,4,6,10,0,1,9,9,7,1,3,19,1,10,7,1,0,1,0,5,1,0,6,4,2,6,0,0,12,6,8,0,3,5,0,1,0,9,0,0,8,1,1,3,4,5,13,0,0,8,2,17, - 4,3,1,1,9,6,0,0,0,2,1,3,2,22,1,9,11,1,13,1,3,12,0,5,9,2,0,6,12,5,3,12,4,1,2,16,1,1,4,6,5,3,0,6,13,15,5,12,8,14,0,0,6,15,3,6,0,18,8,1,6,14,1, - 5,4,12,24,3,13,12,10,24,0,0,0,1,0,1,1,2,9,10,2,2,0,0,3,3,1,0,3,8,0,3,2,4,4,1,6,11,10,14,6,15,3,4,15,1,0,0,5,2,2,0,0,1,6,5,5,6,0,3,6,5,0,0,1,0, - 11,2,2,8,4,7,0,10,0,1,2,17,19,3,0,2,5,0,6,2,4,4,6,1,1,11,2,0,3,1,2,1,2,10,7,6,3,16,0,8,24,0,0,3,1,1,3,0,1,6,0,0,0,2,0,1,5,15,0,1,0,0,2,11,19, - 1,4,19,7,6,5,1,0,0,0,0,5,1,0,1,9,0,0,5,0,2,0,1,0,3,0,11,3,0,2,0,0,0,0,0,9,3,6,4,12,0,14,0,0,29,10,8,0,14,37,13,0,31,16,19,0,8,30,1,20,8,3,48, - 21,1,0,12,0,10,44,34,42,54,11,18,82,0,2,1,2,12,1,0,6,2,17,2,12,7,0,7,17,4,2,6,24,23,8,23,39,2,16,23,1,0,5,1,2,15,14,5,6,2,11,0,8,6,2,2,2,14, - 20,4,15,3,4,11,10,10,2,5,2,1,30,2,1,0,0,22,5,5,0,3,1,5,4,1,0,0,2,2,21,1,5,1,2,16,2,1,3,4,0,8,4,0,0,5,14,11,2,16,1,13,1,7,0,22,15,3,1,22,7,14, - 22,19,11,24,18,46,10,20,64,45,3,2,0,4,5,0,1,4,25,1,0,0,2,10,0,0,0,1,0,1,2,0,0,9,1,2,0,0,0,2,5,2,1,1,5,5,8,1,1,1,5,1,4,9,1,3,0,1,0,1,1,2,0,0, - 2,0,1,8,22,8,1,0,0,0,0,4,2,1,0,9,8,5,0,9,1,30,24,2,6,4,39,0,14,5,16,6,26,179,0,2,1,1,0,0,0,5,2,9,6,0,2,5,16,7,5,1,1,0,2,4,4,7,15,13,14,0,0, - 3,0,1,0,0,0,2,1,6,4,5,1,4,9,0,3,1,8,0,0,10,5,0,43,0,2,6,8,4,0,2,0,0,9,6,0,9,3,1,6,20,14,6,1,4,0,7,2,3,0,2,0,5,0,3,1,0,3,9,7,0,3,4,0,4,9,1,6,0, - 9,0,0,2,3,10,9,28,3,6,2,4,1,2,32,4,1,18,2,0,3,1,5,30,10,0,2,2,2,0,7,9,8,11,10,11,7,2,13,7,5,10,0,3,40,2,0,1,6,12,0,4,5,1,5,11,11,21,4,8,3,7, - 8,8,33,5,23,0,0,19,8,8,2,3,0,6,1,1,1,5,1,27,4,2,5,0,3,5,6,3,1,0,3,1,12,5,3,3,2,0,7,7,2,1,0,4,0,1,1,2,0,10,10,6,2,5,9,7,5,15,15,21,6,11,5,20, - 4,3,5,5,2,5,0,2,1,0,1,7,28,0,9,0,5,12,5,5,18,30,0,12,3,3,21,16,25,32,9,3,14,11,24,5,66,9,1,2,0,5,9,1,5,1,8,0,8,3,3,0,1,15,1,4,8,1,2,7,0,7,2, - 8,3,7,5,3,7,10,2,1,0,0,2,25,0,6,4,0,10,0,4,2,4,1,12,5,38,4,0,4,1,10,5,9,4,0,14,4,2,5,18,20,21,1,3,0,5,0,7,0,3,7,1,3,1,1,8,1,0,0,0,3,2,5,2,11, - 6,0,13,1,3,9,1,12,0,16,6,2,1,0,2,1,12,6,13,11,2,0,28,1,7,8,14,13,8,13,0,2,0,5,4,8,10,2,37,42,19,6,6,7,4,14,11,18,14,80,7,6,0,4,72,12,36,27, - 7,7,0,14,17,19,164,27,0,5,10,7,3,13,6,14,0,2,2,5,3,0,6,13,0,0,10,29,0,4,0,3,13,0,3,1,6,51,1,5,28,2,0,8,0,20,2,4,0,25,2,10,13,10,0,16,4,0,1,0, - 2,1,7,0,1,8,11,0,0,1,2,7,2,23,11,6,6,4,16,2,2,2,0,22,9,3,3,5,2,0,15,16,21,2,9,20,15,15,5,3,9,1,0,0,1,7,7,5,4,2,2,2,38,24,14,0,0,15,5,6,24,14, - 5,5,11,0,21,12,0,3,8,4,11,1,8,0,11,27,7,2,4,9,21,59,0,1,39,3,60,62,3,0,12,11,0,3,30,11,0,13,88,4,15,5,28,13,1,4,48,17,17,4,28,32,46,0,16,0, - 18,11,1,8,6,38,11,2,6,11,38,2,0,45,3,11,2,7,8,4,30,14,17,2,1,1,65,18,12,16,4,2,45,123,12,56,33,1,4,3,4,7,0,0,0,3,2,0,16,4,2,4,2,0,7,4,5,2,26, - 2,25,6,11,6,1,16,2,6,17,77,15,3,35,0,1,0,5,1,0,38,16,6,3,12,3,3,3,0,9,3,1,3,5,2,9,0,18,0,25,1,3,32,1,72,46,6,2,7,1,3,14,17,0,28,1,40,13,0,20, - 15,40,6,38,24,12,43,1,1,9,0,12,6,0,6,2,4,19,3,7,1,48,0,9,5,0,5,6,9,6,10,15,2,11,19,3,9,2,0,1,10,1,27,8,1,3,6,1,14,0,26,0,27,16,3,4,9,6,2,23, - 9,10,5,25,2,1,6,1,1,48,15,9,15,14,3,4,26,60,29,13,37,21,1,6,4,0,2,11,22,23,16,16,2,2,1,3,0,5,1,6,4,0,0,4,0,0,8,3,0,2,5,0,7,1,7,3,13,2,4,10, - 3,0,2,31,0,18,3,0,12,10,4,1,0,7,5,7,0,5,4,12,2,22,10,4,2,15,2,8,9,0,23,2,197,51,3,1,1,4,13,4,3,21,4,19,3,10,5,40,0,4,1,1,10,4,1,27,34,7,21, - 2,17,2,9,6,4,2,3,0,4,2,7,8,2,5,1,15,21,3,4,4,2,2,17,22,1,5,22,4,26,7,0,32,1,11,42,15,4,1,2,5,0,19,3,1,8,6,0,10,1,9,2,13,30,8,2,24,17,19,1,4, - 4,25,13,0,10,16,11,39,18,8,5,30,82,1,6,8,18,77,11,13,20,75,11,112,78,33,3,0,0,60,17,84,9,1,1,12,30,10,49,5,32,158,178,5,5,6,3,3,1,3,1,4,7,6, - 19,31,21,0,2,9,5,6,27,4,9,8,1,76,18,12,1,4,0,3,3,6,3,12,2,8,30,16,2,25,1,5,5,4,3,0,6,10,2,3,1,0,5,1,19,3,0,8,1,5,2,6,0,0,0,19,1,2,0,5,1,2,5, - 1,3,7,0,4,12,7,3,10,22,0,9,5,1,0,2,20,1,1,3,23,30,3,9,9,1,4,191,14,3,15,6,8,50,0,1,0,0,4,0,0,1,0,2,4,2,0,2,3,0,2,0,2,2,8,7,0,1,1,1,3,3,17,11, - 91,1,9,3,2,13,4,24,15,41,3,13,3,1,20,4,125,29,30,1,0,4,12,2,21,4,5,5,19,11,0,13,11,86,2,18,0,7,1,8,8,2,2,22,1,2,6,5,2,0,1,2,8,0,2,0,5,2,1,0, - 2,10,2,0,5,9,2,1,2,0,1,0,4,0,0,10,2,5,3,0,6,1,0,1,4,4,33,3,13,17,3,18,6,4,7,1,5,78,0,4,1,13,7,1,8,1,0,35,27,15,3,0,0,0,1,11,5,41,38,15,22,6, - 14,14,2,1,11,6,20,63,5,8,27,7,11,2,2,40,58,23,50,54,56,293,8,8,1,5,1,14,0,1,12,37,89,8,8,8,2,10,6,0,0,0,4,5,2,1,0,1,1,2,7,0,3,3,0,4,6,0,3,2, - 19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20, - 109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38, +const ImWchar *ImFontAtlas::GetGlyphRangesJapanese() +{ + // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an + // implicit +1. This encoding helps us reduce the source code size. + static const short offsets_from_0x4E00[] = { + -1, 0, 1, 3, 0, 0, 0, 0, 1, 0, 5, 1, 1, 0, 7, 4, 6, 10, 0, 1, 9, 9, 7, 1, 3, 19, 1, 10, + 7, 1, 0, 1, 0, 5, 1, 0, 6, 4, 2, 6, 0, 0, 12, 6, 8, 0, 3, 5, 0, 1, 0, 9, 0, 0, 8, 1, + 1, 3, 4, 5, 13, 0, 0, 8, 2, 17, 4, 3, 1, 1, 9, 6, 0, 0, 0, 2, 1, 3, 2, 22, 1, 9, 11, 1, + 13, 1, 3, 12, 0, 5, 9, 2, 0, 6, 12, 5, 3, 12, 4, 1, 2, 16, 1, 1, 4, 6, 5, 3, 0, 6, 13, 15, + 5, 12, 8, 14, 0, 0, 6, 15, 3, 6, 0, 18, 8, 1, 6, 14, 1, 5, 4, 12, 24, 3, 13, 12, 10, 24, 0, 0, + 0, 1, 0, 1, 1, 2, 9, 10, 2, 2, 0, 0, 3, 3, 1, 0, 3, 8, 0, 3, 2, 4, 4, 1, 6, 11, 10, 14, + 6, 15, 3, 4, 15, 1, 0, 0, 5, 2, 2, 0, 0, 1, 6, 5, 5, 6, 0, 3, 6, 5, 0, 0, 1, 0, 11, 2, + 2, 8, 4, 7, 0, 10, 0, 1, 2, 17, 19, 3, 0, 2, 5, 0, 6, 2, 4, 4, 6, 1, 1, 11, 2, 0, 3, 1, + 2, 1, 2, 10, 7, 6, 3, 16, 0, 8, 24, 0, 0, 3, 1, 1, 3, 0, 1, 6, 0, 0, 0, 2, 0, 1, 5, 15, + 0, 1, 0, 0, 2, 11, 19, 1, 4, 19, 7, 6, 5, 1, 0, 0, 0, 0, 5, 1, 0, 1, 9, 0, 0, 5, 0, 2, + 0, 1, 0, 3, 0, 11, 3, 0, 2, 0, 0, 0, 0, 0, 9, 3, 6, 4, 12, 0, 14, 0, 0, 29, 10, 8, 0, 14, + 37, 13, 0, 31, 16, 19, 0, 8, 30, 1, 20, 8, 3, 48, 21, 1, 0, 12, 0, 10, 44, 34, 42, 54, 11, 18, 82, 0, + 2, 1, 2, 12, 1, 0, 6, 2, 17, 2, 12, 7, 0, 7, 17, 4, 2, 6, 24, 23, 8, 23, 39, 2, 16, 23, 1, 0, + 5, 1, 2, 15, 14, 5, 6, 2, 11, 0, 8, 6, 2, 2, 2, 14, 20, 4, 15, 3, 4, 11, 10, 10, 2, 5, 2, 1, + 30, 2, 1, 0, 0, 22, 5, 5, 0, 3, 1, 5, 4, 1, 0, 0, 2, 2, 21, 1, 5, 1, 2, 16, 2, 1, 3, 4, + 0, 8, 4, 0, 0, 5, 14, 11, 2, 16, 1, 13, 1, 7, 0, 22, 15, 3, 1, 22, 7, 14, 22, 19, 11, 24, 18, 46, + 10, 20, 64, 45, 3, 2, 0, 4, 5, 0, 1, 4, 25, 1, 0, 0, 2, 10, 0, 0, 0, 1, 0, 1, 2, 0, 0, 9, + 1, 2, 0, 0, 0, 2, 5, 2, 1, 1, 5, 5, 8, 1, 1, 1, 5, 1, 4, 9, 1, 3, 0, 1, 0, 1, 1, 2, + 0, 0, 2, 0, 1, 8, 22, 8, 1, 0, 0, 0, 0, 4, 2, 1, 0, 9, 8, 5, 0, 9, 1, 30, 24, 2, 6, 4, + 39, 0, 14, 5, 16, 6, 26, 179, 0, 2, 1, 1, 0, 0, 0, 5, 2, 9, 6, 0, 2, 5, 16, 7, 5, 1, 1, 0, + 2, 4, 4, 7, 15, 13, 14, 0, 0, 3, 0, 1, 0, 0, 0, 2, 1, 6, 4, 5, 1, 4, 9, 0, 3, 1, 8, 0, + 0, 10, 5, 0, 43, 0, 2, 6, 8, 4, 0, 2, 0, 0, 9, 6, 0, 9, 3, 1, 6, 20, 14, 6, 1, 4, 0, 7, + 2, 3, 0, 2, 0, 5, 0, 3, 1, 0, 3, 9, 7, 0, 3, 4, 0, 4, 9, 1, 6, 0, 9, 0, 0, 2, 3, 10, + 9, 28, 3, 6, 2, 4, 1, 2, 32, 4, 1, 18, 2, 0, 3, 1, 5, 30, 10, 0, 2, 2, 2, 0, 7, 9, 8, 11, + 10, 11, 7, 2, 13, 7, 5, 10, 0, 3, 40, 2, 0, 1, 6, 12, 0, 4, 5, 1, 5, 11, 11, 21, 4, 8, 3, 7, + 8, 8, 33, 5, 23, 0, 0, 19, 8, 8, 2, 3, 0, 6, 1, 1, 1, 5, 1, 27, 4, 2, 5, 0, 3, 5, 6, 3, + 1, 0, 3, 1, 12, 5, 3, 3, 2, 0, 7, 7, 2, 1, 0, 4, 0, 1, 1, 2, 0, 10, 10, 6, 2, 5, 9, 7, + 5, 15, 15, 21, 6, 11, 5, 20, 4, 3, 5, 5, 2, 5, 0, 2, 1, 0, 1, 7, 28, 0, 9, 0, 5, 12, 5, 5, + 18, 30, 0, 12, 3, 3, 21, 16, 25, 32, 9, 3, 14, 11, 24, 5, 66, 9, 1, 2, 0, 5, 9, 1, 5, 1, 8, 0, + 8, 3, 3, 0, 1, 15, 1, 4, 8, 1, 2, 7, 0, 7, 2, 8, 3, 7, 5, 3, 7, 10, 2, 1, 0, 0, 2, 25, + 0, 6, 4, 0, 10, 0, 4, 2, 4, 1, 12, 5, 38, 4, 0, 4, 1, 10, 5, 9, 4, 0, 14, 4, 2, 5, 18, 20, + 21, 1, 3, 0, 5, 0, 7, 0, 3, 7, 1, 3, 1, 1, 8, 1, 0, 0, 0, 3, 2, 5, 2, 11, 6, 0, 13, 1, + 3, 9, 1, 12, 0, 16, 6, 2, 1, 0, 2, 1, 12, 6, 13, 11, 2, 0, 28, 1, 7, 8, 14, 13, 8, 13, 0, 2, + 0, 5, 4, 8, 10, 2, 37, 42, 19, 6, 6, 7, 4, 14, 11, 18, 14, 80, 7, 6, 0, 4, 72, 12, 36, 27, 7, 7, + 0, 14, 17, 19, 164, 27, 0, 5, 10, 7, 3, 13, 6, 14, 0, 2, 2, 5, 3, 0, 6, 13, 0, 0, 10, 29, 0, 4, + 0, 3, 13, 0, 3, 1, 6, 51, 1, 5, 28, 2, 0, 8, 0, 20, 2, 4, 0, 25, 2, 10, 13, 10, 0, 16, 4, 0, + 1, 0, 2, 1, 7, 0, 1, 8, 11, 0, 0, 1, 2, 7, 2, 23, 11, 6, 6, 4, 16, 2, 2, 2, 0, 22, 9, 3, + 3, 5, 2, 0, 15, 16, 21, 2, 9, 20, 15, 15, 5, 3, 9, 1, 0, 0, 1, 7, 7, 5, 4, 2, 2, 2, 38, 24, + 14, 0, 0, 15, 5, 6, 24, 14, 5, 5, 11, 0, 21, 12, 0, 3, 8, 4, 11, 1, 8, 0, 11, 27, 7, 2, 4, 9, + 21, 59, 0, 1, 39, 3, 60, 62, 3, 0, 12, 11, 0, 3, 30, 11, 0, 13, 88, 4, 15, 5, 28, 13, 1, 4, 48, 17, + 17, 4, 28, 32, 46, 0, 16, 0, 18, 11, 1, 8, 6, 38, 11, 2, 6, 11, 38, 2, 0, 45, 3, 11, 2, 7, 8, 4, + 30, 14, 17, 2, 1, 1, 65, 18, 12, 16, 4, 2, 45, 123, 12, 56, 33, 1, 4, 3, 4, 7, 0, 0, 0, 3, 2, 0, + 16, 4, 2, 4, 2, 0, 7, 4, 5, 2, 26, 2, 25, 6, 11, 6, 1, 16, 2, 6, 17, 77, 15, 3, 35, 0, 1, 0, + 5, 1, 0, 38, 16, 6, 3, 12, 3, 3, 3, 0, 9, 3, 1, 3, 5, 2, 9, 0, 18, 0, 25, 1, 3, 32, 1, 72, + 46, 6, 2, 7, 1, 3, 14, 17, 0, 28, 1, 40, 13, 0, 20, 15, 40, 6, 38, 24, 12, 43, 1, 1, 9, 0, 12, 6, + 0, 6, 2, 4, 19, 3, 7, 1, 48, 0, 9, 5, 0, 5, 6, 9, 6, 10, 15, 2, 11, 19, 3, 9, 2, 0, 1, 10, + 1, 27, 8, 1, 3, 6, 1, 14, 0, 26, 0, 27, 16, 3, 4, 9, 6, 2, 23, 9, 10, 5, 25, 2, 1, 6, 1, 1, + 48, 15, 9, 15, 14, 3, 4, 26, 60, 29, 13, 37, 21, 1, 6, 4, 0, 2, 11, 22, 23, 16, 16, 2, 2, 1, 3, 0, + 5, 1, 6, 4, 0, 0, 4, 0, 0, 8, 3, 0, 2, 5, 0, 7, 1, 7, 3, 13, 2, 4, 10, 3, 0, 2, 31, 0, + 18, 3, 0, 12, 10, 4, 1, 0, 7, 5, 7, 0, 5, 4, 12, 2, 22, 10, 4, 2, 15, 2, 8, 9, 0, 23, 2, 197, + 51, 3, 1, 1, 4, 13, 4, 3, 21, 4, 19, 3, 10, 5, 40, 0, 4, 1, 1, 10, 4, 1, 27, 34, 7, 21, 2, 17, + 2, 9, 6, 4, 2, 3, 0, 4, 2, 7, 8, 2, 5, 1, 15, 21, 3, 4, 4, 2, 2, 17, 22, 1, 5, 22, 4, 26, + 7, 0, 32, 1, 11, 42, 15, 4, 1, 2, 5, 0, 19, 3, 1, 8, 6, 0, 10, 1, 9, 2, 13, 30, 8, 2, 24, 17, + 19, 1, 4, 4, 25, 13, 0, 10, 16, 11, 39, 18, 8, 5, 30, 82, 1, 6, 8, 18, 77, 11, 13, 20, 75, 11, 112, 78, + 33, 3, 0, 0, 60, 17, 84, 9, 1, 1, 12, 30, 10, 49, 5, 32, 158, 178, 5, 5, 6, 3, 3, 1, 3, 1, 4, 7, + 6, 19, 31, 21, 0, 2, 9, 5, 6, 27, 4, 9, 8, 1, 76, 18, 12, 1, 4, 0, 3, 3, 6, 3, 12, 2, 8, 30, + 16, 2, 25, 1, 5, 5, 4, 3, 0, 6, 10, 2, 3, 1, 0, 5, 1, 19, 3, 0, 8, 1, 5, 2, 6, 0, 0, 0, + 19, 1, 2, 0, 5, 1, 2, 5, 1, 3, 7, 0, 4, 12, 7, 3, 10, 22, 0, 9, 5, 1, 0, 2, 20, 1, 1, 3, + 23, 30, 3, 9, 9, 1, 4, 191, 14, 3, 15, 6, 8, 50, 0, 1, 0, 0, 4, 0, 0, 1, 0, 2, 4, 2, 0, 2, + 3, 0, 2, 0, 2, 2, 8, 7, 0, 1, 1, 1, 3, 3, 17, 11, 91, 1, 9, 3, 2, 13, 4, 24, 15, 41, 3, 13, + 3, 1, 20, 4, 125, 29, 30, 1, 0, 4, 12, 2, 21, 4, 5, 5, 19, 11, 0, 13, 11, 86, 2, 18, 0, 7, 1, 8, + 8, 2, 2, 22, 1, 2, 6, 5, 2, 0, 1, 2, 8, 0, 2, 0, 5, 2, 1, 0, 2, 10, 2, 0, 5, 9, 2, 1, + 2, 0, 1, 0, 4, 0, 0, 10, 2, 5, 3, 0, 6, 1, 0, 1, 4, 4, 33, 3, 13, 17, 3, 18, 6, 4, 7, 1, + 5, 78, 0, 4, 1, 13, 7, 1, 8, 1, 0, 35, 27, 15, 3, 0, 0, 0, 1, 11, 5, 41, 38, 15, 22, 6, 14, 14, + 2, 1, 11, 6, 20, 63, 5, 8, 27, 7, 11, 2, 2, 40, 58, 23, 50, 54, 56, 293, 8, 8, 1, 5, 1, 14, 0, 1, + 12, 37, 89, 8, 8, 8, 2, 10, 6, 0, 0, 0, 4, 5, 2, 1, 0, 1, 1, 2, 7, 0, 3, 3, 0, 4, 6, 0, + 3, 2, 19, 3, 8, 0, 0, 0, 4, 4, 16, 0, 4, 1, 5, 1, 3, 0, 3, 4, 6, 2, 17, 10, 10, 31, 6, 4, + 3, 6, 10, 126, 7, 3, 2, 2, 0, 9, 0, 0, 5, 20, 13, 0, 15, 0, 6, 0, 2, 5, 8, 64, 50, 3, 2, 12, + 2, 9, 0, 0, 11, 8, 20, 109, 2, 18, 23, 0, 0, 9, 61, 3, 0, 28, 41, 77, 27, 19, 17, 81, 5, 2, 14, 5, + 83, 57, 252, 14, 154, 263, 14, 20, 8, 13, 6, 57, 39, 38, }; - static ImWchar base_ranges[] = - { + static ImWchar base_ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters }; - static bool full_ranges_unpacked = false; - static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1]; + static bool full_ranges_unpacked = false; + static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00) * 2 + 1]; if (!full_ranges_unpacked) { // Unpack int codepoint = 0x4e00; memcpy(full_ranges, base_ranges, sizeof(base_ranges)); - ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);; + ImWchar *dst = full_ranges + IM_ARRAYSIZE(base_ranges); + ; for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2) dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1)); - dst[0] = 0; + dst[0] = 0; full_ranges_unpacked = true; } return &full_ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic() +const ImWchar *ImFontAtlas::GetGlyphRangesCyrillic() { - static const ImWchar ranges[] = - { + static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement 0x2DE0, 0x2DFF, // Cyrillic Extended-A @@ -1677,10 +1836,9 @@ const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic() return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesThai() +const ImWchar *ImFontAtlas::GetGlyphRangesThai() { - static const ImWchar ranges[] = - { + static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin 0x0E00, 0x0E7F, // Thai 0, @@ -1694,7 +1852,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesThai() ImFont::ImFont() { - Scale = 1.0f; + Scale = 1.0f; FallbackChar = (ImWchar)'?'; Clear(); } @@ -1712,19 +1870,19 @@ ImFont::~ImFont() Clear(); } -void ImFont::Clear() +void ImFont::Clear() { - FontSize = 0.0f; + FontSize = 0.0f; DisplayOffset = ImVec2(0.0f, 1.0f); Glyphs.clear(); IndexXAdvance.clear(); IndexLookup.clear(); - FallbackGlyph = NULL; + FallbackGlyph = NULL; FallbackXAdvance = 0.0f; - ConfigDataCount = 0; - ConfigData = NULL; - ContainerAtlas = NULL; - Ascent = Descent = 0.0f; + ConfigDataCount = 0; + ConfigData = NULL; + ContainerAtlas = NULL; + Ascent = Descent = 0.0f; MetricsTotalSurface = 0; } @@ -1740,31 +1898,31 @@ void ImFont::BuildLookupTable() GrowIndex(max_codepoint + 1); for (int i = 0; i < Glyphs.Size; i++) { - int codepoint = (int)Glyphs[i].Codepoint; + int codepoint = (int)Glyphs[i].Codepoint; IndexXAdvance[codepoint] = Glyphs[i].XAdvance; - IndexLookup[codepoint] = (unsigned short)i; + IndexLookup[codepoint] = (unsigned short)i; } // Create a glyph to handle TAB - // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?) + // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at + // "column 0" ?) if (FindGlyph((unsigned short)' ')) { - if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times + if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times Glyphs.resize(Glyphs.Size + 1); - ImFont::Glyph& tab_glyph = Glyphs.back(); - tab_glyph = *FindGlyph((unsigned short)' '); - tab_glyph.Codepoint = '\t'; + ImFont::Glyph &tab_glyph = Glyphs.back(); + tab_glyph = *FindGlyph((unsigned short)' '); + tab_glyph.Codepoint = '\t'; tab_glyph.XAdvance *= 4; IndexXAdvance[(int)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance; - IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size-1); + IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size - 1); } - FallbackGlyph = NULL; - FallbackGlyph = FindGlyph(FallbackChar); + FallbackGlyph = NULL; + FallbackGlyph = FindGlyph(FallbackChar); FallbackXAdvance = FallbackGlyph ? FallbackGlyph->XAdvance : 0.0f; for (int i = 0; i < max_codepoint + 1; i++) - if (IndexXAdvance[i] < 0.0f) - IndexXAdvance[i] = FallbackXAdvance; + if (IndexXAdvance[i] < 0.0f) IndexXAdvance[i] = FallbackXAdvance; } void ImFont::SetFallbackChar(ImWchar c) @@ -1777,20 +1935,20 @@ void ImFont::GrowIndex(int new_size) { IM_ASSERT(IndexXAdvance.Size == IndexLookup.Size); int old_size = IndexLookup.Size; - if (new_size <= old_size) - return; + if (new_size <= old_size) return; IndexXAdvance.resize(new_size); IndexLookup.resize(new_size); for (int i = old_size; i < new_size; i++) { IndexXAdvance[i] = -1.0f; - IndexLookup[i] = (unsigned short)-1; + IndexLookup[i] = (unsigned short)-1; } } void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) { - IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function. + IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling + // ImFontAtlas::GetTexDataAs*() function. int index_size = IndexLookup.Size; if (dst < index_size && IndexLookup.Data[dst] == (unsigned short)-1 && !overwrite_dst) // 'dst' already exists @@ -1799,25 +1957,25 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) return; GrowIndex(dst + 1); - IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (unsigned short)-1; + IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (unsigned short)-1; IndexXAdvance[dst] = (src < index_size) ? IndexXAdvance.Data[src] : 1.0f; } -const ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const +const ImFont::Glyph *ImFont::FindGlyph(unsigned short c) const { if (c < IndexLookup.Size) { const unsigned short i = IndexLookup[c]; - if (i != (unsigned short)-1) - return &Glyphs.Data[i]; + if (i != (unsigned short)-1) return &Glyphs.Data[i]; } return FallbackGlyph; } -const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const +const char *ImFont::CalcWordWrapPositionA(float scale, const char *text, const char *text_end, float wrap_width) const { // Simple word-wrapping for English, not full-featured. Please submit failing cases! - // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.) + // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible + // support for punctuations, support for Unicode punctuations, etc.) // For references, possible wrap point marked with ^ // "aaa bbb, ccc,ddd. eee fff. ggg!" @@ -1831,33 +1989,32 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c // Cut words that cannot possibly fit within one line. // e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish" - float line_width = 0.0f; - float word_width = 0.0f; + float line_width = 0.0f; + float word_width = 0.0f; float blank_width = 0.0f; - const char* word_end = text; - const char* prev_word_end = NULL; - bool inside_word = true; + const char *word_end = text; + const char *prev_word_end = NULL; + bool inside_word = true; - const char* s = text; + const char *s = text; while (s < text_end) { unsigned int c = (unsigned int)*s; - const char* next_s; + const char * next_s; if (c < 0x80) next_s = s + 1; else next_s = s + ImTextCharFromUtf8(&c, s, text_end); - if (c == 0) - break; + if (c == 0) break; if (c < 32) { if (c == '\n') { line_width = word_width = blank_width = 0.0f; - inside_word = true; - s = next_s; + inside_word = true; + s = next_s; continue; } if (c == '\r') @@ -1874,7 +2031,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c { line_width += blank_width; blank_width = 0.0f; - word_end = s; + word_end = s; } blank_width += char_width; inside_word = false; @@ -1882,10 +2039,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c else { word_width += char_width; - if (inside_word) - { - word_end = next_s; - } + if (inside_word) { word_end = next_s; } else { prev_word_end = word_end; @@ -1901,8 +2055,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c if (line_width + word_width >= wrap_width) { // Words that cannot possibly fit within an entire line will be cut anywhere. - if (word_width < wrap_width) - s = prev_word_end ? prev_word_end : word_end; + if (word_width < wrap_width) s = prev_word_end ? prev_word_end : word_end; break; } @@ -1912,58 +2065,66 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c return s; } -ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const +ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char *text_begin, const char *text_end, + const char **remaining) const { - if (!text_end) - text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. + if (!text_end) text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. const float line_height = size; - const float scale = size / FontSize; + const float scale = size / FontSize; - ImVec2 text_size = ImVec2(0,0); - float line_width = 0.0f; + ImVec2 text_size = ImVec2(0, 0); + float line_width = 0.0f; - const bool word_wrap_enabled = (wrap_width > 0.0f); - const char* word_wrap_eol = NULL; + const bool word_wrap_enabled = (wrap_width > 0.0f); + const char *word_wrap_eol = NULL; - const char* s = text_begin; + const char *s = text_begin; while (s < text_end) { if (word_wrap_enabled) { - // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. + // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive + // for what's essentially an uncommon feature. if (!word_wrap_eol) { word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width); - if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. - word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below + if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the + // height discontinuity. + word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= + // word_wrap_eol below } if (s >= word_wrap_eol) { - if (text_size.x < line_width) - text_size.x = line_width; + if (text_size.x < line_width) text_size.x = line_width; text_size.y += line_height; - line_width = 0.0f; + line_width = 0.0f; word_wrap_eol = NULL; // Wrapping skips upcoming blanks while (s < text_end) { const char c = *s; - if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } + if (ImCharIsSpace(c)) { s++; } + else if (c == '\n') + { + s++; + break; + } + else + { + break; + } } continue; } } // Decode and advance source - const char* prev_s = s; - unsigned int c = (unsigned int)*s; - if (c < 0x80) - { - s += 1; - } + const char * prev_s = s; + unsigned int c = (unsigned int)*s; + if (c < 0x80) { s += 1; } else { s += ImTextCharFromUtf8(&c, s, text_end); @@ -1980,8 +2141,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons line_width = 0.0f; continue; } - if (c == '\r') - continue; + if (c == '\r') continue; } const float char_width = ((int)c < IndexXAdvance.Size ? IndexXAdvance[(int)c] : FallbackXAdvance) * scale; @@ -1994,27 +2154,24 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons line_width += char_width; } - if (text_size.x < line_width) - text_size.x = line_width; + if (text_size.x < line_width) text_size.x = line_width; - if (line_width > 0 || text_size.y == 0.0f) - text_size.y += line_height; + if (line_width > 0 || text_size.y == 0.0f) text_size.y += line_height; - if (remaining) - *remaining = s; + if (remaining) *remaining = s; return text_size; } -void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const +void ImFont::RenderChar(ImDrawList *draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const { if (c == ' ' || c == '\t' || c == '\n' || c == '\r') // Match behavior of RenderText(), those 4 codepoints are hard-coded. return; - if (const Glyph* glyph = FindGlyph(c)) + if (const Glyph *glyph = FindGlyph(c)) { float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; - pos.x = (float)(int)pos.x + DisplayOffset.x; - pos.y = (float)(int)pos.y + DisplayOffset.y; + pos.x = (float)(int)pos.x + DisplayOffset.x; + pos.y = (float)(int)pos.y + DisplayOffset.y; ImVec2 pos_tl(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale); ImVec2 pos_br(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale); draw_list->PrimReserve(6, 4); @@ -2022,50 +2179,54 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col } } -void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const +void ImFont::RenderText(ImDrawList *draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4 &clip_rect, const char *text_begin, + const char *text_end, float wrap_width, bool cpu_fine_clip) const { if (!text_end) - text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls. + text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is + // merely to handle direct calls. // Align to be pixel perfect - pos.x = (float)(int)pos.x + DisplayOffset.x; - pos.y = (float)(int)pos.y + DisplayOffset.y; + pos.x = (float)(int)pos.x + DisplayOffset.x; + pos.y = (float)(int)pos.y + DisplayOffset.y; float x = pos.x; float y = pos.y; - if (y > clip_rect.w) - return; + if (y > clip_rect.w) return; - const float scale = size / FontSize; - const float line_height = FontSize * scale; - const bool word_wrap_enabled = (wrap_width > 0.0f); - const char* word_wrap_eol = NULL; + const float scale = size / FontSize; + const float line_height = FontSize * scale; + const bool word_wrap_enabled = (wrap_width > 0.0f); + const char *word_wrap_eol = NULL; // Skip non-visible lines - const char* s = text_begin; + const char *s = text_begin; if (!word_wrap_enabled && y + line_height < clip_rect.y) - while (s < text_end && *s != '\n') // Fast-forward to next line + while (s < text_end && *s != '\n') // Fast-forward to next line s++; // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized) - const int vtx_count_max = (int)(text_end - s) * 4; - const int idx_count_max = (int)(text_end - s) * 6; + const int vtx_count_max = (int)(text_end - s) * 4; + const int idx_count_max = (int)(text_end - s) * 6; const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max; draw_list->PrimReserve(idx_count_max, vtx_count_max); - ImDrawVert* vtx_write = draw_list->_VtxWritePtr; - ImDrawIdx* idx_write = draw_list->_IdxWritePtr; + ImDrawVert * vtx_write = draw_list->_VtxWritePtr; + ImDrawIdx * idx_write = draw_list->_IdxWritePtr; unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx; while (s < text_end) { if (word_wrap_enabled) { - // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. + // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive + // for what's essentially an uncommon feature. if (!word_wrap_eol) { word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x)); - if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. - word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below + if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the + // height discontinuity. + word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= + // word_wrap_eol below } if (s >= word_wrap_eol) @@ -2078,7 +2239,16 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col while (s < text_end) { const char c = *s; - if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } + if (ImCharIsSpace(c)) { s++; } + else if (c == '\n') + { + s++; + break; + } + else + { + break; + } } continue; } @@ -2086,10 +2256,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // Decode and advance source unsigned int c = (unsigned int)*s; - if (c < 0x80) - { - s += 1; - } + if (c < 0x80) { s += 1; } else { s += ImTextCharFromUtf8(&c, s, text_end); @@ -2104,26 +2271,25 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col x = pos.x; y += line_height; - if (y > clip_rect.w) - break; + if (y > clip_rect.w) break; if (!word_wrap_enabled && y + line_height < clip_rect.y) - while (s < text_end && *s != '\n') // Fast-forward to next line + while (s < text_end && *s != '\n') // Fast-forward to next line s++; continue; } - if (c == '\r') - continue; + if (c == '\r') continue; } float char_width = 0.0f; - if (const Glyph* glyph = FindGlyph((unsigned short)c)) + if (const Glyph *glyph = FindGlyph((unsigned short)c)) { char_width = glyph->XAdvance * scale; // Arbitrarily assume that both space and tabs are empty glyphs as an optimization if (c != ' ' && c != '\t') { - // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w + // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and + // exit once we pass clip_rect.w float x1 = x + glyph->X0 * scale; float x2 = x + glyph->X1 * scale; float y1 = y + glyph->Y0 * scale; @@ -2136,7 +2302,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col float u2 = glyph->U1; float v2 = glyph->V1; - // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads. + // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis + // aligned quads. if (cpu_fine_clip) { if (x1 < clip_rect.x) @@ -2169,12 +2336,32 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug build. // Inlined here: { - idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); - idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); - vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; - vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; - vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; - vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; + idx_write[0] = (ImDrawIdx)(vtx_current_idx); + idx_write[1] = (ImDrawIdx)(vtx_current_idx + 1); + idx_write[2] = (ImDrawIdx)(vtx_current_idx + 2); + idx_write[3] = (ImDrawIdx)(vtx_current_idx); + idx_write[4] = (ImDrawIdx)(vtx_current_idx + 2); + idx_write[5] = (ImDrawIdx)(vtx_current_idx + 3); + vtx_write[0].pos.x = x1; + vtx_write[0].pos.y = y1; + vtx_write[0].col = col; + vtx_write[0].uv.x = u1; + vtx_write[0].uv.y = v1; + vtx_write[1].pos.x = x2; + vtx_write[1].pos.y = y1; + vtx_write[1].col = col; + vtx_write[1].uv.x = u2; + vtx_write[1].uv.y = v1; + vtx_write[2].pos.x = x2; + vtx_write[2].pos.y = y2; + vtx_write[2].col = col; + vtx_write[2].uv.x = u2; + vtx_write[2].uv.y = v2; + vtx_write[3].pos.x = x1; + vtx_write[3].pos.y = y2; + vtx_write[3].col = col; + vtx_write[3].uv.x = u1; + vtx_write[3].uv.y = v2; vtx_write += 4; vtx_current_idx += 4; idx_write += 6; @@ -2189,9 +2376,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // Give back unused vertices draw_list->VtxBuffer.resize((int)(vtx_write - draw_list->VtxBuffer.Data)); draw_list->IdxBuffer.resize((int)(idx_write - draw_list->IdxBuffer.Data)); - draw_list->CmdBuffer[draw_list->CmdBuffer.Size-1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size); - draw_list->_VtxWritePtr = vtx_write; - draw_list->_IdxWritePtr = idx_write; + draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size); + draw_list->_VtxWritePtr = vtx_write; + draw_list->_IdxWritePtr = idx_write; draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size; } @@ -2210,41 +2397,70 @@ static unsigned int stb_decompress_length(unsigned char *input) static unsigned char *stb__barrier, *stb__barrier2, *stb__barrier3, *stb__barrier4; static unsigned char *stb__dout; -static void stb__match(unsigned char *data, unsigned int length) +static void stb__match(unsigned char *data, unsigned int length) { // INVERSE of memmove... write each byte before copying the next... - IM_ASSERT (stb__dout + length <= stb__barrier); - if (stb__dout + length > stb__barrier) { stb__dout += length; return; } - if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; } - while (length--) *stb__dout++ = *data++; + IM_ASSERT(stb__dout + length <= stb__barrier); + if (stb__dout + length > stb__barrier) + { + stb__dout += length; + return; + } + if (data < stb__barrier4) + { + stb__dout = stb__barrier + 1; + return; + } + while (length--) + *stb__dout++ = *data++; } static void stb__lit(unsigned char *data, unsigned int length) { - IM_ASSERT (stb__dout + length <= stb__barrier); - if (stb__dout + length > stb__barrier) { stb__dout += length; return; } - if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; } + IM_ASSERT(stb__dout + length <= stb__barrier); + if (stb__dout + length > stb__barrier) + { + stb__dout += length; + return; + } + if (data < stb__barrier2) + { + stb__dout = stb__barrier + 1; + return; + } memcpy(stb__dout, data, length); stb__dout += length; } -#define stb__in2(x) ((i[x] << 8) + i[(x)+1]) -#define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1)) -#define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1)) +#define stb__in2(x) ((i[x] << 8) + i[(x) + 1]) +#define stb__in3(x) ((i[x] << 16) + stb__in2((x) + 1)) +#define stb__in4(x) ((i[x] << 24) + stb__in3((x) + 1)) static unsigned char *stb_decompress_token(unsigned char *i) { - if (*i >= 0x20) { // use fewer if's for cases that expand small - if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2; - else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3; - else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); - } else { // more ifs for cases that expand large, since overhead is amortized - if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4; - else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5; - else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1); - else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1); - else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5; - else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6; + if (*i >= 0x20) + { // use fewer if's for cases that expand small + if (*i >= 0x80) + stb__match(stb__dout - i[1] - 1, i[0] - 0x80 + 1), i += 2; + else if (*i >= 0x40) + stb__match(stb__dout - (stb__in2(0) - 0x4000 + 1), i[2] + 1), i += 3; + else /* *i >= 0x20 */ + stb__lit(i + 1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); + } + else + { // more ifs for cases that expand large, since overhead is amortized + if (*i >= 0x18) + stb__match(stb__dout - (stb__in3(0) - 0x180000 + 1), i[3] + 1), i += 4; + else if (*i >= 0x10) + stb__match(stb__dout - (stb__in3(0) - 0x100000 + 1), stb__in2(3) + 1), i += 5; + else if (*i >= 0x08) + stb__lit(i + 2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1); + else if (*i == 0x07) + stb__lit(i + 3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1); + else if (*i == 0x06) + stb__match(stb__dout - (stb__in3(1) + 1), i[4] + 1), i += 5; + else if (*i == 0x04) + stb__match(stb__dout - (stb__in3(1) + 1), stb__in2(4) + 1), i += 6; } return i; } @@ -2252,12 +2468,14 @@ static unsigned char *stb_decompress_token(unsigned char *i) static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) { const unsigned long ADLER_MOD = 65521; - unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; - unsigned long blocklen, i; + unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; + unsigned long blocklen, i; blocklen = buflen % 5552; - while (buflen) { - for (i=0; i + 7 < blocklen; i += 8) { + while (buflen) + { + for (i = 0; i + 7 < blocklen; i += 8) + { s1 += buffer[0], s2 += s1; s1 += buffer[1], s2 += s1; s1 += buffer[2], s2 += s1; @@ -2284,33 +2502,36 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi { unsigned int olen; if (stb__in4(0) != 0x57bC0000) return 0; - if (stb__in4(4) != 0) return 0; // error! stream is > 4GB - olen = stb_decompress_length(i); + if (stb__in4(4) != 0) return 0; // error! stream is > 4GB + olen = stb_decompress_length(i); stb__barrier2 = i; - stb__barrier3 = i+length; - stb__barrier = output + olen; + stb__barrier3 = i + length; + stb__barrier = output + olen; stb__barrier4 = output; i += 16; stb__dout = output; - for (;;) { + for (;;) + { unsigned char *old_i = i; - i = stb_decompress_token(i); - if (i == old_i) { - if (*i == 0x05 && i[1] == 0xfa) { + i = stb_decompress_token(i); + if (i == old_i) + { + if (*i == 0x05 && i[1] == 0xfa) + { IM_ASSERT(stb__dout == output + olen); if (stb__dout != output + olen) return 0; - if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2)) - return 0; + if (stb_adler32(1, output, olen) != (unsigned int)stb__in4(2)) return 0; return olen; - } else { + } + else + { IM_ASSERT(0); /* NOTREACHED */ return 0; } } IM_ASSERT(stb__dout <= output + olen); - if (stb__dout > output + olen) - return 0; + if (stb__dout > output + olen) return 0; } } @@ -2323,95 +2544,184 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi // File: 'ProggyClean.ttf' (41208 bytes) // Exported using binary_to_compressed_c.cpp //----------------------------------------------------------------------------- -static const char proggy_clean_ttf_compressed_data_base85[11980+1] = - "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" - "2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`N" - "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+DNa&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc." - "x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`G" - "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)" - "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#" - "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM" - "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu" - "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/" - "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[Ket`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" - "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%" - "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]" - "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et" - "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:" - "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M" - "D?@f&1'BW-)Ju#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(" - "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs" - "bIu)'Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" - "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'N#(q%.O=?2S]u*(m<-" - "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" - "sZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P r+$%CE=68>K8r0=dSC%%(@p7" - ".m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@" - "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*" - "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u" - "@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/ae&#" - "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$so8lKN%5/$(vdfq7+ebA#" - "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" - "6e%B/:=>)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#" - "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjLV#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#SfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5" - "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%" - "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;" - "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:" - "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'm9)b@p7YsvK3w^YR-" - "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*" - "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-" - "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj" - "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa" - ">gXm8YB`1d@K#n]76-a$U,mF%Ul:#/'xoFM9QX-$.QN'>" - "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I" - "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)" - "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo" - "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P" - "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAO" - "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#" - ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T" - "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" - "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#" - "/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" - "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" +static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] = + "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/" + "e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" + "2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//" + "L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`N" + "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+" + "DNa&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/" + "MrTEH.IAQk.a>D[.e;mc." + "x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`G" + "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/" + "EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)" + "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>" + "$-?Tm$UV(?#P6YY#" + "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/" + "QTtG?-.*^N-4B/ZM" + "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu" + "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^" + "Fw&?D)UDNrocM3A76/" + "/oL?#h7gl85[qW/" + "NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<" + "L" + "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/" + "u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#" + "OQFKNX@QI'IoPp7nb,QU//" + "MQ&ZDkKP)Xet`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'" + "03'eM>&1XxY-caEnO" + "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/" + ":nnDq0(CYcMpG)qLN4$##&J-XTt,%OVU4)S1+R-#dg0/" + "Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%" + "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/" + ")Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]" + "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/" + "^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et" + "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//" + "c&iH&R8pRbA#Kjm%upV1g:" + "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#" + "4XAXN-U&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/" + "Xri.LRcB##=YL3BgM/3M" + "D?@f&1'BW-)Ju#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/" + "5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(" + "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/" + "V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs" + "bIu)'Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" + "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//" + ",]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'N#(q%.O=?2S]u*(m<-" + "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/" + "9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" + "sZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P r+$%CE=68>K8r0=dSC%%(@p7" + ".m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@" + "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/" + "m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*" + "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/" + ",;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u" + "@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/ae&#" + "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s" + "o8lKN%5/$(vdfq7+ebA#" + "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-" + "1pG_&2UdB8" + "6e%B/:=>)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/" + "`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#" + "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/" + "TQ:(Z^xBdLjLV#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#SfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/" + "Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5" + "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#" + "5wF)sP'##p#C0c%-Gb%" + "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//" + ")>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;" + "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/" + "R&CH+s'B;K-M6$EB%is00:" + "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/" + "FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'" + "m9)b@p7YsvK3w^YR-" + "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/" + "P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*" + "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-" + "S(qw%sf/@%#B6;/" + "U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/" + "Coh58KKhLj" + "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/" + "LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa" + ">gXm8YB`1d@K#n]76-a$U,mF%Ul:#" + "/'xoFM9QX-$.QN'>" + "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I" + "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/" + "6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/" + "72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_" + "KEBFkO'oU]^=[-792#ok,)" + "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/" + ",SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo" + "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%" + "ZVmj2bDi%.3L2n+4W'$P" + "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAO" + "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;" + "uM(.a..^2TkL%oR(#" + ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T" + "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/" + "X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/" + "1)K^f1-d>G21&v(35>V`39V7A4=onx4" + "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#" + "uvTB##-hB#'9$C#+E6C#" + "/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?" + "PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" + "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&" + "5o,^<-28ZI'O?;xp" "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; -static const char* GetDefaultCompressedFontDataTTFBase85() +static const char *GetDefaultCompressedFontDataTTFBase85() { return proggy_clean_ttf_compressed_data_base85; } diff --git a/source/main/gui/imgui/imgui_internal.h b/source/main/gui/imgui/imgui_internal.h index effc5ce7fb..bab8497ed7 100644 --- a/source/main/gui/imgui/imgui_internal.h +++ b/source/main/gui/imgui/imgui_internal.h @@ -1,29 +1,31 @@ // dear imgui, v1.50 WIP // (internals) -// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! -// Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) +// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward +// compatibility! Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along +// with your own math types+operators) // #define IMGUI_DEFINE_MATH_OPERATORS #pragma once #ifndef IMGUI_VERSION -#error Must include imgui.h before imgui_internal.h + #error Must include imgui.h before imgui_internal.h #endif -#include // FILE* -#include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf +#include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf +#include // FILE* #ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) + #pragma warning(push) + #pragma warning(disable : 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when + // IMGUI_API is set to__declspec(dllexport) #endif #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h -#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h -#pragma clang diagnostic ignored "-Wold-style-cast" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h + #pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h + #pragma clang diagnostic ignored "-Wold-style-cast" #endif //----------------------------------------------------------------------------- @@ -42,10 +44,10 @@ struct ImGuiMouseCursorData; struct ImGuiPopupRef; struct ImGuiWindow; -typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ -typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ -typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ -typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ +typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ +typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ +typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ +typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ //------------------------------------------------------------------------- // STB libraries @@ -56,9 +58,9 @@ namespace ImGuiStb #undef STB_TEXTEDIT_STRING #undef STB_TEXTEDIT_CHARTYPE -#define STB_TEXTEDIT_STRING ImGuiTextEditState -#define STB_TEXTEDIT_CHARTYPE ImWchar -#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f +#define STB_TEXTEDIT_STRING ImGuiTextEditState +#define STB_TEXTEDIT_CHARTYPE ImWchar +#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f #include "stb_textedit.h" } // namespace ImGuiStb @@ -68,83 +70,205 @@ namespace ImGuiStb //----------------------------------------------------------------------------- #ifndef GImGui -extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer +extern IMGUI_API ImGuiContext *GImGui; // Current implicit ImGui context pointer #endif //----------------------------------------------------------------------------- // Helpers //----------------------------------------------------------------------------- -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_PI 3.14159265358979323846f -#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*_ARR))) +#define IM_PI 3.14159265358979323846f +#define IM_OFFSETOF(_TYPE, _ELM) ((size_t) & (((_TYPE *)0)->_ELM)) // Helpers: UTF-8 <> wchar -IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count -IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count -IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count -IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) -IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points +IMGUI_API int ImTextStrToUtf8(char *buf, int buf_size, const ImWchar *in_text, + const ImWchar *in_text_end); // return output UTF-8 bytes count +IMGUI_API int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, + const char *in_text_end); // return input UTF-8 bytes count +IMGUI_API int ImTextStrFromUtf8(ImWchar *buf, int buf_size, const char *in_text, const char *in_text_end, + const char **in_remaining = NULL); // return input UTF-8 bytes count +IMGUI_API int ImTextCountCharsFromUtf8(const char *in_text, + const char *in_text_end); // return number of UTF-8 code-points (NOT bytes count) +IMGUI_API int ImTextCountUtf8BytesFromStr( + const ImWchar *in_text, const ImWchar *in_text_end); // return number of bytes to express string as UTF-8 code-points // Helpers: Misc -IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings -IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0); -IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode); -IMGUI_API bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c); -static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; } -static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } +IMGUI_API ImU32 ImHash(const void *data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings +IMGUI_API void *ImFileLoadToMemory(const char *filename, const char *file_open_mode, int *out_file_size = NULL, + int padding_bytes = 0); +IMGUI_API FILE * ImFileOpen(const char *filename, const char *file_open_mode); +IMGUI_API bool ImIsPointInTriangle(const ImVec2 &p, const ImVec2 &a, const ImVec2 &b, const ImVec2 &c); +static inline bool ImCharIsSpace(int c) +{ + return c == ' ' || c == '\t' || c == 0x3000; +} +static inline int ImUpperPowerOfTwo(int v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} // Helpers: String -IMGUI_API int ImStricmp(const char* str1, const char* str2); -IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count); -IMGUI_API char* ImStrdup(const char* str); -IMGUI_API int ImStrlenW(const ImWchar* str); -IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line -IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); -IMGUI_API int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_PRINTFARGS(3); -IMGUI_API int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args); +IMGUI_API int ImStricmp(const char *str1, const char *str2); +IMGUI_API int ImStrnicmp(const char *str1, const char *str2, int count); +IMGUI_API char *ImStrdup(const char *str); +IMGUI_API int ImStrlenW(const ImWchar *str); +IMGUI_API const ImWchar *ImStrbolW(const ImWchar *buf_mid_line, const ImWchar *buf_begin); // Find beginning-of-line +IMGUI_API const char * ImStristr(const char *haystack, const char *haystack_end, const char *needle, const char *needle_end); +IMGUI_API int ImFormatString(char *buf, int buf_size, const char *fmt, ...) IM_PRINTFARGS(3); +IMGUI_API int ImFormatStringV(char *buf, int buf_size, const char *fmt, va_list args); // Helpers: Math -// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined) +// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and +// its own types (when IM_VEC2_CLASS_EXTRA is defined) #ifdef IMGUI_DEFINE_MATH_OPERATORS -static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); } -static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); } -static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); } -static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); } -static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); } -static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); } -static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } -static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } -static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } -static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } -static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); } +static inline ImVec2 operator*(const ImVec2 &lhs, const float rhs) +{ + return ImVec2(lhs.x * rhs, lhs.y * rhs); +} +static inline ImVec2 operator/(const ImVec2 &lhs, const float rhs) +{ + return ImVec2(lhs.x / rhs, lhs.y / rhs); +} +static inline ImVec2 operator+(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); +} +static inline ImVec2 operator-(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); +} +static inline ImVec2 operator*(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); +} +static inline ImVec2 operator/(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); +} +static inline ImVec2 &operator+=(ImVec2 &lhs, const ImVec2 &rhs) +{ + lhs.x += rhs.x; + lhs.y += rhs.y; + return lhs; +} +static inline ImVec2 &operator-=(ImVec2 &lhs, const ImVec2 &rhs) +{ + lhs.x -= rhs.x; + lhs.y -= rhs.y; + return lhs; +} +static inline ImVec2 &operator*=(ImVec2 &lhs, const float rhs) +{ + lhs.x *= rhs; + lhs.y *= rhs; + return lhs; +} +static inline ImVec2 &operator/=(ImVec2 &lhs, const float rhs) +{ + lhs.x /= rhs; + lhs.y /= rhs; + return lhs; +} +static inline ImVec4 operator-(const ImVec4 &lhs, const ImVec4 &rhs) +{ + return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); +} #endif -static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; } -static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; } -static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; } -static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; } -static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); } -static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); } -static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } -static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } -static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; } -static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } -static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } -static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } -static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; } -static inline float ImFloor(float f) { return (float)(int)f; } -static inline ImVec2 ImFloor(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } +static inline int ImMin(int lhs, int rhs) +{ + return lhs < rhs ? lhs : rhs; +} +static inline int ImMax(int lhs, int rhs) +{ + return lhs >= rhs ? lhs : rhs; +} +static inline float ImMin(float lhs, float rhs) +{ + return lhs < rhs ? lhs : rhs; +} +static inline float ImMax(float lhs, float rhs) +{ + return lhs >= rhs ? lhs : rhs; +} +static inline ImVec2 ImMin(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(ImMin(lhs.x, rhs.x), ImMin(lhs.y, rhs.y)); +} +static inline ImVec2 ImMax(const ImVec2 &lhs, const ImVec2 &rhs) +{ + return ImVec2(ImMax(lhs.x, rhs.x), ImMax(lhs.y, rhs.y)); +} +static inline int ImClamp(int v, int mn, int mx) +{ + return (v < mn) ? mn : (v > mx) ? mx : v; +} +static inline float ImClamp(float v, float mn, float mx) +{ + return (v < mn) ? mn : (v > mx) ? mx : v; +} +static inline ImVec2 ImClamp(const ImVec2 &f, const ImVec2 &mn, ImVec2 mx) +{ + return ImVec2(ImClamp(f.x, mn.x, mx.x), ImClamp(f.y, mn.y, mx.y)); +} +static inline float ImSaturate(float f) +{ + return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; +} +static inline float ImLerp(float a, float b, float t) +{ + return a + (b - a) * t; +} +static inline ImVec2 ImLerp(const ImVec2 &a, const ImVec2 &b, const ImVec2 &t) +{ + return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); +} +static inline float ImLengthSqr(const ImVec2 &lhs) +{ + return lhs.x * lhs.x + lhs.y * lhs.y; +} +static inline float ImLengthSqr(const ImVec4 &lhs) +{ + return lhs.x * lhs.x + lhs.y * lhs.y + lhs.z * lhs.z + lhs.w * lhs.w; +} +static inline float ImInvLength(const ImVec2 &lhs, float fail_value) +{ + float d = lhs.x * lhs.x + lhs.y * lhs.y; + if (d > 0.0f) return 1.0f / sqrtf(d); + return fail_value; +} +static inline float ImFloor(float f) +{ + return (float)(int)f; +} +static inline ImVec2 ImFloor(ImVec2 v) +{ + return ImVec2((float)(int)v.x, (float)(int)v.y); +} // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. -// Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. +// Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains +// when user has disabled exceptions. #ifdef IMGUI_DEFINE_PLACEMENT_NEW -struct ImPlacementNewDummy {}; -inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; } -inline void operator delete(void*, ImPlacementNewDummy, void*) {} -#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR) +struct ImPlacementNewDummy +{ +}; +inline void *operator new(size_t, ImPlacementNewDummy, void *ptr) +{ + return ptr; +} +inline void operator delete(void *, ImPlacementNewDummy, void *) +{ +} + #define IM_PLACEMENT_NEW(_PTR) new (ImPlacementNewDummy(), _PTR) #endif //----------------------------------------------------------------------------- @@ -153,22 +277,24 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {} enum ImGuiButtonFlags_ { - ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat - ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set) - ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release) - ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release) - ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping - ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press - ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction - ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only - ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held - ImGuiButtonFlags_AllowOverlapMode = 1 << 10 // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat + ImGuiButtonFlags_PressedOnClickRelease = + 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set) + ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release) + ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release) + ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release) + ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping + ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press + ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction + ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only + ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held + ImGuiButtonFlags_AllowOverlapMode = + 1 << 10 // require previous frame HoveredId to either match id or be null before being usable }; enum ImGuiSliderFlags_ { - ImGuiSliderFlags_Vertical = 1 << 0 + ImGuiSliderFlags_Vertical = 1 << 0 }; enum ImGuiSelectableFlagsPrivate_ @@ -213,40 +339,126 @@ enum ImGuiCorner // NB: we can't rely on ImVec2 math operators being available here struct IMGUI_API ImRect { - ImVec2 Min; // Upper-left - ImVec2 Max; // Lower-right - - ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {} - ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} - ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} - ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} - - ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); } - ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); } - float GetWidth() const { return Max.x-Min.x; } - float GetHeight() const { return Max.y-Min.y; } - ImVec2 GetTL() const { return Min; } // Top-left - ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right - ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left - ImVec2 GetBR() const { return Max; } // Bottom-right - bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } - bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; } - bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } - void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; } - void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; } - void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } - void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } - void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } - void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } - void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } - ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const - { - if (!on_edge && Contains(p)) - return p; - if (p.x > Max.x) p.x = Max.x; - else if (p.x < Min.x) p.x = Min.x; - if (p.y > Max.y) p.y = Max.y; - else if (p.y < Min.y) p.y = Min.y; + ImVec2 Min; // Upper-left + ImVec2 Max; // Lower-right + + ImRect() : Min(FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX) + { + } + ImRect(const ImVec2 &min, const ImVec2 &max) : Min(min), Max(max) + { + } + ImRect(const ImVec4 &v) : Min(v.x, v.y), Max(v.z, v.w) + { + } + ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) + { + } + + ImVec2 GetCenter() const + { + return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); + } + ImVec2 GetSize() const + { + return ImVec2(Max.x - Min.x, Max.y - Min.y); + } + float GetWidth() const + { + return Max.x - Min.x; + } + float GetHeight() const + { + return Max.y - Min.y; + } + ImVec2 GetTL() const + { + return Min; + } // Top-left + ImVec2 GetTR() const + { + return ImVec2(Max.x, Min.y); + } // Top-right + ImVec2 GetBL() const + { + return ImVec2(Min.x, Max.y); + } // Bottom-left + ImVec2 GetBR() const + { + return Max; + } // Bottom-right + bool Contains(const ImVec2 &p) const + { + return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; + } + bool Contains(const ImRect &r) const + { + return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; + } + bool Overlaps(const ImRect &r) const + { + return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; + } + void Add(const ImVec2 &rhs) + { + if (Min.x > rhs.x) Min.x = rhs.x; + if (Min.y > rhs.y) Min.y = rhs.y; + if (Max.x < rhs.x) Max.x = rhs.x; + if (Max.y < rhs.y) Max.y = rhs.y; + } + void Add(const ImRect &rhs) + { + if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; + if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; + if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; + if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; + } + void Expand(const float amount) + { + Min.x -= amount; + Min.y -= amount; + Max.x += amount; + Max.y += amount; + } + void Expand(const ImVec2 &amount) + { + Min.x -= amount.x; + Min.y -= amount.y; + Max.x += amount.x; + Max.y += amount.y; + } + void Reduce(const ImVec2 &amount) + { + Min.x += amount.x; + Min.y += amount.y; + Max.x -= amount.x; + Max.y -= amount.y; + } + void Clip(const ImRect &clip) + { + if (Min.x < clip.Min.x) Min.x = clip.Min.x; + if (Min.y < clip.Min.y) Min.y = clip.Min.y; + if (Max.x > clip.Max.x) Max.x = clip.Max.x; + if (Max.y > clip.Max.y) Max.y = clip.Max.y; + } + void Floor() + { + Min.x = (float)(int)Min.x; + Min.y = (float)(int)Min.y; + Max.x = (float)(int)Max.x; + Max.y = (float)(int)Max.y; + } + ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const + { + if (!on_edge && Contains(p)) return p; + if (p.x > Max.x) + p.x = Max.x; + else if (p.x < Min.x) + p.x = Min.x; + if (p.y > Max.y) + p.y = Max.y; + else if (p.y < Min.y) + p.y = Min.y; return p; } }; @@ -254,275 +466,325 @@ struct IMGUI_API ImRect // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColMod { - ImGuiCol Col; - ImVec4 BackupValue; + ImGuiCol Col; + ImVec4 BackupValue; }; // Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. struct ImGuiStyleMod { - ImGuiStyleVar VarIdx; - union { int BackupInt[2]; float BackupFloat[2]; }; - ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } + ImGuiStyleVar VarIdx; + union { + int BackupInt[2]; + float BackupFloat[2]; + }; + ImGuiStyleMod(ImGuiStyleVar idx, int v) + { + VarIdx = idx; + BackupInt[0] = v; + } + ImGuiStyleMod(ImGuiStyleVar idx, float v) + { + VarIdx = idx; + BackupFloat[0] = v; + } + ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) + { + VarIdx = idx; + BackupFloat[0] = v.x; + BackupFloat[1] = v.y; + } }; // Stacked data for BeginGroup()/EndGroup() struct ImGuiGroupData { - ImVec2 BackupCursorPos; - ImVec2 BackupCursorMaxPos; - float BackupIndentX; - float BackupGroupOffsetX; - float BackupCurrentLineHeight; - float BackupCurrentLineTextBaseOffset; - float BackupLogLinePosY; - bool BackupActiveIdIsAlive; - bool AdvanceCursor; + ImVec2 BackupCursorPos; + ImVec2 BackupCursorMaxPos; + float BackupIndentX; + float BackupGroupOffsetX; + float BackupCurrentLineHeight; + float BackupCurrentLineTextBaseOffset; + float BackupLogLinePosY; + bool BackupActiveIdIsAlive; + bool AdvanceCursor; }; // Per column data for Columns() struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - //float IndentX; + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + // float IndentX; }; -// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. +// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic +// helper. struct IMGUI_API ImGuiSimpleColumns { - int Count; - float Spacing; - float Width, NextWidth; - float Pos[8], NextWidths[8]; + int Count; + float Spacing; + float Width, NextWidth; + float Pos[8], NextWidths[8]; ImGuiSimpleColumns(); - void Update(int count, float spacing, bool clear); - float DeclColumns(float w0, float w1, float w2); - float CalcExtraSpace(float avail_w); + void Update(int count, float spacing, bool clear); + float DeclColumns(float w0, float w1, float w2); + float CalcExtraSpace(float avail_w); }; // Internal state of the currently focused/edited text input box struct IMGUI_API ImGuiTextEditState { - ImGuiID Id; // widget id owning the text state - ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. - ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) - ImVector TempTextBuffer; - int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. - int BufSizeA; // end-user buffer size - float ScrollX; - ImGuiStb::STB_TexteditState StbState; - float CursorAnim; - bool CursorFollow; - bool SelectedAllMouseLock; - - ImGuiTextEditState() { memset(this, 0, sizeof(*this)); } - void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); } - bool HasSelection() const { return StbState.select_start != StbState.select_end; } - void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; } - void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; } - void OnKeyPressed(int key); + ImGuiID Id; // widget id owning the text state + ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so + // we copy into own buffer. + ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) + ImVector TempTextBuffer; + int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. + int BufSizeA; // end-user buffer size + float ScrollX; + ImGuiStb::STB_TexteditState StbState; + float CursorAnim; + bool CursorFollow; + bool SelectedAllMouseLock; + + ImGuiTextEditState() + { + memset(this, 0, sizeof(*this)); + } + void CursorAnimReset() + { + CursorAnim = -0.30f; + } // After a user-input the cursor stays on for a while without blinking + void CursorClamp() + { + StbState.cursor = ImMin(StbState.cursor, CurLenW); + StbState.select_start = ImMin(StbState.select_start, CurLenW); + StbState.select_end = ImMin(StbState.select_end, CurLenW); + } + bool HasSelection() const + { + return StbState.select_start != StbState.select_end; + } + void ClearSelection() + { + StbState.select_start = StbState.select_end = StbState.cursor; + } + void SelectAll() + { + StbState.select_start = 0; + StbState.select_end = CurLenW; + StbState.cursor = StbState.select_end; + StbState.has_preferred_x = false; + } + void OnKeyPressed(int key); }; // Data saved in imgui.ini file struct ImGuiIniData { - char* Name; - ImGuiID Id; - ImVec2 Pos; - ImVec2 Size; - bool Collapsed; + char * Name; + ImGuiID Id; + ImVec2 Pos; + ImVec2 Size; + bool Collapsed; }; // Mouse cursor data (used when io.MouseDrawCursor is set) struct ImGuiMouseCursorData { - ImGuiMouseCursor Type; - ImVec2 HotOffset; - ImVec2 Size; - ImVec2 TexUvMin[2]; - ImVec2 TexUvMax[2]; + ImGuiMouseCursor Type; + ImVec2 HotOffset; + ImVec2 Size; + ImVec2 TexUvMin[2]; + ImVec2 TexUvMax[2]; }; // Storage for current popup stack struct ImGuiPopupRef { - ImGuiID PopupId; // Set on OpenPopup() - ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* ParentWindow; // Set on OpenPopup() - ImGuiID ParentMenuSet; // Set on OpenPopup() - ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup + ImGuiID PopupId; // Set on OpenPopup() + ImGuiWindow *Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() + ImGuiWindow *ParentWindow; // Set on OpenPopup() + ImGuiID ParentMenuSet; // Set on OpenPopup() + ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup - ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } + ImGuiPopupRef(ImGuiID id, ImGuiWindow *parent_window, ImGuiID parent_menu_set, const ImVec2 &mouse_pos) + { + PopupId = id; + Window = NULL; + ParentWindow = parent_window; + ParentMenuSet = parent_menu_set; + MousePosOnOpen = mouse_pos; + } }; // Main state for ImGui struct ImGuiContext { - bool Initialized; - ImGuiIO IO; - ImGuiStyle Style; - ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() - float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize() - float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters. - ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel + bool Initialized; + ImGuiIO IO; + ImGuiStyle Style; + ImFont * Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() + float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize() + float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters. + ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel float Time; int FrameCount; int FrameCountEnded; int FrameCountRendered; - ImVector Windows; - ImVector WindowsSortBuffer; - ImGuiWindow* CurrentWindow; // Being drawn into - ImVector CurrentWindowStack; - ImGuiWindow* FocusedWindow; // Will catch keyboard inputs - ImGuiWindow* HoveredWindow; // Will catch mouse inputs - ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) - ImGuiID HoveredId; // Hovered widget + ImVector Windows; + ImVector WindowsSortBuffer; + ImGuiWindow * CurrentWindow; // Being drawn into + ImVector CurrentWindowStack; + ImGuiWindow * FocusedWindow; // Will catch keyboard inputs + ImGuiWindow * HoveredWindow; // Will catch mouse inputs + ImGuiWindow * HoveredRootWindow; // Will catch mouse inputs (for focus/move only) + ImGuiID HoveredId; // Hovered widget bool HoveredIdAllowOverlap; ImGuiID HoveredIdPreviousFrame; - ImGuiID ActiveId; // Active widget + ImGuiID ActiveId; // Active widget ImGuiID ActiveIdPreviousFrame; bool ActiveIdIsAlive; - bool ActiveIdIsJustActivated; // Set at the time of activation for one frame - bool ActiveIdAllowOverlap; // Set only by active widget - ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) - ImGuiWindow* ActiveIdWindow; - ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. - ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId - ImVector Settings; // .ini Settings - float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero - ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() - ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() - ImVector FontStack; // Stack for PushFont()/PopFont() - ImVector OpenPopupStack; // Which popups are open (persistent) - ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) + bool ActiveIdIsJustActivated; // Set at the time of activation for one frame + bool ActiveIdAllowOverlap; // Set only by active widget + ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) + ImGuiWindow * ActiveIdWindow; + ImGuiWindow * MovedWindow; // Track the child window we clicked on to move a window. + ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId + ImVector Settings; // .ini Settings + float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero + ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() + ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() + ImVector FontStack; // Stack for PushFont()/PopFont() + ImVector OpenPopupStack; // Which popups are open (persistent) + ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) // Storage for SetNexWindow** and SetNextTreeNode*** functions - ImVec2 SetNextWindowPosVal; - ImVec2 SetNextWindowSizeVal; - ImVec2 SetNextWindowContentSizeVal; - bool SetNextWindowCollapsedVal; - ImGuiSetCond SetNextWindowPosCond; - ImGuiSetCond SetNextWindowSizeCond; - ImGuiSetCond SetNextWindowContentSizeCond; - ImGuiSetCond SetNextWindowCollapsedCond; - ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true + ImVec2 SetNextWindowPosVal; + ImVec2 SetNextWindowSizeVal; + ImVec2 SetNextWindowContentSizeVal; + bool SetNextWindowCollapsedVal; + ImGuiSetCond SetNextWindowPosCond; + ImGuiSetCond SetNextWindowSizeCond; + ImGuiSetCond SetNextWindowContentSizeCond; + ImGuiSetCond SetNextWindowCollapsedCond; + ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback; - void* SetNextWindowSizeConstraintCallbackUserData; - bool SetNextWindowSizeConstraint; - bool SetNextWindowFocus; - bool SetNextTreeNodeOpenVal; - ImGuiSetCond SetNextTreeNodeOpenCond; + void * SetNextWindowSizeConstraintCallbackUserData; + bool SetNextWindowSizeConstraint; + bool SetNextWindowFocus; + bool SetNextTreeNodeOpenVal; + ImGuiSetCond SetNextTreeNodeOpenCond; // Render - ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user - ImVector RenderDrawLists[3]; - float ModalWindowDarkeningRatio; - ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays - ImGuiMouseCursor MouseCursor; - ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_]; + ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user + ImVector RenderDrawLists[3]; + float ModalWindowDarkeningRatio; + ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays + ImGuiMouseCursor MouseCursor; + ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_]; // Widget state - ImGuiTextEditState InputTextState; - ImFont InputTextPasswordFont; - ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. - ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode - float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings - ImVec2 DragLastMouseDelta; - float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio - float DragSpeedScaleSlow; - float DragSpeedScaleFast; - ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? - char Tooltip[1024]; - char* PrivateClipboard; // If no custom clipboard handler is defined - ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor + ImGuiTextEditState InputTextState; + ImFont InputTextPasswordFont; + ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. + ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode + float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings + ImVec2 DragLastMouseDelta; + float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio + float DragSpeedScaleSlow; + float DragSpeedScaleFast; + ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use + // storage? + char Tooltip[1024]; + char * PrivateClipboard; // If no custom clipboard handler is defined + ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor // Logging - bool LogEnabled; - FILE* LogFile; // If != NULL log to stdout/ file - ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. - int LogStartDepth; - int LogAutoExpandMaxDepth; + bool LogEnabled; + FILE *LogFile; // If != NULL log to stdout/ file + ImGuiTextBuffer + *LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. + int LogStartDepth; + int LogAutoExpandMaxDepth; // Misc - float FramerateSecPerFrame[120]; // calculate estimate of framerate for user - int FramerateSecPerFrameIdx; - float FramerateSecPerFrameAccum; - int CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags - int CaptureKeyboardNextFrame; - char TempBuffer[1024*3+1]; // temporary text buffer + float FramerateSecPerFrame[120]; // calculate estimate of framerate for user + int FramerateSecPerFrameIdx; + float FramerateSecPerFrameAccum; + int CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags + int CaptureKeyboardNextFrame; + char TempBuffer[1024 * 3 + 1]; // temporary text buffer ImGuiContext() { Initialized = false; - Font = NULL; + Font = NULL; FontSize = FontBaseSize = 0.0f; - FontTexUvWhitePixel = ImVec2(0.0f, 0.0f); + FontTexUvWhitePixel = ImVec2(0.0f, 0.0f); - Time = 0.0f; - FrameCount = 0; + Time = 0.0f; + FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; - CurrentWindow = NULL; - FocusedWindow = NULL; - HoveredWindow = NULL; - HoveredRootWindow = NULL; - HoveredId = 0; - HoveredIdAllowOverlap = false; - HoveredIdPreviousFrame = 0; - ActiveId = 0; - ActiveIdPreviousFrame = 0; - ActiveIdIsAlive = false; - ActiveIdIsJustActivated = false; - ActiveIdAllowOverlap = false; - ActiveIdClickOffset = ImVec2(-1,-1); - ActiveIdWindow = NULL; - MovedWindow = NULL; - MovedWindowMoveId = 0; - SettingsDirtyTimer = 0.0f; - - SetNextWindowPosVal = ImVec2(0.0f, 0.0f); - SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); - SetNextWindowCollapsedVal = false; - SetNextWindowPosCond = 0; - SetNextWindowSizeCond = 0; - SetNextWindowContentSizeCond = 0; - SetNextWindowCollapsedCond = 0; - SetNextWindowSizeConstraintRect = ImRect(); - SetNextWindowSizeConstraintCallback = NULL; + CurrentWindow = NULL; + FocusedWindow = NULL; + HoveredWindow = NULL; + HoveredRootWindow = NULL; + HoveredId = 0; + HoveredIdAllowOverlap = false; + HoveredIdPreviousFrame = 0; + ActiveId = 0; + ActiveIdPreviousFrame = 0; + ActiveIdIsAlive = false; + ActiveIdIsJustActivated = false; + ActiveIdAllowOverlap = false; + ActiveIdClickOffset = ImVec2(-1, -1); + ActiveIdWindow = NULL; + MovedWindow = NULL; + MovedWindowMoveId = 0; + SettingsDirtyTimer = 0.0f; + + SetNextWindowPosVal = ImVec2(0.0f, 0.0f); + SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); + SetNextWindowCollapsedVal = false; + SetNextWindowPosCond = 0; + SetNextWindowSizeCond = 0; + SetNextWindowContentSizeCond = 0; + SetNextWindowCollapsedCond = 0; + SetNextWindowSizeConstraintRect = ImRect(); + SetNextWindowSizeConstraintCallback = NULL; SetNextWindowSizeConstraintCallbackUserData = NULL; - SetNextWindowSizeConstraint = false; - SetNextWindowFocus = false; - SetNextTreeNodeOpenVal = false; - SetNextTreeNodeOpenCond = 0; - - ScalarAsInputTextId = 0; - DragCurrentValue = 0.0f; - DragLastMouseDelta = ImVec2(0.0f, 0.0f); - DragSpeedDefaultRatio = 1.0f / 100.0f; - DragSpeedScaleSlow = 0.01f; - DragSpeedScaleFast = 10.0f; + SetNextWindowSizeConstraint = false; + SetNextWindowFocus = false; + SetNextTreeNodeOpenVal = false; + SetNextTreeNodeOpenCond = 0; + + ScalarAsInputTextId = 0; + DragCurrentValue = 0.0f; + DragLastMouseDelta = ImVec2(0.0f, 0.0f); + DragSpeedDefaultRatio = 1.0f / 100.0f; + DragSpeedScaleSlow = 0.01f; + DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); memset(Tooltip, 0, sizeof(Tooltip)); PrivateClipboard = NULL; OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); - ModalWindowDarkeningRatio = 0.0f; + ModalWindowDarkeningRatio = 0.0f; OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging - MouseCursor = ImGuiMouseCursor_Arrow; + MouseCursor = ImGuiMouseCursor_Arrow; memset(MouseCursorData, 0, sizeof(MouseCursorData)); - LogEnabled = false; - LogFile = NULL; - LogClipboard = NULL; - LogStartDepth = 0; + LogEnabled = false; + LogFile = NULL; + LogClipboard = NULL; + LogStartDepth = 0; LogAutoExpandMaxDepth = 2; memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); - FramerateSecPerFrameIdx = 0; + FramerateSecPerFrameIdx = 0; FramerateSecPerFrameAccum = 0.0f; CaptureMouseNextFrame = CaptureKeyboardNextFrame = -1; memset(TempBuffer, 0, sizeof(TempBuffer)); @@ -530,54 +792,61 @@ struct ImGuiContext }; // Transient per-window data, reset at the beginning of the frame -// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered. +// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be +// reconsidered. struct IMGUI_API ImGuiDrawContext { - ImVec2 CursorPos; - ImVec2 CursorPosPrevLine; - ImVec2 CursorStartPos; - ImVec2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame - float CurrentLineHeight; - float CurrentLineTextBaseOffset; - float PrevLineHeight; - float PrevLineTextBaseOffset; - float LogLinePosY; - int TreeDepth; - ImGuiID LastItemId; - ImRect LastItemRect; - bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) - bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) + ImVec2 CursorPos; + ImVec2 CursorPosPrevLine; + ImVec2 CursorStartPos; + ImVec2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at + // the end of the frame + float CurrentLineHeight; + float CurrentLineTextBaseOffset; + float PrevLineHeight; + float PrevLineTextBaseOffset; + float LogLinePosY; + int TreeDepth; + ImGuiID LastItemId; + ImRect LastItemRect; + bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a + // popup preventing access to the window) + bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be + // blocked by a popup preventing access to the window) bool MenuBarAppending; float MenuBarOffsetX; - ImVector ChildWindows; - ImGuiStorage* StateStorage; + ImVector ChildWindows; + ImGuiStorage * StateStorage; ImGuiLayoutType LayoutType; - // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. - float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window - float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] - bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] - bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] - ImVector ItemWidthStack; - ImVector TextWrapPosStack; - ImVector AllowKeyboardFocusStack; - ImVector ButtonRepeatStack; - ImVectorGroupStack; - ImGuiColorEditMode ColorEditMode; - int StackSizesBackup[6]; // Store size of various stacks for asserting - - float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) - float GroupOffsetX; - float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsCellMinY; - float ColumnsCellMaxY; - bool ColumnsShowBorders; - ImGuiID ColumnsSetId; + // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are + // rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. + float + ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window + float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] + bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] + bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] + ImVector ItemWidthStack; + ImVector TextWrapPosStack; + ImVector AllowKeyboardFocusStack; + ImVector ButtonRepeatStack; + ImVector GroupStack; + ImGuiColorEditMode ColorEditMode; + int StackSizesBackup[6]; // Store size of various stacks for asserting + + float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) + float GroupOffsetX; + float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to + // allow use cases like Tree->Column->Tree. Need revamp columns API. + int ColumnsCurrent; + int ColumnsCount; + float ColumnsMinX; + float ColumnsMaxX; + float ColumnsStartPosY; + float ColumnsCellMinY; + float ColumnsCellMaxY; + bool ColumnsShowBorders; + ImGuiID ColumnsSetId; ImVector ColumnsData; ImGuiDrawContext() @@ -585,109 +854,137 @@ struct IMGUI_API ImGuiDrawContext CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f); CurrentLineHeight = PrevLineHeight = 0.0f; CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; - LogLinePosY = -1.0f; - TreeDepth = 0; - LastItemId = 0; - LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); + LogLinePosY = -1.0f; + TreeDepth = 0; + LastItemId = 0; + LastItemRect = ImRect(0.0f, 0.0f, 0.0f, 0.0f); LastItemHoveredAndUsable = LastItemHoveredRect = false; - MenuBarAppending = false; - MenuBarOffsetX = 0.0f; - StateStorage = NULL; - LayoutType = ImGuiLayoutType_Vertical; - ItemWidth = 0.0f; - ButtonRepeat = false; - AllowKeyboardFocus = true; - TextWrapPos = -1.0f; - ColorEditMode = ImGuiColorEditMode_RGB; + MenuBarAppending = false; + MenuBarOffsetX = 0.0f; + StateStorage = NULL; + LayoutType = ImGuiLayoutType_Vertical; + ItemWidth = 0.0f; + ButtonRepeat = false; + AllowKeyboardFocus = true; + TextWrapPos = -1.0f; + ColorEditMode = ImGuiColorEditMode_RGB; memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); - IndentX = 0.0f; - GroupOffsetX = 0.0f; + IndentX = 0.0f; + GroupOffsetX = 0.0f; ColumnsOffsetX = 0.0f; ColumnsCurrent = 0; - ColumnsCount = 1; + ColumnsCount = 1; ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; + ColumnsStartPosY = 0.0f; ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsShowBorders = true; - ColumnsSetId = 0; + ColumnsShowBorders = true; + ColumnsSetId = 0; } }; // Windows data struct IMGUI_API ImGuiWindow { - char* Name; - ImGuiID ID; // == ImHash(Name) - ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ - int IndexWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. - ImVec2 PosFloat; - ImVec2 Pos; // Position rounded-up to nearest pixel - ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) - ImVec2 SizeFull; // Size when non collapsed - ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame - ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() - ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis - ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect - ImGuiID MoveId; // == window->GetID("#MOVE") - ImVec2 Scroll; - ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) - ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered - bool ScrollbarX, ScrollbarY; - ImVec2 ScrollbarSizes; - float BorderSize; - bool Active; // Set to true on Begin() - bool WasActive; - bool Accessed; // Set to true when any widget access the current window - bool Collapsed; // Set when collapsing window to become only title-bar - bool SkipItems; // == Visible && !Collapsed - int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) - ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - int AutoFitFramesX, AutoFitFramesY; - bool AutoFitOnlyGrows; - int AutoPosLastDirection; - int HiddenFrames; - int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. - int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. - int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. - bool SetWindowPosCenterWanted; - - ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame - ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack - ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. - ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. - int LastFrameActive; - float ItemWidthDefault; - ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items - ImGuiStorage StateStorage; - float FontWindowScale; // Scale multiplier per-window - ImDrawList* DrawList; - ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. - ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself. - ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL. + char * Name; + ImGuiID ID; // == ImHash(Name) + ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ + int IndexWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. + ImVec2 PosFloat; + ImVec2 Pos; // Position rounded-up to nearest pixel + ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) + ImVec2 SizeFull; // Size when non collapsed + ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame + ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() + ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? + // SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis + ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder + // would have an effect + ImGuiID MoveId; // == window->GetID("#MOVE") + ImVec2 Scroll; + ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is + // always 0.0f. (FLT_MAX for no change) + ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is + // centered + bool ScrollbarX, ScrollbarY; + ImVec2 ScrollbarSizes; + float BorderSize; + bool Active; // Set to true on Begin() + bool WasActive; + bool Accessed; // Set to true when any widget access the current window + bool Collapsed; // Set when collapsing window to become only title-bar + bool SkipItems; // == Visible && !Collapsed + int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) + ImGuiID + PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) + int AutoFitFramesX, AutoFitFramesY; + bool AutoFitOnlyGrows; + int AutoPosLastDirection; + int HiddenFrames; + int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. + int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. + int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this + // particular flag. + bool SetWindowPosCenterWanted; + + ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame + ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack + ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. + ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. + int LastFrameActive; + float ItemWidthDefault; + ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items + ImGuiStorage StateStorage; + float FontWindowScale; // Scale multiplier per-window + ImDrawList * DrawList; + ImGuiWindow + *RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. + ImGuiWindow *RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. + // Else point to ourself. + ImGuiWindow *ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL. // Navigation / Focus - int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() - int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) - int FocusIdxAllRequestCurrent; // Item being requested for focus - int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus - int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame) - int FocusIdxTabRequestNext; // " - -public: - ImGuiWindow(const char* name); + int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() + int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) + int FocusIdxAllRequestCurrent; // Item being requested for focus + int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus + int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the + // frame pressing TAB and the next frame) + int FocusIdxTabRequestNext; // " + + public: + ImGuiWindow(const char *name); ~ImGuiWindow(); - ImGuiID GetID(const char* str, const char* str_end = NULL); - ImGuiID GetID(const void* ptr); - ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); + ImGuiID GetID(const char *str, const char *str_end = NULL); + ImGuiID GetID(const void *ptr); + ImGuiID GetIDNoKeepAlive(const char *str, const char *str_end = NULL); - ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } - float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } - float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; } - ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } - float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } - ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } + ImRect Rect() const + { + return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); + } + float CalcFontSize() const + { + return GImGui->FontBaseSize * FontWindowScale; + } + float TitleBarHeight() const + { + return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; + } + ImRect TitleBarRect() const + { + return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); + } + float MenuBarHeight() const + { + return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; + } + ImRect MenuBarRect() const + { + float y1 = Pos.y + TitleBarHeight(); + return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); + } }; //----------------------------------------------------------------------------- @@ -701,76 +998,105 @@ namespace ImGui // If this ever crash because g.CurrentWindow is NULL it means that either // - ImGui::NewFrame() has never been called, which is illegal. // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. - inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } - inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; } - IMGUI_API ImGuiWindow* GetParentWindow(); - IMGUI_API ImGuiWindow* FindWindowByName(const char* name); - IMGUI_API void FocusWindow(ImGuiWindow* window); - - IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! - - IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void ClearActiveID(); - IMGUI_API void SetHoveredID(ImGuiID id); - IMGUI_API void KeepAliveID(ImGuiID id); - - IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); - IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); - IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); - IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); - IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false); - IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested - IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); - IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); - IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); - - IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); + inline ImGuiWindow *GetCurrentWindowRead() + { + ImGuiContext &g = *GImGui; + return g.CurrentWindow; + } + inline ImGuiWindow *GetCurrentWindow() + { + ImGuiContext &g = *GImGui; + g.CurrentWindow->Accessed = true; + return g.CurrentWindow; + } + IMGUI_API ImGuiWindow *GetParentWindow(); + IMGUI_API ImGuiWindow *FindWindowByName(const char *name); + IMGUI_API void FocusWindow(ImGuiWindow *window); + + IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call + // that yourself directly. If you don't need to render you can call EndFrame() but you'll have + // wasted CPU already. If you don't need to render, don't create any windows instead! + + IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow *window); + IMGUI_API void ClearActiveID(); + IMGUI_API void SetHoveredID(ImGuiID id); + IMGUI_API void KeepAliveID(ImGuiID id); + + IMGUI_API void ItemSize(const ImVec2 &size, float text_offset_y = 0.0f); + IMGUI_API void ItemSize(const ImRect &bb, float text_offset_y = 0.0f); + IMGUI_API bool ItemAdd(const ImRect &bb, const ImGuiID *id); + IMGUI_API bool IsClippedEx(const ImRect &bb, const ImGuiID *id, bool clip_even_when_logged); + IMGUI_API bool IsHovered(const ImRect &bb, ImGuiID id, bool flatten_childs = false); + IMGUI_API bool FocusableItemRegister(ImGuiWindow *window, bool is_active, + bool tab_stop = true); // Return true if focus is requested + IMGUI_API void FocusableItemUnregister(ImGuiWindow *window); + IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); + IMGUI_API float CalcWrapWidthForPos(const ImVec2 &pos, float wrap_pos_x); + + IMGUI_API void OpenPopupEx(const char *str_id, bool reopen_existing); // NB: All position are in absolute pixels coordinates (not window coordinates) - // FIXME: All those functions are a mess and needs to be refactored into something decent. AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. - // We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers. - IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); - IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); - IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); - IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f); - IMGUI_API void RenderBullet(ImVec2 pos); - IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); - IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. - - IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); - IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); - IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); - - IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format); - - IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power); - IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format); - - IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); - - IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); - IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging - IMGUI_API void TreePushRawID(ImGuiID id); - - IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); - - IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); - IMGUI_API float RoundScalar(float value, int decimal_precision); + // FIXME: All those functions are a mess and needs to be refactored into something decent. AVOID USING OUTSIDE OF IMGUI.CPP! + // NOT FOR PUBLIC CONSUMPTION. We need: a sort of symbol library, preferably baked into font atlas when possible + decent text + // rendering helpers. + IMGUI_API void RenderText(ImVec2 pos, const char *text, const char *text_end = NULL, bool hide_text_after_hash = true); + IMGUI_API void RenderTextWrapped(ImVec2 pos, const char *text, const char *text_end, float wrap_width); + IMGUI_API void RenderTextClipped(const ImVec2 &pos_min, const ImVec2 &pos_max, const char *text, const char *text_end, + const ImVec2 *text_size_if_known, const ImVec2 &align = ImVec2(0, 0), + const ImRect *clip_rect = NULL); + IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); + IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f); + IMGUI_API void RenderBullet(ImVec2 pos); + IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); + IMGUI_API const char *FindRenderedTextEnd( + const char *text, const char *text_end = NULL); // Find the optional ## from which we stop displaying text. + + IMGUI_API bool ButtonBehavior(const ImRect &bb, ImGuiID id, bool *out_hovered, bool *out_held, ImGuiButtonFlags flags = 0); + IMGUI_API bool ButtonEx(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); + IMGUI_API bool CloseButton(ImGuiID id, const ImVec2 &pos, float radius); + + IMGUI_API bool SliderBehavior(const ImRect &frame_bb, ImGuiID id, float *v, float v_min, float v_max, float power, + int decimal_precision, ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloatN(const char *label, float *v, int components, float v_min, float v_max, const char *display_format, + float power); + IMGUI_API bool SliderIntN(const char *label, int *v, int components, int v_min, int v_max, const char *display_format); + + IMGUI_API bool DragBehavior(const ImRect &frame_bb, ImGuiID id, float *v, float v_speed, float v_min, float v_max, + int decimal_precision, float power); + IMGUI_API bool DragFloatN(const char *label, float *v, int components, float v_speed, float v_min, float v_max, + const char *display_format, float power); + IMGUI_API bool DragIntN(const char *label, int *v, int components, float v_speed, int v_min, int v_max, + const char *display_format); + + IMGUI_API bool InputTextEx(const char *label, char *buf, int buf_size, const ImVec2 &size_arg, ImGuiInputTextFlags flags, + ImGuiTextEditCallback callback = NULL, void *user_data = NULL); + IMGUI_API bool InputFloatN(const char *label, float *v, int components, int decimal_precision, + ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputIntN(const char *label, int *v, int components, ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputScalarEx(const char *label, ImGuiDataType data_type, void *data_ptr, void *step_ptr, void *step_fast_ptr, + const char *scalar_format, ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect &aabb, const char *label, ImGuiDataType data_type, void *data_ptr, + ImGuiID id, int decimal_precision); + + IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char *label, const char *label_end = NULL); + IMGUI_API bool TreeNodeBehaviorIsOpen( + ImGuiID id, + ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging + IMGUI_API void TreePushRawID(ImGuiID id); + + IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char *label, float (*values_getter)(void *data, int idx), void *data, + int values_count, int values_offset, const char *overlay_text, float scale_min, float scale_max, + ImVec2 graph_size); + + IMGUI_API int ParseFormatPrecision(const char *fmt, int default_value); + IMGUI_API float RoundScalar(float value, int decimal_precision); } // namespace ImGui #ifdef __clang__ -#pragma clang diagnostic pop + #pragma clang diagnostic pop #endif #ifdef _MSC_VER -#pragma warning (pop) + #pragma warning(pop) #endif diff --git a/source/main/gui/imgui/stb_rect_pack.h b/source/main/gui/imgui/stb_rect_pack.h index 5eef82efe1..a73a638730 100644 --- a/source/main/gui/imgui/stb_rect_pack.h +++ b/source/main/gui/imgui/stb_rect_pack.h @@ -55,128 +55,126 @@ #ifndef STB_INCLUDE_STB_RECT_PACK_H #define STB_INCLUDE_STB_RECT_PACK_H -#define STB_RECT_PACK_VERSION 1 +#define STB_RECT_PACK_VERSION 1 #ifdef STBRP_STATIC -#define STBRP_DEF static + #define STBRP_DEF static #else -#define STBRP_DEF extern + #define STBRP_DEF extern #endif #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef struct stbrp_context stbrp_context; -typedef struct stbrp_node stbrp_node; -typedef struct stbrp_rect stbrp_rect; + typedef struct stbrp_context stbrp_context; + typedef struct stbrp_node stbrp_node; + typedef struct stbrp_rect stbrp_rect; #ifdef STBRP_LARGE_RECTS -typedef int stbrp_coord; + typedef int stbrp_coord; #else typedef unsigned short stbrp_coord; #endif -STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); -// Assign packed locations to rectangles. The rectangles are of type -// 'stbrp_rect' defined below, stored in the array 'rects', and there -// are 'num_rects' many of them. -// -// Rectangles which are successfully packed have the 'was_packed' flag -// set to a non-zero value and 'x' and 'y' store the minimum location -// on each axis (i.e. bottom-left in cartesian coordinates, top-left -// if you imagine y increasing downwards). Rectangles which do not fit -// have the 'was_packed' flag set to 0. -// -// You should not try to access the 'rects' array from another thread -// while this function is running, as the function temporarily reorders -// the array while it executes. -// -// To pack into another rectangle, you need to call stbrp_init_target -// again. To continue packing into the same rectangle, you can call -// this function again. Calling this multiple times with multiple rect -// arrays will probably produce worse packing results than calling it -// a single time with the full rectangle array, but the option is -// available. - -struct stbrp_rect -{ - // reserved for your use: - int id; - - // input: - stbrp_coord w, h; - - // output: - stbrp_coord x, y; - int was_packed; // non-zero if valid packing - -}; // 16 bytes, nominally - - -STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); -// Initialize a rectangle packer to: -// pack a rectangle that is 'width' by 'height' in dimensions -// using temporary storage provided by the array 'nodes', which is 'num_nodes' long -// -// You must call this function every time you start packing into a new target. -// -// There is no "shutdown" function. The 'nodes' memory must stay valid for -// the following stbrp_pack_rects() call (or calls), but can be freed after -// the call (or calls) finish. -// -// Note: to guarantee best results, either: -// 1. make sure 'num_nodes' >= 'width' -// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' -// -// If you don't do either of the above things, widths will be quantized to multiples -// of small integers to guarantee the algorithm doesn't run out of temporary storage. -// -// If you do #2, then the non-quantized algorithm will be used, but the algorithm -// may run out of temporary storage and be unable to pack some rectangles. - -STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); -// Optionally call this function after init but before doing any packing to -// change the handling of the out-of-temp-memory scenario, described above. -// If you call init again, this will be reset to the default (false). - - -STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); -// Optionally select which packing heuristic the library should use. Different -// heuristics will produce better/worse results for different data sets. -// If you call init again, this will be reset to the default. - -enum -{ - STBRP_HEURISTIC_Skyline_default=0, - STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, - STBRP_HEURISTIC_Skyline_BF_sortHeight -}; - - -////////////////////////////////////////////////////////////////////////////// -// -// the details of the following structures don't matter to you, but they must -// be visible so you can handle the memory allocations for them - -struct stbrp_node -{ - stbrp_coord x,y; - stbrp_node *next; -}; - -struct stbrp_context -{ - int width; - int height; - int align; - int init_mode; - int heuristic; - int num_nodes; - stbrp_node *active_head; - stbrp_node *free_head; - stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' -}; + STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects); + // Assign packed locations to rectangles. The rectangles are of type + // 'stbrp_rect' defined below, stored in the array 'rects', and there + // are 'num_rects' many of them. + // + // Rectangles which are successfully packed have the 'was_packed' flag + // set to a non-zero value and 'x' and 'y' store the minimum location + // on each axis (i.e. bottom-left in cartesian coordinates, top-left + // if you imagine y increasing downwards). Rectangles which do not fit + // have the 'was_packed' flag set to 0. + // + // You should not try to access the 'rects' array from another thread + // while this function is running, as the function temporarily reorders + // the array while it executes. + // + // To pack into another rectangle, you need to call stbrp_init_target + // again. To continue packing into the same rectangle, you can call + // this function again. Calling this multiple times with multiple rect + // arrays will probably produce worse packing results than calling it + // a single time with the full rectangle array, but the option is + // available. + + struct stbrp_rect + { + // reserved for your use: + int id; + + // input: + stbrp_coord w, h; + + // output: + stbrp_coord x, y; + int was_packed; // non-zero if valid packing + + }; // 16 bytes, nominally + + STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); + // Initialize a rectangle packer to: + // pack a rectangle that is 'width' by 'height' in dimensions + // using temporary storage provided by the array 'nodes', which is 'num_nodes' long + // + // You must call this function every time you start packing into a new target. + // + // There is no "shutdown" function. The 'nodes' memory must stay valid for + // the following stbrp_pack_rects() call (or calls), but can be freed after + // the call (or calls) finish. + // + // Note: to guarantee best results, either: + // 1. make sure 'num_nodes' >= 'width' + // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' + // + // If you don't do either of the above things, widths will be quantized to multiples + // of small integers to guarantee the algorithm doesn't run out of temporary storage. + // + // If you do #2, then the non-quantized algorithm will be used, but the algorithm + // may run out of temporary storage and be unable to pack some rectangles. + + STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem); + // Optionally call this function after init but before doing any packing to + // change the handling of the out-of-temp-memory scenario, described above. + // If you call init again, this will be reset to the default (false). + + STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic); + // Optionally select which packing heuristic the library should use. Different + // heuristics will produce better/worse results for different data sets. + // If you call init again, this will be reset to the default. + + enum + { + STBRP_HEURISTIC_Skyline_default = 0, + STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, + STBRP_HEURISTIC_Skyline_BF_sortHeight + }; + + ////////////////////////////////////////////////////////////////////////////// + // + // the details of the following structures don't matter to you, but they must + // be visible so you can handle the memory allocations for them + + struct stbrp_node + { + stbrp_coord x, y; + stbrp_node *next; + }; + + struct stbrp_context + { + int width; + int height; + int align; + int init_mode; + int heuristic; + int num_nodes; + stbrp_node *active_head; + stbrp_node *free_head; + stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' + }; #ifdef __cplusplus } @@ -191,368 +189,393 @@ struct stbrp_context #ifdef STB_RECT_PACK_IMPLEMENTATION #ifndef STBRP_SORT -#include -#define STBRP_SORT qsort + #include + #define STBRP_SORT qsort #endif #ifndef STBRP_ASSERT -#include -#define STBRP_ASSERT assert + #include + #define STBRP_ASSERT assert #endif #ifdef _MSC_VER -#define STBRP__NOTUSED(v) (void)(v) + #define STBRP__NOTUSED(v) (void)(v) #else -#define STBRP__NOTUSED(v) (void)sizeof(v) + #define STBRP__NOTUSED(v) (void)sizeof(v) #endif enum { - STBRP__INIT_skyline = 1 + STBRP__INIT_skyline = 1 }; STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) { - switch (context->init_mode) { - case STBRP__INIT_skyline: - STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); - context->heuristic = heuristic; - break; - default: - STBRP_ASSERT(0); - } + switch (context->init_mode) + { + case STBRP__INIT_skyline: + STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); + context->heuristic = heuristic; + break; + default: STBRP_ASSERT(0); + } } STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) { - if (allow_out_of_mem) - // if it's ok to run out of memory, then don't bother aligning them; - // this gives better packing, but may fail due to OOM (even though - // the rectangles easily fit). @TODO a smarter approach would be to only - // quantize once we've hit OOM, then we could get rid of this parameter. - context->align = 1; - else { - // if it's not ok to run out of memory, then quantize the widths - // so that num_nodes is always enough nodes. - // - // I.e. num_nodes * align >= width - // align >= width / num_nodes - // align = ceil(width/num_nodes) - - context->align = (context->width + context->num_nodes-1) / context->num_nodes; - } + if (allow_out_of_mem) + // if it's ok to run out of memory, then don't bother aligning them; + // this gives better packing, but may fail due to OOM (even though + // the rectangles easily fit). @TODO a smarter approach would be to only + // quantize once we've hit OOM, then we could get rid of this parameter. + context->align = 1; + else + { + // if it's not ok to run out of memory, then quantize the widths + // so that num_nodes is always enough nodes. + // + // I.e. num_nodes * align >= width + // align >= width / num_nodes + // align = ceil(width/num_nodes) + + context->align = (context->width + context->num_nodes - 1) / context->num_nodes; + } } STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) { - int i; + int i; #ifndef STBRP_LARGE_RECTS - STBRP_ASSERT(width <= 0xffff && height <= 0xffff); + STBRP_ASSERT(width <= 0xffff && height <= 0xffff); #endif - for (i=0; i < num_nodes-1; ++i) - nodes[i].next = &nodes[i+1]; - nodes[i].next = NULL; - context->init_mode = STBRP__INIT_skyline; - context->heuristic = STBRP_HEURISTIC_Skyline_default; - context->free_head = &nodes[0]; - context->active_head = &context->extra[0]; - context->width = width; - context->height = height; - context->num_nodes = num_nodes; - stbrp_setup_allow_out_of_mem(context, 0); - - // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) - context->extra[0].x = 0; - context->extra[0].y = 0; - context->extra[0].next = &context->extra[1]; - context->extra[1].x = (stbrp_coord) width; + for (i = 0; i < num_nodes - 1; ++i) + nodes[i].next = &nodes[i + 1]; + nodes[i].next = NULL; + context->init_mode = STBRP__INIT_skyline; + context->heuristic = STBRP_HEURISTIC_Skyline_default; + context->free_head = &nodes[0]; + context->active_head = &context->extra[0]; + context->width = width; + context->height = height; + context->num_nodes = num_nodes; + stbrp_setup_allow_out_of_mem(context, 0); + + // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) + context->extra[0].x = 0; + context->extra[0].y = 0; + context->extra[0].next = &context->extra[1]; + context->extra[1].x = (stbrp_coord)width; #ifdef STBRP_LARGE_RECTS - context->extra[1].y = (1<<30); + context->extra[1].y = (1 << 30); #else - context->extra[1].y = 65535; + context->extra[1].y = 65535; #endif - context->extra[1].next = NULL; + context->extra[1].next = NULL; } // find minimum y position if it starts at x1 static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) { - stbrp_node *node = first; - int x1 = x0 + width; - int min_y, visited_width, waste_area; + stbrp_node *node = first; + int x1 = x0 + width; + int min_y, visited_width, waste_area; - STBRP__NOTUSED(c); + STBRP__NOTUSED(c); - STBRP_ASSERT(first->x <= x0); + STBRP_ASSERT(first->x <= x0); - #if 0 +#if 0 // skip in case we're past the node while (node->next->x <= x0) ++node; - #else - STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency - #endif - - STBRP_ASSERT(node->x <= x0); - - min_y = 0; - waste_area = 0; - visited_width = 0; - while (node->x < x1) { - if (node->y > min_y) { - // raise min_y higher. - // we've accounted for all waste up to min_y, - // but we'll now add more waste for everything we've visted - waste_area += visited_width * (node->y - min_y); - min_y = node->y; - // the first time through, visited_width might be reduced - if (node->x < x0) - visited_width += node->next->x - x0; - else - visited_width += node->next->x - node->x; - } else { - // add waste area - int under_width = node->next->x - node->x; - if (under_width + visited_width > width) - under_width = width - visited_width; - waste_area += under_width * (min_y - node->y); - visited_width += under_width; - } - node = node->next; - } - - *pwaste = waste_area; - return min_y; +#else + STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency +#endif + + STBRP_ASSERT(node->x <= x0); + + min_y = 0; + waste_area = 0; + visited_width = 0; + while (node->x < x1) + { + if (node->y > min_y) + { + // raise min_y higher. + // we've accounted for all waste up to min_y, + // but we'll now add more waste for everything we've visted + waste_area += visited_width * (node->y - min_y); + min_y = node->y; + // the first time through, visited_width might be reduced + if (node->x < x0) + visited_width += node->next->x - x0; + else + visited_width += node->next->x - node->x; + } + else + { + // add waste area + int under_width = node->next->x - node->x; + if (under_width + visited_width > width) under_width = width - visited_width; + waste_area += under_width * (min_y - node->y); + visited_width += under_width; + } + node = node->next; + } + + *pwaste = waste_area; + return min_y; } typedef struct { - int x,y; - stbrp_node **prev_link; + int x, y; + stbrp_node **prev_link; } stbrp__findresult; static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) { - int best_waste = (1<<30), best_x, best_y = (1 << 30); - stbrp__findresult fr; - stbrp_node **prev, *node, *tail, **best = NULL; - - // align to multiple of c->align - width = (width + c->align - 1); - width -= width % c->align; - STBRP_ASSERT(width % c->align == 0); - - node = c->active_head; - prev = &c->active_head; - while (node->x + width <= c->width) { - int y,waste; - y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); - if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL - // bottom left - if (y < best_y) { - best_y = y; - best = prev; - } - } else { - // best-fit - if (y + height <= c->height) { - // can only use it if it first vertically - if (y < best_y || (y == best_y && waste < best_waste)) { - best_y = y; - best_waste = waste; - best = prev; + int best_waste = (1 << 30), best_x, best_y = (1 << 30); + stbrp__findresult fr; + stbrp_node ** prev, *node, *tail, **best = NULL; + + // align to multiple of c->align + width = (width + c->align - 1); + width -= width % c->align; + STBRP_ASSERT(width % c->align == 0); + + node = c->active_head; + prev = &c->active_head; + while (node->x + width <= c->width) + { + int y, waste; + y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); + if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) + { // actually just want to test BL + // bottom left + if (y < best_y) + { + best_y = y; + best = prev; + } + } + else + { + // best-fit + if (y + height <= c->height) + { + // can only use it if it first vertically + if (y < best_y || (y == best_y && waste < best_waste)) + { + best_y = y; + best_waste = waste; + best = prev; + } } - } - } - prev = &node->next; - node = node->next; - } - - best_x = (best == NULL) ? 0 : (*best)->x; - - // if doing best-fit (BF), we also have to try aligning right edge to each node position - // - // e.g, if fitting - // - // ____________________ - // |____________________| - // - // into - // - // | | - // | ____________| - // |____________| - // - // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned - // - // This makes BF take about 2x the time - - if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { - tail = c->active_head; - node = c->active_head; - prev = &c->active_head; - // find first node that's admissible - while (tail->x < width) - tail = tail->next; - while (tail) { - int xpos = tail->x - width; - int y,waste; - STBRP_ASSERT(xpos >= 0); - // find the left position that matches this - while (node->next->x <= xpos) { - prev = &node->next; - node = node->next; - } - STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); - y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); - if (y + height < c->height) { - if (y <= best_y) { - if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { - best_x = xpos; - STBRP_ASSERT(y <= best_y); - best_y = y; - best_waste = waste; - best = prev; - } + } + prev = &node->next; + node = node->next; + } + + best_x = (best == NULL) ? 0 : (*best)->x; + + // if doing best-fit (BF), we also have to try aligning right edge to each node position + // + // e.g, if fitting + // + // ____________________ + // |____________________| + // + // into + // + // | | + // | ____________| + // |____________| + // + // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned + // + // This makes BF take about 2x the time + + if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) + { + tail = c->active_head; + node = c->active_head; + prev = &c->active_head; + // find first node that's admissible + while (tail->x < width) + tail = tail->next; + while (tail) + { + int xpos = tail->x - width; + int y, waste; + STBRP_ASSERT(xpos >= 0); + // find the left position that matches this + while (node->next->x <= xpos) + { + prev = &node->next; + node = node->next; } - } - tail = tail->next; - } - } - - fr.prev_link = best; - fr.x = best_x; - fr.y = best_y; - return fr; + STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); + y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); + if (y + height < c->height) + { + if (y <= best_y) + { + if (y < best_y || waste < best_waste || (waste == best_waste && xpos < best_x)) + { + best_x = xpos; + STBRP_ASSERT(y <= best_y); + best_y = y; + best_waste = waste; + best = prev; + } + } + } + tail = tail->next; + } + } + + fr.prev_link = best; + fr.x = best_x; + fr.y = best_y; + return fr; } static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) { - // find best position according to heuristic - stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); - stbrp_node *node, *cur; - - // bail if: - // 1. it failed - // 2. the best node doesn't fit (we don't always check this) - // 3. we're out of memory - if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { - res.prev_link = NULL; - return res; - } - - // on success, create new node - node = context->free_head; - node->x = (stbrp_coord) res.x; - node->y = (stbrp_coord) (res.y + height); - - context->free_head = node->next; - - // insert the new node into the right starting point, and - // let 'cur' point to the remaining nodes needing to be - // stiched back in - - cur = *res.prev_link; - if (cur->x < res.x) { - // preserve the existing one, so start testing with the next one - stbrp_node *next = cur->next; - cur->next = node; - cur = next; - } else { - *res.prev_link = node; - } - - // from here, traverse cur and free the nodes, until we get to one - // that shouldn't be freed - while (cur->next && cur->next->x <= res.x + width) { - stbrp_node *next = cur->next; - // move the current node to the free list - cur->next = context->free_head; - context->free_head = cur; - cur = next; - } - - // stitch the list back in - node->next = cur; - - if (cur->x < res.x + width) - cur->x = (stbrp_coord) (res.x + width); - - // RoR: Removed debugging code - was yielding Codacy review issues - - return res; + // find best position according to heuristic + stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); + stbrp_node * node, *cur; + + // bail if: + // 1. it failed + // 2. the best node doesn't fit (we don't always check this) + // 3. we're out of memory + if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) + { + res.prev_link = NULL; + return res; + } + + // on success, create new node + node = context->free_head; + node->x = (stbrp_coord)res.x; + node->y = (stbrp_coord)(res.y + height); + + context->free_head = node->next; + + // insert the new node into the right starting point, and + // let 'cur' point to the remaining nodes needing to be + // stiched back in + + cur = *res.prev_link; + if (cur->x < res.x) + { + // preserve the existing one, so start testing with the next one + stbrp_node *next = cur->next; + cur->next = node; + cur = next; + } + else + { + *res.prev_link = node; + } + + // from here, traverse cur and free the nodes, until we get to one + // that shouldn't be freed + while (cur->next && cur->next->x <= res.x + width) + { + stbrp_node *next = cur->next; + // move the current node to the free list + cur->next = context->free_head; + context->free_head = cur; + cur = next; + } + + // stitch the list back in + node->next = cur; + + if (cur->x < res.x + width) cur->x = (stbrp_coord)(res.x + width); + + // RoR: Removed debugging code - was yielding Codacy review issues + + return res; } static int rect_height_compare(const void *a, const void *b) { - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - if (p->h > q->h) - return -1; - if (p->h < q->h) - return 1; - return (p->w > q->w) ? -1 : (p->w < q->w); + const stbrp_rect *p = (const stbrp_rect *)a; + const stbrp_rect *q = (const stbrp_rect *)b; + if (p->h > q->h) return -1; + if (p->h < q->h) return 1; + return (p->w > q->w) ? -1 : (p->w < q->w); } static int rect_width_compare(const void *a, const void *b) { - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - if (p->w > q->w) - return -1; - if (p->w < q->w) - return 1; - return (p->h > q->h) ? -1 : (p->h < q->h); + const stbrp_rect *p = (const stbrp_rect *)a; + const stbrp_rect *q = (const stbrp_rect *)b; + if (p->w > q->w) return -1; + if (p->w < q->w) return 1; + return (p->h > q->h) ? -1 : (p->h < q->h); } static int rect_original_order(const void *a, const void *b) { - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); + const stbrp_rect *p = (const stbrp_rect *)a; + const stbrp_rect *q = (const stbrp_rect *)b; + return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); } #ifdef STBRP_LARGE_RECTS -#define STBRP__MAXVAL 0xffffffff + #define STBRP__MAXVAL 0xffffffff #else -#define STBRP__MAXVAL 0xffff + #define STBRP__MAXVAL 0xffff #endif STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { - int i; - - // we use the 'was_packed' field internally to allow sorting/unsorting - for (i=0; i < num_rects; ++i) { - rects[i].was_packed = i; - #ifndef STBRP_LARGE_RECTS - STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); - #endif - } - - // sort according to heuristic - STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); - - for (i=0; i < num_rects; ++i) { - if (rects[i].w == 0 || rects[i].h == 0) { - rects[i].x = rects[i].y = 0; // empty rect needs no space - } else { - stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); - if (fr.prev_link) { - rects[i].x = (stbrp_coord) fr.x; - rects[i].y = (stbrp_coord) fr.y; - } else { - rects[i].x = rects[i].y = STBRP__MAXVAL; - } - } - } - - // unsort - STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); - - // set was_packed flags - for (i=0; i < num_rects; ++i) - rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + int i; + + // we use the 'was_packed' field internally to allow sorting/unsorting + for (i = 0; i < num_rects; ++i) + { + rects[i].was_packed = i; +#ifndef STBRP_LARGE_RECTS + STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); +#endif + } + + // sort according to heuristic + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); + + for (i = 0; i < num_rects; ++i) + { + if (rects[i].w == 0 || rects[i].h == 0) + { + rects[i].x = rects[i].y = 0; // empty rect needs no space + } + else + { + stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); + if (fr.prev_link) + { + rects[i].x = (stbrp_coord)fr.x; + rects[i].y = (stbrp_coord)fr.y; + } + else + { + rects[i].x = rects[i].y = STBRP__MAXVAL; + } + } + } + + // unsort + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); + + // set was_packed flags + for (i = 0; i < num_rects; ++i) + rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); } #endif diff --git a/source/main/gui/imgui/stb_textedit.h b/source/main/gui/imgui/stb_textedit.h index 4b731a0c22..a13c920731 100644 --- a/source/main/gui/imgui/stb_textedit.h +++ b/source/main/gui/imgui/stb_textedit.h @@ -19,7 +19,7 @@ // texts, as its performance does not scale and it has limited undo). // // Non-trivial behaviors are modelled after Windows text controls. -// +// // // LICENSE // @@ -216,20 +216,20 @@ // call this with the mouse x,y on a mouse down; it will update the cursor // and reset the selection start/end to the cursor point. the x,y must // be relative to the text widget, with (0,0) being the top left. -// +// // drag: // call this with the mouse x,y on a mouse drag/up; it will update the // cursor and the selection end point -// +// // cut: // call this to delete the current selection; returns true if there was // one. you should FIRST copy the current selection to the system paste buffer. // (To copy, just copy the current selection out of the string yourself.) -// +// // paste: // call this to paste text at the current cursor point or over the current // selection if there is one. -// +// // key: // call this for keyboard inputs sent to the textfield. you can use it // for "key down" events or for "translated" key events. if you need to @@ -238,7 +238,7 @@ // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is // clear. -// +// // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. // @@ -260,7 +260,6 @@ // efficient, but it's not horrible on modern computers. But you wouldn't // want to edit million-line files with it. - //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //// @@ -281,71 +280,70 @@ // #ifndef STB_TEXTEDIT_UNDOSTATECOUNT -#define STB_TEXTEDIT_UNDOSTATECOUNT 99 + #define STB_TEXTEDIT_UNDOSTATECOUNT 99 #endif #ifndef STB_TEXTEDIT_UNDOCHARCOUNT -#define STB_TEXTEDIT_UNDOCHARCOUNT 999 + #define STB_TEXTEDIT_UNDOCHARCOUNT 999 #endif #ifndef STB_TEXTEDIT_CHARTYPE -#define STB_TEXTEDIT_CHARTYPE int + #define STB_TEXTEDIT_CHARTYPE int #endif #ifndef STB_TEXTEDIT_POSITIONTYPE -#define STB_TEXTEDIT_POSITIONTYPE int + #define STB_TEXTEDIT_POSITIONTYPE int #endif typedef struct { - // private data - STB_TEXTEDIT_POSITIONTYPE where; - short insert_length; - short delete_length; - short char_storage; + // private data + STB_TEXTEDIT_POSITIONTYPE where; + short insert_length; + short delete_length; + short char_storage; } StbUndoRecord; typedef struct { - // private data - StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; - STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; - short undo_point, redo_point; - short undo_char_point, redo_char_point; + // private data + StbUndoRecord undo_rec[STB_TEXTEDIT_UNDOSTATECOUNT]; + STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; + short undo_point, redo_point; + short undo_char_point, redo_char_point; } StbUndoState; typedef struct { - ///////////////////// - // - // public data - // - - int cursor; - // position of the text cursor within the string - - int select_start; // selection start point - int select_end; - // selection start and end point in characters; if equal, no selection. - // note that start may be less than or greater than end (e.g. when - // dragging the mouse, start is where the initial click was, and you - // can drag in either direction) - - unsigned char insert_mode; - // each textfield keeps its own insert mode state. to keep an app-wide - // insert mode, copy this value in/out of the app state - - ///////////////////// - // - // private data - // - unsigned char cursor_at_end_of_line; // not implemented yet - unsigned char initialized; - unsigned char has_preferred_x; - unsigned char single_line; - unsigned char padding1, padding2, padding3; - float preferred_x; // this determines where the cursor up/down tries to seek to along x - StbUndoState undostate; + ///////////////////// + // + // public data + // + + int cursor; + // position of the text cursor within the string + + int select_start; // selection start point + int select_end; + // selection start and end point in characters; if equal, no selection. + // note that start may be less than or greater than end (e.g. when + // dragging the mouse, start is where the initial click was, and you + // can drag in either direction) + + unsigned char insert_mode; + // each textfield keeps its own insert mode state. to keep an app-wide + // insert mode, copy this value in/out of the app state + + ///////////////////// + // + // private data + // + unsigned char cursor_at_end_of_line; // not implemented yet + unsigned char initialized; + unsigned char has_preferred_x; + unsigned char single_line; + unsigned char padding1, padding2, padding3; + float preferred_x; // this determines where the cursor up/down tries to seek to along x + StbUndoState undostate; } STB_TexteditState; - //////////////////////////////////////////////////////////////////////// // // StbTexteditRow @@ -356,13 +354,12 @@ typedef struct // result of layout query typedef struct { - float x0,x1; // starting x location, end x location (allows for align=right, etc) - float baseline_y_delta; // position of baseline relative to previous row's baseline - float ymin,ymax; // height of row above and below baseline - int num_chars; + float x0, x1; // starting x location, end x location (allows for align=right, etc) + float baseline_y_delta; // position of baseline relative to previous row's baseline + float ymin, ymax; // height of row above and below baseline + int num_chars; } StbTexteditRow; -#endif //INCLUDE_STB_TEXTEDIT_H - +#endif // INCLUDE_STB_TEXTEDIT_H //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// @@ -371,17 +368,15 @@ typedef struct //// //// - // implementation isn't include-guarded, since it might have indirectly // included just the "header" portion #ifdef STB_TEXTEDIT_IMPLEMENTATION #ifndef STB_TEXTEDIT_memmove -#include -#define STB_TEXTEDIT_memmove memmove + #include + #define STB_TEXTEDIT_memmove memmove #endif - ///////////////////////////////////////////////////////////////////////////// // // Mouse input handling @@ -390,79 +385,77 @@ typedef struct // traverse the layout to locate the nearest character to a display position static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) { - StbTexteditRow r; - int n = STB_TEXTEDIT_STRINGLEN(str); - float base_y = 0, prev_x; - int i=0, k; - - r.x0 = r.x1 = 0; - r.ymin = r.ymax = 0; - r.num_chars = 0; - - // search rows to find one that straddles 'y' - while (i < n) { - STB_TEXTEDIT_LAYOUTROW(&r, str, i); - if (r.num_chars <= 0) - return n; - - if (i==0 && y < base_y + r.ymin) - return 0; - - if (y < base_y + r.ymax) - break; - - i += r.num_chars; - base_y += r.baseline_y_delta; - } - - // below all text, return 'after' last character - if (i >= n) - return n; - - // check if it's before the beginning of the line - if (x < r.x0) - return i; - - // check if it's before the end of the line - if (x < r.x1) { - // search characters in row for one that straddles 'x' - prev_x = r.x0; - for (k=0; k < r.num_chars; ++k) { - float w = STB_TEXTEDIT_GETWIDTH(str, i, k); - if (x < prev_x+w) { - if (x < prev_x+w/2) - return k+i; - else - return k+i+1; - } - prev_x += w; - } - // shouldn't happen, but if it does, fall through to end-of-line case - } - - // if the last character is a newline, return that. otherwise return 'after' the last character - if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE) - return i+r.num_chars-1; - else - return i+r.num_chars; + StbTexteditRow r; + int n = STB_TEXTEDIT_STRINGLEN(str); + float base_y = 0, prev_x; + int i = 0, k; + + r.x0 = r.x1 = 0; + r.ymin = r.ymax = 0; + r.num_chars = 0; + + // search rows to find one that straddles 'y' + while (i < n) + { + STB_TEXTEDIT_LAYOUTROW(&r, str, i); + if (r.num_chars <= 0) return n; + + if (i == 0 && y < base_y + r.ymin) return 0; + + if (y < base_y + r.ymax) break; + + i += r.num_chars; + base_y += r.baseline_y_delta; + } + + // below all text, return 'after' last character + if (i >= n) return n; + + // check if it's before the beginning of the line + if (x < r.x0) return i; + + // check if it's before the end of the line + if (x < r.x1) + { + // search characters in row for one that straddles 'x' + prev_x = r.x0; + for (k = 0; k < r.num_chars; ++k) + { + float w = STB_TEXTEDIT_GETWIDTH(str, i, k); + if (x < prev_x + w) + { + if (x < prev_x + w / 2) + return k + i; + else + return k + i + 1; + } + prev_x += w; + } + // shouldn't happen, but if it does, fall through to end-of-line case + } + + // if the last character is a newline, return that. otherwise return 'after' the last character + if (STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) == STB_TEXTEDIT_NEWLINE) + return i + r.num_chars - 1; + else + return i + r.num_chars; } // API click: on mouse down, move the cursor to the clicked location, and reset the selection static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { - state->cursor = stb_text_locate_coord(str, x, y); - state->select_start = state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; + state->cursor = stb_text_locate_coord(str, x, y); + state->select_start = state->cursor; + state->select_end = state->cursor; + state->has_preferred_x = 0; } // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { - int p = stb_text_locate_coord(str, x, y); - if (state->select_start == state->select_end) - state->select_start = state->cursor; - state->cursor = state->select_end = p; + int p = stb_text_locate_coord(str, x, y); + if (state->select_start == state->select_end) state->select_start = state->cursor; + state->cursor = state->select_end = p; } ///////////////////////////////////////////////////////////////////////////// @@ -475,583 +468,609 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); -static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); +static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, + int new_length); typedef struct { - float x,y; // position of n'th character - float height; // height of line - int first_char, length; // first char of row, and length - int prev_first; // first char of previous row + float x, y; // position of n'th character + float height; // height of line + int first_char, length; // first char of row, and length + int prev_first; // first char of previous row } StbFindState; // find the x/y location of a character, and remember info about the previous row in // case we get a move-up event (for page up, we'll have to rescan) static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line) { - StbTexteditRow r; - int prev_start = 0; - int z = STB_TEXTEDIT_STRINGLEN(str); - int i=0, first; - - if (n == z) { - // if it's at the end, then find the last line -- simpler than trying to - // explicitly handle this case in the regular code - if (single_line) { - STB_TEXTEDIT_LAYOUTROW(&r, str, 0); - find->y = 0; - find->first_char = 0; - find->length = z; - find->height = r.ymax - r.ymin; - find->x = r.x1; - } else { - find->y = 0; - find->x = 0; - find->height = 1; - while (i < z) { - STB_TEXTEDIT_LAYOUTROW(&r, str, i); - prev_start = i; - i += r.num_chars; - } - find->first_char = i; - find->length = 0; - find->prev_first = prev_start; - } - return; - } - - // search rows to find the one that straddles character n - find->y = 0; - - for(;;) { - STB_TEXTEDIT_LAYOUTROW(&r, str, i); - if (n < i + r.num_chars) - break; - prev_start = i; - i += r.num_chars; - find->y += r.baseline_y_delta; - } - - find->first_char = first = i; - find->length = r.num_chars; - find->height = r.ymax - r.ymin; - find->prev_first = prev_start; - - // now scan to find xpos - find->x = r.x0; - i = 0; - for (i=0; first+i < n; ++i) - find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); + StbTexteditRow r; + int prev_start = 0; + int z = STB_TEXTEDIT_STRINGLEN(str); + int i = 0, first; + + if (n == z) + { + // if it's at the end, then find the last line -- simpler than trying to + // explicitly handle this case in the regular code + if (single_line) + { + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + find->y = 0; + find->first_char = 0; + find->length = z; + find->height = r.ymax - r.ymin; + find->x = r.x1; + } + else + { + find->y = 0; + find->x = 0; + find->height = 1; + while (i < z) + { + STB_TEXTEDIT_LAYOUTROW(&r, str, i); + prev_start = i; + i += r.num_chars; + } + find->first_char = i; + find->length = 0; + find->prev_first = prev_start; + } + return; + } + + // search rows to find the one that straddles character n + find->y = 0; + + for (;;) + { + STB_TEXTEDIT_LAYOUTROW(&r, str, i); + if (n < i + r.num_chars) break; + prev_start = i; + i += r.num_chars; + find->y += r.baseline_y_delta; + } + + find->first_char = first = i; + find->length = r.num_chars; + find->height = r.ymax - r.ymin; + find->prev_first = prev_start; + + // now scan to find xpos + find->x = r.x0; + i = 0; + for (i = 0; first + i < n; ++i) + find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); } -#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) +#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) // make the selection/cursor state valid if client altered the string static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { - int n = STB_TEXTEDIT_STRINGLEN(str); - if (STB_TEXT_HAS_SELECTION(state)) { - if (state->select_start > n) state->select_start = n; - if (state->select_end > n) state->select_end = n; - // if clamping forced them to be equal, move the cursor to match - if (state->select_start == state->select_end) - state->cursor = state->select_start; - } - if (state->cursor > n) state->cursor = n; + int n = STB_TEXTEDIT_STRINGLEN(str); + if (STB_TEXT_HAS_SELECTION(state)) + { + if (state->select_start > n) state->select_start = n; + if (state->select_end > n) state->select_end = n; + // if clamping forced them to be equal, move the cursor to match + if (state->select_start == state->select_end) state->cursor = state->select_start; + } + if (state->cursor > n) state->cursor = n; } // delete characters while updating undo static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) { - stb_text_makeundo_delete(str, state, where, len); - STB_TEXTEDIT_DELETECHARS(str, where, len); - state->has_preferred_x = 0; + stb_text_makeundo_delete(str, state, where, len); + STB_TEXTEDIT_DELETECHARS(str, where, len); + state->has_preferred_x = 0; } // delete the section static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { - stb_textedit_clamp(str, state); - if (STB_TEXT_HAS_SELECTION(state)) { - if (state->select_start < state->select_end) { - stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); - state->select_end = state->cursor = state->select_start; - } else { - stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); - state->select_start = state->cursor = state->select_end; - } - state->has_preferred_x = 0; - } + stb_textedit_clamp(str, state); + if (STB_TEXT_HAS_SELECTION(state)) + { + if (state->select_start < state->select_end) + { + stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); + state->select_end = state->cursor = state->select_start; + } + else + { + stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); + state->select_start = state->cursor = state->select_end; + } + state->has_preferred_x = 0; + } } // canoncialize the selection so start <= end static void stb_textedit_sortselection(STB_TexteditState *state) { - if (state->select_end < state->select_start) { - int temp = state->select_end; - state->select_end = state->select_start; - state->select_start = temp; - } + if (state->select_end < state->select_start) + { + int temp = state->select_end; + state->select_end = state->select_start; + state->select_start = temp; + } } // move cursor to first character of selection static void stb_textedit_move_to_first(STB_TexteditState *state) { - if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_sortselection(state); - state->cursor = state->select_start; - state->select_end = state->select_start; - state->has_preferred_x = 0; - } + if (STB_TEXT_HAS_SELECTION(state)) + { + stb_textedit_sortselection(state); + state->cursor = state->select_start; + state->select_end = state->select_start; + state->has_preferred_x = 0; + } } // move cursor to last character of selection static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { - if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_sortselection(state); - stb_textedit_clamp(str, state); - state->cursor = state->select_end; - state->select_start = state->select_end; - state->has_preferred_x = 0; - } + if (STB_TEXT_HAS_SELECTION(state)) + { + stb_textedit_sortselection(state); + stb_textedit_clamp(str, state); + state->cursor = state->select_end; + state->select_start = state->select_end; + state->has_preferred_x = 0; + } } #ifdef STB_TEXTEDIT_IS_SPACE -static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx ) +static int is_word_boundary(STB_TEXTEDIT_STRING *str, int idx) { - return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; + return idx > 0 ? (STB_TEXTEDIT_IS_SPACE(STB_TEXTEDIT_GETCHAR(str, idx - 1)) && + !STB_TEXTEDIT_IS_SPACE(STB_TEXTEDIT_GETCHAR(str, idx))) + : 1; } -#ifndef STB_TEXTEDIT_MOVEWORDLEFT -static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) + #ifndef STB_TEXTEDIT_MOVEWORDLEFT +static int stb_textedit_move_to_word_previous(STB_TEXTEDIT_STRING *str, int c) { - --c; // always move at least one character - while( c >= 0 && !is_word_boundary( str, c ) ) - --c; + --c; // always move at least one character + while (c >= 0 && !is_word_boundary(str, c)) + --c; - if( c < 0 ) - c = 0; + if (c < 0) c = 0; - return c; + return c; } -#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous -#endif + #define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous + #endif -#ifndef STB_TEXTEDIT_MOVEWORDRIGHT -static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) + #ifndef STB_TEXTEDIT_MOVEWORDRIGHT +static int stb_textedit_move_to_word_next(STB_TEXTEDIT_STRING *str, int c) { - const int len = STB_TEXTEDIT_STRINGLEN(str); - ++c; // always move at least one character - while( c < len && !is_word_boundary( str, c ) ) - ++c; + const int len = STB_TEXTEDIT_STRINGLEN(str); + ++c; // always move at least one character + while (c < len && !is_word_boundary(str, c)) + ++c; - if( c > len ) - c = len; + if (c > len) c = len; - return c; + return c; } -#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next -#endif + #define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next + #endif #endif // update selection and cursor to match each other static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) { - if (!STB_TEXT_HAS_SELECTION(state)) - state->select_start = state->select_end = state->cursor; - else - state->cursor = state->select_end; + if (!STB_TEXT_HAS_SELECTION(state)) + state->select_start = state->select_end = state->cursor; + else + state->cursor = state->select_end; } // API cut: delete selection static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { - if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_delete_selection(str,state); // implicity clamps - state->has_preferred_x = 0; - return 1; - } - return 0; + if (STB_TEXT_HAS_SELECTION(state)) + { + stb_textedit_delete_selection(str, state); // implicity clamps + state->has_preferred_x = 0; + return 1; + } + return 0; } // API paste: replace existing selection with passed-in text static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) { - STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *) ctext; - // if there's a selection, the paste should delete it - stb_textedit_clamp(str, state); - stb_textedit_delete_selection(str,state); - // try to insert the characters - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { - stb_text_makeundo_insert(state, state->cursor, len); - state->cursor += len; - state->has_preferred_x = 0; - return 1; - } - // remove the undo since we didn't actually insert the characters - if (state->undostate.undo_point) - --state->undostate.undo_point; - return 0; + STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *)ctext; + // if there's a selection, the paste should delete it + stb_textedit_clamp(str, state); + stb_textedit_delete_selection(str, state); + // try to insert the characters + if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) + { + stb_text_makeundo_insert(state, state->cursor, len); + state->cursor += len; + state->has_preferred_x = 0; + return 1; + } + // remove the undo since we didn't actually insert the characters + if (state->undostate.undo_point) --state->undostate.undo_point; + return 0; } // API key: process a keyboard input static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) { retry: - switch (key) { - default: { - int c = STB_TEXTEDIT_KEYTOTEXT(key); - if (c > 0) { - STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c; + switch (key) + { + default: + { + int c = STB_TEXTEDIT_KEYTOTEXT(key); + if (c > 0) + { + STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE)c; // can't add newline in single-line mode - if (c == '\n' && state->single_line) - break; - - if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { - stb_text_makeundo_replace(str, state, state->cursor, 1, 1); - STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { - ++state->cursor; - state->has_preferred_x = 0; - } - } else { - stb_textedit_delete_selection(str,state); // implicity clamps - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { - stb_text_makeundo_insert(state, state->cursor, 1); - ++state->cursor; - state->has_preferred_x = 0; - } + if (c == '\n' && state->single_line) break; + + if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) + { + stb_text_makeundo_replace(str, state, state->cursor, 1, 1); + STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); + if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) + { + ++state->cursor; + state->has_preferred_x = 0; + } } - } - break; - } + else + { + stb_textedit_delete_selection(str, state); // implicity clamps + if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) + { + stb_text_makeundo_insert(state, state->cursor, 1); + ++state->cursor; + state->has_preferred_x = 0; + } + } + } + break; + } #ifdef STB_TEXTEDIT_K_INSERT - case STB_TEXTEDIT_K_INSERT: - state->insert_mode = !state->insert_mode; - break; + case STB_TEXTEDIT_K_INSERT: state->insert_mode = !state->insert_mode; break; #endif - - case STB_TEXTEDIT_K_UNDO: - stb_text_undo(str, state); - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_REDO: - stb_text_redo(str, state); - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_LEFT: - // if currently there's a selection, move cursor to start of selection - if (STB_TEXT_HAS_SELECTION(state)) + + case STB_TEXTEDIT_K_UNDO: + stb_text_undo(str, state); + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_REDO: + stb_text_redo(str, state); + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_LEFT: + // if currently there's a selection, move cursor to start of selection + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); - else - if (state->cursor > 0) - --state->cursor; - state->has_preferred_x = 0; - break; + else if (state->cursor > 0) + --state->cursor; + state->has_preferred_x = 0; + break; - case STB_TEXTEDIT_K_RIGHT: - // if currently there's a selection, move cursor to end of selection - if (STB_TEXT_HAS_SELECTION(state)) + case STB_TEXTEDIT_K_RIGHT: + // if currently there's a selection, move cursor to end of selection + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); - else + else ++state->cursor; - stb_textedit_clamp(str, state); - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: - stb_textedit_clamp(str, state); - stb_textedit_prep_selection_at_cursor(state); - // move selection left - if (state->select_end > 0) - --state->select_end; - state->cursor = state->select_end; - state->has_preferred_x = 0; - break; + stb_textedit_clamp(str, state); + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: + stb_textedit_clamp(str, state); + stb_textedit_prep_selection_at_cursor(state); + // move selection left + if (state->select_end > 0) --state->select_end; + state->cursor = state->select_end; + state->has_preferred_x = 0; + break; #ifdef STB_TEXTEDIT_MOVEWORDLEFT - case STB_TEXTEDIT_K_WORDLEFT: - if (STB_TEXT_HAS_SELECTION(state)) + case STB_TEXTEDIT_K_WORDLEFT: + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); - else { + else + { state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); - stb_textedit_clamp( str, state ); - } - break; + stb_textedit_clamp(str, state); + } + break; - case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: - if( !STB_TEXT_HAS_SELECTION( state ) ) - stb_textedit_prep_selection_at_cursor(state); + case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: + if (!STB_TEXT_HAS_SELECTION(state)) stb_textedit_prep_selection_at_cursor(state); - state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); - state->select_end = state->cursor; + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); + state->select_end = state->cursor; - stb_textedit_clamp( str, state ); - break; + stb_textedit_clamp(str, state); + break; #endif #ifdef STB_TEXTEDIT_MOVEWORDRIGHT - case STB_TEXTEDIT_K_WORDRIGHT: - if (STB_TEXT_HAS_SELECTION(state)) + case STB_TEXTEDIT_K_WORDRIGHT: + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); - else { + else + { state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); - stb_textedit_clamp( str, state ); - } - break; + stb_textedit_clamp(str, state); + } + break; - case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: - if( !STB_TEXT_HAS_SELECTION( state ) ) - stb_textedit_prep_selection_at_cursor(state); + case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: + if (!STB_TEXT_HAS_SELECTION(state)) stb_textedit_prep_selection_at_cursor(state); - state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); - state->select_end = state->cursor; + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); + state->select_end = state->cursor; - stb_textedit_clamp( str, state ); - break; + stb_textedit_clamp(str, state); + break; #endif - case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: - stb_textedit_prep_selection_at_cursor(state); - // move selection right - ++state->select_end; - stb_textedit_clamp(str, state); - state->cursor = state->select_end; - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_DOWN: - case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: { - StbFindState find; - StbTexteditRow row; - int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; - - if (state->single_line) { + case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: + stb_textedit_prep_selection_at_cursor(state); + // move selection right + ++state->select_end; + stb_textedit_clamp(str, state); + state->cursor = state->select_end; + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_DOWN: + case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: + { + StbFindState find; + StbTexteditRow row; + int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + + if (state->single_line) + { // on windows, up&down in single-line behave like left&right key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); goto retry; - } + } - if (sel) + if (sel) stb_textedit_prep_selection_at_cursor(state); - else if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_last(str,state); + else if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_last(str, state); - // compute current position of cursor point - stb_textedit_clamp(str, state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); + // compute current position of cursor point + stb_textedit_clamp(str, state); + stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - // now find character position down a row - if (find.length) { + // now find character position down a row + if (find.length) + { float goal_x = state->has_preferred_x ? state->preferred_x : find.x; float x; - int start = find.first_char + find.length; + int start = find.first_char + find.length; state->cursor = start; STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); x = row.x0; - for (i=0; i < row.num_chars; ++i) { - float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); - #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE - if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) - break; - #endif - x += dx; - if (x > goal_x) - break; - ++state->cursor; + for (i = 0; i < row.num_chars; ++i) + { + float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); +#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE + if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) break; +#endif + x += dx; + if (x > goal_x) break; + ++state->cursor; } stb_textedit_clamp(str, state); state->has_preferred_x = 1; - state->preferred_x = goal_x; - - if (sel) - state->select_end = state->cursor; - } - break; - } - - case STB_TEXTEDIT_K_UP: - case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: { - StbFindState find; - StbTexteditRow row; - int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; - - if (state->single_line) { + state->preferred_x = goal_x; + + if (sel) state->select_end = state->cursor; + } + break; + } + + case STB_TEXTEDIT_K_UP: + case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: + { + StbFindState find; + StbTexteditRow row; + int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + + if (state->single_line) + { // on windows, up&down become left&right key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); goto retry; - } + } - if (sel) + if (sel) stb_textedit_prep_selection_at_cursor(state); - else if (STB_TEXT_HAS_SELECTION(state)) + else if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); - // compute current position of cursor point - stb_textedit_clamp(str, state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); + // compute current position of cursor point + stb_textedit_clamp(str, state); + stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - // can only go up if there's a previous row - if (find.prev_first != find.first_char) { + // can only go up if there's a previous row + if (find.prev_first != find.first_char) + { // now find character position up a row float goal_x = state->has_preferred_x ? state->preferred_x : find.x; float x; state->cursor = find.prev_first; STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); x = row.x0; - for (i=0; i < row.num_chars; ++i) { - float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); - #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE - if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) - break; - #endif - x += dx; - if (x > goal_x) - break; - ++state->cursor; + for (i = 0; i < row.num_chars; ++i) + { + float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); +#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE + if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) break; +#endif + x += dx; + if (x > goal_x) break; + ++state->cursor; } stb_textedit_clamp(str, state); state->has_preferred_x = 1; - state->preferred_x = goal_x; + state->preferred_x = goal_x; - if (sel) - state->select_end = state->cursor; - } - break; - } + if (sel) state->select_end = state->cursor; + } + break; + } - case STB_TEXTEDIT_K_DELETE: - case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: - if (STB_TEXT_HAS_SELECTION(state)) + case STB_TEXTEDIT_K_DELETE: + case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_delete_selection(str, state); - else { + else + { int n = STB_TEXTEDIT_STRINGLEN(str); - if (state->cursor < n) - stb_textedit_delete(str, state, state->cursor, 1); - } - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_BACKSPACE: - case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: - if (STB_TEXT_HAS_SELECTION(state)) + if (state->cursor < n) stb_textedit_delete(str, state, state->cursor, 1); + } + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_BACKSPACE: + case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_delete_selection(str, state); - else { + else + { stb_textedit_clamp(str, state); - if (state->cursor > 0) { - stb_textedit_delete(str, state, state->cursor-1, 1); - --state->cursor; + if (state->cursor > 0) + { + stb_textedit_delete(str, state, state->cursor - 1, 1); + --state->cursor; } - } - state->has_preferred_x = 0; - break; - + } + state->has_preferred_x = 0; + break; + #ifdef STB_TEXTEDIT_K_TEXTSTART2 - case STB_TEXTEDIT_K_TEXTSTART2: + case STB_TEXTEDIT_K_TEXTSTART2: #endif - case STB_TEXTEDIT_K_TEXTSTART: - state->cursor = state->select_start = state->select_end = 0; - state->has_preferred_x = 0; - break; + case STB_TEXTEDIT_K_TEXTSTART: + state->cursor = state->select_start = state->select_end = 0; + state->has_preferred_x = 0; + break; #ifdef STB_TEXTEDIT_K_TEXTEND2 - case STB_TEXTEDIT_K_TEXTEND2: + case STB_TEXTEDIT_K_TEXTEND2: #endif - case STB_TEXTEDIT_K_TEXTEND: - state->cursor = STB_TEXTEDIT_STRINGLEN(str); - state->select_start = state->select_end = 0; - state->has_preferred_x = 0; - break; - + case STB_TEXTEDIT_K_TEXTEND: + state->cursor = STB_TEXTEDIT_STRINGLEN(str); + state->select_start = state->select_end = 0; + state->has_preferred_x = 0; + break; + #ifdef STB_TEXTEDIT_K_TEXTSTART2 - case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: #endif - case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: - stb_textedit_prep_selection_at_cursor(state); - state->cursor = state->select_end = 0; - state->has_preferred_x = 0; - break; + case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: + stb_textedit_prep_selection_at_cursor(state); + state->cursor = state->select_end = 0; + state->has_preferred_x = 0; + break; #ifdef STB_TEXTEDIT_K_TEXTEND2 - case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: #endif - case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: - stb_textedit_prep_selection_at_cursor(state); - state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); - state->has_preferred_x = 0; - break; - + case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: + stb_textedit_prep_selection_at_cursor(state); + state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); + state->has_preferred_x = 0; + break; #ifdef STB_TEXTEDIT_K_LINESTART2 - case STB_TEXTEDIT_K_LINESTART2: + case STB_TEXTEDIT_K_LINESTART2: #endif - case STB_TEXTEDIT_K_LINESTART: - stb_textedit_clamp(str, state); - stb_textedit_move_to_first(state); - if (state->single_line) + case STB_TEXTEDIT_K_LINESTART: + stb_textedit_clamp(str, state); + stb_textedit_move_to_first(state); + if (state->single_line) state->cursor = 0; - else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) - --state->cursor; - state->has_preferred_x = 0; - break; + else + while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor - 1) != STB_TEXTEDIT_NEWLINE) + --state->cursor; + state->has_preferred_x = 0; + break; #ifdef STB_TEXTEDIT_K_LINEEND2 - case STB_TEXTEDIT_K_LINEEND2: + case STB_TEXTEDIT_K_LINEEND2: #endif - case STB_TEXTEDIT_K_LINEEND: { - int n = STB_TEXTEDIT_STRINGLEN(str); - stb_textedit_clamp(str, state); - stb_textedit_move_to_first(state); - if (state->single_line) - state->cursor = n; - else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) - ++state->cursor; - state->has_preferred_x = 0; - break; - } + case STB_TEXTEDIT_K_LINEEND: + { + int n = STB_TEXTEDIT_STRINGLEN(str); + stb_textedit_clamp(str, state); + stb_textedit_move_to_first(state); + if (state->single_line) + state->cursor = n; + else + while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) + ++state->cursor; + state->has_preferred_x = 0; + break; + } #ifdef STB_TEXTEDIT_K_LINESTART2 - case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: #endif - case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: - stb_textedit_clamp(str, state); - stb_textedit_prep_selection_at_cursor(state); - if (state->single_line) + case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: + stb_textedit_clamp(str, state); + stb_textedit_prep_selection_at_cursor(state); + if (state->single_line) state->cursor = 0; - else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) - --state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; - break; + else + while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor - 1) != STB_TEXTEDIT_NEWLINE) + --state->cursor; + state->select_end = state->cursor; + state->has_preferred_x = 0; + break; #ifdef STB_TEXTEDIT_K_LINEEND2 - case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: #endif - case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { - int n = STB_TEXTEDIT_STRINGLEN(str); - stb_textedit_clamp(str, state); - stb_textedit_prep_selection_at_cursor(state); - if (state->single_line) - state->cursor = n; - else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) - ++state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; - break; - } - -// @TODO: -// STB_TEXTEDIT_K_PGUP - move cursor up a page -// STB_TEXTEDIT_K_PGDOWN - move cursor down a page - } + case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: + { + int n = STB_TEXTEDIT_STRINGLEN(str); + stb_textedit_clamp(str, state); + stb_textedit_prep_selection_at_cursor(state); + if (state->single_line) + state->cursor = n; + else + while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) + ++state->cursor; + state->select_end = state->cursor; + state->has_preferred_x = 0; + break; + } + + // @TODO: + // STB_TEXTEDIT_K_PGUP - move cursor up a page + // STB_TEXTEDIT_K_PGDOWN - move cursor down a page + } } ///////////////////////////////////////////////////////////////////////////// @@ -1062,27 +1081,32 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, static void stb_textedit_flush_redo(StbUndoState *state) { - state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; - state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; + state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; + state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; } // discard the oldest entry in the undo list static void stb_textedit_discard_undo(StbUndoState *state) { - if (state->undo_point > 0) { - // if the 0th undo state has characters, clean those up - if (state->undo_rec[0].char_storage >= 0) { - int n = state->undo_rec[0].insert_length, i; - // delete n characters from all other records - state->undo_char_point = state->undo_char_point - (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); - for (i=0; i < state->undo_point; ++i) - if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it - } - --state->undo_point; - STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0]))); - } + if (state->undo_point > 0) + { + // if the 0th undo state has characters, clean those up + if (state->undo_rec[0].char_storage >= 0) + { + int n = state->undo_rec[0].insert_length, i; + // delete n characters from all other records + state->undo_char_point = state->undo_char_point - (short)n; // vsnet05 + STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, + (size_t)((size_t)state->undo_char_point * sizeof(STB_TEXTEDIT_CHARTYPE))); + for (i = 0; i < state->undo_point; ++i) + if (state->undo_rec[i].char_storage >= 0) + state->undo_rec[i].char_storage = + state->undo_rec[i].char_storage - (short)n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it + } + --state->undo_point; + STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec + 1, + (size_t)((size_t)state->undo_point * sizeof(state->undo_rec[0]))); + } } // discard the oldest entry in the redo list--it's bad if this @@ -1091,232 +1115,250 @@ static void stb_textedit_discard_undo(StbUndoState *state) // fill up even though the undo buffer didn't static void stb_textedit_discard_redo(StbUndoState *state) { - int k = STB_TEXTEDIT_UNDOSTATECOUNT-1; - - if (state->redo_point <= k) { - // if the k'th undo state has characters, clean those up - if (state->undo_rec[k].char_storage >= 0) { - int n = state->undo_rec[k].insert_length, i; - // delete n characters from all other records - state->redo_char_point = state->redo_char_point + (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); - for (i=state->redo_point; i < k; ++i) - if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05 - } - STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); - ++state->redo_point; - } + int k = STB_TEXTEDIT_UNDOSTATECOUNT - 1; + + if (state->redo_point <= k) + { + // if the k'th undo state has characters, clean those up + if (state->undo_rec[k].char_storage >= 0) + { + int n = state->undo_rec[k].insert_length, i; + // delete n characters from all other records + state->redo_char_point = state->redo_char_point + (short)n; // vsnet05 + STB_TEXTEDIT_memmove( + state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point - n, + (size_t)((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point) * sizeof(STB_TEXTEDIT_CHARTYPE))); + for (i = state->redo_point; i < k; ++i) + if (state->undo_rec[i].char_storage >= 0) + state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short)n; // vsnet05 + } + STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point - 1, + (size_t)((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point) * sizeof(state->undo_rec[0]))); + ++state->redo_point; + } } static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) { - // any time we create a new undo record, we discard redo - stb_textedit_flush_redo(state); - - // if we have no free records, we have to make room, by sliding the - // existing records down - if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) - stb_textedit_discard_undo(state); - - // if the characters to store won't possibly fit in the buffer, we can't undo - if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { - state->undo_point = 0; - state->undo_char_point = 0; - return NULL; - } - - // if we don't have enough free characters in the buffer, we have to make room - while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) - stb_textedit_discard_undo(state); - - return &state->undo_rec[state->undo_point++]; + // any time we create a new undo record, we discard redo + stb_textedit_flush_redo(state); + + // if we have no free records, we have to make room, by sliding the + // existing records down + if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) stb_textedit_discard_undo(state); + + // if the characters to store won't possibly fit in the buffer, we can't undo + if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) + { + state->undo_point = 0; + state->undo_char_point = 0; + return NULL; + } + + // if we don't have enough free characters in the buffer, we have to make room + while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) + stb_textedit_discard_undo(state); + + return &state->undo_rec[state->undo_point++]; } static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) { - StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); - if (r == NULL) - return NULL; - - r->where = pos; - r->insert_length = (short) insert_len; - r->delete_length = (short) delete_len; - - if (insert_len == 0) { - r->char_storage = -1; - return NULL; - } else { - r->char_storage = state->undo_char_point; - state->undo_char_point = state->undo_char_point + (short) insert_len; - return &state->undo_char[r->char_storage]; - } + StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); + if (r == NULL) return NULL; + + r->where = pos; + r->insert_length = (short)insert_len; + r->delete_length = (short)delete_len; + + if (insert_len == 0) + { + r->char_storage = -1; + return NULL; + } + else + { + r->char_storage = state->undo_char_point; + state->undo_char_point = state->undo_char_point + (short)insert_len; + return &state->undo_char[r->char_storage]; + } } static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { - StbUndoState *s = &state->undostate; - StbUndoRecord u, *r; - if (s->undo_point == 0) - return; - - // we need to do two things: apply the undo record, and create a redo record - u = s->undo_rec[s->undo_point-1]; - r = &s->undo_rec[s->redo_point-1]; - r->char_storage = -1; - - r->insert_length = u.delete_length; - r->delete_length = u.insert_length; - r->where = u.where; - - if (u.delete_length) { - // if the undo record says to delete characters, then the redo record will - // need to re-insert the characters that get deleted, so we need to store - // them. - - // there are three cases: - // there's enough room to store the characters - // characters stored for *redoing* don't leave room for redo - // characters stored for *undoing* don't leave room for redo - // if the last is true, we have to bail - - if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { - // the undo records take up too much character space; there's no space to store the redo characters - r->insert_length = 0; - } else { - int i; - - // there's definitely room to store the characters eventually - while (s->undo_char_point + u.delete_length > s->redo_char_point) { - // there's currently not enough room, so discard a redo record - stb_textedit_discard_redo(s); - // should never happen: - if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) - return; - } - r = &s->undo_rec[s->redo_point-1]; - - r->char_storage = s->redo_char_point - u.delete_length; - s->redo_char_point = s->redo_char_point - (short) u.delete_length; - - // now save the characters - for (i=0; i < u.delete_length; ++i) - s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); - } - - // now we can carry out the deletion - STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); - } - - // check type of recorded action: - if (u.insert_length) { - // easy case: was a deletion, so we need to insert n characters - STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); - s->undo_char_point -= u.insert_length; - } - - state->cursor = u.where + u.insert_length; - - s->undo_point--; - s->redo_point--; + StbUndoState *s = &state->undostate; + StbUndoRecord u, *r; + if (s->undo_point == 0) return; + + // we need to do two things: apply the undo record, and create a redo record + u = s->undo_rec[s->undo_point - 1]; + r = &s->undo_rec[s->redo_point - 1]; + r->char_storage = -1; + + r->insert_length = u.delete_length; + r->delete_length = u.insert_length; + r->where = u.where; + + if (u.delete_length) + { + // if the undo record says to delete characters, then the redo record will + // need to re-insert the characters that get deleted, so we need to store + // them. + + // there are three cases: + // there's enough room to store the characters + // characters stored for *redoing* don't leave room for redo + // characters stored for *undoing* don't leave room for redo + // if the last is true, we have to bail + + if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) + { + // the undo records take up too much character space; there's no space to store the redo characters + r->insert_length = 0; + } + else + { + int i; + + // there's definitely room to store the characters eventually + while (s->undo_char_point + u.delete_length > s->redo_char_point) + { + // there's currently not enough room, so discard a redo record + stb_textedit_discard_redo(s); + // should never happen: + if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) return; + } + r = &s->undo_rec[s->redo_point - 1]; + + r->char_storage = s->redo_char_point - u.delete_length; + s->redo_char_point = s->redo_char_point - (short)u.delete_length; + + // now save the characters + for (i = 0; i < u.delete_length; ++i) + s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); + } + + // now we can carry out the deletion + STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); + } + + // check type of recorded action: + if (u.insert_length) + { + // easy case: was a deletion, so we need to insert n characters + STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); + s->undo_char_point -= u.insert_length; + } + + state->cursor = u.where + u.insert_length; + + s->undo_point--; + s->redo_point--; } static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { - StbUndoState *s = &state->undostate; - StbUndoRecord *u, r; - if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) - return; - - // we need to do two things: apply the redo record, and create an undo record - u = &s->undo_rec[s->undo_point]; - r = s->undo_rec[s->redo_point]; - - // we KNOW there must be room for the undo record, because the redo record - // was derived from an undo record - - u->delete_length = r.insert_length; - u->insert_length = r.delete_length; - u->where = r.where; - u->char_storage = -1; - - if (r.delete_length) { - // the redo record requires us to delete characters, so the undo record - // needs to store the characters - - if (s->undo_char_point + u->insert_length > s->redo_char_point) { - u->insert_length = 0; - u->delete_length = 0; - } else { - int i; - u->char_storage = s->undo_char_point; - s->undo_char_point = s->undo_char_point + u->insert_length; - - // now save the characters - for (i=0; i < u->insert_length; ++i) - s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); - } - - STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); - } - - if (r.insert_length) { - // easy case: need to insert n characters - STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); - s->redo_char_point += r.insert_length; - } - - state->cursor = r.where + r.insert_length; - - s->undo_point++; - s->redo_point++; + StbUndoState * s = &state->undostate; + StbUndoRecord *u, r; + if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) return; + + // we need to do two things: apply the redo record, and create an undo record + u = &s->undo_rec[s->undo_point]; + r = s->undo_rec[s->redo_point]; + + // we KNOW there must be room for the undo record, because the redo record + // was derived from an undo record + + u->delete_length = r.insert_length; + u->insert_length = r.delete_length; + u->where = r.where; + u->char_storage = -1; + + if (r.delete_length) + { + // the redo record requires us to delete characters, so the undo record + // needs to store the characters + + if (s->undo_char_point + u->insert_length > s->redo_char_point) + { + u->insert_length = 0; + u->delete_length = 0; + } + else + { + int i; + u->char_storage = s->undo_char_point; + s->undo_char_point = s->undo_char_point + u->insert_length; + + // now save the characters + for (i = 0; i < u->insert_length; ++i) + s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); + } + + STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); + } + + if (r.insert_length) + { + // easy case: need to insert n characters + STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); + s->redo_char_point += r.insert_length; + } + + state->cursor = r.where + r.insert_length; + + s->undo_point++; + s->redo_point++; } static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) { - stb_text_createundo(&state->undostate, where, 0, length); + stb_text_createundo(&state->undostate, where, 0, length); } static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) { - int i; - STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); - if (p) { - for (i=0; i < length; ++i) - p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); - } + int i; + STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); + if (p) + { + for (i = 0; i < length; ++i) + p[i] = STB_TEXTEDIT_GETCHAR(str, where + i); + } } -static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) +static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, + int new_length) { - int i; - STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); - if (p) { - for (i=0; i < old_length; ++i) - p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); - } + int i; + STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); + if (p) + { + for (i = 0; i < old_length; ++i) + p[i] = STB_TEXTEDIT_GETCHAR(str, where + i); + } } // reset the state to default static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) { - state->undostate.undo_point = 0; - state->undostate.undo_char_point = 0; - state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; - state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; - state->select_end = state->select_start = 0; - state->cursor = 0; - state->has_preferred_x = 0; - state->preferred_x = 0; - state->cursor_at_end_of_line = 0; - state->initialized = 1; - state->single_line = (unsigned char) is_single_line; - state->insert_mode = 0; + state->undostate.undo_point = 0; + state->undostate.undo_char_point = 0; + state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; + state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; + state->select_end = state->select_start = 0; + state->cursor = 0; + state->has_preferred_x = 0; + state->preferred_x = 0; + state->cursor_at_end_of_line = 0; + state->initialized = 1; + state->single_line = (unsigned char)is_single_line; + state->insert_mode = 0; } // API initialize static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) { - stb_textedit_clear_state(state, is_single_line); + stb_textedit_clear_state(state, is_single_line); } -#endif//STB_TEXTEDIT_IMPLEMENTATION +#endif // STB_TEXTEDIT_IMPLEMENTATION diff --git a/source/main/gui/imgui/stb_truetype.h b/source/main/gui/imgui/stb_truetype.h index 92b9a87547..2466830149 100644 --- a/source/main/gui/imgui/stb_truetype.h +++ b/source/main/gui/imgui/stb_truetype.h @@ -31,7 +31,7 @@ // "Zer" on mollyrocket (with fix) // Cass Everitt // stoiko (Haemimont Games) -// Brian Hook +// Brian Hook // Walter van Niftrik // David Gow // David Given @@ -217,7 +217,7 @@ // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation // Bitmap management 100 LOC / // Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 +// Font name matching & access 150 LOC ---- 150 // C runtime library abstraction 60 LOC ---- 60 // // @@ -238,8 +238,8 @@ // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless // #if 0 -#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation -#include "stb_truetype.h" + #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation + #include "stb_truetype.h" unsigned char ttf_buffer[1<<20]; unsigned char temp_bitmap[512*512]; @@ -286,9 +286,9 @@ void my_stbtt_print(float x, float y, char *text) // Complete program (this compiles): get a single bitmap, print as ASCII art // #if 0 -#include -#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation -#include "stb_truetype.h" + #include + #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation + #include "stb_truetype.h" char ttf_buffer[1<<25]; @@ -310,7 +310,7 @@ int main(int argc, char **argv) } return 0; } -#endif +#endif // // Output: // @@ -324,9 +324,9 @@ int main(int argc, char **argv) // :@@. M@M // @@@o@@@@ // :M@@V:@@. -// +// ////////////////////////////////////////////////////////////////////////////// -// +// // Complete program: print "Hello World!" banner, with bugs // #if 0 @@ -373,7 +373,6 @@ int main(int arg, char **argv) } #endif - ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// //// @@ -383,58 +382,58 @@ int main(int arg, char **argv) //// of C library functions used by stb_truetype. #ifdef STB_TRUETYPE_IMPLEMENTATION - // #define your own (u)stbtt_int8/16/32 before including to override this - #ifndef stbtt_uint8 - typedef unsigned char stbtt_uint8; - typedef signed char stbtt_int8; - typedef unsigned short stbtt_uint16; - typedef signed short stbtt_int16; - typedef unsigned int stbtt_uint32; - typedef signed int stbtt_int32; - #endif - - typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; - typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h - #ifndef STBTT_ifloor - #include - #define STBTT_ifloor(x) ((int) floor(x)) - #define STBTT_iceil(x) ((int) ceil(x)) - #endif - - #ifndef STBTT_sqrt - #include - #define STBTT_sqrt(x) sqrt(x) - #endif - - #ifndef STBTT_fabs - #include - #define STBTT_fabs(x) fabs(x) - #endif - - // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h - #ifndef STBTT_malloc - #include - #define STBTT_malloc(x,u) ((void)(u),malloc(x)) - #define STBTT_free(x,u) ((void)(u),free(x)) - #endif - - #ifndef STBTT_assert - #include - #define STBTT_assert(x) assert(x) - #endif - - #ifndef STBTT_strlen - #include - #define STBTT_strlen(x) strlen(x) - #endif - - #ifndef STBTT_memcpy - #include - #define STBTT_memcpy memcpy - #define STBTT_memset memset - #endif + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 +typedef unsigned char stbtt_uint8; +typedef signed char stbtt_int8; +typedef unsigned short stbtt_uint16; +typedef signed short stbtt_int16; +typedef unsigned int stbtt_uint32; +typedef signed int stbtt_int32; + #endif + +typedef char stbtt__check_size32[sizeof(stbtt_int32) == 4 ? 1 : -1]; +typedef char stbtt__check_size16[sizeof(stbtt_int16) == 2 ? 1 : -1]; + + // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int)floor(x)) + #define STBTT_iceil(x) ((int)ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x, u) ((void)(u), malloc(x)) + #define STBTT_free(x, u) ((void)(u), free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif #endif /////////////////////////////////////////////////////////////////////////////// @@ -445,505 +444,546 @@ int main(int arg, char **argv) //// #ifndef __STB_INCLUDE_STB_TRUETYPE_H__ -#define __STB_INCLUDE_STB_TRUETYPE_H__ - -#ifdef STBTT_STATIC -#define STBTT_DEF static -#else -#define STBTT_DEF extern -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// private structure -typedef struct -{ - unsigned char *data; - int cursor; - int size; -} stbtt__buf; - -////////////////////////////////////////////////////////////////////////////// -// -// TEXTURE BAKING API -// -// If you use this API, you only have to call two functions ever. -// - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; -} stbtt_bakedchar; - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata); // you allocate this, it's num_chars long -// if return is positive, the first unused row of the bitmap -// if return is negative, returns the negative of the number of characters that fit -// if return is 0, no characters fit and no rows were used -// This uses a very crappy packing. - -typedef struct -{ - float x0,y0,s0,t0; // top-left - float x1,y1,s1,t1; // bottom-right -} stbtt_aligned_quad; - -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier -// Call GetBakedQuad with char_index = 'character - first_char', and it -// creates the quad you need to draw and advances the current position. -// -// The coordinate system used assumes y increases downwards. -// -// Characters will extend both above and below the current position; -// see discussion of "BASELINE" above. -// -// It's inefficient; you might want to c&p it and optimize it. - - - -////////////////////////////////////////////////////////////////////////////// -// -// NEW TEXTURE BAKING API -// -// This provides options for packing multiple fonts into one atlas, not -// perfectly but better than nothing. - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; - float xoff2,yoff2; -} stbtt_packedchar; - -typedef struct stbtt_pack_context stbtt_pack_context; -typedef struct stbtt_fontinfo stbtt_fontinfo; -#ifndef STB_RECT_PACK_VERSION -typedef struct stbrp_rect stbrp_rect; -#endif - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); -// Initializes a packing context stored in the passed-in stbtt_pack_context. -// Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is width * height. stride_in_bytes is -// the distance from one row to the next (or 0 to mean they are packed tightly -// together). "padding" is the amount of padding to leave between each -// character (normally you want '1' for bitmaps you'll use as textures with -// bilinear filtering). -// -// Returns 0 on failure, 1 on success. - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); -// Cleans up the packing context and frees all memory. - -#define STBTT_POINT_SIZE(x) (-(x)) - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, - int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); -// Creates character bitmaps from the font_index'th font found in fontdata (use -// font_index=0 if you don't know what that is). It creates num_chars_in_range -// bitmaps for characters with unicode values starting at first_unicode_char_in_range -// and increasing. Data for how to render them is stored in chardata_for_range; -// pass these to stbtt_GetPackedQuad to get back renderable quads. -// -// font_size is the full height of the character from ascender to descender, -// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed -// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() -// and pass that result as 'font_size': -// ..., 20 , ... // font max minus min y is 20 pixels tall -// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall - -typedef struct -{ - float font_size; - int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint - int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints - int num_chars; - stbtt_packedchar *chardata_for_range; // output - unsigned char h_oversample, v_oversample; // don't set these, they're used internally -} stbtt_pack_range; - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); -// Creates character bitmaps from multiple ranges of characters stored in -// ranges. This will usually create a better-packed bitmap than multiple -// calls to stbtt_PackFontRange. Note that you can call this multiple -// times within a single PackBegin/PackEnd. - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); -// Oversampling a font increases the quality by allowing higher-quality subpixel -// positioning, and is especially valuable at smaller text sizes. -// -// This function sets the amount of oversampling for all following calls to -// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given -// pack context. The default (no oversampling) is achieved by h_oversample=1 -// and v_oversample=1. The total number of pixels required is -// h_oversample*v_oversample larger than the default; for example, 2x2 -// oversampling requires 4x the storage of 1x1. For best results, render -// oversampled textures with bilinear filtering. Look at the readme in -// stb/tests/oversample for information about oversampled fonts -// -// To use with PackFontRangesGather etc., you must set it before calls -// call to PackFontRangesGatherRects. - -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int align_to_integer); - -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -// Calling these functions in sequence is roughly equivalent to calling -// stbtt_PackFontRanges(). If you more control over the packing of multiple -// fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version -// using these functions, e.g. call GatherRects multiple times, -// building up a single array of rects, then call PackRects once, -// then call RenderIntoRects repeatedly. This may result in a -// better packing than calling PackFontRanges multiple times -// (or it may not). - -// this is an opaque structure that you shouldn't mess with which holds -// all the context needed from PackBegin to PackEnd. -struct stbtt_pack_context { - void *user_allocator_context; - void *pack_info; - int width; - int height; - int stride_in_bytes; - int padding; - unsigned int h_oversample, v_oversample; - unsigned char *pixels; - void *nodes; -}; - -////////////////////////////////////////////////////////////////////////////// -// -// FONT LOADING -// -// - -STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); -// This function will determine the number of fonts in a font file. TrueType -// collection (.ttc) files may contain multiple fonts, while TrueType font -// (.ttf) files only contain one font. The number of fonts can be used for -// indexing with the previous function where the index is between zero and one -// less than the total fonts. If an error occurs, -1 is returned. - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); -// Each .ttf/.ttc file may have more than one font. Each font has a sequential -// index number starting from 0. Call this function to get the font offset for -// a given index; it returns -1 if the index is out of range. A regular .ttf -// file will only define one font and it always be at offset 0, so it will -// return '0' for index 0, and -1 for all other indices. - -// The following structure is defined publically so you can declare one on -// the stack or as a global or etc, but you should treat it as opaque. -struct stbtt_fontinfo -{ - void * userdata; - unsigned char * data; // pointer to .ttf file - int fontstart; // offset of start of font - - int numGlyphs; // number of glyphs, needed for range checking - - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf - int index_map; // a cmap mapping for our chosen character encoding - int indexToLocFormat; // format needed to map from glyph index to glyph - - stbtt__buf cff; // cff font data - stbtt__buf charstrings; // the charstring index - stbtt__buf gsubrs; // global charstring subroutines index - stbtt__buf subrs; // private charstring subroutines index - stbtt__buf fontdicts; // array of font dicts - stbtt__buf fdselect; // map from glyph to fontdict -}; - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); -// Given an offset into the file that defines a font, this function builds -// the necessary cached info for the rest of the system. You must allocate -// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't -// need to do anything special to free it, because the contents are pure -// value data with no additional data structures. Returns 0 on failure. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER TO GLYPH-INDEX CONVERSIOn - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); -// If you're going to perform multiple operations on the same character -// and you want a speed-up, call this function with the character you're -// going to process, then use glyph-based functions instead of the -// codepoint-based functions. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER PROPERTIES -// - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose "height" is 'pixels' tall. -// Height is measured as the distance from the highest ascender to the lowest -// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics -// and computing: -// scale = pixels / (ascent - descent) -// so if you prefer to measure height by the ascent only, use a similar calculation. - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose EM size is mapped to -// 'pixels' tall. This is probably what traditional APIs compute, but -// I'm not positive. - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); -// ascent is the coordinate above the baseline the font extends; descent -// is the coordinate below the baseline the font extends (i.e. it is typically negative) -// lineGap is the spacing between one row's descent and the next row's ascent... -// so you should advance the vertical position by "*ascent - *descent + *lineGap" -// these are expressed in unscaled coordinates, so you must multiply by -// the scale factor for a given size - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); -// the bounding box around all possible characters - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); -// leftSideBearing is the offset from the current horizontal position to the left edge of the character -// advanceWidth is the offset from the current horizontal position to the next horizontal position -// these are expressed in unscaled coordinates - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); -// an additional amount to add to the 'advance' value between ch1 and ch2 - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); -// Gets the bounding box of the visible part of the glyph, in unscaled coordinates - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); -// as above, but takes one or more glyph indices for greater efficiency - - -////////////////////////////////////////////////////////////////////////////// -// -// GLYPH SHAPES (you probably don't need these, but they have to go before -// the bitmaps for C declaration-order reasons) -// - -#ifndef STBTT_vmove // you can predefine these to use different values (but why?) - enum { - STBTT_vmove=1, - STBTT_vline, - STBTT_vcurve, - STBTT_vcubic - }; -#endif - -#ifndef stbtt_vertex // you can predefine this to use different values - // (we share this with other code at RAD) - #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file - typedef struct - { - stbtt_vertex_type x,y,cx,cy,cx1,cy1; - unsigned char type,padding; - } stbtt_vertex; -#endif - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); -// returns non-zero if nothing is drawn for this glyph - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); -// returns # of vertices and fills *vertices with the pointer to them -// these are expressed in "unscaled" coordinates -// -// The shape is a series of countours. Each one starts with -// a STBTT_moveto, then consists of a series of mixed -// STBTT_lineto and STBTT_curveto segments. A lineto -// draws a line from previous endpoint to its x,y; a curveto -// draws a quadratic bezier from previous endpoint to -// its x,y, using cx,cy as the bezier control point. - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); -// frees the data allocated above - -////////////////////////////////////////////////////////////////////////////// -// -// BITMAP RENDERING -// - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); -// frees the bitmap allocated below - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// allocates a large-enough single-channel 8bpp bitmap and renders the -// specified character/glyph at the specified scale into it, with -// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). -// *width & *height are filled out with the width & height of the bitmap, -// which is stored left-to-right, top-to-bottom. -// -// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); -// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap -// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap -// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the -// width and height and positioning info for it first. - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); -// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -// get the bbox of the bitmap centered around the glyph origin; so the -// bitmap width is ix1-ix0, height is iy1-iy0, and location to place -// the bitmap top left is (leftSideBearing*scale,iy0). -// (Note that the bitmap uses y-increases-down, but the shape uses -// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); -// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel -// shift for the character - -// the following functions are equivalent to the above functions, but operate -// on glyph indices instead of Unicode codepoints (for efficiency) -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); - - -// @TODO: don't expose this structure -typedef struct -{ - int w,h,stride; - unsigned char *pixels; -} stbtt__bitmap; - -// rasterize a shape with quadratic beziers into a bitmap -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into - float flatness_in_pixels, // allowable error of curve in pixels - stbtt_vertex *vertices, // array of vertices defining shape - int num_verts, // number of vertices in above array - float scale_x, float scale_y, // scale applied to input vertices - float shift_x, float shift_y, // translation applied to input vertices - int x_off, int y_off, // another translation applied to input - int invert, // if non-zero, vertically flip shape - void *userdata); // context for to STBTT_MALLOC - -////////////////////////////////////////////////////////////////////////////// -// -// Finding the right font... -// -// You should really just solve this offline, keep your own tables -// of what font is what, and don't try to get it out of the .ttf file. -// That's because getting it out of the .ttf file is really hard, because -// the names in the file can appear in many possible encodings, in many -// possible languages, and e.g. if you need a case-insensitive comparison, -// the details of that depend on the encoding & language in a complex way -// (actually underspecified in truetype, but also gigantic). -// -// But you can use the provided functions in two possible ways: -// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on -// unicode-encoded names to try to find the font you want; -// you can run this before calling stbtt_InitFont() -// -// stbtt_GetFontNameString() lets you get any of the various strings -// from the file yourself and do your own comparisons on them. -// You have to have called stbtt_InitFont() first. - - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); -// returns the offset (not index) of the font that matches, or -1 if none -// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". -// if you use any other flag, use a font name like "Arial"; this checks -// the 'macStyle' header field; i don't know if fonts set this consistently -#define STBTT_MACSTYLE_DONTCARE 0 -#define STBTT_MACSTYLE_BOLD 1 -#define STBTT_MACSTYLE_ITALIC 2 -#define STBTT_MACSTYLE_UNDERSCORE 4 -#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); -// returns 1/0 whether the first string interpreted as utf8 is identical to -// the second string interpreted as big-endian utf16... useful for strings from next func - -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); -// returns the string (which may be big-endian double byte, e.g. for unicode) -// and puts the length in bytes in *length. -// -// some of the values for the IDs are below; for more see the truetype spec: -// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html -// http://www.microsoft.com/typography/otspec/name.htm - -enum { // platformID - STBTT_PLATFORM_ID_UNICODE =0, - STBTT_PLATFORM_ID_MAC =1, - STBTT_PLATFORM_ID_ISO =2, - STBTT_PLATFORM_ID_MICROSOFT =3 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_UNICODE - STBTT_UNICODE_EID_UNICODE_1_0 =0, - STBTT_UNICODE_EID_UNICODE_1_1 =1, - STBTT_UNICODE_EID_ISO_10646 =2, - STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, - STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT - STBTT_MS_EID_SYMBOL =0, - STBTT_MS_EID_UNICODE_BMP =1, - STBTT_MS_EID_SHIFTJIS =2, - STBTT_MS_EID_UNICODE_FULL =10 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes - STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, - STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, - STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, - STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 -}; - -enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... - // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs - STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, - STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, - STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, - STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, - STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, - STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D -}; - -enum { // languageID for STBTT_PLATFORM_ID_MAC - STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, - STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, - STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, - STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , - STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , - STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, - STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 -}; - -#ifdef __cplusplus + #define __STB_INCLUDE_STB_TRUETYPE_H__ + + #ifdef STBTT_STATIC + #define STBTT_DEF static + #else + #define STBTT_DEF extern + #endif + + #ifdef __cplusplus +extern "C" +{ + #endif + + // private structure + typedef struct + { + unsigned char *data; + int cursor; + int size; + } stbtt__buf; + + ////////////////////////////////////////////////////////////////////////////// + // + // TEXTURE BAKING API + // + // If you use this API, you only have to call two functions ever. + // + + typedef struct + { + unsigned short x0, y0, x1, y1; // coordinates of bbox in bitmap + float xoff, yoff, xadvance; + } stbtt_bakedchar; + + STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long + // if return is positive, the first unused row of the bitmap + // if return is negative, returns the negative of the number of characters that fit + // if return is 0, no characters fit and no rows were used + // This uses a very crappy packing. + + typedef struct + { + float x0, y0, s0, t0; // top-left + float x1, y1, s1, t1; // bottom-right + } stbtt_aligned_quad; + + STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier + // Call GetBakedQuad with char_index = 'character - first_char', and it + // creates the quad you need to draw and advances the current position. + // + // The coordinate system used assumes y increases downwards. + // + // Characters will extend both above and below the current position; + // see discussion of "BASELINE" above. + // + // It's inefficient; you might want to c&p it and optimize it. + + ////////////////////////////////////////////////////////////////////////////// + // + // NEW TEXTURE BAKING API + // + // This provides options for packing multiple fonts into one atlas, not + // perfectly but better than nothing. + + typedef struct + { + unsigned short x0, y0, x1, y1; // coordinates of bbox in bitmap + float xoff, yoff, xadvance; + float xoff2, yoff2; + } stbtt_packedchar; + + typedef struct stbtt_pack_context stbtt_pack_context; + typedef struct stbtt_fontinfo stbtt_fontinfo; + #ifndef STB_RECT_PACK_VERSION + typedef struct stbrp_rect stbrp_rect; + #endif + + STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, + int padding, void *alloc_context); + // Initializes a packing context stored in the passed-in stbtt_pack_context. + // Future calls using this context will pack characters into the bitmap passed + // in here: a 1-channel bitmap that is width * height. stride_in_bytes is + // the distance from one row to the next (or 0 to mean they are packed tightly + // together). "padding" is the amount of padding to leave between each + // character (normally you want '1' for bitmaps you'll use as textures with + // bilinear filtering). + // + // Returns 0 on failure, 1 on success. + + STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc); + // Cleans up the packing context and frees all memory. + + #define STBTT_POINT_SIZE(x) (-(x)) + + STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, + stbtt_packedchar *chardata_for_range); + // Creates character bitmaps from the font_index'th font found in fontdata (use + // font_index=0 if you don't know what that is). It creates num_chars_in_range + // bitmaps for characters with unicode values starting at first_unicode_char_in_range + // and increasing. Data for how to render them is stored in chardata_for_range; + // pass these to stbtt_GetPackedQuad to get back renderable quads. + // + // font_size is the full height of the character from ascender to descender, + // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed + // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() + // and pass that result as 'font_size': + // ..., 20 , ... // font max minus min y is 20 pixels tall + // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + + typedef struct + { + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int * array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally + } stbtt_pack_range; + + STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, + int num_ranges); + // Creates character bitmaps from multiple ranges of characters stored in + // ranges. This will usually create a better-packed bitmap than multiple + // calls to stbtt_PackFontRange. Note that you can call this multiple + // times within a single PackBegin/PackEnd. + + STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); + // Oversampling a font increases the quality by allowing higher-quality subpixel + // positioning, and is especially valuable at smaller text sizes. + // + // This function sets the amount of oversampling for all following calls to + // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given + // pack context. The default (no oversampling) is achieved by h_oversample=1 + // and v_oversample=1. The total number of pixels required is + // h_oversample*v_oversample larger than the default; for example, 2x2 + // oversampling requires 4x the storage of 1x1. For best results, render + // oversampled textures with bilinear filtering. Look at the readme in + // stb/tests/oversample for information about oversampled fonts + // + // To use with PackFontRangesGather etc., you must set it before calls + // call to PackFontRangesGatherRects. + + STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + + STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, + int num_ranges, stbrp_rect *rects); + STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); + STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, + stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); + // Calling these functions in sequence is roughly equivalent to calling + // stbtt_PackFontRanges(). If you more control over the packing of multiple + // fonts, or if you want to pack custom data into a font texture, take a look + // at the source to of stbtt_PackFontRanges() and create a custom version + // using these functions, e.g. call GatherRects multiple times, + // building up a single array of rects, then call PackRects once, + // then call RenderIntoRects repeatedly. This may result in a + // better packing than calling PackFontRanges multiple times + // (or it may not). + + // this is an opaque structure that you shouldn't mess with which holds + // all the context needed from PackBegin to PackEnd. + struct stbtt_pack_context + { + void * user_allocator_context; + void * pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void * nodes; + }; + + ////////////////////////////////////////////////////////////////////////////// + // + // FONT LOADING + // + // + + STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); + // This function will determine the number of fonts in a font file. TrueType + // collection (.ttc) files may contain multiple fonts, while TrueType font + // (.ttf) files only contain one font. The number of fonts can be used for + // indexing with the previous function where the index is between zero and one + // less than the total fonts. If an error occurs, -1 is returned. + + STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); + // Each .ttf/.ttc file may have more than one font. Each font has a sequential + // index number starting from 0. Call this function to get the font offset for + // a given index; it returns -1 if the index is out of range. A regular .ttf + // file will only define one font and it always be at offset 0, so it will + // return '0' for index 0, and -1 for all other indices. + + // The following structure is defined publically so you can declare one on + // the stack or as a global or etc, but you should treat it as opaque. + struct stbtt_fontinfo + { + void * userdata; + unsigned char *data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca, head, glyf, hhea, hmtx, kern; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict + }; + + STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); + // Given an offset into the file that defines a font, this function builds + // the necessary cached info for the rest of the system. You must allocate + // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't + // need to do anything special to free it, because the contents are pure + // value data with no additional data structures. Returns 0 on failure. + + ////////////////////////////////////////////////////////////////////////////// + // + // CHARACTER TO GLYPH-INDEX CONVERSIOn + + STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); + // If you're going to perform multiple operations on the same character + // and you want a speed-up, call this function with the character you're + // going to process, then use glyph-based functions instead of the + // codepoint-based functions. + + ////////////////////////////////////////////////////////////////////////////// + // + // CHARACTER PROPERTIES + // + + STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); + // computes a scale factor to produce a font whose "height" is 'pixels' tall. + // Height is measured as the distance from the highest ascender to the lowest + // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics + // and computing: + // scale = pixels / (ascent - descent) + // so if you prefer to measure height by the ascent only, use a similar calculation. + + STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); + // computes a scale factor to produce a font whose EM size is mapped to + // 'pixels' tall. This is probably what traditional APIs compute, but + // I'm not positive. + + STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); + // ascent is the coordinate above the baseline the font extends; descent + // is the coordinate below the baseline the font extends (i.e. it is typically negative) + // lineGap is the spacing between one row's descent and the next row's ascent... + // so you should advance the vertical position by "*ascent - *descent + *lineGap" + // these are expressed in unscaled coordinates, so you must multiply by + // the scale factor for a given size + + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); + // the bounding box around all possible characters + + STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); + // leftSideBearing is the offset from the current horizontal position to the left edge of the character + // advanceWidth is the offset from the current horizontal position to the next horizontal position + // these are expressed in unscaled coordinates + + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); + // an additional amount to add to the 'advance' value between ch1 and ch2 + + STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); + // Gets the bounding box of the visible part of the glyph, in unscaled coordinates + + STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); + STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); + STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + // as above, but takes one or more glyph indices for greater efficiency + + ////////////////////////////////////////////////////////////////////////////// + // + // GLYPH SHAPES (you probably don't need these, but they have to go before + // the bitmaps for C declaration-order reasons) + // + + #ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum + { + STBTT_vmove = 1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; + #endif + + #ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x, y, cx, cy, cx1, cy1; + unsigned char type, padding; + } stbtt_vertex; + #endif + + STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); + // returns non-zero if nothing is drawn for this glyph + + STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); + STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); + // returns # of vertices and fills *vertices with the pointer to them + // these are expressed in "unscaled" coordinates + // + // The shape is a series of countours. Each one starts with + // a STBTT_moveto, then consists of a series of mixed + // STBTT_lineto and STBTT_curveto segments. A lineto + // draws a line from previous endpoint to its x,y; a curveto + // draws a quadratic bezier from previous endpoint to + // its x,y, using cx,cy as the bezier control point. + + STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); + // frees the data allocated above + + ////////////////////////////////////////////////////////////////////////////// + // + // BITMAP RENDERING + // + + STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); + // frees the bitmap allocated below + + STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, + int *width, int *height, int *xoff, int *yoff); + // allocates a large-enough single-channel 8bpp bitmap and renders the + // specified character/glyph at the specified scale into it, with + // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). + // *width & *height are filled out with the width & height of the bitmap, + // which is stored left-to-right, top-to-bottom. + // + // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + + STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, + float shift_x, float shift_y, int codepoint, int *width, + int *height, int *xoff, int *yoff); + // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel + // shift for the character + + STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, + int out_stride, float scale_x, float scale_y, int codepoint); + // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap + // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap + // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the + // width and height and positioning info for it first. + + STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, + int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, + int codepoint); + // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel + // shift for the character + + STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, + int *iy0, int *ix1, int *iy1); + // get the bbox of the bitmap centered around the glyph origin; so the + // bitmap width is ix1-ix0, height is iy1-iy0, and location to place + // the bitmap top left is (leftSideBearing*scale,iy0). + // (Note that the bitmap uses y-increases-down, but the shape uses + // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + + STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, + float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel + // shift for the character + + // the following functions are equivalent to the above functions, but operate + // on glyph indices instead of Unicode codepoints (for efficiency) + STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, + int *height, int *xoff, int *yoff); + STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, + float shift_y, int glyph, int *width, int *height, int *xoff, + int *yoff); + STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, + float scale_x, float scale_y, int glyph); + STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, + int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, + int glyph); + STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, + int *iy0, int *ix1, int *iy1); + STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, + float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + // @TODO: don't expose this structure + typedef struct + { + int w, h, stride; + unsigned char *pixels; + } stbtt__bitmap; + + // rasterize a shape with quadratic beziers into a bitmap + STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex * vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + + ////////////////////////////////////////////////////////////////////////////// + // + // Finding the right font... + // + // You should really just solve this offline, keep your own tables + // of what font is what, and don't try to get it out of the .ttf file. + // That's because getting it out of the .ttf file is really hard, because + // the names in the file can appear in many possible encodings, in many + // possible languages, and e.g. if you need a case-insensitive comparison, + // the details of that depend on the encoding & language in a complex way + // (actually underspecified in truetype, but also gigantic). + // + // But you can use the provided functions in two possible ways: + // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on + // unicode-encoded names to try to find the font you want; + // you can run this before calling stbtt_InitFont() + // + // stbtt_GetFontNameString() lets you get any of the various strings + // from the file yourself and do your own comparisons on them. + // You have to have called stbtt_InitFont() first. + + STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); + // returns the offset (not index) of the font that matches, or -1 if none + // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". + // if you use any other flag, use a font name like "Arial"; this checks + // the 'macStyle' header field; i don't know if fonts set this consistently + #define STBTT_MACSTYLE_DONTCARE 0 + #define STBTT_MACSTYLE_BOLD 1 + #define STBTT_MACSTYLE_ITALIC 2 + #define STBTT_MACSTYLE_UNDERSCORE 4 + #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + + STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); + // returns 1/0 whether the first string interpreted as utf8 is identical to + // the second string interpreted as big-endian utf16... useful for strings from next func + + STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, + int languageID, int nameID); + // returns the string (which may be big-endian double byte, e.g. for unicode) + // and puts the length in bytes in *length. + // + // some of the values for the IDs are below; for more see the truetype spec: + // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html + // http://www.microsoft.com/typography/otspec/name.htm + + enum + { // platformID + STBTT_PLATFORM_ID_UNICODE = 0, + STBTT_PLATFORM_ID_MAC = 1, + STBTT_PLATFORM_ID_ISO = 2, + STBTT_PLATFORM_ID_MICROSOFT = 3 + }; + + enum + { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 = 0, + STBTT_UNICODE_EID_UNICODE_1_1 = 1, + STBTT_UNICODE_EID_ISO_10646 = 2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP = 3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL = 4 + }; + + enum + { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL = 0, + STBTT_MS_EID_UNICODE_BMP = 1, + STBTT_MS_EID_SHIFTJIS = 2, + STBTT_MS_EID_UNICODE_FULL = 10 + }; + + enum + { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN = 0, + STBTT_MAC_EID_ARABIC = 4, + STBTT_MAC_EID_JAPANESE = 1, + STBTT_MAC_EID_HEBREW = 5, + STBTT_MAC_EID_CHINESE_TRAD = 2, + STBTT_MAC_EID_GREEK = 6, + STBTT_MAC_EID_KOREAN = 3, + STBTT_MAC_EID_RUSSIAN = 7 + }; + + enum + { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH = 0x0409, + STBTT_MS_LANG_ITALIAN = 0x0410, + STBTT_MS_LANG_CHINESE = 0x0804, + STBTT_MS_LANG_JAPANESE = 0x0411, + STBTT_MS_LANG_DUTCH = 0x0413, + STBTT_MS_LANG_KOREAN = 0x0412, + STBTT_MS_LANG_FRENCH = 0x040c, + STBTT_MS_LANG_RUSSIAN = 0x0419, + STBTT_MS_LANG_GERMAN = 0x0407, + STBTT_MS_LANG_SPANISH = 0x0409, + STBTT_MS_LANG_HEBREW = 0x040d, + STBTT_MS_LANG_SWEDISH = 0x041D + }; + + enum + { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH = 0, + STBTT_MAC_LANG_JAPANESE = 11, + STBTT_MAC_LANG_ARABIC = 12, + STBTT_MAC_LANG_KOREAN = 23, + STBTT_MAC_LANG_DUTCH = 4, + STBTT_MAC_LANG_RUSSIAN = 32, + STBTT_MAC_LANG_FRENCH = 1, + STBTT_MAC_LANG_SPANISH = 6, + STBTT_MAC_LANG_GERMAN = 2, + STBTT_MAC_LANG_SWEDISH = 5, + STBTT_MAC_LANG_HEBREW = 10, + STBTT_MAC_LANG_CHINESE_SIMPLIFIED = 33, + STBTT_MAC_LANG_ITALIAN = 3, + STBTT_MAC_LANG_CHINESE_TRAD = 19 + }; + + #ifdef __cplusplus } -#endif + #endif #endif // __STB_INCLUDE_STB_TRUETYPE_H__ @@ -956,25 +996,25 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC #ifdef STB_TRUETYPE_IMPLEMENTATION -#ifndef STBTT_MAX_OVERSAMPLE -#define STBTT_MAX_OVERSAMPLE 8 -#endif + #ifndef STBTT_MAX_OVERSAMPLE + #define STBTT_MAX_OVERSAMPLE 8 + #endif -#if STBTT_MAX_OVERSAMPLE > 255 -#error "STBTT_MAX_OVERSAMPLE cannot be > 255" -#endif + #if STBTT_MAX_OVERSAMPLE > 255 + #error "STBTT_MAX_OVERSAMPLE cannot be > 255" + #endif -typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE - 1)) == 0 ? 1 : -1]; -#ifndef STBTT_RASTERIZER_VERSION -#define STBTT_RASTERIZER_VERSION 2 -#endif + #ifndef STBTT_RASTERIZER_VERSION + #define STBTT_RASTERIZER_VERSION 2 + #endif -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif + #ifdef _MSC_VER + #define STBTT__NOTUSED(v) (void)(v) + #else + #define STBTT__NOTUSED(v) (void)sizeof(v) + #endif ////////////////////////////////////////////////////////////////////////// // @@ -983,143 +1023,152 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) { - if (b->cursor >= b->size) - return 0; - return b->data[b->cursor++]; + if (b->cursor >= b->size) return 0; + return b->data[b->cursor++]; } static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) { - if (b->cursor >= b->size) - return 0; - return b->data[b->cursor]; + if (b->cursor >= b->size) return 0; + return b->data[b->cursor]; } static void stbtt__buf_seek(stbtt__buf *b, int o) { - STBTT_assert(!(o > b->size || o < 0)); - b->cursor = (o > b->size || o < 0) ? b->size : o; + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; } static void stbtt__buf_skip(stbtt__buf *b, int o) { - stbtt__buf_seek(b, b->cursor + o); + stbtt__buf_seek(b, b->cursor + o); } static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) { - stbtt_uint32 v = 0; - int i; - STBTT_assert(n >= 1 && n <= 4); - for (i = 0; i < n; i++) - v = (v << 8) | stbtt__buf_get8(b); - return v; + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; } static stbtt__buf stbtt__new_buf(const void *p, size_t size) { - stbtt__buf r; - STBTT_assert(size < 0x40000000); - r.data = (stbtt_uint8*) p; - r.size = (int) size; - r.cursor = 0; - return r; + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8 *)p; + r.size = (int)size; + r.cursor = 0; + return r; } -#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) -#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + #define stbtt__buf_get16(b) stbtt__buf_get((b), 2) + #define stbtt__buf_get32(b) stbtt__buf_get((b), 4) static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) { - stbtt__buf r = stbtt__new_buf(NULL, 0); - if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; - r.data = b->data + o; - r.size = s; - return r; + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; } static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) { - int count, start, offsize; - start = b->cursor; - count = stbtt__buf_get16(b); - if (count) { - offsize = stbtt__buf_get8(b); - STBTT_assert(offsize >= 1 && offsize <= 4); - stbtt__buf_skip(b, offsize * count); - stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); - } - return stbtt__buf_range(b, start, b->cursor - start); + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) + { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); } static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) { - int b0 = stbtt__buf_get8(b); - if (b0 >= 32 && b0 <= 246) return b0 - 139; - else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; - else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; - else if (b0 == 28) return stbtt__buf_get16(b); - else if (b0 == 29) return stbtt__buf_get32(b); - STBTT_assert(0); - return 0; + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) + return b0 - 139; + else if (b0 >= 247 && b0 <= 250) + return (b0 - 247) * 256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) + return -(b0 - 251) * 256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) + return stbtt__buf_get16(b); + else if (b0 == 29) + return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; } -static void stbtt__cff_skip_operand(stbtt__buf *b) { - int v, b0 = stbtt__buf_peek8(b); - STBTT_assert(b0 >= 28); - if (b0 == 30) { - stbtt__buf_skip(b, 1); - while (b->cursor < b->size) { - v = stbtt__buf_get8(b); - if ((v & 0xF) == 0xF || (v >> 4) == 0xF) - break; - } - } else { - stbtt__cff_int(b); - } +static void stbtt__cff_skip_operand(stbtt__buf *b) +{ + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) + { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) + { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) break; + } + } + else + { + stbtt__cff_int(b); + } } static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) { - stbtt__buf_seek(b, 0); - while (b->cursor < b->size) { - int start = b->cursor, end, op; - while (stbtt__buf_peek8(b) >= 28) - stbtt__cff_skip_operand(b); - end = b->cursor; - op = stbtt__buf_get8(b); - if (op == 12) op = stbtt__buf_get8(b) | 0x100; - if (op == key) return stbtt__buf_range(b, start, end-start); - } - return stbtt__buf_range(b, 0, 0); + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) + { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end - start); + } + return stbtt__buf_range(b, 0, 0); } static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) { - int i; - stbtt__buf operands = stbtt__dict_get(b, key); - for (i = 0; i < outcount && operands.cursor < operands.size; i++) - out[i] = stbtt__cff_int(&operands); + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); } static int stbtt__cff_index_count(stbtt__buf *b) { - stbtt__buf_seek(b, 0); - return stbtt__buf_get16(b); + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); } static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) { - int count, offsize, start, end; - stbtt__buf_seek(&b, 0); - count = stbtt__buf_get16(&b); - offsize = stbtt__buf_get8(&b); - STBTT_assert(i >= 0 && i < count); - STBTT_assert(offsize >= 1 && offsize <= 4); - stbtt__buf_skip(&b, i*offsize); - start = stbtt__buf_get(&b, offsize); - end = stbtt__buf_get(&b, offsize); - return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i * offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2 + (count + 1) * offsize + start, end - start); } ////////////////////////////////////////////////////////////////////////// @@ -1130,1099 +1179,1216 @@ static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) // on platforms that don't allow misaligned reads, if we want to allow // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE -#define ttBYTE(p) (* (stbtt_uint8 *) (p)) -#define ttCHAR(p) (* (stbtt_int8 *) (p)) -#define ttFixed(p) ttLONG(p) + #define ttBYTE(p) (*(stbtt_uint8 *)(p)) + #define ttCHAR(p) (*(stbtt_int8 *)(p)) + #define ttFixed(p) ttLONG(p) -static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } -static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } -static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } -static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) +{ + return p[0] * 256 + p[1]; +} +static stbtt_int16 ttSHORT(stbtt_uint8 *p) +{ + return p[0] * 256 + p[1]; +} +static stbtt_uint32 ttULONG(stbtt_uint8 *p) +{ + return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; +} +static stbtt_int32 ttLONG(stbtt_uint8 *p) +{ + return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; +} -#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) -#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + #define stbtt_tag4(p, c0, c1, c2, c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) + #define stbtt_tag(p, str) stbtt_tag4(p, str[0], str[1], str[2], str[3]) static int stbtt__isfont(stbtt_uint8 *font) { - // check the version number - if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 - if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! - if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF - if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 - if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts - return 0; + // check the version number + if (stbtt_tag4(font, '1', 0, 0, 0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0, 1, 0, 0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; } // @OPTIMIZE: binary search static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) { - stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); - stbtt_uint32 tabledir = fontstart + 12; - stbtt_int32 i; - for (i=0; i < num_tables; ++i) { - stbtt_uint32 loc = tabledir + 16*i; - if (stbtt_tag(data+loc+0, tag)) - return ttULONG(data+loc+8); - } - return 0; + stbtt_int32 num_tables = ttUSHORT(data + fontstart + 4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i = 0; i < num_tables; ++i) + { + stbtt_uint32 loc = tabledir + 16 * i; + if (stbtt_tag(data + loc + 0, tag)) return ttULONG(data + loc + 8); + } + return 0; } static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) { - // if it's just a font, there's only one valid index - if (stbtt__isfont(font_collection)) - return index == 0 ? 0 : -1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - stbtt_int32 n = ttLONG(font_collection+8); - if (index >= n) - return -1; - return ttULONG(font_collection+12+index*4); - } - } - return -1; + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) + { + // version 1? + if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection + 4) == 0x00020000) + { + stbtt_int32 n = ttLONG(font_collection + 8); + if (index >= n) return -1; + return ttULONG(font_collection + 12 + index * 4); + } + } + return -1; } static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) { - // if it's just a font, there's only one valid font - if (stbtt__isfont(font_collection)) - return 1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - return ttLONG(font_collection+8); - } - } - return 0; + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) + { + // version 1? + if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection + 4) == 0x00020000) + { return ttLONG(font_collection + 8); } + } + return 0; } static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) { - stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; - stbtt__buf pdict; - stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); - if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); - pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); - stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); - if (!subrsoff) return stbtt__new_buf(NULL, 0); - stbtt__buf_seek(&cff, private_loc[1]+subrsoff); - return stbtt__cff_get_index(&cff); + stbtt_uint32 subrsoff = 0, private_loc[2] = {0, 0}; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1] + subrsoff); + return stbtt__cff_get_index(&cff); } static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { - stbtt_uint32 cmap, t; - stbtt_int32 i,numTables; - - info->data = data; - info->fontstart = fontstart; - info->cff = stbtt__new_buf(NULL, 0); - - cmap = stbtt__find_table(data, fontstart, "cmap"); // required - info->loca = stbtt__find_table(data, fontstart, "loca"); // required - info->head = stbtt__find_table(data, fontstart, "head"); // required - info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required - info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required - info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required - info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - - if (!cmap || !info->head || !info->hhea || !info->hmtx) - return 0; - if (info->glyf) { - // required for truetype - if (!info->loca) return 0; - } else { - // initialization for CFF / Type2 fonts (OTF) - stbtt__buf b, topdict, topdictidx; - stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; - stbtt_uint32 cff; - - cff = stbtt__find_table(data, fontstart, "CFF "); - if (!cff) return 0; - - info->fontdicts = stbtt__new_buf(NULL, 0); - info->fdselect = stbtt__new_buf(NULL, 0); - - // @TODO this should use size from table (not 512MB) - info->cff = stbtt__new_buf(data+cff, 512*1024*1024); - b = info->cff; - - // read the header - stbtt__buf_skip(&b, 2); - stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize - - // @TODO the name INDEX could list multiple fonts, - // but we just use the first one. - stbtt__cff_get_index(&b); // name INDEX - topdictidx = stbtt__cff_get_index(&b); - topdict = stbtt__cff_index_get(topdictidx, 0); - stbtt__cff_get_index(&b); // string INDEX - info->gsubrs = stbtt__cff_get_index(&b); - - stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); - stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); - stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); - stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); - info->subrs = stbtt__get_subrs(b, topdict); - - // we only support Type 2 charstrings - if (cstype != 2) return 0; - if (charstrings == 0) return 0; - - if (fdarrayoff) { - // looks like a CID font - if (!fdselectoff) return 0; - stbtt__buf_seek(&b, fdarrayoff); - info->fontdicts = stbtt__cff_get_index(&b); - info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); - } - - stbtt__buf_seek(&b, charstrings); - info->charstrings = stbtt__cff_get_index(&b); - } - - t = stbtt__find_table(data, fontstart, "maxp"); - if (t) - info->numGlyphs = ttUSHORT(data+t+4); - else - info->numGlyphs = 0xffff; - - // find a cmap encoding table we understand *now* to avoid searching - // later. (todo: could make this installable) - // the same regardless of glyph. - numTables = ttUSHORT(data + cmap + 2); - info->index_map = 0; - for (i=0; i < numTables; ++i) { - stbtt_uint32 encoding_record = cmap + 4 + 8 * i; - // find an encoding we understand: - switch(ttUSHORT(data+encoding_record)) { - case STBTT_PLATFORM_ID_MICROSOFT: - switch (ttUSHORT(data+encoding_record+2)) { - case STBTT_MS_EID_UNICODE_BMP: - case STBTT_MS_EID_UNICODE_FULL: - // MS/Unicode - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; + stbtt_uint32 cmap, t; + stbtt_int32 i, numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; + if (info->glyf) + { + // required for truetype + if (!info->loca) return 0; + } + else + { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data + cff, 512 * 1024 * 1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) + { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size - fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data + t + 4); + else + info->numGlyphs = 0xffff; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i = 0; i < numTables; ++i) + { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch (ttUSHORT(data + encoding_record)) + { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data + encoding_record + 2)) + { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data + encoding_record + 4); + break; } break; case STBTT_PLATFORM_ID_UNICODE: // Mac/iOS has these // all the encodingIDs are unicode, so we don't bother to check it - info->index_map = cmap + ttULONG(data+encoding_record+4); + info->index_map = cmap + ttULONG(data + encoding_record + 4); break; - } - } - if (info->index_map == 0) - return 0; + } + } + if (info->index_map == 0) return 0; - info->indexToLocFormat = ttUSHORT(data+info->head + 50); - return 1; + info->indexToLocFormat = ttUSHORT(data + info->head + 50); + return 1; } STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) { - stbtt_uint8 *data = info->data; - stbtt_uint32 index_map = info->index_map; - - stbtt_uint16 format = ttUSHORT(data + index_map + 0); - if (format == 0) { // apple byte encoding - stbtt_int32 bytes = ttUSHORT(data + index_map + 2); - if (unicode_codepoint < bytes-6) - return ttBYTE(data + index_map + 6 + unicode_codepoint); - return 0; - } else if (format == 6) { - stbtt_uint32 first = ttUSHORT(data + index_map + 6); - stbtt_uint32 count = ttUSHORT(data + index_map + 8); - if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) - return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); - return 0; - } else if (format == 2) { - STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean - return 0; - } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges - stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; - stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; - stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); - stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; - - // do a binary search of the segments - stbtt_uint32 endCount = index_map + 14; - stbtt_uint32 search = endCount; - - if (unicode_codepoint > 0xffff) - return 0; - - // they lie from endCount .. endCount + segCount - // but searchRange is the nearest power of two, so... - if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) - search += rangeShift*2; - - // now decrement to bias correctly to find smallest - search -= 2; - while (entrySelector) { - stbtt_uint16 end; - searchRange >>= 1; - end = ttUSHORT(data + search + searchRange*2); - if (unicode_codepoint > end) - search += searchRange*2; - --entrySelector; - } - search += 2; - - { - stbtt_uint16 offset, start; - stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); - start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) - return 0; - - offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); - if (offset == 0) - return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); - - return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); - } - } else if (format == 12 || format == 13) { - stbtt_uint32 ngroups = ttULONG(data+index_map+12); - stbtt_int32 low,high; - low = 0; high = (stbtt_int32)ngroups; - // Binary search the right group. - while (low < high) { - stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high - stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); - stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); - if ((stbtt_uint32) unicode_codepoint < start_char) - high = mid; - else if ((stbtt_uint32) unicode_codepoint > end_char) - low = mid+1; - else { - stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); - if (format == 12) - return start_glyph + unicode_codepoint-start_char; - else // format == 13 - return start_glyph; - } - } - return 0; // not found - } - // @TODO - STBTT_assert(0); - return 0; + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) + { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes - 6) return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } + else if (format == 6) + { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32)unicode_codepoint >= first && (stbtt_uint32)unicode_codepoint < first + count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first) * 2); + return 0; + } + else if (format == 2) + { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } + else if (format == 4) + { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data + index_map + 6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data + index_map + 8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data + index_map + 10); + stbtt_uint16 rangeShift = ttUSHORT(data + index_map + 12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift * 2)) search += rangeShift * 2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) + { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange * 2); + if (unicode_codepoint > end) search += searchRange * 2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start; + stbtt_uint16 item = (stbtt_uint16)((search - endCount) >> 1); + + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2 * item)); + start = ttUSHORT(data + index_map + 14 + segcount * 2 + 2 + 2 * item); + if (unicode_codepoint < start) return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount * 6 + 2 + 2 * item); + if (offset == 0) + return (stbtt_uint16)(unicode_codepoint + ttSHORT(data + index_map + 14 + segcount * 4 + 2 + 2 * item)); + + return ttUSHORT(data + offset + (unicode_codepoint - start) * 2 + index_map + 14 + segcount * 6 + 2 + 2 * item); + } + } + else if (format == 12 || format == 13) + { + stbtt_uint32 ngroups = ttULONG(data + index_map + 12); + stbtt_int32 low, high; + low = 0; + high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) + { + stbtt_int32 mid = low + ((high - low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data + index_map + 16 + mid * 12); + stbtt_uint32 end_char = ttULONG(data + index_map + 16 + mid * 12 + 4); + if ((stbtt_uint32)unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32)unicode_codepoint > end_char) + low = mid + 1; + else + { + stbtt_uint32 start_glyph = ttULONG(data + index_map + 16 + mid * 12 + 8); + if (format == 12) + return start_glyph + unicode_codepoint - start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; } STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) { - return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); } static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) { - v->type = type; - v->x = (stbtt_int16) x; - v->y = (stbtt_int16) y; - v->cx = (stbtt_int16) cx; - v->cy = (stbtt_int16) cy; + v->type = type; + v->x = (stbtt_int16)x; + v->y = (stbtt_int16)y; + v->cx = (stbtt_int16)cx; + v->cy = (stbtt_int16)cy; } static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) { - int g1,g2; + int g1, g2; - STBTT_assert(!info->cff.size); + STBTT_assert(!info->cff.size); - if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range - if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format - if (info->indexToLocFormat == 0) { - g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; - g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; - } else { - g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); - g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); - } + if (info->indexToLocFormat == 0) + { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } + else + { + g1 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4 + 4); + } - return g1==g2 ? -1 : g1; // if length is 0, return -1 + return g1 == g2 ? -1 : g1; // if length is 0, return -1 } static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { - if (info->cff.size) { - stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); - } else { - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; - - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); - } - return 1; + if (info->cff.size) { stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); } + else + { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; } STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) { - return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info, codepoint), x0, y0, x1, y1); } STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) { - stbtt_int16 numberOfContours; - int g; - if (info->cff.size) - return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; - g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 1; - numberOfContours = ttSHORT(info->data + g); - return numberOfContours == 0; -} - -static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, - stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) -{ - if (start_off) { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); - } - return num_vertices; + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, stbtt_int32 sx, + stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) + { + if (was_off) stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + scx) >> 1, (cy + scy) >> 1, cx, cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, scx, scy); + } + else + { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, sx, sy, 0, 0); + } + return num_vertices; } static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { - stbtt_int16 numberOfContours; - stbtt_uint8 *endPtsOfContours; - stbtt_uint8 *data = info->data; - stbtt_vertex *vertices=0; - int num_vertices=0; - int g = stbtt__GetGlyfOffset(info, glyph_index); - - *pvertices = NULL; + stbtt_int16 numberOfContours; + stbtt_uint8 * endPtsOfContours; + stbtt_uint8 * data = info->data; + stbtt_vertex *vertices = 0; + int num_vertices = 0; + int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; + *pvertices = NULL; - numberOfContours = ttSHORT(data + g); + if (g < 0) return 0; - if (numberOfContours > 0) { - stbtt_uint8 flags=0,flagcount; - stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; - stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; - stbtt_uint8 *points; - endPtsOfContours = (data + g + 10); - ins = ttUSHORT(data + g + 10 + numberOfContours * 2); - points = data + g + 10 + numberOfContours * 2 + 2 + ins; + numberOfContours = ttSHORT(data + g); - n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + if (numberOfContours > 0) + { + stbtt_uint8 flags = 0, flagcount; + stbtt_int32 ins, i, j = 0, m, n, next_move, was_off = 0, off, start_off = 0; + stbtt_int32 x, y, cx, cy, sx, sy, scx, scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; - m = n + 2*numberOfContours; // a loose bound on how many vertices we might need - vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); - if (vertices == 0) - return 0; + n = 1 + ttUSHORT(endPtsOfContours + numberOfContours * 2 - 2); - next_move = 0; - flagcount=0; + m = n + 2 * numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *)STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) return 0; - // in first pass, we load uninterpreted data into the allocated array - // above, shifted to the end of the array so we won't overwrite it when - // we create our final data starting from the front + next_move = 0; + flagcount = 0; - off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front - // first load flags + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated - for (i=0; i < n; ++i) { - if (flagcount == 0) { - flags = *points++; - if (flags & 8) - flagcount = *points++; - } else - --flagcount; - vertices[off+i].type = flags; - } + // first load flags - // now load x coordinates - x=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 2) { - stbtt_int16 dx = *points++; - x += (flags & 16) ? dx : -dx; // ??? - } else { - if (!(flags & 16)) { - x = x + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; + for (i = 0; i < n; ++i) + { + if (flagcount == 0) + { + flags = *points++; + if (flags & 8) flagcount = *points++; } - } - vertices[off+i].x = (stbtt_int16) x; - } - - // now load y coordinates - y=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 4) { - stbtt_int16 dy = *points++; - y += (flags & 32) ? dy : -dy; // ??? - } else { - if (!(flags & 32)) { - y = y + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; + else + --flagcount; + vertices[off + i].type = flags; + } + + // now load x coordinates + x = 0; + for (i = 0; i < n; ++i) + { + flags = vertices[off + i].type; + if (flags & 2) + { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? } - } - vertices[off+i].y = (stbtt_int16) y; - } - - // now convert them to our format - num_vertices=0; - sx = sy = cx = cy = scx = scy = 0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - x = (stbtt_int16) vertices[off+i].x; - y = (stbtt_int16) vertices[off+i].y; - - if (next_move == i) { - if (i != 0) - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - - // now start the new one - start_off = !(flags & 1); - if (start_off) { - // if we start off with an off-curve point, then when we need to find a point on the curve - // where we can start, and we need to save some state for when we wraparound. - scx = x; - scy = y; - if (!(vertices[off+i+1].type & 1)) { - // next point is also a curve point, so interpolate an on-point curve - sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; - sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; - } else { - // otherwise just use the next point as our start point - sx = (stbtt_int32) vertices[off+i+1].x; - sy = (stbtt_int32) vertices[off+i+1].y; - ++i; // we're using point i+1 as the starting point, so skip it - } - } else { - sx = x; - sy = y; + else + { + if (!(flags & 16)) + { + x = x + (stbtt_int16)(points[0] * 256 + points[1]); + points += 2; + } } - stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); - was_off = 0; - next_move = 1 + ttUSHORT(endPtsOfContours+j*2); - ++j; - } else { - if (!(flags & 1)) { // if it's a curve - if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); - cx = x; - cy = y; - was_off = 1; - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); - was_off = 0; + vertices[off + i].x = (stbtt_int16)x; + } + + // now load y coordinates + y = 0; + for (i = 0; i < n; ++i) + { + flags = vertices[off + i].type; + if (flags & 4) + { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? } - } - } - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { - // Compound shapes. - int more = 1; - stbtt_uint8 *comp = data + g + 10; - num_vertices = 0; - vertices = 0; - while (more) { - stbtt_uint16 flags, gidx; - int comp_num_verts = 0, i; - stbtt_vertex *comp_verts = 0, *tmp = 0; - float mtx[6] = {1,0,0,1,0,0}, m, n; - - flags = ttSHORT(comp); comp+=2; - gidx = ttSHORT(comp); comp+=2; - - if (flags & 2) { // XY values - if (flags & 1) { // shorts - mtx[4] = ttSHORT(comp); comp+=2; - mtx[5] = ttSHORT(comp); comp+=2; - } else { - mtx[4] = ttCHAR(comp); comp+=1; - mtx[5] = ttCHAR(comp); comp+=1; + else + { + if (!(flags & 32)) + { + y = y + (stbtt_int16)(points[0] * 256 + points[1]); + points += 2; + } + } + vertices[off + i].y = (stbtt_int16)y; + } + + // now convert them to our format + num_vertices = 0; + sx = sy = cx = cy = scx = scy = 0; + for (i = 0; i < n; ++i) + { + flags = vertices[off + i].type; + x = (stbtt_int16)vertices[off + i].x; + y = (stbtt_int16)vertices[off + i].y; + + if (next_move == i) + { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx, cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) + { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off + i + 1].type & 1)) + { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32)vertices[off + i + 1].x) >> 1; + sy = (y + (stbtt_int32)vertices[off + i + 1].y) >> 1; + } + else + { + // otherwise just use the next point as our start point + sx = (stbtt_int32)vertices[off + i + 1].x; + sy = (stbtt_int32)vertices[off + i + 1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } + else + { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove, sx, sy, 0, 0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours + j * 2); + ++j; } - } - else { - // @TODO handle matching point - STBTT_assert(0); - } - if (flags & (1<<3)) { // WE_HAVE_A_SCALE - mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } - - // Find transformation scales. - m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); - n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); - - // Get indexed glyph. - comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); - if (comp_num_verts > 0) { - // Transform vertices. - for (i = 0; i < comp_num_verts; ++i) { - stbtt_vertex* v = &comp_verts[i]; - stbtt_vertex_type x,y; - x=v->x; y=v->y; - v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - x=v->cx; y=v->cy; - v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + else + { + if (!(flags & 1)) + { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + x) >> 1, (cy + y) >> 1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } + else + { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x, y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x, y, 0, 0); + was_off = 0; + } } - // Append vertices. - tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); - if (!tmp) { - if (vertices) STBTT_free(vertices, info->userdata); - if (comp_verts) STBTT_free(comp_verts, info->userdata); - return 0; + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx, cy); + } + else if (numberOfContours == -1) + { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) + { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1, 0, 0, 1, 0, 0}, m, n; + + flags = ttSHORT(comp); + comp += 2; + gidx = ttSHORT(comp); + comp += 2; + + if (flags & 2) + { // XY values + if (flags & 1) + { // shorts + mtx[4] = ttSHORT(comp); + comp += 2; + mtx[5] = ttSHORT(comp); + comp += 2; + } + else + { + mtx[4] = ttCHAR(comp); + comp += 1; + mtx[5] = ttCHAR(comp); + comp += 1; + } + } + else + { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1 << 3)) + { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp) / 16384.0f; + comp += 2; + mtx[1] = mtx[2] = 0; + } + else if (flags & (1 << 6)) + { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp) / 16384.0f; + comp += 2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp) / 16384.0f; + comp += 2; + } + else if (flags & (1 << 7)) + { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp) / 16384.0f; + comp += 2; + mtx[1] = ttSHORT(comp) / 16384.0f; + comp += 2; + mtx[2] = ttSHORT(comp) / 16384.0f; + comp += 2; + mtx[3] = ttSHORT(comp) / 16384.0f; + comp += 2; } - if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); - STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); - if (vertices) STBTT_free(vertices, info->userdata); - vertices = tmp; - STBTT_free(comp_verts, info->userdata); - num_vertices += comp_num_verts; - } - // More components ? - more = flags & (1<<5); - } - } else if (numberOfContours < 0) { - // @TODO other compound variations? - STBTT_assert(0); - } else { - // numberOfCounters == 0, do nothing - } - *pvertices = vertices; - return num_vertices; + // Find transformation scales. + m = (float)STBTT_sqrt(mtx[0] * mtx[0] + mtx[1] * mtx[1]); + n = (float)STBTT_sqrt(mtx[2] * mtx[2] + mtx[3] * mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) + { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) + { + stbtt_vertex * v = &comp_verts[i]; + stbtt_vertex_type x, y; + x = v->x; + y = v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5])); + x = v->cx; + y = v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex *)STBTT_malloc((num_vertices + comp_num_verts) * sizeof(stbtt_vertex), info->userdata); + if (!tmp) + { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices * sizeof(stbtt_vertex)); + STBTT_memcpy(tmp + num_vertices, comp_verts, comp_num_verts * sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1 << 5); + } + } + else if (numberOfContours < 0) + { + // @TODO other compound variations? + STBTT_assert(0); + } + else + { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; } typedef struct { - int bounds; - int started; - float first_x, first_y; - float x, y; - stbtt_int32 min_x, max_x, min_y, max_y; + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; - stbtt_vertex *pvertices; - int num_vertices; + stbtt_vertex *pvertices; + int num_vertices; } stbtt__csctx; -#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + #define STBTT__CSCTX_INIT(bounds) \ + { \ + bounds, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0 \ + } static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) { - if (x > c->max_x || !c->started) c->max_x = x; - if (y > c->max_y || !c->started) c->max_y = y; - if (x < c->min_x || !c->started) c->min_x = x; - if (y < c->min_y || !c->started) c->min_y = y; - c->started = 1; + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; } -static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) -{ - if (c->bounds) { - stbtt__track_vertex(c, x, y); - if (type == STBTT_vcubic) { - stbtt__track_vertex(c, cx, cy); - stbtt__track_vertex(c, cx1, cy1); - } - } else { - stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); - c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; - c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; - } - c->num_vertices++; +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, + stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) + { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) + { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } + else + { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16)cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16)cy1; + } + c->num_vertices++; } static void stbtt__csctx_close_shape(stbtt__csctx *ctx) { - if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) - stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); } static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) { - stbtt__csctx_close_shape(ctx); - ctx->first_x = ctx->x = ctx->x + dx; - ctx->first_y = ctx->y = ctx->y + dy; - stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); } static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) { - ctx->x += dx; - ctx->y += dy; - stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); } static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) { - float cx1 = ctx->x + dx1; - float cy1 = ctx->y + dy1; - float cx2 = cx1 + dx2; - float cy2 = cy1 + dy2; - ctx->x = cx2 + dx3; - ctx->y = cy2 + dy3; - stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); } static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) { - int count = stbtt__cff_index_count(&idx); - int bias = 107; - if (count >= 33900) - bias = 32768; - else if (count >= 1240) - bias = 1131; - n += bias; - if (n < 0 || n >= count) - return stbtt__new_buf(NULL, 0); - return stbtt__cff_index_get(idx, n); + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); } static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) { - stbtt__buf fdselect = info->fdselect; - int nranges, start, end, v, fmt, fdselector = -1, i; - - stbtt__buf_seek(&fdselect, 0); - fmt = stbtt__buf_get8(&fdselect); - if (fmt == 0) { - // untested - stbtt__buf_skip(&fdselect, glyph_index); - fdselector = stbtt__buf_get8(&fdselect); - } else if (fmt == 3) { - nranges = stbtt__buf_get16(&fdselect); - start = stbtt__buf_get16(&fdselect); - for (i = 0; i < nranges; i++) { - v = stbtt__buf_get8(&fdselect); - end = stbtt__buf_get16(&fdselect); - if (glyph_index >= start && glyph_index < end) { - fdselector = v; - break; - } - start = end; - } - } - if (fdselector == -1) stbtt__new_buf(NULL, 0); - return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) + { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } + else if (fmt == 3) + { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) + { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) + { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); } static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) { - int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; - int has_subrs = 0, clear_stack; - float s[48]; - stbtt__buf subr_stack[10], subrs = info->subrs, b; - float f; - -#define STBTT__CSERR(s) (0) - - // this currently ignores the initial width value, which isn't needed if we have hmtx - b = stbtt__cff_index_get(info->charstrings, glyph_index); - while (b.cursor < b.size) { - i = 0; - clear_stack = 1; - b0 = stbtt__buf_get8(&b); - switch (b0) { - // @TODO implement hinting - case 0x13: // hintmask - case 0x14: // cntrmask - if (in_header) - maskbits += (sp / 2); // implicit "vstem" - in_header = 0; - stbtt__buf_skip(&b, (maskbits + 7) / 8); - break; - - case 0x01: // hstem - case 0x03: // vstem - case 0x12: // hstemhm - case 0x17: // vstemhm - maskbits += (sp / 2); - break; - - case 0x15: // rmoveto - in_header = 0; - if (sp < 2) return STBTT__CSERR("rmoveto stack"); - stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); - break; - case 0x04: // vmoveto - in_header = 0; - if (sp < 1) return STBTT__CSERR("vmoveto stack"); - stbtt__csctx_rmove_to(c, 0, s[sp-1]); - break; - case 0x16: // hmoveto - in_header = 0; - if (sp < 1) return STBTT__CSERR("hmoveto stack"); - stbtt__csctx_rmove_to(c, s[sp-1], 0); - break; - - case 0x05: // rlineto - if (sp < 2) return STBTT__CSERR("rlineto stack"); - for (; i + 1 < sp; i += 2) - stbtt__csctx_rline_to(c, s[i], s[i+1]); - break; - - // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical - // starting from a different place. - - case 0x07: // vlineto - if (sp < 1) return STBTT__CSERR("vlineto stack"); - goto vlineto; - case 0x06: // hlineto - if (sp < 1) return STBTT__CSERR("hlineto stack"); - for (;;) { - if (i >= sp) break; - stbtt__csctx_rline_to(c, s[i], 0); - i++; - vlineto: - if (i >= sp) break; - stbtt__csctx_rline_to(c, 0, s[i]); - i++; - } - break; - - case 0x1F: // hvcurveto - if (sp < 4) return STBTT__CSERR("hvcurveto stack"); - goto hvcurveto; - case 0x1E: // vhcurveto - if (sp < 4) return STBTT__CSERR("vhcurveto stack"); - for (;;) { - if (i + 3 >= sp) break; - stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); - i += 4; - hvcurveto: - if (i + 3 >= sp) break; - stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); - i += 4; - } - break; - - case 0x08: // rrcurveto - if (sp < 6) return STBTT__CSERR("rcurveline stack"); - for (; i + 5 < sp; i += 6) - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - break; - - case 0x18: // rcurveline - if (sp < 8) return STBTT__CSERR("rcurveline stack"); - for (; i + 5 < sp - 2; i += 6) - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); - stbtt__csctx_rline_to(c, s[i], s[i+1]); - break; - - case 0x19: // rlinecurve - if (sp < 8) return STBTT__CSERR("rlinecurve stack"); - for (; i + 1 < sp - 6; i += 2) - stbtt__csctx_rline_to(c, s[i], s[i+1]); - if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - break; - - case 0x1A: // vvcurveto - case 0x1B: // hhcurveto - if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); - f = 0.0; - if (sp & 1) { f = s[i]; i++; } - for (; i + 3 < sp; i += 4) { - if (b0 == 0x1B) - stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); - else - stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + + #define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) + { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) + { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp - 2], s[sp - 1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp - 1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp - 1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i + 1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) + { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) + { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i + 1], s[i + 2], s[i + 3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i + 1], s[i + 2], (sp - i == 5) ? s[i + 4] : 0.0f, s[i + 3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i + 5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i + 5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i + 1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i + 1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i + 5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); f = 0.0; - } - break; - - case 0x0A: // callsubr - if (!has_subrs) { - if (info->fdselect.size) - subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); - has_subrs = 1; - } - // fallthrough - case 0x1D: // callgsubr - if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); - v = (int) s[--sp]; - if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); - subr_stack[subr_stack_height++] = b; - b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); - if (b.size == 0) return STBTT__CSERR("subr not found"); - b.cursor = 0; - clear_stack = 0; - break; - - case 0x0B: // return - if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); - b = subr_stack[--subr_stack_height]; - clear_stack = 0; - break; - - case 0x0E: // endchar - stbtt__csctx_close_shape(c); - return 1; - - case 0x0C: { // two-byte escape - float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; - float dx, dy; - int b1 = stbtt__buf_get8(&b); - switch (b1) { - // @TODO These "flex" implementations ignore the flex-depth and resolution, - // and always draw beziers. - case 0x22: // hflex - if (sp < 7) return STBTT__CSERR("hflex stack"); - dx1 = s[0]; - dx2 = s[1]; - dy2 = s[2]; - dx3 = s[3]; - dx4 = s[4]; - dx5 = s[5]; - dx6 = s[6]; - stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); - stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + if (sp & 1) + { + f = s[i]; + i++; + } + for (; i + 3 < sp; i += 4) + { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i + 1], s[i + 2], s[i + 3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i + 1], s[i + 2], 0.0, s[i + 3]); + f = 0.0; + } break; - case 0x23: // flex - if (sp < 13) return STBTT__CSERR("flex stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dy3 = s[5]; - dx4 = s[6]; - dy4 = s[7]; - dx5 = s[8]; - dy5 = s[9]; - dx6 = s[10]; - dy6 = s[11]; - //fd is s[12] - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); - stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + case 0x0A: // callsubr + if (!has_subrs) + { + if (info->fdselect.size) subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // fallthrough + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int)s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; break; - case 0x24: // hflex1 - if (sp < 9) return STBTT__CSERR("hflex1 stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dx4 = s[5]; - dx5 = s[6]; - dy5 = s[7]; - dx6 = s[8]; - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); - stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; break; - case 0x25: // flex1 - if (sp < 11) return STBTT__CSERR("flex1 stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dy3 = s[5]; - dx4 = s[6]; - dy4 = s[7]; - dx5 = s[8]; - dy5 = s[9]; - dx6 = dy6 = s[10]; - dx = dx1+dx2+dx3+dx4+dx5; - dy = dy1+dy2+dy3+dy4+dy5; - if (STBTT_fabs(dx) > STBTT_fabs(dy)) - dy6 = -dy; + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: + { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) + { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + // fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1 + dy2 + dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1 + dx2 + dx3 + dx4 + dx5; + dy = dy1 + dy2 + dy3 + dy4 + dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: return STBTT__CSERR("unimplemented"); + } + } + break; + + default: + if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { f = (float)stbtt__buf_get32(&b) / 0x10000; } else - dx6 = -dx; - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); - stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); - default: - return STBTT__CSERR("unimplemented"); - } - } break; - - default: - if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) - return STBTT__CSERR("reserved operator"); - - // push immediate - if (b0 == 255) { - f = (float)stbtt__buf_get32(&b) / 0x10000; - } else { - stbtt__buf_skip(&b, -1); - f = (float)(stbtt_int16)stbtt__cff_int(&b); - } - if (sp >= 48) return STBTT__CSERR("push stack overflow"); - s[sp++] = f; - clear_stack = 0; - break; - } - if (clear_stack) sp = 0; - } - return STBTT__CSERR("no endchar"); - -#undef STBTT__CSERR + #undef STBTT__CSERR } static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { - // runs the charstring twice, once to count and once to output (to avoid realloc) - stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); - stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); - if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { - *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); - output_ctx.pvertices = *pvertices; - if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { - STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); - return output_ctx.num_vertices; - } - } - *pvertices = NULL; - return 0; + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) + { + *pvertices = (stbtt_vertex *)STBTT_malloc(count_ctx.num_vertices * sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) + { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; } static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { - stbtt__csctx c = STBTT__CSCTX_INIT(1); - int r = stbtt__run_charstring(info, glyph_index, &c); - if (x0) { - *x0 = r ? c.min_x : 0; - *y0 = r ? c.min_y : 0; - *x1 = r ? c.max_x : 0; - *y1 = r ? c.max_y : 0; - } - return r ? c.num_vertices : 0; + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) + { + *x0 = r ? c.min_x : 0; + *y0 = r ? c.min_y : 0; + *x1 = r ? c.max_x : 0; + *y1 = r ? c.max_y : 0; + } + return r ? c.num_vertices : 0; } STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { - if (!info->cff.size) - return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); - else - return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); } STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) { - stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); - if (glyph_index < numOfLongHorMetrics) { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); - } else { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); - } + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data + info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) + { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * glyph_index + 2); + } + else + { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * (numOfLongHorMetrics - 1)); + if (leftSideBearing) + *leftSideBearing = + ttSHORT(info->data + info->hmtx + 4 * numOfLongHorMetrics + 2 * (glyph_index - numOfLongHorMetrics)); + } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint8 *data = info->data + info->kern; - stbtt_uint32 needle, straw; - int l, r, m; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - l = 0; - r = ttUSHORT(data+10) - 1; - needle = glyph1 << 16 | glyph2; - while (l <= r) { - m = (l + r) >> 1; - straw = ttULONG(data+18+(m*6)); // note: unaligned read - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else - return ttSHORT(data+22+(m*6)); - } - return 0; +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) return 0; + if (ttUSHORT(data + 2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data + 8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data + 10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) + { + m = (l + r) >> 1; + straw = ttULONG(data + 18 + (m * 6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data + 22 + (m * 6)); + } + return 0; } -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs - return 0; - return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); + if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info, ch1), stbtt_FindGlyphIndex(info, ch2)); } STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) { - stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info, codepoint), advanceWidth, leftSideBearing); } STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) { - if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); - if (descent) *descent = ttSHORT(info->data+info->hhea + 6); - if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); + if (ascent) *ascent = ttSHORT(info->data + info->hhea + 4); + if (descent) *descent = ttSHORT(info->data + info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data + info->hhea + 8); } STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { - *x0 = ttSHORT(info->data + info->head + 36); - *y0 = ttSHORT(info->data + info->head + 38); - *x1 = ttSHORT(info->data + info->head + 40); - *y1 = ttSHORT(info->data + info->head + 42); + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); } STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) { - int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); - return (float) height / fheight; + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float)height / fheight; } STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) { - int unitsPerEm = ttUSHORT(info->data + info->head + 18); - return pixels / unitsPerEm; + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; } STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) { - STBTT_free(v, info->userdata); + STBTT_free(v, info->userdata); } ////////////////////////////////////////////////////////////////////////////// @@ -2230,37 +2396,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) // antialiasing software rasterizer // -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning - if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { - // e.g. space character - if (ix0) *ix0 = 0; - if (iy0) *iy0 = 0; - if (ix1) *ix1 = 0; - if (iy1) *iy1 = 0; - } else { - // move to integral bboxes (treating pixels as little squares, what pixels get touched)? - if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); - if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); - if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); - if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); - } +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, float shift_x, + float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0 = 0, y0 = 0, x1, y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0, &y0, &x1, &y1)) + { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } + else + { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil(x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil(-y0 * scale_y + shift_y); + } } -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, + int *ix1, int *iy1) { - stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y, 0.0f, 0.0f, ix0, iy0, ix1, iy1); } -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, + float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { - stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font, codepoint), scale_x, scale_y, shift_x, shift_y, ix0, iy0, + ix1, iy1); } -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, + int *iy0, int *ix1, int *iy1) { - stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y, 0.0f, 0.0f, ix0, iy0, ix1, iy1); } ////////////////////////////////////////////////////////////////////////////// @@ -2269,970 +2443,1093 @@ STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codep typedef struct stbtt__hheap_chunk { - struct stbtt__hheap_chunk *next; + struct stbtt__hheap_chunk *next; } stbtt__hheap_chunk; typedef struct stbtt__hheap { - struct stbtt__hheap_chunk *head; - void *first_free; - int num_remaining_in_head_chunk; + struct stbtt__hheap_chunk *head; + void * first_free; + int num_remaining_in_head_chunk; } stbtt__hheap; static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) { - if (hh->first_free) { - void *p = hh->first_free; - hh->first_free = * (void **) p; - return p; - } else { - if (hh->num_remaining_in_head_chunk == 0) { - int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); - stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); - if (c == NULL) - return NULL; - c->next = hh->head; - hh->head = c; - hh->num_remaining_in_head_chunk = count; - } - --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; - } + if (hh->first_free) + { + void *p = hh->first_free; + hh->first_free = *(void **)p; + return p; + } + else + { + if (hh->num_remaining_in_head_chunk == 0) + { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *)STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *)(hh->head) + size * hh->num_remaining_in_head_chunk; + } } static void stbtt__hheap_free(stbtt__hheap *hh, void *p) { - *(void **) p = hh->first_free; - hh->first_free = p; + *(void **)p = hh->first_free; + hh->first_free = p; } static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) { - stbtt__hheap_chunk *c = hh->head; - while (c) { - stbtt__hheap_chunk *n = c->next; - STBTT_free(c, userdata); - c = n; - } + stbtt__hheap_chunk *c = hh->head; + while (c) + { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } } -typedef struct stbtt__edge { - float x0,y0, x1,y1; - int invert; +typedef struct stbtt__edge +{ + float x0, y0, x1, y1; + int invert; } stbtt__edge; - typedef struct stbtt__active_edge { - struct stbtt__active_edge *next; - #if STBTT_RASTERIZER_VERSION==1 - int x,dx; - float ey; - int direction; - #elif STBTT_RASTERIZER_VERSION==2 - float fx,fdx,fdy; - float direction; - float sy; - float ey; - #else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" - #endif + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION == 1 + int x, dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION == 2 + float fx, fdx, fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif } stbtt__active_edge; -#if STBTT_RASTERIZER_VERSION == 1 -#define STBTT_FIXSHIFT 10 -#define STBTT_FIX (1 << STBTT_FIXSHIFT) -#define STBTT_FIXMASK (STBTT_FIX-1) + #if STBTT_RASTERIZER_VERSION == 1 + #define STBTT_FIXSHIFT 10 + #define STBTT_FIX (1 << STBTT_FIXSHIFT) + #define STBTT_FIXMASK (STBTT_FIX - 1) static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) { - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - if (!z) return z; - - // round dx down to avoid overshooting - if (dxdy < 0) - z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); - else - z->dx = STBTT_ifloor(STBTT_FIX * dxdy); - - z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount - z->x -= off_x * STBTT_FIX; - - z->ey = e->y1; - z->next = 0; - z->direction = e->invert ? 1 : -1; - return z; -} -#elif STBTT_RASTERIZER_VERSION == 2 + stbtt__active_edge *z = (stbtt__active_edge *)stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} + #elif STBTT_RASTERIZER_VERSION == 2 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) { - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - //STBTT_assert(e->y0 <= start_point); - if (!z) return z; - z->fdx = dxdy; - z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; - z->fx = e->x0 + dxdy * (start_point - e->y0); - z->fx -= off_x; - z->direction = e->invert ? 1.0f : -1.0f; - z->sy = e->y0; - z->ey = e->y1; - z->next = 0; - return z; -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif + stbtt__active_edge *z = (stbtt__active_edge *)stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + // STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f / dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif -#if STBTT_RASTERIZER_VERSION == 1 + #if STBTT_RASTERIZER_VERSION == 1 // note: this routine clips fills that extend off the edges... ideally this // wouldn't happen, but it could happen if the truetype glyph bounding boxes // are wrong, or if the user supplies a too-small bitmap static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) { - // non-zero winding fill - int x0=0, w=0; - - while (e) { - if (w == 0) { - // if we're currently at zero, we need to record the edge start point - x0 = e->x; w += e->direction; - } else { - int x1 = e->x; w += e->direction; - // if we went to zero, we need to draw - if (w == 0) { - int i = x0 >> STBTT_FIXSHIFT; - int j = x1 >> STBTT_FIXSHIFT; - - if (i < len && j >= 0) { - if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage - scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); - } else { - if (i >= 0) // add antialiasing for x0 - scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); - else - i = -1; // clip - - if (j < len) // add antialiasing for x1 - scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); - else - j = len; // clip - - for (++i; i < j; ++i) // fill pixels between x0 and x1 - scanline[i] = scanline[i] + (stbtt_uint8) max_weight; - } + // non-zero winding fill + int x0 = 0, w = 0; + + while (e) + { + if (w == 0) + { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; + w += e->direction; + } + else + { + int x1 = e->x; + w += e->direction; + // if we went to zero, we need to draw + if (w == 0) + { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) + { + if (i == j) + { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8)((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } + else + { + if (i >= 0) // add antialiasing for x0 + scanline[i] = + scanline[i] + (stbtt_uint8)(((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8)(((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8)max_weight; + } + } } - } - } - - e = e->next; - } + } + + e = e->next; + } } -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0; - int max_weight = (255 / vsubsample); // weight per vertical scanline - int s; // vertical subsample index - unsigned char scanline_data[512], *scanline; - - if (result->w > 512) - scanline = (unsigned char *) STBTT_malloc(result->w, userdata); - else - scanline = scanline_data; - - y = off_y * vsubsample; - e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; - - while (j < result->h) { - STBTT_memset(scanline, 0, result->w); - for (s=0; s < vsubsample; ++s) { - // find center of pixel for this scanline - float scan_y = y + 0.5f; - stbtt__active_edge **step = &active; - - // update all active edges; - // remove all active edges that terminate before the center of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, + void *userdata) +{ + stbtt__hheap hh = {0, 0, 0}; + stbtt__active_edge *active = NULL; + int y, j = 0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *)STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float)vsubsample + 1; + + while (j < result->h) + { + STBTT_memset(scanline, 0, result->w); + for (s = 0; s < vsubsample; ++s) + { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) + { + stbtt__active_edge *z = *step; + if (z->ey <= scan_y) + { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } + else + { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } } - } - - // resort the list if needed - for(;;) { - int changed=0; - step = &active; - while (*step && (*step)->next) { - if ((*step)->x > (*step)->next->x) { - stbtt__active_edge *t = *step; - stbtt__active_edge *q = t->next; - - t->next = q->next; - q->next = t; - *step = q; - changed = 1; - } - step = &(*step)->next; + + // resort the list if needed + for (;;) + { + int changed = 0; + step = &active; + while (*step && (*step)->next) + { + if ((*step)->x > (*step)->next->x) + { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; } - if (!changed) break; - } - - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline - while (e->y0 <= scan_y) { - if (e->y1 > scan_y) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - if (z != NULL) { - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; - } - } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) + { + if (e->y1 > scan_y) + { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) + { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) + { + // insert at front + z->next = active; + active = z; + } + else + { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; } - ++e; - } - // now process all active edges in XOR fashion - if (active) - stbtt__fill_active_edges(scanline, result->w, active, max_weight); + // now process all active edges in XOR fashion + if (active) stbtt__fill_active_edges(scanline, result->w, active, max_weight); - ++y; - } - STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); - ++j; - } + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } - stbtt__hheap_cleanup(&hh, userdata); + stbtt__hheap_cleanup(&hh, userdata); - if (scanline != scanline_data) - STBTT_free(scanline, userdata); + if (scanline != scanline_data) STBTT_free(scanline, userdata); } -#elif STBTT_RASTERIZER_VERSION == 2 + #elif STBTT_RASTERIZER_VERSION == 2 // the edge passed in here does not cross the vertical line at x or the vertical line at x+1 // (i.e. it has already been clipped to those) static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) { - if (y0 == y1) return; - STBTT_assert(y0 < y1); - STBTT_assert(e->sy <= e->ey); - if (y0 > e->ey) return; - if (y1 < e->sy) return; - if (y0 < e->sy) { - x0 += (x1-x0) * (e->sy - y0) / (y1-y0); - y0 = e->sy; - } - if (y1 > e->ey) { - x1 += (x1-x0) * (e->ey - y1) / (y1-y0); - y1 = e->ey; - } - - if (x0 == x) - STBTT_assert(x1 <= x+1); - else if (x0 == x+1) - STBTT_assert(x1 >= x); - else if (x0 <= x) - STBTT_assert(x1 <= x); - else if (x0 >= x+1) - STBTT_assert(x1 >= x+1); - else - STBTT_assert(x1 >= x && x1 <= x+1); - - if (x0 <= x && x1 <= x) - scanline[x] += e->direction * (y1-y0); - else if (x0 >= x+1 && x1 >= x+1) - ; - else { - STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); - scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position - } + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) + { + x0 += (x1 - x0) * (e->sy - y0) / (y1 - y0); + y0 = e->sy; + } + if (y1 > e->ey) + { + x1 += (x1 - x0) * (e->ey - y1) / (y1 - y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x + 1); + else if (x0 == x + 1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x + 1) + STBTT_assert(x1 >= x + 1); + else + STBTT_assert(x1 >= x && x1 <= x + 1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1 - y0); + else if (x0 >= x + 1 && x1 >= x + 1) + ; + else + { + STBTT_assert(x0 >= x && x0 <= x + 1 && x1 >= x && x1 <= x + 1); + scanline[x] += e->direction * (y1 - y0) * (1 - ((x0 - x) + (x1 - x)) / 2); // coverage = 1 - average x position + } } static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) { - float y_bottom = y_top+1; - - while (e) { - // brute force every pixel - - // compute intersection points with top & bottom - STBTT_assert(e->ey >= y_top); - - if (e->fdx == 0) { - float x0 = e->fx; - if (x0 < len) { - if (x0 >= 0) { - stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); - stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); - } else { - stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + float y_bottom = y_top + 1; + + while (e) + { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) + { + float x0 = e->fx; + if (x0 < len) + { + if (x0 >= 0) + { + stbtt__handle_clipped_edge(scanline, (int)x0, e, x0, y_top, x0, y_bottom); + stbtt__handle_clipped_edge(scanline_fill - 1, (int)x0 + 1, e, x0, y_top, x0, y_bottom); + } + else + { + stbtt__handle_clipped_edge(scanline_fill - 1, 0, e, x0, y_top, x0, y_bottom); + } } - } - } else { - float x0 = e->fx; - float dx = e->fdx; - float xb = x0 + dx; - float x_top, x_bottom; - float sy0,sy1; - float dy = e->fdy; - STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); - - // compute endpoints of line segment clipped to this scanline (if the - // line segment starts on this scanline. x0 is the intersection of the - // line with y_top, but that may be off the line segment. - if (e->sy > y_top) { - x_top = x0 + dx * (e->sy - y_top); - sy0 = e->sy; - } else { - x_top = x0; - sy0 = y_top; - } - if (e->ey < y_bottom) { - x_bottom = x0 + dx * (e->ey - y_top); - sy1 = e->ey; - } else { - x_bottom = xb; - sy1 = y_bottom; - } - - if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { - // from here on, we don't have to range check x values - - if ((int) x_top == (int) x_bottom) { - float height; - // simple case, only spans one pixel - int x = (int) x_top; - height = sy1 - sy0; - STBTT_assert(x >= 0 && x < len); - scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; - scanline_fill[x] += e->direction * height; // everything right of this pixel is filled - } else { - int x,x1,x2; - float y_crossing, step, sign, area; - // covers 2+ pixels - if (x_top > x_bottom) { - // flip scanline vertically; signed area is the same - float t; - sy0 = y_bottom - (sy0 - y_top); - sy1 = y_bottom - (sy1 - y_top); - t = sy0, sy0 = sy1, sy1 = t; - t = x_bottom, x_bottom = x_top, x_top = t; - dx = -dx; - dy = -dy; - t = x0, x0 = xb, xb = t; - } - - x1 = (int) x_top; - x2 = (int) x_bottom; - // compute intersection with y axis at x1+1 - y_crossing = (x1+1 - x0) * dy + y_top; - - sign = e->direction; - // area of the rectangle covered from y0..y_crossing - area = sign * (y_crossing-sy0); - // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) - scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); - - step = sign * dy; - for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; - area += step; - } - y_crossing += dy * (x2 - (x1+1)); - - STBTT_assert(STBTT_fabs(area) <= 1.01f); - - scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); - - scanline_fill[x2] += sign * (sy1-sy0); + } + else + { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0, sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) + { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; } - } else { - // if edge goes outside of box we're drawing, we require - // clipping logic. since this does not match the intended use - // of this library, we use a different, very slow brute - // force implementation - int x; - for (x=0; x < len; ++x) { - // cases: - // - // there can be up to two intersections with the pixel. any intersection - // with left or right edges can be handled by splitting into two (or three) - // regions. intersections with top & bottom do not necessitate case-wise logic. - // - // the old way of doing this found the intersections with the left & right edges, - // then used some simple logic to produce up to three segments in sorted order - // from top-to-bottom. however, this had a problem: if an x edge was epsilon - // across the x border, then the corresponding y position might not be distinct - // from the other y segment, and it might ignored as an empty segment. to avoid - // that, we need to explicitly produce segments based on x positions. - - // rename variables to clear pairs - float y0 = y_top; - float x1 = (float) (x); - float x2 = (float) (x+1); - float x3 = xb; - float y3 = y_bottom; - float y1,y2; - - // x = e->x + e->dx * (y-y_top) - // (y-y_top) = (x - e->x) / e->dx - // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; - - if (x0 < x1 && x3 > x2) { // three segments descending down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x1 && x0 > x2) { // three segments descending down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else { // one segment - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); - } + else + { + x_top = x0; + sy0 = y_top; } - } - } - e = e->next; - } + if (e->ey < y_bottom) + { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } + else + { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) + { + // from here on, we don't have to range check x values + + if ((int)x_top == (int)x_bottom) + { + float height; + // simple case, only spans one pixel + int x = (int)x_top; + height = sy1 - sy0; + STBTT_assert(x >= 0 && x < len); + scanline[x] += e->direction * (1 - ((x_top - x) + (x_bottom - x)) / 2) * height; + scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + } + else + { + int x, x1, x2; + float y_crossing, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) + { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + + x1 = (int)x_top; + x2 = (int)x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = (x1 + 1 - x0) * dy + y_top; + + sign = e->direction; + // area of the rectangle covered from y0..y_crossing + area = sign * (y_crossing - sy0); + // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) + scanline[x1] += area * (1 - ((x_top - x1) + (x1 + 1 - x1)) / 2); + + step = sign * dy; + for (x = x1 + 1; x < x2; ++x) + { + scanline[x] += area + step / 2; + area += step; + } + y_crossing += dy * (x2 - (x1 + 1)); + + STBTT_assert(STBTT_fabs(area) <= 1.01f); + + scanline[x2] += area + sign * (1 - ((x2 - x2) + (x_bottom - x2)) / 2) * (sy1 - y_crossing); + + scanline_fill[x2] += sign * (sy1 - sy0); + } + } + else + { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + int x; + for (x = 0; x < len; ++x) + { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clear pairs + float y0 = y_top; + float x1 = (float)(x); + float x2 = (float)(x + 1); + float x3 = xb; + float y3 = y_bottom; + float y1, y2; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + y1 = (x - x0) / dx + y_top; + y2 = (x + 1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) + { // three segments descending down-right + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1); + stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x2, y2); + stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3); + } + else if (x3 < x1 && x0 > x2) + { // three segments descending down-left + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2); + stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x1, y1); + stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3); + } + else if (x0 < x1 && x3 > x1) + { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1); + stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3); + } + else if (x3 < x1 && x0 > x1) + { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1); + stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3); + } + else if (x0 < x2 && x3 > x2) + { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2); + stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3); + } + else if (x3 < x2 && x0 > x2) + { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2); + stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3); + } + else + { // one segment + stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x3, y3); + } + } + } + } + e = e->next; + } } // directly AA rasterize edges w/o supersampling -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0, i; - float scanline_data[129], *scanline, *scanline2; - - STBTT__NOTUSED(vsubsample); - - if (result->w > 64) - scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); - else - scanline = scanline_data; - - scanline2 = scanline + result->w; - - y = off_y; - e[n].y0 = (float) (off_y + result->h) + 1; - - while (j < result->h) { - // find center of pixel for this scanline - float scan_y_top = y + 0.0f; - float scan_y_bottom = y + 1.0f; - stbtt__active_edge **step = &active; - - STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); - STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); - - // update all active edges; - // remove all active edges that terminate before the top of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y_top) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - step = &((*step)->next); // advance through list - } - } - - // insert all edges that start before the bottom of this scanline - while (e->y0 <= scan_y_bottom) { - if (e->y0 != e->y1) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - if (z != NULL) { - STBTT_assert(z->ey >= scan_y_top); - // insert at front - z->next = active; - active = z; +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, + void *userdata) +{ + stbtt__hheap hh = {0, 0, 0}; + stbtt__active_edge *active = NULL; + int y, j = 0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *)STBTT_malloc((result->w * 2 + 1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float)(off_y + result->h) + 1; + + while (j < result->h) + { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline, 0, result->w * sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w + 1) * sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) + { + stbtt__active_edge *z = *step; + if (z->ey <= scan_y_top) + { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); } - } - ++e; - } - - // now process all active edges - if (active) - stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); - - { - float sum = 0; - for (i=0; i < result->w; ++i) { - float k; - int m; - sum += scanline2[i]; - k = scanline[i] + sum; - k = (float) STBTT_fabs(k)*255 + 0.5f; - m = (int) k; - if (m > 255) m = 255; - result->pixels[j*result->stride + i] = (unsigned char) m; - } - } - // advance all the edges - step = &active; - while (*step) { - stbtt__active_edge *z = *step; - z->fx += z->fdx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } + else + { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) + { + if (e->y0 != e->y1) + { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) + { + STBTT_assert(z->ey >= scan_y_top); + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) stbtt__fill_active_edges_new(scanline, scanline2 + 1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i = 0; i < result->w; ++i) + { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float)STBTT_fabs(k) * 255 + 0.5f; + m = (int)k; + if (m > 255) m = 255; + result->pixels[j * result->stride + i] = (unsigned char)m; + } + } + // advance all the edges + step = &active; + while (*step) + { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } - ++y; - ++j; - } + ++y; + ++j; + } - stbtt__hheap_cleanup(&hh, userdata); + stbtt__hheap_cleanup(&hh, userdata); - if (scanline != scanline_data) - STBTT_free(scanline, userdata); + if (scanline != scanline_data) STBTT_free(scanline, userdata); } -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif -#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + #define STBTT__COMPARE(a, b) ((a)->y0 < (b)->y0) static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) { - int i,j; - for (i=1; i < n; ++i) { - stbtt__edge t = p[i], *a = &t; - j = i; - while (j > 0) { - stbtt__edge *b = &p[j-1]; - int c = STBTT__COMPARE(a,b); - if (!c) break; - p[j] = p[j-1]; - --j; - } - if (i != j) - p[j] = t; - } + int i, j; + for (i = 1; i < n; ++i) + { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) + { + stbtt__edge *b = &p[j - 1]; + int c = STBTT__COMPARE(a, b); + if (!c) break; + p[j] = p[j - 1]; + --j; + } + if (i != j) p[j] = t; + } } static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) { - /* threshhold for transitioning to insertion sort */ - while (n > 12) { - stbtt__edge t; - int c01,c12,c,m,i,j; - - /* compute median of three */ - m = n >> 1; - c01 = STBTT__COMPARE(&p[0],&p[m]); - c12 = STBTT__COMPARE(&p[m],&p[n-1]); - /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ - if (c01 != c12) { - /* otherwise, we'll need to swap something else to middle */ - int z; - c = STBTT__COMPARE(&p[0],&p[n-1]); - /* 0>mid && midn => n; 0 0 */ - /* 0n: 0>n => 0; 0 n */ - z = (c == c12) ? 0 : n-1; - t = p[z]; - p[z] = p[m]; - p[m] = t; - } - /* now p[m] is the median-of-three */ - /* swap it to the beginning so it won't move around */ - t = p[0]; - p[0] = p[m]; - p[m] = t; - - /* partition loop */ - i=1; - j=n-1; - for(;;) { - /* handling of equality is crucial here */ - /* for sentinels & efficiency with duplicates */ - for (;;++i) { - if (!STBTT__COMPARE(&p[i], &p[0])) break; - } - for (;;--j) { - if (!STBTT__COMPARE(&p[0], &p[j])) break; - } - /* make sure we haven't crossed */ - if (i >= j) break; - t = p[i]; - p[i] = p[j]; - p[j] = t; - - ++i; - --j; - } - /* recurse on smaller side, iterate on larger */ - if (j < (n-i)) { - stbtt__sort_edges_quicksort(p,j); - p = p+i; - n = n-i; - } else { - stbtt__sort_edges_quicksort(p+i, n-i); - n = j; - } - } + /* threshhold for transitioning to insertion sort */ + while (n > 12) + { + stbtt__edge t; + int c01, c12, c, m, i, j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0], &p[m]); + c12 = STBTT__COMPARE(&p[m], &p[n - 1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) + { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0], &p[n - 1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n - 1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i = 1; + j = n - 1; + for (;;) + { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;; ++i) + { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;; --j) + { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n - i)) + { + stbtt__sort_edges_quicksort(p, j); + p = p + i; + n = n - i; + } + else + { + stbtt__sort_edges_quicksort(p + i, n - i); + n = j; + } + } } static void stbtt__sort_edges(stbtt__edge *p, int n) { - stbtt__sort_edges_quicksort(p, n); - stbtt__sort_edges_ins_sort(p, n); + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); } typedef struct { - float x,y; + float x, y; } stbtt__point; -static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) -{ - float y_scale_inv = invert ? -scale_y : scale_y; - stbtt__edge *e; - int n,i,j,k,m; -#if STBTT_RASTERIZER_VERSION == 1 - int vsubsample = result->h < 8 ? 15 : 5; -#elif STBTT_RASTERIZER_VERSION == 2 - int vsubsample = 1; -#else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - // vsubsample should divide 255 evenly; otherwise we won't reach full opacity - - // now we have to blow out the windings into explicit edge lists - n = 0; - for (i=0; i < windings; ++i) - n += wcount[i]; - - e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel - if (e == 0) return; - n = 0; - - m=0; - for (i=0; i < windings; ++i) { - stbtt__point *p = pts + m; - m += wcount[i]; - j = wcount[i]-1; - for (k=0; k < wcount[i]; j=k++) { - int a=k,b=j; - // skip the edge if horizontal - if (p[j].y == p[k].y) - continue; - // add edge from j to k to the list - e[n].invert = 0; - if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { - e[n].invert = 1; - a=j,b=k; - } - e[n].x0 = p[a].x * scale_x + shift_x; - e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; - e[n].x1 = p[b].x * scale_x + shift_x; - e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; - ++n; - } - } - - // now sort the edges by their highest point (should snap to integer, and then by x) - //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); - stbtt__sort_edges(e, n); - - // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule - stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); - - STBTT_free(e, userdata); +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, + float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n, i, j, k, m; + #if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; + #elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i = 0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *)STBTT_malloc(sizeof(*e) * (n + 1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m = 0; + for (i = 0; i < windings; ++i) + { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i] - 1; + for (k = 0; k < wcount[i]; j = k++) + { + int a = k, b = j; + // skip the edge if horizontal + if (p[j].y == p[k].y) continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) + { + e[n].invert = 1; + a = j, b = k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + // STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); } static void stbtt__add_point(stbtt__point *points, int n, float x, float y) { - if (!points) return; // during first pass, it's unallocated - points[n].x = x; - points[n].y = y; + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; } // tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching -static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) -{ - // midpoint - float mx = (x0 + 2*x1 + x2)/4; - float my = (y0 + 2*y1 + y2)/4; - // versus directly drawn line - float dx = (x0+x2)/2 - mx; - float dy = (y0+y2)/2 - my; - if (n > 16) // 65536 segments on one curve better be enough! - return 1; - if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA - stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x2,y2); - *num_points = *num_points+1; - } - return 1; -} - -static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) -{ - // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough - float dx0 = x1-x0; - float dy0 = y1-y0; - float dx1 = x2-x1; - float dy1 = y2-y1; - float dx2 = x3-x2; - float dy2 = y3-y2; - float dx = x3-x0; - float dy = y3-y0; - float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); - float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); - float flatness_squared = longlen*longlen-shortlen*shortlen; - - if (n > 16) // 65536 segments on one curve better be enough! - return; - - if (flatness_squared > objspace_flatness_squared) { - float x01 = (x0+x1)/2; - float y01 = (y0+y1)/2; - float x12 = (x1+x2)/2; - float y12 = (y1+y2)/2; - float x23 = (x2+x3)/2; - float y23 = (y2+y3)/2; - - float xa = (x01+x12)/2; - float ya = (y01+y12)/2; - float xb = (x12+x23)/2; - float yb = (y12+y23)/2; - - float mx = (xa+xb)/2; - float my = (ya+yb)/2; - - stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x3,y3); - *num_points = *num_points+1; - } +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, + float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2 * x1 + x2) / 4; + float my = (y0 + 2 * y1 + y2) / 4; + // versus directly drawn line + float dx = (x0 + x2) / 2 - mx; + float dy = (y0 + y2) / 2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx * dx + dy * dy > objspace_flatness_squared) + { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0, y0, (x0 + x1) / 2.0f, (y0 + y1) / 2.0f, mx, my, objspace_flatness_squared, + n + 1); + stbtt__tesselate_curve(points, num_points, mx, my, (x1 + x2) / 2.0f, (y1 + y2) / 2.0f, x2, y2, objspace_flatness_squared, + n + 1); + } + else + { + stbtt__add_point(points, *num_points, x2, y2); + *num_points = *num_points + 1; + } + return 1; } -// returns number of contours -static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) -{ - stbtt__point *points=0; - int num_points=0; - - float objspace_flatness_squared = objspace_flatness * objspace_flatness; - int i,n=0,start=0, pass; - - // count how many "moves" there are to get the contour count - for (i=0; i < num_verts; ++i) - if (vertices[i].type == STBTT_vmove) - ++n; - - *num_contours = n; - if (n == 0) return 0; - - *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); - - if (*contour_lengths == 0) { - *num_contours = 0; - return 0; - } +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, + float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1 - x0; + float dy0 = y1 - y0; + float dx1 = x2 - x1; + float dy1 = y2 - y1; + float dx2 = x3 - x2; + float dy2 = y3 - y2; + float dx = x3 - x0; + float dy = y3 - y0; + float longlen = + (float)(STBTT_sqrt(dx0 * dx0 + dy0 * dy0) + STBTT_sqrt(dx1 * dx1 + dy1 * dy1) + STBTT_sqrt(dx2 * dx2 + dy2 * dy2)); + float shortlen = (float)STBTT_sqrt(dx * dx + dy * dy); + float flatness_squared = longlen * longlen - shortlen * shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) + { + float x01 = (x0 + x1) / 2; + float y01 = (y0 + y1) / 2; + float x12 = (x1 + x2) / 2; + float y12 = (y1 + y2) / 2; + float x23 = (x2 + x3) / 2; + float y23 = (y2 + y3) / 2; + + float xa = (x01 + x12) / 2; + float ya = (y01 + y12) / 2; + float xb = (x12 + x23) / 2; + float yb = (y12 + y23) / 2; + + float mx = (xa + xb) / 2; + float my = (ya + yb) / 2; + + stbtt__tesselate_cubic(points, num_points, x0, y0, x01, y01, xa, ya, mx, my, objspace_flatness_squared, n + 1); + stbtt__tesselate_cubic(points, num_points, mx, my, xb, yb, x23, y23, x3, y3, objspace_flatness_squared, n + 1); + } + else + { + stbtt__add_point(points, *num_points, x3, y3); + *num_points = *num_points + 1; + } +} - // make two passes through the points so we don't need to realloc - for (pass=0; pass < 2; ++pass) { - float x=0,y=0; - if (pass == 1) { - points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); - if (points == NULL) goto error; - } - num_points = 0; - n= -1; - for (i=0; i < num_verts; ++i) { - switch (vertices[i].type) { +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, + int *num_contours, void *userdata) +{ + stbtt__point *points = 0; + int num_points = 0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i, n = 0, start = 0, pass; + + // count how many "moves" there are to get the contour count + for (i = 0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *)STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) + { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass = 0; pass < 2; ++pass) + { + float x = 0, y = 0; + if (pass == 1) + { + points = (stbtt__point *)STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n = -1; + for (i = 0; i < num_verts; ++i) + { + switch (vertices[i].type) + { case STBTT_vmove: - // start the next contour - if (n >= 0) - (*contour_lengths)[n] = num_points - start; - ++n; - start = num_points; - - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x,y); - break; + // start the next contour + if (n >= 0) (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; case STBTT_vline: - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x, y); - break; + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; case STBTT_vcurve: - stbtt__tesselate_curve(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; + stbtt__tesselate_curve(points, &num_points, x, y, vertices[i].cx, vertices[i].cy, vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; case STBTT_vcubic: - stbtt__tesselate_cubic(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].cx1, vertices[i].cy1, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - } - } - (*contour_lengths)[n] = num_points - start; - } + stbtt__tesselate_cubic(points, &num_points, x, y, vertices[i].cx, vertices[i].cy, vertices[i].cx1, + vertices[i].cy1, vertices[i].x, vertices[i].y, objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } - return points; + return points; error: - STBTT_free(points, userdata); - STBTT_free(*contour_lengths, userdata); - *contour_lengths = 0; - *num_contours = 0; - return NULL; -} - -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) -{ - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; - stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); - if (windings) { - stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); - STBTT_free(winding_lengths, userdata); - STBTT_free(windings, userdata); - } + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, + float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, + void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count, *winding_lengths; + stbtt__point *windings = + stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) + { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, + invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } } STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) { - STBTT_free(bitmap, userdata); + STBTT_free(bitmap, userdata); } -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, + float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) { - int ix0,iy0,ix1,iy1; - stbtt__bitmap gbm; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) { - STBTT_free(vertices, info->userdata); - return NULL; - } - scale_y = scale_x; - } - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + int ix0, iy0, ix1, iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - // now we get the size - gbm.w = (ix1 - ix0); - gbm.h = (iy1 - iy0); - gbm.pixels = NULL; // in case we error - - if (width ) *width = gbm.w; - if (height) *height = gbm.h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - if (gbm.w && gbm.h) { - gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); - if (gbm.pixels) { - gbm.stride = gbm.w; - - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); - } - } - STBTT_free(vertices, info->userdata); - return gbm.pixels; -} + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) + { + if (scale_x == 0) + { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, &ix1, &iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff) *xoff = ix0; + if (yoff) *yoff = iy0; + + if (gbm.w && gbm.h) + { + gbm.pixels = (unsigned char *)STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) + { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, + int *height, int *xoff, int *yoff) { - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); } -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, + int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, + int glyph) { - int ix0,iy0; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; + int ix0, iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); - gbm.pixels = output; - gbm.w = out_w; - gbm.h = out_h; - gbm.stride = out_stride; + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, 0, 0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; - if (gbm.w && gbm.h) - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); - STBTT_free(vertices, info->userdata); + STBTT_free(vertices, info->userdata); } -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, + float scale_x, float scale_y, int glyph) { - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 0.0f, glyph); } -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, + float shift_y, int codepoint, int *width, int *height, int *xoff, + int *yoff) { - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info, codepoint), width, + height, xoff, yoff); +} -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, + int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, + int codepoint) { - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, + stbtt_FindGlyphIndex(info, codepoint)); } -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, + int *width, int *height, int *xoff, int *yoff) { - return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, codepoint, width, height, xoff, yoff); +} -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, + float scale_x, float scale_y, int codepoint) { - stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 0.0f, codepoint); } ////////////////////////////////////////////////////////////////////////////// @@ -3241,71 +3538,70 @@ STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned ch // // This is SUPER-CRAPPY packing to keep source code small -static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata) -{ - float scale; - int x,y,bottom_y, i; - stbtt_fontinfo f; - f.userdata = NULL; - if (!stbtt_InitFont(&f, data, offset)) - return -1; - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - x=y=1; - bottom_y = 1; - - scale = stbtt_ScaleForPixelHeight(&f, pixel_height); - - for (i=0; i < num_chars; ++i) { - int advance, lsb, x0,y0,x1,y1,gw,gh; - int g = stbtt_FindGlyphIndex(&f, first_char + i); - stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); - gw = x1-x0; - gh = y1-y0; - if (x + gw + 1 >= pw) - y = bottom_y, x = 1; // advance to next row - if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row - return -i; - STBTT_assert(x+gw < pw); - STBTT_assert(y+gh < ph); - stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); - chardata[i].x0 = (stbtt_int16) x; - chardata[i].y0 = (stbtt_int16) y; - chardata[i].x1 = (stbtt_int16) (x + gw); - chardata[i].y1 = (stbtt_int16) (y + gh); - chardata[i].xadvance = scale * advance; - chardata[i].xoff = (float) x0; - chardata[i].yoff = (float) y0; - x = x + gw + 1; - if (y+gh+1 > bottom_y) - bottom_y = y+gh+1; - } - return bottom_y; +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x, y, bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) return -1; + STBTT_memset(pixels, 0, pw * ph); // background of 0 around pixels + x = y = 1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i = 0; i < num_chars; ++i) + { + int advance, lsb, x0, y0, x1, y1, gw, gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale, scale, &x0, &y0, &x1, &y1); + gw = x1 - x0; + gh = y1 - y0; + if (x + gw + 1 >= pw) y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x + gw < pw); + STBTT_assert(y + gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels + x + y * pw, gw, gh, pw, scale, scale, g); + chardata[i].x0 = (stbtt_int16)x; + chardata[i].y0 = (stbtt_int16)y; + chardata[i].x1 = (stbtt_int16)(x + gw); + chardata[i].y1 = (stbtt_int16)(y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float)x0; + chardata[i].yoff = (float)y0; + x = x + gw + 1; + if (y + gh + 1 > bottom_y) bottom_y = y + gh + 1; + } + return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, + stbtt_aligned_quad *q, int opengl_fillrule) { - float d3d_bias = opengl_fillrule ? 0 : -0.5f; - float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; - int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); - int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); - q->x0 = round_x + d3d_bias; - q->y0 = round_y + d3d_bias; - q->x1 = round_x + b->x1 - b->x0 + d3d_bias; - q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; - *xpos += b->xadvance; + *xpos += b->xadvance; } ////////////////////////////////////////////////////////////////////////////// @@ -3313,7 +3609,7 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int // rectangle packing replacement routines if you don't have stb_rect_pack.h // -#ifndef STB_RECT_PACK_VERSION + #ifndef STB_RECT_PACK_VERSION typedef int stbrp_coord; @@ -3330,53 +3626,53 @@ typedef int stbrp_coord; typedef struct { - int width,height; - int x,y,bottom_y; + int width, height; + int x, y, bottom_y; } stbrp_context; typedef struct { - unsigned char x; + unsigned char x; } stbrp_node; struct stbrp_rect { - stbrp_coord x,y; - int id,w,h,was_packed; + stbrp_coord x, y; + int id, w, h, was_packed; }; static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) { - con->width = pw; - con->height = ph; - con->x = 0; - con->y = 0; - con->bottom_y = 0; - STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) { - int i; - for (i=0; i < num_rects; ++i) { - if (con->x + rects[i].w > con->width) { - con->x = 0; - con->y = con->bottom_y; - } - if (con->y + rects[i].h > con->height) - break; - rects[i].x = con->x; - rects[i].y = con->y; - rects[i].was_packed = 1; - con->x += rects[i].w; - if (con->y + rects[i].h > con->bottom_y) - con->bottom_y = con->y + rects[i].h; - } - for ( ; i < num_rects; ++i) - rects[i].was_packed = 0; + int i; + for (i = 0; i < num_rects; ++i) + { + if (con->x + rects[i].w > con->width) + { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) con->bottom_y = con->y + rects[i].h; + } + for (; i < num_rects; ++i) + rects[i].was_packed = 0; } -#endif + #endif ////////////////////////////////////////////////////////////////////////////// // @@ -3385,383 +3681,396 @@ static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rect // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, + void *alloc_context) { - stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); - int num_nodes = pw - padding; - stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + stbrp_context *context = (stbrp_context *)STBTT_malloc(sizeof(*context), alloc_context); + int num_nodes = pw - padding; + stbrp_node * nodes = (stbrp_node *)STBTT_malloc(sizeof(*nodes) * num_nodes, alloc_context); - if (context == NULL || nodes == NULL) { - if (context != NULL) STBTT_free(context, alloc_context); - if (nodes != NULL) STBTT_free(nodes , alloc_context); - return 0; - } + if (context == NULL || nodes == NULL) + { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes, alloc_context); + return 0; + } - spc->user_allocator_context = alloc_context; - spc->width = pw; - spc->height = ph; - spc->pixels = pixels; - spc->pack_info = context; - spc->nodes = nodes; - spc->padding = padding; - spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; - spc->h_oversample = 1; - spc->v_oversample = 1; + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; - stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + stbrp_init_target(context, pw - padding, ph - padding, nodes, num_nodes); - if (pixels) - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + if (pixels) STBTT_memset(pixels, 0, pw * ph); // background of 0 around pixels - return 1; + return 1; } -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc) { - STBTT_free(spc->nodes , spc->user_allocator_context); - STBTT_free(spc->pack_info, spc->user_allocator_context); + STBTT_free(spc->nodes, spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); } STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) { - STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); - STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); - if (h_oversample <= STBTT_MAX_OVERSAMPLE) - spc->h_oversample = h_oversample; - if (v_oversample <= STBTT_MAX_OVERSAMPLE) - spc->v_oversample = v_oversample; + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) spc->v_oversample = v_oversample; } -#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE - 1) static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) { - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_w = w - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < h; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 2); + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j = 0; j < h; ++j) + { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) + { + case 2: + for (i = 0; i <= safe_w; ++i) + { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char)(total / 2); } break; - case 3: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 3); + case 3: + for (i = 0; i <= safe_w; ++i) + { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char)(total / 3); } break; - case 4: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 4); + case 4: + for (i = 0; i <= safe_w; ++i) + { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char)(total / 4); } break; - case 5: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 5); + case 5: + for (i = 0; i <= safe_w; ++i) + { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char)(total / 5); } break; - default: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / kernel_width); + default: + for (i = 0; i <= safe_w; ++i) + { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char)(total / kernel_width); } break; - } + } - for (; i < w; ++i) { - STBTT_assert(pixels[i] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i] = (unsigned char) (total / kernel_width); - } + for (; i < w; ++i) + { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char)(total / kernel_width); + } - pixels += stride_in_bytes; - } + pixels += stride_in_bytes; + } } static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) { - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_h = h - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < w; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j = 0; j < w; ++j) + { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) + { + case 2: + for (i = 0; i <= safe_h; ++i) + { + total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes]; + pixels[i * stride_in_bytes] = (unsigned char)(total / 2); } break; - case 3: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + case 3: + for (i = 0; i <= safe_h; ++i) + { + total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes]; + pixels[i * stride_in_bytes] = (unsigned char)(total / 3); } break; - case 4: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + case 4: + for (i = 0; i <= safe_h; ++i) + { + total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes]; + pixels[i * stride_in_bytes] = (unsigned char)(total / 4); } break; - case 5: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + case 5: + for (i = 0; i <= safe_h; ++i) + { + total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes]; + pixels[i * stride_in_bytes] = (unsigned char)(total / 5); } break; - default: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + default: + for (i = 0; i <= safe_h; ++i) + { + total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes]; + pixels[i * stride_in_bytes] = (unsigned char)(total / kernel_width); } break; - } + } - for (; i < h; ++i) { - STBTT_assert(pixels[i*stride_in_bytes] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } + for (; i < h; ++i) + { + STBTT_assert(pixels[i * stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i * stride_in_bytes] = (unsigned char)(total / kernel_width); + } - pixels += 1; - } + pixels += 1; + } } static float stbtt__oversample_shift(int oversample) { - if (!oversample) - return 0.0f; + if (!oversample) return 0.0f; - // The prefilter is a box filter of width "oversample", - // which shifts phase by (oversample - 1)/2 pixels in - // oversampled space. We want to shift in the opposite - // direction to counter this. - return (float)-(oversample - 1) / (2.0f * (float)oversample); + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k; - - k=0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - ranges[i].h_oversample = (unsigned char) spc->h_oversample; - ranges[i].v_oversample = (unsigned char) spc->v_oversample; - for (j=0; j < ranges[i].num_chars; ++j) { - int x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); - ++k; - } - } - - return k; +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, + int num_ranges, stbrp_rect *rects) +{ + int i, j, k; + + k = 0; + for (i = 0; i < num_ranges; ++i) + { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char)spc->h_oversample; + ranges[i].v_oversample = (unsigned char)spc->v_oversample; + for (j = 0; j < ranges[i].num_chars; ++j) + { + int x0, y0, x1, y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j + : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale * spc->h_oversample, scale * spc->v_oversample, 0, 0, &x0, &y0, + &x1, &y1); + rects[k].w = (stbrp_coord)(x1 - x0 + spc->padding + spc->h_oversample - 1); + rects[k].h = (stbrp_coord)(y1 - y0 + spc->padding + spc->v_oversample - 1); + ++k; + } + } + + return k; } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k, return_value = 1; - - // save current values - int old_h_over = spc->h_oversample; - int old_v_over = spc->v_oversample; - - k = 0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - float recip_h,recip_v,sub_x,sub_y; - spc->h_oversample = ranges[i].h_oversample; - spc->v_oversample = ranges[i].v_oversample; - recip_h = 1.0f / spc->h_oversample; - recip_v = 1.0f / spc->v_oversample; - sub_x = stbtt__oversample_shift(spc->h_oversample); - sub_y = stbtt__oversample_shift(spc->v_oversample); - for (j=0; j < ranges[i].num_chars; ++j) { - stbrp_rect *r = &rects[k]; - if (r->was_packed) { - stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; - int advance, lsb, x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbrp_coord pad = (stbrp_coord) spc->padding; - - // pad on left and top - r->x += pad; - r->y += pad; - r->w -= pad; - r->h -= pad; - stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); - stbtt_GetGlyphBitmapBox(info, glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - &x0,&y0,&x1,&y1); - stbtt_MakeGlyphBitmapSubpixel(info, - spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w - spc->h_oversample+1, - r->h - spc->v_oversample+1, - spc->stride_in_bytes, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - glyph); - - if (spc->h_oversample > 1) - stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->h_oversample); - - if (spc->v_oversample > 1) - stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->v_oversample); - - bc->x0 = (stbtt_int16) r->x; - bc->y0 = (stbtt_int16) r->y; - bc->x1 = (stbtt_int16) (r->x + r->w); - bc->y1 = (stbtt_int16) (r->y + r->h); - bc->xadvance = scale * advance; - bc->xoff = (float) x0 * recip_h + sub_x; - bc->yoff = (float) y0 * recip_v + sub_y; - bc->xoff2 = (x0 + r->w) * recip_h + sub_x; - bc->yoff2 = (y0 + r->h) * recip_v + sub_y; - } else { - return_value = 0; // if any fail, report failure - } - - ++k; - } - } +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, + int num_ranges, stbrp_rect *rects) +{ + int i, j, k, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i = 0; i < num_ranges; ++i) + { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h, recip_v, sub_x, sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j = 0; j < ranges[i].num_chars; ++j) + { + stbrp_rect *r = &rects[k]; + if (r->was_packed) + { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0, y0, x1, y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j + : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord)spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, scale * spc->h_oversample, scale * spc->v_oversample, &x0, &y0, &x1, &y1); + stbtt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y * spc->stride_in_bytes, + r->w - spc->h_oversample + 1, r->h - spc->v_oversample + 1, spc->stride_in_bytes, + scale * spc->h_oversample, scale * spc->v_oversample, 0, 0, glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y * spc->stride_in_bytes, r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y * spc->stride_in_bytes, r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16)r->x; + bc->y0 = (stbtt_int16)r->y; + bc->x1 = (stbtt_int16)(r->x + r->w); + bc->y1 = (stbtt_int16)(r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float)x0 * recip_h + sub_x; + bc->yoff = (float)y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + } + else + { + return_value = 0; // if any fail, report failure + } - // restore original values - spc->h_oversample = old_h_over; - spc->v_oversample = old_v_over; + ++k; + } + } - return return_value; + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; } STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) { - stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); + stbrp_pack_rects((stbrp_context *)spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, + int num_ranges) { - stbtt_fontinfo info; - int i,j,n, return_value = 1; - //stbrp_context *context = (stbrp_context *) spc->pack_info; - stbrp_rect *rects; + stbtt_fontinfo info; + int i, j, n, return_value = 1; + // stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; - // flag all characters as NOT packed - for (i=0; i < num_ranges; ++i) - for (j=0; j < ranges[i].num_chars; ++j) - ranges[i].chardata_for_range[j].x0 = - ranges[i].chardata_for_range[j].y0 = - ranges[i].chardata_for_range[j].x1 = - ranges[i].chardata_for_range[j].y1 = 0; + // flag all characters as NOT packed + for (i = 0; i < num_ranges; ++i) + for (j = 0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = ranges[i].chardata_for_range[j].y0 = ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; - n = 0; - for (i=0; i < num_ranges; ++i) - n += ranges[i].num_chars; - - rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); - if (rects == NULL) - return 0; + n = 0; + for (i = 0; i < num_ranges; ++i) + n += ranges[i].num_chars; - info.userdata = spc->user_allocator_context; - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + rects = (stbrp_rect *)STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) return 0; - n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, font_index)); - stbtt_PackFontRangesPackRects(spc, rects, n); - - return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); - STBTT_free(rects, spc->user_allocator_context); - return return_value; -} + stbtt_PackFontRangesPackRects(spc, rects, n); -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, - int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) -{ - stbtt_pack_range range; - range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; - range.array_of_unicode_codepoints = NULL; - range.num_chars = num_chars_in_range; - range.chardata_for_range = chardata_for_range; - range.font_size = font_size; - return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); -} - -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) -{ - float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; - - if (align_to_integer) { - float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); - float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); - q->x0 = x; - q->y0 = y; - q->x1 = x + b->xoff2 - b->xoff; - q->y1 = y + b->yoff2 - b->yoff; - } else { - q->x0 = *xpos + b->xoff; - q->y0 = *ypos + b->yoff; - q->x1 = *xpos + b->xoff2; - q->y1 = *ypos + b->yoff2; - } + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} - *xpos += b->xadvance; +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, + stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } +STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, + stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) + { + float x = (float)STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float)STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } + else + { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} ////////////////////////////////////////////////////////////////////////////// // @@ -3769,204 +4078,232 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) -{ - stbtt_int32 i=0; - - // convert utf16 to utf8 and compare the results while converting - while (len2) { - stbtt_uint16 ch = s2[0]*256 + s2[1]; - if (ch < 0x80) { - if (i >= len1) return -1; - if (s1[i++] != ch) return -1; - } else if (ch < 0x800) { - if (i+1 >= len1) return -1; - if (s1[i++] != 0xc0 + (ch >> 6)) return -1; - if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; - } else if (ch >= 0xd800 && ch < 0xdc00) { - stbtt_uint32 c; - stbtt_uint16 ch2 = s2[2]*256 + s2[3]; - if (i+3 >= len1) return -1; - c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; - if (s1[i++] != 0xf0 + (c >> 18)) return -1; - if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; - s2 += 2; // plus another 2 below - len2 -= 2; - } else if (ch >= 0xdc00 && ch < 0xe000) { - return -1; - } else { - if (i+2 >= len1) return -1; - if (s1[i++] != 0xe0 + (ch >> 12)) return -1; - if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; - } - s2 += 2; - len2 -= 2; - } - return i; +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, + stbtt_int32 len2) +{ + stbtt_int32 i = 0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) + { + stbtt_uint16 ch = s2[0] * 256 + s2[1]; + if (ch < 0x80) + { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } + else if (ch < 0x800) + { + if (i + 1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } + else if (ch >= 0xd800 && ch < 0xdc00) + { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2] * 256 + s2[3]; + if (i + 3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c)&0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } + else if (ch >= 0xdc00 && ch < 0xe000) + { + return -1; + } + else + { + if (i + 2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch)&0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; } -static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8 *)s1, len1, (stbtt_uint8 *)s2, len2); } // returns results in whatever encoding you request... but note that 2-byte encodings // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) -{ - stbtt_int32 i,count,stringOffset; - stbtt_uint8 *fc = font->data; - stbtt_uint32 offset = font->fontstart; - stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return NULL; - - count = ttUSHORT(fc+nm+2); - stringOffset = nm + ttUSHORT(fc+nm+4); - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) - && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { - *length = ttUSHORT(fc+loc+8); - return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); - } - } - return NULL; -} - -static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) -{ - stbtt_int32 i; - stbtt_int32 count = ttUSHORT(fc+nm+2); - stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); - - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - stbtt_int32 id = ttUSHORT(fc+loc+6); - if (id == target_id) { - // find the encoding - stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); - - // is this a Unicode encoding? - if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { - stbtt_int32 slen = ttUSHORT(fc+loc+8); - stbtt_int32 off = ttUSHORT(fc+loc+10); - - // check if there's a prefix match - stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); - if (matchlen >= 0) { - // check for target_id+1 immediately following, with same encoding & language - if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { - slen = ttUSHORT(fc+loc+12+8); - off = ttUSHORT(fc+loc+12+10); - if (slen == 0) { - if (matchlen == nlen) - return 1; - } else if (matchlen < nlen && name[matchlen] == ' ') { - ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) - return 1; - } - } else { - // if nothing immediately following - if (matchlen == nlen) - return 1; - } +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, + int languageID, int nameID) +{ + stbtt_int32 i, count, stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc + nm + 2); + stringOffset = nm + ttUSHORT(fc + nm + 4); + for (i = 0; i < count; ++i) + { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc + loc + 0) && encodingID == ttUSHORT(fc + loc + 2) && + languageID == ttUSHORT(fc + loc + 4) && nameID == ttUSHORT(fc + loc + 6)) + { + *length = ttUSHORT(fc + loc + 8); + return (const char *)(fc + stringOffset + ttUSHORT(fc + loc + 10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, + stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc + nm + 2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc + nm + 4); + + for (i = 0; i < count; ++i) + { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc + loc + 6); + if (id == target_id) + { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc + loc + 0), encoding = ttUSHORT(fc + loc + 2), language = ttUSHORT(fc + loc + 4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) + { + stbtt_int32 slen = ttUSHORT(fc + loc + 8); + stbtt_int32 off = ttUSHORT(fc + loc + 10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc + stringOffset + off, slen); + if (matchlen >= 0) + { + // check for target_id+1 immediately following, with same encoding & language + if (i + 1 < count && ttUSHORT(fc + loc + 12 + 6) == next_id && ttUSHORT(fc + loc + 12) == platform && + ttUSHORT(fc + loc + 12 + 2) == encoding && ttUSHORT(fc + loc + 12 + 4) == language) + { + slen = ttUSHORT(fc + loc + 12 + 8); + off = ttUSHORT(fc + loc + 12 + 10); + if (slen == 0) + { + if (matchlen == nlen) return 1; + } + else if (matchlen < nlen && name[matchlen] == ' ') + { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char *)(name + matchlen), nlen - matchlen, + (char *)(fc + stringOffset + off), slen)) + return 1; + } + } + else + { + // if nothing immediately following + if (matchlen == nlen) return 1; + } + } } - } - // @TODO handle other encodings - } - } - return 0; + // @TODO handle other encodings + } + } + return 0; } static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) { - stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); - stbtt_uint32 nm,hd; - if (!stbtt__isfont(fc+offset)) return 0; - - // check italics/bold/underline flags in macStyle... - if (flags) { - hd = stbtt__find_table(fc, offset, "head"); - if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; - } - - nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return 0; - - if (flags) { - // if we checked the macStyle flags, then just check the family and ignore the subfamily - if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } else { - if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } - - return 0; + stbtt_int32 nlen = (stbtt_int32)STBTT_strlen((char *)name); + stbtt_uint32 nm, hd; + if (!stbtt__isfont(fc + offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) + { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc + hd + 44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) + { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + else + { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; } static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) { - stbtt_int32 i; - for (i=0;;++i) { - stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); - if (off < 0) return off; - if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) - return off; - } + stbtt_int32 i; + for (i = 0;; ++i) + { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *)font_collection, off, (stbtt_uint8 *)name_utf8, flags)) return off; + } } -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif + #if defined(__GNUC__) || defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-qual" + #endif -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, - float pixel_height, unsigned char *pixels, int pw, int ph, - int first_char, int num_chars, stbtt_bakedchar *chardata) +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, float pixel_height, unsigned char *pixels, int pw, + int ph, int first_char, int num_chars, stbtt_bakedchar *chardata) { - return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); + return stbtt_BakeFontBitmap_internal((unsigned char *)data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, + chardata); } STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) { - return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); + return stbtt_GetFontOffsetForIndex_internal((unsigned char *)data, index); } STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) { - return stbtt_GetNumberOfFonts_internal((unsigned char *) data); + return stbtt_GetNumberOfFonts_internal((unsigned char *)data); } STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) { - return stbtt_InitFont_internal(info, (unsigned char *) data, offset); + return stbtt_InitFont_internal(info, (unsigned char *)data, offset); } STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) { - return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); + return stbtt_FindMatchingFont_internal((unsigned char *)fontdata, (char *)name, flags); } STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) { - return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *)s1, len1, (char *)s2, len2); } -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif + #if defined(__GNUC__) || defined(__clang__) + #pragma GCC diagnostic pop + #endif #endif // STB_TRUETYPE_IMPLEMENTATION - // FULL VERSION HISTORY // // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual diff --git a/source/main/gui/mygui/Attribute.h b/source/main/gui/mygui/Attribute.h index 31a7e274f0..9500c052a3 100644 --- a/source/main/gui/mygui/Attribute.h +++ b/source/main/gui/mygui/Attribute.h @@ -26,114 +26,112 @@ #include "RoRPrerequisites.h" -namespace attribute { - -// êëàññ îáåðòêà äëÿ óäàëåíèÿ äàííûõ èç ñòàòè÷åñêîãî âåêòîðà -template -struct DataHolder +namespace attribute { - ~DataHolder() + + // ����� ������� ��� �������� ������ �� ������������ ������� + template struct DataHolder { - for (typename Type::iterator item = data.begin(); item != data.end(); ++item) - delete (*item).first; - } + ~DataHolder() + { + for (typename Type::iterator item = data.begin(); item != data.end(); ++item) + delete (*item).first; + } - Type data; -}; + Type data; + }; -// èíòåðôåéñ äëÿ îáåðòêè ïîëÿ -template -struct Field -{ - virtual void set(OwnerType* _target, typename SetterType::BaseValueType* _value) = 0; -}; + // ��������� ��� ������� ���� + template struct Field + { + virtual void set(OwnerType *_target, typename SetterType::BaseValueType *_value) = 0; + }; -// øàáëîí äëÿ îáåðòêè ïîëÿ -template -struct FieldHolder : public Field -{ - FieldHolder(FieldType* OwnerType::* offset) : m_offset(offset) + // ������ ��� ������� ���� + template + struct FieldHolder : public Field { - } + FieldHolder(FieldType *OwnerType::*offset) : m_offset(offset) + { + } - FieldType* OwnerType::* const m_offset; + FieldType *OwnerType::*const m_offset; - virtual void set(OwnerType* _target, typename SetterType::BaseValueType* _value) + virtual void set(OwnerType *_target, typename SetterType::BaseValueType *_value) + { + _target->*m_offset = SetterType::template convert(_value); + // _target->*m_offset = (_value == 0 ? 0 : + // _value->castType::template(false));//SetterType::convert(_value); + } + }; + + // ������ ��� �������� ���� + template struct AttributeField { - _target ->* m_offset = SetterType::template convert(_value); - // _target->*m_offset = (_value == 0 ? 0 : _value->castType::template(false));//SetterType::convert(_value); - } -}; + typedef std::pair *, ValueType> BindPair; + typedef std::vector VectorBindPair; -// øàáëîí äëÿ àòðèáóòà ïîëÿ -template -struct AttributeField -{ - typedef std::pair*, ValueType> BindPair; - typedef std::vector VectorBindPair; + template AttributeField(FieldType *OwnerType::*_offset, const ValueType &_value) + { + getData().push_back(BindPair(new FieldHolder(_offset), _value)); + } - template - AttributeField(FieldType* OwnerType::* _offset, const ValueType& _value) - { - getData().push_back(BindPair(new FieldHolder(_offset), _value)); - } + static VectorBindPair &getData() + { + static DataHolder data; + return data.data; + } + }; - static VectorBindPair& getData() - { - static DataHolder data; - return data.data; - } -}; - -// ìàêðîñ äëÿ èíñòàíñèðîâàíèÿ àòðèáóòà ïîëÿ -#define DECLARE_ATTRIBUTE_FIELD(_name, _type, _setter) \ - template \ - struct _name : public attribute::AttributeField \ - { \ - template \ - _name(FieldType* OwnerType::* _offset, const ValueType& _value) : \ - AttributeField(_offset, _value) { } \ +// ������ ��� ��������������� �������� ���� +#define DECLARE_ATTRIBUTE_FIELD(_name, _type, _setter) \ + template \ + struct _name : public attribute::AttributeField \ + { \ + template \ + _name(FieldType *OwnerType::*_offset, const ValueType &_value) \ + : AttributeField(_offset, _value) \ + { \ + } \ } -// ìàêðîñ äëÿ èíñòàíñèðîâàíèÿ ýêçåìïëÿðà àòðèáóòà -#define ATTRIBUTE_FIELD(_attribute, _class, _field, _value) \ - struct _attribute##_##_field \ - { \ - _attribute##_##_field() \ - { \ - static attribute::_attribute<_class> bind(&_class::_field, _value); \ - } \ +// ������ ��� ��������������� ���������� �������� +#define ATTRIBUTE_FIELD(_attribute, _class, _field, _value) \ + struct _attribute##_##_field \ + { \ + _attribute##_##_field() \ + { \ + static attribute::_attribute<_class> bind(&_class::_field, _value); \ + } \ } _attribute##_##_field - // øàáëîí äëÿ àòðèáóòà êëàññà - template - struct ClassAttribute + // ������ ��� �������� ������ + template struct ClassAttribute { - ClassAttribute(const ValueType& _value) + ClassAttribute(const ValueType &_value) { getData() = _value; } - static ValueType& getData() + static ValueType &getData() { static ValueType data; return data; } }; - // ìàêðîñ äëÿ èíñòàíñèðîâàíèÿ àòðèáóòà êëàññà -#define DECLARE_ATTRIBUTE_CLASS(_name, _type) \ - template \ - struct _name : public attribute::ClassAttribute<_name, ValueType> \ - { \ - _name(const ValueType& _value) : \ - ClassAttribute<_name, ValueType>(_value) { } \ +// ������ ��� ��������������� �������� ������ +#define DECLARE_ATTRIBUTE_CLASS(_name, _type) \ + template struct _name : public attribute::ClassAttribute<_name, ValueType> \ + { \ + _name(const ValueType &_value) : ClassAttribute<_name, ValueType>(_value) \ + { \ + } \ } - // ìàêðîñ äëÿ èíñòàíñèðîâàíèÿ ýêçåìïëÿðà êëàññà -#define ATTRIBUTE_CLASS(_attribute, _class, _value) \ - class _class; \ +// ������ ��� ��������������� ���������� ������ +#define ATTRIBUTE_CLASS(_attribute, _class, _value) \ + class _class; \ static attribute::_attribute<_class> _attribute##_##_class(_value) - } // namespace attribute diff --git a/source/main/gui/mygui/BaseLayout.h b/source/main/gui/mygui/BaseLayout.h index 2eb5deeafa..6e26fccde7 100644 --- a/source/main/gui/mygui/BaseLayout.h +++ b/source/main/gui/mygui/BaseLayout.h @@ -25,221 +25,221 @@ #pragma once #include "RoRPrerequisites.h" -#include #include "WrapsAttribute.h" -namespace wraps { +#include -class BaseLayout +namespace wraps { -protected: - BaseLayout() : mMainWidget(nullptr) - { - } - BaseLayout(const std::string& _layout, MyGUI::Widget* _parent = nullptr) : mMainWidget(nullptr) + class BaseLayout { - initialise(_layout, _parent); - } + protected: + BaseLayout() : mMainWidget(nullptr) + { + } - template - void assignWidget(T* & _widget, const std::string& _name, bool _throw = true, bool _createFakeWidgets = true) - { - _widget = nullptr; - for (MyGUI::VectorWidgetPtr::iterator iter = mListWindowRoot.begin(); iter != mListWindowRoot.end(); ++iter) + BaseLayout(const std::string &_layout, MyGUI::Widget *_parent = nullptr) : mMainWidget(nullptr) { - MyGUI::Widget* find = (*iter)->findWidget(mPrefix + _name); - if (nullptr != find) + initialise(_layout, _parent); + } + + template + void assignWidget(T *&_widget, const std::string &_name, bool _throw = true, bool _createFakeWidgets = true) + { + _widget = nullptr; + for (MyGUI::VectorWidgetPtr::iterator iter = mListWindowRoot.begin(); iter != mListWindowRoot.end(); ++iter) { - T* cast = find->castType(false); - if (nullptr != cast) - { - _widget = cast; - } - else + MyGUI::Widget *find = (*iter)->findWidget(mPrefix + _name); + if (nullptr != find) { - MYGUI_LOG(Warning, "Widget with name '" << _name << "' have wrong type ('" << - find->getTypeName() << "instead of '" << T::getClassTypeName() << "'). [" << mLayoutName << "]"); - MYGUI_ASSERT( ! _throw, "Can't assign widget with name '" << _name << "'. [" << mLayoutName << "]"); - if (_createFakeWidgets) - _widget = _createFakeWidget(mMainWidget); + T *cast = find->castType(false); + if (nullptr != cast) { _widget = cast; } + else + { + MYGUI_LOG(Warning, "Widget with name '" << _name << "' have wrong type ('" << find->getTypeName() + << "instead of '" << T::getClassTypeName() << "'). [" + << mLayoutName << "]"); + MYGUI_ASSERT(!_throw, "Can't assign widget with name '" << _name << "'. [" << mLayoutName << "]"); + if (_createFakeWidgets) _widget = _createFakeWidget(mMainWidget); + } + + return; } - - return; } + MYGUI_LOG(Warning, "Widget with name '" << _name << "' not found. [" << mLayoutName << "]"); + MYGUI_ASSERT(!_throw, "Can't assign widget with name '" << _name << "'. [" << mLayoutName << "]"); + if (_createFakeWidgets) _widget = _createFakeWidget(mMainWidget); } - MYGUI_LOG(Warning, "Widget with name '" << _name << "' not found. [" << mLayoutName << "]"); - MYGUI_ASSERT( ! _throw, "Can't assign widget with name '" << _name << "'. [" << mLayoutName << "]"); - if (_createFakeWidgets) - _widget = _createFakeWidget(mMainWidget); - } - - template - void assignBase(T* & _widget, const std::string& _name, bool _throw = true, bool _createFakeWidgets = true) - { - _widget = nullptr; - for (MyGUI::VectorWidgetPtr::iterator iter = mListWindowRoot.begin(); iter != mListWindowRoot.end(); ++iter) + + template + void assignBase(T *&_widget, const std::string &_name, bool _throw = true, bool _createFakeWidgets = true) { - MyGUI::Widget* find = (*iter)->findWidget(mPrefix + _name); - if (nullptr != find) + _widget = nullptr; + for (MyGUI::VectorWidgetPtr::iterator iter = mListWindowRoot.begin(); iter != mListWindowRoot.end(); ++iter) { - _widget = new T(find); - mListBase.push_back(_widget); - return; + MyGUI::Widget *find = (*iter)->findWidget(mPrefix + _name); + if (nullptr != find) + { + _widget = new T(find); + mListBase.push_back(_widget); + return; + } } - } - MYGUI_LOG(Warning, "Widget with name '" << _name << "' not found. [" << mLayoutName << "]"); - MYGUI_ASSERT( ! _throw, "Can't assign base widget with name '" << _name << "'. [" << mLayoutName << "]"); - if (_createFakeWidgets) - { - _widget = new T(_createFakeWidget(mMainWidget)); - mListBase.push_back(_widget); + MYGUI_LOG(Warning, "Widget with name '" << _name << "' not found. [" << mLayoutName << "]"); + MYGUI_ASSERT(!_throw, "Can't assign base widget with name '" << _name << "'. [" << mLayoutName << "]"); + if (_createFakeWidgets) + { + _widget = new T(_createFakeWidget(mMainWidget)); + mListBase.push_back(_widget); + } } - } - void initialise(const std::string& _layout, MyGUI::Widget* _parent = nullptr, bool _throw = true, bool _createFakeWidgets = true) - { - const std::string MAIN_WINDOW1 = "_Main"; - const std::string MAIN_WINDOW2 = "Root"; - mLayoutName = _layout; - - // îáîðà÷èâàåì - if (mLayoutName.empty()) + void initialise(const std::string &_layout, MyGUI::Widget *_parent = nullptr, bool _throw = true, + bool _createFakeWidgets = true) { - mMainWidget = _parent; - } - // çàãðóæàåì ëåéàóò íà âèäæåò - else - { - mPrefix = MyGUI::utility::toString(this, "_"); - mListWindowRoot = MyGUI::LayoutManager::getInstance().loadLayout(mLayoutName, mPrefix, _parent); + const std::string MAIN_WINDOW1 = "_Main"; + const std::string MAIN_WINDOW2 = "Root"; + mLayoutName = _layout; - const std::string mainName1 = mPrefix + MAIN_WINDOW1; - const std::string mainName2 = mPrefix + MAIN_WINDOW2; - for (MyGUI::VectorWidgetPtr::iterator iter = mListWindowRoot.begin(); iter != mListWindowRoot.end(); ++iter) + // ����������� + if (mLayoutName.empty()) { mMainWidget = _parent; } + // ��������� ������ �� ������ + else { - if ((*iter)->getName() == mainName1 || (*iter)->getName() == mainName2) + mPrefix = MyGUI::utility::toString(this, "_"); + mListWindowRoot = MyGUI::LayoutManager::getInstance().loadLayout(mLayoutName, mPrefix, _parent); + + const std::string mainName1 = mPrefix + MAIN_WINDOW1; + const std::string mainName2 = mPrefix + MAIN_WINDOW2; + for (MyGUI::VectorWidgetPtr::iterator iter = mListWindowRoot.begin(); iter != mListWindowRoot.end(); ++iter) { - mMainWidget = (*iter); + if ((*iter)->getName() == mainName1 || (*iter)->getName() == mainName2) + { + mMainWidget = (*iter); - snapToParent(mMainWidget); + snapToParent(mMainWidget); - break; + break; + } } - } - if (mMainWidget == nullptr) - { - MYGUI_LOG(Warning, "Root widget with name '" << MAIN_WINDOW1 << "' or '" << MAIN_WINDOW2 << "' not found. [" << mLayoutName << "]"); - MYGUI_ASSERT(_throw, "No root widget. ['" << mLayoutName << "]"); - if (_createFakeWidgets) - mMainWidget = _createFakeWidget(_parent); + if (mMainWidget == nullptr) + { + MYGUI_LOG(Warning, "Root widget with name '" << MAIN_WINDOW1 << "' or '" << MAIN_WINDOW2 << "' not found. [" + << mLayoutName << "]"); + MYGUI_ASSERT(_throw, "No root widget. ['" << mLayoutName << "]"); + if (_createFakeWidgets) mMainWidget = _createFakeWidget(_parent); + } } } - } - - void shutdown() - { - // óäàëÿåì âñå êëàññû - for (VectorBasePtr::reverse_iterator iter = mListBase.rbegin(); iter != mListBase.rend(); ++iter) - delete (*iter); - mListBase.clear(); - - // óäàëÿåì âñå ðóòîâûå âèäæåòû - MyGUI::LayoutManager::getInstance().unloadLayout(mListWindowRoot); - mListWindowRoot.clear(); - } - - template - void initialiseByAttributes(Type* _owner, MyGUI::Widget* _parent = nullptr, bool _throw = true, bool _createFakeWidgets = true) - { - initialise(attribute::AttributeLayout::getData(), _parent, _throw, _createFakeWidgets); - typename attribute::AttributeFieldWidgetName::VectorBindPair& data = attribute::AttributeFieldWidgetName::getData(); - for (typename attribute::AttributeFieldWidgetName::VectorBindPair::iterator item = data.begin(); item != data.end(); ++item) + void shutdown() { - MyGUI::Widget* value = 0; - assignWidget(value, item->second, _throw, _createFakeWidgets); - - item->first->set(_owner, value); + // ������� ��� ������ + for (VectorBasePtr::reverse_iterator iter = mListBase.rbegin(); iter != mListBase.rend(); ++iter) + delete (*iter); + mListBase.clear(); + + // ������� ��� ������� ������� + MyGUI::LayoutManager::getInstance().unloadLayout(mListWindowRoot); + mListWindowRoot.clear(); } - } -private: - void snapToParent(MyGUI::Widget* _child) - { - if (_child->isUserString("SnapTo")) + template + void initialiseByAttributes(Type *_owner, MyGUI::Widget *_parent = nullptr, bool _throw = true, + bool _createFakeWidgets = true) { - MyGUI::Align align = MyGUI::Align::parse(_child->getUserString("SnapTo")); - - MyGUI::IntCoord coord = _child->getCoord(); - MyGUI::IntSize size = _child->getParentSize(); + initialise(attribute::AttributeLayout::getData(), _parent, _throw, _createFakeWidgets); - if (align.isHStretch()) - { - coord.left = 0; - coord.width = size.width; - } - else if (align.isLeft()) + typename attribute::AttributeFieldWidgetName::VectorBindPair &data = + attribute::AttributeFieldWidgetName::getData(); + for (typename attribute::AttributeFieldWidgetName::VectorBindPair::iterator item = data.begin(); + item != data.end(); ++item) { - coord.left = 0; - } - else if (align.isRight()) - { - coord.left = size.width - coord.width; - } - else - { - coord.left = (size.width - coord.width) / 2; - } + MyGUI::Widget *value = 0; + assignWidget(value, item->second, _throw, _createFakeWidgets); - if (align.isVStretch()) - { - coord.top = 0; - coord.height = size.height; - } - else if (align.isTop()) - { - coord.top = 0; - } - else if (align.isBottom()) - { - coord.top = size.height - coord.height; + item->first->set(_owner, value); } - else + } + + private: + void snapToParent(MyGUI::Widget *_child) + { + if (_child->isUserString("SnapTo")) { - coord.top = (size.height - coord.height) / 2; + MyGUI::Align align = MyGUI::Align::parse(_child->getUserString("SnapTo")); + + MyGUI::IntCoord coord = _child->getCoord(); + MyGUI::IntSize size = _child->getParentSize(); + + if (align.isHStretch()) + { + coord.left = 0; + coord.width = size.width; + } + else if (align.isLeft()) + { + coord.left = 0; + } + else if (align.isRight()) + { + coord.left = size.width - coord.width; + } + else + { + coord.left = (size.width - coord.width) / 2; + } + + if (align.isVStretch()) + { + coord.top = 0; + coord.height = size.height; + } + else if (align.isTop()) + { + coord.top = 0; + } + else if (align.isBottom()) + { + coord.top = size.height - coord.height; + } + else + { + coord.top = (size.height - coord.height) / 2; + } + + _child->setCoord(coord); } + } - _child->setCoord(coord); + template T *_createFakeWidget(MyGUI::Widget *_parent) + { + if (_parent) + return _parent->createWidget(MyGUI::SkinManager::getInstance().getDefaultSkin(), MyGUI::IntCoord(), + MyGUI::Align::Default); + + return MyGUI::Gui::getInstance().createWidget(MyGUI::SkinManager::getInstance().getDefaultSkin(), + MyGUI::IntCoord(), MyGUI::Align::Default, ""); } - } - template - T* _createFakeWidget(MyGUI::Widget* _parent) - { - if (_parent) - return _parent->createWidget(MyGUI::SkinManager::getInstance().getDefaultSkin(), MyGUI::IntCoord(), MyGUI::Align::Default); + public: + virtual ~BaseLayout() + { + shutdown(); + } - return MyGUI::Gui::getInstance().createWidget(MyGUI::SkinManager::getInstance().getDefaultSkin(), MyGUI::IntCoord(), MyGUI::Align::Default, ""); - } + public: + MyGUI::Widget *mMainWidget; -public: - virtual ~BaseLayout() - { - shutdown(); - } - -public: - MyGUI::Widget* mMainWidget; - -private: - std::string mPrefix; - std::string mLayoutName; - MyGUI::VectorWidgetPtr mListWindowRoot; - typedef std::vector VectorBasePtr; - VectorBasePtr mListBase; -}; + private: + std::string mPrefix; + std::string mLayoutName; + MyGUI::VectorWidgetPtr mListWindowRoot; + typedef std::vector VectorBasePtr; + VectorBasePtr mListBase; + }; } // namespace wraps diff --git a/source/main/gui/mygui/Dialog.cpp b/source/main/gui/mygui/Dialog.cpp index 86579756de..eaaf1bed0f 100644 --- a/source/main/gui/mygui/Dialog.cpp +++ b/source/main/gui/mygui/Dialog.cpp @@ -32,15 +32,11 @@ using namespace RoR; using namespace GUI; -Dialog::Dialog() : - wraps::BaseLayout(), - mModal(false) +Dialog::Dialog() : wraps::BaseLayout(), mModal(false) { } -Dialog::Dialog(const std::string& _layout) : - wraps::BaseLayout(_layout), - mModal(false) +Dialog::Dialog(const std::string &_layout) : wraps::BaseLayout(_layout), mModal(false) { } @@ -72,4 +68,3 @@ void Dialog::endModal() onEndModal(); } - diff --git a/source/main/gui/mygui/Dialog.h b/source/main/gui/mygui/Dialog.h index 3719d90120..075cb35e9b 100644 --- a/source/main/gui/mygui/Dialog.h +++ b/source/main/gui/mygui/Dialog.h @@ -29,45 +29,47 @@ #pragma once -#include #include "BaseLayout.h" -namespace RoR { -namespace GUI { +#include -class Dialog : - public wraps::BaseLayout +namespace RoR { -public: - typedef MyGUI::delegates::CDelegate2 EventHandle_Result; + namespace GUI + { -public: - Dialog(); - Dialog(const std::string& _layout); - virtual ~Dialog(); + class Dialog : public wraps::BaseLayout + { + public: + typedef MyGUI::delegates::CDelegate2 EventHandle_Result; - void doModal(); - void endModal(); + public: + Dialog(); + Dialog(const std::string &_layout); + virtual ~Dialog(); - bool isModal() - { - return mModal; - } + void doModal(); + void endModal(); - EventHandle_Result eventEndDialog; + bool isModal() + { + return mModal; + } -protected: - virtual void onDoModal() - { - } + EventHandle_Result eventEndDialog; - virtual void onEndModal() - { - } + protected: + virtual void onDoModal() + { + } + + virtual void onEndModal() + { + } -private: - bool mModal; -}; + private: + bool mModal; + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/mygui/GuiPanelBase.h b/source/main/gui/mygui/GuiPanelBase.h index b3a5234e32..cfefa40f89 100644 --- a/source/main/gui/mygui/GuiPanelBase.h +++ b/source/main/gui/mygui/GuiPanelBase.h @@ -32,59 +32,79 @@ namespace RoR { -class GuiPanelBase -{ - friend class RoR::GUIManager; + class GuiPanelBase + { + friend class RoR::GUIManager; -public: - GuiPanelBase(MyGUI::Window* main_widget): - m_panel_widget(main_widget), - m_is_temporarily_hidden(false) - {} + public: + GuiPanelBase(MyGUI::Window *main_widget) : m_panel_widget(main_widget), m_is_temporarily_hidden(false) + { + } - inline void Show() - { - m_panel_widget->setVisible(true); - m_is_temporarily_hidden = false; - } - - inline void HideTemporarily() - { - if (m_panel_widget->getVisible()) + inline void Show() { - m_panel_widget->setVisible(false); - m_is_temporarily_hidden = true; + m_panel_widget->setVisible(true); + m_is_temporarily_hidden = false; } - } - - inline void ShowIfHiddenTemporarily() - { - if (m_is_temporarily_hidden) - { - Show(); - } - } - - inline void Hide() { m_panel_widget->setVisible(false); } - inline bool IsVisible() const { return m_panel_widget->getVisible(); } - inline int GetWidthPixels() const { return GetSizePixels().width; } - inline int GetHeightPixels() const { return GetSizePixels().height; } - - inline void SetPosition(int x_pixels, int y_pixels) { m_panel_widget->setPosition(x_pixels, y_pixels); } - inline void SetWidth(int width_pixels) { m_panel_widget->setSize(width_pixels, GetHeightPixels()); } - inline void SetHeight(int height_pixels) { m_panel_widget->setSize(GetWidthPixels(), height_pixels); } - - inline MyGUI::IntSize GetSizePixels() const { return m_panel_widget->getSize(); } - - inline void CenterToScreen() - { - MyGUI::IntSize parentSize = m_panel_widget->getParentSize(); - SetPosition((parentSize.width - GetWidthPixels()) / 2, (parentSize.height - GetHeightPixels()) / 2); - } - -protected: - MyGUI::Window* m_panel_widget; - bool m_is_temporarily_hidden; -}; + + inline void HideTemporarily() + { + if (m_panel_widget->getVisible()) + { + m_panel_widget->setVisible(false); + m_is_temporarily_hidden = true; + } + } + + inline void ShowIfHiddenTemporarily() + { + if (m_is_temporarily_hidden) { Show(); } + } + + inline void Hide() + { + m_panel_widget->setVisible(false); + } + inline bool IsVisible() const + { + return m_panel_widget->getVisible(); + } + inline int GetWidthPixels() const + { + return GetSizePixels().width; + } + inline int GetHeightPixels() const + { + return GetSizePixels().height; + } + + inline void SetPosition(int x_pixels, int y_pixels) + { + m_panel_widget->setPosition(x_pixels, y_pixels); + } + inline void SetWidth(int width_pixels) + { + m_panel_widget->setSize(width_pixels, GetHeightPixels()); + } + inline void SetHeight(int height_pixels) + { + m_panel_widget->setSize(GetWidthPixels(), height_pixels); + } + + inline MyGUI::IntSize GetSizePixels() const + { + return m_panel_widget->getSize(); + } + + inline void CenterToScreen() + { + MyGUI::IntSize parentSize = m_panel_widget->getParentSize(); + SetPosition((parentSize.width - GetWidthPixels()) / 2, (parentSize.height - GetHeightPixels()) / 2); + } + + protected: + MyGUI::Window *m_panel_widget; + bool m_is_temporarily_hidden; + }; } // namespace RoR diff --git a/source/main/gui/mygui/WrapsAttribute.h b/source/main/gui/mygui/WrapsAttribute.h index 1b339f195a..bc9d50b386 100644 --- a/source/main/gui/mygui/WrapsAttribute.h +++ b/source/main/gui/mygui/WrapsAttribute.h @@ -23,44 +23,36 @@ /// @date 10/2009 /// @module - #pragma once +#include "Attribute.h" #include "RoRPrerequisites.h" + #include -#include "Attribute.h" namespace attribute { -struct FieldSetterWidget -{ - typedef MyGUI::Widget BaseValueType; - - template - static Type* convert(BaseValueType* _value) + struct FieldSetterWidget { - return _value == 0 ? 0 : _value->castType(false); - } -}; - -DECLARE_ATTRIBUTE_FIELD(AttributeFieldWidgetName, std::string, FieldSetterWidget); - -#define ATTRIBUTE_FIELD_WIDGET_NAME(_class, _field, _value) \ - ATTRIBUTE_FIELD(AttributeFieldWidgetName, _class, _field, _value) - + typedef MyGUI::Widget BaseValueType; + template static Type *convert(BaseValueType *_value) + { + return _value == 0 ? 0 : _value->castType(false); + } + }; -DECLARE_ATTRIBUTE_CLASS(AttributeSize, MyGUI::IntSize); + DECLARE_ATTRIBUTE_FIELD(AttributeFieldWidgetName, std::string, FieldSetterWidget); -#define ATTRIBUTE_CLASS_SIZE(_class, _value) \ - ATTRIBUTE_CLASS(AttributeSize, _class, _value) +#define ATTRIBUTE_FIELD_WIDGET_NAME(_class, _field, _value) ATTRIBUTE_FIELD(AttributeFieldWidgetName, _class, _field, _value) + DECLARE_ATTRIBUTE_CLASS(AttributeSize, MyGUI::IntSize); -DECLARE_ATTRIBUTE_CLASS(AttributeLayout, std::string); +#define ATTRIBUTE_CLASS_SIZE(_class, _value) ATTRIBUTE_CLASS(AttributeSize, _class, _value) -#define ATTRIBUTE_CLASS_LAYOUT(_class, _value) \ - ATTRIBUTE_CLASS(AttributeLayout, _class, _value) + DECLARE_ATTRIBUTE_CLASS(AttributeLayout, std::string); -} +#define ATTRIBUTE_CLASS_LAYOUT(_class, _value) ATTRIBUTE_CLASS(AttributeLayout, _class, _value) +} // namespace attribute diff --git a/source/main/gui/panels/GUI_DebugOptions.cpp b/source/main/gui/panels/GUI_DebugOptions.cpp index 3159379ac9..b291741210 100644 --- a/source/main/gui/panels/GUI_DebugOptions.cpp +++ b/source/main/gui/panels/GUI_DebugOptions.cpp @@ -33,30 +33,31 @@ #include "GUI_DebugOptions.h" #include "Application.h" +#include "Language.h" +#include "MainMenu.h" //Get MainMenu pointer #include "RoRPrerequisites.h" -#include "Utils.h" #include "RoRVersion.h" #include "RoRnet.h" -#include "Language.h" -#include "MainMenu.h" //Get MainMenu pointer +#include "Utils.h" #include using namespace RoR; using namespace GUI; -#define CLASS DebugOptions -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) +#define CLASS DebugOptions +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) CLASS::CLASS() { MyGUI::WindowPtr win = dynamic_cast(mMainWidget); - win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::notifyWindowButtonPressed); //The "X" button thing + win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::notifyWindowButtonPressed); // The "X" button thing MyGUI::IntSize gui_area = MyGUI::RenderManager::getInstance().getViewSize(); - mMainWidget->setPosition(gui_area.width / 2 - mMainWidget->getWidth() / 2, gui_area.height / 2 - mMainWidget->getHeight() / 2); + mMainWidget->setPosition(gui_area.width / 2 - mMainWidget->getWidth() / 2, + gui_area.height / 2 - mMainWidget->getHeight() / 2); - //checkboxes + // checkboxes m_debug_truck_mass->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::OnDebugActorMassCheck); m_debug_collision_meshes->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::OnDebugColiMeshesCheck); m_ingame_console->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::OnIngameConsoleCheck); @@ -69,7 +70,7 @@ CLASS::CLASS() m_adv_logging->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::OnAdvLoggingCheck); m_disable_crash_reporting->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::OnCrashReportCheck); - //buttons + // buttons m_Save_btn->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::eventMouseButtonClickSaveButton); Hide(); @@ -82,7 +83,6 @@ CLASS::~CLASS() void CLASS::Show() { MAIN_WIDGET->setVisibleSmooth(true); - } void CLASS::Hide() @@ -92,73 +92,59 @@ void CLASS::Hide() void CLASS::UpdateControls() { - } -void CLASS::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name) +void CLASS::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name) { - if (_name == "close") - Hide(); + if (_name == "close") Hide(); } void CLASS::OnDebugActorMassCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnDebugColiMeshesCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnIngameConsoleCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnDebugEnvMapCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnDebugVideoCameraCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnDebugTriggerCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnDebugDOFCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnBeamBreakCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnBeamDeformCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnAdvLoggingCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::OnCrashReportCheck(MyGUI::WidgetPtr _sender) { - } void CLASS::SaveConfig() { - } void CLASS::SetVisible(bool v) diff --git a/source/main/gui/panels/GUI_DebugOptions.h b/source/main/gui/panels/GUI_DebugOptions.h index f3e2b0a095..c623bbc2b7 100644 --- a/source/main/gui/panels/GUI_DebugOptions.h +++ b/source/main/gui/panels/GUI_DebugOptions.h @@ -28,45 +28,47 @@ #include "ForwardDeclarations.h" #include "GUI_DebugOptionsLayout.h" -namespace RoR { - -namespace GUI { - -class DebugOptions: public DebugOptionsLayout +namespace RoR { -public: - DebugOptions(); - ~DebugOptions(); - - void Show(); - void Hide(); - bool IsVisible(); - void SetVisible(bool v); - -private: - void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name); - void UpdateControls(); - void SaveConfig(); - - //checkboxes - void OnDebugActorMassCheck(MyGUI::WidgetPtr _sender); - void OnDebugColiMeshesCheck(MyGUI::WidgetPtr _sender); - void OnIngameConsoleCheck(MyGUI::WidgetPtr _sender); - void OnDebugEnvMapCheck(MyGUI::WidgetPtr _sender); - void OnDebugVideoCameraCheck(MyGUI::WidgetPtr _sender); - void OnDebugTriggerCheck(MyGUI::WidgetPtr _sender); - void OnDebugDOFCheck(MyGUI::WidgetPtr _sender); - void OnBeamBreakCheck(MyGUI::WidgetPtr _sender); - void OnBeamDeformCheck(MyGUI::WidgetPtr _sender); - void OnAdvLoggingCheck(MyGUI::WidgetPtr _sender); - void OnCrashReportCheck(MyGUI::WidgetPtr _sender); - - //buttons - void eventMouseButtonClickSaveButton(MyGUI::WidgetPtr _sender); - - std::map DebugOptionsMap; -}; - -} // namespace GUI + + namespace GUI + { + + class DebugOptions : public DebugOptionsLayout + { + public: + DebugOptions(); + ~DebugOptions(); + + void Show(); + void Hide(); + bool IsVisible(); + void SetVisible(bool v); + + private: + void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name); + void UpdateControls(); + void SaveConfig(); + + // checkboxes + void OnDebugActorMassCheck(MyGUI::WidgetPtr _sender); + void OnDebugColiMeshesCheck(MyGUI::WidgetPtr _sender); + void OnIngameConsoleCheck(MyGUI::WidgetPtr _sender); + void OnDebugEnvMapCheck(MyGUI::WidgetPtr _sender); + void OnDebugVideoCameraCheck(MyGUI::WidgetPtr _sender); + void OnDebugTriggerCheck(MyGUI::WidgetPtr _sender); + void OnDebugDOFCheck(MyGUI::WidgetPtr _sender); + void OnBeamBreakCheck(MyGUI::WidgetPtr _sender); + void OnBeamDeformCheck(MyGUI::WidgetPtr _sender); + void OnAdvLoggingCheck(MyGUI::WidgetPtr _sender); + void OnCrashReportCheck(MyGUI::WidgetPtr _sender); + + // buttons + void eventMouseButtonClickSaveButton(MyGUI::WidgetPtr _sender); + + std::map DebugOptionsMap; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_DebugOptionsLayout.cpp b/source/main/gui/panels/GUI_DebugOptionsLayout.cpp index 437006fa11..69a3a7b40a 100644 --- a/source/main/gui/panels/GUI_DebugOptionsLayout.cpp +++ b/source/main/gui/panels/GUI_DebugOptionsLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -DebugOptionsLayout::DebugOptionsLayout(MyGUI::Widget* _parent) +DebugOptionsLayout::DebugOptionsLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_DebugOptionsLayout.h b/source/main/gui/panels/GUI_DebugOptionsLayout.h index 992f0c467f..202051e171 100644 --- a/source/main/gui/panels/GUI_DebugOptionsLayout.h +++ b/source/main/gui/panels/GUI_DebugOptionsLayout.h @@ -8,72 +8,71 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(DebugOptionsLayout, "DebugOptions.layout"); -class DebugOptionsLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(DebugOptionsLayout, "DebugOptions.layout"); + class DebugOptionsLayout : public wraps::BaseLayout + { - DebugOptionsLayout(MyGUI::Widget* _parent = nullptr); - virtual ~DebugOptionsLayout(); + public: + DebugOptionsLayout(MyGUI::Widget *_parent = nullptr); + virtual ~DebugOptionsLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_ingame_console, "ingame_console"); + MyGUI::Button *m_ingame_console; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_ingame_console, "ingame_console"); - MyGUI::Button* m_ingame_console; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_truck_mass, "debug_truck_mass"); + MyGUI::Button *m_debug_truck_mass; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_truck_mass, "debug_truck_mass"); - MyGUI::Button* m_debug_truck_mass; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_adv_logging, "adv_logging"); + MyGUI::Button *m_adv_logging; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_adv_logging, "adv_logging"); - MyGUI::Button* m_adv_logging; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_beam_break_debug, "beam_break_debug"); + MyGUI::Button *m_beam_break_debug; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_beam_break_debug, "beam_break_debug"); - MyGUI::Button* m_beam_break_debug; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_collision_meshes, "debug_collision_meshes"); + MyGUI::Button *m_debug_collision_meshes; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_collision_meshes, "debug_collision_meshes"); - MyGUI::Button* m_debug_collision_meshes; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_videocameras, "debug_videocameras"); + MyGUI::Button *m_debug_videocameras; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_videocameras, "debug_videocameras"); - MyGUI::Button* m_debug_videocameras; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_beam_deform_debug, "beam_deform_debug"); + MyGUI::Button *m_beam_deform_debug; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_beam_deform_debug, "beam_deform_debug"); - MyGUI::Button* m_beam_deform_debug; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_envmap, "debug_envmap"); + MyGUI::Button *m_debug_envmap; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_envmap, "debug_envmap"); - MyGUI::Button* m_debug_envmap; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_trigger_debug, "trigger_debug"); + MyGUI::Button *m_trigger_debug; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_trigger_debug, "trigger_debug"); - MyGUI::Button* m_trigger_debug; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_dof, "debug_dof"); + MyGUI::Button *m_debug_dof; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_debug_dof, "debug_dof"); - MyGUI::Button* m_debug_dof; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_disable_crash_reporting, "disable_crash_reporting"); + MyGUI::Button *m_disable_crash_reporting; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_disable_crash_reporting, "disable_crash_reporting"); - MyGUI::Button* m_disable_crash_reporting; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_input_grabing, "input_grabing"); + MyGUI::ComboBox *m_input_grabing; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_input_grabing, "input_grabing"); - MyGUI::ComboBox* m_input_grabing; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_preselected_map, "preselected_map"); + MyGUI::EditBox *m_preselected_map; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_preselected_map, "preselected_map"); - MyGUI::EditBox* m_preselected_map; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_preselected_truck, "preselected_truck"); + MyGUI::EditBox *m_preselected_truck; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_preselected_truck, "preselected_truck"); - MyGUI::EditBox* m_preselected_truck; + ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_Save_btn, "Save_btn"); + MyGUI::Button *m_Save_btn; - ATTRIBUTE_FIELD_WIDGET_NAME(DebugOptionsLayout, m_Save_btn, "Save_btn"); - MyGUI::Button* m_Save_btn; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_FrictionSettings.cpp b/source/main/gui/panels/GUI_FrictionSettings.cpp index ff1928f99b..56e79e3c0d 100644 --- a/source/main/gui/panels/GUI_FrictionSettings.cpp +++ b/source/main/gui/panels/GUI_FrictionSettings.cpp @@ -22,7 +22,6 @@ /// @author Thomas Fischer (thomas{AT}thomasfischer{DOT}biz) /// @date 7th of September 2009 - #include "GUI_FrictionSettings.h" #include "Application.h" @@ -32,859 +31,875 @@ #include "Language.h" #include "Utils.h" -namespace RoR { -namespace GUI { - -using namespace Ogre; - -FrictionSettings::FrictionSettings() : - col(0) - , active_gm(0) - , selected_gm(0) - , win(0) +namespace RoR { - int x = 0, y = 0, by = 0; - MyGUI::EditPtr e; - MyGUI::ScrollBar* h; - MyGUI::ButtonPtr b; - MyGUI::TextBox* t; - - msgwin = MyGUI::Gui::getInstance().createWidget("WindowCSX", 0, 0, 400, 300, MyGUI::Align::Center, "Overlapped"); - msgwin->setCaption(_L("Friction Help")); - msgwin->eventWindowButtonPressed += MyGUI::newDelegate(this, &FrictionSettings::notifyHelpWindowButtonPressed); - e = msgwin->createWidget("EditBoxStretch", 0, 0, 400, 300, MyGUI::Align::Default, "helptext"); - e->setCaption(""); - e->setEditWordWrap(true); - e->setEditStatic(true); - msgwin->setVisible(false); - - win = MyGUI::Gui::getInstance().createWidget("WindowCSX", 0, 0, 400, 500, MyGUI::Align::Center, "Overlapped"); - win->setCaption(_L("Friction Settings")); - - // active ground - x = 10 , y = 10; - t = win->createWidget("TextBox", x, y, 270, 20, MyGUI::Align::Default, "text_current_ground"); - x += 275; - t->setCaption("Current active Ground: n/a"); - t->setFontHeight(18); - b = win->createWidget("Button", x, y, 70, 20, MyGUI::Align::Default, "select_current_ground"); - x += 75; - b->setCaption("select"); - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - - // combo box - x = 20; - y += 20; - t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); - x += 175; - t->setCaption(_L("selected Ground Type:")); - t->setTextAlign(MyGUI::Align::Right); - - MyGUI::ComboBoxPtr cb = win->createWidget("ComboBox", x, y, 115, 20, MyGUI::Align::Default, "combo_grounds"); - cb->eventComboAccept += MyGUI::newDelegate(this, &FrictionSettings::event_combo_grounds_eventComboAccept); - cb->eventComboChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_combo_grounds_eventComboAccept); - cb->setEditStatic(true); - // ground models are not loaded here yet, so we will add them once we show the dialog - - x = 10; - y += 30; - t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); - x += 175; - t->setCaption(_L("Solid ground settings")); - - // adding panel for solid ground - x = 10; - by = y + 20; // set box start now - MyGUI::WidgetPtr p = win->createWidget("PanelSkin", x, by, 370, 25, MyGUI::Align::Default); + namespace GUI { - // solid_level - int lx = 0, ly = 5; // local coordinate system - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Solid ground level:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_level"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_level_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_level_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_level"] = std::pair(_L("Solid ground level"), _L("With this you can define how deep the solid ground is. If it is 0 then the surface will be solid. If it is 0.1 then you'll have 10 cm of fluid on top of solid ground. If it is 100 then the solid ground will be way deep (100m), with fluid on top.")); - minMaxs["solid_level"] = std::pair(0, 200); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_level_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_strength - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Strength:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_strength"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_strength_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_strength_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_strength"] = std::pair(_L("Strength"), _L("This parameter raises or diminishes surface friction in a generic way. It is here so as to be able to do quick calibrations of friction. Start with having this to 1.0 and after tuning the rest of the surface variables, come back and play with this.")); - minMaxs["solid_strength"] = std::pair(0, 2); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_strength_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_static_friction - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Static friction coef:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_static_friction"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_static_friction_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_static_friction_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_static_friction"] = std::pair(_L("Static friction coef"), _L("Static friction keeps you in the same place when you are stopped on a hill. In the real world this friction is always bigger than dynamic friction (sliding friction). Start with 0.5 and work from there. It is better to try to find some experimentally validated values for this and the rest of surface friction variables in the net, and then to fine tune via strength.")); - minMaxs["solid_static_friction"] = std::pair(0.1f, 2); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_static_friction_help"); - lx += 20; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_adhension_velo - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Adhesion velocity:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_adhension_velo"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_adhension_velo_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_adhension_velo_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_adhension_velo"] = std::pair(_L("Adhesion velocity"), _L("Below this value static friction laws apply, above it dynamic friction laws apply. Value should be small, in the range of 0.1-0.4 . This velocity threshold is also used by fluid dynamics so you should always define it. NEVER set it to 0.")); - minMaxs["solid_adhension_velo"] = std::pair(0.1f, 0.5f); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_adhension_velo_help"); - lx += 20; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_dynamic_friction - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Dynamic friction coef:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_dynamic_friction"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_dynamic_friction_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_dynamic_friction_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_dynamic_friction"] = std::pair(_L("Dynamic friction coef"), _L("Or sliding friction coef. It should be smaller than static friction coef. This parameter defines how much friction you'll have when sliding. Try to find some values for it from the net.")); - minMaxs["solid_dynamic_friction"] = std::pair(0.1f, 1.5f); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_dynamic_friction_help"); - lx += 20; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_hydrodynamic - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Hydrodynamic friction coef:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_hydrodynamic"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_hydrodynamic_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_hydrodynamic_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_hydrodynamic"] = std::pair(_L("Hydrodynamic friction coef"), _L("This friction defines the added friction that you'll feel from a surface that has a little film of fluid on it. It is kind of redundant with all the fluid physics below, but it is here so as for experimentally validated values from the net to be usable. If you decide that you'll simulate the film of fluid with the more complex fluid physics below, then just set this to 0.")); - minMaxs["solid_hydrodynamic"] = std::pair(0, 1.5f); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_hydrodynamic_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_stribeck - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Stribeck velocity:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_stribeck"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_stribeck_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_stribeck_scroll"); - lx += 65; - helpTexts["solid_stribeck"] = std::pair(_L("Stribeck velocity"), _L("You'll either find stribeck velocity in the net, or the inverse (1/stribeck velocity) of it described as 'stribeck coef'. It defines the shape of the dynamic friction curve. Lets leave it at that. Just find some nice values for it from the net.")); - minMaxs["solid_stribeck"] = std::pair(0, 1000); - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_stribeck_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // solid_alpha - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("alpha:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_alpha"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_alpha_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_alpha_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["solid_alpha"] = std::pair(_L("Alpha"), _L("Its usual value is 2. But you can try others.")); - minMaxs["solid_alpha"] = std::pair(0, 200); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_alpha_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // combo_fx_type - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("fx_type:")); - t->setTextAlign(MyGUI::Align::Right); - cb = p->createWidget("ComboBox", lx, ly, 115, 20, MyGUI::Align::Default, "combo_fx_type"); - lx += 120; - cb->addItem("dusty"); - cb->addItem("hard"); - cb->addItem("clumpy"); - cb->setEditStatic(true); - cb->setIndexSelected(0); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "combo_fx_type_edited"); - lx += 20; - helpTexts["combo_fx"] = std::pair(_L("FX Type"), _L("The type of special effects that RoR will use to give the appearance of a surface. It doesn't affect the physics at all")); - minMaxs["combo_fx"] = std::pair(0, 0); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "combo_fx_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // fx_color - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("fx_color:")); - t->setTextAlign(MyGUI::Align::Right); - t = p->createWidget("TextBox", lx, ly, 140, 20, MyGUI::Align::Default, "fx_color_text"); - lx += 145; - t->setCaption(""); - t->setTextAlign(MyGUI::Align::Left); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fx_color_text_edited"); - lx += 20; - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fx_color_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - helpTexts["fx_color"] = std::pair(_L("FX Colour"), _L("The color of RoR's special effects")); - minMaxs["fx_color"] = std::pair(0, 0); - // TO BE DONE - - lx = 0; - ly += 20; - // add height to global height - y += ly; - } - p->setSize(370, y - by + 25); - - x = 10; - y += 40; - t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); - x += 175; - t->setCaption(_L("Fluid Settings")); - - // adding panel for solid ground - x = 10; - by = y + 20; // set box start now - p = win->createWidget("PanelSkin", x, by, 370, 25, MyGUI::Align::Default); - { - int lx = 0, ly = 5; // local coordinate system - - // fluid_flowbeh - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Flow behavior index:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_flowbeh"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowbeh_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "fluid_flowbeh_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["fluid_flowbeh"] = std::pair(_L("Flow behavior index"), _L("If it is 1.0 then the fluid will behave like water. The lower you get from 1.0, the more like mud the fluid will behave, meaning that for small velocities the fluid will resist motion and for large velocities the fluid will not resist so much. The higher you get from 1.0 the more like sand the fluid will behave. The bigger the velocity, the bigger the resistance of the fluid (try to hit sand hard it'll feel like stone).")); - minMaxs["fluid_flowbeh"] = std::pair(-2, 2); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowbeh_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // fluid_flowcon - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Flow consistency:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_flowcon"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowcon_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "fluid_flowcon_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["fluid_flowcon"] = std::pair(_L("Flow consistency"), _L("Think of it as default fluid resistance. Behavior index above changes it at real time. Useful values in practice are quite large.")); - minMaxs["fluid_flowcon"] = std::pair(10, 100000); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowcon_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // fluid_density - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Fluid density:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_density"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_density_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "fluid_density_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["fluid_density"] = std::pair(_L("Fluid density"), _L("In mud (or sand) the resistance of the fluid described by the parameters above will stop you and so keep you from sinking. But for substances like water it isn't the drag that stops you from sinking. Its buoyancy. This parameter is here so as to keep you from sinking when you wish to simulate fluids with low drag (resistance). For fluids like mud or sand you can put it at 0, but it is best to keep it at some minimum value. For fluids with behavior index >=1 it will behave like you are in water. For fluids with behavior index <1 it'll behave like you are in mud.")); - minMaxs["fluid_density"] = std::pair(10, 100000); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_density_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - // fluid_drag_anisotropy - lx = 0; - ly += 20; - t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); - lx += 175; - t->setCaption(_L("Drag anisotropy:")); - t->setTextAlign(MyGUI::Align::Right); - e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_drag_anisotropy"); - lx += 85; - e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); - t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_drag_anisotropy_edited"); - lx += 20; - h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "fluid_drag_anisotropy_scroll"); - lx += 65; - h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); - h->setScrollRange(1000); - helpTexts["fluid_drag_anisotropy"] = std::pair(_L("Drag anisotropy"), _L("This parameter is for making it easier(cheating) to get out from mud. To get stuck in real mud isn't fun at all, so this makes the mud push up. Ranges in this parameter are from 0 to 1 . If you set it at 1 then you'll get real mud. For values from 0 to 1, the behavior goes from real mud to easy mud depending on this parameter and the value of Adhesion velocity. For velocity 0 real mud it is. For velocity >= adhesion velocity easy mud it is.")); - minMaxs["fluid_drag_anisotropy"] = std::pair(0, 1); - b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_drag_anisotropy_help"); - lx += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption("?"); - - lx = 0; - ly += 20; - // add height to global height - y += ly; - } - p->setSize(370, y - by + 25); - - x = 10; - y += 40; - b = win->createWidget("Button", x, y, 350, 30, MyGUI::Align::Default, "apply_changes"); - x += 25; - b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); - b->setCaption(_L("Apply Changes")); - - /* - x=10; y+=20; - t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); x+=175; - t->setCaption(_L("Ground Debug")); - */ - - win->eventWindowButtonPressed += MyGUI::newDelegate(this, &FrictionSettings::notifyWindowButtonPressed); - win->setVisible(false); -} - -FrictionSettings::~FrictionSettings() -{ -} -void FrictionSettings::setShaded(bool value) -{ - if (!win || !win->getVisible()) - return; - if (value) - { - MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerFadeAlpha::getClassTypeName()); - MyGUI::ControllerFadeAlpha* controller = item->castType(); - controller->setAlpha(0.9f); - controller->setCoef(3.0f); - controller->setEnabled(true); - MyGUI::ControllerManager::getInstance().addItem(win, controller); - } - else - { - MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerFadeAlpha::getClassTypeName()); - MyGUI::ControllerFadeAlpha* controller = item->castType(); - controller->setAlpha(0.2f); - controller->setCoef(3.0f); - controller->setEnabled(true); - MyGUI::ControllerManager::getInstance().addItem(win, controller); - } -} - -void FrictionSettings::SetVisible(bool value) -{ - if (!col) - return; - if (value) - { - // upon show, refresh list - MyGUI::ComboBoxPtr cb = (MyGUI::ComboBoxPtr)win->findWidget("combo_grounds"); - cb->removeAllItems(); + using namespace Ogre; - std::map::iterator it; - std::map* gmm = col->getGroundModels(); - for (it = gmm->begin(); it != gmm->end(); it++) + FrictionSettings::FrictionSettings() : col(0), active_gm(0), selected_gm(0), win(0) { - cb->addItem((*it).second.name); + int x = 0, y = 0, by = 0; + MyGUI::EditPtr e; + MyGUI::ScrollBar *h; + MyGUI::ButtonPtr b; + MyGUI::TextBox * t; + + msgwin = MyGUI::Gui::getInstance().createWidget("WindowCSX", 0, 0, 400, 300, MyGUI::Align::Center, + "Overlapped"); + msgwin->setCaption(_L("Friction Help")); + msgwin->eventWindowButtonPressed += MyGUI::newDelegate(this, &FrictionSettings::notifyHelpWindowButtonPressed); + e = msgwin->createWidget("EditBoxStretch", 0, 0, 400, 300, MyGUI::Align::Default, "helptext"); + e->setCaption(""); + e->setEditWordWrap(true); + e->setEditStatic(true); + msgwin->setVisible(false); + + win = MyGUI::Gui::getInstance().createWidget("WindowCSX", 0, 0, 400, 500, MyGUI::Align::Center, + "Overlapped"); + win->setCaption(_L("Friction Settings")); + + // active ground + x = 10, y = 10; + t = win->createWidget("TextBox", x, y, 270, 20, MyGUI::Align::Default, "text_current_ground"); + x += 275; + t->setCaption("Current active Ground: n/a"); + t->setFontHeight(18); + b = win->createWidget("Button", x, y, 70, 20, MyGUI::Align::Default, "select_current_ground"); + x += 75; + b->setCaption("select"); + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + + // combo box + x = 20; + y += 20; + t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); + x += 175; + t->setCaption(_L("selected Ground Type:")); + t->setTextAlign(MyGUI::Align::Right); + + MyGUI::ComboBoxPtr cb = + win->createWidget("ComboBox", x, y, 115, 20, MyGUI::Align::Default, "combo_grounds"); + cb->eventComboAccept += MyGUI::newDelegate(this, &FrictionSettings::event_combo_grounds_eventComboAccept); + cb->eventComboChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_combo_grounds_eventComboAccept); + cb->setEditStatic(true); + // ground models are not loaded here yet, so we will add them once we show the dialog + + x = 10; + y += 30; + t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); + x += 175; + t->setCaption(_L("Solid ground settings")); + + // adding panel for solid ground + x = 10; + by = y + 20; // set box start now + MyGUI::WidgetPtr p = win->createWidget("PanelSkin", x, by, 370, 25, MyGUI::Align::Default); + { + // solid_level + int lx = 0, ly = 5; // local coordinate system + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Solid ground level:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_level"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_level_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_level_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_level"] = std::pair( + _L("Solid ground level"), + _L("With this you can define how deep the solid ground is. If it is 0 then the surface " + "will be solid. If it is 0.1 then you'll have 10 cm of fluid on top of solid ground. If " + "it is 100 then the solid ground will be way deep (100m), with fluid on top.")); + minMaxs["solid_level"] = std::pair(0, 200); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_level_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_strength + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Strength:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_strength"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_strength_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "solid_strength_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_strength"] = std::pair( + _L("Strength"), + _L("This parameter raises or diminishes surface friction in a generic way. It is here so as to be " + "able to do quick calibrations of friction. Start with having this to 1.0 and after tuning the " + "rest of the surface variables, come back and play with this.")); + minMaxs["solid_strength"] = std::pair(0, 2); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_strength_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_static_friction + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Static friction coef:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_static_friction"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, + "solid_static_friction_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "solid_static_friction_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_static_friction"] = std::pair( + _L("Static friction coef"), _L("Static friction keeps you in the same place when you are stopped on a hill. " + "In the real world this friction is " + "always bigger than dynamic friction (sliding friction). Start with 0.5 and " + "work from there. It is better to try " + "to find some experimentally validated values for this and the rest of " + "surface friction variables in the net, and " + "then to fine tune via strength.")); + minMaxs["solid_static_friction"] = std::pair(0.1f, 2); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_static_friction_help"); + lx += 20; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_adhension_velo + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Adhesion velocity:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_adhension_velo"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, + "solid_adhension_velo_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "solid_adhension_velo_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_adhension_velo"] = std::pair( + _L("Adhesion velocity"), + _L("Below this value static friction laws apply, above it dynamic friction laws apply. " + "Value should be small, in the range of 0.1-0.4 . This velocity threshold is also used " + "by fluid dynamics so you should always define it. NEVER set it to 0.")); + minMaxs["solid_adhension_velo"] = std::pair(0.1f, 0.5f); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_adhension_velo_help"); + lx += 20; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_dynamic_friction + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Dynamic friction coef:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_dynamic_friction"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, + "solid_dynamic_friction_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "solid_dynamic_friction_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_dynamic_friction"] = std::pair( + _L("Dynamic friction coef"), + _L("Or sliding friction coef. It should be smaller than static friction coef. This parameter defines how " + "much " + "friction you'll have when sliding. Try to find some values for it from the net.")); + minMaxs["solid_dynamic_friction"] = std::pair(0.1f, 1.5f); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, + "solid_dynamic_friction_help"); + lx += 20; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_hydrodynamic + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Hydrodynamic friction coef:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_hydrodynamic"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, + "solid_hydrodynamic_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "solid_hydrodynamic_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_hydrodynamic"] = std::pair( + _L("Hydrodynamic friction coef"), _L("This friction defines the added friction that you'll feel from a " + "surface that has a little film of fluid on it. " + "It is kind of redundant with all the fluid physics below, but it is " + "here so as for experimentally validated " + "values from the net to be usable. If you decide that you'll simulate " + "the film of fluid with the more complex " + "fluid physics below, then just set this to 0.")); + minMaxs["solid_hydrodynamic"] = std::pair(0, 1.5f); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_hydrodynamic_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_stribeck + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Stribeck velocity:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_stribeck"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_stribeck_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "solid_stribeck_scroll"); + lx += 65; + helpTexts["solid_stribeck"] = std::pair( + _L("Stribeck velocity"), + _L("You'll either find stribeck velocity in the net, or the inverse (1/stribeck velocity) " + "of it described as 'stribeck coef'. It defines the shape of the dynamic friction curve. " + "Lets leave it at that. Just find some nice values for it from the net.")); + minMaxs["solid_stribeck"] = std::pair(0, 1000); + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_stribeck_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // solid_alpha + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("alpha:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "solid_alpha"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "solid_alpha_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, "solid_alpha_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["solid_alpha"] = + std::pair(_L("Alpha"), _L("Its usual value is 2. But you can try others.")); + minMaxs["solid_alpha"] = std::pair(0, 200); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "solid_alpha_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // combo_fx_type + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("fx_type:")); + t->setTextAlign(MyGUI::Align::Right); + cb = p->createWidget("ComboBox", lx, ly, 115, 20, MyGUI::Align::Default, "combo_fx_type"); + lx += 120; + cb->addItem("dusty"); + cb->addItem("hard"); + cb->addItem("clumpy"); + cb->setEditStatic(true); + cb->setIndexSelected(0); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "combo_fx_type_edited"); + lx += 20; + helpTexts["combo_fx"] = std::pair( + _L("FX Type"), _L("The type of special effects that RoR will use to give the " + "appearance of a surface. It doesn't affect the physics at all")); + minMaxs["combo_fx"] = std::pair(0, 0); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "combo_fx_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // fx_color + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("fx_color:")); + t->setTextAlign(MyGUI::Align::Right); + t = p->createWidget("TextBox", lx, ly, 140, 20, MyGUI::Align::Default, "fx_color_text"); + lx += 145; + t->setCaption(""); + t->setTextAlign(MyGUI::Align::Left); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fx_color_text_edited"); + lx += 20; + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fx_color_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + helpTexts["fx_color"] = + std::pair(_L("FX Colour"), _L("The color of RoR's special effects")); + minMaxs["fx_color"] = std::pair(0, 0); + // TO BE DONE + + lx = 0; + ly += 20; + // add height to global height + y += ly; + } + p->setSize(370, y - by + 25); + + x = 10; + y += 40; + t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); + x += 175; + t->setCaption(_L("Fluid Settings")); + + // adding panel for solid ground + x = 10; + by = y + 20; // set box start now + p = win->createWidget("PanelSkin", x, by, 370, 25, MyGUI::Align::Default); + { + int lx = 0, ly = 5; // local coordinate system + + // fluid_flowbeh + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Flow behavior index:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_flowbeh"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowbeh_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "fluid_flowbeh_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["fluid_flowbeh"] = std::pair( + _L("Flow behavior index"), + _L("If it is 1.0 then the fluid will behave like water. The lower you get from 1.0, the more like mud the " + "fluid will " + "behave, meaning that for small velocities the fluid will resist motion and for large velocities the " + "fluid will " + "not resist so much. The higher you get from 1.0 the more like sand the fluid will behave. The bigger the " + "velocity, the bigger the resistance of the fluid (try to hit sand hard it'll feel like stone).")); + minMaxs["fluid_flowbeh"] = std::pair(-2, 2); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowbeh_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // fluid_flowcon + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Flow consistency:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_flowcon"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowcon_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "fluid_flowcon_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["fluid_flowcon"] = std::pair( + _L("Flow consistency"), + _L("Think of it as default fluid resistance. Behavior index above changes it at real time. " + "Useful values in practice are quite large.")); + minMaxs["fluid_flowcon"] = std::pair(10, 100000); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_flowcon_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // fluid_density + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Fluid density:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_density"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_density_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "fluid_density_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["fluid_density"] = std::pair( + _L("Fluid density"), _L("In mud (or sand) the resistance of the fluid described by the parameters above will " + "stop you and so keep you " + "from sinking. But for substances like water it isn't the drag that stops you from " + "sinking. Its buoyancy. This " + "parameter is here so as to keep you from sinking when you wish to simulate fluids " + "with low drag (resistance). " + "For fluids like mud or sand you can put it at 0, but it is best to keep it at some " + "minimum value. For fluids " + "with behavior index >=1 it will behave like you are in water. For fluids with " + "behavior index <1 it'll behave " + "like you are in mud.")); + minMaxs["fluid_density"] = std::pair(10, 100000); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_density_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + // fluid_drag_anisotropy + lx = 0; + ly += 20; + t = p->createWidget("TextBox", lx, ly, 170, 20, MyGUI::Align::Default); + lx += 175; + t->setCaption(_L("Drag anisotropy:")); + t->setTextAlign(MyGUI::Align::Right); + e = p->createWidget("EditBox", lx, ly, 80, 20, MyGUI::Align::Default, "fluid_drag_anisotropy"); + lx += 85; + e->eventEditTextChange += MyGUI::newDelegate(this, &FrictionSettings::event_edit_TextChange); + t = p->createWidget("TextBox", lx, ly, 20, 20, MyGUI::Align::Default, + "fluid_drag_anisotropy_edited"); + lx += 20; + h = p->createWidget("ScrollBarH", lx, ly, 60, 20, MyGUI::Align::Default, + "fluid_drag_anisotropy_scroll"); + lx += 65; + h->eventScrollChangePosition += MyGUI::newDelegate(this, &FrictionSettings::event_scroll_value); + h->setScrollRange(1000); + helpTexts["fluid_drag_anisotropy"] = std::pair( + _L("Drag anisotropy"), _L("This parameter is for making it easier(cheating) to get out from mud. To get " + "stuck in real mud isn't fun at all, " + "so this makes the mud push up. Ranges in this parameter are from 0 to 1 . If you " + "set it at 1 then you'll get " + "real mud. For values from 0 to 1, the behavior goes from real mud to easy mud " + "depending on this parameter and " + "the value of Adhesion velocity. For velocity 0 real mud it is. For velocity >= " + "adhesion velocity easy mud it " + "is.")); + minMaxs["fluid_drag_anisotropy"] = std::pair(0, 1); + b = p->createWidget("Button", lx, ly, 20, 20, MyGUI::Align::Default, "fluid_drag_anisotropy_help"); + lx += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption("?"); + + lx = 0; + ly += 20; + // add height to global height + y += ly; + } + p->setSize(370, y - by + 25); + + x = 10; + y += 40; + b = win->createWidget("Button", x, y, 350, 30, MyGUI::Align::Default, "apply_changes"); + x += 25; + b->eventMouseButtonClick += MyGUI::newDelegate(this, &FrictionSettings::event_btn_MouseButtonClick); + b->setCaption(_L("Apply Changes")); + + /* + x=10; y+=20; + t = win->createWidget("TextBox", x, y, 170, 20, MyGUI::Align::Default); x+=175; + t->setCaption(_L("Ground Debug")); + */ + + win->eventWindowButtonPressed += MyGUI::newDelegate(this, &FrictionSettings::notifyWindowButtonPressed); + win->setVisible(false); } - cb->setEditStatic(true); - cb->setIndexSelected(0); - ground_model_t* gm = col->getGroundModelByString(cb->getItemNameAt(0)); - selected_gm = gm; - if (gm) - updateControls(gm, false); - } - else - { - RoR::App::GetGuiManager()->UnfocusGui(); - } - win->setVisibleSmooth(value); -} -bool FrictionSettings::IsVisible() -{ - return win->getVisible(); -} + FrictionSettings::~FrictionSettings() + { + } -void FrictionSettings::setActiveCol(ground_model_t* gm) -{ - if (!gm) - return; - if (active_gm == gm) - return; //only set once - active_gm = gm; - - UTFString tmp = _L("Current active Ground: ") + ANSI_TO_UTF(gm->name); - MyGUI::TextBox* t = (MyGUI::TextBox*)win->findWidget("text_current_ground"); - if (t) - t->setCaption(convertToMyGUIString(tmp)); - if (selected_gm == gm) - updateControls(gm); -} - -void FrictionSettings::updateControls(ground_model_t* gm, bool setCombo) -{ - if (!gm) - return; + void FrictionSettings::setShaded(bool value) + { + if (!win || !win->getVisible()) return; + if (value) + { + MyGUI::ControllerItem *item = + MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerFadeAlpha::getClassTypeName()); + MyGUI::ControllerFadeAlpha *controller = item->castType(); + controller->setAlpha(0.9f); + controller->setCoef(3.0f); + controller->setEnabled(true); + MyGUI::ControllerManager::getInstance().addItem(win, controller); + } + else + { + MyGUI::ControllerItem *item = + MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerFadeAlpha::getClassTypeName()); + MyGUI::ControllerFadeAlpha *controller = item->castType(); + controller->setAlpha(0.2f); + controller->setCoef(3.0f); + controller->setEnabled(true); + MyGUI::ControllerManager::getInstance().addItem(win, controller); + } + } - if (setCombo) - { - MyGUI::ComboBoxPtr cb = (MyGUI::ComboBoxPtr)win->findWidget("combo_grounds"); - if (!cb) - return; + void FrictionSettings::SetVisible(bool value) + { + if (!col) return; + if (value) + { + // upon show, refresh list + MyGUI::ComboBoxPtr cb = (MyGUI::ComboBoxPtr)win->findWidget("combo_grounds"); + cb->removeAllItems(); + + std::map::iterator it; + std::map * gmm = col->getGroundModels(); + for (it = gmm->begin(); it != gmm->end(); it++) + { + cb->addItem((*it).second.name); + } + cb->setEditStatic(true); + cb->setIndexSelected(0); + ground_model_t *gm = col->getGroundModelByString(cb->getItemNameAt(0)); + selected_gm = gm; + if (gm) updateControls(gm, false); + } + else + { + RoR::App::GetGuiManager()->UnfocusGui(); + } + win->setVisibleSmooth(value); + } + + bool FrictionSettings::IsVisible() + { + return win->getVisible(); + } + + void FrictionSettings::setActiveCol(ground_model_t *gm) + { + if (!gm) return; + if (active_gm == gm) return; // only set once + active_gm = gm; + + UTFString tmp = _L("Current active Ground: ") + ANSI_TO_UTF(gm->name); + MyGUI::TextBox *t = (MyGUI::TextBox *)win->findWidget("text_current_ground"); + if (t) t->setCaption(convertToMyGUIString(tmp)); + if (selected_gm == gm) updateControls(gm); + } - for (int i = 0; i < (int)cb->getItemCount(); i++) + void FrictionSettings::updateControls(ground_model_t *gm, bool setCombo) { - if (cb->getItemNameAt(i) == MyGUI::UString(gm->name)) + if (!gm) return; + + if (setCombo) { - cb->setIndexSelected(i); - selected_gm = gm; - break; + MyGUI::ComboBoxPtr cb = (MyGUI::ComboBoxPtr)win->findWidget("combo_grounds"); + if (!cb) return; + + for (int i = 0; i < (int)cb->getItemCount(); i++) + { + if (cb->getItemNameAt(i) == MyGUI::UString(gm->name)) + { + cb->setIndexSelected(i); + selected_gm = gm; + break; + } + } } + + MyGUI::EditPtr e = (MyGUI::EditPtr)win->findWidget("solid_adhension_velo"); + if (e) e->setCaption(TOSTRING(gm->va)); + MyGUI::ScrollBar *h = (MyGUI::ScrollBar *)win->findWidget("solid_adhension_velo_scroll"); + MyGUI::TextBox * edt = (MyGUI::TextBox *)win->findWidget("solid_adhension_velo_edited"); + if (edt) edt->setCaption(""); + std::pair f = minMaxs["solid_adhension_velo"]; + size_t fa = ((gm->va + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_level"); + if (e) e->setCaption(TOSTRING(gm->solid_ground_level)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_adhension_velo_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_level_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_level"]; + fa = ((gm->solid_ground_level + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_static_friction"); + if (e) e->setCaption(TOSTRING(gm->ms)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_static_friction_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_static_friction_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_static_friction"]; + fa = ((gm->ms + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_dynamic_friction"); + if (e) e->setCaption(TOSTRING(gm->mc)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_dynamic_friction_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_dynamic_friction_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_dynamic_friction"]; + fa = ((gm->mc + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_hydrodynamic"); + if (e) e->setCaption(TOSTRING(gm->t2)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_hydrodynamic_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_hydrodynamic_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_hydrodynamic"]; + fa = ((gm->t2 + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_stribeck"); + if (e) e->setCaption(TOSTRING(gm->vs)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_stribeck_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_stribeck_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_stribeck"]; + fa = ((gm->vs + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_alpha"); + if (e) e->setCaption(TOSTRING(gm->alpha)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_alpha_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_alpha_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_alpha"]; + fa = ((gm->alpha + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("solid_strength"); + if (e) e->setCaption(TOSTRING(gm->strength)); + h = (MyGUI::ScrollBar *)win->findWidget("solid_strength_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("solid_strength_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["solid_strength"]; + fa = ((gm->strength + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + // fluid + e = (MyGUI::EditPtr)win->findWidget("fluid_flowbeh"); + if (e) e->setCaption(TOSTRING(gm->flow_behavior_index)); + h = (MyGUI::ScrollBar *)win->findWidget("fluid_flowbeh_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("fluid_flowbeh_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["fluid_flowbeh"]; + fa = ((gm->flow_behavior_index + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("fluid_flowcon"); + if (e) e->setCaption(TOSTRING(gm->flow_consistency_index)); + h = (MyGUI::ScrollBar *)win->findWidget("fluid_flowcon_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("fluid_flowcon_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["fluid_flowcon"]; + fa = ((gm->flow_consistency_index + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("fluid_density"); + if (e) e->setCaption(TOSTRING(gm->fluid_density)); + h = (MyGUI::ScrollBar *)win->findWidget("fluid_density_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("fluid_density_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["fluid_density"]; + fa = ((gm->fluid_density + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); + + e = (MyGUI::EditPtr)win->findWidget("fluid_drag_anisotropy"); + if (e) e->setCaption(TOSTRING(gm->drag_anisotropy)); + h = (MyGUI::ScrollBar *)win->findWidget("fluid_drag_anisotropy_scroll"); + edt = (MyGUI::TextBox *)win->findWidget("fluid_drag_anisotropy_edited"); + if (edt) edt->setCaption(""); + f = minMaxs["fluid_drag_anisotropy"]; + fa = ((gm->drag_anisotropy + f.first) / (f.second - f.first)) * h->getScrollRange(); + if (h) h->setScrollPosition(fa); } - } - - MyGUI::EditPtr e = (MyGUI::EditPtr)win->findWidget("solid_adhension_velo"); - if (e) - e->setCaption(TOSTRING(gm->va)); - MyGUI::ScrollBar* h = (MyGUI::ScrollBar *)win->findWidget("solid_adhension_velo_scroll"); - MyGUI::TextBox* edt = (MyGUI::TextBox *)win->findWidget("solid_adhension_velo_edited"); - if (edt) - edt->setCaption(""); - std::pair f = minMaxs["solid_adhension_velo"]; - size_t fa = ((gm->va + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_level"); - if (e) - e->setCaption(TOSTRING(gm->solid_ground_level)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_adhension_velo_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_level_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_level"]; - fa = ((gm->solid_ground_level + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_static_friction"); - if (e) - e->setCaption(TOSTRING(gm->ms)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_static_friction_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_static_friction_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_static_friction"]; - fa = ((gm->ms + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_dynamic_friction"); - if (e) - e->setCaption(TOSTRING(gm->mc)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_dynamic_friction_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_dynamic_friction_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_dynamic_friction"]; - fa = ((gm->mc + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_hydrodynamic"); - if (e) - e->setCaption(TOSTRING(gm->t2)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_hydrodynamic_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_hydrodynamic_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_hydrodynamic"]; - fa = ((gm->t2 + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_stribeck"); - if (e) - e->setCaption(TOSTRING(gm->vs)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_stribeck_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_stribeck_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_stribeck"]; - fa = ((gm->vs + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_alpha"); - if (e) - e->setCaption(TOSTRING(gm->alpha)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_alpha_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_alpha_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_alpha"]; - fa = ((gm->alpha + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("solid_strength"); - if (e) - e->setCaption(TOSTRING(gm->strength)); - h = (MyGUI::ScrollBar *)win->findWidget("solid_strength_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("solid_strength_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["solid_strength"]; - fa = ((gm->strength + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - // fluid - e = (MyGUI::EditPtr)win->findWidget("fluid_flowbeh"); - if (e) - e->setCaption(TOSTRING(gm->flow_behavior_index)); - h = (MyGUI::ScrollBar *)win->findWidget("fluid_flowbeh_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("fluid_flowbeh_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["fluid_flowbeh"]; - fa = ((gm->flow_behavior_index + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("fluid_flowcon"); - if (e) - e->setCaption(TOSTRING(gm->flow_consistency_index)); - h = (MyGUI::ScrollBar *)win->findWidget("fluid_flowcon_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("fluid_flowcon_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["fluid_flowcon"]; - fa = ((gm->flow_consistency_index + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("fluid_density"); - if (e) - e->setCaption(TOSTRING(gm->fluid_density)); - h = (MyGUI::ScrollBar *)win->findWidget("fluid_density_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("fluid_density_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["fluid_density"]; - fa = ((gm->fluid_density + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - - e = (MyGUI::EditPtr)win->findWidget("fluid_drag_anisotropy"); - if (e) - e->setCaption(TOSTRING(gm->drag_anisotropy)); - h = (MyGUI::ScrollBar *)win->findWidget("fluid_drag_anisotropy_scroll"); - edt = (MyGUI::TextBox *)win->findWidget("fluid_drag_anisotropy_edited"); - if (edt) - edt->setCaption(""); - f = minMaxs["fluid_drag_anisotropy"]; - fa = ((gm->drag_anisotropy + f.first) / (f.second - f.first)) * h->getScrollRange(); - if (h) - h->setScrollPosition(fa); - -} - -void FrictionSettings::event_combo_grounds_eventComboAccept(MyGUI::ComboBoxPtr _sender, size_t _index) -{ - if (!col) - return; - if (!win->getVisible()) - return; - MyGUI::ComboBoxPtr cb = (MyGUI::ComboBoxPtr)win->findWidget("combo_grounds"); - if (!cb) - return; - ground_model_t* gm = col->getGroundModelByString(cb->getItemNameAt(_index).asUTF8_c_str()); - if (gm) - updateControls(gm, false); - selected_gm = gm; -} - -void FrictionSettings::event_edit_TextChange(MyGUI::EditPtr _sender) -{ - String name = _sender->getName(); - MyGUI::TextBox* edt = (MyGUI::TextBox *)win->findWidget(name + "_edited"); - if (edt) - edt->setCaption("!!"); -} -void FrictionSettings::event_btn_MouseButtonClick(MyGUI::WidgetPtr _sender) -{ - String name = _sender->getName(); + void FrictionSettings::event_combo_grounds_eventComboAccept(MyGUI::ComboBoxPtr _sender, size_t _index) + { + if (!col) return; + if (!win->getVisible()) return; + MyGUI::ComboBoxPtr cb = (MyGUI::ComboBoxPtr)win->findWidget("combo_grounds"); + if (!cb) return; + ground_model_t *gm = col->getGroundModelByString(cb->getItemNameAt(_index).asUTF8_c_str()); + if (gm) updateControls(gm, false); + selected_gm = gm; + } - if (name.size() > 5 && name.substr(name.size() - 5, 5) == "_help") - { - String wname = name.substr(0, name.size() - 5); - std::pair hText = helpTexts[wname]; - std::pair minmax = minMaxs[wname]; + void FrictionSettings::event_edit_TextChange(MyGUI::EditPtr _sender) + { + String name = _sender->getName(); + MyGUI::TextBox *edt = (MyGUI::TextBox *)win->findWidget(name + "_edited"); + if (edt) edt->setCaption("!!"); + } - UTFString mTitle = hText.first; - UTFString mTxt = hText.second; - if (fabs(minmax.first - minmax.second) > 0.001f) + void FrictionSettings::event_btn_MouseButtonClick(MyGUI::WidgetPtr _sender) { - wchar_t param[512] = L""; - UTFString fmt = _L("\nParameter range: %f to %f"); - swprintf(param, 512, fmt.asWStr_c_str(), minmax.first, minmax.second); - mTxt = mTxt + UTFString(param); + String name = _sender->getName(); + + if (name.size() > 5 && name.substr(name.size() - 5, 5) == "_help") + { + String wname = name.substr(0, name.size() - 5); + std::pair hText = helpTexts[wname]; + std::pair minmax = minMaxs[wname]; + + UTFString mTitle = hText.first; + UTFString mTxt = hText.second; + if (fabs(minmax.first - minmax.second) > 0.001f) + { + wchar_t param[512] = L""; + UTFString fmt = _L("\nParameter range: %f to %f"); + swprintf(param, 512, fmt.asWStr_c_str(), minmax.first, minmax.second); + mTxt = mTxt + UTFString(param); + } + MyGUI::IntPoint p = _sender->getAbsolutePosition(); + MyGUI::IntSize s = _sender->getSize(); + showHelp(mTitle, mTxt, p.left + s.width, p.top + s.height * 0.5f); + return; + } + + if (name == "select_current_ground") { updateControls(active_gm); } + else if (_sender->getName() == "apply_changes") + { + applyChanges(); + } + + // LOG(" Friction GUI button pressed: " + _sender->getName()); } - MyGUI::IntPoint p = _sender->getAbsolutePosition(); - MyGUI::IntSize s = _sender->getSize(); - showHelp(mTitle, mTxt, p.left + s.width, p.top + s.height * 0.5f); - return; - } - if (name == "select_current_ground") - { - updateControls(active_gm); - } - else if (_sender->getName() == "apply_changes") - { - applyChanges(); - } + void FrictionSettings::event_scroll_value(MyGUI::ScrollBar *_sender, size_t _value) + { + String name = _sender->getName(); + if (name.size() > 7 && name.substr(name.size() - 7, 7) == "_scroll") + { + String wName = name.substr(0, name.size() - 7); + MyGUI::EditPtr e = (MyGUI::EditPtr)win->findWidget(wName); + std::pair f = minMaxs[wName]; + MyGUI::ScrollBar * h = (MyGUI::ScrollBar *)_sender; + Real rvalue = ((((float)_value) / (float)(h->getScrollRange())) * (f.second - f.first)) + f.first; + if (e) e->setCaption(TOSTRING(rvalue)); + + MyGUI::TextBox *edt = (MyGUI::TextBox *)win->findWidget(wName + "_edited"); + if (edt) edt->setCaption("!!"); + } + } - //LOG(" Friction GUI button pressed: " + _sender->getName()); -} + void FrictionSettings::applyChanges() + { + MyGUI::TextBox *edt; + + MyGUI::EditPtr e = (MyGUI::EditPtr)win->findWidget("solid_adhension_velo"); + selected_gm->va = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_adhension_velo_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_level"); + selected_gm->solid_ground_level = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_level_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_static_friction"); + selected_gm->ms = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_static_friction_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_dynamic_friction"); + selected_gm->mc = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_dynamic_friction_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_hydrodynamic"); + selected_gm->t2 = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_hydrodynamic_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_stribeck"); + selected_gm->vs = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_stribeck_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_alpha"); + selected_gm->alpha = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_alpha_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("solid_strength"); + selected_gm->strength = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("solid_strength_edited"); + if (edt) edt->setCaption(""); + + // fluid + e = (MyGUI::EditPtr)win->findWidget("fluid_flowbeh"); + selected_gm->flow_behavior_index = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("fluid_flowbeh_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("fluid_flowcon"); + selected_gm->flow_consistency_index = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("fluid_flowcon_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("fluid_density"); + selected_gm->fluid_density = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("fluid_density_edited"); + if (edt) edt->setCaption(""); + + e = (MyGUI::EditPtr)win->findWidget("fluid_drag_anisotropy"); + selected_gm->drag_anisotropy = StringConverter::parseReal(e->getCaption()); + edt = (MyGUI::TextBox *)win->findWidget("fluid_drag_anisotropy_edited"); + if (edt) edt->setCaption(""); + } -void FrictionSettings::event_scroll_value(MyGUI::ScrollBar* _sender, size_t _value) -{ - String name = _sender->getName(); - if (name.size() > 7 && name.substr(name.size() - 7, 7) == "_scroll") - { - String wName = name.substr(0, name.size() - 7); - MyGUI::EditPtr e = (MyGUI::EditPtr)win->findWidget(wName); - std::pair f = minMaxs[wName]; - MyGUI::ScrollBar* h = (MyGUI::ScrollBar *)_sender; - Real rvalue = ((((float)_value) / (float)(h->getScrollRange())) * (f.second - f.first)) + f.first; - if (e) - e->setCaption(TOSTRING(rvalue)); - - MyGUI::TextBox* edt = (MyGUI::TextBox *)win->findWidget(wName + "_edited"); - if (edt) - edt->setCaption("!!"); - } -} - -void FrictionSettings::applyChanges() -{ - MyGUI::TextBox* edt; - - MyGUI::EditPtr e = (MyGUI::EditPtr)win->findWidget("solid_adhension_velo"); - selected_gm->va = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_adhension_velo_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_level"); - selected_gm->solid_ground_level = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_level_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_static_friction"); - selected_gm->ms = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_static_friction_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_dynamic_friction"); - selected_gm->mc = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_dynamic_friction_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_hydrodynamic"); - selected_gm->t2 = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_hydrodynamic_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_stribeck"); - selected_gm->vs = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_stribeck_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_alpha"); - selected_gm->alpha = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_alpha_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("solid_strength"); - selected_gm->strength = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("solid_strength_edited"); - if (edt) - edt->setCaption(""); - - // fluid - e = (MyGUI::EditPtr)win->findWidget("fluid_flowbeh"); - selected_gm->flow_behavior_index = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("fluid_flowbeh_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("fluid_flowcon"); - selected_gm->flow_consistency_index = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("fluid_flowcon_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("fluid_density"); - selected_gm->fluid_density = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("fluid_density_edited"); - if (edt) - edt->setCaption(""); - - e = (MyGUI::EditPtr)win->findWidget("fluid_drag_anisotropy"); - selected_gm->drag_anisotropy = StringConverter::parseReal(e->getCaption()); - edt = (MyGUI::TextBox *)win->findWidget("fluid_drag_anisotropy_edited"); - if (edt) - edt->setCaption(""); - -} - -void FrictionSettings::notifyWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string& _name) -{ - if (_name == "close") - this->SetVisible(false); -} + void FrictionSettings::notifyWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string &_name) + { + if (_name == "close") this->SetVisible(false); + } -void FrictionSettings::notifyHelpWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string& _name) -{ - if (_name == "close") - msgwin->setVisibleSmooth(false); -} + void FrictionSettings::notifyHelpWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string &_name) + { + if (_name == "close") msgwin->setVisibleSmooth(false); + } -void FrictionSettings::showHelp(UTFString title, UTFString msg, int x, int y) -{ - MyGUI::EditPtr e = (MyGUI::EditPtr)msgwin->findWidget("helptext"); - e->setCaption(convertToMyGUIString(msg)); - UTFString tmp = _L("Friction Help: ") + title; - msgwin->setCaption(convertToMyGUIString(tmp)); - msgwin->setPosition(x + 20, y - 150); - msgwin->setVisibleSmooth(true); -} - -} // namespace GUI + void FrictionSettings::showHelp(UTFString title, UTFString msg, int x, int y) + { + MyGUI::EditPtr e = (MyGUI::EditPtr)msgwin->findWidget("helptext"); + e->setCaption(convertToMyGUIString(msg)); + UTFString tmp = _L("Friction Help: ") + title; + msgwin->setCaption(convertToMyGUIString(tmp)); + msgwin->setPosition(x + 20, y - 150); + msgwin->setVisibleSmooth(true); + } + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_FrictionSettings.h b/source/main/gui/panels/GUI_FrictionSettings.h index 744e7676ee..dd9521174f 100644 --- a/source/main/gui/panels/GUI_FrictionSettings.h +++ b/source/main/gui/panels/GUI_FrictionSettings.h @@ -24,51 +24,53 @@ #pragma once - #include "RoRPrerequisites.h" #include -namespace RoR { -namespace GUI { - -class FrictionSettings : public ZeroedMemoryAllocator +namespace RoR { -public: - - FrictionSettings(); - ~FrictionSettings(); - - bool IsVisible(); - void SetVisible(bool value); - - void setShaded(bool value); - - void setCollisions(Collisions* _col) { col = _col; }; - void setActiveCol(ground_model_t* gm); - -private: - - Collisions* col; - MyGUI::WindowPtr msgwin; - MyGUI::WindowPtr win; - ground_model_t* active_gm; - ground_model_t* selected_gm; - - std::map> helpTexts; - std::map> minMaxs; - - void updateControls(ground_model_t* gm, bool setCombo = true); - - void event_combo_grounds_eventComboAccept(MyGUI::ComboBoxPtr _sender, size_t _index); - void event_btn_MouseButtonClick(MyGUI::WidgetPtr _sender); - void event_edit_TextChange(MyGUI::EditPtr _sender); - void event_scroll_value(MyGUI::ScrollBar* _sender, size_t _value); - void notifyWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string& _name); - void notifyHelpWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string& _name); - void applyChanges(); - void showHelp(Ogre::UTFString title, Ogre::UTFString msg, int x, int y); -}; - -} // namespace GUI + namespace GUI + { + + class FrictionSettings : public ZeroedMemoryAllocator + { + public: + FrictionSettings(); + ~FrictionSettings(); + + bool IsVisible(); + void SetVisible(bool value); + + void setShaded(bool value); + + void setCollisions(Collisions *_col) + { + col = _col; + }; + void setActiveCol(ground_model_t *gm); + + private: + Collisions * col; + MyGUI::WindowPtr msgwin; + MyGUI::WindowPtr win; + ground_model_t * active_gm; + ground_model_t * selected_gm; + + std::map> helpTexts; + std::map> minMaxs; + + void updateControls(ground_model_t *gm, bool setCombo = true); + + void event_combo_grounds_eventComboAccept(MyGUI::ComboBoxPtr _sender, size_t _index); + void event_btn_MouseButtonClick(MyGUI::WidgetPtr _sender); + void event_edit_TextChange(MyGUI::EditPtr _sender); + void event_scroll_value(MyGUI::ScrollBar *_sender, size_t _value); + void notifyWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string &_name); + void notifyHelpWindowButtonPressed(MyGUI::WindowPtr _sender, const std::string &_name); + void applyChanges(); + void showHelp(Ogre::UTFString title, Ogre::UTFString msg, int x, int y); + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_GameAbout.cpp b/source/main/gui/panels/GUI_GameAbout.cpp index 0f45a1648a..369edac0a6 100644 --- a/source/main/gui/panels/GUI_GameAbout.cpp +++ b/source/main/gui/panels/GUI_GameAbout.cpp @@ -25,27 +25,26 @@ #include "GUI_GameAbout.h" -#include "RoRPrerequisites.h" - #include "Application.h" #include "GUIManager.h" #include "Language.h" +#include "RoRPrerequisites.h" #include "RoRVersion.h" -#include "Utils.h" #include "RoRnet.h" +#include "Utils.h" #include using namespace RoR; using namespace GUI; -#define CLASS GameAbout -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) +#define CLASS GameAbout +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) CLASS::CLASS() { MyGUI::WindowPtr win = dynamic_cast(mMainWidget); - win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::notifyWindowButtonPressed); //The "X" button thing + win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::notifyWindowButtonPressed); // The "X" button thing m_backbtn->eventMouseButtonClick += MyGUI::newDelegate(this, &CLASS::eventMouseButtonClickBackButton); m_ror_version->setCaption(Ogre::String(ROR_VERSION_STRING)); @@ -70,10 +69,7 @@ void CLASS::Show() void CLASS::Hide() { MAIN_WIDGET->setVisibleSmooth(false); - if (App::app_state.GetActive() == AppState::MAIN_MENU) - { - App::GetGuiManager()->SetVisible_GameMainMenu(true); - } + if (App::app_state.GetActive() == AppState::MAIN_MENU) { App::GetGuiManager()->SetVisible_GameMainMenu(true); } } void CLASS::CenterToScreen() @@ -92,23 +88,25 @@ bool CLASS::IsVisible() void CLASS::initMisc() { Ogre::UTFString AuthorsText = ""; - Ogre::UTFString orange = U("#FF7D02"); // colour key shortcut - Ogre::UTFString white = U("#FFFFFF"); // colour key shortcut - Ogre::UTFString color1 = U("#66FF33"); // colour key shortcut - Ogre::UTFString newline = U("\n"); + Ogre::UTFString orange = U("#FF7D02"); // colour key shortcut + Ogre::UTFString white = U("#FFFFFF"); // colour key shortcut + Ogre::UTFString color1 = U("#66FF33"); // colour key shortcut + Ogre::UTFString newline = U("\n"); - //Authors: + // Authors: AuthorsText = orange + "Authors:" + newline; - AuthorsText = AuthorsText + color1 + "Pierre-Michel Ricordel (pricorde):" + white + " Physics Genius, Original Author, Core Developer, retired" + newline; + AuthorsText = AuthorsText + color1 + "Pierre-Michel Ricordel (pricorde):" + white + + " Physics Genius, Original Author, Core Developer, retired" + newline; AuthorsText = AuthorsText + color1 + "Thomas Fischer (tdev):" + white + " Core Developer, inactive" + newline; - //Current Project devs: + // Current Project devs: AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Current Developers:" + newline; AuthorsText = AuthorsText + color1 + "Petr Ohlidal (only_a_ptr):" + white + " Core Developer, active" + newline; - AuthorsText = AuthorsText + color1 + "Edgar (AnotherFoxGuy):" + white + " Various fixes and features, developer web services, active" + newline; + AuthorsText = AuthorsText + color1 + "Edgar (AnotherFoxGuy):" + white + + " Various fixes and features, developer web services, active" + newline; - //Server Contributors + // Server Contributors AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Server Contributors:" + newline; AuthorsText = AuthorsText + color1 + "Austin:" + white + " Server funding" + newline; @@ -117,12 +115,14 @@ void CLASS::initMisc() AuthorsText = AuthorsText + color1 + "Charger:" + white + " Branding designer" + newline; AuthorsText = AuthorsText + color1 + "CuriousMike:" + white + " Repository & multiplayer server management" + newline; - //Code Contributors: + // Code Contributors: AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Code Contributors:" + newline; - AuthorsText = AuthorsText + color1 + "Estama:" + white + " Physics Core Optimizations, Collision/Friction code, Support Beams" + newline; + AuthorsText = AuthorsText + color1 + "Estama:" + white + + " Physics Core Optimizations, Collision/Friction code, Support Beams" + newline; AuthorsText = AuthorsText + color1 + "Lifter:" + white + " Triggers, Animators, Animated Props, Shocks2" + newline; - AuthorsText = AuthorsText + color1 + "Aperion:" + white + " Slidenodes, Axles, Improved Engine code, Rigidifiers, Networking code" + newline; + AuthorsText = AuthorsText + color1 + "Aperion:" + white + + " Slidenodes, Axles, Improved Engine code, Rigidifiers, Networking code" + newline; AuthorsText = AuthorsText + color1 + "FlyPiper:" + white + " Inertia Code, minor patches" + newline; AuthorsText = AuthorsText + color1 + "knied:" + white + " MacOSX Patches" + newline; AuthorsText = AuthorsText + color1 + "altren:" + white + " Coded some MyGUI windows" + newline; @@ -135,33 +135,37 @@ void CLASS::initMisc() AuthorsText = AuthorsText + color1 + "synthead:" + white + " Minor Linux fixes" + newline; AuthorsText = AuthorsText + color1 + "theshark:" + white + " Various fixes" + newline; AuthorsText = AuthorsText + color1 + "Clockwork (a.k.a VeyronEB):" + white + " GUI Designer and tweaker" + newline; - AuthorsText = AuthorsText + color1 + "Klink:" + white + " Terrains conversion, few fixes and tweaks, dashboard designer" + newline; + AuthorsText = + AuthorsText + color1 + "Klink:" + white + " Terrains conversion, few fixes and tweaks, dashboard designer" + newline; AuthorsText = AuthorsText + color1 + "hagdervriese:" + white + " Linux fixes" + newline; AuthorsText = AuthorsText + color1 + "skybon:" + white + " Web services, fixes, utilities" + newline; AuthorsText = AuthorsText + color1 + "Niklas Kersten (Hiradur):" + white + " Various fixes and tweaks, retired" + newline; - AuthorsText = AuthorsText + color1 + "Moncef Ben Slimane (max98):" + white + " Few fixes, Few improvements, GUI Overhaul" + newline; + AuthorsText = + AuthorsText + color1 + "Moncef Ben Slimane (max98):" + white + " Few fixes, Few improvements, GUI Overhaul" + newline; AuthorsText = AuthorsText + color1 + "mikadou:" + white + " Modernized thread pool, cmake, various fixes" + newline; AuthorsText = AuthorsText + color1 + "ulteq:" + white + " Various features, multithreading, lots of fixes" + newline; AuthorsText = AuthorsText + color1 + "tritonas00" + white + " Various improvements and Linux fixes" + newline; - //Core Content Contributors + // Core Content Contributors AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Core Content Contributors:" + newline; AuthorsText = AuthorsText + color1 + "donoteat:" + white + " Improved spawner models, terrain work" + newline; AuthorsText = AuthorsText + color1 + "kevinmce:" + white + " Old character" + newline; AuthorsText = AuthorsText + color1 + "vido89" + white + " Character animations" + newline; - //Mod Contributors + // Mod Contributors AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Mod Contributors:" + newline; - AuthorsText = AuthorsText + color1 + "The Rigs of Rods community:" + white + " Provides us with lots of mods to play with" + newline; + AuthorsText = + AuthorsText + color1 + "The Rigs of Rods community:" + white + " Provides us with lots of mods to play with" + newline; - //Testers + // Testers AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Testers:" + newline; - AuthorsText = AuthorsText + color1 + "Invited core team:" + white + " The invited members helped us a lot along the way at various corners" + newline; + AuthorsText = AuthorsText + color1 + "Invited core team:" + white + + " The invited members helped us a lot along the way at various corners" + newline; - //Used Libs + // Used Libs AuthorsText = AuthorsText + newline; AuthorsText = AuthorsText + orange + "Used Libs:" + newline; AuthorsText = AuthorsText + color1 + "Ogre3D:" + white + " 3D rendering engine" + newline; @@ -190,8 +194,8 @@ void CLASS::initMisc() #ifdef USE_SOCKETW AuthorsText = AuthorsText + color1 + "SocketW:" + white + " Used as cross-platform socket abstraction" + newline; #endif - AuthorsText = AuthorsText + color1 + "pThreads:" + white + " POSIX threads library" + newline; - AuthorsText = AuthorsText + color1 + "RapidJSON:" + white + " JSON parser/generator, used for online services" + newline; + AuthorsText = AuthorsText + color1 + "pThreads:" + white + " POSIX threads library" + newline; + AuthorsText = AuthorsText + color1 + "RapidJSON:" + white + " JSON parser/generator, used for online services" + newline; m_authors->setMaxTextLength(4096); m_authors->setCaption(Ogre::String(AuthorsText)); @@ -203,10 +207,9 @@ void CLASS::eventMouseButtonClickBackButton(MyGUI::WidgetPtr _sender) Hide(); } -void CLASS::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name) +void CLASS::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name) { - if (_name == "close") - Hide(); + if (_name == "close") Hide(); } void CLASS::SetVisible(bool v) diff --git a/source/main/gui/panels/GUI_GameAbout.h b/source/main/gui/panels/GUI_GameAbout.h index 3004991adc..464c70e00d 100644 --- a/source/main/gui/panels/GUI_GameAbout.h +++ b/source/main/gui/panels/GUI_GameAbout.h @@ -28,26 +28,28 @@ #include "ForwardDeclarations.h" #include "GUI_GameAboutLayout.h" -namespace RoR { -namespace GUI { - -class GameAbout: public GameAboutLayout +namespace RoR { -public: - GameAbout(); - ~GameAbout(); - - void Show(); - void Hide(); - void SetVisible(bool v); - bool IsVisible(); - -private: - void eventMouseButtonClickBackButton(MyGUI::WidgetPtr _sender); - void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name); - void initMisc(); - void CenterToScreen(); -}; - -} // namespace GUI + namespace GUI + { + + class GameAbout : public GameAboutLayout + { + public: + GameAbout(); + ~GameAbout(); + + void Show(); + void Hide(); + void SetVisible(bool v); + bool IsVisible(); + + private: + void eventMouseButtonClickBackButton(MyGUI::WidgetPtr _sender); + void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name); + void initMisc(); + void CenterToScreen(); + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_GameAboutLayout.cpp b/source/main/gui/panels/GUI_GameAboutLayout.cpp index a09ae9db95..ab7280adc5 100644 --- a/source/main/gui/panels/GUI_GameAboutLayout.cpp +++ b/source/main/gui/panels/GUI_GameAboutLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -GameAboutLayout::GameAboutLayout(MyGUI::Widget* _parent) +GameAboutLayout::GameAboutLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_GameAboutLayout.h b/source/main/gui/panels/GUI_GameAboutLayout.h index 6aaf192c5a..b69aadb2e7 100644 --- a/source/main/gui/panels/GUI_GameAboutLayout.h +++ b/source/main/gui/panels/GUI_GameAboutLayout.h @@ -8,42 +8,41 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(GameAboutLayout, "about.layout"); -class GameAboutLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(GameAboutLayout, "about.layout"); + class GameAboutLayout : public wraps::BaseLayout + { - GameAboutLayout(MyGUI::Widget* _parent = nullptr); - virtual ~GameAboutLayout(); + public: + GameAboutLayout(MyGUI::Widget *_parent = nullptr); + virtual ~GameAboutLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_ror_version, "ror_version"); + MyGUI::EditBox *m_ror_version; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_ror_version, "ror_version"); - MyGUI::EditBox* m_ror_version; + ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_net_version, "net_version"); + MyGUI::EditBox *m_net_version; - ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_net_version, "net_version"); - MyGUI::EditBox* m_net_version; + ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_build_time, "build_time"); + MyGUI::EditBox *m_build_time; - ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_build_time, "build_time"); - MyGUI::EditBox* m_build_time; + ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_authors, "authors"); + MyGUI::EditBox *m_authors; - ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_authors, "authors"); - MyGUI::EditBox* m_authors; + ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_backbtn, "backbtn"); + MyGUI::Button *m_backbtn; - ATTRIBUTE_FIELD_WIDGET_NAME(GameAboutLayout, m_backbtn, "backbtn"); - MyGUI::Button* m_backbtn; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_GameChatBox.cpp b/source/main/gui/panels/GUI_GameChatBox.cpp index 558a9b02d2..e9149814dc 100644 --- a/source/main/gui/panels/GUI_GameChatBox.cpp +++ b/source/main/gui/panels/GUI_GameChatBox.cpp @@ -25,39 +25,34 @@ #include "GUI_GameChatBox.h" -#include -#include -#include -#include - -#include "RoRPrerequisites.h" - +#include "Application.h" #include "ChatSystem.h" -#include "Utils.h" -#include "Language.h" #include "GUIManager.h" -#include "Application.h" +#include "Language.h" #include "OgreSubsystem.h" +#include "RoRPrerequisites.h" +#include "Utils.h" + +#include +#include +#include +#include using namespace RoR; using namespace GUI; -#define CLASS GameChatBox -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) +#define CLASS GameChatBox +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) -CLASS::CLASS() : - alpha(1.0f) - , newMsg(false) - , pushTime(0) +CLASS::CLASS() : alpha(1.0f), newMsg(false), pushTime(0) { MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &CLASS::Update); /* Adjust menu position */ - Ogre::Viewport* viewport = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getViewport(0); - int margin = (viewport->getActualHeight() / 4.5); - MAIN_WIDGET->setPosition( - 2, // left - viewport->getActualHeight() - MAIN_WIDGET->getHeight() - margin // top + Ogre::Viewport *viewport = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getViewport(0); + int margin = (viewport->getActualHeight() / 4.5); + MAIN_WIDGET->setPosition(2, // left + viewport->getActualHeight() - MAIN_WIDGET->getHeight() - margin // top ); m_Chatbox_TextBox->eventEditSelectAccept += MyGUI::newDelegate(this, &CLASS::eventCommandAccept); @@ -92,13 +87,12 @@ void CLASS::pushMsg(Ogre::String txt) m_Chatbox_MainBox->setCaptionWithReplacing(mHistory); } -void CLASS::eventCommandAccept(MyGUI::Edit* _sender) +void CLASS::eventCommandAccept(MyGUI::Edit *_sender) { Ogre::UTFString msg = convertFromMyGUIString(_sender->getCaption()); _sender->setCaption(""); - if (App::mp_chat_auto_hide.GetActive()) - _sender->setEnabled(false); + if (App::mp_chat_auto_hide.GetActive()) _sender->setEnabled(false); if (msg.empty()) { @@ -130,7 +124,7 @@ void CLASS::eventCommandAccept(MyGUI::Edit* _sender) } #endif // USE_SOCKETW - //MyGUI::InputManager::getInstance().resetKeyFocusWidget(); + // MyGUI::InputManager::getInstance().resetKeyFocusWidget(); RoR::App::GetGuiManager()->UnfocusGui(); } @@ -149,7 +143,7 @@ void CLASS::Update(float dt) if (newMsg) { - newMsg = false; + newMsg = false; pushTime = Ogre::Root::getSingleton().getTimer()->getMilliseconds(); MAIN_WIDGET->setAlpha(1); MAIN_WIDGET->setVisible(true); @@ -158,21 +152,15 @@ void CLASS::Update(float dt) if (!MyGUI::InputManager::getInstance().isFocusKey()) { - unsigned long ot = Ogre::Root::getSingleton().getTimer()->getMilliseconds(); - unsigned long endTime = pushTime + 5000; + unsigned long ot = Ogre::Root::getSingleton().getTimer()->getMilliseconds(); + unsigned long endTime = pushTime + 5000; unsigned long startTime = endTime - (long)1000.0f; - if (ot < startTime) - { - alpha = 1.0f; - } + if (ot < startTime) { alpha = 1.0f; } else { alpha = 1 - ((ot - startTime) / 1000.0f); } - if (alpha <= 0.0f) - { - MAIN_WIDGET->setVisible(false); - } + if (alpha <= 0.0f) { MAIN_WIDGET->setVisible(false); } else { MAIN_WIDGET->setAlpha(alpha); diff --git a/source/main/gui/panels/GUI_GameChatBox.h b/source/main/gui/panels/GUI_GameChatBox.h index 53c0a25370..2cfafc4560 100644 --- a/source/main/gui/panels/GUI_GameChatBox.h +++ b/source/main/gui/panels/GUI_GameChatBox.h @@ -28,34 +28,34 @@ #include "ForwardDeclarations.h" #include "GUI_GameChatBoxLayout.h" -namespace RoR { -namespace GUI { - -class GameChatBox: public GameChatBoxLayout +namespace RoR { -public: - - GameChatBox(); - ~GameChatBox(); - - void Show(); - void Hide(); - bool IsVisible(); - void SetVisible(bool value); - void pushMsg(Ogre::String txt); - void Update(float dt); - -private: - - void eventCommandAccept(MyGUI::Edit* _sender); - - Ogre::String mHistory; - bool newMsg; - - // logic - float alpha; - long pushTime; -}; - -} // namespace GUI + namespace GUI + { + + class GameChatBox : public GameChatBoxLayout + { + public: + GameChatBox(); + ~GameChatBox(); + + void Show(); + void Hide(); + bool IsVisible(); + void SetVisible(bool value); + void pushMsg(Ogre::String txt); + void Update(float dt); + + private: + void eventCommandAccept(MyGUI::Edit *_sender); + + Ogre::String mHistory; + bool newMsg; + + // logic + float alpha; + long pushTime; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_GameChatBoxLayout.cpp b/source/main/gui/panels/GUI_GameChatBoxLayout.cpp index e44774afb6..417b72dfa6 100644 --- a/source/main/gui/panels/GUI_GameChatBoxLayout.cpp +++ b/source/main/gui/panels/GUI_GameChatBoxLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -GameChatBoxLayout::GameChatBoxLayout(MyGUI::Widget* _parent) +GameChatBoxLayout::GameChatBoxLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_GameChatBoxLayout.h b/source/main/gui/panels/GUI_GameChatBoxLayout.h index 1b1a1205c1..3c3bb51636 100644 --- a/source/main/gui/panels/GUI_GameChatBoxLayout.h +++ b/source/main/gui/panels/GUI_GameChatBoxLayout.h @@ -8,34 +8,33 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(GameChatBoxLayout, "Chatbox.layout"); -class GameChatBoxLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(GameChatBoxLayout, "Chatbox.layout"); + class GameChatBoxLayout : public wraps::BaseLayout + { - GameChatBoxLayout(MyGUI::Widget* _parent = nullptr); - virtual ~GameChatBoxLayout(); + public: + GameChatBoxLayout(MyGUI::Widget *_parent = nullptr); + virtual ~GameChatBoxLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(GameChatBoxLayout, m_Chatbox_MainBox, "Chatbox_MainBox"); + MyGUI::EditBox *m_Chatbox_MainBox; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(GameChatBoxLayout, m_Chatbox_MainBox, "Chatbox_MainBox"); - MyGUI::EditBox* m_Chatbox_MainBox; + ATTRIBUTE_FIELD_WIDGET_NAME(GameChatBoxLayout, m_Chatbox_TextBox, "Chatbox_TextBox"); + MyGUI::EditBox *m_Chatbox_TextBox; - ATTRIBUTE_FIELD_WIDGET_NAME(GameChatBoxLayout, m_Chatbox_TextBox, "Chatbox_TextBox"); - MyGUI::EditBox* m_Chatbox_TextBox; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_GameConsole.cpp b/source/main/gui/panels/GUI_GameConsole.cpp index e629cde1f9..4b49a4e707 100644 --- a/source/main/gui/panels/GUI_GameConsole.cpp +++ b/source/main/gui/panels/GUI_GameConsole.cpp @@ -19,7 +19,6 @@ along with Rigs of Rods. If not, see . */ - #include "GUI_GameConsole.h" #include "Application.h" @@ -33,15 +32,15 @@ #include "Network.h" #include "OverlayWrapper.h" #include "RoRFrameListener.h" -#include "RoRnet.h" #include "RoRVersion.h" +#include "RoRnet.h" #include "Scripting.h" #include "TerrainManager.h" #include "TerrainObjectManager.h" #include "Utils.h" #if MYGUI_PLATFORM == MYGUI_PLATFORM_LINUX -#include + #include #endif // LINUX using namespace Ogre; @@ -51,17 +50,18 @@ using namespace RoR; Console::Console() { MyGUI::WindowPtr win = dynamic_cast(mMainWidget); - win->eventWindowButtonPressed += MyGUI::newDelegate(this, &Console::notifyWindowButtonPressed); //The "X" button thing + win->eventWindowButtonPressed += MyGUI::newDelegate(this, &Console::notifyWindowButtonPressed); // The "X" button thing //((MyGUI::Window*)mMainWidget) - MyGUI::IntSize windowSize = ((MyGUI::Window*)mMainWidget)->getSize(); - MyGUI::IntSize parentSize = ((MyGUI::Window*)mMainWidget)->getParentSize(); + MyGUI::IntSize windowSize = ((MyGUI::Window *)mMainWidget)->getSize(); + MyGUI::IntSize parentSize = ((MyGUI::Window *)mMainWidget)->getParentSize(); - ((MyGUI::Window*)mMainWidget)->setPosition((parentSize.width - windowSize.width) / 2, (parentSize.height - windowSize.height) / 2); - ((MyGUI::Window*)mMainWidget)->setVisible(false); + ((MyGUI::Window *)mMainWidget) + ->setPosition((parentSize.width - windowSize.width) / 2, (parentSize.height - windowSize.height) / 2); + ((MyGUI::Window *)mMainWidget)->setVisible(false); - ConsoleText = ""; - iText = 0; + ConsoleText = ""; + iText = 0; HistoryCursor = 0; m_Console_TextBox->eventEditSelectAccept += MyGUI::newDelegate(this, &Console::eventCommandAccept); @@ -72,8 +72,8 @@ Console::Console() MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &Console::frameEntered); #ifdef USE_ANGELSCRIPT - //ScriptEngine::getSingleton().loadScript("Console.as"); -#endif //USE_ANGELSCRIPT + // ScriptEngine::getSingleton().loadScript("Console.as"); +#endif // USE_ANGELSCRIPT LogManager::getSingleton().getDefaultLog()->addListener(this); } @@ -82,22 +82,19 @@ Console::~Console() { } -void Console::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name) +void Console::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name) { - if (_name == "close") - { - this->SetVisible(false); - } + if (_name == "close") { this->SetVisible(false); } } void Console::SetVisible(bool _visible) { - ((MyGUI::Window*)mMainWidget)->setVisible(_visible); + ((MyGUI::Window *)mMainWidget)->setVisible(_visible); } bool Console::IsVisible() { - return ((MyGUI::Window*)mMainWidget)->getVisible(); + return ((MyGUI::Window *)mMainWidget)->getVisible(); } void Console::frameEntered(float dt) @@ -109,17 +106,17 @@ void Console::putMessage(int type, int sender_uid, UTFString txt, String icon, u { ConsoleMessage t; - t.type = type; - t.sender_uid = sender_uid; - t.time = Root::getSingleton().getTimer()->getMilliseconds(); - t.ttl = ttl; + t.type = type; + t.sender_uid = sender_uid; + t.time = Root::getSingleton().getTimer()->getMilliseconds(); + t.ttl = ttl; t.forcevisible = forcevisible; - //strncpy(t.txt, txt.c_str(), 2048); + // strncpy(t.txt, txt.c_str(), 2048); t.txt = txt; strncpy(t.icon, icon.c_str(), 50); - //t.channel = "default"; + // t.channel = "default"; - //showMessage(t); + // showMessage(t); push(t); } @@ -132,24 +129,25 @@ void Console::messageUpdate(float dt) { TextCol = "#FFFFFF"; if (message.sender_uid == CONSOLE_TITLE) - TextCol = "#FF8100"; //Orange + TextCol = "#FF8100"; // Orange else if (message.sender_uid == CONSOLE_SYSTEM_ERROR) - TextCol = "#FF0000"; //Red + TextCol = "#FF0000"; // Red else if (message.sender_uid == CONSOLE_SYSTEM_REPLY) - TextCol = "#00FF00"; //Green + TextCol = "#00FF00"; // Green else if (message.sender_uid == CONSOLE_HELP) - TextCol = "#72C0E0"; //Light blue + TextCol = "#72C0E0"; // Light blue ConsoleText += TextCol + message.txt + "\n"; m_Console_MainBox->setMaxTextLength(ConsoleText.length() + 1); - //if (getVisible()) + // if (getVisible()) m_Console_MainBox->setCaptionWithReplacing(ConsoleText); } } -void Console::messageLogged(const String& message, LogMessageLevel lml, bool maskDebug, const String& logName, bool& skipThisMessage) +void Console::messageLogged(const String &message, LogMessageLevel lml, bool maskDebug, const String &logName, + bool &skipThisMessage) { std::string msg = RoR::Utils::SanitizeUtf8String(message); if (message.substr(0, 4) == "SE| ") @@ -176,45 +174,41 @@ void Console::eventMouseButtonClickSendButton(MyGUI::WidgetPtr _sender) m_Console_TextBox->_riseKeyButtonPressed(MyGUI::KeyCode::Return, ' '); } -void Console::eventButtonPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char) +void Console::eventButtonPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char) { switch (MYGUI_GET_SCANCODE(_key)) { case MyGUI::KeyCode::ArrowUp: - { - if (HistoryCursor > iText) - HistoryCursor = 0; + { + if (HistoryCursor > iText) HistoryCursor = 0; - if (sTextHistory[HistoryCursor] != "") - m_Console_TextBox->setCaption(sTextHistory[HistoryCursor]); + if (sTextHistory[HistoryCursor] != "") m_Console_TextBox->setCaption(sTextHistory[HistoryCursor]); - HistoryCursor++; - } - break; + HistoryCursor++; + } + break; case MyGUI::KeyCode::ArrowDown: - { - if (HistoryCursor < 0) - HistoryCursor = iText; + { + if (HistoryCursor < 0) HistoryCursor = iText; - if (sTextHistory[HistoryCursor] != "") - m_Console_TextBox->setCaption(sTextHistory[HistoryCursor]); + if (sTextHistory[HistoryCursor] != "") m_Console_TextBox->setCaption(sTextHistory[HistoryCursor]); - HistoryCursor--; - } - break; + HistoryCursor--; + } + break; } } /* All commands are here */ -void Console::eventCommandAccept(MyGUI::Edit* _sender) +void Console::eventCommandAccept(MyGUI::Edit *_sender) { UTFString msg = convertFromMyGUIString(m_Console_TextBox->getCaption()); const bool is_appstate_sim = (App::app_state.GetActive() == AppState::SIMULATION); - const bool is_sim_select = (App::sim_state.GetActive() == SimState::SELECTING); + const bool is_sim_select = (App::sim_state.GetActive() == SimState::SELECTING); // we did not autoComplete, so try to handle the message m_Console_TextBox->setCaption(""); @@ -227,13 +221,14 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) if (msg[0] == '/' || msg[0] == '\\') { - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L ("Using slashes before commands are deprecated, you can now type command without any slashes"), "help.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, + _L("Using slashes before commands are deprecated, you can now type command without any slashes"), "help.png"); msg.erase(0, 1); } Ogre::StringVector args = StringUtil::split(msg, " "); - sTextHistory[iText] = msg; - iText++; //Used for text history + sTextHistory[iText] = msg; + iText++; // Used for text history if (args[0] == "help") { putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_TITLE, _L("Available commands:"), "help.png"); @@ -242,26 +237,34 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("pos - outputs the current position"), "world.png"); putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("goto - jumps to the mentioned position"), "world.png"); - - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("terrainheight - get height of terrain at current position"), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("terrainheight - get height of terrain at current position"), + "world.png"); putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("log - toggles log output on the console"), "table_save.png"); putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("quit - exit Rigs of Rods"), "table_save.png"); #ifdef USE_ANGELSCRIPT - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("as - interpret angel code using console"), "script_go.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("as - interpret angel code using console"), + "script_go.png"); #endif // USE_ANGELSCRIPT - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("gravity or - changes gravity constant. Outputs current value if no argument is given"), "script_go.png"); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("Possible values: \n earth \n moon \n jupiter \n A random number (use negative)"), "script_go.png"); + putMessage( + CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, + _L("gravity or - changes gravity constant. Outputs current value if no argument is given"), + "script_go.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, + _L("Possible values: \n earth \n moon \n jupiter \n A random number (use negative)"), "script_go.png"); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("setwaterlevel or default - changes water's level"), "script_go.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("setwaterlevel or default - changes water's level"), + "script_go.png"); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("spawnobject - spawn a object at the player position"), "script_go.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("spawnobject - spawn a object at the player position"), + "script_go.png"); putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_TITLE, _L("Tips:"), "help.png"); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("- use Arrow Up/Down Keys in the InputBox to reuse old messages"), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, _L("- use Arrow Up/Down Keys in the InputBox to reuse old messages"), + "information.png"); return; } else if (args[0] == "gravity") @@ -281,30 +284,36 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) } else { - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Current gravity is: ") + StringConverter::toString(App::GetSimTerrain()->getGravity()), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Current gravity is: ") + StringConverter::toString(App::GetSimTerrain()->getGravity()), + "information.png"); return; } App::GetSimTerrain()->setGravity(gValue); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Gravity set to: ") + StringConverter::toString(gValue), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Gravity set to: ") + StringConverter::toString(gValue), + "information.png"); return; } else if (args[0] == "setwaterlevel" && is_appstate_sim) { if (args.size() > 1) { - IWater* water = App::GetSimTerrain()->getWater(); + IWater *water = App::GetSimTerrain()->getWater(); if (water != nullptr) { float height = (args[1] == "default") ? App::GetSimTerrain()->getWaterHeight() : PARSEREAL(args[1]); water->WaterSetCamera(gEnv->mainCamera); water->SetStaticWaterHeight(height); water->UpdateWater(); - putMessage (CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L ("Water level set to: ") + StringConverter::toString (water->GetStaticWaterHeight ()), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Water level set to: ") + StringConverter::toString(water->GetStaticWaterHeight()), + "information.png"); } else { - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_ERROR, _L("This terrain does not have water."), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_ERROR, _L("This terrain does not have water."), + "information.png"); } } else @@ -315,16 +324,22 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) } else if (args[0] == "pos" && (is_appstate_sim && !is_sim_select)) { - Actor* b = App::GetSimController()->GetPlayerActor(); + Actor *b = App::GetSimController()->GetPlayerActor(); if (!b && gEnv->player) { Vector3 pos = gEnv->player->getPosition(); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Character position: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + String(" z: ") + TOSTRING(pos.z), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Character position: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + + String(" z: ") + TOSTRING(pos.z), + "world.png"); } else if (b) { Vector3 pos = b->getPosition(); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Vehicle position: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + String(" z: ") + TOSTRING(pos.z), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Vehicle position: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + + String(" z: ") + TOSTRING(pos.z), + "world.png"); } return; @@ -333,45 +348,51 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) { if (args.size() != 4) { - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, RoR::Color::CommandColour + _L("usage: goto x y z"), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_HELP, RoR::Color::CommandColour + _L("usage: goto x y z"), + "information.png"); return; } Vector3 pos = Vector3(PARSEREAL(args[1]), PARSEREAL(args[2]), PARSEREAL(args[3])); - Actor* b = App::GetSimController()->GetPlayerActor(); + Actor *b = App::GetSimController()->GetPlayerActor(); if (!b && gEnv->player) { gEnv->player->setPosition(pos); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Character position set to: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + String(" z: ") + TOSTRING(pos.z), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Character position set to: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + + String(" z: ") + TOSTRING(pos.z), + "world.png"); } else if (b) { b->ResetPosition(pos, false); TRIGGER_EVENT(SE_TRUCK_TELEPORT, b->ar_instance_id); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Vehicle position set to: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + String(" z: ") + TOSTRING(pos.z), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Vehicle position set to: ") + String("x: ") + TOSTRING(pos.x) + String(" y: ") + TOSTRING(pos.y) + + String(" z: ") + TOSTRING(pos.z), + "world.png"); } return; } else if (args[0] == "terrainheight" && (is_appstate_sim && !is_sim_select)) { - if (!App::GetSimTerrain()) - return; + if (!App::GetSimTerrain()) return; Vector3 pos = Vector3::ZERO; - Actor* b = App::GetSimController()->GetPlayerActor(); - if (!b && gEnv->player) - { - pos = gEnv->player->getPosition(); - } + Actor *b = App::GetSimController()->GetPlayerActor(); + if (!b && gEnv->player) { pos = gEnv->player->getPosition(); } else if (b) { pos = b->getPosition(); } Real h = App::GetSimTerrain()->GetHeightAt(pos.x, pos.z); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Terrain height at position: ") + String("x: ") + TOSTRING(pos.x) + String("z: ") + TOSTRING(pos.z) + _L(" = ") + TOSTRING(h), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Terrain height at position: ") + String("x: ") + TOSTRING(pos.x) + String("z: ") + TOSTRING(pos.z) + + _L(" = ") + TOSTRING(h), + "world.png"); return; } @@ -380,12 +401,13 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_TITLE, "Rigs of Rods:", "information.png"); putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, " Version: " + String(ROR_VERSION_STRING), "information.png"); putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, " Protocol version: " + String(RORNET_VERSION), "information.png"); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, " build time: " + String(ROR_BUILD_DATE) + ", " + String(ROR_BUILD_TIME), "information.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + " build time: " + String(ROR_BUILD_DATE) + ", " + String(ROR_BUILD_TIME), "information.png"); return; } else if (args[0] == "quit") { - RoR::App::app_state.SetPending (RoR::AppState::SHUTDOWN); + RoR::App::app_state.SetPending(RoR::AppState::SHUTDOWN); return; } #ifdef USE_ANGELSCRIPT @@ -397,20 +419,19 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) String command = msg.substr(args[0].length()); StringUtil::trim(command); - if (command.empty()) - return; + if (command.empty()) return; String nmsg = RoR::Color::ScriptCommandColour + ">>> " + RoR::Color::NormalColour + command; putMessage(CONSOLE_MSGTYPE_SCRIPT, CONSOLE_LOCAL_SCRIPT, nmsg, "script_go.png"); ScriptEngine::getSingleton().executeString(command); return; } -#endif //ANGELSCRIPT +#endif // ANGELSCRIPT else if (args[0] == "log") { // switch to console logging - bool now_logging = !App::diag_log_console_echo.GetActive(); - const char* msg = (now_logging) ? " logging to console enabled" : " logging to console disabled"; + bool now_logging = !App::diag_log_console_echo.GetActive(); + const char *msg = (now_logging) ? " logging to console enabled" : " logging to console disabled"; this->putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_NOTICE, _L(msg), "information.png"); App::diag_log_console_echo.SetActive(now_logging); return; @@ -419,17 +440,16 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) { Vector3 pos = Vector3::ZERO; - if (gEnv->player) - { - pos = gEnv->player->getPosition(); - } + if (gEnv->player) { pos = gEnv->player->getPosition(); } try { - SceneNode* bakeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + SceneNode *bakeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); App::GetSimTerrain()->getObjectManager()->LoadTerrainObject(args[1], pos, Vector3::ZERO, bakeNode, "Console", ""); - putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, _L("Spawned object at position: ") + String("x: ") + TOSTRING(pos.x) + String("z: ") + TOSTRING(pos.z), "world.png"); + putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_REPLY, + _L("Spawned object at position: ") + String("x: ") + TOSTRING(pos.x) + String("z: ") + TOSTRING(pos.z), + "world.png"); } catch (std::exception e) { @@ -445,7 +465,6 @@ void Console::eventCommandAccept(MyGUI::Edit* _sender) ScriptEngine::getSingleton().executeString(msg); #else putMessage(CONSOLE_MSGTYPE_INFO, CONSOLE_SYSTEM_ERROR, _L("unknown command: ") + msg, "error.png"); -#endif //ANGELSCRIPT +#endif // ANGELSCRIPT } - } diff --git a/source/main/gui/panels/GUI_GameConsole.h b/source/main/gui/panels/GUI_GameConsole.h index 28fc491041..1ac6201d84 100644 --- a/source/main/gui/panels/GUI_GameConsole.h +++ b/source/main/gui/panels/GUI_GameConsole.h @@ -23,97 +23,105 @@ #pragma once +#define CONSOLE_PUTMESSAGE(a, b, c, d, e, f) \ + while (0) \ + { \ + Console *console = RoR::App::GetConsole(); \ + if (console) console->putMessage(a, b, c, d, e, f); \ + } +#define CONSOLE_PUTMESSAGE_SHORT(a, b, c) \ + while (0) \ + { \ + Console *console = RoR::App::GetConsole(); \ + if (console) console->putMessage(a, b, c); \ + } -#define CONSOLE_PUTMESSAGE(a,b,c,d,e,f) while(0) { Console *console = RoR::App::GetConsole(); if (console) console->putMessage(a,b,c,d,e,f); } -#define CONSOLE_PUTMESSAGE_SHORT(a,b,c) while(0) { Console *console = RoR::App::GetConsole(); if (console) console->putMessage(a,b,c); } - -#include "RoRPrerequisites.h" +#include "GUI_GameConsoleLayout.h" #include "InterThreadStoreVector.h" - +#include "RoRPrerequisites.h" #include "mygui/BaseLayout.h" -#include "GUI_GameConsoleLayout.h" - -namespace RoR { -// Special - not in namespace GUI -struct ConsoleMessage +namespace RoR { - //Kept this for comptability rather than remplacing hunderd of lines. - char type; - int sender_uid; //Not used - unsigned long time; //Not used !< post time in milliseconds since RoR start - unsigned long ttl; //Not used !< in milliseconds - Ogre::UTFString txt; //!< not POD, beware... - char icon[50]; //Not used - bool forcevisible; //Not used -}; - -class Console : - public Ogre::LogListener, - public InterThreadStoreVector, - public GUI::GameConsoleLayout, - public ZeroedMemoryAllocator -{ -public: - - Console(); - ~Console(); + // Special - not in namespace GUI - void SetVisible(bool _visible); - bool IsVisible(); - - enum + struct ConsoleMessage { - CONSOLE_MSGTYPE_LOG, - CONSOLE_MSGTYPE_INFO, - CONSOLE_MSGTYPE_SCRIPT, - CONSOLE_MSGTYPE_NETWORK, - CONSOLE_MSGTYPE_FLASHMESSAGE, - CONSOLE_MSGTYPE_HIGHSCORE + // Kept this for comptability rather than remplacing hunderd of lines. + char type; + int sender_uid; // Not used + unsigned long time; // Not used !< post time in milliseconds since RoR start + unsigned long ttl; // Not used !< in milliseconds + Ogre::UTFString txt; //!< not POD, beware... + char icon[50]; // Not used + bool forcevisible; // Not used }; - enum + class Console : public Ogre::LogListener, + public InterThreadStoreVector, + public GUI::GameConsoleLayout, + public ZeroedMemoryAllocator { - // detailed message type identifier, mostly used for message filtering - CONSOLE_HELP, - CONSOLE_TITLE, + public: + Console(); + ~Console(); - CONSOLE_LOCAL_SCRIPT, // script self + void SetVisible(bool _visible); + bool IsVisible(); - CONSOLE_SYSTEM_NOTICE, - CONSOLE_SYSTEM_ERROR, - CONSOLE_SYSTEM_REPLY, // reply to a commands + enum + { + CONSOLE_MSGTYPE_LOG, + CONSOLE_MSGTYPE_INFO, + CONSOLE_MSGTYPE_SCRIPT, + CONSOLE_MSGTYPE_NETWORK, + CONSOLE_MSGTYPE_FLASHMESSAGE, + CONSOLE_MSGTYPE_HIGHSCORE + }; - CONSOLE_SYSTEM_DEBUG, + enum + { + // detailed message type identifier, mostly used for message filtering + CONSOLE_HELP, + CONSOLE_TITLE, - CONSOLE_LOGMESSAGE, - CONSOLE_LOGMESSAGE_SCRIPT, + CONSOLE_LOCAL_SCRIPT, // script self - MSG_CUSTOM, - }; + CONSOLE_SYSTEM_NOTICE, + CONSOLE_SYSTEM_ERROR, + CONSOLE_SYSTEM_REPLY, // reply to a commands - void putMessage(int type, int uid, Ogre::UTFString msg, Ogre::String icon = "bullet_black.png", unsigned long ttl = 30000, bool forcevisible = false); + CONSOLE_SYSTEM_DEBUG, -protected: + CONSOLE_LOGMESSAGE, + CONSOLE_LOGMESSAGE_SCRIPT, - void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name); - void messageUpdate(float dt); + MSG_CUSTOM, + }; - Ogre::String ConsoleText; - Ogre::UTFString TextCol; - bool angelscriptMode; + void putMessage(int type, int uid, Ogre::UTFString msg, Ogre::String icon = "bullet_black.png", unsigned long ttl = 30000, + bool forcevisible = false); - void frameEntered(float dt); + protected: + void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name); + void messageUpdate(float dt); - void messageLogged(const Ogre::String& message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String& logName, bool& skipThisMessage); + Ogre::String ConsoleText; + Ogre::UTFString TextCol; + bool angelscriptMode; - void eventCommandAccept(MyGUI::Edit* _sender); - void eventMouseButtonClickSendButton(MyGUI::WidgetPtr _sender); - void eventButtonPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char); + void frameEntered(float dt); - Ogre::String sTextHistory[500]; - int iText; - int HistoryCursor; -}; + void messageLogged(const Ogre::String &message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String &logName, + bool &skipThisMessage); + + void eventCommandAccept(MyGUI::Edit *_sender); + void eventMouseButtonClickSendButton(MyGUI::WidgetPtr _sender); + void eventButtonPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char); + + Ogre::String sTextHistory[500]; + int iText; + int HistoryCursor; + }; } // namespace RoR diff --git a/source/main/gui/panels/GUI_GameConsoleLayout.cpp b/source/main/gui/panels/GUI_GameConsoleLayout.cpp index 00fd8b3b6e..932e566f0d 100644 --- a/source/main/gui/panels/GUI_GameConsoleLayout.cpp +++ b/source/main/gui/panels/GUI_GameConsoleLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -GameConsoleLayout::GameConsoleLayout(MyGUI::Widget* _parent) +GameConsoleLayout::GameConsoleLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_GameConsoleLayout.h b/source/main/gui/panels/GUI_GameConsoleLayout.h index 3a7f76f163..bf058bcf55 100644 --- a/source/main/gui/panels/GUI_GameConsoleLayout.h +++ b/source/main/gui/panels/GUI_GameConsoleLayout.h @@ -8,36 +8,35 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(GameConsoleLayout, "Console.layout"); -class GameConsoleLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(GameConsoleLayout, "Console.layout"); + class GameConsoleLayout : public wraps::BaseLayout + { - GameConsoleLayout(MyGUI::Widget* _parent = nullptr); - virtual ~GameConsoleLayout(); + public: + GameConsoleLayout(MyGUI::Widget *_parent = nullptr); + virtual ~GameConsoleLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(GameConsoleLayout, m_Console_MainBox, "Console_MainBox"); + MyGUI::EditBox *m_Console_MainBox; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(GameConsoleLayout, m_Console_MainBox, "Console_MainBox"); - MyGUI::EditBox* m_Console_MainBox; + ATTRIBUTE_FIELD_WIDGET_NAME(GameConsoleLayout, m_Console_TextBox, "Console_TextBox"); + MyGUI::EditBox *m_Console_TextBox; - ATTRIBUTE_FIELD_WIDGET_NAME(GameConsoleLayout, m_Console_TextBox, "Console_TextBox"); - MyGUI::EditBox* m_Console_TextBox; + ATTRIBUTE_FIELD_WIDGET_NAME(GameConsoleLayout, m_Console_Send, "Console_Send"); + MyGUI::Button *m_Console_Send; - ATTRIBUTE_FIELD_WIDGET_NAME(GameConsoleLayout, m_Console_Send, "Console_Send"); - MyGUI::Button* m_Console_Send; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_GameMainMenu.cpp b/source/main/gui/panels/GUI_GameMainMenu.cpp index fc64a3f52d..a8e37dee26 100644 --- a/source/main/gui/panels/GUI_GameMainMenu.cpp +++ b/source/main/gui/panels/GUI_GameMainMenu.cpp @@ -31,13 +31,9 @@ #include "MainMenu.h" #include "PlatformUtils.h" -RoR::GUI::GameMainMenu::GameMainMenu(): - m_is_visible(false), m_num_buttons(5), m_kb_focus_index(-1), m_kb_enter_index(-1) +RoR::GUI::GameMainMenu::GameMainMenu() : m_is_visible(false), m_num_buttons(5), m_kb_focus_index(-1), m_kb_enter_index(-1) { - if (FileExists(PathCombine(App::sys_savegames_dir.GetActive(), "autosave.sav"))) - { - m_num_buttons++; - } + if (FileExists(PathCombine(App::sys_savegames_dir.GetActive(), "autosave.sav"))) { m_num_buttons++; } } void RoR::GUI::GameMainMenu::Draw() @@ -50,32 +46,29 @@ void RoR::GUI::GameMainMenu::Draw() // Display in bottom left corner for single-screen setups and centered for multi-screen (typically 3-screen) setups. ImVec2 display_size = ImGui::GetIO().DisplaySize; if ((display_size.x > 2200.f) && (display_size.y < 1100.f)) // Silly approximate values - { - ImGui::SetNextWindowPosCenter(); - } + { ImGui::SetNextWindowPosCenter(); } else { - const float btn_height = ImGui::GetTextLineHeight() + (BUTTON_PADDING.y * 2); - const float window_height = (6*btn_height) + (5*ImGui::GetStyle().ItemSpacing.y) + (2*ImGui::GetStyle().WindowPadding.y); // 5 buttons + titlebar; 2x spacing around separator + const float btn_height = ImGui::GetTextLineHeight() + (BUTTON_PADDING.y * 2); + const float window_height = (6 * btn_height) + (5 * ImGui::GetStyle().ItemSpacing.y) + + (2 * ImGui::GetStyle().WindowPadding.y); // 5 buttons + titlebar; 2x spacing around separator const float margin = display_size.y / 15.f; - const float top = display_size.y - window_height - margin; + const float top = display_size.y - window_height - margin; ImGui::SetNextWindowPos(ImVec2(margin, top)); } ImGui::SetNextWindowContentWidth(WINDOW_WIDTH); int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize; if (ImGui::Begin("Main menu", nullptr, static_cast(flags))) { - int button_index = 0; + int button_index = 0; ImVec2 btn_size(WINDOW_WIDTH - ImGui::GetStyle().WindowPadding.x, 0.f); - const char* sp_title = (m_kb_focus_index == button_index) ? "--> Single player <--" : "Single player"; // TODO: Localize all! + const char *sp_title = + (m_kb_focus_index == button_index) ? "--> Single player <--" : "Single player"; // TODO: Localize all! if (ImGui::Button(sp_title, btn_size) || (m_kb_enter_index == button_index++)) { this->SetVisible(false); - if (App::diag_preset_terrain.IsActiveEmpty()) - { - App::GetGuiManager()->GetMainSelector()->Show(LT_Terrain); - } + if (App::diag_preset_terrain.IsActiveEmpty()) { App::GetGuiManager()->GetMainSelector()->Show(LT_Terrain); } else { App::app_state.SetPending(RoR::AppState::SIMULATION); @@ -84,7 +77,7 @@ void RoR::GUI::GameMainMenu::Draw() if (FileExists(PathCombine(App::sys_savegames_dir.GetActive(), "autosave.sav"))) { - const char* resume_title = (m_kb_focus_index == button_index) ? "--> Resume game <--" : "Resume game"; + const char *resume_title = (m_kb_focus_index == button_index) ? "--> Resume game <--" : "Resume game"; if (ImGui::Button(resume_title, btn_size) || (m_kb_enter_index == button_index++)) { App::sim_savegame.SetActive("autosave.sav"); @@ -94,28 +87,28 @@ void RoR::GUI::GameMainMenu::Draw() } } - const char* mp_title = (m_kb_focus_index == button_index) ? "--> Multi player <--" : "Multi player"; - if (ImGui::Button(mp_title , btn_size) || (m_kb_enter_index == button_index++)) + const char *mp_title = (m_kb_focus_index == button_index) ? "--> Multi player <--" : "Multi player"; + if (ImGui::Button(mp_title, btn_size) || (m_kb_enter_index == button_index++)) { App::GetGuiManager()->SetVisible_MultiplayerSelector(true); this->SetVisible(false); } - const char* settings_title = (m_kb_focus_index == button_index) ? "--> Settings <--" : "Settings"; + const char *settings_title = (m_kb_focus_index == button_index) ? "--> Settings <--" : "Settings"; if (ImGui::Button(settings_title, btn_size) || (m_kb_enter_index == button_index++)) { App::GetGuiManager()->SetVisible_GameSettings(true); this->SetVisible(false); } - const char* about_title = (m_kb_focus_index == button_index) ? "--> About <--" : "About"; - if (ImGui::Button(about_title, btn_size)|| (m_kb_enter_index == button_index++)) + const char *about_title = (m_kb_focus_index == button_index) ? "--> About <--" : "About"; + if (ImGui::Button(about_title, btn_size) || (m_kb_enter_index == button_index++)) { App::GetGuiManager()->SetVisible_GameAbout(true); this->SetVisible(false); } - const char* exit_title = (m_kb_focus_index == button_index) ? "--> Exit game <--" : "Exit game"; + const char *exit_title = (m_kb_focus_index == button_index) ? "--> Exit game <--" : "Exit game"; if (ImGui::Button(exit_title, btn_size) || (m_kb_enter_index == button_index++)) { App::app_state.SetPending(RoR::AppState::SHUTDOWN); @@ -128,4 +121,3 @@ void RoR::GUI::GameMainMenu::Draw() ImGui::PopStyleColor(3); m_kb_enter_index = -1; } - diff --git a/source/main/gui/panels/GUI_GameMainMenu.h b/source/main/gui/panels/GUI_GameMainMenu.h index 9f1fe0f786..5ca02b663d 100644 --- a/source/main/gui/panels/GUI_GameMainMenu.h +++ b/source/main/gui/panels/GUI_GameMainMenu.h @@ -27,36 +27,54 @@ #include -namespace RoR { -namespace GUI { - -class GameMainMenu +namespace RoR { -public: - // This class implements hand-made keyboard focus - button count must be known for wrapping - const float WINDOW_WIDTH = 200.f; - const ImVec4 WINDOW_BG_COLOR = ImVec4(0.1f, 0.1f, 0.1f, 0.8f); - const ImVec4 BUTTON_BG_COLOR = ImVec4(0.25f, 0.25f, 0.24f, 0.6f); // Drawn on top of a transparent panel; make it just a shade - const ImVec2 BUTTON_PADDING = ImVec2(4.f, 6.f); + namespace GUI + { - GameMainMenu(); + class GameMainMenu + { + public: + // This class implements hand-made keyboard focus - button count must be known for wrapping + const float WINDOW_WIDTH = 200.f; + const ImVec4 WINDOW_BG_COLOR = ImVec4(0.1f, 0.1f, 0.1f, 0.8f); + const ImVec4 BUTTON_BG_COLOR = + ImVec4(0.25f, 0.25f, 0.24f, 0.6f); // Drawn on top of a transparent panel; make it just a shade + const ImVec2 BUTTON_PADDING = ImVec2(4.f, 6.f); - // Keyboard updates - move up/down and wrap on top/bottom. Initial index is '-1' which means "no focus" - inline void KeyUpPressed() { m_kb_focus_index = (m_kb_focus_index <= 0) ? (m_num_buttons - 1) : (m_kb_focus_index - 1); } - inline void KeyDownPressed() { m_kb_focus_index = (m_kb_focus_index < (m_num_buttons - 1)) ? (m_kb_focus_index + 1) : 0; } - void EnterKeyPressed() { m_kb_enter_index = m_kb_focus_index; } + GameMainMenu(); - inline bool IsVisible() const { return m_is_visible; } - inline void SetVisible(bool v) { m_is_visible = v; m_kb_focus_index = -1; } - void Draw(); + // Keyboard updates - move up/down and wrap on top/bottom. Initial index is '-1' which means "no focus" + inline void KeyUpPressed() + { + m_kb_focus_index = (m_kb_focus_index <= 0) ? (m_num_buttons - 1) : (m_kb_focus_index - 1); + } + inline void KeyDownPressed() + { + m_kb_focus_index = (m_kb_focus_index < (m_num_buttons - 1)) ? (m_kb_focus_index + 1) : 0; + } + void EnterKeyPressed() + { + m_kb_enter_index = m_kb_focus_index; + } -private: + inline bool IsVisible() const + { + return m_is_visible; + } + inline void SetVisible(bool v) + { + m_is_visible = v; + m_kb_focus_index = -1; + } + void Draw(); - bool m_is_visible; - int m_num_buttons; - int m_kb_focus_index; // -1 = no focus; 0+ = button index - int m_kb_enter_index; // Focus positon when enter key was pressed. -}; + private: + bool m_is_visible; + int m_num_buttons; + int m_kb_focus_index; // -1 = no focus; 0+ = button index + int m_kb_enter_index; // Focus positon when enter key was pressed. + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_GamePauseMenu.cpp b/source/main/gui/panels/GUI_GamePauseMenu.cpp index afa74fc101..e85ab80ab0 100644 --- a/source/main/gui/panels/GUI_GamePauseMenu.cpp +++ b/source/main/gui/panels/GUI_GamePauseMenu.cpp @@ -28,9 +28,9 @@ #include "Application.h" #include "RoRPrerequisites.h" -RoR::GUI::GamePauseMenu::GamePauseMenu(): - m_kb_focus_index(-1), m_kb_enter_index(-1) -{} +RoR::GUI::GamePauseMenu::GamePauseMenu() : m_kb_focus_index(-1), m_kb_enter_index(-1) +{ +} void RoR::GUI::GamePauseMenu::Draw() // TODO: Copypaste of 'GameMainMenu' -- cleanup and unify the logic! ~ only_a_ptr, 06/2017 { @@ -42,16 +42,14 @@ void RoR::GUI::GamePauseMenu::Draw() // TODO: Copypaste of 'GameMainMenu' -- cle // Display in bottom left corner for single-screen setups and centered for multi-screen (typically 3-screen) setups. ImVec2 display_size = ImGui::GetIO().DisplaySize; if ((display_size.x > 2200.f) && (display_size.y < 1100.f)) // Silly approximate values - { - ImGui::SetNextWindowPosCenter(); - } + { ImGui::SetNextWindowPosCenter(); } else { - const float btn_height = ImGui::GetTextLineHeight() + (BUTTON_PADDING.y * 2); - const float window_height = ((NUM_BUTTONS+1)*btn_height) + ((NUM_BUTTONS+1)*ImGui::GetStyle().ItemSpacing.y) - + (2*ImGui::GetStyle().WindowPadding.y); // 5 buttons + titlebar; 2x spacing around separator + const float btn_height = ImGui::GetTextLineHeight() + (BUTTON_PADDING.y * 2); + const float window_height = ((NUM_BUTTONS + 1) * btn_height) + ((NUM_BUTTONS + 1) * ImGui::GetStyle().ItemSpacing.y) + + (2 * ImGui::GetStyle().WindowPadding.y); // 5 buttons + titlebar; 2x spacing around separator const float margin = display_size.y / 15.f; - const float top = display_size.y - window_height - margin; + const float top = display_size.y - window_height - margin; ImGui::SetNextWindowPos(ImVec2(margin, top)); } ImGui::SetNextWindowContentWidth(WINDOW_WIDTH); @@ -60,23 +58,16 @@ void RoR::GUI::GamePauseMenu::Draw() // TODO: Copypaste of 'GameMainMenu' -- cle { ImVec2 btn_size(WINDOW_WIDTH - ImGui::GetStyle().WindowPadding.x, 0.f); - const char* resume_title = (m_kb_focus_index == 0) ? "--> Resume game <--" : "Resume game"; // TODO: Localize all! - if (ImGui::Button(resume_title, btn_size) || (m_kb_enter_index == 0)) - { - App::sim_state.SetPending(SimState::RUNNING); - } + const char *resume_title = (m_kb_focus_index == 0) ? "--> Resume game <--" : "Resume game"; // TODO: Localize all! + if (ImGui::Button(resume_title, btn_size) || (m_kb_enter_index == 0)) { App::sim_state.SetPending(SimState::RUNNING); } - const char* settings_title = (m_kb_focus_index == 1) ? "--> Return to menu <--" : "Return to menu"; + const char *settings_title = (m_kb_focus_index == 1) ? "--> Return to menu <--" : "Return to menu"; if (ImGui::Button(settings_title, btn_size) || (m_kb_enter_index == 1)) - { - App::app_state.SetPending(RoR::AppState::MAIN_MENU); - } + { App::app_state.SetPending(RoR::AppState::MAIN_MENU); } - const char* exit_title = (m_kb_focus_index == 2) ? "--> Exit game <--" : "Exit game"; + const char *exit_title = (m_kb_focus_index == 2) ? "--> Exit game <--" : "Exit game"; if (ImGui::Button(exit_title, btn_size) || (m_kb_enter_index == 2)) - { - App::app_state.SetPending(RoR::AppState::SHUTDOWN); - } + { App::app_state.SetPending(RoR::AppState::SHUTDOWN); } } ImGui::End(); @@ -85,4 +76,3 @@ void RoR::GUI::GamePauseMenu::Draw() // TODO: Copypaste of 'GameMainMenu' -- cle m_kb_enter_index = -1; } - diff --git a/source/main/gui/panels/GUI_GamePauseMenu.h b/source/main/gui/panels/GUI_GamePauseMenu.h index b538e67003..9686ea6f09 100644 --- a/source/main/gui/panels/GUI_GamePauseMenu.h +++ b/source/main/gui/panels/GUI_GamePauseMenu.h @@ -27,32 +27,44 @@ #include -namespace RoR { -namespace GUI { - -class GamePauseMenu // TODO: Copypaste of 'GameMainMenu' -- cleanup and unify the logic! ~ only_a_ptr, 06/2017 +namespace RoR { -public: - // This class implements hand-made keyboard focus - button count must be known for wrapping - const int NUM_BUTTONS = 3; // Buttons: Resumegame, BackToMenu, Quitgame - const float WINDOW_WIDTH = 200.f; - const ImVec4 WINDOW_BG_COLOR = ImVec4(0.1f, 0.1f, 0.1f, 0.8f); - const ImVec4 BUTTON_BG_COLOR = ImVec4(0.3f, 0.3f, 0.3f, 0.5f); // Drawn on top of a transparent panel; make it just a shade - const ImVec2 BUTTON_PADDING = ImVec2(4.f, 6.f); + namespace GUI + { + + class GamePauseMenu // TODO: Copypaste of 'GameMainMenu' -- cleanup and unify the logic! ~ only_a_ptr, 06/2017 + { + public: + // This class implements hand-made keyboard focus - button count must be known for wrapping + const int NUM_BUTTONS = 3; // Buttons: Resumegame, BackToMenu, Quitgame + const float WINDOW_WIDTH = 200.f; + const ImVec4 WINDOW_BG_COLOR = ImVec4(0.1f, 0.1f, 0.1f, 0.8f); + const ImVec4 BUTTON_BG_COLOR = + ImVec4(0.3f, 0.3f, 0.3f, 0.5f); // Drawn on top of a transparent panel; make it just a shade + const ImVec2 BUTTON_PADDING = ImVec2(4.f, 6.f); - GamePauseMenu(); + GamePauseMenu(); - // Keyboard updates - move up/down and wrap on top/bottom. Initial index is '-1' which means "no focus" - inline void KeyUpPressed() { m_kb_focus_index = (m_kb_focus_index <= 0) ? (NUM_BUTTONS-1) : (m_kb_focus_index - 1); } - inline void KeyDownPressed() { m_kb_focus_index = (m_kb_focus_index < (NUM_BUTTONS - 1)) ? (m_kb_focus_index + 1) : 0; } - inline void EnterKeyPressed() { m_kb_enter_index = m_kb_focus_index; } + // Keyboard updates - move up/down and wrap on top/bottom. Initial index is '-1' which means "no focus" + inline void KeyUpPressed() + { + m_kb_focus_index = (m_kb_focus_index <= 0) ? (NUM_BUTTONS - 1) : (m_kb_focus_index - 1); + } + inline void KeyDownPressed() + { + m_kb_focus_index = (m_kb_focus_index < (NUM_BUTTONS - 1)) ? (m_kb_focus_index + 1) : 0; + } + inline void EnterKeyPressed() + { + m_kb_enter_index = m_kb_focus_index; + } - void Draw(); + void Draw(); -private: - int m_kb_focus_index; // -1 = no focus; 0+ = button index - int m_kb_enter_index; // Index of focus confirmed by ENTER key -}; + private: + int m_kb_focus_index; // -1 = no focus; 0+ = button index + int m_kb_enter_index; // Index of focus confirmed by ENTER key + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_GameSettings.cpp b/source/main/gui/panels/GUI_GameSettings.cpp index a7ad579411..14edd6a81d 100644 --- a/source/main/gui/panels/GUI_GameSettings.cpp +++ b/source/main/gui/panels/GUI_GameSettings.cpp @@ -22,23 +22,20 @@ #include "CacheSystem.h" #include "GUIManager.h" #include "GUIUtils.h" -#include "OgreSubsystem.h" #include "Language.h" +#include "OgreSubsystem.h" void RoR::GUI::GameSettings::Draw() { - bool is_visible = true; - const int flags = ImGuiWindowFlags_NoCollapse; + bool is_visible = true; + const int flags = ImGuiWindowFlags_NoCollapse; ImGui::SetNextWindowSize(ImVec2(640.f, 400.f), ImGuiSetCond_FirstUseEver); ImGui::SetNextWindowPosCenter(ImGuiSetCond_Appearing); ImGui::Begin(_LC("GameSettings", "Game settings"), &is_visible, flags); - if (! is_visible) + if (!is_visible) { this->SetVisible(false); - if (App::app_state.GetActive() == RoR::AppState::MAIN_MENU) - { - App::GetGuiManager()->SetVisible_GameMainMenu(true); - } + if (App::app_state.GetActive() == RoR::AppState::MAIN_MENU) { App::GetGuiManager()->SetVisible_GameMainMenu(true); } ImGui::End(); return; } @@ -48,22 +45,19 @@ void RoR::GUI::GameSettings::Draw() if (ImGui::Button(_LC("GameSettings", "Render System"))) { m_tab = SettingsTab::RENDER_SYSTEM; } ImGui::SameLine(); - if (ImGui::Button(_LC("GameSettings", "General"))) { m_tab = SettingsTab::GENERAL; } + if (ImGui::Button(_LC("GameSettings", "General"))) { m_tab = SettingsTab::GENERAL; } ImGui::SameLine(); - if (ImGui::Button(_LC("GameSettings", "Graphics"))) { m_tab = SettingsTab::GRAPHICS; } + if (ImGui::Button(_LC("GameSettings", "Graphics"))) { m_tab = SettingsTab::GRAPHICS; } ImGui::SameLine(); #ifdef USE_OPENAL - if (ImGui::Button(_LC("GameSettings", "Audio"))) { m_tab = SettingsTab::AUDIO; } + if (ImGui::Button(_LC("GameSettings", "Audio"))) { m_tab = SettingsTab::AUDIO; } ImGui::SameLine(); #endif // USE_OPENAL - if (ImGui::Button(_LC("GameSettings", "Controls"))) { m_tab = SettingsTab::CONTROL; } + if (ImGui::Button(_LC("GameSettings", "Controls"))) { m_tab = SettingsTab::CONTROL; } ImGui::SameLine(); - if (ImGui::Button(_LC("GameSettings", "Diagnostic"))) { m_tab = SettingsTab::DIAG; } + if (ImGui::Button(_LC("GameSettings", "Diagnostic"))) { m_tab = SettingsTab::DIAG; } ImGui::SameLine(); - if (ImGui::Button(_LC("GameSettings", "Update cache"))) - { - App::app_force_cache_udpate.SetActive(true); - } + if (ImGui::Button(_LC("GameSettings", "Update cache"))) { App::app_force_cache_udpate.SetActive(true); } ImGui::PopStyleVar(1); @@ -74,50 +68,43 @@ void RoR::GUI::GameSettings::Draw() { ImGui::TextDisabled(_LC("GameSettings", "Render system (changes require a restart)")); - const auto ogre_root = App::GetOgreSubsystem()->GetOgreRoot(); - const auto render_systems = ogre_root->getAvailableRenderers(); + const auto ogre_root = App::GetOgreSubsystem()->GetOgreRoot(); + const auto render_systems = ogre_root->getAvailableRenderers(); std::string render_system_names; for (auto rs : render_systems) { render_system_names += rs->getName() + '\0'; } - const auto ro = ogre_root->getRenderSystemByName(App::app_rendersys_override.GetActive()); - const auto rs = ro ? ro : ogre_root->getRenderSystem(); - const auto it = std::find(render_systems.begin(), render_systems.end(), rs); - int render_id = it != render_systems.end() ? std::distance(render_systems.begin(), it) : 0; + const auto ro = ogre_root->getRenderSystemByName(App::app_rendersys_override.GetActive()); + const auto rs = ro ? ro : ogre_root->getRenderSystem(); + const auto it = std::find(render_systems.begin(), render_systems.end(), rs); + int render_id = it != render_systems.end() ? std::distance(render_systems.begin(), it) : 0; /* Combobox for selecting the Render System*/ - if (ImGui::Combo(_LC ("GameSettings", "Render System"), &render_id, render_system_names.c_str())) - { - App::app_rendersys_override.SetActive(render_systems[render_id]->getName().c_str()); - } + if (ImGui::Combo(_LC("GameSettings", "Render System"), &render_id, render_system_names.c_str())) + { App::app_rendersys_override.SetActive(render_systems[render_id]->getName().c_str()); } - const auto config_options = ogre_root->getRenderSystem()->getConfigOptions(); - std::set filter = {"Allow NVPerfHUD", "Colour Depth", "Fixed Pipeline Enabled", - "Floating-point mode", "Resource Creation Policy", "VSync Interval", "sRGB Gamma Conversion"}; + const auto config_options = ogre_root->getRenderSystem()->getConfigOptions(); + std::set filter = { + "Allow NVPerfHUD", "Colour Depth", "Fixed Pipeline Enabled", "Floating-point mode", + "Resource Creation Policy", "VSync Interval", "sRGB Gamma Conversion"}; for (auto opt : config_options) { auto co = opt.second; - if (co.immutable) - continue; - if (co.possibleValues.empty()) - continue; - if (filter.find(co.name) != filter.end()) - continue; + if (co.immutable) continue; + if (co.possibleValues.empty()) continue; + if (filter.find(co.name) != filter.end()) continue; std::sort(co.possibleValues.rbegin(), co.possibleValues.rend()); std::string option_values; for (auto value : co.possibleValues) { option_values += value + '\0'; } - const auto it = std::find(co.possibleValues.begin(), co.possibleValues.end(), opt.second.currentValue); - int option_id = it != co.possibleValues.end() ? std::distance(co.possibleValues.begin(), it) : 0; + const auto it = std::find(co.possibleValues.begin(), co.possibleValues.end(), opt.second.currentValue); + int option_id = it != co.possibleValues.end() ? std::distance(co.possibleValues.begin(), it) : 0; if (ImGui::Combo(co.name.c_str(), &option_id, option_values.c_str())) { rs->setConfigOption(co.name, co.possibleValues[option_id]); - if (rs->validateConfigOptions().empty()) - { - ogre_root->saveConfig(); - } + if (rs->validateConfigOptions().empty()) { ogre_root->saveConfig(); } } } } @@ -127,14 +114,15 @@ void RoR::GUI::GameSettings::Draw() #ifndef NOLANG std::vector> languages = LanguageEngine::getSingleton().getLanguages(); - std::string lang_values; + std::string lang_values; for (auto value : languages) { lang_values += value.first + '\0'; } - const auto it = std::find_if(languages.begin(), languages.end(), - [](const std::pair& l) { return l.second == App::app_language.GetActive(); }); - int lang_selection = it != languages.end() ? std::distance(languages.begin(), it) : 0; + const auto it = std::find_if(languages.begin(), languages.end(), [](const std::pair &l) { + return l.second == App::app_language.GetActive(); + }); + int lang_selection = it != languages.end() ? std::distance(languages.begin(), it) : 0; if (ImGui::Combo(_LC("GameSettings", "Language"), &lang_selection, lang_values.c_str())) { App::app_language.SetActive(languages[lang_selection].second.c_str()); @@ -149,13 +137,11 @@ void RoR::GUI::GameSettings::Draw() static std::vector countries; if (countries.empty()) { - for (auto& file : *fl) + for (auto &file : *fl) { std::string country = Ogre::StringUtil::replaceAll(file.filename, ".png", ""); if (country.size() == 2) // RoR protocol limitation - { - countries.push_back(country); - } + { countries.push_back(country); } } std::sort(countries.begin(), countries.end()); } @@ -165,22 +151,19 @@ void RoR::GUI::GameSettings::Draw() country_values += value + '\0'; } const auto it = std::find(countries.begin(), countries.end(), std::string(App::app_country.GetActive())); - int country_selection = it != countries.end() ? std::distance(countries.begin(), it) : 0; + int country_selection = it != countries.end() ? std::distance(countries.begin(), it) : 0; if (ImGui::Combo(_LC("GameSettings", "Country"), &country_selection, country_values.c_str())) - { - App::app_country.SetActive(countries[country_selection].c_str()); - } + { App::app_country.SetActive(countries[country_selection].c_str()); } } - int sshot_select = (std::strcmp(App::app_screenshot_format.GetActive(),"jpg") == 0) ? 1 : 0; // Hardcoded; TODO: list available formats. + int sshot_select = + (std::strcmp(App::app_screenshot_format.GetActive(), "jpg") == 0) ? 1 : 0; // Hardcoded; TODO: list available formats. /* Screenshot format: Can be png or jpg*/ if (ImGui::Combo(_LC("GameSettings", "Screenshot format"), &sshot_select, "png\0jpg\0\0")) - { - App::app_screenshot_format.SetActive((sshot_select == 1) ? "jpg" : "png"); - } + { App::app_screenshot_format.SetActive((sshot_select == 1) ? "jpg" : "png"); } - DrawGTextEdit(App::app_extra_mod_path, _LC("GameSettings", "Extra mod path"), m_buf_app_extra_mod_dir); + DrawGTextEdit(App::app_extra_mod_path, _LC("GameSettings", "Extra mod path"), m_buf_app_extra_mod_dir); DrawGCheckbox(App::app_skip_main_menu, _LC("GameSettings", "Skip main menu")); DrawGCheckbox(App::app_async_physics, _LC("GameSettings", "Async physics")); @@ -190,17 +173,17 @@ void RoR::GUI::GameSettings::Draw() ImGui::TextDisabled(_LC("GameSettings", "Simulation settings")); DrawGCombo(App::sim_gearbox_mode, _LC("GameSettings", "Gearbox mode"), - "Automatic shift\0" - "Manual shift - Auto clutch\0" - "Fully Manual: sequential shift\0" - "Fully manual: stick shift\0" - "Fully Manual: stick shift with ranges\00"); + "Automatic shift\0" + "Manual shift - Auto clutch\0" + "Fully Manual: sequential shift\0" + "Fully manual: stick shift\0" + "Fully Manual: stick shift with ranges\00"); DrawGCheckbox(App::gfx_speedo_digital, _LC("GameSettings", "Digital speedometer")); DrawGCheckbox(App::gfx_speedo_imperial, _LC("GameSettings", "Imperial speedometer")); - //DrawGCheckbox(App::gfx_flexbody_lods, "Enable flexbody LODs"); - //DrawGCheckbox(App::gfx_flexbody_cache, "Enable flexbody cache"); + // DrawGCheckbox(App::gfx_flexbody_lods, "Enable flexbody LODs"); + // DrawGCheckbox(App::gfx_flexbody_cache, "Enable flexbody cache"); DrawGCheckbox(App::sim_spawn_running, _LC("GameSettings", "Engines spawn running")); @@ -225,27 +208,25 @@ void RoR::GUI::GameSettings::Draw() { ImGui::TextDisabled(_LC("GameSettings", "Audio settings")); - static const ALCchar *devices = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); - const ALCchar *device = devices, *next = devices + 1; + static const ALCchar * devices = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); + const ALCchar * device = devices, *next = devices + 1; std::vector audio_devices; while (device && *device != '\0' && next && *next != '\0') { - audio_devices.push_back(device); - size_t len = strlen(device); - device += (len + 1); - next += (len + 2); + audio_devices.push_back(device); + size_t len = strlen(device); + device += (len + 1); + next += (len + 2); } - const auto it = std::find(audio_devices.begin(), audio_devices.end(), App::audio_device_name.GetActive()); - int device_id = it != audio_devices.end() ? std::distance(audio_devices.begin(), it) : 0; + const auto it = std::find(audio_devices.begin(), audio_devices.end(), App::audio_device_name.GetActive()); + int device_id = it != audio_devices.end() ? std::distance(audio_devices.begin(), it) : 0; if (ImGui::Combo(_LC("GameSettings", "Audio device"), &device_id, devices)) - { - App::audio_device_name.SetActive(audio_devices[device_id].c_str()); - } + { App::audio_device_name.SetActive(audio_devices[device_id].c_str()); } - DrawGCheckbox(App::audio_enable_creak, _LC("GameSettings", "Creak sound")); - DrawGCheckbox(App::audio_menu_music, _LC("GameSettings", "Main menu music")); + DrawGCheckbox(App::audio_enable_creak, _LC("GameSettings", "Creak sound")); + DrawGCheckbox(App::audio_menu_music, _LC("GameSettings", "Main menu music")); DrawGFloatSlider(App::audio_master_volume, _LC("GameSettings", "Master volume"), 0, 1); } #endif // USE_OPENAL @@ -254,71 +235,70 @@ void RoR::GUI::GameSettings::Draw() ImGui::TextDisabled(_LC("GameSettings", "Video settings")); DrawGCombo(App::gfx_flares_mode, _LC("GameSettings", "Lights"), - "None (fastest)\0" - "No light sources\0" - "Only current vehicle, main lights\0" - "All vehicles, main lights\0" - "All vehicles, all lights\0\0"); + "None (fastest)\0" + "No light sources\0" + "Only current vehicle, main lights\0" + "All vehicles, main lights\0" + "All vehicles, all lights\0\0"); DrawGCombo(App::gfx_shadow_type, _LC("GameSettings", "Shadow type (requires restart)"), - "Disabled\0" - "PSSM\0\0"); + "Disabled\0" + "PSSM\0\0"); if (App::gfx_shadow_type.GetActive() != GfxShadowType::NONE) { DrawGCheckbox(App::gfx_reduce_shadows, _LC("GameSettings", "Shadow optimizations")); if (App::gfx_shadow_type.GetActive() == GfxShadowType::PSSM) - { - DrawGIntSlider(App::gfx_shadow_quality, _LC("GameSettings", "Shadow quality"), 0, 3); - } + { DrawGIntSlider(App::gfx_shadow_quality, _LC("GameSettings", "Shadow quality"), 0, 3); } } DrawGCombo(App::gfx_sky_mode, "Sky gfx", - "Sandstorm (fastest)\0" - "Caelum (best looking, slower)\0" - "SkyX (best looking, slower)\0\0"); + "Sandstorm (fastest)\0" + "Caelum (best looking, slower)\0" + "SkyX (best looking, slower)\0\0"); if (App::gfx_sky_mode.GetActive() != GfxSkyMode::SKYX) - { - DrawGIntSlider(App::gfx_sight_range, _LC("GameSettings", "Sight range (meters)"), 100, 5000); - } + { DrawGIntSlider(App::gfx_sight_range, _LC("GameSettings", "Sight range (meters)"), 100, 5000); } - DrawGCombo(App::gfx_texture_filter , _LC("GameSettings", "Texture filtering"), - "None\0" - "Bilinear\0" - "Trilinear\0" - "Anisotropic\0\0"); + DrawGCombo(App::gfx_texture_filter, _LC("GameSettings", "Texture filtering"), + "None\0" + "Bilinear\0" + "Trilinear\0" + "Anisotropic\0\0"); if (App::gfx_texture_filter.GetActive() == GfxTexFilter::ANISOTROPIC) { int anisotropy = Ogre::Math::Clamp(App::gfx_anisotropy.GetActive(), 1, 16); - int selection = std::log2(anisotropy); - if (ImGui::Combo(_LC("GameSettings", "Anisotropy"), &selection, "1\0""2\0""4\0""8\0""16\0\0")) - { - App::gfx_anisotropy.SetActive(std::pow(2, selection)); - } + int selection = std::log2(anisotropy); + if (ImGui::Combo(_LC("GameSettings", "Anisotropy"), &selection, + "1\0" + "2\0" + "4\0" + "8\0" + "16\0\0")) + { App::gfx_anisotropy.SetActive(std::pow(2, selection)); } } DrawGCombo(App::gfx_vegetation_mode, _LC("GameSettings", "Vegetation density"), - "None\0" - "20%\0" - "50%\0" - "Full\0\0"); + "None\0" + "20%\0" + "50%\0" + "Full\0\0"); DrawGCombo(App::gfx_water_mode, _LC("GameSettings", "Water gfx"), - "None\0" - "Basic (fastest)\0" - "Reflection\0" - "Reflection + refraction (speed optimized)\0" - "Reflection + refraction (quality optimized)\0" - "HydraX\0\0"); + "None\0" + "Basic (fastest)\0" + "Reflection\0" + "Reflection + refraction (speed optimized)\0" + "Reflection + refraction (quality optimized)\0" + "HydraX\0\0"); - DrawGIntSlider(App::gfx_fps_limit, _LC("GameSettings", "FPS limit"), 0, 240); + DrawGIntSlider(App::gfx_fps_limit, _LC("GameSettings", "FPS limit"), 0, 240); - DrawGIntCheck(App::gfx_particles_mode, _LC("GameSettings", "Enable particle gfx")); - DrawGIntCheck(App::gfx_skidmarks_mode, _LC("GameSettings", "Enable skidmarks")); + DrawGIntCheck(App::gfx_particles_mode, _LC("GameSettings", "Enable particle gfx")); + DrawGIntCheck(App::gfx_skidmarks_mode, _LC("GameSettings", "Enable skidmarks")); - DrawGCheckbox(App::gfx_envmap_enabled, _LC("GameSettings", "Realtime reflections")); + DrawGCheckbox(App::gfx_envmap_enabled, _LC("GameSettings", "Realtime reflections")); if (App::gfx_envmap_enabled.GetActive()) { ImGui::PushItemWidth(125.f); // Width includes [+/-] buttons @@ -327,17 +307,15 @@ void RoR::GUI::GameSettings::Draw() } DrawGCheckbox(App::gfx_enable_videocams, _LC("GameSettings", "Render video cameras")); - DrawGCheckbox(App::gfx_surveymap_icons, _LC("GameSettings", "Overview map icons")); + DrawGCheckbox(App::gfx_surveymap_icons, _LC("GameSettings", "Overview map icons")); if (App::gfx_surveymap_icons.GetActive()) - { - DrawGCheckbox(App::gfx_declutter_map, _LC("GameSettings", "Declutter overview map")); - } - DrawGCheckbox(App::gfx_water_waves, _LC("GameSettings", "Waves on water")); + { DrawGCheckbox(App::gfx_declutter_map, _LC("GameSettings", "Declutter overview map")); } + DrawGCheckbox(App::gfx_water_waves, _LC("GameSettings", "Waves on water")); DrawGCombo(App::gfx_extcam_mode, "Exterior camera mode", - "None\0" - "Static\0" - "Pitching\0\0"); + "None\0" + "Static\0" + "Pitching\0\0"); DrawGIntSlider(App::gfx_camera_height, _LC("GameSettings", "Static camera height (meters)"), 1, 50); DrawGIntSlider(App::gfx_fov_external, _LC("GameSettings", "Exterior field of view"), 10, 120); @@ -349,46 +327,41 @@ void RoR::GUI::GameSettings::Draw() int physics_fps = std::round(1.0f / App::diag_physics_dt.GetActive()); if (ImGui::SliderInt(_LC("GameSettings", "Physics frames per second"), &physics_fps, 2000, 10000)) - { - App::diag_physics_dt.SetActive(Ogre::Math::Clamp(1.0f / physics_fps, 0.0001f, 0.0005f)); - } - DrawGTextEdit(App::diag_preset_terrain, _LC("GameSettings", "Preselected terrain"), m_buf_diag_preset_terrain, false); - DrawGTextEdit(App::diag_preset_vehicle, _LC("GameSettings", "Preselected vehicle"), m_buf_diag_preset_vehicle, true); - DrawGTextEdit(App::diag_preset_veh_config, _LC("GameSettings", "Presel. veh. config"), m_buf_diag_preset_veh_config); - DrawGCheckbox(App::diag_preset_veh_enter, _LC("GameSettings", "Enter preselected vehicle")); + { App::diag_physics_dt.SetActive(Ogre::Math::Clamp(1.0f / physics_fps, 0.0001f, 0.0005f)); } + DrawGTextEdit(App::diag_preset_terrain, _LC("GameSettings", "Preselected terrain"), m_buf_diag_preset_terrain, false); + DrawGTextEdit(App::diag_preset_vehicle, _LC("GameSettings", "Preselected vehicle"), m_buf_diag_preset_vehicle, true); + DrawGTextEdit(App::diag_preset_veh_config, _LC("GameSettings", "Presel. veh. config"), m_buf_diag_preset_veh_config); + DrawGCheckbox(App::diag_preset_veh_enter, _LC("GameSettings", "Enter preselected vehicle")); DrawGCheckbox(App::diag_auto_spawner_report, _LC("GameSettings", "Auto actor spawner report")); DrawGCheckbox(App::diag_rig_log_node_import, _LC("GameSettings", "Log node import (spawn)")); - DrawGCheckbox(App::diag_rig_log_node_stats, _LC("GameSettings", "Log node stats (spawn)")); - DrawGCheckbox(App::diag_rig_log_messages, _LC("GameSettings", "Log messages (spawn)")); - DrawGCheckbox(App::diag_camera, _LC("GameSettings", "Debug camera (rails)")); - DrawGCheckbox(App::diag_collisions, _LC("GameSettings", "Debug collisions")); - DrawGCheckbox(App::diag_truck_mass, _LC("GameSettings", "Debug actor mass")); - DrawGCheckbox(App::diag_envmap, _LC("GameSettings", "Debug realtime reflections")); - DrawGCheckbox(App::diag_videocameras, _LC("GameSettings", "Debug videocameras")); - DrawGCheckbox(App::diag_warning_texture, _LC("GameSettings", "Debug textures")); - DrawGCheckbox(App::diag_hide_broken_beams, _LC("GameSettings", "Hide broken beams")); - DrawGCheckbox(App::diag_hide_wheel_info, _LC("GameSettings", "Hide wheel info")); - DrawGCheckbox(App::diag_hide_wheels, _LC("GameSettings", "Hide wheels")); - DrawGCheckbox(App::diag_hide_nodes, _LC("GameSettings", "Hide nodes")); - DrawGCheckbox(App::diag_log_console_echo, _LC("GameSettings", "Echo log to console")); - DrawGCheckbox(App::diag_log_beam_break, _LC("GameSettings", "Log beam breaking")); - DrawGCheckbox(App::diag_log_beam_deform, _LC("GameSettings", "Log beam deforming")); - DrawGCheckbox(App::diag_log_beam_trigger, _LC("GameSettings", "Log beam triggers")); - if (ImGui::Button(_LC("GameSettings", "Rebuild cache"))) - { - App::app_force_cache_purge.SetActive(true); - } + DrawGCheckbox(App::diag_rig_log_node_stats, _LC("GameSettings", "Log node stats (spawn)")); + DrawGCheckbox(App::diag_rig_log_messages, _LC("GameSettings", "Log messages (spawn)")); + DrawGCheckbox(App::diag_camera, _LC("GameSettings", "Debug camera (rails)")); + DrawGCheckbox(App::diag_collisions, _LC("GameSettings", "Debug collisions")); + DrawGCheckbox(App::diag_truck_mass, _LC("GameSettings", "Debug actor mass")); + DrawGCheckbox(App::diag_envmap, _LC("GameSettings", "Debug realtime reflections")); + DrawGCheckbox(App::diag_videocameras, _LC("GameSettings", "Debug videocameras")); + DrawGCheckbox(App::diag_warning_texture, _LC("GameSettings", "Debug textures")); + DrawGCheckbox(App::diag_hide_broken_beams, _LC("GameSettings", "Hide broken beams")); + DrawGCheckbox(App::diag_hide_wheel_info, _LC("GameSettings", "Hide wheel info")); + DrawGCheckbox(App::diag_hide_wheels, _LC("GameSettings", "Hide wheels")); + DrawGCheckbox(App::diag_hide_nodes, _LC("GameSettings", "Hide nodes")); + DrawGCheckbox(App::diag_log_console_echo, _LC("GameSettings", "Echo log to console")); + DrawGCheckbox(App::diag_log_beam_break, _LC("GameSettings", "Log beam breaking")); + DrawGCheckbox(App::diag_log_beam_deform, _LC("GameSettings", "Log beam deforming")); + DrawGCheckbox(App::diag_log_beam_trigger, _LC("GameSettings", "Log beam triggers")); + if (ImGui::Button(_LC("GameSettings", "Rebuild cache"))) { App::app_force_cache_purge.SetActive(true); } } else if (m_tab == SettingsTab::CONTROL) { ImGui::TextDisabled(_LC("GameSettings", "Controller options")); DrawGCombo(App::io_input_grab_mode, _LC("GameSettings", "Input grab mode"), - "None\0" - "All\0" - "Dynamic\0\0"); + "None\0" + "All\0" + "Dynamic\0\0"); - DrawGFloatSlider(App::io_analog_smoothing, _LC("GameSettings", "Analog Input Smoothing"), 0.5f, 2.0f); + DrawGFloatSlider(App::io_analog_smoothing, _LC("GameSettings", "Analog Input Smoothing"), 0.5f, 2.0f); DrawGFloatSlider(App::io_analog_sensitivity, _LC("GameSettings", "Analog Input Sensitivity"), 0.5f, 2.0f); DrawGCheckbox(App::io_arcade_controls, _LC("GameSettings", "Use arcade controls")); @@ -409,8 +382,8 @@ void RoR::GUI::GameSettings::Draw() { DrawGTextEdit(App::io_outgauge_ip, _LC("GameSettings", "OutGauge IP"), m_buf_io_outgauge_ip); ImGui::PushItemWidth(125.f); - DrawGIntBox(App::io_outgauge_port, _LC("GameSettings", "OutGauge port")); - DrawGIntBox(App::io_outgauge_id, _LC("GameSettings", "OutGauge ID")); + DrawGIntBox(App::io_outgauge_port, _LC("GameSettings", "OutGauge port")); + DrawGIntBox(App::io_outgauge_id, _LC("GameSettings", "OutGauge ID")); DrawGFloatBox(App::io_outgauge_delay, _LC("GameSettings", "OutGauge delay")); ImGui::PopItemWidth(); } diff --git a/source/main/gui/panels/GUI_GameSettings.h b/source/main/gui/panels/GUI_GameSettings.h index 130c3617ae..1be84d78d1 100644 --- a/source/main/gui/panels/GUI_GameSettings.h +++ b/source/main/gui/panels/GUI_GameSettings.h @@ -22,38 +22,50 @@ #include "Application.h" #include "OgreImGui.h" -namespace RoR { -namespace GUI { - -class GameSettings +namespace RoR { -public: - enum SettingsTab { RENDER_SYSTEM, GENERAL, GRAPHICS, AUDIO, CONTROL, DIAG }; + namespace GUI + { - GameSettings(): m_is_visible(false), m_tab(SettingsTab::RENDER_SYSTEM) {} + class GameSettings + { + public: + enum SettingsTab + { + RENDER_SYSTEM, + GENERAL, + GRAPHICS, + AUDIO, + CONTROL, + DIAG + }; - void Draw(); + GameSettings() : m_is_visible(false), m_tab(SettingsTab::RENDER_SYSTEM) + { + } - inline bool IsVisible() const { return m_is_visible; } - inline void SetVisible(bool v) - { - if (!v) - { - m_tab = SettingsTab::RENDER_SYSTEM; - } - m_is_visible = v; - } - -private: - bool m_is_visible; - SettingsTab m_tab; - - Str<100> m_buf_diag_preset_terrain; - Str<100> m_buf_diag_preset_vehicle; - Str<100> m_buf_diag_preset_veh_config; - Str<300> m_buf_app_extra_mod_dir; - Str<50> m_buf_io_outgauge_ip; -}; - -} // namespace GUI + void Draw(); + + inline bool IsVisible() const + { + return m_is_visible; + } + inline void SetVisible(bool v) + { + if (!v) { m_tab = SettingsTab::RENDER_SYSTEM; } + m_is_visible = v; + } + + private: + bool m_is_visible; + SettingsTab m_tab; + + Str<100> m_buf_diag_preset_terrain; + Str<100> m_buf_diag_preset_vehicle; + Str<100> m_buf_diag_preset_veh_config; + Str<300> m_buf_app_extra_mod_dir; + Str<50> m_buf_io_outgauge_ip; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_LoadingWindow.cpp b/source/main/gui/panels/GUI_LoadingWindow.cpp index dadd22873b..75e55cc768 100644 --- a/source/main/gui/panels/GUI_LoadingWindow.cpp +++ b/source/main/gui/panels/GUI_LoadingWindow.cpp @@ -18,42 +18,44 @@ along with Rigs of Rods. If not, see . */ - #include "GUI_LoadingWindow.h" #include "GUIManager.h" #include "Language.h" #include "Utils.h" -namespace RoR { -namespace GUI { - -LoadingWindow::LoadingWindow() -{ - initialiseByAttributes(this); - - MyGUI::IntSize gui_area = MyGUI::RenderManager::getInstance().getViewSize(); - mMainWidget->setPosition(gui_area.width / 2 - mMainWidget->getWidth() / 2, gui_area.height / 2 - mMainWidget->getHeight() / 2); - ((MyGUI::Window*)mMainWidget)->setCaption(_L("Loading ...")); - mMainWidget->setVisible(false); -} - -void LoadingWindow::setProgress(int _percent, const Ogre::UTFString& _text, bool force_update) +namespace RoR { - mMainWidget->setVisible(true); - mInfoStaticText->setCaption(convertToMyGUIString(_text)); - - mBarProgress->setProgressAutoTrack(false); - mBarProgress->setProgressPosition(_percent); - - if (force_update || m_timer.getMilliseconds() > 10) + namespace GUI { - m_timer.reset(); - // we must pump the window messages, otherwise the window will get white on Vista ... - OgreBites::WindowEventUtilities::messagePump(); - Ogre::Root::getSingleton().renderOneFrame(); - } -} - -} // namespace GUI + + LoadingWindow::LoadingWindow() + { + initialiseByAttributes(this); + + MyGUI::IntSize gui_area = MyGUI::RenderManager::getInstance().getViewSize(); + mMainWidget->setPosition(gui_area.width / 2 - mMainWidget->getWidth() / 2, + gui_area.height / 2 - mMainWidget->getHeight() / 2); + ((MyGUI::Window *)mMainWidget)->setCaption(_L("Loading ...")); + mMainWidget->setVisible(false); + } + + void LoadingWindow::setProgress(int _percent, const Ogre::UTFString &_text, bool force_update) + { + mMainWidget->setVisible(true); + mInfoStaticText->setCaption(convertToMyGUIString(_text)); + + mBarProgress->setProgressAutoTrack(false); + mBarProgress->setProgressPosition(_percent); + + if (force_update || m_timer.getMilliseconds() > 10) + { + m_timer.reset(); + // we must pump the window messages, otherwise the window will get white on Vista ... + OgreBites::WindowEventUtilities::messagePump(); + Ogre::Root::getSingleton().renderOneFrame(); + } + } + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_LoadingWindow.h b/source/main/gui/panels/GUI_LoadingWindow.h index 8ffece238f..406327ec65 100644 --- a/source/main/gui/panels/GUI_LoadingWindow.h +++ b/source/main/gui/panels/GUI_LoadingWindow.h @@ -18,7 +18,6 @@ along with Rigs of Rods. If not, see . */ - #pragma once #include "RoRPrerequisites.h" @@ -27,35 +26,39 @@ #include #include -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(LoadingWindow, "LoadingWindow.layout"); - -class LoadingWindow : - public wraps::BaseLayout, - public ZeroedMemoryAllocator +namespace RoR { -public: + namespace GUI + { - LoadingWindow(); + ATTRIBUTE_CLASS_LAYOUT(LoadingWindow, "LoadingWindow.layout"); - void setProgress(int _percent, const Ogre::UTFString& _text = "", bool force_update = true); + class LoadingWindow : public wraps::BaseLayout, public ZeroedMemoryAllocator + { + public: + LoadingWindow(); - void SetVisible(bool v) { mMainWidget->setVisible(v); } - bool IsVisible() { return mMainWidget->getVisible(); } + void setProgress(int _percent, const Ogre::UTFString &_text = "", bool force_update = true); -private: + void SetVisible(bool v) + { + mMainWidget->setVisible(v); + } + bool IsVisible() + { + return mMainWidget->getVisible(); + } - ATTRIBUTE_FIELD_WIDGET_NAME(LoadingWindow, mBarProgress, "Bar"); + private: + ATTRIBUTE_FIELD_WIDGET_NAME(LoadingWindow, mBarProgress, "Bar"); - MyGUI::ProgressBar* mBarProgress; - ATTRIBUTE_FIELD_WIDGET_NAME(LoadingWindow, mInfoStaticText, "Info"); + MyGUI::ProgressBar *mBarProgress; + ATTRIBUTE_FIELD_WIDGET_NAME(LoadingWindow, mInfoStaticText, "Info"); - MyGUI::TextBox* mInfoStaticText; + MyGUI::TextBox *mInfoStaticText; - Ogre::Timer m_timer; -}; + Ogre::Timer m_timer; + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_MainSelector.cpp b/source/main/gui/panels/GUI_MainSelector.cpp index 16d1f530cf..45ca517487 100644 --- a/source/main/gui/panels/GUI_MainSelector.cpp +++ b/source/main/gui/panels/GUI_MainSelector.cpp @@ -40,19 +40,15 @@ using namespace RoR; using namespace GUI; -#define CLASS MainSelector -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) +#define CLASS MainSelector +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) -CLASS::CLASS() : - m_keys_bound(false) - , m_selected_entry(nullptr) - , m_selection_done(true) - , m_searching(false) +CLASS::CLASS() : m_keys_bound(false), m_selected_entry(nullptr), m_selection_done(true), m_searching(false) { MAIN_WIDGET->setVisible(false); MyGUI::WindowPtr win = dynamic_cast(mMainWidget); - win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::NotifyWindowButtonPressed); //The "X" button thing + win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::NotifyWindowButtonPressed); // The "X" button thing win->eventWindowChangeCoord += MyGUI::newDelegate(this, &CLASS::NotifyWindowChangeCoord); MyGUI::IntSize windowSize = MAIN_WIDGET->getSize(); @@ -73,7 +69,7 @@ CLASS::CLASS() : MAIN_WIDGET->setPosition((parentSize.width - windowSize.width) / 2, (parentSize.height - windowSize.height) / 2); - //From old file + // From old file MAIN_WIDGET->setCaption(_L("Loader")); m_SearchLine->setCaption(""); @@ -117,16 +113,14 @@ void CLASS::BindKeys(bool bind) } } -void CLASS::NotifyWindowChangeCoord(MyGUI::Window* _sender) +void CLASS::NotifyWindowChangeCoord(MyGUI::Window *_sender) { - if (m_Preview->isVisible()) - ResizePreviewImage(); + if (m_Preview->isVisible()) ResizePreviewImage(); } void CLASS::EventKeyButtonPressed_Main(MyGUI::WidgetPtr _sender, MyGUI::KeyCode _key, MyGUI::Char _char) { - if (!mMainWidget->getVisible()) - return; + if (!mMainWidget->getVisible()) return; int cid = (int)m_Type->getIndexSelected(); int iid = (int)m_Model->getIndexSelected(); @@ -161,18 +155,12 @@ void CLASS::EventKeyButtonPressed_Main(MyGUI::WidgetPtr _sender, MyGUI::KeyCode if (_key == MyGUI::KeyCode::ArrowLeft) { newitem--; - if (cid == 0) - { - newitem = (int)m_Type->getItemCount() - 1; - } + if (cid == 0) { newitem = (int)m_Type->getItemCount() - 1; } } else { newitem++; - if (cid == (int)m_Type->getItemCount() - 1) - { - newitem = 0; - } + if (cid == (int)m_Type->getItemCount() - 1) { newitem = 0; } } try @@ -195,11 +183,8 @@ void CLASS::EventKeyButtonPressed_Main(MyGUI::WidgetPtr _sender, MyGUI::KeyCode else newitem++; - //Annd fixed :3 - if (iid == 0 && _key == MyGUI::KeyCode::ArrowUp) - { - newitem = (int)m_Model->getItemCount() - 1; - } + // Annd fixed :3 + if (iid == 0 && _key == MyGUI::KeyCode::ArrowUp) { newitem = (int)m_Model->getItemCount() - 1; } else if (iid == (int)m_Model->getItemCount() - 1 && _key == MyGUI::KeyCode::ArrowDown) { newitem = 0; @@ -218,17 +203,11 @@ void CLASS::EventKeyButtonPressed_Main(MyGUI::WidgetPtr _sender, MyGUI::KeyCode EventListChangePositionModelList(m_Model, newitem); // fix cursor position - if (searching) - { - m_SearchLine->setTextCursor(m_SearchLine->getTextLength()); - } + if (searching) { m_SearchLine->setTextCursor(m_SearchLine->getTextLength()); } } else if (_key == MyGUI::KeyCode::Return) { - if (m_loader_type == LT_Skin || (m_loader_type != LT_Skin && m_selected_entry)) - { - OnSelectionDone(); - } + if (m_loader_type == LT_Skin || (m_loader_type != LT_Skin && m_selected_entry)) { OnSelectionDone(); } } } @@ -243,10 +222,7 @@ void CLASS::Cancel() App::GetGuiManager()->SetVisible_GameMainMenu(true); } - if (App::sim_state.GetActive() == SimState::SELECTING) - { - App::sim_state.SetActive(SimState::RUNNING); - } + if (App::sim_state.GetActive() == SimState::SELECTING) { App::sim_state.SetActive(SimState::RUNNING); } } void CLASS::EventMouseButtonClickOkButton(MyGUI::WidgetPtr _sender) @@ -261,19 +237,14 @@ void CLASS::EventMouseButtonClickCancelButton(MyGUI::WidgetPtr _sender) void CLASS::EventComboChangePositionTypeComboBox(MyGUI::ComboBoxPtr _sender, size_t _index) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; - if (_index < 0 || _index >= m_Type->getItemCount()) - return; + if (_index < 0 || _index >= m_Type->getItemCount()) return; int categoryID = *m_Type->getItemDataAt(_index); m_SearchLine->setCaption(_L("Search ...")); OnCategorySelected(categoryID); - if (!m_searching) - { - m_category_index[m_loader_type] = static_cast(_index); - } + if (!m_searching) { m_category_index[m_loader_type] = static_cast(_index); } } void CLASS::EventListChangePositionModelListAccept(MyGUI::ListPtr _sender, size_t _index) @@ -284,54 +255,41 @@ void CLASS::EventListChangePositionModelListAccept(MyGUI::ListPtr _sender, size_ void CLASS::EventListChangePositionModelList(MyGUI::ListPtr _sender, size_t _index) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; - if (_index < 0 || _index >= m_Model->getItemCount()) - return; + if (_index < 0 || _index >= m_Model->getItemCount()) return; int entryID = *m_Model->getItemDataAt(_index); OnEntrySelected(entryID); - if (!m_searching) - { - m_entry_index[m_loader_type] = static_cast(_index); - } + if (!m_searching) { m_entry_index[m_loader_type] = static_cast(_index); } } void CLASS::EventComboAcceptConfigComboBox(MyGUI::ComboBoxPtr _sender, size_t _index) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; - if (_index < 0 || _index >= m_Config->getItemCount()) - return; + if (_index < 0 || _index >= m_Config->getItemCount()) return; m_actor_spawn_rq.asr_config = *m_Config->getItemDataAt(_index); } -template -struct sort_cats +template struct sort_cats { - bool operator ()(std::pair const& a, std::pair const& b) const + bool operator()(std::pair const &a, std::pair const &b) const { - if (a.first == CacheSystem::CID_All) - return true; - if (b.first == CacheSystem::CID_All) - return false; - if (a.first == CacheSystem::CID_Fresh) - return true; - if (b.first == CacheSystem::CID_Fresh) - return false; + if (a.first == CacheSystem::CID_All) return true; + if (b.first == CacheSystem::CID_All) return false; + if (a.first == CacheSystem::CID_Fresh) return true; + if (b.first == CacheSystem::CID_Fresh) return false; return a.second < b.second; } }; -template -struct sort_entries +template struct sort_entries { - bool operator ()(CacheEntry const& a, CacheEntry const& b) const + bool operator()(CacheEntry const &a, CacheEntry const &b) const { - Ogre::String first = a.dname; + Ogre::String first = a.dname; Ogre::String second = b.dname; Ogre::StringUtil::toLowerCase(first); Ogre::StringUtil::toLowerCase(second); @@ -341,7 +299,7 @@ struct sort_entries struct sort_search_results { - bool operator ()(std::pair const& a, std::pair const& b) const + bool operator()(std::pair const &a, std::pair const &b) const { return a.second < b.second; } @@ -355,23 +313,25 @@ void CLASS::UpdateGuiData() m_entries.clear(); std::vector timestamps; - std::vector entries = RoR::App::GetCacheSystem()->GetEntries(); + std::vector entries = RoR::App::GetCacheSystem()->GetEntries(); std::sort(entries.begin(), entries.end(), sort_entries()); for (std::vector::iterator it = entries.begin(); it != entries.end(); it++) { bool add = false; - if (it->fext == "terrn2") - add = (m_loader_type == LT_Terrain); + if (it->fext == "terrn2") add = (m_loader_type == LT_Terrain); if (it->fext == "skin") add = (m_loader_type == LT_Skin && it->guid == m_actor_spawn_rq.asr_cache_entry->guid); else if (it->fext == "truck") - add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Vehicle || m_loader_type == LT_Truck || m_loader_type == LT_Network || m_loader_type == LT_NetworkWithBoat); + add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Vehicle || m_loader_type == LT_Truck || + m_loader_type == LT_Network || m_loader_type == LT_NetworkWithBoat); else if (it->fext == "car") - add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Vehicle || m_loader_type == LT_Truck || m_loader_type == LT_Car || m_loader_type == LT_Network || m_loader_type == LT_NetworkWithBoat); + add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Vehicle || m_loader_type == LT_Truck || + m_loader_type == LT_Car || m_loader_type == LT_Network || m_loader_type == LT_NetworkWithBoat); else if (it->fext == "boat") add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Boat || m_loader_type == LT_NetworkWithBoat); else if (it->fext == "airplane") - add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Airplane || m_loader_type == LT_Network || m_loader_type == LT_NetworkWithBoat); + add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Airplane || m_loader_type == LT_Network || + m_loader_type == LT_NetworkWithBoat); else if (it->fext == "trailer") add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Trailer || m_loader_type == LT_Extension); else if (it->fext == "train") @@ -379,16 +339,13 @@ void CLASS::UpdateGuiData() else if (it->fext == "load") add = (m_loader_type == LT_AllBeam || m_loader_type == LT_Load || m_loader_type == LT_Extension); - if (!add) - continue; + if (!add) continue; // remove invalid category ID's - if (it->categoryid >= CacheSystem::CID_Max) - it->categoryid = -1; + if (it->categoryid >= CacheSystem::CID_Max) it->categoryid = -1; // category unsorted - if (it->categoryid == -1) - it->categoryid = CacheSystem::CID_Unsorted; + if (it->categoryid == -1) it->categoryid = CacheSystem::CID_Unsorted; mCategoryUsage[it->categoryid]++; @@ -410,26 +367,23 @@ void CLASS::UpdateGuiData() } } - int tally_categories = 0, current_category = 0; - std::map cats = RoR::App::GetCacheSystem()->GetCategories(); + int tally_categories = 0, current_category = 0; + std::map cats = RoR::App::GetCacheSystem()->GetCategories(); std::vector> sorted_cats(cats.begin(), cats.end()); std::sort(sorted_cats.begin(), sorted_cats.end(), sort_cats()); - for (const auto& cat : sorted_cats) + for (const auto &cat : sorted_cats) { - if (mCategoryUsage[cat.first] > 0) - tally_categories++; + if (mCategoryUsage[cat.first] > 0) tally_categories++; } - for (const auto& cat : sorted_cats) + for (const auto &cat : sorted_cats) { int num_elements = mCategoryUsage[cat.first]; if (num_elements > 0) { Ogre::UTFString title = _L("unknown"); - if (!cat.second.empty()) - { - title = _L(cat.second.c_str()); - } - Ogre::UTFString txt = U("[") + TOUTFSTRING(++current_category) + U("/") + TOUTFSTRING(tally_categories) + U("] (") + TOUTFSTRING(num_elements) + U(") ") + title; + if (!cat.second.empty()) { title = _L(cat.second.c_str()); } + Ogre::UTFString txt = U("[") + TOUTFSTRING(++current_category) + U("/") + TOUTFSTRING(tally_categories) + U("] (") + + TOUTFSTRING(num_elements) + U(") ") + title; m_Type->addItem(convertToMyGUIString(txt), cat.first); } } @@ -442,7 +396,7 @@ void CLASS::UpdateGuiData() } } -size_t CLASS::SearchCompare(Ogre::String searchString, CacheEntry* ce) +size_t CLASS::SearchCompare(Ogre::String searchString, CacheEntry *ce) { if (searchString.find(":") == Ogre::String::npos) { @@ -451,20 +405,17 @@ size_t CLASS::SearchCompare(Ogre::String searchString, CacheEntry* ce) // the name Ogre::String dname_lower = ce->dname; Ogre::StringUtil::toLowerCase(dname_lower); - if (dname_lower.find(searchString) != Ogre::String::npos) - return dname_lower.find(searchString); + if (dname_lower.find(searchString) != Ogre::String::npos) return dname_lower.find(searchString); // the filename Ogre::String fname_lower = ce->fname; Ogre::StringUtil::toLowerCase(fname_lower); - if (fname_lower.find(searchString) != Ogre::String::npos) - return 100 + fname_lower.find(searchString); + if (fname_lower.find(searchString) != Ogre::String::npos) return 100 + fname_lower.find(searchString); // the description Ogre::String desc = ce->description; Ogre::StringUtil::toLowerCase(desc); - if (desc.find(searchString) != Ogre::String::npos) - return 200 + desc.find(searchString); + if (desc.find(searchString) != Ogre::String::npos) return 200 + desc.find(searchString); // the authors if (!ce->authors.empty()) @@ -475,14 +426,12 @@ size_t CLASS::SearchCompare(Ogre::String searchString, CacheEntry* ce) // author name Ogre::String aname = it->name; Ogre::StringUtil::toLowerCase(aname); - if (aname.find(searchString) != Ogre::String::npos) - return 300 + aname.find(searchString); + if (aname.find(searchString) != Ogre::String::npos) return 300 + aname.find(searchString); // author email Ogre::String aemail = it->email; Ogre::StringUtil::toLowerCase(aemail); - if (aemail.find(searchString) != Ogre::String::npos) - return 400 + aemail.find(searchString); + if (aemail.find(searchString) != Ogre::String::npos) return 400 + aemail.find(searchString); } } return Ogre::String::npos; @@ -490,8 +439,7 @@ size_t CLASS::SearchCompare(Ogre::String searchString, CacheEntry* ce) else { Ogre::StringVector v = Ogre::StringUtil::split(searchString, ":"); - if (v.size() < 2) - return Ogre::String::npos; //invalid syntax + if (v.size() < 2) return Ogre::String::npos; // invalid syntax if (v[0] == "guid") { @@ -510,14 +458,12 @@ size_t CLASS::SearchCompare(Ogre::String searchString, CacheEntry* ce) // author name Ogre::String aname = it->name; Ogre::StringUtil::toLowerCase(aname); - if (aname.find(v[1]) != Ogre::String::npos) - return aname.find(v[1]); + if (aname.find(v[1]) != Ogre::String::npos) return aname.find(v[1]); // author email Ogre::String aemail = it->email; Ogre::StringUtil::toLowerCase(aemail); - if (aemail.find(v[1]) != Ogre::String::npos) - return aemail.find(v[1]); + if (aemail.find(v[1]) != Ogre::String::npos) return aemail.find(v[1]); } } return Ogre::String::npos; @@ -541,33 +487,28 @@ void CLASS::OnCategorySelected(int categoryID) { m_Model->removeAllItems(); - std::vector> entries; + std::vector> entries; entries.reserve(m_entries.size()); if (categoryID == CacheSystem::CID_SearchResults) { Ogre::String search_cmd = m_SearchLine->getCaption(); Ogre::StringUtil::toLowerCase(search_cmd); - for (auto& entry : m_entries) + for (auto &entry : m_entries) { size_t score = SearchCompare(search_cmd, &entry); - if (score != Ogre::String::npos) - { - entries.push_back(std::make_pair(&entry, score)); - } + if (score != Ogre::String::npos) { entries.push_back(std::make_pair(&entry, score)); } } std::stable_sort(entries.begin(), entries.end(), sort_search_results()); } else { - for (auto& entry : m_entries) + for (auto &entry : m_entries) { - if (entry.categoryid == categoryID || categoryID == CacheSystem::CID_All - || (categoryID == CacheSystem::CID_Fresh && - (entry.addtimestamp >= m_cache_file_freshness || entry.filetime >= m_cache_file_freshness - 86400))) - { - entries.push_back(std::make_pair(&entry, 0)); - } + if (entry.categoryid == categoryID || categoryID == CacheSystem::CID_All || + (categoryID == CacheSystem::CID_Fresh && + (entry.addtimestamp >= m_cache_file_freshness || entry.filetime >= m_cache_file_freshness - 86400))) + { entries.push_back(std::make_pair(&entry, 0)); } } } @@ -578,7 +519,7 @@ void CLASS::OnCategorySelected(int categoryID) int count = 1; - for (const auto& entry : entries) + for (const auto &entry : entries) { try { @@ -622,11 +563,10 @@ void CLASS::OnEntrySelected(int entryID) void CLASS::OnSelectionDone() { - if ((m_loader_type != LT_Skin && !m_selected_entry) || m_selection_done) - return; + if ((m_loader_type != LT_Skin && !m_selected_entry) || m_selection_done) return; m_selection_done = true; - + bool new_actor_selected = false; if (m_selected_entry != nullptr) // Default skin is nullptr @@ -635,8 +575,7 @@ void CLASS::OnSelectionDone() if (m_loader_type != LT_Skin) { - if (m_loader_type != LT_Terrain && m_loader_type != LT_Skin) - RoR::App::GetCacheSystem()->LoadResource(*m_selected_entry); + if (m_loader_type != LT_Terrain && m_loader_type != LT_Skin) RoR::App::GetCacheSystem()->LoadResource(*m_selected_entry); // Check if skins are available and show skin selector std::vector skin_entries = App::GetCacheSystem()->GetUsableSkins(m_selected_entry->guid); @@ -651,7 +590,7 @@ void CLASS::OnSelectionDone() if (m_loader_type != LT_Terrain) { m_actor_spawn_rq.asr_cache_entry = m_selected_entry; - new_actor_selected = true; + new_actor_selected = true; } } } @@ -666,14 +605,14 @@ void CLASS::OnSelectionDone() if (m_loader_type != LT_Terrain) { m_actor_spawn_rq.asr_skin_entry = m_selected_entry; - new_actor_selected = true; + new_actor_selected = true; } } if (new_actor_selected) { ActorSpawnRequest rq = m_actor_spawn_rq; // actor+skin+sectionconfig entries already filled - rq.asr_origin = ActorSpawnRequest::Origin::USER; + rq.asr_origin = ActorSpawnRequest::Origin::USER; App::GetSimController()->QueueActorSpawn(rq); this->Reset(); RoR::App::GetGuiManager()->UnfocusGui(); @@ -681,7 +620,7 @@ void CLASS::OnSelectionDone() App::sim_state.SetActive(SimState::RUNNING); // TODO: use 'Pending' mechanism! } -void CLASS::UpdateControls(CacheEntry* entry) +void CLASS::UpdateControls(CacheEntry *entry) { if (entry->sectionconfigs.size()) { @@ -706,7 +645,7 @@ void CLASS::UpdateControls(CacheEntry* entry) { m_Config->setVisible(false); } - Ogre::UTFString authors = ""; + Ogre::UTFString authors = ""; std::set author_names; for (auto it = entry->authors.begin(); it != entry->authors.end(); it++) { @@ -722,12 +661,9 @@ void CLASS::UpdateControls(CacheEntry* entry) Ogre::UTFString name = ANSI_TO_UTF(*it); authors.append(U(" ") + name); } - if (authors.length() == 0) - { - authors = _L("no author information available"); - } + if (authors.length() == 0) { authors = _L("no author information available"); } - Ogre::UTFString c = U("#FF7D02"); // colour key shortcut + Ogre::UTFString c = U("#FF7D02"); // colour key shortcut Ogre::UTFString nc = U("#FFFFFF"); // colour key shortcut Ogre::UTFString newline = U("\n"); @@ -736,18 +672,18 @@ void CLASS::UpdateControls(CacheEntry* entry) descriptiontxt = descriptiontxt + _L("Author(s): ") + c + authors + nc + newline; - if (entry->version > 0) - descriptiontxt = descriptiontxt + _L("Version: ") + c + TOUTFSTRING(entry->version) + nc + newline; + if (entry->version > 0) descriptiontxt = descriptiontxt + _L("Version: ") + c + TOUTFSTRING(entry->version) + nc + newline; if (entry->wheelcount > 0) - descriptiontxt = descriptiontxt + _L("Wheels: ") + c + TOUTFSTRING(entry->wheelcount) + U("x") + TOUTFSTRING(entry->propwheelcount) + nc + newline; + descriptiontxt = descriptiontxt + _L("Wheels: ") + c + TOUTFSTRING(entry->wheelcount) + U("x") + + TOUTFSTRING(entry->propwheelcount) + nc + newline; if (entry->truckmass > 0) - descriptiontxt = descriptiontxt + _L("Mass: ") + c + TOUTFSTRING(Round(entry->truckmass / 1000.0f, 3)) + U(" ") + _L("tons") + nc + newline; + descriptiontxt = descriptiontxt + _L("Mass: ") + c + TOUTFSTRING(Round(entry->truckmass / 1000.0f, 3)) + U(" ") + + _L("tons") + nc + newline; if (entry->loadmass > 0) - descriptiontxt = descriptiontxt + _L("Load Mass: ") + c + TOUTFSTRING(Round(entry->loadmass / 1000.0f, 3)) + U(" ") + _L("tons") + nc + newline; - if (entry->nodecount > 0) - descriptiontxt = descriptiontxt + _L("Nodes: ") + c + TOUTFSTRING(entry->nodecount) + nc + newline; - if (entry->beamcount > 0) - descriptiontxt = descriptiontxt + _L("Beams: ") + c + TOUTFSTRING(entry->beamcount) + nc + newline; + descriptiontxt = descriptiontxt + _L("Load Mass: ") + c + TOUTFSTRING(Round(entry->loadmass / 1000.0f, 3)) + U(" ") + + _L("tons") + nc + newline; + if (entry->nodecount > 0) descriptiontxt = descriptiontxt + _L("Nodes: ") + c + TOUTFSTRING(entry->nodecount) + nc + newline; + if (entry->beamcount > 0) descriptiontxt = descriptiontxt + _L("Beams: ") + c + TOUTFSTRING(entry->beamcount) + nc + newline; if (entry->shockcount > 0) descriptiontxt = descriptiontxt + _L("Shocks: ") + c + TOUTFSTRING(entry->shockcount) + nc + newline; if (entry->hydroscount > 0) @@ -762,8 +698,7 @@ void CLASS::UpdateControls(CacheEntry* entry) descriptiontxt = descriptiontxt + _L("Exhausts: ") + c + TOUTFSTRING(entry->exhaustscount) + nc + newline; if (entry->flarescount > 0) descriptiontxt = descriptiontxt + _L("Flares: ") + c + TOUTFSTRING(entry->flarescount) + nc + newline; - if (entry->torque > 0) - descriptiontxt = descriptiontxt + _L("Torque: ") + c + TOUTFSTRING(entry->torque) + nc + newline; + if (entry->torque > 0) descriptiontxt = descriptiontxt + _L("Torque: ") + c + TOUTFSTRING(entry->torque) + nc + newline; if (entry->flexbodiescount > 0) descriptiontxt = descriptiontxt + _L("Flexbodies: ") + c + TOUTFSTRING(entry->flexbodiescount) + nc + newline; if (entry->propscount > 0) @@ -775,7 +710,8 @@ void CLASS::UpdateControls(CacheEntry* entry) if (entry->numgears > 0) descriptiontxt = descriptiontxt + _L("Transmission Gear Count: ") + c + TOUTFSTRING(entry->numgears) + nc + newline; if (entry->minrpm > 0) - descriptiontxt = descriptiontxt + _L("Engine RPM: ") + c + TOUTFSTRING(entry->minrpm) + U(" - ") + TOUTFSTRING(entry->maxrpm) + nc + newline; + descriptiontxt = descriptiontxt + _L("Engine RPM: ") + c + TOUTFSTRING(entry->minrpm) + U(" - ") + + TOUTFSTRING(entry->maxrpm) + nc + newline; if (!entry->uniqueid.empty() && entry->uniqueid != "no-uid") descriptiontxt = descriptiontxt + _L("Unique ID: ") + c + entry->uniqueid + nc + newline; if (!entry->guid.empty() && entry->guid != "no-guid") @@ -786,12 +722,12 @@ void CLASS::UpdateControls(CacheEntry* entry) if (entry->filetime > 0) { Ogre::String filetime = Ogre::StringUtil::format("%s", asctime(gmtime(&entry->filetime))); - descriptiontxt = descriptiontxt + _L("Date and Time modified: ") + c + filetime + nc; + descriptiontxt = descriptiontxt + _L("Date and Time modified: ") + c + filetime + nc; } if (entry->addtimestamp > 0) { Ogre::String addtimestamp = Ogre::StringUtil::format("%s", asctime(gmtime(&entry->addtimestamp))); - descriptiontxt = descriptiontxt + _L("Date and Time installed: ") + c + addtimestamp + nc; + descriptiontxt = descriptiontxt + _L("Date and Time installed: ") + c + addtimestamp + nc; } Ogre::UTFString driveableStr[5] = {_L("Non-Driveable"), _L("Truck"), _L("Airplane"), _L("Boat"), _L("Machine")}; @@ -800,36 +736,25 @@ void CLASS::UpdateControls(CacheEntry* entry) descriptiontxt = descriptiontxt + "#FF0000\n"; // red colour for the props - if (entry->forwardcommands) - descriptiontxt = descriptiontxt + _L("[forwards commands]") + newline; - if (entry->importcommands) - descriptiontxt = descriptiontxt + _L("[imports commands]") + newline; - if (entry->rescuer) - descriptiontxt = descriptiontxt + _L("[is rescuer]") + newline; - if (entry->custom_particles) - descriptiontxt = descriptiontxt + _L("[uses custom particles]") + newline; - if (entry->fixescount > 0) - descriptiontxt = descriptiontxt + _L("[has fixes]") + newline; + if (entry->forwardcommands) descriptiontxt = descriptiontxt + _L("[forwards commands]") + newline; + if (entry->importcommands) descriptiontxt = descriptiontxt + _L("[imports commands]") + newline; + if (entry->rescuer) descriptiontxt = descriptiontxt + _L("[is rescuer]") + newline; + if (entry->custom_particles) descriptiontxt = descriptiontxt + _L("[uses custom particles]") + newline; + if (entry->fixescount > 0) descriptiontxt = descriptiontxt + _L("[has fixes]") + newline; // t is the default, do not display it - //if (entry->enginetype == 't') descriptiontxt = descriptiontxt +_L("[TRUCK ENGINE]") + newline; - if (entry->enginetype == 'c') - descriptiontxt = descriptiontxt + _L("[car engine]") + newline; - if (entry->resource_bundle_type == "Zip") - descriptiontxt = descriptiontxt + _L("[zip archive]") + newline; - if (entry->resource_bundle_type == "FileSystem") - descriptiontxt = descriptiontxt + _L("[unpacked in directory]") + newline; + // if (entry->enginetype == 't') descriptiontxt = descriptiontxt +_L("[TRUCK ENGINE]") + newline; + if (entry->enginetype == 'c') descriptiontxt = descriptiontxt + _L("[car engine]") + newline; + if (entry->resource_bundle_type == "Zip") descriptiontxt = descriptiontxt + _L("[zip archive]") + newline; + if (entry->resource_bundle_type == "FileSystem") descriptiontxt = descriptiontxt + _L("[unpacked in directory]") + newline; descriptiontxt = descriptiontxt + "#66CCFF\n"; // now blue-ish color* if (!entry->resource_bundle_path.empty()) descriptiontxt = descriptiontxt + _L("Source: ") + entry->resource_bundle_path + newline; - if (!entry->fname.empty()) - descriptiontxt = descriptiontxt + _L("Filename: ") + entry->fname + newline; + if (!entry->fname.empty()) descriptiontxt = descriptiontxt + _L("Filename: ") + entry->fname + newline; if (!entry->sectionconfigs.empty()) - { - descriptiontxt = descriptiontxt + U("\n\n#e10000") + _L("Please select a configuration below!") + nc + U("\n\n"); - } + { descriptiontxt = descriptiontxt + U("\n\n#e10000") + _L("Please select a configuration below!") + nc + U("\n\n"); } trimUTFString(descriptiontxt); @@ -854,18 +779,20 @@ void CLASS::SetPreviewImage(Ogre::String texture) } catch (...) { - Ogre::LogManager::getSingleton().stream() << "[RoR|SelectorGUI] Failed to load preview image: " << m_preview_image_texture; + Ogre::LogManager::getSingleton().stream() + << "[RoR|SelectorGUI] Failed to load preview image: " << m_preview_image_texture; m_Preview->setVisible(false); } } void CLASS::ResizePreviewImage() { - MyGUI::IntSize imgSize(0, 0); - Ogre::TexturePtr t = Ogre::TextureManager::getSingleton().load(m_preview_image_texture, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); + MyGUI::IntSize imgSize(0, 0); + Ogre::TexturePtr t = Ogre::TextureManager::getSingleton().load(m_preview_image_texture, + Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); if (!t.isNull()) { - imgSize.width = (int)t->getWidth() * 10; + imgSize.width = (int)t->getWidth() * 10; imgSize.height = (int)t->getHeight() * 10; } @@ -876,23 +803,23 @@ void CLASS::ResizePreviewImage() float imgRatio = imgSize.width / (float)imgSize.height; float maxRatio = maxSize.width / (float)maxSize.height; - MyGUI::IntSize newSize(0, 0); + MyGUI::IntSize newSize(0, 0); MyGUI::IntPoint newPosition(0, 0); // scale with aspect ratio if (imgRatio > maxRatio) { - newSize.width = maxSize.width; - newSize.height = maxSize.width / imgRatio; + newSize.width = maxSize.width; + newSize.height = maxSize.width / imgRatio; newPosition.left = 0; - newPosition.top = maxSize.height - newSize.height; + newPosition.top = maxSize.height - newSize.height; } else { - newSize.width = maxSize.height * imgRatio; - newSize.height = maxSize.height; + newSize.width = maxSize.height * imgRatio; + newSize.height = maxSize.height; newPosition.left = maxSize.width - newSize.width; - newPosition.top = 0; + newPosition.top = 0; } m_Preview->setSize(newSize); @@ -907,18 +834,14 @@ bool CLASS::IsFinishedSelecting() void CLASS::Show(LoaderType type, RoR::ActorSpawnRequest req) { - if (!m_selection_done) - { - return; - } + if (!m_selection_done) { return; } m_actor_spawn_rq = req; this->Show(type); } void CLASS::Show(LoaderType type) { - if (!m_selection_done) - return; + if (!m_selection_done) return; m_selection_done = false; m_selected_entry = nullptr; @@ -938,9 +861,7 @@ void CLASS::Show(LoaderType type) } if (type == LT_Terrain && (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED)) - { - m_Cancel->setCaption(_L("Cancel (disconnect)")); - } + { m_Cancel->setCaption(_L("Cancel (disconnect)")); } else { m_Cancel->setCaption(_L("Cancel")); @@ -951,10 +872,7 @@ void CLASS::Hide(bool smooth) { m_selection_done = true; RoR::App::GetGuiManager()->UnfocusGui(); - if (smooth) - { - MAIN_WIDGET->setVisibleSmooth(false); - } + if (smooth) { MAIN_WIDGET->setVisibleSmooth(false); } else { MAIN_WIDGET->setVisible(false); @@ -963,26 +881,18 @@ void CLASS::Hide(bool smooth) BindKeys(false); } -void CLASS::EventSearchTextChange(MyGUI::EditBox* _sender) +void CLASS::EventSearchTextChange(MyGUI::EditBox *_sender) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; OnCategorySelected(CacheSystem::CID_SearchResults); - if (m_SearchLine->getTextLength() > 0) - { - m_Type->setCaption(_L("Search Results")); - } + if (m_SearchLine->getTextLength() > 0) { m_Type->setCaption(_L("Search Results")); } } void CLASS::EventSearchTextGotFocus(MyGUI::WidgetPtr _sender, MyGUI::WidgetPtr oldWidget) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; - if (m_SearchLine->getCaption() == _L("Search ...")) - { - m_SearchLine->setCaption(""); - } + if (m_SearchLine->getCaption() == _L("Search ...")) { m_SearchLine->setCaption(""); } } bool CLASS::IsVisible() @@ -990,10 +900,7 @@ bool CLASS::IsVisible() return MAIN_WIDGET->isVisible(); } -void CLASS::NotifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name) +void CLASS::NotifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name) { - if (_name == "close") - { - Cancel(); - } + if (_name == "close") { Cancel(); } } diff --git a/source/main/gui/panels/GUI_MainSelector.h b/source/main/gui/panels/GUI_MainSelector.h index ebd7085a4e..583d49742d 100644 --- a/source/main/gui/panels/GUI_MainSelector.h +++ b/source/main/gui/panels/GUI_MainSelector.h @@ -29,65 +29,69 @@ #include "ForwardDeclarations.h" #include "GUI_MainSelectorLayout.h" -namespace RoR { -namespace GUI { - -class MainSelector : public MainSelectorLayout +namespace RoR { -public: - MainSelector(); - ~MainSelector(); - - bool IsFinishedSelecting(); - void Show(LoaderType type, ActorSpawnRequest req); - void Show(LoaderType type); - void Hide(bool smooth = true); - bool IsVisible(); - void Reset(); - void Cancel(); - - CacheEntry* GetSelectedEntry() { return m_selected_entry; } - -private: - - void NotifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name); - - // gui events - void EventComboAcceptConfigComboBox(MyGUI::ComboBoxPtr _sender, size_t _index); - void EventComboChangePositionTypeComboBox(MyGUI::ComboBoxPtr _sender, size_t _index); - void EventKeyButtonPressed_Main(MyGUI::WidgetPtr _sender, MyGUI::KeyCode _key, MyGUI::Char _char); - void EventListChangePositionModelList(MyGUI::ListPtr _sender, size_t _index); - void EventListChangePositionModelListAccept(MyGUI::ListPtr _sender, size_t _index); - void EventMouseButtonClickCancelButton(MyGUI::WidgetPtr _sender); - void EventMouseButtonClickOkButton(MyGUI::WidgetPtr _sender); - void EventSearchTextChange(MyGUI::EditBox* _sender); - void EventSearchTextGotFocus(MyGUI::WidgetPtr _sender, MyGUI::WidgetPtr oldWidget); - void NotifyWindowChangeCoord(MyGUI::Window* _sender); - void ResizePreviewImage(); - void BindKeys(bool bind = true); - - // other functions - void UpdateGuiData(); - void OnCategorySelected(int categoryID); - void OnEntrySelected(int entryID); - void OnSelectionDone(); - size_t SearchCompare(Ogre::String searchString, CacheEntry* ce); - void UpdateControls(CacheEntry* entry); - void SetPreviewImage(Ogre::String texture); - void FrameEntered(float dt); - - CacheEntry* m_selected_entry; - LoaderType m_loader_type; - Ogre::String m_preview_image_texture; - bool m_selection_done; - std::vector m_entries; - bool m_keys_bound; - ActorSpawnRequest m_actor_spawn_rq; //!< Serves as context when spawning an actor - std::time_t m_cache_file_freshness; - std::map m_category_index; //!< Stores the last manually selected category index for each loader type - std::map m_entry_index; //!< Stores the last manually selected entry index for each loader type - bool m_searching; -}; - -} // namespace GUI + namespace GUI + { + + class MainSelector : public MainSelectorLayout + { + public: + MainSelector(); + ~MainSelector(); + + bool IsFinishedSelecting(); + void Show(LoaderType type, ActorSpawnRequest req); + void Show(LoaderType type); + void Hide(bool smooth = true); + bool IsVisible(); + void Reset(); + void Cancel(); + + CacheEntry *GetSelectedEntry() + { + return m_selected_entry; + } + + private: + void NotifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name); + + // gui events + void EventComboAcceptConfigComboBox(MyGUI::ComboBoxPtr _sender, size_t _index); + void EventComboChangePositionTypeComboBox(MyGUI::ComboBoxPtr _sender, size_t _index); + void EventKeyButtonPressed_Main(MyGUI::WidgetPtr _sender, MyGUI::KeyCode _key, MyGUI::Char _char); + void EventListChangePositionModelList(MyGUI::ListPtr _sender, size_t _index); + void EventListChangePositionModelListAccept(MyGUI::ListPtr _sender, size_t _index); + void EventMouseButtonClickCancelButton(MyGUI::WidgetPtr _sender); + void EventMouseButtonClickOkButton(MyGUI::WidgetPtr _sender); + void EventSearchTextChange(MyGUI::EditBox *_sender); + void EventSearchTextGotFocus(MyGUI::WidgetPtr _sender, MyGUI::WidgetPtr oldWidget); + void NotifyWindowChangeCoord(MyGUI::Window *_sender); + void ResizePreviewImage(); + void BindKeys(bool bind = true); + + // other functions + void UpdateGuiData(); + void OnCategorySelected(int categoryID); + void OnEntrySelected(int entryID); + void OnSelectionDone(); + size_t SearchCompare(Ogre::String searchString, CacheEntry *ce); + void UpdateControls(CacheEntry *entry); + void SetPreviewImage(Ogre::String texture); + void FrameEntered(float dt); + + CacheEntry * m_selected_entry; + LoaderType m_loader_type; + Ogre::String m_preview_image_texture; + bool m_selection_done; + std::vector m_entries; + bool m_keys_bound; + ActorSpawnRequest m_actor_spawn_rq; //!< Serves as context when spawning an actor + std::time_t m_cache_file_freshness; + std::map m_category_index; //!< Stores the last manually selected category index for each loader type + std::map m_entry_index; //!< Stores the last manually selected entry index for each loader type + bool m_searching; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_MainSelectorLayout.cpp b/source/main/gui/panels/GUI_MainSelectorLayout.cpp index 8b21682dbe..3b8588ab4f 100644 --- a/source/main/gui/panels/GUI_MainSelectorLayout.cpp +++ b/source/main/gui/panels/GUI_MainSelectorLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -MainSelectorLayout::MainSelectorLayout(MyGUI::Widget* _parent) +MainSelectorLayout::MainSelectorLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_MainSelectorLayout.h b/source/main/gui/panels/GUI_MainSelectorLayout.h index a2c87561fd..360311f4fb 100644 --- a/source/main/gui/panels/GUI_MainSelectorLayout.h +++ b/source/main/gui/panels/GUI_MainSelectorLayout.h @@ -8,57 +8,56 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(MainSelectorLayout, "SelectorWindow.layout"); -class MainSelectorLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(MainSelectorLayout, "SelectorWindow.layout"); + class MainSelectorLayout : public wraps::BaseLayout + { - MainSelectorLayout(MyGUI::Widget* _parent = nullptr); - virtual ~MainSelectorLayout(); + public: + MainSelectorLayout(MyGUI::Widget *_parent = nullptr); + virtual ~MainSelectorLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Type, "Type"); + MyGUI::ComboBox *m_Type; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Type, "Type"); - MyGUI::ComboBox* m_Type; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Model, "Model"); + MyGUI::ListBox *m_Model; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Model, "Model"); - MyGUI::ListBox* m_Model; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_SearchLine, "SearchLine"); + MyGUI::EditBox *m_SearchLine; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_SearchLine, "SearchLine"); - MyGUI::EditBox* m_SearchLine; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_EntryName, "EntryName"); + MyGUI::TextBox *m_EntryName; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_EntryName, "EntryName"); - MyGUI::TextBox* m_EntryName; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_EntryDescription, "EntryDescription"); + MyGUI::TextBox *m_EntryDescription; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_EntryDescription, "EntryDescription"); - MyGUI::TextBox* m_EntryDescription; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Config, "Config"); + MyGUI::ComboBox *m_Config; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Config, "Config"); - MyGUI::ComboBox* m_Config; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_PreviewBox, "PreviewBox"); + MyGUI::Widget *m_PreviewBox; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_PreviewBox, "PreviewBox"); - MyGUI::Widget* m_PreviewBox; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Preview, "Preview"); + MyGUI::ImageBox *m_Preview; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Preview, "Preview"); - MyGUI::ImageBox* m_Preview; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Ok, "Ok"); + MyGUI::Button *m_Ok; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Ok, "Ok"); - MyGUI::Button* m_Ok; + ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Cancel, "Cancel"); + MyGUI::Button *m_Cancel; - ATTRIBUTE_FIELD_WIDGET_NAME(MainSelectorLayout, m_Cancel, "Cancel"); - MyGUI::Button* m_Cancel; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_MessageBox.cpp b/source/main/gui/panels/GUI_MessageBox.cpp index a4b193d700..fedebe0684 100644 --- a/source/main/gui/panels/GUI_MessageBox.cpp +++ b/source/main/gui/panels/GUI_MessageBox.cpp @@ -24,25 +24,26 @@ /// @date 12/2014 #include "GUI_MessageBox.h" + #include "ScriptEvents.h" #include "Scripting.h" #include -RoR::GUI::MessageBoxDialog::MessageBoxDialog(): - m_close_handle(nullptr), - m_is_visible(false) -{} +RoR::GUI::MessageBoxDialog::MessageBoxDialog() : m_close_handle(nullptr), m_is_visible(false) +{ +} RoR::GUI::MessageBoxDialog::~MessageBoxDialog() -{} +{ +} void RoR::GUI::MessageBoxDialog::Draw() { const bool was_visible = m_is_visible; // Draw window - ImGui::SetNextWindowContentWidth(300.f); // Initial size only + ImGui::SetNextWindowContentWidth(300.f); // Initial size only ImGui::SetNextWindowPosCenter(ImGuiSetCond_Appearing); // Initial pos. only ImGui::Begin(m_title.c_str(), m_close_handle); ImGui::TextWrapped("%s", m_text.c_str()); @@ -73,21 +74,18 @@ void RoR::GUI::MessageBoxDialog::Draw() } } -void RoR::GUI::MessageBoxDialog::Show(const char* title, const char* text, bool allow_close, const char* button1_text, const char* button2_text) +void RoR::GUI::MessageBoxDialog::Show(const char *title, const char *text, bool allow_close, const char *button1_text, + const char *button2_text) { - m_is_visible = true; - m_title = title; - m_text = text; + m_is_visible = true; + m_title = title; + m_text = text; m_button1_text = ((button1_text != nullptr) ? button1_text : ""); m_button2_text = ((button2_text != nullptr) ? button2_text : ""); - if (allow_close) - { - m_close_handle = &m_is_visible; - } + if (allow_close) { m_close_handle = &m_is_visible; } else { m_close_handle = nullptr; } } - diff --git a/source/main/gui/panels/GUI_MessageBox.h b/source/main/gui/panels/GUI_MessageBox.h index f8e07567d0..60882c6f33 100644 --- a/source/main/gui/panels/GUI_MessageBox.h +++ b/source/main/gui/panels/GUI_MessageBox.h @@ -29,27 +29,32 @@ #include -namespace RoR { -namespace GUI { - -class MessageBoxDialog +namespace RoR { -public: - MessageBoxDialog(); - ~MessageBoxDialog(); - - void Show(const char* title, const char* text, bool allow_close, const char* button1_text, const char* button2_text); - void Draw(); - inline bool IsVisible() const { return m_is_visible; } - -private: - std::string m_title; - std::string m_text; - std::string m_button1_text; - std::string m_button2_text; - bool* m_close_handle; // If nullptr, close button is hidden. Otherwise visible. - bool m_is_visible; -}; - -} // namespace GUI + namespace GUI + { + + class MessageBoxDialog + { + public: + MessageBoxDialog(); + ~MessageBoxDialog(); + + void Show(const char *title, const char *text, bool allow_close, const char *button1_text, const char *button2_text); + void Draw(); + inline bool IsVisible() const + { + return m_is_visible; + } + + private: + std::string m_title; + std::string m_text; + std::string m_button1_text; + std::string m_button2_text; + bool * m_close_handle; // If nullptr, close button is hidden. Otherwise visible. + bool m_is_visible; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_MultiplayerClientList.cpp b/source/main/gui/panels/GUI_MultiplayerClientList.cpp index d4c00f8994..9ab384404c 100644 --- a/source/main/gui/panels/GUI_MultiplayerClientList.cpp +++ b/source/main/gui/panels/GUI_MultiplayerClientList.cpp @@ -22,7 +22,6 @@ /// @author Thomas Fischer (thomas{AT}thomasfischer{DOT}biz) /// @date 7th of September 2009 - #include "GUI_MultiplayerClientList.h" #include "Application.h" @@ -36,24 +35,23 @@ using namespace RoR; using namespace GUI; using namespace Ogre; -MpClientList::MpClientList() : - clients(0) - , lineheight(16) - , msgwin(0) +MpClientList::MpClientList() : clients(0), lineheight(16), msgwin(0) { // allocate some buffers clients = (client_t *)calloc(RORNET_MAX_PEERS, sizeof(client_t)); // tooltip window - tooltipPanel = MyGUI::Gui::getInstance().createWidget("PanelSkin", 0, 0, 200, 20, MyGUI::Align::Default, "ToolTip"); + tooltipPanel = + MyGUI::Gui::getInstance().createWidget("PanelSkin", 0, 0, 200, 20, MyGUI::Align::Default, "ToolTip"); tooltipText = tooltipPanel->createWidget("TextBox", 4, 2, 200, 16, MyGUI::Align::Default); tooltipText->setFontName("VeraMono"); - //tooltipPanel->setAlpha(0.9f); + // tooltipPanel->setAlpha(0.9f); tooltipText->setFontHeight(16); tooltipPanel->setVisible(false); // message window - msgwin = MyGUI::Gui::getInstance().createWidget("WindowCSX", 0, 0, 400, 300, MyGUI::Align::Center, "Overlapped"); + msgwin = + MyGUI::Gui::getInstance().createWidget("WindowCSX", 0, 0, 400, 300, MyGUI::Align::Center, "Overlapped"); msgwin->setCaption(_L("Player Information")); msgtext = msgwin->createWidget("EditStretch", 0, 0, 400, 300, MyGUI::Align::Default, "helptext"); msgtext->setCaption(""); @@ -62,9 +60,10 @@ MpClientList::MpClientList() : msgwin->setVisible(false); // network quality warning - netmsgwin = MyGUI::Gui::getInstance().createWidget("FlowContainer", 5, 30, 300, 40, MyGUI::Align::Default, "Main"); + netmsgwin = + MyGUI::Gui::getInstance().createWidget("FlowContainer", 5, 30, 300, 40, MyGUI::Align::Default, "Main"); netmsgwin->setAlpha(0.8f); - MyGUI::ImageBox* nimg = netmsgwin->createWidget("ImageBox", 0, 0, 16, 16, MyGUI::Align::Default, "Main"); + MyGUI::ImageBox *nimg = netmsgwin->createWidget("ImageBox", 0, 0, 16, 16, MyGUI::Align::Default, "Main"); nimg->setImageTexture("error.png"); netmsgtext = netmsgwin->createWidget("TextBox", 18, 2, 300, 40, MyGUI::Align::Default, "helptext"); netmsgtext->setCaption(_L("Slow Network Download")); @@ -75,21 +74,24 @@ MpClientList::MpClientList() : // now the main GUI MyGUI::IntSize gui_area = MyGUI::RenderManager::getInstance().getViewSize(); - int x = gui_area.width - 300, y = 30; + int x = gui_area.width - 300, y = 30; - MyGUI::ImageBox* ib = MyGUI::Gui::getInstance().createWidget("ImageBox", x, y, sidebarWidth, gui_area.height, MyGUI::Align::Default, "Back"); + MyGUI::ImageBox *ib = MyGUI::Gui::getInstance().createWidget("ImageBox", x, y, sidebarWidth, gui_area.height, + MyGUI::Align::Default, "Back"); ib->setImageTexture("mpbg.png"); - mpPanel = ib; //->createWidget("FlowContainer", x, y, sidebarWidth, gui_area.height, MyGUI::Align::Default, "Main"); + mpPanel = + ib; //->createWidget("FlowContainer", x, y, sidebarWidth, gui_area.height, MyGUI::Align::Default, "Main"); mpPanel->setVisible(false); y = 5; UTFString tmp; for (int i = 0; i < RORNET_MAX_PEERS + 1; i++) // plus 1 for local entry { - x = 100; // space for icons - player_row_t* row = &player_rows[i]; - row->playername = mpPanel->createWidget("TextBox", x, y + 1, sidebarWidth, lineheight, MyGUI::Align::Default, "Main"); + x = 100; // space for icons + player_row_t *row = &player_rows[i]; + row->playername = + mpPanel->createWidget("TextBox", x, y + 1, sidebarWidth, lineheight, MyGUI::Align::Default, "Main"); row->playername->setCaption("Player " + TOSTRING(i)); row->playername->setFontName("DefaultBig"); tmp = _L("user name"); @@ -102,7 +104,7 @@ MpClientList::MpClientList() : x -= 18; row->flagimg = mpPanel->createWidget("ImageBox", x, y + 3, 16, 11, MyGUI::Align::Default, "Main"); - tmp = _L("user country"); + tmp = _L("user country"); row->flagimg->setUserString("tooltip", tmp.asUTF8()); row->flagimg->eventToolTip += MyGUI::newDelegate(this, &MpClientList::openToolTip); row->flagimg->setNeedToolTip(true); @@ -110,7 +112,7 @@ MpClientList::MpClientList() : x -= 18; row->statimg = mpPanel->createWidget("ImageBox", x, y, 16, 16, MyGUI::Align::Default, "Main"); - tmp = _L("user authentication level"); + tmp = _L("user authentication level"); row->statimg->setUserString("tooltip", tmp.asUTF8()); row->statimg->eventToolTip += MyGUI::newDelegate(this, &MpClientList::openToolTip); row->statimg->setNeedToolTip(true); @@ -118,7 +120,7 @@ MpClientList::MpClientList() : x -= 18; row->user_actor_ok_img = mpPanel->createWidget("ImageBox", x, y, 16, 16, MyGUI::Align::Default, "Main"); - tmp = _L("truck loading state"); + tmp = _L("truck loading state"); row->user_actor_ok_img->setUserString("tooltip", tmp.asUTF8()); row->user_actor_ok_img->eventToolTip += MyGUI::newDelegate(this, &MpClientList::openToolTip); row->user_actor_ok_img->setNeedToolTip(true); @@ -126,7 +128,8 @@ MpClientList::MpClientList() : row->user_actor_ok_img->eventMouseButtonClick += MyGUI::newDelegate(this, &MpClientList::clickInfoIcon); x -= 18; - row->user_remote_actor_ok_img = mpPanel->createWidget("ImageBox", x, y, 16, 16, MyGUI::Align::Default, "Main"); + row->user_remote_actor_ok_img = + mpPanel->createWidget("ImageBox", x, y, 16, 16, MyGUI::Align::Default, "Main"); tmp = _L("remote truck loading state"); row->user_remote_actor_ok_img->setUserString("tooltip", tmp.asUTF8()); row->user_remote_actor_ok_img->eventToolTip += MyGUI::newDelegate(this, &MpClientList::openToolTip); @@ -146,10 +149,9 @@ MpClientList::MpClientList() : row->usergoimg->eventMouseButtonClick += MyGUI::newDelegate(this, &MpClientList::clickUserGoIcon); /* - img = MyGUI::Gui::getInstance().createWidget("ImageBox", x-36, y, 16, 16, MyGUI::Align::Default, "Overlapped"); - img->setImageTexture("information.png"); - img->eventMouseButtonClick += MyGUI::newDelegate(this, &MpClientList::clickInfoIcon); - img->eventToolTip += MyGUI::newDelegate(this, &MpClientList::openToolTip); + img = MyGUI::Gui::getInstance().createWidget("ImageBox", x-36, y, 16, 16, MyGUI::Align::Default, + "Overlapped"); img->setImageTexture("information.png"); img->eventMouseButtonClick += MyGUI::newDelegate(this, + &MpClientList::clickInfoIcon); img->eventToolTip += MyGUI::newDelegate(this, &MpClientList::openToolTip); img->setNeedToolTip(true); img->setUserString("info", TOSTRING(i)); img->setUserString("tooltip", _L("information about the user")); @@ -168,10 +170,9 @@ MpClientList::~MpClientList() } } -void MpClientList::updateSlot(player_row_t* row, RoRnet::UserInfo c, bool self) +void MpClientList::updateSlot(player_row_t *row, RoRnet::UserInfo c, bool self) { - if (!row) - return; + if (!row) return; int x = 100; int y = row->playername->getPosition().top; @@ -203,10 +204,7 @@ void MpClientList::updateSlot(player_row_t* row, RoRnet::UserInfo c, bool self) UTFString tmp; // auth - if (c.authstatus == RoRnet::AUTH_NONE) - { - row->statimg->setVisible(false); - } + if (c.authstatus == RoRnet::AUTH_NONE) { row->statimg->setVisible(false); } else if (c.authstatus & RoRnet::AUTH_ADMIN) { row->statimg->setVisible(true); @@ -303,7 +301,7 @@ void MpClientList::update() int slotid = 0; MyGUI::IntSize gui_area = MyGUI::RenderManager::getInstance().getViewSize(); - int x = gui_area.width - sidebarWidth, y = 30; + int x = gui_area.width - sidebarWidth, y = 30; mpPanel->setPosition(x, y); // add local player to first slot always @@ -315,7 +313,7 @@ void MpClientList::update() std::vector users = RoR::Networking::GetUserInfos(); for (RoRnet::UserInfo user : users) { - player_row_t* row = &player_rows[slotid]; + player_row_t *row = &player_rows[slotid]; slotid++; try { @@ -327,7 +325,7 @@ void MpClientList::update() } for (int i = slotid; i < RORNET_MAX_PEERS; i++) { - player_row_t* row = &player_rows[i]; + player_row_t *row = &player_rows[i]; // not used, hide everything row->flagimg->setVisible(false); row->playername->setVisible(false); @@ -346,16 +344,16 @@ void MpClientList::update() void MpClientList::clickUserGoIcon(MyGUI::WidgetPtr sender) { - //int uid = StringConverter::parseInt(sender->getUserString("uid")); + // int uid = StringConverter::parseInt(sender->getUserString("uid")); } void MpClientList::clickInfoIcon(MyGUI::WidgetPtr sender) { - //msgtext->setCaption("FOOBAR: "+sender->getUserString("info")); - //msgwin->setVisible(true); + // msgtext->setCaption("FOOBAR: "+sender->getUserString("info")); + // msgwin->setVisible(true); } -void MpClientList::openToolTip(MyGUI::WidgetPtr sender, const MyGUI::ToolTipInfo& t) +void MpClientList::openToolTip(MyGUI::WidgetPtr sender, const MyGUI::ToolTipInfo &t) { if (t.type == MyGUI::ToolTipInfo::Show) { @@ -363,8 +361,8 @@ void MpClientList::openToolTip(MyGUI::WidgetPtr sender, const MyGUI::ToolTipInfo if (!txt.empty()) { tooltipText->setCaption(txt); - MyGUI::IntSize s = tooltipText->getTextSize(); - int newWidth = s.width + 10; + MyGUI::IntSize s = tooltipText->getTextSize(); + int newWidth = s.width + 10; tooltipPanel->setPosition(t.point - MyGUI::IntPoint(newWidth + 10, 10)); tooltipPanel->setSize(newWidth, 20); tooltipText->setSize(newWidth, 16); diff --git a/source/main/gui/panels/GUI_MultiplayerClientList.h b/source/main/gui/panels/GUI_MultiplayerClientList.h index f813fdbf8b..18461d0ad6 100644 --- a/source/main/gui/panels/GUI_MultiplayerClientList.h +++ b/source/main/gui/panels/GUI_MultiplayerClientList.h @@ -22,70 +22,67 @@ /// @author Thomas Fischer (thomas{AT}thomasfischer{DOT}biz) /// @date 18th of July 2010 - #pragma once #include "RoRPrerequisites.h" - #include "RoRnet.h" #include -namespace RoR { -namespace GUI { - -struct client_t -{ - RoRnet::UserInfo user; //!< user struct - bool used; //!< if this slot is used already -}; - -class MpClientList +namespace RoR { -public: - - MpClientList(); - ~MpClientList(); + namespace GUI + { - void update(); + struct client_t + { + RoRnet::UserInfo user; //!< user struct + bool used; //!< if this slot is used already + }; - bool IsVisible(); - void SetVisible(bool value); + class MpClientList + { + public: + MpClientList(); + ~MpClientList(); -protected: + void update(); - struct player_row_t - { - MyGUI::StaticImagePtr flagimg; - MyGUI::StaticImagePtr statimg; - MyGUI::StaticImagePtr usergoimg; - MyGUI::StaticImagePtr user_actor_ok_img; - MyGUI::StaticImagePtr user_remote_actor_ok_img; - MyGUI::StaticTextPtr playername; - }; + bool IsVisible(); + void SetVisible(bool value); - MyGUI::EditPtr msgtext; - MyGUI::StaticTextPtr tooltipText; - MyGUI::WidgetPtr tooltipPanel, mpPanel; - MyGUI::WindowPtr msgwin; + protected: + struct player_row_t + { + MyGUI::StaticImagePtr flagimg; + MyGUI::StaticImagePtr statimg; + MyGUI::StaticImagePtr usergoimg; + MyGUI::StaticImagePtr user_actor_ok_img; + MyGUI::StaticImagePtr user_remote_actor_ok_img; + MyGUI::StaticTextPtr playername; + }; - player_row_t player_rows[RORNET_MAX_PEERS + 1]; + MyGUI::EditPtr msgtext; + MyGUI::StaticTextPtr tooltipText; + MyGUI::WidgetPtr tooltipPanel, mpPanel; + MyGUI::WindowPtr msgwin; - void clickInfoIcon(MyGUI::WidgetPtr sender); - void clickUserGoIcon(MyGUI::WidgetPtr sender); - void openToolTip(MyGUI::WidgetPtr sender, const MyGUI::ToolTipInfo& t); + player_row_t player_rows[RORNET_MAX_PEERS + 1]; - MyGUI::WindowPtr netmsgwin; - MyGUI::StaticTextPtr netmsgtext; + void clickInfoIcon(MyGUI::WidgetPtr sender); + void clickUserGoIcon(MyGUI::WidgetPtr sender); + void openToolTip(MyGUI::WidgetPtr sender, const MyGUI::ToolTipInfo &t); - void updateSlot(player_row_t* row, RoRnet::UserInfo c, bool self); + MyGUI::WindowPtr netmsgwin; + MyGUI::StaticTextPtr netmsgtext; - client_t* clients; - int lineheight; + void updateSlot(player_row_t *row, RoRnet::UserInfo c, bool self); - static const int sidebarWidth = 250; -}; + client_t *clients; + int lineheight; + static const int sidebarWidth = 250; + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_MultiplayerSelector.cpp b/source/main/gui/panels/GUI_MultiplayerSelector.cpp index f0b95b7fff..bf8b5bc002 100644 --- a/source/main/gui/panels/GUI_MultiplayerSelector.cpp +++ b/source/main/gui/panels/GUI_MultiplayerSelector.cpp @@ -26,41 +26,43 @@ #include "GUIManager.h" #include "GUIUtils.h" #include "MainMenu.h" -#include "RoRnet.h" #include "RoRVersion.h" +#include "RoRnet.h" #include #include #include #ifdef USE_CURL -# include -# include -#endif //USE_CURL + #include + #include +#endif // USE_CURL #if defined(_MSC_VER) && defined(GetObject) // This MS Windows macro from (Windows Kit 8.1) clashes with RapidJSON -# undef GetObject + #undef GetObject #endif struct RoR::GUI::MpServerlistData { struct ServerInfo { - bool has_password; - Str<50> display_passwd; - Str<100> display_name; - Str<100> display_terrn; - int num_users; - int max_users; - Str<20> display_users; - Str<100> net_host; - Str<20> net_version; - Str<20> display_version; - int net_port; - Str<50> display_host; + bool has_password; + Str<50> display_passwd; + Str<100> display_name; + Str<100> display_terrn; + int num_users; + int max_users; + Str<20> display_users; + Str<100> net_host; + Str<20> net_version; + Str<20> display_version; + int net_port; + Str<50> display_host; }; - MpServerlistData(): success(false) {} + MpServerlistData() : success(false) + { + } std::vector servers; std::string message; @@ -70,13 +72,13 @@ struct RoR::GUI::MpServerlistData #if defined(USE_CURL) // From example: https://gist.github.com/whoshuu/2dc858b8730079602044 -size_t CurlWriteFunc(void *ptr, size_t size, size_t nmemb, std::string* data) +size_t CurlWriteFunc(void *ptr, size_t size, size_t nmemb, std::string *data) { - data->append((char*) ptr, size * nmemb); + data->append((char *)ptr, size * nmemb); return size * nmemb; } -RoR::GUI::MpServerlistData* FetchServerlist(std::string portal_url) +RoR::GUI::MpServerlistData *FetchServerlist(std::string portal_url) { std::string serverlist_url = portal_url + "/server-list?json=true"; std::string response_payload; @@ -84,10 +86,10 @@ RoR::GUI::MpServerlistData* FetchServerlist(std::string portal_url) long response_code = 0; CURL *curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_URL, serverlist_url.c_str()); + curl_easy_setopt(curl, CURLOPT_URL, serverlist_url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteFunc); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_payload); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response_header); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_payload); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response_header); curl_easy_perform(curl); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); @@ -95,10 +97,10 @@ RoR::GUI::MpServerlistData* FetchServerlist(std::string portal_url) curl_easy_cleanup(curl); curl = nullptr; - RoR::GUI::MpServerlistData* res = new RoR::GUI::MpServerlistData(); + RoR::GUI::MpServerlistData *res = new RoR::GUI::MpServerlistData(); if (response_code != 200) { - Ogre::LogManager::getSingleton().stream() + Ogre::LogManager::getSingleton().stream() << "[RoR|Multiplayer] Failed to retrieve serverlist; HTTP status code: " << response_code; res->message = "Error connecting to server :("; return res; @@ -108,7 +110,7 @@ RoR::GUI::MpServerlistData* FetchServerlist(std::string portal_url) j_data_doc.Parse(response_payload.c_str()); if (j_data_doc.HasParseError() || !j_data_doc.IsArray()) { - Ogre::LogManager::getSingleton().stream() + Ogre::LogManager::getSingleton().stream() << "[RoR|Multiplayer] Error parsing serverlist JSON"; // TODO: Report the actual error res->message = "Server returned invalid data :("; return res; @@ -119,25 +121,25 @@ RoR::GUI::MpServerlistData* FetchServerlist(std::string portal_url) res->servers.resize(num_rows); for (size_t i = 0; i < num_rows; ++i) { - rapidjson::Value& j_row = j_data_doc[static_cast(i)]; + rapidjson::Value &j_row = j_data_doc[static_cast(i)]; res->servers[i].display_name = j_row["name"].GetString(); res->servers[i].display_terrn = j_row["terrain-name"].GetString(); res->servers[i].net_host = j_row["ip"].GetString(); res->servers[i].net_port = j_row["port"].GetInt(); - res->servers[i].has_password = j_row["has-password"].GetBool(); + res->servers[i].has_password = j_row["has-password"].GetBool(); res->servers[i].display_passwd = res->servers[i].has_password ? "Yes" : "No"; char display_host[400]; snprintf(display_host, 400, "%s:%d", j_row["ip"].GetString(), j_row["port"].GetInt()); - res->servers[i].display_host = display_host; + res->servers[i].display_host = display_host; char display_users[200]; snprintf(display_users, 200, "%d / %d", j_row["current-users"].GetInt(), j_row["max-clients"].GetInt()); res->servers[i].display_users = display_users; - res->servers[i].net_version = j_row["version"].GetString(); + res->servers[i].net_version = j_row["version"].GetString(); res->servers[i].display_version = Ogre::StringUtil::replaceAll(j_row["version"].GetString(), "RoRnet_", ""); } @@ -146,7 +148,7 @@ RoR::GUI::MpServerlistData* FetchServerlist(std::string portal_url) } #endif // defined(USE_CURL) -inline void DrawTableHeader(const char* title) // Internal helper +inline void DrawTableHeader(const char *title) // Internal helper { float table_padding_y = 4.f; ImGui::SetCursorPosY(ImGui::GetCursorPosY() + table_padding_y); @@ -154,34 +156,30 @@ inline void DrawTableHeader(const char* title) // Internal helper ImGui::NextColumn(); } -RoR::GUI::MultiplayerSelector::MultiplayerSelector(): - m_selected_item(-1), m_mode(Mode::ONLINE), m_is_refreshing(false), m_is_visible(false) +RoR::GUI::MultiplayerSelector::MultiplayerSelector() + : m_selected_item(-1), m_mode(Mode::ONLINE), m_is_refreshing(false), m_is_visible(false) { snprintf(m_window_title, 100, "Multiplayer (Rigs of Rods %s | %s)", ROR_VERSION_STRING, RORNET_VERSION); } RoR::GUI::MultiplayerSelector::~MultiplayerSelector() -{} +{ +} void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() { const float TABS_BOTTOM_PADDING = 4.f; // They're actually buttons in role of tabs. const float CONTENT_TOP_PADDING = 4.f; // Extra space under top horizontal separator bar. const float BUTTONS_EXTRA_SPACE = 6.f; - const float TABLE_PADDING_LEFT = 4.f; + const float TABLE_PADDING_LEFT = 4.f; int window_flags = ImGuiWindowFlags_NoCollapse; ImGui::SetNextWindowSize(ImVec2(750.f, 400.f), ImGuiSetCond_FirstUseEver); ImGui::SetNextWindowPosCenter(); - if (!ImGui::Begin(m_window_title, &m_is_visible, window_flags)) - { - return; - } + if (!ImGui::Begin(m_window_title, &m_is_visible, window_flags)) { return; } if (!m_is_visible) // If the window was closed... - { - App::GetGuiManager()->SetVisible_GameMainMenu(true); - } + { App::GetGuiManager()->SetVisible_GameMainMenu(true); } // Window mode buttons MultiplayerSelector::Mode next_mode = m_mode; @@ -194,15 +192,9 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() next_mode = Mode::ONLINE; } ImGui::SameLine(); - if (ImGui::Button("Direct IP")) - { - next_mode = Mode::DIRECT; - } + if (ImGui::Button("Direct IP")) { next_mode = Mode::DIRECT; } ImGui::SameLine(); - if (ImGui::Button("Settings")) - { - next_mode = Mode::SETUP; - } + if (ImGui::Button("Settings")) { next_mode = Mode::SETUP; } ImGui::SetCursorPosY(ImGui::GetCursorPosY() + TABS_BOTTOM_PADDING); ImGui::Separator(); @@ -214,25 +206,25 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() { ImGui::PushID("setup"); - DrawGCheckbox(App::mp_join_on_startup, "Auto connect"); - DrawGCheckbox(App::mp_chat_auto_hide, "Auto hide chat"); - DrawGCheckbox(App::mp_hide_net_labels, "Hide net labels"); + DrawGCheckbox(App::mp_join_on_startup, "Auto connect"); + DrawGCheckbox(App::mp_chat_auto_hide, "Auto hide chat"); + DrawGCheckbox(App::mp_hide_net_labels, "Hide net labels"); DrawGCheckbox(App::mp_hide_own_net_label, "Hide own net label"); - DrawGCheckbox(App::mp_pseudo_collisions, "Multiplayer collisions"); + DrawGCheckbox(App::mp_pseudo_collisions, "Multiplayer collisions"); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + BUTTONS_EXTRA_SPACE); ImGui::Separator(); ImGui::PushItemWidth(250.f); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + CONTENT_TOP_PADDING); - DrawGTextEdit(App::mp_player_name, "Player nickname", m_player_name_buf); - DrawGTextEdit(App::mp_server_password, "Default server password", m_password_buf, true); + DrawGTextEdit(App::mp_player_name, "Player nickname", m_player_name_buf); + DrawGTextEdit(App::mp_server_password, "Default server password", m_password_buf, true); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + BUTTONS_EXTRA_SPACE); ImGui::Separator(); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + CONTENT_TOP_PADDING); - DrawGTextEdit(App::mp_player_token, "User token", m_user_token_buf); + DrawGTextEdit(App::mp_player_token, "User token", m_user_token_buf); ImGui::PopItemWidth(); ImGui::PopID(); @@ -258,14 +250,14 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() } else if (m_mode == Mode::ONLINE) { - const char* draw_label_text = nullptr; + const char *draw_label_text = nullptr; ImVec4 draw_label_color; bool draw_table = false; // DETERMINE WHAT TO DRAW if (m_is_refreshing) { - draw_label_text = "... refreshing ..."; + draw_label_text = "... refreshing ..."; draw_label_color = App::GetGuiManager()->GetTheme().in_progress_text_color; } else if (m_serverlist_data != nullptr) @@ -275,13 +267,13 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() draw_table = true; if (m_serverlist_data->servers.size() == 0) { - draw_label_text = "There are no available servers :/"; // Draw empty table _and_ the label. + draw_label_text = "There are no available servers :/"; // Draw empty table _and_ the label. draw_label_color = App::GetGuiManager()->GetTheme().no_entries_text_color; } } else { - draw_label_text = m_serverlist_data->message.c_str(); + draw_label_text = m_serverlist_data->message.c_str(); draw_label_color = App::GetGuiManager()->GetTheme().error_text_color; } } @@ -290,18 +282,19 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() if (draw_table) { // Setup serverlist table ... the scroll area - const float table_height = ImGui::GetWindowHeight() - - ((2.f * ImGui::GetStyle().WindowPadding.y) + (3.f * ImGui::GetItemsLineHeightWithSpacing()) - + TABS_BOTTOM_PADDING + CONTENT_TOP_PADDING - ImGui::GetStyle().ItemSpacing.y); + const float table_height = + ImGui::GetWindowHeight() - + ((2.f * ImGui::GetStyle().WindowPadding.y) + (3.f * ImGui::GetItemsLineHeightWithSpacing()) + + TABS_BOTTOM_PADDING + CONTENT_TOP_PADDING - ImGui::GetStyle().ItemSpacing.y); ImGui::BeginChild("scrolling", ImVec2(0.f, table_height), false); // ... and the table itself const float table_width = ImGui::GetWindowContentRegionWidth(); - ImGui::Columns(6, "mp-selector-columns"); // Col #0: Passwd - ImGui::SetColumnOffset(1, 0.09f * table_width); // Col #1: Server name - ImGui::SetColumnOffset(2, 0.36f * table_width); // Col #2: Terrain name - ImGui::SetColumnOffset(3, 0.67f * table_width); // Col #3: Users/Max - ImGui::SetColumnOffset(4, 0.74f * table_width); // Col #4: Version - ImGui::SetColumnOffset(5, 0.82f * table_width); // Col #5: Host/Port + ImGui::Columns(6, "mp-selector-columns"); // Col #0: Passwd + ImGui::SetColumnOffset(1, 0.09f * table_width); // Col #1: Server name + ImGui::SetColumnOffset(2, 0.36f * table_width); // Col #2: Terrain name + ImGui::SetColumnOffset(3, 0.67f * table_width); // Col #3: Users/Max + ImGui::SetColumnOffset(4, 0.74f * table_width); // Col #4: Version + ImGui::SetColumnOffset(5, 0.82f * table_width); // Col #5: Host/Port // Draw table header ImGui::SetCursorPosX(ImGui::GetCursorPosX() + TABLE_PADDING_LEFT); DrawTableHeader("Passwd?"); @@ -319,24 +312,27 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() // First column - selection control ImGui::SetCursorPosX(ImGui::GetCursorPosX() + TABLE_PADDING_LEFT); - MpServerlistData::ServerInfo& server = m_serverlist_data->servers[i]; + MpServerlistData::ServerInfo &server = m_serverlist_data->servers[i]; if (ImGui::Selectable(server.display_passwd, m_selected_item == i, ImGuiSelectableFlags_SpanAllColumns)) - { - m_selected_item = i; - } + { m_selected_item = i; } ImGui::NextColumn(); - bool compatible = (server.net_version == RORNET_VERSION); + bool compatible = (server.net_version == RORNET_VERSION); ImVec4 version_color = compatible ? ImVec4(0.0f, 0.9f, 0.0f, 1.0f) : ImVec4(0.9f, 0.0f, 0.0f, 1.0f); // Other collumns - ImGui::Text("%s", server.display_name.ToCStr()); ImGui::NextColumn(); - ImGui::Text("%s", server.display_terrn.ToCStr()); ImGui::NextColumn(); - ImGui::Text("%s", server.display_users.ToCStr()); ImGui::NextColumn(); + ImGui::Text("%s", server.display_name.ToCStr()); + ImGui::NextColumn(); + ImGui::Text("%s", server.display_terrn.ToCStr()); + ImGui::NextColumn(); + ImGui::Text("%s", server.display_users.ToCStr()); + ImGui::NextColumn(); ImGui::PushStyleColor(ImGuiCol_Text, version_color); - ImGui::Text("%s", server.display_version.ToCStr()); ImGui::NextColumn(); + ImGui::Text("%s", server.display_version.ToCStr()); + ImGui::NextColumn(); ImGui::PopStyleColor(); - ImGui::Text("%s", server.display_host.ToCStr()); ImGui::NextColumn(); + ImGui::Text("%s", server.display_host.ToCStr()); + ImGui::NextColumn(); ImGui::PopID(); } @@ -346,7 +342,7 @@ void RoR::GUI::MultiplayerSelector::MultiplayerSelector::Draw() // Simple join button (and password input box) if (m_selected_item != -1 && m_serverlist_data->servers[m_selected_item].net_version == RORNET_VERSION) { - MpServerlistData::ServerInfo& server = m_serverlist_data->servers[m_selected_item]; + MpServerlistData::ServerInfo &server = m_serverlist_data->servers[m_selected_item]; if (ImGui::Button("Join", ImVec2(200.f, 0.f))) { App::mp_server_password.SetActive(m_password_buf.GetBuffer()); @@ -384,10 +380,10 @@ void RoR::GUI::MultiplayerSelector::RefreshServerlist() m_serverlist_data.reset(); m_selected_item = -1; m_is_refreshing = true; - std::packaged_task task(FetchServerlist); + std::packaged_task task(FetchServerlist); m_serverlist_future = task.get_future(); std::thread(std::move(task), App::mp_api_url.GetActive()).detach(); // launch on a thread -#endif // defined(USE_CURL) +#endif // defined(USE_CURL) } bool RoR::GUI::MultiplayerSelector::IsRefreshThreadRunning() const @@ -398,13 +394,10 @@ bool RoR::GUI::MultiplayerSelector::IsRefreshThreadRunning() const void RoR::GUI::MultiplayerSelector::CheckAndProcessRefreshResult() { std::future_status status = m_serverlist_future.wait_for(std::chrono::seconds(0)); - if (status != std::future_status::ready) - { - return; - } + if (status != std::future_status::ready) { return; } m_serverlist_data = std::unique_ptr(m_serverlist_future.get()); - m_is_refreshing = false; + m_is_refreshing = false; return; } diff --git a/source/main/gui/panels/GUI_MultiplayerSelector.h b/source/main/gui/panels/GUI_MultiplayerSelector.h index 5b1d169ad9..ca6c8714e3 100644 --- a/source/main/gui/panels/GUI_MultiplayerSelector.h +++ b/source/main/gui/panels/GUI_MultiplayerSelector.h @@ -29,40 +29,49 @@ #include #include -namespace RoR{ -namespace GUI { - -struct MpServerlistData; // Forward declaration, private implementation. - -class MultiplayerSelector +namespace RoR { -public: - - MultiplayerSelector(); - ~MultiplayerSelector(); - - void SetVisible(bool v); - inline bool IsVisible() { return m_is_visible; } - void RefreshServerlist(); /// Launch refresh from main thread - bool IsRefreshThreadRunning() const; /// Check status from main thread - void CheckAndProcessRefreshResult(); /// To be invoked periodically from main thread if refresh is in progress. - void Draw(); - -private: - enum class Mode { ONLINE, DIRECT, SETUP }; - - std::future m_serverlist_future; - std::unique_ptr m_serverlist_data; - int m_selected_item; - Mode m_mode; - bool m_is_refreshing; - char m_window_title[100]; - bool m_is_visible; - Str<100> m_user_token_buf; - Str<100> m_player_name_buf; - Str<100> m_password_buf; - Str<200> m_server_host_buf; -}; - -} // namespace GUI + namespace GUI + { + + struct MpServerlistData; // Forward declaration, private implementation. + + class MultiplayerSelector + { + public: + MultiplayerSelector(); + ~MultiplayerSelector(); + + void SetVisible(bool v); + inline bool IsVisible() + { + return m_is_visible; + } + void RefreshServerlist(); /// Launch refresh from main thread + bool IsRefreshThreadRunning() const; /// Check status from main thread + void CheckAndProcessRefreshResult(); /// To be invoked periodically from main thread if refresh is in progress. + void Draw(); + + private: + enum class Mode + { + ONLINE, + DIRECT, + SETUP + }; + + std::future m_serverlist_future; + std::unique_ptr m_serverlist_data; + int m_selected_item; + Mode m_mode; + bool m_is_refreshing; + char m_window_title[100]; + bool m_is_visible; + Str<100> m_user_token_buf; + Str<100> m_player_name_buf; + Str<100> m_password_buf; + Str<200> m_server_host_buf; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_NodeBeamUtils.cpp b/source/main/gui/panels/GUI_NodeBeamUtils.cpp index 537702044b..0951782408 100644 --- a/source/main/gui/panels/GUI_NodeBeamUtils.cpp +++ b/source/main/gui/panels/GUI_NodeBeamUtils.cpp @@ -26,12 +26,12 @@ void RoR::GUI::NodeBeamUtils::Draw() { - bool is_visible = true; - const int flags = ImGuiWindowFlags_NoCollapse; + bool is_visible = true; + const int flags = ImGuiWindowFlags_NoCollapse; ImGui::SetNextWindowSize(ImVec2(600.f, 675.f), ImGuiSetCond_FirstUseEver); ImGui::Begin("Node/Beam Utils", &is_visible, flags); - Actor* actor = App::GetSimController()->GetPlayerActor(); + Actor *actor = App::GetSimController()->GetPlayerActor(); if (!is_visible || actor == nullptr) { @@ -46,87 +46,72 @@ void RoR::GUI::NodeBeamUtils::Draw() float cur_mass = actor->getTotalMass(false); if (ImGui::SliderFloat("Total mass", &cur_mass, ref_mass * 0.5f, ref_mass * 2.0f, "%.2f kg")) { - actor->ar_nb_mass_scale = cur_mass / ref_mass; + actor->ar_nb_mass_scale = cur_mass / ref_mass; actor->ar_nb_initialized = false; actor->ApplyNodeBeamScales(); } ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Beams:"); if (ImGui::SliderFloat("Spring##Beams", &actor->ar_nb_beams_scale.first, 0.1f, 10.0f, "%.5f")) - { - actor->ApplyNodeBeamScales(); - } + { actor->ApplyNodeBeamScales(); } if (ImGui::SliderFloat("Damping##Beams", &actor->ar_nb_beams_scale.second, 0.1f, 10.0f, "%.5f")) - { - actor->ApplyNodeBeamScales(); - } + { actor->ApplyNodeBeamScales(); } ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Shocks:"); if (ImGui::SliderFloat("Spring##Shocks", &actor->ar_nb_shocks_scale.first, 0.1f, 10.0f, "%.5f")) - { - actor->ApplyNodeBeamScales(); - } + { actor->ApplyNodeBeamScales(); } if (ImGui::SliderFloat("Damping##Shocks", &actor->ar_nb_shocks_scale.second, 0.1f, 10.0f, "%.5f")) - { - actor->ApplyNodeBeamScales(); - } + { actor->ApplyNodeBeamScales(); } ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Wheels:"); if (ImGui::SliderFloat("Spring##Wheels", &actor->ar_nb_wheels_scale.first, 0.1f, 10.0f, "%.5f")) - { - actor->ApplyNodeBeamScales(); - } + { actor->ApplyNodeBeamScales(); } if (ImGui::SliderFloat("Damping##Wheels", &actor->ar_nb_wheels_scale.second, 0.1f, 10.0f, "%.5f")) - { - actor->ApplyNodeBeamScales(); - } + { actor->ApplyNodeBeamScales(); } ImGui::Separator(); ImGui::Spacing(); if (ImGui::Button("Reset to default settings", ImVec2(280.f, 25.f))) { - actor->ar_nb_mass_scale = 1.0f; - actor->ar_nb_beams_scale = {1.0f, 1.0f}; + actor->ar_nb_mass_scale = 1.0f; + actor->ar_nb_beams_scale = {1.0f, 1.0f}; actor->ar_nb_shocks_scale = {1.0f, 1.0f}; actor->ar_nb_wheels_scale = {1.0f, 1.0f}; actor->SyncReset(true); } ImGui::SameLine(); - if (ImGui::Button("Update initial node positions", ImVec2(280.f, 25.f))) - { - actor->UpdateInitPosition(); - } + if (ImGui::Button("Update initial node positions", ImVec2(280.f, 25.f))) { actor->UpdateInitPosition(); } ImGui::PopItemWidth(); ImGui::PushItemWidth(235.f); // Width includes [+/-] buttons ImGui::TextColored(GRAY_HINT_TEXT, "Physics steps:"); - ImGui::SliderInt("Skip##BeamsInt", &actor->ar_nb_skip_steps, 0, 2000); + ImGui::SliderInt("Skip##BeamsInt", &actor->ar_nb_skip_steps, 0, 2000); ImGui::SameLine(); - ImGui::SliderInt("Measure##BeamsInt", &actor->ar_nb_measure_steps, 2, 6000); + ImGui::SliderInt("Measure##BeamsInt", &actor->ar_nb_measure_steps, 2, 6000); ImGui::PopItemWidth(); ImGui::PushItemWidth(138.f); // Width includes [+/-] buttons ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Beams (spring & damping search interval):"); - ImGui::SliderFloat("##BSL", &actor->ar_nb_beams_k_interval.first, 0.1f, actor->ar_nb_beams_k_interval.second); + ImGui::SliderFloat("##BSL", &actor->ar_nb_beams_k_interval.first, 0.1f, actor->ar_nb_beams_k_interval.second); ImGui::SameLine(); - ImGui::SliderFloat("##BSU", &actor->ar_nb_beams_k_interval.second, actor->ar_nb_beams_k_interval.first, 10.0f); + ImGui::SliderFloat("##BSU", &actor->ar_nb_beams_k_interval.second, actor->ar_nb_beams_k_interval.first, 10.0f); ImGui::SameLine(); - ImGui::SliderFloat("##BDL", &actor->ar_nb_beams_d_interval.first, 0.1f, actor->ar_nb_beams_d_interval.second); + ImGui::SliderFloat("##BDL", &actor->ar_nb_beams_d_interval.first, 0.1f, actor->ar_nb_beams_d_interval.second); ImGui::SameLine(); - ImGui::SliderFloat("##BDU", &actor->ar_nb_beams_d_interval.second, actor->ar_nb_beams_d_interval.first, 10.0f); + ImGui::SliderFloat("##BDU", &actor->ar_nb_beams_d_interval.second, actor->ar_nb_beams_d_interval.first, 10.0f); ImGui::TextColored(GRAY_HINT_TEXT, "Shocks (spring & damping search interval):"); - ImGui::SliderFloat("##SSL", &actor->ar_nb_shocks_k_interval.first, 0.1f, actor->ar_nb_shocks_k_interval.second); + ImGui::SliderFloat("##SSL", &actor->ar_nb_shocks_k_interval.first, 0.1f, actor->ar_nb_shocks_k_interval.second); ImGui::SameLine(); ImGui::SliderFloat("##SSU", &actor->ar_nb_shocks_k_interval.second, actor->ar_nb_shocks_k_interval.first, 10.0f); ImGui::SameLine(); - ImGui::SliderFloat("##SDL", &actor->ar_nb_shocks_d_interval.first, 0.1f, actor->ar_nb_shocks_d_interval.second); + ImGui::SliderFloat("##SDL", &actor->ar_nb_shocks_d_interval.first, 0.1f, actor->ar_nb_shocks_d_interval.second); ImGui::SameLine(); ImGui::SliderFloat("##SDU", &actor->ar_nb_shocks_d_interval.second, actor->ar_nb_shocks_d_interval.first, 10.0f); ImGui::TextColored(GRAY_HINT_TEXT, "Wheels (spring & damping search interval):"); - ImGui::SliderFloat("##WSL", &actor->ar_nb_wheels_k_interval.first, 0.1f, actor->ar_nb_wheels_k_interval.second); + ImGui::SliderFloat("##WSL", &actor->ar_nb_wheels_k_interval.first, 0.1f, actor->ar_nb_wheels_k_interval.second); ImGui::SameLine(); ImGui::SliderFloat("##WSU", &actor->ar_nb_wheels_k_interval.second, actor->ar_nb_wheels_k_interval.first, 10.0f); ImGui::SameLine(); - ImGui::SliderFloat("##WDL", &actor->ar_nb_wheels_d_interval.first, 0.1f, actor->ar_nb_wheels_d_interval.second); + ImGui::SliderFloat("##WDL", &actor->ar_nb_wheels_d_interval.first, 0.1f, actor->ar_nb_wheels_d_interval.second); ImGui::SameLine(); ImGui::SliderFloat("##WDU", &actor->ar_nb_wheels_d_interval.second, actor->ar_nb_wheels_d_interval.first, 10.0f); ImGui::PopItemWidth(); @@ -136,16 +121,13 @@ void RoR::GUI::NodeBeamUtils::Draw() if (ImGui::Button(txt, ImVec2(280.f, 25.f))) { m_is_searching = !m_is_searching; - if (!m_is_searching) - { - actor->SyncReset(true); - } + if (!m_is_searching) { actor->SyncReset(true); } } ImGui::SameLine(); if (ImGui::Button("Reset search", ImVec2(280.f, 25.f))) { actor->ar_nb_initialized = false; - m_is_searching = false; + m_is_searching = false; } ImGui::Separator(); ImGui::Spacing(); @@ -158,20 +140,17 @@ void RoR::GUI::NodeBeamUtils::Draw() ImGui::Text("Optimum"); ImGui::NextColumn(); ImGui::Separator(); - ImGui::Text("Movement: %f (%f)", actor->ar_nb_reference[5] / actor->ar_num_nodes, actor->ar_nb_reference[4]); + ImGui::Text("Movement: %f (%f)", actor->ar_nb_reference[5] / actor->ar_num_nodes, actor->ar_nb_reference[4]); ImGui::Text("Stress: %.2f (%.2f)", actor->ar_nb_reference[1] / actor->ar_num_beams, actor->ar_nb_reference[0]); - ImGui::Text("Yitter: %f (%f)", actor->ar_nb_reference[3] / actor->ar_num_beams, actor->ar_nb_reference[2]); + ImGui::Text("Yitter: %f (%f)", actor->ar_nb_reference[3] / actor->ar_num_beams, actor->ar_nb_reference[2]); ImGui::NextColumn(); - ImGui::Text("Movement: %f (%f)", actor->ar_nb_optimum[5] / actor->ar_num_nodes, actor->ar_nb_optimum[4]); + ImGui::Text("Movement: %f (%f)", actor->ar_nb_optimum[5] / actor->ar_num_nodes, actor->ar_nb_optimum[4]); ImGui::Text("Stress: %.2f (%.2f)", actor->ar_nb_optimum[1] / actor->ar_num_beams, actor->ar_nb_optimum[0]); - ImGui::Text("Yitter: %f (%f)", actor->ar_nb_optimum[3] / actor->ar_num_beams, actor->ar_nb_optimum[2]); + ImGui::Text("Yitter: %f (%f)", actor->ar_nb_optimum[3] / actor->ar_num_beams, actor->ar_nb_optimum[2]); ImGui::Columns(1); } - if (m_is_searching) - { - actor->SearchBeamDefaults(); - } + if (m_is_searching) { actor->SearchBeamDefaults(); } ImGui::End(); } diff --git a/source/main/gui/panels/GUI_NodeBeamUtils.h b/source/main/gui/panels/GUI_NodeBeamUtils.h index f3c062b13c..fc19a4c1ad 100644 --- a/source/main/gui/panels/GUI_NodeBeamUtils.h +++ b/source/main/gui/panels/GUI_NodeBeamUtils.h @@ -22,25 +22,35 @@ #include "Application.h" #include "OgreImGui.h" -namespace RoR { -namespace GUI { - -class NodeBeamUtils +namespace RoR { -public: - NodeBeamUtils(): m_is_visible(false), m_is_searching(false) {} - - void Draw(); - - inline bool IsVisible() const { return m_is_visible; } - inline void SetVisible(bool v) { m_is_visible = v; } - -private: - bool m_is_visible; - bool m_is_searching; - - const ImVec4 GRAY_HINT_TEXT = ImVec4(0.62f, 0.62f, 0.61f, 1.f); -}; - -} // namespace GUI + namespace GUI + { + + class NodeBeamUtils + { + public: + NodeBeamUtils() : m_is_visible(false), m_is_searching(false) + { + } + + void Draw(); + + inline bool IsVisible() const + { + return m_is_visible; + } + inline void SetVisible(bool v) + { + m_is_visible = v; + } + + private: + bool m_is_visible; + bool m_is_searching; + + const ImVec4 GRAY_HINT_TEXT = ImVec4(0.62f, 0.62f, 0.61f, 1.f); + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_OpenSaveFileDialog.cpp b/source/main/gui/panels/GUI_OpenSaveFileDialog.cpp index 4473c2955b..75975973e9 100644 --- a/source/main/gui/panels/GUI_OpenSaveFileDialog.cpp +++ b/source/main/gui/panels/GUI_OpenSaveFileDialog.cpp @@ -34,16 +34,9 @@ using namespace RoR; using namespace GUI; -OpenSaveFileDialog::OpenSaveFileDialog() : - Dialog("OpenSaveFileDialog.layout"), - mWindow(nullptr), - mListFiles(nullptr), - mEditFileName(nullptr), - mButtonUp(nullptr), - mCurrentFolderField(nullptr), - mButtonOpenSave(nullptr), - mFileMask("*.*"), - mFolderMode(false) +OpenSaveFileDialog::OpenSaveFileDialog() + : Dialog("OpenSaveFileDialog.layout"), mWindow(nullptr), mListFiles(nullptr), mEditFileName(nullptr), mButtonUp(nullptr), + mCurrentFolderField(nullptr), mButtonOpenSave(nullptr), mFileMask("*.*"), mFolderMode(false) { assignWidget(mListFiles, "ListFiles"); assignWidget(mEditFileName, "EditFileName"); @@ -57,7 +50,8 @@ OpenSaveFileDialog::OpenSaveFileDialog() : mEditFileName->eventEditSelectAccept += MyGUI::newDelegate(this, &OpenSaveFileDialog::notifyEditSelectAccept); mButtonUp->eventMouseButtonClick += MyGUI::newDelegate(this, &OpenSaveFileDialog::notifyUpButtonClick); mCurrentFolderField->eventComboAccept += MyGUI::newDelegate(this, &OpenSaveFileDialog::notifyDirectoryComboAccept); - mCurrentFolderField->eventComboChangePosition += MyGUI::newDelegate(this, &OpenSaveFileDialog::notifyDirectoryComboChangePosition); + mCurrentFolderField->eventComboChangePosition += + MyGUI::newDelegate(this, &OpenSaveFileDialog::notifyDirectoryComboChangePosition); mButtonOpenSave->eventMouseButtonClick += MyGUI::newDelegate(this, &OpenSaveFileDialog::notifyMouseButtonClick); mWindow = mMainWidget->castType(); @@ -70,28 +64,27 @@ OpenSaveFileDialog::OpenSaveFileDialog() : update(); } -void OpenSaveFileDialog::notifyWindowButtonPressed(MyGUI::Window* _sender, const std::string& _name) +void OpenSaveFileDialog::notifyWindowButtonPressed(MyGUI::Window *_sender, const std::string &_name) { - if (_name == "close") - eventEndDialog(this, false); + if (_name == "close") eventEndDialog(this, false); } -void OpenSaveFileDialog::notifyEditSelectAccept(MyGUI::EditBox* _sender) +void OpenSaveFileDialog::notifyEditSelectAccept(MyGUI::EditBox *_sender) { accept(); } -void OpenSaveFileDialog::notifyMouseButtonClick(MyGUI::Widget* _sender) +void OpenSaveFileDialog::notifyMouseButtonClick(MyGUI::Widget *_sender) { accept(); } -void OpenSaveFileDialog::notifyUpButtonClick(MyGUI::Widget* _sender) +void OpenSaveFileDialog::notifyUpButtonClick(MyGUI::Widget *_sender) { upFolder(); } -void OpenSaveFileDialog::setDialogInfo(const MyGUI::UString& _caption, const MyGUI::UString& _button, bool _folderMode) +void OpenSaveFileDialog::setDialogInfo(const MyGUI::UString &_caption, const MyGUI::UString &_button, bool _folderMode) { mFolderMode = _folderMode; mWindow->setCaption(_caption); @@ -99,32 +92,24 @@ void OpenSaveFileDialog::setDialogInfo(const MyGUI::UString& _caption, const MyG mEditFileName->setVisible(!_folderMode); } -void OpenSaveFileDialog::notifyListChangePosition(MyGUI::ListBox* _sender, size_t _index) +void OpenSaveFileDialog::notifyListChangePosition(MyGUI::ListBox *_sender, size_t _index) { - if (_index == MyGUI::ITEM_NONE) - { - mEditFileName->setCaption(""); - } + if (_index == MyGUI::ITEM_NONE) { mEditFileName->setCaption(""); } else { FileSystem::FileInfo info = *_sender->getItemDataAt(_index); - if (!info.folder) - mEditFileName->setCaption(info.name); + if (!info.folder) mEditFileName->setCaption(info.name); } } -void OpenSaveFileDialog::notifyListSelectAccept(MyGUI::ListBox* _sender, size_t _index) +void OpenSaveFileDialog::notifyListSelectAccept(MyGUI::ListBox *_sender, size_t _index) { - if (_index == MyGUI::ITEM_NONE) - return; + if (_index == MyGUI::ITEM_NONE) return; FileSystem::FileInfo info = *_sender->getItemDataAt(_index); if (info.folder) { - if (info.name == L"..") - { - upFolder(); - } + if (info.name == L"..") { upFolder(); } else { mCurrentFolder = FileSystem::concatenatePath(mCurrentFolder.asWStr(), info.name); @@ -142,8 +127,7 @@ void OpenSaveFileDialog::accept() if (!mFolderMode) { mFileName = mEditFileName->getOnlyText(); - if (!mFileName.empty()) - eventEndDialog(this, true); + if (!mFileName.empty()) eventEndDialog(this, true); } else { @@ -160,14 +144,11 @@ void OpenSaveFileDialog::accept() void OpenSaveFileDialog::upFolder() { size_t index = mCurrentFolder.find_last_of(L"\\/"); - if (index != std::string::npos) - { - mCurrentFolder = mCurrentFolder.substr(0, index); - } + if (index != std::string::npos) { mCurrentFolder = mCurrentFolder.substr(0, index); } update(); } -void OpenSaveFileDialog::setCurrentFolder(const MyGUI::UString& _folder) +void OpenSaveFileDialog::setCurrentFolder(const MyGUI::UString &_folder) { mCurrentFolder = _folder.empty() ? MyGUI::UString(FileSystem::getSystemCurrentFolder()) : _folder; @@ -176,8 +157,7 @@ void OpenSaveFileDialog::setCurrentFolder(const MyGUI::UString& _folder) void OpenSaveFileDialog::update() { - if (mCurrentFolder.empty()) - mCurrentFolder = "/"; + if (mCurrentFolder.empty()) mCurrentFolder = "/"; mCurrentFolderField->setCaption(mCurrentFolder); mListFiles->removeAllItems(); @@ -188,8 +168,7 @@ void OpenSaveFileDialog::update() for (FileSystem::VectorFileInfo::iterator item = infos.begin(); item != infos.end(); ++item) { - if ((*item).folder) - mListFiles->addItem(L"[" + (*item).name + L"]", *item); + if ((*item).folder) mListFiles->addItem(L"[" + (*item).name + L"]", *item); } if (!mFolderMode) @@ -200,25 +179,24 @@ void OpenSaveFileDialog::update() for (FileSystem::VectorFileInfo::iterator item = infos.begin(); item != infos.end(); ++item) { - if (!(*item).folder) - mListFiles->addItem((*item).name, *item); + if (!(*item).folder) mListFiles->addItem((*item).name, *item); } } } -void OpenSaveFileDialog::setFileName(const MyGUI::UString& _value) +void OpenSaveFileDialog::setFileName(const MyGUI::UString &_value) { mFileName = _value; mEditFileName->setCaption(_value); } -void OpenSaveFileDialog::setFileMask(const MyGUI::UString& _value) +void OpenSaveFileDialog::setFileMask(const MyGUI::UString &_value) { mFileMask = _value; update(); } -const MyGUI::UString& OpenSaveFileDialog::getFileMask() const +const MyGUI::UString &OpenSaveFileDialog::getFileMask() const { return mFileMask; } @@ -237,41 +215,40 @@ void OpenSaveFileDialog::onEndModal() { } -void OpenSaveFileDialog::notifyDirectoryComboAccept(MyGUI::ComboBox* _sender, size_t _index) +void OpenSaveFileDialog::notifyDirectoryComboAccept(MyGUI::ComboBox *_sender, size_t _index) { setCurrentFolder(_sender->getOnlyText()); } -const MyGUI::UString& OpenSaveFileDialog::getCurrentFolder() const +const MyGUI::UString &OpenSaveFileDialog::getCurrentFolder() const { return mCurrentFolder; } -const MyGUI::UString& OpenSaveFileDialog::getFileName() const +const MyGUI::UString &OpenSaveFileDialog::getFileName() const { return mFileName; } -const MyGUI::UString& OpenSaveFileDialog::getMode() const +const MyGUI::UString &OpenSaveFileDialog::getMode() const { return mMode; } -void OpenSaveFileDialog::setMode(const MyGUI::UString& _value) +void OpenSaveFileDialog::setMode(const MyGUI::UString &_value) { mMode = _value; } -void OpenSaveFileDialog::setRecentFolders(const VectorUString& _listFolders) +void OpenSaveFileDialog::setRecentFolders(const VectorUString &_listFolders) { mCurrentFolderField->removeAllItems(); - for (VectorUString::const_iterator item = _listFolders.begin(); item != _listFolders.end(); ++ item) + for (VectorUString::const_iterator item = _listFolders.begin(); item != _listFolders.end(); ++item) mCurrentFolderField->addItem((*item)); } -void OpenSaveFileDialog::notifyDirectoryComboChangePosition(MyGUI::ComboBox* _sender, size_t _index) +void OpenSaveFileDialog::notifyDirectoryComboChangePosition(MyGUI::ComboBox *_sender, size_t _index) { - if (_index != MyGUI::ITEM_NONE) - setCurrentFolder(_sender->getItemNameAt(_index)); + if (_index != MyGUI::ITEM_NONE) setCurrentFolder(_sender->getItemNameAt(_index)); } diff --git a/source/main/gui/panels/GUI_OpenSaveFileDialog.h b/source/main/gui/panels/GUI_OpenSaveFileDialog.h index 77a3e5ff0f..865baee838 100644 --- a/source/main/gui/panels/GUI_OpenSaveFileDialog.h +++ b/source/main/gui/panels/GUI_OpenSaveFileDialog.h @@ -29,69 +29,71 @@ #pragma once -#include #include "Dialog.h" -namespace RoR { -namespace GUI { +#include -class OpenSaveFileDialog : - public Dialog +namespace RoR { -public: - OpenSaveFileDialog(); + namespace GUI + { + + class OpenSaveFileDialog : public Dialog + { + public: + OpenSaveFileDialog(); - void setDialogInfo(const MyGUI::UString& _caption, const MyGUI::UString& _button, bool _folderMode = false); + void setDialogInfo(const MyGUI::UString &_caption, const MyGUI::UString &_button, bool _folderMode = false); - void setCurrentFolder(const MyGUI::UString& _value); - const MyGUI::UString& getCurrentFolder() const; + void setCurrentFolder(const MyGUI::UString &_value); + const MyGUI::UString &getCurrentFolder() const; - void setFileName(const MyGUI::UString& _value); - const MyGUI::UString& getFileName() const; + void setFileName(const MyGUI::UString &_value); + const MyGUI::UString &getFileName() const; - const MyGUI::UString& getMode() const; - void setMode(const MyGUI::UString& _value); + const MyGUI::UString &getMode() const; + void setMode(const MyGUI::UString &_value); - typedef std::vector VectorUString; - void setRecentFolders(const VectorUString& _listFolders); + typedef std::vector VectorUString; + void setRecentFolders(const VectorUString &_listFolders); - void setFileMask(const MyGUI::UString& _value); - const MyGUI::UString& getFileMask() const; + void setFileMask(const MyGUI::UString &_value); + const MyGUI::UString &getFileMask() const; -protected: - virtual void onDoModal(); - virtual void onEndModal(); + protected: + virtual void onDoModal(); + virtual void onEndModal(); -private: - void notifyWindowButtonPressed(MyGUI::Window* _sender, const std::string& _name); - void notifyDirectoryComboAccept(MyGUI::ComboBox* _sender, size_t _index); - void notifyDirectoryComboChangePosition(MyGUI::ComboBox* _sender, size_t _index); - void notifyListChangePosition(MyGUI::ListBox* _sender, size_t _index); - void notifyListSelectAccept(MyGUI::ListBox* _sender, size_t _index); - void notifyEditSelectAccept(MyGUI::EditBox* _sender); - void notifyMouseButtonClick(MyGUI::Widget* _sender); - void notifyUpButtonClick(MyGUI::Widget* _sender); + private: + void notifyWindowButtonPressed(MyGUI::Window *_sender, const std::string &_name); + void notifyDirectoryComboAccept(MyGUI::ComboBox *_sender, size_t _index); + void notifyDirectoryComboChangePosition(MyGUI::ComboBox *_sender, size_t _index); + void notifyListChangePosition(MyGUI::ListBox *_sender, size_t _index); + void notifyListSelectAccept(MyGUI::ListBox *_sender, size_t _index); + void notifyEditSelectAccept(MyGUI::EditBox *_sender); + void notifyMouseButtonClick(MyGUI::Widget *_sender); + void notifyUpButtonClick(MyGUI::Widget *_sender); - void update(); - void accept(); + void update(); + void accept(); - void upFolder(); + void upFolder(); -private: - MyGUI::Window* mWindow; - MyGUI::ListBox* mListFiles; - MyGUI::EditBox* mEditFileName; - MyGUI::Button* mButtonUp; - MyGUI::ComboBox* mCurrentFolderField; - MyGUI::Button* mButtonOpenSave; + private: + MyGUI::Window * mWindow; + MyGUI::ListBox * mListFiles; + MyGUI::EditBox * mEditFileName; + MyGUI::Button * mButtonUp; + MyGUI::ComboBox *mCurrentFolderField; + MyGUI::Button * mButtonOpenSave; - MyGUI::UString mCurrentFolder; - MyGUI::UString mFileName; - MyGUI::UString mFileMask; + MyGUI::UString mCurrentFolder; + MyGUI::UString mFileName; + MyGUI::UString mFileMask; - MyGUI::UString mMode; - bool mFolderMode; -}; + MyGUI::UString mMode; + bool mFolderMode; + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_RigSpawnerReportWindow.cpp b/source/main/gui/panels/GUI_RigSpawnerReportWindow.cpp index 614311626b..1ea1678f5b 100644 --- a/source/main/gui/panels/GUI_RigSpawnerReportWindow.cpp +++ b/source/main/gui/panels/GUI_RigSpawnerReportWindow.cpp @@ -28,11 +28,10 @@ using namespace RoR; using namespace GUI; -ActorSpawnerReportWindow::ActorSpawnerReportWindow(): - GuiPanelBase(m_rig_spawner_report_window) +ActorSpawnerReportWindow::ActorSpawnerReportWindow() : GuiPanelBase(m_rig_spawner_report_window) { // Close window [X] button - MyGUI::Window* main_window = m_rig_spawner_report_window->castType(); + MyGUI::Window *main_window = m_rig_spawner_report_window->castType(); main_window->eventWindowButtonPressed += MyGUI::newDelegate(this, &ActorSpawnerReportWindow::WindowButtonClicked); // Center on screen @@ -44,12 +43,13 @@ ActorSpawnerReportWindow::ActorSpawnerReportWindow(): main_window->setVisible(false); } -void ActorSpawnerReportWindow::SetRigLoadingReport(std::string const& vehicle_name, std::string const& text, int num_errors, int num_warnings, int num_other) +void ActorSpawnerReportWindow::SetRigLoadingReport(std::string const &vehicle_name, std::string const &text, int num_errors, + int num_warnings, int num_other) { m_rig_spawner_report_window->setCaption("Loading report: " + vehicle_name); std::stringstream summary; - bool first = true; + bool first = true; if (num_errors > 0) { summary << num_errors << "#FF3300 Errors #FFFFFF"; @@ -57,19 +57,13 @@ void ActorSpawnerReportWindow::SetRigLoadingReport(std::string const& vehicle_na } if (num_warnings > 0) { - if (!first) - { - summary << ", "; - } + if (!first) { summary << ", "; } summary << num_warnings << "#FFFF00 Warnings #FFFFFF"; first = false; } if (num_other > 0) { - if (!first) - { - summary << ", "; - } + if (!first) { summary << ", "; } summary << num_other << " notes"; } m_report_summary_textbox->setCaption(summary.str()); @@ -77,10 +71,16 @@ void ActorSpawnerReportWindow::SetRigLoadingReport(std::string const& vehicle_na m_report_text_area->setCaption(text); } -void ActorSpawnerReportWindow::WindowButtonClicked(MyGUI::Widget* sender, const std::string& name) +void ActorSpawnerReportWindow::WindowButtonClicked(MyGUI::Widget *sender, const std::string &name) { this->Hide(); } -void ActorSpawnerReportWindow::SetVisible(bool v) { m_rig_spawner_report_window->setVisible(v); } -bool ActorSpawnerReportWindow::IsVisible() { return m_rig_spawner_report_window->getVisible(); } +void ActorSpawnerReportWindow::SetVisible(bool v) +{ + m_rig_spawner_report_window->setVisible(v); +} +bool ActorSpawnerReportWindow::IsVisible() +{ + return m_rig_spawner_report_window->getVisible(); +} diff --git a/source/main/gui/panels/GUI_RigSpawnerReportWindow.h b/source/main/gui/panels/GUI_RigSpawnerReportWindow.h index a570730c2a..3e61cfe02f 100644 --- a/source/main/gui/panels/GUI_RigSpawnerReportWindow.h +++ b/source/main/gui/panels/GUI_RigSpawnerReportWindow.h @@ -29,26 +29,27 @@ #include "GUI_RigSpawnerReportWindowLayout.h" #include "GuiPanelBase.h" -namespace RoR { -namespace GUI { - -class ActorSpawnerReportWindow: public ActorSpawnerReportWindowLayout, public GuiPanelBase +namespace RoR { -public: - - ActorSpawnerReportWindow(); + namespace GUI + { - void SetRigLoadingReport(std::string const& vehicle_name, std::string const& text, int num_errors, int num_warnings, int num_other); + class ActorSpawnerReportWindow : public ActorSpawnerReportWindowLayout, public GuiPanelBase + { + public: + ActorSpawnerReportWindow(); - void SetVisible(bool v); - bool IsVisible(); + void SetRigLoadingReport(std::string const &vehicle_name, std::string const &text, int num_errors, int num_warnings, + int num_other); -private: + void SetVisible(bool v); + bool IsVisible(); - void WindowButtonClicked(MyGUI::Widget* sender, const std::string& name); + private: + void WindowButtonClicked(MyGUI::Widget *sender, const std::string &name); - GuiManagerInterface* m_gui_manager_interface; -}; + GuiManagerInterface *m_gui_manager_interface; + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.cpp b/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.cpp index 4e1e9e8ec4..4c4db5e74b 100644 --- a/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.cpp +++ b/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -ActorSpawnerReportWindowLayout::ActorSpawnerReportWindowLayout(MyGUI::Widget* _parent) +ActorSpawnerReportWindowLayout::ActorSpawnerReportWindowLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.h b/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.h index eec0a6f0b5..0c166185bd 100644 --- a/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.h +++ b/source/main/gui/panels/GUI_RigSpawnerReportWindowLayout.h @@ -8,36 +8,37 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(ActorSpawnerReportWindowLayout, "RigSpawnerReportWindow.layout"); // Keeping old name, the panel will be replaced by DearIMGUI soon anyway ~ only_a_ptr, 02/2018 -class ActorSpawnerReportWindowLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(ActorSpawnerReportWindowLayout, + "RigSpawnerReportWindow.layout"); // Keeping old name, the panel will be replaced by DearIMGUI soon + // anyway ~ only_a_ptr, 02/2018 + class ActorSpawnerReportWindowLayout : public wraps::BaseLayout + { - ActorSpawnerReportWindowLayout(MyGUI::Widget* _parent = nullptr); - virtual ~ActorSpawnerReportWindowLayout(); + public: + ActorSpawnerReportWindowLayout(MyGUI::Widget *_parent = nullptr); + virtual ~ActorSpawnerReportWindowLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(ActorSpawnerReportWindowLayout, m_rig_spawner_report_window, "rig_spawner_report_window"); + MyGUI::Window *m_rig_spawner_report_window; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(ActorSpawnerReportWindowLayout, m_rig_spawner_report_window, "rig_spawner_report_window"); - MyGUI::Window* m_rig_spawner_report_window; + ATTRIBUTE_FIELD_WIDGET_NAME(ActorSpawnerReportWindowLayout, m_report_summary_textbox, "report_summary_textbox"); + MyGUI::TextBox *m_report_summary_textbox; - ATTRIBUTE_FIELD_WIDGET_NAME(ActorSpawnerReportWindowLayout, m_report_summary_textbox, "report_summary_textbox"); - MyGUI::TextBox* m_report_summary_textbox; + ATTRIBUTE_FIELD_WIDGET_NAME(ActorSpawnerReportWindowLayout, m_report_text_area, "report_text_area"); + MyGUI::EditBox *m_report_text_area; - ATTRIBUTE_FIELD_WIDGET_NAME(ActorSpawnerReportWindowLayout, m_report_text_area, "report_text_area"); - MyGUI::EditBox* m_report_text_area; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_SimUtils.cpp b/source/main/gui/panels/GUI_SimUtils.cpp index e6312a43e2..35bde9b25b 100644 --- a/source/main/gui/panels/GUI_SimUtils.cpp +++ b/source/main/gui/panels/GUI_SimUtils.cpp @@ -29,38 +29,36 @@ #include "GUI_SimUtils.h" -#include -#include -#include -#include - -#include "RoRPrerequisites.h" - -#include "Utils.h" -#include "RoRVersion.h" -#include "Language.h" -#include "GUIManager.h" +#include "AeroEngine.h" #include "Application.h" -#include "OgreSubsystem.h" #include "Beam.h" - -#include "AeroEngine.h" #include "BeamEngine.h" +#include "GUIManager.h" +#include "Language.h" +#include "OgreSubsystem.h" +#include "RoRPrerequisites.h" +#include "RoRVersion.h" #include "ScrewProp.h" +#include "Utils.h" + +#include +#include +#include +#include using namespace RoR; using namespace GUI; -#define CLASS SimUtils -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) +#define CLASS SimUtils +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) CLASS::CLASS() { - //Usefull + // Usefull MainThemeColor = U("#FF7D02"); - WhiteColor = U("#FFFFFF"); - RedColor = U("#DF2121"); - BlueColor = U("#3399DD"); + WhiteColor = U("#FFFFFF"); + RedColor = U("#DF2121"); + BlueColor = U("#3399DD"); MAIN_WIDGET->setUserString("interactive", "0"); MAIN_WIDGET->setPosition(0, 0); @@ -70,11 +68,11 @@ CLASS::CLASS() m_actor_stats_str = ""; - m_fps_box_visible = false; + m_fps_box_visible = false; m_actor_info_visible = false; m_last_notifi_push_time = 0.0f; - m_notifi_box_alpha = 1.0f; + m_notifi_box_alpha = 1.0f; m_notifications_disabled = false; } @@ -114,10 +112,8 @@ void CLASS::SetActorInfoBoxVisible(bool v) void CLASS::PushNotification(Ogre::String Title, Ogre::String text) { - if (!MAIN_WIDGET->getVisible()) - return; - if (m_notifications_disabled) - return; + if (!MAIN_WIDGET->getVisible()) return; + if (m_notifications_disabled) return; m_not_title->setCaption(Title); m_not_text->setCaption(text); @@ -137,18 +133,14 @@ void CLASS::DisableNotifications(bool disabled) void CLASS::FrameStepSimGui(float dt) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; unsigned long ot = Ogre::Root::getSingleton().getTimer()->getMilliseconds(); if (m_notification->getVisible()) { - unsigned long endTime = m_last_notifi_push_time + 5000; + unsigned long endTime = m_last_notifi_push_time + 5000; unsigned long startTime = endTime - (long)1000.0f; - if (ot < startTime) - { - m_notifi_box_alpha = 1.0f; - } + if (ot < startTime) { m_notifi_box_alpha = 1.0f; } else { m_notifi_box_alpha = 1 - ((ot - startTime) / 1000.0f); @@ -156,19 +148,17 @@ void CLASS::FrameStepSimGui(float dt) m_notification->setAlpha(m_notifi_box_alpha); - if (m_notifi_box_alpha <= 0.1) - m_notification->setVisible(false); + if (m_notifi_box_alpha <= 0.1) m_notification->setVisible(false); } } -void CLASS::UpdateStats(float dt, Actor* actor) +void CLASS::UpdateStats(float dt, Actor *actor) { - if (!MAIN_WIDGET->getVisible()) - return; + if (!MAIN_WIDGET->getVisible()) return; if (m_fps_box_visible) { - const Ogre::RenderTarget::FrameStats& stats = App::GetOgreSubsystem()->GetRenderWindow()->getStatistics(); + const Ogre::RenderTarget::FrameStats &stats = App::GetOgreSubsystem()->GetRenderWindow()->getStatistics(); m_cur_fps->setCaptionWithReplacing(_L("Current FPS: ") + TOUTFSTRING(stats.lastFPS)); m_avg_fps->setCaptionWithReplacing(_L("Average FPS: ") + TOUTFSTRING(stats.avgFPS)); m_worst_fps->setCaptionWithReplacing(_L("Worst FPS: ") + TOUTFSTRING(stats.worstFPS)); @@ -181,91 +171,105 @@ void CLASS::UpdateStats(float dt, Actor* actor) if (m_actor_info_visible && actor != nullptr) { - if (!m_truckinfo_box->getVisible()) - m_truckinfo_box->setVisible(true); + if (!m_truckinfo_box->getVisible()) m_truckinfo_box->setVisible(true); m_truck_name->setMaxTextLength(28); m_truck_name->setCaptionWithReplacing(actor->GetActorDesignName()); - m_actor_stats_str = "\n"; //always reset on each frame + space - - //taken from TruckHUD.cpp (now removed), TODO: needs cleanup - beam_t* beam = actor->ar_beams; - float average_deformation = 0.0f; - float beamstress = 0.0f; - float current_deformation = 0.0f; - float mass = actor->getTotalMass(); - int beambroken = 0; - int beamdeformed = 0; - - for (int i = 0; i < actor->ar_num_beams; i++ , beam++) + m_actor_stats_str = "\n"; // always reset on each frame + space + + // taken from TruckHUD.cpp (now removed), TODO: needs cleanup + beam_t *beam = actor->ar_beams; + float average_deformation = 0.0f; + float beamstress = 0.0f; + float current_deformation = 0.0f; + float mass = actor->getTotalMass(); + int beambroken = 0; + int beamdeformed = 0; + + for (int i = 0; i < actor->ar_num_beams; i++, beam++) { - if (beam->bm_broken != 0) - { - beambroken++; - } + if (beam->bm_broken != 0) { beambroken++; } beamstress += std::abs(beam->stress); current_deformation = fabs(beam->L - beam->refL); - if (fabs(current_deformation) > 0.0001f && beam->bm_type != BEAM_HYDRO) - { - beamdeformed++; - } + if (fabs(current_deformation) > 0.0001f && beam->bm_type != BEAM_HYDRO) { beamdeformed++; } average_deformation += current_deformation; } - float health = ((float)beambroken / (float)actor->ar_num_beams) * 10.0f + ((float)beamdeformed / (float)actor->ar_num_beams); + float health = + ((float)beambroken / (float)actor->ar_num_beams) * 10.0f + ((float)beamdeformed / (float)actor->ar_num_beams); if (health < 1.0f) { - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Vehicle health: ") + WhiteColor + TOUTFSTRING(Round((1.0f - health) * 100.0f, 2)) + U("%") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Vehicle health: ") + WhiteColor + + TOUTFSTRING(Round((1.0f - health) * 100.0f, 2)) + U("%") + "\n"; } else if (health >= 1.0f) { - //When this condition is true, it means that health is at 0% which means 100% of destruction. + // When this condition is true, it means that health is at 0% which means 100% of destruction. m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Vehicle destruction: ") + WhiteColor + U("100%") + "\n"; } - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Beam count: ") + WhiteColor + TOUTFSTRING(actor->ar_num_beams) + "\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Broken beams count: ") + WhiteColor + TOUTFSTRING(beambroken) + U(" (") + TOUTFSTRING(Round((float)beambroken / (float)actor->ar_num_beams, 2) * 100.0f) + U("%)") + "\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Deformed beams count: ") + WhiteColor + TOUTFSTRING(beamdeformed) + U(" (") + TOUTFSTRING(Round((float)beamdeformed / (float)actor->ar_num_beams, 2) * 100.0f) + U("%)") + "\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Average deformation: ") + WhiteColor + TOUTFSTRING(Round((float)average_deformation / (float)actor->ar_num_beams, 4) * 100.0f) + "\n"; - - //Taken from TruckHUD.cpp .. + m_actor_stats_str = + m_actor_stats_str + MainThemeColor + _L("Beam count: ") + WhiteColor + TOUTFSTRING(actor->ar_num_beams) + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Broken beams count: ") + WhiteColor + + TOUTFSTRING(beambroken) + U(" (") + + TOUTFSTRING(Round((float)beambroken / (float)actor->ar_num_beams, 2) * 100.0f) + U("%)") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Deformed beams count: ") + WhiteColor + + TOUTFSTRING(beamdeformed) + U(" (") + + TOUTFSTRING(Round((float)beamdeformed / (float)actor->ar_num_beams, 2) * 100.0f) + U("%)") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Average deformation: ") + WhiteColor + + TOUTFSTRING(Round((float)average_deformation / (float)actor->ar_num_beams, 4) * 100.0f) + "\n"; + + // Taken from TruckHUD.cpp .. wchar_t beamstressstr[256]; swprintf(beamstressstr, 256, L"% 08.0f", 1 - (float)beamstress / (float)actor->ar_num_beams); - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Average stress: ") + WhiteColor + Ogre::UTFString(beamstressstr) + "\n"; + m_actor_stats_str = + m_actor_stats_str + MainThemeColor + _L("Average stress: ") + WhiteColor + Ogre::UTFString(beamstressstr) + "\n"; - m_actor_stats_str = m_actor_stats_str + "\n"; //Some space + m_actor_stats_str = m_actor_stats_str + "\n"; // Some space - int wcount = actor->getWheelNodeCount(); + int wcount = actor->getWheelNodeCount(); wchar_t nodecountstr[256]; swprintf(nodecountstr, 256, L"%d (wheels: %d)", actor->ar_num_nodes, wcount); - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Node count: ") + WhiteColor + Ogre::UTFString(nodecountstr) + "\n"; + m_actor_stats_str = + m_actor_stats_str + MainThemeColor + _L("Node count: ") + WhiteColor + Ogre::UTFString(nodecountstr) + "\n"; wchar_t truckmassstr[256]; swprintf(truckmassstr, 256, L"%8.2f kg (%.2f tons)", mass, mass / 1000.0f); - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Total mass: ") + WhiteColor + Ogre::UTFString(truckmassstr) + "\n"; + m_actor_stats_str = + m_actor_stats_str + MainThemeColor + _L("Total mass: ") + WhiteColor + Ogre::UTFString(truckmassstr) + "\n"; - m_actor_stats_str = m_actor_stats_str + "\n"; //Some space + m_actor_stats_str = m_actor_stats_str + "\n"; // Some space if (actor->ar_driveable == TRUCK && actor->ar_engine) { if (actor->ar_engine->GetEngineRpm() > actor->ar_engine->getMaxRPM()) - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Engine RPM: ") + RedColor + TOUTFSTRING(Round(actor->ar_engine->GetEngineRpm())) + U(" / ") + TOUTFSTRING(Round(actor->ar_engine->getMaxRPM())) + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Engine RPM: ") + RedColor + + TOUTFSTRING(Round(actor->ar_engine->GetEngineRpm())) + U(" / ") + + TOUTFSTRING(Round(actor->ar_engine->getMaxRPM())) + "\n"; else - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Engine RPM: ") + WhiteColor + TOUTFSTRING(Round(actor->ar_engine->GetEngineRpm())) + U(" / ") + TOUTFSTRING(Round(actor->ar_engine->getMaxRPM())) + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Engine RPM: ") + WhiteColor + + TOUTFSTRING(Round(actor->ar_engine->GetEngineRpm())) + U(" / ") + + TOUTFSTRING(Round(actor->ar_engine->getMaxRPM())) + "\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Input shaft RPM: ") + WhiteColor + TOUTFSTRING(Round(std::max(0.0f, actor->ar_engine->GetInputShaftRpm()))) + "\n\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Input shaft RPM: ") + WhiteColor + + TOUTFSTRING(Round(std::max(0.0f, actor->ar_engine->GetInputShaftRpm()))) + "\n\n"; float currentTorque = actor->ar_engine->GetEngineTorque(); - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current torque: ") + WhiteColor + TOUTFSTRING(Round(currentTorque)) + U(" Nm") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current torque: ") + WhiteColor + + TOUTFSTRING(Round(currentTorque)) + U(" Nm") + "\n"; float currentKw = currentTorque * Ogre::Math::TWO_PI * (actor->ar_engine->GetEngineRpm() / 60.0f) / 1000.0f; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current power: ") + WhiteColor + TOUTFSTRING(Round(currentKw / 0.73549875f)) + U(" hp / ") + TOUTFSTRING(Round(currentKw)) + U(" Kw") + "\n\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current power: ") + WhiteColor + + TOUTFSTRING(Round(currentKw / 0.73549875f)) + U(" hp / ") + TOUTFSTRING(Round(currentKw)) + + U(" Kw") + "\n\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current gear: ") + WhiteColor + TOUTFSTRING(Round(actor->ar_engine->GetGear())) + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current gear: ") + WhiteColor + + TOUTFSTRING(Round(actor->ar_engine->GetGear())) + "\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Drive ratio: ") + WhiteColor + TOUTFSTRING(Round(actor->ar_engine->GetDriveRatio())) + ":1\n\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Drive ratio: ") + WhiteColor + + TOUTFSTRING(Round(actor->ar_engine->GetDriveRatio())) + ":1\n\n"; float velocityKMH = actor->ar_wheel_speed * 3.6f; float velocityMPH = actor->ar_wheel_speed * 2.23693629f; @@ -273,42 +277,50 @@ void CLASS::UpdateStats(float dt, Actor* actor) float carSpeedMPH = actor->ar_nodes[0].Velocity.length() * 2.23693629f; // apply a deadzone ==> no flickering +/- - if (fabs(velocityMPH) < 0.5f) - { - velocityKMH = velocityMPH = 0.0f; - } - if (fabs(carSpeedMPH) < 0.5f) - { - carSpeedKPH = carSpeedMPH = 0.0f; - } + if (fabs(velocityMPH) < 0.5f) { velocityKMH = velocityMPH = 0.0f; } + if (fabs(carSpeedMPH) < 0.5f) { carSpeedKPH = carSpeedMPH = 0.0f; } Ogre::UTFString wsmsg = _L("Wheel speed: "); - //Some kind of wheel skidding detection? lol + // Some kind of wheel skidding detection? lol if (velocityKMH > carSpeedKPH * 1.25f) - m_actor_stats_str = m_actor_stats_str + MainThemeColor + wsmsg + RedColor + TOUTFSTRING(Round(velocityKMH)) + U(" km/h (") + TOUTFSTRING(Round(velocityMPH)) + U(" mph)") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + wsmsg + RedColor + TOUTFSTRING(Round(velocityKMH)) + + U(" km/h (") + TOUTFSTRING(Round(velocityMPH)) + U(" mph)") + "\n"; else if (velocityKMH < carSpeedKPH / 1.25f) - m_actor_stats_str = m_actor_stats_str + MainThemeColor + wsmsg + BlueColor + TOUTFSTRING(Round(velocityKMH)) + U(" km/h (") + TOUTFSTRING(Round(velocityMPH)) + U(" mph)") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + wsmsg + BlueColor + TOUTFSTRING(Round(velocityKMH)) + + U(" km/h (") + TOUTFSTRING(Round(velocityMPH)) + U(" mph)") + "\n"; else - m_actor_stats_str = m_actor_stats_str + MainThemeColor + wsmsg + WhiteColor + TOUTFSTRING(Round(velocityKMH)) + U(" km/h (") + TOUTFSTRING(Round(velocityMPH)) + U(" mph)") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + wsmsg + WhiteColor + TOUTFSTRING(Round(velocityKMH)) + + U(" km/h (") + TOUTFSTRING(Round(velocityMPH)) + U(" mph)") + "\n"; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Vehicle speed: ") + WhiteColor + TOUTFSTRING(Round(carSpeedKPH)) + U(" km/h (") + TOUTFSTRING(Round(carSpeedMPH)) + U(" mph)") + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Vehicle speed: ") + WhiteColor + + TOUTFSTRING(Round(carSpeedKPH)) + U(" km/h (") + TOUTFSTRING(Round(carSpeedMPH)) + U(" mph)") + + "\n"; } else { - float speedKN = actor->ar_nodes[0].Velocity.length() * 1.94384449f; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current speed: ") + WhiteColor + TOUTFSTRING(Round(speedKN)) + U(" kn (") + TOUTFSTRING(Round(speedKN * 1.852)) + U(" km/h) (") + TOUTFSTRING(Round(speedKN * 1.151)) + U(" mph)") + "\n"; + float speedKN = actor->ar_nodes[0].Velocity.length() * 1.94384449f; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Current speed: ") + WhiteColor + + TOUTFSTRING(Round(speedKN)) + U(" kn (") + TOUTFSTRING(Round(speedKN * 1.852)) + U(" km/h) (") + + TOUTFSTRING(Round(speedKN * 1.151)) + U(" mph)") + "\n"; Ogre::UTFString engmsg = _L("Engine "); if (actor->ar_driveable == AIRPLANE) { - float altitude = actor->ar_nodes[0].AbsPosition.y / 30.48 * 100; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Altitude: ") + WhiteColor + TOUTFSTRING(Round(altitude)) + U(" feet (") + TOUTFSTRING(Round(altitude * 0.30480)) + U(" meters)") + "\n"; + float altitude = actor->ar_nodes[0].AbsPosition.y / 30.48 * 100; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Altitude: ") + WhiteColor + + TOUTFSTRING(Round(altitude)) + U(" feet (") + TOUTFSTRING(Round(altitude * 0.30480)) + + U(" meters)") + "\n"; for (int i = 0; i < 8; i++) { if (actor->ar_aeroengines[i] && actor->ar_aeroengines[i]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOJET) - m_actor_stats_str = m_actor_stats_str + MainThemeColor + engmsg + TOUTFSTRING(i + 1 /*not to start with 0, players wont like it i guess*/) + " : " + WhiteColor + TOUTFSTRING(Round(actor->ar_aeroengines[i]->getRPM())) + "%" + "\n"; - else if (actor->ar_aeroengines[i] && actor->ar_aeroengines[i]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP) - m_actor_stats_str = m_actor_stats_str + MainThemeColor + engmsg + TOUTFSTRING(i + 1 /*not to start with 0, players wont like it i guess*/) + " : " + WhiteColor + TOUTFSTRING(Round(actor->ar_aeroengines[i]->getRPM())) + " RPM" + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + engmsg + + TOUTFSTRING(i + 1 /*not to start with 0, players wont like it i guess*/) + " : " + + WhiteColor + TOUTFSTRING(Round(actor->ar_aeroengines[i]->getRPM())) + "%" + "\n"; + else if (actor->ar_aeroengines[i] && + actor->ar_aeroengines[i]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP) + m_actor_stats_str = m_actor_stats_str + MainThemeColor + engmsg + + TOUTFSTRING(i + 1 /*not to start with 0, players wont like it i guess*/) + " : " + + WhiteColor + TOUTFSTRING(Round(actor->ar_aeroengines[i]->getRPM())) + " RPM" + "\n"; } } else if (actor->ar_driveable == BOAT) @@ -316,24 +328,28 @@ void CLASS::UpdateStats(float dt, Actor* actor) for (int i = 0; i < 8; i++) { if (actor->ar_screwprops[i]) - m_actor_stats_str = m_actor_stats_str + MainThemeColor + engmsg + TOUTFSTRING(i + 1 /*not to start with 0, players wont like it i guess*/) + " : " + WhiteColor + TOUTFSTRING(Round(actor->ar_screwprops[i]->getThrottle() *100 )) + "%" + "\n"; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + engmsg + + TOUTFSTRING(i + 1 /*not to start with 0, players wont like it i guess*/) + " : " + + WhiteColor + TOUTFSTRING(Round(actor->ar_screwprops[i]->getThrottle() * 100)) + "%" + + "\n"; } } } - m_actor_stats_str = m_actor_stats_str + "\n"; //Some space + m_actor_stats_str = m_actor_stats_str + "\n"; // Some space - float speedKPH = actor->ar_top_speed * 3.6f; - float speedMPH = actor->ar_top_speed * 2.23693629f; - m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Top speed: ") + WhiteColor + TOUTFSTRING(Round(speedKPH)) + U(" km/h (") + TOUTFSTRING(Round(speedMPH)) + U(" mph)") + "\n"; + float speedKPH = actor->ar_top_speed * 3.6f; + float speedMPH = actor->ar_top_speed * 2.23693629f; + m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("Top speed: ") + WhiteColor + TOUTFSTRING(Round(speedKPH)) + + U(" km/h (") + TOUTFSTRING(Round(speedMPH)) + U(" mph)") + "\n"; - //Is this really usefull? people really use it? - m_actor_stats_str = m_actor_stats_str + "\n"; //Some space + // Is this really usefull? people really use it? + m_actor_stats_str = m_actor_stats_str + "\n"; // Some space - wchar_t geesstr[256]; - Ogre::Vector3 gcur = actor->GetGForcesCur(); - Ogre::Vector3 gmax = actor->GetGForcesMax(); - Ogre::UTFString tmp = _L("Vertical: % 6.2fg (%1.2fg)\nSagittal: % 6.2fg (%1.2fg)\nLateral: % 6.2fg (%1.2fg)"); + wchar_t geesstr[256]; + Ogre::Vector3 gcur = actor->GetGForcesCur(); + Ogre::Vector3 gmax = actor->GetGForcesMax(); + Ogre::UTFString tmp = _L("Vertical: % 6.2fg (%1.2fg)\nSagittal: % 6.2fg (%1.2fg)\nLateral: % 6.2fg (%1.2fg)"); swprintf(geesstr, 256, tmp.asWStr_c_str(), gcur.x, gmax.x, gcur.y, gmax.y, gcur.z, gmax.z); m_actor_stats_str = m_actor_stats_str + MainThemeColor + _L("G-Forces:\n") + WhiteColor + Ogre::UTFString(geesstr) + "\n"; diff --git a/source/main/gui/panels/GUI_SimUtils.h b/source/main/gui/panels/GUI_SimUtils.h index ccbba04eb3..215ed1e9eb 100644 --- a/source/main/gui/panels/GUI_SimUtils.h +++ b/source/main/gui/panels/GUI_SimUtils.h @@ -28,54 +28,58 @@ #include "ForwardDeclarations.h" #include "GUI_SimUtilsLayout.h" -namespace RoR { - -struct NotificationMessage -{ - unsigned long time; //!< post time in milliseconds since RoR start - unsigned long ttl; //!< in milliseconds - Ogre::UTFString txt; //!< not POD, beware... - Ogre::UTFString title; //!< not POD, beware... -}; - -namespace GUI { - -class SimUtils: public SimUtilsLayout +namespace RoR { -public: - SimUtils(); - ~SimUtils(); - - void SetBaseVisible(bool v); - bool IsBaseVisible(); - - void SetFPSBoxVisible(bool v); - bool IsFPSBoxVisible() { return m_fps_box_visible; } - - void SetActorInfoBoxVisible(bool v); - - void UpdateStats(float dt, Actor* actor); //different from Framestep! - void FrameStepSimGui(float dt); - - void PushNotification(Ogre::String Title, Ogre::String text); - void HideNotificationBox(); - void DisableNotifications(bool disabled); - -private: - - //Colors - Ogre::UTFString MainThemeColor; // colour key shortcut - Ogre::UTFString WhiteColor; // colour key shortcut - Ogre::UTFString RedColor; // colour key shortcut - Ogre::UTFString BlueColor; // colour key shortcut - - std::string m_actor_stats_str; - float m_notifi_box_alpha; //!< Animated - long m_last_notifi_push_time; - bool m_notifications_disabled; - bool m_fps_box_visible; - bool m_actor_info_visible; -}; -} // namespace GUI + struct NotificationMessage + { + unsigned long time; //!< post time in milliseconds since RoR start + unsigned long ttl; //!< in milliseconds + Ogre::UTFString txt; //!< not POD, beware... + Ogre::UTFString title; //!< not POD, beware... + }; + + namespace GUI + { + + class SimUtils : public SimUtilsLayout + { + public: + SimUtils(); + ~SimUtils(); + + void SetBaseVisible(bool v); + bool IsBaseVisible(); + + void SetFPSBoxVisible(bool v); + bool IsFPSBoxVisible() + { + return m_fps_box_visible; + } + + void SetActorInfoBoxVisible(bool v); + + void UpdateStats(float dt, Actor *actor); // different from Framestep! + void FrameStepSimGui(float dt); + + void PushNotification(Ogre::String Title, Ogre::String text); + void HideNotificationBox(); + void DisableNotifications(bool disabled); + + private: + // Colors + Ogre::UTFString MainThemeColor; // colour key shortcut + Ogre::UTFString WhiteColor; // colour key shortcut + Ogre::UTFString RedColor; // colour key shortcut + Ogre::UTFString BlueColor; // colour key shortcut + + std::string m_actor_stats_str; + float m_notifi_box_alpha; //!< Animated + long m_last_notifi_push_time; + bool m_notifications_disabled; + bool m_fps_box_visible; + bool m_actor_info_visible; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_SimUtilsLayout.cpp b/source/main/gui/panels/GUI_SimUtilsLayout.cpp index dfe28d8d9c..99c1ba6ff1 100644 --- a/source/main/gui/panels/GUI_SimUtilsLayout.cpp +++ b/source/main/gui/panels/GUI_SimUtilsLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -SimUtilsLayout::SimUtilsLayout(MyGUI::Widget* _parent) +SimUtilsLayout::SimUtilsLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_SimUtilsLayout.h b/source/main/gui/panels/GUI_SimUtilsLayout.h index 48cb4866fd..55b1575237 100644 --- a/source/main/gui/panels/GUI_SimUtilsLayout.h +++ b/source/main/gui/panels/GUI_SimUtilsLayout.h @@ -8,66 +8,65 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(SimUtilsLayout, "Utils.layout"); -class SimUtilsLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(SimUtilsLayout, "Utils.layout"); + class SimUtilsLayout : public wraps::BaseLayout + { - SimUtilsLayout(MyGUI::Widget* _parent = nullptr); - virtual ~SimUtilsLayout(); + public: + SimUtilsLayout(MyGUI::Widget *_parent = nullptr); + virtual ~SimUtilsLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_fpscounter_box, "fpscounter_box"); + MyGUI::ImageBox *m_fpscounter_box; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_fpscounter_box, "fpscounter_box"); - MyGUI::ImageBox* m_fpscounter_box; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_cur_fps, "cur_fps"); + MyGUI::EditBox *m_cur_fps; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_cur_fps, "cur_fps"); - MyGUI::EditBox* m_cur_fps; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_avg_fps, "avg_fps"); + MyGUI::EditBox *m_avg_fps; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_avg_fps, "avg_fps"); - MyGUI::EditBox* m_avg_fps; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_worst_fps, "worst_fps"); + MyGUI::EditBox *m_worst_fps; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_worst_fps, "worst_fps"); - MyGUI::EditBox* m_worst_fps; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_best_fps, "best_fps"); + MyGUI::EditBox *m_best_fps; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_best_fps, "best_fps"); - MyGUI::EditBox* m_best_fps; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_triangle_count, "triangle_count"); + MyGUI::EditBox *m_triangle_count; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_triangle_count, "triangle_count"); - MyGUI::EditBox* m_triangle_count; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_batch_count, "batch_count"); + MyGUI::EditBox *m_batch_count; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_batch_count, "batch_count"); - MyGUI::EditBox* m_batch_count; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_truckinfo_box, "truckinfo_box"); + MyGUI::ImageBox *m_truckinfo_box; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_truckinfo_box, "truckinfo_box"); - MyGUI::ImageBox* m_truckinfo_box; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_truck_name, "truck_name"); + MyGUI::EditBox *m_truck_name; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_truck_name, "truck_name"); - MyGUI::EditBox* m_truck_name; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_truck_stats, "truck_stats"); + MyGUI::EditBox *m_truck_stats; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_truck_stats, "truck_stats"); - MyGUI::EditBox* m_truck_stats; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_notification, "notification"); + MyGUI::ImageBox *m_notification; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_notification, "notification"); - MyGUI::ImageBox* m_notification; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_not_title, "not_title"); + MyGUI::EditBox *m_not_title; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_not_title, "not_title"); - MyGUI::EditBox* m_not_title; + ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_not_text, "not_text"); + MyGUI::EditBox *m_not_text; - ATTRIBUTE_FIELD_WIDGET_NAME(SimUtilsLayout, m_not_text, "not_text"); - MyGUI::EditBox* m_not_text; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/gui/panels/GUI_TextureToolWindow.cpp b/source/main/gui/panels/GUI_TextureToolWindow.cpp index d056e6a601..cecc116e42 100644 --- a/source/main/gui/panels/GUI_TextureToolWindow.cpp +++ b/source/main/gui/panels/GUI_TextureToolWindow.cpp @@ -18,243 +18,221 @@ along with Rigs of Rods. If not, see . */ - #include "GUI_TextureToolWindow.h" -#include - #include "Application.h" #include "GUI_GameConsole.h" #include "Language.h" #include "PlatformUtils.h" #include "Utils.h" -namespace RoR { -namespace GUI { - -using namespace Ogre; - -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) - -TextureToolWindow::TextureToolWindow() -{ - initialiseByAttributes(this); - - ((MyGUI::Window*)mMainWidget)->setCaption(_L("Texture Tool")); - ((MyGUI::Window*)mMainWidget)->eventWindowButtonPressed += MyGUI::newDelegate(this, &TextureToolWindow::notifyWindowPressed); - - mBtnSavePNG->setCaption(_L("Save as PNG")); - mBtnSavePNG->eventMouseButtonClick += MyGUI::newDelegate(this, &TextureToolWindow::eventClickSavePNGButton); - - mBtnSaveRAW->setCaption(_L("Save Raw")); - mBtnSaveRAW->eventMouseButtonClick += MyGUI::newDelegate(this, &TextureToolWindow::eventClickSaveRAWButton); - - mCBo->eventComboAccept += MyGUI::newDelegate(this, &TextureToolWindow::eventSelectTexture); - mCBo->eventComboChangePosition += MyGUI::newDelegate(this, &TextureToolWindow::eventSelectTexture2); - - mChkDynamic->eventMouseButtonClick += MyGUI::newDelegate(this, &TextureToolWindow::eventClickDynamicButton); - mChkDynamic->setStateSelected(true); - - MAIN_WIDGET->setVisible(false); -} +#include -void TextureToolWindow::SetVisible(bool v) +namespace RoR { - MAIN_WIDGET->setVisible(v); - if (v) + namespace GUI { - fillCombo(); - } -} -bool TextureToolWindow::IsVisible() -{ - return MAIN_WIDGET->getVisible(); -} + using namespace Ogre; -void TextureToolWindow::fillCombo() -{ - bool dynamicOnly = mChkDynamic->getStateSelected(); - mCBo->removeAllItems(); +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) - ResourceManager::ResourceMapIterator it = TextureManager::getSingleton().getResourceIterator(); + TextureToolWindow::TextureToolWindow() + { + initialiseByAttributes(this); - std::vector> texture_names; - while (it.hasMoreElements()) - { - TexturePtr txt(it.getNext().staticCast()); + ((MyGUI::Window *)mMainWidget)->setCaption(_L("Texture Tool")); + ((MyGUI::Window *)mMainWidget)->eventWindowButtonPressed += + MyGUI::newDelegate(this, &TextureToolWindow::notifyWindowPressed); - if (dynamicOnly && ((txt->getUsage() & TU_STATIC) != 0)) - continue; + mBtnSavePNG->setCaption(_L("Save as PNG")); + mBtnSavePNG->eventMouseButtonClick += MyGUI::newDelegate(this, &TextureToolWindow::eventClickSavePNGButton); - String name = txt->getName(); - StringUtil::toLowerCase(name); - texture_names.push_back({name, txt->getName()}); - } + mBtnSaveRAW->setCaption(_L("Save Raw")); + mBtnSaveRAW->eventMouseButtonClick += MyGUI::newDelegate(this, &TextureToolWindow::eventClickSaveRAWButton); - std::sort(texture_names.begin(), texture_names.end()); + mCBo->eventComboAccept += MyGUI::newDelegate(this, &TextureToolWindow::eventSelectTexture); + mCBo->eventComboChangePosition += MyGUI::newDelegate(this, &TextureToolWindow::eventSelectTexture2); - for (auto name : texture_names) - { - mCBo->addItem(name.second); - } + mChkDynamic->eventMouseButtonClick += MyGUI::newDelegate(this, &TextureToolWindow::eventClickDynamicButton); + mChkDynamic->setStateSelected(true); - if (mCBo->getItemCount() > 0) - { - int index = 0; - const auto it = std::find_if(texture_names.begin(), texture_names.end(), - [](const std::pair& t) { return t.second.substr(0, 9) == "MapRttTex"; }); - if (it != texture_names.end()) - { - index = std::distance(texture_names.begin(), it); + MAIN_WIDGET->setVisible(false); } - mCBo->setIndexSelected(index); - mCBo->beginToItemSelected(); - updateControls(mCBo->getItemNameAt(index)); - } -} -void TextureToolWindow::saveTexture(String texName, bool usePNG) -{ - try - { - TexturePtr tex = TextureManager::getSingleton().getByName(texName); - if (tex.isNull()) - return; - - Image img; - tex->convertToImage(img); - - // Save to disk! - String outname = PathCombine(App::sys_user_dir.GetActive(), StringUtil::replaceAll(texName, "/", "_")); - if (usePNG) - outname += ".png"; - - img.save(outname); + void TextureToolWindow::SetVisible(bool v) + { + MAIN_WIDGET->setVisible(v); + if (v) { fillCombo(); } + } - UTFString msg = _L("saved texture as ") + outname; - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_MSGTYPE_INFO, msg, "information.png"); - } - catch (Exception& e) - { - UTFString str = "Exception while saving image: " + e.getFullDescription(); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_MSGTYPE_INFO, str, "error.png"); - } -} + bool TextureToolWindow::IsVisible() + { + return MAIN_WIDGET->getVisible(); + } -void TextureToolWindow::updateControls(String texName) -{ - try - { - bool exists = TextureManager::getSingleton().resourceExists(texName); - if (!exists) + void TextureToolWindow::fillCombo() { - mTxt->setCaption(convertToMyGUIString("Texture not found:\n" + texName)); - mBtnSavePNG->setEnabled(false); - return; + bool dynamicOnly = mChkDynamic->getStateSelected(); + mCBo->removeAllItems(); + + ResourceManager::ResourceMapIterator it = TextureManager::getSingleton().getResourceIterator(); + + std::vector> texture_names; + while (it.hasMoreElements()) + { + TexturePtr txt(it.getNext().staticCast()); + + if (dynamicOnly && ((txt->getUsage() & TU_STATIC) != 0)) continue; + + String name = txt->getName(); + StringUtil::toLowerCase(name); + texture_names.push_back({name, txt->getName()}); + } + + std::sort(texture_names.begin(), texture_names.end()); + + for (auto name : texture_names) + { + mCBo->addItem(name.second); + } + + if (mCBo->getItemCount() > 0) + { + int index = 0; + const auto it = + std::find_if(texture_names.begin(), texture_names.end(), [](const std::pair &t) { + return t.second.substr(0, 9) == "MapRttTex"; + }); + if (it != texture_names.end()) { index = std::distance(texture_names.begin(), it); } + mCBo->setIndexSelected(index); + mCBo->beginToItemSelected(); + updateControls(mCBo->getItemNameAt(index)); + } } - TexturePtr tex = TextureManager::getSingleton().getByName(texName); - if (tex.isNull()) + void TextureToolWindow::saveTexture(String texName, bool usePNG) { - mTxt->setCaption(convertToMyGUIString("Error loading texture:\n" + texName)); - mBtnSavePNG->setEnabled(false); - return; + try + { + TexturePtr tex = TextureManager::getSingleton().getByName(texName); + if (tex.isNull()) return; + + Image img; + tex->convertToImage(img); + + // Save to disk! + String outname = PathCombine(App::sys_user_dir.GetActive(), StringUtil::replaceAll(texName, "/", "_")); + if (usePNG) outname += ".png"; + + img.save(outname); + + UTFString msg = _L("saved texture as ") + outname; + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_MSGTYPE_INFO, msg, + "information.png"); + } + catch (Exception &e) + { + UTFString str = "Exception while saving image: " + e.getFullDescription(); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_MSGTYPE_INFO, str, + "error.png"); + } } - String str = "#aa0000" + texName + "#000000\n"; - str += "#00aa00res: #000000" + TOSTRING(tex->getWidth()) + " x " + TOSTRING(tex->getHeight()) + " pixels\n"; - str += "#00aa00size: #000000" + formatBytes(tex->getSize()) + "\n"; - str += "#00aa00format: #000000" + PixelUtil::getFormatName(tex->getFormat()) + "\n"; - if (tex->getNumFaces() > 1) - str += "#00aa00faces: #000000" + TOSTRING(tex->getNumFaces()) + "\n"; - if (tex->getFSAA() > 0) - str += "#00aa00FSAA: #000000" + TOSTRING(tex->getFSAA()) + "\n"; - if (tex->getNumMipmaps() > 0) - str += "#00aa00mipmaps: #000000" + TOSTRING(tex->getNumMipmaps()) + "\n"; - - String typeStr = ""; - switch (tex->getTextureType()) + void TextureToolWindow::updateControls(String texName) { - case TEX_TYPE_1D: typeStr = "1D"; - break; - case TEX_TYPE_2D: typeStr = "2D"; - break; - case TEX_TYPE_3D: typeStr = "3D"; - break; - case TEX_TYPE_CUBE_MAP: typeStr = "Cube Map"; - break; + try + { + bool exists = TextureManager::getSingleton().resourceExists(texName); + if (!exists) + { + mTxt->setCaption(convertToMyGUIString("Texture not found:\n" + texName)); + mBtnSavePNG->setEnabled(false); + return; + } + + TexturePtr tex = TextureManager::getSingleton().getByName(texName); + if (tex.isNull()) + { + mTxt->setCaption(convertToMyGUIString("Error loading texture:\n" + texName)); + mBtnSavePNG->setEnabled(false); + return; + } + + String str = "#aa0000" + texName + "#000000\n"; + str += "#00aa00res: #000000" + TOSTRING(tex->getWidth()) + " x " + TOSTRING(tex->getHeight()) + " pixels\n"; + str += "#00aa00size: #000000" + formatBytes(tex->getSize()) + "\n"; + str += "#00aa00format: #000000" + PixelUtil::getFormatName(tex->getFormat()) + "\n"; + if (tex->getNumFaces() > 1) str += "#00aa00faces: #000000" + TOSTRING(tex->getNumFaces()) + "\n"; + if (tex->getFSAA() > 0) str += "#00aa00FSAA: #000000" + TOSTRING(tex->getFSAA()) + "\n"; + if (tex->getNumMipmaps() > 0) str += "#00aa00mipmaps: #000000" + TOSTRING(tex->getNumMipmaps()) + "\n"; + + String typeStr = ""; + switch (tex->getTextureType()) + { + case TEX_TYPE_1D: typeStr = "1D"; break; + case TEX_TYPE_2D: typeStr = "2D"; break; + case TEX_TYPE_3D: typeStr = "3D"; break; + case TEX_TYPE_CUBE_MAP: typeStr = "Cube Map"; break; + } + str += "#00aa00type: #000000" + typeStr + "\n"; + + String usageStr = ""; + if (tex->getUsage() & TU_STATIC) usageStr += "static,\n"; + if (tex->getUsage() & TU_DYNAMIC) usageStr += "dynamic,\n"; + if (tex->getUsage() & TU_WRITE_ONLY) usageStr += "write only,\n"; + if (tex->getUsage() & TU_STATIC_WRITE_ONLY) usageStr += "static write only,\n"; + if (tex->getUsage() & TU_DYNAMIC_WRITE_ONLY) usageStr += "dynamic write only,\n"; + if (tex->getUsage() & TU_DYNAMIC_WRITE_ONLY_DISCARDABLE) usageStr += "dynamic write only discardable,\n"; + if (tex->getUsage() & TU_AUTOMIPMAP) usageStr += "automipmap,\n"; + if (tex->getUsage() & TU_RENDERTARGET) usageStr += "rendertarget,\n"; + if (tex->getUsage() & TU_DEFAULT) usageStr += "default\n"; + + str += "#00aa00usage: #000000" + usageStr + "\n"; + if (tex->getDepth() > 1) str += "#00aa00depth: #000000" + TOSTRING(tex->getDepth()) + "\n"; + + mTxt->setCaption(convertToMyGUIString(str)); + mImage->setImageTexture(texName); + mBtnSavePNG->setEnabled(true); + } + catch (Exception &e) + { + UTFString str = "Exception while opening texture:" + e.getFullDescription(); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_MSGTYPE_INFO, str, + "error.png"); + } } - str += "#00aa00type: #000000" + typeStr + "\n"; - - String usageStr = ""; - if (tex->getUsage() & TU_STATIC) - usageStr += "static,\n"; - if (tex->getUsage() & TU_DYNAMIC) - usageStr += "dynamic,\n"; - if (tex->getUsage() & TU_WRITE_ONLY) - usageStr += "write only,\n"; - if (tex->getUsage() & TU_STATIC_WRITE_ONLY) - usageStr += "static write only,\n"; - if (tex->getUsage() & TU_DYNAMIC_WRITE_ONLY) - usageStr += "dynamic write only,\n"; - if (tex->getUsage() & TU_DYNAMIC_WRITE_ONLY_DISCARDABLE) - usageStr += "dynamic write only discardable,\n"; - if (tex->getUsage() & TU_AUTOMIPMAP) - usageStr += "automipmap,\n"; - if (tex->getUsage() & TU_RENDERTARGET) - usageStr += "rendertarget,\n"; - if (tex->getUsage() & TU_DEFAULT) - usageStr += "default\n"; - - str += "#00aa00usage: #000000" + usageStr + "\n"; - if (tex->getDepth() > 1) - str += "#00aa00depth: #000000" + TOSTRING(tex->getDepth()) + "\n"; - - mTxt->setCaption(convertToMyGUIString(str)); - mImage->setImageTexture(texName); - mBtnSavePNG->setEnabled(true); - } - catch (Exception& e) - { - UTFString str = "Exception while opening texture:" + e.getFullDescription(); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_MSGTYPE_INFO, str, "error.png"); - } -} -void TextureToolWindow::eventSelectTexture2(MyGUI::ComboBoxPtr _sender, size_t _index) -{ - updateControls(mCBo->getItemNameAt(_index)); -} + void TextureToolWindow::eventSelectTexture2(MyGUI::ComboBoxPtr _sender, size_t _index) + { + updateControls(mCBo->getItemNameAt(_index)); + } -void TextureToolWindow::eventClickDynamicButton(MyGUI::WidgetPtr _sender) -{ - mChkDynamic->setStateSelected(!mChkDynamic->getStateSelected()); - fillCombo(); -} + void TextureToolWindow::eventClickDynamicButton(MyGUI::WidgetPtr _sender) + { + mChkDynamic->setStateSelected(!mChkDynamic->getStateSelected()); + fillCombo(); + } -void TextureToolWindow::notifyWindowPressed(MyGUI::Window* _widget, const std::string& _name) -{ - if (_name == "close") - { - SetVisible(false); - } -} + void TextureToolWindow::notifyWindowPressed(MyGUI::Window *_widget, const std::string &_name) + { + if (_name == "close") { SetVisible(false); } + } -void TextureToolWindow::eventClickSavePNGButton(MyGUI::WidgetPtr _sender) -{ - saveTexture(mCBo->getItemNameAt(mCBo->getIndexSelected()), true); -} + void TextureToolWindow::eventClickSavePNGButton(MyGUI::WidgetPtr _sender) + { + saveTexture(mCBo->getItemNameAt(mCBo->getIndexSelected()), true); + } -void TextureToolWindow::eventClickSaveRAWButton(MyGUI::WidgetPtr _sender) -{ - saveTexture(mCBo->getItemNameAt(mCBo->getIndexSelected()), false); -} + void TextureToolWindow::eventClickSaveRAWButton(MyGUI::WidgetPtr _sender) + { + saveTexture(mCBo->getItemNameAt(mCBo->getIndexSelected()), false); + } -void TextureToolWindow::eventSelectTexture(MyGUI::WidgetPtr _sender) -{ - updateControls(mCBo->getItemNameAt(mCBo->getIndexSelected())); -} + void TextureToolWindow::eventSelectTexture(MyGUI::WidgetPtr _sender) + { + updateControls(mCBo->getItemNameAt(mCBo->getIndexSelected())); + } -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_TextureToolWindow.h b/source/main/gui/panels/GUI_TextureToolWindow.h index 783a96dc5b..d7d15da217 100644 --- a/source/main/gui/panels/GUI_TextureToolWindow.h +++ b/source/main/gui/panels/GUI_TextureToolWindow.h @@ -18,57 +18,56 @@ along with Rigs of Rods. If not, see . */ - #pragma once #include "RoRPrerequisites.h" #include "mygui/BaseLayout.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(TextureToolWindow, "TextureTool.layout"); - -class TextureToolWindow : public wraps::BaseLayout, public ZeroedMemoryAllocator +namespace RoR { -public: + namespace GUI + { - TextureToolWindow(); + ATTRIBUTE_CLASS_LAYOUT(TextureToolWindow, "TextureTool.layout"); - bool IsVisible(); - void SetVisible(bool value); + class TextureToolWindow : public wraps::BaseLayout, public ZeroedMemoryAllocator + { + public: + TextureToolWindow(); -private: + bool IsVisible(); + void SetVisible(bool value); - ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mTxt, "txtInfo"); - MyGUI::TextBox* mTxt; + private: + ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mTxt, "txtInfo"); + MyGUI::TextBox *mTxt; - ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mCBo, "cboTextures"); - MyGUI::ComboBox* mCBo; + ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mCBo, "cboTextures"); + MyGUI::ComboBox *mCBo; - ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mBtnSavePNG, "btnSavePNG"); - MyGUI::Button* mBtnSavePNG; + ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mBtnSavePNG, "btnSavePNG"); + MyGUI::Button *mBtnSavePNG; - ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mBtnSaveRAW, "btnSaveRAW"); - MyGUI::Button* mBtnSaveRAW; + ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mBtnSaveRAW, "btnSaveRAW"); + MyGUI::Button *mBtnSaveRAW; - ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mImage, "imgTexture"); - MyGUI::ImageBox* mImage; + ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mImage, "imgTexture"); + MyGUI::ImageBox *mImage; - ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mChkDynamic, "chkDynamic"); - MyGUI::Button* mChkDynamic; + ATTRIBUTE_FIELD_WIDGET_NAME(TextureToolWindow, mChkDynamic, "chkDynamic"); + MyGUI::Button *mChkDynamic; - void notifyWindowPressed(MyGUI::Window* _widget, const std::string& _name); - void eventClickSavePNGButton(MyGUI::WidgetPtr _sender); - void eventClickSaveRAWButton(MyGUI::WidgetPtr _sender); - void eventClickDynamicButton(MyGUI::WidgetPtr _sender); - void eventSelectTexture(MyGUI::WidgetPtr _sender); - void eventSelectTexture2(MyGUI::ComboBoxPtr _sender, size_t _index); + void notifyWindowPressed(MyGUI::Window *_widget, const std::string &_name); + void eventClickSavePNGButton(MyGUI::WidgetPtr _sender); + void eventClickSaveRAWButton(MyGUI::WidgetPtr _sender); + void eventClickDynamicButton(MyGUI::WidgetPtr _sender); + void eventSelectTexture(MyGUI::WidgetPtr _sender); + void eventSelectTexture2(MyGUI::ComboBoxPtr _sender, size_t _index); - void updateControls(Ogre::String texName); - void saveTexture( Ogre::String texName, bool png ); - void fillCombo(); -}; + void updateControls(Ogre::String texName); + void saveTexture(Ogre::String texName, bool png); + void fillCombo(); + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_TopMenubar.cpp b/source/main/gui/panels/GUI_TopMenubar.cpp index e62b913986..1bb7d7db08 100644 --- a/source/main/gui/panels/GUI_TopMenubar.cpp +++ b/source/main/gui/panels/GUI_TopMenubar.cpp @@ -44,35 +44,36 @@ void RoR::GUI::TopMenubar::Update() // ## ImGui's 'menubar' and 'menuitem' features won't quite cut it... // ## Let's do our own menus and menuitems using buttons and coloring tricks. - const char* sim_title = "Simulation"; // TODO: Localize all! - Str<50> actors_title; - auto actors = App::GetSimController()->GetActors(); - int num_playable_actors = std::count_if(actors.begin(), actors.end(), [](Actor* a) {return !a->ar_hide_in_actor_list;}); + const char *sim_title = "Simulation"; // TODO: Localize all! + Str<50> actors_title; + auto actors = App::GetSimController()->GetActors(); + int num_playable_actors = std::count_if(actors.begin(), actors.end(), [](Actor *a) { return !a->ar_hide_in_actor_list; }); actors_title << "Vehicles (" << num_playable_actors << ")"; - const char* savegames_title = "Saves"; - const char* settings_title = "Settings"; - const char* tools_title = "Tools"; - - float panel_target_width = (ImGui::GetStyle().ItemSpacing.x * 10) + // Item spacing - (ImGui::GetStyle().WindowPadding.x) + (ImGui::GetStyle().FramePadding.x) + // Left + Right padding - ImGui::CalcTextSize(sim_title).x + ImGui::CalcTextSize(actors_title.GetBuffer()).x + // Items - ImGui::CalcTextSize(savegames_title).x + ImGui::CalcTextSize(settings_title).x + // Items - ImGui::CalcTextSize(tools_title).x; // Items - - ImVec2 window_target_pos = ImVec2((ImGui::GetIO().DisplaySize.x/2.f) - (panel_target_width / 2.f), ImGui::GetStyle().WindowPadding.y); + const char *savegames_title = "Saves"; + const char *settings_title = "Settings"; + const char *tools_title = "Tools"; + + float panel_target_width = (ImGui::GetStyle().ItemSpacing.x * 10) + // Item spacing + (ImGui::GetStyle().WindowPadding.x) + (ImGui::GetStyle().FramePadding.x) + // Left + Right padding + ImGui::CalcTextSize(sim_title).x + ImGui::CalcTextSize(actors_title.GetBuffer()).x + // Items + ImGui::CalcTextSize(savegames_title).x + ImGui::CalcTextSize(settings_title).x + // Items + ImGui::CalcTextSize(tools_title).x; // Items + + ImVec2 window_target_pos = + ImVec2((ImGui::GetIO().DisplaySize.x / 2.f) - (panel_target_width / 2.f), ImGui::GetStyle().WindowPadding.y); if (!this->ShouldDisplay(window_target_pos)) { - m_open_menu = TopMenu::TOPMENU_NONE; + m_open_menu = TopMenu::TOPMENU_NONE; m_confirm_remove_all = false; return; } ImGui::PushStyleColor(ImGuiCol_WindowBg, PANEL_BG_COLOR); - ImGui::PushStyleColor(ImGuiCol_Button, TRANSPARENT_COLOR); + ImGui::PushStyleColor(ImGuiCol_Button, TRANSPARENT_COLOR); // The panel - int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove - | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize; + int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_AlwaysAutoResize; ImGui::SetNextWindowContentSize(ImVec2(panel_target_width, 0.f)); ImGui::SetNextWindowPos(window_target_pos); if (!ImGui::Begin("Top menubar", nullptr, static_cast(flags))) @@ -85,20 +86,14 @@ void RoR::GUI::TopMenubar::Update() ImVec2 window_pos = ImGui::GetWindowPos(); ImVec2 sim_cursor = ImGui::GetCursorPos(); ImGui::Button(sim_title); - if ((m_open_menu != TopMenu::TOPMENU_SIM) && ImGui::IsItemHovered()) - { - m_open_menu = TopMenu::TOPMENU_SIM; - } + if ((m_open_menu != TopMenu::TOPMENU_SIM) && ImGui::IsItemHovered()) { m_open_menu = TopMenu::TOPMENU_SIM; } ImGui::SameLine(); // The 'vehicles' button ImVec2 actors_cursor = ImGui::GetCursorPos(); ImGui::Button(actors_title); - if ((m_open_menu != TopMenu::TOPMENU_ACTORS) && ImGui::IsItemHovered()) - { - m_open_menu = TopMenu::TOPMENU_ACTORS; - } + if ((m_open_menu != TopMenu::TOPMENU_ACTORS) && ImGui::IsItemHovered()) { m_open_menu = TopMenu::TOPMENU_ACTORS; } ImGui::SameLine(); @@ -107,9 +102,9 @@ void RoR::GUI::TopMenubar::Update() ImGui::Button(savegames_title); if ((m_open_menu != TopMenu::TOPMENU_SAVEGAMES) && ImGui::IsItemHovered()) { - m_open_menu = TopMenu::TOPMENU_SAVEGAMES; + m_open_menu = TopMenu::TOPMENU_SAVEGAMES; m_quicksave_name = App::GetSimController()->GetBeamFactory()->GetQuicksaveFilename(); - m_quickload = FileExists(PathCombine(App::sys_savegames_dir.GetActive(), m_quicksave_name)); + m_quickload = FileExists(PathCombine(App::sys_savegames_dir.GetActive(), m_quicksave_name)); m_savegame_names.clear(); for (int i = 0; i <= 9; i++) { @@ -127,8 +122,7 @@ void RoR::GUI::TopMenubar::Update() { m_open_menu = TopMenu::TOPMENU_SETTINGS; #ifdef USE_CAELUM - if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) - m_daytime = App::GetSimTerrain()->getSkyManager()->GetTime(); + if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) m_daytime = App::GetSimTerrain()->getSkyManager()->GetTime(); #endif // USE_CAELUM } @@ -137,15 +131,12 @@ void RoR::GUI::TopMenubar::Update() // The 'tools' button ImVec2 tools_cursor = ImGui::GetCursorPos(); ImGui::Button(tools_title); - if ((m_open_menu != TopMenu::TOPMENU_TOOLS) && ImGui::IsItemHovered()) - { - m_open_menu = TopMenu::TOPMENU_TOOLS; - } + if ((m_open_menu != TopMenu::TOPMENU_TOOLS) && ImGui::IsItemHovered()) { m_open_menu = TopMenu::TOPMENU_TOOLS; } ImGui::End(); ImVec2 menu_pos; - Actor* current_actor = App::GetSimController()->GetPlayerActor(); + Actor *current_actor = App::GetSimController()->GetPlayerActor(); switch (m_open_menu) { case TopMenu::TOPMENU_SIM: @@ -165,10 +156,7 @@ void RoR::GUI::TopMenubar::Update() if (current_actor != nullptr) { - if (ImGui::Button("Show vehicle description")) - { - App::GetGuiManager()->SetVisible_VehicleDescription(true); - } + if (ImGui::Button("Show vehicle description")) { App::GetGuiManager()->SetVisible_VehicleDescription(true); } if (current_actor->ar_sim_state != Actor::SimState::NETWORKED_OK) { @@ -176,7 +164,7 @@ void RoR::GUI::TopMenubar::Update() { { ActorModifyRequest rq; - rq.amr_type = ActorModifyRequest::Type::RELOAD; + rq.amr_type = ActorModifyRequest::Type::RELOAD; rq.amr_actor = current_actor; App::GetSimController()->QueueActorModify(rq); @@ -184,19 +172,13 @@ void RoR::GUI::TopMenubar::Update() } } - if (ImGui::Button("Remove current vehicle")) - { - App::GetSimController()->QueueActorRemove(current_actor); - } + if (ImGui::Button("Remove current vehicle")) { App::GetSimController()->QueueActorRemove(current_actor); } } } if (!App::GetSimController()->GetLocalActors().empty()) { - if (ImGui::Button("Remove all vehicles")) - { - m_confirm_remove_all = true; - } + if (ImGui::Button("Remove all vehicles")) { m_confirm_remove_all = true; } if (m_confirm_remove_all) { ImGui::PushStyleColor(ImGuiCol_Text, ORANGE_TEXT); @@ -204,47 +186,32 @@ void RoR::GUI::TopMenubar::Update() { for (auto actor : App::GetSimController()->GetLocalActors()) { - if (!actor->ar_hide_in_actor_list && !actor->isPreloadedWithTerrain() && - actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - { - App::GetSimController()->QueueActorRemove(actor); - } + if (!actor->ar_hide_in_actor_list && !actor->isPreloadedWithTerrain() && + actor->ar_sim_state != Actor::SimState::NETWORKED_OK) + { App::GetSimController()->QueueActorRemove(actor); } } m_confirm_remove_all = false; } ImGui::PopStyleColor(); } - if (ImGui::Button("Activate all vehicles")) - { - App::GetSimController()->GetBeamFactory()->WakeUpAllActors(); - } + if (ImGui::Button("Activate all vehicles")) { App::GetSimController()->GetBeamFactory()->WakeUpAllActors(); } bool force_trucks_active = App::GetSimController()->GetBeamFactory()->AreTrucksForcedAwake(); if (ImGui::Checkbox("Activated vehicles never sleep", &force_trucks_active)) - { - App::GetSimController()->GetBeamFactory()->SetTrucksForcedAwake(force_trucks_active); - } + { App::GetSimController()->GetBeamFactory()->SetTrucksForcedAwake(force_trucks_active); } if (ImGui::Button("Send all vehicles to sleep")) - { - App::GetSimController()->GetBeamFactory()->SendAllActorsSleeping(); - } + { App::GetSimController()->GetBeamFactory()->SendAllActorsSleeping(); } } ImGui::Separator(); - if (ImGui::Button("Back to menu")) - { - App::app_state.SetPending(RoR::AppState::MAIN_MENU); - } + if (ImGui::Button("Back to menu")) { App::app_state.SetPending(RoR::AppState::MAIN_MENU); } - if (ImGui::Button("Exit")) - { - App::app_state.SetPending(RoR::AppState::SHUTDOWN); - } + if (ImGui::Button("Exit")) { App::app_state.SetPending(RoR::AppState::SHUTDOWN); } - m_open_menu_hoverbox_min = menu_pos; + m_open_menu_hoverbox_min = menu_pos; m_open_menu_hoverbox_max.x = menu_pos.x + ImGui::GetWindowWidth(); m_open_menu_hoverbox_max.y = menu_pos.y + ImGui::GetWindowHeight(); ImGui::End(); @@ -257,10 +224,7 @@ void RoR::GUI::TopMenubar::Update() ImGui::SetNextWindowPos(menu_pos); if (ImGui::Begin("Actors menu", nullptr, static_cast(flags))) { - if (App::mp_state.GetActive() != MpState::CONNECTED) - { - this->DrawActorListSinglePlayer(); - } + if (App::mp_state.GetActive() != MpState::CONNECTED) { this->DrawActorListSinglePlayer(); } else { #ifdef USE_SOCKETW @@ -268,13 +232,13 @@ void RoR::GUI::TopMenubar::Update() this->DrawMpUserToActorList(net_user_info); std::vector remote_users = RoR::Networking::GetUserInfos(); - for (auto& user: remote_users) + for (auto &user : remote_users) { this->DrawMpUserToActorList(user); } #endif // USE_SOCKETW } - m_open_menu_hoverbox_min = menu_pos; + m_open_menu_hoverbox_min = menu_pos; m_open_menu_hoverbox_max.x = menu_pos.x + ImGui::GetWindowWidth(); m_open_menu_hoverbox_max.y = menu_pos.y + ImGui::GetWindowHeight(); ImGui::End(); @@ -312,10 +276,7 @@ void RoR::GUI::TopMenubar::Update() for (int i = 1; i <= 5; i++) { Ogre::String name = "Empty Slot"; - if (!m_savegame_names[i].empty()) - { - name = m_savegame_names[i]; - } + if (!m_savegame_names[i].empty()) { name = m_savegame_names[i]; } Ogre::String caption = Ogre::StringUtil::format("%d. %s##Save", i, name.c_str()); if (ImGui::Button(caption.c_str())) { @@ -330,7 +291,7 @@ void RoR::GUI::TopMenubar::Update() { if (!m_savegame_names[i].empty()) { - Ogre::String name = m_savegame_names[i]; + Ogre::String name = m_savegame_names[i]; Ogre::String caption = Ogre::StringUtil::format("%d. %s##Load", i, name.c_str()); if (ImGui::Button(caption.c_str())) { @@ -341,7 +302,7 @@ void RoR::GUI::TopMenubar::Update() } } - m_open_menu_hoverbox_min = menu_pos; + m_open_menu_hoverbox_min = menu_pos; m_open_menu_hoverbox_max.x = menu_pos.x + ImGui::GetWindowWidth(); m_open_menu_hoverbox_max.y = menu_pos.y + ImGui::GetWindowHeight() * 2; ImGui::End(); @@ -359,28 +320,19 @@ void RoR::GUI::TopMenubar::Update() DrawGFloatSlider(App::audio_master_volume, "Volume", 0, 1); ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Frames per second:"); - if (App::gfx_envmap_enabled.GetActive()) - { - DrawGIntSlider(App::gfx_envmap_rate, "Reflections", 0, 6); - } + if (App::gfx_envmap_enabled.GetActive()) { DrawGIntSlider(App::gfx_envmap_rate, "Reflections", 0, 6); } DrawGIntSlider(App::gfx_fps_limit, "Graphics", 0, 240); int physics_fps = std::round(1.0f / App::diag_physics_dt.GetActive()); if (ImGui::SliderInt("Physics", &physics_fps, 2000, 10000)) - { - App::diag_physics_dt.SetActive(Ogre::Math::Clamp(1.0f / physics_fps, 0.0001f, 0.0005f)); - } + { App::diag_physics_dt.SetActive(Ogre::Math::Clamp(1.0f / physics_fps, 0.0001f, 0.0005f)); } ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Simulation:"); float slowmotion = std::min(App::GetSimController()->GetBeamFactory()->GetSimulationSpeed(), 1.0f); if (ImGui::SliderFloat("Slow motion", &slowmotion, 0.01f, 1.0f)) - { - App::GetSimController()->GetBeamFactory()->SetSimulationSpeed(slowmotion); - } + { App::GetSimController()->GetBeamFactory()->SetSimulationSpeed(slowmotion); } float timelapse = std::max(App::GetSimController()->GetBeamFactory()->GetSimulationSpeed(), 1.0f); if (ImGui::SliderFloat("Time lapse", &timelapse, 1.0f, 10.0f)) - { - App::GetSimController()->GetBeamFactory()->SetSimulationSpeed(timelapse); - } + { App::GetSimController()->GetBeamFactory()->SetSimulationSpeed(timelapse); } if (App::GetSimController()->GetCameraBehavior() == CameraManager::CAMERA_BEHAVIOR_STATIC) { ImGui::Separator(); @@ -411,9 +363,7 @@ void RoR::GUI::TopMenubar::Update() } } if (App::GetSimController()->GetCameraBehavior() == CameraManager::CAMERA_BEHAVIOR_FIXED) - { - DrawGCheckbox(App::gfx_fixed_cam_tracking, "Tracking"); - } + { DrawGCheckbox(App::gfx_fixed_cam_tracking, "Tracking"); } } #ifdef USE_CAELUM if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) @@ -422,20 +372,18 @@ void RoR::GUI::TopMenubar::Update() ImGui::TextColored(GRAY_HINT_TEXT, "Time of day:"); float time = App::GetSimTerrain()->getSkyManager()->GetTime(); if (ImGui::SliderFloat("", &time, m_daytime - 0.5f, m_daytime + 0.5f, "")) - { - App::GetSimTerrain()->getSkyManager()->SetTime(time); - } - } + { App::GetSimTerrain()->getSkyManager()->SetTime(time); } + } #endif // USE_CAELUM if (App::mp_state.GetActive() == MpState::CONNECTED) { ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Multiplayer:"); DrawGCheckbox(App::mp_pseudo_collisions, "Collisions"); - DrawGCheckbox(App::mp_hide_net_labels, "Hide labels"); + DrawGCheckbox(App::mp_hide_net_labels, "Hide labels"); } ImGui::PopItemWidth(); - m_open_menu_hoverbox_min = menu_pos; + m_open_menu_hoverbox_min = menu_pos; m_open_menu_hoverbox_max.x = menu_pos.x + ImGui::GetWindowWidth(); m_open_menu_hoverbox_max.y = menu_pos.y + ImGui::GetWindowHeight(); ImGui::End(); @@ -462,7 +410,7 @@ void RoR::GUI::TopMenubar::Update() if (ImGui::Button("Show console")) { - App::GetGuiManager()->SetVisible_Console(! App::GetGuiManager()->IsVisible_Console()); + App::GetGuiManager()->SetVisible_Console(!App::GetGuiManager()->IsVisible_Console()); m_open_menu = TopMenu::TOPMENU_NONE; } @@ -485,22 +433,17 @@ void RoR::GUI::TopMenubar::Update() ImGui::TextColored(GRAY_HINT_TEXT, "Pre-spawn diag. options:"); bool diag_mass = App::diag_truck_mass.GetActive(); - if (ImGui::Checkbox("Node mass recalc. logging", &diag_mass)) - { - App::diag_truck_mass.SetActive(diag_mass); - } + if (ImGui::Checkbox("Node mass recalc. logging", &diag_mass)) { App::diag_truck_mass.SetActive(diag_mass); } if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("Extra logging on runtime - mass recalculation (config: \"Debug Truck Mass\"; GVar: \"diag_truck_mass\")"); + ImGui::Text( + "Extra logging on runtime - mass recalculation (config: \"Debug Truck Mass\"; GVar: \"diag_truck_mass\")"); ImGui::EndTooltip(); } bool diag_break = App::diag_log_beam_break.GetActive(); - if (ImGui::Checkbox("Beam break logging", &diag_break)) - { - App::diag_log_beam_break.SetActive(diag_break); - } + if (ImGui::Checkbox("Beam break logging", &diag_break)) { App::diag_log_beam_break.SetActive(diag_break); } if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -509,10 +452,7 @@ void RoR::GUI::TopMenubar::Update() } bool diag_deform = App::diag_log_beam_deform.GetActive(); - if (ImGui::Checkbox("Beam deform. logging", &diag_deform)) - { - App::diag_log_beam_deform.SetActive(diag_deform); - } + if (ImGui::Checkbox("Beam deform. logging", &diag_deform)) { App::diag_log_beam_deform.SetActive(diag_deform); } if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -521,26 +461,22 @@ void RoR::GUI::TopMenubar::Update() } bool diag_trig = App::diag_log_beam_trigger.GetActive(); - if (ImGui::Checkbox("Trigger logging", &diag_trig)) - { - App::diag_log_beam_trigger.SetActive(diag_trig); - } + if (ImGui::Checkbox("Trigger logging", &diag_trig)) { App::diag_log_beam_trigger.SetActive(diag_trig); } if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("Extra logging on runtime - trigger beams activity (config: \"Trigger Debug\"; GVar: \"diag_log_beam_trigger\")"); + ImGui::Text("Extra logging on runtime - trigger beams activity (config: \"Trigger Debug\"; GVar: " + "\"diag_log_beam_trigger\")"); ImGui::EndTooltip(); } bool diag_vcam = App::diag_videocameras.GetActive(); - if (ImGui::Checkbox("VideoCamera direction marker", &diag_vcam)) - { - App::diag_videocameras.SetActive(diag_vcam); - } + if (ImGui::Checkbox("VideoCamera direction marker", &diag_vcam)) { App::diag_videocameras.SetActive(diag_vcam); } if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("Visual marker of VideoCameras direction (config: \"VideoCameraDebug\"; GVar: \"diag_videocameras\")"); + ImGui::Text( + "Visual marker of VideoCameras direction (config: \"VideoCameraDebug\"; GVar: \"diag_videocameras\")"); ImGui::EndTooltip(); } @@ -549,69 +485,71 @@ void RoR::GUI::TopMenubar::Update() ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "Live diagnostic views:"); - ImGui::TextColored(GRAY_HINT_TEXT, "(Toggle with 'K')"); // !!TODO!! - display actual configured hotkey (EV_COMMON_TOGGLE_DEBUG_VIEW) - ImGui::TextColored(GRAY_HINT_TEXT, "(Cycle with 'CTRL+K')"); // !!TODO!! - display actual configured hotkey (EV_COMMON_CYCLE_DEBUG_VIEWS) + ImGui::TextColored( + GRAY_HINT_TEXT, + "(Toggle with 'K')"); // !!TODO!! - display actual configured hotkey (EV_COMMON_TOGGLE_DEBUG_VIEW) + ImGui::TextColored( + GRAY_HINT_TEXT, + "(Cycle with 'CTRL+K')"); // !!TODO!! - display actual configured hotkey (EV_COMMON_CYCLE_DEBUG_VIEWS) int debug_view_type = static_cast(GfxActor::DebugViewType::DEBUGVIEW_NONE); if (current_actor != nullptr) - { - debug_view_type = static_cast(current_actor->GetGfxActor()->GetDebugView()); - } - ImGui::RadioButton("Normal view", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_NONE)); - ImGui::RadioButton("Skeleton view", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_SKELETON)); - ImGui::RadioButton("Node details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_NODES)); - ImGui::RadioButton("Beam details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_BEAMS)); + { debug_view_type = static_cast(current_actor->GetGfxActor()->GetDebugView()); } + ImGui::RadioButton("Normal view", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_NONE)); + ImGui::RadioButton("Skeleton view", &debug_view_type, + static_cast(GfxActor::DebugViewType::DEBUGVIEW_SKELETON)); + ImGui::RadioButton("Node details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_NODES)); + ImGui::RadioButton("Beam details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_BEAMS)); if (current_actor->ar_num_wheels > 0) { - ImGui::RadioButton("Wheel details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_WHEELS)); + ImGui::RadioButton("Wheel details", &debug_view_type, + static_cast(GfxActor::DebugViewType::DEBUGVIEW_WHEELS)); } if (current_actor->ar_num_shocks > 0) { - ImGui::RadioButton("Shock details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_SHOCKS)); + ImGui::RadioButton("Shock details", &debug_view_type, + static_cast(GfxActor::DebugViewType::DEBUGVIEW_SHOCKS)); } if (current_actor->ar_num_rotators > 0) { - ImGui::RadioButton("Rotator details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_ROTATORS)); + ImGui::RadioButton("Rotator details", &debug_view_type, + static_cast(GfxActor::DebugViewType::DEBUGVIEW_ROTATORS)); } if (current_actor->hasSlidenodes()) { - ImGui::RadioButton("Slidenode details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_SLIDENODES)); + ImGui::RadioButton("Slidenode details", &debug_view_type, + static_cast(GfxActor::DebugViewType::DEBUGVIEW_SLIDENODES)); } if (current_actor->ar_num_cabs > 0) { - ImGui::RadioButton("Submesh details", &debug_view_type, static_cast(GfxActor::DebugViewType::DEBUGVIEW_SUBMESH)); + ImGui::RadioButton("Submesh details", &debug_view_type, + static_cast(GfxActor::DebugViewType::DEBUGVIEW_SUBMESH)); } - if ((current_actor != nullptr) && (debug_view_type != static_cast(current_actor->GetGfxActor()->GetDebugView()))) - { - current_actor->GetGfxActor()->SetDebugView(static_cast(debug_view_type)); - } + if ((current_actor != nullptr) && + (debug_view_type != static_cast(current_actor->GetGfxActor()->GetDebugView()))) + { current_actor->GetGfxActor()->SetDebugView(static_cast(debug_view_type)); } - if (debug_view_type >= 1 && debug_view_type <= static_cast(GfxActor::DebugViewType::DEBUGVIEW_BEAMS)) + if (debug_view_type >= 1 && debug_view_type <= static_cast(GfxActor::DebugViewType::DEBUGVIEW_BEAMS)) { ImGui::Separator(); - ImGui::TextColored(GRAY_HINT_TEXT, "Settings:"); - DrawGCheckbox(App::diag_hide_broken_beams, "Hide broken beams"); - DrawGCheckbox(App::diag_hide_beam_stress, "Hide beam stress"); - DrawGCheckbox(App::diag_hide_wheels, "Hide wheels"); - DrawGCheckbox(App::diag_hide_nodes, "Hide nodes"); - if (debug_view_type >= 2) - { - DrawGCheckbox(App::diag_hide_wheel_info, "Hide wheel info"); - } + ImGui::TextColored(GRAY_HINT_TEXT, "Settings:"); + DrawGCheckbox(App::diag_hide_broken_beams, "Hide broken beams"); + DrawGCheckbox(App::diag_hide_beam_stress, "Hide beam stress"); + DrawGCheckbox(App::diag_hide_wheels, "Hide wheels"); + DrawGCheckbox(App::diag_hide_nodes, "Hide nodes"); + if (debug_view_type >= 2) { DrawGCheckbox(App::diag_hide_wheel_info, "Hide wheel info"); } } } - m_open_menu_hoverbox_min = menu_pos; + m_open_menu_hoverbox_min = menu_pos; m_open_menu_hoverbox_max.x = menu_pos.x + ImGui::GetWindowWidth(); m_open_menu_hoverbox_max.y = menu_pos.y + ImGui::GetWindowHeight(); ImGui::End(); } break; - default: - m_open_menu_hoverbox_min = ImVec2(0,0); - m_open_menu_hoverbox_max = ImVec2(0,0); + default: m_open_menu_hoverbox_min = ImVec2(0, 0); m_open_menu_hoverbox_max = ImVec2(0, 0); } ImGui::PopStyleColor(2); @@ -619,19 +557,16 @@ void RoR::GUI::TopMenubar::Update() bool RoR::GUI::TopMenubar::ShouldDisplay(ImVec2 window_pos) { - ImVec2 box_min(0,0); + ImVec2 box_min(0, 0); ImVec2 box_max(ImGui::GetIO().DisplaySize.x, ImGui::GetStyle().WindowPadding.y + PANEL_HOVERBOX_HEIGHT); ImVec2 mouse_pos = ImGui::GetIO().MousePos; - bool window_hovered ((mouse_pos.x >= box_min.x) && (mouse_pos.x <= box_max.x) && - (mouse_pos.y >= box_min.y) && (mouse_pos.y <= box_max.y)); + bool window_hovered((mouse_pos.x >= box_min.x) && (mouse_pos.x <= box_max.x) && (mouse_pos.y >= box_min.y) && + (mouse_pos.y <= box_max.y)); - if (m_open_menu == TopMenu::TOPMENU_NONE) - { - return window_hovered; - } + if (m_open_menu == TopMenu::TOPMENU_NONE) { return window_hovered; } - bool menu_hovered ((mouse_pos.x >= m_open_menu_hoverbox_min.x) && (mouse_pos.x <= m_open_menu_hoverbox_max.x) && - (mouse_pos.y >= m_open_menu_hoverbox_min.y) && (mouse_pos.y <= m_open_menu_hoverbox_max.y)); + bool menu_hovered((mouse_pos.x >= m_open_menu_hoverbox_min.x) && (mouse_pos.x <= m_open_menu_hoverbox_max.x) && + (mouse_pos.y >= m_open_menu_hoverbox_min.y) && (mouse_pos.y <= m_open_menu_hoverbox_max.y)); return (menu_hovered || window_hovered); } @@ -639,25 +574,34 @@ void RoR::GUI::TopMenubar::DrawMpUserToActorList(RoRnet::UserInfo &user) { // Count actors owned by the player unsigned int num_actors_player = 0; - for (Actor* actor : App::GetSimController()->GetActors()) + for (Actor *actor : App::GetSimController()->GetActors()) { - if (actor->ar_net_source_id == user.uniqueid) - { - ++num_actors_player; - } + if (actor->ar_net_source_id == user.uniqueid) { ++num_actors_player; } } // Prepare user info text - const char* user_type_str = ""; - if (user.authstatus & RoRnet::AUTH_BOT) { user_type_str = "Bot, "; } // Old coloring: #0000c9 - else if (user.authstatus & RoRnet::AUTH_BANNED) { user_type_str = "Banned, "; } // Old coloring: none - else if (user.authstatus & RoRnet::AUTH_RANKED) { user_type_str = "Ranked, "; } // Old coloring: #00c900 - else if (user.authstatus & RoRnet::AUTH_MOD) { user_type_str = "Moderator, "; } // Old coloring: #c90000 - else if (user.authstatus & RoRnet::AUTH_ADMIN) { user_type_str = "Admin, "; } // Old coloring: #c97100 + const char *user_type_str = ""; + if (user.authstatus & RoRnet::AUTH_BOT) { user_type_str = "Bot, "; } // Old coloring: #0000c9 + else if (user.authstatus & RoRnet::AUTH_BANNED) + { + user_type_str = "Banned, "; + } // Old coloring: none + else if (user.authstatus & RoRnet::AUTH_RANKED) + { + user_type_str = "Ranked, "; + } // Old coloring: #00c900 + else if (user.authstatus & RoRnet::AUTH_MOD) + { + user_type_str = "Moderator, "; + } // Old coloring: #c90000 + else if (user.authstatus & RoRnet::AUTH_ADMIN) + { + user_type_str = "Admin, "; + } // Old coloring: #c97100 char usertext_buf[400]; - snprintf(usertext_buf, 400, "%s: %u (%sVer: %s, Lang: %s)", - user.username, num_actors_player, user_type_str, user.clientversion, user.language); + snprintf(usertext_buf, 400, "%s: %u (%sVer: %s, Lang: %s)", user.username, num_actors_player, user_type_str, + user.clientversion, user.language); // Display user in list Ogre::ColourValue player_color; @@ -676,24 +620,20 @@ void RoR::GUI::TopMenubar::DrawMpUserToActorList(RoRnet::UserInfo &user) if ((!actor->ar_hide_in_actor_list) && (actor->ar_net_source_id == user.uniqueid)) { char actortext_buf[400]; - snprintf(actortext_buf, 400, " + %s (%s) ##[%d:%d]", actor->ar_design_name.c_str(), actor->ar_filename.c_str(), i++, user.uniqueid); + snprintf(actortext_buf, 400, " + %s (%s) ##[%d:%d]", actor->ar_design_name.c_str(), actor->ar_filename.c_str(), i++, + user.uniqueid); if (ImGui::Button(actortext_buf)) // Button clicked? - { - App::GetSimController()->SetPendingPlayerActor(actor); - } + { App::GetSimController()->SetPendingPlayerActor(actor); } } } } void RoR::GUI::TopMenubar::DrawActorListSinglePlayer() { - std::vector actor_list; + std::vector actor_list; for (auto actor : App::GetSimController()->GetActors()) { - if (!actor->ar_hide_in_actor_list) - { - actor_list.emplace_back(actor); - } + if (!actor->ar_hide_in_actor_list) { actor_list.emplace_back(actor); } } if (actor_list.empty()) { @@ -704,17 +644,14 @@ void RoR::GUI::TopMenubar::DrawActorListSinglePlayer() } else { - Actor* player_actor = App::GetSimController()->GetPlayerActor(); - int i = 0; + Actor *player_actor = App::GetSimController()->GetPlayerActor(); + int i = 0; for (auto actor : actor_list) { char text_buf[200]; snprintf(text_buf, 200, "[%d] %s", i++, actor->ar_design_name.c_str()); auto linked_actors = actor->GetAllLinkedActors(); - if (actor == player_actor) - { - ImGui::PushStyleColor(ImGuiCol_Text, GREEN_TEXT); - } + if (actor == player_actor) { ImGui::PushStyleColor(ImGuiCol_Text, GREEN_TEXT); } else if (std::find(linked_actors.begin(), linked_actors.end(), player_actor) != linked_actors.end()) { ImGui::PushStyleColor(ImGuiCol_Text, ORANGE_TEXT); @@ -728,9 +665,7 @@ void RoR::GUI::TopMenubar::DrawActorListSinglePlayer() ImGui::PushStyleColor(ImGuiCol_Text, GRAY_HINT_TEXT); } if (ImGui::Button(text_buf)) // Button clicked? - { - App::GetSimController()->SetPendingPlayerActor(actor); - } + { App::GetSimController()->SetPendingPlayerActor(actor); } ImGui::PopStyleColor(); } } diff --git a/source/main/gui/panels/GUI_TopMenubar.h b/source/main/gui/panels/GUI_TopMenubar.h index 396d0e62ea..490478228b 100644 --- a/source/main/gui/panels/GUI_TopMenubar.h +++ b/source/main/gui/panels/GUI_TopMenubar.h @@ -29,44 +29,59 @@ #include -namespace RoR { -namespace GUI { - -class TopMenubar +namespace RoR { -public: - const float MENU_Y_OFFSET = 40.f; - const float PANEL_HOVERBOX_HEIGHT = 50.f; - const ImVec4 PANEL_BG_COLOR = ImVec4(0.1f, 0.1f, 0.1f, 0.8f); - const ImVec4 TRANSPARENT_COLOR = ImVec4(0,0,0,0); - const ImVec4 GRAY_HINT_TEXT = ImVec4(0.62f, 0.62f, 0.61f, 1.f); - const ImVec4 WHITE_TEXT = ImVec4(0.9f, 0.9f, 0.9f, 1.f); - const ImVec4 GREEN_TEXT = ImVec4(0.0f, 0.9f, 0.0f, 1.f); - const ImVec4 ORANGE_TEXT = ImVec4(0.9f, 0.6f, 0.0f, 1.f); - - enum class TopMenu { TOPMENU_NONE, TOPMENU_SIM, TOPMENU_ACTORS, TOPMENU_SAVEGAMES, TOPMENU_SETTINGS, TOPMENU_TOOLS }; - - TopMenubar(): m_open_menu(TopMenu::TOPMENU_NONE), m_daytime(0), m_quickload(false), m_confirm_remove_all(false) {} - - void Update(); - bool ShouldDisplay(ImVec2 window_pos); - - bool IsVisible() { return m_open_menu != TopMenu::TOPMENU_NONE; }; - -private: - void DrawActorListSinglePlayer(); - void DrawMpUserToActorList(RoRnet::UserInfo &user); // Multiplayer - - ImVec2 m_open_menu_hoverbox_min; - ImVec2 m_open_menu_hoverbox_max; - TopMenu m_open_menu; - bool m_confirm_remove_all; - - float m_daytime; - bool m_quickload; - std::string m_quicksave_name; - std::vector m_savegame_names; -}; - -} // namespace GUI + namespace GUI + { + + class TopMenubar + { + public: + const float MENU_Y_OFFSET = 40.f; + const float PANEL_HOVERBOX_HEIGHT = 50.f; + const ImVec4 PANEL_BG_COLOR = ImVec4(0.1f, 0.1f, 0.1f, 0.8f); + const ImVec4 TRANSPARENT_COLOR = ImVec4(0, 0, 0, 0); + const ImVec4 GRAY_HINT_TEXT = ImVec4(0.62f, 0.62f, 0.61f, 1.f); + const ImVec4 WHITE_TEXT = ImVec4(0.9f, 0.9f, 0.9f, 1.f); + const ImVec4 GREEN_TEXT = ImVec4(0.0f, 0.9f, 0.0f, 1.f); + const ImVec4 ORANGE_TEXT = ImVec4(0.9f, 0.6f, 0.0f, 1.f); + + enum class TopMenu + { + TOPMENU_NONE, + TOPMENU_SIM, + TOPMENU_ACTORS, + TOPMENU_SAVEGAMES, + TOPMENU_SETTINGS, + TOPMENU_TOOLS + }; + + TopMenubar() : m_open_menu(TopMenu::TOPMENU_NONE), m_daytime(0), m_quickload(false), m_confirm_remove_all(false) + { + } + + void Update(); + bool ShouldDisplay(ImVec2 window_pos); + + bool IsVisible() + { + return m_open_menu != TopMenu::TOPMENU_NONE; + }; + + private: + void DrawActorListSinglePlayer(); + void DrawMpUserToActorList(RoRnet::UserInfo &user); // Multiplayer + + ImVec2 m_open_menu_hoverbox_min; + ImVec2 m_open_menu_hoverbox_max; + TopMenu m_open_menu; + bool m_confirm_remove_all; + + float m_daytime; + bool m_quickload; + std::string m_quicksave_name; + std::vector m_savegame_names; + }; + + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_VehicleDescription.cpp b/source/main/gui/panels/GUI_VehicleDescription.cpp index 0c3ca3c438..ef1e550f14 100644 --- a/source/main/gui/panels/GUI_VehicleDescription.cpp +++ b/source/main/gui/panels/GUI_VehicleDescription.cpp @@ -30,23 +30,23 @@ #include "BeamFactory.h" #include "GUIManager.h" #include "InputEngine.h" -#include "Utils.h" -#include "RoRnet.h" #include "Language.h" #include "RoRFrameListener.h" +#include "RoRnet.h" +#include "Utils.h" #include using namespace RoR; using namespace GUI; -#define CLASS VehicleDescription -#define MAIN_WIDGET ((MyGUI::Window*)mMainWidget) +#define CLASS VehicleDescription +#define MAIN_WIDGET ((MyGUI::Window *)mMainWidget) CLASS::CLASS() { MyGUI::WindowPtr win = dynamic_cast(mMainWidget); - win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::notifyWindowButtonPressed); //The "X" button thing + win->eventWindowButtonPressed += MyGUI::newDelegate(this, &CLASS::notifyWindowButtonPressed); // The "X" button thing CenterToScreen(); MAIN_WIDGET->setVisible(false); @@ -59,10 +59,9 @@ CLASS::~CLASS() void CLASS::LoadText() { - Actor* currTruck = App::GetSimController()->GetPlayerActor(); + Actor *currTruck = App::GetSimController()->GetPlayerActor(); - if (currTruck == nullptr) - return; + if (currTruck == nullptr) return; m_vehicle_title->setMaxTextLength(33); m_vehicle_title->setCaptionWithReplacing(currTruck->GetActorDesignName()); @@ -94,34 +93,27 @@ void CLASS::LoadText() int filledCommands = 0; for (int i = 1; i < MAX_COMMANDS && filledCommands < COMMANDS_VISIBLE; i += 2) { - if (currTruck->ar_command_key[i].description == "hide") - continue; - if (currTruck->ar_command_key[i].beams.empty() && currTruck->ar_command_key[i].rotators.empty()) - continue; + if (currTruck->ar_command_key[i].description == "hide") continue; + if (currTruck->ar_command_key[i].beams.empty() && currTruck->ar_command_key[i].rotators.empty()) continue; filledCommands++; - char commandID[256] = {}; - Ogre::String keyStr = ""; + char commandID[256] = {}; + Ogre::String keyStr = ""; sprintf(commandID, "COMMANDS_%02d", i); - int eventID = RoR::App::GetInputEngine()->resolveEventName(Ogre::String(commandID)); - Ogre::String keya = RoR::App::GetInputEngine()->getEventCommand(eventID); + int eventID = RoR::App::GetInputEngine()->resolveEventName(Ogre::String(commandID)); + Ogre::String keya = RoR::App::GetInputEngine()->getEventCommand(eventID); sprintf(commandID, "COMMANDS_%02d", i + 1); - eventID = RoR::App::GetInputEngine()->resolveEventName(Ogre::String(commandID)); + eventID = RoR::App::GetInputEngine()->resolveEventName(Ogre::String(commandID)); Ogre::String keyb = RoR::App::GetInputEngine()->getEventCommand(eventID); // cut off expl - if (keya.size() > 6 && keya.substr(0, 5) == "EXPL+") - keya = keya.substr(5); - if (keyb.size() > 6 && keyb.substr(0, 5) == "EXPL+") - keyb = keyb.substr(5); + if (keya.size() > 6 && keya.substr(0, 5) == "EXPL+") keya = keya.substr(5); + if (keyb.size() > 6 && keyb.substr(0, 5) == "EXPL+") keyb = keyb.substr(5); keyStr = keya + "/" + keyb; - if (currTruck->ar_command_key[i].description.empty()) - { - txt = txt + "* " + keyStr + ": " + _L("unknown function"); - } + if (currTruck->ar_command_key[i].description.empty()) { txt = txt + "* " + keyStr + ": " + _L("unknown function"); } else { txt = txt + "* " + keyStr + ": " + currTruck->ar_command_key[i].description; @@ -140,8 +132,7 @@ bool CLASS::IsVisible() void CLASS::SetVisible(bool vis) { - if (vis && !IsVisible()) - LoadText(); + if (vis && !IsVisible()) LoadText(); MAIN_WIDGET->setVisible(vis); } @@ -154,8 +145,7 @@ void CLASS::CenterToScreen() MAIN_WIDGET->setPosition((parentSize.width - windowSize.width) / 2, (parentSize.height - windowSize.height) / 2); } -void CLASS::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name) +void CLASS::notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name) { - if (_name == "close") - SetVisible(false); + if (_name == "close") SetVisible(false); } diff --git a/source/main/gui/panels/GUI_VehicleDescription.h b/source/main/gui/panels/GUI_VehicleDescription.h index e98e6cd8b1..56b0cf4b2f 100644 --- a/source/main/gui/panels/GUI_VehicleDescription.h +++ b/source/main/gui/panels/GUI_VehicleDescription.h @@ -26,25 +26,27 @@ #include "ForwardDeclarations.h" #include "GUI_VehicleDescriptionLayout.h" -namespace RoR { -namespace GUI { - -class VehicleDescription: public VehicleDescriptionLayout +namespace RoR { -public: - VehicleDescription(); - ~VehicleDescription(); + namespace GUI + { + + class VehicleDescription : public VehicleDescriptionLayout + { + public: + VehicleDescription(); + ~VehicleDescription(); - bool IsVisible(); - void SetVisible(bool v); + bool IsVisible(); + void SetVisible(bool v); -private: - void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string& _name); - void CenterToScreen(); - void LoadText(); + private: + void notifyWindowButtonPressed(MyGUI::WidgetPtr _sender, const std::string &_name); + void CenterToScreen(); + void LoadText(); - static const unsigned int COMMANDS_VISIBLE = 50; -}; + static const unsigned int COMMANDS_VISIBLE = 50; + }; -} // namespace GUI + } // namespace GUI } // namespace RoR diff --git a/source/main/gui/panels/GUI_VehicleDescriptionLayout.cpp b/source/main/gui/panels/GUI_VehicleDescriptionLayout.cpp index 1d761d065e..8277cfbc36 100644 --- a/source/main/gui/panels/GUI_VehicleDescriptionLayout.cpp +++ b/source/main/gui/panels/GUI_VehicleDescriptionLayout.cpp @@ -11,7 +11,7 @@ using namespace RoR; using namespace GUI; -VehicleDescriptionLayout::VehicleDescriptionLayout(MyGUI::Widget* _parent) +VehicleDescriptionLayout::VehicleDescriptionLayout(MyGUI::Widget *_parent) { initialiseByAttributes(this, _parent); } diff --git a/source/main/gui/panels/GUI_VehicleDescriptionLayout.h b/source/main/gui/panels/GUI_VehicleDescriptionLayout.h index 185dd8aeea..a8bcba7b43 100644 --- a/source/main/gui/panels/GUI_VehicleDescriptionLayout.h +++ b/source/main/gui/panels/GUI_VehicleDescriptionLayout.h @@ -8,33 +8,32 @@ // Do not modify this code directly. Create a derived class instead. // ---------------------------------------------------------------------------- -#include "ForwardDeclarations.h" #include "BaseLayout.h" +#include "ForwardDeclarations.h" -namespace RoR { -namespace GUI { - -ATTRIBUTE_CLASS_LAYOUT(VehicleDescriptionLayout, "VehicleDesc.layout"); -class VehicleDescriptionLayout : public wraps::BaseLayout +namespace RoR { + namespace GUI + { -public: + ATTRIBUTE_CLASS_LAYOUT(VehicleDescriptionLayout, "VehicleDesc.layout"); + class VehicleDescriptionLayout : public wraps::BaseLayout + { - VehicleDescriptionLayout(MyGUI::Widget* _parent = nullptr); - virtual ~VehicleDescriptionLayout(); + public: + VehicleDescriptionLayout(MyGUI::Widget *_parent = nullptr); + virtual ~VehicleDescriptionLayout(); -protected: + protected: + //%LE Widget_Declaration list start + ATTRIBUTE_FIELD_WIDGET_NAME(VehicleDescriptionLayout, m_vehicle_title, "vehicle_title"); + MyGUI::EditBox *m_vehicle_title; - //%LE Widget_Declaration list start - ATTRIBUTE_FIELD_WIDGET_NAME(VehicleDescriptionLayout, m_vehicle_title, "vehicle_title"); - MyGUI::EditBox* m_vehicle_title; + ATTRIBUTE_FIELD_WIDGET_NAME(VehicleDescriptionLayout, m_vehicle_desc, "vehicle_desc"); + MyGUI::EditBox *m_vehicle_desc; - ATTRIBUTE_FIELD_WIDGET_NAME(VehicleDescriptionLayout, m_vehicle_desc, "vehicle_desc"); - MyGUI::EditBox* m_vehicle_desc; + //%LE Widget_Declaration list end + }; - //%LE Widget_Declaration list end -}; - -} // namespace GUI + } // namespace GUI } // namespace RoR - diff --git a/source/main/icon.rc b/source/main/icon.rc index 878b5fe84e..3adf4c897a 100644 --- a/source/main/icon.rc +++ b/source/main/icon.rc @@ -2,93 +2,66 @@ // Microsoft Visual C++ generated resource script. // -#include -#include "version_def.h" #include "resource.h" +#include "version_def.h" + +#include ///////////////////////////////////////////////////////////////////////////// // English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) +LANGUAGE LANG_ENGLISH, + SUBLANG_ENGLISH_US + #pragma code_page(1252) -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// + ///////////////////////////////////////////////////////////////////////////// + // + // Icon + // -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON "ror.ico" + // Icon with lowest ID value placed first to ensure application icon + // remains consistent on all systems. + IDI_ICON1 ICON "ror.ico" -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + #ifdef APSTUDIO_INVOKED + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE -BEGIN - "\0" -END + 2 TEXTINCLUDE BEGIN "\0" END -3 TEXTINCLUDE -BEGIN + 3 TEXTINCLUDE BEGIN "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - + "\0" END + + #endif // APSTUDIO_INVOKED + + ///////////////////////////////////////////////////////////////////////////// + // + // Version + // + + VS_VERSION_INFO VERSIONINFO FILEVERSION ROR_RESOURCE_VERSION PRODUCTVERSION ROR_RESOURCE_VERSION FILEFLAGSMASK 0x3fL + #ifdef _DEBUG + FILEFLAGS 0x1L + #else + FILEFLAGS 0x0L + #endif + FILEOS 0x40004L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", + "rigsofrods.org" VALUE "FileDescription", "Rigs of Rods Simulator" VALUE "FileVersion", + ROR_RESOURCE_VERSION_STRING VALUE "InternalName", "RoR" VALUE "LegalCopyright", + "Copyright (C) 2005-2019 rigsofrods.org" VALUE "OriginalFilename", "RoR.exe" VALUE "ProductName", + "Rigs of Rods" VALUE "ProductVersion", + ROR_RESOURCE_VERSION_STRING + + END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", + 0x409, 1200 END END + +#endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ROR_RESOURCE_VERSION - PRODUCTVERSION ROR_RESOURCE_VERSION - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "rigsofrods.org" - VALUE "FileDescription", "Rigs of Rods Simulator" - VALUE "FileVersion", ROR_RESOURCE_VERSION_STRING - VALUE "InternalName", "RoR" - VALUE "LegalCopyright", "Copyright (C) 2005-2019 rigsofrods.org" - VALUE "OriginalFilename", "RoR.exe" - VALUE "ProductName", "Rigs of Rods" - VALUE "ProductVersion", ROR_RESOURCE_VERSION_STRING - - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -96,7 +69,5 @@ END // Generated from the TEXTINCLUDE 3 resource. // - ///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +#endif // not APSTUDIO_INVOKED diff --git a/source/main/main.cpp b/source/main/main.cpp index e6d688136d..26e8ec0669 100644 --- a/source/main/main.cpp +++ b/source/main/main.cpp @@ -19,8 +19,6 @@ along with Rigs of Rods. If not, see . */ -#include "RoRPrerequisites.h" - #include "Application.h" #include "CacheSystem.h" #include "ContentManager.h" @@ -34,6 +32,7 @@ #include "OgreSubsystem.h" #include "PlatformUtils.h" #include "RoRFrameListener.h" +#include "RoRPrerequisites.h" #include "RoRVersion.h" #include "Scripting.h" #include "Settings.h" @@ -47,380 +46,367 @@ #include #ifdef USE_CURL -# include -#endif //USE_CURL + #include +#endif // USE_CURL -GlobalEnvironment* gEnv; // Global pointer used throughout the game. Declared in "RoRPrerequisites.h". TODO: Eliminate +GlobalEnvironment *gEnv; // Global pointer used throughout the game. Declared in "RoRPrerequisites.h". TODO: Eliminate GlobalEnvironment gEnvInstance; // The actual instance #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -int main(int argc, char *argv[]) -{ - using namespace RoR; + int main(int argc, char *argv[]) + { + using namespace RoR; #ifdef USE_CURL - curl_global_init(CURL_GLOBAL_ALL); // MUST init before any threads are started + curl_global_init(CURL_GLOBAL_ALL); // MUST init before any threads are started #endif #ifndef _DEBUG - try - { + try + { #endif - gEnv = &gEnvInstance; + gEnv = &gEnvInstance; - // ### Detect system paths ### + // ### Detect system paths ### - // Process directory - std::string exe_path = RoR::GetExecutablePath(); - if (exe_path.empty()) - { - ErrorUtils::ShowError(_L("Startup error"), _L("Error while retrieving program directory path")); - return -1; - } - App::sys_process_dir.SetActive(RoR::GetParentDirectory(exe_path.c_str()).c_str()); - - // RoR's home directory - std::string local_userdir = PathCombine(App::sys_process_dir.GetActive(), "config"); // TODO: Think of a better name, this is ambiguious with ~/.rigsofrods/config which stores configfiles! ~ only_a_ptr, 02/2018 - if (FolderExists(local_userdir)) - { - // It's a portable installation - App::sys_user_dir.SetActive(local_userdir.c_str()); - } - else - { - // Default location - user's home directory - std::string user_home = RoR::GetUserHomeDirectory(); - if (user_home.empty()) + // Process directory + std::string exe_path = RoR::GetExecutablePath(); + if (exe_path.empty()) { - ErrorUtils::ShowError(_L("Startup error"), _L("Error while retrieving user directory path")); + ErrorUtils::ShowError(_L("Startup error"), _L("Error while retrieving program directory path")); return -1; } - RoR::Str<500> ror_homedir; + App::sys_process_dir.SetActive(RoR::GetParentDirectory(exe_path.c_str()).c_str()); + + // RoR's home directory + std::string local_userdir = + PathCombine(App::sys_process_dir.GetActive(), + "config"); // TODO: Think of a better name, this is ambiguious with ~/.rigsofrods/config + // which stores configfiles! ~ only_a_ptr, 02/2018 + if (FolderExists(local_userdir)) + { + // It's a portable installation + App::sys_user_dir.SetActive(local_userdir.c_str()); + } + else + { + // Default location - user's home directory + std::string user_home = RoR::GetUserHomeDirectory(); + if (user_home.empty()) + { + ErrorUtils::ShowError(_L("Startup error"), _L("Error while retrieving user directory path")); + return -1; + } + RoR::Str<500> ror_homedir; #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - ror_homedir << user_home << PATH_SLASH << "Rigs of Rods " << ROR_VERSION_STRING_SHORT; + ror_homedir << user_home << PATH_SLASH << "Rigs of Rods " << ROR_VERSION_STRING_SHORT; #elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX - char* env_SNAP = getenv("SNAP_USER_COMMON"); - if(env_SNAP) - ror_homedir = env_SNAP; - else - ror_homedir << user_home << PATH_SLASH << ".rigsofrods"; + char *env_SNAP = getenv("SNAP_USER_COMMON"); + if (env_SNAP) + ror_homedir = env_SNAP; + else + ror_homedir << user_home << PATH_SLASH << ".rigsofrods"; #elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE - ror_homedir << user_home << PATH_SLASH << "RigsOfRods"; + ror_homedir << user_home << PATH_SLASH << "RigsOfRods"; #endif - CreateFolder(ror_homedir.ToCStr ()); - App::sys_user_dir.SetActive(ror_homedir.ToCStr ()); - } + CreateFolder(ror_homedir.ToCStr()); + App::sys_user_dir.SetActive(ror_homedir.ToCStr()); + } - // ### Create OGRE default logger early. ### + // ### Create OGRE default logger early. ### - std::string logs_dir = PathCombine(App::sys_user_dir.GetActive(), "logs"); - CreateFolder(logs_dir); - App::sys_logs_dir.SetActive(logs_dir.c_str()); + std::string logs_dir = PathCombine(App::sys_user_dir.GetActive(), "logs"); + CreateFolder(logs_dir); + App::sys_logs_dir.SetActive(logs_dir.c_str()); - auto ogre_log_manager = OGRE_NEW Ogre::LogManager(); - std::string rorlog_path = PathCombine(logs_dir, "RoR.log"); - Ogre::Log* rorlog = ogre_log_manager->createLog(rorlog_path, true, true); - rorlog->stream() << "[RoR] Rigs of Rods (www.rigsofrods.org) version " << ROR_VERSION_STRING; - std::time_t t = std::time(nullptr); - rorlog->stream() << "[RoR] Current date: " << std::put_time(std::localtime(&t), "%Y-%m-%d"); - App::diag_trace_globals.SetActive(true); // We have logger -> we can trace. + auto ogre_log_manager = OGRE_NEW Ogre::LogManager(); + std::string rorlog_path = PathCombine(logs_dir, "RoR.log"); + Ogre::Log * rorlog = ogre_log_manager->createLog(rorlog_path, true, true); + rorlog->stream() << "[RoR] Rigs of Rods (www.rigsofrods.org) version " << ROR_VERSION_STRING; + std::time_t t = std::time(nullptr); + rorlog->stream() << "[RoR] Current date: " << std::put_time(std::localtime(&t), "%Y-%m-%d"); + App::diag_trace_globals.SetActive(true); // We have logger -> we can trace. - if (! Settings::SetupAllPaths()) // Updates globals - { - ErrorUtils::ShowError(_L("Startup error"), _L("Resources folder not found. Check if correctly installed.")); - return -1; - } + if (!Settings::SetupAllPaths()) // Updates globals + { + ErrorUtils::ShowError(_L("Startup error"), _L("Resources folder not found. Check if correctly installed.")); + return -1; + } - Settings::getSingleton().LoadRoRCfg(); // Main config file - path obtained from GVars - Settings::getSingleton().ProcessCommandLine(argc, argv); + Settings::getSingleton().LoadRoRCfg(); // Main config file - path obtained from GVars + Settings::getSingleton().ProcessCommandLine(argc, argv); - if (App::app_state.GetPending() == AppState::PRINT_HELP_EXIT) - { - ShowCommandLineUsage(); - return 0; - } - if (App::app_state.GetPending() == AppState::PRINT_VERSION_EXIT) - { - ShowVersion(); - return 0; - } + if (App::app_state.GetPending() == AppState::PRINT_HELP_EXIT) + { + ShowCommandLineUsage(); + return 0; + } + if (App::app_state.GetPending() == AppState::PRINT_VERSION_EXIT) + { + ShowVersion(); + return 0; + } - App::StartOgreSubsystem(); + App::StartOgreSubsystem(); - Ogre::String src_path = PathCombine(App::sys_resources_dir.GetActive(), "skeleton.zip"); - Ogre::ResourceGroupManager::getSingleton().addResourceLocation(src_path, "Zip", "SrcRG"); - Ogre::FileInfoListPtr fl = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("SrcRG", "*", true); - if (fl->empty()) - { - ErrorUtils::ShowError(_L("Startup error"), _L("Faulty resource folder. Check if correctly installed.")); - return -1; - } - Ogre::String dst_path = PathCombine(App::sys_user_dir.GetActive(), ""); - for (auto file : *fl) - { - CreateFolder(dst_path + file.basename); - } - fl = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("SrcRG", "*"); - if (fl->empty()) - { - ErrorUtils::ShowError(_L("Startup error"), _L("Faulty resource folder. Check if correctly installed.")); - return -1; - } - Ogre::ResourceGroupManager::getSingleton().addResourceLocation(dst_path, "FileSystem", "DstRG", false, false); - for (auto file : *fl) - { - if (file.uncompressedSize == 0) - continue; - Ogre::String path = file.path + file.basename; - if (!Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("DstRG", path)->empty()) - continue; - Ogre::DataStreamPtr src_ds = Ogre::ResourceGroupManager::getSingleton().openResource(path, "SrcRG"); - Ogre::DataStreamPtr dst_ds = Ogre::ResourceGroupManager::getSingleton().createResource(path, "DstRG"); - std::vector buf(src_ds->size()); - size_t read = src_ds->read(buf.data(), src_ds->size()); - if (read > 0) + Ogre::String src_path = PathCombine(App::sys_resources_dir.GetActive(), "skeleton.zip"); + Ogre::ResourceGroupManager::getSingleton().addResourceLocation(src_path, "Zip", "SrcRG"); + Ogre::FileInfoListPtr fl = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("SrcRG", "*", true); + if (fl->empty()) { - dst_ds->write(buf.data(), read); + ErrorUtils::ShowError(_L("Startup error"), _L("Faulty resource folder. Check if correctly installed.")); + return -1; + } + Ogre::String dst_path = PathCombine(App::sys_user_dir.GetActive(), ""); + for (auto file : *fl) + { + CreateFolder(dst_path + file.basename); + } + fl = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("SrcRG", "*"); + if (fl->empty()) + { + ErrorUtils::ShowError(_L("Startup error"), _L("Faulty resource folder. Check if correctly installed.")); + return -1; + } + Ogre::ResourceGroupManager::getSingleton().addResourceLocation(dst_path, "FileSystem", "DstRG", false, false); + for (auto file : *fl) + { + if (file.uncompressedSize == 0) continue; + Ogre::String path = file.path + file.basename; + if (!Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("DstRG", path)->empty()) continue; + Ogre::DataStreamPtr src_ds = Ogre::ResourceGroupManager::getSingleton().openResource(path, "SrcRG"); + Ogre::DataStreamPtr dst_ds = Ogre::ResourceGroupManager::getSingleton().createResource(path, "DstRG"); + std::vector buf(src_ds->size()); + size_t read = src_ds->read(buf.data(), src_ds->size()); + if (read > 0) { dst_ds->write(buf.data(), read); } + } + Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("SrcRG"); + Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("DstRG"); + + Ogre::OverlaySystem *overlay_system = new Ogre::OverlaySystem(); // Overlay init + + Ogre::ConfigOptionMap ropts = App::GetOgreSubsystem()->GetOgreRoot()->getRenderSystem()->getConfigOptions(); + int resolution = + Ogre::StringConverter::parseInt(Ogre::StringUtil::split(ropts["Video Mode"].currentValue, " x ")[0], 1024); + int fsaa = 2 * (Ogre::StringConverter::parseInt(ropts["FSAA"].currentValue, 0) / 4); + int res = std::pow(2, std::floor(std::log2(resolution))); + + Ogre::TextureManager::getSingleton().createManual( + "EnvironmentTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_CUBE_MAP, res / 4, + res / 4, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); + Ogre::TextureManager::getSingleton().createManual( + "Refraction", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res / 2, res / 2, 0, + Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); + Ogre::TextureManager::getSingleton().createManual( + "Reflection", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res / 2, res / 2, 0, + Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); + + if (!App::diag_warning_texture.GetActive()) + { + // We overwrite the default warning texture (yellow stripes) with something unobtrusive + Ogre::uchar data[3] = {0}; + Ogre::PixelBox pixels(1, 1, 1, Ogre::PF_BYTE_RGB, &data); + Ogre::TextureManager::getSingleton()._getWarningTexture()->getBuffer()->blitFromMemory(pixels); } - } - Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("SrcRG"); - Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("DstRG"); - - Ogre::OverlaySystem* overlay_system = new Ogre::OverlaySystem(); //Overlay init - - Ogre::ConfigOptionMap ropts = App::GetOgreSubsystem()->GetOgreRoot()->getRenderSystem()->getConfigOptions(); - int resolution = Ogre::StringConverter::parseInt(Ogre::StringUtil::split(ropts["Video Mode"].currentValue, " x ")[0], 1024); - int fsaa = 2 * (Ogre::StringConverter::parseInt(ropts["FSAA"].currentValue, 0) / 4); - int res = std::pow(2, std::floor(std::log2(resolution))); - - Ogre::TextureManager::getSingleton().createManual ("EnvironmentTexture", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_CUBE_MAP, res / 4, res / 4, 0, - Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); - Ogre::TextureManager::getSingleton ().createManual ("Refraction", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res / 2, res / 2, 0, - Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); - Ogre::TextureManager::getSingleton ().createManual ("Reflection", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res / 2, res / 2, 0, - Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); - - if (!App::diag_warning_texture.GetActive()) - { - // We overwrite the default warning texture (yellow stripes) with something unobtrusive - Ogre::uchar data[3] = {0}; - Ogre::PixelBox pixels(1, 1, 1, Ogre::PF_BYTE_RGB, &data); - Ogre::TextureManager::getSingleton()._getWarningTexture()->getBuffer()->blitFromMemory(pixels); - } - App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::FLAGS); - App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::ICONS); - App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::OGRE_CORE); - App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::WALLPAPERS); + App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::FLAGS); + App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::ICONS); + App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::OGRE_CORE); + App::GetContentManager()->AddResourcePack(ContentManager::ResourcePack::WALLPAPERS); #ifndef NOLANG - LanguageEngine::getSingleton().setup(); + LanguageEngine::getSingleton().setup(); #endif // NOLANG - // Setup rendering (menu + simulation) - Ogre::SceneManager* scene_manager = App::GetOgreSubsystem()->GetOgreRoot()->createSceneManager(Ogre::ST_EXTERIOR_CLOSE, "main_scene_manager"); - gEnv->sceneManager = scene_manager; - if (overlay_system) - { - scene_manager->addRenderQueueListener(overlay_system); - } + // Setup rendering (menu + simulation) + Ogre::SceneManager *scene_manager = + App::GetOgreSubsystem()->GetOgreRoot()->createSceneManager(Ogre::ST_EXTERIOR_CLOSE, "main_scene_manager"); + gEnv->sceneManager = scene_manager; + if (overlay_system) { scene_manager->addRenderQueueListener(overlay_system); } - Ogre::Camera* camera = scene_manager->createCamera("PlayerCam"); - camera->setPosition(Ogre::Vector3(128, 25, 128)); // Position it at 500 in Z direction - camera->lookAt(Ogre::Vector3(0, 0, -300)); // Look back along -Z - camera->setNearClipDistance(0.5); - camera->setFarClipDistance(1000.0 * 1.733); - camera->setFOVy(Ogre::Degree(60)); - camera->setAutoAspectRatio(true); - App::GetOgreSubsystem()->GetViewport()->setCamera(camera); - gEnv->mainCamera = camera; + Ogre::Camera *camera = scene_manager->createCamera("PlayerCam"); + camera->setPosition(Ogre::Vector3(128, 25, 128)); // Position it at 500 in Z direction + camera->lookAt(Ogre::Vector3(0, 0, -300)); // Look back along -Z + camera->setNearClipDistance(0.5); + camera->setFarClipDistance(1000.0 * 1.733); + camera->setFOVy(Ogre::Degree(60)); + camera->setAutoAspectRatio(true); + App::GetOgreSubsystem()->GetViewport()->setCamera(camera); + gEnv->mainCamera = camera; - Ogre::String menu_wallpaper_texture_name = GUIManager::getRandomWallpaperImage(); + Ogre::String menu_wallpaper_texture_name = GUIManager::getRandomWallpaperImage(); - App::GetContentManager()->InitContentManager(); + App::GetContentManager()->InitContentManager(); - App::CreateGuiManagerIfNotExists(); + App::CreateGuiManagerIfNotExists(); - // Load and show menu wallpaper - MyGUI::VectorWidgetPtr v = MyGUI::LayoutManager::getInstance().loadLayout("wallpaper.layout"); - MyGUI::Widget* menu_wallpaper_widget = nullptr; - if (!v.empty()) - { - MyGUI::Widget* mainw = v.at(0); - if (mainw) + // Load and show menu wallpaper + MyGUI::VectorWidgetPtr v = MyGUI::LayoutManager::getInstance().loadLayout("wallpaper.layout"); + MyGUI::Widget * menu_wallpaper_widget = nullptr; + if (!v.empty()) { - MyGUI::ImageBox* img = (MyGUI::ImageBox *)(mainw->getChildAt(0)); - if (img) - img->setImageTexture(menu_wallpaper_texture_name); - menu_wallpaper_widget = mainw; + MyGUI::Widget *mainw = v.at(0); + if (mainw) + { + MyGUI::ImageBox *img = (MyGUI::ImageBox *)(mainw->getChildAt(0)); + if (img) img->setImageTexture(menu_wallpaper_texture_name); + menu_wallpaper_widget = mainw; + } } - } - InitDiscord(); + InitDiscord(); #ifdef USE_ANGELSCRIPT - new ScriptEngine(); // Init singleton. TODO: Move under Application + new ScriptEngine(); // Init singleton. TODO: Move under Application #endif - App::CreateInputEngine(); - App::GetInputEngine()->setupDefault(App::GetOgreSubsystem()->GetMainHWND()); + App::CreateInputEngine(); + App::GetInputEngine()->setupDefault(App::GetOgreSubsystem()->GetMainHWND()); - App::GetContentManager()->InitModCache(); + App::GetContentManager()->InitModCache(); - RoR::ForceFeedback force_feedback; + RoR::ForceFeedback force_feedback; #ifdef _WIN32 - if (App::io_ffb_enabled.GetActive()) // Force feedback - { - if (App::GetInputEngine()->getForceFeedbackDevice()) - { - force_feedback.Setup(); - } - else + if (App::io_ffb_enabled.GetActive()) // Force feedback { - LOG("No force feedback device detected, disabling force feedback"); - App::io_ffb_enabled.SetActive(false); + if (App::GetInputEngine()->getForceFeedbackDevice()) { force_feedback.Setup(); } + else + { + LOG("No force feedback device detected, disabling force feedback"); + App::io_ffb_enabled.SetActive(false); + } } - } #endif // _WIN32 - RoR::App::GetInputEngine()->windowResized(App::GetOgreSubsystem()->GetRenderWindow()); + RoR::App::GetInputEngine()->windowResized(App::GetOgreSubsystem()->GetRenderWindow()); - MainMenu main_obj; - SkidmarkConfig skidmark_conf; // Loads 'skidmark.cfg' in constructor + MainMenu main_obj; + SkidmarkConfig skidmark_conf; // Loads 'skidmark.cfg' in constructor - // ### Main loop (switches application states) ### + // ### Main loop (switches application states) ### - AppState prev_app_state = App::app_state.GetActive(); - App::app_state.SetPending(AppState::MAIN_MENU); + AppState prev_app_state = App::app_state.GetActive(); + App::app_state.SetPending(AppState::MAIN_MENU); - if (App::mp_join_on_startup.GetActive()) - { - App::mp_state.SetPending(RoR::MpState::CONNECTED); - } - else if (!App::diag_preset_terrain.IsActiveEmpty()) - { - App::app_state.SetPending(AppState::SIMULATION); - } - else if (App::sim_load_savegame.GetActive()) - { - App::app_state.SetPending(AppState::SIMULATION); - } + if (App::mp_join_on_startup.GetActive()) { App::mp_state.SetPending(RoR::MpState::CONNECTED); } + else if (!App::diag_preset_terrain.IsActiveEmpty()) + { + App::app_state.SetPending(AppState::SIMULATION); + } + else if (App::sim_load_savegame.GetActive()) + { + App::app_state.SetPending(AppState::SIMULATION); + } - while (App::app_state.GetPending() != AppState::SHUTDOWN) - { - if (App::app_state.GetPending() == AppState::MAIN_MENU) - + while (App::app_state.GetPending() != AppState::SHUTDOWN) { - App::app_state.ApplyPending(); + if (App::app_state.GetPending() == AppState::MAIN_MENU) - if (App::sim_load_savegame.GetActive()) { - App::app_state.SetPending(AppState::SIMULATION); - continue; - } + App::app_state.ApplyPending(); -#ifdef USE_OPENAL - if (App::audio_menu_music.GetActive()) - { - SoundScriptManager::getSingleton().createInstance("tracks/main_menu_tune", -1, nullptr); - SOUND_START(-1, SS_TRIG_MAIN_MENU); - } -#endif // USE_OPENAL + if (App::sim_load_savegame.GetActive()) + { + App::app_state.SetPending(AppState::SIMULATION); + continue; + } - App::GetGuiManager()->ReflectGameState(); - if (!App::mp_join_on_startup.GetActive() && App::app_skip_main_menu.GetActive()) - { - // MainMenu disabled (singleplayer mode) -> go directly to map selector (traditional behavior) - if (App::diag_preset_terrain.IsActiveEmpty()) +#ifdef USE_OPENAL + if (App::audio_menu_music.GetActive()) { - App::GetGuiManager()->SetVisible_GameMainMenu(false); - App::GetGuiManager()->GetMainSelector()->Show(LT_Terrain); + SoundScriptManager::getSingleton().createInstance("tracks/main_menu_tune", -1, nullptr); + SOUND_START(-1, SS_TRIG_MAIN_MENU); } - } +#endif // USE_OPENAL - main_obj.EnterMainMenuLoop(); - } - else if (App::app_state.GetPending() == AppState::SIMULATION) - { - { // Enclosing scope for SimController - SimController sim_controller(&force_feedback, &skidmark_conf); - App::SetSimController(&sim_controller); - if (sim_controller.SetupGameplayLoop()) + App::GetGuiManager()->ReflectGameState(); + if (!App::mp_join_on_startup.GetActive() && App::app_skip_main_menu.GetActive()) { - App::app_state.ApplyPending(); - App::GetGuiManager()->ReflectGameState(); - App::sim_state.SetActive(SimState::RUNNING); - sim_controller.EnterGameplayLoop(); - App::SetSimController(nullptr); - App::GetMainMenu()->LeaveMultiplayerServer(); -#ifdef USE_MUMBLE - if (App::GetMumble() != nullptr) + // MainMenu disabled (singleplayer mode) -> go directly to map selector (traditional behavior) + if (App::diag_preset_terrain.IsActiveEmpty()) { - App::GetMumble()->SetNonPositionalAudio(); + App::GetGuiManager()->SetVisible_GameMainMenu(false); + App::GetGuiManager()->GetMainSelector()->Show(LT_Terrain); } -#endif // USE_MUMBLE - menu_wallpaper_widget->setVisible(true); - } - else - { - App::app_state.SetPending(AppState::MAIN_MENU); } - } // Enclosing scope for SimController - gEnv->sceneManager->clearScene(); // Wipe the scene after SimController was destroyed - } - prev_app_state = App::app_state.GetActive(); + main_obj.EnterMainMenuLoop(); + } + else if (App::app_state.GetPending() == AppState::SIMULATION) + { + { // Enclosing scope for SimController + SimController sim_controller(&force_feedback, &skidmark_conf); + App::SetSimController(&sim_controller); + if (sim_controller.SetupGameplayLoop()) + { + App::app_state.ApplyPending(); + App::GetGuiManager()->ReflectGameState(); + App::sim_state.SetActive(SimState::RUNNING); + sim_controller.EnterGameplayLoop(); + App::SetSimController(nullptr); + App::GetMainMenu()->LeaveMultiplayerServer(); +#ifdef USE_MUMBLE + if (App::GetMumble() != nullptr) { App::GetMumble()->SetNonPositionalAudio(); } +#endif // USE_MUMBLE + menu_wallpaper_widget->setVisible(true); + } + else + { + App::app_state.SetPending(AppState::MAIN_MENU); + } + } // Enclosing scope for SimController + gEnv->sceneManager->clearScene(); // Wipe the scene after SimController was destroyed + } + prev_app_state = App::app_state.GetActive(); - } // End of app state loop + } // End of app state loop - // ======================================================================== - // Cleanup - // ======================================================================== + // ======================================================================== + // Cleanup + // ======================================================================== - ShutdownDiscord(); + ShutdownDiscord(); - Settings::getSingleton().SaveSettings(); // Save RoR.cfg + Settings::getSingleton().SaveSettings(); // Save RoR.cfg - App::GetGuiManager()->GetMainSelector()->~MainSelector(); + App::GetGuiManager()->GetMainSelector()->~MainSelector(); - App::GetMainMenu()->LeaveMultiplayerServer(); + App::GetMainMenu()->LeaveMultiplayerServer(); - //TODO: we should destroy OIS here - //TODO: we could also try to destroy SoundScriptManager, but we don't care! + // TODO: we should destroy OIS here + // TODO: we could also try to destroy SoundScriptManager, but we don't care! - scene_manager->destroyCamera(camera); - App::GetOgreSubsystem()->GetOgreRoot()->destroySceneManager(scene_manager); + scene_manager->destroyCamera(camera); + App::GetOgreSubsystem()->GetOgreRoot()->destroySceneManager(scene_manager); - App::DestroyOverlayWrapper(); + App::DestroyOverlayWrapper(); #ifndef _DEBUG - } - catch (Ogre::Exception& e) - { - LOG(e.getFullDescription()); - ErrorUtils::ShowError(_L("An exception has occured!"), e.getFullDescription()); - } - catch (std::runtime_error& e) - { - LOG(e.what()); - ErrorUtils::ShowError(_L("An exception (std::runtime_error) has occured!"), e.what()); - } + } + catch (Ogre::Exception &e) + { + LOG(e.getFullDescription()); + ErrorUtils::ShowError(_L("An exception has occured!"), e.getFullDescription()); + } + catch (std::runtime_error &e) + { + LOG(e.what()); + ErrorUtils::ShowError(_L("An exception (std::runtime_error) has occured!"), e.what()); + } #endif - return 0; -} + return 0; + } #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 -INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) -{ - return main(__argc, __argv); -} + INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT) + { + return main(__argc, __argv); + } #endif #ifdef __cplusplus diff --git a/source/main/network/Network.cpp b/source/main/network/Network.cpp index 0ece0d1e4b..88f0890a5e 100644 --- a/source/main/network/Network.cpp +++ b/source/main/network/Network.cpp @@ -21,783 +21,783 @@ #ifdef USE_SOCKETW -#include "Network.h" - -#include "Application.h" -#include "ChatSystem.h" -#include "ErrorUtils.h" -#include "GUIManager.h" -#include "GUI_TopMenubar.h" -#include "Language.h" -#include "RoRVersion.h" -#include "ScriptEngine.h" -#include "Utils.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace RoR { -namespace Networking { - -static Ogre::ColourValue MP_COLORS[] = // Classic RoR multiplayer colors + #include "Network.h" + + #include "Application.h" + #include "ChatSystem.h" + #include "ErrorUtils.h" + #include "GUIManager.h" + #include "GUI_TopMenubar.h" + #include "Language.h" + #include "RoRVersion.h" + #include "ScriptEngine.h" + #include "Utils.h" + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + +namespace RoR { - Ogre::ColourValue(0.0, 0.8, 0.0), - Ogre::ColourValue(0.0, 0.4, 0.701960784314), - Ogre::ColourValue(1.0, 0.501960784314, 0.0), - Ogre::ColourValue(1.0, 0.8, 0.0), - //Ogre::ColourValue(0.2, 0.0, 0.6), - //Ogre::ColourValue(0.6, 0.0, 0.6), - Ogre::ColourValue(0.8, 1.0, 0.0), - Ogre::ColourValue(1.0, 0.0, 0.0), - Ogre::ColourValue(0.501960784314, 0.501960784314, 0.501960784314), - Ogre::ColourValue(0.0, 0.560784313725, 0.0), - //Ogre::ColourValue(0.0, 0.282352941176, 0.490196078431), - Ogre::ColourValue(0.701960784314, 0.352941176471, 0.0), - Ogre::ColourValue(0.701960784314, 0.560784313725, 0.0), - //Ogre::ColourValue(0.419607843137, 0.0, 0.419607843137), - Ogre::ColourValue(0.560784313725, 0.701960784314, 0.0), - Ogre::ColourValue(0.701960784314, 0.0, 0.0), - Ogre::ColourValue(0.745098039216, 0.745098039216, 0.745098039216), - Ogre::ColourValue(0.501960784314, 1.0, 0.501960784314), - Ogre::ColourValue(0.501960784314, 0.788235294118, 1.0), - Ogre::ColourValue(1.0, 0.752941176471, 0.501960784314), - Ogre::ColourValue(1.0, 0.901960784314, 0.501960784314), - Ogre::ColourValue(0.666666666667, 0.501960784314, 1.0), - Ogre::ColourValue(0.933333333333, 0.0, 0.8), - Ogre::ColourValue(1.0, 0.501960784314, 0.501960784314), - Ogre::ColourValue(0.4, 0.4, 0.0), - Ogre::ColourValue(1.0, 0.749019607843, 1.0), - Ogre::ColourValue(0.0, 1.0, 0.8), - Ogre::ColourValue(0.8, 0.4, 0.6), - Ogre::ColourValue(0.6, 0.6, 0.0), -}; - -using namespace RoRnet; - -struct send_packet_t -{ - char buffer[RORNET_MAX_MESSAGE_LENGTH]; - int size; -}; + namespace Networking + { -static RoRnet::ServerInfo m_server_settings; + static Ogre::ColourValue MP_COLORS[] = // Classic RoR multiplayer colors + { + Ogre::ColourValue(0.0, 0.8, 0.0), + Ogre::ColourValue(0.0, 0.4, 0.701960784314), + Ogre::ColourValue(1.0, 0.501960784314, 0.0), + Ogre::ColourValue(1.0, 0.8, 0.0), + // Ogre::ColourValue(0.2, 0.0, 0.6), + // Ogre::ColourValue(0.6, 0.0, 0.6), + Ogre::ColourValue(0.8, 1.0, 0.0), + Ogre::ColourValue(1.0, 0.0, 0.0), + Ogre::ColourValue(0.501960784314, 0.501960784314, 0.501960784314), + Ogre::ColourValue(0.0, 0.560784313725, 0.0), + // Ogre::ColourValue(0.0, 0.282352941176, 0.490196078431), + Ogre::ColourValue(0.701960784314, 0.352941176471, 0.0), + Ogre::ColourValue(0.701960784314, 0.560784313725, 0.0), + // Ogre::ColourValue(0.419607843137, 0.0, 0.419607843137), + Ogre::ColourValue(0.560784313725, 0.701960784314, 0.0), + Ogre::ColourValue(0.701960784314, 0.0, 0.0), + Ogre::ColourValue(0.745098039216, 0.745098039216, 0.745098039216), + Ogre::ColourValue(0.501960784314, 1.0, 0.501960784314), + Ogre::ColourValue(0.501960784314, 0.788235294118, 1.0), + Ogre::ColourValue(1.0, 0.752941176471, 0.501960784314), + Ogre::ColourValue(1.0, 0.901960784314, 0.501960784314), + Ogre::ColourValue(0.666666666667, 0.501960784314, 1.0), + Ogre::ColourValue(0.933333333333, 0.0, 0.8), + Ogre::ColourValue(1.0, 0.501960784314, 0.501960784314), + Ogre::ColourValue(0.4, 0.4, 0.0), + Ogre::ColourValue(1.0, 0.749019607843, 1.0), + Ogre::ColourValue(0.0, 1.0, 0.8), + Ogre::ColourValue(0.8, 0.4, 0.6), + Ogre::ColourValue(0.6, 0.6, 0.0), + }; + + using namespace RoRnet; + + struct send_packet_t + { + char buffer[RORNET_MAX_MESSAGE_LENGTH]; + int size; + }; -static Ogre::UTFString m_username; // Shadows GVar 'mp_player_name' for multithreaded access. -static Str<400> m_net_host; // Shadows GVar 'mp_server_host' for multithreaded access. -static Str<100> m_password; // Shadows GVar 'mp_server_password' for multithreaded access. -static Str<100> m_token; // Shadows GVar 'mp_player_token' for multithreaded access. -static int m_net_port; // Shadows GVar 'mp_server_port' for multithreaded access. -static int m_uid; -static int m_authlevel; -static RoRnet::UserInfo m_userdata; + static RoRnet::ServerInfo m_server_settings; -static int m_stream_id = 10; + static Ogre::UTFString m_username; // Shadows GVar 'mp_player_name' for multithreaded access. + static Str<400> m_net_host; // Shadows GVar 'mp_server_host' for multithreaded access. + static Str<100> m_password; // Shadows GVar 'mp_server_password' for multithreaded access. + static Str<100> m_token; // Shadows GVar 'mp_player_token' for multithreaded access. + static int m_net_port; // Shadows GVar 'mp_server_port' for multithreaded access. + static int m_uid; + static int m_authlevel; + static RoRnet::UserInfo m_userdata; -static std::atomic m_net_quality; + static int m_stream_id = 10; -static std::vector m_users; + static std::atomic m_net_quality; -static SWInetSocket socket; + static std::vector m_users; -static std::thread m_send_thread; -static std::thread m_recv_thread; -static std::thread m_connect_thread; + static SWInetSocket socket; -static NetEventQueue m_event_queue; -static std::string m_status_message; -static std::atomic m_shutdown; + static std::thread m_send_thread; + static std::thread m_recv_thread; + static std::thread m_connect_thread; -static std::mutex m_users_mutex; -static std::mutex m_userdata_mutex; -static std::mutex m_recv_packetqueue_mutex; -static std::mutex m_send_packetqueue_mutex; -static std::mutex m_event_queue_mutex; + static NetEventQueue m_event_queue; + static std::string m_status_message; + static std::atomic m_shutdown; -static std::condition_variable m_send_packet_available_cv; + static std::mutex m_users_mutex; + static std::mutex m_userdata_mutex; + static std::mutex m_recv_packetqueue_mutex; + static std::mutex m_send_packetqueue_mutex; + static std::mutex m_event_queue_mutex; -static std::vector m_recv_packet_buffer; -static std::deque m_send_packet_buffer; + static std::condition_variable m_send_packet_available_cv; -static const unsigned int m_packet_buffer_size = 20; + static std::vector m_recv_packet_buffer; + static std::deque m_send_packet_buffer; -#define LOG_THREAD(_MSG_) { std::stringstream s; s << _MSG_ << " (Thread ID: " << std::this_thread::get_id() << ")"; LOG(s.str()); } -#define LOGSTREAM Ogre::LogManager().getSingleton().stream() + static const unsigned int m_packet_buffer_size = 20; -bool ConnectThread(); // Declaration. + #define LOG_THREAD(_MSG_) \ + { \ + std::stringstream s; \ + s << _MSG_ << " (Thread ID: " << std::this_thread::get_id() << ")"; \ + LOG(s.str()); \ + } + #define LOGSTREAM Ogre::LogManager().getSingleton().stream() -Ogre::ColourValue GetPlayerColor(int color_num) -{ - int numColours = sizeof(MP_COLORS) / sizeof(Ogre::ColourValue); - if (color_num < 0 || color_num >= numColours) - return Ogre::ColourValue::ZERO; + bool ConnectThread(); // Declaration. - return MP_COLORS[color_num]; -} + Ogre::ColourValue GetPlayerColor(int color_num) + { + int numColours = sizeof(MP_COLORS) / sizeof(Ogre::ColourValue); + if (color_num < 0 || color_num >= numColours) return Ogre::ColourValue::ZERO; -void FireNetEvent(NetEvent::Type type, std::string const & message) -{ - std::lock_guard lock(m_event_queue_mutex); - m_event_queue.emplace(type, message); -} + return MP_COLORS[color_num]; + } -void DebugPacket(const char *name, RoRnet::Header *header, char *buffer) -{ - std::stringstream msg; - msg << "++ " << name << ": " << header->source << ", " << header->streamid - << ", "<< header->command << ", " << header->size << ", hash: " << HashData(buffer, header->size); - LOG(msg.str()); -} + void FireNetEvent(NetEvent::Type type, std::string const &message) + { + std::lock_guard lock(m_event_queue_mutex); + m_event_queue.emplace(type, message); + } -void SetNetQuality(int quality) -{ - m_net_quality = quality; -} + void DebugPacket(const char *name, RoRnet::Header *header, char *buffer) + { + std::stringstream msg; + msg << "++ " << name << ": " << header->source << ", " << header->streamid << ", " << header->command << ", " + << header->size << ", hash: " << HashData(buffer, header->size); + LOG(msg.str()); + } -int GetNetQuality() -{ - return m_net_quality; -} + void SetNetQuality(int quality) + { + m_net_quality = quality; + } -int GetUID() -{ - return m_uid; -} + int GetNetQuality() + { + return m_net_quality; + } -bool SendMessageRaw(char *buffer, int msgsize) -{ - SWBaseSocket::SWBaseError error; + int GetUID() + { + return m_uid; + } - if (socket.fsend(buffer, msgsize, &error) < msgsize) - { - LOG("NET send error: " + error.get_error()); - return false; - } + bool SendMessageRaw(char *buffer, int msgsize) + { + SWBaseSocket::SWBaseError error; - return true; -} + if (socket.fsend(buffer, msgsize, &error) < msgsize) + { + LOG("NET send error: " + error.get_error()); + return false; + } -bool SendNetMessage(int type, unsigned int streamid, int len, char* content) -{ - RoRnet::Header head; - memset(&head, 0, sizeof(RoRnet::Header)); - head.command = type; - head.source = m_uid; - head.size = len; - head.streamid = streamid; + return true; + } - const int msgsize = sizeof(RoRnet::Header) + len; + bool SendNetMessage(int type, unsigned int streamid, int len, char *content) + { + RoRnet::Header head; + memset(&head, 0, sizeof(RoRnet::Header)); + head.command = type; + head.source = m_uid; + head.size = len; + head.streamid = streamid; - if (msgsize >= RORNET_MAX_MESSAGE_LENGTH) - { - return false; - } + const int msgsize = sizeof(RoRnet::Header) + len; - char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; - memcpy(buffer, (char *)&head, sizeof(RoRnet::Header)); - memcpy(buffer + sizeof(RoRnet::Header), content, len); + if (msgsize >= RORNET_MAX_MESSAGE_LENGTH) { return false; } - return SendMessageRaw(buffer, msgsize); -} + char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; + memcpy(buffer, (char *)&head, sizeof(RoRnet::Header)); + memcpy(buffer + sizeof(RoRnet::Header), content, len); -void QueueStreamData(RoRnet::Header &header, char *buffer, size_t buffer_len) -{ - recv_packet_t packet; - packet.header = header; - memcpy(packet.buffer, buffer, std::min(buffer_len, size_t(RORNET_MAX_MESSAGE_LENGTH))); + return SendMessageRaw(buffer, msgsize); + } - std::lock_guard lock(m_recv_packetqueue_mutex); - m_recv_packet_buffer.push_back(packet); -} + void QueueStreamData(RoRnet::Header &header, char *buffer, size_t buffer_len) + { + recv_packet_t packet; + packet.header = header; + memcpy(packet.buffer, buffer, std::min(buffer_len, size_t(RORNET_MAX_MESSAGE_LENGTH))); -int ReceiveMessage(RoRnet::Header *head, char* content, int bufferlen) -{ - SWBaseSocket::SWBaseError error; + std::lock_guard lock(m_recv_packetqueue_mutex); + m_recv_packet_buffer.push_back(packet); + } -#ifdef DEBUG - LOG_THREAD("[RoR|Networking] ReceiveMessage() waiting..."); -#endif //DEBUG + int ReceiveMessage(RoRnet::Header *head, char *content, int bufferlen) + { + SWBaseSocket::SWBaseError error; - if (socket.frecv((char*)head, sizeof(RoRnet::Header), &error) < sizeof(RoRnet::Header)) - { - LOG("NET receive error 1: " + error.get_error()); - return -1; - } + #ifdef DEBUG + LOG_THREAD("[RoR|Networking] ReceiveMessage() waiting..."); + #endif // DEBUG -#ifdef DEBUG - LOG_THREAD("[RoR|Networking] ReceiveMessage() header received"); -#endif //DEBUG + if (socket.frecv((char *)head, sizeof(RoRnet::Header), &error) < sizeof(RoRnet::Header)) + { + LOG("NET receive error 1: " + error.get_error()); + return -1; + } - if (head->size > uint32_t(bufferlen)) - { - return -3; - } + #ifdef DEBUG + LOG_THREAD("[RoR|Networking] ReceiveMessage() header received"); + #endif // DEBUG - if (head->size > 0) - { - // Read the packet content - std::memset(content, 0, bufferlen); - if (socket.frecv(content, head->size, &error) < static_cast(head->size)) - { - LOG_THREAD("NET receive error 2: "+ error.get_error()); - return -1; - } - } + if (head->size > uint32_t(bufferlen)) { return -3; } -#ifdef DEBUG - LOG_THREAD("[RoR|Networking] ReceiveMessage() body received"); -#endif //DEBUG + if (head->size > 0) + { + // Read the packet content + std::memset(content, 0, bufferlen); + if (socket.frecv(content, head->size, &error) < static_cast(head->size)) + { + LOG_THREAD("NET receive error 2: " + error.get_error()); + return -1; + } + } - return 0; -} + #ifdef DEBUG + LOG_THREAD("[RoR|Networking] ReceiveMessage() body received"); + #endif // DEBUG -void SendThread() -{ - LOG("[RoR|Networking] SendThread started"); - while (!m_shutdown) - { - send_packet_t packet; + return 0; + } + + void SendThread() { - std::unique_lock queue_lock(m_send_packetqueue_mutex); - while (m_send_packet_buffer.empty() && !m_shutdown) - { - m_send_packet_available_cv.wait(queue_lock); - } - if (m_shutdown) + LOG("[RoR|Networking] SendThread started"); + while (!m_shutdown) { - break; + send_packet_t packet; + { + std::unique_lock queue_lock(m_send_packetqueue_mutex); + while (m_send_packet_buffer.empty() && !m_shutdown) + { + m_send_packet_available_cv.wait(queue_lock); + } + if (m_shutdown) { break; } + packet = m_send_packet_buffer.front(); + m_send_packet_buffer.pop_front(); + } + SendMessageRaw(packet.buffer, packet.size); } - packet = m_send_packet_buffer.front(); - m_send_packet_buffer.pop_front(); + LOG("[RoR|Networking] SendThread stopped"); } - SendMessageRaw(packet.buffer, packet.size); - } - LOG("[RoR|Networking] SendThread stopped"); -} -void RecvThread() -{ - LOG_THREAD("[RoR|Networking] RecvThread starting..."); + void RecvThread() + { + LOG_THREAD("[RoR|Networking] RecvThread starting..."); - RoRnet::Header header; + RoRnet::Header header; - char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; + char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; - while (!m_shutdown) - { - int err = ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH); - //LOG("Received data: " + TOSTRING(header.command) + ", source: " + TOSTRING(header.source) + ":" + TOSTRING(header.streamid) + ", size: " + TOSTRING(header.size)); - if (err != 0) - { - LOG_THREAD("[RoR|Networking] RecvThread: Error while receiving data: " + TOSTRING(err)); - m_shutdown = true; // Atomic; instruct sender thread to stop - FireNetEvent(NetEvent::Type::RECV_ERROR, _LC("Network", "Error receiving data from network")); - continue; // Stop receiving data - } + while (!m_shutdown) + { + int err = ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH); + // LOG("Received data: " + TOSTRING(header.command) + ", source: " + TOSTRING(header.source) + ":" + + // TOSTRING(header.streamid) + ", size: " + TOSTRING(header.size)); + if (err != 0) + { + LOG_THREAD("[RoR|Networking] RecvThread: Error while receiving data: " + TOSTRING(err)); + m_shutdown = true; // Atomic; instruct sender thread to stop + FireNetEvent(NetEvent::Type::RECV_ERROR, _LC("Network", "Error receiving data from network")); + continue; // Stop receiving data + } - if (header.command == MSG2_STREAM_REGISTER) - { - if (header.source == m_uid) - continue; + if (header.command == MSG2_STREAM_REGISTER) + { + if (header.source == m_uid) continue; - RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)buffer; + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)buffer; - LOG(" * received stream registration: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid) + ", type: " + TOSTRING(reg->type)); - } - else if (header.command == MSG2_STREAM_REGISTER_RESULT) - { - RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)buffer; - LOG(" * received stream registration result: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid) + ", status: " + TOSTRING(reg->status)); - } - else if (header.command == MSG2_STREAM_UNREGISTER) - { - LOG(" * received stream deregistration: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid)); - } - else if (header.command == MSG2_UTF8_CHAT || header.command == MSG2_UTF8_PRIVCHAT) - { - // Chat message + LOG(" * received stream registration: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid) + + ", type: " + TOSTRING(reg->type)); + } + else if (header.command == MSG2_STREAM_REGISTER_RESULT) + { + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)buffer; + LOG(" * received stream registration result: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid) + + ", status: " + TOSTRING(reg->status)); + } + else if (header.command == MSG2_STREAM_UNREGISTER) + { + LOG(" * received stream deregistration: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid)); + } + else if (header.command == MSG2_UTF8_CHAT || header.command == MSG2_UTF8_PRIVCHAT) + { + // Chat message + } + else if (header.command == MSG2_NETQUALITY && header.source == -1) + { + if (header.size != sizeof(int)) { continue; } + int quality = *(int *)buffer; + SetNetQuality(quality); + continue; + } + else if (header.command == MSG2_USER_LEAVE) + { + if (header.source == m_uid) + { + m_shutdown = + true; // Atomic; stop sending/receiving data - server closes the connection quickly after kick. + + std::stringstream msg; + msg << _L("disconnected: remote side closed the connection"); + msg << " ** "; + msg << buffer; + if (std::strstr(buffer, "disconnected on request") != + nullptr) // FIXME: Add a reason code to MSG2_USER_LEAVE, this is ugly! + FireNetEvent(NetEvent::Type::USER_DISCONNECT, msg.str()); + else + FireNetEvent(NetEvent::Type::SERVER_KICK, msg.str()); + } + else + { + std::lock_guard lock(m_users_mutex); + auto user = std::find_if(m_users.begin(), m_users.end(), [header](const RoRnet::UserInfo &u) { + return static_cast(u.uniqueid) == header.source; + }); + if (user != m_users.end()) + { + Ogre::UTFString msg = RoR::ChatSystem::GetColouredName(user->username, user->colournum) + + RoR::Color::CommandColour + _L(" left the game"); + const char * utf8_line = msg.asUTF8_c_str(); + RoRnet::Header head; + head.command = MSG2_UTF8_CHAT; + head.source = -1; + head.size = (int)strlen(utf8_line); + QueueStreamData(head, (char *)utf8_line, strlen(utf8_line) + 1); + LOG_THREAD(Ogre::UTFString(user->username) + _L(" left the game")); + m_users.erase(user); + } + } + } + else if (header.command == MSG2_USER_INFO || header.command == MSG2_USER_JOIN) + { + if (header.source == m_uid) + { + std::lock_guard lock(m_userdata_mutex); + memcpy(&m_userdata, buffer, sizeof(RoRnet::UserInfo)); + m_authlevel = m_userdata.authstatus; + m_username = Ogre::UTFString(m_userdata.username); + // TODO: Update the global variable 'mp_player_name' in a threadsafe way. + } + else + { + RoRnet::UserInfo user_info; + memcpy(&user_info, buffer, sizeof(RoRnet::UserInfo)); + + bool user_exists = false; + { + std::lock_guard lock(m_users_mutex); + for (RoRnet::UserInfo &user : m_users) + { + if ((int)user.uniqueid == header.source) + { + user = user_info; + user_exists = true; + break; + } + } + if (!user_exists) + { + m_users.push_back(user_info); + Ogre::UTFString msg = RoR::ChatSystem::GetColouredName(user_info.username, user_info.colournum) + + RoR::Color::CommandColour + _L(" joined the game"); + const char * utf8_line = msg.asUTF8_c_str(); + RoRnet::Header head; + head.command = MSG2_UTF8_CHAT; + head.source = -1; + head.size = (int)strlen(utf8_line); + QueueStreamData(head, (char *)utf8_line, strlen(utf8_line) + 1); + LOG(Ogre::UTFString(user_info.username) + _L(" joined the game")); + } + } + } + continue; + } + else if (header.command == MSG2_GAME_CMD) + { + #ifdef USE_ANGELSCRIPT + ScriptEngine::getSingleton().queueStringForExecution(Ogre::String(buffer)); + #endif // USE_ANGELSCRIPT + continue; + } + // DebugPacket("recv", &header, buffer); + + QueueStreamData(header, buffer, RORNET_MAX_MESSAGE_LENGTH); + } + + LOG_THREAD("[RoR|Networking] RecvThread stopped"); } - else if (header.command == MSG2_NETQUALITY && header.source == -1) + + void CouldNotConnect(std::string const &msg, bool close_socket = true) { - if (header.size != sizeof(int)) + RoR::LogFormat("[RoR|Networking] Failed to connect to server [%s:%d], message: %s", m_net_host.GetBuffer(), + m_net_port, msg.c_str()); + FireNetEvent(NetEvent::Type::CONNECT_FAILURE, msg); + + if (close_socket) { - continue; + socket.set_timeout(1, 0); + socket.disconnect(); } - int quality = *(int *)buffer; - SetNetQuality(quality); - continue; } - else if (header.command == MSG2_USER_LEAVE) + + bool StartConnecting() { - if (header.source == m_uid) + // Shadow vars for threaded access + m_username = App::mp_player_name.GetActive(); + m_token = App::mp_player_token.GetActive(); + m_net_host = App::mp_server_host.GetActive(); + m_net_port = App::mp_server_port.GetActive(); + m_password = App::mp_server_password.GetActive(); + + try { - m_shutdown = true; // Atomic; stop sending/receiving data - server closes the connection quickly after kick. - - std::stringstream msg; - msg << _L("disconnected: remote side closed the connection"); - msg << " ** "; - msg << buffer; - if (std::strstr(buffer, "disconnected on request") != nullptr) // FIXME: Add a reason code to MSG2_USER_LEAVE, this is ugly! - FireNetEvent(NetEvent::Type::USER_DISCONNECT, msg.str()); - else - FireNetEvent(NetEvent::Type::SERVER_KICK, msg.str()); + m_connect_thread = std::thread(ConnectThread); + App::mp_state.SetActive(MpState::CONNECTING); // Mark connect thread as started + FireNetEvent(NetEvent::Type::CONNECT_STARTED, _LC("Network", "Starting...")); + return true; } - else + catch (std::exception &e) { - std::lock_guard lock(m_users_mutex); - auto user = std::find_if(m_users.begin(), m_users.end(), [header](const RoRnet::UserInfo& u) { return static_cast(u.uniqueid) == header.source; }); - if (user != m_users.end()) - { - Ogre::UTFString msg = RoR::ChatSystem::GetColouredName(user->username, user->colournum) + RoR::Color::CommandColour + _L(" left the game"); - const char *utf8_line = msg.asUTF8_c_str(); - RoRnet::Header head; - head.command = MSG2_UTF8_CHAT; - head.source = -1; - head.size = (int)strlen(utf8_line); - QueueStreamData(head, (char *)utf8_line, strlen(utf8_line) + 1); - LOG_THREAD(Ogre::UTFString(user->username) + _L(" left the game")); - m_users.erase(user); - } + App::mp_state.SetActive(MpState::DISABLED); + FireNetEvent(NetEvent::Type::CONNECT_FAILURE, _L("Failed to launch connection thread")); + RoR::LogFormat("[RoR|Networking] Failed to launch connection thread, message: %s", e.what()); + return false; } } - else if (header.command == MSG2_USER_INFO || header.command == MSG2_USER_JOIN) + + NetEventQueue CheckEvents() { - if (header.source == m_uid) - { - std::lock_guard lock(m_userdata_mutex); - memcpy(&m_userdata, buffer, sizeof(RoRnet::UserInfo)); - m_authlevel = m_userdata.authstatus; - m_username = Ogre::UTFString(m_userdata.username); - // TODO: Update the global variable 'mp_player_name' in a threadsafe way. - } - else - { - RoRnet::UserInfo user_info; - memcpy(&user_info, buffer, sizeof(RoRnet::UserInfo)); + std::lock_guard lock(m_event_queue_mutex); - bool user_exists = false; + NetEventQueue qcopy; + while (!m_event_queue.empty()) + { + switch (m_event_queue.front().type) { - std::lock_guard lock(m_users_mutex); - for (RoRnet::UserInfo &user : m_users) - { - if ((int)user.uniqueid == header.source) - { - user = user_info; - user_exists = true; - break; - } - } - if (!user_exists) - { - m_users.push_back(user_info); - Ogre::UTFString msg = RoR::ChatSystem::GetColouredName(user_info.username, user_info.colournum) + RoR::Color::CommandColour + _L(" joined the game"); - const char *utf8_line = msg.asUTF8_c_str(); - RoRnet::Header head; - head.command = MSG2_UTF8_CHAT; - head.source = -1; - head.size = (int)strlen(utf8_line); - QueueStreamData(head, (char *)utf8_line, strlen(utf8_line) + 1); - LOG(Ogre::UTFString(user_info.username) + _L(" joined the game")); - } + case NetEvent::Type::CONNECT_FAILURE: + case NetEvent::Type::CONNECT_SUCCESS: + if (m_connect_thread.joinable()) m_connect_thread.join(); // Clean up + break; + default:; } + qcopy.push(m_event_queue.front()); + m_event_queue.pop(); } - continue; + return qcopy; } - else if (header.command == MSG2_GAME_CMD) + + bool ConnectThread() { -#ifdef USE_ANGELSCRIPT - ScriptEngine::getSingleton().queueStringForExecution(Ogre::String(buffer)); -#endif // USE_ANGELSCRIPT - continue; - } - //DebugPacket("recv", &header, buffer); + RoR::LogFormat("[RoR|Networking] Trying to join server '%s' on port '%d' ...", m_net_host.GetBuffer(), m_net_port); - QueueStreamData(header, buffer, RORNET_MAX_MESSAGE_LENGTH); - } + SWBaseSocket::SWBaseError error; - LOG_THREAD("[RoR|Networking] RecvThread stopped"); -} + FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Estabilishing connection...")); + socket.set_timeout(10, 0); + socket.connect(App::mp_server_port.GetActive(), App::mp_server_host.GetActive(), &error); + if (error != SWBaseSocket::ok) + { + CouldNotConnect(_L("Could not create connection"), false); + return false; + } + FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Getting server info...")); + if (!SendNetMessage(MSG2_HELLO, 0, (int)strlen(RORNET_VERSION), (char *)RORNET_VERSION)) + { + CouldNotConnect(_L("Establishing network session: error sending hello")); + return false; + } -void CouldNotConnect(std::string const & msg, bool close_socket = true) -{ - RoR::LogFormat("[RoR|Networking] Failed to connect to server [%s:%d], message: %s", m_net_host.GetBuffer(), m_net_port, msg.c_str()); - FireNetEvent(NetEvent::Type::CONNECT_FAILURE, msg); + RoRnet::Header header; + char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; - if (close_socket) - { - socket.set_timeout(1, 0); - socket.disconnect(); - } -} + // Receive server (rornet protocol) version + if (ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH)) + { + CouldNotConnect(_L("Establishing network session: error getting server version")); + return false; + } + if (header.command == MSG2_WRONG_VER_LEGACY) // Pre-RoRnet_2.40 server + { + RoRnet::LegacyServerInfo info; + memcpy(&info, buffer, sizeof(RoRnet::LegacyServerInfo)); + Ogre::UTFString format_wstr = _L("Establishing network session: wrong server version, you are using version '%s' " + "and the server is using '%s'"); + const char * server_ver = + (info.protocolversion[0] != 0) ? info.protocolversion : "~ RoRnet_2.38 or earlier (not detected) ~"; + char msg_buf[500]; + snprintf(msg_buf, 500, format_wstr.asUTF8_c_str(), RORNET_VERSION, server_ver); + CouldNotConnect(msg_buf); + return false; + } + if (header.command == MSG2_WRONG_VER) + { + CouldNotConnect(_L("server uses a different protocol version")); + return false; + } + if (header.command != MSG2_HELLO) + { + CouldNotConnect(_L("Establishing network session: error getting server hello")); + return false; + } -bool StartConnecting() -{ - // Shadow vars for threaded access - m_username = App::mp_player_name.GetActive(); - m_token = App::mp_player_token.GetActive(); - m_net_host = App::mp_server_host.GetActive(); - m_net_port = App::mp_server_port.GetActive(); - m_password = App::mp_server_password.GetActive(); - - try - { - m_connect_thread = std::thread(ConnectThread); - App::mp_state.SetActive(MpState::CONNECTING); // Mark connect thread as started - FireNetEvent(NetEvent::Type::CONNECT_STARTED, _LC("Network", "Starting...")); - return true; - } - catch (std::exception& e) - { - App::mp_state.SetActive(MpState::DISABLED); - FireNetEvent(NetEvent::Type::CONNECT_FAILURE, _L("Failed to launch connection thread")); - RoR::LogFormat("[RoR|Networking] Failed to launch connection thread, message: %s", e.what()); - return false; - } -} - -NetEventQueue CheckEvents() -{ - std::lock_guard lock(m_event_queue_mutex); + // Save server settings + memcpy(&m_server_settings, buffer, sizeof(RoRnet::ServerInfo)); - NetEventQueue qcopy; - while (!m_event_queue.empty()) - { - switch (m_event_queue.front().type) - { - case NetEvent::Type::CONNECT_FAILURE: - case NetEvent::Type::CONNECT_SUCCESS: - if (m_connect_thread.joinable()) - m_connect_thread.join(); // Clean up - break; - default:; - } - qcopy.push(m_event_queue.front()); - m_event_queue.pop(); - } - return qcopy; -} + if (strncmp(m_server_settings.protocolversion, RORNET_VERSION, strlen(RORNET_VERSION))) + { + wchar_t tmp[512] = L""; + Ogre::UTFString tmp2 = _L("Establishing network session: wrong server version, you are using version '%s' and " + "the server is using '%s'"); + swprintf(tmp, 512, tmp2.asWStr_c_str(), RORNET_VERSION, m_server_settings.protocolversion); + CouldNotConnect(MyGUI::UString(tmp).asUTF8_c_str()); + return false; + } -bool ConnectThread() -{ - RoR::LogFormat("[RoR|Networking] Trying to join server '%s' on port '%d' ...", m_net_host.GetBuffer(), m_net_port); + FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Authorizing...")); + + // First handshake done, increase the timeout, important! + socket.set_timeout(0, 0); + + // Construct user credentials + // Beware of the wchar_t converted to UTF8 for networking + RoRnet::UserInfo c; + memset(&c, 0, sizeof(RoRnet::UserInfo)); + // Cut off the UTF string on the highest level, otherwise you will break UTF info + strncpy((char *)c.username, m_username.substr(0, RORNET_MAX_USERNAME_LEN * 0.5f).asUTF8_c_str(), + RORNET_MAX_USERNAME_LEN); + strncpy(c.serverpassword, Utils::Sha1Hash(m_password.GetBuffer()).c_str(), size_t(40)); + strncpy(c.usertoken, Utils::Sha1Hash(m_token.GetBuffer()).c_str(), size_t(40)); + strncpy(c.clientversion, ROR_VERSION_STRING, strnlen(ROR_VERSION_STRING, 25)); + strncpy(c.clientname, "RoR", 10); + std::string language = std::string(App::app_language.GetActive()).substr(0, 2); + std::string country = std::string(App::app_country.GetActive()).substr(0, 2); + strncpy(c.language, (language + std::string("_") + country).c_str(), 5); + strcpy(c.sessiontype, "normal"); + if (!SendNetMessage(MSG2_USER_INFO, 0, sizeof(RoRnet::UserInfo), (char *)&c)) + { + CouldNotConnect(_L("Establishing network session: error sending user info")); + return false; + } - SWBaseSocket::SWBaseError error; + // Getting authorization + if (ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH)) + { + CouldNotConnect(_L("Establishing network session: error getting server authorization")); + return false; + } - FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Estabilishing connection...")); - socket.set_timeout(10, 0); - socket.connect(App::mp_server_port.GetActive(), App::mp_server_host.GetActive(), &error); - if (error != SWBaseSocket::ok) - { - CouldNotConnect(_L("Could not create connection"), false); - return false; - } + if (header.command == MSG2_FULL) + { + CouldNotConnect(_L("Establishing network session: sorry, server has too many players")); + return false; + } + else if (header.command == MSG2_BANNED) + { + wchar_t tmp[512]; + memset(tmp, 0, 512); + if (strnlen(buffer, 20) > 0) + { + buffer[header.size] = {0}; + Ogre::UTFString tmp2 = _L("Establishing network session: sorry, you are banned:\n%s"); + swprintf(tmp, 512, tmp2.asWStr_c_str(), buffer); + CouldNotConnect(Ogre::UTFString(tmp)); + } + else + { + CouldNotConnect(_L("Establishing network session: sorry, you are banned!")); + } + return false; + } + else if (header.command == MSG2_WRONG_PW) + { + CouldNotConnect(_L("Establishing network session: sorry, wrong password!")); + return false; + } + else if (header.command == MSG2_WRONG_VER) + { + CouldNotConnect(_L("Establishing network session: sorry, wrong protocol version!")); + return false; + } - FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Getting server info...")); - if (!SendNetMessage(MSG2_HELLO, 0, (int)strlen(RORNET_VERSION), (char *)RORNET_VERSION)) - { - CouldNotConnect(_L("Establishing network session: error sending hello")); - return false; - } + if (header.command != MSG2_WELCOME) + { + CouldNotConnect(_L("Establishing network session: sorry, unknown server response")); + return false; + } - RoRnet::Header header; - char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0}; + FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Finishing...")); - // Receive server (rornet protocol) version - if (ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH)) - { - CouldNotConnect(_L("Establishing network session: error getting server version")); - return false; - } - if (header.command == MSG2_WRONG_VER_LEGACY) // Pre-RoRnet_2.40 server - { - RoRnet::LegacyServerInfo info; - memcpy(&info, buffer, sizeof(RoRnet::LegacyServerInfo)); - Ogre::UTFString format_wstr = _L("Establishing network session: wrong server version, you are using version '%s' and the server is using '%s'"); - const char* server_ver = (info.protocolversion[0] != 0) ? info.protocolversion : "~ RoRnet_2.38 or earlier (not detected) ~"; - char msg_buf[500]; - snprintf(msg_buf, 500, format_wstr.asUTF8_c_str(), RORNET_VERSION, server_ver); - CouldNotConnect(msg_buf); - return false; - } - if (header.command == MSG2_WRONG_VER) - { - CouldNotConnect(_L("server uses a different protocol version")); - return false; - } - if (header.command != MSG2_HELLO) - { - CouldNotConnect(_L("Establishing network session: error getting server hello")); - return false; - } + m_uid = header.source; - // Save server settings - memcpy(&m_server_settings, buffer, sizeof(RoRnet::ServerInfo)); + // we get our userdata back + memcpy(&m_userdata, buffer, std::min(sizeof(RoRnet::UserInfo), header.size)); - if (strncmp(m_server_settings.protocolversion, RORNET_VERSION, strlen(RORNET_VERSION))) - { - wchar_t tmp[512] = L""; - Ogre::UTFString tmp2 = _L("Establishing network session: wrong server version, you are using version '%s' and the server is using '%s'"); - swprintf(tmp, 512, tmp2.asWStr_c_str(), RORNET_VERSION, m_server_settings.protocolversion); - CouldNotConnect(MyGUI::UString(tmp).asUTF8_c_str()); - return false; - } - - FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Authorizing...")); - - // First handshake done, increase the timeout, important! - socket.set_timeout(0, 0); - - // Construct user credentials - // Beware of the wchar_t converted to UTF8 for networking - RoRnet::UserInfo c; - memset(&c, 0, sizeof(RoRnet::UserInfo)); - // Cut off the UTF string on the highest level, otherwise you will break UTF info - strncpy((char *)c.username, m_username.substr(0, RORNET_MAX_USERNAME_LEN * 0.5f).asUTF8_c_str(), RORNET_MAX_USERNAME_LEN); - strncpy(c.serverpassword, Utils::Sha1Hash(m_password.GetBuffer()).c_str(), size_t(40)); - strncpy(c.usertoken, Utils::Sha1Hash(m_token.GetBuffer()).c_str(), size_t(40)); - strncpy(c.clientversion, ROR_VERSION_STRING, strnlen(ROR_VERSION_STRING, 25)); - strncpy(c.clientname, "RoR", 10); - std::string language = std::string(App::app_language.GetActive()).substr(0, 2); - std::string country = std::string(App::app_country.GetActive()).substr(0, 2); - strncpy(c.language, (language + std::string("_") + country).c_str(), 5); - strcpy(c.sessiontype, "normal"); - if (!SendNetMessage(MSG2_USER_INFO, 0, sizeof(RoRnet::UserInfo), (char*)&c)) - { - CouldNotConnect(_L("Establishing network session: error sending user info")); - return false; - } + m_shutdown = false; - // Getting authorization - if (ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH)) - { - CouldNotConnect(_L("Establishing network session: error getting server authorization")); - return false; - } + LOG("[RoR|Networking] Connect(): Creating Send/Recv threads"); + m_send_thread = std::thread(SendThread); + m_recv_thread = std::thread(RecvThread); + FireNetEvent(NetEvent::Type::CONNECT_SUCCESS, ""); - if (header.command==MSG2_FULL) - { - CouldNotConnect(_L("Establishing network session: sorry, server has too many players")); - return false; - } - else if (header.command==MSG2_BANNED) - { - wchar_t tmp[512]; - memset(tmp, 0, 512); - if (strnlen(buffer, 20) > 0) - { - buffer[header.size] = {0}; - Ogre::UTFString tmp2 = _L("Establishing network session: sorry, you are banned:\n%s"); - swprintf(tmp, 512, tmp2.asWStr_c_str(), buffer); - CouldNotConnect(Ogre::UTFString(tmp)); - } - else - { - CouldNotConnect(_L("Establishing network session: sorry, you are banned!")); + return true; } - return false; - } - else if (header.command==MSG2_WRONG_PW) - { - CouldNotConnect(_L("Establishing network session: sorry, wrong password!")); - return false; - } - else if (header.command==MSG2_WRONG_VER) - { - CouldNotConnect(_L("Establishing network session: sorry, wrong protocol version!")); - return false; - } - if (header.command!=MSG2_WELCOME) - { - CouldNotConnect(_L("Establishing network session: sorry, unknown server response")); - return false; - } - - FireNetEvent(NetEvent::Type::CONNECT_PROGRESS, _LC("Network", "Finishing...")); + void Disconnect() + { + LOG("[RoR|Networking] Disconnect() disconnecting..."); + bool is_clean_disconnect = !m_shutdown; // Hacky detection of invalid network state - m_uid = header.source; + m_shutdown = true; // Instruct Send/Recv threads to shut down. - // we get our userdata back - memcpy(&m_userdata, buffer, std::min(sizeof(RoRnet::UserInfo), header.size)); + m_send_packet_available_cv.notify_one(); - m_shutdown = false; + m_send_thread.join(); + LOG("[RoR|Networking] Disconnect() sender thread cleaned up"); - LOG("[RoR|Networking] Connect(): Creating Send/Recv threads"); - m_send_thread = std::thread(SendThread); - m_recv_thread = std::thread(RecvThread); - FireNetEvent(NetEvent::Type::CONNECT_SUCCESS, ""); + socket.set_timeout(1, 0); - return true; -} + if (is_clean_disconnect) { SendNetMessage(MSG2_USER_LEAVE, 0, 0, 0); } -void Disconnect() -{ - LOG("[RoR|Networking] Disconnect() disconnecting..."); - bool is_clean_disconnect = !m_shutdown; // Hacky detection of invalid network state + m_recv_thread.join(); + LOG("[RoR|Networking] Disconnect() receiver thread cleaned up"); - m_shutdown = true; // Instruct Send/Recv threads to shut down. + if (is_clean_disconnect) { socket.disconnect(); } + else + { + socket.close_fd(); + } - m_send_packet_available_cv.notify_one(); + m_users.clear(); + m_recv_packet_buffer.clear(); + m_send_packet_buffer.clear(); - m_send_thread.join(); - LOG("[RoR|Networking] Disconnect() sender thread cleaned up"); + m_shutdown = false; + App::mp_state.SetActive(RoR::MpState::DISABLED); - socket.set_timeout(1, 0); + LOG("[RoR|Networking] Disconnect() done"); + } - if (is_clean_disconnect) - { - SendNetMessage(MSG2_USER_LEAVE, 0, 0, 0); - } + void AddPacket(int streamid, int type, int len, char *content) + { + const auto max_len = RORNET_MAX_MESSAGE_LENGTH - sizeof(RoRnet::Header); + if (len > max_len) + { + LOGSTREAM << "[RoR|Networking] Discarding network packet (StreamID: " << streamid << ", Type: " << type + << "), length is " << len << ", max is " << max_len; + return; + } - m_recv_thread.join(); - LOG("[RoR|Networking] Disconnect() receiver thread cleaned up"); + send_packet_t packet; + memset(&packet, 0, sizeof(send_packet_t)); - if (is_clean_disconnect) - { - socket.disconnect(); - } - else - { - socket.close_fd(); - } + char *buffer = (char *)(packet.buffer); - m_users.clear(); - m_recv_packet_buffer.clear(); - m_send_packet_buffer.clear(); + RoRnet::Header *head = (RoRnet::Header *)buffer; + head->command = type; + head->source = m_uid; + head->size = len; + head->streamid = streamid; - m_shutdown = false; - App::mp_state.SetActive(RoR::MpState::DISABLED); + // then copy the contents + char *bufferContent = (char *)(buffer + sizeof(RoRnet::Header)); + memcpy(bufferContent, content, len); - LOG("[RoR|Networking] Disconnect() done"); -} + // record the packet size + packet.size = len + sizeof(RoRnet::Header); -void AddPacket(int streamid, int type, int len, char *content) -{ - const auto max_len = RORNET_MAX_MESSAGE_LENGTH - sizeof(RoRnet::Header); - if (len > max_len) - { - LOGSTREAM << "[RoR|Networking] Discarding network packet (StreamID: " - < lock(m_send_packetqueue_mutex); + if (type == MSG2_STREAM_DATA_DISCARDABLE) + { + if (m_send_packet_buffer.size() > m_packet_buffer_size) + { + // buffer full, discard unimportant data packets + return; + } + auto search = + std::find_if(m_send_packet_buffer.begin(), m_send_packet_buffer.end(), [&](const send_packet_t &p) { + return !memcmp(packet.buffer, p.buffer, sizeof(RoRnet::Header)); + }); + if (search != m_send_packet_buffer.end()) + { + // Found outdated discardable streamdata -> replace it + (*search) = packet; + m_send_packet_available_cv.notify_one(); + return; + } + } + // DebugPacket("send", head, buffer); + m_send_packet_buffer.push_back(packet); + } - char *buffer = (char*)(packet.buffer); + m_send_packet_available_cv.notify_one(); + } - RoRnet::Header *head = (RoRnet::Header *)buffer; - head->command = type; - head->source = m_uid; - head->size = len; - head->streamid = streamid; + void AddLocalStream(RoRnet::StreamRegister *reg, int size) + { + reg->origin_sourceid = m_uid; + reg->origin_streamid = m_stream_id; + reg->status = 0; - // then copy the contents - char *bufferContent = (char *)(buffer + sizeof(RoRnet::Header)); - memcpy(bufferContent, content, len); + AddPacket(m_stream_id, MSG2_STREAM_REGISTER, size, (char *)reg); + LOG("adding local stream: " + TOSTRING(m_uid) + ":" + TOSTRING(m_stream_id) + ", type: " + TOSTRING(reg->type)); - // record the packet size - packet.size = len + sizeof(RoRnet::Header); + m_stream_id++; + } - { // Lock scope - std::lock_guard lock(m_send_packetqueue_mutex); - if (type == MSG2_STREAM_DATA_DISCARDABLE) + std::vector GetIncomingStreamData() { - if (m_send_packet_buffer.size() > m_packet_buffer_size) - { - // buffer full, discard unimportant data packets - return; - } - auto search = std::find_if(m_send_packet_buffer.begin(), m_send_packet_buffer.end(), - [&](const send_packet_t& p) { return !memcmp(packet.buffer, p.buffer, sizeof(RoRnet::Header)); }); - if (search != m_send_packet_buffer.end()) - { - // Found outdated discardable streamdata -> replace it - (*search) = packet; - m_send_packet_available_cv.notify_one(); - return; - } + std::lock_guard lock(m_recv_packetqueue_mutex); + std::vector buf_copy = m_recv_packet_buffer; + m_recv_packet_buffer.clear(); + return buf_copy; } - //DebugPacket("send", head, buffer); - m_send_packet_buffer.push_back(packet); - } - - m_send_packet_available_cv.notify_one(); -} - -void AddLocalStream(RoRnet::StreamRegister *reg, int size) -{ - reg->origin_sourceid = m_uid; - reg->origin_streamid = m_stream_id; - reg->status = 0; - - AddPacket(m_stream_id, MSG2_STREAM_REGISTER, size, (char*)reg); - LOG("adding local stream: " + TOSTRING(m_uid) + ":"+ TOSTRING(m_stream_id) + ", type: " + TOSTRING(reg->type)); - - m_stream_id++; -} - -std::vector GetIncomingStreamData() -{ - std::lock_guard lock(m_recv_packetqueue_mutex); - std::vector buf_copy = m_recv_packet_buffer; - m_recv_packet_buffer.clear(); - return buf_copy; -} -Ogre::String GetTerrainName() -{ - return m_server_settings.terrain; -} + Ogre::String GetTerrainName() + { + return m_server_settings.terrain; + } -int GetUserColor() -{ - std::lock_guard lock(m_userdata_mutex); - return m_userdata.colournum; -} + int GetUserColor() + { + std::lock_guard lock(m_userdata_mutex); + return m_userdata.colournum; + } -Ogre::UTFString GetUsername() -{ - std::lock_guard lock(m_userdata_mutex); - return m_username; -} + Ogre::UTFString GetUsername() + { + std::lock_guard lock(m_userdata_mutex); + return m_username; + } -RoRnet::UserInfo GetLocalUserData() -{ - std::lock_guard lock(m_userdata_mutex); - return m_userdata; -} + RoRnet::UserInfo GetLocalUserData() + { + std::lock_guard lock(m_userdata_mutex); + return m_userdata; + } -std::vector GetUserInfos() -{ - std::lock_guard lock(m_users_mutex); - return m_users; -} + std::vector GetUserInfos() + { + std::lock_guard lock(m_users_mutex); + return m_users; + } -bool GetUserInfo(int uid, RoRnet::UserInfo &result) -{ - std::lock_guard lock(m_users_mutex); - for (RoRnet::UserInfo user : m_users) - { - if ((int)user.uniqueid == uid) + bool GetUserInfo(int uid, RoRnet::UserInfo &result) { - result = user; - return true; + std::lock_guard lock(m_users_mutex); + for (RoRnet::UserInfo user : m_users) + { + if ((int)user.uniqueid == uid) + { + result = user; + return true; + } + } + return false; } - } - return false; -} -} // namespace Networking + } // namespace Networking } // namespace RoR #endif // USE_SOCKETW diff --git a/source/main/network/Network.h b/source/main/network/Network.h index fe2a51f60b..7b2057df96 100644 --- a/source/main/network/Network.h +++ b/source/main/network/Network.h @@ -23,106 +23,110 @@ #ifdef USE_SOCKETW -#include "Application.h" -#include "RoRnet.h" -#include "RoRPrerequisites.h" + #include "Application.h" + #include "RoRPrerequisites.h" + #include "RoRnet.h" -#include -#include -#include -#include + #include + #include + #include + #include -namespace RoR { -namespace Networking { - -// ----------------------- Network messages (packed) ------------------------- - -#pragma pack(push, 1) - -enum CharacterCmd -{ - CHARACTER_CMD_INVALID, - CHARACTER_CMD_POSITION, - CHARACTER_CMD_ATTACH, - CHARACTER_CMD_DETACH -}; - -struct CharacterMsgGeneric -{ - int32_t command; -}; - -struct CharacterMsgPos -{ - int32_t command; - float pos_x, pos_y, pos_z; - float rot_angle; - float anim_time; - char anim_name[CHARACTER_ANIM_NAME_LEN]; -}; - -struct CharacterMsgAttach -{ - int32_t command; - int32_t source_id; - int32_t stream_id; - int32_t position; -}; - -struct recv_packet_t +namespace RoR { - RoRnet::Header header; - char buffer[RORNET_MAX_MESSAGE_LENGTH]; -}; - -#pragma pack(pop) - -// ------------------------ End of network messages -------------------------- - -struct NetEvent -{ - enum class Type + namespace Networking { - INVALID, - CONNECT_STARTED, - CONNECT_PROGRESS, - CONNECT_SUCCESS, - CONNECT_FAILURE, - SERVER_KICK, - USER_DISCONNECT, - RECV_ERROR, - }; - - NetEvent(Type t, std::string const& msg) :type(t), message(msg) {} - - Type type; - std::string message; -}; - -typedef std::queue < NetEvent, std::list> NetEventQueue; - -bool StartConnecting(); ///< Launches connecting on background. -NetEventQueue CheckEvents(); ///< Processes and returns the event queue. -void Disconnect(); - -void AddPacket(int streamid, int type, int len, char *content); -void AddLocalStream(RoRnet::StreamRegister *reg, int size); - -std::vector GetIncomingStreamData(); - -int GetUID(); -int GetNetQuality(); - -Ogre::String GetTerrainName(); - -int GetUserColor(); -Ogre::UTFString GetUsername(); -RoRnet::UserInfo GetLocalUserData(); -std::vector GetUserInfos(); -bool GetUserInfo(int uid, RoRnet::UserInfo &result); -Ogre::ColourValue GetPlayerColor(int color_num); -} // namespace Networking + // ----------------------- Network messages (packed) ------------------------- + + #pragma pack(push, 1) + + enum CharacterCmd + { + CHARACTER_CMD_INVALID, + CHARACTER_CMD_POSITION, + CHARACTER_CMD_ATTACH, + CHARACTER_CMD_DETACH + }; + + struct CharacterMsgGeneric + { + int32_t command; + }; + + struct CharacterMsgPos + { + int32_t command; + float pos_x, pos_y, pos_z; + float rot_angle; + float anim_time; + char anim_name[CHARACTER_ANIM_NAME_LEN]; + }; + + struct CharacterMsgAttach + { + int32_t command; + int32_t source_id; + int32_t stream_id; + int32_t position; + }; + + struct recv_packet_t + { + RoRnet::Header header; + char buffer[RORNET_MAX_MESSAGE_LENGTH]; + }; + + #pragma pack(pop) + + // ------------------------ End of network messages -------------------------- + + struct NetEvent + { + enum class Type + { + INVALID, + CONNECT_STARTED, + CONNECT_PROGRESS, + CONNECT_SUCCESS, + CONNECT_FAILURE, + SERVER_KICK, + USER_DISCONNECT, + RECV_ERROR, + }; + + NetEvent(Type t, std::string const &msg) : type(t), message(msg) + { + } + + Type type; + std::string message; + }; + + typedef std::queue> NetEventQueue; + + bool StartConnecting(); ///< Launches connecting on background. + NetEventQueue CheckEvents(); ///< Processes and returns the event queue. + void Disconnect(); + + void AddPacket(int streamid, int type, int len, char *content); + void AddLocalStream(RoRnet::StreamRegister *reg, int size); + + std::vector GetIncomingStreamData(); + + int GetUID(); + int GetNetQuality(); + + Ogre::String GetTerrainName(); + + int GetUserColor(); + Ogre::UTFString GetUsername(); + RoRnet::UserInfo GetLocalUserData(); + std::vector GetUserInfos(); + bool GetUserInfo(int uid, RoRnet::UserInfo &result); + Ogre::ColourValue GetPlayerColor(int color_num); + + } // namespace Networking } // namespace RoR #endif // USE_SOCKETW diff --git a/source/main/network/RoRnet.h b/source/main/network/RoRnet.h index 0b09bd72c9..1ba08798a1 100644 --- a/source/main/network/RoRnet.h +++ b/source/main/network/RoRnet.h @@ -21,176 +21,177 @@ #include "BitFlags.h" -namespace RoRnet { - -#define RORNET_MAX_PEERS 64 //!< maximum clients connected at the same time -#define RORNET_MAX_MESSAGE_LENGTH 8192 //!< maximum size of a RoR message. 8192 bytes = 8 kibibytes -#define RORNET_LAN_BROADCAST_PORT 13000 //!< port used to send the broadcast announcement in LAN mode -#define RORNET_MAX_USERNAME_LEN 40 //!< port used to send the broadcast announcement in LAN mode - -#define RORNET_VERSION "RoRnet_2.41" - -enum MessageType -{ - MSG2_HELLO = 1025, //!< client sends its version as first message - - // Hello responses - MSG2_FULL, //!< no more slots for us - MSG2_WRONG_PW, //!< server send that on wrong pw - MSG2_WRONG_VER, //!< wrong version - MSG2_BANNED, //!< client not allowed to join - MSG2_WELCOME, //!< we can proceed - - // Technical - MSG2_VERSION, //!< server responds with its version - MSG2_SERVER_SETTINGS, //!< server send client the terrain name: server_info_t - MSG2_USER_INFO, //!< user data that is sent from the server to the clients - MSG2_MASTERINFO, //!< master information response - MSG2_NETQUALITY, //!< network quality information - - // Gameplay - MSG2_GAME_CMD, //!< Script message. Can be sent in both directions. - MSG2_USER_JOIN, //!< new user joined - MSG2_USER_LEAVE, //!< user leaves - MSG2_UTF8_CHAT, //!< chat line in UTF8 encoding - MSG2_UTF8_PRIVCHAT, //!< private chat line in UTF8 encoding - - // Stream functions - MSG2_STREAM_REGISTER, //!< create new stream - MSG2_STREAM_REGISTER_RESULT, //!< result of a stream creation - MSG2_STREAM_UNREGISTER, //!< remove stream - MSG2_STREAM_DATA, //!< stream data - MSG2_STREAM_DATA_DISCARDABLE, //!< stream data that is allowed to be discarded - - // Legacy values (RoRnet_2.38 and earlier) - MSG2_WRONG_VER_LEGACY = 1003 //!< Wrong version -}; - -enum UserAuth +namespace RoRnet { - AUTH_NONE = 0, //!< no authentication - AUTH_ADMIN = BITMASK(1), //!< admin on the server - AUTH_RANKED = BITMASK(2), //!< ranked status - AUTH_MOD = BITMASK(3), //!< moderator status - AUTH_BOT = BITMASK(4), //!< bot status - AUTH_BANNED = BITMASK(5) //!< banned -}; - -enum Netmask -{ - NETMASK_HORN = BITMASK(1), //!< horn is in use - NETMASK_LIGHTS = BITMASK(2), //!< lights on - NETMASK_BRAKES = BITMASK(3), //!< brake lights on - NETMASK_REVERSE = BITMASK(4), //!< reverse light on - NETMASK_BEACONS = BITMASK(5), //!< beacons on - NETMASK_BLINK_LEFT = BITMASK(6), //!< left blinker on - NETMASK_BLINK_RIGHT = BITMASK(7), //!< right blinker on - NETMASK_BLINK_WARN = BITMASK(8), //!< warn blinker on - NETMASK_CLIGHT1 = BITMASK(9), //!< custom light 1 on - NETMASK_CLIGHT2 = BITMASK(10), //!< custom light 2 on - NETMASK_CLIGHT3 = BITMASK(11), //!< custom light 3 on - NETMASK_CLIGHT4 = BITMASK(12), //!< custom light 4 on - NETMASK_POLICEAUDIO = BITMASK(13), //!< police siren on - NETMASK_PARTICLE = BITMASK(14), //!< custom particles on - NETMASK_PBRAKE = BITMASK(15), //!< custom particles on - NETMASK_TC_ACTIVE = BITMASK(16), //!< traction control light on? - NETMASK_ALB_ACTIVE = BITMASK(17), //!< anti lock brake light on? - NETMASK_ENGINE_CONT = BITMASK(18), //!< ignition on? - NETMASK_ENGINE_RUN = BITMASK(19), //!< engine running? - - NETMASK_ENGINE_MODE_AUTOMATIC = BITMASK(20), //!< engine mode - NETMASK_ENGINE_MODE_SEMIAUTO = BITMASK(21), //!< engine mode - NETMASK_ENGINE_MODE_MANUAL = BITMASK(22), //!< engine mode - NETMASK_ENGINE_MODE_MANUAL_STICK = BITMASK(23), //!< engine mode - NETMASK_ENGINE_MODE_MANUAL_RANGES = BITMASK(24) //!< engine mode -}; - -// -------------------------------- structs ----------------------------------- -// Only use datatypes with defined binary sizes (avoid bool, int, wchar_t...) -// Prefer alignment to 4 or 2 bytes (put int32/float/etc. fields on top) - -#pragma pack(push, 1) -struct Header //!< Common header for every packet -{ - uint32_t command; //!< the command of this packet: MSG2_* - int32_t source; //!< source of this command: 0 = server - uint32_t streamid; //!< streamid for this command - uint32_t size; //!< size of the attached data block -}; +#define RORNET_MAX_PEERS 64 //!< maximum clients connected at the same time +#define RORNET_MAX_MESSAGE_LENGTH 8192 //!< maximum size of a RoR message. 8192 bytes = 8 kibibytes +#define RORNET_LAN_BROADCAST_PORT 13000 //!< port used to send the broadcast announcement in LAN mode +#define RORNET_MAX_USERNAME_LEN 40 //!< port used to send the broadcast announcement in LAN mode + +#define RORNET_VERSION "RoRnet_2.41" + + enum MessageType + { + MSG2_HELLO = 1025, //!< client sends its version as first message + + // Hello responses + MSG2_FULL, //!< no more slots for us + MSG2_WRONG_PW, //!< server send that on wrong pw + MSG2_WRONG_VER, //!< wrong version + MSG2_BANNED, //!< client not allowed to join + MSG2_WELCOME, //!< we can proceed + + // Technical + MSG2_VERSION, //!< server responds with its version + MSG2_SERVER_SETTINGS, //!< server send client the terrain name: server_info_t + MSG2_USER_INFO, //!< user data that is sent from the server to the clients + MSG2_MASTERINFO, //!< master information response + MSG2_NETQUALITY, //!< network quality information + + // Gameplay + MSG2_GAME_CMD, //!< Script message. Can be sent in both directions. + MSG2_USER_JOIN, //!< new user joined + MSG2_USER_LEAVE, //!< user leaves + MSG2_UTF8_CHAT, //!< chat line in UTF8 encoding + MSG2_UTF8_PRIVCHAT, //!< private chat line in UTF8 encoding + + // Stream functions + MSG2_STREAM_REGISTER, //!< create new stream + MSG2_STREAM_REGISTER_RESULT, //!< result of a stream creation + MSG2_STREAM_UNREGISTER, //!< remove stream + MSG2_STREAM_DATA, //!< stream data + MSG2_STREAM_DATA_DISCARDABLE, //!< stream data that is allowed to be discarded + + // Legacy values (RoRnet_2.38 and earlier) + MSG2_WRONG_VER_LEGACY = 1003 //!< Wrong version + }; + + enum UserAuth + { + AUTH_NONE = 0, //!< no authentication + AUTH_ADMIN = BITMASK(1), //!< admin on the server + AUTH_RANKED = BITMASK(2), //!< ranked status + AUTH_MOD = BITMASK(3), //!< moderator status + AUTH_BOT = BITMASK(4), //!< bot status + AUTH_BANNED = BITMASK(5) //!< banned + }; + + enum Netmask + { + NETMASK_HORN = BITMASK(1), //!< horn is in use + NETMASK_LIGHTS = BITMASK(2), //!< lights on + NETMASK_BRAKES = BITMASK(3), //!< brake lights on + NETMASK_REVERSE = BITMASK(4), //!< reverse light on + NETMASK_BEACONS = BITMASK(5), //!< beacons on + NETMASK_BLINK_LEFT = BITMASK(6), //!< left blinker on + NETMASK_BLINK_RIGHT = BITMASK(7), //!< right blinker on + NETMASK_BLINK_WARN = BITMASK(8), //!< warn blinker on + NETMASK_CLIGHT1 = BITMASK(9), //!< custom light 1 on + NETMASK_CLIGHT2 = BITMASK(10), //!< custom light 2 on + NETMASK_CLIGHT3 = BITMASK(11), //!< custom light 3 on + NETMASK_CLIGHT4 = BITMASK(12), //!< custom light 4 on + NETMASK_POLICEAUDIO = BITMASK(13), //!< police siren on + NETMASK_PARTICLE = BITMASK(14), //!< custom particles on + NETMASK_PBRAKE = BITMASK(15), //!< custom particles on + NETMASK_TC_ACTIVE = BITMASK(16), //!< traction control light on? + NETMASK_ALB_ACTIVE = BITMASK(17), //!< anti lock brake light on? + NETMASK_ENGINE_CONT = BITMASK(18), //!< ignition on? + NETMASK_ENGINE_RUN = BITMASK(19), //!< engine running? + + NETMASK_ENGINE_MODE_AUTOMATIC = BITMASK(20), //!< engine mode + NETMASK_ENGINE_MODE_SEMIAUTO = BITMASK(21), //!< engine mode + NETMASK_ENGINE_MODE_MANUAL = BITMASK(22), //!< engine mode + NETMASK_ENGINE_MODE_MANUAL_STICK = BITMASK(23), //!< engine mode + NETMASK_ENGINE_MODE_MANUAL_RANGES = BITMASK(24) //!< engine mode + }; + + // -------------------------------- structs ----------------------------------- + // Only use datatypes with defined binary sizes (avoid bool, int, wchar_t...) + // Prefer alignment to 4 or 2 bytes (put int32/float/etc. fields on top) -struct StreamRegister //!< Sent from the client to server and vice versa, to broadcast a new stream -{ - int32_t type; //!< stream type - int32_t status; //!< initial stream status - int32_t origin_sourceid; //!< origin sourceid - int32_t origin_streamid; //!< origin streamid - char name[128]; //!< the actor filename - char data[128]; //!< data used for stream setup -}; - -struct ActorStreamRegister -{ - int32_t type; //!< stream type - int32_t status; //!< initial stream status - int32_t origin_sourceid; //!< origin sourceid - int32_t origin_streamid; //!< origin streamid - char name[128]; //!< filename - int32_t bufferSize; //!< initial stream status - int32_t time; //!< initial time stamp - char skin[60]; //!< skin - char sectionconfig[60]; //!< section configuration -}; - -struct StreamUnRegister //< sent to remove a stream -{ - uint32_t streamid; -}; +#pragma pack(push, 1) -struct UserInfo -{ - uint32_t uniqueid; //!< user unique id - int32_t authstatus; //!< auth status set by server: AUTH_* - int32_t slotnum; //!< slot number set by server - int32_t colournum; //!< colour set by server - - char username[RORNET_MAX_USERNAME_LEN]; //!< the nickname of the user WIDE CHAR! - char usertoken[40]; //!< user token - char serverpassword[40]; //!< server password - char language[10]; //!< user's language. For example "de-DE" or "en-US" - char clientname[10]; //!< the name and version of the client. For exmaple: "ror" or "gamebot" - char clientversion[25]; //!< a version number of the client. For example 1 for RoR 0.35 - char clientGUID[40]; //!< the clients GUID - char sessiontype[10]; //!< the requested session type. For example "normal", "bot", "rcon" - char sessionoptions[128]; //!< reserved for future options -}; - -struct VehicleState //!< Formerly `oob_t` -{ - int32_t time; //!< time data - float engine_speed; //!< engine RPM - float engine_force; //!< engine acceleration - float engine_clutch; //!< the clutch value - int32_t engine_gear; //!< engine gear - float hydrodirstate; //!< the turning direction status - float brake; //!< the brake value - float wheelspeed; //!< the wheel speed value - uint32_t flagmask; //!< flagmask: NETMASK_* -}; - -struct ServerInfo -{ - char protocolversion[20]; //!< protocol version being used - char terrain[128]; //!< terrain name - char servername[128]; //!< name of the server - uint8_t has_password; //!< passworded server? - char info[4096]; //!< info text -}; - -struct LegacyServerInfo -{ - char protocolversion[20]; //!< protocol version being used -}; + struct Header //!< Common header for every packet + { + uint32_t command; //!< the command of this packet: MSG2_* + int32_t source; //!< source of this command: 0 = server + uint32_t streamid; //!< streamid for this command + uint32_t size; //!< size of the attached data block + }; + + struct StreamRegister //!< Sent from the client to server and vice versa, to broadcast a new stream + { + int32_t type; //!< stream type + int32_t status; //!< initial stream status + int32_t origin_sourceid; //!< origin sourceid + int32_t origin_streamid; //!< origin streamid + char name[128]; //!< the actor filename + char data[128]; //!< data used for stream setup + }; + + struct ActorStreamRegister + { + int32_t type; //!< stream type + int32_t status; //!< initial stream status + int32_t origin_sourceid; //!< origin sourceid + int32_t origin_streamid; //!< origin streamid + char name[128]; //!< filename + int32_t bufferSize; //!< initial stream status + int32_t time; //!< initial time stamp + char skin[60]; //!< skin + char sectionconfig[60]; //!< section configuration + }; + + struct StreamUnRegister //< sent to remove a stream + { + uint32_t streamid; + }; + + struct UserInfo + { + uint32_t uniqueid; //!< user unique id + int32_t authstatus; //!< auth status set by server: AUTH_* + int32_t slotnum; //!< slot number set by server + int32_t colournum; //!< colour set by server + + char username[RORNET_MAX_USERNAME_LEN]; //!< the nickname of the user WIDE CHAR! + char usertoken[40]; //!< user token + char serverpassword[40]; //!< server password + char language[10]; //!< user's language. For example "de-DE" or "en-US" + char clientname[10]; //!< the name and version of the client. For exmaple: "ror" or "gamebot" + char clientversion[25]; //!< a version number of the client. For example 1 for RoR 0.35 + char clientGUID[40]; //!< the clients GUID + char sessiontype[10]; //!< the requested session type. For example "normal", "bot", "rcon" + char sessionoptions[128]; //!< reserved for future options + }; + + struct VehicleState //!< Formerly `oob_t` + { + int32_t time; //!< time data + float engine_speed; //!< engine RPM + float engine_force; //!< engine acceleration + float engine_clutch; //!< the clutch value + int32_t engine_gear; //!< engine gear + float hydrodirstate; //!< the turning direction status + float brake; //!< the brake value + float wheelspeed; //!< the wheel speed value + uint32_t flagmask; //!< flagmask: NETMASK_* + }; + + struct ServerInfo + { + char protocolversion[20]; //!< protocol version being used + char terrain[128]; //!< terrain name + char servername[128]; //!< name of the server + uint8_t has_password; //!< passworded server? + char info[4096]; //!< info text + }; + + struct LegacyServerInfo + { + char protocolversion[20]; //!< protocol version being used + }; } // namespace RoRnet diff --git a/source/main/physics/ApproxMath.h b/source/main/physics/ApproxMath.h index 40ea4a67f9..ac09136968 100644 --- a/source/main/physics/ApproxMath.h +++ b/source/main/physics/ApproxMath.h @@ -34,9 +34,9 @@ inline float frand() mirand *= 16807; - a = (mirand&0x007fffff) | 0x40000000; + a = (mirand & 0x007fffff) | 0x40000000; - return( *((float*)&a) - 2.0f )*0.5f; + return (*((float *)&a) - 2.0f) * 0.5f; } // Returns a random number in the range [0, 2] @@ -46,9 +46,9 @@ inline float frand_02() mirand *= 16807; - a = (mirand&0x007fffff) | 0x40000000; + a = (mirand & 0x007fffff) | 0x40000000; - return( *((float*)&a) - 2.0f ); + return (*((float *)&a) - 2.0f); } // Returns a random number in the range [-1, 1] @@ -58,9 +58,9 @@ inline float frand_11() mirand *= 16807; - a = (mirand&0x007fffff) | 0x40000000; + a = (mirand & 0x007fffff) | 0x40000000; - return( *((float*)&a) - 3.0f ); + return (*((float *)&a) - 3.0f); } // Calculates approximate e^x. @@ -68,11 +68,12 @@ inline float frand_11() inline float approx_exp(const float x) { if (x < -15) - return 0.f ; + return 0.f; else if (x > 88) - return 1e38f ; - else { - int i=12102203*x+1064652319; + return 1e38f; + else + { + int i = 12102203 * x + 1064652319; return *(float *)&i; } } @@ -81,7 +82,7 @@ inline float approx_exp(const float x) // Use it in code not requiring precision inline float approx_pow2(const float x) { - int i = 8388608*x+1065353216; + int i = 8388608 * x + 1065353216; return *(float *)&i; } @@ -91,7 +92,7 @@ inline float approx_pow2(const float x) inline float approx_pow(const float x, const float y) { float v = x; - int i = y * ( (*(int *)&v) - 1065353216) + 1065353216; + int i = y * ((*(int *)&v) - 1065353216) + 1065353216; return *(float *)&i; } @@ -101,7 +102,7 @@ inline float approx_pow(const float x, const float y) inline float approx_sqrt(const float y) { float f = y; - int i = (( (*(int *)&f) - 1065353216)>>1) + 1065353216; + int i = (((*(int *)&f) - 1065353216) >> 1) + 1065353216; return *(float *)&i; } @@ -112,7 +113,7 @@ inline float approx_sqrt(const float y) inline float approx_invSqrt(const float y) { float f = y; - int i = 0x5f3759df - ( (*(int *)&f) >> 1); + int i = 0x5f3759df - ((*(int *)&f) >> 1); return *(float *)&i; } @@ -124,8 +125,8 @@ inline float approx_invSqrt(const float y) inline float fast_invSqrt(const float v) { float y = v; - int i = 0x5f3759df - ( (*(int *)&y) >>1); - y = *(float *)&i; + int i = 0x5f3759df - ((*(int *)&y) >> 1); + y = *(float *)&i; y *= (1.5f - (0.5f * v * y * y)); return y; @@ -145,12 +146,12 @@ inline float sign(const float x) // Ogre3 specific helpers inline Ogre::Vector3 approx_normalise(Ogre::Vector3 v) { - return v*approx_invSqrt(v.squaredLength()); + return v * approx_invSqrt(v.squaredLength()); } inline Ogre::Vector3 fast_normalise(Ogre::Vector3 v) { - return v*fast_invSqrt(v.squaredLength()); + return v * fast_invSqrt(v.squaredLength()); } inline float approx_length(Ogre::Vector3 v) @@ -162,4 +163,3 @@ inline float fast_length(Ogre::Vector3 v) { return fast_sqrt(v.squaredLength()); } - diff --git a/source/main/physics/Beam.cpp b/source/main/physics/Beam.cpp index ca8bc42520..dc2c0d9169 100644 --- a/source/main/physics/Beam.cpp +++ b/source/main/physics/Beam.cpp @@ -109,16 +109,13 @@ Actor::~Actor() ar_autopilot = nullptr; } - if (m_fusealge_airfoil) - delete m_fusealge_airfoil; + if (m_fusealge_airfoil) delete m_fusealge_airfoil; m_fusealge_airfoil = 0; - if (m_replay_handler) - delete m_replay_handler; + if (m_replay_handler) delete m_replay_handler; m_replay_handler = nullptr; - if (ar_vehicle_ai) - delete ar_vehicle_ai; + if (ar_vehicle_ai) delete ar_vehicle_ai; ar_vehicle_ai = 0; // TODO: Make sure we catch everything here @@ -127,8 +124,7 @@ Actor::~Actor() { for (unsigned int i = 0; i < m_deletion_scene_nodes.size(); i++) { - if (!m_deletion_scene_nodes[i]) - continue; + if (!m_deletion_scene_nodes[i]) continue; m_deletion_scene_nodes[i]->removeAndDestroyAllChildren(); gEnv->sceneManager->destroySceneNode(m_deletion_scene_nodes[i]); } @@ -139,8 +135,7 @@ Actor::~Actor() { for (unsigned int i = 0; i < m_deletion_entities.size(); i++) { - if (!m_deletion_entities[i]) - continue; + if (!m_deletion_entities[i]) continue; m_deletion_entities[i]->detachAllObjectsFromBone(); gEnv->sceneManager->destroyEntity(m_deletion_entities[i]->getName()); } @@ -151,8 +146,7 @@ Actor::~Actor() for (int i = 0; i < ar_num_wings; i++) { // flexAirfoil, airfoil - if (ar_wings[i].fa) - delete ar_wings[i].fa; + if (ar_wings[i].fa) delete ar_wings[i].fa; if (ar_wings[i].cnode) { ar_wings[i].cnode->removeAndDestroyAllChildren(); @@ -163,8 +157,7 @@ Actor::~Actor() // delete aeroengines for (int i = 0; i < ar_num_aeroengines; i++) { - if (ar_aeroengines[i]) - delete ar_aeroengines[i]; + if (ar_aeroengines[i]) delete ar_aeroengines[i]; } // delete screwprops @@ -178,7 +171,7 @@ Actor::~Actor() } // delete airbrakes - for (Airbrake* ab: ar_airbrakes) + for (Airbrake *ab : ar_airbrakes) { delete ab; } @@ -199,10 +192,8 @@ Actor::~Actor() ar_flares[i].snode->removeAndDestroyAllChildren(); gEnv->sceneManager->destroySceneNode(ar_flares[i].snode); } - if (ar_flares[i].bbs) - gEnv->sceneManager->destroyBillboardSet(ar_flares[i].bbs); - if (ar_flares[i].light) - gEnv->sceneManager->destroyLight(ar_flares[i].light); + if (ar_flares[i].bbs) gEnv->sceneManager->destroyBillboardSet(ar_flares[i].bbs); + if (ar_flares[i].light) gEnv->sceneManager->destroyLight(ar_flares[i].light); } this->ar_flares.clear(); @@ -239,7 +230,7 @@ Actor::~Actor() } // delete Rails - for (std::vector::iterator it = m_railgroups.begin(); it != m_railgroups.end(); it++) + for (std::vector::iterator it = m_railgroups.begin(); it != m_railgroups.end(); it++) { delete (*it); } @@ -263,19 +254,16 @@ Actor::~Actor() m_inter_point_col_detector = nullptr; } - if (m_transfer_case) - delete m_transfer_case; + if (m_transfer_case) delete m_transfer_case; for (int i = 0; i < m_num_axle_diffs; ++i) { - if (m_axle_diffs[i] != nullptr) - delete m_axle_diffs[i]; + if (m_axle_diffs[i] != nullptr) delete m_axle_diffs[i]; } for (int i = 0; i < m_num_wheel_diffs; ++i) { - if (m_wheel_diffs[i] != nullptr) - delete m_wheel_diffs[i]; + if (m_wheel_diffs[i] != nullptr) delete m_wheel_diffs[i]; } delete ar_nodes; @@ -289,19 +277,18 @@ Actor::~Actor() // the material type and they do not depend on length or scale. void Actor::ScaleActor(float value) { - if (value < 0) - return; + if (value < 0) return; ar_scale *= value; // scale beams for (int i = 0; i < ar_num_beams; i++) { - //ar_beams[i].k *= value; + // ar_beams[i].k *= value; ar_beams[i].d *= value; ar_beams[i].L *= value; ar_beams[i].refL *= value; } // scale hydros - for (hydrobeam_t& hbeam: ar_hydros) + for (hydrobeam_t &hbeam : ar_hydros) { hbeam.hb_ref_length *= value; hbeam.hb_speed *= value; @@ -312,8 +299,8 @@ void Actor::ScaleActor(float value) for (int i = 1; i < ar_num_nodes; i++) { ar_initial_node_positions[i] = refpos + (ar_initial_node_positions[i] - refpos) * value; - ar_nodes[i].AbsPosition = refpos + (ar_nodes[i].AbsPosition - refpos) * value; - ar_nodes[i].RelPosition = relpos + (ar_nodes[i].RelPosition - relpos) * value; + ar_nodes[i].AbsPosition = refpos + (ar_nodes[i].AbsPosition - refpos) * value; + ar_nodes[i].RelPosition = relpos + (ar_nodes[i].RelPosition - relpos) * value; ar_nodes[i].Velocity *= value; ar_nodes[i].Forces *= value; ar_nodes[i].mass *= value; @@ -321,7 +308,6 @@ void Actor::ScaleActor(float value) updateSlideNodePositions(); m_gfx_actor->ScaleActor(relpos, value); - } float Actor::getRotation() @@ -338,10 +324,10 @@ Vector3 Actor::getDirection() Vector3 Actor::getPosition() { - return m_avg_node_position; //the position is already in absolute position + return m_avg_node_position; // the position is already in absolute position } -void Actor::PushNetwork(char* data, int size) +void Actor::PushNetwork(char *data, int size) { NetUpdate update; @@ -353,7 +339,7 @@ void Actor::PushNetwork(char* data, int size) if ((unsigned int)size == (m_net_buffer_size + sizeof(RoRnet::VehicleState))) { // we walk through the incoming data and separate it a bit - char* ptr = data; + char *ptr = data; // put the RoRnet::VehicleState in front, describes actor basics, engine state, flares, etc memcpy(update.veh_state.data(), ptr, sizeof(RoRnet::VehicleState)); @@ -366,7 +352,7 @@ void Actor::PushNetwork(char* data, int size) // then take care of the wheel speeds for (int i = 0; i < ar_num_wheels; i++) { - float wspeed = *(float*)(ptr); + float wspeed = *(float *)(ptr); update.wheel_data[i] = wspeed; ptr += sizeof(float); } @@ -378,18 +364,19 @@ void Actor::PushNetwork(char* data, int size) // Update stream status (remote and local) RoRnet::StreamRegister reg; memset(®, 0, sizeof(RoRnet::StreamRegister)); - reg.status = -2; + reg.status = -2; reg.origin_sourceid = ar_net_source_id; reg.origin_streamid = ar_net_stream_id; strncpy(reg.name, ar_filename.c_str(), 128); - Networking::AddPacket(reg.origin_streamid, RoRnet::MSG2_STREAM_REGISTER_RESULT, - sizeof(RoRnet::StreamRegister), (char *)®); + Networking::AddPacket(reg.origin_streamid, RoRnet::MSG2_STREAM_REGISTER_RESULT, sizeof(RoRnet::StreamRegister), + (char *)®); App::GetSimController()->GetBeamFactory()->AddStreamMismatch(ar_net_source_id, ar_net_stream_id); // Inform the local player RoRnet::UserInfo info; RoR::Networking::GetUserInfo(reg.origin_sourceid, info); - UTFString message = RoR::ChatSystem::GetColouredName(info.username, info.colournum) + RoR::Color::WarningColour + _L(" content mismatch: ") + RoR::Color::NormalColour + reg.name; + UTFString message = RoR::ChatSystem::GetColouredName(info.username, info.colournum) + RoR::Color::WarningColour + + _L(" content mismatch: ") + RoR::Color::NormalColour + reg.name; RoR::App::GetGuiManager()->pushMessageChatBox(message); // Remove self @@ -404,13 +391,11 @@ void Actor::PushNetwork(char* data, int size) // Required to catch up when joining late (since the StreamRegister time stamp is received delayed) if (!m_net_initialized) { - RoRnet::VehicleState* oob = (RoRnet::VehicleState*)update.veh_state.data(); - int tnow = App::GetSimController()->GetBeamFactory()->GetNetTime(); + RoRnet::VehicleState *oob = (RoRnet::VehicleState *)update.veh_state.data(); + int tnow = App::GetSimController()->GetBeamFactory()->GetNetTime(); int rnow = std::max(0, tnow + App::GetSimController()->GetBeamFactory()->GetNetTimeOffset(ar_net_source_id)); if (oob->time > rnow + 100) - { - App::GetSimController()->GetBeamFactory()->UpdateNetTimeOffset(ar_net_source_id, oob->time - rnow); - } + { App::GetSimController()->GetBeamFactory()->UpdateNetTimeOffset(ar_net_source_id, oob->time - rnow); } } m_net_updates.push_back(update); @@ -420,8 +405,7 @@ void Actor::CalcNetwork() { using namespace RoRnet; - if (m_net_updates.size() < 2) - return; + if (m_net_updates.size() < 2) return; int tnow = App::GetSimController()->GetBeamFactory()->GetNetTime(); int rnow = std::max(0, tnow + App::GetSimController()->GetBeamFactory()->GetNetTimeOffset(ar_net_source_id)); @@ -430,18 +414,17 @@ void Actor::CalcNetwork() int index_offset = 0; for (int i = 0; i < m_net_updates.size() - 1; i++) { - VehicleState* oob = (VehicleState*)m_net_updates[i].veh_state.data(); - if (oob->time > rnow) - break; + VehicleState *oob = (VehicleState *)m_net_updates[i].veh_state.data(); + if (oob->time > rnow) break; index_offset = i; } - VehicleState* oob1 = (VehicleState*)m_net_updates[index_offset ].veh_state.data(); - VehicleState* oob2 = (VehicleState*)m_net_updates[index_offset + 1].veh_state.data(); - char* netb1 = (char*) m_net_updates[index_offset ].node_data.data(); - char* netb2 = (char*) m_net_updates[index_offset + 1].node_data.data(); - float* net_rp1 = (float*) m_net_updates[index_offset ].wheel_data.data(); - float* net_rp2 = (float*) m_net_updates[index_offset + 1].wheel_data.data(); + VehicleState *oob1 = (VehicleState *)m_net_updates[index_offset].veh_state.data(); + VehicleState *oob2 = (VehicleState *)m_net_updates[index_offset + 1].veh_state.data(); + char * netb1 = (char *)m_net_updates[index_offset].node_data.data(); + char * netb2 = (char *)m_net_updates[index_offset + 1].node_data.data(); + float * net_rp1 = (float *)m_net_updates[index_offset].wheel_data.data(); + float * net_rp2 = (float *)m_net_updates[index_offset + 1].wheel_data.data(); float tratio = (float)(rnow - oob1->time) / (float)(oob2->time - oob1->time); @@ -459,26 +442,26 @@ void Actor::CalcNetwork() App::GetSimController()->GetBeamFactory()->UpdateNetTimeOffset(ar_net_source_id, +1); } - short* sp1 = (short*)(netb1 + sizeof(float) * 3); - short* sp2 = (short*)(netb2 + sizeof(float) * 3); + short * sp1 = (short *)(netb1 + sizeof(float) * 3); + short * sp2 = (short *)(netb2 + sizeof(float) * 3); Vector3 p1ref = Vector3::ZERO; Vector3 p2ref = Vector3::ZERO; - Vector3 p1 = Vector3::ZERO; - Vector3 p2 = Vector3::ZERO; + Vector3 p1 = Vector3::ZERO; + Vector3 p2 = Vector3::ZERO; for (int i = 0; i < m_net_first_wheel_node; i++) { if (i == 0) { // first node is uncompressed - p1.x = ((float*)netb1)[0]; - p1.y = ((float*)netb1)[1]; - p1.z = ((float*)netb1)[2]; + p1.x = ((float *)netb1)[0]; + p1.y = ((float *)netb1)[1]; + p1.z = ((float *)netb1)[2]; p1ref = p1; - p2.x = ((float*)netb2)[0]; - p2.y = ((float*)netb2)[1]; - p2.z = ((float*)netb2)[2]; + p2.x = ((float *)netb2)[0]; + p2.y = ((float *)netb2)[1]; + p2.z = ((float *)netb2)[2]; p2ref = p2; } else @@ -488,12 +471,12 @@ void Actor::CalcNetwork() p1.x = (float)(sp1[(i - 1) * 3 + 0]) / m_net_node_compression; p1.y = (float)(sp1[(i - 1) * 3 + 1]) / m_net_node_compression; p1.z = (float)(sp1[(i - 1) * 3 + 2]) / m_net_node_compression; - p1 = p1 + p1ref; + p1 = p1 + p1ref; p2.x = (float)(sp2[(i - 1) * 3 + 0]) / m_net_node_compression; p2.y = (float)(sp2[(i - 1) * 3 + 1]) / m_net_node_compression; p2.z = (float)(sp2[(i - 1) * 3 + 2]) / m_net_node_compression; - p2 = p2 + p2ref; + p2 = p2 + p2ref; } // linear interpolation @@ -505,11 +488,12 @@ void Actor::CalcNetwork() for (int i = 0; i < ar_num_wheels; i++) { float rp = net_rp1[i] + tratio * (net_rp2[i] - net_rp1[i]); - //compute ideal positions + // compute ideal positions Vector3 axis = ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition; axis.normalise(); - Plane pplan = Plane(axis, ar_wheels[i].wh_axis_node_0->AbsPosition); - Vector3 ortho = -pplan.projectVector(ar_wheels[i].wh_near_attach_node->AbsPosition) - ar_wheels[i].wh_axis_node_0->AbsPosition; + Plane pplan = Plane(axis, ar_wheels[i].wh_axis_node_0->AbsPosition); + Vector3 ortho = + -pplan.projectVector(ar_wheels[i].wh_near_attach_node->AbsPosition) - ar_wheels[i].wh_axis_node_0->AbsPosition; Vector3 ray = ortho.crossProduct(axis); ray.normalise(); ray *= ar_wheels[i].wh_radius; @@ -540,22 +524,19 @@ void Actor::CalcNetwork() this->UpdateBoundingBoxes(); this->calculateAveragePosition(); - float engspeed = oob1->engine_speed + tratio * (oob2->engine_speed - oob1->engine_speed); - float engforce = oob1->engine_force + tratio * (oob2->engine_force - oob1->engine_force); + float engspeed = oob1->engine_speed + tratio * (oob2->engine_speed - oob1->engine_speed); + float engforce = oob1->engine_force + tratio * (oob2->engine_force - oob1->engine_force); float engclutch = oob1->engine_clutch + tratio * (oob2->engine_clutch - oob1->engine_clutch); float netwspeed = oob1->wheelspeed + tratio * (oob2->wheelspeed - oob1->wheelspeed); - float netbrake = oob1->brake + tratio * (oob2->brake - oob1->brake); + float netbrake = oob1->brake + tratio * (oob2->brake - oob1->brake); ar_hydro_dir_wheel_display = oob1->hydrodirstate; - ar_wheel_speed = netwspeed; + ar_wheel_speed = netwspeed; - int gear = oob1->engine_gear; + int gear = oob1->engine_gear; unsigned int flagmask = oob1->flagmask; - if (ar_engine) - { - SOUND_MODULATE(ar_instance_id, SS_MOD_ENGINE, engspeed); - } + if (ar_engine) { SOUND_MODULATE(ar_instance_id, SS_MOD_ENGINE, engspeed); } if (ar_num_aeroengines > 0) { SOUND_MODULATE(ar_instance_id, SS_MOD_AEROENGINE1, engspeed); @@ -569,11 +550,23 @@ void Actor::CalcNetwork() if (ar_engine) { int automode = -1; - if ((flagmask & NETMASK_ENGINE_MODE_AUTOMATIC) != 0) { automode = static_cast(SimGearboxMode::AUTO); } - else if ((flagmask & NETMASK_ENGINE_MODE_SEMIAUTO) != 0) { automode = static_cast(SimGearboxMode::SEMI_AUTO); } - else if ((flagmask & NETMASK_ENGINE_MODE_MANUAL) != 0) { automode = static_cast(SimGearboxMode::MANUAL); } - else if ((flagmask & NETMASK_ENGINE_MODE_MANUAL_STICK) != 0) { automode = static_cast(SimGearboxMode::MANUAL_STICK); } - else if ((flagmask & NETMASK_ENGINE_MODE_MANUAL_RANGES) != 0) { automode = static_cast(SimGearboxMode::MANUAL_RANGES); } + if ((flagmask & NETMASK_ENGINE_MODE_AUTOMATIC) != 0) { automode = static_cast(SimGearboxMode::AUTO); } + else if ((flagmask & NETMASK_ENGINE_MODE_SEMIAUTO) != 0) + { + automode = static_cast(SimGearboxMode::SEMI_AUTO); + } + else if ((flagmask & NETMASK_ENGINE_MODE_MANUAL) != 0) + { + automode = static_cast(SimGearboxMode::MANUAL); + } + else if ((flagmask & NETMASK_ENGINE_MODE_MANUAL_STICK) != 0) + { + automode = static_cast(SimGearboxMode::MANUAL_STICK); + } + else if ((flagmask & NETMASK_ENGINE_MODE_MANUAL_RANGES) != 0) + { + automode = static_cast(SimGearboxMode::MANUAL_RANGES); + } bool contact = ((flagmask & NETMASK_ENGINE_CONT) != 0); bool running = ((flagmask & NETMASK_ENGINE_RUN) != 0); @@ -582,18 +575,15 @@ void Actor::CalcNetwork() } // set particle cannon - if (((flagmask & NETMASK_PARTICLE) != 0) != m_custom_particles_enabled) - ToggleCustomParticles(); + if (((flagmask & NETMASK_PARTICLE) != 0) != m_custom_particles_enabled) ToggleCustomParticles(); // set lights - if (((flagmask & NETMASK_LIGHTS) != 0) != ar_lights) - ToggleLights(); - if (((flagmask & NETMASK_BEACONS) != 0) != m_beacon_light_is_active) - ToggleBeacons(); + if (((flagmask & NETMASK_LIGHTS) != 0) != ar_lights) ToggleLights(); + if (((flagmask & NETMASK_BEACONS) != 0) != m_beacon_light_is_active) ToggleBeacons(); - m_antilockbrake = flagmask & NETMASK_ALB_ACTIVE; + m_antilockbrake = flagmask & NETMASK_ALB_ACTIVE; m_tractioncontrol = flagmask & NETMASK_TC_ACTIVE; - ar_parking_brake = flagmask & NETMASK_PBRAKE; + ar_parking_brake = flagmask & NETMASK_PBRAKE; blinktype btype = BLINK_NONE; if ((flagmask & NETMASK_BLINK_LEFT) != 0) @@ -609,7 +599,7 @@ void Actor::CalcNetwork() setCustomLightVisible(2, ((flagmask & NETMASK_CLIGHT3) > 0)); setCustomLightVisible(3, ((flagmask & NETMASK_CLIGHT4) > 0)); - m_net_brake_light = ((flagmask & NETMASK_BRAKES) != 0); + m_net_brake_light = ((flagmask & NETMASK_BRAKES) != 0); m_net_reverse_light = ((flagmask & NETMASK_REVERSE) != 0); if ((flagmask & NETMASK_HORN)) @@ -632,8 +622,7 @@ void Actor::CalcNetwork() bool Actor::AddTyrePressure(float v) { - if (!ar_free_pressure_beam) - return false; + if (!ar_free_pressure_beam) return false; float newpressure = Math::Clamp(m_ref_tyre_pressure + v, 0.0f, 100.0f); @@ -642,8 +631,7 @@ bool Actor::AddTyrePressure(float v) ar_beams[ar_pressure_beams[i]].k = 10000 + newpressure * 10000; } - if (newpressure == m_ref_tyre_pressure) - return false; + if (newpressure == m_ref_tyre_pressure) return false; m_ref_tyre_pressure = newpressure; @@ -652,39 +640,33 @@ bool Actor::AddTyrePressure(float v) float Actor::GetTyrePressure() { - if (ar_free_pressure_beam) - return m_ref_tyre_pressure; + if (ar_free_pressure_beam) return m_ref_tyre_pressure; return 0; } void Actor::RecalculateNodeMasses(Real total) { - //reset + // reset for (int i = 0; i < ar_num_nodes; i++) { if (!ar_nodes[i].nd_tyre_node) { - if (!ar_nodes[i].nd_loaded_mass) - { - ar_nodes[i].mass = 0; - } + if (!ar_nodes[i].nd_loaded_mass) { ar_nodes[i].mass = 0; } else if (!ar_nodes[i].nd_override_mass) { ar_nodes[i].mass = m_load_mass / (float)m_masscount; } } } - //average linear density + // average linear density Real len = 0.0f; for (int i = 0; i < ar_num_beams; i++) { if (ar_beams[i].bm_type != BEAM_VIRTUAL) { Real half_newlen = ar_beams[i].L / 2.0; - if (!ar_beams[i].p1->nd_tyre_node) - len += half_newlen; - if (!ar_beams[i].p2->nd_tyre_node) - len += half_newlen; + if (!ar_beams[i].p1->nd_tyre_node) len += half_newlen; + if (!ar_beams[i].p2->nd_tyre_node) len += half_newlen; } } @@ -693,13 +675,11 @@ void Actor::RecalculateNodeMasses(Real total) if (ar_beams[i].bm_type != BEAM_VIRTUAL) { Real half_mass = ar_beams[i].L * total / len / 2.0f; - if (!ar_beams[i].p1->nd_tyre_node) - ar_beams[i].p1->mass += half_mass; - if (!ar_beams[i].p2->nd_tyre_node) - ar_beams[i].p2->mass += half_mass; + if (!ar_beams[i].p1->nd_tyre_node) ar_beams[i].p1->mass += half_mass; + if (!ar_beams[i].p2->nd_tyre_node) ar_beams[i].p2->mass += half_mass; } } - //fix rope masses + // fix rope masses for (std::vector::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++) { it->rp_beam->p2->mass = 100.0f; @@ -712,17 +692,17 @@ void Actor::RecalculateNodeMasses(Real total) ar_nodes[ar_cinecam_node[i]].mass = m_definition->root_module->cinecam[i].node_mass; } - //update mass + // update mass for (int i = 0; i < ar_num_nodes; i++) { - if (!ar_nodes[i].nd_tyre_node && - !(m_definition->minimass_skip_loaded_nodes && ar_nodes[i].nd_loaded_mass) && + if (!ar_nodes[i].nd_tyre_node && !(m_definition->minimass_skip_loaded_nodes && ar_nodes[i].nd_loaded_mass) && ar_nodes[i].mass < ar_minimass[i]) { if (App::diag_truck_mass.GetActive()) { char buf[300]; - snprintf(buf, 300, "Node '%d' mass (%f Kg) is too light. Resetting to 'minimass' (%f Kg)", i, ar_nodes[i].mass, ar_minimass[i]); + snprintf(buf, 300, "Node '%d' mass (%f Kg) is too light. Resetting to 'minimass' (%f Kg)", i, ar_nodes[i].mass, + ar_minimass[i]); LOG(buf); } ar_nodes[i].mass = ar_minimass[i]; @@ -746,13 +726,12 @@ void Actor::RecalculateNodeMasses(Real total) } m_total_mass += ar_nodes[i].mass; } - LOG("TOTAL VEHICLE MASS: " + TOSTRING((int)m_total_mass) +" kg"); + LOG("TOTAL VEHICLE MASS: " + TOSTRING((int)m_total_mass) + " kg"); } float Actor::getTotalMass(bool withLocked) { - if (!withLocked) - return m_total_mass; // already computed in RecalculateNodeMasses + if (!withLocked) return m_total_mass; // already computed in RecalculateNodeMasses float mass = m_total_mass; @@ -764,23 +743,26 @@ float Actor::getTotalMass(bool withLocked) return mass; } -void Actor::DetermineLinkedActors() //TODO: Refactor this - logic iterating over all actors should be in `ActorManager`! ~ only_a_ptr, 01/2018 +void Actor::DetermineLinkedActors() // TODO: Refactor this - logic iterating over all actors should be in `ActorManager`! ~ + // only_a_ptr, 01/2018 { m_linked_actors.clear(); - bool found = true; - std::map lookup_table; - std::pair::iterator, bool> ret; + bool found = true; + std::map lookup_table; + std::pair::iterator, bool> ret; + + lookup_table.insert(std::pair(this, false)); - lookup_table.insert(std::pair(this, false)); - - auto inter_actor_links = App::GetSimController()->GetBeamFactory()->inter_actor_links; // TODO: Shouldn't this have been a reference?? Also, ugly, see the TODO note above ~ only_a_ptr, 01/2018 + auto inter_actor_links = + App::GetSimController()->GetBeamFactory()->inter_actor_links; // TODO: Shouldn't this have been a reference?? Also, ugly, + // see the TODO note above ~ only_a_ptr, 01/2018 while (found) { found = false; - for (std::map::iterator it_beam = lookup_table.begin(); it_beam != lookup_table.end(); ++it_beam) + for (std::map::iterator it_beam = lookup_table.begin(); it_beam != lookup_table.end(); ++it_beam) { if (!it_beam->second) { @@ -791,7 +773,7 @@ void Actor::DetermineLinkedActors() //TODO: Refactor this - logic iterating over if (actor == actor_pair.first || actor == actor_pair.second) { auto other_actor = (actor != actor_pair.first) ? actor_pair.first : actor_pair.second; - ret = lookup_table.insert(std::pair(other_actor, false)); + ret = lookup_table.insert(std::pair(other_actor, false)); if (ret.second) { m_linked_actors.push_back(other_actor); @@ -829,14 +811,13 @@ void Actor::calcNodeConnectivityGraph() } } -bool Actor::Intersects(Actor* actor, Vector3 offset) +bool Actor::Intersects(Actor *actor, Vector3 offset) { - Vector3 bb_min = ar_bounding_box.getMinimum() + offset; - Vector3 bb_max = ar_bounding_box.getMaximum() + offset; - AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max); + Vector3 bb_min = ar_bounding_box.getMinimum() + offset; + Vector3 bb_max = ar_bounding_box.getMaximum() + offset; + AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max); - if (!bb.intersects(actor->ar_bounding_box)) - return false; + if (!bb.intersects(actor->ar_bounding_box)) return false; // Test own (contactable) beams against others cabs for (int i = 0; i < ar_num_beams; i++) @@ -852,16 +833,13 @@ bool Actor::Intersects(Actor* actor, Vector3 offset) for (int j = 0; j < actor->ar_num_collcabs; j++) { - int index = actor->ar_collcabs[j] * 3; - Vector3 a = actor->ar_nodes[actor->ar_cabs[index + 0]].AbsPosition; - Vector3 b = actor->ar_nodes[actor->ar_cabs[index + 1]].AbsPosition; - Vector3 c = actor->ar_nodes[actor->ar_cabs[index + 2]].AbsPosition; + int index = actor->ar_collcabs[j] * 3; + Vector3 a = actor->ar_nodes[actor->ar_cabs[index + 0]].AbsPosition; + Vector3 b = actor->ar_nodes[actor->ar_cabs[index + 1]].AbsPosition; + Vector3 c = actor->ar_nodes[actor->ar_cabs[index + 2]].AbsPosition; auto result = Ogre::Math::intersects(ray, a, b, c); - if (result.first && result.second < 1.0f) - { - return true; - } + if (result.first && result.second < 1.0f) { return true; } } } @@ -879,16 +857,13 @@ bool Actor::Intersects(Actor* actor, Vector3 offset) for (int j = 0; j < ar_num_collcabs; j++) { - int index = ar_collcabs[j] * 3; - Vector3 a = ar_nodes[ar_cabs[index + 0]].AbsPosition + offset; - Vector3 b = ar_nodes[ar_cabs[index + 1]].AbsPosition + offset; - Vector3 c = ar_nodes[ar_cabs[index + 2]].AbsPosition + offset; + int index = ar_collcabs[j] * 3; + Vector3 a = ar_nodes[ar_cabs[index + 0]].AbsPosition + offset; + Vector3 b = ar_nodes[ar_cabs[index + 1]].AbsPosition + offset; + Vector3 c = ar_nodes[ar_cabs[index + 2]].AbsPosition + offset; auto result = Ogre::Math::intersects(ray, a, b, c); - if (result.first && result.second < 1.0f) - { - return true; - } + if (result.first && result.second < 1.0f) { return true; } } } @@ -897,8 +872,7 @@ bool Actor::Intersects(Actor* actor, Vector3 offset) Vector3 Actor::calculateCollisionOffset(Vector3 direction) { - if (direction == Vector3::ZERO) - return Vector3::ZERO; + if (direction == Vector3::ZERO) return Vector3::ZERO; Real max_distance = direction.normalise(); @@ -907,40 +881,34 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction) while (collision_offset.length() < max_distance) { - Vector3 bb_min = ar_bounding_box.getMinimum() + collision_offset; - Vector3 bb_max = ar_bounding_box.getMaximum() + collision_offset; - AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max); + Vector3 bb_min = ar_bounding_box.getMinimum() + collision_offset; + Vector3 bb_max = ar_bounding_box.getMaximum() + collision_offset; + AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max); bool collision = false; for (auto actor : App::GetSimController()->GetActors()) { - if (actor == this) - continue; - if (!bb.intersects(actor->ar_bounding_box)) - continue; + if (actor == this) continue; + if (!bb.intersects(actor->ar_bounding_box)) continue; // Test own contactables against others cabs if (m_intra_point_col_detector) { for (int i = 0; i < actor->ar_num_collcabs; i++) { - int tmpv = actor->ar_collcabs[i] * 3; - node_t* no = &actor->ar_nodes[actor->ar_cabs[tmpv]]; - node_t* na = &actor->ar_nodes[actor->ar_cabs[tmpv + 1]]; - node_t* nb = &actor->ar_nodes[actor->ar_cabs[tmpv + 2]]; - - m_intra_point_col_detector->query(no->AbsPosition - collision_offset, - na->AbsPosition - collision_offset, - nb->AbsPosition - collision_offset, - actor->ar_collision_range * 3.0f); - - if (collision = !m_intra_point_col_detector->hit_list.empty()) - break; + int tmpv = actor->ar_collcabs[i] * 3; + node_t *no = &actor->ar_nodes[actor->ar_cabs[tmpv]]; + node_t *na = &actor->ar_nodes[actor->ar_cabs[tmpv + 1]]; + node_t *nb = &actor->ar_nodes[actor->ar_cabs[tmpv + 2]]; + + m_intra_point_col_detector->query(no->AbsPosition - collision_offset, na->AbsPosition - collision_offset, + nb->AbsPosition - collision_offset, actor->ar_collision_range * 3.0f); + + if (collision = !m_intra_point_col_detector->hit_list.empty()) break; } - if (collision) - break; + if (collision) break; } float proximity = std::max(.05f, std::sqrt(std::max(m_min_camera_radius, actor->m_min_camera_radius)) / 50.f); @@ -948,26 +916,21 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction) // Test proximity of own nodes against others nodes for (int i = 0; i < ar_num_nodes; i++) { - if (!ar_nodes[i].nd_contacter && !ar_nodes[i].nd_contactable) - continue; + if (!ar_nodes[i].nd_contacter && !ar_nodes[i].nd_contactable) continue; Vector3 query_position = ar_nodes[i].AbsPosition + collision_offset; for (int j = 0; j < actor->ar_num_nodes; j++) { - if (!actor->ar_nodes[j].nd_contacter && !actor->ar_nodes[j].nd_contactable) - continue; + if (!actor->ar_nodes[j].nd_contacter && !actor->ar_nodes[j].nd_contactable) continue; - if (collision = query_position.squaredDistance(actor->ar_nodes[j].AbsPosition) < proximity) - break; + if (collision = query_position.squaredDistance(actor->ar_nodes[j].AbsPosition) < proximity) break; } - if (collision) - break; + if (collision) break; } - if (collision) - break; + if (collision) break; } // Test own cabs against others contacters @@ -975,18 +938,15 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction) { for (int i = 0; i < ar_num_collcabs; i++) { - int tmpv = ar_collcabs[i] * 3; - node_t* no = &ar_nodes[ar_cabs[tmpv]]; - node_t* na = &ar_nodes[ar_cabs[tmpv + 1]]; - node_t* nb = &ar_nodes[ar_cabs[tmpv + 2]]; - - m_inter_point_col_detector->query(no->AbsPosition + collision_offset, - na->AbsPosition + collision_offset, - nb->AbsPosition + collision_offset, - ar_collision_range * 3.0f); - - if (collision = !m_inter_point_col_detector->hit_list.empty()) - break; + int tmpv = ar_collcabs[i] * 3; + node_t *no = &ar_nodes[ar_cabs[tmpv]]; + node_t *na = &ar_nodes[ar_cabs[tmpv + 1]]; + node_t *nb = &ar_nodes[ar_cabs[tmpv + 2]]; + + m_inter_point_col_detector->query(no->AbsPosition + collision_offset, na->AbsPosition + collision_offset, + nb->AbsPosition + collision_offset, ar_collision_range * 3.0f); + + if (collision = !m_inter_point_col_detector->hit_list.empty()) break; } } @@ -995,15 +955,12 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction) { for (auto actor : App::GetSimController()->GetActors()) { - if (actor == this) - continue; - if (collision = this->Intersects(actor, collision_offset)) - break; + if (actor == this) continue; + if (collision = this->Intersects(actor, collision_offset)) break; } } - if (!collision) - break; + if (!collision) break; collision_offset += direction * 0.05f; } @@ -1013,42 +970,38 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction) void Actor::resolveCollisions(Vector3 direction) { - if (m_intra_point_col_detector) - m_intra_point_col_detector->UpdateIntraPoint(true); + if (m_intra_point_col_detector) m_intra_point_col_detector->UpdateIntraPoint(true); - if (m_inter_point_col_detector) - m_inter_point_col_detector->UpdateInterPoint(true); + if (m_inter_point_col_detector) m_inter_point_col_detector->UpdateInterPoint(true); Vector3 offset = calculateCollisionOffset(direction); - if (offset == Vector3::ZERO) - return; + if (offset == Vector3::ZERO) return; // Additional 20 cm safe-guard (horizontally) offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy(); - ResetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z, false, this->GetMinHeight() + offset.y); + ResetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z, false, + this->GetMinHeight() + offset.y); } void Actor::resolveCollisions(float max_distance, bool consider_up) { - if (m_intra_point_col_detector) - m_intra_point_col_detector->UpdateIntraPoint(true); + if (m_intra_point_col_detector) m_intra_point_col_detector->UpdateIntraPoint(true); - if (m_inter_point_col_detector) - m_inter_point_col_detector->UpdateInterPoint(true); + if (m_inter_point_col_detector) m_inter_point_col_detector->UpdateInterPoint(true); Vector3 u = Vector3::UNIT_Y; Vector3 f = Vector3(getDirection().x, 0.0f, getDirection().z).normalisedCopy(); Vector3 l = u.crossProduct(f); // Calculate an ideal collision avoidance direction (prefer left over right over [front / back / up]) - Vector3 left = calculateCollisionOffset(+l * max_distance); - Vector3 right = calculateCollisionOffset(-l * left.length()); + Vector3 left = calculateCollisionOffset(+l * max_distance); + Vector3 right = calculateCollisionOffset(-l * left.length()); Vector3 lateral = left.length() < right.length() * 1.1f ? left : right; - Vector3 front = calculateCollisionOffset(+f * lateral.length()); - Vector3 back = calculateCollisionOffset(-f * front.length()); + Vector3 front = calculateCollisionOffset(+f * lateral.length()); + Vector3 back = calculateCollisionOffset(-f * front.length()); Vector3 sagittal = front.length() < back.length() * 1.1f ? front : back; Vector3 offset = lateral.length() < sagittal.length() * 1.2f ? lateral : sagittal; @@ -1056,26 +1009,22 @@ void Actor::resolveCollisions(float max_distance, bool consider_up) if (consider_up) { Vector3 up = calculateCollisionOffset(+u * offset.length()); - if (up.length() * 1.2f < offset.length()) - offset = up; + if (up.length() * 1.2f < offset.length()) offset = up; } - if (offset == Vector3::ZERO) - return; + if (offset == Vector3::ZERO) return; // Additional 20 cm safe-guard (horizontally) offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy(); - ResetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z, true, this->GetMinHeight() + offset.y); + ResetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z, true, + this->GetMinHeight() + offset.y); } void Actor::calculateAveragePosition() { // calculate average position - if (ar_custom_camera_node >= 0) - { - m_avg_node_position = ar_nodes[ar_custom_camera_node].AbsPosition; - } + if (ar_custom_camera_node >= 0) { m_avg_node_position = ar_nodes[ar_custom_camera_node].AbsPosition; } else if (ar_extern_camera_mode == 1 && ar_num_cinecams > 0) { // the new (strange) approach: reuse the cinecam node @@ -1098,7 +1047,7 @@ void Actor::calculateAveragePosition() } } -inline void PadBoundingBox(Ogre::AxisAlignedBox& box) // Internal helper +inline void PadBoundingBox(Ogre::AxisAlignedBox &box) // Internal helper { box.setMinimum(box.getMinimum() - BOUNDING_BOX_PADDING); box.setMaximum(box.getMaximum() + BOUNDING_BOX_PADDING); @@ -1107,11 +1056,11 @@ inline void PadBoundingBox(Ogre::AxisAlignedBox& box) // Internal helper void Actor::UpdateBoundingBoxes() { // Reset - ar_bounding_box = AxisAlignedBox::BOX_NULL; + ar_bounding_box = AxisAlignedBox::BOX_NULL; ar_predicted_bounding_box = AxisAlignedBox::BOX_NULL; for (size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i) { - ar_collision_bounding_boxes[i] = AxisAlignedBox::BOX_NULL; + ar_collision_bounding_boxes[i] = AxisAlignedBox::BOX_NULL; ar_predicted_coll_bounding_boxes[i] = AxisAlignedBox::BOX_NULL; } @@ -1122,9 +1071,9 @@ void Actor::UpdateBoundingBoxes() Vector3 pos = ar_nodes[i].AbsPosition; int16_t cid = ar_nodes[i].nd_coll_bbox_id; - ar_bounding_box.merge(pos); // Current box - ar_predicted_bounding_box.merge(pos); // Predicted box (current position) - ar_predicted_bounding_box.merge(pos + vel); // Predicted box (future position) + ar_bounding_box.merge(pos); // Current box + ar_predicted_bounding_box.merge(pos); // Predicted box (current position) + ar_predicted_bounding_box.merge(pos + vel); // Predicted box (future position) if (cid != node_t::INVALID_BBOX) { ar_collision_bounding_boxes[cid].merge(pos); @@ -1199,13 +1148,10 @@ void Actor::ResetPosition(float px, float pz, bool setInitPosition, float miny) // vertical displacement float vertical_offset = miny - this->GetMinHeight(); if (App::GetSimTerrain()->getWater()) - { - vertical_offset += std::max(0.0f, App::GetSimTerrain()->getWater()->GetStaticWaterHeight() - miny); - } + { vertical_offset += std::max(0.0f, App::GetSimTerrain()->getWater()->GetStaticWaterHeight() - miny); } for (int i = 1; i < ar_num_nodes; i++) { - if (ar_nodes[i].nd_no_ground_contact) - continue; + if (ar_nodes[i].nd_no_ground_contact) continue; float terrainHeight = App::GetSimTerrain()->GetHeightAt(ar_nodes[i].AbsPosition.x, ar_nodes[i].AbsPosition.z); vertical_offset += std::max(0.0f, terrainHeight - (ar_nodes[i].AbsPosition.y + vertical_offset)); } @@ -1219,10 +1165,8 @@ void Actor::ResetPosition(float px, float pz, bool setInitPosition, float miny) float mesh_offset = 0.0f; for (int i = 0; i < ar_num_nodes; i++) { - if (mesh_offset >= 1.0f) - break; - if (ar_nodes[i].nd_no_ground_contact) - continue; + if (mesh_offset >= 1.0f) break; + if (ar_nodes[i].nd_no_ground_contact) continue; float offset = mesh_offset; while (offset < 1.0f) { @@ -1271,9 +1215,9 @@ void Actor::ResetPosition(Vector3 translation, bool setInitPosition) void Actor::HandleMouseMove(int node, Vector3 pos, float force) { - m_mouse_grab_node = node; + m_mouse_grab_node = node; m_mouse_grab_move_force = force * std::pow(m_total_mass / 3000.0f, 0.75f); - m_mouse_grab_pos = pos; + m_mouse_grab_pos = pos; } void Actor::ToggleWheelDiffMode() @@ -1297,9 +1241,9 @@ void Actor::DisplayAxleDiffMode() if (m_num_axle_diffs == 0) { App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - _L("No inter-axle differential installed on current vehicle!"), "warning.png", 3000); + _L("No inter-axle differential installed on current vehicle!"), "warning.png", 3000); App::GetGuiManager()->PushNotification("Inter-axle differentials:", - _L("No inter-axle differential installed on current vehicle!")); + _L("No inter-axle differential installed on current vehicle!")); } else { @@ -1316,7 +1260,7 @@ void Actor::DisplayAxleDiffMode() } } App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - "Inter-axle differentials:\n" + message, "cog.png", 3000); + "Inter-axle differentials:\n" + message, "cog.png", 3000); App::GetGuiManager()->PushNotification("Inter-axle differentials:", message); } } @@ -1326,9 +1270,9 @@ void Actor::DisplayWheelDiffMode() if (m_num_wheel_diffs == 0) { App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - _L("No inter-wheel differential installed on current vehicle!"), "warning.png", 3000); + _L("No inter-wheel differential installed on current vehicle!"), "warning.png", 3000); App::GetGuiManager()->PushNotification("Inter-wheel differentials:", - _L("No inter-wheel differential installed on current vehicle!")); + _L("No inter-wheel differential installed on current vehicle!")); } else { @@ -1343,7 +1287,7 @@ void Actor::DisplayWheelDiffMode() } } App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - "Inter-wheel differentials:\n" + message, "cog.png", 3000); + "Inter-wheel differentials:\n" + message, "cog.png", 3000); App::GetGuiManager()->PushNotification("Inter-wheel differentials:", message); } } @@ -1353,29 +1297,27 @@ void Actor::DisplayTransferCaseMode() if (m_transfer_case) { App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - _L("Transfercase switched to: ") + this->GetTransferCaseName(), "cog.png", 3000); + _L("Transfercase switched to: ") + this->GetTransferCaseName(), "cog.png", 3000); App::GetGuiManager()->PushNotification("Transfercase:", "Switched to: " + this->GetTransferCaseName()); } else { App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - _L("No transfercase installed on current vehicle!"), "warning.png", 3000); + _L("No transfercase installed on current vehicle!"), "warning.png", 3000); App::GetGuiManager()->PushNotification("Transfercase:", "No transfercase installed on current vehicle!"); } } void Actor::ToggleTransferCaseMode() { - if (!ar_engine || !m_transfer_case || m_transfer_case->tr_ax_2 < 0 || !m_transfer_case->tr_2wd) - return; + if (!ar_engine || !m_transfer_case || m_transfer_case->tr_ax_2 < 0 || !m_transfer_case->tr_2wd) return; if (m_transfer_case->tr_4wd_mode && !m_transfer_case->tr_2wd_lo) { for (int i = 0; i < m_transfer_case->tr_gear_ratios.size(); i++) { this->ToggleTransferCaseGearRatio(); - if (m_transfer_case->tr_gear_ratios[0] == 1.0f) - break; + if (m_transfer_case->tr_gear_ratios[0] == 1.0f) break; } } @@ -1397,8 +1339,7 @@ void Actor::ToggleTransferCaseMode() void Actor::ToggleTransferCaseGearRatio() { - if (!ar_engine || !m_transfer_case || m_transfer_case->tr_gear_ratios.size() < 2) - return; + if (!ar_engine || !m_transfer_case || m_transfer_case->tr_gear_ratios.size() < 2) return; if (m_transfer_case->tr_4wd_mode || m_transfer_case->tr_2wd_lo) { @@ -1425,13 +1366,13 @@ String Actor::GetTransferCaseName() Ogre::Vector3 Actor::GetRotationCenter() { - Vector3 sum = Vector3::ZERO; + Vector3 sum = Vector3::ZERO; std::vector positions; for (int i = 0; i < ar_num_nodes; i++) { - Vector3 pos = ar_nodes[i].AbsPosition; - const auto it = std::find_if(positions.begin(), positions.end(), - [pos](const Vector3 ref) { return pos.positionEquals(ref, 0.01f); }); + Vector3 pos = ar_nodes[i].AbsPosition; + const auto it = + std::find_if(positions.begin(), positions.end(), [pos](const Vector3 ref) { return pos.positionEquals(ref, 0.01f); }); if (it == positions.end()) { sum += pos; @@ -1443,39 +1384,33 @@ Ogre::Vector3 Actor::GetRotationCenter() float Actor::GetMinHeight(bool skip_virtual_nodes) { - float height = std::numeric_limits::max(); + float height = std::numeric_limits::max(); for (int i = 0; i < ar_num_nodes; i++) { - if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact) - { - height = std::min(ar_nodes[i].AbsPosition.y, height); - } + if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact) { height = std::min(ar_nodes[i].AbsPosition.y, height); } } return (!skip_virtual_nodes || height < std::numeric_limits::max()) ? height : GetMinHeight(false); } float Actor::GetMaxHeight(bool skip_virtual_nodes) { - float height = std::numeric_limits::min(); + float height = std::numeric_limits::min(); for (int i = 0; i < ar_num_nodes; i++) { - if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact) - { - height = std::max(height, ar_nodes[i].AbsPosition.y); - } + if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact) { height = std::max(height, ar_nodes[i].AbsPosition.y); } } return (!skip_virtual_nodes || height > std::numeric_limits::min()) ? height : GetMaxHeight(false); } float Actor::GetHeightAboveGround(bool skip_virtual_nodes) { - float agl = std::numeric_limits::max(); + float agl = std::numeric_limits::max(); for (int i = 0; i < ar_num_nodes; i++) { if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact) { Vector3 pos = ar_nodes[i].AbsPosition; - agl = std::min(pos.y - gEnv->collisions->getSurfaceHeight(pos.x, pos.z), agl); + agl = std::min(pos.y - gEnv->collisions->getSurfaceHeight(pos.x, pos.z), agl); } } return (!skip_virtual_nodes || agl < std::numeric_limits::max()) ? agl : GetHeightAboveGround(false); @@ -1483,13 +1418,13 @@ float Actor::GetHeightAboveGround(bool skip_virtual_nodes) float Actor::GetHeightAboveGroundBelow(float height, bool skip_virtual_nodes) { - float agl = std::numeric_limits::max(); + float agl = std::numeric_limits::max(); for (int i = 0; i < ar_num_nodes; i++) { if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact) { Vector3 pos = ar_nodes[i].AbsPosition; - agl = std::min(pos.y - gEnv->collisions->getSurfaceHeightBelow(pos.x, pos.z, height), agl); + agl = std::min(pos.y - gEnv->collisions->getSurfaceHeightBelow(pos.x, pos.z, height), agl); } } return (!skip_virtual_nodes || agl < std::numeric_limits::max()) ? agl : GetHeightAboveGroundBelow(height, false); @@ -1502,9 +1437,7 @@ void Actor::SoftReset() float agl = this->GetHeightAboveGroundBelow(this->GetMaxHeight(true), true); if (App::GetSimTerrain()->getWater()) - { - agl = std::min(this->GetMinHeight(true) - App::GetSimTerrain()->getWater()->GetStaticWaterHeight(), agl); - } + { agl = std::min(this->GetMinHeight(true) - App::GetSimTerrain()->getWater()->GetStaticWaterHeight(), agl); } if (agl < 0.0f) { @@ -1528,101 +1461,98 @@ void Actor::SyncReset(bool reset_position) m_camera_local_gforces_cur = Vector3::ZERO; m_camera_local_gforces_max = Vector3::ZERO; - ar_hydro_dir_state = 0.0; - ar_hydro_aileron_state = 0.0; - ar_hydro_rudder_state = 0.0; - ar_hydro_elevator_state = 0.0; + ar_hydro_dir_state = 0.0; + ar_hydro_aileron_state = 0.0; + ar_hydro_rudder_state = 0.0; + ar_hydro_elevator_state = 0.0; ar_hydro_dir_wheel_display = 0.0; - - ar_fusedrag = Vector3::ZERO; - m_blink_type = BLINK_NONE; - ar_parking_brake = false; + + ar_fusedrag = Vector3::ZERO; + m_blink_type = BLINK_NONE; + ar_parking_brake = false; ar_trailer_parking_brake = false; - ar_avg_wheel_speed = 0.0f; - ar_wheel_speed = 0.0f; - ar_wheel_spin = 0.0f; - cc_mode = false; + ar_avg_wheel_speed = 0.0f; + ar_wheel_speed = 0.0f; + ar_wheel_spin = 0.0f; + cc_mode = false; - ar_origin = Vector3::ZERO; - float cur_rot = getRotation(); + ar_origin = Vector3::ZERO; + float cur_rot = getRotation(); Vector3 cur_position = ar_nodes[0].AbsPosition; for (int i = 0; i < ar_num_nodes; i++) { ar_nodes[i].AbsPosition = ar_initial_node_positions[i]; ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin; - ar_nodes[i].Velocity = Vector3::ZERO; - ar_nodes[i].Forces = Vector3::ZERO; + ar_nodes[i].Velocity = Vector3::ZERO; + ar_nodes[i].Forces = Vector3::ZERO; } for (int i = 0; i < ar_num_beams; i++) { - ar_beams[i].maxposstress = ar_beams[i].default_beam_deform; - ar_beams[i].maxnegstress = -ar_beams[i].default_beam_deform; + ar_beams[i].maxposstress = ar_beams[i].default_beam_deform; + ar_beams[i].maxnegstress = -ar_beams[i].default_beam_deform; ar_beams[i].minmaxposnegstress = ar_beams[i].default_beam_deform; - ar_beams[i].strength = ar_beams[i].initial_beam_strength; - ar_beams[i].L = ar_beams[i].refL; - ar_beams[i].stress = 0.0; - ar_beams[i].bm_broken = false; - ar_beams[i].bm_disabled = false; + ar_beams[i].strength = ar_beams[i].initial_beam_strength; + ar_beams[i].L = ar_beams[i].refL; + ar_beams[i].stress = 0.0; + ar_beams[i].bm_broken = false; + ar_beams[i].bm_disabled = false; } this->ApplyNodeBeamScales(); this->DisjoinInterActorBeams(); - for (auto& h : ar_hooks) + for (auto &h : ar_hooks) { - h.hk_locked = UNLOCKED; - h.hk_lock_node = nullptr; - h.hk_locked_actor = nullptr; - h.hk_beam->p2 = &ar_nodes[0]; - h.hk_beam->bm_disabled = true; + h.hk_locked = UNLOCKED; + h.hk_lock_node = nullptr; + h.hk_locked_actor = nullptr; + h.hk_beam->p2 = &ar_nodes[0]; + h.hk_beam->bm_disabled = true; h.hk_beam->bm_inter_actor = false; - h.hk_beam->L = (ar_nodes[0].AbsPosition - h.hk_hook_node->AbsPosition).length(); + h.hk_beam->L = (ar_nodes[0].AbsPosition - h.hk_hook_node->AbsPosition).length(); this->RemoveInterActorBeam(h.hk_beam); } - for (auto& r : ar_ropes) + for (auto &r : ar_ropes) { - r.rp_locked = UNLOCKED; + r.rp_locked = UNLOCKED; r.rp_locked_ropable = nullptr; - r.rp_locked_actor = nullptr; + r.rp_locked_actor = nullptr; this->RemoveInterActorBeam(r.rp_beam); } - for (auto& t : ar_ties) + for (auto &t : ar_ties) { - t.ti_tied = false; - t.ti_tying = false; - t.ti_locked_actor = nullptr; - t.ti_locked_ropable = nullptr; - t.ti_beam->p2 = &ar_nodes[0]; - t.ti_beam->bm_disabled = true; + t.ti_tied = false; + t.ti_tying = false; + t.ti_locked_actor = nullptr; + t.ti_locked_ropable = nullptr; + t.ti_beam->p2 = &ar_nodes[0]; + t.ti_beam->bm_disabled = true; t.ti_beam->bm_inter_actor = false; this->RemoveInterActorBeam(t.ti_beam); } - for (auto& r : ar_ropables) + for (auto &r : ar_ropables) { - r.attached_ties = 0; + r.attached_ties = 0; r.attached_ropes = 0; } for (int i = 0; i < ar_num_wheels; i++) { - ar_wheels[i].wh_speed = 0.0; - ar_wheels[i].wh_torque = 0.0; - ar_wheels[i].wh_avg_speed = 0.0; + ar_wheels[i].wh_speed = 0.0; + ar_wheels[i].wh_torque = 0.0; + ar_wheels[i].wh_avg_speed = 0.0; ar_wheels[i].wh_is_detached = false; } if (ar_engine) { - if (App::sim_spawn_running.GetActive()) - { - ar_engine->StartEngine(); - } + if (App::sim_spawn_running.GetActive()) { ar_engine->StartEngine(); } ar_engine->SetWheelSpin(0.0f); } @@ -1639,12 +1569,10 @@ void Actor::SyncReset(bool reset_position) ar_rotators[i].angle = 0.0; for (int i = 0; i < ar_num_wings; i++) ar_wings[i].fa->broken = false; - if (ar_autopilot) - this->ar_autopilot->reset(); - if (m_buoyance) - m_buoyance->sink = false; + if (ar_autopilot) this->ar_autopilot->reset(); + if (m_buoyance) m_buoyance->sink = false; - for (hydrobeam_t& hydrobeam: ar_hydros) + for (hydrobeam_t &hydrobeam : ar_hydros) { hydrobeam.hb_inertia.ResetCmdKeyDelay(); } @@ -1658,13 +1586,8 @@ void Actor::SyncReset(bool reset_position) this->ResetPosition(cur_position, false); float agl = this->GetHeightAboveGroundBelow(this->GetMaxHeight(true), true); if (App::GetSimTerrain()->getWater()) - { - agl = std::min(this->GetMinHeight(true) - App::GetSimTerrain()->getWater()->GetStaticWaterHeight(), agl); - } - if (agl < 0.0f) - { - this->ResetPosition(ar_nodes[0].AbsPosition - agl * Vector3::UNIT_Y, false); - } + { agl = std::min(this->GetMinHeight(true) - App::GetSimTerrain()->getWater()->GetStaticWaterHeight(), agl); } + if (agl < 0.0f) { this->ResetPosition(ar_nodes[0].AbsPosition - agl * Vector3::UNIT_Y, false); } } else { @@ -1674,21 +1597,18 @@ void Actor::SyncReset(bool reset_position) for (int i = 0; i < MAX_COMMANDS; i++) { - ar_command_key[i].commandValue = 0.0; + ar_command_key[i].commandValue = 0.0; ar_command_key[i].triggerInputValue = 0.0f; - ar_command_key[i].playerInputValue = 0.0f; - for (auto& b : ar_command_key[i].beams) + ar_command_key[i].playerInputValue = 0.0f; + for (auto &b : ar_command_key[i].beams) { - b.cmb_state->auto_moving_mode = 0; + b.cmb_state->auto_moving_mode = 0; b.cmb_state->pressed_center_mode = false; } } this->resetSlideNodes(); - if (m_slidenodes_locked) - { - this->ToggleSlideNodeLock(); - } + if (m_slidenodes_locked) { this->ToggleSlideNodeLock(); } m_ongoing_reset = true; } @@ -1712,7 +1632,8 @@ void Actor::ApplyNodeBeamScales() } else if (ar_beams[i].bounded == SHOCK1 || ar_beams[i].bounded == SHOCK2 || ar_beams[i].bounded == SHOCK3) { - ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_shocks_scale.first;; + ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_shocks_scale.first; + ; ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_shocks_scale.second; } else @@ -1725,15 +1646,14 @@ void Actor::ApplyNodeBeamScales() bool Actor::ReplayStep() { - if (!ar_replay_mode || !m_replay_handler || !m_replay_handler->isValid()) - return false; + if (!ar_replay_mode || !m_replay_handler || !m_replay_handler->isValid()) return false; // no replay update needed if position was not changed if (ar_replay_pos != m_replay_pos_prev) { unsigned long time = 0; - node_simple_t* nbuff = (node_simple_t *)m_replay_handler->getReadBuffer(ar_replay_pos, 0, time); + node_simple_t *nbuff = (node_simple_t *)m_replay_handler->getReadBuffer(ar_replay_pos, 0, time); if (nbuff) { for (int i = 0; i < ar_num_nodes; i++) @@ -1742,7 +1662,7 @@ bool Actor::ReplayStep() ar_nodes[i].RelPosition = nbuff[i].position - ar_origin; ar_nodes[i].Velocity = nbuff[i].velocity; - ar_nodes[i].Forces = Vector3::ZERO; + ar_nodes[i].Forces = Vector3::ZERO; } updateSlideNodePositions(); @@ -1750,12 +1670,12 @@ bool Actor::ReplayStep() calculateAveragePosition(); } - beam_simple_t* bbuff = (beam_simple_t *)m_replay_handler->getReadBuffer(ar_replay_pos, 1, time); + beam_simple_t *bbuff = (beam_simple_t *)m_replay_handler->getReadBuffer(ar_replay_pos, 1, time); if (bbuff) { for (int i = 0; i < ar_num_beams; i++) { - ar_beams[i].bm_broken = bbuff[i].broken; + ar_beams[i].bm_broken = bbuff[i].broken; ar_beams[i].bm_disabled = bbuff[i].disabled; } } @@ -1769,9 +1689,7 @@ void Actor::ForceFeedbackStep(int steps) { m_force_sensors.out_body_forces = m_force_sensors.accu_body_forces / steps; if (!ar_hydros.empty()) // Vehicle has hydros? - { - m_force_sensors.out_hydros_forces = (m_force_sensors.accu_hydros_forces / steps) / ar_hydros.size(); - } + { m_force_sensors.out_hydros_forces = (m_force_sensors.accu_hydros_forces / steps) / ar_hydros.size(); } } void Actor::HandleAngelScriptEvents(float dt) @@ -1791,14 +1709,14 @@ void Actor::SearchBeamDefaults() { SyncReset(true); - auto old_beams_scale = ar_nb_beams_scale; + auto old_beams_scale = ar_nb_beams_scale; auto old_shocks_scale = ar_nb_shocks_scale; auto old_wheels_scale = ar_nb_wheels_scale; if (ar_nb_initialized) { - ar_nb_beams_scale.first = Math::RangeRandom(ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second); - ar_nb_beams_scale.second = Math::RangeRandom(ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second); + ar_nb_beams_scale.first = Math::RangeRandom(ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second); + ar_nb_beams_scale.second = Math::RangeRandom(ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second); ar_nb_shocks_scale.first = Math::RangeRandom(ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second); ar_nb_shocks_scale.second = Math::RangeRandom(ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second); ar_nb_wheels_scale.first = Math::RangeRandom(ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second); @@ -1806,14 +1724,14 @@ void Actor::SearchBeamDefaults() } else { - ar_nb_beams_scale.first = Math::Clamp(1.0f, ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second); - ar_nb_beams_scale.second = Math::Clamp(1.0f, ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second); + ar_nb_beams_scale.first = Math::Clamp(1.0f, ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second); + ar_nb_beams_scale.second = Math::Clamp(1.0f, ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second); ar_nb_shocks_scale.first = Math::Clamp(1.0f, ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second); ar_nb_shocks_scale.second = Math::Clamp(1.0f, ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second); ar_nb_wheels_scale.first = Math::Clamp(1.0f, ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second); ar_nb_wheels_scale.second = Math::Clamp(1.0f, ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second); - ar_nb_reference = std::vector(ar_nb_reference.size(), std::numeric_limits::max()); - ar_nb_optimum = std::vector(ar_nb_reference.size(), std::numeric_limits::max()); + ar_nb_reference = std::vector(ar_nb_reference.size(), std::numeric_limits::max()); + ar_nb_optimum = std::vector(ar_nb_reference.size(), std::numeric_limits::max()); } this->ApplyNodeBeamScales(); @@ -1823,18 +1741,17 @@ void Actor::SearchBeamDefaults() for (int i = 0; i < ar_nb_skip_steps; i++) { this->CalcForcesEulerCompute(i == 0, ar_nb_skip_steps); - if (m_ongoing_reset) - break; + if (m_ongoing_reset) break; } m_ongoing_reset = true; float sum_movement = 0.0f; - float movement = 0.0f; + float movement = 0.0f; float sum_velocity = 0.0f; - float velocity = 0.0f; - float sum_stress = 0.0f; - float stress = 0.0f; - int sum_broken = 0; + float velocity = 0.0f; + float sum_stress = 0.0f; + float stress = 0.0f; + int sum_broken = 0; for (int k = 0; k < ar_nb_measure_steps; k++) { this->CalcForcesEulerCompute(false, ar_nb_measure_steps); @@ -1847,19 +1764,16 @@ void Actor::SearchBeamDefaults() for (int i = 0; i < ar_num_beams; i++) { Vector3 dis = (ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition).normalisedCopy(); - float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis); + float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis); sum_velocity += std::abs(v) / (float)ar_nb_measure_steps; velocity = std::max(velocity, std::abs(v)); sum_stress += std::abs(ar_beams[i].stress) / (float)ar_nb_measure_steps; stress = std::max(stress, std::abs(ar_beams[i].stress)); - if (k == 0 && ar_beams[i].bm_broken) - { - sum_broken++; - } + if (k == 0 && ar_beams[i].bm_broken) { sum_broken++; } } - if (sum_broken > ar_nb_reference[6] || - stress > ar_nb_reference[0] || velocity > ar_nb_reference[2] || movement > ar_nb_optimum[4] || - sum_stress > ar_nb_reference[1] || sum_velocity > ar_nb_reference[3] || sum_movement > ar_nb_optimum[5] * 2.f) + if (sum_broken > ar_nb_reference[6] || stress > ar_nb_reference[0] || velocity > ar_nb_reference[2] || + movement > ar_nb_optimum[4] || sum_stress > ar_nb_reference[1] || sum_velocity > ar_nb_reference[3] || + sum_movement > ar_nb_optimum[5] * 2.f) { ar_nb_beams_scale = old_beams_scale; ar_nb_shocks_scale = old_shocks_scale; @@ -1871,25 +1785,21 @@ void Actor::SearchBeamDefaults() SyncReset(true); ar_nb_optimum = {stress, sum_stress, velocity, sum_velocity, movement, sum_movement, (float)sum_broken}; - if (!ar_nb_initialized) - { - ar_nb_reference = ar_nb_optimum; - } + if (!ar_nb_initialized) { ar_nb_reference = ar_nb_optimum; } ar_nb_initialized = true; } void Actor::HandleInputEvents(float dt) { - if (!m_ongoing_reset) - return; + if (!m_ongoing_reset) return; if (m_anglesnap_request > 0) { - float rotation = Radian(getRotation()).valueDegrees(); - float target_rotation = std::round(rotation / m_anglesnap_request) * m_anglesnap_request; - m_rotation_request = -Degree(target_rotation - rotation).valueRadians(); - m_rotation_request_center = GetRotationCenter(); - m_anglesnap_request = 0; + float rotation = Radian(getRotation()).valueDegrees(); + float target_rotation = std::round(rotation / m_anglesnap_request) * m_anglesnap_request; + m_rotation_request = -Degree(target_rotation - rotation).valueRadians(); + m_rotation_request_center = GetRotationCenter(); + m_anglesnap_request = 0; } if (m_rotation_request != 0.0f) @@ -1902,8 +1812,8 @@ void Actor::HandleInputEvents(float dt) ar_nodes[i].AbsPosition = rot * ar_nodes[i].AbsPosition; ar_nodes[i].AbsPosition += m_rotation_request_center; ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin; - ar_nodes[i].Velocity = rot * ar_nodes[i].Velocity; - ar_nodes[i].Forces = rot * ar_nodes[i].Forces; + ar_nodes[i].Velocity = rot * ar_nodes[i].Velocity; + ar_nodes[i].Forces = rot * ar_nodes[i].Forces; } m_rotation_request = 0.0f; @@ -1930,13 +1840,10 @@ void Actor::sendStreamSetup() RoRnet::ActorStreamRegister reg; memset(®, 0, sizeof(RoRnet::ActorStreamRegister)); reg.status = 0; - reg.type = 0; - reg.time = App::GetSimController()->GetBeamFactory()->GetNetTime(); + reg.type = 0; + reg.time = App::GetSimController()->GetBeamFactory()->GetNetTime(); strncpy(reg.name, ar_filename.c_str(), 128); - if (m_used_skin_entry != nullptr) - { - strncpy(reg.skin, m_used_skin_entry->dname.c_str(), 60); - } + if (m_used_skin_entry != nullptr) { strncpy(reg.skin, m_used_skin_entry->dname.c_str(), 60); } strncpy(reg.sectionconfig, m_section_config.c_str(), 60); #ifdef USE_SOCKETW @@ -1951,12 +1858,11 @@ void Actor::sendStreamData() { using namespace RoRnet; #ifdef USE_SOCKETW - if (ar_net_timer.getMilliseconds() - ar_net_last_update_time < 100) - return; + if (ar_net_timer.getMilliseconds() - ar_net_last_update_time < 100) return; ar_net_last_update_time = ar_net_timer.getMilliseconds(); - //look if the packet is too big first + // look if the packet is too big first if (m_net_buffer_size + sizeof(RoRnet::VehicleState) > 8192) { ErrorUtils::ShowError(_L("Actor is too big to be sent over the net."), _L("Network error!")); @@ -1969,7 +1875,7 @@ void Actor::sendStreamData() // RoRnet::VehicleState is at the beginning of the buffer { - RoRnet::VehicleState* send_oob = (RoRnet::VehicleState *)send_buffer; + RoRnet::VehicleState *send_oob = (RoRnet::VehicleState *)send_buffer; packet_len += sizeof(RoRnet::VehicleState); send_oob->flagmask = 0; @@ -1977,39 +1883,32 @@ void Actor::sendStreamData() send_oob->time = App::GetSimController()->GetBeamFactory()->GetNetTime(); if (ar_engine) { - send_oob->engine_speed = ar_engine->GetEngineRpm(); - send_oob->engine_force = ar_engine->GetAcceleration(); + send_oob->engine_speed = ar_engine->GetEngineRpm(); + send_oob->engine_force = ar_engine->GetAcceleration(); send_oob->engine_clutch = ar_engine->GetClutch(); - send_oob->engine_gear = ar_engine->GetGear(); + send_oob->engine_gear = ar_engine->GetGear(); - if (ar_engine->HasStarterContact()) - send_oob->flagmask += NETMASK_ENGINE_CONT; - if (ar_engine->IsRunning()) - send_oob->flagmask += NETMASK_ENGINE_RUN; + if (ar_engine->HasStarterContact()) send_oob->flagmask += NETMASK_ENGINE_CONT; + if (ar_engine->IsRunning()) send_oob->flagmask += NETMASK_ENGINE_RUN; switch (ar_engine->GetAutoShiftMode()) { - case RoR::SimGearboxMode::AUTO: send_oob->flagmask += NETMASK_ENGINE_MODE_AUTOMATIC; - break; - case RoR::SimGearboxMode::SEMI_AUTO: send_oob->flagmask += NETMASK_ENGINE_MODE_SEMIAUTO; - break; - case RoR::SimGearboxMode::MANUAL: send_oob->flagmask += NETMASK_ENGINE_MODE_MANUAL; - break; - case RoR::SimGearboxMode::MANUAL_STICK: send_oob->flagmask += NETMASK_ENGINE_MODE_MANUAL_STICK; - break; - case RoR::SimGearboxMode::MANUAL_RANGES: send_oob->flagmask += NETMASK_ENGINE_MODE_MANUAL_RANGES; - break; + case RoR::SimGearboxMode::AUTO: send_oob->flagmask += NETMASK_ENGINE_MODE_AUTOMATIC; break; + case RoR::SimGearboxMode::SEMI_AUTO: send_oob->flagmask += NETMASK_ENGINE_MODE_SEMIAUTO; break; + case RoR::SimGearboxMode::MANUAL: send_oob->flagmask += NETMASK_ENGINE_MODE_MANUAL; break; + case RoR::SimGearboxMode::MANUAL_STICK: send_oob->flagmask += NETMASK_ENGINE_MODE_MANUAL_STICK; break; + case RoR::SimGearboxMode::MANUAL_RANGES: send_oob->flagmask += NETMASK_ENGINE_MODE_MANUAL_RANGES; break; } } if (ar_num_aeroengines > 0) { - float rpm = ar_aeroengines[0]->getRPM(); + float rpm = ar_aeroengines[0]->getRPM(); send_oob->engine_speed = rpm; } send_oob->hydrodirstate = ar_hydro_dir_state; - send_oob->brake = ar_brake; - send_oob->wheelspeed = ar_wheel_speed; + send_oob->brake = ar_brake; + send_oob->wheelspeed = ar_wheel_speed; blinktype b = getBlinkType(); if (b == BLINK_LEFT) @@ -2019,59 +1918,46 @@ void Actor::sendStreamData() else if (b == BLINK_WARN) send_oob->flagmask += NETMASK_BLINK_WARN; - if (ar_lights) - send_oob->flagmask += NETMASK_LIGHTS; - if (getCustomLightVisible(0)) - send_oob->flagmask += NETMASK_CLIGHT1; - if (getCustomLightVisible(1)) - send_oob->flagmask += NETMASK_CLIGHT2; - if (getCustomLightVisible(2)) - send_oob->flagmask += NETMASK_CLIGHT3; - if (getCustomLightVisible(3)) - send_oob->flagmask += NETMASK_CLIGHT4; - - if (getBrakeLightVisible()) - send_oob->flagmask += NETMASK_BRAKES; - if (getReverseLightVisible()) - send_oob->flagmask += NETMASK_REVERSE; - if (getBeaconMode()) - send_oob->flagmask += NETMASK_BEACONS; - if (getCustomParticleMode()) - send_oob->flagmask += NETMASK_PARTICLE; - - if (ar_parking_brake) - send_oob->flagmask += NETMASK_PBRAKE; - if (m_tractioncontrol) - send_oob->flagmask += NETMASK_TC_ACTIVE; - if (m_antilockbrake) - send_oob->flagmask += NETMASK_ALB_ACTIVE; - - if (SOUND_GET_STATE(ar_instance_id, SS_TRIG_HORN)) - send_oob->flagmask += NETMASK_HORN; + if (ar_lights) send_oob->flagmask += NETMASK_LIGHTS; + if (getCustomLightVisible(0)) send_oob->flagmask += NETMASK_CLIGHT1; + if (getCustomLightVisible(1)) send_oob->flagmask += NETMASK_CLIGHT2; + if (getCustomLightVisible(2)) send_oob->flagmask += NETMASK_CLIGHT3; + if (getCustomLightVisible(3)) send_oob->flagmask += NETMASK_CLIGHT4; + + if (getBrakeLightVisible()) send_oob->flagmask += NETMASK_BRAKES; + if (getReverseLightVisible()) send_oob->flagmask += NETMASK_REVERSE; + if (getBeaconMode()) send_oob->flagmask += NETMASK_BEACONS; + if (getCustomParticleMode()) send_oob->flagmask += NETMASK_PARTICLE; + + if (ar_parking_brake) send_oob->flagmask += NETMASK_PBRAKE; + if (m_tractioncontrol) send_oob->flagmask += NETMASK_TC_ACTIVE; + if (m_antilockbrake) send_oob->flagmask += NETMASK_ALB_ACTIVE; + + if (SOUND_GET_STATE(ar_instance_id, SS_TRIG_HORN)) send_oob->flagmask += NETMASK_HORN; } // then process the contents { - char* ptr = send_buffer + sizeof(RoRnet::VehicleState); - float* send_nodes = (float *)ptr; + char * ptr = send_buffer + sizeof(RoRnet::VehicleState); + float *send_nodes = (float *)ptr; packet_len += m_net_buffer_size; // copy data into the buffer int i; // reference node first - Vector3& refpos = ar_nodes[0].AbsPosition; - send_nodes[0] = refpos.x; - send_nodes[1] = refpos.y; - send_nodes[2] = refpos.z; + Vector3 &refpos = ar_nodes[0].AbsPosition; + send_nodes[0] = refpos.x; + send_nodes[1] = refpos.y; + send_nodes[2] = refpos.z; - ptr += sizeof(float) * 3;// plus 3 floats from above + ptr += sizeof(float) * 3; // plus 3 floats from above // then copy the other nodes into a compressed short format - short* sbuf = (short*)ptr; + short *sbuf = (short *)ptr; for (i = 1; i < m_net_first_wheel_node; i++) { - Vector3 relpos = ar_nodes[i].AbsPosition - refpos; + Vector3 relpos = ar_nodes[i].AbsPosition - refpos; sbuf[(i - 1) * 3 + 0] = (short int)(relpos.x * m_net_node_compression); sbuf[(i - 1) * 3 + 1] = (short int)(relpos.y * m_net_node_compression); sbuf[(i - 1) * 3 + 2] = (short int)(relpos.z * m_net_node_compression); @@ -2080,7 +1966,7 @@ void Actor::sendStreamData() } // then to the wheels - float* wfbuf = (float*)ptr; + float *wfbuf = (float *)ptr; for (i = 0; i < ar_num_wheels; i++) { wfbuf[i] = ar_wheels[i].wh_net_rp; @@ -2088,13 +1974,15 @@ void Actor::sendStreamData() } RoR::Networking::AddPacket(ar_net_stream_id, MSG2_STREAM_DATA_DISCARDABLE, packet_len, send_buffer); -#endif //SOCKETW +#endif // SOCKETW } -void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real timer, const float lower_limit, const float upper_limit, const float option3) +void Actor::CalcAnimators(const int flag_state, float &cstate, int &div, Real timer, const float lower_limit, + const float upper_limit, const float option3) { // ## DEV NOTE: - // ## Until 06/2018, this function was used for both animator-beams (physics, part of softbody) and animated props (visual-only). + // ## Until 06/2018, this function was used for both animator-beams (physics, part of softbody) and animated props + // (visual-only). // ## Animated props are now done by `GfxActor::CalcPropAnimation()` ~ only_a_ptr // -- WRITES -- @@ -2103,48 +1991,41 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti Real dt = timer; - //boat rudder - read only + // boat rudder - read only if (flag_state & ANIM_FLAG_BRUDDER) { - int spi; + int spi; float ctmp = 0.0f; for (spi = 0; spi < ar_num_screwprops; spi++) - if (ar_screwprops[spi]) - ctmp += ar_screwprops[spi]->getRudder(); + if (ar_screwprops[spi]) ctmp += ar_screwprops[spi]->getRudder(); - if (spi > 0) - ctmp = ctmp / spi; + if (spi > 0) ctmp = ctmp / spi; cstate = ctmp; div++; } - //boat throttle - read only + // boat throttle - read only if (flag_state & ANIM_FLAG_BTHROTTLE) { - int spi; + int spi; float ctmp = 0.0f; for (spi = 0; spi < ar_num_screwprops; spi++) - if (ar_screwprops[spi]) - ctmp += ar_screwprops[spi]->getThrottle(); + if (ar_screwprops[spi]) ctmp += ar_screwprops[spi]->getThrottle(); - if (spi > 0) - ctmp = ctmp / spi; + if (spi > 0) ctmp = ctmp / spi; cstate = ctmp; div++; } - //differential lock status - read only + // differential lock status - read only if (flag_state & ANIM_FLAG_DIFFLOCK) { if (m_num_wheel_diffs && m_wheel_diffs[0]) { String name = m_wheel_diffs[0]->GetDifferentialTypeName(); - if (name == "Open") - cstate = 0.0f; - if (name == "Split") - cstate = 0.5f; - if (name == "Locked") - cstate = 1.0f; + if (name == "Open") cstate = 0.0f; + if (name == "Split") cstate = 0.5f; + if (name == "Locked") cstate = 1.0f; } else // no axles/diffs avail, mode is split by default cstate = 0.5f; @@ -2152,7 +2033,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //heading - read only + // heading - read only if (flag_state & ANIM_FLAG_HEADING) { float heading = getRotation(); @@ -2161,24 +2042,22 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //torque - WRITES + // torque - WRITES if (ar_engine && flag_state & ANIM_FLAG_TORQUE) { float torque = ar_engine->GetCrankFactor(); - if (torque <= 0.0f) - torque = 0.0f; + if (torque <= 0.0f) torque = 0.0f; if (torque >= ar_anim_previous_crank) cstate -= torque / 10.0f; else cstate = 0.0f; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate <= -1.0f) cstate = -1.0f; ar_anim_previous_crank = torque; div++; } - //shifterseq, to amimate sequentiell shifting + // shifterseq, to amimate sequentiell shifting if (ar_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 3.0f) { // opt1 &opt2 = 0 this is a shifter @@ -2187,12 +2066,12 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti int shifter = ar_engine->GetGear(); if (shifter > m_previous_gear) { - cstate = 1.0f; + cstate = 1.0f; ar_anim_shift_timer = 0.2f; } if (shifter < m_previous_gear) { - cstate = -1.0f; + cstate = -1.0f; ar_anim_shift_timer = -0.2f; } m_previous_gear = shifter; @@ -2201,40 +2080,33 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti { cstate = 1.0f; ar_anim_shift_timer -= dt; - if (ar_anim_shift_timer < 0.0f) - ar_anim_shift_timer = 0.0f; + if (ar_anim_shift_timer < 0.0f) ar_anim_shift_timer = 0.0f; } if (ar_anim_shift_timer < 0.0f) { cstate = -1.0f; ar_anim_shift_timer += dt; - if (ar_anim_shift_timer > 0.0f) - ar_anim_shift_timer = 0.0f; + if (ar_anim_shift_timer > 0.0f) ar_anim_shift_timer = 0.0f; } } else { // check if lower_limit is a valid to get commandvalue, then get commandvalue if (lower_limit >= 1.0f && lower_limit <= 48.0) - if (ar_command_key[int(lower_limit)].commandValue > 0) - cstate += 1.0f; + if (ar_command_key[int(lower_limit)].commandValue > 0) cstate += 1.0f; // check if upper_limit is a valid to get commandvalue, then get commandvalue if (upper_limit >= 1.0f && upper_limit <= 48.0) - if (ar_command_key[int(upper_limit)].commandValue > 0) - cstate -= 1.0f; + if (ar_command_key[int(upper_limit)].commandValue > 0) cstate -= 1.0f; } div++; } - //shifterman1, left/right + // shifterman1, left/right if (ar_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 1.0f) { int shifter = ar_engine->GetGear(); - if (!shifter) - { - cstate = -0.5f; - } + if (!shifter) { cstate = -0.5f; } else if (shifter < 0) { cstate = 1.0f; @@ -2246,32 +2118,26 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //shifterman2, up/down + // shifterman2, up/down if (ar_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 2.0f) { int shifter = ar_engine->GetGear(); - cstate = 0.5f; - if (shifter < 0) - { - cstate = 1.0f; - } - if (shifter > 0) - { - cstate = shifter % 2; - } + cstate = 0.5f; + if (shifter < 0) { cstate = 1.0f; } + if (shifter > 0) { cstate = shifter % 2; } div++; } - //shifterlinear, to amimate cockpit gearselect gauge and autotransmission stick + // shifterlinear, to amimate cockpit gearselect gauge and autotransmission stick if (ar_engine && (flag_state & ANIM_FLAG_SHIFTER) && option3 == 4.0f) { - int shifter = ar_engine->GetGear(); + int shifter = ar_engine->GetGear(); int numgears = ar_engine->getNumGears(); cstate -= (shifter + 2.0) / (numgears + 2.0); div++; } - //parking brake + // parking brake if (flag_state & ANIM_FLAG_PBRAKE) { float pbrake = ar_parking_brake; @@ -2279,7 +2145,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //speedo ( scales with speedomax ) + // speedo ( scales with speedomax ) if (flag_state & ANIM_FLAG_SPEEDO) { float speedo = ar_wheel_speed / ar_speedo_max_kph; @@ -2287,7 +2153,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //engine tacho ( scales with maxrpm, default is 3500 ) + // engine tacho ( scales with maxrpm, default is 3500 ) if (ar_engine && flag_state & ANIM_FLAG_TACHO) { float tacho = ar_engine->GetEngineRpm() / ar_engine->getMaxRPM(); @@ -2295,7 +2161,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //turbo + // turbo if (ar_engine && flag_state & ANIM_FLAG_TURBO) { float turbo = ar_engine->GetTurboPsi() * 3.34; @@ -2303,14 +2169,14 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //brake + // brake if (flag_state & ANIM_FLAG_BRAKE) { cstate -= ar_brake; div++; } - //accelerator + // accelerator if (ar_engine && flag_state & ANIM_FLAG_ACCEL) { float accel = ar_engine->GetAcceleration(); @@ -2319,7 +2185,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //clutch + // clutch if (ar_engine && flag_state & ANIM_FLAG_CLUTCH) { float clutch = ar_engine->GetClutch(); @@ -2327,7 +2193,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //aeroengines rpm + throttle + torque ( turboprop ) + pitch ( turboprop ) + status + fire + // aeroengines rpm + throttle + torque ( turboprop ) + pitch ( turboprop ) + status + fire int ftp = ar_num_aeroengines; if (ftp > option3 - 1.0f) @@ -2356,16 +2222,16 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti if (flag_state & ANIM_FLAG_AETORQUE) if (ar_aeroengines[aenum]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP) { - Turboprop* tp = (Turboprop*)ar_aeroengines[aenum]; - cstate = (100.0 * tp->indicated_torque / tp->max_torque) / 120.0f; + Turboprop *tp = (Turboprop *)ar_aeroengines[aenum]; + cstate = (100.0 * tp->indicated_torque / tp->max_torque) / 120.0f; div++; } if (flag_state & ANIM_FLAG_AEPITCH) if (ar_aeroengines[aenum]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP) { - Turboprop* tp = (Turboprop*)ar_aeroengines[aenum]; - cstate = tp->pitch / 120.0f; + Turboprop *tp = (Turboprop *)ar_aeroengines[aenum]; + cstate = tp->pitch / 120.0f; div++; } @@ -2375,121 +2241,110 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti cstate = 0.0f; else cstate = 0.5f; - if (ar_aeroengines[aenum]->isFailed()) - cstate = 1.0f; + if (ar_aeroengines[aenum]->isFailed()) cstate = 1.0f; div++; } } - //airspeed indicator + // airspeed indicator if (flag_state & ANIM_FLAG_AIRSPEED) { // TODO Unused Varaible - //float angle=0.0; + // float angle=0.0; float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438; - float altitude = ar_nodes[0].AbsPosition.y; + float altitude = ar_nodes[0].AbsPosition.y; // TODO Unused Varaible - //float sea_level_temperature=273.15+15.0; //in Kelvin - float sea_level_pressure = 101325; //in Pa + // float sea_level_temperature=273.15+15.0; //in Kelvin + float sea_level_pressure = 101325; // in Pa // TODO Unused Varaible - //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin - float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa - float airdensity = airpressure * 0.0000120896;//1.225 at sea level - float kt = ground_speed_kt * sqrt(airdensity / 1.225); + // float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin + float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896; // 1.225 at sea level + float kt = ground_speed_kt * sqrt(airdensity / 1.225); cstate -= kt / 100.0f; div++; } - //vvi indicator + // vvi indicator if (flag_state & ANIM_FLAG_VVI) { float vvi = ar_nodes[0].Velocity.y * 196.85; // limit vvi scale to +/- 6m/s cstate -= vvi / 6000.0f; - if (cstate >= 1.0f) - cstate = 1.0f; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate >= 1.0f) cstate = 1.0f; + if (cstate <= -1.0f) cstate = -1.0f; div++; } - //altimeter + // altimeter if (flag_state & ANIM_FLAG_ALTIMETER) { - //altimeter indicator 1k oscillating + // altimeter indicator 1k oscillating if (option3 == 3.0f) { float altimeter = (ar_nodes[0].AbsPosition.y * 1.1811) / 360.0f; - int alti_int = int(altimeter); - float alti_mod = (altimeter - alti_int); + int alti_int = int(altimeter); + float alti_mod = (altimeter - alti_int); cstate -= alti_mod; } - //altimeter indicator 10k oscillating + // altimeter indicator 10k oscillating if (option3 == 2.0f) { - float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 3600.0f; - int alti_int = int(alti); + float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 3600.0f; + int alti_int = int(alti); float alti_mod = (alti - alti_int); cstate -= alti_mod; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate <= -1.0f) cstate = -1.0f; } - //altimeter indicator 100k limited + // altimeter indicator 100k limited if (option3 == 1.0f) { float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 36000.0f; cstate -= alti; - if (cstate <= -1.0f) - cstate = -1.0f; + if (cstate <= -1.0f) cstate = -1.0f; } div++; } - //AOA + // AOA if (flag_state & ANIM_FLAG_AOA) { float aoa = 0; - if (ar_num_wings > 4) - aoa = (ar_wings[4].fa->aoa) / 25.0f; - if ((ar_nodes[0].Velocity.length() * 1.9438) < 10.0f) - aoa = 0; + if (ar_num_wings > 4) aoa = (ar_wings[4].fa->aoa) / 25.0f; + if ((ar_nodes[0].Velocity.length() * 1.9438) < 10.0f) aoa = 0; cstate -= aoa; - if (cstate <= -1.0f) - cstate = -1.0f; - if (cstate >= 1.0f) - cstate = 1.0f; + if (cstate <= -1.0f) cstate = -1.0f; + if (cstate >= 1.0f) cstate = 1.0f; div++; } // roll if (flag_state & ANIM_FLAG_ROLL) { - Vector3 rollv = this->GetCameraRoll(); - Vector3 dirv = this->GetCameraDir(); - Vector3 upv = dirv.crossProduct(-rollv); - float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y)); + Vector3 rollv = this->GetCameraRoll(); + Vector3 dirv = this->GetCameraDir(); + Vector3 upv = dirv.crossProduct(-rollv); + float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y)); // rad to deg rollangle = Math::RadiansToDegrees(rollangle); // flip to other side when upside down - if (upv.y < 0) - rollangle = 180.0f - rollangle; + if (upv.y < 0) rollangle = 180.0f - rollangle; cstate = rollangle / 180.0f; // data output is -0.5 to 1.5, normalize to -1 to +1 without changing the zero position. // this is vital for the animator beams and does not effect the animated props - if (cstate >= 1.0f) - cstate = cstate - 2.0f; + if (cstate >= 1.0f) cstate = cstate - 2.0f; div++; } // pitch if (flag_state & ANIM_FLAG_PITCH) { - Vector3 dirv = this->GetCameraDir(); - float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y)); + Vector3 dirv = this->GetCameraDir(); + float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y)); // radian to degrees with a max cstate of +/- 1.0 cstate = (Math::RadiansToDegrees(pitchangle) / 90.0f); div++; @@ -2504,7 +2359,7 @@ void Actor::CalcAnimators(const int flag_state, float& cstate, int& div, Real ti div++; } - //flaps + // flaps if (flag_state & ANIM_FLAG_FLAP) { float flaps = flapangles[ar_aerial_flap]; @@ -2523,19 +2378,12 @@ void Actor::CalcCabCollisions() if (m_intra_point_col_detector != nullptr) { m_intra_point_col_detector->UpdateIntraPoint(); - ResolveIntraActorCollisions(PHYSICS_DT, - *m_intra_point_col_detector, - ar_num_collcabs, - ar_collcabs, - ar_cabs, - ar_intra_collcabrate, - ar_nodes, - ar_collision_range, - *ar_submesh_ground_model); + ResolveIntraActorCollisions(PHYSICS_DT, *m_intra_point_col_detector, ar_num_collcabs, ar_collcabs, ar_cabs, + ar_intra_collcabrate, ar_nodes, ar_collision_range, *ar_submesh_ground_model); } } -void Actor::CalcShocks2(int i, Real difftoBeamL, Real& k, Real& d, Real v) +void Actor::CalcShocks2(int i, Real difftoBeamL, Real &k, Real &d, Real v) { if (v > 0) // Extension { @@ -2568,8 +2416,8 @@ void Actor::CalcShocks2(int i, Real difftoBeamL, Real& k, Real& d, Real v) if (ar_beams[i].shock->flags & SHOCK_FLAG_SOFTBUMP) { // soft bump shocks - float beamsLep = ar_beams[i].L * 0.8f; - float longboundprelimit = ar_beams[i].longbound * beamsLep; + float beamsLep = ar_beams[i].L * 0.8f; + float longboundprelimit = ar_beams[i].longbound * beamsLep; float shortboundprelimit = -ar_beams[i].shortbound * beamsLep; if (difftoBeamL > longboundprelimit) { @@ -2646,25 +2494,25 @@ void Actor::CalcShocks2(int i, Real difftoBeamL, Real& k, Real& d, Real v) } } -void Actor::CalcShocks3(int i, Real difftoBeamL, Real &k, Real& d, Real v) +void Actor::CalcShocks3(int i, Real difftoBeamL, Real &k, Real &d, Real v) { if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L) { - float interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L; + float interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L; k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio; - d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio; + d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio; } else if (difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L) { float interp_ratio = -difftoBeamL - ar_beams[i].shortbound * ar_beams[i].L; k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio; - d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio; + d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio; } else if (v > 0) // Extension { v = Math::Clamp(std::abs(v), +0.15f, +20.0f); k = ar_beams[i].shock->springout; - d = ar_beams[i].shock->dampout * ar_beams[i].shock->dslowout * std::min(v, ar_beams[i].shock->splitout) + + d = ar_beams[i].shock->dampout * ar_beams[i].shock->dslowout * std::min(v, ar_beams[i].shock->splitout) + ar_beams[i].shock->dampout * ar_beams[i].shock->dfastout * std::max(0.0f, v - ar_beams[i].shock->splitout); d /= v; } @@ -2672,30 +2520,36 @@ void Actor::CalcShocks3(int i, Real difftoBeamL, Real &k, Real& d, Real v) { v = Math::Clamp(std::abs(v), +0.15f, +20.0f); k = ar_beams[i].shock->springin; - d = ar_beams[i].shock->dampin * ar_beams[i].shock->dslowin * std::min(v, ar_beams[i].shock->splitin ) + - ar_beams[i].shock->dampin * ar_beams[i].shock->dfastin * std::max(0.0f, v - ar_beams[i].shock->splitin ); + d = ar_beams[i].shock->dampin * ar_beams[i].shock->dslowin * std::min(v, ar_beams[i].shock->splitin) + + ar_beams[i].shock->dampin * ar_beams[i].shock->dfastin * std::max(0.0f, v - ar_beams[i].shock->splitin); d /= v; } } void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) { - if ((ar_beams[i].shock->flags & SHOCK_FLAG_ISTRIGGER) && ar_beams[i].shock->trigger_enabled) // this is a trigger and its enabled + if ((ar_beams[i].shock->flags & SHOCK_FLAG_ISTRIGGER) && + ar_beams[i].shock->trigger_enabled) // this is a trigger and its enabled { const float dt = PHYSICS_DT; - if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L) // that has hit boundary + if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || + difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L) // that has hit boundary { ar_beams[i].shock->trigger_switch_state -= dt; if (ar_beams[i].shock->trigger_switch_state <= 0.0f) // emergency release for dead-switched trigger ar_beams[i].shock->trigger_switch_state = 0.0f; if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_BLOCKER) // this is an enabled blocker and past boundary { - for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++) // (cycle blockerbeamID +1) to (blockerbeamID + beams to lock) + for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; + scount++) // (cycle blockerbeamID +1) to (blockerbeamID + beams to lock) { - if (ar_beams[scount].shock && (ar_beams[scount].shock->flags & SHOCK_FLAG_ISTRIGGER)) // don't mess anything up if the user set the number too big + if (ar_beams[scount].shock && + (ar_beams[scount].shock->flags & + SHOCK_FLAG_ISTRIGGER)) // don't mess anything up if the user set the number too big { - if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 1) + if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && + ar_beams[i].shock->last_debug_state != 1) { LOG(" Trigger disabled. Blocker BeamID " + TOSTRING(i) + " enabled trigger " + TOSTRING(scount)); ar_beams[i].shock->last_debug_state = 1; @@ -2704,15 +2558,21 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) } } } - else if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_BLOCKER_A) // this is an enabled inverted blocker and inside boundary + else if (ar_beams[i].shock->flags & + SHOCK_FLAG_TRG_BLOCKER_A) // this is an enabled inverted blocker and inside boundary { - for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++) // (cycle blockerbeamID + 1) to (blockerbeamID + beams to release) + for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; + scount++) // (cycle blockerbeamID + 1) to (blockerbeamID + beams to release) { - if (ar_beams[scount].shock && (ar_beams[scount].shock->flags & SHOCK_FLAG_ISTRIGGER)) // don't mess anything up if the user set the number too big + if (ar_beams[scount].shock && + (ar_beams[scount].shock->flags & + SHOCK_FLAG_ISTRIGGER)) // don't mess anything up if the user set the number too big { - if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 9) + if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && + ar_beams[i].shock->last_debug_state != 9) { - LOG(" Trigger enabled. Inverted Blocker BeamID " + TOSTRING(i) + " disabled trigger " + TOSTRING(scount)); + LOG(" Trigger enabled. Inverted Blocker BeamID " + TOSTRING(i) + " disabled trigger " + + TOSTRING(scount)); ar_beams[i].shock->last_debug_state = 9; } ar_beams[scount].shock->trigger_enabled = true; // enable the triggers @@ -2724,30 +2584,40 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state = false; // Release the cmdKey if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 2) { - LOG(" F-key trigger block released. Blocker BeamID " + TOSTRING(i) + " Released F" + TOSTRING(ar_beams[i].shock->trigger_cmdshort)); + LOG(" F-key trigger block released. Blocker BeamID " + TOSTRING(i) + " Released F" + + TOSTRING(ar_beams[i].shock->trigger_cmdshort)); ar_beams[i].shock->last_debug_state = 2; } } else if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CMD_SWITCH) // this is an enabled cmdkey switch and past a boundary { - if (!ar_beams[i].shock->trigger_switch_state)// this switch is triggered first time in this boundary + if (!ar_beams[i].shock->trigger_switch_state) // this switch is triggered first time in this boundary { for (int scount = 0; scount < ar_num_shocks; scount++) { - int short1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort; // cmdshort of checked trigger beam - int short2 = ar_beams[i].shock->trigger_cmdshort; // cmdshort of switch beam - int long1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong; // cmdlong of checked trigger beam - int long2 = ar_beams[i].shock->trigger_cmdlong; // cmdlong of switch beam - int tmpi = ar_beams[ar_shocks[scount].beamid].shock->beamid; // beamID global of checked trigger beam - if (((short1 == short2 && long1 == long2) || (short1 == long2 && long1 == short2)) && i != tmpi) // found both command triggers then swap if its not the switching trigger + int short1 = + ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort; // cmdshort of checked trigger beam + int short2 = ar_beams[i].shock->trigger_cmdshort; // cmdshort of switch beam + int long1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong; // cmdlong of checked trigger beam + int long2 = ar_beams[i].shock->trigger_cmdlong; // cmdlong of switch beam + int tmpi = ar_beams[ar_shocks[scount].beamid].shock->beamid; // beamID global of checked trigger beam + if (((short1 == short2 && long1 == long2) || (short1 == long2 && long1 == short2)) && + i != tmpi) // found both command triggers then swap if its not the switching trigger { int tmpcmdkey = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong; - ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort; + ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong = + ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort; ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort = tmpcmdkey; - ar_beams[i].shock->trigger_switch_state = ar_beams[i].shock->trigger_boundary_t; //prevent trigger switching again before leaving boundaries or timeout + ar_beams[i].shock->trigger_switch_state = + ar_beams[i].shock->trigger_boundary_t; // prevent trigger switching again before leaving + // boundaries or timeout if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 3) { - LOG(" Trigger F-key commands switched. Switch BeamID " + TOSTRING(i)+ " switched commands of Trigger BeamID " + TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->beamid) + " to cmdShort: F" + TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort) + ", cmdlong: F" + TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong)); + LOG(" Trigger F-key commands switched. Switch BeamID " + TOSTRING(i) + + " switched commands of Trigger BeamID " + + TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->beamid) + " to cmdShort: F" + + TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort) + ", cmdlong: F" + + TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong)); ar_beams[i].shock->last_debug_state = 3; } } @@ -2755,14 +2625,14 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) } } else - { // just a trigger, check high/low boundary and set action + { // just a trigger, check high/low boundary and set action if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L) // trigger past longbound { if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_HOOK_UNLOCK) { if (trigger_hooks) { - //autolock hooktoggle unlock + // autolock hooktoggle unlock ToggleHooks(ar_beams[i].shock->trigger_cmdlong, HOOK_UNLOCK, -1); } } @@ -2770,7 +2640,7 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) { if (trigger_hooks) { - //autolock hooktoggle lock + // autolock hooktoggle lock ToggleHooks(ar_beams[i].shock->trigger_cmdlong, HOOK_LOCK, -1); } } @@ -2780,16 +2650,19 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) } else { - //just a trigger - if (!ar_command_key[ar_beams[i].shock->trigger_cmdlong].trigger_cmdkeyblock_state) // related cmdkey is not blocked + // just a trigger + if (!ar_command_key[ar_beams[i].shock->trigger_cmdlong] + .trigger_cmdkeyblock_state) // related cmdkey is not blocked { if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CONTINUOUS) - ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1; // continuous trigger only operates on trigger_cmdshort + ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = + 1; // continuous trigger only operates on trigger_cmdshort else ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = 1; if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 4) { - LOG(" Trigger Longbound activated. Trigger BeamID " + TOSTRING(i) + " Triggered F" + TOSTRING(ar_beams[i].shock->trigger_cmdlong)); + LOG(" Trigger Longbound activated. Trigger BeamID " + TOSTRING(i) + " Triggered F" + + TOSTRING(ar_beams[i].shock->trigger_cmdlong)); ar_beams[i].shock->last_debug_state = 4; } } @@ -2801,7 +2674,7 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) { if (trigger_hooks) { - //autolock hooktoggle unlock + // autolock hooktoggle unlock ToggleHooks(ar_beams[i].shock->trigger_cmdshort, HOOK_UNLOCK, -1); } } @@ -2809,29 +2682,34 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) { if (trigger_hooks) { - //autolock hooktoggle lock + // autolock hooktoggle lock ToggleHooks(ar_beams[i].shock->trigger_cmdshort, HOOK_LOCK, -1); } } else if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_ENGINE) { - bool triggerValue = !(ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CONTINUOUS); // 0 if trigger is continuous, 1 otherwise + bool triggerValue = + !(ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CONTINUOUS); // 0 if trigger is continuous, 1 otherwise - EngineTriggerHelper(ar_beams[i].shock->trigger_cmdshort, ar_beams[i].shock->trigger_cmdlong, triggerValue); + EngineTriggerHelper(ar_beams[i].shock->trigger_cmdshort, ar_beams[i].shock->trigger_cmdlong, + triggerValue); } else { - //just a trigger - if (!ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state) // related cmdkey is not blocked + // just a trigger + if (!ar_command_key[ar_beams[i].shock->trigger_cmdshort] + .trigger_cmdkeyblock_state) // related cmdkey is not blocked { if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CONTINUOUS) - ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 0; // continuous trigger only operates on trigger_cmdshort + ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = + 0; // continuous trigger only operates on trigger_cmdshort else ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1; if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 5) { - LOG(" Trigger Shortbound activated. Trigger BeamID " + TOSTRING(i) + " Triggered F" + TOSTRING(ar_beams[i].shock->trigger_cmdshort)); + LOG(" Trigger Shortbound activated. Trigger BeamID " + TOSTRING(i) + " Triggered F" + + TOSTRING(ar_beams[i].shock->trigger_cmdshort)); ar_beams[i].shock->last_debug_state = 5; } } @@ -2846,30 +2724,36 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) if (ar_beams[i].longbound - ar_beams[i].shortbound > 0.0f) { float diffPercentage = difftoBeamL / ar_beams[i].L; - float triggerValue = (diffPercentage - ar_beams[i].shortbound) / (ar_beams[i].longbound - ar_beams[i].shortbound); + float triggerValue = + (diffPercentage - ar_beams[i].shortbound) / (ar_beams[i].longbound - ar_beams[i].shortbound); triggerValue = std::max(0.0f, triggerValue); triggerValue = std::min(triggerValue, 1.0f); if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_ENGINE) // this trigger controls an engine { - EngineTriggerHelper(ar_beams[i].shock->trigger_cmdshort, ar_beams[i].shock->trigger_cmdlong, triggerValue); + EngineTriggerHelper(ar_beams[i].shock->trigger_cmdshort, ar_beams[i].shock->trigger_cmdlong, + triggerValue); } else { // normal trigger ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = triggerValue; - ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = triggerValue; + ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = triggerValue; } } } else if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_BLOCKER) // this is an enabled blocker and inside boundary { - for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++) // (cycle blockerbeamID + 1) to (blockerbeamID + beams to release) + for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; + scount++) // (cycle blockerbeamID + 1) to (blockerbeamID + beams to release) { - if (ar_beams[scount].shock && (ar_beams[scount].shock->flags & SHOCK_FLAG_ISTRIGGER)) // don't mess anything up if the user set the number too big + if (ar_beams[scount].shock && + (ar_beams[scount].shock->flags & + SHOCK_FLAG_ISTRIGGER)) // don't mess anything up if the user set the number too big { - if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 6) + if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && + ar_beams[i].shock->last_debug_state != 6) { LOG(" Trigger enabled. Blocker BeamID " + TOSTRING(i) + " disabled trigger " + TOSTRING(scount)); ar_beams[i].shock->last_debug_state = 6; @@ -2880,34 +2764,44 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) } else if (ar_beams[i].shock->flags & SHOCK_FLAG_TRG_BLOCKER_A) // this is an enabled reverse blocker and past boundary { - for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++) // (cylce blockerbeamID +1) to (blockerbeamID + beams tob lock) + for (int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; + scount++) // (cylce blockerbeamID +1) to (blockerbeamID + beams tob lock) { - if (ar_beams[scount].shock && (ar_beams[scount].shock->flags & SHOCK_FLAG_ISTRIGGER)) // dont mess anything up if the user set the number too big + if (ar_beams[scount].shock && + (ar_beams[scount].shock->flags & + SHOCK_FLAG_ISTRIGGER)) // dont mess anything up if the user set the number too big { - if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 10) + if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && + ar_beams[i].shock->last_debug_state != 10) { - LOG(" Trigger disabled. Inverted Blocker BeamID " + TOSTRING(i) + " enabled trigger " + TOSTRING(scount)); + LOG(" Trigger disabled. Inverted Blocker BeamID " + TOSTRING(i) + " enabled trigger " + + TOSTRING(scount)); ar_beams[i].shock->last_debug_state = 10; } ar_beams[scount].shock->trigger_enabled = false; // disable the trigger } } } - else if ((ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CMD_SWITCH) && ar_beams[i].shock->trigger_switch_state) // this is a switch that was activated and is back inside boundaries again + else if ((ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CMD_SWITCH) && + ar_beams[i] + .shock->trigger_switch_state) // this is a switch that was activated and is back inside boundaries again { - ar_beams[i].shock->trigger_switch_state = 0.0f; //trigger_switch reset + ar_beams[i].shock->trigger_switch_state = 0.0f; // trigger_switch reset if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 7) { LOG(" Trigger switch reset. Switch BeamID " + TOSTRING(i)); ar_beams[i].shock->last_debug_state = 7; } } - else if ((ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CMD_BLOCKER) && !ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state) // this cmdkeyblocker is inside boundaries and cmdkeystate is diabled + else if ((ar_beams[i].shock->flags & SHOCK_FLAG_TRG_CMD_BLOCKER) && + !ar_command_key[ar_beams[i].shock->trigger_cmdshort] + .trigger_cmdkeyblock_state) // this cmdkeyblocker is inside boundaries and cmdkeystate is diabled { ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state = true; // activate trigger blocking if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 8) { - LOG(" F-key trigger blocked. Blocker BeamID " + TOSTRING(i) + " Blocked F" + TOSTRING(ar_beams[i].shock->trigger_cmdshort)); + LOG(" F-key trigger blocked. Blocker BeamID " + TOSTRING(i) + " Blocked F" + + TOSTRING(ar_beams[i].shock->trigger_cmdshort)); ar_beams[i].shock->last_debug_state = 8; } } @@ -2918,7 +2812,7 @@ void Actor::CalcTriggers(int i, Real difftoBeamL, bool trigger_hooks) void Actor::setAirbrakeIntensity(float intensity) { ar_airbrake_intensity = intensity; - for (Airbrake* ab: ar_airbrakes) + for (Airbrake *ab : ar_airbrakes) { ab->updatePosition((float)ar_airbrake_intensity / 5.0); } @@ -2929,17 +2823,14 @@ void Actor::updateSkidmarks() { for (int i = 0; i < ar_num_wheels; i++) { - if (!m_skid_trails[i]) - continue; + if (!m_skid_trails[i]) continue; for (int j = 0; j < ar_wheels[i].wh_num_nodes; j++) { auto n = ar_wheels[i].wh_nodes[j]; if (!n || !n->nd_has_ground_contact || n->nd_last_collision_gm == nullptr || - n->nd_last_collision_gm->fx_type != Collisions::FX_HARD) - { - continue; - } + n->nd_last_collision_gm->fx_type != Collisions::FX_HARD) + { continue; } if (n->nd_avg_collision_slip > 6.f && n->nd_last_collision_slip.squaredLength() > 9.f) { m_skid_trails[i]->update(n->AbsPosition, j, n->nd_avg_collision_slip, n->nd_last_collision_gm->name); @@ -2963,10 +2854,7 @@ void Actor::prepareInside(bool inside) } else { - if (ar_dashboard) - { - ar_dashboard->setVisible(false); - } + if (ar_dashboard) { ar_dashboard->setVisible(false); } gEnv->mainCamera->setNearClipDistance(0.5f); @@ -2976,22 +2864,19 @@ void Actor::prepareInside(bool inside) seatmat->setSceneBlending(SBT_REPLACE); } - // TEMPORARY - until this function is moved to GfxActor ~ 08/2018 - // if (m_cab_scene_node != nullptr) - // { - // m_gfx_actor->GetCabTransMaterial()->setReceiveShadows(!inside); - // } + // TEMPORARY - until this function is moved to GfxActor ~ 08/2018 + // if (m_cab_scene_node != nullptr) + // { + // m_gfx_actor->GetCabTransMaterial()->setReceiveShadows(!inside); + // } - if (App::gfx_reduce_shadows.GetActive()) - { - m_gfx_actor->SetCastShadows(!inside); - } + if (App::gfx_reduce_shadows.GetActive()) { m_gfx_actor->SetCastShadows(!inside); } } void Actor::ToggleLights() { // export light command - Actor* player_actor = App::GetSimController()->GetPlayerActor(); + Actor *player_actor = App::GetSimController()->GetPlayerActor(); if (ar_sim_state == Actor::SimState::LOCAL_SIMULATED && this == player_actor && ar_forward_commands) { for (auto actor : App::GetSimController()->GetActors()) @@ -3008,10 +2893,8 @@ void Actor::ToggleLights() if (ar_flares[i].fl_type == FlareType::HEADLIGHT) { ar_flares[i].snode->setVisible(false); - if (ar_flares[i].bbs) - ar_flares[i].snode->detachAllObjects(); - if (ar_flares[i].light) - ar_flares[i].light->setVisible(false); + if (ar_flares[i].bbs) ar_flares[i].snode->detachAllObjects(); + if (ar_flares[i].light) ar_flares[i].light->setVisible(false); ar_flares[i].isVisible = false; } } @@ -3022,11 +2905,9 @@ void Actor::ToggleLights() { if (ar_flares[i].fl_type == FlareType::HEADLIGHT) { - if (ar_flares[i].light) - ar_flares[i].light->setVisible(true); + if (ar_flares[i].light) ar_flares[i].light->setVisible(true); ar_flares[i].isVisible = true; - if (ar_flares[i].bbs) - ar_flares[i].snode->attachObject(ar_flares[i].bbs); + if (ar_flares[i].bbs) ar_flares[i].snode->attachObject(ar_flares[i].bbs); } } } @@ -3038,14 +2919,13 @@ void Actor::ToggleLights() void Actor::UpdateFlareStates(float dt) { - if (m_custom_light_toggle_countdown > -1) - m_custom_light_toggle_countdown -= dt; + if (m_custom_light_toggle_countdown > -1) m_custom_light_toggle_countdown -= dt; if (m_flares_mode == GfxFlaresMode::NONE) { return; } // NOTE: Beacon flares are now updated in GfxActor::UpdateBeaconFlares() - //the flares + // the flares bool keysleep = false; for (size_t i = 0; i < this->ar_flares.size(); i++) { @@ -3055,7 +2935,7 @@ void Actor::UpdateFlareStates(float dt) ar_flares[i].blinkdelay_curr -= dt; if (ar_flares[i].blinkdelay_curr <= 0) { - ar_flares[i].blinkdelay_curr = ar_flares[i].blinkdelay; + ar_flares[i].blinkdelay_curr = ar_flares[i].blinkdelay; ar_flares[i].blinkdelay_state = !ar_flares[i].blinkdelay_state; } } @@ -3065,13 +2945,12 @@ void Actor::UpdateFlareStates(float dt) } // manage light states - bool isvisible = true; //this must be true to be able to switch on the frontlight + bool isvisible = true; // this must be true to be able to switch on the frontlight // NOTE: headlight (type 'f') is updated if (ar_flares[i].fl_type == FlareType::HEADLIGHT) { // NOTE: Material flare is updated in GfxActor - if (!ar_lights) - continue; + if (!ar_lights) continue; } else if (ar_flares[i].fl_type == FlareType::BRAKE_LIGHT) { @@ -3084,15 +2963,18 @@ void Actor::UpdateFlareStates(float dt) else isvisible = false; } - else if (ar_flares[i].fl_type == FlareType::USER && ar_flares[i].controlnumber != -1) // controlnumber = read only attribute + else if (ar_flares[i].fl_type == FlareType::USER && + ar_flares[i].controlnumber != -1) // controlnumber = read only attribute { - if (ar_sim_state == Actor::SimState::LOCAL_SIMULATED && this == App::GetSimController()->GetPlayerActor()) // no network!! + if (ar_sim_state == Actor::SimState::LOCAL_SIMULATED && + this == App::GetSimController()->GetPlayerActor()) // no network!! { // networked customs are set directly, so skip this - if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_LIGHTTOGGLE01 + (ar_flares[i].controlnumber - 1)) && m_custom_light_toggle_countdown <= 0) + if (RoR::App::GetInputEngine()->getEventBoolValue(EV_TRUCK_LIGHTTOGGLE01 + (ar_flares[i].controlnumber - 1)) && + m_custom_light_toggle_countdown <= 0) { - ar_flares[i].controltoggle_status = ! ar_flares[i].controltoggle_status; - keysleep = true; + ar_flares[i].controltoggle_status = !ar_flares[i].controltoggle_status; + keysleep = true; } } isvisible = ar_flares[i].controltoggle_status; @@ -3112,8 +2994,7 @@ void Actor::UpdateFlareStates(float dt) { ar_left_blink_on = isvisible; - if (ar_left_blink_on) - SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_TURN_SIGNAL_TICK); + if (ar_left_blink_on) SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_TURN_SIGNAL_TICK); ar_dashboard->setBool(DD_SIGNAL_TURNLEFT, isvisible); } @@ -3121,8 +3002,7 @@ void Actor::UpdateFlareStates(float dt) { ar_right_blink_on = isvisible; - if (ar_right_blink_on) - SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_TURN_SIGNAL_TICK); + if (ar_right_blink_on) SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_TURN_SIGNAL_TICK); ar_dashboard->setBool(DD_SIGNAL_TURNRIGHT, isvisible); } @@ -3130,8 +3010,7 @@ void Actor::UpdateFlareStates(float dt) { ar_warn_blink_on = isvisible; - if (ar_warn_blink_on) - SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_TURN_SIGNAL_WARN_TICK); + if (ar_warn_blink_on) SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_TURN_SIGNAL_WARN_TICK); ar_dashboard->setBool(DD_SIGNAL_TURNRIGHT, isvisible); ar_dashboard->setBool(DD_SIGNAL_TURNLEFT, isvisible); @@ -3139,8 +3018,7 @@ void Actor::UpdateFlareStates(float dt) ar_flares[i].isVisible = isvisible; // 3D engine objects are updated in GfxActor } - if (keysleep) - m_custom_light_toggle_countdown = 0.2; + if (keysleep) m_custom_light_toggle_countdown = 0.2; } void Actor::toggleBlinkType(blinktype blink) @@ -3155,14 +3033,11 @@ void Actor::setBlinkType(blinktype blink) { m_blink_type = blink; - ar_left_blink_on = false; + ar_left_blink_on = false; ar_right_blink_on = false; - ar_warn_blink_on = false; + ar_warn_blink_on = false; - if (blink == BLINK_NONE) - { - SOUND_STOP(ar_instance_id, SS_TRIG_TURN_SIGNAL); - } + if (blink == BLINK_NONE) { SOUND_STOP(ar_instance_id, SS_TRIG_TURN_SIGNAL); } else { SOUND_START(ar_instance_id, SS_TRIG_TURN_SIGNAL); @@ -3175,7 +3050,7 @@ void Actor::autoBlinkReset() float blink_lock_range = 0.1f; if (m_blink_type == BLINK_LEFT && ar_hydro_dir_state < -blink_lock_range) - // passed the threshold: the turn signal gets locked + // passed the threshold: the turn signal gets locked m_blinker_autoreset = true; if (m_blink_type == BLINK_LEFT && m_blinker_autoreset && ar_hydro_dir_state > -blink_lock_range) @@ -3186,8 +3061,7 @@ void Actor::autoBlinkReset() } // same for the right turn signal - if (m_blink_type == BLINK_RIGHT && ar_hydro_dir_state > blink_lock_range) - m_blinker_autoreset = true; + if (m_blink_type == BLINK_RIGHT && ar_hydro_dir_state > blink_lock_range) m_blinker_autoreset = true; if (m_blink_type == BLINK_RIGHT && m_blinker_autoreset && ar_hydro_dir_state < blink_lock_range) { @@ -3212,24 +3086,24 @@ void Actor::ToggleCustomParticles() } } - //ScriptEvent - Particle Toggle + // ScriptEvent - Particle Toggle TRIGGER_EVENT(SE_TRUCK_CPARTICLES_TOGGLE, ar_instance_id); } void Actor::UpdateSoundSources() { #ifdef USE_OPENAL - if (SoundScriptManager::getSingleton().isDisabled()) - return; + if (SoundScriptManager::getSingleton().isDisabled()) return; for (int i = 0; i < ar_num_soundsources; i++) { // TODO: Investigate segfaults after terrain reloads ~ ulteq 11/2018 - ar_soundsources[i].ssi->setPosition(ar_nodes[ar_soundsources[i].nodenum].AbsPosition, ar_nodes[ar_soundsources[i].nodenum].Velocity); + ar_soundsources[i].ssi->setPosition(ar_nodes[ar_soundsources[i].nodenum].AbsPosition, + ar_nodes[ar_soundsources[i].nodenum].Velocity); } - //also this, so it is updated always, and for any vehicle + // also this, so it is updated always, and for any vehicle SOUND_MODULATE(ar_instance_id, SS_MOD_AIRSPEED, ar_nodes[0].Velocity.length() * 1.9438); SOUND_MODULATE(ar_instance_id, SS_MOD_WHEELSPEED, ar_wheel_speed * 3.6); -#endif //OPENAL +#endif // OPENAL } void Actor::updateVisual(float dt) @@ -3239,7 +3113,7 @@ void Actor::updateVisual(float dt) UpdateSoundSources(); #ifdef USE_OPENAL - //airplane radio chatter + // airplane radio chatter if (ar_driveable == AIRPLANE && ar_sim_state != SimState::LOCAL_SLEEPING) { // play random chatter at random time @@ -3250,7 +3124,7 @@ void Actor::updateVisual(float dt) m_avionic_chatter_timer = Math::RangeRandom(11, 30); } } -#endif //openAL +#endif // openAL // update exhausts // TODO: Move to GfxActor, don't forget dt*m_simulation_speed @@ -3259,11 +3133,10 @@ void Actor::updateVisual(float dt) std::vector::iterator it; for (it = exhausts.begin(); it != exhausts.end(); it++) { - if (!it->smoker) - continue; + if (!it->smoker) continue; Vector3 dir = ar_nodes[it->emitterNode].AbsPosition - ar_nodes[it->directionNode].AbsPosition; // dir.normalise(); - ParticleEmitter* emit = it->smoker->getEmitter(0); + ParticleEmitter *emit = it->smoker->getEmitter(0); it->smokeNode->setPosition(ar_nodes[it->emitterNode].AbsPosition); emit->setDirection(dir); if (ar_engine->GetSmoke() != -1.0) @@ -3281,75 +3154,58 @@ void Actor::updateVisual(float dt) } // Wings (only physics, graphics are updated in GfxActor) - float autoaileron = 0; - float autorudder = 0; + float autoaileron = 0; + float autorudder = 0; float autoelevator = 0; if (ar_autopilot) { ar_autopilot->UpdateIls(App::GetSimTerrain()->getObjectManager()->GetLocalizers()); - autoaileron = ar_autopilot->getAilerons(); - autorudder = ar_autopilot->getRudder(); + autoaileron = ar_autopilot->getAilerons(); + autorudder = ar_autopilot->getRudder(); autoelevator = ar_autopilot->getElevator(); ar_autopilot->gpws_update(ar_posnode_spawn_height); } autoaileron += ar_aileron; autorudder += ar_rudder; autoelevator += ar_elevator; - if (autoaileron < -1.0) - autoaileron = -1.0; - if (autoaileron > 1.0) - autoaileron = 1.0; - if (autorudder < -1.0) - autorudder = -1.0; - if (autorudder > 1.0) - autorudder = 1.0; - if (autoelevator < -1.0) - autoelevator = -1.0; - if (autoelevator > 1.0) - autoelevator = 1.0; + if (autoaileron < -1.0) autoaileron = -1.0; + if (autoaileron > 1.0) autoaileron = 1.0; + if (autorudder < -1.0) autorudder = -1.0; + if (autorudder > 1.0) autorudder = 1.0; + if (autoelevator < -1.0) autoelevator = -1.0; + if (autoelevator > 1.0) autoelevator = 1.0; for (int i = 0; i < ar_num_wings; i++) { - if (ar_wings[i].fa->type == 'a') - ar_wings[i].fa->setControlDeflection(autoaileron); - if (ar_wings[i].fa->type == 'b') - ar_wings[i].fa->setControlDeflection(-autoaileron); - if (ar_wings[i].fa->type == 'r') - ar_wings[i].fa->setControlDeflection(autorudder); + if (ar_wings[i].fa->type == 'a') ar_wings[i].fa->setControlDeflection(autoaileron); + if (ar_wings[i].fa->type == 'b') ar_wings[i].fa->setControlDeflection(-autoaileron); + if (ar_wings[i].fa->type == 'r') ar_wings[i].fa->setControlDeflection(autorudder); if (ar_wings[i].fa->type == 'e' || ar_wings[i].fa->type == 'S' || ar_wings[i].fa->type == 'T') ar_wings[i].fa->setControlDeflection(autoelevator); - if (ar_wings[i].fa->type == 'f') - ar_wings[i].fa->setControlDeflection(flapangles[ar_aerial_flap]); + if (ar_wings[i].fa->type == 'f') ar_wings[i].fa->setControlDeflection(flapangles[ar_aerial_flap]); if (ar_wings[i].fa->type == 'c' || ar_wings[i].fa->type == 'V') ar_wings[i].fa->setControlDeflection((autoaileron + autoelevator) / 2.0); if (ar_wings[i].fa->type == 'd' || ar_wings[i].fa->type == 'U') ar_wings[i].fa->setControlDeflection((-autoaileron + autoelevator) / 2.0); - if (ar_wings[i].fa->type == 'g') - ar_wings[i].fa->setControlDeflection((autoaileron + flapangles[ar_aerial_flap]) / 2.0); - if (ar_wings[i].fa->type == 'h') - ar_wings[i].fa->setControlDeflection((-autoaileron + flapangles[ar_aerial_flap]) / 2.0); - if (ar_wings[i].fa->type == 'i') - ar_wings[i].fa->setControlDeflection((-autoelevator + autorudder) / 2.0); - if (ar_wings[i].fa->type == 'j') - ar_wings[i].fa->setControlDeflection((autoelevator + autorudder) / 2.0); + if (ar_wings[i].fa->type == 'g') ar_wings[i].fa->setControlDeflection((autoaileron + flapangles[ar_aerial_flap]) / 2.0); + if (ar_wings[i].fa->type == 'h') ar_wings[i].fa->setControlDeflection((-autoaileron + flapangles[ar_aerial_flap]) / 2.0); + if (ar_wings[i].fa->type == 'i') ar_wings[i].fa->setControlDeflection((-autoelevator + autorudder) / 2.0); + if (ar_wings[i].fa->type == 'j') ar_wings[i].fa->setControlDeflection((autoelevator + autorudder) / 2.0); ar_wings[i].fa->updateVerticesPhysics(); // Actual graphics update moved to GfxActor } - //setup commands for hydros - ar_hydro_aileron_command = autoaileron; - ar_hydro_rudder_command = autorudder; + // setup commands for hydros + ar_hydro_aileron_command = autoaileron; + ar_hydro_rudder_command = autorudder; ar_hydro_elevator_command = autoelevator; } -void Actor::AddInterActorBeam(beam_t* beam, Actor* a, Actor* b) +void Actor::AddInterActorBeam(beam_t *beam, Actor *a, Actor *b) { beam->bm_locked_actor = b; auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam); - if (pos == ar_inter_beams.end()) - { - ar_inter_beams.push_back(beam); - } + if (pos == ar_inter_beams.end()) { ar_inter_beams.push_back(beam); } - std::pair actor_pair(a, b); + std::pair actor_pair(a, b); App::GetSimController()->GetBeamFactory()->inter_actor_links[beam] = actor_pair; a->DetermineLinkedActors(); @@ -3361,13 +3217,10 @@ void Actor::AddInterActorBeam(beam_t* beam, Actor* a, Actor* b) actor->DetermineLinkedActors(); } -void Actor::RemoveInterActorBeam(beam_t* beam) +void Actor::RemoveInterActorBeam(beam_t *beam) { auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam); - if (pos != ar_inter_beams.end()) - { - ar_inter_beams.erase(pos); - } + if (pos != ar_inter_beams.end()) { ar_inter_beams.erase(pos); } auto it = App::GetSimController()->GetBeamFactory()->inter_actor_links.find(beam); if (it != App::GetSimController()->GetBeamFactory()->inter_actor_links.end()) @@ -3395,8 +3248,8 @@ void Actor::DisjoinInterActorBeams() if (this == actor_pair.first || this == actor_pair.second) { it->first->bm_locked_actor = nullptr; - it->first->bm_inter_actor = false; - it->first->bm_disabled = true; + it->first->bm_inter_actor = false; + it->first->bm_disabled = true; inter_actor_links->erase(it++); actor_pair.first->DetermineLinkedActors(); @@ -3416,7 +3269,7 @@ void Actor::DisjoinInterActorBeams() void Actor::ToggleTies(int group) { - Actor* player_actor = App::GetSimController()->GetPlayerActor(); + Actor *player_actor = App::GetSimController()->GetPlayerActor(); // untie all ties if one is tied bool istied = false; @@ -3424,8 +3277,7 @@ void Actor::ToggleTies(int group) for (std::vector::iterator it = ar_ties.begin(); it != ar_ties.end(); it++) { // only handle ties with correct group - if (group != -1 && (it->ti_group != -1 && it->ti_group != group)) - continue; + if (group != -1 && (it->ti_group != -1 && it->ti_group != group)) continue; // if tied, untie it. And the other way round if (it->ti_tied) @@ -3433,14 +3285,13 @@ void Actor::ToggleTies(int group) istied = !it->ti_beam->bm_disabled; // tie is locked and should get unlocked and stop tying - it->ti_tied = false; + it->ti_tied = false; it->ti_tying = false; - if (it->ti_locked_ropable) - it->ti_locked_ropable->attached_ties--; + if (it->ti_locked_ropable) it->ti_locked_ropable->attached_ties--; // disable the ties beam - it->ti_beam->p2 = &ar_nodes[0]; + it->ti_beam->p2 = &ar_nodes[0]; it->ti_beam->bm_inter_actor = false; - it->ti_beam->bm_disabled = true; + it->ti_beam->bm_disabled = true; if (it->ti_locked_actor != this) { this->RemoveInterActorBeam(it->ti_beam); @@ -3476,44 +3327,38 @@ void Actor::ToggleTies(int group) for (std::vector::iterator it = ar_ties.begin(); it != ar_ties.end(); it++) { // only handle ties with correct group - if (group != -1 && (it->ti_group != -1 && it->ti_group != group)) - continue; + if (group != -1 && (it->ti_group != -1 && it->ti_group != group)) continue; if (!it->ti_tied) { // tie is unlocked and should get locked, search new remote ropable to lock to - float mindist = it->ti_beam->refL; - node_t* nearest_node = 0; - Actor* nearest_actor = 0; - ropable_t* locktedto = 0; + float mindist = it->ti_beam->refL; + node_t * nearest_node = 0; + Actor * nearest_actor = 0; + ropable_t *locktedto = 0; // iterate over all actors for (auto actor : App::GetSimController()->GetActors()) { - if (actor->ar_sim_state == SimState::LOCAL_SLEEPING || - (actor == this && it->ti_no_self_lock)) - { - continue; - } + if (actor->ar_sim_state == SimState::LOCAL_SLEEPING || (actor == this && it->ti_no_self_lock)) { continue; } // and their ropables - for (std::vector::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++) + for (std::vector::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); + itr++) { // if the ropable is not multilock and used, then discard this ropable - if (!itr->multilock && itr->attached_ties > 0) - continue; + if (!itr->multilock && itr->attached_ties > 0) continue; // skip if tienode is ropable too (no selflock) - if (this == actor && itr->node->pos == it->ti_beam->p1->pos) - continue; + if (this == actor && itr->node->pos == it->ti_beam->p1->pos) continue; // calculate the distance and record the nearest ropable float dist = (it->ti_beam->p1->AbsPosition - itr->node->AbsPosition).length(); if (dist < mindist) { - mindist = dist; - nearest_node = itr->node; + mindist = dist; + nearest_node = itr->node; nearest_actor = actor; - locktedto = &(*itr); + locktedto = &(*itr); } } } @@ -3523,14 +3368,14 @@ void Actor::ToggleTies(int group) // enable the beam and visually display the beam it->ti_beam->bm_disabled = false; // now trigger the tying action - it->ti_locked_actor = nearest_actor; - it->ti_beam->p2 = nearest_node; + it->ti_locked_actor = nearest_actor; + it->ti_beam->p2 = nearest_node; it->ti_beam->bm_inter_actor = nearest_actor != this; - it->ti_beam->stress = 0; - it->ti_beam->L = it->ti_beam->refL; - it->ti_tied = true; - it->ti_tying = true; - it->ti_locked_ropable = locktedto; + it->ti_beam->stress = 0; + it->ti_beam->L = it->ti_beam->refL; + it->ti_tied = true; + it->ti_tying = true; + it->ti_locked_ropable = locktedto; it->ti_locked_ropable->attached_ties++; if (it->ti_beam->bm_inter_actor) { @@ -3558,28 +3403,26 @@ void Actor::ToggleTies(int group) } } - //ScriptEvent - Tie toggle + // ScriptEvent - Tie toggle TRIGGER_EVENT(SE_TRUCK_TIE_TOGGLE, ar_instance_id); } void Actor::ToggleRopes(int group) { - Actor* player_actor = App::GetSimController()->GetPlayerActor(); + Actor *player_actor = App::GetSimController()->GetPlayerActor(); // iterate over all ropes for (std::vector::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++) { // only handle ropes with correct group - if (group != -1 && (it->rp_group != -1 && it->rp_group != group)) - continue; + if (group != -1 && (it->rp_group != -1 && it->rp_group != group)) continue; if (it->rp_locked == LOCKED || it->rp_locked == PRELOCK) { // we unlock ropes it->rp_locked = UNLOCKED; // remove node locking - if (it->rp_locked_ropable) - it->rp_locked_ropable->attached_ropes--; + if (it->rp_locked_ropable) it->rp_locked_ropable->attached_ropes--; if (it->rp_locked_actor != this) { this->RemoveInterActorBeam(it->rp_beam); @@ -3605,44 +3448,42 @@ void Actor::ToggleRopes(int group) } } } - it->rp_locked_actor = nullptr; + it->rp_locked_actor = nullptr; it->rp_locked_ropable = nullptr; } else { - //we lock ropes + // we lock ropes // search new remote ropable to lock to - float mindist = it->rp_beam->L; - Actor* nearest_actor = nullptr; - ropable_t* rop = 0; + float mindist = it->rp_beam->L; + Actor * nearest_actor = nullptr; + ropable_t *rop = 0; // iterate over all actor_slots for (auto actor : App::GetSimController()->GetActors()) { - if (actor->ar_sim_state == SimState::LOCAL_SLEEPING) - continue; + if (actor->ar_sim_state == SimState::LOCAL_SLEEPING) continue; // and their ropables for (std::vector::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++) { // if the ropable is not multilock and used, then discard this ropable - if (!itr->multilock && itr->attached_ropes > 0) - continue; + if (!itr->multilock && itr->attached_ropes > 0) continue; // calculate the distance and record the nearest ropable float dist = (it->rp_beam->p1->AbsPosition - itr->node->AbsPosition).length(); if (dist < mindist) { - mindist = dist; + mindist = dist; nearest_actor = actor; - rop = &(*itr); + rop = &(*itr); } } } // if we found a ropable, then lock it if (nearest_actor) { - //okay, we have found a rope to tie - it->rp_locked_actor = nearest_actor; - it->rp_locked = LOCKED; + // okay, we have found a rope to tie + it->rp_locked_actor = nearest_actor; + it->rp_locked = LOCKED; it->rp_locked_ropable = rop; it->rp_locked_ropable->attached_ropes++; if (nearest_actor != this) @@ -3678,74 +3519,64 @@ void Actor::ToggleHooks(int group, hook_states mode, int node_number) { if (mode == MOUSE_HOOK_TOGGLE && it->hk_hook_node->pos != node_number) { - //skip all other nodes except the one manually toggled by mouse + // skip all other nodes except the one manually toggled by mouse continue; } if (mode == HOOK_TOGGLE && group == -1) { - //manually triggerd (EV_COMMON_LOCK). Toggle all hooks groups with group#: -1, 0, 1 ++ - if (it->hk_group <= -2) - continue; + // manually triggerd (EV_COMMON_LOCK). Toggle all hooks groups with group#: -1, 0, 1 ++ + if (it->hk_group <= -2) continue; } if (mode == HOOK_LOCK && group == -2) { - //automatic lock attempt (cyclic with doupdate). Toggle all hooks groups with group#: -2, -3, -4 --, skip the ones which are not autolock (triggered only) - if (it->hk_group >= -1 || !it->hk_autolock) - continue; + // automatic lock attempt (cyclic with doupdate). Toggle all hooks groups with group#: -2, -3, -4 --, skip the ones + // which are not autolock (triggered only) + if (it->hk_group >= -1 || !it->hk_autolock) continue; } if (mode == HOOK_UNLOCK && group == -2) { - //manual unlock ALL autolock and triggerlock, do not unlock standard hooks (EV_COMMON_AUTOLOCK) - if (it->hk_group >= -1 || !it->hk_autolock) - continue; + // manual unlock ALL autolock and triggerlock, do not unlock standard hooks (EV_COMMON_AUTOLOCK) + if (it->hk_group >= -1 || !it->hk_autolock) continue; } if ((mode == HOOK_LOCK || mode == HOOK_UNLOCK) && group <= -3) { - //trigger beam lock or unlock. Toggle one hook group with group#: group - if (it->hk_group != group) - continue; - } - if ((mode == HOOK_LOCK || mode == HOOK_UNLOCK) && group >= -1) - { - continue; + // trigger beam lock or unlock. Toggle one hook group with group#: group + if (it->hk_group != group) continue; } + if ((mode == HOOK_LOCK || mode == HOOK_UNLOCK) && group >= -1) { continue; } if (mode == HOOK_LOCK && it->hk_timer > 0.0f) { - //check relock delay timer for autolock nodes and skip if not 0 + // check relock delay timer for autolock nodes and skip if not 0 continue; } - Actor* prev_locked_actor = it->hk_locked_actor; // memorize current value + Actor *prev_locked_actor = it->hk_locked_actor; // memorize current value // do this only for toggle or lock attempts, skip prelocked or locked nodes for performance if (mode != HOOK_UNLOCK && it->hk_locked == UNLOCKED) { // we lock hooks // search new remote ropable to lock to - float mindist = it->hk_lockrange; + float mindist = it->hk_lockrange; float distance = 100000000.0f; // iterate over all actor_slots for (auto actor : App::GetSimController()->GetActors()) { - if (actor->ar_sim_state == SimState::LOCAL_SLEEPING) - continue; - if (this == actor && !it->hk_selflock) - continue; // don't lock to self + if (actor->ar_sim_state == SimState::LOCAL_SLEEPING) continue; + if (this == actor && !it->hk_selflock) continue; // don't lock to self - node_t* nearest_node = nullptr; + node_t *nearest_node = nullptr; for (int i = 0; i < actor->ar_num_nodes; i++) { // skip all nodes with lockgroup 9999 (deny lock) - if (actor->ar_nodes[i].nd_lockgroup == 9999) - continue; + if (actor->ar_nodes[i].nd_lockgroup == 9999) continue; // exclude this truck and its current hooknode from the locking search - if (this == actor && i == it->hk_hook_node->pos) - continue; + if (this == actor && i == it->hk_hook_node->pos) continue; - // a lockgroup for this hooknode is set -> skip all nodes that do not have the same lockgroup (-1 = default(all nodes)) - if (it->hk_lockgroup != -1 && it->hk_lockgroup != actor->ar_nodes[i].nd_lockgroup) - continue; + // a lockgroup for this hooknode is set -> skip all nodes that do not have the same lockgroup (-1 = + // default(all nodes)) + if (it->hk_lockgroup != -1 && it->hk_lockgroup != actor->ar_nodes[i].nd_lockgroup) continue; // measure distance float n2n_distance = (it->hk_hook_node->AbsPosition - actor->ar_nodes[i].AbsPosition).length(); @@ -3754,7 +3585,7 @@ void Actor::ToggleHooks(int group, hook_states mode, int node_number) if (distance >= n2n_distance) { // located a node that is closer - distance = n2n_distance; + distance = n2n_distance; nearest_node = &actor->ar_nodes[i]; } } @@ -3762,28 +3593,29 @@ void Actor::ToggleHooks(int group, hook_states mode, int node_number) if (nearest_node) { // we found a node, lock to it - it->hk_lock_node = nearest_node; + it->hk_lock_node = nearest_node; it->hk_locked_actor = actor; - it->hk_locked = PRELOCK; + it->hk_locked = PRELOCK; } } } - // this is a locked or prelocked hook and its not a locking attempt or the locked actor was removed (bm_inter_actor == false) + // this is a locked or prelocked hook and its not a locking attempt or the locked actor was removed (bm_inter_actor == + // false) else if ((it->hk_locked == LOCKED || it->hk_locked == PRELOCK) && (mode != HOOK_LOCK || !it->hk_beam->bm_inter_actor)) { // we unlock ropes it->hk_locked = PREUNLOCK; if (it->hk_group <= -2) { - it->hk_timer = it->hk_timer_preset; //timer reset for autolock nodes + it->hk_timer = it->hk_timer_preset; // timer reset for autolock nodes } - it->hk_lock_node = 0; + it->hk_lock_node = 0; it->hk_locked_actor = 0; - //disable hook-assistance beam - it->hk_beam->p2 = &ar_nodes[0]; + // disable hook-assistance beam + it->hk_beam->p2 = &ar_nodes[0]; it->hk_beam->bm_inter_actor = false; - it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length(); - it->hk_beam->bm_disabled = true; + it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length(); + it->hk_beam->bm_disabled = true; } // update skeletonview on the (un)hooked actor @@ -3818,20 +3650,18 @@ void Actor::ToggleParkingBrake() else SOUND_STOP(ar_instance_id, SS_TRIG_PARK); - //ScriptEvent - Parking Brake toggle + // ScriptEvent - Parking Brake toggle TRIGGER_EVENT(SE_TRUCK_PARKINGBREAK_TOGGLE, ar_instance_id); } void Actor::ToggleAntiLockBrake() { - if (!alb_notoggle) - alb_mode = !alb_mode; + if (!alb_notoggle) alb_mode = !alb_mode; } void Actor::ToggleTractionControl() { - if (!tc_notoggle) - tc_mode = !tc_mode; + if (!tc_notoggle) tc_mode = !tc_mode; } void Actor::ToggleCruiseControl() @@ -3841,37 +3671,33 @@ void Actor::ToggleCruiseControl() if (cc_mode) { cc_target_speed = ar_avg_wheel_speed; - cc_target_rpm = ar_engine->GetEngineRpm(); + cc_target_rpm = ar_engine->GetEngineRpm(); } else { cc_target_speed = 0; - cc_target_rpm = 0; + cc_target_rpm = 0; cc_accs.clear(); } } void Actor::ToggleBeacons() { - if (m_flares_mode == GfxFlaresMode::NONE) - { - return; - } + if (m_flares_mode == GfxFlaresMode::NONE) { return; } m_beacon_light_is_active = !m_beacon_light_is_active; - //ScriptEvent - Beacon toggle + // ScriptEvent - Beacon toggle TRIGGER_EVENT(SE_TRUCK_BEACONS_TOGGLE, ar_instance_id); } void Actor::setReplayMode(bool rm) { - if (!m_replay_handler || !m_replay_handler->isValid()) - return; + if (!m_replay_handler || !m_replay_handler->isValid()) return; if (ar_replay_mode && !rm) { - ar_replay_pos = 0; + ar_replay_pos = 0; m_replay_pos_prev = -1; } @@ -3881,11 +3707,9 @@ void Actor::setReplayMode(bool rm) bool Actor::getReverseLightVisible() { - if (ar_sim_state == SimState::NETWORKED_OK) - return m_net_reverse_light; + if (ar_sim_state == SimState::NETWORKED_OK) return m_net_reverse_light; - if (ar_engine) - return (ar_engine->GetGear() < 0); + if (ar_engine) return (ar_engine->GetGear() < 0); return m_reverse_light_active; } @@ -3895,8 +3719,7 @@ void Actor::StopAllSounds() #ifdef USE_OPENAL for (int i = 0; i < ar_num_soundsources; i++) { - if (ar_soundsources[i].ssi) - ar_soundsources[i].ssi->setEnabled(false); + if (ar_soundsources[i].ssi) ar_soundsources[i].ssi->setEnabled(false); } #endif // USE_OPENAL } @@ -3924,17 +3747,16 @@ void Actor::NotifyActorCameraChanged() #endif // USE_OPENAL // NOTE: Prop visibility now updated in GfxActor::UpdateProps() ~ only_a_ptr, 06/2018 - - } -//Returns the number of active (non bounded) beams connected to a node +// Returns the number of active (non bounded) beams connected to a node int Actor::GetNumActiveConnectedBeams(int nodeid) { int totallivebeams = 0; for (unsigned int ni = 0; ni < ar_node_to_beam_connections[nodeid].size(); ++ni) { - if (!ar_beams[ar_node_to_beam_connections[nodeid][ni]].bm_disabled && !ar_beams[ar_node_to_beam_connections[nodeid][ni]].bounded) + if (!ar_beams[ar_node_to_beam_connections[nodeid][ni]].bm_disabled && + !ar_beams[ar_node_to_beam_connections[nodeid][ni]].bounded) totallivebeams++; } return totallivebeams; @@ -3943,23 +3765,20 @@ int Actor::GetNumActiveConnectedBeams(int nodeid) bool Actor::isTied() { for (std::vector::iterator it = ar_ties.begin(); it != ar_ties.end(); it++) - if (it->ti_tied) - return true; + if (it->ti_tied) return true; return false; } bool Actor::isLocked() { for (std::vector::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++) - if (it->hk_locked == LOCKED) - return true; + if (it->hk_locked == LOCKED) return true; return false; } void Actor::updateDashBoards(float dt) { - if (!ar_dashboard) - return; + if (!ar_dashboard) return; // some temp vars Vector3 dir; @@ -3997,7 +3816,7 @@ void Actor::updateDashBoards(float dt) } else { - //str = "#b8b8b8M\na\nn\nu\na\nl"; + // str = "#b8b8b8M\na\nn\nu\na\nl"; str = "#b8b8b8M\na\nn\nu"; } ar_dashboard->setChar(DD_ENGINE_AUTOGEAR_STRING, str.c_str()); @@ -4043,10 +3862,7 @@ void Actor::updateDashBoards(float dt) // speedo float velocity = ar_nodes[0].Velocity.length(); - if (cam_dir != Vector3::ZERO) - { - velocity = cam_dir.dotProduct(ar_nodes[0].Velocity); - } + if (cam_dir != Vector3::ZERO) { velocity = cam_dir.dotProduct(ar_nodes[0].Velocity); } float speed_kph = velocity * 3.6f; ar_dashboard->setFloat(DD_ENGINE_SPEEDO_KPH, speed_kph); float speed_mph = velocity * 2.23693629f; @@ -4056,10 +3872,8 @@ void Actor::updateDashBoards(float dt) if (cam_roll != Vector3::ZERO) { float angle = asin(cam_roll.dotProduct(Vector3::UNIT_Y)); - if (angle < -1) - angle = -1; - if (angle > 1) - angle = 1; + if (angle < -1) angle = -1; + if (angle > 1) angle = 1; float f = Radian(angle).valueDegrees(); ar_dashboard->setFloat(DD_ROLL, f); @@ -4069,7 +3883,7 @@ void Actor::updateDashBoards(float dt) if (this->ar_has_active_shocks) { // TOFIX: certainly not working: - float roll_corr = - m_stabilizer_shock_ratio * 10.0f; + float roll_corr = -m_stabilizer_shock_ratio * 10.0f; ar_dashboard->setFloat(DD_ROLL_CORR, roll_corr); bool corr_active = (m_stabilizer_shock_request > 0); @@ -4080,10 +3894,8 @@ void Actor::updateDashBoards(float dt) if (cam_dir != Vector3::ZERO) { float angle = asin(cam_dir.dotProduct(Vector3::UNIT_Y)); - if (angle < -1) - angle = -1; - if (angle > 1) - angle = 1; + if (angle < -1) angle = -1; + if (angle > 1) angle = 1; float f = Radian(angle).valueDegrees(); ar_dashboard->setFloat(DD_PITCH, f); @@ -4161,8 +3973,8 @@ void Actor::updateDashBoards(float dt) ar_dashboard->setFloat(DD_WATER_DEPTH, depth); // water speed - Vector3 hdir = this->GetCameraDir(); - float knots = hdir.dotProduct(ar_nodes[ar_main_camera_node_pos].Velocity) * 1.9438f; // 1.943 = m/s in knots/s + Vector3 hdir = this->GetCameraDir(); + float knots = hdir.dotProduct(ar_nodes[ar_main_camera_node_pos].Velocity) * 1.9438f; // 1.943 = m/s in knots/s ar_dashboard->setFloat(DD_WATER_SPEED, knots); } @@ -4196,19 +4008,19 @@ void Actor::updateDashBoards(float dt) // some things only activate when a wing or an aeroengine is present if (ar_num_wings || ar_num_aeroengines) { - //airspeed + // airspeed { float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438f; // 1.943 = m/s in knots/s - //tropospheric model valid up to 11.000m (33.000ft) + // tropospheric model valid up to 11.000m (33.000ft) float altitude = ar_nodes[0].AbsPosition.y; - //float sea_level_temperature = 273.15 + 15.0; //in Kelvin // MAGICs D: - float sea_level_pressure = 101325; //in Pa - //float airtemperature = sea_level_temperature - altitude * 0.0065f; //in Kelvin - float airpressure = sea_level_pressure * pow(1.0f - 0.0065f * altitude / 288.15f, 5.24947f); //in Pa - float airdensity = airpressure * 0.0000120896f; //1.225 at sea level + // float sea_level_temperature = 273.15 + 15.0; //in Kelvin // MAGICs D: + float sea_level_pressure = 101325; // in Pa + // float airtemperature = sea_level_temperature - altitude * 0.0065f; //in Kelvin + float airpressure = sea_level_pressure * pow(1.0f - 0.0065f * altitude / 288.15f, 5.24947f); // in Pa + float airdensity = airpressure * 0.0000120896f; // 1.225 at sea level - float knots = ground_speed_kt * sqrt(airdensity / 1.225f); //KIAS + float knots = ground_speed_kt * sqrt(airdensity / 1.225f); // KIAS ar_dashboard->setFloat(DD_AIRSPEED, knots); } @@ -4229,13 +4041,13 @@ void Actor::updateDashBoards(float dt) // set the features of this vehicle once if (!m_hud_features_ok) { - bool hasEngine = (ar_engine != nullptr); - bool hasturbo = false; + bool hasEngine = (ar_engine != nullptr); + bool hasturbo = false; bool autogearVisible = false; if (hasEngine) { - hasturbo = ar_engine->HasTurbo(); + hasturbo = ar_engine->HasTurbo(); autogearVisible = (ar_engine->getAutoShift() != EngineSim::MANUALMODE); } @@ -4368,7 +4180,7 @@ void Actor::updateDashBoards(float dt) if (ftp>3 && curr_truck->aeroengines[3]->getIgnition()) RoR::App::GetOverlayWrapper()->engstarto4->setMaterialName("tracks/engstart-on"); else RoR::App::GetOverlayWrapper()->engstarto4->setMaterialName("tracks/engstart-off"); } -#endif //0 +#endif // 0 ar_dashboard->update(dt); } @@ -4397,188 +4209,93 @@ void Actor::calculateLocalGForces() void Actor::EngineTriggerHelper(int engineNumber, int type, float triggerValue) { // engineNumber tells us which engine - EngineSim* e = ar_engine; // placeholder: actors do not have multiple engines yet + EngineSim *e = ar_engine; // placeholder: actors do not have multiple engines yet switch (type) { case TRG_ENGINE_CLUTCH: - if (e) - e->SetClutch(triggerValue); - break; - case TRG_ENGINE_BRAKE: - ar_brake = triggerValue; + if (e) e->SetClutch(triggerValue); break; + case TRG_ENGINE_BRAKE: ar_brake = triggerValue; break; case TRG_ENGINE_ACC: - if (e) - e->SetAcceleration(triggerValue); + if (e) e->SetAcceleration(triggerValue); break; case TRG_ENGINE_RPM: // TODO: Implement setTargetRPM in the EngineSim.cpp break; case TRG_ENGINE_SHIFTUP: - if (e) - e->shift(1); + if (e) e->shift(1); break; case TRG_ENGINE_SHIFTDOWN: - if (e) - e->shift(-1); - break; - default: + if (e) e->shift(-1); break; + default: break; } } -Actor::Actor( - int actor_id, - unsigned int vector_index, - std::shared_ptr def, - RoR::ActorSpawnRequest rq -) - : ar_nodes(nullptr), ar_num_nodes(0) - , ar_beams(nullptr), ar_num_beams(0) - , ar_shocks(nullptr), ar_num_shocks(0) - , ar_has_active_shocks(false) - , ar_rotators(nullptr), ar_num_rotators(0) - , ar_wings(nullptr), ar_num_wings(0) - , m_hud_features_ok(false) - , ar_aileron(0) - , m_avionic_chatter_timer(11.0f) // some pseudo random number, doesn't matter - , m_beacon_light_is_active(false) - , m_blink_type(BLINK_NONE) - , m_blinker_autoreset(false) - , ar_brake(0.0) - , m_camera_gforces_accu(Ogre::Vector3::ZERO) - , m_camera_gforces(Ogre::Vector3::ZERO) - , m_camera_local_gforces_cur(Ogre::Vector3::ZERO) - , m_camera_local_gforces_max(Ogre::Vector3::ZERO) - , ar_engine_hydraulics_ready(true) - , m_custom_particles_enabled(false) - , ar_scale(1) - , ar_current_cinecam(-1) // -1 = external - , ar_dashboard(nullptr) - , ar_disable_aerodyn_turbulent_drag(false) - , ar_elevator(0) - , ar_aerial_flap(0) - , ar_fusedrag(Ogre::Vector3::ZERO) - , ar_hydro_aileron_command(0) - , ar_hydro_aileron_state(0) - , ar_hydro_dir_command(0) - , ar_hydro_dir_state(0) - , ar_hydro_dir_wheel_display(0.0) - , ar_hydro_elevator_command(0) - , ar_hydro_elevator_state(0) - , ar_hydro_rudder_command(0) - , ar_hydro_rudder_state(0) - , ar_nb_initialized(false) - , ar_nb_skip_steps(0) - , ar_nb_measure_steps(500) - , ar_nb_optimum(7, std::numeric_limits::max()) - , ar_nb_reference(7, std::numeric_limits::max()) - , ar_nb_mass_scale(1.0f) - , ar_nb_beams_scale(std::make_pair(1.0f, 1.0f)) - , ar_nb_shocks_scale(std::make_pair(1.0f, 1.0f)) - , ar_nb_wheels_scale(std::make_pair(1.0f, 1.0f)) - , ar_nb_beams_k_interval(std::make_pair(0.1f, 2.0f)) - , ar_nb_beams_d_interval(std::make_pair(0.1f, 2.0f)) - , ar_nb_shocks_k_interval(std::make_pair(0.1f, 8.0f)) - , ar_nb_shocks_d_interval(std::make_pair(0.1f, 8.0f)) - , ar_nb_wheels_k_interval(std::make_pair(1.0f, 1.0f)) - , ar_nb_wheels_d_interval(std::make_pair(1.0f, 1.0f)) - , m_inter_point_col_detector(nullptr) - , m_intra_point_col_detector(nullptr) - , ar_net_last_update_time(0) - , m_avg_node_position_prev(rq.asr_position) - , ar_left_mirror_angle(0.52) - , ar_lights(1) - , m_avg_node_velocity(Ogre::Vector3::ZERO) - , ar_custom_camera_node(-1) - , ar_main_camera_dir_corr(Ogre::Quaternion::IDENTITY) - , ar_main_camera_node_pos(0) - , ar_main_camera_node_dir(0) - , ar_main_camera_node_roll(0) - , m_preloaded_with_terrain(rq.asr_origin == RoR::ActorSpawnRequest::Origin::TERRN_DEF) - , ar_net_source_id(0) - , m_spawn_rotation(0.0) - , ar_net_stream_id(0) - , m_custom_light_toggle_countdown(0) - , m_min_camera_radius(0.0f) - , m_mouse_grab_move_force(0.0f) - , m_mouse_grab_node(-1) - , m_mouse_grab_pos(Ogre::Vector3::ZERO) - , m_net_initialized(false) - , m_net_brake_light(false) - , m_net_label_node(0) - , m_net_label_mt(0) - , m_net_reverse_light(false) - , ar_initial_total_mass(0) - , m_replay_pos_prev(-1) - , ar_parking_brake(false) - , ar_trailer_parking_brake(false) - , m_avg_node_position(rq.asr_position) - , m_previous_gear(0) - , m_ref_tyre_pressure(50.0) - , m_replay_handler(nullptr) - , ar_replay_precision(0) - , m_replay_timer(0) - , ar_replay_length(10000) - , ar_replay_mode(false) - , ar_replay_pos(0) - , m_reverse_light_active(false) - , ar_right_mirror_angle(-0.52) - , ar_rudder(0) - , ar_update_physics(false) - , ar_sleep_counter(0.0f) - , m_stabilizer_shock_request(0) - , m_stabilizer_shock_ratio(0.0) - , m_stabilizer_shock_sleep(0.0) - , m_total_mass(0) - , m_water_contact(false) - , m_water_contact_old(false) - , m_num_axle_diffs(0) - , m_axle_diffs{} // Init array to nullptr - , m_num_wheel_diffs(0) - , m_wheel_diffs{} // Init array to nullptr - , m_has_command_beams(false) - , m_num_command_beams(0) - , m_load_mass(0.f) - , m_dry_mass(0.f) - , ar_gui_use_engine_max_rpm(false) - , ar_autopilot(nullptr) - , ar_is_police(false) - , m_disable_default_sounds(false) - , ar_engine(nullptr) - , ar_driveable(NOT_DRIVEABLE) - , m_skid_trails{} // Init array to nullptr - , ar_collision_range(DEFAULT_COLLISION_RANGE) - , ar_instance_id(actor_id) - , ar_vector_index(vector_index) - , ar_rescuer_flag(false) - , m_antilockbrake(false) - , m_tractioncontrol(false) - , ar_forward_commands(false) - , ar_import_commands(false) - , ar_toggle_ties(false) - , ar_airbrakes{} // Init array to nullptr - , ar_cabs{} // Init array to 0 - , ar_num_cabs(0) - , ar_num_contactable_nodes(0) - , ar_num_contacters(0) - , ar_screwprops{} // Init array to nullptr - , ar_num_screwprops(0) - , ar_num_camera_rails(0) - , ar_aeroengines() // Zero-init array - , ar_num_aeroengines() // Zero-init - , ar_pressure_beams() // Zero-init array - , ar_free_pressure_beam() // Zero-init - , ar_wheels() // array - , ar_num_wheels() // int - , m_avg_proped_wheel_radius(0.2f) - , ar_filename(rq.asr_filename) - , m_section_config(rq.asr_config) - , m_ongoing_reset(false) - , ar_top_speed(0.0f) - , ar_last_fuzzy_ground_model(nullptr) - , m_transfer_case(nullptr) +Actor::Actor(int actor_id, unsigned int vector_index, std::shared_ptr def, RoR::ActorSpawnRequest rq) + : ar_nodes(nullptr), ar_num_nodes(0), ar_beams(nullptr), ar_num_beams(0), ar_shocks(nullptr), ar_num_shocks(0), + ar_has_active_shocks(false), ar_rotators(nullptr), ar_num_rotators(0), ar_wings(nullptr), ar_num_wings(0), + m_hud_features_ok(false), ar_aileron(0), m_avionic_chatter_timer(11.0f) // some pseudo random number, doesn't matter + , + m_beacon_light_is_active(false), m_blink_type(BLINK_NONE), m_blinker_autoreset(false), ar_brake(0.0), + m_camera_gforces_accu(Ogre::Vector3::ZERO), m_camera_gforces(Ogre::Vector3::ZERO), + m_camera_local_gforces_cur(Ogre::Vector3::ZERO), m_camera_local_gforces_max(Ogre::Vector3::ZERO), + ar_engine_hydraulics_ready(true), m_custom_particles_enabled(false), ar_scale(1), ar_current_cinecam(-1) // -1 = external + , + ar_dashboard(nullptr), ar_disable_aerodyn_turbulent_drag(false), ar_elevator(0), ar_aerial_flap(0), + ar_fusedrag(Ogre::Vector3::ZERO), ar_hydro_aileron_command(0), ar_hydro_aileron_state(0), ar_hydro_dir_command(0), + ar_hydro_dir_state(0), ar_hydro_dir_wheel_display(0.0), ar_hydro_elevator_command(0), ar_hydro_elevator_state(0), + ar_hydro_rudder_command(0), ar_hydro_rudder_state(0), ar_nb_initialized(false), ar_nb_skip_steps(0), + ar_nb_measure_steps(500), ar_nb_optimum(7, std::numeric_limits::max()), + ar_nb_reference(7, std::numeric_limits::max()), ar_nb_mass_scale(1.0f), + ar_nb_beams_scale(std::make_pair(1.0f, 1.0f)), ar_nb_shocks_scale(std::make_pair(1.0f, 1.0f)), + ar_nb_wheels_scale(std::make_pair(1.0f, 1.0f)), ar_nb_beams_k_interval(std::make_pair(0.1f, 2.0f)), + ar_nb_beams_d_interval(std::make_pair(0.1f, 2.0f)), ar_nb_shocks_k_interval(std::make_pair(0.1f, 8.0f)), + ar_nb_shocks_d_interval(std::make_pair(0.1f, 8.0f)), ar_nb_wheels_k_interval(std::make_pair(1.0f, 1.0f)), + ar_nb_wheels_d_interval(std::make_pair(1.0f, 1.0f)), m_inter_point_col_detector(nullptr), + m_intra_point_col_detector(nullptr), ar_net_last_update_time(0), m_avg_node_position_prev(rq.asr_position), + ar_left_mirror_angle(0.52), ar_lights(1), m_avg_node_velocity(Ogre::Vector3::ZERO), ar_custom_camera_node(-1), + ar_main_camera_dir_corr(Ogre::Quaternion::IDENTITY), ar_main_camera_node_pos(0), ar_main_camera_node_dir(0), + ar_main_camera_node_roll(0), m_preloaded_with_terrain(rq.asr_origin == RoR::ActorSpawnRequest::Origin::TERRN_DEF), + ar_net_source_id(0), m_spawn_rotation(0.0), ar_net_stream_id(0), m_custom_light_toggle_countdown(0), + m_min_camera_radius(0.0f), m_mouse_grab_move_force(0.0f), m_mouse_grab_node(-1), m_mouse_grab_pos(Ogre::Vector3::ZERO), + m_net_initialized(false), m_net_brake_light(false), m_net_label_node(0), m_net_label_mt(0), m_net_reverse_light(false), + ar_initial_total_mass(0), m_replay_pos_prev(-1), ar_parking_brake(false), ar_trailer_parking_brake(false), + m_avg_node_position(rq.asr_position), m_previous_gear(0), m_ref_tyre_pressure(50.0), m_replay_handler(nullptr), + ar_replay_precision(0), m_replay_timer(0), ar_replay_length(10000), ar_replay_mode(false), ar_replay_pos(0), + m_reverse_light_active(false), ar_right_mirror_angle(-0.52), ar_rudder(0), ar_update_physics(false), ar_sleep_counter(0.0f), + m_stabilizer_shock_request(0), m_stabilizer_shock_ratio(0.0), m_stabilizer_shock_sleep(0.0), m_total_mass(0), + m_water_contact(false), m_water_contact_old(false), m_num_axle_diffs(0), m_axle_diffs{} // Init array to nullptr + , + m_num_wheel_diffs(0), m_wheel_diffs{} // Init array to nullptr + , + m_has_command_beams(false), m_num_command_beams(0), m_load_mass(0.f), m_dry_mass(0.f), ar_gui_use_engine_max_rpm(false), + ar_autopilot(nullptr), ar_is_police(false), m_disable_default_sounds(false), ar_engine(nullptr), + ar_driveable(NOT_DRIVEABLE), m_skid_trails{} // Init array to nullptr + , + ar_collision_range(DEFAULT_COLLISION_RANGE), ar_instance_id(actor_id), ar_vector_index(vector_index), + ar_rescuer_flag(false), m_antilockbrake(false), m_tractioncontrol(false), ar_forward_commands(false), + ar_import_commands(false), ar_toggle_ties(false), ar_airbrakes{} // Init array to nullptr + , + ar_cabs{} // Init array to 0 + , + ar_num_cabs(0), ar_num_contactable_nodes(0), ar_num_contacters(0), ar_screwprops{} // Init array to nullptr + , + ar_num_screwprops(0), ar_num_camera_rails(0), ar_aeroengines() // Zero-init array + , + ar_num_aeroengines() // Zero-init + , + ar_pressure_beams() // Zero-init array + , + ar_free_pressure_beam() // Zero-init + , + ar_wheels() // array + , + ar_num_wheels() // int + , + m_avg_proped_wheel_radius(0.2f), ar_filename(rq.asr_filename), m_section_config(rq.asr_config), m_ongoing_reset(false), + ar_top_speed(0.0f), ar_last_fuzzy_ground_model(nullptr), m_transfer_case(nullptr) { } @@ -4604,8 +4321,7 @@ void Actor::setMass(float m) bool Actor::getBrakeLightVisible() { - if (ar_sim_state == SimState::NETWORKED_OK) - return m_net_brake_light; + if (ar_sim_state == SimState::NETWORKED_OK) return m_net_brake_light; return (ar_brake > 0.01f && !ar_parking_brake); } @@ -4633,10 +4349,7 @@ void Actor::setCustomLightVisible(int number, bool visible) unsigned int flareID = m_net_custom_lights[number]; - if (flareID < ar_flares.size() && ar_flares[flareID].snode) - { - ar_flares[flareID].controltoggle_status = visible; - } + if (flareID < ar_flares.size() && ar_flares[flareID].snode) { ar_flares[flareID].controltoggle_status = visible; } } bool Actor::getBeaconMode() // Angelscript export @@ -4659,17 +4372,14 @@ Ogre::Real Actor::getMinimalCameraRadius() return m_min_camera_radius; } -Replay* Actor::getReplay() +Replay *Actor::getReplay() { return m_replay_handler; } Vector3 Actor::getNodePosition(int nodeNumber) { - if (nodeNumber >= 0 && nodeNumber < ar_num_nodes) - { - return ar_nodes[nodeNumber].AbsPosition; - } + if (nodeNumber >= 0 && nodeNumber < ar_num_nodes) { return ar_nodes[nodeNumber].AbsPosition; } else { return Ogre::Vector3(); diff --git a/source/main/physics/Beam.h b/source/main/physics/Beam.h index b5d7c10d9f..65aa47776c 100644 --- a/source/main/physics/Beam.h +++ b/source/main/physics/Beam.h @@ -21,14 +21,13 @@ #pragma once -#include "RoRPrerequisites.h" - #include "Application.h" #include "BeamData.h" #include "CmdKeyInertia.h" #include "GfxActor.h" #include "PerVehicleCameraContext.h" #include "RigDef_Prerequisites.h" +#include "RoRPrerequisites.h" #include @@ -40,508 +39,597 @@ class Actor : public ZeroedMemoryAllocator friend class ActorSpawner; friend class RoR::ActorManager; friend class RoR::GfxActor; // Temporary until all visuals are moved there. ~ only_a_ptr, 2018 -public: - + public: enum class SimState { - LOCAL_SIMULATED, //!< simulated (local) actor - NETWORKED_OK, //!< not simulated (remote) actor - LOCAL_SLEEPING, //!< sleeping (local) actor + LOCAL_SIMULATED, //!< simulated (local) actor + NETWORKED_OK, //!< not simulated (remote) actor + LOCAL_SLEEPING, //!< sleeping (local) actor }; - Actor( - int actor_id - , unsigned int vector_index - , std::shared_ptr def - , RoR::ActorSpawnRequest rq - ); + Actor(int actor_id, unsigned int vector_index, std::shared_ptr def, RoR::ActorSpawnRequest rq); ~Actor(); - void ApplyNodeBeamScales(); - void PushNetwork(char* data, int size); //!< Parses network data; fills actor's data buffers and flips them. Called by the network thread. - void CalcNetwork(); - bool AddTyrePressure(float v); - float GetTyrePressure(); - float getRotation(); - Ogre::Vector3 getDirection(); - Ogre::Vector3 getPosition(); - void UpdateInitPosition(); + void ApplyNodeBeamScales(); + void PushNetwork(char *data, + int size); //!< Parses network data; fills actor's data buffers and flips them. Called by the network thread. + void CalcNetwork(); + bool AddTyrePressure(float v); + float GetTyrePressure(); + float getRotation(); + Ogre::Vector3 getDirection(); + Ogre::Vector3 getPosition(); + void UpdateInitPosition(); /// Moves the actor. /// @param translation Offset to move in world coordinates /// @param setInitPosition Set initial positions of nodes to current position? - void ResetPosition(Ogre::Vector3 translation, bool setInitPosition); - void ResetPosition(float px, float pz, bool setInitPosition, float miny); - void RequestRotation(float rotation, Ogre::Vector3 center) { m_rotation_request += rotation; m_rotation_request_center = center; }; - void RequestAngleSnap(int division) { m_anglesnap_request = division; }; - void RequestTranslation(Ogre::Vector3 translation) { m_translation_request += translation; }; - Ogre::Vector3 GetRotationCenter(); - float GetMinHeight(bool skip_virtual_nodes=true); - float GetMaxHeight(bool skip_virtual_nodes=true); - float GetHeightAboveGround(bool skip_virtual_nodes=true); - float GetHeightAboveGroundBelow(float height, bool skip_virtual_nodes=true); - bool ReplayStep(); - void ForceFeedbackStep(int steps); - void HandleInputEvents(float dt); - void HandleAngelScriptEvents(float dt); - void UpdateSoundSources(); - void HandleMouseMove(int node, Ogre::Vector3 pos, float force); //!< Event handler - void ToggleLights(); //!< Event handler - void ToggleTies(int group=-1); - void ToggleRopes(int group=-1); //!< Event handler - void ToggleHooks(int group=-1, hook_states mode=HOOK_TOGGLE, int node_number=-1); //!< Event handler - void EngineTriggerHelper(int engineNumber, int type, float triggerValue); - void ToggleSlideNodeLock(); - void ToggleCustomParticles(); - void ToggleAxleDiffMode(); //! Cycles through the available inter axle diff modes - void DisplayAxleDiffMode(); //! Displays the current inter axle diff mode - void ToggleWheelDiffMode(); //! Cycles through the available inter wheel diff modes - void DisplayWheelDiffMode(); //! Displays the current inter wheel diff mode - void ToggleTransferCaseMode(); //! Toggles between 2WD and 4WD mode - void ToggleTransferCaseGearRatio(); //! Toggles between Hi and Lo mode - Ogre::String GetTransferCaseName(); //! Gets the current transfer case mode name (4WD Hi, ...) - void DisplayTransferCaseMode(); //! Displays the current transfer case mode - void ToggleParkingBrake(); //!< Event handler - void ToggleAntiLockBrake(); //!< Event handler - void ToggleTractionControl(); //!< Event handler - void ToggleCruiseControl(); //!< Event handler - void ToggleBeacons(); //!< Event handler - void setReplayMode(bool rm); //!< Event handler; toggle replay mode. - bool Intersects(Actor* actor, Ogre::Vector3 offset = Ogre::Vector3::ZERO); //!< Slow intersection test + void ResetPosition(Ogre::Vector3 translation, bool setInitPosition); + void ResetPosition(float px, float pz, bool setInitPosition, float miny); + void RequestRotation(float rotation, Ogre::Vector3 center) + { + m_rotation_request += rotation; + m_rotation_request_center = center; + }; + void RequestAngleSnap(int division) + { + m_anglesnap_request = division; + }; + void RequestTranslation(Ogre::Vector3 translation) + { + m_translation_request += translation; + }; + Ogre::Vector3 GetRotationCenter(); + float GetMinHeight(bool skip_virtual_nodes = true); + float GetMaxHeight(bool skip_virtual_nodes = true); + float GetHeightAboveGround(bool skip_virtual_nodes = true); + float GetHeightAboveGroundBelow(float height, bool skip_virtual_nodes = true); + bool ReplayStep(); + void ForceFeedbackStep(int steps); + void HandleInputEvents(float dt); + void HandleAngelScriptEvents(float dt); + void UpdateSoundSources(); + void HandleMouseMove(int node, Ogre::Vector3 pos, float force); //!< Event handler + void ToggleLights(); //!< Event handler + void ToggleTies(int group = -1); + void ToggleRopes(int group = -1); //!< Event handler + void ToggleHooks(int group = -1, hook_states mode = HOOK_TOGGLE, int node_number = -1); //!< Event handler + void EngineTriggerHelper(int engineNumber, int type, float triggerValue); + void ToggleSlideNodeLock(); + void ToggleCustomParticles(); + void ToggleAxleDiffMode(); //! Cycles through the available inter axle diff modes + void DisplayAxleDiffMode(); //! Displays the current inter axle diff mode + void ToggleWheelDiffMode(); //! Cycles through the available inter wheel diff modes + void DisplayWheelDiffMode(); //! Displays the current inter wheel diff mode + void ToggleTransferCaseMode(); //! Toggles between 2WD and 4WD mode + void ToggleTransferCaseGearRatio(); //! Toggles between Hi and Lo mode + Ogre::String GetTransferCaseName(); //! Gets the current transfer case mode name (4WD Hi, ...) + void DisplayTransferCaseMode(); //! Displays the current transfer case mode + void ToggleParkingBrake(); //!< Event handler + void ToggleAntiLockBrake(); //!< Event handler + void ToggleTractionControl(); //!< Event handler + void ToggleCruiseControl(); //!< Event handler + void ToggleBeacons(); //!< Event handler + void setReplayMode(bool rm); //!< Event handler; toggle replay mode. + bool Intersects(Actor *actor, Ogre::Vector3 offset = Ogre::Vector3::ZERO); //!< Slow intersection test /// Moves the actor at most 'direction.length()' meters towards 'direction' to resolve any collisions - void resolveCollisions(Ogre::Vector3 direction); + void resolveCollisions(Ogre::Vector3 direction); /// Auto detects an ideal collision avoidance direction (front, back, left, right, up) /// Then moves the actor at most 'max_distance' meters towards that direction to resolve any collisions - void resolveCollisions(float max_distance, bool consider_up); - void updateSkidmarks(); //!< Creates or updates skidmarks. No side effects. - void prepareInside(bool inside); //!< Prepares vehicle for in-cabin camera use. - void UpdateFlareStates(float dt_sec); - void updateVisual(float dt=0); - void ScaleActor(float value); - Ogre::Vector3 GetGForcesCur() { return m_camera_local_gforces_cur; }; - Ogre::Vector3 GetGForcesMax() { return m_camera_local_gforces_max; }; - float getSteeringAngle(); - float getMinCameraRadius() { return m_min_camera_radius; }; - std::string GetActorDesignName() { return ar_design_name; }; - std::string GetActorFileName() { return ar_filename; }; - std::string GetActorFileHash() { return ar_filehash; }; - int GetActorType() { return ar_driveable; }; - int GetNumActiveConnectedBeams(int nodeid); //!< Returns the number of active (non bounded) beams connected to a node - void NotifyActorCameraChanged(); //!< Logic: sound, display; Notify this vehicle that camera changed; - void StopAllSounds(); - void UnmuteAllSounds(); - float getTotalMass(bool withLocked=true); - float getAvgPropedWheelRadius() { return m_avg_proped_wheel_radius; }; - int getWheelNodeCount(); - void setMass(float m); - bool getBrakeLightVisible(); - bool getReverseLightVisible(); //!< Tells if the reverse-light is currently lit. - bool getCustomLightVisible(int number); - void setCustomLightVisible(int number, bool visible); - bool getBeaconMode(); - void toggleBlinkType(blinktype blink); - void setBlinkType(blinktype blink); - void setAirbrakeIntensity(float intensity); - bool getCustomParticleMode(); - void sendStreamData(); - bool isTied(); - bool isLocked(); - bool hasSlidenodes() { return !m_slidenodes.empty(); }; - void updateDashBoards(float dt); - void UpdateBoundingBoxes(); - void calculateAveragePosition(); - void UpdatePhysicsOrigin(); - void SoftReset(); - void SyncReset(bool reset_position); //!< this one should be called only synchronously (without physics running in background) - blinktype getBlinkType(); - std::vector getAuthors(); - std::vector getDescription(); - Ogre::String GetSectionConfig() { return m_section_config; } - RoR::PerVehicleCameraContext* GetCameraContext() { return &m_camera_context; } - std::vector GetAllLinkedActors() { return m_linked_actors; }; //!< Returns a list of all connected (hooked) actors - Ogre::Vector3 GetCameraDir() { return (ar_nodes[ar_main_camera_node_pos].RelPosition - ar_nodes[ar_main_camera_node_dir].RelPosition).normalisedCopy(); } - Ogre::Vector3 GetCameraRoll() { return (ar_nodes[ar_main_camera_node_pos].RelPosition - ar_nodes[ar_main_camera_node_roll].RelPosition).normalisedCopy(); } - Ogre::Vector3 GetFFbBodyForces() const { return m_force_sensors.out_body_forces; } - RoR::GfxActor* GetGfxActor() { return m_gfx_actor.get(); } - void RequestUpdateHudFeatures() { m_hud_features_ok = false; } - Ogre::Vector3 getNodePosition(int nodeNumber); //!< Returns world position of node - Ogre::Real getMinimalCameraRadius(); - Replay* getReplay(); - float GetFFbHydroForces() const { return m_force_sensors.out_hydros_forces; } - bool isPreloadedWithTerrain() const { return m_preloaded_with_terrain; }; - bool isBeingReset() const { return m_ongoing_reset; }; - VehicleAI* getVehicleAI() { return ar_vehicle_ai; } - float getWheelSpeed() const { return ar_wheel_speed; } - int GetNumNodes() const { return ar_num_nodes; } - CacheEntry* GetUsedSkin() const { return m_used_skin_entry; } - void SetUsedSkin(CacheEntry* skin) { m_used_skin_entry = skin; } - float getSpeed() { return m_avg_node_velocity.length(); }; - Ogre::Vector3 getVelocity() const { return m_avg_node_velocity; }; //!< average actor velocity, calculated using the actor positions of the last two frames + void resolveCollisions(float max_distance, bool consider_up); + void updateSkidmarks(); //!< Creates or updates skidmarks. No side effects. + void prepareInside(bool inside); //!< Prepares vehicle for in-cabin camera use. + void UpdateFlareStates(float dt_sec); + void updateVisual(float dt = 0); + void ScaleActor(float value); + Ogre::Vector3 GetGForcesCur() + { + return m_camera_local_gforces_cur; + }; + Ogre::Vector3 GetGForcesMax() + { + return m_camera_local_gforces_max; + }; + float getSteeringAngle(); + float getMinCameraRadius() + { + return m_min_camera_radius; + }; + std::string GetActorDesignName() + { + return ar_design_name; + }; + std::string GetActorFileName() + { + return ar_filename; + }; + std::string GetActorFileHash() + { + return ar_filehash; + }; + int GetActorType() + { + return ar_driveable; + }; + int GetNumActiveConnectedBeams(int nodeid); //!< Returns the number of active (non bounded) beams connected to a node + void NotifyActorCameraChanged(); //!< Logic: sound, display; Notify this vehicle that camera changed; + void StopAllSounds(); + void UnmuteAllSounds(); + float getTotalMass(bool withLocked = true); + float getAvgPropedWheelRadius() + { + return m_avg_proped_wheel_radius; + }; + int getWheelNodeCount(); + void setMass(float m); + bool getBrakeLightVisible(); + bool getReverseLightVisible(); //!< Tells if the reverse-light is currently lit. + bool getCustomLightVisible(int number); + void setCustomLightVisible(int number, bool visible); + bool getBeaconMode(); + void toggleBlinkType(blinktype blink); + void setBlinkType(blinktype blink); + void setAirbrakeIntensity(float intensity); + bool getCustomParticleMode(); + void sendStreamData(); + bool isTied(); + bool isLocked(); + bool hasSlidenodes() + { + return !m_slidenodes.empty(); + }; + void updateDashBoards(float dt); + void UpdateBoundingBoxes(); + void calculateAveragePosition(); + void UpdatePhysicsOrigin(); + void SoftReset(); + void SyncReset(bool reset_position); //!< this one should be called only synchronously (without physics running in background) + blinktype getBlinkType(); + std::vector getAuthors(); + std::vector getDescription(); + Ogre::String GetSectionConfig() + { + return m_section_config; + } + RoR::PerVehicleCameraContext *GetCameraContext() + { + return &m_camera_context; + } + std::vector GetAllLinkedActors() + { + return m_linked_actors; + }; //!< Returns a list of all connected (hooked) actors + Ogre::Vector3 GetCameraDir() + { + return (ar_nodes[ar_main_camera_node_pos].RelPosition - ar_nodes[ar_main_camera_node_dir].RelPosition).normalisedCopy(); + } + Ogre::Vector3 GetCameraRoll() + { + return (ar_nodes[ar_main_camera_node_pos].RelPosition - ar_nodes[ar_main_camera_node_roll].RelPosition).normalisedCopy(); + } + Ogre::Vector3 GetFFbBodyForces() const + { + return m_force_sensors.out_body_forces; + } + RoR::GfxActor *GetGfxActor() + { + return m_gfx_actor.get(); + } + void RequestUpdateHudFeatures() + { + m_hud_features_ok = false; + } + Ogre::Vector3 getNodePosition(int nodeNumber); //!< Returns world position of node + Ogre::Real getMinimalCameraRadius(); + Replay * getReplay(); + float GetFFbHydroForces() const + { + return m_force_sensors.out_hydros_forces; + } + bool isPreloadedWithTerrain() const + { + return m_preloaded_with_terrain; + }; + bool isBeingReset() const + { + return m_ongoing_reset; + }; + VehicleAI *getVehicleAI() + { + return ar_vehicle_ai; + } + float getWheelSpeed() const + { + return ar_wheel_speed; + } + int GetNumNodes() const + { + return ar_num_nodes; + } + CacheEntry *GetUsedSkin() const + { + return m_used_skin_entry; + } + void SetUsedSkin(CacheEntry *skin) + { + m_used_skin_entry = skin; + } + float getSpeed() + { + return m_avg_node_velocity.length(); + }; + Ogre::Vector3 getVelocity() const + { + return m_avg_node_velocity; + }; //!< average actor velocity, calculated using the actor positions of the last two frames #ifdef USE_ANGELSCRIPT // we have to add this to be able to use the class as reference inside scripts - void addRef() {}; - void release() {}; + void addRef(){}; + void release(){}; #endif // -------------------- Public data -------------------- // - node_t* ar_nodes; - int ar_num_nodes; - beam_t* ar_beams; - int ar_num_beams; - std::vector ar_inter_beams; //!< Beams connecting 2 actors - shock_t* ar_shocks; //!< Shock absorbers - int ar_num_shocks; //!< Number of shock absorbers - bool ar_has_active_shocks; //!< Are there active stabilizer shocks? - rotator_t* ar_rotators; - int ar_num_rotators; - wing_t* ar_wings; - int ar_num_wings; - std::vector description; - std::vector authors; - std::vector exhausts; - std::vector ar_ropes; - std::vector ar_ropables; - std::vector ar_ties; - std::vector ar_hooks; - std::vector ar_flares; - std::vector ar_airbrakes; - Ogre::AxisAlignedBox ar_bounding_box; //!< standard bounding box (surrounds all nodes of an actor) - Ogre::AxisAlignedBox ar_predicted_bounding_box; - float ar_initial_total_mass; - std::vector ar_initial_node_masses; - std::vector ar_initial_node_positions; + node_t * ar_nodes; + int ar_num_nodes; + beam_t * ar_beams; + int ar_num_beams; + std::vector ar_inter_beams; //!< Beams connecting 2 actors + shock_t * ar_shocks; //!< Shock absorbers + int ar_num_shocks; //!< Number of shock absorbers + bool ar_has_active_shocks; //!< Are there active stabilizer shocks? + rotator_t * ar_rotators; + int ar_num_rotators; + wing_t * ar_wings; + int ar_num_wings; + std::vector description; + std::vector authors; + std::vector exhausts; + std::vector ar_ropes; + std::vector ar_ropables; + std::vector ar_ties; + std::vector ar_hooks; + std::vector ar_flares; + std::vector ar_airbrakes; + Ogre::AxisAlignedBox ar_bounding_box; //!< standard bounding box (surrounds all nodes of an actor) + Ogre::AxisAlignedBox ar_predicted_bounding_box; + float ar_initial_total_mass; + std::vector ar_initial_node_masses; + std::vector ar_initial_node_positions; std::vector> ar_initial_beam_defaults; - std::vector ar_minimass; //!< minimum node mass in Kg - std::vector> ar_node_to_node_connections; - std::vector> ar_node_to_beam_connections; - std::vector ar_collision_bounding_boxes; //!< smart bounding boxes, used for determining the state of an actor (every box surrounds only a subset of nodes) - std::vector ar_predicted_coll_bounding_boxes; - int ar_num_contactable_nodes; //!< Total number of nodes which can contact ground or cabs - int ar_num_contacters; //!< Total number of nodes which can selfcontact cabs - wheel_t ar_wheels[MAX_WHEELS]; - int ar_num_wheels; - command_t ar_command_key[MAX_COMMANDS + 10]; // 0 for safety - cparticle_t ar_custom_particles[MAX_CPARTICLES]; - int ar_num_custom_particles; - soundsource_t ar_soundsources[MAX_SOUNDSCRIPTS_PER_TRUCK]; - int ar_num_soundsources; - int ar_pressure_beams[MAX_PRESSURE_BEAMS]; - int ar_free_pressure_beam; - AeroEngine* ar_aeroengines[MAX_AEROENGINES]; - int ar_num_aeroengines; - Screwprop* ar_screwprops[MAX_SCREWPROPS]; - int ar_num_screwprops; - int ar_cabs[MAX_CABS*3]; - int ar_num_cabs; - std::vector ar_hydros; - int ar_collcabs[MAX_CABS]; - collcab_rate_t ar_inter_collcabrate[MAX_CABS]; - collcab_rate_t ar_intra_collcabrate[MAX_CABS]; - int ar_num_collcabs; - int ar_buoycabs[MAX_CABS]; - int ar_buoycab_types[MAX_CABS]; - int ar_num_buoycabs; - int ar_camera_rail[MAX_CAMERARAIL]; //!< Nodes defining camera-movement spline - int ar_num_camera_rails; - bool ar_hide_in_actor_list; //!< Hide in list of spawned actors (available in top menubar). Useful for fixed-place machinery, i.e. cranes. - Ogre::String ar_design_name; //!< Name of the vehicle/machine/object this actor represents - float ar_anim_previous_crank; //!< For 'animator' with flag 'torque' - float alb_ratio; //!< Anti-lock brake attribute: Regulating force - float alb_minspeed; //!< Anti-lock brake attribute; - bool alb_mode; //!< Anti-lock brake state; Enabled? {1/0} - float alb_pulse_time; //!< Anti-lock brake attribute; - bool alb_pulse_state; //!< Anti-lock brake state; - bool alb_nodash; //!< Anti-lock brake attribute: Hide the dashboard indicator? - bool alb_notoggle; //!< Anti-lock brake attribute: Disable in-game toggle? - float alb_timer; //!< Anti-lock brake state; - float tc_ratio; //!< Traction control attribute: Regulating force - bool tc_mode; //!< Traction control state; Enabled? {1/0} - float tc_pulse_time; //!< Traction control attribute; - bool tc_pulse_state; //!< Traction control state; - bool tc_nodash; //!< Traction control attribute; Hide the dashboard indicator? - bool tc_notoggle; //!< Traction control attribute; Disable in-game toggle? - float tc_timer; //!< Traction control state; - float ar_anim_shift_timer;//!< For 'animator' with flag 'shifter' - bool cc_mode; //!< Cruise Control - bool cc_can_brake; //!< Cruise Control - float cc_target_rpm; //!< Cruise Control - float cc_target_speed; //!< Cruise Control + std::vector ar_minimass; //!< minimum node mass in Kg + std::vector> ar_node_to_node_connections; + std::vector> ar_node_to_beam_connections; + std::vector ar_collision_bounding_boxes; //!< smart bounding boxes, used for determining the state of an + //!< actor (every box surrounds only a subset of nodes) + std::vector ar_predicted_coll_bounding_boxes; + int ar_num_contactable_nodes; //!< Total number of nodes which can contact ground or cabs + int ar_num_contacters; //!< Total number of nodes which can selfcontact cabs + wheel_t ar_wheels[MAX_WHEELS]; + int ar_num_wheels; + command_t ar_command_key[MAX_COMMANDS + 10]; // 0 for safety + cparticle_t ar_custom_particles[MAX_CPARTICLES]; + int ar_num_custom_particles; + soundsource_t ar_soundsources[MAX_SOUNDSCRIPTS_PER_TRUCK]; + int ar_num_soundsources; + int ar_pressure_beams[MAX_PRESSURE_BEAMS]; + int ar_free_pressure_beam; + AeroEngine * ar_aeroengines[MAX_AEROENGINES]; + int ar_num_aeroengines; + Screwprop * ar_screwprops[MAX_SCREWPROPS]; + int ar_num_screwprops; + int ar_cabs[MAX_CABS * 3]; + int ar_num_cabs; + std::vector ar_hydros; + int ar_collcabs[MAX_CABS]; + collcab_rate_t ar_inter_collcabrate[MAX_CABS]; + collcab_rate_t ar_intra_collcabrate[MAX_CABS]; + int ar_num_collcabs; + int ar_buoycabs[MAX_CABS]; + int ar_buoycab_types[MAX_CABS]; + int ar_num_buoycabs; + int ar_camera_rail[MAX_CAMERARAIL]; //!< Nodes defining camera-movement spline + int ar_num_camera_rails; + bool ar_hide_in_actor_list; //!< Hide in list of spawned actors (available in top menubar). Useful for fixed-place machinery, + //!< i.e. cranes. + Ogre::String ar_design_name; //!< Name of the vehicle/machine/object this actor represents + float ar_anim_previous_crank; //!< For 'animator' with flag 'torque' + float alb_ratio; //!< Anti-lock brake attribute: Regulating force + float alb_minspeed; //!< Anti-lock brake attribute; + bool alb_mode; //!< Anti-lock brake state; Enabled? {1/0} + float alb_pulse_time; //!< Anti-lock brake attribute; + bool alb_pulse_state; //!< Anti-lock brake state; + bool alb_nodash; //!< Anti-lock brake attribute: Hide the dashboard indicator? + bool alb_notoggle; //!< Anti-lock brake attribute: Disable in-game toggle? + float alb_timer; //!< Anti-lock brake state; + float tc_ratio; //!< Traction control attribute: Regulating force + bool tc_mode; //!< Traction control state; Enabled? {1/0} + float tc_pulse_time; //!< Traction control attribute; + bool tc_pulse_state; //!< Traction control state; + bool tc_nodash; //!< Traction control attribute; Hide the dashboard indicator? + bool tc_notoggle; //!< Traction control attribute; Disable in-game toggle? + float tc_timer; //!< Traction control state; + float ar_anim_shift_timer; //!< For 'animator' with flag 'shifter' + bool cc_mode; //!< Cruise Control + bool cc_can_brake; //!< Cruise Control + float cc_target_rpm; //!< Cruise Control + float cc_target_speed; //!< Cruise Control float cc_target_speed_lower_limit; //!< Cruise Control - std::deque cc_accs; //!< Cruise Control - bool sl_enabled; //!< Speed limiter; - float sl_speed_limit; //!< Speed limiter; + std::deque cc_accs; //!< Cruise Control + bool sl_enabled; //!< Speed limiter; + float sl_speed_limit; //!< Speed limiter; int ar_extern_camera_mode; int ar_extern_camera_node; int ar_exhaust_pos_node; //!< Old-format exhaust (one per vehicle) emitter node int ar_exhaust_dir_node; //!< Old-format exhaust (one per vehicle) backwards direction node - int ar_instance_id; //!< Static attr; session-unique ID - unsigned int ar_vector_index; //!< Sim attr; actor element index in std::vector - int ar_driveable; //!< Sim attr; marks vehicle type and features - EngineSim* ar_engine; - int ar_cinecam_node[MAX_CAMERAS];//!< Sim attr; Cine-camera node indexes - int ar_num_cinecams; //!< Sim attr; - std::string ar_help_panel_material; //!< GUI attr, defined in truckfile - Autopilot* ar_autopilot; - float ar_brake_force; //!< Physics attr; filled at spawn - float ar_speedo_max_kph; //!< GUI attr - Ogre::Vector3 ar_origin; //!< Physics state; base position for softbody nodes + int ar_instance_id; //!< Static attr; session-unique ID + unsigned int ar_vector_index; //!< Sim attr; actor element index in std::vector + int ar_driveable; //!< Sim attr; marks vehicle type and features + EngineSim * ar_engine; + int ar_cinecam_node[MAX_CAMERAS]; //!< Sim attr; Cine-camera node indexes + int ar_num_cinecams; //!< Sim attr; + std::string ar_help_panel_material; //!< GUI attr, defined in truckfile + Autopilot * ar_autopilot; + float ar_brake_force; //!< Physics attr; filled at spawn + float ar_speedo_max_kph; //!< GUI attr + Ogre::Vector3 ar_origin; //!< Physics state; base position for softbody nodes int ar_num_cameras; - Ogre::Quaternion ar_main_camera_dir_corr; //!< Sim attr; - int ar_main_camera_node_pos; //!< Sim attr; ar_camera_node_pos[0] >= 0 ? ar_camera_node_pos[0] : 0 - int ar_main_camera_node_dir; //!< Sim attr; ar_camera_node_dir[0] >= 0 ? ar_camera_node_dir[0] : 0 - int ar_main_camera_node_roll; //!< Sim attr; ar_camera_node_roll[0] >= 0 ? ar_camera_node_roll[0] : 0 - int ar_camera_node_pos[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; origin node - int ar_camera_node_dir[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; back node + Ogre::Quaternion ar_main_camera_dir_corr; //!< Sim attr; + int ar_main_camera_node_pos; //!< Sim attr; ar_camera_node_pos[0] >= 0 ? ar_camera_node_pos[0] : 0 + int ar_main_camera_node_dir; //!< Sim attr; ar_camera_node_dir[0] >= 0 ? ar_camera_node_dir[0] : 0 + int ar_main_camera_node_roll; //!< Sim attr; ar_camera_node_roll[0] >= 0 ? ar_camera_node_roll[0] : 0 + int ar_camera_node_pos[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; origin node + int ar_camera_node_dir[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; back node int ar_camera_node_roll[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; left node - bool ar_camera_node_roll_inv[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; indicates roll node is right instead of left - float ar_posnode_spawn_height; - VehicleAI* ar_vehicle_ai; - float ar_scale; //!< Physics state; scale of the actor (nominal = 1.0) - Ogre::Real ar_brake; //!< Physics state; braking intensity - float ar_wheel_speed; //!< Physics state; wheel speed in m/s - float ar_wheel_spin; //!< Physics state; wheel speed in radians/s - float ar_avg_wheel_speed; //!< Physics state; avg wheel speed in m/s - float ar_hydro_dir_command; - float ar_hydro_dir_state; - Ogre::Real ar_hydro_dir_wheel_display; - float ar_hydro_aileron_command; - float ar_hydro_aileron_state; - float ar_hydro_rudder_command; - float ar_hydro_rudder_state; - float ar_hydro_elevator_command; - float ar_hydro_elevator_state; - Ogre::Real ar_replay_precision; //!< Sim attribute; determined at startup - int ar_replay_length; //!< Sim attribute; clone of GVar 'sim_replay_length' - int ar_replay_pos; //!< Sim state - float ar_sleep_counter; //!< Sim state; idle time counter - ground_model_t* ar_submesh_ground_model; - bool ar_parking_brake; - bool ar_trailer_parking_brake; - int ar_lights; //!< boolean 1/0 - float ar_left_mirror_angle; //!< Sim state; rear view mirror angle - float ar_right_mirror_angle; //!< Sim state; rear view mirror angle - float ar_elevator; //!< Sim state; aerial controller - float ar_rudder; //!< Sim state; aerial/marine controller - float ar_aileron; //!< Sim state; aerial controller - int ar_aerial_flap; //!< Sim state; state of aircraft flaps (values: 0-5) - Ogre::Vector3 ar_fusedrag; //!< Physics state - int ar_current_cinecam; //!< Sim state; index of current CineCam (-1 if using 3rd-person camera) - int ar_custom_camera_node; //!< Sim state; custom tracking node for 3rd-person camera - std::string ar_filename; //!< Attribute; filled at spawn - std::string ar_filehash; //!< Attribute; filled at spawn - int ar_airbrake_intensity; //!< Physics state; values 0-5 - int ar_net_source_id; - int ar_net_stream_id; - std::map ar_net_stream_results; - Ogre::Timer ar_net_timer; - unsigned long ar_net_last_update_time; - DashBoardManager* ar_dashboard; - SimState ar_sim_state; //!< Sim state - float ar_collision_range; //!< Physics attr - float ar_top_speed; //!< Sim state - ground_model_t* ar_last_fuzzy_ground_model; //!< GUI state + bool ar_camera_node_roll_inv[MAX_CAMERAS]; //!< Physics attr; 'camera' = frame of reference; indicates roll node is right + //!< instead of left + float ar_posnode_spawn_height; + VehicleAI * ar_vehicle_ai; + float ar_scale; //!< Physics state; scale of the actor (nominal = 1.0) + Ogre::Real ar_brake; //!< Physics state; braking intensity + float ar_wheel_speed; //!< Physics state; wheel speed in m/s + float ar_wheel_spin; //!< Physics state; wheel speed in radians/s + float ar_avg_wheel_speed; //!< Physics state; avg wheel speed in m/s + float ar_hydro_dir_command; + float ar_hydro_dir_state; + Ogre::Real ar_hydro_dir_wheel_display; + float ar_hydro_aileron_command; + float ar_hydro_aileron_state; + float ar_hydro_rudder_command; + float ar_hydro_rudder_state; + float ar_hydro_elevator_command; + float ar_hydro_elevator_state; + Ogre::Real ar_replay_precision; //!< Sim attribute; determined at startup + int ar_replay_length; //!< Sim attribute; clone of GVar 'sim_replay_length' + int ar_replay_pos; //!< Sim state + float ar_sleep_counter; //!< Sim state; idle time counter + ground_model_t * ar_submesh_ground_model; + bool ar_parking_brake; + bool ar_trailer_parking_brake; + int ar_lights; //!< boolean 1/0 + float ar_left_mirror_angle; //!< Sim state; rear view mirror angle + float ar_right_mirror_angle; //!< Sim state; rear view mirror angle + float ar_elevator; //!< Sim state; aerial controller + float ar_rudder; //!< Sim state; aerial/marine controller + float ar_aileron; //!< Sim state; aerial controller + int ar_aerial_flap; //!< Sim state; state of aircraft flaps (values: 0-5) + Ogre::Vector3 ar_fusedrag; //!< Physics state + int ar_current_cinecam; //!< Sim state; index of current CineCam (-1 if using 3rd-person camera) + int ar_custom_camera_node; //!< Sim state; custom tracking node for 3rd-person camera + std::string ar_filename; //!< Attribute; filled at spawn + std::string ar_filehash; //!< Attribute; filled at spawn + int ar_airbrake_intensity; //!< Physics state; values 0-5 + int ar_net_source_id; + int ar_net_stream_id; + std::map ar_net_stream_results; + Ogre::Timer ar_net_timer; + unsigned long ar_net_last_update_time; + DashBoardManager * ar_dashboard; + SimState ar_sim_state; //!< Sim state + float ar_collision_range; //!< Physics attr + float ar_top_speed; //!< Sim state + ground_model_t * ar_last_fuzzy_ground_model; //!< GUI state // Realtime node/beam structure editing helpers - void SearchBeamDefaults(); //!< Searches for more stable beam defaults + void SearchBeamDefaults(); //!< Searches for more stable beam defaults bool ar_nb_initialized; - std::vector ar_nb_optimum; //!< Temporary storage of the optimum search result - std::vector ar_nb_reference; //!< Temporary storage of the reference search result - int ar_nb_skip_steps; //!< Amount of physics steps to be skipped before measuring - int ar_nb_measure_steps; //!< Amount of physics steps to be measured - float ar_nb_mass_scale; //!< Global mass scale (affects all nodes the same way) - std::pair ar_nb_beams_scale; //!< Scales for springiness & damping of regular beams - std::pair ar_nb_shocks_scale; //!< Scales for springiness & damping of shock beams - std::pair ar_nb_wheels_scale; //!< Scales for springiness & damping of wheel / rim beams - std::pair ar_nb_beams_d_interval; //!< Search interval for springiness & damping of regular beams - std::pair ar_nb_beams_k_interval; //!< Search interval for springiness & damping of regular beams - std::pair ar_nb_shocks_d_interval; //!< Search interval for springiness & damping of shock beams - std::pair ar_nb_shocks_k_interval; //!< Search interval for springiness & damping of shock beams - std::pair ar_nb_wheels_d_interval; //!< Search interval for springiness & damping of wheel / rim beams - std::pair ar_nb_wheels_k_interval; //!< Search interval for springiness & damping of wheel / rim beams + std::vector ar_nb_optimum; //!< Temporary storage of the optimum search result + std::vector ar_nb_reference; //!< Temporary storage of the reference search result + int ar_nb_skip_steps; //!< Amount of physics steps to be skipped before measuring + int ar_nb_measure_steps; //!< Amount of physics steps to be measured + float ar_nb_mass_scale; //!< Global mass scale (affects all nodes the same way) + std::pair ar_nb_beams_scale; //!< Scales for springiness & damping of regular beams + std::pair ar_nb_shocks_scale; //!< Scales for springiness & damping of shock beams + std::pair ar_nb_wheels_scale; //!< Scales for springiness & damping of wheel / rim beams + std::pair ar_nb_beams_d_interval; //!< Search interval for springiness & damping of regular beams + std::pair ar_nb_beams_k_interval; //!< Search interval for springiness & damping of regular beams + std::pair ar_nb_shocks_d_interval; //!< Search interval for springiness & damping of shock beams + std::pair ar_nb_shocks_k_interval; //!< Search interval for springiness & damping of shock beams + std::pair ar_nb_wheels_d_interval; //!< Search interval for springiness & damping of wheel / rim beams + std::pair ar_nb_wheels_k_interval; //!< Search interval for springiness & damping of wheel / rim beams // Bit flags - bool ar_left_blink_on:1; //!< Gfx state; turn signals - bool ar_right_blink_on:1; //!< Gfx state; turn signals - bool ar_warn_blink_on:1; //!< Gfx state; turn signals - bool ar_update_physics:1; //!< Physics state; Should this actor be updated (locally) in the next physics step? - bool ar_disable_aerodyn_turbulent_drag:1; //!< Physics state - bool ar_engine_hydraulics_ready:1; //!< Sim state; does engine have enough RPM to power hydraulics? - bool ar_gui_use_engine_max_rpm:1; //!< Gfx attr - bool ar_hydro_speed_coupling:1; - bool ar_collision_relevant:1; //!< Physics state; - bool ar_replay_mode:1; //!< Sim state - bool ar_is_police:1; //!< Gfx/sfx attr - bool ar_rescuer_flag:1; //!< Gameplay attr; defined in truckfile. TODO: Does anybody use this anymore? - bool ar_forward_commands:1; //!< Sim state - bool ar_import_commands:1; //!< Sim state - bool ar_toggle_ropes:1; //!< Sim state - bool ar_toggle_ties:1; //!< Sim state - bool ar_physics_paused:1; //!< Sim state - -private: + bool ar_left_blink_on : 1; //!< Gfx state; turn signals + bool ar_right_blink_on : 1; //!< Gfx state; turn signals + bool ar_warn_blink_on : 1; //!< Gfx state; turn signals + bool ar_update_physics : 1; //!< Physics state; Should this actor be updated (locally) in the next physics step? + bool ar_disable_aerodyn_turbulent_drag : 1; //!< Physics state + bool ar_engine_hydraulics_ready : 1; //!< Sim state; does engine have enough RPM to power hydraulics? + bool ar_gui_use_engine_max_rpm : 1; //!< Gfx attr + bool ar_hydro_speed_coupling : 1; + bool ar_collision_relevant : 1; //!< Physics state; + bool ar_replay_mode : 1; //!< Sim state + bool ar_is_police : 1; //!< Gfx/sfx attr + bool ar_rescuer_flag : 1; //!< Gameplay attr; defined in truckfile. TODO: Does anybody use this anymore? + bool ar_forward_commands : 1; //!< Sim state + bool ar_import_commands : 1; //!< Sim state + bool ar_toggle_ropes : 1; //!< Sim state + bool ar_toggle_ties : 1; //!< Sim state + bool ar_physics_paused : 1; //!< Sim state - bool CalcForcesEulerPrepare(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcAircraftForces(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcAnimatedProps(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcForcesEulerCompute(bool doUpdate, int num_steps); //!< TIGHT LOOP; Physics; - void CalcAnimators(const int flag_state, float &cstate, int &div, float timer, const float lower_limit, const float upper_limit, const float option3); //!< TIGHT LOOP; Physics; - void CalcBeams(bool trigger_hooks); //!< TIGHT LOOP; Physics; - void CalcBeamsInterActor(); //!< TIGHT LOOP; Physics; - void CalcBuoyance(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcCommands(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcCabCollisions(); //!< TIGHT LOOP; Physics; - void CalcDifferentials(); //!< TIGHT LOOP; Physics; - void CalcForceFeedback(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcFuseDrag(); //!< TIGHT LOOP; Physics; - void CalcHooks(); //!< TIGHT LOOP; Physics; - void CalcHooks(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcHydros(); //!< TIGHT LOOP; Physics; - void CalcMouse(); //!< TIGHT LOOP; Physics; - void CalcNodes(); //!< TIGHT LOOP; Physics; - void CalcReplay(); //!< TIGHT LOOP; Physics; - void CalcRopes(); //!< TIGHT LOOP; Physics; - void CalcShocks(bool doUpdate, int num_steps); //!< TIGHT LOOP; Physics; - void CalcShocks2(int i, Ogre::Real difftoBeamL, Ogre::Real &k, Ogre::Real &d, Ogre::Real v); - void CalcShocks3(int i, Ogre::Real difftoBeamL, Ogre::Real &k, Ogre::Real &d, Ogre::Real v); - void CalcTriggers(int i, Ogre::Real difftoBeamL, bool update_hooks); - void CalcSlideNodes(); //!< TIGHT LOOP; Physics; - void CalcTies(); //!< TIGHT LOOP; Physics; - void CalcTruckEngine(bool doUpdate); //!< TIGHT LOOP; Physics; - void CalcAxles(); //!< TIGHT LOOP; Physics; - void CalcWheels(bool doUpdate, int num_steps); //!< TIGHT LOOP; Physics; + private: + bool CalcForcesEulerPrepare(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcAircraftForces(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcAnimatedProps(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcForcesEulerCompute(bool doUpdate, int num_steps); //!< TIGHT LOOP; Physics; + void CalcAnimators(const int flag_state, float &cstate, int &div, float timer, const float lower_limit, + const float upper_limit, const float option3); //!< TIGHT LOOP; Physics; + void CalcBeams(bool trigger_hooks); //!< TIGHT LOOP; Physics; + void CalcBeamsInterActor(); //!< TIGHT LOOP; Physics; + void CalcBuoyance(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcCommands(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcCabCollisions(); //!< TIGHT LOOP; Physics; + void CalcDifferentials(); //!< TIGHT LOOP; Physics; + void CalcForceFeedback(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcFuseDrag(); //!< TIGHT LOOP; Physics; + void CalcHooks(); //!< TIGHT LOOP; Physics; + void CalcHooks(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcHydros(); //!< TIGHT LOOP; Physics; + void CalcMouse(); //!< TIGHT LOOP; Physics; + void CalcNodes(); //!< TIGHT LOOP; Physics; + void CalcReplay(); //!< TIGHT LOOP; Physics; + void CalcRopes(); //!< TIGHT LOOP; Physics; + void CalcShocks(bool doUpdate, int num_steps); //!< TIGHT LOOP; Physics; + void CalcShocks2(int i, Ogre::Real difftoBeamL, Ogre::Real &k, Ogre::Real &d, Ogre::Real v); + void CalcShocks3(int i, Ogre::Real difftoBeamL, Ogre::Real &k, Ogre::Real &d, Ogre::Real v); + void CalcTriggers(int i, Ogre::Real difftoBeamL, bool update_hooks); + void CalcSlideNodes(); //!< TIGHT LOOP; Physics; + void CalcTies(); //!< TIGHT LOOP; Physics; + void CalcTruckEngine(bool doUpdate); //!< TIGHT LOOP; Physics; + void CalcAxles(); //!< TIGHT LOOP; Physics; + void CalcWheels(bool doUpdate, int num_steps); //!< TIGHT LOOP; Physics; - void DetermineLinkedActors(); - void RecalculateNodeMasses(Ogre::Real total); //!< Previously 'calc_masses2()' - void calcNodeConnectivityGraph(); - void AddInterActorBeam(beam_t* beam, Actor* a, Actor* b); - void RemoveInterActorBeam(beam_t* beam); - void DisjoinInterActorBeams(); //!< Destroys all inter-actor beams which are connected with this actor - void autoBlinkReset(); //!< Resets the turn signal when the steering wheel is turned back. - void sendStreamSetup(); - void UpdateSlideNodeForces(const Ogre::Real delta_time_sec); //!< calculate and apply Corrective forces - void resetSlideNodePositions(); //!< Recalculate SlideNode positions - void resetSlideNodes(); //!< Reset all the SlideNodes - void updateSlideNodePositions(); //!< incrementally update the position of all SlideNodes - void ResetAngle(float rot); - void calculateLocalGForces(); //!< Derive the truck local g-forces from the global ones + void DetermineLinkedActors(); + void RecalculateNodeMasses(Ogre::Real total); //!< Previously 'calc_masses2()' + void calcNodeConnectivityGraph(); + void AddInterActorBeam(beam_t *beam, Actor *a, Actor *b); + void RemoveInterActorBeam(beam_t *beam); + void DisjoinInterActorBeams(); //!< Destroys all inter-actor beams which are connected with this actor + void autoBlinkReset(); //!< Resets the turn signal when the steering wheel is turned back. + void sendStreamSetup(); + void UpdateSlideNodeForces(const Ogre::Real delta_time_sec); //!< calculate and apply Corrective forces + void resetSlideNodePositions(); //!< Recalculate SlideNode positions + void resetSlideNodes(); //!< Reset all the SlideNodes + void updateSlideNodePositions(); //!< incrementally update the position of all SlideNodes + void ResetAngle(float rot); + void calculateLocalGForces(); //!< Derive the truck local g-forces from the global ones /// Virtually moves the actor at most 'direction.length()' meters towards 'direction' trying to resolve any collisions /// Returns a minimal offset by which the actor needs to be moved to resolve any collisions // Both PointColDetectors need to be updated accordingly before calling this - Ogre::Vector3 calculateCollisionOffset(Ogre::Vector3 direction); + Ogre::Vector3 calculateCollisionOffset(Ogre::Vector3 direction); /// @param actor which actor to retrieve the closest Rail from /// @param node which SlideNode is being checked against /// @return a pair containing the rail, and the distant to the SlideNode - std::pair GetClosestRailOnActor( Actor* actor, const SlideNode& node); + std::pair GetClosestRailOnActor(Actor *actor, const SlideNode &node); // -------------------- data -------------------- // - std::vector> m_flexbody_tasks; //!< Gfx state + std::vector> m_flexbody_tasks; //!< Gfx state std::shared_ptr m_definition; std::unique_ptr m_gfx_actor; RoR::PerVehicleCameraContext m_camera_context; Ogre::String m_section_config; - std::vector m_slidenodes; //!< all the SlideNodes available on this actor - std::vector m_railgroups; //!< all the available RailGroups for this actor - std::vector m_deletion_entities; //!< For unloading vehicle; filled at spawn. - std::vector m_deletion_scene_nodes; //!< For unloading vehicle; filled at spawn. - int m_proped_wheel_pairs[MAX_WHEELS]; //!< Physics attr; For inter-differential locking - int m_num_proped_wheels; //!< Physics attr, filled at spawn - Number of propelled wheels. - float m_avg_proped_wheel_radius; //!< Physics attr, filled at spawn - Average proped wheel radius. - float m_avionic_chatter_timer; //!< Sound fx state - PointColDetector* m_inter_point_col_detector; //!< Physics - PointColDetector* m_intra_point_col_detector; //!< Physics - std::vector m_linked_actors; //!< Sim state; other actors linked using 'hooks' - Ogre::Vector3 m_avg_node_position; //!< average node position - Ogre::Real m_min_camera_radius; - Ogre::Vector3 m_avg_node_position_prev; - Ogre::Vector3 m_avg_node_velocity; //!< average node velocity (compared to the previous frame step) - Ogre::Real m_replay_timer; //!< Sim state - blinktype m_blink_type; //!< Sim state; Blinker = turn signal - float m_stabilizer_shock_sleep; //!< Sim state - Replay* m_replay_handler; - float m_total_mass; //!< Physics state; total mass in Kg - int m_mouse_grab_node; //!< Sim state; node currently being dragged by user - Ogre::Vector3 m_mouse_grab_pos; - float m_mouse_grab_move_force; - float m_spawn_rotation; - Ogre::MovableText* m_net_label_mt; - Ogre::SceneNode* m_net_label_node; - Ogre::UTFString m_net_username; - Ogre::Timer m_reset_timer; - float m_custom_light_toggle_countdown; //!< Input system helper status - Ogre::Vector3 m_rotation_request_center; - float m_rotation_request; //!< Accumulator - int m_anglesnap_request; //!< Accumulator - Ogre::Vector3 m_translation_request; //!< Accumulator - Ogre::Vector3 m_camera_gforces_accu; //!< Accumulator for 'camera' G-forces - Ogre::Vector3 m_camera_gforces; //!< Physics state (global) - Ogre::Vector3 m_camera_local_gforces_cur; //!< Physics state (camera local) - Ogre::Vector3 m_camera_local_gforces_max; //!< Physics state (camera local) - float m_ref_tyre_pressure; //!< Physics state - float m_stabilizer_shock_ratio; //!< Physics state - int m_stabilizer_shock_request; //!< Physics state; values: { -1, 0, 1 } - Differential* m_axle_diffs[1+MAX_WHEELS/2];//!< Physics - int m_num_axle_diffs; //!< Physics attr - Differential* m_wheel_diffs[MAX_WHEELS/2];//!< Physics - int m_num_wheel_diffs; //!< Physics attr - TransferCase* m_transfer_case; //!< Physics - float m_net_node_compression; //!< Sim attr; - int m_net_first_wheel_node; //!< Network attr; Determines data buffer layout - int m_net_node_buf_size; //!< Network attr; buffer size - int m_net_buffer_size; //!< Network attr; buffer size - int m_wheel_node_count; //!< Static attr; filled at spawn - int m_replay_pos_prev; //!< Sim state - int m_previous_gear; //!< Sim state; land vehicle shifting - float m_handbrake_force; //!< Physics attr; defined in truckfile - Airfoil* m_fusealge_airfoil; //!< Physics attr; defined in truckfile - node_t* m_fusealge_front; //!< Physics attr; defined in truckfile - node_t* m_fusealge_back; //!< Physics attr; defined in truckfile - float m_fusealge_width; //!< Physics attr; defined in truckfile - float m_odometer_total; //!< GUI state - float m_odometer_user; //!< GUI state - int m_num_command_beams; //!< TODO: Remove! Spawner context only; likely unused feature - float m_load_mass; //!< Physics attr; predefined load mass in Kg - int m_masscount; //!< Physics attr; Number of nodes loaded with l option - float m_dry_mass; //!< Physics attr; - unsigned int m_net_custom_lights[4]; //!< Sim state - unsigned char m_net_custom_light_count;//!< Sim attr - RoR::GfxFlaresMode m_flares_mode; //!< Gfx attr, clone of GVar -- TODO: remove - std::unique_ptr m_buoyance; //!< Physics - CacheEntry* m_used_skin_entry; //!< Graphics - RoR::Skidmark* m_skid_trails[MAX_WHEELS*2]; - bool m_antilockbrake; //!< GUI state - bool m_tractioncontrol; //!< GUI state - bool m_ongoing_reset; //!< Hack to prevent position/rotation creep during interactive truck reset - bool m_has_axles_section; //!< Temporary (legacy parsing helper) until central diffs are implemented + std::vector m_slidenodes; //!< all the SlideNodes available on this actor + std::vector m_railgroups; //!< all the available RailGroups for this actor + std::vector m_deletion_entities; //!< For unloading vehicle; filled at spawn. + std::vector m_deletion_scene_nodes; //!< For unloading vehicle; filled at spawn. + int m_proped_wheel_pairs[MAX_WHEELS]; //!< Physics attr; For inter-differential locking + int m_num_proped_wheels; //!< Physics attr, filled at spawn - Number of propelled wheels. + float m_avg_proped_wheel_radius; //!< Physics attr, filled at spawn - Average proped wheel radius. + float m_avionic_chatter_timer; //!< Sound fx state + PointColDetector * m_inter_point_col_detector; //!< Physics + PointColDetector * m_intra_point_col_detector; //!< Physics + std::vector m_linked_actors; //!< Sim state; other actors linked using 'hooks' + Ogre::Vector3 m_avg_node_position; //!< average node position + Ogre::Real m_min_camera_radius; + Ogre::Vector3 m_avg_node_position_prev; + Ogre::Vector3 m_avg_node_velocity; //!< average node velocity (compared to the previous frame step) + Ogre::Real m_replay_timer; //!< Sim state + blinktype m_blink_type; //!< Sim state; Blinker = turn signal + float m_stabilizer_shock_sleep; //!< Sim state + Replay * m_replay_handler; + float m_total_mass; //!< Physics state; total mass in Kg + int m_mouse_grab_node; //!< Sim state; node currently being dragged by user + Ogre::Vector3 m_mouse_grab_pos; + float m_mouse_grab_move_force; + float m_spawn_rotation; + Ogre::MovableText * m_net_label_mt; + Ogre::SceneNode * m_net_label_node; + Ogre::UTFString m_net_username; + Ogre::Timer m_reset_timer; + float m_custom_light_toggle_countdown; //!< Input system helper status + Ogre::Vector3 m_rotation_request_center; + float m_rotation_request; //!< Accumulator + int m_anglesnap_request; //!< Accumulator + Ogre::Vector3 m_translation_request; //!< Accumulator + Ogre::Vector3 m_camera_gforces_accu; //!< Accumulator for 'camera' G-forces + Ogre::Vector3 m_camera_gforces; //!< Physics state (global) + Ogre::Vector3 m_camera_local_gforces_cur; //!< Physics state (camera local) + Ogre::Vector3 m_camera_local_gforces_max; //!< Physics state (camera local) + float m_ref_tyre_pressure; //!< Physics state + float m_stabilizer_shock_ratio; //!< Physics state + int m_stabilizer_shock_request; //!< Physics state; values: { -1, 0, 1 } + Differential * m_axle_diffs[1 + MAX_WHEELS / 2]; //!< Physics + int m_num_axle_diffs; //!< Physics attr + Differential * m_wheel_diffs[MAX_WHEELS / 2]; //!< Physics + int m_num_wheel_diffs; //!< Physics attr + TransferCase * m_transfer_case; //!< Physics + float m_net_node_compression; //!< Sim attr; + int m_net_first_wheel_node; //!< Network attr; Determines data buffer layout + int m_net_node_buf_size; //!< Network attr; buffer size + int m_net_buffer_size; //!< Network attr; buffer size + int m_wheel_node_count; //!< Static attr; filled at spawn + int m_replay_pos_prev; //!< Sim state + int m_previous_gear; //!< Sim state; land vehicle shifting + float m_handbrake_force; //!< Physics attr; defined in truckfile + Airfoil * m_fusealge_airfoil; //!< Physics attr; defined in truckfile + node_t * m_fusealge_front; //!< Physics attr; defined in truckfile + node_t * m_fusealge_back; //!< Physics attr; defined in truckfile + float m_fusealge_width; //!< Physics attr; defined in truckfile + float m_odometer_total; //!< GUI state + float m_odometer_user; //!< GUI state + int m_num_command_beams; //!< TODO: Remove! Spawner context only; likely unused feature + float m_load_mass; //!< Physics attr; predefined load mass in Kg + int m_masscount; //!< Physics attr; Number of nodes loaded with l option + float m_dry_mass; //!< Physics attr; + unsigned int m_net_custom_lights[4]; //!< Sim state + unsigned char m_net_custom_light_count; //!< Sim attr + RoR::GfxFlaresMode m_flares_mode; //!< Gfx attr, clone of GVar -- TODO: remove + std::unique_ptr m_buoyance; //!< Physics + CacheEntry * m_used_skin_entry; //!< Graphics + RoR::Skidmark * m_skid_trails[MAX_WHEELS * 2]; + bool m_antilockbrake; //!< GUI state + bool m_tractioncontrol; //!< GUI state + bool m_ongoing_reset; //!< Hack to prevent position/rotation creep during interactive truck reset + bool m_has_axles_section; //!< Temporary (legacy parsing helper) until central diffs are implemented - bool m_hud_features_ok:1; //!< Gfx state; Are HUD features matching actor's capabilities? - bool m_slidenodes_locked:1; //!< Physics state; Are SlideNodes locked? - bool m_blinker_autoreset:1; //!< Gfx state; We're steering - when we finish, the blinker should turn off - bool m_net_initialized:1; - bool m_net_brake_light:1; - bool m_net_reverse_light:1; - bool m_reverse_light_active:1; //!< Gfx state - bool m_water_contact:1; //!< Scripting state - bool m_water_contact_old:1; //!< Scripting state - bool m_has_command_beams:1; //!< Physics attr; - bool m_beacon_light_is_active:1; //!< Gfx state - bool m_custom_particles_enabled:1; //!< Gfx state - bool m_preloaded_with_terrain:1; //!< Spawn context (TODO: remove!) - bool m_beam_break_debug_enabled:1; //!< Logging state - bool m_beam_deform_debug_enabled:1; //!< Logging state - bool m_trigger_debug_enabled:1; //!< Logging state - bool m_disable_default_sounds:1; //!< Spawner context; TODO: remove - bool m_disable_smoke:1; //!< Gfx state + bool m_hud_features_ok : 1; //!< Gfx state; Are HUD features matching actor's capabilities? + bool m_slidenodes_locked : 1; //!< Physics state; Are SlideNodes locked? + bool m_blinker_autoreset : 1; //!< Gfx state; We're steering - when we finish, the blinker should turn off + bool m_net_initialized : 1; + bool m_net_brake_light : 1; + bool m_net_reverse_light : 1; + bool m_reverse_light_active : 1; //!< Gfx state + bool m_water_contact : 1; //!< Scripting state + bool m_water_contact_old : 1; //!< Scripting state + bool m_has_command_beams : 1; //!< Physics attr; + bool m_beacon_light_is_active : 1; //!< Gfx state + bool m_custom_particles_enabled : 1; //!< Gfx state + bool m_preloaded_with_terrain : 1; //!< Spawn context (TODO: remove!) + bool m_beam_break_debug_enabled : 1; //!< Logging state + bool m_beam_deform_debug_enabled : 1; //!< Logging state + bool m_trigger_debug_enabled : 1; //!< Logging state + bool m_disable_default_sounds : 1; //!< Spawner context; TODO: remove + bool m_disable_smoke : 1; //!< Gfx state struct VehicleForceSensors { inline void Reset() { - accu_body_forces = Ogre::Vector3::ZERO; - accu_hydros_forces = 0; - out_body_forces = Ogre::Vector3::ZERO; - out_hydros_forces = 0; + accu_body_forces = Ogre::Vector3::ZERO; + accu_hydros_forces = 0; + out_body_forces = Ogre::Vector3::ZERO; + out_hydros_forces = 0; }; Ogre::Vector3 accu_body_forces; @@ -552,8 +640,8 @@ class Actor : public ZeroedMemoryAllocator struct NetUpdate { - std::vector veh_state; //!< Actor properties (engine, brakes, lights, ...) - std::vector node_data; //!< Compressed node positions + std::vector veh_state; //!< Actor properties (engine, brakes, lights, ...) + std::vector node_data; //!< Compressed node positions std::vector wheel_data; //!< Wheel rotations }; diff --git a/source/main/physics/BeamConstants.h b/source/main/physics/BeamConstants.h index de40d39919..6539f80bf7 100644 --- a/source/main/physics/BeamConstants.h +++ b/source/main/physics/BeamConstants.h @@ -18,56 +18,56 @@ #pragma once /* maximum limits */ -static const int MAX_ACTORS = 5000; //!< maximum number of actors per game session -static const int MAX_WHEELS = 64; //!< maximum number of wheels per actor -static const int MAX_SUBMESHES = 500; //!< maximum number of submeshes per actor -static const int MAX_TEXCOORDS = 3000; //!< maximum number of texture coordinates per actor -static const int MAX_CABS = 3000; //!< maximum number of cabs per actor -static const int MAX_COMMANDS = 84; //!< maximum number of commands per actor -static const int MAX_CAMERAS = 10; //!< maximum number of cameras per actor -static const int MAX_AEROENGINES = 8; //!< maximum number of aero engines per actor -static const int MAX_SCREWPROPS = 8; //!< maximum number of boat screws per actor -static const int MAX_SOUNDSCRIPTS_PER_TRUCK = 128; //!< maximum number of soundsscripts per actor -static const int MAX_CPARTICLES = 10; //!< maximum number of custom particles per actor -static const int MAX_PRESSURE_BEAMS = 4000; //!< maximum number of pressure beams per actor -static const int MAX_CAMERARAIL = 50; //!< maximum number of camera rail points +static const int MAX_ACTORS = 5000; //!< maximum number of actors per game session +static const int MAX_WHEELS = 64; //!< maximum number of wheels per actor +static const int MAX_SUBMESHES = 500; //!< maximum number of submeshes per actor +static const int MAX_TEXCOORDS = 3000; //!< maximum number of texture coordinates per actor +static const int MAX_CABS = 3000; //!< maximum number of cabs per actor +static const int MAX_COMMANDS = 84; //!< maximum number of commands per actor +static const int MAX_CAMERAS = 10; //!< maximum number of cameras per actor +static const int MAX_AEROENGINES = 8; //!< maximum number of aero engines per actor +static const int MAX_SCREWPROPS = 8; //!< maximum number of boat screws per actor +static const int MAX_SOUNDSCRIPTS_PER_TRUCK = 128; //!< maximum number of soundsscripts per actor +static const int MAX_CPARTICLES = 10; //!< maximum number of custom particles per actor +static const int MAX_PRESSURE_BEAMS = 4000; //!< maximum number of pressure beams per actor +static const int MAX_CAMERARAIL = 50; //!< maximum number of camera rail points -static const float RAD_PER_SEC_TO_RPM = 9.5492965855137f; //!< Convert radian/second to RPM (60/2*PI) +static const float RAD_PER_SEC_TO_RPM = 9.5492965855137f; //!< Convert radian/second to RPM (60/2*PI) /* other global static definitions */ -static const int TRUCKFILEFORMATVERSION = 3; //!< truck file format version number +static const int TRUCKFILEFORMATVERSION = 3; //!< truck file format version number /* physics defaults */ -static const float DEFAULT_RIGIDIFIER_SPRING = 1000000.0f; -static const float DEFAULT_RIGIDIFIER_DAMP = 50000.0f; -static const float DEFAULT_SPRING = 9000000.0f; -static const float DEFAULT_DAMP = 12000.0f; -static const float DEFAULT_GRAVITY = -9.8f; //!< earth gravity -static const float DEFAULT_DRAG = 0.05f; -static const float DEFAULT_BEAM_DIAMETER = 0.05f; //!< 5 centimeters default beam width -static const float DEFAULT_COLLISION_RANGE = 0.02f; -static const float DEFAULT_MINIMASS = 50.0f; //!< minimum node mass in Kg -static const float MIN_BEAM_LENGTH = 0.1f; //!< minimum beam lenght is 10 centimeters -static const float INVERTED_MIN_BEAM_LENGTH = 1.0f / MIN_BEAM_LENGTH; -static const float BEAM_SKELETON_DIAMETER = 0.01f; -static const float DEFAULT_WATERDRAG = 10.0f; -static const float IRON_DENSITY = 7874.0f; -static const float BEAM_BREAK = 1000000.0f; -static const float BEAM_DEFORM = 400000.0f; -static const float BEAM_CREAK_DEFAULT = 100000.0f; -static const float WHEEL_FRICTION_COEF = 2.0f; -static const float CHASSIS_FRICTION_COEF = 0.5f; //!< Chassis has 1/4 the friction of wheels. -static const float SPEED_STOP = 0.2f; -static const float STAB_RATE = 0.025f; -static const float NODE_FRICTION_COEF_DEFAULT = 1.0f; -static const float NODE_VOLUME_COEF_DEFAULT = 1.0f; -static const float NODE_SURFACE_COEF_DEFAULT = 1.0f; -static const float NODE_LOADWEIGHT_DEFAULT = -1.0f; -static const float SUPPORT_BEAM_LIMIT_DEFAULT = 4.0f; -static const float ROTATOR_FORCE_DEFAULT = 10000000.0f; -static const float ROTATOR_TOLERANCE_DEFAULT = 0.0f; -static const float HOOK_FORCE_DEFAULT = 10000000.0f; -static const float HOOK_RANGE_DEFAULT = 0.4f; -static const float HOOK_SPEED_DEFAULT = 0.00025f; -static const float HOOK_LOCK_TIMER_DEFAULT = 5.0; -static const int NODE_LOCKGROUP_DEFAULT = -1; // all hooks scan all nodes +static const float DEFAULT_RIGIDIFIER_SPRING = 1000000.0f; +static const float DEFAULT_RIGIDIFIER_DAMP = 50000.0f; +static const float DEFAULT_SPRING = 9000000.0f; +static const float DEFAULT_DAMP = 12000.0f; +static const float DEFAULT_GRAVITY = -9.8f; //!< earth gravity +static const float DEFAULT_DRAG = 0.05f; +static const float DEFAULT_BEAM_DIAMETER = 0.05f; //!< 5 centimeters default beam width +static const float DEFAULT_COLLISION_RANGE = 0.02f; +static const float DEFAULT_MINIMASS = 50.0f; //!< minimum node mass in Kg +static const float MIN_BEAM_LENGTH = 0.1f; //!< minimum beam lenght is 10 centimeters +static const float INVERTED_MIN_BEAM_LENGTH = 1.0f / MIN_BEAM_LENGTH; +static const float BEAM_SKELETON_DIAMETER = 0.01f; +static const float DEFAULT_WATERDRAG = 10.0f; +static const float IRON_DENSITY = 7874.0f; +static const float BEAM_BREAK = 1000000.0f; +static const float BEAM_DEFORM = 400000.0f; +static const float BEAM_CREAK_DEFAULT = 100000.0f; +static const float WHEEL_FRICTION_COEF = 2.0f; +static const float CHASSIS_FRICTION_COEF = 0.5f; //!< Chassis has 1/4 the friction of wheels. +static const float SPEED_STOP = 0.2f; +static const float STAB_RATE = 0.025f; +static const float NODE_FRICTION_COEF_DEFAULT = 1.0f; +static const float NODE_VOLUME_COEF_DEFAULT = 1.0f; +static const float NODE_SURFACE_COEF_DEFAULT = 1.0f; +static const float NODE_LOADWEIGHT_DEFAULT = -1.0f; +static const float SUPPORT_BEAM_LIMIT_DEFAULT = 4.0f; +static const float ROTATOR_FORCE_DEFAULT = 10000000.0f; +static const float ROTATOR_TOLERANCE_DEFAULT = 0.0f; +static const float HOOK_FORCE_DEFAULT = 10000000.0f; +static const float HOOK_RANGE_DEFAULT = 0.4f; +static const float HOOK_SPEED_DEFAULT = 0.00025f; +static const float HOOK_LOCK_TIMER_DEFAULT = 5.0; +static const int NODE_LOCKGROUP_DEFAULT = -1; // all hooks scan all nodes diff --git a/source/main/physics/BeamData.h b/source/main/physics/BeamData.h index 722471346e..dec83bea76 100644 --- a/source/main/physics/BeamData.h +++ b/source/main/physics/BeamData.h @@ -35,13 +35,14 @@ */ // The RoR required includes (should be included already) -#include "ForwardDeclarations.h" #include "BeamConstants.h" #include "BitFlags.h" #include "CmdKeyInertia.h" +#include "ForwardDeclarations.h" -enum event_types { - EVENT_NONE=0, +enum event_types +{ + EVENT_NONE = 0, EVENT_ALL, EVENT_AVATAR, EVENT_TRUCK, @@ -50,52 +51,59 @@ enum event_types { EVENT_DELETE }; -enum hook_states { - HOOK_LOCK=0, +enum hook_states +{ + HOOK_LOCK = 0, HOOK_UNLOCK, HOOK_TOGGLE, MOUSE_HOOK_TOGGLE, }; /* Enumerations */ -enum { +enum +{ BEAM_NORMAL, BEAM_HYDRO, - BEAM_VIRTUAL, //!< Excluded from mass calculations, visuals permanently disabled + BEAM_VIRTUAL, //!< Excluded from mass calculations, visuals permanently disabled }; -enum { - UNLOCKED, //!< lock not locked - PREUNLOCK, //!< preunlocking, inter-actor beam deletion in progress - PRELOCK, //!< prelocking, attraction forces in action - LOCKED //!< lock locked. +enum +{ + UNLOCKED, //!< lock not locked + PREUNLOCK, //!< preunlocking, inter-actor beam deletion in progress + PRELOCK, //!< prelocking, attraction forces in action + LOCKED //!< lock locked. }; -enum { - NOT_DRIVEABLE, //!< not drivable at all - TRUCK, //!< its a truck (or other land vehicle) - AIRPLANE, //!< its an airplane - BOAT, //!< its a boat - MACHINE, //!< its a machine - AI, //!< machine controlled by an Artificial Intelligence +enum +{ + NOT_DRIVEABLE, //!< not drivable at all + TRUCK, //!< its a truck (or other land vehicle) + AIRPLANE, //!< its an airplane + BOAT, //!< its a boat + MACHINE, //!< its a machine + AI, //!< machine controlled by an Artificial Intelligence }; -enum { - NOSHOCK, //!< not a shock - SHOCK1, //!< shock1 - SHOCK2, //!< shock2 - SHOCK3, //!< shock3 - TRIGGER, //!< trigger - SUPPORTBEAM, //!< - ROPE //!< -}; -enum blinktype { - BLINK_NONE, //!< - BLINK_LEFT, //!< - BLINK_RIGHT, //!< - BLINK_WARN //!< +enum +{ + NOSHOCK, //!< not a shock + SHOCK1, //!< shock1 + SHOCK2, //!< shock2 + SHOCK3, //!< shock3 + TRIGGER, //!< trigger + SUPPORTBEAM, //!< + ROPE //!< +}; +enum blinktype +{ + BLINK_NONE, //!< + BLINK_LEFT, //!< + BLINK_RIGHT, //!< + BLINK_WARN //!< }; -enum { +enum +{ HYDRO_FLAG_SPEED = BITMASK(1), HYDRO_FLAG_DIR = BITMASK(2), HYDRO_FLAG_AILERON = BITMASK(3), @@ -106,93 +114,98 @@ enum { HYDRO_FLAG_REV_ELEVATOR = BITMASK(8), }; -enum { - ANIM_FLAG_AIRSPEED = BITMASK(1), - ANIM_FLAG_VVI = BITMASK(2), - ANIM_FLAG_ALTIMETER = BITMASK(3), - ANIM_FLAG_AOA = BITMASK(4), - ANIM_FLAG_FLAP = BITMASK(5), - ANIM_FLAG_AIRBRAKE = BITMASK(6), - ANIM_FLAG_ROLL = BITMASK(7), - ANIM_FLAG_PITCH = BITMASK(8), - ANIM_FLAG_THROTTLE = BITMASK(9), - ANIM_FLAG_RPM = BITMASK(10), - ANIM_FLAG_ACCEL = BITMASK(11), - ANIM_FLAG_BRAKE = BITMASK(12), - ANIM_FLAG_CLUTCH = BITMASK(13), - ANIM_FLAG_TACHO = BITMASK(14), - ANIM_FLAG_SPEEDO = BITMASK(15), - ANIM_FLAG_PBRAKE = BITMASK(16), - ANIM_FLAG_TURBO = BITMASK(17), - ANIM_FLAG_SHIFTER = BITMASK(18), - ANIM_FLAG_AETORQUE = BITMASK(19), - ANIM_FLAG_AEPITCH = BITMASK(20), - ANIM_FLAG_AESTATUS = BITMASK(21), - ANIM_FLAG_TORQUE = BITMASK(22), - ANIM_FLAG_HEADING = BITMASK(23), - ANIM_FLAG_DIFFLOCK = BITMASK(24), - ANIM_FLAG_STEERING = BITMASK(25), - ANIM_FLAG_EVENT = BITMASK(26), - ANIM_FLAG_AILERONS = BITMASK(27), - ANIM_FLAG_ARUDDER = BITMASK(28), - ANIM_FLAG_BRUDDER = BITMASK(29), - ANIM_FLAG_BTHROTTLE = BITMASK(30), - ANIM_FLAG_PERMANENT = BITMASK(31), - ANIM_FLAG_ELEVATORS = BITMASK(32), -}; - -enum { - ANIM_MODE_ROTA_X = BITMASK(1), - ANIM_MODE_ROTA_Y = BITMASK(2), - ANIM_MODE_ROTA_Z = BITMASK(3), - ANIM_MODE_OFFSET_X = BITMASK(4), - ANIM_MODE_OFFSET_Y = BITMASK(5), - ANIM_MODE_OFFSET_Z = BITMASK(6), - ANIM_MODE_AUTOANIMATE = BITMASK(7), - ANIM_MODE_NOFLIP = BITMASK(8), - ANIM_MODE_BOUNCE = BITMASK(9), -}; - -enum { - SHOCK_FLAG_NORMAL = BITMASK(1), - SHOCK_FLAG_LACTIVE = BITMASK(3), - SHOCK_FLAG_RACTIVE = BITMASK(4), - SHOCK_FLAG_ISSHOCK2 = BITMASK(5), - SHOCK_FLAG_ISSHOCK3 = BITMASK(6), - SHOCK_FLAG_SOFTBUMP = BITMASK(7), - SHOCK_FLAG_ISTRIGGER = BITMASK(8), - SHOCK_FLAG_TRG_BLOCKER = BITMASK(9), - SHOCK_FLAG_TRG_CMD_SWITCH = BITMASK(10), - SHOCK_FLAG_TRG_CMD_BLOCKER = BITMASK(11), - SHOCK_FLAG_TRG_BLOCKER_A = BITMASK(12), - SHOCK_FLAG_TRG_HOOK_UNLOCK = BITMASK(13), - SHOCK_FLAG_TRG_HOOK_LOCK = BITMASK(14), - SHOCK_FLAG_TRG_CONTINUOUS = BITMASK(15), - SHOCK_FLAG_TRG_ENGINE = BITMASK(16) -}; - -enum { +enum +{ + ANIM_FLAG_AIRSPEED = BITMASK(1), + ANIM_FLAG_VVI = BITMASK(2), + ANIM_FLAG_ALTIMETER = BITMASK(3), + ANIM_FLAG_AOA = BITMASK(4), + ANIM_FLAG_FLAP = BITMASK(5), + ANIM_FLAG_AIRBRAKE = BITMASK(6), + ANIM_FLAG_ROLL = BITMASK(7), + ANIM_FLAG_PITCH = BITMASK(8), + ANIM_FLAG_THROTTLE = BITMASK(9), + ANIM_FLAG_RPM = BITMASK(10), + ANIM_FLAG_ACCEL = BITMASK(11), + ANIM_FLAG_BRAKE = BITMASK(12), + ANIM_FLAG_CLUTCH = BITMASK(13), + ANIM_FLAG_TACHO = BITMASK(14), + ANIM_FLAG_SPEEDO = BITMASK(15), + ANIM_FLAG_PBRAKE = BITMASK(16), + ANIM_FLAG_TURBO = BITMASK(17), + ANIM_FLAG_SHIFTER = BITMASK(18), + ANIM_FLAG_AETORQUE = BITMASK(19), + ANIM_FLAG_AEPITCH = BITMASK(20), + ANIM_FLAG_AESTATUS = BITMASK(21), + ANIM_FLAG_TORQUE = BITMASK(22), + ANIM_FLAG_HEADING = BITMASK(23), + ANIM_FLAG_DIFFLOCK = BITMASK(24), + ANIM_FLAG_STEERING = BITMASK(25), + ANIM_FLAG_EVENT = BITMASK(26), + ANIM_FLAG_AILERONS = BITMASK(27), + ANIM_FLAG_ARUDDER = BITMASK(28), + ANIM_FLAG_BRUDDER = BITMASK(29), + ANIM_FLAG_BTHROTTLE = BITMASK(30), + ANIM_FLAG_PERMANENT = BITMASK(31), + ANIM_FLAG_ELEVATORS = BITMASK(32), +}; + +enum +{ + ANIM_MODE_ROTA_X = BITMASK(1), + ANIM_MODE_ROTA_Y = BITMASK(2), + ANIM_MODE_ROTA_Z = BITMASK(3), + ANIM_MODE_OFFSET_X = BITMASK(4), + ANIM_MODE_OFFSET_Y = BITMASK(5), + ANIM_MODE_OFFSET_Z = BITMASK(6), + ANIM_MODE_AUTOANIMATE = BITMASK(7), + ANIM_MODE_NOFLIP = BITMASK(8), + ANIM_MODE_BOUNCE = BITMASK(9), +}; + +enum +{ + SHOCK_FLAG_NORMAL = BITMASK(1), + SHOCK_FLAG_LACTIVE = BITMASK(3), + SHOCK_FLAG_RACTIVE = BITMASK(4), + SHOCK_FLAG_ISSHOCK2 = BITMASK(5), + SHOCK_FLAG_ISSHOCK3 = BITMASK(6), + SHOCK_FLAG_SOFTBUMP = BITMASK(7), + SHOCK_FLAG_ISTRIGGER = BITMASK(8), + SHOCK_FLAG_TRG_BLOCKER = BITMASK(9), + SHOCK_FLAG_TRG_CMD_SWITCH = BITMASK(10), + SHOCK_FLAG_TRG_CMD_BLOCKER = BITMASK(11), + SHOCK_FLAG_TRG_BLOCKER_A = BITMASK(12), + SHOCK_FLAG_TRG_HOOK_UNLOCK = BITMASK(13), + SHOCK_FLAG_TRG_HOOK_LOCK = BITMASK(14), + SHOCK_FLAG_TRG_CONTINUOUS = BITMASK(15), + SHOCK_FLAG_TRG_ENGINE = BITMASK(16) +}; + +enum +{ TRG_ENGINE_CLUTCH = 0, TRG_ENGINE_BRAKE = 1, TRG_ENGINE_ACC = 2, TRG_ENGINE_RPM = 3, TRG_ENGINE_SHIFTUP = 4, - TRG_ENGINE_SHIFTDOWN = 5 + TRG_ENGINE_SHIFTDOWN = 5 }; -enum { - DEFAULT_DETACHER_GROUP = 0, // default for detaching beam group +enum +{ + DEFAULT_DETACHER_GROUP = 0, // default for detaching beam group }; -enum class FlareType: char +enum class FlareType : char { - NONE = 0, - HEADLIGHT = 'f', - BRAKE_LIGHT = 'b', - REVERSE_LIGHT = 'R', - BLINKER_LEFT = 'l', - BLINKER_RIGHT = 'r', - USER = 'u' + NONE = 0, + HEADLIGHT = 'f', + BRAKE_LIGHT = 'b', + REVERSE_LIGHT = 'R', + BLINKER_LEFT = 'l', + BLINKER_RIGHT = 'r', + USER = 'u' }; /* some info holding arrays */ @@ -213,9 +226,9 @@ struct collcab_rate_t struct soundsource_t { - SoundScriptInstance* ssi; - int nodenum; - int type; + SoundScriptInstance *ssi; + int nodenum; + int type; }; #include "datatypes/wheel_t.h" @@ -234,115 +247,118 @@ struct hook_t float hk_timer; float hk_timer_preset; float hk_min_length; //!< Absolute value in meters - node_t* hk_hook_node; - node_t* hk_lock_node; - beam_t* hk_beam; - Actor* hk_locked_actor; + node_t *hk_hook_node; + node_t *hk_lock_node; + beam_t *hk_beam; + Actor * hk_locked_actor; }; struct ropable_t { node_t *node; - int pos; //!< Index into ar_ropables - int group; - int attached_ties; //!< State - int attached_ropes; //!< State - bool multilock; //!< Attribute + int pos; //!< Index into ar_ropables + int group; + int attached_ties; //!< State + int attached_ropes; //!< State + bool multilock; //!< Attribute }; struct rope_t { int rp_locked; int rp_group; - beam_t* rp_beam; - ropable_t* rp_locked_ropable; - Actor* rp_locked_actor; + beam_t * rp_beam; + ropable_t *rp_locked_ropable; + Actor * rp_locked_actor; }; struct tie_t { - Actor* ti_locked_actor; - beam_t* ti_beam; - ropable_t* ti_locked_ropable; + Actor * ti_locked_actor; + beam_t * ti_beam; + ropable_t *ti_locked_ropable; int ti_group; float ti_contract_speed; float ti_max_stress; - float ti_min_length; //!< Proportional to orig; length + float ti_min_length; //!< Proportional to orig; length - bool ti_no_self_lock:1; //!< Attribute - bool ti_tied:1; //!< State - bool ti_tying:1; //!< State + bool ti_no_self_lock : 1; //!< Attribute + bool ti_tied : 1; //!< State + bool ti_tying : 1; //!< State }; struct wing_t { - FlexAirfoil *fa; + FlexAirfoil * fa; Ogre::SceneNode *cnode; }; struct commandbeam_state_t { - commandbeam_state_t() { memset(this, 0, sizeof(commandbeam_state_t)); } + commandbeam_state_t() + { + memset(this, 0, sizeof(commandbeam_state_t)); + } - int8_t auto_moving_mode; //!< State + int8_t auto_moving_mode; //!< State // Bit flags - bool pressed_center_mode:1; //!< State - bool auto_move_lock:1; //!< State + bool pressed_center_mode : 1; //!< State + bool auto_move_lock : 1; //!< State }; struct commandbeam_t { - uint16_t cmb_beam_index; //!< Index to Actor::ar_beams array - float cmb_engine_coupling; //!< Attr from truckfile - float cmb_center_length; //!< Attr computed at spawn - float cmb_speed; //!< Attr; Rate of contraction/extension - float cmb_boundary_length; //!< Attr; Maximum/minimum length proportional to orig. len. + uint16_t cmb_beam_index; //!< Index to Actor::ar_beams array + float cmb_engine_coupling; //!< Attr from truckfile + float cmb_center_length; //!< Attr computed at spawn + float cmb_speed; //!< Attr; Rate of contraction/extension + float cmb_boundary_length; //!< Attr; Maximum/minimum length proportional to orig. len. // Bit flags - bool cmb_is_contraction:1; //!< Attribute defined at spawn - bool cmb_is_force_restricted:1; //!< Attribute defined in truckfile - bool cmb_needs_engine:1; //!< Attribute defined in truckfile - bool cmb_is_autocentering:1; //!< Attribute defined in truckfile - bool cmb_plays_sound:1; //!< Attribute defined in truckfile - bool cmb_is_1press:1; //!< Attribute defined in truckfile - bool cmb_is_1press_center:1; //!< Attribute defined in truckfile + bool cmb_is_contraction : 1; //!< Attribute defined at spawn + bool cmb_is_force_restricted : 1; //!< Attribute defined in truckfile + bool cmb_needs_engine : 1; //!< Attribute defined in truckfile + bool cmb_is_autocentering : 1; //!< Attribute defined in truckfile + bool cmb_plays_sound : 1; //!< Attribute defined in truckfile + bool cmb_is_1press : 1; //!< Attribute defined in truckfile + bool cmb_is_1press_center : 1; //!< Attribute defined in truckfile std::shared_ptr cmb_state; }; struct command_t { - int commandValueState; - float commandValue; - float triggerInputValue; - float playerInputValue; - bool trigger_cmdkeyblock_state; //!< identifies blocked F-commands for triggers + int commandValueState; + float commandValue; + float triggerInputValue; + float playerInputValue; + bool trigger_cmdkeyblock_state; //!< identifies blocked F-commands for triggers std::vector beams; - std::vector rotators; - Ogre::String description; - RoR::CmdKeyInertia rotator_inertia; - RoR::CmdKeyInertia command_inertia; + std::vector rotators; + Ogre::String description; + RoR::CmdKeyInertia rotator_inertia; + RoR::CmdKeyInertia command_inertia; }; struct hydrobeam_t { - uint16_t hb_beam_index; //!< Index to Actor::ar_beams array - float hb_ref_length; //!< Idle length in meters - float hb_speed; //!< Rate of change - int hb_flags; - int hb_anim_flags; //!< Animators (beams updating length based on simulation variables) - float hb_anim_param; //!< Animators (beams updating length based on simulation variables) - RoR::CmdKeyInertia hb_inertia; + uint16_t hb_beam_index; //!< Index to Actor::ar_beams array + float hb_ref_length; //!< Idle length in meters + float hb_speed; //!< Rate of change + int hb_flags; + int hb_anim_flags; //!< Animators (beams updating length based on simulation variables) + float hb_anim_param; //!< Animators (beams updating length based on simulation variables) + RoR::CmdKeyInertia hb_inertia; }; struct rotator_t { - bool needs_engine; - int nodes1[4]; - int nodes2[4]; - int axis1; //!< rot axis - int axis2; + bool needs_engine; + int nodes1[4]; + int nodes2[4]; + int axis1; //!< rot axis + int axis2; float angle; float rate; float force; @@ -354,50 +370,54 @@ struct rotator_t struct flare_t { - int noderef; - int nodex; - int nodey; - float offsetx; - float offsety; - float offsetz; - Ogre::SceneNode *snode; + int noderef; + int nodex; + int nodey; + float offsetx; + float offsety; + float offsetz; + Ogre::SceneNode * snode; Ogre::BillboardSet *bbs; - Ogre::Light *light; - FlareType fl_type; - int controlnumber; - bool controltoggle_status; - float blinkdelay; - float blinkdelay_curr; - bool blinkdelay_state; - float size; - bool isVisible; + Ogre::Light * light; + FlareType fl_type; + int controlnumber; + bool controltoggle_status; + float blinkdelay; + float blinkdelay_curr; + bool blinkdelay_state; + float size; + bool isVisible; }; /** -* SIM-CORE; Prop = an object mounted on vehicle chassis. -*/ + * SIM-CORE; Prop = an object mounted on vehicle chassis. + */ struct prop_t { - prop_t() { memset(this, 0, sizeof(*this)); } - - int noderef; - int nodex; - int nodey; - float offsetx; - float offsety; - float offsetz; - float rotaX; - float rotaY; - float rotaZ; - float orgoffsetX; - float orgoffsetY; - float orgoffsetZ; + prop_t() + { + memset(this, 0, sizeof(*this)); + } + + int noderef; + int nodex; + int nodey; + float offsetx; + float offsety; + float offsetz; + float rotaX; + float rotaY; + float rotaZ; + float orgoffsetX; + float orgoffsetY; + float orgoffsetZ; Ogre::Quaternion rot; Ogre::SceneNode *scene_node; //!< The pivot scene node (parented to root-node). - Ogre::SceneNode *wheel; //!< Special prop: custom steering wheel for dashboard - Ogre::Vector3 wheelpos; //!< Special prop: custom steering wheel for dashboard - int mirror; //1 then liquid is Dilatant fluid (less common) float flow_behavior_index; - - float solid_ground_level; //!< how deep the solid ground is - float drag_anisotropy; //!< Upwards/Downwards drag anisotropy + float solid_ground_level; //!< how deep the solid ground is + float drag_anisotropy; //!< Upwards/Downwards drag anisotropy - int fx_type; + int fx_type; Ogre::ColourValue fx_colour; - char name[256]; - char basename[256]; - char particle_name[256]; + char name[256]; + char basename[256]; + char particle_name[256]; - int fx_particle_amount; //!< amount of particles + int fx_particle_amount; //!< amount of particles - float fx_particle_min_velo; //!< minimum velocity to display sparks - float fx_particle_max_velo; //!< maximum velocity to display sparks - float fx_particle_fade; //!< fade coefficient - float fx_particle_timedelta; //!< delta for particle animation - float fx_particle_velo_factor; //!< velocity factor + float fx_particle_min_velo; //!< minimum velocity to display sparks + float fx_particle_max_velo; //!< maximum velocity to display sparks + float fx_particle_fade; //!< fade coefficient + float fx_particle_timedelta; //!< delta for particle animation + float fx_particle_velo_factor; //!< velocity factor float fx_particle_ttl; }; struct authorinfo_t { - int id; + int id; Ogre::String type; Ogre::String name; Ogre::String email; }; -namespace RoR { - -struct ActorSpawnRequest +namespace RoR { - enum class Origin //!< Enables special processing + + struct ActorSpawnRequest { - UNKNOWN, - CONFIG_FILE, //!< 'Preselected vehicle' in RoR.cfg - TERRN_DEF, //!< Preloaded with terrain - USER, //!< Direct selection by user via GUI - SAVEGAME, //!< User spawned and part of a savegame - NETWORK //!< Remote controlled + enum class Origin //!< Enables special processing + { + UNKNOWN, + CONFIG_FILE, //!< 'Preselected vehicle' in RoR.cfg + TERRN_DEF, //!< Preloaded with terrain + USER, //!< Direct selection by user via GUI + SAVEGAME, //!< User spawned and part of a savegame + NETWORK //!< Remote controlled + }; + + ActorSpawnRequest(); + + CacheEntry * asr_cache_entry; //!< Optional, overrides 'asr_filename' and 'asr_cache_entry_num' + std::string asr_filename; + Ogre::String asr_config; + Ogre::Vector3 asr_position; + Ogre::Quaternion asr_rotation; + collision_box_t *asr_spawnbox; + CacheEntry * asr_skin_entry; + Origin asr_origin; + Ogre::UTFString asr_net_username; + int asr_net_color; + bool asr_free_position : 1; //!< Disables the automatic spawn position adjustment + bool asr_terrn_machine : 1; //!< This is a fixed machinery }; - ActorSpawnRequest(); - - CacheEntry* asr_cache_entry; //!< Optional, overrides 'asr_filename' and 'asr_cache_entry_num' - std::string asr_filename; - Ogre::String asr_config; - Ogre::Vector3 asr_position; - Ogre::Quaternion asr_rotation; - collision_box_t* asr_spawnbox; - CacheEntry* asr_skin_entry; - Origin asr_origin; - Ogre::UTFString asr_net_username; - int asr_net_color; - bool asr_free_position:1; //!< Disables the automatic spawn position adjustment - bool asr_terrn_machine:1; //!< This is a fixed machinery -}; - -struct ActorModifyRequest -{ - enum class Type + struct ActorModifyRequest { - INVALID, - RELOAD, //!< Full reload from filesystem, requested by user - RESET_ON_INIT_POS, - RESET_ON_SPOT, - SOFT_RESET + enum class Type + { + INVALID, + RELOAD, //!< Full reload from filesystem, requested by user + RESET_ON_INIT_POS, + RESET_ON_SPOT, + SOFT_RESET + }; + + Actor *amr_actor; + Type amr_type; }; - Actor* amr_actor; - Type amr_type; -}; - } // namespace RoR diff --git a/source/main/physics/BeamFactory.cpp b/source/main/physics/BeamFactory.cpp index 102b253397..02fc23cce2 100644 --- a/source/main/physics/BeamFactory.cpp +++ b/source/main/physics/BeamFactory.cpp @@ -29,9 +29,9 @@ #include "Beam.h" #include "BeamEngine.h" #include "CacheSystem.h" -#include "ContentManager.h" #include "ChatSystem.h" #include "Collisions.h" +#include "ContentManager.h" #include "DashBoardManager.h" #include "DynamicCollisions.h" #include "GUIManager.h" @@ -59,11 +59,8 @@ using namespace RoR; static int m_actor_counter = 0; ActorManager::ActorManager() - : m_dt_remainder(0.0f) - , m_forced_awake(false) - , m_physics_steps(2000) - , m_simulation_speed(1.0f) - , m_savegame_terrain_has_changed(false) + : m_dt_remainder(0.0f), m_forced_awake(false), m_physics_steps(2000), m_simulation_speed(1.0f), + m_savegame_terrain_has_changed(false) { // Create worker thread (used for physics calculations) m_sim_thread_pool = std::unique_ptr(new ThreadPool(1)); @@ -92,11 +89,11 @@ ActorManager::~ActorManager() delete gEnv->threadPool; } -void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_ptr def) +void ActorManager::SetupActor(Actor *actor, ActorSpawnRequest rq, std::shared_ptr def) { // ~~~~ Code ported from Actor::Actor() - Ogre::SceneNode* parent_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + Ogre::SceneNode *parent_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); // ~~~~ Code ported from Actor::LoadActor() // LoadActor(def, beams_parent, pos, rot, spawnbox, cache_entry_number) @@ -114,10 +111,7 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt spawner.Setup(actor, def, parent_scene_node, rq.asr_position); /* Setup modules */ spawner.AddModule(def->root_module); - if (!actor->m_section_config.empty()) - { - spawner.AddModule(actor->m_section_config); - } + if (!actor->m_section_config.empty()) { spawner.AddModule(actor->m_section_config); } spawner.SpawnActor(); def->report_num_errors += spawner.GetMessagesNumErrors(); def->report_num_warnings += spawner.GetMessagesNumWarnings(); @@ -125,13 +119,11 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt // Spawner log already printed to RoR.log def->loading_report += spawner.ProcessMessagesToString() + "\n\n"; - RoR::App::GetGuiManager()->AddRigLoadingReport(def->name, def->loading_report, def->report_num_errors, def->report_num_warnings, def->report_num_other); + RoR::App::GetGuiManager()->AddRigLoadingReport(def->name, def->loading_report, def->report_num_errors, + def->report_num_warnings, def->report_num_other); if (def->report_num_errors != 0) { - if (App::diag_auto_spawner_report.GetActive()) - { - RoR::App::GetGuiManager()->SetVisible_SpawnerReport(true); - } + if (App::diag_auto_spawner_report.GetActive()) { RoR::App::GetGuiManager()->SetVisible_SpawnerReport(true); } } /* POST-PROCESSING (Old-spawn code from Actor::loadTruck2) */ @@ -144,10 +136,10 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { // Calculate optimal node position compression (for network transfer) - Vector3 aabb_size = actor->ar_bounding_box.getSize(); - float max_dimension = std::max(1.0f, aabb_size.x); - max_dimension = std::max(max_dimension, aabb_size.y); - max_dimension = std::max(max_dimension, aabb_size.z); + Vector3 aabb_size = actor->ar_bounding_box.getSize(); + float max_dimension = std::max(1.0f, aabb_size.x); + max_dimension = std::max(max_dimension, aabb_size.y); + max_dimension = std::max(max_dimension, aabb_size.z); actor->m_net_node_compression = std::numeric_limits::max() / std::ceil(max_dimension * 1.5f); } // Apply spawn position & spawn rotation @@ -169,15 +161,9 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt float miny = 0.0f; - if (!actor->m_preloaded_with_terrain) - { - miny = vehicle_position.y; - } + if (!actor->m_preloaded_with_terrain) { miny = vehicle_position.y; } - if (rq.asr_spawnbox != nullptr) - { - miny = rq.asr_spawnbox->relo.y + rq.asr_spawnbox->center.y; - } + if (rq.asr_spawnbox != nullptr) { miny = rq.asr_spawnbox->relo.y + rq.asr_spawnbox->center.y; } if (rq.asr_free_position) actor->ResetPosition(vehicle_position, true); @@ -195,7 +181,11 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt { Vector3 gpos = Vector3(vehicle_position.x, 0.0f, vehicle_position.z); - gpos -= rq.asr_rotation * Vector3((rq.asr_spawnbox->hi.x - rq.asr_spawnbox->lo.x + actor->ar_bounding_box.getMaximum().x - actor->ar_bounding_box.getMinimum().x) * 0.6f, 0.0f, 0.0f); + gpos -= + rq.asr_rotation * Vector3((rq.asr_spawnbox->hi.x - rq.asr_spawnbox->lo.x + + actor->ar_bounding_box.getMaximum().x - actor->ar_bounding_box.getMinimum().x) * + 0.6f, + 0.0f, 0.0f); actor->ResetPosition(gpos.x, gpos.z, true, miny); } @@ -207,7 +197,7 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt } actor->UpdateBoundingBoxes(); - //compute final mass + // compute final mass actor->RecalculateNodeMasses(actor->m_dry_mass); actor->ar_initial_total_mass = actor->m_total_mass; for (int i = 0; i < actor->ar_num_nodes; i++) @@ -215,13 +205,10 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt actor->ar_initial_node_masses[i] = actor->ar_nodes[i].mass; } - //setup default sounds - if (!actor->m_disable_default_sounds) - { - ActorSpawner::SetupDefaultSoundSources(actor); - } + // setup default sounds + if (!actor->m_disable_default_sounds) { ActorSpawner::SetupDefaultSoundSources(actor); } - //compute node connectivity graph + // compute node connectivity graph actor->calcNodeConnectivityGraph(); actor->UpdateBoundingBoxes(); @@ -232,10 +219,7 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt for (int i = 0; i < actor->ar_num_nodes; i++) { Real dist = actor->ar_nodes[i].AbsPosition.squaredDistance(actor->m_avg_node_position); - if (dist > actor->m_min_camera_radius) - { - actor->m_min_camera_radius = dist; - } + if (dist > actor->m_min_camera_radius) { actor->m_min_camera_radius = dist; } } actor->m_min_camera_radius = std::sqrt(actor->m_min_camera_radius) * 1.2f; // twenty percent buffer @@ -244,18 +228,15 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt if (!subMeshGroundModelName.empty()) { actor->ar_submesh_ground_model = gEnv->collisions->getGroundModelByString(subMeshGroundModelName); - if (!actor->ar_submesh_ground_model) - { - actor->ar_submesh_ground_model = gEnv->collisions->defaultgm; - } + if (!actor->ar_submesh_ground_model) { actor->ar_submesh_ground_model = gEnv->collisions->defaultgm; } } // Set beam defaults for (int i = 0; i < actor->ar_num_beams; i++) { - actor->ar_beams[i].initial_beam_strength = actor->ar_beams[i].strength; - actor->ar_beams[i].default_beam_deform = actor->ar_beams[i].minmaxposnegstress; - actor->ar_initial_beam_defaults[i] = std::make_pair(actor->ar_beams[i].k, actor->ar_beams[i].d); + actor->ar_beams[i].initial_beam_strength = actor->ar_beams[i].strength; + actor->ar_beams[i].default_beam_deform = actor->ar_beams[i].minmaxposnegstress; + actor->ar_initial_beam_defaults[i] = std::make_pair(actor->ar_beams[i].k, actor->ar_beams[i].d); } actor->m_spawn_rotation = actor->getRotation(); @@ -270,8 +251,7 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt actor->m_wheel_node_count = 0; for (int i = 0; i < actor->ar_num_nodes; i++) { - if (actor->ar_nodes[i].nd_tyre_node) - actor->m_wheel_node_count++; + if (actor->ar_nodes[i].nd_tyre_node) actor->m_wheel_node_count++; } // search m_net_first_wheel_node @@ -293,12 +273,12 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt { actor->GetGfxActor()->UpdateSimDataBuffer(); // Initial fill of sim data buffers - actor->GetGfxActor()->UpdateFlexbodies(); // Push tasks to threadpool + actor->GetGfxActor()->UpdateFlexbodies(); // Push tasks to threadpool actor->GetGfxActor()->UpdateWheelVisuals(); // Push tasks to threadpool actor->GetGfxActor()->UpdateCabMesh(); actor->GetGfxActor()->UpdateWingMeshes(); actor->GetGfxActor()->UpdateProps(0.f, false); - actor->GetGfxActor()->FinishWheelUpdates(); // Sync tasks from threadpool + actor->GetGfxActor()->FinishWheelUpdates(); // Sync tasks from threadpool actor->GetGfxActor()->FinishFlexbodyTasks(); // Sync tasks from threadpool } @@ -325,15 +305,12 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt // - ar_num_wheels times a float for the wheel rotation // actor->m_net_node_buf_size = sizeof(float) * 3 + (actor->m_net_first_wheel_node - 1) * sizeof(short int) * 3; - actor->m_net_buffer_size = actor->m_net_node_buf_size + actor->ar_num_wheels * sizeof(float); + actor->m_net_buffer_size = actor->m_net_node_buf_size + actor->ar_num_wheels * sizeof(float); if (rq.asr_origin == ActorSpawnRequest::Origin::NETWORK) { actor->ar_sim_state = Actor::SimState::NETWORKED_OK; - if (actor->ar_engine) - { - actor->ar_engine->StartEngine(); - } + if (actor->ar_engine) { actor->ar_engine->StartEngine(); } } actor->m_net_username = rq.asr_net_username; @@ -368,15 +345,13 @@ void ActorManager::SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_pt LOG(" ===== DONE LOADING VEHICLE"); } -Actor* ActorManager::CreateActorInstance(ActorSpawnRequest rq, std::shared_ptr def) +Actor *ActorManager::CreateActorInstance(ActorSpawnRequest rq, std::shared_ptr def) { - Actor* actor = new Actor(m_actor_counter++, static_cast(m_actors.size()), def, rq); + Actor *actor = new Actor(m_actor_counter++, static_cast(m_actors.size()), def, rq); actor->SetUsedSkin(rq.asr_skin_entry); if (App::mp_state.GetActive() == MpState::CONNECTED && rq.asr_origin != ActorSpawnRequest::Origin::NETWORK) - { - actor->sendStreamSetup(); - } + { actor->sendStreamSetup(); } this->SetupActor(actor, rq, def); @@ -391,13 +366,9 @@ void ActorManager::RemoveStreamSource(int sourceid) for (auto actor : m_actors) { - if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - continue; + if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) continue; - if (actor->ar_net_source_id == sourceid) - { - App::GetSimController()->QueueActorRemove(actor); - } + if (actor->ar_net_source_id == sourceid) { App::GetSimController()->QueueActorRemove(actor); } } } @@ -406,25 +377,28 @@ void ActorManager::HandleActorStreamData(std::vector b.header.source; }); + [](const RoR::Networking::recv_packet_t &a, const RoR::Networking::recv_packet_t &b) { + return a.header.source > b.header.source; + }); // Compress data stream by eliminating all but the last update from every consecutive group of stream data updates auto it = std::unique(packet_buffer.rbegin(), packet_buffer.rend(), - [](const RoR::Networking::recv_packet_t& a, const RoR::Networking::recv_packet_t& b) - { return !memcmp(&a.header, &b.header, sizeof(RoRnet::Header)) && - a.header.command == RoRnet::MSG2_STREAM_DATA; }); + [](const RoR::Networking::recv_packet_t &a, const RoR::Networking::recv_packet_t &b) { + return !memcmp(&a.header, &b.header, sizeof(RoRnet::Header)) && + a.header.command == RoRnet::MSG2_STREAM_DATA; + }); packet_buffer.erase(packet_buffer.begin(), it.base()); - for (auto& packet : packet_buffer) + for (auto &packet : packet_buffer) { if (packet.header.command == RoRnet::MSG2_STREAM_REGISTER) { - RoRnet::StreamRegister* reg = (RoRnet::StreamRegister *)packet.buffer; + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)packet.buffer; if (reg->type == 0) { RoRnet::UserInfo info; RoR::Networking::GetUserInfo(reg->origin_sourceid, info); - UTFString message = RoR::ChatSystem::GetColouredName(info.username, info.colournum) + RoR::Color::CommandColour + _L(" spawned a new vehicle: ") + RoR::Color::NormalColour + reg->name; + UTFString message = RoR::ChatSystem::GetColouredName(info.username, info.colournum) + RoR::Color::CommandColour + + _L(" spawned a new vehicle: ") + RoR::Color::NormalColour + reg->name; RoR::App::GetGuiManager()->pushMessageChatBox(message); LOG("[RoR] Creating remote actor for " + TOSTRING(reg->origin_sourceid) + ":" + TOSTRING(reg->origin_streamid)); @@ -440,10 +414,10 @@ void ActorManager::HandleActorStreamData(std::vector(reg); + auto actor_reg = reinterpret_cast(reg); if (m_stream_time_offsets.find(reg->origin_sourceid) == m_stream_time_offsets.end()) { - int offset = actor_reg->time - m_net_timer.getMilliseconds(); + int offset = actor_reg->time - m_net_timer.getMilliseconds(); m_stream_time_offsets[reg->origin_sourceid] = offset - 100; } ActorSpawnRequest rq; @@ -451,56 +425,49 @@ void ActorManager::HandleActorStreamData(std::vectorskin, 60) < 60 && actor_reg->skin[0] != '\0') - { - rq.asr_skin_entry = App::GetCacheSystem()->FetchSkinByName(actor_reg->skin); - } - if (strnlen(actor_reg->sectionconfig, 60) < 60) - { - rq.asr_config = actor_reg->sectionconfig; - } + { rq.asr_skin_entry = App::GetCacheSystem()->FetchSkinByName(actor_reg->skin); } + if (strnlen(actor_reg->sectionconfig, 60) < 60) { rq.asr_config = actor_reg->sectionconfig; } rq.asr_net_username = tryConvertUTF(info.username); rq.asr_net_color = info.colournum; - Actor* actor = App::GetSimController()->SpawnActorDirectly(rq); + Actor *actor = App::GetSimController()->SpawnActorDirectly(rq); actor->ar_net_source_id = reg->origin_sourceid; actor->ar_net_stream_id = reg->origin_streamid; reg->status = 1; } - RoR::Networking::AddPacket(reg->origin_streamid, RoRnet::MSG2_STREAM_REGISTER_RESULT, sizeof(RoRnet::StreamRegister), (char *)reg); + RoR::Networking::AddPacket(reg->origin_streamid, RoRnet::MSG2_STREAM_REGISTER_RESULT, + sizeof(RoRnet::StreamRegister), (char *)reg); } } else if (packet.header.command == RoRnet::MSG2_STREAM_REGISTER_RESULT) { - RoRnet::StreamRegister* reg = (RoRnet::StreamRegister *)packet.buffer; + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *)packet.buffer; for (auto actor : m_actors) { if (actor->ar_net_source_id == reg->origin_sourceid && actor->ar_net_stream_id == reg->origin_streamid) { - int sourceid = packet.header.source; + int sourceid = packet.header.source; actor->ar_net_stream_results[sourceid] = reg->status; String message = ""; switch (reg->status) { - case 1: message = "successfully loaded stream"; break; - case -2: message = "detected mismatch stream"; break; - default: message = "could not load stream"; break; + case 1: message = "successfully loaded stream"; break; + case -2: message = "detected mismatch stream"; break; + default: message = "could not load stream"; break; } - LOG("Client " + TOSTRING(sourceid) + " " + message + " " + TOSTRING(reg->origin_streamid) + - " with name '" + reg->name + "', result code: " + TOSTRING(reg->status)); + LOG("Client " + TOSTRING(sourceid) + " " + message + " " + TOSTRING(reg->origin_streamid) + " with name '" + + reg->name + "', result code: " + TOSTRING(reg->status)); break; } } } else if (packet.header.command == RoRnet::MSG2_STREAM_UNREGISTER) { - Actor* b = this->GetActorByNetworkLinks(packet.header.source, packet.header.streamid); - if (b && b->ar_sim_state == Actor::SimState::NETWORKED_OK) - { - App::GetSimController()->QueueActorRemove(b); - } + Actor *b = this->GetActorByNetworkLinks(packet.header.source, packet.header.streamid); + if (b && b->ar_sim_state == Actor::SimState::NETWORKED_OK) { App::GetSimController()->QueueActorRemove(b); } m_stream_mismatches[packet.header.source].erase(packet.header.streamid); } else if (packet.header.command == RoRnet::MSG2_USER_LEAVE) @@ -511,8 +478,7 @@ void ActorManager::HandleActorStreamData(std::vectorar_sim_state != Actor::SimState::NETWORKED_OK) - continue; + if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) continue; if (packet.header.source == actor->ar_net_source_id && packet.header.streamid == actor->ar_net_stream_id) { actor->PushNetwork(packet.buffer, packet.header.size); @@ -527,35 +493,24 @@ void ActorManager::HandleActorStreamData(std::vectorsecond; - } + if (search != m_stream_time_offsets.end()) { return search->second; } return 0; } void ActorManager::UpdateNetTimeOffset(int sourceid, int offset) { - if (m_stream_time_offsets.find(sourceid) != m_stream_time_offsets.end()) - { - m_stream_time_offsets[sourceid] += offset; - } + if (m_stream_time_offsets.find(sourceid) != m_stream_time_offsets.end()) { m_stream_time_offsets[sourceid] += offset; } } int ActorManager::CheckNetworkStreamsOk(int sourceid) { - if (!m_stream_mismatches[sourceid].empty()) - return 0; + if (!m_stream_mismatches[sourceid].empty()) return 0; for (auto actor : m_actors) { - if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - continue; + if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) continue; - if (actor->ar_net_source_id == sourceid) - { - return 1; - } + if (actor->ar_net_source_id == sourceid) { return 1; } } return 2; @@ -567,27 +522,21 @@ int ActorManager::CheckNetRemoteStreamsOk(int sourceid) for (auto actor : m_actors) { - if (actor->ar_sim_state == Actor::SimState::NETWORKED_OK) - continue; + if (actor->ar_sim_state == Actor::SimState::NETWORKED_OK) continue; int stream_result = actor->ar_net_stream_results[sourceid]; - if (stream_result == -1 || stream_result == -2) - return 0; - if (stream_result == 1) - result = 1; + if (stream_result == -1 || stream_result == -2) return 0; + if (stream_result == 1) result = 1; } return result; } -Actor* ActorManager::GetActorByNetworkLinks(int source_id, int stream_id) +Actor *ActorManager::GetActorByNetworkLinks(int source_id, int stream_id) { for (auto actor : m_actors) { - if (actor->ar_net_source_id == source_id && actor->ar_net_stream_id == stream_id) - { - return actor; - } + if (actor->ar_net_source_id == source_id && actor->ar_net_stream_id == stream_id) { return actor; } } return nullptr; @@ -596,27 +545,22 @@ Actor* ActorManager::GetActorByNetworkLinks(int source_id, int stream_id) bool ActorManager::CheckActorCollAabbIntersect(int a, int b) { if (m_actors[a]->ar_collision_bounding_boxes.empty() && m_actors[b]->ar_collision_bounding_boxes.empty()) - { - return m_actors[a]->ar_bounding_box.intersects(m_actors[b]->ar_bounding_box); - } + { return m_actors[a]->ar_bounding_box.intersects(m_actors[b]->ar_bounding_box); } else if (m_actors[a]->ar_collision_bounding_boxes.empty()) { - for (const auto& bbox_b : m_actors[b]->ar_collision_bounding_boxes) - if (bbox_b.intersects(m_actors[a]->ar_bounding_box)) - return true; + for (const auto &bbox_b : m_actors[b]->ar_collision_bounding_boxes) + if (bbox_b.intersects(m_actors[a]->ar_bounding_box)) return true; } else if (m_actors[b]->ar_collision_bounding_boxes.empty()) { - for (const auto& bbox_a : m_actors[a]->ar_collision_bounding_boxes) - if (bbox_a.intersects(m_actors[b]->ar_bounding_box)) - return true; + for (const auto &bbox_a : m_actors[a]->ar_collision_bounding_boxes) + if (bbox_a.intersects(m_actors[b]->ar_bounding_box)) return true; } else { - for (const auto& bbox_a : m_actors[a]->ar_collision_bounding_boxes) - for (const auto& bbox_b : m_actors[b]->ar_collision_bounding_boxes) - if (bbox_a.intersects(bbox_b)) - return true; + for (const auto &bbox_a : m_actors[a]->ar_collision_bounding_boxes) + for (const auto &bbox_b : m_actors[b]->ar_collision_bounding_boxes) + if (bbox_a.intersects(bbox_b)) return true; } return false; @@ -625,43 +569,36 @@ bool ActorManager::CheckActorCollAabbIntersect(int a, int b) bool ActorManager::PredictActorCollAabbIntersect(int a, int b) { if (m_actors[a]->ar_predicted_coll_bounding_boxes.empty() && m_actors[b]->ar_predicted_coll_bounding_boxes.empty()) - { - return m_actors[a]->ar_predicted_bounding_box.intersects(m_actors[b]->ar_predicted_bounding_box); - } + { return m_actors[a]->ar_predicted_bounding_box.intersects(m_actors[b]->ar_predicted_bounding_box); } else if (m_actors[a]->ar_predicted_coll_bounding_boxes.empty()) { - for (const auto& bbox_b : m_actors[b]->ar_predicted_coll_bounding_boxes) - if (bbox_b.intersects(m_actors[a]->ar_predicted_bounding_box)) - return true; + for (const auto &bbox_b : m_actors[b]->ar_predicted_coll_bounding_boxes) + if (bbox_b.intersects(m_actors[a]->ar_predicted_bounding_box)) return true; } else if (m_actors[b]->ar_predicted_coll_bounding_boxes.empty()) { - for (const auto& bbox_a : m_actors[a]->ar_predicted_coll_bounding_boxes) - if (bbox_a.intersects(m_actors[b]->ar_predicted_bounding_box)) - return true; + for (const auto &bbox_a : m_actors[a]->ar_predicted_coll_bounding_boxes) + if (bbox_a.intersects(m_actors[b]->ar_predicted_bounding_box)) return true; } else { - for (const auto& bbox_a : m_actors[a]->ar_predicted_coll_bounding_boxes) - for (const auto& bbox_b : m_actors[b]->ar_predicted_coll_bounding_boxes) - if (bbox_a.intersects(bbox_b)) - return true; + for (const auto &bbox_a : m_actors[a]->ar_predicted_coll_bounding_boxes) + for (const auto &bbox_b : m_actors[b]->ar_predicted_coll_bounding_boxes) + if (bbox_a.intersects(bbox_b)) return true; } return false; } -void ActorManager::RecursiveActivation(int j, std::vector& visited) +void ActorManager::RecursiveActivation(int j, std::vector &visited) { - if (visited[j] || m_actors[j]->ar_sim_state != Actor::SimState::LOCAL_SIMULATED) - return; + if (visited[j] || m_actors[j]->ar_sim_state != Actor::SimState::LOCAL_SIMULATED) return; visited[j] = true; for (unsigned int t = 0; t < m_actors.size(); t++) { - if (t == j || visited[t]) - continue; + if (t == j || visited[t]) continue; if (m_actors[t]->ar_sim_state == Actor::SimState::LOCAL_SIMULATED && CheckActorCollAabbIntersect(t, j)) { m_actors[t]->ar_sleep_counter = 0.0f; @@ -670,13 +607,13 @@ void ActorManager::RecursiveActivation(int j, std::vector& visited) if (m_actors[t]->ar_sim_state == Actor::SimState::LOCAL_SLEEPING && PredictActorCollAabbIntersect(t, j)) { m_actors[t]->ar_sleep_counter = 0.0f; - m_actors[t]->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; + m_actors[t]->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; this->RecursiveActivation(t, visited); } } } -void ActorManager::ForwardCommands(Actor* source_actor) +void ActorManager::ForwardCommands(Actor *source_actor) { if (source_actor->ar_forward_commands) { @@ -685,67 +622,56 @@ void ActorManager::ForwardCommands(Actor* source_actor) for (auto actor : RoR::App::GetSimController()->GetActors()) { if (actor != source_actor && actor->ar_import_commands && - (actor->getPosition().distance(source_actor->getPosition()) < - actor->m_min_camera_radius + source_actor->m_min_camera_radius)) + (actor->getPosition().distance(source_actor->getPosition()) < + actor->m_min_camera_radius + source_actor->m_min_camera_radius)) { // activate the truck if (actor->ar_sim_state == Actor::SimState::LOCAL_SLEEPING) { actor->ar_sleep_counter = 0.0f; - actor->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; + actor->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; } if (App::sim_realistic_commands.GetActive()) { - if (std::find(linked_actors.begin(), linked_actors.end(), actor) == linked_actors.end()) - continue; + if (std::find(linked_actors.begin(), linked_actors.end(), actor) == linked_actors.end()) continue; } // forward commands for (int j = 1; j <= MAX_COMMANDS; j++) { - actor->ar_command_key[j].playerInputValue = std::max(source_actor->ar_command_key[j].playerInputValue, - source_actor->ar_command_key[j].commandValue); - } - if (source_actor->ar_toggle_ties) - { - actor->ToggleTies(); - } - if (source_actor->ar_toggle_ropes) - { - actor->ToggleRopes(-1); + actor->ar_command_key[j].playerInputValue = + std::max(source_actor->ar_command_key[j].playerInputValue, source_actor->ar_command_key[j].commandValue); } + if (source_actor->ar_toggle_ties) { actor->ToggleTies(); } + if (source_actor->ar_toggle_ropes) { actor->ToggleRopes(-1); } } } // just send brake and lights to the connected trucks, and no one else :) for (auto hook : source_actor->ar_hooks) { - if (!hook.hk_locked_actor || hook.hk_locked_actor == source_actor) - continue; + if (!hook.hk_locked_actor || hook.hk_locked_actor == source_actor) continue; // forward brakes hook.hk_locked_actor->ar_brake = source_actor->ar_brake; if (hook.hk_locked_actor->ar_parking_brake != source_actor->ar_trailer_parking_brake) - { - hook.hk_locked_actor->ToggleParkingBrake(); - } + { hook.hk_locked_actor->ToggleParkingBrake(); } // forward lights - hook.hk_locked_actor->ar_lights = source_actor->ar_lights; - hook.hk_locked_actor->m_blink_type = source_actor->m_blink_type; + hook.hk_locked_actor->ar_lights = source_actor->ar_lights; + hook.hk_locked_actor->m_blink_type = source_actor->m_blink_type; hook.hk_locked_actor->m_reverse_light_active = source_actor->getReverseLightVisible(); } } } -void ActorManager::UpdateSleepingState(Actor* player_actor, float dt) +void ActorManager::UpdateSleepingState(Actor *player_actor, float dt) { if (!m_forced_awake) { for (auto actor : m_actors) { - if (actor->ar_sim_state != Actor::SimState::LOCAL_SIMULATED) - continue; + if (actor->ar_sim_state != Actor::SimState::LOCAL_SIMULATED) continue; if (actor->getVelocity().squaredLength() > 0.01f) { actor->ar_sleep_counter = 0.0f; @@ -754,17 +680,12 @@ void ActorManager::UpdateSleepingState(Actor* player_actor, float dt) actor->ar_sleep_counter += dt; - if (actor->ar_sleep_counter >= 10.0f) - { - actor->ar_sim_state = Actor::SimState::LOCAL_SLEEPING; - } + if (actor->ar_sleep_counter >= 10.0f) { actor->ar_sim_state = Actor::SimState::LOCAL_SLEEPING; } } } if (player_actor && player_actor->ar_sim_state == Actor::SimState::LOCAL_SLEEPING) - { - player_actor->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; - } + { player_actor->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; } std::vector visited(m_actors.size()); // Recursivly activate all actors which can be reached from current actor @@ -787,7 +708,7 @@ void ActorManager::WakeUpAllActors() { if (actor->ar_sim_state == Actor::SimState::LOCAL_SLEEPING) { - actor->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; + actor->ar_sim_state = Actor::SimState::LOCAL_SIMULATED; actor->ar_sleep_counter = 0.0f; } } @@ -798,42 +719,39 @@ void ActorManager::SendAllActorsSleeping() m_forced_awake = false; for (auto actor : m_actors) { - if (actor->ar_sim_state == Actor::SimState::LOCAL_SIMULATED) - { - actor->ar_sim_state = Actor::SimState::LOCAL_SLEEPING; - } + if (actor->ar_sim_state == Actor::SimState::LOCAL_SIMULATED) { actor->ar_sim_state = Actor::SimState::LOCAL_SLEEPING; } } } -Actor* ActorManager::FindActorInsideBox(Collisions* collisions, const Ogre::String& inst, const Ogre::String& box) +Actor *ActorManager::FindActorInsideBox(Collisions *collisions, const Ogre::String &inst, const Ogre::String &box) { // try to find the desired actor (the one in the box) - Actor* ret = nullptr; + Actor *ret = nullptr; for (auto actor : m_actors) { if (collisions->isInside(actor->ar_nodes[0].AbsPosition, inst, box)) { if (ret == nullptr) - // first actor found + // first actor found ret = actor; else - // second actor found -> unclear which one was meant + // second actor found -> unclear which one was meant return nullptr; } } return ret; } -void ActorManager::RepairActor(Collisions* collisions, const Ogre::String& inst, const Ogre::String& box, bool keepPosition) +void ActorManager::RepairActor(Collisions *collisions, const Ogre::String &inst, const Ogre::String &box, bool keepPosition) { - Actor* actor = this->FindActorInsideBox(collisions, inst, box); + Actor *actor = this->FindActorInsideBox(collisions, inst, box); if (actor != nullptr) { SOUND_PLAY_ONCE(actor, SS_TRIG_REPAIR); ActorModifyRequest rq; rq.amr_actor = actor; - rq.amr_type = ActorModifyRequest::Type::RESET_ON_SPOT; + rq.amr_type = ActorModifyRequest::Type::RESET_ON_SPOT; App::GetSimController()->QueueActorModify(rq); } } @@ -854,17 +772,17 @@ void ActorManager::UnmuteAllActors() } } -std::pair ActorManager::GetNearestActor(Vector3 position) +std::pair ActorManager::GetNearestActor(Vector3 position) { - Actor* nearest_actor = nullptr; - float min_squared_distance = std::numeric_limits::max(); + Actor *nearest_actor = nullptr; + float min_squared_distance = std::numeric_limits::max(); for (auto actor : m_actors) { float squared_distance = position.squaredDistance(actor->ar_nodes[0].AbsPosition); if (squared_distance < min_squared_distance) { min_squared_distance = squared_distance; - nearest_actor = actor; + nearest_actor = actor; } } return std::make_pair(nearest_actor, std::sqrt(min_squared_distance)); @@ -879,10 +797,9 @@ void ActorManager::CleanUpAllActors() // Called after simulation finishes m_actors.clear(); } -void ActorManager::DeleteActorInternal(Actor* actor) +void ActorManager::DeleteActorInternal(Actor *actor) { - if (actor == 0) - return; + if (actor == 0) return; this->SyncWithSimThread(); @@ -890,11 +807,9 @@ void ActorManager::DeleteActorInternal(Actor* actor) if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - { - RoR::Networking::AddPacket(actor->ar_net_stream_id, RoRnet::MSG2_STREAM_UNREGISTER, 0, 0); - } - else if (std::count_if(m_actors.begin(), m_actors.end(), [actor](Actor* b) - { return b->ar_net_source_id == actor->ar_net_source_id; }) == 1) + { RoR::Networking::AddPacket(actor->ar_net_stream_id, RoRnet::MSG2_STREAM_UNREGISTER, 0, 0); } + else if (std::count_if(m_actors.begin(), m_actors.end(), + [actor](Actor *b) { return b->ar_net_source_id == actor->ar_net_source_id; }) == 1) { // We're deleting the last actor from this stream source, reset the stream time offset m_stream_time_offsets.erase(actor->ar_net_source_id); @@ -910,7 +825,7 @@ void ActorManager::DeleteActorInternal(Actor* actor) m_actors[i]->ar_vector_index = i; } -int FindPivotActorId(Actor* player, Actor* prev_player) +int FindPivotActorId(Actor *player, Actor *prev_player) { if (player != nullptr) return player->ar_vector_index; @@ -919,75 +834,62 @@ int FindPivotActorId(Actor* player, Actor* prev_player) return -1; } -Actor* ActorManager::FetchNextVehicleOnList(Actor* player, Actor* prev_player) +Actor *ActorManager::FetchNextVehicleOnList(Actor *player, Actor *prev_player) { int pivot_index = FindPivotActorId(player, prev_player); for (int i = pivot_index + 1; i < m_actors.size(); i++) { if (m_actors[i]->ar_sim_state != Actor::SimState::NETWORKED_OK && !m_actors[i]->isPreloadedWithTerrain()) - { - return m_actors[i]; - } + { return m_actors[i]; } } for (int i = 0; i < pivot_index; i++) { if (m_actors[i]->ar_sim_state != Actor::SimState::NETWORKED_OK && !m_actors[i]->isPreloadedWithTerrain()) - { - return m_actors[i]; - } + { return m_actors[i]; } } - if (pivot_index >= 0 && m_actors[pivot_index]->ar_sim_state != Actor::SimState::NETWORKED_OK && !m_actors[pivot_index]->isPreloadedWithTerrain()) - { - return m_actors[pivot_index]; - } + if (pivot_index >= 0 && m_actors[pivot_index]->ar_sim_state != Actor::SimState::NETWORKED_OK && + !m_actors[pivot_index]->isPreloadedWithTerrain()) + { return m_actors[pivot_index]; } return nullptr; } -Actor* ActorManager::FetchPreviousVehicleOnList(Actor* player, Actor* prev_player) +Actor *ActorManager::FetchPreviousVehicleOnList(Actor *player, Actor *prev_player) { int pivot_index = FindPivotActorId(player, prev_player); for (int i = pivot_index - 1; i >= 0; i--) { if (m_actors[i]->ar_sim_state != Actor::SimState::NETWORKED_OK && !m_actors[i]->isPreloadedWithTerrain()) - { - return m_actors[i]; - } + { return m_actors[i]; } } for (int i = static_cast(m_actors.size()) - 1; i > pivot_index; i--) { if (m_actors[i]->ar_sim_state != Actor::SimState::NETWORKED_OK && !m_actors[i]->isPreloadedWithTerrain()) - { - return m_actors[i]; - } + { return m_actors[i]; } } - if (pivot_index >= 0 && m_actors[pivot_index]->ar_sim_state != Actor::SimState::NETWORKED_OK && !m_actors[pivot_index]->isPreloadedWithTerrain()) - { - return m_actors[pivot_index]; - } + if (pivot_index >= 0 && m_actors[pivot_index]->ar_sim_state != Actor::SimState::NETWORKED_OK && + !m_actors[pivot_index]->isPreloadedWithTerrain()) + { return m_actors[pivot_index]; } return nullptr; } -Actor* ActorManager::FetchRescueVehicle() +Actor *ActorManager::FetchRescueVehicle() { for (auto actor : m_actors) { - if (actor->ar_rescuer_flag) - { - return actor; - } + if (actor->ar_rescuer_flag) { return actor; } } return nullptr; } -void ActorManager::UpdateActors(Actor* player_actor, float dt) +void ActorManager::UpdateActors(Actor *player_actor, float dt) { // do not allow dt > 1/20 dt = std::min(dt, 1.0f / 20.0f); @@ -996,13 +898,10 @@ void ActorManager::UpdateActors(Actor* player_actor, float dt) dt += m_dt_remainder; m_physics_steps = dt / PHYSICS_DT; - if (m_physics_steps == 0) - { - return; - } + if (m_physics_steps == 0) { return; } m_dt_remainder = dt - (m_physics_steps * PHYSICS_DT); - dt = PHYSICS_DT * m_physics_steps; + dt = PHYSICS_DT * m_physics_steps; gEnv->mrTime += dt; @@ -1016,20 +915,13 @@ void ActorManager::UpdateActors(Actor* player_actor, float dt) actor->HandleAngelScriptEvents(dt); #ifdef USE_ANGELSCRIPT - if (actor->ar_vehicle_ai && actor->ar_vehicle_ai->IsActive()) - actor->ar_vehicle_ai->update(dt, 0); + if (actor->ar_vehicle_ai && actor->ar_vehicle_ai->IsActive()) actor->ar_vehicle_ai->update(dt, 0); #endif // USE_ANGELSCRIPT if (actor->ar_engine) { - if (actor->ar_driveable == TRUCK) - { - LandVehicleSimulation::UpdateVehicle(actor, dt); - } - if (actor->ar_sim_state == Actor::SimState::LOCAL_SLEEPING) - { - actor->ar_engine->UpdateEngineSim(dt, 1); - } + if (actor->ar_driveable == TRUCK) { LandVehicleSimulation::UpdateVehicle(actor, dt); } + if (actor->ar_sim_state == Actor::SimState::LOCAL_SLEEPING) { actor->ar_engine->UpdateEngineSim(dt, 1); } actor->ar_engine->UpdateEngineAudio(); } @@ -1037,10 +929,7 @@ void ActorManager::UpdateActors(Actor* player_actor, float dt) { actor->updateVisual(dt); actor->UpdateFlareStates(dt); // Only state, visuals done by GfxActor - if (actor->ar_update_physics && App::gfx_skidmarks_mode.GetActive() > 0) - { - actor->updateSkidmarks(); - } + if (actor->ar_update_physics && App::gfx_skidmarks_mode.GetActive() > 0) { actor->updateSkidmarks(); } } if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { @@ -1066,18 +955,13 @@ void ActorManager::UpdateActors(Actor* player_actor, float dt) } player_actor->updateDashBoards(dt); player_actor->ForceFeedbackStep(m_physics_steps); - if (player_actor->ReplayStep()) - return; // Skip UpdatePhysicsSimulation() + if (player_actor->ReplayStep()) return; // Skip UpdatePhysicsSimulation() } - auto func = std::function([this]() - { - this->UpdatePhysicsSimulation(); - }); + auto func = std::function([this]() { this->UpdatePhysicsSimulation(); }); m_sim_task = m_sim_thread_pool->RunTask(func); - if (!RoR::App::app_async_physics.GetActive()) - m_sim_task->join(); + if (!RoR::App::app_async_physics.GetActive()) m_sim_task->join(); } void ActorManager::NotifyActorsWindowResized() @@ -1088,14 +972,11 @@ void ActorManager::NotifyActorsWindowResized() } } -Actor* ActorManager::GetActorByIdInternal(int actor_id) +Actor *ActorManager::GetActorByIdInternal(int actor_id) { for (auto actor : m_actors) { - if (actor->ar_instance_id == actor_id) - { - return actor; - } + if (actor->ar_instance_id == actor_id) { return actor; } } return 0; } @@ -1114,45 +995,35 @@ void ActorManager::UpdatePhysicsSimulation() { if (actor->ar_update_physics = actor->CalcForcesEulerPrepare(i == 0)) { - auto func = std::function([this, i, actor]() - { - actor->CalcForcesEulerCompute(i == 0, m_physics_steps); - }); + auto func = + std::function([this, i, actor]() { actor->CalcForcesEulerCompute(i == 0, m_physics_steps); }); tasks.push_back(func); } } gEnv->threadPool->Parallelize(tasks); for (auto actor : m_actors) { - if (actor->ar_update_physics) - { - actor->CalcBeamsInterActor(); - } + if (actor->ar_update_physics) { actor->CalcBeamsInterActor(); } } } { std::vector> tasks; for (auto actor : m_actors) { - if (actor->m_inter_point_col_detector != nullptr && (actor->ar_update_physics || - (App::mp_pseudo_collisions.GetActive() && actor->ar_sim_state == Actor::SimState::NETWORKED_OK))) + if (actor->m_inter_point_col_detector != nullptr && + (actor->ar_update_physics || + (App::mp_pseudo_collisions.GetActive() && actor->ar_sim_state == Actor::SimState::NETWORKED_OK))) { - auto func = std::function([this, actor]() + auto func = std::function([this, actor]() { + actor->m_inter_point_col_detector->UpdateInterPoint(); + if (actor->ar_collision_relevant) { - actor->m_inter_point_col_detector->UpdateInterPoint(); - if (actor->ar_collision_relevant) - { - ResolveInterActorCollisions(PHYSICS_DT, - *actor->m_inter_point_col_detector, - actor->ar_num_collcabs, - actor->ar_collcabs, - actor->ar_cabs, - actor->ar_inter_collcabrate, - actor->ar_nodes, - actor->ar_collision_range, - *actor->ar_submesh_ground_model); - } - }); + ResolveInterActorCollisions(PHYSICS_DT, *actor->m_inter_point_col_detector, actor->ar_num_collcabs, + actor->ar_collcabs, actor->ar_cabs, actor->ar_inter_collcabrate, + actor->ar_nodes, actor->ar_collision_range, + *actor->ar_submesh_ground_model); + } + }); tasks.push_back(func); } } @@ -1164,23 +1035,22 @@ void ActorManager::UpdatePhysicsSimulation() actor->m_ongoing_reset = false; if (actor->ar_update_physics && m_physics_steps > 0) { - Vector3 camera_gforces = actor->m_camera_gforces_accu / m_physics_steps; + Vector3 camera_gforces = actor->m_camera_gforces_accu / m_physics_steps; actor->m_camera_gforces_accu = Vector3::ZERO; - actor->m_camera_gforces = actor->m_camera_gforces * 0.5f + camera_gforces * 0.5f; + actor->m_camera_gforces = actor->m_camera_gforces * 0.5f + camera_gforces * 0.5f; actor->calculateLocalGForces(); actor->calculateAveragePosition(); - actor->m_avg_node_velocity = actor->m_avg_node_position - actor->m_avg_node_position_prev; + actor->m_avg_node_velocity = actor->m_avg_node_position - actor->m_avg_node_position_prev; actor->m_avg_node_velocity /= (m_physics_steps * PHYSICS_DT); actor->m_avg_node_position_prev = actor->m_avg_node_position; - actor->ar_top_speed = std::max(actor->ar_top_speed, actor->ar_nodes[0].Velocity.length()); + actor->ar_top_speed = std::max(actor->ar_top_speed, actor->ar_nodes[0].Velocity.length()); } } } void ActorManager::SyncWithSimThread() { - if (m_sim_task) - m_sim_task->join(); + if (m_sim_task) m_sim_task->join(); } void HandleErrorLoadingFile(std::string type, std::string filename, std::string exception_msg) @@ -1192,8 +1062,8 @@ void HandleErrorLoadingFile(std::string type, std::string filename, std::string if (RoR::App::GetConsole()) { - RoR::App::GetConsole()->putMessage( - Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR, msg.ToCStr(), "error.png", 30000, true); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR, msg.ToCStr(), + "error.png", 30000, true); } } @@ -1205,7 +1075,7 @@ void HandleErrorLoadingTruckfile(std::string filename, std::string exception_msg std::shared_ptr ActorManager::FetchActorDef(std::string filename, bool predefined_on_terrain) { // Find the user content - CacheEntry* cache_entry = App::GetCacheSystem()->FindEntryByFilename(filename); + CacheEntry *cache_entry = App::GetCacheSystem()->FindEntryByFilename(filename); if (cache_entry == nullptr) { HandleErrorLoadingTruckfile(filename, "Truckfile not found in ModCache (probably not installed)"); @@ -1213,22 +1083,21 @@ std::shared_ptr ActorManager::FetchActorDef(std::string filename, } // If already parsed, re-use - if (cache_entry->actor_def != nullptr) - { - return cache_entry->actor_def; - } + if (cache_entry->actor_def != nullptr) { return cache_entry->actor_def; } // Load the 'truckfile' try { Ogre::String resource_filename = filename; Ogre::String resource_groupname; - if (!RoR::App::GetCacheSystem()->CheckResourceLoaded(resource_filename, resource_groupname)) // Validates the filename and finds resource group + if (!RoR::App::GetCacheSystem()->CheckResourceLoaded( + resource_filename, resource_groupname)) // Validates the filename and finds resource group { HandleErrorLoadingTruckfile(filename, "Truckfile not found"); return nullptr; } - Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(resource_filename, resource_groupname); + Ogre::DataStreamPtr stream = + Ogre::ResourceGroupManager::getSingleton().openResource(resource_filename, resource_groupname); if (stream.isNull() || !stream->isReadable()) { @@ -1244,14 +1113,14 @@ std::shared_ptr ActorManager::FetchActorDef(std::string filename, auto def = parser.GetFile(); - def->report_num_errors = parser.GetMessagesNumErrors(); + def->report_num_errors = parser.GetMessagesNumErrors(); def->report_num_warnings = parser.GetMessagesNumWarnings(); - def->report_num_other = parser.GetMessagesNumOther(); - def->loading_report = parser.ProcessMessagesToString(); + def->report_num_other = parser.GetMessagesNumOther(); + def->loading_report = parser.ProcessMessagesToString(); def->loading_report += "\n\n"; LOG(def->loading_report); - auto* importer = parser.GetSequentialImporter(); + auto *importer = parser.GetSequentialImporter(); if (importer->IsEnabled() && App::diag_rig_log_messages.GetActive()) { def->report_num_errors += importer->GetMessagesNumErrors(); @@ -1278,10 +1147,7 @@ std::shared_ptr ActorManager::FetchActorDef(std::string filename, // These files can have no beams. Possible extensions: .load or .fixed std::string file_extension = filename.substr(filename.find_last_of('.')); Ogre::StringUtil::toLowerCase(file_extension); - if ((file_extension == ".load") | (file_extension == ".fixed")) - { - validator.SetCheckBeams(false); - } + if ((file_extension == ".load") | (file_extension == ".fixed")) { validator.SetCheckBeams(false); } } bool valid = validator.Validate(); @@ -1297,14 +1163,8 @@ std::shared_ptr ActorManager::FetchActorDef(std::string filename, // Extra information to RoR.log if (importer->IsEnabled()) { - if (App::diag_rig_log_node_stats.GetActive()) - { - LOG(importer->GetNodeStatistics()); - } - if (App::diag_rig_log_node_import.GetActive()) - { - LOG(importer->IterateAndPrintAllNodes()); - } + if (App::diag_rig_log_node_stats.GetActive()) { LOG(importer->GetNodeStatistics()); } + if (App::diag_rig_log_node_import.GetActive()) { LOG(importer->IterateAndPrintAllNodes()); } } def->hash = Utils::Sha1Hash(stream->getAsString()); @@ -1312,12 +1172,12 @@ std::shared_ptr ActorManager::FetchActorDef(std::string filename, cache_entry->actor_def = def; return def; } - catch (Ogre::Exception& oex) + catch (Ogre::Exception &oex) { HandleErrorLoadingTruckfile(filename, oex.getFullDescription().c_str()); return nullptr; } - catch (std::exception& stex) + catch (std::exception &stex) { HandleErrorLoadingTruckfile(filename, stex.what()); return nullptr; @@ -1329,26 +1189,19 @@ std::shared_ptr ActorManager::FetchActorDef(std::string filename, } } -std::vector ActorManager::GetLocalActors() +std::vector ActorManager::GetLocalActors() { - std::vector actors; + std::vector actors; for (auto actor : m_actors) { - if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - actors.push_back(actor); + if (actor->ar_sim_state != Actor::SimState::NETWORKED_OK) actors.push_back(actor); } return actors; } ActorSpawnRequest::ActorSpawnRequest() - : asr_position(Ogre::Vector3::ZERO) - , asr_rotation(Ogre::Quaternion::ZERO) - , asr_spawnbox(nullptr) - , asr_skin_entry(nullptr) - , asr_origin(Origin::UNKNOWN) - , asr_cache_entry(nullptr) - , asr_free_position(false) - , asr_terrn_machine(false) - , asr_net_username("") - , asr_net_color(0) -{} + : asr_position(Ogre::Vector3::ZERO), asr_rotation(Ogre::Quaternion::ZERO), asr_spawnbox(nullptr), asr_skin_entry(nullptr), + asr_origin(Origin::UNKNOWN), asr_cache_entry(nullptr), asr_free_position(false), asr_terrn_machine(false), + asr_net_username(""), asr_net_color(0) +{ +} diff --git a/source/main/physics/BeamFactory.h b/source/main/physics/BeamFactory.h index 0839e9d10d..d693f90675 100644 --- a/source/main/physics/BeamFactory.h +++ b/source/main/physics/BeamFactory.h @@ -24,12 +24,11 @@ #pragma once -#include "RoRPrerequisites.h" - #include "BeamData.h" #include "CmdKeyInertia.h" #include "Network.h" #include "RigDef_Prerequisites.h" +#include "RoRPrerequisites.h" #include #include @@ -38,94 +37,121 @@ class ThreadPool; -namespace RoR { - -/// Builds and manages softbody actors. Manage physics and threading. -/// TODO: Currently also manages gfx, which should be done by GfxActor -/// HISTORICAL NOTE: Until 01/2018, this class was named `BeamFactory` (because `Actor` was `Beam`) -class ActorManager +namespace RoR { - friend class GameScript; // needs to call RemoveActorByCollisionBox() -public: - - ActorManager(); - ~ActorManager(); - - Actor* CreateActorInstance(ActorSpawnRequest rq, std::shared_ptr def); - void UpdateActors(Actor* player_actor, float dt); - void SyncWithSimThread(); - void UpdatePhysicsSimulation(); - void WakeUpAllActors(); - void SendAllActorsSleeping(); - unsigned long GetNetTime() { return m_net_timer.getMilliseconds(); }; - int GetNetTimeOffset(int sourceid); - void UpdateNetTimeOffset(int sourceid, int offset); - void AddStreamMismatch(int sourceid, int streamid) { m_stream_mismatches[sourceid].insert(streamid); }; - int CheckNetworkStreamsOk(int sourceid); - int CheckNetRemoteStreamsOk(int sourceid); - void NotifyActorsWindowResized(); - void MuteAllActors(); - void UnmuteAllActors(); - void SetTrucksForcedAwake(bool forced) { m_forced_awake = forced; }; - bool AreTrucksForcedAwake() const { return m_forced_awake; } - void SetSimulationSpeed(float speed) { m_simulation_speed = std::max(0.0f, speed); }; - float GetSimulationSpeed() const { return m_simulation_speed; }; - RoR::CmdKeyInertiaConfig& GetInertiaConfig() { return m_inertia_config; } - Actor* FetchNextVehicleOnList(Actor* player, Actor* prev_player); - Actor* FetchPreviousVehicleOnList(Actor* player, Actor* prev_player); - Actor* FetchRescueVehicle(); - void CleanUpAllActors(); //!< Call this after simulation loop finishes. - Actor* GetActorByNetworkLinks(int source_id, int stream_id); // used by character - void RepairActor(Collisions* collisions, const Ogre::String& inst, const Ogre::String& box, bool keepPosition = false); - void UpdateSleepingState(Actor* player_actor, float dt); - void DeleteActorInternal(Actor* b); //!< DO NOT CALL DIRECTLY! Use `SimController` for public interface - Actor* GetActorByIdInternal(int actor_id); //!< DO NOT CALL DIRECTLY! Use `SimController` for public interface - Actor* FindActorInsideBox(Collisions* collisions, const Ogre::String& inst, const Ogre::String& box); - std::shared_ptr FetchActorDef(std::string filename, bool predefined_on_terrain = false); + + /// Builds and manages softbody actors. Manage physics and threading. + /// TODO: Currently also manages gfx, which should be done by GfxActor + /// HISTORICAL NOTE: Until 01/2018, this class was named `BeamFactory` (because `Actor` was `Beam`) + class ActorManager + { + friend class GameScript; // needs to call RemoveActorByCollisionBox() + public: + ActorManager(); + ~ActorManager(); + + Actor * CreateActorInstance(ActorSpawnRequest rq, std::shared_ptr def); + void UpdateActors(Actor *player_actor, float dt); + void SyncWithSimThread(); + void UpdatePhysicsSimulation(); + void WakeUpAllActors(); + void SendAllActorsSleeping(); + unsigned long GetNetTime() + { + return m_net_timer.getMilliseconds(); + }; + int GetNetTimeOffset(int sourceid); + void UpdateNetTimeOffset(int sourceid, int offset); + void AddStreamMismatch(int sourceid, int streamid) + { + m_stream_mismatches[sourceid].insert(streamid); + }; + int CheckNetworkStreamsOk(int sourceid); + int CheckNetRemoteStreamsOk(int sourceid); + void NotifyActorsWindowResized(); + void MuteAllActors(); + void UnmuteAllActors(); + void SetTrucksForcedAwake(bool forced) + { + m_forced_awake = forced; + }; + bool AreTrucksForcedAwake() const + { + return m_forced_awake; + } + void SetSimulationSpeed(float speed) + { + m_simulation_speed = std::max(0.0f, speed); + }; + float GetSimulationSpeed() const + { + return m_simulation_speed; + }; + RoR::CmdKeyInertiaConfig &GetInertiaConfig() + { + return m_inertia_config; + } + Actor *FetchNextVehicleOnList(Actor *player, Actor *prev_player); + Actor *FetchPreviousVehicleOnList(Actor *player, Actor *prev_player); + Actor *FetchRescueVehicle(); + void CleanUpAllActors(); //!< Call this after simulation loop finishes. + Actor *GetActorByNetworkLinks(int source_id, int stream_id); // used by character + void RepairActor(Collisions *collisions, const Ogre::String &inst, const Ogre::String &box, bool keepPosition = false); + void UpdateSleepingState(Actor *player_actor, float dt); + void DeleteActorInternal(Actor *b); //!< DO NOT CALL DIRECTLY! Use `SimController` for public interface + Actor *GetActorByIdInternal(int actor_id); //!< DO NOT CALL DIRECTLY! Use `SimController` for public interface + Actor *FindActorInsideBox(Collisions *collisions, const Ogre::String &inst, const Ogre::String &box); + std::shared_ptr FetchActorDef(std::string filename, bool predefined_on_terrain = false); #ifdef USE_SOCKETW - void HandleActorStreamData(std::vector packet); + void HandleActorStreamData(std::vector packet); #endif #ifdef USE_ANGELSCRIPT - void AddRef() {}; // we have to add this to be able to use the class as reference inside scripts - void Release() {}; + void AddRef(){}; // we have to add this to be able to use the class as reference inside scripts + void Release(){}; #endif - Ogre::String GetQuicksaveFilename(Ogre::String filename = ""); - Ogre::String ExtractSceneName(Ogre::String filename); - bool LoadScene(Ogre::String filename); - bool SaveScene(Ogre::String filename); - - std::vector GetActors() const { return m_actors; }; - std::vector GetLocalActors(); - - std::pair GetNearestActor(Ogre::Vector3 position); - - // A list of all beams interconnecting two actors - std::map> inter_actor_links; - -private: - - void SetupActor(Actor* actor, ActorSpawnRequest rq, std::shared_ptr def); - bool CheckActorCollAabbIntersect(int a, int b); //!< Returns whether or not the bounding boxes of truck a and truck b intersect. Based on the truck collision bounding boxes. - bool PredictActorCollAabbIntersect(int a, int b); //!< Returns whether or not the bounding boxes of truck a and truck b might intersect during the next framestep. Based on the truck collision bounding boxes. - void RemoveStreamSource(int sourceid); - void RecursiveActivation(int j, std::vector& visited); - void ForwardCommands(Actor* source_actor); //< Fowards things to trailers - - std::map> m_stream_mismatches; //!< Networking: A set of streams without a corresponding actor in the actor-array for each stream source - std::map m_stream_time_offsets; //!< Networking: A network time offset for each stream source - std::unique_ptr m_sim_thread_pool; - std::shared_ptr m_sim_task; - std::vector m_actors; - Ogre::Timer m_net_timer; - RoR::CmdKeyInertiaConfig m_inertia_config; - bool m_forced_awake; //!< disables sleep counters - int m_physics_steps; - float m_dt_remainder; ///< Keeps track of the rounding error in the time step calculation - float m_simulation_speed; ///< slow motion < 1.0 < fast motion - bool m_savegame_terrain_has_changed; -}; + Ogre::String GetQuicksaveFilename(Ogre::String filename = ""); + Ogre::String ExtractSceneName(Ogre::String filename); + bool LoadScene(Ogre::String filename); + bool SaveScene(Ogre::String filename); + + std::vector GetActors() const + { + return m_actors; + }; + std::vector GetLocalActors(); + + std::pair GetNearestActor(Ogre::Vector3 position); + + // A list of all beams interconnecting two actors + std::map> inter_actor_links; + + private: + void SetupActor(Actor *actor, ActorSpawnRequest rq, std::shared_ptr def); + bool CheckActorCollAabbIntersect(int a, int b); //!< Returns whether or not the bounding boxes of truck a and truck b + //!< intersect. Based on the truck collision bounding boxes. + bool PredictActorCollAabbIntersect( + int a, int b); //!< Returns whether or not the bounding boxes of truck a and truck b might intersect during the next + //!< framestep. Based on the truck collision bounding boxes. + void RemoveStreamSource(int sourceid); + void RecursiveActivation(int j, std::vector &visited); + void ForwardCommands(Actor *source_actor); //< Fowards things to trailers + + std::map> m_stream_mismatches; //!< Networking: A set of streams without a corresponding actor in the + //!< actor-array for each stream source + std::map m_stream_time_offsets; //!< Networking: A network time offset for each stream source + std::unique_ptr m_sim_thread_pool; + std::shared_ptr m_sim_task; + std::vector m_actors; + Ogre::Timer m_net_timer; + RoR::CmdKeyInertiaConfig m_inertia_config; + bool m_forced_awake; //!< disables sleep counters + int m_physics_steps; + float m_dt_remainder; ///< Keeps track of the rounding error in the time step calculation + float m_simulation_speed; ///< slow motion < 1.0 < fast motion + bool m_savegame_terrain_has_changed; + }; } // namespace RoR diff --git a/source/main/physics/BeamForcesEuler.cpp b/source/main/physics/BeamForcesEuler.cpp index 199a37268d..748af0d9e4 100644 --- a/source/main/physics/BeamForcesEuler.cpp +++ b/source/main/physics/BeamForcesEuler.cpp @@ -18,8 +18,6 @@ along with Rigs of Rods. If not, see . */ -#include "RoRPrerequisites.h" - #include "AeroEngine.h" #include "AirBrake.h" #include "Airfoil.h" @@ -35,6 +33,7 @@ #include "FlexAirfoil.h" #include "Replay.h" #include "RoRFrameListener.h" +#include "RoRPrerequisites.h" #include "ScrewProp.h" #include "SoundScriptManager.h" #include "TerrainManager.h" @@ -68,23 +67,16 @@ void Actor::CalcForceFeedback(bool doUpdate) { if (this == RoR::App::GetSimController()->GetPlayerActor()) { - if (doUpdate) - { - m_force_sensors.Reset(); - } + if (doUpdate) { m_force_sensors.Reset(); } if (ar_current_cinecam != -1) - { - m_force_sensors.accu_body_forces += ar_nodes[ar_camera_node_pos[ar_current_cinecam]].Forces; - } + { m_force_sensors.accu_body_forces += ar_nodes[ar_camera_node_pos[ar_current_cinecam]].Forces; } - for (hydrobeam_t& hydrobeam: ar_hydros) + for (hydrobeam_t &hydrobeam : ar_hydros) { - beam_t* beam = &ar_beams[hydrobeam.hb_beam_index]; + beam_t *beam = &ar_beams[hydrobeam.hb_beam_index]; if ((hydrobeam.hb_flags & (HYDRO_FLAG_DIR | HYDRO_FLAG_SPEED)) && !beam->bm_broken) - { - m_force_sensors.accu_hydros_forces += hydrobeam.hb_speed * beam->refL * beam->stress; - } + { m_force_sensors.accu_hydros_forces += hydrobeam.hb_speed * beam->refL * beam->stress; } } } } @@ -100,49 +92,45 @@ void Actor::CalcMouse() void Actor::CalcAircraftForces(bool doUpdate) { - //airbrake forces - for (Airbrake* ab: ar_airbrakes) + // airbrake forces + for (Airbrake *ab : ar_airbrakes) ab->applyForce(); - //turboprop forces + // turboprop forces for (int i = 0; i < ar_num_aeroengines; i++) - if (ar_aeroengines[i]) - ar_aeroengines[i]->updateForces(PHYSICS_DT, doUpdate); + if (ar_aeroengines[i]) ar_aeroengines[i]->updateForces(PHYSICS_DT, doUpdate); - //screwprop forces + // screwprop forces for (int i = 0; i < ar_num_screwprops; i++) - if (ar_screwprops[i]) - ar_screwprops[i]->updateForces(doUpdate); + if (ar_screwprops[i]) ar_screwprops[i]->updateForces(doUpdate); - //wing forces + // wing forces for (int i = 0; i < ar_num_wings; i++) - if (ar_wings[i].fa) - ar_wings[i].fa->updateForces(); + if (ar_wings[i].fa) ar_wings[i].fa->updateForces(); } void Actor::CalcFuseDrag() { if (m_fusealge_airfoil && m_fusealge_width > 0.0f) { - Vector3 wind = -m_fusealge_front->Velocity; - float wspeed = wind.length(); - Vector3 axis = m_fusealge_front->RelPosition - m_fusealge_back->RelPosition; - float s = axis.length() * m_fusealge_width; - float cz, cx, cm; - float v = axis.getRotationTo(wind).w; - float aoa = 0; - if (v < 1.0 && v > -1.0) - aoa = 2.0 * acos(v); //quaternion fun + Vector3 wind = -m_fusealge_front->Velocity; + float wspeed = wind.length(); + Vector3 axis = m_fusealge_front->RelPosition - m_fusealge_back->RelPosition; + float s = axis.length() * m_fusealge_width; + float cz, cx, cm; + float v = axis.getRotationTo(wind).w; + float aoa = 0; + if (v < 1.0 && v > -1.0) aoa = 2.0 * acos(v); // quaternion fun m_fusealge_airfoil->getparams(aoa, 1.0, 0.0, &cz, &cx, &cm); - //tropospheric model valid up to 11.000m (33.000ft) - float altitude = m_fusealge_front->AbsPosition.y; - float sea_level_pressure = 101325; //in Pa - float airpressure = sea_level_pressure * approx_pow(1.0 - 0.0065 * altitude / 288.1, 5.24947); //in Pa - float airdensity = airpressure * 0.0000120896f;//1.225 at sea level + // tropospheric model valid up to 11.000m (33.000ft) + float altitude = m_fusealge_front->AbsPosition.y; + float sea_level_pressure = 101325; // in Pa + float airpressure = sea_level_pressure * approx_pow(1.0 - 0.0065 * altitude / 288.1, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896f; // 1.225 at sea level - //fuselage as an airfoil + parasitic drag (half fuselage front surface almost as a flat plane!) - ar_fusedrag = ((cx * s + m_fusealge_width * m_fusealge_width * 0.5) * 0.5 * airdensity * wspeed / ar_num_nodes) * wind; + // fuselage as an airfoil + parasitic drag (half fuselage front surface almost as a flat plane!) + ar_fusedrag = ((cx * s + m_fusealge_width * m_fusealge_width * 0.5) * 0.5 * airdensity * wspeed / ar_num_nodes) * wind; } } @@ -153,7 +141,8 @@ void Actor::CalcBuoyance(bool doUpdate) for (int i = 0; i < ar_num_buoycabs; i++) { int tmpv = ar_buoycabs[i] * 3; - m_buoyance->computeNodeForce(&ar_nodes[ar_cabs[tmpv]], &ar_nodes[ar_cabs[tmpv + 1]], &ar_nodes[ar_cabs[tmpv + 2]], doUpdate == 1, ar_buoycab_types[i]); + m_buoyance->computeNodeForce(&ar_nodes[ar_cabs[tmpv]], &ar_nodes[ar_cabs[tmpv + 1]], &ar_nodes[ar_cabs[tmpv + 2]], + doUpdate == 1, ar_buoycab_types[i]); } } } @@ -169,8 +158,7 @@ void Actor::CalcDifferentials() } for (int i = 0; i < ar_num_wheels; i++) { - if (ar_wheels[i].wh_propulsed && !ar_wheels[i].wh_is_detached) - ar_wheels[i].wh_torque += torque; + if (ar_wheels[i].wh_propulsed && !ar_wheels[i].wh_is_detached) ar_wheels[i].wh_torque += torque; } } @@ -179,10 +167,10 @@ void Actor::CalcDifferentials() // Handle detached wheels for (int i = 0; i < num_axle_diffs; i++) { - int a_1 = m_axle_diffs[i]->di_idx_1; - int a_2 = m_axle_diffs[i]->di_idx_2; - wheel_t* axle_1_wheels[2] = {&ar_wheels[m_wheel_diffs[a_1]->di_idx_1], &ar_wheels[m_wheel_diffs[a_1]->di_idx_2]}; - wheel_t* axle_2_wheels[2] = {&ar_wheels[m_wheel_diffs[a_2]->di_idx_1], &ar_wheels[m_wheel_diffs[a_2]->di_idx_2]}; + int a_1 = m_axle_diffs[i]->di_idx_1; + int a_2 = m_axle_diffs[i]->di_idx_2; + wheel_t *axle_1_wheels[2] = {&ar_wheels[m_wheel_diffs[a_1]->di_idx_1], &ar_wheels[m_wheel_diffs[a_1]->di_idx_2]}; + wheel_t *axle_2_wheels[2] = {&ar_wheels[m_wheel_diffs[a_2]->di_idx_1], &ar_wheels[m_wheel_diffs[a_2]->di_idx_2]}; if (axle_1_wheels[0]->wh_is_detached && axle_1_wheels[1]->wh_is_detached) { axle_1_wheels[0]->wh_speed = axle_2_wheels[0]->wh_speed; @@ -196,7 +184,7 @@ void Actor::CalcDifferentials() } for (int i = 0; i < m_num_wheel_diffs; i++) { - wheel_t* axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]}; + wheel_t *axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]}; if (axle_wheels[0]->wh_is_detached) axle_wheels[0]->wh_speed = axle_wheels[1]->wh_speed; if (axle_wheels[1]->wh_is_detached) axle_wheels[1]->wh_speed = axle_wheels[0]->wh_speed; } @@ -208,19 +196,15 @@ void Actor::CalcDifferentials() int a_1 = m_axle_diffs[i]->di_idx_1; int a_2 = m_axle_diffs[i]->di_idx_2; - Ogre::Real axle_torques[2] = {0.0f, 0.0f}; - DifferentialData diff_data = - { - { - (ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_speed + ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_speed) * 0.5f, - (ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_speed + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_speed) * 0.5f - }, + Ogre::Real axle_torques[2] = {0.0f, 0.0f}; + DifferentialData diff_data = { + {(ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_speed + ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_speed) * 0.5f, + (ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_speed + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_speed) * 0.5f}, m_axle_diffs[i]->di_delta_rotation, {axle_torques[0], axle_torques[1]}, ar_wheels[m_wheel_diffs[a_1]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_1]->di_idx_2].wh_torque + - ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_torque, - PHYSICS_DT - }; + ar_wheels[m_wheel_diffs[a_2]->di_idx_1].wh_torque + ar_wheels[m_wheel_diffs[a_2]->di_idx_2].wh_torque, + PHYSICS_DT}; m_axle_diffs[i]->CalcAxleTorque(diff_data); @@ -237,16 +221,13 @@ void Actor::CalcDifferentials() for (int i = 0; i < m_num_wheel_diffs; i++) { Ogre::Real axle_torques[2] = {0.0f, 0.0f}; - wheel_t* axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]}; + wheel_t * axle_wheels[2] = {&ar_wheels[m_wheel_diffs[i]->di_idx_1], &ar_wheels[m_wheel_diffs[i]->di_idx_2]}; - DifferentialData diff_data = - { - {axle_wheels[0]->wh_speed, axle_wheels[1]->wh_speed}, - m_wheel_diffs[i]->di_delta_rotation, - {axle_torques[0], axle_torques[1]}, - axle_wheels[0]->wh_torque + axle_wheels[1]->wh_torque, - PHYSICS_DT - }; + DifferentialData diff_data = {{axle_wheels[0]->wh_speed, axle_wheels[1]->wh_speed}, + m_wheel_diffs[i]->di_delta_rotation, + {axle_torques[0], axle_torques[1]}, + axle_wheels[0]->wh_torque + axle_wheels[1]->wh_torque, + PHYSICS_DT}; m_wheel_diffs[i]->CalcAxleTorque(diff_data); @@ -265,38 +246,37 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) if (alb_timer >= alb_pulse_time) { - alb_timer = 0.0f; + alb_timer = 0.0f; alb_pulse_state = !alb_pulse_state; } if (tc_timer >= tc_pulse_time) { - tc_timer = 0.0f; + tc_timer = 0.0f; tc_pulse_state = !tc_pulse_state; } - m_antilockbrake = false; + m_antilockbrake = false; m_tractioncontrol = false; - ar_wheel_spin = 0.0f; + ar_wheel_spin = 0.0f; ar_wheel_speed = 0.0f; for (int i = 0; i < ar_num_wheels; i++) { if (doUpdate) { - ar_wheels[i].debug_rpm = 0.0f; - ar_wheels[i].debug_torque = 0.0f; - ar_wheels[i].debug_vel = Vector3::ZERO; - ar_wheels[i].debug_slip = Vector3::ZERO; - ar_wheels[i].debug_force = Vector3::ZERO; + ar_wheels[i].debug_rpm = 0.0f; + ar_wheels[i].debug_torque = 0.0f; + ar_wheels[i].debug_vel = Vector3::ZERO; + ar_wheels[i].debug_slip = Vector3::ZERO; + ar_wheels[i].debug_force = Vector3::ZERO; ar_wheels[i].debug_scaled_cforce = Vector3::ZERO; } - if (ar_wheels[i].wh_is_detached) - continue; + if (ar_wheels[i].wh_is_detached) continue; - float relspeed = ar_nodes[0].Velocity.dotProduct(getDirection()); - float curspeed = fabs(relspeed); + float relspeed = ar_nodes[0].Velocity.dotProduct(getDirection()); + float curspeed = fabs(relspeed); float wheel_slip = fabs(ar_wheels[i].wh_speed - relspeed) / std::max(1.0f, curspeed); // traction control @@ -323,26 +303,22 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) // handbrake float hbrake = 0.0f; - if (ar_parking_brake && (ar_wheels[i].wh_braking != wheel_t::BrakeCombo::FOOT_ONLY)) - { - hbrake = m_handbrake_force; - } + if (ar_parking_brake && (ar_wheels[i].wh_braking != wheel_t::BrakeCombo::FOOT_ONLY)) { hbrake = m_handbrake_force; } // directional braking float dbrake = 0.0f; - if ((ar_wheels[i].wh_speed < 20.0f) - && (((ar_wheels[i].wh_braking == wheel_t::BrakeCombo::FOOT_HAND_SKID_LEFT) && (ar_hydro_dir_state > 0.0f)) - || ((ar_wheels[i].wh_braking == wheel_t::BrakeCombo::FOOT_HAND_SKID_RIGHT) && (ar_hydro_dir_state < 0.0f)))) - { - dbrake = ar_brake_force * abs(ar_hydro_dir_state); - } + if ((ar_wheels[i].wh_speed < 20.0f) && + (((ar_wheels[i].wh_braking == wheel_t::BrakeCombo::FOOT_HAND_SKID_LEFT) && (ar_hydro_dir_state > 0.0f)) || + ((ar_wheels[i].wh_braking == wheel_t::BrakeCombo::FOOT_HAND_SKID_RIGHT) && (ar_hydro_dir_state < 0.0f)))) + { dbrake = ar_brake_force * abs(ar_hydro_dir_state); } if (abrake != 0.0 || dbrake != 0.0 || hbrake != 0.0) { - float adbrake = abrake + dbrake; + float adbrake = abrake + dbrake; // anti-lock braking - if (alb_mode && curspeed > alb_minspeed && curspeed > fabs(ar_wheels[i].wh_speed) && (adbrake > 0.0f) && wheel_slip > 0.25f) + if (alb_mode && curspeed > alb_minspeed && curspeed > fabs(ar_wheels[i].wh_speed) && (adbrake > 0.0f) && + wheel_slip > 0.25f) { if (alb_pulse_state) { @@ -371,26 +347,23 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) // application to wheel Vector3 axis = (ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition).normalisedCopy(); - float axis_precalc = ar_wheels[i].wh_torque / (Real)(ar_wheels[i].wh_num_nodes); + float axis_precalc = ar_wheels[i].wh_torque / (Real)(ar_wheels[i].wh_num_nodes); float expected_wheel_speed = ar_wheels[i].wh_speed; - ar_wheels[i].wh_speed = 0.0f; + ar_wheels[i].wh_speed = 0.0f; - Real contact_counter = 0.0f; - Vector3 slip = Vector3::ZERO; - Vector3 force = Vector3::ZERO; + Real contact_counter = 0.0f; + Vector3 slip = Vector3::ZERO; + Vector3 force = Vector3::ZERO; for (int j = 0; j < ar_wheels[i].wh_num_nodes; j++) { - node_t* outer_node = ar_wheels[i].wh_nodes[j]; - node_t* inner_node = (j % 2) ? ar_wheels[i].wh_axis_node_1 : ar_wheels[i].wh_axis_node_0; + node_t *outer_node = ar_wheels[i].wh_nodes[j]; + node_t *inner_node = (j % 2) ? ar_wheels[i].wh_axis_node_1 : ar_wheels[i].wh_axis_node_0; - Vector3 radius = outer_node->RelPosition - inner_node->RelPosition; - float inverted_rlen = 1.0f / radius.length(); + Vector3 radius = outer_node->RelPosition - inner_node->RelPosition; + float inverted_rlen = 1.0f / radius.length(); - if (ar_wheels[i].wh_propulsed == 2) - { - radius = -radius; - } + if (ar_wheels[i].wh_propulsed == 2) { radius = -radius; } Vector3 dir = axis.crossProduct(radius) * inverted_rlen; ar_wheels[i].wh_nodes[j]->Forces += dir * axis_precalc * inverted_rlen; @@ -400,20 +373,20 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) { contact_counter += 1.0f; float force_ratio = ar_wheels[i].wh_nodes[j]->nd_last_collision_force.length(); - slip += ar_wheels[i].wh_nodes[j]->nd_last_collision_slip * force_ratio; + slip += ar_wheels[i].wh_nodes[j]->nd_last_collision_slip * force_ratio; force += ar_wheels[i].wh_nodes[j]->nd_last_collision_force; } } if (contact_counter > 0.0f && !force.isZeroLength()) { - slip /= force.length(); // slip vector weighted by down force - slip /= contact_counter; // average slip vector - force /= contact_counter; // average force vector + slip /= force.length(); // slip vector weighted by down force + slip /= contact_counter; // average slip vector + force /= contact_counter; // average force vector Vector3 normal = force.normalisedCopy(); // contact plane normal - Vector3 v = ar_wheels[i].wh_axis_node_0->Velocity.midPoint(ar_wheels[i].wh_axis_node_1->Velocity); - Vector3 vel = v - v.dotProduct(normal) * normal; - ar_wheels[i].debug_vel += vel / (float)num_steps; - ar_wheels[i].debug_slip += slip / (float)num_steps; + Vector3 v = ar_wheels[i].wh_axis_node_0->Velocity.midPoint(ar_wheels[i].wh_axis_node_1->Velocity); + Vector3 vel = v - v.dotProduct(normal) * normal; + ar_wheels[i].debug_vel += vel / (float)num_steps; + ar_wheels[i].debug_slip += slip / (float)num_steps; ar_wheels[i].debug_force += force / (float)num_steps; } @@ -425,8 +398,8 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) if (ar_wheels[i].wh_propulsed == 1) { float speedacc = ar_wheels[i].wh_speed / (float)m_num_proped_wheels; - ar_wheel_speed += speedacc; // Accumulate the average wheel speed (m/s) - ar_wheel_spin += speedacc / ar_wheels[i].wh_radius; // Accumulate the average wheel spin (radians) + ar_wheel_speed += speedacc; // Accumulate the average wheel speed (m/s) + ar_wheel_spin += speedacc / ar_wheels[i].wh_radius; // Accumulate the average wheel spin (radians) } expected_wheel_speed += ((ar_wheels[i].wh_last_torque / ar_wheels[i].wh_radius) / ar_wheels[i].wh_mass) * PHYSICS_DT; @@ -434,9 +407,9 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) // reaction torque Vector3 rradius = ar_wheels[i].wh_arm_node->RelPosition - ar_wheels[i].wh_near_attach_node->RelPosition; - Vector3 radius = Plane(axis, ar_wheels[i].wh_near_attach_node->RelPosition).projectVector(rradius); - float offset = (rradius - radius).length(); // length of the error arm - Real rlen = radius.normalise(); // length of the projected arm + Vector3 radius = Plane(axis, ar_wheels[i].wh_near_attach_node->RelPosition).projectVector(rradius); + float offset = (rradius - radius).length(); // length of the error arm + Real rlen = radius.normalise(); // length of the projected arm // TODO: Investigate the offset length abort condition ~ ulteq 10/2018 if (rlen > 0.01 && offset * 2.0f < rlen && fabs(ar_wheels[i].wh_torque) > 0.01f) { @@ -449,7 +422,7 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) } ar_wheels[i].wh_last_torque = ar_wheels[i].wh_torque; - ar_wheels[i].wh_torque = 0.0f; + ar_wheels[i].wh_torque = 0.0f; } ar_avg_wheel_speed = ar_avg_wheel_speed * 0.995 + ar_wheel_speed * 0.005; @@ -461,19 +434,13 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) if (doUpdate) { - if (!m_antilockbrake) - { - SOUND_STOP(ar_instance_id, SS_TRIG_ALB_ACTIVE); - } + if (!m_antilockbrake) { SOUND_STOP(ar_instance_id, SS_TRIG_ALB_ACTIVE); } else { SOUND_START(ar_instance_id, SS_TRIG_ALB_ACTIVE); } - if (!m_tractioncontrol) - { - SOUND_STOP(ar_instance_id, SS_TRIG_TC_ACTIVE); - } + if (!m_tractioncontrol) { SOUND_STOP(ar_instance_id, SS_TRIG_TC_ACTIVE); } else { SOUND_START(ar_instance_id, SS_TRIG_TC_ACTIVE); @@ -488,10 +455,11 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) void Actor::CalcShocks(bool doUpdate, int num_steps) { - //variable shocks for stabilization + // variable shocks for stabilization if (this->ar_has_active_shocks && m_stabilizer_shock_request) { - if ((m_stabilizer_shock_request == 1 && m_stabilizer_shock_ratio < 0.1) || (m_stabilizer_shock_request == -1 && m_stabilizer_shock_ratio > -0.1)) + if ((m_stabilizer_shock_request == 1 && m_stabilizer_shock_ratio < 0.1) || + (m_stabilizer_shock_request == -1 && m_stabilizer_shock_ratio > -0.1)) m_stabilizer_shock_ratio = m_stabilizer_shock_ratio + (float)m_stabilizer_shock_request * PHYSICS_DT * STAB_RATE; for (int i = 0; i < ar_num_shocks; i++) { @@ -502,23 +470,20 @@ void Actor::CalcShocks(bool doUpdate, int num_steps) ar_beams[ar_shocks[i].beamid].L = ar_beams[ar_shocks[i].beamid].refL * (1.0 - m_stabilizer_shock_ratio); } } - //auto shock adjust + // auto shock adjust if (this->ar_has_active_shocks && doUpdate) { m_stabilizer_shock_sleep -= PHYSICS_DT * num_steps; float roll = asin(GetCameraRoll().dotProduct(Vector3::UNIT_Y)); - //mWindow->setDebugText("Roll:"+ TOSTRING(roll)); + // mWindow->setDebugText("Roll:"+ TOSTRING(roll)); if (fabs(roll) > 0.2) { - m_stabilizer_shock_sleep = -1.0; //emergency timeout stop + m_stabilizer_shock_sleep = -1.0; // emergency timeout stop } if (fabs(roll) > 0.01 && m_stabilizer_shock_sleep < 0.0) { - if (roll > 0.0 && m_stabilizer_shock_request != -1) - { - m_stabilizer_shock_request = 1; - } + if (roll > 0.0 && m_stabilizer_shock_request != -1) { m_stabilizer_shock_request = 1; } else if (roll < 0.0 && m_stabilizer_shock_request != 1) { m_stabilizer_shock_request = -1; @@ -526,7 +491,7 @@ void Actor::CalcShocks(bool doUpdate, int num_steps) else { m_stabilizer_shock_request = 0; - m_stabilizer_shock_sleep = 3.0; + m_stabilizer_shock_sleep = 3.0; } } else @@ -543,16 +508,16 @@ void Actor::CalcShocks(bool doUpdate, int num_steps) void Actor::CalcHydros() { - //direction + // direction if (ar_hydro_dir_state != 0 || ar_hydro_dir_command != 0) { if (!ar_hydro_speed_coupling) { // need a maximum rate for analog devices, otherwise hydro beams break - float smoothing = Math::Clamp(App::io_analog_smoothing.GetActive(), 0.5f, 2.0f); + float smoothing = Math::Clamp(App::io_analog_smoothing.GetActive(), 0.5f, 2.0f); float sensitivity = Math::Clamp(App::io_analog_sensitivity.GetActive(), 0.5f, 2.0f); - float diff = ar_hydro_dir_command - ar_hydro_dir_state; - float rate = std::exp(-std::min(std::abs(diff), 1.0f) / sensitivity) * diff; + float diff = ar_hydro_dir_command - ar_hydro_dir_state; + float rate = std::exp(-std::min(std::abs(diff), 1.0f) / sensitivity) * diff; ar_hydro_dir_state += (10.0f / smoothing) * PHYSICS_DT * rate; } else @@ -575,7 +540,7 @@ void Actor::CalcHydros() ar_hydro_dir_state = 0; } } - //aileron + // aileron if (ar_hydro_aileron_state != 0 || ar_hydro_aileron_command != 0) { if (ar_hydro_aileron_command != 0) @@ -593,7 +558,7 @@ void Actor::CalcHydros() else ar_hydro_aileron_state = 0; } - //rudder + // rudder if (ar_hydro_rudder_state != 0 || ar_hydro_rudder_command != 0) { if (ar_hydro_rudder_command != 0) @@ -612,7 +577,7 @@ void Actor::CalcHydros() else ar_hydro_rudder_state = 0; } - //elevator + // elevator if (ar_hydro_elevator_state != 0 || ar_hydro_elevator_command != 0) { if (ar_hydro_elevator_command != 0) @@ -630,20 +595,19 @@ void Actor::CalcHydros() else ar_hydro_elevator_state = 0; } - //update length, dirstate between -1.0 and 1.0 + // update length, dirstate between -1.0 and 1.0 const int num_hydros = static_cast(ar_hydros.size()); for (int i = 0; i < num_hydros; ++i) { - hydrobeam_t& hydrobeam = ar_hydros[i]; + hydrobeam_t &hydrobeam = ar_hydros[i]; - //compound hydro + // compound hydro float cstate = 0.0f; - int div = 0; + int div = 0; if (hydrobeam.hb_flags & HYDRO_FLAG_SPEED) { - //special treatment for SPEED - if (ar_wheel_speed < 12.0f) - cstate += ar_hydro_dir_state * (12.0f - ar_wheel_speed) / 12.0f; + // special treatment for SPEED + if (ar_wheel_speed < 12.0f) cstate += ar_hydro_dir_state * (12.0f - ar_wheel_speed) / 12.0f; div++; } if (hydrobeam.hb_flags & HYDRO_FLAG_DIR) @@ -684,16 +648,11 @@ void Actor::CalcHydros() const uint16_t beam_idx = hydrobeam.hb_beam_index; - if (cstate > 1.0) - cstate = 1.0; - if (cstate < -1.0) - cstate = -1.0; + if (cstate > 1.0) cstate = 1.0; + if (cstate < -1.0) cstate = -1.0; // Animators following, if no animator, skip all the tests... int flagstate = hydrobeam.hb_anim_flags; - if (flagstate) - { - this->CalcAnimators(flagstate, cstate, div, PHYSICS_DT, 0.0f, 0.0f, hydrobeam.hb_anim_param); - } + if (flagstate) { this->CalcAnimators(flagstate, cstate, div, PHYSICS_DT, 0.0f, 0.0f, hydrobeam.hb_anim_param); } if (div) { @@ -701,18 +660,15 @@ void Actor::CalcHydros() cstate = hydrobeam.hb_inertia.CalcCmdKeyDelay(cstate, PHYSICS_DT); - if (!(hydrobeam.hb_flags & HYDRO_FLAG_SPEED) && !flagstate) - ar_hydro_dir_wheel_display = cstate; + if (!(hydrobeam.hb_flags & HYDRO_FLAG_SPEED) && !flagstate) ar_hydro_dir_wheel_display = cstate; float factor = 1.0 - cstate * hydrobeam.hb_speed; // check and apply animators limits if set if (flagstate) { - if (factor < 1.0f - ar_beams[beam_idx].shortbound) - factor = 1.0f - ar_beams[beam_idx].shortbound; - if (factor > 1.0f + ar_beams[beam_idx].longbound) - factor = 1.0f + ar_beams[beam_idx].longbound; + if (factor < 1.0f - ar_beams[beam_idx].shortbound) factor = 1.0f - ar_beams[beam_idx].shortbound; + if (factor > 1.0f + ar_beams[beam_idx].longbound) factor = 1.0f + ar_beams[beam_idx].longbound; } ar_beams[beam_idx].L = hydrobeam.hb_ref_length * factor; @@ -724,9 +680,9 @@ void Actor::CalcCommands(bool doUpdate) { if (m_has_command_beams) { - int active = 0; - bool requested = false; - float work = 0.0; + int active = 0; + bool requested = false; + float work = 0.0; // hydraulics ready? if (ar_engine) @@ -736,12 +692,10 @@ void Actor::CalcCommands(bool doUpdate) // crankfactor float crankfactor = 1.0f; - if (ar_engine) - crankfactor = ar_engine->GetCrankFactor(); + if (ar_engine) crankfactor = ar_engine->GetCrankFactor(); // speed up machines - if (ar_driveable == MACHINE) - crankfactor = 2; + if (ar_driveable == MACHINE) crankfactor = 2; for (int i = 0; i <= MAX_COMMANDS; i++) { @@ -776,9 +730,7 @@ void Actor::CalcCommands(bool doUpdate) { ar_command_key[i].beams[j].cmb_state->auto_move_lock = true; if (ar_command_key[i].beams[j].cmb_is_autocentering) - { - ar_command_key[i].beams[j].cmb_state->auto_moving_mode = 0; - } + { ar_command_key[i].beams[j].cmb_state->auto_moving_mode = 0; } } } } @@ -789,26 +741,23 @@ void Actor::CalcCommands(bool doUpdate) bool requestpower = false; for (int j = 0; j < (int)ar_command_key[i].beams.size(); j++) { - commandbeam_t& cmd_beam = ar_command_key[i].beams[j]; - int bbeam_dir = (cmd_beam.cmb_is_contraction) ? -1 : 1; - int bbeam = cmd_beam.cmb_beam_index; + commandbeam_t &cmd_beam = ar_command_key[i].beams[j]; + int bbeam_dir = (cmd_beam.cmb_is_contraction) ? -1 : 1; + int bbeam = cmd_beam.cmb_beam_index; - if (bbeam > ar_num_beams) - continue; + if (bbeam > ar_num_beams) continue; // restrict forces - if (cmd_beam.cmb_is_force_restricted) - crankfactor = std::min(crankfactor, 1.0f); + if (cmd_beam.cmb_is_force_restricted) crankfactor = std::min(crankfactor, 1.0f); - float v = ar_command_key[i].commandValue; - int& vst = ar_command_key[i].commandValueState; + float v = ar_command_key[i].commandValue; + int & vst = ar_command_key[i].commandValueState; // self centering if (cmd_beam.cmb_is_autocentering && !cmd_beam.cmb_state->auto_move_lock) { // check for some error - if (ar_beams[bbeam].refL == 0 || ar_beams[bbeam].L == 0) - continue; + if (ar_beams[bbeam].refL == 0 || ar_beams[bbeam].L == 0) continue; float current = (ar_beams[bbeam].L / ar_beams[bbeam].refL); @@ -830,7 +779,7 @@ void Actor::CalcCommands(bool doUpdate) // avoid overshooting if (mode != 0 && mode != cmd_beam.cmb_state->auto_moving_mode) { - ar_beams[bbeam].L = cmd_beam.cmb_center_length * ar_beams[bbeam].refL; + ar_beams[bbeam].L = cmd_beam.cmb_center_length * ar_beams[bbeam].refL; cmd_beam.cmb_state->auto_moving_mode = 0; } } @@ -839,19 +788,24 @@ void Actor::CalcCommands(bool doUpdate) if (ar_beams[bbeam].refL != 0 && ar_beams[bbeam].L != 0) { float clen = ar_beams[bbeam].L / ar_beams[bbeam].refL; - if ((bbeam_dir > 0 && clen < cmd_beam.cmb_boundary_length) || (bbeam_dir < 0 && clen > cmd_beam.cmb_boundary_length)) + if ((bbeam_dir > 0 && clen < cmd_beam.cmb_boundary_length) || + (bbeam_dir < 0 && clen > cmd_beam.cmb_boundary_length)) { float dl = ar_beams[bbeam].L; if (cmd_beam.cmb_is_1press_center) { // one press + centering - if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode > 0 && bbeam_dir * clen > bbeam_dir * cmd_beam.cmb_center_length && !cmd_beam.cmb_state->pressed_center_mode) + if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode > 0 && + bbeam_dir * clen > bbeam_dir * cmd_beam.cmb_center_length && + !cmd_beam.cmb_state->pressed_center_mode) { cmd_beam.cmb_state->pressed_center_mode = true; - cmd_beam.cmb_state->auto_moving_mode = 0; + cmd_beam.cmb_state->auto_moving_mode = 0; } - else if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode < 0 && bbeam_dir * clen > bbeam_dir * cmd_beam.cmb_center_length && cmd_beam.cmb_state->pressed_center_mode) + else if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode < 0 && + bbeam_dir * clen > bbeam_dir * cmd_beam.cmb_center_length && + cmd_beam.cmb_state->pressed_center_mode) { cmd_beam.cmb_state->pressed_center_mode = false; } @@ -860,9 +814,7 @@ void Actor::CalcCommands(bool doUpdate) { bool key = (v > 0.5); if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode <= 0 && key) - { - cmd_beam.cmb_state->auto_moving_mode = bbeam_dir * 1; - } + { cmd_beam.cmb_state->auto_moving_mode = bbeam_dir * 1; } else if (cmd_beam.cmb_state->auto_moving_mode == bbeam_dir * 1 && !key) { cmd_beam.cmb_state->auto_moving_mode = bbeam_dir * 2; @@ -879,14 +831,12 @@ void Actor::CalcCommands(bool doUpdate) v = ar_command_key[i].command_inertia.CalcCmdKeyDelay(v, PHYSICS_DT); - if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode > 0) - v = 1; + if (bbeam_dir * cmd_beam.cmb_state->auto_moving_mode > 0) v = 1; if (cmd_beam.cmb_needs_engine && ((ar_engine && !ar_engine->IsRunning()) || !ar_engine_hydraulics_ready)) continue; - if (v > 0.0f && cmd_beam.cmb_engine_coupling > 0.0f) - requestpower = true; + if (v > 0.0f && cmd_beam.cmb_engine_coupling > 0.0f) requestpower = true; #ifdef USE_OPENAL if (cmd_beam.cmb_plays_sound) @@ -895,27 +845,30 @@ void Actor::CalcCommands(bool doUpdate) if (vst == 1) { // just started - SoundScriptManager::getSingleton().trigStop(ar_instance_id, SS_TRIG_LINKED_COMMAND, SL_COMMAND, -i); - SoundScriptManager::getSingleton().trigStart(ar_instance_id, SS_TRIG_LINKED_COMMAND, SL_COMMAND, i); + SoundScriptManager::getSingleton().trigStop(ar_instance_id, SS_TRIG_LINKED_COMMAND, SL_COMMAND, + -i); + SoundScriptManager::getSingleton().trigStart(ar_instance_id, SS_TRIG_LINKED_COMMAND, SL_COMMAND, + i); vst = 0; } else if (vst == -1) { // just stopped - SoundScriptManager::getSingleton().trigStop(ar_instance_id, SS_TRIG_LINKED_COMMAND, SL_COMMAND, i); + SoundScriptManager::getSingleton().trigStop(ar_instance_id, SS_TRIG_LINKED_COMMAND, SL_COMMAND, + i); vst = 0; } else if (vst == 0) { // already running, modulate - SoundScriptManager::getSingleton().modulate(ar_instance_id, SS_MOD_LINKED_COMMANDRATE, v, SL_COMMAND, i); + SoundScriptManager::getSingleton().modulate(ar_instance_id, SS_MOD_LINKED_COMMANDRATE, v, + SL_COMMAND, i); } } -#endif //USE_OPENAL +#endif // USE_OPENAL float cf = 1.0f; - if (cmd_beam.cmb_engine_coupling > 0) - cf = crankfactor; + if (cmd_beam.cmb_engine_coupling > 0) cf = crankfactor; if (bbeam_dir > 0) ar_beams[bbeam].L *= (1.0 + cmd_beam.cmb_speed * v * cf * PHYSICS_DT / ar_beams[bbeam].L); @@ -929,7 +882,8 @@ void Actor::CalcCommands(bool doUpdate) work += fabs(ar_beams[bbeam].stress) * dl * cmd_beam.cmb_engine_coupling; } } - else if ((cmd_beam.cmb_is_1press || cmd_beam.cmb_is_1press_center) && bbeam_dir * cmd_beam.cmb_state->auto_moving_mode > 0) + else if ((cmd_beam.cmb_is_1press || cmd_beam.cmb_is_1press_center) && + bbeam_dir * cmd_beam.cmb_state->auto_moving_mode > 0) { // beyond length cmd_beam.cmb_state->auto_moving_mode = 0; @@ -939,34 +893,28 @@ void Actor::CalcCommands(bool doUpdate) // also for rotators for (int j = 0; j < (int)ar_command_key[i].rotators.size(); j++) { - float v = 0.0f; - int rota = std::abs(ar_command_key[i].rotators[j]) - 1; + float v = 0.0f; + int rota = std::abs(ar_command_key[i].rotators[j]) - 1; if (ar_rotators[rota].needs_engine && ((ar_engine && !ar_engine->IsRunning()) || !ar_engine_hydraulics_ready)) continue; v = ar_command_key[i].rotator_inertia.CalcCmdKeyDelay(ar_command_key[i].commandValue, PHYSICS_DT); - if (v > 0.0f && ar_rotators[rota].engine_coupling > 0.0f) - requestpower = true; + if (v > 0.0f && ar_rotators[rota].engine_coupling > 0.0f) requestpower = true; float cf = 1.0f; - if (ar_rotators[rota].engine_coupling > 0.0f) - cf = crankfactor; + if (ar_rotators[rota].engine_coupling > 0.0f) cf = crankfactor; if (ar_command_key[i].rotators[j] > 0) ar_rotators[rota].angle += ar_rotators[rota].rate * v * cf * PHYSICS_DT; else ar_rotators[rota].angle -= ar_rotators[rota].rate * v * cf * PHYSICS_DT; - if (doUpdate || v != 0.0f) - { - ar_rotators[rota].debug_rate = ar_rotators[rota].rate * v * cf; - } + if (doUpdate || v != 0.0f) { ar_rotators[rota].debug_rate = ar_rotators[rota].rate * v * cf; } } - if (requestpower) - requested=true; + if (requestpower) requested = true; } if (ar_engine) @@ -988,14 +936,14 @@ void Actor::CalcCommands(bool doUpdate) { SOUND_STOP(ar_instance_id, SS_TRIG_PUMP); } -#endif //USE_OPENAL +#endif // USE_OPENAL } // rotators for (int i = 0; i < ar_num_rotators; i++) { // compute rotation axis - Vector3 ax1 = ar_nodes[ar_rotators[i].axis1].RelPosition; - Vector3 ax2 = ar_nodes[ar_rotators[i].axis2].RelPosition; + Vector3 ax1 = ar_nodes[ar_rotators[i].axis1].RelPosition; + Vector3 ax2 = ar_nodes[ar_rotators[i].axis2].RelPosition; Vector3 axis = ax1 - ax2; axis.normalise(); // find the reference plane @@ -1005,28 +953,26 @@ void Actor::CalcCommands(bool doUpdate) for (int k = 0; k < 2; k++) { // find the reference vectors - Vector3 ref1 = pl.projectVector(ax1 - ar_nodes[ar_rotators[i].nodes1[k]].RelPosition); - Vector3 ref2 = pl.projectVector(ax2 - ar_nodes[ar_rotators[i].nodes2[k]].RelPosition); - float ref1len = ref1.normalise(); - float ref2len = ref2.normalise(); + Vector3 ref1 = pl.projectVector(ax1 - ar_nodes[ar_rotators[i].nodes1[k]].RelPosition); + Vector3 ref2 = pl.projectVector(ax2 - ar_nodes[ar_rotators[i].nodes2[k]].RelPosition); + float ref1len = ref1.normalise(); + float ref2len = ref2.normalise(); // theory vector Vector3 th1 = Quaternion(Radian(ar_rotators[i].angle + Math::HALF_PI), axis) * ref1; // find the angle error float aerror = asin(th1.dotProduct(ref2)); ar_rotators[i].debug_aerror += 0.5f * aerror; // exert forces - float rigidity = ar_rotators[i].force; - Vector3 dir1 = ref1.crossProduct(axis); - Vector3 dir2 = ref2.crossProduct(axis); + float rigidity = ar_rotators[i].force; + Vector3 dir1 = ref1.crossProduct(axis); + Vector3 dir2 = ref2.crossProduct(axis); // simple jitter fix - if (ref1len <= ar_rotators[i].tolerance) - ref1len = 0.0f; - if (ref2len <= ar_rotators[i].tolerance) - ref2len = 0.0f; + if (ref1len <= ar_rotators[i].tolerance) ref1len = 0.0f; + if (ref2len <= ar_rotators[i].tolerance) ref2len = 0.0f; - ar_nodes[ar_rotators[i].nodes1[k ]].Forces += (aerror * ref1len * rigidity) * dir1; - ar_nodes[ar_rotators[i].nodes2[k ]].Forces -= (aerror * ref2len * rigidity) * dir2; + ar_nodes[ar_rotators[i].nodes1[k]].Forces += (aerror * ref1len * rigidity) * dir1; + ar_nodes[ar_rotators[i].nodes2[k]].Forces -= (aerror * ref2len * rigidity) * dir2; // symmetric ar_nodes[ar_rotators[i].nodes1[k + 2]].Forces -= (aerror * ref1len * rigidity) * dir1; ar_nodes[ar_rotators[i].nodes2[k + 2]].Forces += (aerror * ref2len * rigidity) * dir2; @@ -1041,18 +987,13 @@ void Actor::CalcTies() for (std::vector::iterator it = ar_ties.begin(); it != ar_ties.end(); it++) { // only process tying ties - if (!it->ti_tying) - continue; + if (!it->ti_tying) continue; // division through zero guard - if (it->ti_beam->refL == 0 || it->ti_beam->L == 0) - continue; + if (it->ti_beam->refL == 0 || it->ti_beam->L == 0) continue; float clen = it->ti_beam->L / it->ti_beam->refL; - if (clen > it->ti_min_length) - { - it->ti_beam->L *= (1.0 - it->ti_contract_speed * PHYSICS_DT / it->ti_beam->L); - } + if (clen > it->ti_min_length) { it->ti_beam->L *= (1.0 - it->ti_contract_speed * PHYSICS_DT / it->ti_beam->L); } else { // tying finished, end reached @@ -1060,18 +1001,12 @@ void Actor::CalcTies() } // check if we hit a certain force limit, then abort the tying process - if (fabs(it->ti_beam->stress) > it->ti_max_stress) - { - it->ti_tying = false; - } + if (fabs(it->ti_beam->stress) > it->ti_max_stress) { it->ti_tying = false; } } } void Actor::CalcTruckEngine(bool doUpdate) { - if (ar_engine) - { - ar_engine->UpdateEngineSim(PHYSICS_DT, doUpdate); - } + if (ar_engine) { ar_engine->UpdateEngineSim(PHYSICS_DT, doUpdate); } } void Actor::CalcReplay() @@ -1082,7 +1017,7 @@ void Actor::CalcReplay() if (m_replay_timer >= ar_replay_precision) { // store nodes - node_simple_t* nbuff = (node_simple_t *)m_replay_handler->getWriteBuffer(0); + node_simple_t *nbuff = (node_simple_t *)m_replay_handler->getWriteBuffer(0); if (nbuff) { for (int i = 0; i < ar_num_nodes; i++) @@ -1093,12 +1028,12 @@ void Actor::CalcReplay() } // store beams - beam_simple_t* bbuff = (beam_simple_t *)m_replay_handler->getWriteBuffer(1); + beam_simple_t *bbuff = (beam_simple_t *)m_replay_handler->getWriteBuffer(1); if (bbuff) { for (int i = 0; i < ar_num_beams; i++) { - bbuff[i].broken = ar_beams[i].bm_broken; + bbuff[i].broken = ar_beams[i].bm_broken; bbuff[i].disabled = ar_beams[i].bm_disabled; } } @@ -1111,15 +1046,11 @@ void Actor::CalcReplay() bool Actor::CalcForcesEulerPrepare(bool doUpdate) { - if (m_ongoing_reset) - return false; - if (ar_physics_paused) - return false; - if (ar_sim_state != Actor::SimState::LOCAL_SIMULATED) - return false; + if (m_ongoing_reset) return false; + if (ar_physics_paused) return false; + if (ar_sim_state != Actor::SimState::LOCAL_SIMULATED) return false; - if (doUpdate) - this->ToggleHooks(-2, HOOK_LOCK, -1); + if (doUpdate) this->ToggleHooks(-2, HOOK_LOCK, -1); this->CalcHooks(); this->CalcRopes(); @@ -1127,14 +1058,12 @@ bool Actor::CalcForcesEulerPrepare(bool doUpdate) return true; } -template -void LogNodeId(RoR::Str& msg, node_t* node) // Internal helper +template void LogNodeId(RoR::Str &msg, node_t *node) // Internal helper { msg << " (index: " << node->pos << ")"; } -template -void LogBeamNodes(RoR::Str& msg, beam_t& beam) // Internal helper +template void LogBeamNodes(RoR::Str &msg, beam_t &beam) // Internal helper { msg << "It was between nodes "; LogNodeId(msg, beam.p1); @@ -1152,7 +1081,7 @@ void Actor::CalcBeams(bool trigger_hooks) // Calculate beam length Vector3 dis = ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition; - Real dislen = dis.squaredLength(); + Real dislen = dis.squaredLength(); Real inverted_dislen = fast_invSqrt(dislen); dislen *= inverted_dislen; @@ -1180,13 +1109,13 @@ void Actor::CalcBeams(bool trigger_hooks) { // Hard (normal) shock bump float tspring = DEFAULT_SPRING; - float tdamp = DEFAULT_DAMP; + float tdamp = DEFAULT_DAMP; // Skip camera, wheels or any other shocks which are not generated in a shocks or shocks2 section if (ar_beams[i].bm_type == BEAM_HYDRO) { tspring = ar_beams[i].shock->sbd_spring; - tdamp = ar_beams[i].shock->sbd_damp; + tdamp = ar_beams[i].shock->sbd_damp; } k += (tspring - k) * interp_ratio; @@ -1221,13 +1150,13 @@ void Actor::CalcBeams(bool trigger_hooks) // If support beam is extended the originallength * break_limit, break and disable it if (difftoBeamL > ar_beams[i].L * break_limit) { - ar_beams[i].bm_broken = true; + ar_beams[i].bm_broken = true; ar_beams[i].bm_disabled = true; if (m_beam_break_debug_enabled) { RoR::Str<300> msg; msg << "[RoR|Diag] XXX Support-Beam " << i << " limit extended and broke. " - << "Length: " << difftoBeamL << " / max. Length: " << (ar_beams[i].L*break_limit) << ". "; + << "Length: " << difftoBeamL << " / max. Length: " << (ar_beams[i].L * break_limit) << ". "; LogBeamNodes(msg, ar_beams[i]); RoR::Log(msg.ToCStr()); } @@ -1250,7 +1179,7 @@ void Actor::CalcBeams(bool trigger_hooks) ar_beams[i].debug_v = std::abs(v); } - float slen = -k * difftoBeamL - d * v; + float slen = -k * difftoBeamL - d * v; ar_beams[i].stress = slen; // Fast test for deformation @@ -1263,12 +1192,12 @@ void Actor::CalcBeams(bool trigger_hooks) if (slen > ar_beams[i].maxposstress && difftoBeamL < 0.0f) // compression { Real yield_length = ar_beams[i].maxposstress / k; - Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef); - Real Lold = ar_beams[i].L; + Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef); + Real Lold = ar_beams[i].L; ar_beams[i].L += deform; ar_beams[i].L = std::max(MIN_BEAM_LENGTH, ar_beams[i].L); - slen = slen - (slen - ar_beams[i].maxposstress) * 0.5f; - len = slen; + slen = slen - (slen - ar_beams[i].maxposstress) * 0.5f; + len = slen; if (ar_beams[i].L > 0.0f && Lold > ar_beams[i].L) { ar_beams[i].maxposstress *= Lold / ar_beams[i].L; @@ -1277,12 +1206,12 @@ void Actor::CalcBeams(bool trigger_hooks) } // For the compression case we do not remove any of the beam's // strength for structure stability reasons - //ar_beams[i].strength += deform * k * 0.5f; + // ar_beams[i].strength += deform * k * 0.5f; if (m_beam_deform_debug_enabled) { RoR::Str<300> msg; - msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " - << len << " / " << ar_beams[i].strength << ". "; + msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " << len << " / " + << ar_beams[i].strength << ". "; LogBeamNodes(msg, ar_beams[i]); RoR::Log(msg.ToCStr()); } @@ -1290,11 +1219,11 @@ void Actor::CalcBeams(bool trigger_hooks) else if (slen < ar_beams[i].maxnegstress && difftoBeamL > 0.0f) // expansion { Real yield_length = ar_beams[i].maxnegstress / k; - Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef); - Real Lold = ar_beams[i].L; + Real deform = difftoBeamL + yield_length * (1.0f - ar_beams[i].plastic_coef); + Real Lold = ar_beams[i].L; ar_beams[i].L += deform; slen = slen - (slen - ar_beams[i].maxnegstress) * 0.5f; - len = -slen; + len = -slen; if (Lold > 0.0f && ar_beams[i].L > Lold) { ar_beams[i].maxnegstress *= ar_beams[i].L / Lold; @@ -1305,8 +1234,8 @@ void Actor::CalcBeams(bool trigger_hooks) if (m_beam_deform_debug_enabled) { RoR::Str<300> msg; - msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " - << len << " / " << ar_beams[i].strength << ". "; + msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " << len << " / " + << ar_beams[i].strength << ". "; LogBeamNodes(msg, ar_beams[i]); RoR::Log(msg.ToCStr()); } @@ -1321,25 +1250,28 @@ void Actor::CalcBeams(bool trigger_hooks) SOUND_MODULATE(ar_instance_id, SS_MOD_BREAK, 0.5 * k * difftoBeamL * difftoBeamL); SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_BREAK); - //Break the beam only when it is not connected to a node - //which is a part of a collision triangle and has 2 "live" beams or less - //connected to it. - if (!((ar_beams[i].p1->nd_cab_node && GetNumActiveConnectedBeams(ar_beams[i].p1->pos) < 3) || (ar_beams[i].p2->nd_cab_node && GetNumActiveConnectedBeams(ar_beams[i].p2->pos) < 3))) + // Break the beam only when it is not connected to a node + // which is a part of a collision triangle and has 2 "live" beams or less + // connected to it. + if (!((ar_beams[i].p1->nd_cab_node && GetNumActiveConnectedBeams(ar_beams[i].p1->pos) < 3) || + (ar_beams[i].p2->nd_cab_node && GetNumActiveConnectedBeams(ar_beams[i].p2->pos) < 3))) { - slen = 0.0f; - ar_beams[i].bm_broken = true; + slen = 0.0f; + ar_beams[i].bm_broken = true; ar_beams[i].bm_disabled = true; if (m_beam_break_debug_enabled) { RoR::Str<200> msg; - msg << "[RoR|Diag] XXX Beam " << i << " just broke with force " << len << " / " << ar_beams[i].strength << ". "; + msg << "[RoR|Diag] XXX Beam " << i << " just broke with force " << len << " / " + << ar_beams[i].strength << ". "; LogBeamNodes(msg, ar_beams[i]); RoR::Log(msg.ToCStr()); } - // detachergroup check: beam[i] is already broken, check detacher group# == 0/default skip the check ( performance bypass for beams with default setting ) - // only perform this check if this is a master detacher beams (positive detacher group id > 0) + // detachergroup check: beam[i] is already broken, check detacher group# == 0/default skip the check ( + // performance bypass for beams with default setting ) only perform this check if this is a master + // detacher beams (positive detacher group id > 0) if (ar_beams[i].detacher_group > 0) { // cycle once through the other beams @@ -1349,11 +1281,12 @@ void Actor::CalcBeams(bool trigger_hooks) // do this with all master(positive id) and minor(negative id) beams of this detacher group if (abs(ar_beams[j].detacher_group) == ar_beams[i].detacher_group) { - ar_beams[j].bm_broken = true; + ar_beams[j].bm_broken = true; ar_beams[j].bm_disabled = true; if (m_beam_break_debug_enabled) { - LOG("Deleting Detacher BeamID: " + TOSTRING(j) + ", Detacher Group: " + TOSTRING(ar_beams[i].detacher_group)+ ", actor ID: " + TOSTRING(ar_instance_id)); + LOG("Deleting Detacher BeamID: " + TOSTRING(j) + ", Detacher Group: " + + TOSTRING(ar_beams[i].detacher_group) + ", actor ID: " + TOSTRING(ar_instance_id)); } } } @@ -1361,9 +1294,7 @@ void Actor::CalcBeams(bool trigger_hooks) for (int j = 0; j < ar_num_wheels; j++) { if (ar_wheels[j].wh_detacher_group == ar_beams[i].detacher_group) - { - ar_wheels[j].wh_is_detached = true; - } + { ar_wheels[j].wh_is_detached = true; } } } } @@ -1376,13 +1307,12 @@ void Actor::CalcBeams(bool trigger_hooks) for (int mk = 0; mk < ar_num_buoycabs; mk++) { int tmpv = ar_buoycabs[mk] * 3; - if (ar_buoycab_types[mk] == Buoyance::BUOY_DRAGONLY) - continue; - if ((ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv]] || ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv + 1]] || ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv + 2]]) && - (ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv]] || ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv + 1]] || ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv + 2]])) - { - m_buoyance->sink = true; - } + if (ar_buoycab_types[mk] == Buoyance::BUOY_DRAGONLY) continue; + if ((ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv]] || ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv + 1]] || + ar_beams[i].p1 == &ar_nodes[ar_cabs[tmpv + 2]]) && + (ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv]] || ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv + 1]] || + ar_beams[i].p2 == &ar_nodes[ar_cabs[tmpv + 2]])) + { m_buoyance->sink = true; } } } } @@ -1405,7 +1335,7 @@ void Actor::CalcBeamsInterActor() // Calculate beam length Vector3 dis = ar_inter_beams[i]->p1->AbsPosition - ar_inter_beams[i]->p2->AbsPosition; - Real dislen = dis.squaredLength(); + Real dislen = dis.squaredLength(); Real inverted_dislen = fast_invSqrt(dislen); dislen *= inverted_dislen; @@ -1425,7 +1355,7 @@ void Actor::CalcBeamsInterActor() // Calculate beam's rate of change Vector3 v = ar_inter_beams[i]->p1->Velocity - ar_inter_beams[i]->p2->Velocity; - float slen = -k * (difftoBeamL) - d * v.dotProduct(dis) * inverted_dislen; + float slen = -k * (difftoBeamL)-d * v.dotProduct(dis) * inverted_dislen; ar_inter_beams[i]->stress = slen; // Fast test for deformation @@ -1438,26 +1368,28 @@ void Actor::CalcBeamsInterActor() if (slen > ar_inter_beams[i]->maxposstress && difftoBeamL < 0.0f) // compression { Real yield_length = ar_inter_beams[i]->maxposstress / k; - Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef); - Real Lold = ar_inter_beams[i]->L; + Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef); + Real Lold = ar_inter_beams[i]->L; ar_inter_beams[i]->L += deform; ar_inter_beams[i]->L = std::max(MIN_BEAM_LENGTH, ar_inter_beams[i]->L); - slen = slen - (slen - ar_inter_beams[i]->maxposstress) * 0.5f; - len = slen; + slen = slen - (slen - ar_inter_beams[i]->maxposstress) * 0.5f; + len = slen; if (ar_inter_beams[i]->L > 0.0f && Lold > ar_inter_beams[i]->L) { ar_inter_beams[i]->maxposstress *= Lold / ar_inter_beams[i]->L; - ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress); - ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength); + ar_inter_beams[i]->minmaxposnegstress = + std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress); + ar_inter_beams[i]->minmaxposnegstress = + std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength); } // For the compression case we do not remove any of the beam's // strength for structure stability reasons - //ar_inter_beams[i]->strength += deform * k * 0.5f; + // ar_inter_beams[i]->strength += deform * k * 0.5f; if (m_beam_deform_debug_enabled) { RoR::Str<300> msg; - msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " - << len << " / " << ar_inter_beams[i]->strength << ". "; + msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " << len << " / " + << ar_inter_beams[i]->strength << ". "; LogBeamNodes(msg, (*ar_inter_beams[i])); RoR::Log(msg.ToCStr()); } @@ -1465,23 +1397,25 @@ void Actor::CalcBeamsInterActor() else if (slen < ar_inter_beams[i]->maxnegstress && difftoBeamL > 0.0f) // expansion { Real yield_length = ar_inter_beams[i]->maxnegstress / k; - Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef); - Real Lold = ar_inter_beams[i]->L; + Real deform = difftoBeamL + yield_length * (1.0f - ar_inter_beams[i]->plastic_coef); + Real Lold = ar_inter_beams[i]->L; ar_inter_beams[i]->L += deform; slen = slen - (slen - ar_inter_beams[i]->maxnegstress) * 0.5f; - len = -slen; + len = -slen; if (Lold > 0.0f && ar_inter_beams[i]->L > Lold) { ar_inter_beams[i]->maxnegstress *= ar_inter_beams[i]->L / Lold; - ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress); - ar_inter_beams[i]->minmaxposnegstress = std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength); + ar_inter_beams[i]->minmaxposnegstress = + std::min(ar_inter_beams[i]->maxposstress, -ar_inter_beams[i]->maxnegstress); + ar_inter_beams[i]->minmaxposnegstress = + std::min(ar_inter_beams[i]->minmaxposnegstress, ar_inter_beams[i]->strength); } ar_inter_beams[i]->strength -= deform * k; if (m_beam_deform_debug_enabled) { RoR::Str<300> msg; - msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " - << len << " / " << ar_inter_beams[i]->strength << ". "; + msg << "[RoR|Diag] YYY Beam " << i << " just deformed with extension force " << len << " / " + << ar_inter_beams[i]->strength << ". "; LogBeamNodes(msg, (*ar_inter_beams[i])); RoR::Log(msg.ToCStr()); } @@ -1496,19 +1430,21 @@ void Actor::CalcBeamsInterActor() SOUND_MODULATE(ar_instance_id, SS_MOD_BREAK, 0.5 * k * difftoBeamL * difftoBeamL); SOUND_PLAY_ONCE(ar_instance_id, SS_TRIG_BREAK); - //Break the beam only when it is not connected to a node - //which is a part of a collision triangle and has 2 "live" beams or less - //connected to it. - if (!((ar_inter_beams[i]->p1->nd_cab_node && GetNumActiveConnectedBeams(ar_inter_beams[i]->p1->pos) < 3) || (ar_inter_beams[i]->p2->nd_cab_node && GetNumActiveConnectedBeams(ar_inter_beams[i]->p2->pos) < 3))) + // Break the beam only when it is not connected to a node + // which is a part of a collision triangle and has 2 "live" beams or less + // connected to it. + if (!((ar_inter_beams[i]->p1->nd_cab_node && GetNumActiveConnectedBeams(ar_inter_beams[i]->p1->pos) < 3) || + (ar_inter_beams[i]->p2->nd_cab_node && GetNumActiveConnectedBeams(ar_inter_beams[i]->p2->pos) < 3))) { - slen = 0.0f; - ar_inter_beams[i]->bm_broken = true; + slen = 0.0f; + ar_inter_beams[i]->bm_broken = true; ar_inter_beams[i]->bm_disabled = true; if (m_beam_break_debug_enabled) { RoR::Str<200> msg; - msg << "[RoR|Diag] XXX Beam " << i << " just broke with force " << len << " / " << ar_inter_beams[i]->strength << ". "; + msg << "[RoR|Diag] XXX Beam " << i << " just broke with force " << len << " / " + << ar_inter_beams[i]->strength << ". "; LogBeamNodes(msg, (*ar_inter_beams[i])); RoR::Log(msg.ToCStr()); } @@ -1531,18 +1467,18 @@ void Actor::CalcBeamsInterActor() void Actor::CalcNodes() { - const auto water = App::GetSimTerrain()->getWater(); + const auto water = App::GetSimTerrain()->getWater(); const float gravity = App::GetSimTerrain()->getGravity(); - m_water_contact = false; + m_water_contact = false; for (int i = 0; i < ar_num_nodes; i++) { // COLLISION if (!ar_nodes[i].nd_no_ground_contact) { - Vector3 oripos = ar_nodes[i].AbsPosition; - bool contacted = gEnv->collisions->groundCollision(&ar_nodes[i], PHYSICS_DT); - contacted = contacted | gEnv->collisions->nodeCollision(&ar_nodes[i], PHYSICS_DT, false); + Vector3 oripos = ar_nodes[i].AbsPosition; + bool contacted = gEnv->collisions->groundCollision(&ar_nodes[i], PHYSICS_DT); + contacted = contacted | gEnv->collisions->nodeCollision(&ar_nodes[i], PHYSICS_DT, false); ar_nodes[i].nd_has_ground_contact = contacted; if (ar_nodes[i].nd_has_ground_contact || ar_nodes[i].nd_has_mesh_contact) { @@ -1583,7 +1519,7 @@ void Actor::CalcNodes() { ActorModifyRequest rq; // actor exploded, schedule reset rq.amr_actor = this; - rq.amr_type = ActorModifyRequest::Type::RESET_ON_SPOT; + rq.amr_type = ActorModifyRequest::Type::RESET_ON_SPOT; App::GetSimController()->QueueActorModify(rq); m_ongoing_reset = true; } @@ -1596,8 +1532,8 @@ void Actor::CalcNodes() else if (!ar_disable_aerodyn_turbulent_drag) { // add viscous drag (turbulent model) - Real defdragxspeed = DEFAULT_DRAG * approx_speed; - Vector3 drag = -defdragxspeed * ar_nodes[i].Velocity; + Real defdragxspeed = DEFAULT_DRAG * approx_speed; + Vector3 drag = -defdragxspeed * ar_nodes[i].Velocity; // plus: turbulences Real maxtur = defdragxspeed * approx_speed * 0.005f; drag += maxtur * Vector3(frand_11(), frand_11(), frand_11()); @@ -1618,10 +1554,7 @@ void Actor::CalcNodes() ar_nodes[i].Forces += ar_nodes[i].buoyancy * Vector3::UNIT_Y; } // engine stall - if (i == ar_cinecam_node[0] && ar_engine) - { - ar_engine->StopEngine(); - } + if (i == ar_cinecam_node[0] && ar_engine) { ar_engine->StopEngine(); } } ar_nodes[i].nd_under_water = is_under_water; } @@ -1632,62 +1565,60 @@ void Actor::CalcNodes() void Actor::CalcHooks() { - //locks - this is not active in network mode + // locks - this is not active in network mode for (std::vector::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++) { - //we need to do this here to avoid countdown speedup by triggers + // we need to do this here to avoid countdown speedup by triggers it->hk_timer = std::max(0.0f, it->hk_timer - PHYSICS_DT); if (it->hk_lock_node && it->hk_locked == PRELOCK) { if (it->hk_beam->bm_disabled) { - //enable beam if not enabled yet between those 2 nodes - it->hk_beam->p2 = it->hk_lock_node; + // enable beam if not enabled yet between those 2 nodes + it->hk_beam->p2 = it->hk_lock_node; it->hk_beam->bm_inter_actor = it->hk_locked_actor != 0; - it->hk_beam->L = (it->hk_hook_node->AbsPosition - it->hk_lock_node->AbsPosition).length(); - it->hk_beam->bm_disabled = false; + it->hk_beam->L = (it->hk_hook_node->AbsPosition - it->hk_lock_node->AbsPosition).length(); + it->hk_beam->bm_disabled = false; AddInterActorBeam(it->hk_beam, this, it->hk_locked_actor); } else { if (it->hk_beam->L < it->hk_min_length) { - //shortlimit reached -> status LOCKED + // shortlimit reached -> status LOCKED it->hk_locked = LOCKED; } else { - //shorten the connecting beam slowly to locking minrange + // shorten the connecting beam slowly to locking minrange if (it->hk_beam->L > it->hk_lockspeed && fabs(it->hk_beam->stress) < it->hk_maxforce) - { - it->hk_beam->L = (it->hk_beam->L - it->hk_lockspeed); - } + { it->hk_beam->L = (it->hk_beam->L - it->hk_lockspeed); } else { if (fabs(it->hk_beam->stress) < it->hk_maxforce) { it->hk_beam->L = 0.001f; - //locking minrange or stress exeeded -> status LOCKED + // locking minrange or stress exeeded -> status LOCKED it->hk_locked = LOCKED; } else { if (it->hk_nodisable) { - //force exceed, but beam is set to nodisable, just lock it in this position + // force exceed, but beam is set to nodisable, just lock it in this position it->hk_locked = LOCKED; } else { - //force exceeded reset the hook node - it->hk_locked = UNLOCKED; - it->hk_lock_node = 0; - it->hk_locked_actor = 0; - it->hk_beam->p2 = &ar_nodes[0]; + // force exceeded reset the hook node + it->hk_locked = UNLOCKED; + it->hk_lock_node = 0; + it->hk_locked_actor = 0; + it->hk_beam->p2 = &ar_nodes[0]; it->hk_beam->bm_inter_actor = false; - it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length(); - it->hk_beam->bm_disabled = true; + it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length(); + it->hk_beam->bm_disabled = true; RemoveInterActorBeam(it->hk_beam); } } @@ -1709,12 +1640,12 @@ void Actor::CalcRopes() { if (r.rp_locked == LOCKED && r.rp_locked_ropable) { - auto locked_node = r.rp_locked_ropable->node; + auto locked_node = r.rp_locked_ropable->node; r.rp_beam->p2->AbsPosition = locked_node->AbsPosition; r.rp_beam->p2->RelPosition = locked_node->AbsPosition - ar_origin; r.rp_beam->p2->Velocity = locked_node->Velocity; - locked_node->Forces += r.rp_beam->p2->Forces; - r.rp_beam->p2->Forces = Vector3::ZERO; + locked_node->Forces += r.rp_beam->p2->Forces; + r.rp_beam->p2->Forces = Vector3::ZERO; } } } diff --git a/source/main/physics/BeamSlideNode.cpp b/source/main/physics/BeamSlideNode.cpp index cbc278813c..1ad9d92a72 100644 --- a/source/main/physics/BeamSlideNode.cpp +++ b/source/main/physics/BeamSlideNode.cpp @@ -23,10 +23,9 @@ /// @author Christopher Ritchey /// @date 10/30/2009 -#include "SlideNode.h" - #include "Beam.h" #include "RoRFrameListener.h" +#include "SlideNode.h" // ug... BAD PERFORMNCE, BAD!! void Actor::ToggleSlideNodeLock() @@ -34,15 +33,12 @@ void Actor::ToggleSlideNodeLock() // for every slide node on this truck for (std::vector::iterator itNode = m_slidenodes.begin(); itNode != m_slidenodes.end(); itNode++) { - std::pair closest((RailGroup*)NULL, std::numeric_limits::infinity()); - std::pair current((RailGroup*)NULL, std::numeric_limits::infinity()); + std::pair closest((RailGroup *)NULL, std::numeric_limits::infinity()); + std::pair current((RailGroup *)NULL, std::numeric_limits::infinity()); // if neither foreign, nor self attach is set then we cannot change the // Rail attachments - if (!itNode->sn_attach_self && !itNode->sn_attach_foreign) - { - continue; - } + if (!itNode->sn_attach_self && !itNode->sn_attach_foreign) { continue; } if (m_slidenodes_locked) { @@ -54,12 +50,10 @@ void Actor::ToggleSlideNodeLock() for (auto actor : RoR::App::GetSimController()->GetActors()) { // make sure this truck is allowed - if ((this != actor && !itNode->sn_attach_foreign) || (this == actor && !itNode->sn_attach_self)) - continue; + if ((this != actor && !itNode->sn_attach_foreign) || (this == actor && !itNode->sn_attach_self)) continue; current = GetClosestRailOnActor(actor, (*itNode)); - if (current.second < closest.second) - closest = current; + if (current.second < closest.second) closest = current; } // this many itNode->AttachToRail(closest.first); @@ -68,27 +62,25 @@ void Actor::ToggleSlideNodeLock() m_slidenodes_locked = !m_slidenodes_locked; } // is ugly.... -std::pair Actor::GetClosestRailOnActor(Actor* actor, const SlideNode& node) +std::pair Actor::GetClosestRailOnActor(Actor *actor, const SlideNode &node) { - std::pair closest((RailGroup*)NULL, std::numeric_limits::infinity()); + std::pair closest((RailGroup *)NULL, std::numeric_limits::infinity()); - RailSegment* curRail = NULL; - Ogre::Real lenToCurRail = std::numeric_limits::infinity(); + RailSegment *curRail = NULL; + Ogre::Real lenToCurRail = std::numeric_limits::infinity(); - for (std::vector::iterator itGroup = actor->m_railgroups.begin(); - itGroup != actor->m_railgroups.end(); + for (std::vector::iterator itGroup = actor->m_railgroups.begin(); itGroup != actor->m_railgroups.end(); itGroup++) { // find the rail closest to the Node - if (*itGroup == nullptr) - continue; + if (*itGroup == nullptr) continue; - curRail = (*itGroup)->FindClosestSegment(node.GetSlideNodePosition()); + curRail = (*itGroup)->FindClosestSegment(node.GetSlideNodePosition()); lenToCurRail = node.getLenTo(curRail); if (lenToCurRail < node.GetAttachmentDistance() && lenToCurRail < closest.second) { - closest.first = (*itGroup); + closest.first = (*itGroup); closest.second = lenToCurRail; } } @@ -109,8 +101,7 @@ void Actor::UpdateSlideNodeForces(const Ogre::Real dt) void Actor::resetSlideNodePositions() { - if (m_slidenodes.empty()) - return; + if (m_slidenodes.empty()) return; for (std::vector::iterator it = m_slidenodes.begin(); it != m_slidenodes.end(); ++it) { it->ResetPositions(); diff --git a/source/main/physics/CmdKeyInertia.cpp b/source/main/physics/CmdKeyInertia.cpp index d960725832..e0e9da3e73 100644 --- a/source/main/physics/CmdKeyInertia.cpp +++ b/source/main/physics/CmdKeyInertia.cpp @@ -29,62 +29,51 @@ #include RoR::CmdKeyInertia::CmdKeyInertia() - : m_start_spline(nullptr) - , m_stop_spline(nullptr) - , m_start_delay(0.f) - , m_stop_delay(0.f) - , m_last_output(0.f) - , m_time(0.f) -{} + : m_start_spline(nullptr), m_stop_spline(nullptr), m_start_delay(0.f), m_stop_delay(0.f), m_last_output(0.f), m_time(0.f) +{ +} float RoR::CmdKeyInertia::CalcCmdKeyDelay(float cmd_input, float dt) { - if (!m_start_spline || !m_stop_spline) - { - return cmd_input; - } + if (!m_start_spline || !m_stop_spline) { return cmd_input; } float calculated_output = m_last_output; - float last_output = m_last_output; + float last_output = m_last_output; // rel difference to calculate if we have to use start values(accelerating) or stop values float rel_diff = fabs(cmd_input) - fabs(last_output); // difference to calculate if were are on the negative side float abs_diff = cmd_input - last_output; // if the value is close to our input, reset the timer - if (fabs(abs_diff) < 0.002) - m_time = 0; + if (fabs(abs_diff) < 0.002) m_time = 0; // +dt after the timer had been set to zero prevents the motion to stop at 0.002 m_time += dt; const float start_factor = m_start_delay * m_time; - const float stop_factor = m_stop_delay * m_time; + const float stop_factor = m_stop_delay * m_time; // positive values between 0 and 1 if (abs_diff > 0) { // we have to accelerate our last outout to the new commanded input - if (rel_diff > 0) - calculated_output = last_output + this->CalculateCmdOutput(start_factor, m_start_spline); + if (rel_diff > 0) calculated_output = last_output + this->CalculateCmdOutput(start_factor, m_start_spline); if (rel_diff < 0) - // we have to deccelerate our last outout to the new commanded input + // we have to deccelerate our last outout to the new commanded input calculated_output = last_output + this->CalculateCmdOutput(stop_factor, m_stop_spline); if (calculated_output > cmd_input) - // if the calculated value is bigger than input set to input to avoid overshooting + // if the calculated value is bigger than input set to input to avoid overshooting calculated_output = cmd_input; } // negative values, mainly needed for hydros, between 0 and -1 if (abs_diff < 0) { - if (rel_diff > 0) - calculated_output = last_output - this->CalculateCmdOutput(start_factor, m_start_spline); - if (rel_diff < 0) - calculated_output = last_output - this->CalculateCmdOutput(stop_factor, m_stop_spline); - if (calculated_output < cmd_input) - calculated_output = cmd_input; + if (rel_diff > 0) calculated_output = last_output - this->CalculateCmdOutput(start_factor, m_start_spline); + if (rel_diff < 0) calculated_output = last_output - this->CalculateCmdOutput(stop_factor, m_stop_spline); + if (calculated_output < cmd_input) calculated_output = cmd_input; } m_last_output = calculated_output; return calculated_output; } -int RoR::CmdKeyInertia::SetCmdKeyDelay(RoR::CmdKeyInertiaConfig& cfg, float start_delay, float stop_delay, std::string start_function, std::string stop_function) +int RoR::CmdKeyInertia::SetCmdKeyDelay(RoR::CmdKeyInertiaConfig &cfg, float start_delay, float stop_delay, + std::string start_function, std::string stop_function) { // Delay values should always be greater than 0 if (start_delay > 0) @@ -98,13 +87,13 @@ int RoR::CmdKeyInertia::SetCmdKeyDelay(RoR::CmdKeyInertiaConfig& cfg, float star RoR::LogFormat("[RoR|Inertia] Warning: Stop Delay '%f', should be >0, using 0", start_delay); // if we don't find the spline, we use the "constant" one - Ogre::SimpleSpline* start_spline = cfg.GetSplineByName(start_function); + Ogre::SimpleSpline *start_spline = cfg.GetSplineByName(start_function); if (start_spline != nullptr) m_start_spline = start_spline; else RoR::LogFormat("[RoR|Inertia] Start Function '%s' not found", start_function.c_str()); - Ogre::SimpleSpline* stop_spline = cfg.GetSplineByName(stop_function); + Ogre::SimpleSpline *stop_spline = cfg.GetSplineByName(stop_function); if (stop_spline != nullptr) m_stop_spline = stop_spline; else @@ -113,7 +102,7 @@ int RoR::CmdKeyInertia::SetCmdKeyDelay(RoR::CmdKeyInertiaConfig& cfg, float star return 0; } -float RoR::CmdKeyInertia::CalculateCmdOutput(float time, Ogre::SimpleSpline* spline) +float RoR::CmdKeyInertia::CalculateCmdOutput(float time, Ogre::SimpleSpline *spline) { time = std::min(time, 1.0f); @@ -126,7 +115,7 @@ float RoR::CmdKeyInertia::CalculateCmdOutput(float time, Ogre::SimpleSpline* spl return 0; } -Ogre::SimpleSpline* RoR::CmdKeyInertiaConfig::GetSplineByName(Ogre::String model) +Ogre::SimpleSpline *RoR::CmdKeyInertiaConfig::GetSplineByName(Ogre::String model) { auto itor = m_splines.find(model); if (itor != m_splines.end()) @@ -139,28 +128,22 @@ void RoR::CmdKeyInertiaConfig::LoadDefaultInertiaModels() { try { - Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton().openResource("inertia_models.cfg", Ogre::RGN_AUTODETECT); + Ogre::DataStreamPtr ds = + Ogre::ResourceGroupManager::getSingleton().openResource("inertia_models.cfg", Ogre::RGN_AUTODETECT); std::string current_model; while (!ds->eof()) { std::string line = RoR::Utils::SanitizeUtf8String(ds->getLine()); Ogre::StringUtil::trim(line); - if (line.empty() || line[0] == ';') - continue; + if (line.empty() || line[0] == ';') continue; Ogre::StringVector args = Ogre::StringUtil::split(line, ","); - if (args.size() == 1) - { - current_model = line; - } + if (args.size() == 1) { current_model = line; } else if (args.size() == 2 && !current_model.empty()) { // find the spline to attach the points - if (m_splines.find(current_model) == m_splines.end()) - { - m_splines[current_model] = Ogre::SimpleSpline(); - } + if (m_splines.find(current_model) == m_splines.end()) { m_splines[current_model] = Ogre::SimpleSpline(); } // parse the data const float point_x = Ogre::StringConverter::parseReal(args[0]); @@ -171,7 +154,7 @@ void RoR::CmdKeyInertiaConfig::LoadDefaultInertiaModels() } } } - catch (std::exception& e) + catch (std::exception &e) { RoR::LogFormat("[RoR|Inertia] Failed to load 'inertia_models.cfg', message: '%s'", e.what()); } @@ -181,5 +164,5 @@ void RoR::CmdKeyInertia::ResetCmdKeyDelay() { // reset last_output and time, if we reset the truck m_last_output = 0.0; - m_time = 0.0; + m_time = 0.0; } diff --git a/source/main/physics/CmdKeyInertia.h b/source/main/physics/CmdKeyInertia.h index ce5e7ebdc4..d7fa8e08c7 100644 --- a/source/main/physics/CmdKeyInertia.h +++ b/source/main/physics/CmdKeyInertia.h @@ -23,37 +23,39 @@ #include #include -namespace RoR { - -/// Loads and manages 'inertia_models.cfg' -class CmdKeyInertiaConfig +namespace RoR { -public: - void LoadDefaultInertiaModels(); - Ogre::SimpleSpline* GetSplineByName(Ogre::String model); - -private: - std::map m_splines; -}; -class CmdKeyInertia -{ -public: - CmdKeyInertia(); - - float CalcCmdKeyDelay(float cmd_input, float dt); - int SetCmdKeyDelay(RoR::CmdKeyInertiaConfig& cfg, float start_delay, float stop_delay, std::string start_function, std::string stop_function); - void ResetCmdKeyDelay(); - -protected: - float m_last_output; - float m_start_delay; - float m_stop_delay; - float m_time; - Ogre::SimpleSpline* m_start_spline; - Ogre::SimpleSpline* m_stop_spline; - - float CalculateCmdOutput(float time, Ogre::SimpleSpline* spline); -}; + /// Loads and manages 'inertia_models.cfg' + class CmdKeyInertiaConfig + { + public: + void LoadDefaultInertiaModels(); + Ogre::SimpleSpline *GetSplineByName(Ogre::String model); + + private: + std::map m_splines; + }; + + class CmdKeyInertia + { + public: + CmdKeyInertia(); + + float CalcCmdKeyDelay(float cmd_input, float dt); + int SetCmdKeyDelay(RoR::CmdKeyInertiaConfig &cfg, float start_delay, float stop_delay, std::string start_function, + std::string stop_function); + void ResetCmdKeyDelay(); + + protected: + float m_last_output; + float m_start_delay; + float m_stop_delay; + float m_time; + Ogre::SimpleSpline *m_start_spline; + Ogre::SimpleSpline *m_stop_spline; + + float CalculateCmdOutput(float time, Ogre::SimpleSpline *spline); + }; } // namespace RoR diff --git a/source/main/physics/Differentials.cpp b/source/main/physics/Differentials.cpp index 439080f2d7..1a122d8a70 100644 --- a/source/main/physics/Differentials.cpp +++ b/source/main/physics/Differentials.cpp @@ -18,53 +18,50 @@ along with Rigs of Rods. If not, see . */ -#include "Application.h" #include "Differentials.h" + +#include "Application.h" #include "Language.h" void Differential::ToggleDifferentialMode() { if (m_available_diffs.size() > 1) - { - std::rotate(m_available_diffs.begin(), m_available_diffs.begin() + 1, m_available_diffs.end()); - } + { std::rotate(m_available_diffs.begin(), m_available_diffs.begin() + 1, m_available_diffs.end()); } } -void Differential::CalcAxleTorque(DifferentialData& diff_data) +void Differential::CalcAxleTorque(DifferentialData &diff_data) { - if (m_available_diffs.empty()) - return; + if (m_available_diffs.empty()) return; switch (m_available_diffs[0]) { - case SPLIT_DIFF: this->CalcSeparateDiff(diff_data); return; - case OPEN_DIFF: this->CalcOpenDiff(diff_data); return; - case VISCOUS_DIFF: this->CalcViscousDiff(diff_data); return; - case LOCKED_DIFF: this->CalcLockedDiff(diff_data); return; + case SPLIT_DIFF: this->CalcSeparateDiff(diff_data); return; + case OPEN_DIFF: this->CalcOpenDiff(diff_data); return; + case VISCOUS_DIFF: this->CalcViscousDiff(diff_data); return; + case LOCKED_DIFF: this->CalcLockedDiff(diff_data); return; } } Ogre::UTFString Differential::GetDifferentialTypeName() { - if (m_available_diffs.empty()) - return _L("invalid"); + if (m_available_diffs.empty()) return _L("invalid"); switch (m_available_diffs[0]) { - case SPLIT_DIFF: return _L("Split"); - case OPEN_DIFF: return _L("Open"); + case SPLIT_DIFF: return _L("Split"); + case OPEN_DIFF: return _L("Open"); case VISCOUS_DIFF: return _L("Viscous"); - case LOCKED_DIFF: return _L("Locked"); - default: return _L("invalid"); + case LOCKED_DIFF: return _L("Locked"); + default: return _L("invalid"); } } -void Differential::CalcSeparateDiff(DifferentialData& diff_data) +void Differential::CalcSeparateDiff(DifferentialData &diff_data) { diff_data.out_torque[0] = diff_data.out_torque[1] = diff_data.in_torque / 2.0f; } -void Differential::CalcOpenDiff(DifferentialData& diff_data) +void Differential::CalcOpenDiff(DifferentialData &diff_data) { /* Open differential calculations ************************* * These calculation are surprisingly tricky @@ -85,15 +82,15 @@ void Differential::CalcOpenDiff(DifferentialData& diff_data) const Ogre::Real power_ratio = min_of_vel > 1.0f ? fabs(diff_data.speed[0]) / sum_of_vel : 0.5f; // Diff model taken from Torcs, ror needs to model reaction torque for this to work. - //DrTq0 = DrTq*0.5f + spiderTq; - //DrTq1 = DrTq*0.5f - spiderTq; + // DrTq0 = DrTq*0.5f + spiderTq; + // DrTq1 = DrTq*0.5f - spiderTq; // get the final ratio based on the speed of the wheels diff_data.out_torque[0] *= Ogre::Math::Clamp(0.0f + power_ratio, 0.1f, 0.9f); diff_data.out_torque[1] *= Ogre::Math::Clamp(1.0f - power_ratio, 0.1f, 0.9f); } -void Differential::CalcViscousDiff(DifferentialData& diff_data) +void Differential::CalcViscousDiff(DifferentialData &diff_data) { /* Viscous axle calculation ******************************** * Two wheels are joined together by a rotary viscous coupling. @@ -102,7 +99,7 @@ void Differential::CalcViscousDiff(DifferentialData& diff_data) */ const Ogre::Real m_torsion_damp = 10000.0f; - const Ogre::Real delta_speed = diff_data.speed[0] - diff_data.speed[1]; + const Ogre::Real delta_speed = diff_data.speed[0] - diff_data.speed[1]; diff_data.out_torque[0] = diff_data.out_torque[1] = diff_data.in_torque / 2.0f; @@ -113,7 +110,7 @@ void Differential::CalcViscousDiff(DifferentialData& diff_data) diff_data.out_torque[1] += delta_speed * m_torsion_damp; } -void Differential::CalcLockedDiff(DifferentialData& diff_data) +void Differential::CalcLockedDiff(DifferentialData &diff_data) { /* Locked axle calculation ******************************** * This is straight forward, two wheels are joined together @@ -126,7 +123,7 @@ void Differential::CalcLockedDiff(DifferentialData& diff_data) // keep as variable for now since this value will be user configurable const Ogre::Real m_torsion_rate = 1000000.0f; const Ogre::Real m_torsion_damp = m_torsion_rate / 100.0f; - const Ogre::Real delta_speed = diff_data.speed[0] - diff_data.speed[1]; + const Ogre::Real delta_speed = diff_data.speed[0] - diff_data.speed[1]; diff_data.out_torque[0] = diff_data.out_torque[1] = diff_data.in_torque / 2.0f; diff --git a/source/main/physics/Differentials.h b/source/main/physics/Differentials.h index 0a6ede2e61..5860f7b94e 100644 --- a/source/main/physics/Differentials.h +++ b/source/main/physics/Differentials.h @@ -33,16 +33,16 @@ struct DifferentialData class TransferCase { -public: - TransferCase(int a1, int a2, bool has_2wd, bool has_2wd_lo, std::vector grs): - tr_ax_1(a1), tr_ax_2(a2), tr_2wd(has_2wd), tr_2wd_lo(has_2wd_lo), tr_4wd_mode(false), tr_gear_ratios(grs) {}; + public: + TransferCase(int a1, int a2, bool has_2wd, bool has_2wd_lo, std::vector grs) + : tr_ax_1(a1), tr_ax_2(a2), tr_2wd(has_2wd), tr_2wd_lo(has_2wd_lo), tr_4wd_mode(false), tr_gear_ratios(grs){}; - int tr_ax_1; //!< This axle is always driven - int tr_ax_2; //!< This axle is only driven in 4WD mode - bool tr_2wd; //!< Does it support 2WD mode? - bool tr_2wd_lo; //!< Does it support 2WD Lo mode? - bool tr_4wd_mode; //!< Enables 4WD mode - std::vector tr_gear_ratios; //!< Gear reduction ratios + int tr_ax_1; //!< This axle is always driven + int tr_ax_2; //!< This axle is only driven in 4WD mode + bool tr_2wd; //!< Does it support 2WD mode? + bool tr_2wd_lo; //!< Does it support 2WD Lo mode? + bool tr_4wd_mode; //!< Enables 4WD mode + std::vector tr_gear_ratios; //!< Gear reduction ratios }; enum DiffType @@ -56,26 +56,35 @@ enum DiffType class Differential { -public: - Differential(): di_idx_1(0), di_idx_2(0), di_delta_rotation(0.0f) {}; + public: + Differential() : di_idx_1(0), di_idx_2(0), di_delta_rotation(0.0f){}; - int di_idx_1; //!< array location of wheel / axle 1 - int di_idx_2; //!< array location of wheel / axle 2 - float di_delta_rotation; //!< difference of rotational position between two wheels/axles... a kludge at best + int di_idx_1; //!< array location of wheel / axle 1 + int di_idx_2; //!< array location of wheel / axle 2 + float di_delta_rotation; //!< difference of rotational position between two wheels/axles... a kludge at best - void AddDifferentialType(DiffType diff) { m_available_diffs.push_back(diff); } - void ToggleDifferentialMode(); - void CalcAxleTorque(DifferentialData& diff_data); - Ogre::UTFString GetDifferentialTypeName(); - DiffType GetActiveDiffType() const { return m_available_diffs[0]; } - int GetNumDiffTypes() { return static_cast(m_available_diffs.size()); } - - static void CalcSeparateDiff(DifferentialData& diff_data); //!< a differential that always splits the torque evenly, this is the original method - static void CalcOpenDiff(DifferentialData& diff_data ); //!< more power goes to the faster spining wheel - static void CalcViscousDiff(DifferentialData& diff_data ); //!< more power goes to the slower spining wheel - static void CalcLockedDiff(DifferentialData& diff_data ); //!< ensures both wheels rotate at the the same speed + void AddDifferentialType(DiffType diff) + { + m_available_diffs.push_back(diff); + } + void ToggleDifferentialMode(); + void CalcAxleTorque(DifferentialData &diff_data); + Ogre::UTFString GetDifferentialTypeName(); + DiffType GetActiveDiffType() const + { + return m_available_diffs[0]; + } + int GetNumDiffTypes() + { + return static_cast(m_available_diffs.size()); + } -private: + static void CalcSeparateDiff( + DifferentialData &diff_data); //!< a differential that always splits the torque evenly, this is the original method + static void CalcOpenDiff(DifferentialData &diff_data); //!< more power goes to the faster spining wheel + static void CalcViscousDiff(DifferentialData &diff_data); //!< more power goes to the slower spining wheel + static void CalcLockedDiff(DifferentialData &diff_data); //!< ensures both wheels rotate at the the same speed + + private: std::vector m_available_diffs; }; - diff --git a/source/main/physics/RigSpawner.cpp b/source/main/physics/RigSpawner.cpp index 18ea37ee08..a44de71749 100644 --- a/source/main/physics/RigSpawner.cpp +++ b/source/main/physics/RigSpawner.cpp @@ -19,14 +19,11 @@ along with Rigs of Rods. If not, see . */ - /// @file /// @brief Vehicle spawning logic. /// @author Petr Ohlidal /// @date 12/2013 - -#include "RoRPrerequisites.h" #include "RigSpawner.h" #include "AirBrake.h" @@ -56,6 +53,7 @@ #include "PointColDetector.h" #include "Renderdash.h" #include "RoRFrameListener.h" +#include "RoRPrerequisites.h" #include "ScrewProp.h" #include "Skidmark.h" #include "SkinManager.h" @@ -67,14 +65,14 @@ #include "Utils.h" #include "VehicleAI.h" +#include #include -#include #include #include -#include +#include #include -const char* ACTOR_ID_TOKEN = "@Actor_"; // Appended to material name, followed by actor ID (aka 'trucknum') +const char *ACTOR_ID_TOKEN = "@Actor_"; // Appended to material name, followed by actor ID (aka 'trucknum') using namespace RoR; @@ -82,26 +80,22 @@ using namespace RoR; /* Prepare for loading /* -------------------------------------------------------------------------- */ -void ActorSpawner::Setup( - Actor *rig, - std::shared_ptr file, - Ogre::SceneNode *parent, - Ogre::Vector3 const & spawn_position -) +void ActorSpawner::Setup(Actor *rig, std::shared_ptr file, Ogre::SceneNode *parent, + Ogre::Vector3 const &spawn_position) { - m_actor = rig; - m_file = file; + m_actor = rig; + m_file = file; m_particles_parent_scenenode = parent; - m_spawn_position = spawn_position; - m_current_keyword = RigDef::File::KEYWORD_INVALID; - m_wing_area = 0.f; - m_fuse_z_min = 1000.0f; - m_fuse_z_max = -1000.0f; - m_fuse_y_min = 1000.0f; - m_fuse_y_max = -1000.0f; - m_first_wing_index = -1; - m_driverseat_prop_index = -1; - m_oldstyle_renderdash = nullptr; + m_spawn_position = spawn_position; + m_current_keyword = RigDef::File::KEYWORD_INVALID; + m_wing_area = 0.f; + m_fuse_z_min = 1000.0f; + m_fuse_z_max = -1000.0f; + m_fuse_y_min = 1000.0f; + m_fuse_y_max = -1000.0f; + m_first_wing_index = -1; + m_driverseat_prop_index = -1; + m_oldstyle_renderdash = nullptr; m_generate_wing_position_lights = true; // TODO: Handle modules @@ -110,23 +104,20 @@ void ActorSpawner::Setup( m_generate_wing_position_lights = false; // Disable aerial pos. lights for land vehicles. } - m_messages_num_errors = 0; + m_messages_num_errors = 0; m_messages_num_warnings = 0; - m_messages_num_other = 0; + m_messages_num_other = 0; App::GetCacheSystem()->CheckResourceLoaded(m_actor->ar_filename, m_custom_resource_group); } -void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef::File::Module* module_def) +void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements &req, RigDef::File::Module *module_def) { // 'nodes' req.num_nodes += module_def->nodes.size(); - for (auto& def: module_def->nodes) + for (auto &def : module_def->nodes) { - if (BITMASK_IS_1(def.options, RigDef::Node::OPTION_h_HOOK_POINT)) - { - req.num_beams += 1; - } + if (BITMASK_IS_1(def.options, RigDef::Node::OPTION_h_HOOK_POINT)) { req.num_beams += 1; } } // 'beams' @@ -142,7 +133,7 @@ void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef:: req.num_beams += module_def->hydros.size(); // 'triggers' - req.num_beams += module_def->triggers.size(); + req.num_beams += module_def->triggers.size(); req.num_shocks += module_def->triggers.size(); // 'animators' @@ -153,11 +144,11 @@ void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef:: req.num_beams += module_def->cinecam.size() * 8; // 'shocks' and 'shocks2' - req.num_beams += module_def->shocks.size(); + req.num_beams += module_def->shocks.size(); req.num_shocks += module_def->shocks.size(); - req.num_beams += module_def->shocks_2.size(); + req.num_beams += module_def->shocks_2.size(); req.num_shocks += module_def->shocks_2.size(); - req.num_beams += module_def->shocks_3.size(); + req.num_beams += module_def->shocks_3.size(); req.num_shocks += module_def->shocks_3.size(); // 'commands' and 'commands2' (unified) @@ -171,14 +162,14 @@ void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef:: req.num_wings += module_def->wings.size(); // 'wheels' - for (RigDef::Wheel& wheel: module_def->wheels) + for (RigDef::Wheel &wheel : module_def->wheels) { - req.num_nodes += wheel.num_rays * 2; // BuildWheelObjectAndNodes() + req.num_nodes += wheel.num_rays * 2; // BuildWheelObjectAndNodes() req.num_beams += wheel.num_rays * ((wheel.rigidity_node.IsValidAnyState()) ? 9 : 8); // BuildWheelBeams() } // 'wheels2' - for (RigDef::Wheel2& wheel2: module_def->wheels_2) + for (RigDef::Wheel2 &wheel2 : module_def->wheels_2) { req.num_nodes += wheel2.num_rays * 4; // Rim beams: num_rays*10 (*11 with valid rigidity_node) @@ -187,14 +178,14 @@ void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef:: } // 'meshwheels' & 'meshwheels2' (unified) - for (RigDef::MeshWheel& meshwheel: module_def->mesh_wheels) + for (RigDef::MeshWheel &meshwheel : module_def->mesh_wheels) { - req.num_nodes += meshwheel.num_rays * 2; // BuildWheelObjectAndNodes() + req.num_nodes += meshwheel.num_rays * 2; // BuildWheelObjectAndNodes() req.num_beams += meshwheel.num_rays * ((meshwheel.rigidity_node.IsValidAnyState()) ? 9 : 8); // BuildWheelBeams() } // 'flexbodywheels' - for (RigDef::FlexBodyWheel& flexwheel: module_def->flex_body_wheels) + for (RigDef::FlexBodyWheel &flexwheel : module_def->flex_body_wheels) { req.num_nodes += flexwheel.num_rays * 4; // Rim beams: num_rays*8 @@ -212,8 +203,8 @@ void ActorSpawner::CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef:: void ActorSpawner::InitializeRig() { - ActorMemoryRequirements & req = m_memory_requirements; - for (auto module: m_selected_modules) // _Root_ module is included + ActorMemoryRequirements &req = m_memory_requirements; + for (auto module : m_selected_modules) // _Root_ module is included { this->CalcMemoryRequirements(req, module.get()); } @@ -222,26 +213,23 @@ void ActorSpawner::InitializeRig() m_actor->ar_beams = new beam_t[req.num_beams]; m_actor->ar_nodes = new node_t[req.num_nodes]; - if (req.num_shocks > 0) - m_actor->ar_shocks = new shock_t[req.num_shocks]; + if (req.num_shocks > 0) m_actor->ar_shocks = new shock_t[req.num_shocks]; - if (req.num_rotators > 0) - m_actor->ar_rotators = new rotator_t[req.num_rotators]; + if (req.num_rotators > 0) m_actor->ar_rotators = new rotator_t[req.num_rotators]; - if (req.num_wings > 0) - m_actor->ar_wings = new wing_t[req.num_wings]; + if (req.num_wings > 0) m_actor->ar_wings = new wing_t[req.num_wings]; m_actor->ar_minimass.resize(req.num_nodes); // TODO: Perform these inits in constructor instead! ~ only_a_ptr, 01/2018 // commands contain complex data structures, do not memset them ... - for (int i=0;iar_command_key[i].commandValue=0; + m_actor->ar_command_key[i].commandValue = 0; m_actor->ar_command_key[i].beams.clear(); m_actor->ar_command_key[i].rotators.clear(); - m_actor->ar_command_key[i].description=""; + m_actor->ar_command_key[i].description = ""; } m_actor->exhausts.clear(); @@ -256,70 +244,70 @@ void ActorSpawner::InitializeRig() memset(m_actor->ar_buoycabs, 0, sizeof(int) * MAX_CABS); m_actor->ar_num_buoycabs = 0; memset(m_actor->ar_buoycab_types, 0, sizeof(int) * MAX_CABS); - memset(m_actor->m_skid_trails, 0, sizeof(Skidmark *) * (MAX_WHEELS*2)); + memset(m_actor->m_skid_trails, 0, sizeof(Skidmark *) * (MAX_WHEELS * 2)); m_actor->description.clear(); - m_actor->ar_extern_camera_mode=0; - m_actor->ar_extern_camera_node=-1; + m_actor->ar_extern_camera_mode = 0; + m_actor->ar_extern_camera_node = -1; m_actor->authors.clear(); m_actor->m_odometer_total = 0; m_actor->m_odometer_user = 0; - m_actor->m_masscount=0; - m_actor->m_disable_smoke = App::gfx_particles_mode.GetActive() == 0; - m_actor->ar_exhaust_pos_node=0; - m_actor->ar_exhaust_dir_node=0; + m_actor->m_masscount = 0; + m_actor->m_disable_smoke = App::gfx_particles_mode.GetActive() == 0; + m_actor->ar_exhaust_pos_node = 0; + m_actor->ar_exhaust_dir_node = 0; m_actor->m_beam_break_debug_enabled = App::diag_log_beam_break.GetActive(); m_actor->m_beam_deform_debug_enabled = App::diag_log_beam_deform.GetActive(); - m_actor->m_trigger_debug_enabled = App::diag_log_beam_trigger.GetActive(); - m_actor->ar_origin=Ogre::Vector3::ZERO; + m_actor->m_trigger_debug_enabled = App::diag_log_beam_trigger.GetActive(); + m_actor->ar_origin = Ogre::Vector3::ZERO; m_actor->m_slidenodes.clear(); - m_actor->ar_cinecam_node[0]=-1; - m_actor->ar_num_cinecams=0; + m_actor->ar_cinecam_node[0] = -1; + m_actor->ar_num_cinecams = 0; m_actor->m_deletion_scene_nodes.clear(); - m_actor->m_net_custom_lights[0] = UINT_MAX; - m_actor->m_net_custom_lights[1] = UINT_MAX; - m_actor->m_net_custom_lights[2] = UINT_MAX; - m_actor->m_net_custom_lights[3] = UINT_MAX; + m_actor->m_net_custom_lights[0] = UINT_MAX; + m_actor->m_net_custom_lights[1] = UINT_MAX; + m_actor->m_net_custom_lights[2] = UINT_MAX; + m_actor->m_net_custom_lights[3] = UINT_MAX; m_actor->m_net_custom_light_count = 0; - m_actor->ar_sim_state = Actor::SimState::LOCAL_SLEEPING; + m_actor->ar_sim_state = Actor::SimState::LOCAL_SLEEPING; m_actor->m_fusealge_airfoil = nullptr; - m_actor->m_fusealge_front = nullptr; - m_actor->m_fusealge_back = nullptr; - m_actor->m_fusealge_width=0; - m_actor->ar_brake_force=30000.0; - m_actor->m_handbrake_force = 2 * m_actor->ar_brake_force; + m_actor->m_fusealge_front = nullptr; + m_actor->m_fusealge_back = nullptr; + m_actor->m_fusealge_width = 0; + m_actor->ar_brake_force = 30000.0; + m_actor->m_handbrake_force = 2 * m_actor->ar_brake_force; - m_actor->m_num_proped_wheels=0; + m_actor->m_num_proped_wheels = 0; - m_actor->ar_speedo_max_kph=140; - m_actor->ar_num_cameras=0; - m_actor->ar_camera_node_pos[0]=-1; - m_actor->ar_camera_node_dir[0]=-1; - m_actor->ar_camera_node_roll[0]=-1; + m_actor->ar_speedo_max_kph = 140; + m_actor->ar_num_cameras = 0; + m_actor->ar_camera_node_pos[0] = -1; + m_actor->ar_camera_node_dir[0] = -1; + m_actor->ar_camera_node_roll[0] = -1; #ifdef USE_ANGELSCRIPT m_actor->ar_vehicle_ai = new VehicleAI(m_actor); #endif // USE_ANGELSCRIPT m_actor->ar_airbrake_intensity = 0; - m_actor->alb_minspeed = 0.0f; - m_actor->alb_mode = false; - m_actor->alb_nodash = true; - m_actor->alb_notoggle = false; - m_actor->alb_pulse_time = 2000.0f; - m_actor->alb_pulse_state = false; - m_actor->alb_ratio = 1.0f; - m_actor->alb_timer = 0.0f; - m_actor->ar_anim_shift_timer = 0.0f; - - m_actor->cc_mode = false; - m_actor->cc_can_brake = false; - m_actor->cc_target_rpm = 0.0f; - m_actor->cc_target_speed = 0.0f; + m_actor->alb_minspeed = 0.0f; + m_actor->alb_mode = false; + m_actor->alb_nodash = true; + m_actor->alb_notoggle = false; + m_actor->alb_pulse_time = 2000.0f; + m_actor->alb_pulse_state = false; + m_actor->alb_ratio = 1.0f; + m_actor->alb_timer = 0.0f; + m_actor->ar_anim_shift_timer = 0.0f; + + m_actor->cc_mode = false; + m_actor->cc_can_brake = false; + m_actor->cc_target_rpm = 0.0f; + m_actor->cc_target_speed = 0.0f; m_actor->cc_target_speed_lower_limit = 0.0f; m_actor->ar_collision_relevant = false; @@ -328,30 +316,24 @@ void ActorSpawner::InitializeRig() m_actor->ar_anim_previous_crank = 0.f; - m_actor->sl_enabled = false; + m_actor->sl_enabled = false; m_actor->sl_speed_limit = 0.f; - m_actor->tc_mode = false; - m_actor->tc_nodash = true; - m_actor->tc_notoggle = false; - m_actor->tc_pulse_time = 2000.0f; + m_actor->tc_mode = false; + m_actor->tc_nodash = true; + m_actor->tc_notoggle = false; + m_actor->tc_pulse_time = 2000.0f; m_actor->tc_pulse_state = false; - m_actor->tc_ratio = 1.f; - m_actor->tc_timer = 0.f; + m_actor->tc_ratio = 1.f; + m_actor->tc_timer = 0.f; m_actor->ar_dashboard = new DashBoardManager(); /* Collisions */ - if (!App::sim_no_collisions.GetActive()) - { - m_actor->m_inter_point_col_detector = new PointColDetector(m_actor); - } + if (!App::sim_no_collisions.GetActive()) { m_actor->m_inter_point_col_detector = new PointColDetector(m_actor); } - if (!App::sim_no_self_collisions.GetActive()) - { - m_actor->m_intra_point_col_detector = new PointColDetector(m_actor); - } + if (!App::sim_no_self_collisions.GetActive()) { m_actor->m_intra_point_col_detector = new PointColDetector(m_actor); } m_actor->ar_submesh_ground_model = gEnv->collisions->defaultgm; @@ -364,7 +346,8 @@ void ActorSpawner::InitializeRig() m_flex_factory.CheckAndLoadFlexbodyCache(); - m_placeholder_managedmat = Ogre::MaterialManager::getSingleton().getByName("rigsofrods/managedmaterial-placeholder"); // Built-in + m_placeholder_managedmat = + Ogre::MaterialManager::getSingleton().getByName("rigsofrods/managedmaterial-placeholder"); // Built-in m_apply_simple_materials = App::diag_simple_materials.GetActive(); if (m_apply_simple_materials) @@ -372,12 +355,13 @@ void ActorSpawner::InitializeRig() m_simple_material_base = Ogre::MaterialManager::getSingleton().getByName("tracks/simple"); // Built-in material if (m_simple_material_base.isNull()) { - this->AddMessage(Message::TYPE_INTERNAL_ERROR, "Failed to load built-in material 'tracks/simple'; disabling 'SimpleMaterials'"); + this->AddMessage(Message::TYPE_INTERNAL_ERROR, + "Failed to load built-in material 'tracks/simple'; disabling 'SimpleMaterials'"); m_apply_simple_materials = false; } } - m_curr_mirror_prop_type = CustomMaterial::MirrorPropType::MPROP_NONE; + m_curr_mirror_prop_type = CustomMaterial::MirrorPropType::MPROP_NONE; m_curr_mirror_prop_scenenode = nullptr; } @@ -386,48 +370,45 @@ void ActorSpawner::FinalizeRig() // we should post-process the torque curve if existing if (m_actor->ar_engine) { - int result = m_actor->ar_engine->getTorqueCurve()->spaceCurveEvenly(m_actor->ar_engine->getTorqueCurve()->getUsedSpline()); + int result = + m_actor->ar_engine->getTorqueCurve()->spaceCurveEvenly(m_actor->ar_engine->getTorqueCurve()->getUsedSpline()); if (result) { m_actor->ar_engine->getTorqueCurve()->setTorqueModel("default"); if (result == 1) - { - AddMessage(Message::TYPE_ERROR, "TorqueCurve: Points (rpm) must be in an ascending order. Using default curve"); - } + { AddMessage(Message::TYPE_ERROR, "TorqueCurve: Points (rpm) must be in an ascending order. Using default curve"); } } - //Gearbox + // Gearbox m_actor->ar_engine->SetAutoMode(App::sim_gearbox_mode.GetActive()); } - + // Sanitize trigger_cmdshort and trigger_cmdlong - for (int i=0; iar_num_beams; i++) + for (int i = 0; i < m_actor->ar_num_beams; i++) { - shock_t* shock = m_actor->ar_beams[i].shock; + shock_t *shock = m_actor->ar_beams[i].shock; if (shock && ((shock->flags & SHOCK_FLAG_TRG_BLOCKER) || (shock->flags & SHOCK_FLAG_TRG_BLOCKER_A))) { shock->trigger_cmdshort = std::min(shock->trigger_cmdshort, m_actor->ar_num_beams - i - 1); - shock->trigger_cmdlong = std::min(shock->trigger_cmdlong , m_actor->ar_num_beams - i - 1); + shock->trigger_cmdlong = std::min(shock->trigger_cmdlong, m_actor->ar_num_beams - i - 1); } } - //calculate gwps height offset - //get a starting value - m_actor->ar_posnode_spawn_height=m_actor->ar_nodes[0].RelPosition.y; - //start at 0 to avoid a crash whith a 1-node truck - for (int i=0; iar_num_nodes; i++) + // calculate gwps height offset + // get a starting value + m_actor->ar_posnode_spawn_height = m_actor->ar_nodes[0].RelPosition.y; + // start at 0 to avoid a crash whith a 1-node truck + for (int i = 0; i < m_actor->ar_num_nodes; i++) { // scan and store the y-coord for the lowest node of the truck if (m_actor->ar_nodes[i].RelPosition.y <= m_actor->ar_posnode_spawn_height) - { - m_actor->ar_posnode_spawn_height = m_actor->ar_nodes[i].RelPosition.y; - } + { m_actor->ar_posnode_spawn_height = m_actor->ar_nodes[i].RelPosition.y; } } m_actor->ar_main_camera_node_pos = std::max(0, m_actor->ar_camera_node_pos[0]); m_actor->ar_main_camera_node_dir = std::max(0, m_actor->ar_camera_node_dir[0]); m_actor->ar_main_camera_node_roll = std::max(0, m_actor->ar_camera_node_roll[0]); - + m_actor->m_has_axles_section = m_actor->m_num_wheel_diffs > 0; // Calculate mass of each wheel (without rim) @@ -445,10 +426,7 @@ void ActorSpawner::FinalizeRig() float proped_wheels_radius_sum = 0.0f; for (int i = 0; i < m_actor->ar_num_wheels; i++) { - if (m_actor->ar_wheels[i].wh_propulsed > 0) - { - proped_wheels_radius_sum += m_actor->ar_wheels[i].wh_radius; - } + if (m_actor->ar_wheels[i].wh_propulsed > 0) { proped_wheels_radius_sum += m_actor->ar_wheels[i].wh_radius; } } m_actor->m_avg_proped_wheel_radius = proped_wheels_radius_sum / m_actor->m_num_proped_wheels; } @@ -482,8 +460,7 @@ void ActorSpawner::FinalizeRig() { int a1 = std::min(m_actor->m_transfer_case->tr_ax_1, m_actor->m_transfer_case->tr_ax_2); int a2 = std::max(m_actor->m_transfer_case->tr_ax_1, m_actor->m_transfer_case->tr_ax_2); - if ((a1 == i - 1) && (a2 == i - 0)) - continue; + if ((a1 == i - 1) && (a2 == i - 0)) continue; } Differential *diff = new Differential(); @@ -505,8 +482,8 @@ void ActorSpawner::FinalizeRig() if (m_actor->m_transfer_case && m_actor->m_transfer_case->tr_ax_2 >= 0) { Differential *diff = new Differential(); - diff->di_idx_1 = m_actor->m_transfer_case->tr_ax_1; - diff->di_idx_2 = m_actor->m_transfer_case->tr_ax_2; + diff->di_idx_1 = m_actor->m_transfer_case->tr_ax_1; + diff->di_idx_2 = m_actor->m_transfer_case->tr_ax_2; diff->AddDifferentialType(LOCKED_DIFF); m_actor->m_axle_diffs[m_actor->m_num_axle_diffs] = diff; } @@ -515,68 +492,73 @@ void ActorSpawner::FinalizeRig() { Ogre::Vector3 ref = m_actor->ar_nodes[m_actor->ar_main_camera_node_pos].RelPosition; // Step 1: Find a suitable camera node dir - float max_dist = 0.0f; - int furthest_node = 0; + float max_dist = 0.0f; + int furthest_node = 0; for (int i = 0; i < m_actor->ar_num_nodes; i++) { float dist = m_actor->ar_nodes[i].RelPosition.squaredDistance(ref); if (dist > max_dist) { - max_dist = dist; + max_dist = dist; furthest_node = i; } } m_actor->ar_main_camera_node_dir = furthest_node; // Step 2: Correct the misalignment - Ogre::Vector3 dir = m_actor->ar_nodes[furthest_node].RelPosition - ref; - float offset = atan2(dir.dotProduct(Ogre::Vector3::UNIT_Z), dir.dotProduct(Ogre::Vector3::UNIT_X)); + Ogre::Vector3 dir = m_actor->ar_nodes[furthest_node].RelPosition - ref; + float offset = atan2(dir.dotProduct(Ogre::Vector3::UNIT_Z), dir.dotProduct(Ogre::Vector3::UNIT_X)); m_actor->ar_main_camera_dir_corr = Ogre::Quaternion(Ogre::Radian(offset), Ogre::Vector3::UNIT_Y); } if (m_actor->ar_camera_node_pos[0] > 0) { // store the y-difference between the trucks lowest node and the campos-node for the gwps system - m_actor->ar_posnode_spawn_height = m_actor->ar_nodes[m_actor->ar_camera_node_pos[0]].RelPosition.y - m_actor->ar_posnode_spawn_height; - } + m_actor->ar_posnode_spawn_height = + m_actor->ar_nodes[m_actor->ar_camera_node_pos[0]].RelPosition.y - m_actor->ar_posnode_spawn_height; + } else { - //this can not be an airplane, just set it to 0. + // this can not be an airplane, just set it to 0. m_actor->ar_posnode_spawn_height = 0.0f; } - //cameras workaround - for (int i=0; iar_num_cameras; i++) + // cameras workaround + for (int i = 0; i < m_actor->ar_num_cameras; i++) { - //LogManager::getSingleton().logMessage("Camera dir="+StringConverter::toString(ar_nodes[ar_camera_node_dir[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition)+" roll="+StringConverter::toString(ar_nodes[ar_camera_node_roll[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition)); - Ogre::Vector3 dir_node_offset = GetNode(m_actor->ar_camera_node_dir[i]).RelPosition - GetNode(m_actor->ar_camera_node_pos[i]).RelPosition; - Ogre::Vector3 roll_node_offset = GetNode(m_actor->ar_camera_node_roll[i]).RelPosition - GetNode(m_actor->ar_camera_node_pos[i]).RelPosition; + // LogManager::getSingleton().logMessage("Camera + // dir="+StringConverter::toString(ar_nodes[ar_camera_node_dir[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition)+" + // roll="+StringConverter::toString(ar_nodes[ar_camera_node_roll[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition)); + Ogre::Vector3 dir_node_offset = + GetNode(m_actor->ar_camera_node_dir[i]).RelPosition - GetNode(m_actor->ar_camera_node_pos[i]).RelPosition; + Ogre::Vector3 roll_node_offset = + GetNode(m_actor->ar_camera_node_roll[i]).RelPosition - GetNode(m_actor->ar_camera_node_pos[i]).RelPosition; Ogre::Vector3 cross = dir_node_offset.crossProduct(roll_node_offset); - - m_actor->ar_camera_node_roll_inv[i]=cross.y > 0;//(ar_nodes[ar_camera_node_dir[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition).crossProduct(ar_nodes[ar_camera_node_roll[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition).y>0; + + m_actor->ar_camera_node_roll_inv[i] = + cross.y > + 0; //(ar_nodes[ar_camera_node_dir[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition).crossProduct(ar_nodes[ar_camera_node_roll[i]].RelPosition-ar_nodes[ar_camera_node_pos[i]].RelPosition).y>0; if (m_actor->ar_camera_node_roll_inv[i]) { - AddMessage(Message::TYPE_WARNING, "camera definition is probably invalid and has been corrected. It should be center, back, left"); + AddMessage(Message::TYPE_WARNING, + "camera definition is probably invalid and has been corrected. It should be center, back, left"); } } - - //wing closure - if (m_first_wing_index!=-1) + + // wing closure + if (m_first_wing_index != -1) { - if (m_actor->ar_autopilot != nullptr) + if (m_actor->ar_autopilot != nullptr) { - m_actor->ar_autopilot->setInertialReferences( - & GetNode(m_airplane_left_light), - & GetNode(m_airplane_right_light), - m_actor->m_fusealge_back, - & GetNode(m_actor->ar_camera_node_pos[0]) - ); + m_actor->ar_autopilot->setInertialReferences(&GetNode(m_airplane_left_light), &GetNode(m_airplane_right_light), + m_actor->m_fusealge_back, &GetNode(m_actor->ar_camera_node_pos[0])); } - //inform wing segments - float span=GetNode(m_actor->ar_wings[m_first_wing_index].fa->nfrd).RelPosition.distance(GetNode(m_actor->ar_wings[m_actor->ar_num_wings-1].fa->nfld).RelPosition); - - m_actor->ar_wings[m_first_wing_index].fa->enableInducedDrag(span,m_wing_area, false); - m_actor->ar_wings[m_actor->ar_num_wings-1].fa->enableInducedDrag(span,m_wing_area, true); - //wash calculator + // inform wing segments + float span = GetNode(m_actor->ar_wings[m_first_wing_index].fa->nfrd) + .RelPosition.distance(GetNode(m_actor->ar_wings[m_actor->ar_num_wings - 1].fa->nfld).RelPosition); + + m_actor->ar_wings[m_first_wing_index].fa->enableInducedDrag(span, m_wing_area, false); + m_actor->ar_wings[m_actor->ar_num_wings - 1].fa->enableInducedDrag(span, m_wing_area, true); + // wash calculator WashCalculator(); } @@ -598,37 +580,40 @@ void ActorSpawner::FinalizeRig() void ActorSpawner::WashCalculator() { - //we will compute wash - int w,p; - for (p=0; par_num_aeroengines; p++) + // we will compute wash + int w, p; + for (p = 0; p < m_actor->ar_num_aeroengines; p++) { - Ogre::Vector3 prop=m_actor->ar_nodes[m_actor->ar_aeroengines[p]->getNoderef()].RelPosition; - float radius=m_actor->ar_aeroengines[p]->getRadius(); - for (w=0; war_num_wings; w++) + Ogre::Vector3 prop = m_actor->ar_nodes[m_actor->ar_aeroengines[p]->getNoderef()].RelPosition; + float radius = m_actor->ar_aeroengines[p]->getRadius(); + for (w = 0; w < m_actor->ar_num_wings; w++) { - //left wash - Ogre::Vector3 wcent=((m_actor->ar_nodes[m_actor->ar_wings[w].fa->nfld].RelPosition+m_actor->ar_nodes[m_actor->ar_wings[w].fa->nfrd].RelPosition)/2.0); - //check if wing is near enough along X (less than 15m back) - if (wcent.x>prop.x && wcent.xar_nodes[m_actor->ar_wings[w].fa->nfld].RelPosition + + m_actor->ar_nodes[m_actor->ar_wings[w].fa->nfrd].RelPosition) / + 2.0); + // check if wing is near enough along X (less than 15m back) + if (wcent.x > prop.x && wcent.x < prop.x + 15.0) { - //check if it's okay vertically - if (wcent.y>prop.y-radius && wcent.y prop.y - radius && wcent.y < prop.y + radius) { - //okay, compute wash coverage ratio along Z - float wleft=(m_actor->ar_nodes[m_actor->ar_wings[w].fa->nfld].RelPosition).z; - float wright=(m_actor->ar_nodes[m_actor->ar_wings[w].fa->nfrd].RelPosition).z; - float pleft=prop.z+radius; - float pright=prop.z-radius; - float aleft=wleft; - if (pleftaright) aright=pright; - if (arightar_nodes[m_actor->ar_wings[w].fa->nfld].RelPosition).z; + float wright = (m_actor->ar_nodes[m_actor->ar_wings[w].fa->nfrd].RelPosition).z; + float pleft = prop.z + radius; + float pright = prop.z - radius; + float aleft = wleft; + if (pleft < aleft) aleft = pleft; + float aright = wright; + if (pright > aright) aright = pright; + if (aright < aleft) { - //we have a wash - float wratio=(aleft-aright)/(wleft-wright); + // we have a wash + float wratio = (aleft - aright) / (wleft - wright); m_actor->ar_wings[w].fa->addwash(p, wratio); - Ogre::String msg = "Wing "+TOSTRING(w)+" is washed by prop "+TOSTRING(p)+" at "+TOSTRING((float)(wratio*100.0))+"%"; + Ogre::String msg = "Wing " + TOSTRING(w) + " is washed by prop " + TOSTRING(p) + " at " + + TOSTRING((float)(wratio * 100.0)) + "%"; AddMessage(Message::TYPE_INFO, msg); } } @@ -637,9 +622,9 @@ void ActorSpawner::WashCalculator() } } -void ActorSpawner::ProcessTurbojet(RigDef::Turbojet & def) +void ActorSpawner::ProcessTurbojet(RigDef::Turbojet &def) { - int front,back,ref; + int front, back, ref; front = GetNodeIndexOrThrow(def.front_node); back = GetNodeIndexOrThrow(def.back_node); ref = GetNodeIndexOrThrow(def.side_node); @@ -647,32 +632,29 @@ void ActorSpawner::ProcessTurbojet(RigDef::Turbojet & def) Turbojet *tj = new Turbojet(m_actor, front, back, ref, def); // Visuals - std::string nozzle_name = this->ComposeName("TurbojetNozzle", m_actor->ar_num_aeroengines); - Ogre::Entity* nozzle_ent = gEnv->sceneManager->createEntity(nozzle_name, "nozzle.mesh", m_custom_resource_group); + std::string nozzle_name = this->ComposeName("TurbojetNozzle", m_actor->ar_num_aeroengines); + Ogre::Entity *nozzle_ent = gEnv->sceneManager->createEntity(nozzle_name, "nozzle.mesh", m_custom_resource_group); this->SetupNewEntity(nozzle_ent, Ogre::ColourValue(1, 0.5, 0.5)); - Ogre::Entity* afterburn_ent = nullptr; + Ogre::Entity *afterburn_ent = nullptr; if (def.wet_thrust > 0.f) { std::string flame_name = this->ComposeName("AfterburnerFlame", m_actor->ar_num_aeroengines); - afterburn_ent = gEnv->sceneManager->createEntity(flame_name, "abflame.mesh", m_custom_resource_group); + afterburn_ent = gEnv->sceneManager->createEntity(flame_name, "abflame.mesh", m_custom_resource_group); this->SetupNewEntity(afterburn_ent, Ogre::ColourValue(1, 1, 0)); } std::string propname = this->ComposeName("Turbojet", m_actor->ar_num_aeroengines); tj->tjet_visual.SetNodes(front, back, ref); - tj->tjet_visual.SetupVisuals(def, m_actor->ar_num_aeroengines, - propname, nozzle_ent, afterburn_ent, m_actor->m_disable_smoke); + tj->tjet_visual.SetupVisuals(def, m_actor->ar_num_aeroengines, propname, nozzle_ent, afterburn_ent, m_actor->m_disable_smoke); - m_actor->ar_aeroengines[m_actor->ar_num_aeroengines]=tj; - m_actor->ar_driveable=AIRPLANE; + m_actor->ar_aeroengines[m_actor->ar_num_aeroengines] = tj; + m_actor->ar_driveable = AIRPLANE; if (m_actor->ar_autopilot == nullptr && m_actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - { - m_actor->ar_autopilot=new Autopilot(m_actor->ar_instance_id); - } + { m_actor->ar_autopilot = new Autopilot(m_actor->ar_instance_id); } m_actor->ar_num_aeroengines++; } -std::string ActorSpawner::ComposeName(const char* type, int number) +std::string ActorSpawner::ComposeName(const char *type, int number) { char buf[500]; snprintf(buf, 500, "%s_%d%s%d", type, number, ACTOR_ID_TOKEN, m_actor->ar_instance_id); @@ -680,42 +662,33 @@ std::string ActorSpawner::ComposeName(const char* type, int number) } // static -void ActorSpawner::ComposeName(RoR::Str<100>& str, const char* type, int number, int actor_id) +void ActorSpawner::ComposeName(RoR::Str<100> &str, const char *type, int number, int actor_id) { str.Clear(); str << type << "_" << number << ACTOR_ID_TOKEN << actor_id; } -void ActorSpawner::ProcessScrewprop(RigDef::Screwprop & def) +void ActorSpawner::ProcessScrewprop(RigDef::Screwprop &def) { - if (! CheckScrewpropLimit(1)) - { - return; - } + if (!CheckScrewpropLimit(1)) { return; } - int ref_node_idx = GetNodeIndexOrThrow(def.prop_node); + int ref_node_idx = GetNodeIndexOrThrow(def.prop_node); int back_node_idx = GetNodeIndexOrThrow(def.back_node); - int top_node_idx = GetNodeIndexOrThrow(def.top_node); - - m_actor->ar_screwprops[m_actor->ar_num_screwprops] = new Screwprop( - m_actor->ar_nodes, - ref_node_idx, - back_node_idx, - top_node_idx, - def.power, - m_actor->ar_instance_id - ); - m_actor->ar_driveable=BOAT; + int top_node_idx = GetNodeIndexOrThrow(def.top_node); + + m_actor->ar_screwprops[m_actor->ar_num_screwprops] = + new Screwprop(m_actor->ar_nodes, ref_node_idx, back_node_idx, top_node_idx, def.power, m_actor->ar_instance_id); + m_actor->ar_driveable = BOAT; m_actor->ar_num_screwprops++; } -void ActorSpawner::ProcessFusedrag(RigDef::Fusedrag & def) +void ActorSpawner::ProcessFusedrag(RigDef::Fusedrag &def) { - //parse fusedrag - int front_node_idx = GetNodeIndexOrThrow(def.front_node); - float width = 1.f; - float factor = 1.f; - char fusefoil[256]; + // parse fusedrag + int front_node_idx = GetNodeIndexOrThrow(def.front_node); + float width = 1.f; + float factor = 1.f; + char fusefoil[256]; strncpy(fusefoil, def.airfoil_name.c_str(), 255); if (def.autocalc) @@ -724,63 +697,39 @@ void ActorSpawner::ProcessFusedrag(RigDef::Fusedrag & def) // calculate fusedrag by truck size factor = def.area_coefficient; - width = (m_fuse_z_max - m_fuse_z_min) * (m_fuse_y_max - m_fuse_y_min) * factor; + width = (m_fuse_z_max - m_fuse_z_min) * (m_fuse_y_max - m_fuse_y_min) * factor; m_actor->m_fusealge_airfoil = new Airfoil(fusefoil); - m_actor->m_fusealge_front = & GetNode(front_node_idx); - m_actor->m_fusealge_back = & GetNode(front_node_idx); // This equals v0.38 / v0.4.0.7, but it's probably a bug - m_actor->m_fusealge_width = width; - AddMessage(Message::TYPE_INFO, "Fusedrag autocalculation size: "+TOSTRING(width)+" m^2"); - } + m_actor->m_fusealge_front = &GetNode(front_node_idx); + m_actor->m_fusealge_back = &GetNode(front_node_idx); // This equals v0.38 / v0.4.0.7, but it's probably a bug + m_actor->m_fusealge_width = width; + AddMessage(Message::TYPE_INFO, "Fusedrag autocalculation size: " + TOSTRING(width) + " m^2"); + } else { // original fusedrag calculation - width = def.approximate_width; + width = def.approximate_width; m_actor->m_fusealge_airfoil = new Airfoil(fusefoil); - m_actor->m_fusealge_front = & GetNode(front_node_idx); - m_actor->m_fusealge_back = & GetNode(front_node_idx); // This equals v0.38 / v0.4.0.7, but it's probably a bug - m_actor->m_fusealge_width = width; + m_actor->m_fusealge_front = &GetNode(front_node_idx); + m_actor->m_fusealge_back = &GetNode(front_node_idx); // This equals v0.38 / v0.4.0.7, but it's probably a bug + m_actor->m_fusealge_width = width; } } -void ActorSpawner::BuildAerialEngine( - int ref_node_index, - int back_node_index, - int blade_1_node_index, - int blade_2_node_index, - int blade_3_node_index, - int blade_4_node_index, - int couplenode_index, - bool is_turboprops, - Ogre::String const & airfoil, - float power, - float pitch - ) +void ActorSpawner::BuildAerialEngine(int ref_node_index, int back_node_index, int blade_1_node_index, int blade_2_node_index, + int blade_3_node_index, int blade_4_node_index, int couplenode_index, bool is_turboprops, + Ogre::String const &airfoil, float power, float pitch) { int aeroengine_index = m_actor->ar_num_aeroengines; Turboprop *turbo_prop = new Turboprop( - this->ComposeName("Turboprop", aeroengine_index).c_str(), - m_actor->ar_nodes, - ref_node_index, - back_node_index, - blade_1_node_index, - blade_2_node_index, - blade_3_node_index, - blade_4_node_index, - couplenode_index, - power, - airfoil, - m_actor->ar_num_aeroengines, - m_actor->ar_instance_id, - m_actor->m_disable_smoke, - ! is_turboprops, - pitch - ); + this->ComposeName("Turboprop", aeroengine_index).c_str(), m_actor->ar_nodes, ref_node_index, back_node_index, + blade_1_node_index, blade_2_node_index, blade_3_node_index, blade_4_node_index, couplenode_index, power, airfoil, + m_actor->ar_num_aeroengines, m_actor->ar_instance_id, m_actor->m_disable_smoke, !is_turboprops, pitch); m_actor->ar_aeroengines[m_actor->ar_num_aeroengines] = turbo_prop; m_actor->ar_num_aeroengines++; @@ -788,13 +737,11 @@ void ActorSpawner::BuildAerialEngine( /* Autopilot */ if (m_actor->ar_autopilot == nullptr && m_actor->ar_sim_state != Actor::SimState::NETWORKED_OK) - { - m_actor->ar_autopilot = new Autopilot(m_actor->ar_instance_id); - } + { m_actor->ar_autopilot = new Autopilot(m_actor->ar_instance_id); } /* Visuals */ float scale = GetNode(ref_node_index).RelPosition.distance(GetNode(blade_1_node_index).RelPosition) / 2.25f; - for (prop_t& prop: m_props) + for (prop_t &prop : m_props) { if ((prop.noderef == ref_node_index) && (prop.pp_aero_propeller_blade || prop.pp_aero_propeller_spin)) { @@ -804,73 +751,39 @@ void ActorSpawner::BuildAerialEngine( } } -void ActorSpawner::ProcessTurboprop2(RigDef::Turboprop2 & def) +void ActorSpawner::ProcessTurboprop2(RigDef::Turboprop2 &def) { - int p3_node_index = (def.blade_tip_nodes[2].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[2]) : -1; - int p4_node_index = (def.blade_tip_nodes[3].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[3]) : -1; + int p3_node_index = (def.blade_tip_nodes[2].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[2]) : -1; + int p4_node_index = (def.blade_tip_nodes[3].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[3]) : -1; int couple_node_index = (def.couple_node.IsValidAnyState()) ? GetNodeIndexOrThrow(def.couple_node) : -1; - BuildAerialEngine( - GetNodeIndexOrThrow(def.reference_node), - GetNodeIndexOrThrow(def.axis_node), - GetNodeIndexOrThrow(def.blade_tip_nodes[0]), - GetNodeIndexOrThrow(def.blade_tip_nodes[1]), - p3_node_index, - p4_node_index, - couple_node_index, - true, - def.airfoil, - def.turbine_power_kW, - -10 - ); + BuildAerialEngine(GetNodeIndexOrThrow(def.reference_node), GetNodeIndexOrThrow(def.axis_node), + GetNodeIndexOrThrow(def.blade_tip_nodes[0]), GetNodeIndexOrThrow(def.blade_tip_nodes[1]), p3_node_index, + p4_node_index, couple_node_index, true, def.airfoil, def.turbine_power_kW, -10); } -void ActorSpawner::ProcessPistonprop(RigDef::Pistonprop & def) +void ActorSpawner::ProcessPistonprop(RigDef::Pistonprop &def) { - int p3_node_index = (def.blade_tip_nodes[2].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[2]) : -1; - int p4_node_index = (def.blade_tip_nodes[3].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[3]) : -1; + int p3_node_index = (def.blade_tip_nodes[2].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[2]) : -1; + int p4_node_index = (def.blade_tip_nodes[3].IsValidAnyState()) ? GetNodeIndexOrThrow(def.blade_tip_nodes[3]) : -1; int couple_node_index = (def.couple_node.IsValidAnyState()) ? GetNodeIndexOrThrow(def.couple_node) : -1; - BuildAerialEngine( - GetNodeIndexOrThrow(def.reference_node), - GetNodeIndexOrThrow(def.axis_node), - GetNodeIndexOrThrow(def.blade_tip_nodes[0]), - GetNodeIndexOrThrow(def.blade_tip_nodes[1]), - p3_node_index, - p4_node_index, - couple_node_index, - false, - def.airfoil, - def.turbine_power_kW, - def.pitch - ); + BuildAerialEngine(GetNodeIndexOrThrow(def.reference_node), GetNodeIndexOrThrow(def.axis_node), + GetNodeIndexOrThrow(def.blade_tip_nodes[0]), GetNodeIndexOrThrow(def.blade_tip_nodes[1]), p3_node_index, + p4_node_index, couple_node_index, false, def.airfoil, def.turbine_power_kW, def.pitch); } -void ActorSpawner::ProcessAirbrake(RigDef::Airbrake & def) +void ActorSpawner::ProcessAirbrake(RigDef::Airbrake &def) { const int airbrake_idx = static_cast(m_actor->ar_airbrakes.size()); m_actor->ar_airbrakes.push_back(new Airbrake( - m_actor, - this->ComposeName("Airbrake", airbrake_idx).c_str(), - airbrake_idx, - GetNodePointerOrThrow(def.reference_node), - GetNodePointerOrThrow(def.x_axis_node), - GetNodePointerOrThrow(def.y_axis_node), - GetNodePointerOrThrow(def.aditional_node), - def.offset, - def.width, - def.height, - def.max_inclination_angle, - m_cab_material_name, - def.texcoord_x1, - def.texcoord_y1, - def.texcoord_x2, - def.texcoord_y2, - def.lift_coefficient - )); -} - -void ActorSpawner::ProcessWing(RigDef::Wing & def) + m_actor, this->ComposeName("Airbrake", airbrake_idx).c_str(), airbrake_idx, GetNodePointerOrThrow(def.reference_node), + GetNodePointerOrThrow(def.x_axis_node), GetNodePointerOrThrow(def.y_axis_node), GetNodePointerOrThrow(def.aditional_node), + def.offset, def.width, def.height, def.max_inclination_angle, m_cab_material_name, def.texcoord_x1, def.texcoord_y1, + def.texcoord_x2, def.texcoord_y2, def.lift_coefficient)); +} + +void ActorSpawner::ProcessWing(RigDef::Wing &def) { if ((m_first_wing_index != -1) && (m_actor->ar_wings[m_actor->ar_num_wings - 1].fa == nullptr)) { @@ -891,37 +804,19 @@ void ActorSpawner::ProcessWing(RigDef::Wing & def) node_indices[i] = this->GetNodeIndexOrThrow(def.nodes[i]); } - const std::string wing_name = this->ComposeName("Wing", m_actor->ar_num_wings); - auto flex_airfoil = new FlexAirfoil( - wing_name, - m_actor, - node_indices[0], - node_indices[1], - node_indices[2], - node_indices[3], - node_indices[4], - node_indices[5], - node_indices[6], - node_indices[7], - m_cab_material_name, - Ogre::Vector2(def.tex_coords[0], def.tex_coords[1]), - Ogre::Vector2(def.tex_coords[2], def.tex_coords[3]), - Ogre::Vector2(def.tex_coords[4], def.tex_coords[5]), - Ogre::Vector2(def.tex_coords[6], def.tex_coords[7]), - def.control_surface, - def.chord_point, - def.min_deflection, - def.max_deflection, - def.airfoil, - def.efficacy_coef, - m_actor->ar_sim_state != Actor::SimState::NETWORKED_OK - ); + const std::string wing_name = this->ComposeName("Wing", m_actor->ar_num_wings); + auto flex_airfoil = new FlexAirfoil( + wing_name, m_actor, node_indices[0], node_indices[1], node_indices[2], node_indices[3], node_indices[4], node_indices[5], + node_indices[6], node_indices[7], m_cab_material_name, Ogre::Vector2(def.tex_coords[0], def.tex_coords[1]), + Ogre::Vector2(def.tex_coords[2], def.tex_coords[3]), Ogre::Vector2(def.tex_coords[4], def.tex_coords[5]), + Ogre::Vector2(def.tex_coords[6], def.tex_coords[7]), def.control_surface, def.chord_point, def.min_deflection, + def.max_deflection, def.airfoil, def.efficacy_coef, m_actor->ar_sim_state != Actor::SimState::NETWORKED_OK); - Ogre::Entity* entity = nullptr; + Ogre::Entity *entity = nullptr; try { const std::string wing_instance_name = this->ComposeName("WingEntity", m_actor->ar_num_wings); - entity = gEnv->sceneManager->createEntity(wing_instance_name, wing_name); + entity = gEnv->sceneManager->createEntity(wing_instance_name, wing_name); m_actor->m_deletion_entities.emplace_back(entity); this->SetupNewEntity(entity, Ogre::ColourValue(0.5, 1, 0)); } @@ -936,328 +831,307 @@ void ActorSpawner::ProcessWing(RigDef::Wing & def) if (m_first_wing_index == -1) { m_first_wing_index = m_actor->ar_num_wings; - m_wing_area=ComputeWingArea( - this->GetNode(flex_airfoil->nfld).AbsPosition, this->GetNode(flex_airfoil->nfrd).AbsPosition, - this->GetNode(flex_airfoil->nbld).AbsPosition, this->GetNode(flex_airfoil->nbrd).AbsPosition - ); + m_wing_area = + ComputeWingArea(this->GetNode(flex_airfoil->nfld).AbsPosition, this->GetNode(flex_airfoil->nfrd).AbsPosition, + this->GetNode(flex_airfoil->nbld).AbsPosition, this->GetNode(flex_airfoil->nbrd).AbsPosition); } else { - wing_t & previous_wing = m_actor->ar_wings[m_actor->ar_num_wings - 1]; + wing_t &previous_wing = m_actor->ar_wings[m_actor->ar_num_wings - 1]; if (node_indices[1] != previous_wing.fa->nfld) { - wing_t & start_wing = m_actor->ar_wings[m_first_wing_index]; + wing_t &start_wing = m_actor->ar_wings[m_first_wing_index]; + + // discontinuity + // inform wing segments + float span = GetNode(start_wing.fa->nfrd).RelPosition.distance(GetNode(previous_wing.fa->nfld).RelPosition); - //discontinuity - //inform wing segments - float span = GetNode( start_wing.fa->nfrd).RelPosition.distance( GetNode(previous_wing.fa->nfld).RelPosition ); - start_wing.fa->enableInducedDrag(span, m_wing_area, false); previous_wing.fa->enableInducedDrag(span, m_wing_area, true); - //we want also to add positional lights for first wing + // we want also to add positional lights for first wing if (m_generate_wing_position_lights && (m_actor->m_flares_mode != GfxFlaresMode::NONE)) { - //Left green - m_airplane_left_light=previous_wing.fa->nfld; + // Left green + m_airplane_left_light = previous_wing.fa->nfld; prop_t left_green_prop; - left_green_prop.noderef=previous_wing.fa->nfld; - left_green_prop.nodex=previous_wing.fa->nflu; - left_green_prop.nodey=previous_wing.fa->nfld; //ignored - left_green_prop.offsetx=0.5; - left_green_prop.offsety=0.0; - left_green_prop.offsetz=0.0; - left_green_prop.rot=Ogre::Quaternion::IDENTITY; - left_green_prop.wheel=nullptr; - left_green_prop.wheelrotdegree=0.0; - left_green_prop.mirror=0; - left_green_prop.scene_node=nullptr; //no visible prop - left_green_prop.beacon_light_rotation_angle[0]=0.0; - left_green_prop.beacon_light_rotation_rate[0]=1.0; - left_green_prop.beacontype='L'; - left_green_prop.beacon_light[0]=nullptr; //no light - //the flare billboard - left_green_prop.beacon_flare_billboard_scene_node[0] = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - left_green_prop.beacon_flares_billboard_system[0]=gEnv->sceneManager->createBillboardSet(this->ComposeName("Prop", static_cast(m_props.size())+1),1); - left_green_prop.beacon_flares_billboard_system[0]->createBillboard(0,0,0); + left_green_prop.noderef = previous_wing.fa->nfld; + left_green_prop.nodex = previous_wing.fa->nflu; + left_green_prop.nodey = previous_wing.fa->nfld; // ignored + left_green_prop.offsetx = 0.5; + left_green_prop.offsety = 0.0; + left_green_prop.offsetz = 0.0; + left_green_prop.rot = Ogre::Quaternion::IDENTITY; + left_green_prop.wheel = nullptr; + left_green_prop.wheelrotdegree = 0.0; + left_green_prop.mirror = 0; + left_green_prop.scene_node = nullptr; // no visible prop + left_green_prop.beacon_light_rotation_angle[0] = 0.0; + left_green_prop.beacon_light_rotation_rate[0] = 1.0; + left_green_prop.beacontype = 'L'; + left_green_prop.beacon_light[0] = nullptr; // no light + // the flare billboard + left_green_prop.beacon_flare_billboard_scene_node[0] = + gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + left_green_prop.beacon_flares_billboard_system[0] = + gEnv->sceneManager->createBillboardSet(this->ComposeName("Prop", static_cast(m_props.size()) + 1), 1); + left_green_prop.beacon_flares_billboard_system[0]->createBillboard(0, 0, 0); if (left_green_prop.beacon_flares_billboard_system[0]) { left_green_prop.beacon_flares_billboard_system[0]->setVisibilityFlags(DEPTHMAP_DISABLED); left_green_prop.beacon_flares_billboard_system[0]->setMaterialName("tracks/greenflare"); - left_green_prop.beacon_flare_billboard_scene_node[0]->attachObject(left_green_prop.beacon_flares_billboard_system[0]); + left_green_prop.beacon_flare_billboard_scene_node[0]->attachObject( + left_green_prop.beacon_flares_billboard_system[0]); } left_green_prop.beacon_flare_billboard_scene_node[0]->setVisible(false); left_green_prop.beacon_flares_billboard_system[0]->setDefaultDimensions(0.5, 0.5); - left_green_prop.animFlags[0]=0; - left_green_prop.animMode[0]=0; + left_green_prop.animFlags[0] = 0; + left_green_prop.animMode[0] = 0; m_props.push_back(left_green_prop); - - //Left flash + + // Left flash prop_t left_flash_prop; - left_flash_prop.noderef=previous_wing.fa->nbld; - left_flash_prop.nodex=previous_wing.fa->nblu; - left_flash_prop.nodey=previous_wing.fa->nbld; //ignored - left_flash_prop.offsetx=0.5; - left_flash_prop.offsety=0.0; - left_flash_prop.offsetz=0.0; - left_flash_prop.rot=Ogre::Quaternion::IDENTITY; - left_flash_prop.wheel=nullptr; - left_flash_prop.wheelrotdegree=0.0; - left_flash_prop.mirror=0; - left_flash_prop.scene_node=nullptr; //no visible prop - left_flash_prop.beacon_light_rotation_angle[0]=0.5; //alt - left_flash_prop.beacon_light_rotation_rate[0]=1.0; - left_flash_prop.beacontype='w'; - //light - std::string prop_name = this->ComposeName("Prop", static_cast(m_props.size())+1); - left_flash_prop.beacon_light[0]=gEnv->sceneManager->createLight(prop_name); + left_flash_prop.noderef = previous_wing.fa->nbld; + left_flash_prop.nodex = previous_wing.fa->nblu; + left_flash_prop.nodey = previous_wing.fa->nbld; // ignored + left_flash_prop.offsetx = 0.5; + left_flash_prop.offsety = 0.0; + left_flash_prop.offsetz = 0.0; + left_flash_prop.rot = Ogre::Quaternion::IDENTITY; + left_flash_prop.wheel = nullptr; + left_flash_prop.wheelrotdegree = 0.0; + left_flash_prop.mirror = 0; + left_flash_prop.scene_node = nullptr; // no visible prop + left_flash_prop.beacon_light_rotation_angle[0] = 0.5; // alt + left_flash_prop.beacon_light_rotation_rate[0] = 1.0; + left_flash_prop.beacontype = 'w'; + // light + std::string prop_name = this->ComposeName("Prop", static_cast(m_props.size()) + 1); + left_flash_prop.beacon_light[0] = gEnv->sceneManager->createLight(prop_name); left_flash_prop.beacon_light[0]->setType(Ogre::Light::LT_POINT); - left_flash_prop.beacon_light[0]->setDiffuseColour( Ogre::ColourValue(1.0, 1.0, 1.0)); - left_flash_prop.beacon_light[0]->setSpecularColour( Ogre::ColourValue(1.0, 1.0, 1.0)); + left_flash_prop.beacon_light[0]->setDiffuseColour(Ogre::ColourValue(1.0, 1.0, 1.0)); + left_flash_prop.beacon_light[0]->setSpecularColour(Ogre::ColourValue(1.0, 1.0, 1.0)); left_flash_prop.beacon_light[0]->setAttenuation(50.0, 1.0, 0.3, 0.0); left_flash_prop.beacon_light[0]->setCastShadows(false); left_flash_prop.beacon_light[0]->setVisible(false); - //the flare billboard - left_flash_prop.beacon_flare_billboard_scene_node[0] = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - left_flash_prop.beacon_flares_billboard_system[0]=gEnv->sceneManager->createBillboardSet(prop_name,1); - left_flash_prop.beacon_flares_billboard_system[0]->createBillboard(0,0,0); + // the flare billboard + left_flash_prop.beacon_flare_billboard_scene_node[0] = + gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + left_flash_prop.beacon_flares_billboard_system[0] = gEnv->sceneManager->createBillboardSet(prop_name, 1); + left_flash_prop.beacon_flares_billboard_system[0]->createBillboard(0, 0, 0); if (left_flash_prop.beacon_flares_billboard_system[0]) { left_flash_prop.beacon_flares_billboard_system[0]->setVisibilityFlags(DEPTHMAP_DISABLED); left_flash_prop.beacon_flares_billboard_system[0]->setMaterialName("tracks/flare"); - left_flash_prop.beacon_flare_billboard_scene_node[0]->attachObject(left_flash_prop.beacon_flares_billboard_system[0]); + left_flash_prop.beacon_flare_billboard_scene_node[0]->attachObject( + left_flash_prop.beacon_flares_billboard_system[0]); } left_flash_prop.beacon_flare_billboard_scene_node[0]->setVisible(false); left_flash_prop.beacon_flares_billboard_system[0]->setDefaultDimensions(1.0, 1.0); m_props.push_back(left_flash_prop); - - //Right red - m_airplane_right_light=previous_wing.fa->nfrd; + + // Right red + m_airplane_right_light = previous_wing.fa->nfrd; prop_t right_red_prop; - - right_red_prop.noderef=start_wing.fa->nfrd; - right_red_prop.nodex=start_wing.fa->nfru; - right_red_prop.nodey=start_wing.fa->nfrd; //ignored - right_red_prop.offsetx=0.5; - right_red_prop.offsety=0.0; - right_red_prop.offsetz=0.0; - right_red_prop.rot=Ogre::Quaternion::IDENTITY; - right_red_prop.wheel=nullptr; - right_red_prop.wheelrotdegree=0.0; - right_red_prop.mirror=0; - right_red_prop.scene_node=nullptr; //no visible prop - right_red_prop.beacon_light_rotation_angle[0]=0.0; - right_red_prop.beacon_light_rotation_rate[0]=1.0; - right_red_prop.beacontype='R'; - right_red_prop.beacon_light[0]=nullptr; /* No light */ - //the flare billboard - right_red_prop.beacon_flare_billboard_scene_node[0] = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - right_red_prop.beacon_flares_billboard_system[0]=gEnv->sceneManager->createBillboardSet(this->ComposeName("Prop", static_cast(m_props.size())+1),1); - right_red_prop.beacon_flares_billboard_system[0]->createBillboard(0,0,0); + right_red_prop.noderef = start_wing.fa->nfrd; + right_red_prop.nodex = start_wing.fa->nfru; + right_red_prop.nodey = start_wing.fa->nfrd; // ignored + right_red_prop.offsetx = 0.5; + right_red_prop.offsety = 0.0; + right_red_prop.offsetz = 0.0; + right_red_prop.rot = Ogre::Quaternion::IDENTITY; + right_red_prop.wheel = nullptr; + right_red_prop.wheelrotdegree = 0.0; + right_red_prop.mirror = 0; + right_red_prop.scene_node = nullptr; // no visible prop + right_red_prop.beacon_light_rotation_angle[0] = 0.0; + right_red_prop.beacon_light_rotation_rate[0] = 1.0; + right_red_prop.beacontype = 'R'; + right_red_prop.beacon_light[0] = nullptr; /* No light */ + // the flare billboard + right_red_prop.beacon_flare_billboard_scene_node[0] = + gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + right_red_prop.beacon_flares_billboard_system[0] = + gEnv->sceneManager->createBillboardSet(this->ComposeName("Prop", static_cast(m_props.size()) + 1), 1); + right_red_prop.beacon_flares_billboard_system[0]->createBillboard(0, 0, 0); if (right_red_prop.beacon_flares_billboard_system[0]) { right_red_prop.beacon_flares_billboard_system[0]->setVisibilityFlags(DEPTHMAP_DISABLED); right_red_prop.beacon_flares_billboard_system[0]->setMaterialName("tracks/redflare"); - right_red_prop.beacon_flare_billboard_scene_node[0]->attachObject(right_red_prop.beacon_flares_billboard_system[0]); + right_red_prop.beacon_flare_billboard_scene_node[0]->attachObject( + right_red_prop.beacon_flares_billboard_system[0]); } right_red_prop.beacon_flare_billboard_scene_node[0]->setVisible(false); right_red_prop.beacon_flares_billboard_system[0]->setDefaultDimensions(0.5, 0.5); - right_red_prop.animFlags[0]=0; - right_red_prop.animMode[0]=0; + right_red_prop.animFlags[0] = 0; + right_red_prop.animMode[0] = 0; m_props.push_back(right_red_prop); - - //Right flash + + // Right flash prop_t right_flash_prop; - right_flash_prop.noderef=start_wing.fa->nbrd; - right_flash_prop.nodex=start_wing.fa->nbru; - right_flash_prop.nodey=start_wing.fa->nbrd; //ignored - right_flash_prop.offsetx=0.5; - right_flash_prop.offsety=0.0; - right_flash_prop.offsetz=0.0; - right_flash_prop.rot=Ogre::Quaternion::IDENTITY; - right_flash_prop.wheel=nullptr; - right_flash_prop.wheelrotdegree=0.0; - right_flash_prop.mirror=0; - right_flash_prop.scene_node=nullptr; //no visible prop - right_flash_prop.beacon_light_rotation_angle[0]=0.5; //alt - right_flash_prop.beacon_light_rotation_rate[0]=1.0; - right_flash_prop.beacontype='w'; - //light - prop_name = this->ComposeName("Prop", static_cast(m_props.size())+1); - right_flash_prop.beacon_light[0]=gEnv->sceneManager->createLight(prop_name); + right_flash_prop.noderef = start_wing.fa->nbrd; + right_flash_prop.nodex = start_wing.fa->nbru; + right_flash_prop.nodey = start_wing.fa->nbrd; // ignored + right_flash_prop.offsetx = 0.5; + right_flash_prop.offsety = 0.0; + right_flash_prop.offsetz = 0.0; + right_flash_prop.rot = Ogre::Quaternion::IDENTITY; + right_flash_prop.wheel = nullptr; + right_flash_prop.wheelrotdegree = 0.0; + right_flash_prop.mirror = 0; + right_flash_prop.scene_node = nullptr; // no visible prop + right_flash_prop.beacon_light_rotation_angle[0] = 0.5; // alt + right_flash_prop.beacon_light_rotation_rate[0] = 1.0; + right_flash_prop.beacontype = 'w'; + // light + prop_name = this->ComposeName("Prop", static_cast(m_props.size()) + 1); + right_flash_prop.beacon_light[0] = gEnv->sceneManager->createLight(prop_name); right_flash_prop.beacon_light[0]->setType(Ogre::Light::LT_POINT); - right_flash_prop.beacon_light[0]->setDiffuseColour( Ogre::ColourValue(1.0, 1.0, 1.0)); - right_flash_prop.beacon_light[0]->setSpecularColour( Ogre::ColourValue(1.0, 1.0, 1.0)); + right_flash_prop.beacon_light[0]->setDiffuseColour(Ogre::ColourValue(1.0, 1.0, 1.0)); + right_flash_prop.beacon_light[0]->setSpecularColour(Ogre::ColourValue(1.0, 1.0, 1.0)); right_flash_prop.beacon_light[0]->setAttenuation(50.0, 1.0, 0.3, 0.0); right_flash_prop.beacon_light[0]->setCastShadows(false); right_flash_prop.beacon_light[0]->setVisible(false); - //the flare billboard - right_flash_prop.beacon_flare_billboard_scene_node[0] = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - right_flash_prop.beacon_flares_billboard_system[0]=gEnv->sceneManager->createBillboardSet(prop_name,1); - right_flash_prop.beacon_flares_billboard_system[0]->createBillboard(0,0,0); + // the flare billboard + right_flash_prop.beacon_flare_billboard_scene_node[0] = + gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + right_flash_prop.beacon_flares_billboard_system[0] = gEnv->sceneManager->createBillboardSet(prop_name, 1); + right_flash_prop.beacon_flares_billboard_system[0]->createBillboard(0, 0, 0); if (right_flash_prop.beacon_flares_billboard_system[0] != nullptr) { right_flash_prop.beacon_flares_billboard_system[0]->setVisibilityFlags(DEPTHMAP_DISABLED); right_flash_prop.beacon_flares_billboard_system[0]->setMaterialName("tracks/flare"); - right_flash_prop.beacon_flare_billboard_scene_node[0]->attachObject(right_flash_prop.beacon_flares_billboard_system[0]); + right_flash_prop.beacon_flare_billboard_scene_node[0]->attachObject( + right_flash_prop.beacon_flares_billboard_system[0]); } right_flash_prop.beacon_flare_billboard_scene_node[0]->setVisible(false); right_flash_prop.beacon_flares_billboard_system[0]->setDefaultDimensions(1.0, 1.0); - right_flash_prop.animFlags[0]=0; - right_flash_prop.animMode[0]=0; + right_flash_prop.animFlags[0] = 0; + right_flash_prop.animMode[0] = 0; m_props.push_back(right_flash_prop); - + m_generate_wing_position_lights = false; // Already done } m_first_wing_index = m_actor->ar_num_wings; - m_wing_area=ComputeWingArea( - this->GetNode(flex_airfoil->nfld).AbsPosition, this->GetNode(flex_airfoil->nfrd).AbsPosition, - this->GetNode(flex_airfoil->nbld).AbsPosition, this->GetNode(flex_airfoil->nbrd).AbsPosition - ); + m_wing_area = + ComputeWingArea(this->GetNode(flex_airfoil->nfld).AbsPosition, this->GetNode(flex_airfoil->nfrd).AbsPosition, + this->GetNode(flex_airfoil->nbld).AbsPosition, this->GetNode(flex_airfoil->nbrd).AbsPosition); } - else + else { - m_wing_area+=ComputeWingArea( - this->GetNode(flex_airfoil->nfld).AbsPosition, this->GetNode(flex_airfoil->nfrd).AbsPosition, - this->GetNode(flex_airfoil->nbld).AbsPosition, this->GetNode(flex_airfoil->nbrd).AbsPosition - ); + m_wing_area += + ComputeWingArea(this->GetNode(flex_airfoil->nfld).AbsPosition, this->GetNode(flex_airfoil->nfrd).AbsPosition, + this->GetNode(flex_airfoil->nbld).AbsPosition, this->GetNode(flex_airfoil->nbrd).AbsPosition); } } // Add new wing to rig - m_actor->ar_wings[m_actor->ar_num_wings].fa = flex_airfoil; + m_actor->ar_wings[m_actor->ar_num_wings].fa = flex_airfoil; m_actor->ar_wings[m_actor->ar_num_wings].cnode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_actor->ar_wings[m_actor->ar_num_wings].cnode->attachObject(entity); ++m_actor->ar_num_wings; } -float ActorSpawner::ComputeWingArea(Ogre::Vector3 const & ref, Ogre::Vector3 const & x, Ogre::Vector3 const & y, Ogre::Vector3 const & aref) +float ActorSpawner::ComputeWingArea(Ogre::Vector3 const &ref, Ogre::Vector3 const &x, Ogre::Vector3 const &y, + Ogre::Vector3 const &aref) { - return (((x-ref).crossProduct(y-ref)).length()+((x-aref).crossProduct(y-aref)).length())*0.5f; + return (((x - ref).crossProduct(y - ref)).length() + ((x - aref).crossProduct(y - aref)).length()) * 0.5f; } -void ActorSpawner::ProcessSoundSource2(RigDef::SoundSource2 & def) +void ActorSpawner::ProcessSoundSource2(RigDef::SoundSource2 &def) { #ifdef USE_OPENAL - int mode = (def.mode == RigDef::SoundSource2::MODE_CINECAM) ? def.cinecam_index : def.mode; + int mode = (def.mode == RigDef::SoundSource2::MODE_CINECAM) ? def.cinecam_index : def.mode; int node_index = FindNodeIndex(def.node); - if (node_index == -1) - { - return; - } - AddSoundSource( - m_actor, - SoundScriptManager::getSingleton().createInstance(def.sound_script_name, m_actor->ar_instance_id), - node_index, - mode - ); + if (node_index == -1) { return; } + AddSoundSource(m_actor, SoundScriptManager::getSingleton().createInstance(def.sound_script_name, m_actor->ar_instance_id), + node_index, mode); #endif // USE_OPENAL } -void ActorSpawner::AddSoundSourceInstance(Actor *vehicle, Ogre::String const & sound_script_name, int node_index, int type) +void ActorSpawner::AddSoundSourceInstance(Actor *vehicle, Ogre::String const &sound_script_name, int node_index, int type) { #ifdef USE_OPENAL - AddSoundSource(vehicle, SoundScriptManager::getSingleton().createInstance(sound_script_name, vehicle->ar_instance_id, nullptr), node_index); + AddSoundSource(vehicle, + SoundScriptManager::getSingleton().createInstance(sound_script_name, vehicle->ar_instance_id, nullptr), + node_index); #endif // USE_OPENAL } void ActorSpawner::AddSoundSource(Actor *vehicle, SoundScriptInstance *sound_script, int node_index, int type) { - if (! CheckSoundScriptLimit(vehicle, 1)) - { - return; - } + if (!CheckSoundScriptLimit(vehicle, 1)) { return; } - if (sound_script == nullptr) - { - return; - } + if (sound_script == nullptr) { return; } - vehicle->ar_soundsources[vehicle->ar_num_soundsources].ssi=sound_script; - vehicle->ar_soundsources[vehicle->ar_num_soundsources].nodenum=node_index; - vehicle->ar_soundsources[vehicle->ar_num_soundsources].type=type; + vehicle->ar_soundsources[vehicle->ar_num_soundsources].ssi = sound_script; + vehicle->ar_soundsources[vehicle->ar_num_soundsources].nodenum = node_index; + vehicle->ar_soundsources[vehicle->ar_num_soundsources].type = type; vehicle->ar_num_soundsources++; } -void ActorSpawner::ProcessSoundSource(RigDef::SoundSource & def) +void ActorSpawner::ProcessSoundSource(RigDef::SoundSource &def) { #ifdef USE_OPENAL - AddSoundSource( - m_actor, - SoundScriptManager::getSingleton().createInstance(def.sound_script_name, m_actor->ar_instance_id), - GetNodeIndexOrThrow(def.node), - -2 - ); + AddSoundSource(m_actor, SoundScriptManager::getSingleton().createInstance(def.sound_script_name, m_actor->ar_instance_id), + GetNodeIndexOrThrow(def.node), -2); #endif // USE_OPENAL } -void ActorSpawner::ProcessCameraRail(RigDef::CameraRail & def) +void ActorSpawner::ProcessCameraRail(RigDef::CameraRail &def) { auto itor = def.nodes.begin(); auto end = def.nodes.end(); - for(; itor != end; ++itor) + for (; itor != end; ++itor) { - if (! CheckCameraRailLimit(1)) - { - return; - } + if (!CheckCameraRailLimit(1)) { return; } m_actor->ar_camera_rail[m_actor->ar_num_camera_rails] = GetNodeIndexOrThrow(*itor); m_actor->ar_num_camera_rails++; } } -void ActorSpawner::ProcessExtCamera(RigDef::ExtCamera & def) +void ActorSpawner::ProcessExtCamera(RigDef::ExtCamera &def) { m_actor->ar_extern_camera_mode = def.mode; - if (def.node.IsValidAnyState()) - { - m_actor->ar_extern_camera_node = GetNodeIndexOrThrow(def.node); - } + if (def.node.IsValidAnyState()) { m_actor->ar_extern_camera_node = GetNodeIndexOrThrow(def.node); } } -void ActorSpawner::ProcessGuiSettings(RigDef::GuiSettings & def) +void ActorSpawner::ProcessGuiSettings(RigDef::GuiSettings &def) { // Currently unused (was relevant to overlay-based HUD): def.tacho_material; def.speedo_material; - if (! def.help_material.empty()) - { - m_actor->ar_help_panel_material = def.help_material; - } + if (!def.help_material.empty()) { m_actor->ar_help_panel_material = def.help_material; } if (def.speedo_highest_kph > 10 && def.speedo_highest_kph < 32000) - { - m_actor->ar_speedo_max_kph = def.speedo_highest_kph; /* Handles default */ - } + { m_actor->ar_speedo_max_kph = def.speedo_highest_kph; /* Handles default */ } else { std::stringstream msg; - msg << "Invalid 'speedo_highest_kph' value (" << def.speedo_highest_kph << "), allowed range is <10 -32000>. Falling back to default..."; + msg << "Invalid 'speedo_highest_kph' value (" << def.speedo_highest_kph + << "), allowed range is <10 -32000>. Falling back to default..."; AddMessage(Message::TYPE_ERROR, msg.str()); m_actor->ar_speedo_max_kph = RigDef::GuiSettings::DEFAULT_SPEEDO_MAX; } - m_actor->ar_gui_use_engine_max_rpm = def.use_max_rpm; /* Handles default */ + m_actor->ar_gui_use_engine_max_rpm = def.use_max_rpm; /* Handles default */ // NOTE: Dashboard layouts are processed later } void ActorSpawner::ProcessFixedNode(RigDef::Node::Ref node_ref) { - node_t & node = GetNodeOrThrow(node_ref); + node_t &node = GetNodeOrThrow(node_ref); node.nd_immovable = true; } -void ActorSpawner::ProcessExhaust(RigDef::Exhaust & def) +void ActorSpawner::ProcessExhaust(RigDef::Exhaust &def) { - if (m_actor->m_disable_smoke) - { - return; - } + if (m_actor->m_disable_smoke) { return; } exhaust_t exhaust; exhaust.emitterNode = this->GetNodeIndexOrThrow(def.reference_node); @@ -1270,11 +1144,11 @@ void ActorSpawner::ProcessExhaust(RigDef::Exhaust & def) } std::string name = this->ComposeName(template_name.c_str(), static_cast(m_actor->exhausts.size())); - exhaust.smoker = this->CreateParticleSystem(name, template_name); + exhaust.smoker = this->CreateParticleSystem(name, template_name); if (exhaust.smoker == nullptr) { std::stringstream msg; - msg << "Failed to create particle system '" << name << "' (template: '" << template_name <<"')"; + msg << "Failed to create particle system '" << name << "' (template: '" << template_name << "')"; AddMessage(Message::TYPE_ERROR, msg.str()); return; } @@ -1284,12 +1158,9 @@ void ActorSpawner::ProcessExhaust(RigDef::Exhaust & def) exhaust.smokeNode->setPosition(this->GetNode(exhaust.emitterNode).AbsPosition); // Update GFX for nodes - for (GfxActor::NodeGfx& nfx : m_gfx_nodes) + for (GfxActor::NodeGfx &nfx : m_gfx_nodes) { - if (nfx.nx_node_idx == exhaust.emitterNode || nfx.nx_node_idx == exhaust.directionNode) - { - nfx.nx_is_hot = true; - } + if (nfx.nx_node_idx == exhaust.emitterNode || nfx.nx_node_idx == exhaust.directionNode) { nfx.nx_is_hot = true; } } m_actor->exhausts.push_back(exhaust); @@ -1301,30 +1172,21 @@ std::string ActorSpawner::GetSubmeshGroundmodelName() auto module_end = m_selected_modules.end(); for (; module_itor != module_end; ++module_itor) { - if (! module_itor->get()->submeshes_ground_model_name.empty()) - { - return module_itor->get()->submeshes_ground_model_name; - } + if (!module_itor->get()->submeshes_ground_model_name.empty()) { return module_itor->get()->submeshes_ground_model_name; } } return std::string(); }; -void ActorSpawner::ProcessSubmesh(RigDef::Submesh & def) +void ActorSpawner::ProcessSubmesh(RigDef::Submesh &def) { - if (! CheckSubmeshLimit(1)) - { - return; - } + if (!CheckSubmeshLimit(1)) { return; } /* TEXCOORDS */ std::vector::iterator texcoord_itor = def.texcoords.begin(); - for ( ; texcoord_itor != def.texcoords.end(); texcoord_itor++) + for (; texcoord_itor != def.texcoords.end(); texcoord_itor++) { - if (! CheckTexcoordLimit(1)) - { - break; - } + if (!CheckTexcoordLimit(1)) { break; } CabTexcoord texcoord; texcoord.node_id = GetNodeIndexOrThrow(texcoord_itor->node); @@ -1335,14 +1197,11 @@ void ActorSpawner::ProcessSubmesh(RigDef::Submesh & def) /* CAB */ - auto cab_itor = def.cab_triangles.begin(); + auto cab_itor = def.cab_triangles.begin(); auto cab_itor_end = def.cab_triangles.end(); - for ( ; cab_itor != cab_itor_end; ++cab_itor) + for (; cab_itor != cab_itor_end; ++cab_itor) { - if (! CheckCabLimit(1)) - { - return; - } + if (!CheckCabLimit(1)) { return; } else if (m_actor->ar_num_collcabs >= MAX_CABS) { std::stringstream msg; @@ -1353,42 +1212,41 @@ void ActorSpawner::ProcessSubmesh(RigDef::Submesh & def) bool mk_buoyance = false; - m_actor->ar_cabs[m_actor->ar_num_cabs*3]=GetNodeIndexOrThrow(cab_itor->nodes[0]); - m_actor->ar_cabs[m_actor->ar_num_cabs*3+1]=GetNodeIndexOrThrow(cab_itor->nodes[1]); - m_actor->ar_cabs[m_actor->ar_num_cabs*3+2]=GetNodeIndexOrThrow(cab_itor->nodes[2]); + m_actor->ar_cabs[m_actor->ar_num_cabs * 3] = GetNodeIndexOrThrow(cab_itor->nodes[0]); + m_actor->ar_cabs[m_actor->ar_num_cabs * 3 + 1] = GetNodeIndexOrThrow(cab_itor->nodes[1]); + m_actor->ar_cabs[m_actor->ar_num_cabs * 3 + 2] = GetNodeIndexOrThrow(cab_itor->nodes[2]); // TODO: Clean this up properly ~ ulteq 10/2018 if (BITMASK_IS_1(cab_itor->options, RigDef::Cab::OPTION_c_CONTACT) || BITMASK_IS_1(cab_itor->options, RigDef::Cab::OPTION_p_10xTOUGHER) || BITMASK_IS_1(cab_itor->options, RigDef::Cab::OPTION_u_INVULNERABLE)) { - m_actor->ar_collcabs[m_actor->ar_num_collcabs]=m_actor->ar_num_cabs; + m_actor->ar_collcabs[m_actor->ar_num_collcabs] = m_actor->ar_num_cabs; m_actor->ar_num_collcabs++; } if (BITMASK_IS_1(cab_itor->options, RigDef::Cab::OPTION_b_BUOYANT)) { - m_actor->ar_buoycabs[m_actor->ar_num_buoycabs]=m_actor->ar_num_cabs; - m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs]=Buoyance::BUOY_NORMAL; - m_actor->ar_num_buoycabs++; + m_actor->ar_buoycabs[m_actor->ar_num_buoycabs] = m_actor->ar_num_cabs; + m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs] = Buoyance::BUOY_NORMAL; + m_actor->ar_num_buoycabs++; mk_buoyance = true; } if (BITMASK_IS_1(cab_itor->options, RigDef::Cab::OPTION_r_BUOYANT_ONLY_DRAG)) { - m_actor->ar_buoycabs[m_actor->ar_num_buoycabs]=m_actor->ar_num_cabs; - m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs]=Buoyance::BUOY_DRAGONLY; - m_actor->ar_num_buoycabs++; + m_actor->ar_buoycabs[m_actor->ar_num_buoycabs] = m_actor->ar_num_cabs; + m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs] = Buoyance::BUOY_DRAGONLY; + m_actor->ar_num_buoycabs++; mk_buoyance = true; } if (BITMASK_IS_1(cab_itor->options, RigDef::Cab::OPTION_s_BUOYANT_NO_DRAG)) { - m_actor->ar_buoycabs[m_actor->ar_num_buoycabs]=m_actor->ar_num_cabs; - m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs]=Buoyance::BUOY_DRAGLESS; - m_actor->ar_num_buoycabs++; + m_actor->ar_buoycabs[m_actor->ar_num_buoycabs] = m_actor->ar_num_cabs; + m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs] = Buoyance::BUOY_DRAGLESS; + m_actor->ar_num_buoycabs++; mk_buoyance = true; } - if (cab_itor->GetOption_D_ContactBuoyant() || - cab_itor->GetOption_F_10xTougherBuoyant() || + if (cab_itor->GetOption_D_ContactBuoyant() || cab_itor->GetOption_F_10xTougherBuoyant() || cab_itor->GetOption_S_UnpenetrableBuoyant()) { @@ -1407,27 +1265,27 @@ void ActorSpawner::ProcessSubmesh(RigDef::Submesh & def) return; } - m_actor->ar_collcabs[m_actor->ar_num_collcabs]=m_actor->ar_num_cabs; + m_actor->ar_collcabs[m_actor->ar_num_collcabs] = m_actor->ar_num_cabs; m_actor->ar_num_collcabs++; - m_actor->ar_buoycabs[m_actor->ar_num_buoycabs]=m_actor->ar_num_cabs; - m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs]=Buoyance::BUOY_NORMAL; - m_actor->ar_num_buoycabs++; + m_actor->ar_buoycabs[m_actor->ar_num_buoycabs] = m_actor->ar_num_cabs; + m_actor->ar_buoycab_types[m_actor->ar_num_buoycabs] = Buoyance::BUOY_NORMAL; + m_actor->ar_num_buoycabs++; mk_buoyance = true; } if (mk_buoyance && (m_actor->m_buoyance == nullptr)) { - auto& dustman = App::GetSimController()->GetGfxScene(); - Buoyance* buoy = new Buoyance(dustman.GetDustPool("splash"), dustman.GetDustPool("ripple")); + auto & dustman = App::GetSimController()->GetGfxScene(); + Buoyance *buoy = new Buoyance(dustman.GetDustPool("splash"), dustman.GetDustPool("ripple")); m_actor->m_buoyance.reset(buoy); } m_actor->ar_num_cabs++; } - //close the current mesh + // close the current mesh CabSubmesh submesh; submesh.texcoords_pos = m_oldstyle_cab_texcoords.size(); - submesh.cabs_pos = static_cast(m_actor->ar_num_cabs); + submesh.cabs_pos = static_cast(m_actor->ar_num_cabs); submesh.backmesh_type = CabSubmesh::BACKMESH_NONE; m_oldstyle_cab_submeshes.push_back(submesh); @@ -1437,25 +1295,24 @@ void ActorSpawner::ProcessSubmesh(RigDef::Submesh & def) { // Check limit - if (! CheckCabLimit(1)) - { - return; - } + if (!CheckCabLimit(1)) { return; } // === add an extra front mesh === - //texcoords - int uv_start = (m_oldstyle_cab_submeshes.size()==1) ? 0 : static_cast((m_oldstyle_cab_submeshes.rbegin()+1)->texcoords_pos); - for (size_t i=uv_start; i((m_oldstyle_cab_submeshes.rbegin() + 1)->texcoords_pos); + for (size_t i = uv_start; i < m_oldstyle_cab_submeshes.back().texcoords_pos; i++) { m_oldstyle_cab_texcoords.push_back(m_oldstyle_cab_texcoords[i]); } - //cab - int cab_start = (m_oldstyle_cab_submeshes.size()==1) ? 0 : static_cast((m_oldstyle_cab_submeshes.rbegin()+1)->cabs_pos); - for (size_t i=cab_start; i((m_oldstyle_cab_submeshes.rbegin() + 1)->cabs_pos); + for (size_t i = cab_start; i < m_oldstyle_cab_submeshes.back().cabs_pos; i++) { - m_actor->ar_cabs[m_actor->ar_num_cabs*3]=m_actor->ar_cabs[i*3]; - m_actor->ar_cabs[m_actor->ar_num_cabs*3+1]=m_actor->ar_cabs[i*3+1]; - m_actor->ar_cabs[m_actor->ar_num_cabs*3+2]=m_actor->ar_cabs[i*3+2]; + m_actor->ar_cabs[m_actor->ar_num_cabs * 3] = m_actor->ar_cabs[i * 3]; + m_actor->ar_cabs[m_actor->ar_num_cabs * 3 + 1] = m_actor->ar_cabs[i * 3 + 1]; + m_actor->ar_cabs[m_actor->ar_num_cabs * 3 + 2] = m_actor->ar_cabs[i * 3 + 2]; m_actor->ar_num_cabs++; } // Finalize @@ -1466,27 +1323,29 @@ void ActorSpawner::ProcessSubmesh(RigDef::Submesh & def) m_oldstyle_cab_submeshes.push_back(submesh); // === add an extra back mesh === - //texcoords - uv_start = (m_oldstyle_cab_submeshes.size()==1) ? 0 : static_cast((m_oldstyle_cab_submeshes.rbegin()+1)->texcoords_pos); - for (size_t i=uv_start; i((m_oldstyle_cab_submeshes.rbegin() + 1)->texcoords_pos); + for (size_t i = uv_start; i < m_oldstyle_cab_submeshes.back().texcoords_pos; i++) { m_oldstyle_cab_texcoords.push_back(m_oldstyle_cab_texcoords[i]); } - //cab - cab_start = (m_oldstyle_cab_submeshes.size()==1) ? 0 : static_cast((m_oldstyle_cab_submeshes.rbegin()+1)->cabs_pos); - for (size_t i=cab_start; i((m_oldstyle_cab_submeshes.rbegin() + 1)->cabs_pos); + for (size_t i = cab_start; i < m_oldstyle_cab_submeshes.back().cabs_pos; i++) { - m_actor->ar_cabs[m_actor->ar_num_cabs*3]=m_actor->ar_cabs[i*3+1]; - m_actor->ar_cabs[m_actor->ar_num_cabs*3+1]=m_actor->ar_cabs[i*3]; - m_actor->ar_cabs[m_actor->ar_num_cabs*3+2]=m_actor->ar_cabs[i*3+2]; + m_actor->ar_cabs[m_actor->ar_num_cabs * 3] = m_actor->ar_cabs[i * 3 + 1]; + m_actor->ar_cabs[m_actor->ar_num_cabs * 3 + 1] = m_actor->ar_cabs[i * 3]; + m_actor->ar_cabs[m_actor->ar_num_cabs * 3 + 2] = m_actor->ar_cabs[i * 3 + 2]; m_actor->ar_num_cabs++; } - - //close the current mesh + + // close the current mesh CabSubmesh submesh2; submesh2.texcoords_pos = m_oldstyle_cab_texcoords.size(); - submesh2.cabs_pos = static_cast(m_actor->ar_num_cabs); + submesh2.cabs_pos = static_cast(m_actor->ar_num_cabs); submesh2.backmesh_type = CabSubmesh::BACKMESH_OPAQUE; m_oldstyle_cab_submeshes.push_back(submesh2); } @@ -1496,8 +1355,8 @@ void ActorSpawner::ProcessFlexbody(std::shared_ptr def) { // Collect nodes std::vector node_indices; - bool nodes_found = true; - for (auto& node_def: def->node_list) + bool nodes_found = true; + for (auto &node_def : def->node_list) { auto result = this->GetNodeIndex(node_def); if (!result.second) @@ -1508,7 +1367,7 @@ void ActorSpawner::ProcessFlexbody(std::shared_ptr def) node_indices.push_back(result.first); } - if (! nodes_found) + if (!nodes_found) { this->AddMessage(Message::TYPE_ERROR, "Failed to collect nodes from node-ranges, skipping flexbody: " + def->mesh_name); return; @@ -1523,17 +1382,16 @@ void ActorSpawner::ProcessFlexbody(std::shared_ptr def) return; } - Ogre::Quaternion rot=Ogre::Quaternion(Ogre::Degree(def->rotation.z), Ogre::Vector3::UNIT_Z); - rot=rot*Ogre::Quaternion(Ogre::Degree(def->rotation.y), Ogre::Vector3::UNIT_Y); - rot=rot*Ogre::Quaternion(Ogre::Degree(def->rotation.x), Ogre::Vector3::UNIT_X); + Ogre::Quaternion rot = Ogre::Quaternion(Ogre::Degree(def->rotation.z), Ogre::Vector3::UNIT_Z); + rot = rot * Ogre::Quaternion(Ogre::Degree(def->rotation.y), Ogre::Vector3::UNIT_Y); + rot = rot * Ogre::Quaternion(Ogre::Degree(def->rotation.x), Ogre::Vector3::UNIT_X); try { - auto* flexbody = m_flex_factory.CreateFlexBody( - def.get(), reference_node, x_axis_node, y_axis_node, rot, node_indices, m_custom_resource_group); + auto *flexbody = m_flex_factory.CreateFlexBody(def.get(), reference_node, x_axis_node, y_axis_node, rot, node_indices, + m_custom_resource_group); - if (flexbody == nullptr) - return; // Error already logged + if (flexbody == nullptr) return; // Error already logged if (def->camera_settings.mode == RigDef::CameraSettings::MODE_CINECAM) flexbody->setCameraMode(static_cast(def->camera_settings.cinecam_index)); @@ -1542,40 +1400,37 @@ void ActorSpawner::ProcessFlexbody(std::shared_ptr def) m_actor->GetGfxActor()->AddFlexbody(flexbody); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - this->AddMessage(Message::TYPE_ERROR, - "Failed to create flexbody '" + def->mesh_name + "', reason:" + e.getFullDescription()); + this->AddMessage(Message::TYPE_ERROR, + "Failed to create flexbody '" + def->mesh_name + "', reason:" + e.getFullDescription()); } } -void ActorSpawner::ProcessProp(RigDef::Prop & def) +void ActorSpawner::ProcessProp(RigDef::Prop &def) { prop_t prop; - int prop_index = static_cast(m_props.size()); + int prop_index = static_cast(m_props.size()); memset(&prop, 0, sizeof(prop_t)); - prop.noderef = GetNodeIndexOrThrow(def.reference_node); - prop.nodex = FindNodeIndex(def.x_axis_node); - prop.nodey = FindNodeIndex(def.y_axis_node); - if (prop.nodex == -1 || prop.nodey == -1) - { - return; - } - prop.offsetx = def.offset.x; - prop.offsety = def.offset.y; - prop.offsetz = def.offset.z; - prop.orgoffsetX = def.offset.x; - prop.orgoffsetY = def.offset.y; - prop.orgoffsetZ = def.offset.z; - prop.rotaX = def.rotation.x; - prop.rotaY = def.rotation.y; - prop.rotaZ = def.rotation.z; - prop.rot = Ogre::Quaternion(Ogre::Degree(def.rotation.z), Ogre::Vector3::UNIT_Z); - prop.rot = prop.rot * Ogre::Quaternion(Ogre::Degree(def.rotation.y), Ogre::Vector3::UNIT_Y); - prop.rot = prop.rot * Ogre::Quaternion(Ogre::Degree(def.rotation.x), Ogre::Vector3::UNIT_X); - prop.cameramode = def.camera_settings.mode; /* Handles default value */ - prop.wheelrotdegree = 160.f; + prop.noderef = GetNodeIndexOrThrow(def.reference_node); + prop.nodex = FindNodeIndex(def.x_axis_node); + prop.nodey = FindNodeIndex(def.y_axis_node); + if (prop.nodex == -1 || prop.nodey == -1) { return; } + prop.offsetx = def.offset.x; + prop.offsety = def.offset.y; + prop.offsetz = def.offset.z; + prop.orgoffsetX = def.offset.x; + prop.orgoffsetY = def.offset.y; + prop.orgoffsetZ = def.offset.z; + prop.rotaX = def.rotation.x; + prop.rotaY = def.rotation.y; + prop.rotaZ = def.rotation.z; + prop.rot = Ogre::Quaternion(Ogre::Degree(def.rotation.z), Ogre::Vector3::UNIT_Z); + prop.rot = prop.rot * Ogre::Quaternion(Ogre::Degree(def.rotation.y), Ogre::Vector3::UNIT_Y); + prop.rot = prop.rot * Ogre::Quaternion(Ogre::Degree(def.rotation.x), Ogre::Vector3::UNIT_X); + prop.cameramode = def.camera_settings.mode; /* Handles default value */ + prop.wheelrotdegree = 160.f; /* Set no animation by default */ prop.animKey[0] = -1; prop.animKeyState[0] = -1.f; @@ -1585,53 +1440,40 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) /* Rear view mirror (left) */ if (def.special == RigDef::Prop::SPECIAL_MIRROR_LEFT) { - prop.mirror = 1; + prop.mirror = 1; m_curr_mirror_prop_type = CustomMaterial::MirrorPropType::MPROP_LEFT; } /* Rear view mirror (right) */ if (def.special == RigDef::Prop::SPECIAL_MIRROR_RIGHT) { - prop.mirror = -1; + prop.mirror = -1; m_curr_mirror_prop_type = CustomMaterial::MirrorPropType::MPROP_RIGHT; } /* Custom steering wheel */ Ogre::Vector3 steering_wheel_offset = Ogre::Vector3::ZERO; - if (def.special == RigDef::Prop::SPECIAL_DASHBOARD_LEFT) - { - steering_wheel_offset = Ogre::Vector3(-0.67, -0.61,0.24); - } - if (def.special == RigDef::Prop::SPECIAL_DASHBOARD_RIGHT) - { - steering_wheel_offset = Ogre::Vector3(0.67, -0.61,0.24); - } + if (def.special == RigDef::Prop::SPECIAL_DASHBOARD_LEFT) { steering_wheel_offset = Ogre::Vector3(-0.67, -0.61, 0.24); } + if (def.special == RigDef::Prop::SPECIAL_DASHBOARD_RIGHT) { steering_wheel_offset = Ogre::Vector3(0.67, -0.61, 0.24); } if (steering_wheel_offset != Ogre::Vector3::ZERO) { - if (def.special_prop_dashboard._offset_is_set) - { - steering_wheel_offset = def.special_prop_dashboard.offset; - } - prop.wheelrotdegree = def.special_prop_dashboard.rotation_angle; - prop.wheel = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - prop.wheelpos = steering_wheel_offset; + if (def.special_prop_dashboard._offset_is_set) { steering_wheel_offset = def.special_prop_dashboard.offset; } + prop.wheelrotdegree = def.special_prop_dashboard.rotation_angle; + prop.wheel = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + prop.wheelpos = steering_wheel_offset; const std::string instance_name = this->ComposeName("SteeringWheelPropEntity", prop_index); - prop.wheelmo = new MeshObject( - def.special_prop_dashboard.mesh_name, - m_custom_resource_group, - instance_name, - prop.wheel - ); + prop.wheelmo = new MeshObject(def.special_prop_dashboard.mesh_name, m_custom_resource_group, instance_name, prop.wheel); this->SetupNewEntity(prop.wheelmo->getEntity(), Ogre::ColourValue(0, 0.5, 0.5)); } /* CREATE THE PROP */ - prop.scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + prop.scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); const std::string instance_name = this->ComposeName("PropEntity", prop_index); - prop.mo = new MeshObject(def.mesh_name, m_custom_resource_group, instance_name, prop.scene_node); - prop.mo->setCastShadows(true); // Orig code {{ prop.mo->setCastShadows(shadowmode != 0); }}, shadowmode has default value 1 and changes with undocumented directive 'set_shadows' - prop.beacontype = 'n'; // Orig: hardcoded in BTS_PROPS + prop.mo = new MeshObject(def.mesh_name, m_custom_resource_group, instance_name, prop.scene_node); + prop.mo->setCastShadows(true); // Orig code {{ prop.mo->setCastShadows(shadowmode != 0); }}, shadowmode has default value 1 + // and changes with undocumented directive 'set_shadows' + prop.beacontype = 'n'; // Orig: hardcoded in BTS_PROPS if (def.special == RigDef::Prop::SPECIAL_AERO_PROP_SPIN) { @@ -1639,13 +1481,13 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) prop.mo->setCastShadows(false); prop.scene_node->setVisible(false); } - else if(def.special == RigDef::Prop::SPECIAL_AERO_PROP_BLADE) + else if (def.special == RigDef::Prop::SPECIAL_AERO_PROP_BLADE) { prop.pp_aero_propeller_blade = true; } - else if(def.special == RigDef::Prop::SPECIAL_DRIVER_SEAT) + else if (def.special == RigDef::Prop::SPECIAL_DRIVER_SEAT) { - //driver seat, used to position the driver and make the seat translucent at times + // driver seat, used to position the driver and make the seat translucent at times if (m_driverseat_prop_index == -1) { m_driverseat_prop_index = prop_index; @@ -1653,43 +1495,42 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) } else { - this->AddMessage(Message::TYPE_INFO, "Found more than one 'seat[2]' special props. Only the first one will be the driver's seat."); + this->AddMessage(Message::TYPE_INFO, + "Found more than one 'seat[2]' special props. Only the first one will be the driver's seat."); } } - else if(def.special == RigDef::Prop::SPECIAL_DRIVER_SEAT_2) + else if (def.special == RigDef::Prop::SPECIAL_DRIVER_SEAT_2) { // Same as DRIVER_SEAT, except it doesn't force the "driversseat" material - if (m_driverseat_prop_index == -1) - { - m_driverseat_prop_index = prop_index; - } + if (m_driverseat_prop_index == -1) { m_driverseat_prop_index = prop_index; } else { - this->AddMessage(Message::TYPE_INFO, "Found more than one 'seat[2]' special props. Only the first one will be the driver's seat."); + this->AddMessage(Message::TYPE_INFO, + "Found more than one 'seat[2]' special props. Only the first one will be the driver's seat."); } } else if (m_actor->m_flares_mode != GfxFlaresMode::NONE) { - if(def.special == RigDef::Prop::SPECIAL_BEACON) + if (def.special == RigDef::Prop::SPECIAL_BEACON) { - prop.beacontype = 'b'; + prop.beacontype = 'b'; prop.beacon_light_rotation_angle[0] = 2.0 * 3.14 * frand(); - prop.beacon_light_rotation_rate[0] = 4.0 * 3.14 + frand() - 0.5; + prop.beacon_light_rotation_rate[0] = 4.0 * 3.14 + frand() - 0.5; /* the light */ auto beacon_light = gEnv->sceneManager->createLight(); beacon_light->setType(Ogre::Light::LT_SPOTLIGHT); beacon_light->setDiffuseColour(def.special_prop_beacon.color); beacon_light->setSpecularColour(def.special_prop_beacon.color); beacon_light->setAttenuation(50.0, 1.0, 0.3, 0.0); - beacon_light->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) ); + beacon_light->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(45)); beacon_light->setCastShadows(false); beacon_light->setVisible(false); /* the flare billboard */ - auto flare_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + auto flare_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); auto flare_billboard_sys = gEnv->sceneManager->createBillboardSet(1); //(propname,1); if (flare_billboard_sys) { - flare_billboard_sys->createBillboard(0,0,0); + flare_billboard_sys->createBillboard(0, 0, 0); flare_billboard_sys->setMaterialName(def.special_prop_beacon.flare_material_name); flare_billboard_sys->setVisibilityFlags(DEPTHMAP_DISABLED); flare_scene_node->attachObject(flare_billboard_sys); @@ -1698,28 +1539,28 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) // Complete prop.beacon_flare_billboard_scene_node[0] = flare_scene_node; - prop.beacon_flares_billboard_system[0] = flare_billboard_sys; - prop.beacon_light[0] = beacon_light; + prop.beacon_flares_billboard_system[0] = flare_billboard_sys; + prop.beacon_light[0] = beacon_light; } - else if(def.special == RigDef::Prop::SPECIAL_REDBEACON) + else if (def.special == RigDef::Prop::SPECIAL_REDBEACON) { prop.beacon_light_rotation_angle[0] = 0.f; - prop.beacon_light_rotation_rate[0] = 1.0; - prop.beacontype = 'r'; - //the light - auto beacon_light=gEnv->sceneManager->createLight();//propname); + prop.beacon_light_rotation_rate[0] = 1.0; + prop.beacontype = 'r'; + // the light + auto beacon_light = gEnv->sceneManager->createLight(); // propname); beacon_light->setType(Ogre::Light::LT_POINT); - beacon_light->setDiffuseColour( Ogre::ColourValue(1.0, 0.0, 0.0)); - beacon_light->setSpecularColour( Ogre::ColourValue(1.0, 0.0, 0.0)); + beacon_light->setDiffuseColour(Ogre::ColourValue(1.0, 0.0, 0.0)); + beacon_light->setSpecularColour(Ogre::ColourValue(1.0, 0.0, 0.0)); beacon_light->setAttenuation(50.0, 1.0, 0.3, 0.0); beacon_light->setCastShadows(false); beacon_light->setVisible(false); - //the flare billboard - auto flare_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - auto flare_billboard_sys = gEnv->sceneManager->createBillboardSet(1); //propname,1); + // the flare billboard + auto flare_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + auto flare_billboard_sys = gEnv->sceneManager->createBillboardSet(1); // propname,1); if (flare_billboard_sys) { - flare_billboard_sys->createBillboard(0,0,0); + flare_billboard_sys->createBillboard(0, 0, 0); flare_billboard_sys->setMaterialName("tracks/redbeaconflare"); flare_billboard_sys->setVisibilityFlags(DEPTHMAP_DISABLED); flare_billboard_sys->setDefaultDimensions(1.0, 1.0); @@ -1728,47 +1569,43 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) flare_scene_node->setVisible(false); // Finalize - prop.beacon_light[0] = beacon_light; + prop.beacon_light[0] = beacon_light; prop.beacon_flare_billboard_scene_node[0] = flare_scene_node; - prop.beacon_flares_billboard_system[0] = flare_billboard_sys; - + prop.beacon_flares_billboard_system[0] = flare_billboard_sys; } - else if(def.special == RigDef::Prop::SPECIAL_LIGHTBAR) + else if (def.special == RigDef::Prop::SPECIAL_LIGHTBAR) { m_actor->ar_is_police = true; - prop.beacontype='p'; - for (int k=0; k<4; k++) + prop.beacontype = 'p'; + for (int k = 0; k < 4; k++) { - prop.beacon_light_rotation_angle[k] = 2.0 * 3.14 * frand(); - prop.beacon_light_rotation_rate[k] = 4.0 * 3.14 + frand() - 0.5; + prop.beacon_light_rotation_angle[k] = 2.0 * 3.14 * frand(); + prop.beacon_light_rotation_rate[k] = 4.0 * 3.14 + frand() - 0.5; prop.beacon_flares_billboard_system[k] = nullptr; - //the light - prop.beacon_light[k]=gEnv->sceneManager->createLight(); + // the light + prop.beacon_light[k] = gEnv->sceneManager->createLight(); prop.beacon_light[k]->setType(Ogre::Light::LT_SPOTLIGHT); - if (k>1) + if (k > 1) { - prop.beacon_light[k]->setDiffuseColour( Ogre::ColourValue(1.0, 0.0, 0.0)); - prop.beacon_light[k]->setSpecularColour( Ogre::ColourValue(1.0, 0.0, 0.0)); + prop.beacon_light[k]->setDiffuseColour(Ogre::ColourValue(1.0, 0.0, 0.0)); + prop.beacon_light[k]->setSpecularColour(Ogre::ColourValue(1.0, 0.0, 0.0)); } else { - prop.beacon_light[k]->setDiffuseColour( Ogre::ColourValue(0.0, 0.5, 1.0)); - prop.beacon_light[k]->setSpecularColour( Ogre::ColourValue(0.0, 0.5, 1.0)); + prop.beacon_light[k]->setDiffuseColour(Ogre::ColourValue(0.0, 0.5, 1.0)); + prop.beacon_light[k]->setSpecularColour(Ogre::ColourValue(0.0, 0.5, 1.0)); } prop.beacon_light[k]->setAttenuation(50.0, 1.0, 0.3, 0.0); - prop.beacon_light[k]->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) ); + prop.beacon_light[k]->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(45)); prop.beacon_light[k]->setCastShadows(false); prop.beacon_light[k]->setVisible(false); - //the flare billboard + // the flare billboard prop.beacon_flare_billboard_scene_node[k] = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - prop.beacon_flares_billboard_system[k]=gEnv->sceneManager->createBillboardSet(1); - prop.beacon_flares_billboard_system[k]->createBillboard(0,0,0); + prop.beacon_flares_billboard_system[k] = gEnv->sceneManager->createBillboardSet(1); + prop.beacon_flares_billboard_system[k]->createBillboard(0, 0, 0); if (prop.beacon_flares_billboard_system[k]) { - if (k>1) - { - prop.beacon_flares_billboard_system[k]->setMaterialName("tracks/brightredflare"); - } + if (k > 1) { prop.beacon_flares_billboard_system[k]->setMaterialName("tracks/brightredflare"); } else { prop.beacon_flares_billboard_system[k]->setMaterialName("tracks/brightblueflare"); @@ -1782,34 +1619,33 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) } if (m_curr_mirror_prop_type != CustomMaterial::MirrorPropType::MPROP_NONE) - { - m_curr_mirror_prop_scenenode = prop.mo->GetSceneNode(); - } + { m_curr_mirror_prop_scenenode = prop.mo->GetSceneNode(); } } this->SetupNewEntity(prop.mo->getEntity(), Ogre::ColourValue(1.f, 1.f, 0.f)); m_curr_mirror_prop_scenenode = nullptr; - m_curr_mirror_prop_type = CustomMaterial::MirrorPropType::MPROP_NONE; + m_curr_mirror_prop_type = CustomMaterial::MirrorPropType::MPROP_NONE; /* PROCESS ANIMATIONS */ if (def.animations.size() > 10) { std::stringstream msg; - msg << "Prop (mesh: " << def.mesh_name << ") has too many animations: " << def.animations.size() << " (max. is 10). Using first 10 ..."; + msg << "Prop (mesh: " << def.mesh_name << ") has too many animations: " << def.animations.size() + << " (max. is 10). Using first 10 ..."; AddMessage(Message::TYPE_WARNING, msg.str()); } - std::list::iterator anim_itor = def.animations.begin(); - int anim_index = 0; + std::list::iterator anim_itor = def.animations.begin(); + int anim_index = 0; while (anim_itor != def.animations.end() && anim_index < 10) { prop.animKeyState[anim_index] = -1.0f; // Orig: hardcoded in {add_animation} /* Arg #1: ratio */ prop.animratio[anim_index] = anim_itor->ratio; - if (anim_itor->ratio == 0) + if (anim_itor->ratio == 0) { std::stringstream msg; msg << "Prop (mesh: " << def.mesh_name << ") has invalid animation ratio (0), using it anyway (compatibility)..."; @@ -1823,164 +1659,141 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) prop.constraints[anim_index].upper_limit = anim_itor->upper_limit; /* Handles default */ /* Arg #4: source */ - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AIRSPEED)) { /* (NOTE: code formatting relaxed) */ + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AIRSPEED)) + { /* (NOTE: code formatting relaxed) */ BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AIRSPEED); } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_VERTICAL_VELOCITY)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_VVI); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ALTIMETER_100K)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_VERTICAL_VELOCITY)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_VVI); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ALTIMETER_100K)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ALTIMETER); prop.animOpt3[anim_index] = 1.f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ALTIMETER_10K)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ALTIMETER_10K)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ALTIMETER); prop.animOpt3[anim_index] = 2.f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ALTIMETER_1K)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ALTIMETER_1K)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ALTIMETER); prop.animOpt3[anim_index] = 3.f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ANGLE_OF_ATTACK)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AOA); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_FLAP)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_FLAP); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AIR_BRAKE)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AIRBRAKE); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ROLL)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ROLL); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_PITCH)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_PITCH); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_BRAKES)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_BRAKE); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ACCEL)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ACCEL); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_CLUTCH)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_CLUTCH); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SPEEDO)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_SPEEDO); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_TACHO)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_TACHO); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_TURBO)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_TURBO); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_PARKING)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_PBRAKE); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SHIFT_LEFT_RIGHT)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ANGLE_OF_ATTACK)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AOA); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_FLAP)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_FLAP); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AIR_BRAKE)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AIRBRAKE); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ROLL)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ROLL); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_PITCH)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_PITCH); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_BRAKES)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_BRAKE); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ACCEL)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ACCEL); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_CLUTCH)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_CLUTCH); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SPEEDO)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_SPEEDO); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_TACHO)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_TACHO); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_TURBO)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_TURBO); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_PARKING)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_PBRAKE); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SHIFT_LEFT_RIGHT)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_SHIFTER); prop.animOpt3[anim_index] = 1.0f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SHIFT_BACK_FORTH)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SHIFT_BACK_FORTH)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_SHIFTER); prop.animOpt3[anim_index] = 2.0f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SEQUENTIAL_SHIFT)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SEQUENTIAL_SHIFT)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_SHIFTER); prop.animOpt3[anim_index] = 3.0f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SHIFTERLIN)) { + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_SHIFTERLIN)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_SHIFTER); prop.animOpt3[anim_index] = 4.0f; } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_TORQUE)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_TORQUE); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_HEADING)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_HEADING); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_DIFFLOCK)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_DIFFLOCK); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_STEERING_WHEEL)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_STEERING); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AILERON)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AILERONS); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ELEVATOR)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ELEVATORS); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AIR_RUDDER)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ARUDDER); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_BOAT_RUDDER)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_BRUDDER); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_BOAT_THROTTLE)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_BTHROTTLE); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_PERMANENT)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_PERMANENT); - } - if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_EVENT)) { - BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_EVENT); - } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_TORQUE)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_TORQUE); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_HEADING)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_HEADING); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_DIFFLOCK)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_DIFFLOCK); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_STEERING_WHEEL)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_STEERING); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AILERON)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AILERONS); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_ELEVATOR)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ELEVATORS); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_AIR_RUDDER)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_ARUDDER); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_BOAT_RUDDER)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_BRUDDER); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_BOAT_THROTTLE)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_BTHROTTLE); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_PERMANENT)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_PERMANENT); } + if (BITMASK_IS_1(anim_itor->source, RigDef::Animation::SOURCE_EVENT)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_EVENT); } /* Motor-indexed sources */ std::list::iterator source_itor = anim_itor->motor_sources.begin(); - for ( ; source_itor != anim_itor->motor_sources.end(); source_itor++) + for (; source_itor != anim_itor->motor_sources.end(); source_itor++) { - if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_THROTTLE)) { + if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_THROTTLE)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_THROTTLE); prop.animOpt3[anim_index] = static_cast(source_itor->motor); } - if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_RPM)) { + if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_RPM)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_RPM); prop.animOpt3[anim_index] = static_cast(source_itor->motor); } - if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_TORQUE)) { + if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_TORQUE)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AETORQUE); prop.animOpt3[anim_index] = static_cast(source_itor->motor); } - if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_PITCH)) { + if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_PITCH)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AEPITCH); prop.animOpt3[anim_index] = static_cast(source_itor->motor); } - if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_STATUS)) { + if (BITMASK_IS_1(source_itor->source, RigDef::Animation::MotorSource::SOURCE_AERO_STATUS)) + { BITMASK_SET_1(prop.animFlags[anim_index], ANIM_FLAG_AESTATUS); prop.animOpt3[anim_index] = static_cast(source_itor->motor); } } - if (prop.animFlags[anim_index] == 0) - { - AddMessage(Message::TYPE_ERROR, "Failed to identify animation source"); - } + if (prop.animFlags[anim_index] == 0) { AddMessage(Message::TYPE_ERROR, "Failed to identify animation source"); } /* Anim modes */ - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_X)) { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_ROTA_X); - } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Y)) { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_ROTA_Y); - } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Z)) { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_ROTA_Z); - } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_X)) { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_OFFSET_X); - } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Y)) { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_OFFSET_Y); - } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Z)) { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_OFFSET_Z); - } - if (prop.animMode[anim_index] == 0) - { - AddMessage(Message::TYPE_ERROR, "Failed to identify animation mode"); - } - - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_AUTO_ANIMATE)) + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_X)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_ROTA_X); } + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Y)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_ROTA_Y); } + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Z)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_ROTA_Z); } + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_X)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_OFFSET_X); } + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Y)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_OFFSET_Y); } + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Z)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_OFFSET_Z); } + if (prop.animMode[anim_index] == 0) { AddMessage(Message::TYPE_ERROR, "Failed to identify animation mode"); } + + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_AUTO_ANIMATE)) { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_AUTOANIMATE); @@ -1988,58 +1801,71 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) const bool use_default_lower_limit = (anim_itor->lower_limit == 0.f); const bool use_default_upper_limit = (anim_itor->upper_limit == 0.f); - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_X)) { - prop.constraints[anim_index].lower_limit = (use_default_lower_limit) ? (-180.f) : (anim_itor->lower_limit + prop.rotaX); - prop.constraints[anim_index].upper_limit = (use_default_upper_limit) ? ( 180.f) : (anim_itor->upper_limit + prop.rotaX); + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_X)) + { + prop.constraints[anim_index].lower_limit = + (use_default_lower_limit) ? (-180.f) : (anim_itor->lower_limit + prop.rotaX); + prop.constraints[anim_index].upper_limit = + (use_default_upper_limit) ? (180.f) : (anim_itor->upper_limit + prop.rotaX); } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Y)) { - prop.constraints[anim_index].lower_limit = (use_default_lower_limit) ? (-180.f) : (anim_itor->lower_limit + prop.rotaY); - prop.constraints[anim_index].upper_limit = (use_default_upper_limit) ? ( 180.f) : (anim_itor->upper_limit + prop.rotaY); + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Y)) + { + prop.constraints[anim_index].lower_limit = + (use_default_lower_limit) ? (-180.f) : (anim_itor->lower_limit + prop.rotaY); + prop.constraints[anim_index].upper_limit = + (use_default_upper_limit) ? (180.f) : (anim_itor->upper_limit + prop.rotaY); } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Z)) { - prop.constraints[anim_index].lower_limit = (use_default_lower_limit) ? (-180.f) : (anim_itor->lower_limit + prop.rotaZ); - prop.constraints[anim_index].upper_limit = (use_default_upper_limit) ? ( 180.f) : (anim_itor->upper_limit + prop.rotaZ); + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_ROTATION_Z)) + { + prop.constraints[anim_index].lower_limit = + (use_default_lower_limit) ? (-180.f) : (anim_itor->lower_limit + prop.rotaZ); + prop.constraints[anim_index].upper_limit = + (use_default_upper_limit) ? (180.f) : (anim_itor->upper_limit + prop.rotaZ); } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_X)) { - prop.constraints[anim_index].lower_limit = (use_default_lower_limit) ? (-10.f) : (anim_itor->lower_limit + prop.orgoffsetX); - prop.constraints[anim_index].upper_limit = (use_default_upper_limit) ? ( 10.f) : (anim_itor->upper_limit + prop.orgoffsetX); + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_X)) + { + prop.constraints[anim_index].lower_limit = + (use_default_lower_limit) ? (-10.f) : (anim_itor->lower_limit + prop.orgoffsetX); + prop.constraints[anim_index].upper_limit = + (use_default_upper_limit) ? (10.f) : (anim_itor->upper_limit + prop.orgoffsetX); } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Y)) { - prop.constraints[anim_index].lower_limit = (use_default_lower_limit) ? (-10.f) : (anim_itor->lower_limit + prop.orgoffsetY); - prop.constraints[anim_index].upper_limit = (use_default_upper_limit) ? ( 10.f) : (anim_itor->upper_limit + prop.orgoffsetY); + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Y)) + { + prop.constraints[anim_index].lower_limit = + (use_default_lower_limit) ? (-10.f) : (anim_itor->lower_limit + prop.orgoffsetY); + prop.constraints[anim_index].upper_limit = + (use_default_upper_limit) ? (10.f) : (anim_itor->upper_limit + prop.orgoffsetY); } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Z)) { - prop.constraints[anim_index].lower_limit = (use_default_lower_limit) ? (-10.f) : (anim_itor->lower_limit + prop.orgoffsetZ); - prop.constraints[anim_index].upper_limit = (use_default_upper_limit) ? ( 10.f) : (anim_itor->upper_limit + prop.orgoffsetZ); + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_OFFSET_Z)) + { + prop.constraints[anim_index].lower_limit = + (use_default_lower_limit) ? (-10.f) : (anim_itor->lower_limit + prop.orgoffsetZ); + prop.constraints[anim_index].upper_limit = + (use_default_upper_limit) ? (10.f) : (anim_itor->upper_limit + prop.orgoffsetZ); } } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_NO_FLIP)) - { - BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_NOFLIP); - } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_BOUNCE)) + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_NO_FLIP)) + { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_NOFLIP); } + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_BOUNCE)) { BITMASK_SET_1(prop.animMode[anim_index], ANIM_MODE_BOUNCE); prop.animOpt5[anim_index] = 1.f; } - if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_EVENT_LOCK)) + if (BITMASK_IS_1(anim_itor->mode, RigDef::Animation::MODE_EVENT_LOCK)) { prop.animKeyState[anim_index] = 0.0f; - prop.lastanimKS[anim_index] = 0.0f; + prop.lastanimKS[anim_index] = 0.0f; } - + /* Parameter 'event:' */ - if (! anim_itor->event.empty()) + if (!anim_itor->event.empty()) { // we are using keys as source prop.animFlags[anim_index] |= ANIM_FLAG_EVENT; int event_id = RoR::App::GetInputEngine()->resolveEventName(anim_itor->event); - if (event_id == -1) - { - AddMessage(Message::TYPE_ERROR, "Unknown animation event: " + anim_itor->event); - } + if (event_id == -1) { AddMessage(Message::TYPE_ERROR, "Unknown animation event: " + anim_itor->event); } else { prop.animKey[anim_index] = event_id; @@ -2053,30 +1879,25 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) m_props.push_back(prop); } -void ActorSpawner::ProcessFlare2(RigDef::Flare2 & def) +void ActorSpawner::ProcessFlare2(RigDef::Flare2 &def) { if (m_actor->m_flares_mode == GfxFlaresMode::NONE) { return; } - int blink_delay = def.blink_delay_milis; - float size = def.size; + int blink_delay = def.blink_delay_milis; + float size = def.size; /* Backwards compatibility */ - if (blink_delay == -2) + if (blink_delay == -2) { if (def.type == RigDef::Flare2::TYPE_l_LEFT_BLINKER || def.type == RigDef::Flare2::TYPE_r_RIGHT_BLINKER) - { - blink_delay = -1; /* Default blink */ - } + { blink_delay = -1; /* Default blink */ } else { blink_delay = 0; /* Default no blink */ } } - - if (size == -2.f && def.type == RigDef::Flare2::TYPE_f_HEADLIGHT) - { - size = 1.f; - } + + if (size == -2.f && def.type == RigDef::Flare2::TYPE_f_HEADLIGHT) { size = 1.f; } else if ((size == -2.f && def.type != RigDef::Flare2::TYPE_f_HEADLIGHT) || size == -1.f) { size = 0.5f; @@ -2098,26 +1919,24 @@ void ActorSpawner::ProcessFlare2(RigDef::Flare2 & def) flare.size = size; /* Visuals */ - flare.snode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - std::string flare_name = this->ComposeName("Flare", static_cast(m_actor->ar_flares.size())); - flare.bbs = gEnv->sceneManager->createBillboardSet(flare_name, 1); + flare.snode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + std::string flare_name = this->ComposeName("Flare", static_cast(m_actor->ar_flares.size())); + flare.bbs = gEnv->sceneManager->createBillboardSet(flare_name, 1); bool using_default_material = true; if (flare.bbs == nullptr) { - AddMessage(Message::TYPE_WARNING, "Failed to create flare: '" + flare_name + "', continuing without it (compatibility)..."); + AddMessage(Message::TYPE_WARNING, + "Failed to create flare: '" + flare_name + "', continuing without it (compatibility)..."); } else { - flare.bbs->createBillboard(0,0,0); + flare.bbs->createBillboard(0, 0, 0); flare.bbs->setVisibilityFlags(DEPTHMAP_DISABLED); std::string material_name = def.material_name; - using_default_material = (material_name.length() == 0 || material_name == "default"); + using_default_material = (material_name.length() == 0 || material_name == "default"); if (using_default_material) { - if (def.type == RigDef::Flare2::TYPE_b_BRAKELIGHT) - { - material_name = "tracks/brakeflare"; - } + if (def.type == RigDef::Flare2::TYPE_b_BRAKELIGHT) { material_name = "tracks/brakeflare"; } else if (def.type == RigDef::Flare2::TYPE_l_LEFT_BLINKER || (def.type == RigDef::Flare2::TYPE_r_RIGHT_BLINKER)) { material_name = "tracks/blinkflare"; @@ -2135,61 +1954,61 @@ void ActorSpawner::ProcessFlare2(RigDef::Flare2 & def) } } flare.isVisible = true; - flare.light = nullptr; + flare.light = nullptr; if ((App::gfx_flares_mode.GetActive() >= GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY) && size > 0.001) { - //if (type == 'f' && usingDefaultMaterial && flaresMode >=2 && size > 0.001) - if (def.type == RigDef::Flare2::TYPE_f_HEADLIGHT && using_default_material ) + // if (type == 'f' && usingDefaultMaterial && flaresMode >=2 && size > 0.001) + if (def.type == RigDef::Flare2::TYPE_f_HEADLIGHT && using_default_material) { /* front light */ - flare.light=gEnv->sceneManager->createLight(flare_name); + flare.light = gEnv->sceneManager->createLight(flare_name); flare.light->setType(Ogre::Light::LT_SPOTLIGHT); - flare.light->setDiffuseColour( Ogre::ColourValue(1, 1, 1)); - flare.light->setSpecularColour( Ogre::ColourValue(1, 1, 1)); + flare.light->setDiffuseColour(Ogre::ColourValue(1, 1, 1)); + flare.light->setSpecularColour(Ogre::ColourValue(1, 1, 1)); flare.light->setAttenuation(400, 0.9, 0, 0); - flare.light->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) ); + flare.light->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(45)); flare.light->setCastShadows(false); } } if ((App::gfx_flares_mode.GetActive() >= GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS) && size > 0.001) { - if (def.type == RigDef::Flare2::TYPE_f_HEADLIGHT && ! using_default_material) + if (def.type == RigDef::Flare2::TYPE_f_HEADLIGHT && !using_default_material) { /* this is a quick fix for the red backlight when frontlight is switched on */ - flare.light=gEnv->sceneManager->createLight(flare_name); - flare.light->setDiffuseColour( Ogre::ColourValue(1.0, 0, 0)); - flare.light->setSpecularColour( Ogre::ColourValue(1.0, 0, 0)); + flare.light = gEnv->sceneManager->createLight(flare_name); + flare.light->setDiffuseColour(Ogre::ColourValue(1.0, 0, 0)); + flare.light->setSpecularColour(Ogre::ColourValue(1.0, 0, 0)); flare.light->setAttenuation(10.0, 1.0, 0, 0); } else if (def.type == RigDef::Flare2::TYPE_R_REVERSE_LIGHT) { - flare.light=gEnv->sceneManager->createLight(flare_name); + flare.light = gEnv->sceneManager->createLight(flare_name); flare.light->setDiffuseColour(Ogre::ColourValue(1, 1, 1)); flare.light->setSpecularColour(Ogre::ColourValue(1, 1, 1)); flare.light->setAttenuation(20.0, 1, 0, 0); } else if (def.type == RigDef::Flare2::TYPE_b_BRAKELIGHT) { - flare.light=gEnv->sceneManager->createLight(flare_name); - flare.light->setDiffuseColour( Ogre::ColourValue(1.0, 0, 0)); - flare.light->setSpecularColour( Ogre::ColourValue(1.0, 0, 0)); + flare.light = gEnv->sceneManager->createLight(flare_name); + flare.light->setDiffuseColour(Ogre::ColourValue(1.0, 0, 0)); + flare.light->setSpecularColour(Ogre::ColourValue(1.0, 0, 0)); flare.light->setAttenuation(10.0, 1.0, 0, 0); } else if (def.type == RigDef::Flare2::TYPE_l_LEFT_BLINKER || (def.type == RigDef::Flare2::TYPE_r_RIGHT_BLINKER)) { - flare.light=gEnv->sceneManager->createLight(flare_name); - flare.light->setDiffuseColour( Ogre::ColourValue(1, 1, 0)); - flare.light->setSpecularColour( Ogre::ColourValue(1, 1, 0)); + flare.light = gEnv->sceneManager->createLight(flare_name); + flare.light->setDiffuseColour(Ogre::ColourValue(1, 1, 0)); + flare.light->setSpecularColour(Ogre::ColourValue(1, 1, 0)); flare.light->setAttenuation(10.0, 1, 1, 0); } - //else if ((type == 'u') && flaresMode >= 4 && size > 0.001) + // else if ((type == 'u') && flaresMode >= 4 && size > 0.001) else if (def.type == RigDef::Flare2::TYPE_u_USER) { /* user light always white (TODO: improve this) */ - flare.light=gEnv->sceneManager->createLight(flare_name); - flare.light->setDiffuseColour( Ogre::ColourValue(1, 1, 1)); - flare.light->setSpecularColour( Ogre::ColourValue(1, 1, 1)); + flare.light = gEnv->sceneManager->createLight(flare_name); + flare.light->setDiffuseColour(Ogre::ColourValue(1, 1, 1)); + flare.light->setSpecularColour(Ogre::ColourValue(1, 1, 1)); flare.light->setAttenuation(50.0, 1.0, 1, 0.2); if (m_actor->m_net_custom_light_count < 4) @@ -2204,13 +2023,13 @@ void ActorSpawner::ProcessFlare2(RigDef::Flare2 & def) if (flare.light != nullptr) { flare.light->setType(Ogre::Light::LT_SPOTLIGHT); - flare.light->setSpotlightRange( Ogre::Degree(35), Ogre::Degree(45) ); + flare.light->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(45)); flare.light->setCastShadows(false); } m_actor->ar_flares.push_back(flare); } -Ogre::MaterialPtr ActorSpawner::InstantiateManagedMaterial(Ogre::String const & source_name, Ogre::String const & clone_name) +Ogre::MaterialPtr ActorSpawner::InstantiateManagedMaterial(Ogre::String const &source_name, Ogre::String const &clone_name) { Ogre::MaterialPtr src_mat = Ogre::MaterialManager::getSingleton().getByName(source_name); if (src_mat.isNull()) @@ -2224,7 +2043,7 @@ Ogre::MaterialPtr ActorSpawner::InstantiateManagedMaterial(Ogre::String const & return src_mat->clone(clone_name, true, m_custom_resource_group); } -void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) +void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial &def) { if (m_managed_materials.find(def.name) != m_managed_materials.end()) { @@ -2236,18 +2055,16 @@ void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) // This is necessary to load meshes with original material names (= unchanged managed mat names) // - if not found, OGRE substitutes them with 'BaseWhite' which breaks subsequent processing. if (Ogre::MaterialManager::getSingleton().getByName(def.name, m_custom_resource_group).isNull()) - { - m_placeholder_managedmat->clone(def.name, /*changeGroup=*/true, m_custom_resource_group); - } + { m_placeholder_managedmat->clone(def.name, /*changeGroup=*/true, m_custom_resource_group); } - std::string custom_name = def.name + ACTOR_ID_TOKEN + TOSTRING(m_actor->ar_instance_id); + std::string custom_name = def.name + ACTOR_ID_TOKEN + TOSTRING(m_actor->ar_instance_id); Ogre::MaterialPtr material; - if (def.type == RigDef::ManagedMaterial::TYPE_FLEXMESH_STANDARD || def.type == RigDef::ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT) + if (def.type == RigDef::ManagedMaterial::TYPE_FLEXMESH_STANDARD || + def.type == RigDef::ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT) { - std::string mat_name_base - = (def.type == RigDef::ManagedMaterial::TYPE_FLEXMESH_STANDARD) - ? "managed/flexmesh_standard" - : "managed/flexmesh_transparent"; + std::string mat_name_base = (def.type == RigDef::ManagedMaterial::TYPE_FLEXMESH_STANDARD) + ? "managed/flexmesh_standard" + : "managed/flexmesh_transparent"; if (def.HasDamagedDiffuseMap()) { @@ -2255,24 +2072,33 @@ void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) { /* FLEXMESH, damage, specular */ material = this->InstantiateManagedMaterial(mat_name_base + "/speculardamage", custom_name); - if (material.isNull()) - { - return; - } - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Diffuse_Map")->setTextureName(def.diffuse_map); - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Dmg_Diffuse_Map")->setTextureName(def.damaged_diffuse_map); - material->getTechnique("BaseTechnique")->getPass("SpecularMapping1")->getTextureUnitState("SpecularMapping1_Tex")->setTextureName(def.specular_map); + if (material.isNull()) { return; } + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Diffuse_Map") + ->setTextureName(def.diffuse_map); + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Dmg_Diffuse_Map") + ->setTextureName(def.damaged_diffuse_map); + material->getTechnique("BaseTechnique") + ->getPass("SpecularMapping1") + ->getTextureUnitState("SpecularMapping1_Tex") + ->setTextureName(def.specular_map); } else { /* FLEXMESH, damage, no_specular */ material = this->InstantiateManagedMaterial(mat_name_base + "/damageonly", custom_name); - if (material.isNull()) - { - return; - } - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Diffuse_Map")->setTextureName(def.diffuse_map); - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Dmg_Diffuse_Map")->setTextureName(def.damaged_diffuse_map); + if (material.isNull()) { return; } + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Diffuse_Map") + ->setTextureName(def.diffuse_map); + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Dmg_Diffuse_Map") + ->setTextureName(def.damaged_diffuse_map); } } else @@ -2281,53 +2107,57 @@ void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) { /* FLEXMESH, no_damage, specular */ material = this->InstantiateManagedMaterial(mat_name_base + "/specularonly", custom_name); - if (material.isNull()) - { - return; - } - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Diffuse_Map")->setTextureName(def.diffuse_map); - material->getTechnique("BaseTechnique")->getPass("SpecularMapping1")->getTextureUnitState("SpecularMapping1_Tex")->setTextureName(def.specular_map); + if (material.isNull()) { return; } + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Diffuse_Map") + ->setTextureName(def.diffuse_map); + material->getTechnique("BaseTechnique") + ->getPass("SpecularMapping1") + ->getTextureUnitState("SpecularMapping1_Tex") + ->setTextureName(def.specular_map); } else { /* FLEXMESH, no_damage, no_specular */ material = this->InstantiateManagedMaterial(mat_name_base + "/simple", custom_name); - if (material.isNull()) - { - return; - } - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Diffuse_Map")->setTextureName(def.diffuse_map); + if (material.isNull()) { return; } + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Diffuse_Map") + ->setTextureName(def.diffuse_map); } } } - else if (def.type == RigDef::ManagedMaterial::TYPE_MESH_STANDARD || def.type == RigDef::ManagedMaterial::TYPE_MESH_TRANSPARENT) + else if (def.type == RigDef::ManagedMaterial::TYPE_MESH_STANDARD || + def.type == RigDef::ManagedMaterial::TYPE_MESH_TRANSPARENT) { - Ogre::String mat_name_base - = (def.type == RigDef::ManagedMaterial::TYPE_MESH_STANDARD) - ? "managed/mesh_standard" - : "managed/mesh_transparent"; + Ogre::String mat_name_base = + (def.type == RigDef::ManagedMaterial::TYPE_MESH_STANDARD) ? "managed/mesh_standard" : "managed/mesh_transparent"; if (def.HasSpecularMap()) { /* MESH, specular */ material = this->InstantiateManagedMaterial(mat_name_base + "/specular", custom_name); - if (material.isNull()) - { - return; - } - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Diffuse_Map")->setTextureName(def.diffuse_map); - material->getTechnique("BaseTechnique")->getPass("SpecularMapping1")->getTextureUnitState("SpecularMapping1_Tex")->setTextureName(def.specular_map); + if (material.isNull()) { return; } + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Diffuse_Map") + ->setTextureName(def.diffuse_map); + material->getTechnique("BaseTechnique") + ->getPass("SpecularMapping1") + ->getTextureUnitState("SpecularMapping1_Tex") + ->setTextureName(def.specular_map); } else { /* MESH, no_specular */ material = this->InstantiateManagedMaterial(mat_name_base + "/simple", custom_name); - if (material.isNull()) - { - return; - } - material->getTechnique("BaseTechnique")->getPass("BaseRender")->getTextureUnitState("Diffuse_Map")->setTextureName(def.diffuse_map); - + if (material.isNull()) { return; } + material->getTechnique("BaseTechnique") + ->getPass("BaseRender") + ->getTextureUnitState("Diffuse_Map") + ->setTextureName(def.diffuse_map); } } @@ -2337,9 +2167,7 @@ void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) { material->getTechnique("BaseTechnique")->getPass("BaseRender")->setCullingMode(Ogre::CULL_NONE); if (def.HasSpecularMap()) - { - material->getTechnique("BaseTechnique")->getPass("SpecularMapping1")->setCullingMode(Ogre::CULL_NONE); - } + { material->getTechnique("BaseTechnique")->getPass("SpecularMapping1")->setCullingMode(Ogre::CULL_NONE); } } } @@ -2349,13 +2177,13 @@ void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) m_managed_materials.insert(std::make_pair(def.name, material)); } -void ActorSpawner::ProcessCollisionBox(RigDef::CollisionBox & def) +void ActorSpawner::ProcessCollisionBox(RigDef::CollisionBox &def) { int8_t bbox_id = static_cast(m_actor->ar_collision_bounding_boxes.size()); - for (RigDef::Node::Ref& node_ref: def.nodes) + for (RigDef::Node::Ref &node_ref : def.nodes) { std::pair node_result = this->GetNodeIndex(node_ref); - if (! node_result.second) + if (!node_result.second) { RoR::LogFormat("[RoR|Spawner] Collision box: skipping invalid node '%s'", node_ref.ToString().c_str()); continue; @@ -2363,9 +2191,7 @@ void ActorSpawner::ProcessCollisionBox(RigDef::CollisionBox & def) if (m_actor->ar_nodes[node_result.first].nd_coll_bbox_id != node_t::INVALID_BBOX) { RoR::LogFormat("[RoR|Spawner] Collision box: re-assigning node '%s' from box ID '%d' to '%d'", - node_ref.ToString().c_str(), - m_actor->ar_nodes[node_result.first].nd_coll_bbox_id, - bbox_id); + node_ref.ToString().c_str(), m_actor->ar_nodes[node_result.first].nd_coll_bbox_id, bbox_id); } m_actor->ar_nodes[node_result.first].nd_coll_bbox_id = bbox_id; } @@ -2374,14 +2200,13 @@ void ActorSpawner::ProcessCollisionBox(RigDef::CollisionBox & def) m_actor->ar_predicted_coll_bounding_boxes.push_back(Ogre::AxisAlignedBox()); } -bool ActorSpawner::AssignWheelToAxle(int & _out_axle_wheel, node_t *axis_node_1, node_t *axis_node_2) +bool ActorSpawner::AssignWheelToAxle(int &_out_axle_wheel, node_t *axis_node_1, node_t *axis_node_2) { for (int i = 0; i < m_actor->ar_num_wheels; i++) { - wheel_t & wheel = m_actor->ar_wheels[i]; - if ( (wheel.wh_axis_node_0 == axis_node_1 && wheel.wh_axis_node_1 == axis_node_2) - || (wheel.wh_axis_node_0 == axis_node_2 && wheel.wh_axis_node_1 == axis_node_1) - ) + wheel_t &wheel = m_actor->ar_wheels[i]; + if ((wheel.wh_axis_node_0 == axis_node_1 && wheel.wh_axis_node_1 == axis_node_2) || + (wheel.wh_axis_node_0 == axis_node_2 && wheel.wh_axis_node_1 == axis_node_1)) { _out_axle_wheel = i; return true; @@ -2390,12 +2215,9 @@ bool ActorSpawner::AssignWheelToAxle(int & _out_axle_wheel, node_t *axis_node_1, return false; } -void ActorSpawner::ProcessAxle(RigDef::Axle & def) +void ActorSpawner::ProcessAxle(RigDef::Axle &def) { - if (! CheckAxleLimit(1)) - { - return; - } + if (!CheckAxleLimit(1)) { return; } node_t *wheel_1_node_1 = GetNodePointerOrThrow(def.wheels[0][0]); node_t *wheel_1_node_2 = GetNodePointerOrThrow(def.wheels[0][1]); @@ -2404,19 +2226,19 @@ void ActorSpawner::ProcessAxle(RigDef::Axle & def) Differential *diff = new Differential(); - if (! AssignWheelToAxle(diff->di_idx_1, wheel_1_node_1, wheel_1_node_2)) + if (!AssignWheelToAxle(diff->di_idx_1, wheel_1_node_1, wheel_1_node_2)) { std::stringstream msg; - msg << "Couldn't find wheel with axis nodes '" << def.wheels[0][0].ToString() - << "' and '" << def.wheels[0][1].ToString() << "'"; + msg << "Couldn't find wheel with axis nodes '" << def.wheels[0][0].ToString() << "' and '" << def.wheels[0][1].ToString() + << "'"; AddMessage(Message::TYPE_WARNING, msg.str()); } - if (! AssignWheelToAxle(diff->di_idx_2, wheel_2_node_1, wheel_2_node_2)) + if (!AssignWheelToAxle(diff->di_idx_2, wheel_2_node_1, wheel_2_node_2)) { std::stringstream msg; - msg << "Couldn't find wheel with axis nodes '" << def.wheels[1][0].ToString() - << "' and '" << def.wheels[1][1].ToString() << "'"; + msg << "Couldn't find wheel with axis nodes '" << def.wheels[1][0].ToString() << "' and '" << def.wheels[1][1].ToString() + << "'"; AddMessage(Message::TYPE_WARNING, msg.str()); } @@ -2433,21 +2255,11 @@ void ActorSpawner::ProcessAxle(RigDef::Axle & def) { switch (*itor) { - case RigDef::Axle::OPTION_l_LOCKED: - diff->AddDifferentialType(LOCKED_DIFF); - break; - case RigDef::Axle::OPTION_o_OPEN: - diff->AddDifferentialType(OPEN_DIFF); - break; - case RigDef::Axle::OPTION_s_SPLIT: - diff->AddDifferentialType(SPLIT_DIFF); - break; - case RigDef::Axle::OPTION_s_VISCOUS: - diff->AddDifferentialType(VISCOUS_DIFF); - break; - default: - AddMessage(Message::TYPE_WARNING, "Unknown differential type: " + *itor); - break; + case RigDef::Axle::OPTION_l_LOCKED: diff->AddDifferentialType(LOCKED_DIFF); break; + case RigDef::Axle::OPTION_o_OPEN: diff->AddDifferentialType(OPEN_DIFF); break; + case RigDef::Axle::OPTION_s_SPLIT: diff->AddDifferentialType(SPLIT_DIFF); break; + case RigDef::Axle::OPTION_s_VISCOUS: diff->AddDifferentialType(VISCOUS_DIFF); break; + default: AddMessage(Message::TYPE_WARNING, "Unknown differential type: " + *itor); break; } } } @@ -2456,9 +2268,9 @@ void ActorSpawner::ProcessAxle(RigDef::Axle & def) m_actor->m_num_wheel_diffs++; } -void ActorSpawner::ProcessInterAxle(RigDef::InterAxle & def) +void ActorSpawner::ProcessInterAxle(RigDef::InterAxle &def) { - if (def.a1 == def.a2 || std::min(def.a1, def.a2) < 0 || std::max(def.a1 , def.a2) >= m_actor->m_num_wheel_diffs) + if (def.a1 == def.a2 || std::min(def.a1, def.a2) < 0 || std::max(def.a1, def.a2) >= m_actor->m_num_wheel_diffs) { AddMessage(Message::TYPE_ERROR, "Invalid 'interaxle' axle ids, skipping..."); return; @@ -2469,7 +2281,9 @@ void ActorSpawner::ProcessInterAxle(RigDef::InterAxle & def) if ((m_actor->m_transfer_case->tr_ax_1 == def.a1 && m_actor->m_transfer_case->tr_ax_2 == def.a2) || (m_actor->m_transfer_case->tr_ax_1 == def.a2 && m_actor->m_transfer_case->tr_ax_2 == def.a1)) { - AddMessage(Message::TYPE_ERROR, "You cannot have both an inter-axle differential and a transfercase between the same two axles, skipping..."); + AddMessage( + Message::TYPE_ERROR, + "You cannot have both an inter-axle differential and a transfercase between the same two axles, skipping..."); return; } } @@ -2491,21 +2305,11 @@ void ActorSpawner::ProcessInterAxle(RigDef::InterAxle & def) { switch (*itor) { - case RigDef::Axle::OPTION_l_LOCKED: - diff->AddDifferentialType(LOCKED_DIFF); - break; - case RigDef::Axle::OPTION_o_OPEN: - diff->AddDifferentialType(OPEN_DIFF); - break; - case RigDef::Axle::OPTION_s_SPLIT: - diff->AddDifferentialType(SPLIT_DIFF); - break; - case RigDef::Axle::OPTION_s_VISCOUS: - diff->AddDifferentialType(VISCOUS_DIFF); - break; - default: - AddMessage(Message::TYPE_WARNING, "Unknown differential type: " + *itor); - break; + case RigDef::Axle::OPTION_l_LOCKED: diff->AddDifferentialType(LOCKED_DIFF); break; + case RigDef::Axle::OPTION_o_OPEN: diff->AddDifferentialType(OPEN_DIFF); break; + case RigDef::Axle::OPTION_s_SPLIT: diff->AddDifferentialType(SPLIT_DIFF); break; + case RigDef::Axle::OPTION_s_VISCOUS: diff->AddDifferentialType(VISCOUS_DIFF); break; + default: AddMessage(Message::TYPE_WARNING, "Unknown differential type: " + *itor); break; } } } @@ -2514,9 +2318,9 @@ void ActorSpawner::ProcessInterAxle(RigDef::InterAxle & def) m_actor->m_num_axle_diffs++; } -void ActorSpawner::ProcessTransferCase(RigDef::TransferCase & def) +void ActorSpawner::ProcessTransferCase(RigDef::TransferCase &def) { - if (def.a1 == def.a2 || def.a1 < 0 || std::max(def.a1 , def.a2) >= m_actor->m_num_wheel_diffs) + if (def.a1 == def.a2 || def.a1 < 0 || std::max(def.a1, def.a2) >= m_actor->m_num_wheel_diffs) { AddMessage(Message::TYPE_ERROR, "Invalid 'transfercase' axle ids, skipping..."); return; @@ -2542,29 +2346,29 @@ void ActorSpawner::ProcessTransferCase(RigDef::TransferCase & def) } m_actor->ar_wheels[m_actor->m_wheel_diffs[def.a1]->di_idx_1].wh_propulsed = true; m_actor->ar_wheels[m_actor->m_wheel_diffs[def.a1]->di_idx_2].wh_propulsed = true; - m_actor->m_num_proped_wheels = 2; + m_actor->m_num_proped_wheels = 2; if (!def.has_2wd) { m_actor->ar_wheels[m_actor->m_wheel_diffs[def.a2]->di_idx_1].wh_propulsed = true; m_actor->ar_wheels[m_actor->m_wheel_diffs[def.a2]->di_idx_2].wh_propulsed = true; - m_actor->m_num_proped_wheels = 4; - m_actor->m_transfer_case->tr_4wd_mode = true; + m_actor->m_num_proped_wheels = 4; + m_actor->m_transfer_case->tr_4wd_mode = true; } } -void ActorSpawner::ProcessCruiseControl(RigDef::CruiseControl & def) +void ActorSpawner::ProcessCruiseControl(RigDef::CruiseControl &def) { m_actor->cc_target_speed_lower_limit = def.min_speed; if (m_actor->cc_target_speed_lower_limit <= 0.f) { std::stringstream msg; - msg << "Invalid parameter 'lower_limit' (" << m_actor->cc_target_speed_lower_limit + msg << "Invalid parameter 'lower_limit' (" << m_actor->cc_target_speed_lower_limit << ") must be positive nonzero number. Using it anyway (compatibility)"; } m_actor->cc_can_brake = def.autobrake != 0; } -void ActorSpawner::ProcessTorqueCurve(RigDef::TorqueCurve & def) +void ActorSpawner::ProcessTorqueCurve(RigDef::TorqueCurve &def) { if (m_actor->ar_engine == nullptr) { @@ -2574,40 +2378,34 @@ void ActorSpawner::ProcessTorqueCurve(RigDef::TorqueCurve & def) TorqueCurve *target_torque_curve = m_actor->ar_engine->getTorqueCurve(); - if (def.predefined_func_name.length() != 0) - { - target_torque_curve->setTorqueModel(def.predefined_func_name); - } + if (def.predefined_func_name.length() != 0) { target_torque_curve->setTorqueModel(def.predefined_func_name); } else { target_torque_curve->CreateNewCurve(); /* Use default name for custom curve */ std::vector::iterator itor = def.samples.begin(); - for ( ; itor != def.samples.end(); itor++) + for (; itor != def.samples.end(); itor++) { target_torque_curve->AddCurveSample(itor->power, itor->torque_percent); } } } -void ActorSpawner::ProcessParticle(RigDef::Particle & def) +void ActorSpawner::ProcessParticle(RigDef::Particle &def) { - if (App::gfx_particles_mode.GetActive() != 1) - { - return; - } + if (App::gfx_particles_mode.GetActive() != 1) { return; } - int particle_index = m_actor->ar_num_custom_particles; - cparticle_t & particle = m_actor->ar_custom_particles[particle_index]; + int particle_index = m_actor->ar_num_custom_particles; + cparticle_t &particle = m_actor->ar_custom_particles[particle_index]; - particle.emitterNode = GetNodeIndexOrThrow(def.emitter_node); + particle.emitterNode = GetNodeIndexOrThrow(def.emitter_node); particle.directionNode = GetNodeIndexOrThrow(def.reference_node); std::string name = this->ComposeName(def.particle_system_name.c_str(), particle_index); - particle.psys = this->CreateParticleSystem(name, def.particle_system_name); + particle.psys = this->CreateParticleSystem(name, def.particle_system_name); if (particle.psys == nullptr) { std::stringstream msg; - msg << "Failed to create particle system '" << name << "' (template: '" << def.particle_system_name <<"')"; + msg << "Failed to create particle system '" << name << "' (template: '" << def.particle_system_name << "')"; AddMessage(Message::TYPE_ERROR, msg.str()); return; } @@ -2617,7 +2415,7 @@ void ActorSpawner::ProcessParticle(RigDef::Particle & def) particle.snode->setPosition(this->GetNode(particle.emitterNode).AbsPosition); /* Shut down the emitters */ - particle.active = false; + particle.active = false; for (unsigned int i = 0; i < particle.psys->getNumEmitters(); i++) { particle.psys->getEmitter(i)->setEnabled(false); @@ -2626,122 +2424,116 @@ void ActorSpawner::ProcessParticle(RigDef::Particle & def) ++m_actor->ar_num_custom_particles; } -void ActorSpawner::ProcessRopable(RigDef::Ropable & def) +void ActorSpawner::ProcessRopable(RigDef::Ropable &def) { ropable_t ropable; - ropable.node = GetNodePointerOrThrow(def.node); - ropable.pos = static_cast(m_actor->ar_ropables.size()); - ropable.group = def.group; - ropable.attached_ties = 0; + ropable.node = GetNodePointerOrThrow(def.node); + ropable.pos = static_cast(m_actor->ar_ropables.size()); + ropable.group = def.group; + ropable.attached_ties = 0; ropable.attached_ropes = 0; - ropable.multilock = def.has_multilock; + ropable.multilock = def.has_multilock; m_actor->ar_ropables.push_back(ropable); } -void ActorSpawner::ProcessTie(RigDef::Tie & def) +void ActorSpawner::ProcessTie(RigDef::Tie &def) { - node_t & node_1 = GetNodeOrThrow(def.root_node); - node_t & node_2 = GetNode( (node_1.pos == 0) ? 1 : 0 ); + node_t &node_1 = GetNodeOrThrow(def.root_node); + node_t &node_2 = GetNode((node_1.pos == 0) ? 1 : 0); - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); SetBeamStrength(beam, def.beam_defaults->GetScaledBreakingThreshold()); - beam.k = def.beam_defaults->GetScaledSpringiness(); - beam.d = def.beam_defaults->GetScaledDamping(); - beam.bm_type = BEAM_HYDRO; - beam.L = def.max_reach_length; - beam.refL = def.max_reach_length; - beam.bounded = ROPE; + beam.k = def.beam_defaults->GetScaledSpringiness(); + beam.d = def.beam_defaults->GetScaledDamping(); + beam.bm_type = BEAM_HYDRO; + beam.L = def.max_reach_length; + beam.refL = def.max_reach_length; + beam.bounded = ROPE; beam.bm_disabled = true; - if (!def.is_invisible) - { - this->CreateBeamVisuals(beam, beam_index, false, def.beam_defaults); - } + if (!def.is_invisible) { this->CreateBeamVisuals(beam, beam_index, false, def.beam_defaults); } /* Register tie */ tie_t tie; - tie.ti_group = def.group; - tie.ti_tying = false; - tie.ti_tied = false; - tie.ti_beam = & beam; + tie.ti_group = def.group; + tie.ti_tying = false; + tie.ti_tied = false; + tie.ti_beam = &beam; tie.ti_locked_actor = nullptr; tie.ti_locked_ropable = nullptr; tie.ti_contract_speed = def.auto_shorten_rate; - tie.ti_max_stress = def.max_stress; - tie.ti_min_length = def.min_length; - tie.ti_no_self_lock = def.disable_self_lock; + tie.ti_max_stress = def.max_stress; + tie.ti_min_length = def.min_length; + tie.ti_no_self_lock = def.disable_self_lock; m_actor->ar_ties.push_back(tie); m_actor->m_has_command_beams = true; } -void ActorSpawner::ProcessRope(RigDef::Rope & def) +void ActorSpawner::ProcessRope(RigDef::Rope &def) { - node_t & root_node = GetNodeOrThrow(def.root_node); - node_t & end_node = GetNodeOrThrow(def.end_node); + node_t &root_node = GetNodeOrThrow(def.root_node); + node_t &end_node = GetNodeOrThrow(def.end_node); /* Add beam */ - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(root_node, end_node, def.beam_defaults, def.detacher_group); + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(root_node, end_node, def.beam_defaults, def.detacher_group); SetBeamStrength(beam, def.beam_defaults->GetScaledBreakingThreshold()); - beam.k = def.beam_defaults->GetScaledSpringiness(); - beam.d = def.beam_defaults->GetScaledDamping(); + beam.k = def.beam_defaults->GetScaledSpringiness(); + beam.d = def.beam_defaults->GetScaledDamping(); beam.bounded = ROPE; beam.bm_type = BEAM_HYDRO; - beam.L = root_node.AbsPosition.distance(end_node.AbsPosition); - beam.refL = beam.L; + beam.L = root_node.AbsPosition.distance(end_node.AbsPosition); + beam.refL = beam.L; this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults, "tracks/beam"); /* Register rope */ rope_t rope; - rope.rp_beam = & beam; - rope.rp_locked = UNLOCKED; + rope.rp_beam = &beam; + rope.rp_locked = UNLOCKED; rope.rp_locked_ropable = nullptr; - rope.rp_group = 0; // Orig: hardcoded in BTS_ROPES. TODO: To be used. + rope.rp_group = 0; // Orig: hardcoded in BTS_ROPES. TODO: To be used. m_actor->ar_ropes.push_back(rope); } -void ActorSpawner::ProcessRailGroup(RigDef::RailGroup & def) +void ActorSpawner::ProcessRailGroup(RigDef::RailGroup &def) { - RailGroup* rail_group = this->CreateRail(def.node_list); - rail_group->rg_id = def.id; + RailGroup *rail_group = this->CreateRail(def.node_list); + rail_group->rg_id = def.id; m_actor->m_railgroups.push_back(rail_group); } -void ActorSpawner::ProcessSlidenode(RigDef::SlideNode & def) +void ActorSpawner::ProcessSlidenode(RigDef::SlideNode &def) { - node_t & node = GetNodeOrThrow(def.slide_node); - SlideNode slide_node(& node, nullptr); + node_t & node = GetNodeOrThrow(def.slide_node); + SlideNode slide_node(&node, nullptr); slide_node.SetCorThreshold(def.tolerance); slide_node.SetSpringRate(def.spring_rate); slide_node.SetAttachmentRate(def.attachment_rate); - if (def._break_force_set) - { - slide_node.SetBreakForce(def.break_force); - } + if (def._break_force_set) { slide_node.SetBreakForce(def.break_force); } slide_node.SetAttachmentDistance(def.max_attachment_distance); // Constraints if (BITMASK_IS_1(def.constraint_flags, RigDef::SlideNode::CONSTRAINT_ATTACH_ALL)) { - slide_node.sn_attach_self = true; + slide_node.sn_attach_self = true; slide_node.sn_attach_foreign = true; } if (BITMASK_IS_1(def.constraint_flags, RigDef::SlideNode::CONSTRAINT_ATTACH_SELF)) { - slide_node.sn_attach_self = true; + slide_node.sn_attach_self = true; slide_node.sn_attach_foreign = false; } if (BITMASK_IS_1(def.constraint_flags, RigDef::SlideNode::CONSTRAINT_ATTACH_FOREIGN)) { - slide_node.sn_attach_self = false; + slide_node.sn_attach_self = false; slide_node.sn_attach_foreign = true; } if (BITMASK_IS_1(def.constraint_flags, RigDef::SlideNode::CONSTRAINT_ATTACH_NONE)) { - slide_node.sn_attach_self = false; + slide_node.sn_attach_self = false; slide_node.sn_attach_foreign = false; } @@ -2749,8 +2541,8 @@ void ActorSpawner::ProcessSlidenode(RigDef::SlideNode & def) RailGroup *rail_group = nullptr; if (def._railgroup_id_set) { - std::vector::iterator itor = m_actor->m_railgroups.begin(); - for ( ; itor != m_actor->m_railgroups.end(); itor++) + std::vector::iterator itor = m_actor->m_railgroups.begin(); + for (; itor != m_actor->m_railgroups.end(); itor++) { if ((*itor)->rg_id == def.railgroup_id) { @@ -2770,10 +2562,7 @@ void ActorSpawner::ProcessSlidenode(RigDef::SlideNode & def) else if (def.rail_node_ranges.size() > 0) { rail_group = this->CreateRail(def.rail_node_ranges); - if (rail_group != nullptr) - { - m_actor->m_railgroups.push_back(rail_group); - } + if (rail_group != nullptr) { m_actor->m_railgroups.push_back(rail_group); } } else { @@ -2784,16 +2573,13 @@ void ActorSpawner::ProcessSlidenode(RigDef::SlideNode & def) m_actor->m_slidenodes.push_back(slide_node); } -int ActorSpawner::FindNodeIndex(RigDef::Node::Ref & node_ref, bool silent /* Default: false */) +int ActorSpawner::FindNodeIndex(RigDef::Node::Ref &node_ref, bool silent /* Default: false */) { std::pair result = GetNodeIndex(node_ref, /* quiet */ true); - if (result.second) - { - return static_cast(result.first); - } + if (result.second) { return static_cast(result.first); } else { - if (! silent) + if (!silent) { std::stringstream msg; msg << "Failed to find node by reference: " << node_ref.ToString(); @@ -2803,27 +2589,22 @@ int ActorSpawner::FindNodeIndex(RigDef::Node::Ref & node_ref, bool silent /* Def } } -bool ActorSpawner::CollectNodesFromRanges( - std::vector & node_ranges, - std::vector & out_node_indices - ) +bool ActorSpawner::CollectNodesFromRanges(std::vector &node_ranges, + std::vector & out_node_indices) { std::vector::iterator itor = node_ranges.begin(); - for ( ; itor != node_ranges.end(); itor++) + for (; itor != node_ranges.end(); itor++) { if (itor->IsRange()) { int result_a = FindNodeIndex(itor->start, /* silent */ false); - int result_b = FindNodeIndex(itor->end, /* silent */ true); + int result_b = FindNodeIndex(itor->end, /* silent */ true); unsigned int start = 0; - unsigned int end = 0; + unsigned int end = 0; - if (result_a == -1) - { - return false; - } + if (result_a == -1) { return false; } else { start = static_cast(result_a); @@ -2832,7 +2613,8 @@ bool ActorSpawner::CollectNodesFromRanges( if (result_b == -1) { std::stringstream msg; - msg << "Encountered non-existent node '" << itor->end.ToString() << "' in range [" << itor->start.ToString() << " - " << itor->end.ToString() << "], " + msg << "Encountered non-existent node '" << itor->end.ToString() << "' in range [" << itor->start.ToString() + << " - " << itor->end.ToString() << "], " << "highest node index is '" << m_actor->ar_num_nodes - 1 << "'."; if (itor->end.Str().empty()) /* If the node is numeric... */ @@ -2856,8 +2638,8 @@ bool ActorSpawner::CollectNodesFromRanges( if (end < start) { unsigned int swap = start; - start = end; - end = swap; + start = end; + end = swap; } for (unsigned int i = start; i <= end; i++) @@ -2873,14 +2655,14 @@ bool ActorSpawner::CollectNodesFromRanges( return true; } -RailGroup *ActorSpawner::CreateRail(std::vector & node_ranges) +RailGroup *ActorSpawner::CreateRail(std::vector &node_ranges) { // Collect nodes std::vector node_indices; this->CollectNodesFromRanges(node_ranges, node_indices); // Build the rail - RailGroup* rg = new RailGroup(); + RailGroup *rg = new RailGroup(); for (unsigned int i = 0; i < node_indices.size() - 1; i++) { beam_t *beam = FindBeamInRig(node_indices[i], node_indices[i + 1]); @@ -2907,11 +2689,11 @@ RailGroup *ActorSpawner::CreateRail(std::vector & node_rang const bool is_loop = (node_indices.front() == node_indices.back()); if (rg->rg_segments.size() > 1) { - rg->rg_segments[0].rs_next = &rg->rg_segments[1]; + rg->rg_segments[0].rs_next = &rg->rg_segments[1]; rg->rg_segments[num_seg - 1].rs_prev = &rg->rg_segments[num_seg - 2]; if (is_loop) { - rg->rg_segments[0].rs_prev = &rg->rg_segments[num_seg - 1]; + rg->rg_segments[0].rs_prev = &rg->rg_segments[num_seg - 1]; rg->rg_segments[num_seg - 1].rs_next = &rg->rg_segments[0]; } } @@ -2921,34 +2703,26 @@ RailGroup *ActorSpawner::CreateRail(std::vector & node_rang beam_t *ActorSpawner::FindBeamInRig(unsigned int node_a_index, unsigned int node_b_index) { - node_t *node_a = & m_actor->ar_nodes[node_a_index]; - node_t *node_b = & m_actor->ar_nodes[node_b_index]; + node_t *node_a = &m_actor->ar_nodes[node_a_index]; + node_t *node_b = &m_actor->ar_nodes[node_b_index]; for (unsigned int i = 0; i < static_cast(m_actor->ar_num_beams); i++) { - if ( - (GetBeam(i).p1 == node_a && GetBeam(i).p2 == node_b) - || (GetBeam(i).p2 == node_a && GetBeam(i).p1 == node_b) - ) - { - return & GetBeam(i); - } + if ((GetBeam(i).p1 == node_a && GetBeam(i).p2 == node_b) || (GetBeam(i).p2 == node_a && GetBeam(i).p1 == node_b)) + { return &GetBeam(i); } } return nullptr; } -void ActorSpawner::ProcessHook(RigDef::Hook & def) +void ActorSpawner::ProcessHook(RigDef::Hook &def) { /* Find the node */ node_t *node = GetNodePointer(def.node); - if (node == nullptr) - { - return; - } + if (node == nullptr) { return; } /* Find the hook */ - hook_t *hook = nullptr; - std::vector ::iterator itor = m_actor->ar_hooks.begin(); + hook_t * hook = nullptr; + std::vector::iterator itor = m_actor->ar_hooks.begin(); for (; itor != m_actor->ar_hooks.end(); itor++) { if (itor->hk_hook_node == node) @@ -2967,28 +2741,22 @@ void ActorSpawner::ProcessHook(RigDef::Hook & def) } /* Process options */ - hook->hk_lockrange = def.option_hook_range; - hook->hk_lockspeed = def.option_speed_coef * HOOK_SPEED_DEFAULT; - hook->hk_maxforce = def.option_max_force; - hook->hk_group = def.option_hookgroup; - hook->hk_lockgroup = def.option_lockgroup; - hook->hk_timer = 0.f; // Hardcoded in BTS_HOOKS + hook->hk_lockrange = def.option_hook_range; + hook->hk_lockspeed = def.option_speed_coef * HOOK_SPEED_DEFAULT; + hook->hk_maxforce = def.option_max_force; + hook->hk_group = def.option_hookgroup; + hook->hk_lockgroup = def.option_lockgroup; + hook->hk_timer = 0.f; // Hardcoded in BTS_HOOKS hook->hk_timer_preset = def.option_timer; - hook->hk_min_length = def.option_min_range_meters; - hook->hk_selflock = def.flag_self_lock; - hook->hk_nodisable = def.flag_no_disable; + hook->hk_min_length = def.option_min_range_meters; + hook->hk_selflock = def.flag_self_lock; + hook->hk_nodisable = def.flag_no_disable; if (def.flag_auto_lock) { hook->hk_autolock = true; - if (hook->hk_group == -1) - { - hook->hk_group = -2; /* only overwrite hgroup when its still default (-1) */ - } - } - if (def.flag_no_rope) - { - hook->hk_beam->bounded = NOSHOCK; + if (hook->hk_group == -1) { hook->hk_group = -2; /* only overwrite hgroup when its still default (-1) */ } } + if (def.flag_no_rope) { hook->hk_beam->bounded = NOSHOCK; } if (!def.flag_visible) // NOTE: This flag can only hide a visible beam - it won't show a beam defined with 'invisible' flag. { // Find beam index @@ -3017,7 +2785,7 @@ void ActorSpawner::ProcessHook(RigDef::Hook & def) } } -void ActorSpawner::ProcessLockgroup(RigDef::Lockgroup & lockgroup) +void ActorSpawner::ProcessLockgroup(RigDef::Lockgroup &lockgroup) { auto itor = lockgroup.nodes.begin(); auto end = lockgroup.nodes.end(); @@ -3027,57 +2795,41 @@ void ActorSpawner::ProcessLockgroup(RigDef::Lockgroup & lockgroup) } } -void ActorSpawner::ProcessTrigger(RigDef::Trigger & def) +void ActorSpawner::ProcessTrigger(RigDef::Trigger &def) { - shock_t & shock = this->GetFreeShock(); + shock_t &shock = this->GetFreeShock(); // Disable trigger on startup? (default enabled) shock.trigger_enabled = !def.HasFlag_x_StartDisabled(); m_actor->ar_command_key[def.shortbound_trigger_action].trigger_cmdkeyblock_state = false; if (def.longbound_trigger_action != -1) - { - m_actor->ar_command_key[def.longbound_trigger_action].trigger_cmdkeyblock_state = false; - } + { m_actor->ar_command_key[def.longbound_trigger_action].trigger_cmdkeyblock_state = false; } - unsigned int hydro_type = BEAM_HYDRO; + unsigned int hydro_type = BEAM_HYDRO; unsigned int shock_flags = SHOCK_FLAG_NORMAL | SHOCK_FLAG_ISTRIGGER; - float short_limit = def.contraction_trigger_limit; - float long_limit = def.expansion_trigger_limit; + float short_limit = def.contraction_trigger_limit; + float long_limit = def.expansion_trigger_limit; - if (def.HasFlag_B_TriggerBlocker()) - { - BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_BLOCKER); - } - if (def.HasFlag_s_CmdNumSwitch()) // switch that exchanges cmdshort/cmdshort for all triggers with the same commandnumbers, default false - { - BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_CMD_SWITCH); - } + if (def.HasFlag_B_TriggerBlocker()) { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_BLOCKER); } + if (def.HasFlag_s_CmdNumSwitch()) // switch that exchanges cmdshort/cmdshort for all triggers with the same commandnumbers, + // default false + { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_CMD_SWITCH); } if (def.HasFlag_c_CommandStyle()) // // trigger is set with commandstyle boundaries instead of shocksytle { short_limit = fabs(short_limit - 1); - long_limit = long_limit - 1; - } - if (def.HasFlag_A_InvTriggerBlocker()) // Blocker that enable/disable other triggers, reversed activation method (inverted Blocker style, auto-ON) - { - BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_BLOCKER_A); - } - if (def.HasFlag_h_UnlocksHookGroup()) - { - BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_HOOK_UNLOCK); - } - if (def.HasFlag_H_LocksHookGroup()) - { - BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_HOOK_LOCK); + long_limit = long_limit - 1; } + if (def.HasFlag_A_InvTriggerBlocker()) // Blocker that enable/disable other triggers, reversed activation method (inverted + // Blocker style, auto-ON) + { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_BLOCKER_A); } + if (def.HasFlag_h_UnlocksHookGroup()) { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_HOOK_UNLOCK); } + if (def.HasFlag_H_LocksHookGroup()) { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_HOOK_LOCK); } if (def.HasFlag_t_Continuous()) { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_CONTINUOUS); // this trigger sends values between 0 and 1 } - if (def.HasFlag_E_EngineTrigger()) - { - BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_ENGINE); - } + if (def.HasFlag_E_EngineTrigger()) { BITMASK_SET_1(shock_flags, SHOCK_FLAG_TRG_ENGINE); } // Checks if (!def.IsTriggerBlockerAnyType() && !def.IsHookToggleTrigger() && !def.HasFlag_E_EngineTrigger()) @@ -3085,7 +2837,8 @@ void ActorSpawner::ProcessTrigger(RigDef::Trigger & def) if (def.shortbound_trigger_action < 1 || def.shortbound_trigger_action > MAX_COMMANDS) { std::stringstream msg; - msg << "Invalid value of 'shortbound_trigger_action': '" << def.shortbound_trigger_action << "'. Must be between 1 and "<ar_num_beams; - beam_t & beam = AddBeam(GetNode(node_1_index), GetNode(node_2_index), def.beam_defaults, def.detacher_group); - beam.bm_type = hydro_type; + if (node_1_index == -1 || node_2_index == -1) { return; } + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(GetNode(node_1_index), GetNode(node_2_index), def.beam_defaults, def.detacher_group); + beam.bm_type = hydro_type; SetBeamStrength(beam, def.beam_defaults->breaking_threshold); SetBeamSpring(beam, 0.f); SetBeamDamping(beam, 0.f); CalculateBeamLength(beam); beam.shortbound = short_limit; - beam.longbound = long_limit; - beam.bounded = TRIGGER; - beam.shock = &shock; + beam.longbound = long_limit; + beam.bounded = TRIGGER; + beam.shock = &shock; - if (! def.HasFlag_i_Invisible()) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + if (!def.HasFlag_i_Invisible()) { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } - if (m_actor->m_trigger_debug_enabled) - { - LOG("Trigger added. BeamID " + TOSTRING(beam_index)); - } + if (m_actor->m_trigger_debug_enabled) { LOG("Trigger added. BeamID " + TOSTRING(beam_index)); } - shock.beamid = beam_index; - shock.trigger_switch_state = 0.0f; // used as bool and countdowntimer, dont touch! + shock.beamid = beam_index; + shock.trigger_switch_state = 0.0f; // used as bool and countdowntimer, dont touch! if (!def.IsTriggerBlockerAnyType()) { @@ -3152,20 +2896,20 @@ void ActorSpawner::ProcessTrigger(RigDef::Trigger & def) // this is a commandkeyblocker shock_flags |= SHOCK_FLAG_TRG_CMD_BLOCKER; } - } - else + } + else { // this is a trigger_blocker if (!def.HasFlag_A_InvTriggerBlocker()) { - //normal BLOCKER + // normal BLOCKER shock_flags |= SHOCK_FLAG_TRG_BLOCKER; shock.trigger_cmdshort = def.shortbound_trigger_action; shock.trigger_cmdlong = def.longbound_trigger_action; - } + } else { - //inverted BLOCKER + // inverted BLOCKER shock_flags |= SHOCK_FLAG_TRG_BLOCKER_A; shock.trigger_cmdshort = def.shortbound_trigger_action; shock.trigger_cmdlong = def.longbound_trigger_action; @@ -3176,9 +2920,7 @@ void ActorSpawner::ProcessTrigger(RigDef::Trigger & def) { m_actor->ar_command_key[def.shortbound_trigger_action].trigger_cmdkeyblock_state = true; if (def.longbound_trigger_action != -1) - { - m_actor->ar_command_key[def.longbound_trigger_action].trigger_cmdkeyblock_state = true; - } + { m_actor->ar_command_key[def.longbound_trigger_action].trigger_cmdkeyblock_state = true; } } shock.trigger_boundary_t = def.boundary_timer; @@ -3186,27 +2928,26 @@ void ActorSpawner::ProcessTrigger(RigDef::Trigger & def) shock.sbd_spring = def.beam_defaults->springiness; shock.sbd_damp = def.beam_defaults->damping_constant; shock.last_debug_state = 0; - } -void ActorSpawner::ProcessContacter(RigDef::Node::Ref & node_ref) +void ActorSpawner::ProcessContacter(RigDef::Node::Ref &node_ref) { - unsigned int node_index = GetNodeIndexOrThrow(node_ref); + unsigned int node_index = GetNodeIndexOrThrow(node_ref); m_actor->ar_nodes[node_index].nd_contacter = true; }; -void ActorSpawner::ProcessRotator(RigDef::Rotator & def) +void ActorSpawner::ProcessRotator(RigDef::Rotator &def) { - rotator_t & rotator = m_actor->ar_rotators[m_actor->ar_num_rotators]; + rotator_t &rotator = m_actor->ar_rotators[m_actor->ar_num_rotators]; - rotator.angle = 0; - rotator.rate = def.rate; - rotator.axis1 = GetNodeIndexOrThrow(def.axis_nodes[0]); - rotator.axis2 = GetNodeIndexOrThrow(def.axis_nodes[1]); - rotator.force = ROTATOR_FORCE_DEFAULT; - rotator.tolerance = ROTATOR_TOLERANCE_DEFAULT; + rotator.angle = 0; + rotator.rate = def.rate; + rotator.axis1 = GetNodeIndexOrThrow(def.axis_nodes[0]); + rotator.axis2 = GetNodeIndexOrThrow(def.axis_nodes[1]); + rotator.force = ROTATOR_FORCE_DEFAULT; + rotator.tolerance = ROTATOR_TOLERANCE_DEFAULT; rotator.engine_coupling = def.engine_coupling; - rotator.needs_engine = def.needs_engine; + rotator.needs_engine = def.needs_engine; for (unsigned int i = 0; i < 4; i++) { rotator.nodes1[i] = GetNodeIndexOrThrow(def.base_plate_nodes[i]); @@ -3217,32 +2958,31 @@ void ActorSpawner::ProcessRotator(RigDef::Rotator & def) this->ValidateRotator(m_actor->ar_num_rotators + 1, rotator.axis1, rotator.axis2, rotator.nodes1, rotator.nodes2); // Rotate left key - m_actor->ar_command_key[def.spin_left_key].rotators.push_back(- (m_actor->ar_num_rotators + 1)); + m_actor->ar_command_key[def.spin_left_key].rotators.push_back(-(m_actor->ar_num_rotators + 1)); m_actor->ar_command_key[def.spin_left_key].description = "Rotate_Left/Right"; // Rotate right key m_actor->ar_command_key[def.spin_right_key].rotators.push_back(m_actor->ar_num_rotators + 1); - this->_ProcessKeyInertia(def.inertia, *def.inertia_defaults, - m_actor->ar_command_key[def.spin_left_key].rotator_inertia, + this->_ProcessKeyInertia(def.inertia, *def.inertia_defaults, m_actor->ar_command_key[def.spin_left_key].rotator_inertia, m_actor->ar_command_key[def.spin_right_key].rotator_inertia); m_actor->ar_num_rotators++; m_actor->m_has_command_beams = true; } -void ActorSpawner::ProcessRotator2(RigDef::Rotator2 & def) +void ActorSpawner::ProcessRotator2(RigDef::Rotator2 &def) { - rotator_t & rotator = m_actor->ar_rotators[m_actor->ar_num_rotators]; + rotator_t &rotator = m_actor->ar_rotators[m_actor->ar_num_rotators]; - rotator.angle = 0; - rotator.rate = def.rate; - rotator.axis1 = GetNodeIndexOrThrow(def.axis_nodes[0]); - rotator.axis2 = GetNodeIndexOrThrow(def.axis_nodes[1]); - rotator.force = def.rotating_force; // Default value is set in constructor - rotator.tolerance = def.tolerance; // Default value is set in constructor + rotator.angle = 0; + rotator.rate = def.rate; + rotator.axis1 = GetNodeIndexOrThrow(def.axis_nodes[0]); + rotator.axis2 = GetNodeIndexOrThrow(def.axis_nodes[1]); + rotator.force = def.rotating_force; // Default value is set in constructor + rotator.tolerance = def.tolerance; // Default value is set in constructor rotator.engine_coupling = def.engine_coupling; - rotator.needs_engine = def.needs_engine; + rotator.needs_engine = def.needs_engine; for (unsigned int i = 0; i < 4; i++) { rotator.nodes1[i] = GetNodeIndexOrThrow(def.base_plate_nodes[i]); @@ -3253,11 +2993,8 @@ void ActorSpawner::ProcessRotator2(RigDef::Rotator2 & def) this->ValidateRotator(m_actor->ar_num_rotators + 1, rotator.axis1, rotator.axis2, rotator.nodes1, rotator.nodes2); // Rotate left key - m_actor->ar_command_key[def.spin_left_key].rotators.push_back(- (m_actor->ar_num_rotators + 1)); - if (! def.description.empty()) - { - m_actor->ar_command_key[def.spin_left_key].description = def.description; - } + m_actor->ar_command_key[def.spin_left_key].rotators.push_back(-(m_actor->ar_num_rotators + 1)); + if (!def.description.empty()) { m_actor->ar_command_key[def.spin_left_key].description = def.description; } else { m_actor->ar_command_key[def.spin_left_key].description = "Rotate_Left/Right"; @@ -3266,73 +3003,46 @@ void ActorSpawner::ProcessRotator2(RigDef::Rotator2 & def) // Rotate right key m_actor->ar_command_key[def.spin_right_key].rotators.push_back(m_actor->ar_num_rotators + 1); - this->_ProcessKeyInertia(def.inertia, *def.inertia_defaults, - m_actor->ar_command_key[def.spin_left_key].rotator_inertia, + this->_ProcessKeyInertia(def.inertia, *def.inertia_defaults, m_actor->ar_command_key[def.spin_left_key].rotator_inertia, m_actor->ar_command_key[def.spin_right_key].rotator_inertia); m_actor->ar_num_rotators++; m_actor->m_has_command_beams = true; } -void ActorSpawner::_ProcessKeyInertia( - RigDef::Inertia & inertia, - RigDef::Inertia & inertia_defaults, - RoR::CmdKeyInertia& contract_cmd, - RoR::CmdKeyInertia& extend_cmd -) +void ActorSpawner::_ProcessKeyInertia(RigDef::Inertia &inertia, RigDef::Inertia &inertia_defaults, + RoR::CmdKeyInertia &contract_cmd, RoR::CmdKeyInertia &extend_cmd) { /* Handle placeholders */ Ogre::String start_function; Ogre::String stop_function; - if (! inertia.start_function.empty() && inertia.start_function != "/" && inertia.start_function != "-") - { - start_function = inertia.start_function; - } - if (! inertia.stop_function.empty() && inertia.stop_function != "/" && inertia.stop_function != "-") - { - stop_function = inertia.stop_function; - } + if (!inertia.start_function.empty() && inertia.start_function != "/" && inertia.start_function != "-") + { start_function = inertia.start_function; } + if (!inertia.stop_function.empty() && inertia.stop_function != "/" && inertia.stop_function != "-") + { stop_function = inertia.stop_function; } if (inertia.start_delay_factor != 0.f && inertia.stop_delay_factor != 0.f) { - contract_cmd.SetCmdKeyDelay( - App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), - inertia.start_delay_factor, - inertia.stop_delay_factor, - start_function, - stop_function - ); + contract_cmd.SetCmdKeyDelay(App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), inertia.start_delay_factor, + inertia.stop_delay_factor, start_function, stop_function); - extend_cmd.SetCmdKeyDelay( - App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), - inertia.start_delay_factor, - inertia.stop_delay_factor, - start_function, - stop_function - ); + extend_cmd.SetCmdKeyDelay(App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), inertia.start_delay_factor, + inertia.stop_delay_factor, start_function, stop_function); } else if (inertia_defaults.start_delay_factor > 0 || inertia_defaults.stop_delay_factor > 0) { - contract_cmd.SetCmdKeyDelay( - App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), - inertia_defaults.start_delay_factor, - inertia_defaults.stop_delay_factor, - inertia_defaults.start_function, - inertia_defaults.stop_function - ); + contract_cmd.SetCmdKeyDelay(App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), + inertia_defaults.start_delay_factor, inertia_defaults.stop_delay_factor, + inertia_defaults.start_function, inertia_defaults.stop_function); - extend_cmd.SetCmdKeyDelay( - App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), - inertia_defaults.start_delay_factor, - inertia_defaults.stop_delay_factor, - inertia_defaults.start_function, - inertia_defaults.stop_function - ); + extend_cmd.SetCmdKeyDelay(App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), + inertia_defaults.start_delay_factor, inertia_defaults.stop_delay_factor, + inertia_defaults.start_function, inertia_defaults.stop_function); } } -void ActorSpawner::ProcessCommand(RigDef::Command2 & def) +void ActorSpawner::ProcessCommand(RigDef::Command2 &def) { - int beam_index = m_actor->ar_num_beams; + int beam_index = m_actor->ar_num_beams; int node_1_index = FindNodeIndex(def.nodes[0]); int node_2_index = FindNodeIndex(def.nodes[1]); if (node_1_index == -1 || node_2_index == -1) @@ -3340,7 +3050,8 @@ void ActorSpawner::ProcessCommand(RigDef::Command2 & def) AddMessage(Message::TYPE_ERROR, "Failed to fetch node"); return; } - beam_t & beam = AddBeam(m_actor->ar_nodes[node_1_index], m_actor->ar_nodes[node_2_index], def.beam_defaults, def.detacher_group); + beam_t &beam = + AddBeam(m_actor->ar_nodes[node_1_index], m_actor->ar_nodes[node_2_index], def.beam_defaults, def.detacher_group); CalculateBeamLength(beam); SetBeamStrength(beam, def.beam_defaults->GetScaledBreakingThreshold()); /* Override settings from AddBeam() */ SetBeamSpring(beam, def.beam_defaults->GetScaledSpringiness()); @@ -3348,253 +3059,203 @@ void ActorSpawner::ProcessCommand(RigDef::Command2 & def) beam.bm_type = BEAM_HYDRO; /* Options */ - if (def.option_r_rope) { beam.bounded = ROPE; } + if (def.option_r_rope) { beam.bounded = ROPE; } /* set the middle of the command, so its not required to recalculate this everytime ... */ float center_length = 0.f; if (def.max_extension > def.max_contraction) - { - center_length = (def.max_extension - def.max_contraction) / 2 + def.max_contraction; - } + { center_length = (def.max_extension - def.max_contraction) / 2 + def.max_contraction; } else { center_length = (def.max_contraction - def.max_extension) / 2 + def.max_extension; } /* Add keys */ - command_t* contract_command = &m_actor->ar_command_key[def.contract_key]; + command_t * contract_command = &m_actor->ar_command_key[def.contract_key]; commandbeam_t cmd_beam; - cmd_beam.cmb_beam_index = static_cast(beam_index); - cmd_beam.cmb_is_contraction = true; - cmd_beam.cmb_speed = def.shorten_rate; - cmd_beam.cmb_boundary_length = def.max_contraction; + cmd_beam.cmb_beam_index = static_cast(beam_index); + cmd_beam.cmb_is_contraction = true; + cmd_beam.cmb_speed = def.shorten_rate; + cmd_beam.cmb_boundary_length = def.max_contraction; cmd_beam.cmb_is_force_restricted = def.option_f_not_faster; - cmd_beam.cmb_is_autocentering = def.option_c_auto_center; - cmd_beam.cmb_needs_engine = def.needs_engine; - cmd_beam.cmb_is_1press = def.option_p_1press; - cmd_beam.cmb_is_1press_center = def.option_o_1press_center; - cmd_beam.cmb_plays_sound = def.plays_sound; - cmd_beam.cmb_engine_coupling = def.affect_engine; - cmd_beam.cmb_center_length = center_length; - cmd_beam.cmb_state = std::shared_ptr(new commandbeam_state_t); + cmd_beam.cmb_is_autocentering = def.option_c_auto_center; + cmd_beam.cmb_needs_engine = def.needs_engine; + cmd_beam.cmb_is_1press = def.option_p_1press; + cmd_beam.cmb_is_1press_center = def.option_o_1press_center; + cmd_beam.cmb_plays_sound = def.plays_sound; + cmd_beam.cmb_engine_coupling = def.affect_engine; + cmd_beam.cmb_center_length = center_length; + cmd_beam.cmb_state = std::shared_ptr(new commandbeam_state_t); contract_command->beams.push_back(cmd_beam); - if (contract_command->description.empty()) - { - contract_command->description = def.description; - } + if (contract_command->description.empty()) { contract_command->description = def.description; } - command_t* extend_command = &m_actor->ar_command_key[def.extend_key]; - cmd_beam.cmb_is_contraction = false; - cmd_beam.cmb_speed = def.lengthen_rate; + command_t *extend_command = &m_actor->ar_command_key[def.extend_key]; + cmd_beam.cmb_is_contraction = false; + cmd_beam.cmb_speed = def.lengthen_rate; cmd_beam.cmb_boundary_length = def.max_extension; extend_command->beams.push_back(cmd_beam); - if (extend_command->description.empty()) - { - extend_command->description = def.description; - } + if (extend_command->description.empty()) { extend_command->description = def.description; } - this->_ProcessKeyInertia(def.inertia, *def.inertia_defaults, - contract_command->command_inertia, + this->_ProcessKeyInertia(def.inertia, *def.inertia_defaults, contract_command->command_inertia, extend_command->command_inertia); - if (! def.option_i_invisible) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + if (!def.option_i_invisible) { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } m_actor->m_num_command_beams++; m_actor->m_has_command_beams = true; } -void ActorSpawner::ProcessAnimator(RigDef::Animator & def) +void ActorSpawner::ProcessAnimator(RigDef::Animator &def) { - int anim_flags = 0; + int anim_flags = 0; float anim_option = 0; /* Options. '{' intentionally misplaced. */ - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_AIRSPEED)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_AIRSPEED); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_VERTICAL_VELOCITY)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_VVI); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ANGLE_OF_ATTACK)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_AOA); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_FLAP)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_FLAP); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_AIR_BRAKE)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_AIRBRAKE); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ROLL)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_ROLL); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_PITCH)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_PITCH); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_BRAKES)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_BRAKE); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ACCEL)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_ACCEL); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_CLUTCH)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_CLUTCH); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SPEEDO)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_SPEEDO); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_TACHO)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_TACHO); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_TURBO)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_TURBO); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_PARKING)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_PBRAKE); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_TORQUE)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_TORQUE); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_BOAT_THROTTLE)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_BTHROTTLE); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_BOAT_RUDDER)) { - BITMASK_SET_1(anim_flags, ANIM_FLAG_BRUDDER); - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SHIFT_LEFT_RIGHT)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_AIRSPEED)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_AIRSPEED); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_VERTICAL_VELOCITY)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_VVI); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ANGLE_OF_ATTACK)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_AOA); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_FLAP)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_FLAP); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_AIR_BRAKE)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_AIRBRAKE); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ROLL)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_ROLL); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_PITCH)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_PITCH); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_BRAKES)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_BRAKE); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ACCEL)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_ACCEL); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_CLUTCH)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_CLUTCH); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SPEEDO)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_SPEEDO); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_TACHO)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_TACHO); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_TURBO)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_TURBO); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_PARKING)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_PBRAKE); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_TORQUE)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_TORQUE); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_BOAT_THROTTLE)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_BTHROTTLE); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_BOAT_RUDDER)) { BITMASK_SET_1(anim_flags, ANIM_FLAG_BRUDDER); } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SHIFT_LEFT_RIGHT)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_SHIFTER); anim_option = 1.f; } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SHIFT_BACK_FORTH)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SHIFT_BACK_FORTH)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_SHIFTER); anim_option = 2.f; } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SEQUENTIAL_SHIFT)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SEQUENTIAL_SHIFT)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_SHIFTER); anim_option = 3.f; } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_GEAR_SELECT)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_GEAR_SELECT)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_SHIFTER); anim_option = 4.f; } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ALTIMETER_100K)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ALTIMETER_100K)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_ALTIMETER); anim_option = 1.f; } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ALTIMETER_10K)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ALTIMETER_10K)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_ALTIMETER); anim_option = 2.f; } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ALTIMETER_1K)) { + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_ALTIMETER_1K)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_ALTIMETER); anim_option = 3.f; } - + /* Aerial */ - if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_THROTTLE)) { + if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_THROTTLE)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_THROTTLE); anim_option = static_cast(def.aero_animator.motor); } - if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_RPM)) { + if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_RPM)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_RPM); anim_option = static_cast(def.aero_animator.motor); } - if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_TORQUE)) { + if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_TORQUE)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_AETORQUE); anim_option = static_cast(def.aero_animator.motor); } - if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_PITCH)) { + if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_PITCH)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_AEPITCH); anim_option = static_cast(def.aero_animator.motor); } - if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_STATUS)) { + if (BITMASK_IS_1(def.aero_animator.flags, RigDef::AeroAnimator::OPTION_STATUS)) + { BITMASK_SET_1(anim_flags, ANIM_FLAG_AESTATUS); anim_option = static_cast(def.aero_animator.motor); } unsigned int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(GetNode(def.nodes[0]), GetNode(def.nodes[1]), def.beam_defaults, def.detacher_group); + beam_t & beam = AddBeam(GetNode(def.nodes[0]), GetNode(def.nodes[1]), def.beam_defaults, def.detacher_group); /* set the limits to something with sense by default */ beam.shortbound = 0.99999f; - beam.longbound = 1000000.0f; - beam.bm_type = BEAM_HYDRO; + beam.longbound = 1000000.0f; + beam.bm_type = BEAM_HYDRO; CalculateBeamLength(beam); SetBeamStrength(beam, def.beam_defaults->GetScaledBreakingThreshold()); SetBeamSpring(beam, def.beam_defaults->GetScaledSpringiness()); SetBeamDamping(beam, def.beam_defaults->GetScaledDamping()); if (BITMASK_IS_0(def.flags, RigDef::Animator::OPTION_INVISIBLE)) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SHORT_LIMIT)) - { - beam.shortbound = def.short_limit; - } - if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_LONG_LIMIT)) - { - beam.longbound = def.long_limit; - } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_SHORT_LIMIT)) { beam.shortbound = def.short_limit; } + if (BITMASK_IS_1(def.flags, RigDef::Animator::OPTION_LONG_LIMIT)) { beam.longbound = def.long_limit; } hydrobeam_t hb; hb.hb_beam_index = static_cast(beam_index); - hb.hb_speed = def.lenghtening_factor; + hb.hb_speed = def.lenghtening_factor; hb.hb_ref_length = beam.L; - hb.hb_flags = 0; + hb.hb_flags = 0; hb.hb_anim_flags = anim_flags; hb.hb_anim_param = anim_option; if (def.inertia_defaults->start_delay_factor > 0 && def.inertia_defaults->stop_delay_factor > 0) { - hb.hb_inertia.SetCmdKeyDelay( - App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), - def.inertia_defaults->start_delay_factor, - def.inertia_defaults->stop_delay_factor, - def.inertia_defaults->start_function, - def.inertia_defaults->stop_function - ); + hb.hb_inertia.SetCmdKeyDelay(App::GetSimController()->GetBeamFactory()->GetInertiaConfig(), + def.inertia_defaults->start_delay_factor, def.inertia_defaults->stop_delay_factor, + def.inertia_defaults->start_function, def.inertia_defaults->stop_function); } m_actor->ar_hydros.push_back(hb); } -beam_t & ActorSpawner::AddBeam( - node_t & node_1, - node_t & node_2, - std::shared_ptr & beam_defaults, - int detacher_group -) +beam_t &ActorSpawner::AddBeam(node_t &node_1, node_t &node_2, std::shared_ptr &beam_defaults, + int detacher_group) { /* Init */ - beam_t & beam = GetAndInitFreeBeam(node_1, node_2); + beam_t &beam = GetAndInitFreeBeam(node_1, node_2); beam.detacher_group = detacher_group; - beam.bm_disabled = false; + beam.bm_disabled = false; /* Breaking threshold (strength) */ float strength = beam_defaults->breaking_threshold; - beam.strength = strength; + beam.strength = strength; /* Deformation */ SetBeamDeformationThreshold(beam, beam_defaults); float plastic_coef = beam_defaults->plastic_deform_coef; - beam.plastic_coef = plastic_coef; + beam.plastic_coef = plastic_coef; return beam; } -void ActorSpawner::SetBeamStrength(beam_t & beam, float strength) +void ActorSpawner::SetBeamStrength(beam_t &beam, float strength) { beam.strength = strength; } -void ActorSpawner::ProcessHydro(RigDef::Hydro & def) +void ActorSpawner::ProcessHydro(RigDef::Hydro &def) { - bool invisible = false; + bool invisible = false; unsigned int hydro_flags = 0; // Parse options @@ -3610,79 +3271,71 @@ void ActorSpawner::ProcessHydro(RigDef::Hydro & def) const char c = def.options[i]; switch (c) { - case RigDef::Hydro::OPTION_i_INVISIBLE: // i - invisible = true; - break; - case RigDef::Hydro::OPTION_n_NORMAL: // n - invisible = false; - hydro_flags |= HYDRO_FLAG_DIR; - break; - case RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED: // 's': // speed changing hydro - hydro_flags |= HYDRO_FLAG_SPEED; - break; - case RigDef::Hydro::OPTION_a_INPUT_AILERON: // 'a': - hydro_flags |= HYDRO_FLAG_AILERON; - break; - case RigDef::Hydro::OPTION_r_INPUT_RUDDER: // 'r': - hydro_flags |= HYDRO_FLAG_RUDDER; - break; - case RigDef::Hydro::OPTION_e_INPUT_ELEVATOR: // 'e': - hydro_flags |= HYDRO_FLAG_ELEVATOR; - break; - case RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR: // 'u': - hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_ELEVATOR); - break; - case RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR: // 'v': - hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_ELEVATOR); - break; - case RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER: // 'x': - hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_RUDDER); - break; - case RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER: // 'y': - hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_RUDDER); - break; - case RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER: // 'g': - hydro_flags |= (HYDRO_FLAG_ELEVATOR | HYDRO_FLAG_RUDDER); - break; - case RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER: // 'h': - hydro_flags |= (HYDRO_FLAG_REV_ELEVATOR | HYDRO_FLAG_RUDDER); - break; - default: - this->AddMessage(Message::TYPE_WARNING, std::string("Ignoring invalid flag:") + c); - break; + case RigDef::Hydro::OPTION_i_INVISIBLE: // i + invisible = true; + break; + case RigDef::Hydro::OPTION_n_NORMAL: // n + invisible = false; + hydro_flags |= HYDRO_FLAG_DIR; + break; + case RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED: // 's': // speed changing hydro + hydro_flags |= HYDRO_FLAG_SPEED; + break; + case RigDef::Hydro::OPTION_a_INPUT_AILERON: // 'a': + hydro_flags |= HYDRO_FLAG_AILERON; + break; + case RigDef::Hydro::OPTION_r_INPUT_RUDDER: // 'r': + hydro_flags |= HYDRO_FLAG_RUDDER; + break; + case RigDef::Hydro::OPTION_e_INPUT_ELEVATOR: // 'e': + hydro_flags |= HYDRO_FLAG_ELEVATOR; + break; + case RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR: // 'u': + hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_ELEVATOR); + break; + case RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR: // 'v': + hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_ELEVATOR); + break; + case RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER: // 'x': + hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_RUDDER); + break; + case RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER: // 'y': + hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_RUDDER); + break; + case RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER: // 'g': + hydro_flags |= (HYDRO_FLAG_ELEVATOR | HYDRO_FLAG_RUDDER); + break; + case RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER: // 'h': + hydro_flags |= (HYDRO_FLAG_REV_ELEVATOR | HYDRO_FLAG_RUDDER); + break; + default: this->AddMessage(Message::TYPE_WARNING, std::string("Ignoring invalid flag:") + c); break; } - + // NOTE: This is a quirk ported from v0.4.0.7 spawner (for compatibility) // This code obviously belongs after the options-loop. // However, since it's inside the loop, it only works correctly if the 'i' flag is last. // // ORIGINAL COMMENT: if you use the i flag on its own, add the direction to it - if (invisible && !hydro_flags) - { - hydro_flags |= HYDRO_FLAG_DIR; - } + if (invisible && !hydro_flags) { hydro_flags |= HYDRO_FLAG_DIR; } } } - node_t & node_1 = GetNode(def.nodes[0]); - node_t & node_2 = GetNode(def.nodes[1]); + node_t &node_1 = GetNode(def.nodes[0]); + node_t &node_2 = GetNode(def.nodes[1]); - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); SetBeamStrength(beam, def.beam_defaults->GetScaledBreakingThreshold()); CalculateBeamLength(beam); - beam.bm_type = BEAM_HYDRO; - beam.k = def.beam_defaults->GetScaledSpringiness(); - beam.d = def.beam_defaults->GetScaledDamping(); + beam.bm_type = BEAM_HYDRO; + beam.k = def.beam_defaults->GetScaledSpringiness(); + beam.d = def.beam_defaults->GetScaledDamping(); - if (!invisible) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + if (!invisible) { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } hydrobeam_t hb; - hb.hb_flags = hydro_flags; - hb.hb_speed = def.lenghtening_factor; + hb.hb_flags = hydro_flags; + hb.hb_speed = def.lenghtening_factor; hb.hb_beam_index = static_cast(beam_index); hb.hb_ref_length = beam.L; hb.hb_anim_flags = 0; @@ -3692,12 +3345,12 @@ void ActorSpawner::ProcessHydro(RigDef::Hydro & def) m_actor->ar_hydros.push_back(hb); } -void ActorSpawner::ProcessShock3(RigDef::Shock3 & def) +void ActorSpawner::ProcessShock3(RigDef::Shock3 &def) { - node_t & node_1 = GetNode(def.nodes[0]); - node_t & node_2 = GetNode(def.nodes[1]); - float short_bound = def.short_bound; - float long_bound = def.long_bound; + node_t & node_1 = GetNode(def.nodes[0]); + node_t & node_2 = GetNode(def.nodes[1]); + float short_bound = def.short_bound; + float long_bound = def.long_bound; unsigned int shock_flags = SHOCK_FLAG_NORMAL | SHOCK_FLAG_ISSHOCK3; if (BITMASK_IS_1(def.options, RigDef::Shock3::OPTION_m_METRIC)) @@ -3709,49 +3362,43 @@ void ActorSpawner::ProcessShock3(RigDef::Shock3 & def) if (BITMASK_IS_1(def.options, RigDef::Shock3::OPTION_M_ABSOLUTE_METRIC)) { float beam_length = node_1.AbsPosition.distance(node_2.AbsPosition); - short_bound = (beam_length - short_bound) / beam_length; - long_bound = (long_bound - beam_length) / beam_length; + short_bound = (beam_length - short_bound) / beam_length; + long_bound = (long_bound - beam_length) / beam_length; if (long_bound < 0.f) { - AddMessage( - Message::TYPE_WARNING, - "Metric shock length calculation failed, 'short_bound' less than beams spawn length. Resetting to beam's spawn length (short_bound = 0)" - ); + AddMessage(Message::TYPE_WARNING, "Metric shock length calculation failed, 'short_bound' less than beams spawn " + "length. Resetting to beam's spawn length (short_bound = 0)"); long_bound = 0.f; } if (short_bound > 1.f) { - AddMessage( - Message::TYPE_WARNING, - "Metric shock length calculation failed, 'short_bound' less than 0 meters. Resetting to 0 meters (short_bound = 1)" - ); + AddMessage(Message::TYPE_WARNING, "Metric shock length calculation failed, 'short_bound' less than 0 meters. " + "Resetting to 0 meters (short_bound = 1)"); short_bound = 1.f; } } - - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); + + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); SetBeamStrength(beam, def.beam_defaults->breaking_threshold * 4.f); - beam.bm_type = BEAM_HYDRO; - beam.bounded = SHOCK3; - beam.k = def.spring_in; - beam.d = def.damp_in; - beam.shortbound = short_bound; - beam.longbound = long_bound; + beam.bm_type = BEAM_HYDRO; + beam.bounded = SHOCK3; + beam.k = def.spring_in; + beam.d = def.damp_in; + beam.shortbound = short_bound; + beam.longbound = long_bound; /* Length + pre-compression */ CalculateBeamLength(beam); - beam.L *= def.precompression; - beam.refL *= def.precompression; + beam.L *= def.precompression; + beam.refL *= def.precompression; if (BITMASK_IS_0(def.options, RigDef::Shock3::OPTION_i_INVISIBLE)) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } - shock_t & shock = GetFreeShock(); + shock_t &shock = GetFreeShock(); shock.flags = shock_flags; shock.sbd_spring = def.beam_defaults->springiness; shock.sbd_damp = def.beam_defaults->damping_constant; @@ -3766,16 +3413,16 @@ void ActorSpawner::ProcessShock3(RigDef::Shock3 & def) shock.dslowout = def.damp_out_slow; shock.dfastout = def.damp_out_fast; - beam.shock = & shock; + beam.shock = &shock; shock.beamid = beam_index; } -void ActorSpawner::ProcessShock2(RigDef::Shock2 & def) +void ActorSpawner::ProcessShock2(RigDef::Shock2 &def) { - node_t & node_1 = GetNode(def.nodes[0]); - node_t & node_2 = GetNode(def.nodes[1]); - float short_bound = def.short_bound; - float long_bound = def.long_bound; + node_t & node_1 = GetNode(def.nodes[0]); + node_t & node_2 = GetNode(def.nodes[1]); + float short_bound = def.short_bound; + float long_bound = def.long_bound; unsigned int shock_flags = SHOCK_FLAG_NORMAL | SHOCK_FLAG_ISSHOCK2; if (BITMASK_IS_1(def.options, RigDef::Shock2::OPTION_s_SOFT_BUMP_BOUNDS)) @@ -3792,49 +3439,43 @@ void ActorSpawner::ProcessShock2(RigDef::Shock2 & def) if (BITMASK_IS_1(def.options, RigDef::Shock2::OPTION_M_ABSOLUTE_METRIC)) { float beam_length = node_1.AbsPosition.distance(node_2.AbsPosition); - short_bound = (beam_length - short_bound) / beam_length; - long_bound = (long_bound - beam_length) / beam_length; + short_bound = (beam_length - short_bound) / beam_length; + long_bound = (long_bound - beam_length) / beam_length; if (long_bound < 0.f) { - AddMessage( - Message::TYPE_WARNING, - "Metric shock length calculation failed, 'short_bound' less than beams spawn length. Resetting to beam's spawn length (short_bound = 0)" - ); + AddMessage(Message::TYPE_WARNING, "Metric shock length calculation failed, 'short_bound' less than beams spawn " + "length. Resetting to beam's spawn length (short_bound = 0)"); long_bound = 0.f; } if (short_bound > 1.f) { - AddMessage( - Message::TYPE_WARNING, - "Metric shock length calculation failed, 'short_bound' less than 0 meters. Resetting to 0 meters (short_bound = 1)" - ); + AddMessage(Message::TYPE_WARNING, "Metric shock length calculation failed, 'short_bound' less than 0 meters. " + "Resetting to 0 meters (short_bound = 1)"); short_bound = 1.f; } } - - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); + + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); SetBeamStrength(beam, def.beam_defaults->breaking_threshold * 4.f); - beam.bm_type = BEAM_HYDRO; - beam.bounded = SHOCK2; - beam.k = def.spring_in; - beam.d = def.damp_in; - beam.shortbound = short_bound; - beam.longbound = long_bound; + beam.bm_type = BEAM_HYDRO; + beam.bounded = SHOCK2; + beam.k = def.spring_in; + beam.d = def.damp_in; + beam.shortbound = short_bound; + beam.longbound = long_bound; /* Length + pre-compression */ CalculateBeamLength(beam); - beam.L *= def.precompression; - beam.refL *= def.precompression; + beam.L *= def.precompression; + beam.refL *= def.precompression; if (BITMASK_IS_0(def.options, RigDef::Shock2::OPTION_i_INVISIBLE)) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } - shock_t & shock = GetFreeShock(); + shock_t &shock = GetFreeShock(); shock.flags = shock_flags; shock.sbd_spring = def.beam_defaults->springiness; shock.sbd_damp = def.beam_defaults->damping_constant; @@ -3847,16 +3488,16 @@ void ActorSpawner::ProcessShock2(RigDef::Shock2 & def) shock.sprogout = def.progress_factor_spring_out; shock.dprogout = def.progress_factor_damp_out; - beam.shock = & shock; + beam.shock = &shock; shock.beamid = beam_index; } -void ActorSpawner::ProcessShock(RigDef::Shock & def) +void ActorSpawner::ProcessShock(RigDef::Shock &def) { - node_t & node_1 = GetNode(def.nodes[0]); - node_t & node_2 = GetNode(def.nodes[1]); - float short_bound = def.short_bound; - float long_bound = def.long_bound; + node_t & node_1 = GetNode(def.nodes[0]); + node_t & node_2 = GetNode(def.nodes[1]); + float short_bound = def.short_bound; + float long_bound = def.long_bound; unsigned int shock_flags = SHOCK_FLAG_NORMAL; if (BITMASK_IS_1(def.options, RigDef::Shock::OPTION_L_ACTIVE_LEFT)) @@ -3877,42 +3518,36 @@ void ActorSpawner::ProcessShock(RigDef::Shock & def) short_bound /= beam_length; long_bound /= beam_length; } - - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); - beam.shortbound = short_bound; - beam.longbound = long_bound; - beam.bounded = SHOCK1; - beam.bm_type = BEAM_HYDRO; - beam.k = def.spring_rate; - beam.d = def.damping; + + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(node_1, node_2, def.beam_defaults, def.detacher_group); + beam.shortbound = short_bound; + beam.longbound = long_bound; + beam.bounded = SHOCK1; + beam.bm_type = BEAM_HYDRO; + beam.k = def.spring_rate; + beam.d = def.damping; SetBeamStrength(beam, def.beam_defaults->breaking_threshold * 4.f); /* Length + pre-compression */ CalculateBeamLength(beam); - beam.L *= def.precompression; - beam.refL *= def.precompression; + beam.L *= def.precompression; + beam.refL *= def.precompression; - shock_t & shock = GetFreeShock(); + shock_t &shock = GetFreeShock(); shock.flags = shock_flags; shock.sbd_spring = def.beam_defaults->springiness; shock.sbd_damp = def.beam_defaults->damping_constant; if (BITMASK_IS_0(def.options, RigDef::Shock::OPTION_i_INVISIBLE)) - { - this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); - } + { this->CreateBeamVisuals(beam, beam_index, true, def.beam_defaults); } - beam.shock = & shock; + beam.shock = &shock; shock.beamid = beam_index; } -void ActorSpawner::FetchAxisNodes( - node_t* & axis_node_1, - node_t* & axis_node_2, - RigDef::Node::Ref const & axis_node_1_id, - RigDef::Node::Ref const & axis_node_2_id -) +void ActorSpawner::FetchAxisNodes(node_t *&axis_node_1, node_t *&axis_node_2, RigDef::Node::Ref const &axis_node_1_id, + RigDef::Node::Ref const &axis_node_2_id) { axis_node_1 = GetNodePointer(axis_node_1_id); axis_node_2 = GetNodePointer(axis_node_2_id); @@ -3924,36 +3559,36 @@ void ActorSpawner::FetchAxisNodes( if (pos_1.z > pos_2.z) { node_t *swap = axis_node_1; - axis_node_1 = axis_node_2; - axis_node_2 = swap; + axis_node_1 = axis_node_2; + axis_node_2 = swap; } } -void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) +void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel &def) { unsigned int base_node_index = m_actor->ar_num_nodes; - wheel_t & wheel = m_actor->ar_wheels[m_actor->ar_num_wheels]; + wheel_t & wheel = m_actor->ar_wheels[m_actor->ar_num_wheels]; node_t *axis_node_1 = nullptr; node_t *axis_node_2 = nullptr; FetchAxisNodes(axis_node_1, axis_node_2, def.nodes[0], def.nodes[1]); // Rigidity node - node_t *rigidity_node = nullptr; + node_t *rigidity_node = nullptr; node_t *axis_node_closest_to_rigidity_node = nullptr; if (def.rigidity_node.IsValidAnyState()) { - rigidity_node = GetNodePointer(def.rigidity_node); - Ogre::Real distance_1 = (rigidity_node->RelPosition - axis_node_1->RelPosition).length(); - Ogre::Real distance_2 = (rigidity_node->RelPosition - axis_node_2->RelPosition).length(); + rigidity_node = GetNodePointer(def.rigidity_node); + Ogre::Real distance_1 = (rigidity_node->RelPosition - axis_node_1->RelPosition).length(); + Ogre::Real distance_2 = (rigidity_node->RelPosition - axis_node_2->RelPosition).length(); axis_node_closest_to_rigidity_node = ((distance_1 < distance_2)) ? axis_node_1 : axis_node_2; } // Node&beam generation Ogre::Vector3 axis_vector = axis_node_2->RelPosition - axis_node_1->RelPosition; - wheel.wh_width = axis_vector.length(); // wheel_def.width is ignored. + wheel.wh_width = axis_vector.length(); // wheel_def.width is ignored. axis_vector.normalise(); - Ogre::Vector3 rim_ray_vector = axis_vector.perpendicular() * def.rim_radius; + Ogre::Vector3 rim_ray_vector = axis_vector.perpendicular() * def.rim_radius; Ogre::Quaternion rim_ray_rotator = Ogre::Quaternion(Ogre::Degree(-360.f / (def.num_rays * 2)), axis_vector); // Rim nodes @@ -3963,9 +3598,9 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) // Outer ring Ogre::Vector3 ray_point = axis_node_1->RelPosition + rim_ray_vector; - rim_ray_vector = rim_ray_rotator * rim_ray_vector; + rim_ray_vector = rim_ray_rotator * rim_ray_vector; - node_t & outer_node = GetFreeNode(); + node_t &outer_node = GetFreeNode(); InitNode(outer_node, ray_point, def.node_defaults); outer_node.mass = node_mass; @@ -3977,10 +3612,10 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(outer_node.pos))); // Inner ring - ray_point = axis_node_2->RelPosition + rim_ray_vector; + ray_point = axis_node_2->RelPosition + rim_ray_vector; rim_ray_vector = rim_ray_rotator * rim_ray_vector; - node_t & inner_node = GetFreeNode(); + node_t &inner_node = GetFreeNode(); InitNode(inner_node, ray_point, def.node_defaults); inner_node.mass = node_mass; @@ -3992,23 +3627,23 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(inner_node.pos))); // Wheel object - wheel.wh_rim_nodes[i * 2] = & outer_node; - wheel.wh_rim_nodes[(i * 2) + 1] = & inner_node; + wheel.wh_rim_nodes[i * 2] = &outer_node; + wheel.wh_rim_nodes[(i * 2) + 1] = &inner_node; } - Ogre::Vector3 tyre_ray_vector = axis_vector.perpendicular() * def.tyre_radius; - Ogre::Quaternion& tyre_ray_rotator = rim_ray_rotator; - tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; + Ogre::Vector3 tyre_ray_vector = axis_vector.perpendicular() * def.tyre_radius; + Ogre::Quaternion &tyre_ray_rotator = rim_ray_rotator; + tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; // Tyre nodes for (unsigned int i = 0; i < def.num_rays; i++) { /* Outer ring */ - float node_mass = def.mass / (4.f * def.num_rays); + float node_mass = def.mass / (4.f * def.num_rays); Ogre::Vector3 ray_point = axis_node_1->RelPosition + tyre_ray_vector; - tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; + tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; - node_t & outer_node = GetFreeNode(); + node_t &outer_node = GetFreeNode(); InitNode(outer_node, ray_point); outer_node.mass = node_mass; outer_node.friction_coef = def.node_defaults->friction; @@ -4021,10 +3656,10 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(outer_node.pos))); // Inner ring - ray_point = axis_node_2->RelPosition + tyre_ray_vector; + ray_point = axis_node_2->RelPosition + tyre_ray_vector; tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; - node_t & inner_node = GetFreeNode(); + node_t &inner_node = GetFreeNode(); InitNode(inner_node, ray_point); inner_node.mass = node_mass; inner_node.friction_coef = def.node_defaults->friction; @@ -4037,26 +3672,26 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(inner_node.pos))); // Wheel object - wheel.wh_nodes[i * 2] = & outer_node; - wheel.wh_nodes[(i * 2) + 1] = & inner_node; + wheel.wh_nodes[i * 2] = &outer_node; + wheel.wh_nodes[(i * 2) + 1] = &inner_node; } // Beams - float rim_spring = def.rim_springiness; - float rim_damp = def.rim_damping; - float tyre_spring = def.tyre_springiness; - float tyre_damp = def.tyre_damping; + float rim_spring = def.rim_springiness; + float rim_damp = def.rim_damping; + float tyre_spring = def.tyre_springiness; + float tyre_damp = def.tyre_damping; float tread_spring = def.beam_defaults->springiness; - float tread_damp = def.beam_defaults->damping_constant; + float tread_damp = def.beam_defaults->damping_constant; for (unsigned int i = 0; i < def.num_rays; i++) { - // --- Rim --- + // --- Rim --- // Rim axis to rim ring unsigned int rim_outer_node_index = base_node_index + (i * 2); - node_t *rim_outer_node = & m_actor->ar_nodes[rim_outer_node_index]; - node_t *rim_inner_node = & m_actor->ar_nodes[rim_outer_node_index + 1]; + node_t * rim_outer_node = &m_actor->ar_nodes[rim_outer_node_index]; + node_t * rim_inner_node = &m_actor->ar_nodes[rim_outer_node_index + 1]; AddWheelBeam(axis_node_1, rim_outer_node, rim_spring, rim_damp, def.beam_defaults); AddWheelBeam(axis_node_2, rim_inner_node, rim_spring, rim_damp, def.beam_defaults); @@ -4065,10 +3700,10 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) // Reinforcement rim ring unsigned int rim_next_outer_node_index = base_node_index + (((i + 1) % def.num_rays) * 2); - node_t *rim_next_outer_node = & m_actor->ar_nodes[rim_next_outer_node_index]; - node_t *rim_next_inner_node = & m_actor->ar_nodes[rim_next_outer_node_index + 1]; + node_t * rim_next_outer_node = &m_actor->ar_nodes[rim_next_outer_node_index]; + node_t * rim_next_inner_node = &m_actor->ar_nodes[rim_next_outer_node_index + 1]; - AddWheelBeam(rim_outer_node, rim_inner_node, rim_spring, rim_damp, def.beam_defaults); + AddWheelBeam(rim_outer_node, rim_inner_node, rim_spring, rim_damp, def.beam_defaults); AddWheelBeam(rim_outer_node, rim_next_outer_node, rim_spring, rim_damp, def.beam_defaults); AddWheelBeam(rim_inner_node, rim_next_inner_node, rim_spring, rim_damp, def.beam_defaults); AddWheelBeam(rim_inner_node, rim_next_outer_node, rim_spring, rim_damp, def.beam_defaults); @@ -4078,48 +3713,55 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) // Quick&dirty port from original SerializedRig::addWheel3() for (unsigned int i = 0; i < def.num_rays; i++) { - int rim_node_index = base_node_index + i*2; - int tyre_node_index = base_node_index + i*2 + def.num_rays*2; - node_t * rim_node = & m_actor->ar_nodes[rim_node_index]; + int rim_node_index = base_node_index + i * 2; + int tyre_node_index = base_node_index + i * 2 + def.num_rays * 2; + node_t *rim_node = &m_actor->ar_nodes[rim_node_index]; - AddWheelBeam(rim_node, & m_actor->ar_nodes[tyre_node_index], tyre_spring/2.f, tyre_damp, def.beam_defaults); + AddWheelBeam(rim_node, &m_actor->ar_nodes[tyre_node_index], tyre_spring / 2.f, tyre_damp, def.beam_defaults); int tyre_base_index = (i == 0) ? tyre_node_index + (def.num_rays * 2) : tyre_node_index; - AddWheelBeam(rim_node, & m_actor->ar_nodes[tyre_base_index - 1], tyre_spring/2.f, tyre_damp, def.beam_defaults); - AddWheelBeam(rim_node, & m_actor->ar_nodes[tyre_base_index - 2], tyre_spring/2.f, tyre_damp, def.beam_defaults); + AddWheelBeam(rim_node, &m_actor->ar_nodes[tyre_base_index - 1], tyre_spring / 2.f, tyre_damp, def.beam_defaults); + AddWheelBeam(rim_node, &m_actor->ar_nodes[tyre_base_index - 2], tyre_spring / 2.f, tyre_damp, def.beam_defaults); - node_t * next_rim_node = & m_actor->ar_nodes[rim_node_index + 1]; - AddWheelBeam(next_rim_node, & m_actor->ar_nodes[tyre_node_index], tyre_spring/2.f, tyre_damp, def.beam_defaults); - AddWheelBeam(next_rim_node, & m_actor->ar_nodes[tyre_node_index + 1], tyre_spring/2.f, tyre_damp, def.beam_defaults); + node_t *next_rim_node = &m_actor->ar_nodes[rim_node_index + 1]; + AddWheelBeam(next_rim_node, &m_actor->ar_nodes[tyre_node_index], tyre_spring / 2.f, tyre_damp, def.beam_defaults); + AddWheelBeam(next_rim_node, &m_actor->ar_nodes[tyre_node_index + 1], tyre_spring / 2.f, tyre_damp, def.beam_defaults); { - int index = (i == 0) ? tyre_node_index + (def.num_rays * 2) - 1 : tyre_node_index - 1; - node_t * tyre_node = & m_actor->ar_nodes[index]; - AddWheelBeam(next_rim_node, tyre_node, tyre_spring/2.f, tyre_damp, def.beam_defaults); + int index = (i == 0) ? tyre_node_index + (def.num_rays * 2) - 1 : tyre_node_index - 1; + node_t *tyre_node = &m_actor->ar_nodes[index]; + AddWheelBeam(next_rim_node, tyre_node, tyre_spring / 2.f, tyre_damp, def.beam_defaults); } - //reinforcement (tire tread) + // reinforcement (tire tread) { // Very messy port :( // Aliases int rimnode = rim_node_index; - int rays = def.num_rays; - - AddWheelBeam(&m_actor->ar_nodes[rimnode+rays*2], &m_actor->ar_nodes[base_node_index+i*2+1+rays*2], tread_spring, tread_damp, def.beam_defaults); - AddWheelBeam(&m_actor->ar_nodes[rimnode+rays*2], &m_actor->ar_nodes[base_node_index+((i+1)%rays)*2+rays*2], tread_spring, tread_damp, def.beam_defaults); - AddWheelBeam(&m_actor->ar_nodes[base_node_index+i*2+1+rays*2], &m_actor->ar_nodes[base_node_index+((i+1)%rays)*2+1+rays*2], tread_spring, tread_damp, def.beam_defaults); - AddWheelBeam(&m_actor->ar_nodes[rimnode+1+rays*2], &m_actor->ar_nodes[base_node_index+((i+1)%rays)*2+rays*2], tread_spring, tread_damp, def.beam_defaults); + int rays = def.num_rays; + + AddWheelBeam(&m_actor->ar_nodes[rimnode + rays * 2], &m_actor->ar_nodes[base_node_index + i * 2 + 1 + rays * 2], + tread_spring, tread_damp, def.beam_defaults); + AddWheelBeam(&m_actor->ar_nodes[rimnode + rays * 2], + &m_actor->ar_nodes[base_node_index + ((i + 1) % rays) * 2 + rays * 2], tread_spring, tread_damp, + def.beam_defaults); + AddWheelBeam(&m_actor->ar_nodes[base_node_index + i * 2 + 1 + rays * 2], + &m_actor->ar_nodes[base_node_index + ((i + 1) % rays) * 2 + 1 + rays * 2], tread_spring, tread_damp, + def.beam_defaults); + AddWheelBeam(&m_actor->ar_nodes[rimnode + 1 + rays * 2], + &m_actor->ar_nodes[base_node_index + ((i + 1) % rays) * 2 + rays * 2], tread_spring, tread_damp, + def.beam_defaults); if (rigidity_node != nullptr) { if (axis_node_closest_to_rigidity_node == axis_node_1) + { axis_node_closest_to_rigidity_node = &m_actor->ar_nodes[base_node_index + i * 2 + rays * 2]; } + else { - axis_node_closest_to_rigidity_node = & m_actor->ar_nodes[base_node_index+i*2+rays*2]; - } else - { - axis_node_closest_to_rigidity_node = & m_actor->ar_nodes[base_node_index+i*2+1+rays*2]; + axis_node_closest_to_rigidity_node = &m_actor->ar_nodes[base_node_index + i * 2 + 1 + rays * 2]; }; - unsigned int beam_index = AddWheelBeam(rigidity_node, axis_node_closest_to_rigidity_node, tyre_spring, tyre_damp, def.beam_defaults); + unsigned int beam_index = + AddWheelBeam(rigidity_node, axis_node_closest_to_rigidity_node, tyre_spring, tyre_damp, def.beam_defaults); GetBeam(beam_index).bm_type = BEAM_VIRTUAL; } } @@ -4130,33 +3772,33 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) float support_beams_short_bound = 1.0f - ((def.rim_radius / def.tyre_radius) * 0.95f); - for (unsigned int i=0; iar_nodes[tirenode], tyre_spring/2.f, tyre_damp, def.beam_defaults); + beam_index = AddWheelBeam(axis_node_1, &m_actor->ar_nodes[tirenode], tyre_spring / 2.f, tyre_damp, def.beam_defaults); GetBeam(beam_index).shortbound = support_beams_short_bound; GetBeam(beam_index).longbound = 0.f; - GetBeam(beam_index).bounded = SHOCK1; + GetBeam(beam_index).bounded = SHOCK1; - beam_index = AddWheelBeam(axis_node_2, &m_actor->ar_nodes[tirenode + 1], tyre_spring/2.f, tyre_damp, def.beam_defaults); + beam_index = AddWheelBeam(axis_node_2, &m_actor->ar_nodes[tirenode + 1], tyre_spring / 2.f, tyre_damp, def.beam_defaults); GetBeam(beam_index).shortbound = support_beams_short_bound; GetBeam(beam_index).longbound = 0.f; - GetBeam(beam_index).bounded = SHOCK1; + GetBeam(beam_index).bounded = SHOCK1; } // Wheel object - wheel.wh_braking = this->TranslateBrakingDef(def.braking); - wheel.wh_propulsed = def.propulsion; - wheel.wh_num_nodes = 2 * def.num_rays; + wheel.wh_braking = this->TranslateBrakingDef(def.braking); + wheel.wh_propulsed = def.propulsion; + wheel.wh_num_nodes = 2 * def.num_rays; wheel.wh_num_rim_nodes = wheel.wh_num_nodes; - wheel.wh_axis_node_0 = axis_node_1; - wheel.wh_axis_node_1 = axis_node_2; - wheel.wh_radius = def.tyre_radius; - wheel.wh_rim_radius = def.rim_radius; - wheel.wh_arm_node = this->GetNodePointer(def.reference_arm_node); + wheel.wh_axis_node_0 = axis_node_1; + wheel.wh_axis_node_1 = axis_node_2; + wheel.wh_radius = def.tyre_radius; + wheel.wh_rim_radius = def.rim_radius; + wheel.wh_arm_node = this->GetNodePointer(def.reference_arm_node); if (def.propulsion != RigDef::Wheels::PROPULSION_NONE) { @@ -4166,8 +3808,8 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) } // Find near attach - Ogre::Real length_1 = (axis_node_1->RelPosition - wheel.wh_arm_node->RelPosition).length(); - Ogre::Real length_2 = (axis_node_2->RelPosition - wheel.wh_arm_node->RelPosition).length(); + Ogre::Real length_1 = (axis_node_1->RelPosition - wheel.wh_arm_node->RelPosition).length(); + Ogre::Real length_2 = (axis_node_2->RelPosition - wheel.wh_arm_node->RelPosition).length(); wheel.wh_near_attach_node = (length_1 < length_2) ? axis_node_1 : axis_node_2; // Commit the wheel @@ -4182,16 +3824,16 @@ wheel_t::BrakeCombo ActorSpawner::TranslateBrakingDef(RigDef::Wheels::Braking de { switch (def) { - case RigDef::Wheels::Braking::BRAKING_NO: return wheel_t::BrakeCombo::NONE; - case RigDef::Wheels::Braking::BRAKING_YES: return wheel_t::BrakeCombo::FOOT_HAND; - case RigDef::Wheels::Braking::BRAKING_DIRECTIONAL_LEFT: return wheel_t::BrakeCombo::FOOT_HAND_SKID_LEFT; + case RigDef::Wheels::Braking::BRAKING_NO: return wheel_t::BrakeCombo::NONE; + case RigDef::Wheels::Braking::BRAKING_YES: return wheel_t::BrakeCombo::FOOT_HAND; + case RigDef::Wheels::Braking::BRAKING_DIRECTIONAL_LEFT: return wheel_t::BrakeCombo::FOOT_HAND_SKID_LEFT; case RigDef::Wheels::Braking::BRAKING_DIRECTIONAL_RIGHT: return wheel_t::BrakeCombo::FOOT_HAND_SKID_RIGHT; - case RigDef::Wheels::Braking::BRAKING_ONLY_FOOT: return wheel_t::BrakeCombo::FOOT_ONLY; - default: return wheel_t::BrakeCombo::NONE; + case RigDef::Wheels::Braking::BRAKING_ONLY_FOOT: return wheel_t::BrakeCombo::FOOT_ONLY; + default: return wheel_t::BrakeCombo::NONE; } } -void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def) +void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel &meshwheel_def) { if (meshwheel_def._is_meshwheel2) { @@ -4200,8 +3842,8 @@ void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def) } unsigned int base_node_index = m_actor->ar_num_nodes; - node_t *axis_node_1 = GetNodePointer(meshwheel_def.nodes[0]); - node_t *axis_node_2 = GetNodePointer(meshwheel_def.nodes[1]); + node_t * axis_node_1 = GetNodePointer(meshwheel_def.nodes[0]); + node_t * axis_node_2 = GetNodePointer(meshwheel_def.nodes[1]); Ogre::Vector3 pos_1 = axis_node_1->AbsPosition; Ogre::Vector3 pos_2 = axis_node_2->AbsPosition; @@ -4210,36 +3852,20 @@ void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def) if (pos_1.z > pos_2.z) { node_t *swap = axis_node_1; - axis_node_1 = axis_node_2; - axis_node_2 = swap; + axis_node_1 = axis_node_2; + axis_node_2 = swap; } unsigned int wheel_index = BuildWheelObjectAndNodes( - meshwheel_def.num_rays, - axis_node_1, - axis_node_2, - GetNodePointer(meshwheel_def.reference_arm_node), - meshwheel_def.num_rays * 2, - meshwheel_def.num_rays * 8, - meshwheel_def.tyre_radius, - meshwheel_def.propulsion, - meshwheel_def.braking, - meshwheel_def.node_defaults, - meshwheel_def.mass - ); + meshwheel_def.num_rays, axis_node_1, axis_node_2, GetNodePointer(meshwheel_def.reference_arm_node), + meshwheel_def.num_rays * 2, meshwheel_def.num_rays * 8, meshwheel_def.tyre_radius, meshwheel_def.propulsion, + meshwheel_def.braking, meshwheel_def.node_defaults, meshwheel_def.mass); - BuildWheelBeams( - meshwheel_def.num_rays, - base_node_index, - axis_node_1, - axis_node_2, - meshwheel_def.spring, /* Tyre */ - meshwheel_def.damping, /* Tyre */ - meshwheel_def.spring, /* Rim */ - meshwheel_def.damping, /* Rim */ - meshwheel_def.beam_defaults, - meshwheel_def.rigidity_node - ); + BuildWheelBeams(meshwheel_def.num_rays, base_node_index, axis_node_1, axis_node_2, meshwheel_def.spring, /* Tyre */ + meshwheel_def.damping, /* Tyre */ + meshwheel_def.spring, /* Rim */ + meshwheel_def.damping, /* Rim */ + meshwheel_def.beam_defaults, meshwheel_def.rigidity_node); m_wheel_visuals_queue.push_back( WheelVisualsTicket(wheel_index, base_node_index, &meshwheel_def, axis_node_1->pos, axis_node_2->pos)); @@ -4247,11 +3873,11 @@ void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def) CreateWheelSkidmarks(wheel_index); } -void ActorSpawner::ProcessMeshWheel2(RigDef::MeshWheel & def) +void ActorSpawner::ProcessMeshWheel2(RigDef::MeshWheel &def) { unsigned int base_node_index = m_actor->ar_num_nodes; - node_t *axis_node_1 = GetNodePointer(def.nodes[0]); - node_t *axis_node_2 = GetNodePointer(def.nodes[1]); + node_t * axis_node_1 = GetNodePointer(def.nodes[0]); + node_t * axis_node_2 = GetNodePointer(def.nodes[1]); if (axis_node_1 == nullptr || axis_node_2 == nullptr) { @@ -4266,126 +3892,84 @@ void ActorSpawner::ProcessMeshWheel2(RigDef::MeshWheel & def) if (pos_1.z > pos_2.z) { node_t *swap = axis_node_1; - axis_node_1 = axis_node_2; - axis_node_2 = swap; - } + axis_node_1 = axis_node_2; + axis_node_2 = swap; + } - unsigned int wheel_index = BuildWheelObjectAndNodes( - def.num_rays, - axis_node_1, - axis_node_2, - GetNodePointer(def.reference_arm_node), - def.num_rays * 2, - def.num_rays * 8, - def.tyre_radius, - def.propulsion, - def.braking, - def.node_defaults, - def.mass - ); + unsigned int wheel_index = + BuildWheelObjectAndNodes(def.num_rays, axis_node_1, axis_node_2, GetNodePointer(def.reference_arm_node), def.num_rays * 2, + def.num_rays * 8, def.tyre_radius, def.propulsion, def.braking, def.node_defaults, def.mass); /* --- Beams --- */ /* Use data from directive 'set_beam_defaults' for the tiretread beams */ float tyre_spring = def.spring; - float tyre_damp = def.damping; - float rim_spring = def.beam_defaults->springiness; - float rim_damp = def.beam_defaults->damping_constant; - - BuildWheelBeams( - def.num_rays, - base_node_index, - axis_node_1, - axis_node_2, - tyre_spring, - tyre_damp, - rim_spring, - rim_damp, - def.beam_defaults, - def.rigidity_node, - 0.15 // max_extension + float tyre_damp = def.damping; + float rim_spring = def.beam_defaults->springiness; + float rim_damp = def.beam_defaults->damping_constant; + + BuildWheelBeams(def.num_rays, base_node_index, axis_node_1, axis_node_2, tyre_spring, tyre_damp, rim_spring, rim_damp, + def.beam_defaults, def.rigidity_node, + 0.15 // max_extension ); - m_wheel_visuals_queue.push_back(WheelVisualsTicket( - wheel_index, base_node_index, &def, axis_node_1->pos, axis_node_2->pos)); + m_wheel_visuals_queue.push_back(WheelVisualsTicket(wheel_index, base_node_index, &def, axis_node_1->pos, axis_node_2->pos)); CreateWheelSkidmarks(wheel_index); } -void ActorSpawner::BuildMeshWheelVisuals( - unsigned int wheel_index, - unsigned int base_node_index, - unsigned int axis_node_1_index, - unsigned int axis_node_2_index, - unsigned int num_rays, - Ogre::String mesh_name, - Ogre::String material_name, - float rim_radius, - bool rim_reverse -) +void ActorSpawner::BuildMeshWheelVisuals(unsigned int wheel_index, unsigned int base_node_index, unsigned int axis_node_1_index, + unsigned int axis_node_2_index, unsigned int num_rays, Ogre::String mesh_name, + Ogre::String material_name, float rim_radius, bool rim_reverse) { try { - FlexMeshWheel* flexmesh_wheel = m_flex_factory.CreateFlexMeshWheel( - wheel_index, - axis_node_1_index, - axis_node_2_index, - base_node_index, - num_rays, - rim_radius, - rim_reverse, - mesh_name, - material_name); - Ogre::SceneNode* scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + FlexMeshWheel *flexmesh_wheel = + m_flex_factory.CreateFlexMeshWheel(wheel_index, axis_node_1_index, axis_node_2_index, base_node_index, num_rays, + rim_radius, rim_reverse, mesh_name, material_name); + Ogre::SceneNode *scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); scene_node->attachObject(flexmesh_wheel->GetTireEntity()); GfxActor::WheelGfx visual_wheel; visual_wheel.wx_is_meshwheel = false; - visual_wheel.wx_flex_mesh = flexmesh_wheel; - visual_wheel.wx_scenenode = scene_node; + visual_wheel.wx_flex_mesh = flexmesh_wheel; + visual_wheel.wx_scenenode = scene_node; m_actor->m_gfx_actor->SetWheelVisuals(wheel_index, visual_wheel); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { this->AddMessage(Message::TYPE_ERROR, "Failed to create meshwheel visuals, message: " + e.getFullDescription()); return; } } -unsigned int ActorSpawner::BuildWheelObjectAndNodes( - unsigned int num_rays, - node_t *axis_node_1, - node_t *axis_node_2, - node_t *reference_arm_node, - unsigned int reserve_nodes, - unsigned int reserve_beams, - float wheel_radius, - RigDef::Wheels::Propulsion propulsion, - RigDef::Wheels::Braking braking, - std::shared_ptr node_defaults, - float wheel_mass, - float wheel_width /* Default: -1.f */ +unsigned int ActorSpawner::BuildWheelObjectAndNodes(unsigned int num_rays, node_t *axis_node_1, node_t *axis_node_2, + node_t *reference_arm_node, unsigned int reserve_nodes, + unsigned int reserve_beams, float wheel_radius, + RigDef::Wheels::Propulsion propulsion, RigDef::Wheels::Braking braking, + std::shared_ptr node_defaults, float wheel_mass, + float wheel_width /* Default: -1.f */ ) { - wheel_t & wheel = m_actor->ar_wheels[m_actor->ar_num_wheels]; + wheel_t &wheel = m_actor->ar_wheels[m_actor->ar_num_wheels]; /* Axis */ Ogre::Vector3 axis_vector = axis_node_2->RelPosition - axis_node_1->RelPosition; - float axis_length = axis_vector.length(); + float axis_length = axis_vector.length(); axis_vector.normalise(); /* Wheel object */ - wheel.wh_braking = this->TranslateBrakingDef(braking); - wheel.wh_propulsed = propulsion; - wheel.wh_num_nodes = 2 * num_rays; - wheel.wh_axis_node_0 = axis_node_1; - wheel.wh_axis_node_1 = axis_node_2; - wheel.wh_radius = wheel_radius; - wheel.wh_width = (wheel_width < 0) ? axis_length : wheel_width; - wheel.wh_arm_node = reference_arm_node; + wheel.wh_braking = this->TranslateBrakingDef(braking); + wheel.wh_propulsed = propulsion; + wheel.wh_num_nodes = 2 * num_rays; + wheel.wh_axis_node_0 = axis_node_1; + wheel.wh_axis_node_1 = axis_node_2; + wheel.wh_radius = wheel_radius; + wheel.wh_width = (wheel_width < 0) ? axis_length : wheel_width; + wheel.wh_arm_node = reference_arm_node; /* Find near attach */ - Ogre::Real length_1 = (axis_node_1->RelPosition - wheel.wh_arm_node->RelPosition).length(); - Ogre::Real length_2 = (axis_node_2->RelPosition - wheel.wh_arm_node->RelPosition).length(); + Ogre::Real length_1 = (axis_node_1->RelPosition - wheel.wh_arm_node->RelPosition).length(); + Ogre::Real length_2 = (axis_node_2->RelPosition - wheel.wh_arm_node->RelPosition).length(); wheel.wh_near_attach_node = (length_1 < length_2) ? axis_node_1 : axis_node_2; if (propulsion != RigDef::Wheels::PROPULSION_NONE) @@ -4394,15 +3978,16 @@ unsigned int ActorSpawner::BuildWheelObjectAndNodes( m_actor->m_proped_wheel_pairs[m_actor->m_num_proped_wheels] = m_actor->ar_num_wheels; m_actor->m_num_proped_wheels++; } - + /* Nodes */ - Ogre::Vector3 ray_vector = axis_vector.perpendicular() * wheel_radius; + Ogre::Vector3 ray_vector = axis_vector.perpendicular() * wheel_radius; Ogre::Quaternion ray_rotator = Ogre::Quaternion(Ogre::Degree(-360.0 / (num_rays * 2)), axis_vector); #ifdef DEBUG_TRUCKPARSER2013 // TRUCK PARSER 2013 DEBUG std::stringstream msg; - msg << "\nDBG ActorSpawner::BuildWheelObjectAndNodes()\nDBG nodebase:" << m_actor->ar_num_nodes <<", axis-node-0:"<pos <<", axis-node-1:"<pos<<"\n"; + msg << "\nDBG ActorSpawner::BuildWheelObjectAndNodes()\nDBG nodebase:" << m_actor->ar_num_nodes + << ", axis-node-0:" << axis_node_1->pos << ", axis-node-1:" << axis_node_2->pos << "\n"; msg << "DBG ==== Adding nodes ===="; // END #endif @@ -4411,41 +3996,42 @@ unsigned int ActorSpawner::BuildWheelObjectAndNodes( { /* Outer ring */ Ogre::Vector3 ray_point = axis_node_1->RelPosition + ray_vector; - ray_vector = ray_rotator * ray_vector; + ray_vector = ray_rotator * ray_vector; - node_t & outer_node = GetFreeNode(); + node_t &outer_node = GetFreeNode(); InitNode(outer_node, ray_point, node_defaults); - outer_node.mass = wheel_mass / (2.f * num_rays); - outer_node.nd_contacter = true; - outer_node.nd_tyre_node = true; + outer_node.mass = wheel_mass / (2.f * num_rays); + outer_node.nd_contacter = true; + outer_node.nd_tyre_node = true; AdjustNodeBuoyancy(outer_node, node_defaults); m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(outer_node.pos))); /* Inner ring */ - ray_point = axis_node_2->RelPosition + ray_vector; + ray_point = axis_node_2->RelPosition + ray_vector; ray_vector = ray_rotator * ray_vector; - node_t & inner_node = GetFreeNode(); + node_t &inner_node = GetFreeNode(); InitNode(inner_node, ray_point, node_defaults); - inner_node.mass = wheel_mass / (2.f * num_rays); - inner_node.nd_contacter = true; - inner_node.nd_tyre_node = true; + inner_node.mass = wheel_mass / (2.f * num_rays); + inner_node.nd_contacter = true; + inner_node.nd_tyre_node = true; AdjustNodeBuoyancy(inner_node, node_defaults); m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(inner_node.pos))); /* Wheel object */ - wheel.wh_nodes[i * 2] = & outer_node; - wheel.wh_nodes[(i * 2) + 1] = & inner_node; + wheel.wh_nodes[i * 2] = &outer_node; + wheel.wh_nodes[(i * 2) + 1] = &inner_node; #ifdef DEBUG_TRUCKPARSER2013 // TRUCK PARSER 2013 DEBUG int modifier = 0; - msg << "\nDBG\tN1: index=" << outer_node.pos + modifier << ", iswheel=" << WHEEL_DEFAULT - <<", X=" << outer_node.AbsPosition.x <<", Y=" << outer_node.AbsPosition.y <<", Z=" << outer_node.AbsPosition.z << std::endl - << "DBG\tN2: index=" << inner_node.pos + modifier << ", iswheel=" << WHEEL_DEFAULT - <<", X=" << inner_node.AbsPosition.x <<", Y=" << inner_node.AbsPosition.y <<", Z=" << inner_node.AbsPosition.z; + msg << "\nDBG\tN1: index=" << outer_node.pos + modifier << ", iswheel=" << WHEEL_DEFAULT + << ", X=" << outer_node.AbsPosition.x << ", Y=" << outer_node.AbsPosition.y << ", Z=" << outer_node.AbsPosition.z + << std::endl + << "DBG\tN2: index=" << inner_node.pos + modifier << ", iswheel=" << WHEEL_DEFAULT + << ", X=" << inner_node.AbsPosition.x << ", Y=" << inner_node.AbsPosition.y << ", Z=" << inner_node.AbsPosition.z; // END #endif } @@ -4462,39 +4048,31 @@ unsigned int ActorSpawner::BuildWheelObjectAndNodes( return wheel_index; } -void ActorSpawner::AdjustNodeBuoyancy(node_t & node, RigDef::Node & node_def, std::shared_ptr defaults) +void ActorSpawner::AdjustNodeBuoyancy(node_t &node, RigDef::Node &node_def, std::shared_ptr defaults) { unsigned int options = (defaults->options | node_def.options); // Merge flags - node.buoyancy = BITMASK_IS_1(options, RigDef::Node::OPTION_b_EXTRA_BUOYANCY) ? 10000.f : m_actor->m_dry_mass/15.f; + node.buoyancy = BITMASK_IS_1(options, RigDef::Node::OPTION_b_EXTRA_BUOYANCY) ? 10000.f : m_actor->m_dry_mass / 15.f; } -void ActorSpawner::AdjustNodeBuoyancy(node_t & node, std::shared_ptr defaults) +void ActorSpawner::AdjustNodeBuoyancy(node_t &node, std::shared_ptr defaults) { - node.buoyancy = BITMASK_IS_1(defaults->options, RigDef::Node::OPTION_b_EXTRA_BUOYANCY) ? 10000.f : m_actor->m_dry_mass/15.f; + node.buoyancy = BITMASK_IS_1(defaults->options, RigDef::Node::OPTION_b_EXTRA_BUOYANCY) ? 10000.f : m_actor->m_dry_mass / 15.f; } -void ActorSpawner::BuildWheelBeams( - unsigned int num_rays, - unsigned int base_node_index, - node_t *axis_node_1, - node_t *axis_node_2, - float tyre_spring, - float tyre_damping, - float rim_spring, - float rim_damping, - std::shared_ptr beam_defaults, - RigDef::Node::Ref const & rigidity_node_id, - float max_extension // = 0.f +void ActorSpawner::BuildWheelBeams(unsigned int num_rays, unsigned int base_node_index, node_t *axis_node_1, node_t *axis_node_2, + float tyre_spring, float tyre_damping, float rim_spring, float rim_damping, + std::shared_ptr beam_defaults, RigDef::Node::Ref const &rigidity_node_id, + float max_extension // = 0.f ) { /* Find out where to connect rigidity node */ - bool rigidity_beam_side_1 = false; - node_t *rigidity_node = nullptr; + bool rigidity_beam_side_1 = false; + node_t *rigidity_node = nullptr; if (rigidity_node_id.IsValidAnyState()) { - rigidity_node = GetNodePointerOrThrow(rigidity_node_id); - float distance_1 = rigidity_node->RelPosition.distance(axis_node_1->RelPosition); - float distance_2 = rigidity_node->RelPosition.distance(axis_node_2->RelPosition); + rigidity_node = GetNodePointerOrThrow(rigidity_node_id); + float distance_1 = rigidity_node->RelPosition.distance(axis_node_1->RelPosition); + float distance_2 = rigidity_node->RelPosition.distance(axis_node_2->RelPosition); rigidity_beam_side_1 = distance_1 < distance_2; } @@ -4502,9 +4080,9 @@ void ActorSpawner::BuildWheelBeams( { /* Bounded */ unsigned int outer_ring_node_index = base_node_index + (i * 2); - node_t *outer_ring_node = & m_actor->ar_nodes[outer_ring_node_index]; - node_t *inner_ring_node = & m_actor->ar_nodes[outer_ring_node_index + 1]; - + node_t * outer_ring_node = &m_actor->ar_nodes[outer_ring_node_index]; + node_t * inner_ring_node = &m_actor->ar_nodes[outer_ring_node_index + 1]; + AddWheelBeam(axis_node_1, outer_ring_node, tyre_spring, tyre_damping, beam_defaults, 0.66f, max_extension); AddWheelBeam(axis_node_2, inner_ring_node, tyre_spring, tyre_damping, beam_defaults, 0.66f, max_extension); AddWheelBeam(axis_node_2, outer_ring_node, tyre_spring, tyre_damping, beam_defaults); @@ -4512,10 +4090,10 @@ void ActorSpawner::BuildWheelBeams( /* Reinforcement */ unsigned int next_outer_ring_node_index = base_node_index + (((i + 1) % num_rays) * 2); - node_t *next_outer_ring_node = & m_actor->ar_nodes[next_outer_ring_node_index]; - node_t *next_inner_ring_node = & m_actor->ar_nodes[next_outer_ring_node_index + 1]; + node_t * next_outer_ring_node = &m_actor->ar_nodes[next_outer_ring_node_index]; + node_t * next_inner_ring_node = &m_actor->ar_nodes[next_outer_ring_node_index + 1]; - AddWheelBeam(outer_ring_node, inner_ring_node, rim_spring, rim_damping, beam_defaults); + AddWheelBeam(outer_ring_node, inner_ring_node, rim_spring, rim_damping, beam_defaults); AddWheelBeam(outer_ring_node, next_outer_ring_node, rim_spring, rim_damping, beam_defaults); AddWheelBeam(inner_ring_node, next_inner_ring_node, rim_spring, rim_damping, beam_defaults); AddWheelBeam(inner_ring_node, next_outer_ring_node, rim_spring, rim_damping, beam_defaults); @@ -4523,18 +4101,19 @@ void ActorSpawner::BuildWheelBeams( /* Rigidity beams */ if (rigidity_node != nullptr) { - node_t *target_node = (rigidity_beam_side_1) ? outer_ring_node : inner_ring_node; - unsigned int beam_index = AddWheelBeam(rigidity_node, target_node, tyre_spring, tyre_damping, beam_defaults, -1.f, -1.f, BEAM_VIRTUAL); + node_t * target_node = (rigidity_beam_side_1) ? outer_ring_node : inner_ring_node; + unsigned int beam_index = + AddWheelBeam(rigidity_node, target_node, tyre_spring, tyre_damping, beam_defaults, -1.f, -1.f, BEAM_VIRTUAL); m_actor->ar_beams[beam_index].bm_type = BEAM_VIRTUAL; } } } -unsigned int ActorSpawner::AddWheel(RigDef::Wheel & wheel_def) +unsigned int ActorSpawner::AddWheel(RigDef::Wheel &wheel_def) { unsigned int base_node_index = m_actor->ar_num_nodes; - node_t *axis_node_1 = GetNodePointer(wheel_def.nodes[0]); - node_t *axis_node_2 = GetNodePointer(wheel_def.nodes[1]); + node_t * axis_node_1 = GetNodePointer(wheel_def.nodes[0]); + node_t * axis_node_2 = GetNodePointer(wheel_def.nodes[1]); if (axis_node_1 == nullptr || axis_node_2 == nullptr) { @@ -4553,37 +4132,22 @@ unsigned int ActorSpawner::AddWheel(RigDef::Wheel & wheel_def) if (pos_1.z > pos_2.z) { node_t *swap = axis_node_1; - axis_node_1 = axis_node_2; - axis_node_2 = swap; - } + axis_node_1 = axis_node_2; + axis_node_2 = swap; + } - unsigned int wheel_index = BuildWheelObjectAndNodes( - wheel_def.num_rays, - axis_node_1, - axis_node_2, - GetNodePointer(wheel_def.reference_arm_node), - wheel_def.num_rays * 2, - wheel_def.num_rays * 8, - wheel_def.radius, - wheel_def.propulsion, - wheel_def.braking, - wheel_def.node_defaults, - wheel_def.mass, - -1.f // Set width to axis length (width in definition is ignored) - ); + unsigned int wheel_index = + BuildWheelObjectAndNodes(wheel_def.num_rays, axis_node_1, axis_node_2, GetNodePointer(wheel_def.reference_arm_node), + wheel_def.num_rays * 2, wheel_def.num_rays * 8, wheel_def.radius, wheel_def.propulsion, + wheel_def.braking, wheel_def.node_defaults, wheel_def.mass, + -1.f // Set width to axis length (width in definition is ignored) + ); - BuildWheelBeams( - wheel_def.num_rays, - base_node_index, - axis_node_1, - axis_node_2, - wheel_def.springiness, /* Tyre */ - wheel_def.damping, /* Tyre */ - wheel_def.springiness, /* Rim */ - wheel_def.damping, /* Rim */ - wheel_def.beam_defaults, - wheel_def.rigidity_node - ); + BuildWheelBeams(wheel_def.num_rays, base_node_index, axis_node_1, axis_node_2, wheel_def.springiness, /* Tyre */ + wheel_def.damping, /* Tyre */ + wheel_def.springiness, /* Rim */ + wheel_def.damping, /* Rim */ + wheel_def.beam_defaults, wheel_def.rigidity_node); m_wheel_visuals_queue.push_back(WheelVisualsTicket(wheel_index, base_node_index, &wheel_def)); @@ -4599,12 +4163,12 @@ void ActorSpawner::CreateWheelSkidmarks(unsigned int wheel_index) RoR::App::GetSimController()->GetSkidmarkConf(), &m_actor->ar_wheels[wheel_index], m_particles_parent_scenenode, 300, 20); } -unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) +unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 &wheel_2_def) { unsigned int base_node_index = m_actor->ar_num_nodes; - wheel_t & wheel = m_actor->ar_wheels[m_actor->ar_num_wheels]; - node_t *axis_node_1 = GetNodePointer(wheel_2_def.nodes[0]); - node_t *axis_node_2 = GetNodePointer(wheel_2_def.nodes[1]); + wheel_t & wheel = m_actor->ar_wheels[m_actor->ar_num_wheels]; + node_t * axis_node_1 = GetNodePointer(wheel_2_def.nodes[0]); + node_t * axis_node_2 = GetNodePointer(wheel_2_def.nodes[1]); if (axis_node_1 == nullptr || axis_node_2 == nullptr) { @@ -4623,25 +4187,24 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) if (pos_1.z > pos_2.z) { node_t *swap = axis_node_1; - axis_node_1 = axis_node_2; - axis_node_2 = swap; + axis_node_1 = axis_node_2; + axis_node_2 = swap; } /* Find out where to connect rigidity node */ bool rigidity_beam_side_1 = false; if (wheel_2_def.rigidity_node.IsValidAnyState()) { - node_t & rigidity_node = GetNode(wheel_2_def.rigidity_node); - Ogre::Real distance_1 = (rigidity_node.RelPosition - axis_node_1->RelPosition).length(); - Ogre::Real distance_2 = (rigidity_node.RelPosition - axis_node_2->RelPosition).length(); - rigidity_beam_side_1 = distance_1 < distance_2; + node_t & rigidity_node = GetNode(wheel_2_def.rigidity_node); + Ogre::Real distance_1 = (rigidity_node.RelPosition - axis_node_1->RelPosition).length(); + Ogre::Real distance_2 = (rigidity_node.RelPosition - axis_node_2->RelPosition).length(); + rigidity_beam_side_1 = distance_1 < distance_2; } - /* Node&beam generation */ Ogre::Vector3 axis_vector = axis_node_2->RelPosition - axis_node_1->RelPosition; axis_vector.normalise(); - Ogre::Vector3 rim_ray_vector = Ogre::Vector3(0, wheel_2_def.rim_radius, 0); + Ogre::Vector3 rim_ray_vector = Ogre::Vector3(0, wheel_2_def.rim_radius, 0); Ogre::Quaternion rim_ray_rotator = Ogre::Quaternion(Ogre::Degree(-360.f / wheel_2_def.num_rays), axis_vector); /* Width */ @@ -4655,7 +4218,7 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) /* Outer ring */ Ogre::Vector3 ray_point = axis_node_1->RelPosition + rim_ray_vector; - node_t & outer_node = GetFreeNode(); + node_t &outer_node = GetFreeNode(); InitNode(outer_node, ray_point, wheel_2_def.node_defaults); outer_node.mass = node_mass; outer_node.nd_rim_node = true; @@ -4667,7 +4230,7 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) /* Inner ring */ ray_point = axis_node_2->RelPosition + rim_ray_vector; - node_t & inner_node = GetFreeNode(); + node_t &inner_node = GetFreeNode(); InitNode(inner_node, ray_point, wheel_2_def.node_defaults); inner_node.mass = node_mass; inner_node.nd_rim_node = true; @@ -4677,15 +4240,15 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(inner_node.pos))); /* Wheel object */ - wheel.wh_rim_nodes[i * 2] = & outer_node; - wheel.wh_rim_nodes[(i * 2) + 1] = & inner_node; + wheel.wh_rim_nodes[i * 2] = &outer_node; + wheel.wh_rim_nodes[(i * 2) + 1] = &inner_node; rim_ray_vector = rim_ray_rotator * rim_ray_vector; } - Ogre::Vector3 tyre_ray_vector = Ogre::Vector3(0, wheel_2_def.tyre_radius, 0); + Ogre::Vector3 tyre_ray_vector = Ogre::Vector3(0, wheel_2_def.tyre_radius, 0); Ogre::Quaternion tyre_ray_rotator = Ogre::Quaternion(Ogre::Degree(-180.f / wheel_2_def.num_rays), axis_vector); - tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; + tyre_ray_vector = tyre_ray_rotator * tyre_ray_vector; /* Tyre nodes */ for (unsigned int i = 0; i < wheel_2_def.num_rays; i++) @@ -4693,7 +4256,7 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) /* Outer ring */ Ogre::Vector3 ray_point = axis_node_1->RelPosition + tyre_ray_vector; - node_t & outer_node = GetFreeNode(); + node_t &outer_node = GetFreeNode(); InitNode(outer_node, ray_point); outer_node.mass = (0.67f * wheel_2_def.mass) / (2.f * wheel_2_def.num_rays); outer_node.friction_coef = wheel.wh_width * WHEEL_FRICTION_COEF; @@ -4707,7 +4270,7 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) /* Inner ring */ ray_point = axis_node_2->RelPosition + tyre_ray_vector; - node_t & inner_node = GetFreeNode(); + node_t &inner_node = GetFreeNode(); InitNode(inner_node, ray_point); inner_node.mass = (0.33f * wheel_2_def.mass) / (2.f * wheel_2_def.num_rays); inner_node.friction_coef = wheel.wh_width * WHEEL_FRICTION_COEF; @@ -4719,8 +4282,8 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) m_gfx_nodes.push_back(GfxActor::NodeGfx(static_cast(inner_node.pos))); /* Wheel object */ - wheel.wh_nodes[i * 2] = & outer_node; - wheel.wh_nodes[(i * 2) + 1] = & inner_node; + wheel.wh_nodes[i * 2] = &outer_node; + wheel.wh_nodes[(i * 2) + 1] = &inner_node; tyre_ray_vector = rim_ray_rotator * tyre_ray_vector; // This is OK } @@ -4732,21 +4295,21 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) /* Bounded */ unsigned int rim_outer_node_index = base_node_index + (i * 2); - node_t *rim_outer_node = & m_actor->ar_nodes[rim_outer_node_index]; - node_t *rim_inner_node = & m_actor->ar_nodes[rim_outer_node_index + 1]; + node_t * rim_outer_node = &m_actor->ar_nodes[rim_outer_node_index]; + node_t * rim_inner_node = &m_actor->ar_nodes[rim_outer_node_index + 1]; unsigned int beam_index; - beam_index = AddWheelRimBeam(wheel_2_def, axis_node_1, rim_outer_node); + beam_index = AddWheelRimBeam(wheel_2_def, axis_node_1, rim_outer_node); GetBeam(beam_index).shortbound = 0.66; - beam_index = AddWheelRimBeam(wheel_2_def, axis_node_2, rim_inner_node); + beam_index = AddWheelRimBeam(wheel_2_def, axis_node_2, rim_inner_node); GetBeam(beam_index).shortbound = 0.66; AddWheelRimBeam(wheel_2_def, axis_node_2, rim_outer_node); AddWheelRimBeam(wheel_2_def, axis_node_1, rim_inner_node); /* Reinforcement */ unsigned int rim_next_outer_node_index = base_node_index + (((i + 1) % wheel_2_def.num_rays) * 2); - node_t *rim_next_outer_node = & m_actor->ar_nodes[rim_next_outer_node_index]; - node_t *rim_next_inner_node = & m_actor->ar_nodes[rim_next_outer_node_index + 1]; + node_t * rim_next_outer_node = &m_actor->ar_nodes[rim_next_outer_node_index]; + node_t * rim_next_inner_node = &m_actor->ar_nodes[rim_next_outer_node_index + 1]; AddWheelRimBeam(wheel_2_def, axis_node_1, rim_outer_node); AddWheelRimBeam(wheel_2_def, rim_outer_node, rim_inner_node); @@ -4758,21 +4321,19 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) /* -- Rigidity -- */ if (wheel_2_def.rigidity_node.IsValidAnyState()) { - unsigned int rig_beam_index = AddWheelRimBeam(wheel_2_def, - GetNodePointer(wheel_2_def.rigidity_node), - (rigidity_beam_side_1) ? rim_outer_node : rim_inner_node - ); + unsigned int rig_beam_index = AddWheelRimBeam(wheel_2_def, GetNodePointer(wheel_2_def.rigidity_node), + (rigidity_beam_side_1) ? rim_outer_node : rim_inner_node); m_actor->ar_beams[rig_beam_index].bm_type = BEAM_VIRTUAL; } /* --- Tyre --- */ - unsigned int tyre_node_index = rim_outer_node_index + (2 * wheel_2_def.num_rays); - node_t *tyre_outer_node = & m_actor->ar_nodes[tyre_node_index]; - node_t *tyre_inner_node = & m_actor->ar_nodes[tyre_node_index + 1]; + unsigned int tyre_node_index = rim_outer_node_index + (2 * wheel_2_def.num_rays); + node_t * tyre_outer_node = &m_actor->ar_nodes[tyre_node_index]; + node_t * tyre_inner_node = &m_actor->ar_nodes[tyre_node_index + 1]; unsigned int tyre_next_node_index = rim_next_outer_node_index + (2 * wheel_2_def.num_rays); - node_t *tyre_next_outer_node = & m_actor->ar_nodes[tyre_next_node_index]; - node_t *tyre_next_inner_node = & m_actor->ar_nodes[tyre_next_node_index + 1]; + node_t * tyre_next_outer_node = &m_actor->ar_nodes[tyre_next_node_index]; + node_t * tyre_next_inner_node = &m_actor->ar_nodes[tyre_next_node_index + 1]; /* Tyre band */ AddTyreBeam(wheel_2_def, tyre_outer_node, tyre_next_outer_node); @@ -4813,8 +4374,8 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) } /* Find near attach */ - Ogre::Real length_1 = (axis_node_1->RelPosition - wheel.wh_arm_node->RelPosition).length(); - Ogre::Real length_2 = (axis_node_2->RelPosition - wheel.wh_arm_node->RelPosition).length(); + Ogre::Real length_1 = (axis_node_1->RelPosition - wheel.wh_arm_node->RelPosition).length(); + Ogre::Real length_2 = (axis_node_2->RelPosition - wheel.wh_arm_node->RelPosition).length(); wheel.wh_near_attach_node = (length_1 < length_2) ? axis_node_1 : axis_node_2; CreateWheelSkidmarks(static_cast(m_actor->ar_num_wheels)); @@ -4825,93 +4386,74 @@ unsigned int ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) return wheel_index; } -void ActorSpawner::CreateWheelVisuals( - unsigned int wheel_index, - unsigned int node_base_index, - unsigned int num_rays, - Ogre::String const & rim_material_name, - Ogre::String const & band_material_name, - bool separate_rim, - float rim_ratio -) +void ActorSpawner::CreateWheelVisuals(unsigned int wheel_index, unsigned int node_base_index, unsigned int num_rays, + Ogre::String const &rim_material_name, Ogre::String const &band_material_name, + bool separate_rim, float rim_ratio) { - wheel_t & wheel = m_actor->ar_wheels[wheel_index]; + wheel_t &wheel = m_actor->ar_wheels[wheel_index]; try { GfxActor::WheelGfx visual_wheel; const std::string wheel_mesh_name = this->ComposeName("WheelMesh", wheel_index); - visual_wheel.wx_is_meshwheel = false; - visual_wheel.wx_flex_mesh = new FlexMesh( - wheel_mesh_name, - m_actor->m_gfx_actor.get(), - wheel.wh_axis_node_0->pos, - wheel.wh_axis_node_1->pos, - node_base_index, - num_rays, - rim_material_name, - band_material_name, - separate_rim, - rim_ratio - ); + visual_wheel.wx_is_meshwheel = false; + visual_wheel.wx_flex_mesh = + new FlexMesh(wheel_mesh_name, m_actor->m_gfx_actor.get(), wheel.wh_axis_node_0->pos, wheel.wh_axis_node_1->pos, + node_base_index, num_rays, rim_material_name, band_material_name, separate_rim, rim_ratio); const std::string instance_name = this->ComposeName("WheelEntity", wheel_index); - Ogre::Entity *ec = gEnv->sceneManager->createEntity(instance_name, wheel_mesh_name); + Ogre::Entity * ec = gEnv->sceneManager->createEntity(instance_name, wheel_mesh_name); this->SetupNewEntity(ec, Ogre::ColourValue(0, 0.5, 0.5)); visual_wheel.wx_scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_actor->m_deletion_entities.emplace_back(ec); visual_wheel.wx_scenenode->attachObject(ec); m_actor->m_gfx_actor->SetWheelVisuals(wheel_index, visual_wheel); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - AddMessage(Message::TYPE_ERROR, "Failed to create wheel visuals: " + e.getFullDescription()); + AddMessage(Message::TYPE_ERROR, "Failed to create wheel visuals: " + e.getFullDescription()); } } -unsigned int ActorSpawner::AddWheelBeam( - node_t *node_1, - node_t *node_2, - float spring, - float damping, - std::shared_ptr beam_defaults, - float max_contraction, /* Default: -1.f */ - float max_extension, /* Default: -1.f */ - int type /* Default: BEAM_INVISIBLE */ +unsigned int ActorSpawner::AddWheelBeam(node_t *node_1, node_t *node_2, float spring, float damping, + std::shared_ptr beam_defaults, + float max_contraction, /* Default: -1.f */ + float max_extension, /* Default: -1.f */ + int type /* Default: BEAM_INVISIBLE */ ) { unsigned int index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(*node_1, *node_2, beam_defaults, DEFAULT_DETACHER_GROUP); - beam.bm_type = type; - beam.k = spring; - beam.d = damping; + beam_t & beam = AddBeam(*node_1, *node_2, beam_defaults, DEFAULT_DETACHER_GROUP); + beam.bm_type = type; + beam.k = spring; + beam.d = damping; if (max_contraction > 0.f) { beam.shortbound = max_contraction; - beam.longbound = max_extension; - beam.bounded = SHOCK1; + beam.longbound = max_extension; + beam.bounded = SHOCK1; } CalculateBeamLength(beam); return index; } -unsigned int ActorSpawner::AddWheelRimBeam(RigDef::Wheel2 & wheel_2_def, node_t *node_1, node_t *node_2) +unsigned int ActorSpawner::AddWheelRimBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2) { unsigned int beam_index = _SectionWheels2AddBeam(wheel_2_def, node_1, node_2); - beam_t & beam = GetBeam(beam_index); - beam.k = wheel_2_def.rim_springiness; - beam.d = wheel_2_def.rim_damping; + beam_t & beam = GetBeam(beam_index); + beam.k = wheel_2_def.rim_springiness; + beam.d = wheel_2_def.rim_damping; return beam_index; } -unsigned int ActorSpawner::AddTyreBeam(RigDef::Wheel2 & wheel_2_def, node_t *node_1, node_t *node_2) +unsigned int ActorSpawner::AddTyreBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2) { unsigned int beam_index = _SectionWheels2AddBeam(wheel_2_def, node_1, node_2); - beam_t & beam = GetBeam(beam_index); - beam.k = wheel_2_def.tyre_springiness; - beam.d = wheel_2_def.tyre_damping; + beam_t & beam = GetBeam(beam_index); + beam.k = wheel_2_def.tyre_springiness; + beam.d = wheel_2_def.tyre_damping; m_actor->ar_pressure_beams[m_actor->ar_free_pressure_beam] = beam_index; m_actor->ar_free_pressure_beam++; @@ -4919,10 +4461,10 @@ unsigned int ActorSpawner::AddTyreBeam(RigDef::Wheel2 & wheel_2_def, node_t *nod return beam_index; } -unsigned int ActorSpawner::_SectionWheels2AddBeam(RigDef::Wheel2 & wheel_2_def, node_t *node_1, node_t *node_2) +unsigned int ActorSpawner::_SectionWheels2AddBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2) { unsigned int index = m_actor->ar_num_beams; - beam_t & beam = GetFreeBeam(); + beam_t & beam = GetFreeBeam(); InitBeam(beam, node_1, node_2); beam.bm_type = BEAM_NORMAL; SetBeamStrength(beam, wheel_2_def.beam_defaults->breaking_threshold); @@ -4930,19 +4472,19 @@ unsigned int ActorSpawner::_SectionWheels2AddBeam(RigDef::Wheel2 & wheel_2_def, return index; } -void ActorSpawner::ProcessWheel2(RigDef::Wheel2 & def) +void ActorSpawner::ProcessWheel2(RigDef::Wheel2 &def) { unsigned int node_base_index = m_actor->ar_num_nodes; - unsigned int wheel_index = AddWheel2(def); + unsigned int wheel_index = AddWheel2(def); m_wheel_visuals_queue.push_back(WheelVisualsTicket(wheel_index, node_base_index, &def)); }; -void ActorSpawner::ProcessWheel(RigDef::Wheel & def) +void ActorSpawner::ProcessWheel(RigDef::Wheel &def) { AddWheel(def); }; -void ActorSpawner::ProcessWheelDetacher(RigDef::WheelDetacher & def) +void ActorSpawner::ProcessWheelDetacher(RigDef::WheelDetacher &def) { if (def.wheel_id > m_actor->ar_num_wheels - 1) { @@ -4953,7 +4495,7 @@ void ActorSpawner::ProcessWheelDetacher(RigDef::WheelDetacher & def) m_actor->ar_wheels[def.wheel_id].wh_detacher_group = def.detacher_group; }; -void ActorSpawner::ProcessTractionControl(RigDef::TractionControl & def) +void ActorSpawner::ProcessTractionControl(RigDef::TractionControl &def) { /* #1: regulating_force */ float force = def.regulation_force; @@ -4974,19 +4516,16 @@ void ActorSpawner::ProcessTractionControl(RigDef::TractionControl & def) /* #4: pulse/sec */ float pulse = def.pulse_per_sec; - if (pulse <= 1.0f || pulse >= 2000.0f) - { - pulse = 2000.0f; - } + if (pulse <= 1.0f || pulse >= 2000.0f) { pulse = 2000.0f; } m_actor->tc_pulse_time = 1 / pulse; /* #4: mode */ - m_actor->tc_mode = def.attr_is_on; - m_actor->tc_nodash = def.attr_no_dashboard; + m_actor->tc_mode = def.attr_is_on; + m_actor->tc_nodash = def.attr_no_dashboard; m_actor->tc_notoggle = def.attr_no_toggle; }; -void ActorSpawner::ProcessAntiLockBrakes(RigDef::AntiLockBrakes & def) +void ActorSpawner::ProcessAntiLockBrakes(RigDef::AntiLockBrakes &def) { /* #1: regulating_force */ float force = def.regulation_force; @@ -5001,34 +4540,28 @@ void ActorSpawner::ProcessAntiLockBrakes(RigDef::AntiLockBrakes & def) /* #2: min_speed */ /* Wheelspeed adaption: 60 sec * 60 mins / 1000(kilometer) = 3.6 to get meter per sec */ - float min_speed = def.min_speed / 3.6f; + float min_speed = def.min_speed / 3.6f; m_actor->alb_minspeed = std::max(0.5f, min_speed); /* #3: pulse_per_sec */ float pulse = def.pulse_per_sec; - if (pulse <= 1.0f || pulse >= 2000.0f) - { - pulse = 2000.0f; - } + if (pulse <= 1.0f || pulse >= 2000.0f) { pulse = 2000.0f; } m_actor->alb_pulse_time = 1 / pulse; /* #4: mode */ - m_actor->alb_mode = def.attr_is_on; - m_actor->alb_nodash = def.attr_no_dashboard; + m_actor->alb_mode = def.attr_is_on; + m_actor->alb_nodash = def.attr_no_dashboard; m_actor->alb_notoggle = def.attr_no_toggle; } -void ActorSpawner::ProcessBrakes(RigDef::Brakes & def) +void ActorSpawner::ProcessBrakes(RigDef::Brakes &def) { - m_actor->ar_brake_force = def.default_braking_force; + m_actor->ar_brake_force = def.default_braking_force; m_actor->m_handbrake_force = 2.f * m_actor->ar_brake_force; - if (def.parking_brake_force != -1.f) - { - m_actor->m_handbrake_force = def.parking_brake_force; - } + if (def.parking_brake_force != -1.f) { m_actor->m_handbrake_force = def.parking_brake_force; } }; -void ActorSpawner::ProcessEngturbo(RigDef::Engturbo & def) +void ActorSpawner::ProcessEngturbo(RigDef::Engturbo &def) { /* Is this a land vehicle? */ if (m_actor->ar_engine == nullptr) @@ -5036,23 +4569,23 @@ void ActorSpawner::ProcessEngturbo(RigDef::Engturbo & def) AddMessage(Message::TYPE_WARNING, "Section 'engturbo' found but no engine defined. Skipping ..."); return; } - - /* Find it */ - std::shared_ptr engturbo; + + /* Find it */ + std::shared_ptr engturbo; std::list>::iterator module_itor = m_selected_modules.begin(); for (; module_itor != m_selected_modules.end(); module_itor++) { - if (module_itor->get()->engturbo != nullptr) - { - engturbo = module_itor->get()->engturbo; - } + if (module_itor->get()->engturbo != nullptr) { engturbo = module_itor->get()->engturbo; } } - - /* Process it */ - m_actor->ar_engine->SetTurboOptions(engturbo->version, engturbo->tinertiaFactor, engturbo->nturbos, engturbo->param1, engturbo->param2, engturbo->param3, engturbo->param4, engturbo->param5, engturbo->param6, engturbo->param7, engturbo->param8, engturbo->param9, engturbo->param10, engturbo->param11); + + /* Process it */ + m_actor->ar_engine->SetTurboOptions(engturbo->version, engturbo->tinertiaFactor, engturbo->nturbos, engturbo->param1, + engturbo->param2, engturbo->param3, engturbo->param4, engturbo->param5, engturbo->param6, + engturbo->param7, engturbo->param8, engturbo->param9, engturbo->param10, + engturbo->param11); }; -void ActorSpawner::ProcessEngoption(RigDef::Engoption & def) +void ActorSpawner::ProcessEngoption(RigDef::Engoption &def) { /* Is this a land vehicle? */ if (m_actor->ar_engine == nullptr) @@ -5062,38 +4595,24 @@ void ActorSpawner::ProcessEngoption(RigDef::Engoption & def) } /* Find it */ - std::shared_ptr engoption; + std::shared_ptr engoption; std::list>::iterator module_itor = m_selected_modules.begin(); for (; module_itor != m_selected_modules.end(); module_itor++) { - if (module_itor->get()->engoption != nullptr) - { - engoption = module_itor->get()->engoption; - } + if (module_itor->get()->engoption != nullptr) { engoption = module_itor->get()->engoption; } } if (engoption->idle_rpm > 0 && engoption->stall_rpm > 0 && engoption->stall_rpm > engoption->idle_rpm) - { - AddMessage(Message::TYPE_WARNING, "Stall RPM is set higher than Idle RPM."); - } + { AddMessage(Message::TYPE_WARNING, "Stall RPM is set higher than Idle RPM."); } /* Process it */ - m_actor->ar_engine->SetEngineOptions( - engoption->inertia, - engoption->type, - engoption->clutch_force, - engoption->shift_time, - engoption->clutch_time, - engoption->post_shift_time, - engoption->idle_rpm, - engoption->stall_rpm, - engoption->max_idle_mixture, - engoption->min_idle_mixture, - engoption->braking_torque - ); + m_actor->ar_engine->SetEngineOptions(engoption->inertia, engoption->type, engoption->clutch_force, engoption->shift_time, + engoption->clutch_time, engoption->post_shift_time, engoption->idle_rpm, + engoption->stall_rpm, engoption->max_idle_mixture, engoption->min_idle_mixture, + engoption->braking_torque); }; -void ActorSpawner::ProcessEngine(RigDef::Engine & def) +void ActorSpawner::ProcessEngine(RigDef::Engine &def) { /* Process it */ m_actor->ar_driveable = TRUCK; @@ -5110,14 +4629,8 @@ void ActorSpawner::ProcessEngine(RigDef::Engine & def) gears_compat.push_back(*itor); } - m_actor->ar_engine = new EngineSim( - def.shift_down_rpm, - def.shift_up_rpm, - def.torque, - gears_compat, - def.global_gear_ratio, - m_actor - ); + m_actor->ar_engine = + new EngineSim(def.shift_down_rpm, def.shift_up_rpm, def.torque, gears_compat, def.global_gear_ratio, m_actor); m_actor->ar_engine->SetAutoMode(App::sim_gearbox_mode.GetActive()); }; @@ -5131,7 +4644,7 @@ void ActorSpawner::ProcessHelp() for (; module_itor != m_selected_modules.end(); module_itor++) { auto module = module_itor->get(); - if (! module->help_panel_material_name.empty()) + if (!module->help_panel_material_name.empty()) { m_actor->ar_help_panel_material = module->help_panel_material_name; material_count++; @@ -5142,7 +4655,7 @@ void ActorSpawner::ProcessHelp() { std::stringstream msg; msg << "Multiple (" << material_count << ") 'help' sections found. Using the last one..."; - AddMessage(Message::TYPE_WARNING, msg.str()); + AddMessage(Message::TYPE_WARNING, msg.str()); } SetCurrentKeyword(RigDef::File::KEYWORD_INVALID); @@ -5156,23 +4669,20 @@ void ActorSpawner::ProcessAuthors() for (; author_itor != m_file->authors.end(); author_itor++) { authorinfo_t author; - author.type = author_itor->type; - author.name = author_itor->name; + author.type = author_itor->type; + author.name = author_itor->name; author.email = author_itor->email; - if (author_itor->_has_forum_account) - { - author.id = author_itor->forum_account_id; - } + if (author_itor->_has_forum_account) { author.id = author_itor->forum_account_id; } m_actor->authors.push_back(author); - } + } SetCurrentKeyword(RigDef::File::KEYWORD_INVALID); }; -unsigned int ActorSpawner::GetNodeIndexOrThrow(RigDef::Node::Ref const & node_ref) +unsigned int ActorSpawner::GetNodeIndexOrThrow(RigDef::Node::Ref const &node_ref) { std::pair result = GetNodeIndex(node_ref); - if (! result.second) + if (!result.second) { std::stringstream msg; msg << "Failed to retrieve required node: " << node_ref.ToString(); @@ -5181,19 +4691,16 @@ unsigned int ActorSpawner::GetNodeIndexOrThrow(RigDef::Node::Ref const & node_re return result.first; } -node_t & ActorSpawner::GetNodeOrThrow(RigDef::Node::Ref const & node_ref) +node_t &ActorSpawner::GetNodeOrThrow(RigDef::Node::Ref const &node_ref) { return m_actor->ar_nodes[GetNodeIndexOrThrow(node_ref)]; } -void ActorSpawner::ProcessCamera(RigDef::Camera & def) +void ActorSpawner::ProcessCamera(RigDef::Camera &def) { /* Center node */ if (def.center_node.IsValidAnyState()) - { - m_actor->ar_camera_node_pos[m_actor->ar_num_cameras] - = static_cast(GetNodeIndexOrThrow(def.center_node)); - } + { m_actor->ar_camera_node_pos[m_actor->ar_num_cameras] = static_cast(GetNodeIndexOrThrow(def.center_node)); } else { m_actor->ar_camera_node_pos[m_actor->ar_num_cameras] = -1; @@ -5201,10 +4708,7 @@ void ActorSpawner::ProcessCamera(RigDef::Camera & def) /* Direction node */ if (def.back_node.IsValidAnyState()) - { - m_actor->ar_camera_node_dir[m_actor->ar_num_cameras] - = static_cast(GetNodeIndexOrThrow(def.back_node)); - } + { m_actor->ar_camera_node_dir[m_actor->ar_num_cameras] = static_cast(GetNodeIndexOrThrow(def.back_node)); } else { m_actor->ar_camera_node_dir[m_actor->ar_num_cameras] = -1; @@ -5212,10 +4716,7 @@ void ActorSpawner::ProcessCamera(RigDef::Camera & def) /* Roll node */ if (def.left_node.IsValidAnyState()) - { - m_actor->ar_camera_node_roll[m_actor->ar_num_cameras] - = static_cast(GetNodeIndexOrThrow(def.left_node)); - } + { m_actor->ar_camera_node_roll[m_actor->ar_num_cameras] = static_cast(GetNodeIndexOrThrow(def.left_node)); } else { m_actor->ar_camera_node_roll[m_actor->ar_num_cameras] = -1; @@ -5225,21 +4726,18 @@ void ActorSpawner::ProcessCamera(RigDef::Camera & def) m_actor->ar_num_cameras++; }; -node_t* ActorSpawner::GetBeamNodePointer(RigDef::Node::Ref const & node_ref) +node_t *ActorSpawner::GetBeamNodePointer(RigDef::Node::Ref const &node_ref) { - node_t* node = GetNodePointer(node_ref); - if (node != nullptr) - { - return node; - } + node_t *node = GetNodePointer(node_ref); + if (node != nullptr) { return node; } return nullptr; } -void ActorSpawner::ProcessBeam(RigDef::Beam & def) +void ActorSpawner::ProcessBeam(RigDef::Beam &def) { // Nodes - node_t* ar_nodes[] = {nullptr, nullptr}; - ar_nodes[0] = GetBeamNodePointer(def.nodes[0]); + node_t *ar_nodes[] = {nullptr, nullptr}; + ar_nodes[0] = GetBeamNodePointer(def.nodes[0]); if (ar_nodes[0] == nullptr) { AddMessage(Message::TYPE_WARNING, std::string("Ignoring beam, could not find node: ") + def.nodes[0].ToString()); @@ -5253,12 +4751,12 @@ void ActorSpawner::ProcessBeam(RigDef::Beam & def) } // Beam - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(*ar_nodes[0], *ar_nodes[1], def.defaults, def.detacher_group); - beam.bm_type = BEAM_NORMAL; - beam.k = def.defaults->GetScaledSpringiness(); - beam.d = def.defaults->GetScaledDamping(); - beam.bounded = NOSHOCK; // Orig: if (shortbound) ... hardcoded in BTS_BEAMS + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(*ar_nodes[0], *ar_nodes[1], def.defaults, def.detacher_group); + beam.bm_type = BEAM_NORMAL; + beam.k = def.defaults->GetScaledSpringiness(); + beam.d = def.defaults->GetScaledDamping(); + beam.bounded = NOSHOCK; // Orig: if (shortbound) ... hardcoded in BTS_BEAMS /* Calculate length */ // orig = precompression hardcoded to 1 @@ -5266,26 +4764,21 @@ void ActorSpawner::ProcessBeam(RigDef::Beam & def) /* Strength */ float beam_strength = def.defaults->GetScaledBreakingThreshold(); - beam.strength = beam_strength; + beam.strength = beam_strength; /* Options */ - if (BITMASK_IS_1(def.options, RigDef::Beam::OPTION_r_ROPE)) - { - beam.bounded = ROPE; - } + if (BITMASK_IS_1(def.options, RigDef::Beam::OPTION_r_ROPE)) { beam.bounded = ROPE; } if (BITMASK_IS_1(def.options, RigDef::Beam::OPTION_s_SUPPORT)) { - beam.bounded = SUPPORTBEAM; + beam.bounded = SUPPORTBEAM; beam.longbound = def.extension_break_limit; } if (BITMASK_IS_0(def.options, RigDef::Beam::OPTION_i_INVISIBLE)) - { - this->CreateBeamVisuals(beam, beam_index, true, def.defaults); - } + { this->CreateBeamVisuals(beam, beam_index, true, def.defaults); } } -void ActorSpawner::SetBeamDeformationThreshold(beam_t & beam, std::shared_ptr beam_defaults) +void ActorSpawner::SetBeamDeformationThreshold(beam_t &beam, std::shared_ptr beam_defaults) { /* --------------------------------------------------------------------------- @@ -5307,7 +4800,7 @@ void ActorSpawner::SetBeamDeformationThreshold(beam_t & beam, std::shared_ptr_is_user_defined) { default_deform = beam_defaults->deformation_threshold; - if (!beam_defaults->_enable_advanced_deformation && default_deform < BEAM_DEFORM) - { - default_deform = BEAM_DEFORM; - } + if (!beam_defaults->_enable_advanced_deformation && default_deform < BEAM_DEFORM) { default_deform = BEAM_DEFORM; } if (beam_defaults->_is_plastic_deform_coef_user_defined && beam_defaults->plastic_deform_coef >= 0.f) - { - beam_creak = 0.f; - } + { beam_creak = 0.f; } } // Old 'add_beam' - if (default_deform < beam_creak) - { - default_deform = beam_creak; - } + if (default_deform < beam_creak) { default_deform = beam_creak; } float deformation_threshold = default_deform * beam_defaults->scale.deformation_threshold_constant; @@ -5411,15 +4896,13 @@ void ActorSpawner::SetBeamDeformationThreshold(beam_t & beam, std::shared_ptr const& beam_defaults, std::string material_override) +void ActorSpawner::CreateBeamVisuals(beam_t const &beam, int beam_index, bool visible, + std::shared_ptr const &beam_defaults, std::string material_override) { std::string material_name = material_override; if (material_name.empty()) { - if (beam.bm_type == BEAM_HYDRO) - { - material_name = "tracks/Chrome"; - } + if (beam.bm_type == BEAM_HYDRO) { material_name = "tracks/Chrome"; } else { material_name = beam_defaults->beam_material_name; @@ -5428,10 +4911,7 @@ void ActorSpawner::CreateBeamVisuals(beam_t const & beam, int beam_index, bool v if (it != m_managed_materials.end()) { auto material = it->second; - if (!material.isNull()) - { - material_name = material->getName(); - } + if (!material.isNull()) { material_name = material->getName(); } } } } @@ -5439,14 +4919,14 @@ void ActorSpawner::CreateBeamVisuals(beam_t const & beam, int beam_index, bool v m_beam_visuals_queue.emplace_back(beam_index, beam_defaults->visual_beam_diameter, material_name.c_str(), visible); } -void ActorSpawner::CalculateBeamLength(beam_t & beam) +void ActorSpawner::CalculateBeamLength(beam_t &beam) { float beam_length = (beam.p1->RelPosition - beam.p2->RelPosition).length(); - beam.L = beam_length; - beam.refL = beam_length; + beam.L = beam_length; + beam.refL = beam_length; } -void ActorSpawner::InitBeam(beam_t & beam, node_t *node_1, node_t *node_2) +void ActorSpawner::InitBeam(beam_t &beam, node_t *node_1, node_t *node_2) { beam.p1 = node_1; beam.p2 = node_2; @@ -5455,7 +4935,7 @@ void ActorSpawner::InitBeam(beam_t & beam, node_t *node_1, node_t *node_2) CalculateBeamLength(beam); } -void ActorSpawner::AddMessage(ActorSpawner::Message::Type type, Ogre::String const & text) +void ActorSpawner::AddMessage(ActorSpawner::Message::Type type, Ogre::String const &text) { /* Add message to report */ m_messages.push_back(Message(type, text, m_current_keyword)); @@ -5465,50 +4945,45 @@ void ActorSpawner::AddMessage(ActorSpawner::Message::Type type, Ogre::String con report << " == ActorSpawner: "; switch (type) { - case (ActorSpawner::Message::TYPE_INTERNAL_ERROR): - report << "INTERNAL ERROR"; - ++m_messages_num_errors; - break; + case (ActorSpawner::Message::TYPE_INTERNAL_ERROR): + report << "INTERNAL ERROR"; + ++m_messages_num_errors; + break; - case (ActorSpawner::Message::TYPE_ERROR): - report << "ERROR"; - ++m_messages_num_errors; - break; + case (ActorSpawner::Message::TYPE_ERROR): + report << "ERROR"; + ++m_messages_num_errors; + break; - case (ActorSpawner::Message::TYPE_WARNING): - report << "WARNING"; - ++m_messages_num_warnings; - break; + case (ActorSpawner::Message::TYPE_WARNING): + report << "WARNING"; + ++m_messages_num_warnings; + break; - default: - report << "INFO"; - ++m_messages_num_other; - break; + default: + report << "INFO"; + ++m_messages_num_other; + break; } report << " (Keyword " << RigDef::File::KeywordToString(m_current_keyword) << ") " << text; Ogre::LogManager::getSingleton().logMessage(report.str()); } -std::pair ActorSpawner::GetNodeIndex(RigDef::Node::Ref const & node_ref, bool quiet /* Default: false */) +std::pair ActorSpawner::GetNodeIndex(RigDef::Node::Ref const &node_ref, bool quiet /* Default: false */) { if (!node_ref.IsValidAnyState()) { - if (! quiet) - { - AddMessage(Message::TYPE_ERROR, std::string("Attempt to resolve invalid node reference: ") + node_ref.ToString()); - } + if (!quiet) + { AddMessage(Message::TYPE_ERROR, std::string("Attempt to resolve invalid node reference: ") + node_ref.ToString()); } return std::make_pair(0, false); } bool is_imported = node_ref.GetImportState_IsValid(); - bool is_named = (is_imported ? node_ref.GetImportState_IsResolvedNamed() : node_ref.GetRegularState_IsNamed()); + bool is_named = (is_imported ? node_ref.GetImportState_IsResolvedNamed() : node_ref.GetRegularState_IsNamed()); if (is_named) { auto result = m_named_nodes.find(node_ref.Str()); - if (result != m_named_nodes.end()) - { - return std::make_pair(result->second, true); - } - else if (! quiet) + if (result != m_named_nodes.end()) { return std::make_pair(result->second, true); } + else if (!quiet) { std::stringstream msg; msg << "Failed to resolve node-ref (node not found):" << node_ref.ToString(); @@ -5521,10 +4996,11 @@ std::pair ActorSpawner::GetNodeIndex(RigDef::Node::Ref const // Imported nodes pass without check if (!is_imported && (node_ref.Num() >= static_cast(m_actor->ar_num_nodes))) { - if (! quiet) + if (!quiet) { std::stringstream msg; - msg << "Failed to resolve node-ref (node index too big, node count is: "<ar_num_nodes<<"): " << node_ref.ToString(); + msg << "Failed to resolve node-ref (node index too big, node count is: " << m_actor->ar_num_nodes + << "): " << node_ref.ToString(); AddMessage(Message::TYPE_ERROR, msg.str()); } return std::make_pair(0, false); @@ -5533,20 +5009,17 @@ std::pair ActorSpawner::GetNodeIndex(RigDef::Node::Ref const } } -node_t* ActorSpawner::GetNodePointer(RigDef::Node::Ref const & node_ref) +node_t *ActorSpawner::GetNodePointer(RigDef::Node::Ref const &node_ref) { std::pair result = GetNodeIndex(node_ref); - if (result.second) - { - return & m_actor->ar_nodes[result.first]; - } + if (result.second) { return &m_actor->ar_nodes[result.first]; } else { return nullptr; } } -node_t* ActorSpawner::GetNodePointerOrThrow(RigDef::Node::Ref const & node_ref) +node_t *ActorSpawner::GetNodePointerOrThrow(RigDef::Node::Ref const &node_ref) { node_t *node = GetNodePointer(node_ref); if (node == nullptr) @@ -5558,24 +5031,26 @@ node_t* ActorSpawner::GetNodePointerOrThrow(RigDef::Node::Ref const & node_ref) return node; } -std::pair ActorSpawner::AddNode(RigDef::Node::Id & id) +std::pair ActorSpawner::AddNode(RigDef::Node::Id &id) { if (!id.IsValid()) { std::stringstream msg; - msg << "Attempt to add node with 'INVALID' flag: " << id.ToString() << " (number of nodes at this point: " << m_actor->ar_num_nodes << ")"; + msg << "Attempt to add node with 'INVALID' flag: " << id.ToString() + << " (number of nodes at this point: " << m_actor->ar_num_nodes << ")"; this->AddMessage(Message::TYPE_ERROR, msg.str()); return std::make_pair(0, false); } if (id.IsTypeNamed()) { - unsigned int new_index = static_cast(m_actor->ar_num_nodes); - auto insert_result = m_named_nodes.insert(std::make_pair(id.Str(), new_index)); - if (! insert_result.second) + unsigned int new_index = static_cast(m_actor->ar_num_nodes); + auto insert_result = m_named_nodes.insert(std::make_pair(id.Str(), new_index)); + if (!insert_result.second) { std::stringstream msg; - msg << "Ignoring named node! Duplicate name: " << id.Str() << " (number of nodes at this point: " << m_actor->ar_num_nodes << ")"; + msg << "Ignoring named node! Duplicate name: " << id.Str() + << " (number of nodes at this point: " << m_actor->ar_num_nodes << ")"; this->AddMessage(Message::TYPE_ERROR, msg.str()); return std::make_pair(0, false); } @@ -5587,7 +5062,8 @@ std::pair ActorSpawner::AddNode(RigDef::Node::Id & id) if (id.Num() < static_cast(m_actor->ar_num_nodes)) { std::stringstream msg; - msg << "Duplicate node number, previous definition will be overriden! - " << id.ToString() << " (number of nodes at this point: " << m_actor->ar_num_nodes << ")"; + msg << "Duplicate node number, previous definition will be overriden! - " << id.ToString() + << " (number of nodes at this point: " << m_actor->ar_num_nodes << ")"; this->AddMessage(Message::TYPE_WARNING, msg.str()); } unsigned int new_index = static_cast(m_actor->ar_num_nodes); @@ -5598,25 +5074,22 @@ std::pair ActorSpawner::AddNode(RigDef::Node::Id & id) throw Exception("Invalid Node::Id without type flags!"); } -void ActorSpawner::ProcessNode(RigDef::Node & def) +void ActorSpawner::ProcessNode(RigDef::Node &def) { std::pair inserted_node = AddNode(def.id); - if (! inserted_node.second) - { - return; - } + if (!inserted_node.second) { return; } - node_t & node = m_actor->ar_nodes[inserted_node.first]; - node.pos = inserted_node.first; /* Node index */ + node_t &node = m_actor->ar_nodes[inserted_node.first]; + node.pos = inserted_node.first; /* Node index */ /* Positioning */ Ogre::Vector3 node_position = m_spawn_position + def.position; - node.AbsPosition = node_position; - node.RelPosition = node_position - m_actor->ar_origin; + node.AbsPosition = node_position; + node.RelPosition = node_position - m_actor->ar_origin; node.friction_coef = def.node_defaults->friction; - node.volume_coef = def.node_defaults->volume; - node.surface_coef = def.node_defaults->surface; + node.volume_coef = def.node_defaults->volume; + node.surface_coef = def.node_defaults->surface; /* Mass */ m_actor->ar_minimass[inserted_node.first] = def.node_minimass->min_mass; @@ -5624,18 +5097,19 @@ void ActorSpawner::ProcessNode(RigDef::Node & def) if (def.node_defaults->load_weight >= 0.f) // The >= operator is in orig. { // orig = further override of hardcoded default. - node.mass = def.node_defaults->load_weight; + node.mass = def.node_defaults->load_weight; node.nd_override_mass = true; - node.nd_loaded_mass = true; + node.nd_loaded_mass = true; } else { - node.mass = 10; // Hardcoded in original (bts_nodes, call to init_node()) + node.mass = 10; // Hardcoded in original (bts_nodes, call to init_node()) node.nd_loaded_mass = false; } /* Lockgroup */ - node.nd_lockgroup = (m_file->lockgroup_default_nolock) ? RigDef::Lockgroup::LOCKGROUP_NOLOCK : RigDef::Lockgroup::LOCKGROUP_DEFAULT; + node.nd_lockgroup = + (m_file->lockgroup_default_nolock) ? RigDef::Lockgroup::LOCKGROUP_NOLOCK : RigDef::Lockgroup::LOCKGROUP_DEFAULT; /* Options */ unsigned int options = def.options | def.node_defaults->options; /* Merge bit flags */ @@ -5645,7 +5119,7 @@ void ActorSpawner::ProcessNode(RigDef::Node & def) if (def._has_load_weight_override) { node.nd_override_mass = true; - node.mass = def.load_weight_override; + node.mass = def.load_weight_override; } else { @@ -5656,47 +5130,47 @@ void ActorSpawner::ProcessNode(RigDef::Node & def) { /* Link [current-node] -> [node-0] */ /* If current node is 0, link [node-0] -> [node-1] */ - node_t & node_2 = (node.pos == 0) ? GetNode(1) : GetNode(0); + node_t & node_2 = (node.pos == 0) ? GetNode(1) : GetNode(0); unsigned int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(node, node_2, def.beam_defaults, def.detacher_group); + beam_t &beam = AddBeam(node, node_2, def.beam_defaults, def.detacher_group); SetBeamStrength(beam, def.beam_defaults->GetScaledBreakingThreshold() * 100.f); - beam.bm_type = BEAM_HYDRO; - beam.d = def.beam_defaults->GetScaledDamping() * 0.1f; - beam.k = def.beam_defaults->GetScaledSpringiness(); - beam.bounded = ROPE; - beam.bm_disabled = true; - beam.L = HOOK_RANGE_DEFAULT; - beam.refL = HOOK_RANGE_DEFAULT; + beam.bm_type = BEAM_HYDRO; + beam.d = def.beam_defaults->GetScaledDamping() * 0.1f; + beam.k = def.beam_defaults->GetScaledSpringiness(); + beam.bounded = ROPE; + beam.bm_disabled = true; + beam.L = HOOK_RANGE_DEFAULT; + beam.refL = HOOK_RANGE_DEFAULT; SetBeamDeformationThreshold(beam, def.beam_defaults); CreateBeamVisuals(beam, beam_index, false, def.beam_defaults); - + // Logic cloned from SerializedRig.cpp, section BTS_NODES hook_t hook; - hook.hk_hook_node = & node; - hook.hk_group = -1; - hook.hk_locked = UNLOCKED; - hook.hk_lock_node = nullptr; - hook.hk_locked_actor = nullptr; - hook.hk_lockgroup = -1; - hook.hk_beam = & beam; - hook.hk_maxforce = HOOK_FORCE_DEFAULT; - hook.hk_lockrange = HOOK_RANGE_DEFAULT; - hook.hk_lockspeed = HOOK_SPEED_DEFAULT; - hook.hk_selflock = false; - hook.hk_nodisable = false; - hook.hk_timer = 0.0f; - hook.hk_timer_preset = HOOK_LOCK_TIMER_DEFAULT; - hook.hk_autolock = false; - hook.hk_min_length = 0.f; + hook.hk_hook_node = &node; + hook.hk_group = -1; + hook.hk_locked = UNLOCKED; + hook.hk_lock_node = nullptr; + hook.hk_locked_actor = nullptr; + hook.hk_lockgroup = -1; + hook.hk_beam = &beam; + hook.hk_maxforce = HOOK_FORCE_DEFAULT; + hook.hk_lockrange = HOOK_RANGE_DEFAULT; + hook.hk_lockspeed = HOOK_SPEED_DEFAULT; + hook.hk_selflock = false; + hook.hk_nodisable = false; + hook.hk_timer = 0.0f; + hook.hk_timer_preset = HOOK_LOCK_TIMER_DEFAULT; + hook.hk_autolock = false; + hook.hk_min_length = 0.f; m_actor->ar_hooks.push_back(hook); } AdjustNodeBuoyancy(node, def, def.node_defaults); node.nd_no_ground_contact = BITMASK_IS_1(options, RigDef::Node::OPTION_c_NO_GROUND_CONTACT); - node.nd_no_mouse_grab = BITMASK_IS_1(options, RigDef::Node::OPTION_m_NO_MOUSE_GRAB); + node.nd_no_mouse_grab = BITMASK_IS_1(options, RigDef::Node::OPTION_m_NO_MOUSE_GRAB); - m_actor->ar_exhaust_dir_node = BITMASK_IS_1(options, RigDef::Node::OPTION_y_EXHAUST_DIRECTION) ? node.pos : 0; - m_actor->ar_exhaust_pos_node = BITMASK_IS_1(options, RigDef::Node::OPTION_x_EXHAUST_POINT) ? node.pos : 0; + m_actor->ar_exhaust_dir_node = BITMASK_IS_1(options, RigDef::Node::OPTION_y_EXHAUST_DIRECTION) ? node.pos : 0; + m_actor->ar_exhaust_pos_node = BITMASK_IS_1(options, RigDef::Node::OPTION_x_EXHAUST_POINT) ? node.pos : 0; // Update "fusedrag" autocalc y & z span if (def.position.z < m_fuse_z_min) { m_fuse_z_min = def.position.z; } @@ -5713,23 +5187,17 @@ void ActorSpawner::ProcessNode(RigDef::Node & def) m_gfx_nodes.push_back(nfx); } -void ActorSpawner::AddExhaust( - unsigned int emitter_node_idx, - unsigned int direction_node_idx - ) +void ActorSpawner::AddExhaust(unsigned int emitter_node_idx, unsigned int direction_node_idx) { - if (m_actor->m_disable_smoke) - { - return; - } + if (m_actor->m_disable_smoke) { return; } exhaust_t exhaust; - exhaust.emitterNode = emitter_node_idx; + exhaust.emitterNode = emitter_node_idx; exhaust.directionNode = direction_node_idx; - exhaust.smoker = gEnv->sceneManager->createParticleSystem( - this->ComposeName("Exhaust", static_cast(m_actor->exhausts.size())), - /*quota=*/500, // Default value - m_custom_resource_group); + exhaust.smoker = + gEnv->sceneManager->createParticleSystem(this->ComposeName("Exhaust", static_cast(m_actor->exhausts.size())), + /*quota=*/500, // Default value + m_custom_resource_group); if (exhaust.smoker == nullptr) { @@ -5746,18 +5214,15 @@ void ActorSpawner::AddExhaust( exhaust.smokeNode->setPosition(m_actor->ar_nodes[exhaust.emitterNode].AbsPosition); // Update GFX for nodes - for (GfxActor::NodeGfx& nfx : m_gfx_nodes) + for (GfxActor::NodeGfx &nfx : m_gfx_nodes) { - if (nfx.nx_node_idx == emitter_node_idx || nfx.nx_node_idx == direction_node_idx) - { - nfx.nx_is_hot = true; - } + if (nfx.nx_node_idx == emitter_node_idx || nfx.nx_node_idx == direction_node_idx) { nfx.nx_is_hot = true; } } m_actor->exhausts.push_back(exhaust); } -bool ActorSpawner::AddModule(Ogre::String const & module_name) +bool ActorSpawner::AddModule(Ogre::String const &module_name) { auto result = m_file->user_modules.find(module_name); @@ -5771,17 +5236,18 @@ bool ActorSpawner::AddModule(Ogre::String const & module_name) return false; } -void ActorSpawner::ProcessCinecam(RigDef::Cinecam & def) +void ActorSpawner::ProcessCinecam(RigDef::Cinecam &def) { // Node - Ogre::Vector3 node_pos = m_spawn_position + def.position; - node_t & camera_node = GetAndInitFreeNode(node_pos); - camera_node.nd_no_ground_contact = true; // Orig: hardcoded in BTS_CINECAM - camera_node.friction_coef = NODE_FRICTION_COEF_DEFAULT; // Node defaults are ignored here. + Ogre::Vector3 node_pos = m_spawn_position + def.position; + node_t & camera_node = GetAndInitFreeNode(node_pos); + camera_node.nd_no_ground_contact = true; // Orig: hardcoded in BTS_CINECAM + camera_node.friction_coef = NODE_FRICTION_COEF_DEFAULT; // Node defaults are ignored here. AdjustNodeBuoyancy(camera_node, def.node_defaults); - camera_node.volume_coef = def.node_defaults->volume; - camera_node.surface_coef = def.node_defaults->surface; - // NOTE: Not applying the 'node_mass' value here for backwards compatibility - this node must go through initial `Actor::RecalculateNodeMasses()` pass with default weight. + camera_node.volume_coef = def.node_defaults->volume; + camera_node.surface_coef = def.node_defaults->surface; + // NOTE: Not applying the 'node_mass' value here for backwards compatibility - this node must go through initial + // `Actor::RecalculateNodeMasses()` pass with default weight. m_actor->ar_minimass[camera_node.pos] = m_file->global_minimass->min_mass; @@ -5791,51 +5257,46 @@ void ActorSpawner::ProcessCinecam(RigDef::Cinecam & def) // Beams for (unsigned int i = 0; i < 8; i++) { - int beam_index = m_actor->ar_num_beams; - beam_t & beam = AddBeam(camera_node, GetNode(def.nodes[i]), def.beam_defaults, DEFAULT_DETACHER_GROUP); - beam.bm_type = BEAM_NORMAL; + int beam_index = m_actor->ar_num_beams; + beam_t &beam = AddBeam(camera_node, GetNode(def.nodes[i]), def.beam_defaults, DEFAULT_DETACHER_GROUP); + beam.bm_type = BEAM_NORMAL; CalculateBeamLength(beam); beam.k = def.spring; beam.d = def.damping; } }; -void ActorSpawner::InitNode(node_t & node, Ogre::Vector3 const & position) +void ActorSpawner::InitNode(node_t &node, Ogre::Vector3 const &position) { /* Position */ node.AbsPosition = position; node.RelPosition = position - m_actor->ar_origin; } -void ActorSpawner::InitNode( - node_t & node, - Ogre::Vector3 const & position, - std::shared_ptr node_defaults -) +void ActorSpawner::InitNode(node_t &node, Ogre::Vector3 const &position, std::shared_ptr node_defaults) { InitNode(node, position); node.friction_coef = node_defaults->friction; - node.volume_coef = node_defaults->volume; - node.surface_coef = node_defaults->surface; + node.volume_coef = node_defaults->volume; + node.surface_coef = node_defaults->surface; } -void ActorSpawner::ProcessGlobals(RigDef::Globals & def) +void ActorSpawner::ProcessGlobals(RigDef::Globals &def) { - m_actor->m_dry_mass = def.dry_mass; + m_actor->m_dry_mass = def.dry_mass; m_actor->m_load_mass = def.cargo_mass; // NOTE: Don't do any material pre-processing here; it'll be done on actual entities (via `SetupNewEntity()`). - if (! def.material_name.empty()) + if (!def.material_name.empty()) { - Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(def.material_name); // Check if exists (compatibility) - if (!mat.isNull()) - { - m_cab_material_name = def.material_name; - } + Ogre::MaterialPtr mat = + Ogre::MaterialManager::getSingleton().getByName(def.material_name); // Check if exists (compatibility) + if (!mat.isNull()) { m_cab_material_name = def.material_name; } else { std::stringstream msg; - msg << "Material '" << def.material_name << "' defined in section 'globals' not found. Trying material 'tracks/transred'"; + msg << "Material '" << def.material_name + << "' defined in section 'globals' not found. Trying material 'tracks/transred'"; this->AddMessage(Message::TYPE_ERROR, msg.str()); m_cab_material_name = "tracks/transred"; @@ -5861,10 +5322,10 @@ bool ActorSpawner::CheckParticleLimit(unsigned int count) bool ActorSpawner::CheckAxleLimit(unsigned int count) { - if ((m_actor->m_num_wheel_diffs + count) > MAX_WHEELS/2) + if ((m_actor->m_num_wheel_diffs + count) > MAX_WHEELS / 2) { std::stringstream msg; - msg << "Axle limit (" << MAX_WHEELS/2 << ") exceeded"; + msg << "Axle limit (" << MAX_WHEELS / 2 << ") exceeded"; AddMessage(Message::TYPE_ERROR, msg.str()); return false; } @@ -5956,80 +5417,77 @@ bool ActorSpawner::CheckScrewpropLimit(unsigned int count) return true; } -node_t &ActorSpawner:: GetNode(unsigned int node_index) +node_t &ActorSpawner::GetNode(unsigned int node_index) { return m_actor->ar_nodes[node_index]; } -void ActorSpawner::InitNode(unsigned int node_index, Ogre::Vector3 const & position) +void ActorSpawner::InitNode(unsigned int node_index, Ogre::Vector3 const &position) { InitNode(m_actor->ar_nodes[node_index], position); } -beam_t & ActorSpawner::GetBeam(unsigned int index) +beam_t &ActorSpawner::GetBeam(unsigned int index) { return m_actor->ar_beams[index]; } -node_t & ActorSpawner::GetFreeNode() +node_t &ActorSpawner::GetFreeNode() { - node_t & node = m_actor->ar_nodes[m_actor->ar_num_nodes]; - node.pos = m_actor->ar_num_nodes; + node_t &node = m_actor->ar_nodes[m_actor->ar_num_nodes]; + node.pos = m_actor->ar_num_nodes; m_actor->ar_num_nodes++; return node; } -beam_t & ActorSpawner::GetFreeBeam() +beam_t &ActorSpawner::GetFreeBeam() { - beam_t & beam = m_actor->ar_beams[m_actor->ar_num_beams]; + beam_t &beam = m_actor->ar_beams[m_actor->ar_num_beams]; m_actor->ar_num_beams++; return beam; } -shock_t & ActorSpawner::GetFreeShock() +shock_t &ActorSpawner::GetFreeShock() { - shock_t & shock = m_actor->ar_shocks[m_actor->ar_num_shocks]; + shock_t &shock = m_actor->ar_shocks[m_actor->ar_num_shocks]; m_actor->ar_num_shocks++; return shock; } -beam_t & ActorSpawner::GetAndInitFreeBeam(node_t & node_1, node_t & node_2) +beam_t &ActorSpawner::GetAndInitFreeBeam(node_t &node_1, node_t &node_2) { - beam_t & beam = GetFreeBeam(); - beam.p1 = & node_1; - beam.p2 = & node_2; + beam_t &beam = GetFreeBeam(); + beam.p1 = &node_1; + beam.p2 = &node_2; return beam; } -node_t & ActorSpawner::GetAndInitFreeNode(Ogre::Vector3 const & position) +node_t &ActorSpawner::GetAndInitFreeNode(Ogre::Vector3 const &position) { - node_t & node = GetFreeNode(); + node_t &node = GetFreeNode(); InitNode(node, position); return node; } -void ActorSpawner::SetBeamSpring(beam_t & beam, float spring) +void ActorSpawner::SetBeamSpring(beam_t &beam, float spring) { beam.k = spring; } -void ActorSpawner::SetBeamDamping(beam_t & beam, float damping) +void ActorSpawner::SetBeamDamping(beam_t &beam, float damping) { beam.d = damping; } void ActorSpawner::SetupDefaultSoundSources(Actor *vehicle) { - int trucknum = vehicle->ar_instance_id; + int trucknum = vehicle->ar_instance_id; int ar_exhaust_pos_node = vehicle->ar_exhaust_pos_node; #ifdef USE_OPENAL - if (SoundScriptManager::getSingleton().isDisabled()) - { - return; - } + if (SoundScriptManager::getSingleton().isDisabled()) { return; } - //engine + // engine if (vehicle->ar_engine != nullptr) /* Land vehicle */ { if (vehicle->ar_engine->m_engine_type == 't') @@ -6040,8 +5498,7 @@ void ActorSpawner::SetupDefaultSoundSources(Actor *vehicle) AddSoundSourceInstance(vehicle, "tracks/default_parkbrakes", 0); AddSoundSourceInstance(vehicle, "tracks/default_reverse_beep", 0); } - if (vehicle->ar_engine->m_engine_type == 'c') - AddSoundSourceInstance(vehicle, "tracks/default_car", ar_exhaust_pos_node); + if (vehicle->ar_engine->m_engine_type == 'c') AddSoundSourceInstance(vehicle, "tracks/default_car", ar_exhaust_pos_node); if (vehicle->ar_engine->HasTurbo()) { if (vehicle->ar_engine->m_turbo_inertia_factor >= 3) @@ -6055,59 +5512,47 @@ void ActorSpawner::SetupDefaultSoundSources(Actor *vehicle) AddSoundSourceInstance(vehicle, "tracks/default_wastegate_flutter", ar_exhaust_pos_node); } - if (vehicle->ar_engine->m_engine_has_air) - AddSoundSourceInstance(vehicle, "tracks/default_air_purge", 0); - //starter + if (vehicle->ar_engine->m_engine_has_air) AddSoundSourceInstance(vehicle, "tracks/default_air_purge", 0); + // starter AddSoundSourceInstance(vehicle, "tracks/default_starter", 0); // turn signals AddSoundSourceInstance(vehicle, "tracks/default_turn_signal", 0); } - if (vehicle->ar_driveable==TRUCK) + if (vehicle->ar_driveable == TRUCK) { - //horn + // horn if (vehicle->ar_is_police) AddSoundSourceInstance(vehicle, "tracks/default_police", 0); else AddSoundSourceInstance(vehicle, "tracks/default_horn", 0); - //shift - AddSoundSourceInstance(vehicle, "tracks/default_shift", 0); - } - //pump - if (vehicle->m_has_command_beams) - { - AddSoundSourceInstance(vehicle, "tracks/default_pump", 0); - } - //antilock brake - if (vehicle->alb_mode || !vehicle->alb_notoggle) - { - AddSoundSourceInstance(vehicle, "tracks/default_antilock", 0); - } - //tractioncontrol - if (vehicle->tc_mode || !vehicle->tc_notoggle) - { - AddSoundSourceInstance(vehicle, "tracks/default_tractioncontrol", 0); - } - //screetch - if ((vehicle->ar_driveable==TRUCK || vehicle->ar_driveable==AIRPLANE) && vehicle->ar_num_wheels != 0) - { - AddSoundSourceInstance(vehicle, "tracks/default_screetch", 0); - } - //break & creak + // shift + AddSoundSourceInstance(vehicle, "tracks/default_shift", 0); + } + // pump + if (vehicle->m_has_command_beams) { AddSoundSourceInstance(vehicle, "tracks/default_pump", 0); } + // antilock brake + if (vehicle->alb_mode || !vehicle->alb_notoggle) { AddSoundSourceInstance(vehicle, "tracks/default_antilock", 0); } + // tractioncontrol + if (vehicle->tc_mode || !vehicle->tc_notoggle) { AddSoundSourceInstance(vehicle, "tracks/default_tractioncontrol", 0); } + // screetch + if ((vehicle->ar_driveable == TRUCK || vehicle->ar_driveable == AIRPLANE) && vehicle->ar_num_wheels != 0) + { AddSoundSourceInstance(vehicle, "tracks/default_screetch", 0); } + // break & creak AddSoundSourceInstance(vehicle, "tracks/default_break", 0); AddSoundSourceInstance(vehicle, "tracks/default_creak", 0); - //boat engine - if (vehicle->ar_driveable==BOAT) + // boat engine + if (vehicle->ar_driveable == BOAT) { - if (vehicle->m_total_mass>50000.0) + if (vehicle->m_total_mass > 50000.0) AddSoundSourceInstance(vehicle, "tracks/default_marine_large", ar_exhaust_pos_node); else AddSoundSourceInstance(vehicle, "tracks/default_marine_small", ar_exhaust_pos_node); - //no start/stop engine for boats, so set sound always on! + // no start/stop engine for boats, so set sound always on! SOUND_START(trucknum, SS_TRIG_ENGINE); SOUND_MODULATE(trucknum, SS_MOD_ENGINE, 0.5); } - //airplane warnings - if (vehicle->ar_driveable==AIRPLANE) + // airplane warnings + if (vehicle->ar_driveable == AIRPLANE) { AddSoundSourceInstance(vehicle, "tracks/default_gpws_10", 0); AddSoundSourceInstance(vehicle, "tracks/default_gpws_20", 0); @@ -6135,25 +5580,23 @@ void ActorSpawner::SetupDefaultSoundSources(Actor *vehicle) AddSoundSourceInstance(vehicle, "tracks/default_aivionic_chat12", 0); AddSoundSourceInstance(vehicle, "tracks/default_aivionic_chat13", 0); } - //airplane engines - for (int i=0; iar_num_aeroengines && i<8; i++) + // airplane engines + for (int i = 0; i < vehicle->ar_num_aeroengines && i < 8; i++) { - int turbojet_node = vehicle->ar_aeroengines[i]->getNoderef(); - Ogre::String index_str = TOSTRING(i+1); + int turbojet_node = vehicle->ar_aeroengines[i]->getNoderef(); + Ogre::String index_str = TOSTRING(i + 1); - if (vehicle->ar_aeroengines[i]->getType()==AeroEngine::AEROENGINE_TYPE_TURBOJET) + if (vehicle->ar_aeroengines[i]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOJET) { AddSoundSourceInstance(vehicle, "tracks/default_turbojet_start" + index_str, turbojet_node); AddSoundSourceInstance(vehicle, "tracks/default_turbojet_lopower" + index_str, turbojet_node); AddSoundSourceInstance(vehicle, "tracks/default_turbojet_hipower" + index_str, turbojet_node); - if (((Turbojet*)(vehicle->ar_aeroengines[i]))->tjet_afterburnable) - { - AddSoundSourceInstance(vehicle, "tracks/default_turbojet_afterburner" + index_str, turbojet_node); - } + if (((Turbojet *)(vehicle->ar_aeroengines[i]))->tjet_afterburnable) + { AddSoundSourceInstance(vehicle, "tracks/default_turbojet_afterburner" + index_str, turbojet_node); } } - else if (vehicle->ar_aeroengines[i]->getType()==AeroEngine::AEROENGINE_TYPE_TURBOPROP) + else if (vehicle->ar_aeroengines[i]->getType() == AeroEngine::AEROENGINE_TYPE_TURBOPROP) { - if (((Turboprop*)vehicle->ar_aeroengines[i])->is_piston) + if (((Turboprop *)vehicle->ar_aeroengines[i])->is_piston) { AddSoundSourceInstance(vehicle, "tracks/default_pistonprop_start" + index_str, turbojet_node); AddSoundSourceInstance(vehicle, "tracks/default_pistonprop_lopower" + index_str, turbojet_node); @@ -6169,23 +5612,29 @@ void ActorSpawner::SetupDefaultSoundSources(Actor *vehicle) } // linked sounds - for (int i=0; im_num_command_beams; i++) + for (int i = 0; i < vehicle->m_num_command_beams; i++) { - AddSoundSource(vehicle, SoundScriptManager::getSingleton().createInstance(Ogre::String("tracks/linked/default_command/extend"), trucknum, NULL, SL_COMMAND, i), 0); - AddSoundSource(vehicle, SoundScriptManager::getSingleton().createInstance(Ogre::String("tracks/linked/default_command/retract"), trucknum, NULL, SL_COMMAND, -i), 0); + AddSoundSource(vehicle, + SoundScriptManager::getSingleton().createInstance(Ogre::String("tracks/linked/default_command/extend"), + trucknum, NULL, SL_COMMAND, i), + 0); + AddSoundSource(vehicle, + SoundScriptManager::getSingleton().createInstance(Ogre::String("tracks/linked/default_command/retract"), + trucknum, NULL, SL_COMMAND, -i), + 0); } -#endif //OPENAL +#endif // OPENAL } void ActorSpawner::UpdateCollcabContacterNodes() { - for (int i=0; iar_num_collcabs; i++) + for (int i = 0; i < m_actor->ar_num_collcabs; i++) { - int tmpv = m_actor->ar_collcabs[i] * 3; - m_actor->ar_nodes[m_actor->ar_cabs[tmpv]].nd_cab_node = true; - m_actor->ar_nodes[m_actor->ar_cabs[tmpv+1]].nd_cab_node = true; - m_actor->ar_nodes[m_actor->ar_cabs[tmpv+2]].nd_cab_node = true; + int tmpv = m_actor->ar_collcabs[i] * 3; + m_actor->ar_nodes[m_actor->ar_cabs[tmpv]].nd_cab_node = true; + m_actor->ar_nodes[m_actor->ar_cabs[tmpv + 1]].nd_cab_node = true; + m_actor->ar_nodes[m_actor->ar_cabs[tmpv + 2]].nd_cab_node = true; } for (int i = 0; i < m_actor->ar_num_nodes; i++) { @@ -6213,21 +5662,13 @@ std::string ActorSpawner::ProcessMessagesToString() { switch (itor->type) { - case (Message::TYPE_INTERNAL_ERROR): - report << "#FF3300 INTERNAL ERROR #FFFFFF"; - break; + case (Message::TYPE_INTERNAL_ERROR): report << "#FF3300 INTERNAL ERROR #FFFFFF"; break; - case (Message::TYPE_ERROR): - report << "#FF3300 ERROR #FFFFFF"; - break; + case (Message::TYPE_ERROR): report << "#FF3300 ERROR #FFFFFF"; break; - case (Message::TYPE_WARNING): - report << "#FFFF00 WARNING #FFFFFF"; - break; + case (Message::TYPE_WARNING): report << "#FFFF00 WARNING #FFFFFF"; break; - default: - report << "INFO"; - break; + default: report << "INFO"; break; } report << "(Keyword " << RigDef::File::KeywordToString(itor->keyword) << ")" << std::endl; report << "\t" << itor->text << std::endl; @@ -6235,31 +5676,25 @@ std::string ActorSpawner::ProcessMessagesToString() return report.str(); } -RigDef::MaterialFlareBinding* ActorSpawner::FindFlareBindingForMaterial(std::string const & material_name) +RigDef::MaterialFlareBinding *ActorSpawner::FindFlareBindingForMaterial(std::string const &material_name) { - for (auto& module: m_selected_modules) + for (auto &module : m_selected_modules) { - for (auto& def: module->material_flare_bindings) + for (auto &def : module->material_flare_bindings) { - if (def.material_name == material_name) - { - return &def; - } + if (def.material_name == material_name) { return &def; } } } return nullptr; } -RigDef::VideoCamera* ActorSpawner::FindVideoCameraByMaterial(std::string const & material_name) +RigDef::VideoCamera *ActorSpawner::FindVideoCameraByMaterial(std::string const &material_name) { - for (auto& module: m_selected_modules) + for (auto &module : m_selected_modules) { - for (auto& def: module->videocameras) + for (auto &def : module->videocameras) { - if (def.material_name == material_name) - { - return &def; - } + if (def.material_name == material_name) { return &def; } } } @@ -6272,38 +5707,33 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l { // Check for existing substitute auto lookup_res = m_material_substitutions.find(mat_lookup_name); - if (lookup_res != m_material_substitutions.end()) - { - return lookup_res->second.material; - } + if (lookup_res != m_material_substitutions.end()) { return lookup_res->second.material; } CustomMaterial lookup_entry; // Query old-style mirrors (=special props, hardcoded material name 'mirror') if (mat_lookup_name == "mirror") { - lookup_entry.mirror_prop_type = m_curr_mirror_prop_type; + lookup_entry.mirror_prop_type = m_curr_mirror_prop_type; lookup_entry.mirror_prop_scenenode = m_curr_mirror_prop_scenenode; - lookup_entry.material_flare_def = nullptr; - static int mirror_counter = 0; - const std::string new_mat_name = this->ComposeName("RenderMaterial", mirror_counter); + lookup_entry.material_flare_def = nullptr; + static int mirror_counter = 0; + const std::string new_mat_name = this->ComposeName("RenderMaterial", mirror_counter); ++mirror_counter; - lookup_entry.material = Ogre::MaterialManager::getSingleton().getByName("mirror")->clone(new_mat_name, true, m_custom_resource_group); + lookup_entry.material = + Ogre::MaterialManager::getSingleton().getByName("mirror")->clone(new_mat_name, true, m_custom_resource_group); // Special case - register under generated name. This is because all mirrors use the same material 'mirror' m_material_substitutions.insert(std::make_pair(new_mat_name, lookup_entry)); return lookup_entry.material; // Done! } // Query 'videocameras' - RigDef::VideoCamera* videocam_def = this->FindVideoCameraByMaterial(mat_lookup_name); + RigDef::VideoCamera *videocam_def = this->FindVideoCameraByMaterial(mat_lookup_name); if (videocam_def != nullptr) { Ogre::MaterialPtr video_mat_shared; - auto found_managedmat = m_managed_materials.find(mat_lookup_name); - if (found_managedmat != m_managed_materials.end()) - { - video_mat_shared = found_managedmat->second; - } + auto found_managedmat = m_managed_materials.find(mat_lookup_name); + if (found_managedmat != m_managed_materials.end()) { video_mat_shared = found_managedmat->second; } else { video_mat_shared = Ogre::MaterialManager::getSingleton().getByName(mat_lookup_name); @@ -6311,9 +5741,9 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l if (!video_mat_shared.isNull()) { - lookup_entry.video_camera_def = videocam_def; + lookup_entry.video_camera_def = videocam_def; const std::string video_mat_name = this->ComposeName(videocam_def->material_name.c_str(), 0); - lookup_entry.material = video_mat_shared->clone(video_mat_name, true, m_custom_resource_group); + lookup_entry.material = video_mat_shared->clone(video_mat_name, true, m_custom_resource_group); m_material_substitutions.insert(std::make_pair(mat_lookup_name, lookup_entry)); return lookup_entry.material; // Done! } @@ -6326,22 +5756,19 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l } // Resolve 'materialflarebindings'. - RigDef::MaterialFlareBinding* mat_flare_def = this->FindFlareBindingForMaterial(mat_lookup_name); - if (mat_flare_def != nullptr) - { - lookup_entry.material_flare_def = mat_flare_def; - } + RigDef::MaterialFlareBinding *mat_flare_def = this->FindFlareBindingForMaterial(mat_lookup_name); + if (mat_flare_def != nullptr) { lookup_entry.material_flare_def = mat_flare_def; } // Query .skin material replacements if (m_actor->m_used_skin_entry != nullptr) { - std::shared_ptr& skin_def = m_actor->m_used_skin_entry->skin_def; + std::shared_ptr &skin_def = m_actor->m_used_skin_entry->skin_def; auto skin_res = skin_def->replace_materials.find(mat_lookup_name); if (skin_res != skin_def->replace_materials.end()) { - Ogre::MaterialPtr skin_mat = Ogre::MaterialManager::getSingleton().getByName( - skin_res->second, m_actor->m_used_skin_entry->resource_group); + Ogre::MaterialPtr skin_mat = + Ogre::MaterialManager::getSingleton().getByName(skin_res->second, m_actor->m_used_skin_entry->resource_group); if (!skin_mat.isNull()) { std::stringstream name_buf; @@ -6354,9 +5781,8 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l { std::stringstream buf; buf << "Material '" << skin_res->second << "' from skin '" << m_actor->m_used_skin_entry->dname - << "' not found (filename: '" << m_actor->m_used_skin_entry->fname - << "', resource group: '"<< m_actor->m_used_skin_entry->resource_group - <<"')! Ignoring it..."; + << "' not found (filename: '" << m_actor->m_used_skin_entry->fname << "', resource group: '" + << m_actor->m_used_skin_entry->resource_group << "')! Ignoring it..."; this->AddMessage(Message::TYPE_ERROR, buf.str()); } } @@ -6372,7 +5798,8 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l else { // Generate new substitute - Ogre::MaterialPtr orig_mat = Ogre::MaterialManager::getSingleton().getByName(mat_lookup_name, m_custom_resource_group); + Ogre::MaterialPtr orig_mat = + Ogre::MaterialManager::getSingleton().getByName(mat_lookup_name, m_custom_resource_group); if (orig_mat.isNull()) { std::stringstream buf; @@ -6387,11 +5814,11 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l } // Finally, query texture replacements - .skin and builtins - for (auto& technique: lookup_entry.material->getTechniques()) + for (auto &technique : lookup_entry.material->getTechniques()) { - for (auto& pass: technique->getPasses()) + for (auto &pass : technique->getPasses()) { - for (auto& tex_unit: pass->getTextureUnitStates()) + for (auto &tex_unit : pass->getTextureUnitStates()) { // Built-ins if (tex_unit->getTextureName() == "dashtexture") @@ -6416,11 +5843,13 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l for (size_t i = 0; i < num_frames; ++i) { const auto end = m_actor->m_used_skin_entry->skin_def->replace_textures.end(); - const auto query = m_actor->m_used_skin_entry->skin_def->replace_textures.find(tex_unit->getFrameTextureName(i)); + const auto query = + m_actor->m_used_skin_entry->skin_def->replace_textures.find(tex_unit->getFrameTextureName(i)); if (query != end) { // Skin has replacement for this texture - if (m_actor->m_used_skin_entry->resource_group != m_custom_resource_group) // The skin comes from a SkinZip bundle (different resource group) + if (m_actor->m_used_skin_entry->resource_group != + m_custom_resource_group) // The skin comes from a SkinZip bundle (different resource group) { Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName( query->second, m_actor->m_used_skin_entry->resource_group); @@ -6443,13 +5872,13 @@ Ogre::MaterialPtr ActorSpawner::FindOrCreateCustomizedMaterial(std::string mat_l } } } // texture unit states - } // passes - } // techniques + } // passes + } // techniques m_material_substitutions.insert(std::make_pair(mat_lookup_name, lookup_entry)); // Register the substitute return lookup_entry.material; } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { std::stringstream msg; msg << "Exception while customizing material \"" << mat_lookup_name << "\", message: " << e.getFullDescription(); @@ -6463,7 +5892,7 @@ Ogre::MaterialPtr ActorSpawner::CreateSimpleMaterial(Ogre::ColourValue color) assert(!m_simple_material_base.isNull()); static unsigned int simple_mat_counter = 0; - char name_buf[300]; + char name_buf[300]; snprintf(name_buf, 300, "SimpleMaterial-%u%s%d", simple_mat_counter, ACTOR_ID_TOKEN, m_actor->ar_instance_id); Ogre::MaterialPtr newmat = m_simple_material_base->clone(name_buf); ++simple_mat_counter; @@ -6472,7 +5901,7 @@ Ogre::MaterialPtr ActorSpawner::CreateSimpleMaterial(Ogre::ColourValue color) return newmat; } -void ActorSpawner::SetupNewEntity(Ogre::Entity* ent, Ogre::ColourValue simple_color) +void ActorSpawner::SetupNewEntity(Ogre::Entity *ent, Ogre::ColourValue simple_color) { if (ent == nullptr) { @@ -6489,7 +5918,7 @@ void ActorSpawner::SetupNewEntity(Ogre::Entity* ent, Ogre::ColourValue simple_co size_t num_sub_entities = ent->getNumSubEntities(); for (size_t i = 0; i < num_sub_entities; i++) { - Ogre::SubEntity* subent = ent->getSubEntity(i); + Ogre::SubEntity *subent = ent->getSubEntity(i); subent->setMaterial(mat); } @@ -6500,15 +5929,12 @@ void ActorSpawner::SetupNewEntity(Ogre::Entity* ent, Ogre::ColourValue simple_co size_t subent_max = ent->getNumSubEntities(); for (size_t i = 0; i < subent_max; ++i) { - Ogre::SubEntity* subent = ent->getSubEntity(i); + Ogre::SubEntity *subent = ent->getSubEntity(i); if (!subent->getMaterial().isNull()) { Ogre::MaterialPtr own_mat = this->FindOrCreateCustomizedMaterial(subent->getMaterialName()); - if (!own_mat.isNull()) - { - subent->setMaterial(own_mat); - } + if (!own_mat.isNull()) { subent->setMaterial(own_mat); } } } } @@ -6516,8 +5942,8 @@ void ActorSpawner::SetupNewEntity(Ogre::Entity* ent, Ogre::ColourValue simple_co void ActorSpawner::CreateGfxActor() { // Create the actor - m_actor->m_gfx_actor = std::unique_ptr( - new RoR::GfxActor(m_actor, this, m_custom_resource_group, m_gfx_nodes, m_props, m_driverseat_prop_index, m_oldstyle_renderdash)); + m_actor->m_gfx_actor = std::unique_ptr(new RoR::GfxActor( + m_actor, this, m_custom_resource_group, m_gfx_nodes, m_props, m_driverseat_prop_index, m_oldstyle_renderdash)); m_actor->GetGfxActor()->UpdateSimDataBuffer(); // Initial fill (to setup flexing meshes) } @@ -6528,17 +5954,14 @@ void ActorSpawner::FinalizeGfxSetup() // TODO &*&* // Process special materials - for (auto& entry: m_material_substitutions) + for (auto &entry : m_material_substitutions) { if (entry.second.material_flare_def != nullptr) // 'materialflarebindings' - { - m_actor->m_gfx_actor->AddMaterialFlare( - entry.second.material_flare_def->flare_number, entry.second.material); - } + { m_actor->m_gfx_actor->AddMaterialFlare(entry.second.material_flare_def->flare_number, entry.second.material); } else if (entry.second.mirror_prop_type != CustomMaterial::MirrorPropType::MPROP_NONE) // special 'prop' - rear view mirror { - this->CreateMirrorPropVideoCam( - entry.second.material, entry.second.mirror_prop_type, entry.second.mirror_prop_scenenode); + this->CreateMirrorPropVideoCam(entry.second.material, entry.second.mirror_prop_type, + entry.second.mirror_prop_scenenode); } else if (entry.second.video_camera_def != nullptr) // 'videocameras' { @@ -6549,21 +5972,19 @@ void ActorSpawner::FinalizeGfxSetup() } if (!App::gfx_enable_videocams.GetActive()) - { - m_actor->m_gfx_actor->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_DISABLED); - } + { m_actor->m_gfx_actor->SetVideoCamState(GfxActor::VideoCamState::VCSTATE_DISABLED); } // Load dashboard layouts - for (auto& module: m_selected_modules) + for (auto &module : m_selected_modules) { if (module->gui_settings != nullptr) { - for (std::string& layout: module->gui_settings->dashboard_layouts) + for (std::string &layout : module->gui_settings->dashboard_layouts) { m_actor->ar_dashboard->loadDashBoard(layout, false); } - for (std::string& layout: module->gui_settings->rtt_dashboard_layouts) + for (std::string &layout : module->gui_settings->rtt_dashboard_layouts) { m_actor->ar_dashboard->loadDashBoard(layout, true); } @@ -6581,7 +6002,8 @@ void ActorSpawner::FinalizeGfxSetup() { if (m_actor->ar_engine->getMaxRPM() > 3500) { - m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_mph.layout", false); //7000 rpm tachometer thanks to Klink + m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_mph.layout", + false); // 7000 rpm tachometer thanks to Klink m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_mph.layout", true); } else @@ -6594,7 +6016,8 @@ void ActorSpawner::FinalizeGfxSetup() { if (m_actor->ar_engine->getMaxRPM() > 3500) { - m_actor->ar_dashboard->loadDashBoard("default_dashboard7000.layout", false); //7000 rpm tachometer thanks to Klink + m_actor->ar_dashboard->loadDashBoard("default_dashboard7000.layout", + false); // 7000 rpm tachometer thanks to Klink m_actor->ar_dashboard->loadDashBoard("default_dashboard7000.layout", true); } else @@ -6610,7 +6033,8 @@ void ActorSpawner::FinalizeGfxSetup() { if (m_actor->ar_engine->getMaxRPM() > 3500) { - m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_analog_mph.layout", false); //7000 rpm tachometer thanks to Klink + m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_analog_mph.layout", + false); // 7000 rpm tachometer thanks to Klink m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_analog_mph.layout", true); } else @@ -6623,7 +6047,8 @@ void ActorSpawner::FinalizeGfxSetup() { if (m_actor->ar_engine->getMaxRPM() > 3500) { - m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_analog.layout", false); //7000 rpm tachometer thanks to Klink + m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_analog.layout", + false); // 7000 rpm tachometer thanks to Klink m_actor->ar_dashboard->loadDashBoard("default_dashboard7000_analog.layout", true); } else @@ -6644,106 +6069,80 @@ void ActorSpawner::FinalizeGfxSetup() m_actor->ar_dashboard->setVisible(false); // Process rods (beam visuals) - for (BeamVisualsTicket& bv: m_beam_visuals_queue) + for (BeamVisualsTicket &bv : m_beam_visuals_queue) { int node1 = m_actor->ar_beams[bv.beam_index].p1->pos; int node2 = m_actor->ar_beams[bv.beam_index].p2->pos; m_actor->m_gfx_actor->AddRod(bv.beam_index, node1, node2, bv.material_name.c_str(), bv.visible, bv.diameter); } - //add the cab visual - // TODO: The 'cab mesh' functionality is a legacy quagmire, + // add the cab visual + // TODO: The 'cab mesh' functionality is a legacy quagmire, // data are scattered across `Actor`, `GfxActor` and `FlexObj` - research and unify!! ~ only_a_ptr, 04/2018 - if (!m_oldstyle_cab_texcoords.empty() && m_actor->ar_num_cabs>0) + if (!m_oldstyle_cab_texcoords.empty() && m_actor->ar_num_cabs > 0) { - //the cab materials are as follow: - //texname: base texture with emissive(2 pass) or without emissive if none available(1 pass), alpha cutting - //texname-trans: transparency texture (1 pass) - //texname-back: backface texture: black+alpha cutting (1 pass) - //texname-noem: base texture without emissive (1 pass), alpha cutting + // the cab materials are as follow: + // texname: base texture with emissive(2 pass) or without emissive if none available(1 pass), alpha cutting + // texname-trans: transparency texture (1 pass) + // texname-back: backface texture: black+alpha cutting (1 pass) + // texname-noem: base texture without emissive (1 pass), alpha cutting - //material passes must be: - //0: normal texture - //1: transparent (windows) - //2: emissive + // material passes must be: + // 0: normal texture + // 1: transparent (windows) + // 2: emissive Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(m_cab_material_name); if (mat.isNull()) { - Ogre::String msg = "Material '"+m_cab_material_name+"' missing!"; + Ogre::String msg = "Material '" + m_cab_material_name + "' missing!"; AddMessage(Message::TYPE_ERROR, msg); return; } //-trans - char transmatname[256]; + char transmatname[256]; static int trans_counter = 0; sprintf(transmatname, "%s-trans-%d", m_cab_material_name.c_str(), trans_counter++); - Ogre::MaterialPtr transmat=mat->clone(transmatname); - if (mat->getTechnique(0)->getNumPasses()>1) // If there's the "emissive pass", remove it from the 'transmat' - { - transmat->getTechnique(0)->removePass(1); - } + Ogre::MaterialPtr transmat = mat->clone(transmatname); + if (mat->getTechnique(0)->getNumPasses() > 1) // If there's the "emissive pass", remove it from the 'transmat' + { transmat->getTechnique(0)->removePass(1); } transmat->getTechnique(0)->getPass(0)->setAlphaRejectSettings(Ogre::CMPF_LESS_EQUAL, 128); transmat->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - if (transmat->getTechnique(0)->getPass(0)->getNumTextureUnitStates()>0) - { - transmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::TFO_NONE); - } + if (transmat->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0) + { transmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::TFO_NONE); } transmat->compile(); m_cab_trans_material = transmat; //-back - char backmatname[256]; + char backmatname[256]; static int back_counter = 0; sprintf(backmatname, "%s-back-%d", m_cab_material_name.c_str(), back_counter++); - Ogre::MaterialPtr backmat=mat->clone(backmatname); - if (mat->getTechnique(0)->getNumPasses()>1)// If there's the "emissive pass", remove it from the 'transmat' - { - backmat->getTechnique(0)->removePass(1); - } - if (transmat->getTechnique(0)->getPass(0)->getNumTextureUnitStates()>0) + Ogre::MaterialPtr backmat = mat->clone(backmatname); + if (mat->getTechnique(0)->getNumPasses() > 1) // If there's the "emissive pass", remove it from the 'transmat' + { backmat->getTechnique(0)->removePass(1); } + if (transmat->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0) { backmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx( - Ogre::LBX_SOURCE1, - Ogre::LBS_MANUAL, - Ogre::LBS_MANUAL, - Ogre::ColourValue(0,0,0), - Ogre::ColourValue(0,0,0) - ); - } - if (App::gfx_reduce_shadows.GetActive()) - { - backmat->setReceiveShadows(false); + Ogre::LBX_SOURCE1, Ogre::LBS_MANUAL, Ogre::LBS_MANUAL, Ogre::ColourValue(0, 0, 0), Ogre::ColourValue(0, 0, 0)); } + if (App::gfx_reduce_shadows.GetActive()) { backmat->setReceiveShadows(false); } backmat->compile(); char cab_material_name_cstr[1000] = {}; strncpy(cab_material_name_cstr, m_cab_material_name.c_str(), 999); std::string mesh_name = this->ComposeName("VehicleCabMesh", 0); - FlexObj* cab_mesh =new FlexObj( - m_actor->m_gfx_actor.get(), - m_actor->ar_nodes, - m_oldstyle_cab_texcoords, - m_actor->ar_num_cabs, - m_actor->ar_cabs, - m_oldstyle_cab_submeshes, - cab_material_name_cstr, - mesh_name.c_str(), - backmatname, - transmatname - ); + FlexObj * cab_mesh = new FlexObj(m_actor->m_gfx_actor.get(), m_actor->ar_nodes, m_oldstyle_cab_texcoords, + m_actor->ar_num_cabs, m_actor->ar_cabs, m_oldstyle_cab_submeshes, cab_material_name_cstr, + mesh_name.c_str(), backmatname, transmatname); - Ogre::SceneNode* cab_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - Ogre::Entity *ec = nullptr; + Ogre::SceneNode *cab_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + Ogre::Entity * ec = nullptr; try { ec = gEnv->sceneManager->createEntity(this->ComposeName("VehicleCabEntity", 0), mesh_name); this->SetupNewEntity(ec, Ogre::ColourValue(0.5, 1, 0.5)); - if (ec) - { - cab_scene_node->attachObject(ec); - } + if (ec) { cab_scene_node->attachObject(ec); } // Process "emissive cab" materials auto search_itor = m_material_substitutions.find(m_cab_material_name); @@ -6754,101 +6153,68 @@ void ActorSpawner::FinalizeGfxSetup() } catch (...) { - this->AddMessage(Message::TYPE_ERROR, "error loading mesh: "+mesh_name); + this->AddMessage(Message::TYPE_ERROR, "error loading mesh: " + mesh_name); // TODO: do not leak memory here! ~ 08/2018 } }; // Process wheel visuals - for (WheelVisualsTicket& ticket: m_wheel_visuals_queue) + for (WheelVisualsTicket &ticket : m_wheel_visuals_queue) { if (ticket.wheel_def != nullptr) { - this->CreateWheelVisuals( - ticket.wheel_index, - ticket.base_node_index, - ticket.wheel_def->num_rays, - ticket.wheel_def->face_material_name, - ticket.wheel_def->band_material_name, - false - ); + this->CreateWheelVisuals(ticket.wheel_index, ticket.base_node_index, ticket.wheel_def->num_rays, + ticket.wheel_def->face_material_name, ticket.wheel_def->band_material_name, false); } else if (ticket.wheel2_def != nullptr) { - this->CreateWheelVisuals( - ticket.wheel_index, - ticket.base_node_index, - ticket.wheel2_def->num_rays, - ticket.wheel2_def->face_material_name, - ticket.wheel2_def->band_material_name, - true, - ticket.wheel2_def->rim_radius / ticket.wheel2_def->tyre_radius - ); + this->CreateWheelVisuals(ticket.wheel_index, ticket.base_node_index, ticket.wheel2_def->num_rays, + ticket.wheel2_def->face_material_name, ticket.wheel2_def->band_material_name, true, + ticket.wheel2_def->rim_radius / ticket.wheel2_def->tyre_radius); } else if (ticket.meshwheel_def != nullptr) { - this->BuildMeshWheelVisuals( - ticket.wheel_index, - ticket.base_node_index, - ticket.axis_node_1, - ticket.axis_node_2, - ticket.meshwheel_def->num_rays, - ticket.meshwheel_def->mesh_name, - ticket.meshwheel_def->material_name, - ticket.meshwheel_def->rim_radius, - ticket.meshwheel_def->side != RigDef::MeshWheel::SIDE_RIGHT - ); + this->BuildMeshWheelVisuals(ticket.wheel_index, ticket.base_node_index, ticket.axis_node_1, ticket.axis_node_2, + ticket.meshwheel_def->num_rays, ticket.meshwheel_def->mesh_name, + ticket.meshwheel_def->material_name, ticket.meshwheel_def->rim_radius, + ticket.meshwheel_def->side != RigDef::MeshWheel::SIDE_RIGHT); } else if (ticket.flexbodywheel_def != nullptr) { - RigDef::FlexBodyWheel& def = *ticket.flexbodywheel_def; - this->BuildMeshWheelVisuals( - ticket.wheel_index, - ticket.base_node_index, - ticket.axis_node_1, - ticket.axis_node_2, - def.num_rays, - def.rim_mesh_name, - "tracks/trans", // Rim material name. Original parser: was hardcoded in BTS_FLEXBODYWHEELS - def.rim_radius, - def.side != RigDef::MeshWheel::SIDE_RIGHT - ); - - int num_nodes = def.num_rays * 4; + RigDef::FlexBodyWheel &def = *ticket.flexbodywheel_def; + this->BuildMeshWheelVisuals(ticket.wheel_index, ticket.base_node_index, ticket.axis_node_1, ticket.axis_node_2, + def.num_rays, def.rim_mesh_name, + "tracks/trans", // Rim material name. Original parser: was hardcoded in BTS_FLEXBODYWHEELS + def.rim_radius, def.side != RigDef::MeshWheel::SIDE_RIGHT); + + int num_nodes = def.num_rays * 4; std::vector node_indices; node_indices.reserve(num_nodes); for (int i = 0; i < num_nodes; ++i) { - node_indices.push_back( ticket.base_node_index + i ); + node_indices.push_back(ticket.base_node_index + i); } RigDef::Flexbody flexbody_def; flexbody_def.mesh_name = def.tyre_mesh_name; - flexbody_def.offset = Ogre::Vector3(0.5,0,0); + flexbody_def.offset = Ogre::Vector3(0.5, 0, 0); try { - auto* flexbody = m_flex_factory.CreateFlexBody( - &flexbody_def, - ticket.axis_node_1, - ticket.axis_node_2, - static_cast(ticket.base_node_index), - Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_Y), - node_indices, - m_custom_resource_group - ); - - if (flexbody == nullptr) - return; // Error already logged + auto *flexbody = m_flex_factory.CreateFlexBody( + &flexbody_def, ticket.axis_node_1, ticket.axis_node_2, static_cast(ticket.base_node_index), + Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_Y), node_indices, m_custom_resource_group); + + if (flexbody == nullptr) return; // Error already logged this->CreateWheelSkidmarks(static_cast(ticket.wheel_index)); m_actor->GetGfxActor()->AddFlexbody(flexbody); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - this->AddMessage(Message::TYPE_ERROR, - "Failed to create flexbodywheel visuals '" + def.tyre_mesh_name + "', reason:" + e.getFullDescription()); + this->AddMessage(Message::TYPE_ERROR, "Failed to create flexbodywheel visuals '" + def.tyre_mesh_name + + "', reason:" + e.getFullDescription()); } } } @@ -6858,61 +6224,59 @@ void ActorSpawner::FinalizeGfxSetup() void ActorSpawner::ValidateRotator(int id, int axis1, int axis2, int *nodes1, int *nodes2) { - const auto eps = 0.001f; - const auto ax1 = m_actor->ar_nodes[axis1].AbsPosition; - const auto ax2 = m_actor->ar_nodes[axis2].AbsPosition; - Ogre::Plane pl = Ogre::Plane((ax1 - ax2).normalisedCopy(), 0); - - Ogre::Vector3 a1 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[0]].AbsPosition); - Ogre::Vector3 a2 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[1]].AbsPosition); - Ogre::Vector3 a3 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[2]].AbsPosition); - Ogre::Vector3 a4 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[3]].AbsPosition); - float a1len = a1.normalise(); - float a2len = a2.normalise(); - float a3len = a3.normalise(); - float a4len = a4.normalise(); + const auto eps = 0.001f; + const auto ax1 = m_actor->ar_nodes[axis1].AbsPosition; + const auto ax2 = m_actor->ar_nodes[axis2].AbsPosition; + Ogre::Plane pl = Ogre::Plane((ax1 - ax2).normalisedCopy(), 0); + + Ogre::Vector3 a1 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[0]].AbsPosition); + Ogre::Vector3 a2 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[1]].AbsPosition); + Ogre::Vector3 a3 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[2]].AbsPosition); + Ogre::Vector3 a4 = pl.projectVector(ax1 - m_actor->ar_nodes[nodes1[3]].AbsPosition); + float a1len = a1.normalise(); + float a2len = a2.normalise(); + float a3len = a3.normalise(); + float a4len = a4.normalise(); if ((std::max(a1len, a3len) / std::min(a1len, a3len) > 1.f + eps) || (std::max(a2len, a4len) / std::min(a2len, a4len) > 1.f + eps)) { Ogre::String msg = Ogre::StringUtil::format("Off-centered axis on base plate of rotator %d", id); - AddMessage(Message::TYPE_WARNING, msg); + AddMessage(Message::TYPE_WARNING, msg); } - Ogre::Vector3 b1 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[0]].AbsPosition); - Ogre::Vector3 b2 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[1]].AbsPosition); - Ogre::Vector3 b3 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[2]].AbsPosition); - Ogre::Vector3 b4 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[3]].AbsPosition); - float b1len = b1.normalise(); - float b2len = b2.normalise(); - float b3len = b3.normalise(); - float b4len = b4.normalise(); + Ogre::Vector3 b1 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[0]].AbsPosition); + Ogre::Vector3 b2 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[1]].AbsPosition); + Ogre::Vector3 b3 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[2]].AbsPosition); + Ogre::Vector3 b4 = pl.projectVector(ax2 - m_actor->ar_nodes[nodes2[3]].AbsPosition); + float b1len = b1.normalise(); + float b2len = b2.normalise(); + float b3len = b3.normalise(); + float b4len = b4.normalise(); if ((std::max(b1len, b3len) / std::min(b1len, b3len) > 1.f + eps) || (std::max(b2len, b4len) / std::min(b2len, b4len) > 1.f + eps)) { Ogre::String msg = Ogre::StringUtil::format("Off-centered axis on rotating plate of rotator %d", id); - AddMessage(Message::TYPE_WARNING, msg); + AddMessage(Message::TYPE_WARNING, msg); } float rot1 = a1.dotProduct(b1); float rot2 = a2.dotProduct(b2); float rot3 = a3.dotProduct(b3); float rot4 = a4.dotProduct(b4); - if ((std::max(rot1, rot2) / std::min(rot1, rot2) > 1.f + eps) || - (std::max(rot2, rot3) / std::min(rot2, rot3) > 1.f + eps) || - (std::max(rot3, rot4) / std::min(rot3, rot4) > 1.f + eps) || - (std::max(rot4, rot1) / std::min(rot4, rot1) > 1.f + eps)) + if ((std::max(rot1, rot2) / std::min(rot1, rot2) > 1.f + eps) || (std::max(rot2, rot3) / std::min(rot2, rot3) > 1.f + eps) || + (std::max(rot3, rot4) / std::min(rot3, rot4) > 1.f + eps) || (std::max(rot4, rot1) / std::min(rot4, rot1) > 1.f + eps)) { Ogre::String msg = Ogre::StringUtil::format("Misaligned plates on rotator %d", id); - AddMessage(Message::TYPE_WARNING, msg); + AddMessage(Message::TYPE_WARNING, msg); } } -Ogre::ManualObject* CreateVideocameraDebugMesh() +Ogre::ManualObject *CreateVideocameraDebugMesh() { // Create material - static size_t counter = 0; - Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create( - "VideoCamDebugMat-" + TOSTRING(counter), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + static size_t counter = 0; + Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create("VideoCamDebugMat-" + TOSTRING(counter), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); ++counter; mat->getTechnique(0)->getPass(0)->createTextureUnitState(); mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::TFO_ANISOTROPIC); @@ -6920,38 +6284,38 @@ Ogre::ManualObject* CreateVideocameraDebugMesh() mat->setLightingEnabled(false); mat->setReceiveShadows(false); // Create mesh - Ogre::ManualObject* mo = gEnv->sceneManager->createManualObject(); // TODO: Eliminate gEnv + Ogre::ManualObject *mo = gEnv->sceneManager->createManualObject(); // TODO: Eliminate gEnv mo->begin(mat->getName(), Ogre::RenderOperation::OT_LINE_LIST); Ogre::ColourValue pos_mark_col(1.f, 0.82f, 0.26f); Ogre::ColourValue dir_mark_col(0.f, 1.f, 1.f); // TODO: This comes out green in simulation - why? ~ only_a_ptr, 05/2017 - const float pos_mark_len = 0.8f; - const float dir_mark_len = 4.f; + const float pos_mark_len = 0.8f; + const float dir_mark_len = 4.f; // X - mo->position(pos_mark_len,0,0); + mo->position(pos_mark_len, 0, 0); mo->colour(pos_mark_col); - mo->position(-pos_mark_len,0,0); + mo->position(-pos_mark_len, 0, 0); mo->colour(pos_mark_col); // Y - mo->position(0,pos_mark_len,0); + mo->position(0, pos_mark_len, 0); mo->colour(pos_mark_col); - mo->position(0,-pos_mark_len,0); + mo->position(0, -pos_mark_len, 0); mo->colour(pos_mark_col); // +Z - mo->position(0,0,pos_mark_len); + mo->position(0, 0, pos_mark_len); mo->colour(pos_mark_col); - mo->position(0,0,0); + mo->position(0, 0, 0); mo->colour(pos_mark_col); // -Z = the direction - mo->position(0,0,-dir_mark_len); + mo->position(0, 0, -dir_mark_len); mo->colour(dir_mark_col); - mo->position(0,0,0); + mo->position(0, 0, 0); mo->colour(dir_mark_col); mo->end(); // Don't forget this! return mo; } -void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) +void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera *def) { try { @@ -6966,11 +6330,12 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) switch (def->camera_role) { - case -1: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_VIDEOCAM; break; - case 0: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_TRACKING_VIDEOCAM; break; - case 1: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_MIRROR; break; + case -1: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_VIDEOCAM; break; + case 0: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_TRACKING_VIDEOCAM; break; + case 1: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_MIRROR; break; default: - this->AddMessage(Message::TYPE_ERROR, "VideoCamera (mat: " + def->material_name + ") has invalid 'role': " + TOSTRING(def->camera_role)); + this->AddMessage(Message::TYPE_ERROR, + "VideoCamera (mat: " + def->material_name + ") has invalid 'role': " + TOSTRING(def->camera_role)); return; } @@ -6979,18 +6344,15 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) vcam.vcam_node_dir_z = static_cast(this->GetNodeOrThrow(def->left_node).pos); vcam.vcam_pos_offset = def->offset; - //rotate camera picture 180 degrees, skip for mirrors - float rotation_z = (def->camera_role != 1) ? def->rotation.z + 180 : def->rotation.z; - vcam.vcam_rotation - = Ogre::Quaternion(Ogre::Degree(rotation_z), Ogre::Vector3::UNIT_Z) - * Ogre::Quaternion(Ogre::Degree(def->rotation.y), Ogre::Vector3::UNIT_Y) - * Ogre::Quaternion(Ogre::Degree(def->rotation.x), Ogre::Vector3::UNIT_X); + // rotate camera picture 180 degrees, skip for mirrors + float rotation_z = (def->camera_role != 1) ? def->rotation.z + 180 : def->rotation.z; + vcam.vcam_rotation = Ogre::Quaternion(Ogre::Degree(rotation_z), Ogre::Vector3::UNIT_Z) * + Ogre::Quaternion(Ogre::Degree(def->rotation.y), Ogre::Vector3::UNIT_Y) * + Ogre::Quaternion(Ogre::Degree(def->rotation.x), Ogre::Vector3::UNIT_X); // set alternative camposition (optional) if (def->alt_reference_node.IsValidAnyState()) - { - vcam.vcam_node_alt_pos = static_cast(this->GetNodeOrThrow(def->alt_reference_node).pos); - } + { vcam.vcam_node_alt_pos = static_cast(this->GetNodeOrThrow(def->alt_reference_node).pos); } else { vcam.vcam_node_alt_pos = vcam.vcam_node_center; @@ -7000,7 +6362,7 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) if (def->alt_orientation_node.IsValidAnyState()) { // This is a tracker camera - vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_TRACKING_VIDEOCAM; + vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_TRACKING_VIDEOCAM; vcam.vcam_node_lookat = static_cast(this->GetNodeOrThrow(def->alt_orientation_node).pos); } @@ -7010,14 +6372,10 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) if (!App::gfx_window_videocams.GetActive()) { vcam.vcam_render_tex = Ogre::TextureManager::getSingleton().createManual( - vcam.vcam_material->getName() + "_texture", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - def->texture_width, - def->texture_height, + vcam.vcam_material->getName() + "_texture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, def->texture_width, def->texture_height, 0, // no mip maps - Ogre::PF_R8G8B8, - Ogre::TU_RENDERTARGET); + Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); vcam.vcam_render_target = vcam.vcam_render_tex->getBuffer()->getRenderTarget(); vcam.vcam_render_target->setAutoUpdated(false); } @@ -7026,11 +6384,11 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) Ogre::NameValuePairList misc; Ogre::ConfigOptionMap ropts = App::GetOgreSubsystem()->GetOgreRoot()->getRenderSystem()->getConfigOptions(); - misc["FSAA"] = Ogre::StringConverter::parseInt(ropts["FSAA"].currentValue, 0); + misc["FSAA"] = Ogre::StringConverter::parseInt(ropts["FSAA"].currentValue, 0); const std::string window_name = (!def->camera_name.empty()) ? def->camera_name : def->material_name; - vcam.vcam_render_window = Ogre::Root::getSingleton().createRenderWindow( - window_name, def->texture_width, def->texture_height, false, &misc); + vcam.vcam_render_window = + Ogre::Root::getSingleton().createRenderWindow(window_name, def->texture_width, def->texture_height, false, &misc); vcam.vcam_render_window->setAutoUpdated(false); fixRenderWindowIcon(vcam.vcam_render_window); // Function from 'Utils.h' @@ -7048,14 +6406,15 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) if (vcam.vcam_render_target) { - Ogre::Viewport* vp = vcam.vcam_render_target->addViewport(vcam.vcam_ogre_camera); + Ogre::Viewport *vp = vcam.vcam_render_target->addViewport(vcam.vcam_ogre_camera); vp->setClearEveryFrame(true); vp->setBackgroundColour(gEnv->mainCamera->getViewport()->getBackgroundColour()); vp->setVisibilityMask(~HIDE_MIRROR); vp->setVisibilityMask(~DEPTHMAP_DISABLED); vp->setOverlaysEnabled(false); - vcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(vcam.vcam_render_tex->getName()); + vcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName( + vcam.vcam_render_tex->getName()); // this is a mirror, flip the image left<>right to have a mirror and not a cameraimage if (def->camera_role == 1) @@ -7064,7 +6423,7 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) if (vcam.vcam_render_window) { - Ogre::Viewport* vp = vcam.vcam_render_window->addViewport(vcam.vcam_ogre_camera); + Ogre::Viewport *vp = vcam.vcam_render_window->addViewport(vcam.vcam_ogre_camera); vp->setClearEveryFrame(true); vp->setBackgroundColour(gEnv->mainCamera->getViewport()->getBackgroundColour()); vp->setVisibilityMask(~HIDE_MIRROR); @@ -7075,14 +6434,14 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) if (App::diag_videocameras.GetActive()) { - Ogre::ManualObject* mo = CreateVideocameraDebugMesh(); // local helper function - vcam.vcam_debug_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + Ogre::ManualObject *mo = CreateVideocameraDebugMesh(); // local helper function + vcam.vcam_debug_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); vcam.vcam_debug_node->attachObject(mo); } m_actor->m_gfx_actor->m_videocameras.push_back(vcam); } - catch (std::exception & ex) + catch (std::exception &ex) { this->AddMessage(Message::TYPE_ERROR, ex.what()); } @@ -7092,44 +6451,35 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def) } } -void ActorSpawner::CreateMirrorPropVideoCam( - Ogre::MaterialPtr custom_mat, CustomMaterial::MirrorPropType type, Ogre::SceneNode* prop_scenenode) +void ActorSpawner::CreateMirrorPropVideoCam(Ogre::MaterialPtr custom_mat, CustomMaterial::MirrorPropType type, + Ogre::SceneNode *prop_scenenode) { static size_t mprop_counter = 0; try { // Prepare videocamera entry GfxActor::VideoCamera vcam; - vcam.vcam_off_tex_name = "mirror.dds"; + vcam.vcam_off_tex_name = "mirror.dds"; vcam.vcam_prop_scenenode = prop_scenenode; switch (type) { - case CustomMaterial::MirrorPropType::MPROP_LEFT: - vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_MIRROR_PROP_LEFT; - break; + case CustomMaterial::MirrorPropType::MPROP_LEFT: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_MIRROR_PROP_LEFT; break; case CustomMaterial::MirrorPropType::MPROP_RIGHT: vcam.vcam_type = GfxActor::VideoCamType::VCTYPE_MIRROR_PROP_RIGHT; break; - default: - this->AddMessage(Message::TYPE_ERROR, "Cannot create mirror prop of type 'MPROP_NONE'"); - return; + default: this->AddMessage(Message::TYPE_ERROR, "Cannot create mirror prop of type 'MPROP_NONE'"); return; } // Create rendering texture const std::string mirror_tex_name = this->ComposeName("MirrorPropTexture-", static_cast(mprop_counter)); - vcam.vcam_render_tex = Ogre::TextureManager::getSingleton().createManual(mirror_tex_name - , m_custom_resource_group - , Ogre::TEX_TYPE_2D - , 128 - , 256 - , 0 - , Ogre::PF_R8G8B8 - , Ogre::TU_RENDERTARGET); + vcam.vcam_render_tex = Ogre::TextureManager::getSingleton().createManual( + mirror_tex_name, m_custom_resource_group, Ogre::TEX_TYPE_2D, 128, 256, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); // Create OGRE camera - vcam.vcam_ogre_camera = gEnv->sceneManager->createCamera(this->ComposeName("MirrorPropCamera-", static_cast(mprop_counter))); + vcam.vcam_ogre_camera = + gEnv->sceneManager->createCamera(this->ComposeName("MirrorPropCamera-", static_cast(mprop_counter))); vcam.vcam_ogre_camera->setNearClipDistance(0.2f); vcam.vcam_ogre_camera->setFarClipDistance(gEnv->mainCamera->getFarClipDistance()); vcam.vcam_ogre_camera->setFOVy(Ogre::Degree(50)); @@ -7139,7 +6489,7 @@ void ActorSpawner::CreateMirrorPropVideoCam( // Setup rendering vcam.vcam_render_target = vcam.vcam_render_tex->getBuffer()->getRenderTarget(); vcam.vcam_render_target->setActive(true); - Ogre::Viewport* v = vcam.vcam_render_target->addViewport(vcam.vcam_ogre_camera); + Ogre::Viewport *v = vcam.vcam_render_target->addViewport(vcam.vcam_ogre_camera); v->setClearEveryFrame(true); v->setBackgroundColour(gEnv->mainCamera->getViewport()->getBackgroundColour()); v->setOverlaysEnabled(false); @@ -7152,7 +6502,7 @@ void ActorSpawner::CreateMirrorPropVideoCam( // Submit the videocamera m_actor->m_gfx_actor->m_videocameras.push_back(vcam); } - catch (std::exception & ex) + catch (std::exception &ex) { this->AddMessage(Message::TYPE_ERROR, ex.what()); } @@ -7165,14 +6515,17 @@ void ActorSpawner::CreateMirrorPropVideoCam( void ActorSpawner::HandleException() { - try { throw; } // Rethrow + try + { + throw; + } // Rethrow - catch (Ogre::Exception& ogre_e) + catch (Ogre::Exception &ogre_e) { // Add the message silently, OGRE already printed it to RoR.log m_messages.push_back(Message(Message::TYPE_ERROR, ogre_e.getFullDescription(), m_current_keyword)); } - catch (std::exception& std_e) + catch (std::exception &std_e) { this->AddMessage(Message::TYPE_ERROR, std_e.what()); } @@ -7182,18 +6535,18 @@ void ActorSpawner::HandleException() } } -Ogre::ParticleSystem* ActorSpawner::CreateParticleSystem(std::string const & name, std::string const & template_name) +Ogre::ParticleSystem *ActorSpawner::CreateParticleSystem(std::string const &name, std::string const &template_name) { // None of `Ogre::SceneManager::createParticleSystem()` overloads // lets us specify both resource group and template name. Ogre::NameValuePairList params; params["resourceGroup"] = m_custom_resource_group; - params["templateName"] = template_name; + params["templateName"] = template_name; - Ogre::MovableObject* obj = gEnv->sceneManager->createMovableObject( - name, Ogre::ParticleSystemFactory::FACTORY_TYPE_NAME, ¶ms); - Ogre::ParticleSystem* psys = static_cast(obj); + Ogre::MovableObject *obj = + gEnv->sceneManager->createMovableObject(name, Ogre::ParticleSystemFactory::FACTORY_TYPE_NAME, ¶ms); + Ogre::ParticleSystem *psys = static_cast(obj); psys->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap return psys; } diff --git a/source/main/physics/RigSpawner.h b/source/main/physics/RigSpawner.h index 317147f813..caf34ef7ea 100644 --- a/source/main/physics/RigSpawner.h +++ b/source/main/physics/RigSpawner.h @@ -24,62 +24,70 @@ /// @author Petr Ohlidal /// @date 12/2013 - #pragma once #include "Application.h" -#include "RoRPrerequisites.h" -#include "RigDef_Parser.h" #include "BeamData.h" #include "FlexFactory.h" #include "FlexObj.h" #include "GfxActor.h" +#include "RigDef_Parser.h" +#include "RoRPrerequisites.h" #include #include -/// Processes a RigDef::File data structure (result of parsing a "Truckfile" fileformat) into 'an Actor' - a simulated physical object. +/// Processes a RigDef::File data structure (result of parsing a "Truckfile" fileformat) into 'an Actor' - a simulated physical +/// object. /// /// HISTORY: /// -/// Before v0.4.5, truckfiles were parsed&spawned on-the-fly: RoR's simulation used data structures with arrays of pre-defined sizes -/// (i.e. MAX_NODES, MAX_BEAMS, MAX_* ...) and the spawner (class `SerializedRig`) wrote directly into them while reading data from the truckfile. Gfx elements were also created immediately. -/// As a result, the logic was chaotic: some features broke each other (most notably VideoCameras X MaterialFlares X SkinZips) and the sim. structs often contained parser context variables. -/// Also, the whole system was extremely sensitive to order of definitions in truckfile - often [badly/not] documented, known only by forum/IRC users at the time. +/// Before v0.4.5, truckfiles were parsed&spawned on-the-fly: RoR's simulation used data structures with arrays of pre-defined +/// sizes (i.e. MAX_NODES, MAX_BEAMS, MAX_* ...) and the spawner (class `SerializedRig`) wrote directly into them while reading +/// data from the truckfile. Gfx elements were also created immediately. As a result, the logic was chaotic: some features broke +/// each other (most notably VideoCameras X MaterialFlares X SkinZips) and the sim. structs often contained parser context +/// variables. Also, the whole system was extremely sensitive to order of definitions in truckfile - often [badly/not] documented, +/// known only by forum/IRC users at the time. /// -/// Since v0.4.5, RoR has `RigDef::Parser` which reads truckfile and emits instance of `RigDef::File` - all data from truckfile in memory. `RigDef::File` doesn't preserve the order of definitions, -/// instead it's designed to resolve all order-dependent references to order-independent, see `RigDef::SequentialImporter` (resources/rig_def_fileformat/RigDef_SequentialImporter.h) for more info. -/// `ActorSpawner` was created by carefully refactoring old `SerializedRig` described above, so a lot of the dirty logic remained. Elements were still written into constant-size arrays. +/// Since v0.4.5, RoR has `RigDef::Parser` which reads truckfile and emits instance of `RigDef::File` - all data from truckfile in +/// memory. `RigDef::File` doesn't preserve the order of definitions, instead it's designed to resolve all order-dependent +/// references to order-independent, see `RigDef::SequentialImporter` (resources/rig_def_fileformat/RigDef_SequentialImporter.h) +/// for more info. `ActorSpawner` was created by carefully refactoring old `SerializedRig` described above, so a lot of the dirty +/// logic remained. Elements were still written into constant-size arrays. /// /// PRESENT (06/2017): /// -/// RoR is being refactored to get rid of the MAX_[BEAMS/NODES/***] limits. Static arrays in `rig_t` are replaced with pointers to dynamically allocated memory. -/// Memory requirements are calculated upfront from `RigDef::File`. +/// RoR is being refactored to get rid of the MAX_[BEAMS/NODES/***] limits. Static arrays in `rig_t` are replaced with pointers to +/// dynamically allocated memory. Memory requirements are calculated upfront from `RigDef::File`. /// /// FUTURE: /// /// ActorSpawner will work in 2 steps: /// 1. Physics/simulation data are fully prepared. This should be very fast (we can pre-calculate and cache things if needed). -/// 2. Graphics/sounds are set up, reading the completed physics/sim data. Graphics are fully managed by `GfxActor`. Similar utility will be added for sound. +/// 2. Graphics/sounds are set up, reading the completed physics/sim data. Graphics are fully managed by `GfxActor`. Similar +/// utility will be added for sound. /// /// CONVENTIONS: /// /// * Functions "Process*(Definition & def)" Transform elements of truckfile to rig structures. -/// * Functions "FindAndProcess*(Definition & def)" Find and process an element which should be unique in the current actor configuration. +/// * Functions "FindAndProcess*(Definition & def)" Find and process an element which should be unique in the current +/// actor configuration. /// * Functions "Add*()", "Create*()" or "Build*()" Add partial structures to the actor. /// * Functions Other functions are utilities. /// /// @author Petr Ohlidal class ActorSpawner { - friend class VideoCamera; // Needs to add log messages + friend class VideoCamera; // Needs to add log messages friend class RoR::FlexFactory; // Needs to use `ComposeName()` and `SetupNewEntity()` -public: - + public: struct ActorMemoryRequirements { - ActorMemoryRequirements() { memset(this,0, sizeof(ActorMemoryRequirements)); } + ActorMemoryRequirements() + { + memset(this, 0, sizeof(ActorMemoryRequirements)); + } size_t num_nodes; size_t num_beams; @@ -103,50 +111,38 @@ class ActorSpawner TYPE_INVALID = 0xFFFFFFFF }; - Message( - Message::Type type, - Ogre::String const & text, - RigDef::File::Keyword keyword = RigDef::File::KEYWORD_INVALID - ): - type(type), - text(text), - keyword(keyword) - {} - - Ogre::String text; - Type type; + Message(Message::Type type, Ogre::String const &text, RigDef::File::Keyword keyword = RigDef::File::KEYWORD_INVALID) + : type(type), text(text), keyword(keyword) + { + } + + Ogre::String text; + Type type; RigDef::File::Keyword keyword; }; - class Exception: public std::runtime_error + class Exception : public std::runtime_error { - public: - - Exception(Ogre::String const & message): - runtime_error(message) - {} - + public: + Exception(Ogre::String const &message) : runtime_error(message) + { + } }; - void Setup( - Actor *actor, - std::shared_ptr file, - Ogre::SceneNode *parent, - Ogre::Vector3 const & spawn_position - ); + void Setup(Actor *actor, std::shared_ptr file, Ogre::SceneNode *parent, Ogre::Vector3 const &spawn_position); Actor *SpawnActor(); /** - * Adds a vehicle module to the validated configuration. - * @param module_name A module from the validated rig-def file. - */ - bool AddModule(Ogre::String const & module_name); + * Adds a vehicle module to the validated configuration. + * @param module_name A module from the validated rig-def file. + */ + bool AddModule(Ogre::String const &module_name); /** - * Adds a vehicle module to the validated configuration. - * @param module_name A module from the validated rig-def file. - */ + * Adds a vehicle module to the validated configuration. + * @param module_name A module from the validated rig-def file. + */ void AddModule(std::shared_ptr module) { m_selected_modules.push_back(module); @@ -157,38 +153,49 @@ class ActorSpawner return m_actor; } - ActorMemoryRequirements const& GetMemoryRequirements() + ActorMemoryRequirements const &GetMemoryRequirements() { return m_memory_requirements; } /** - * Finds and clones given material. Reports errors. - * @return NULL Ogre::MaterialPtr on error. - */ - Ogre::MaterialPtr InstantiateManagedMaterial(Ogre::String const & source_name, Ogre::String const & clone_name); + * Finds and clones given material. Reports errors. + * @return NULL Ogre::MaterialPtr on error. + */ + Ogre::MaterialPtr InstantiateManagedMaterial(Ogre::String const &source_name, Ogre::String const &clone_name); /** - * Finds existing node by Node::Ref; throws an exception if the node doesn't exist. - * @return Index of existing node - * @throws Exception If the node isn't found. - */ - unsigned int GetNodeIndexOrThrow(RigDef::Node::Ref const & id); + * Finds existing node by Node::Ref; throws an exception if the node doesn't exist. + * @return Index of existing node + * @throws Exception If the node isn't found. + */ + unsigned int GetNodeIndexOrThrow(RigDef::Node::Ref const &id); static void SetupDefaultSoundSources(Actor *vehicle); - static void ComposeName(RoR::Str<100>& str, const char* type, int number, int actor_id); + static void ComposeName(RoR::Str<100> &str, const char *type, int number, int actor_id); std::string GetSubmeshGroundmodelName(); - std::string ProcessMessagesToString(); - std::list & GetMessages() { return m_messages; } - int GetMessagesNumErrors() const { return m_messages_num_errors; } - int GetMessagesNumWarnings() const { return m_messages_num_warnings; } - int GetMessagesNumOther() const { return m_messages_num_other; } - -private: + std::string ProcessMessagesToString(); + std::list &GetMessages() + { + return m_messages; + } + int GetMessagesNumErrors() const + { + return m_messages_num_errors; + } + int GetMessagesNumWarnings() const + { + return m_messages_num_warnings; + } + int GetMessagesNumOther() const + { + return m_messages_num_other; + } + private: struct CustomMaterial { enum class MirrorPropType @@ -198,869 +205,790 @@ class ActorSpawner MPROP_RIGHT, }; - CustomMaterial(): - material_flare_def(nullptr), - video_camera_def(nullptr), - mirror_prop_type(MirrorPropType::MPROP_NONE), - mirror_prop_scenenode(nullptr) - {} - - CustomMaterial(Ogre::MaterialPtr& mat): - material(mat), - material_flare_def(nullptr), - video_camera_def(nullptr), - mirror_prop_type(MirrorPropType::MPROP_NONE), - mirror_prop_scenenode(nullptr) - {} - - Ogre::MaterialPtr material; - RigDef::MaterialFlareBinding* material_flare_def; - RigDef::VideoCamera* video_camera_def; - MirrorPropType mirror_prop_type; - Ogre::SceneNode* mirror_prop_scenenode; + CustomMaterial() + : material_flare_def(nullptr), video_camera_def(nullptr), mirror_prop_type(MirrorPropType::MPROP_NONE), + mirror_prop_scenenode(nullptr) + { + } + + CustomMaterial(Ogre::MaterialPtr &mat) + : material(mat), material_flare_def(nullptr), video_camera_def(nullptr), mirror_prop_type(MirrorPropType::MPROP_NONE), + mirror_prop_scenenode(nullptr) + { + } + + Ogre::MaterialPtr material; + RigDef::MaterialFlareBinding *material_flare_def; + RigDef::VideoCamera * video_camera_def; + MirrorPropType mirror_prop_type; + Ogre::SceneNode * mirror_prop_scenenode; }; struct BeamVisualsTicket //!< Visuals are queued for processing using this struct { - BeamVisualsTicket(int idx, float diam, const char* mtr=nullptr, bool vis=true): - beam_index(idx), diameter(diam), material_name(mtr), visible(vis) - {} + BeamVisualsTicket(int idx, float diam, const char *mtr = nullptr, bool vis = true) + : beam_index(idx), diameter(diam), material_name(mtr), visible(vis) + { + } - int beam_index; + int beam_index; std::string material_name; // TODO: how does std::string behave when parent struct is re-allocated within std::vector? ;) - float diameter; - bool visible; // Some beams are spawned as hidden (ties, hooks) and displayed only when activated + float diameter; + bool visible; // Some beams are spawned as hidden (ties, hooks) and displayed only when activated }; struct WheelVisualsTicket //!< Wheel visuals are queued for processing using this struct { - WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::Wheel* def): - wheel_index(wheel_idx), base_node_index(node_idx), - wheel_def(def), wheel2_def(nullptr), meshwheel_def(nullptr), flexbodywheel_def(nullptr) - {} - - WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::Wheel2* def): - wheel_index(wheel_idx), base_node_index(node_idx), - wheel_def(nullptr), wheel2_def(def), meshwheel_def(nullptr), flexbodywheel_def(nullptr) - {} - - WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::MeshWheel* def, uint16_t axis1, uint16_t axis2): - wheel_index(wheel_idx), base_node_index(node_idx), - wheel_def(nullptr), wheel2_def(nullptr), meshwheel_def(def), flexbodywheel_def(nullptr), - axis_node_1(axis1), axis_node_2(axis2) - {} - - WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::FlexBodyWheel* def, uint16_t axis1, uint16_t axis2): - wheel_index(wheel_idx), base_node_index(node_idx), - wheel_def(nullptr), wheel2_def(nullptr), meshwheel_def(nullptr), flexbodywheel_def(def), - axis_node_1(axis1), axis_node_2(axis2) - {} - - RigDef::Wheel* wheel_def; - RigDef::Wheel2* wheel2_def; - RigDef::MeshWheel* meshwheel_def; - RigDef::FlexBodyWheel* flexbodywheel_def; - - uint16_t wheel_index; - uint16_t base_node_index; - uint16_t axis_node_1; - uint16_t axis_node_2; + WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::Wheel *def) + : wheel_index(wheel_idx), base_node_index(node_idx), wheel_def(def), wheel2_def(nullptr), meshwheel_def(nullptr), + flexbodywheel_def(nullptr) + { + } + + WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::Wheel2 *def) + : wheel_index(wheel_idx), base_node_index(node_idx), wheel_def(nullptr), wheel2_def(def), meshwheel_def(nullptr), + flexbodywheel_def(nullptr) + { + } + + WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::MeshWheel *def, uint16_t axis1, uint16_t axis2) + : wheel_index(wheel_idx), base_node_index(node_idx), wheel_def(nullptr), wheel2_def(nullptr), meshwheel_def(def), + flexbodywheel_def(nullptr), axis_node_1(axis1), axis_node_2(axis2) + { + } + + WheelVisualsTicket(uint16_t wheel_idx, uint16_t node_idx, RigDef::FlexBodyWheel *def, uint16_t axis1, uint16_t axis2) + : wheel_index(wheel_idx), base_node_index(node_idx), wheel_def(nullptr), wheel2_def(nullptr), meshwheel_def(nullptr), + flexbodywheel_def(def), axis_node_1(axis1), axis_node_2(axis2) + { + } + + RigDef::Wheel * wheel_def; + RigDef::Wheel2 * wheel2_def; + RigDef::MeshWheel * meshwheel_def; + RigDef::FlexBodyWheel *flexbodywheel_def; + + uint16_t wheel_index; + uint16_t base_node_index; + uint16_t axis_node_1; + uint16_t axis_node_2; }; -/* -------------------------------------------------------------------------- */ -/* Processing functions. */ -/* NOTE: Please maintain alphabetical order. */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Processing functions. */ + /* NOTE: Please maintain alphabetical order. */ + /* -------------------------------------------------------------------------- */ /** - * Section 'airbrakes'. - */ - void ProcessAirbrake(RigDef::Airbrake & def); + * Section 'airbrakes'. + */ + void ProcessAirbrake(RigDef::Airbrake &def); /** - * Section 'animators'. - */ - void ProcessAnimator(RigDef::Animator & def); + * Section 'animators'. + */ + void ProcessAnimator(RigDef::Animator &def); /** - * Section 'AntiLockBrakes'. - */ - void ProcessAntiLockBrakes(RigDef::AntiLockBrakes & def); + * Section 'AntiLockBrakes'. + */ + void ProcessAntiLockBrakes(RigDef::AntiLockBrakes &def); /** - * Section 'author' in root module. - */ + * Section 'author' in root module. + */ void ProcessAuthors(); /** - * Section 'axles'. - */ - void ProcessAxle(RigDef::Axle & def); + * Section 'axles'. + */ + void ProcessAxle(RigDef::Axle &def); /** - * Section 'beams'. Depends on 'nodes' - */ - void ProcessBeam(RigDef::Beam & def); + * Section 'beams'. Depends on 'nodes' + */ + void ProcessBeam(RigDef::Beam &def); /** - * Section 'brakes' in any module. - */ - void ProcessBrakes(RigDef::Brakes & def); + * Section 'brakes' in any module. + */ + void ProcessBrakes(RigDef::Brakes &def); /** - * Section 'camerarail', depends on 'nodes'. - */ - void ProcessCameraRail(RigDef::CameraRail & def); + * Section 'camerarail', depends on 'nodes'. + */ + void ProcessCameraRail(RigDef::CameraRail &def); /** - * Section 'cameras', depends on 'nodes'. - */ - void ProcessCamera(RigDef::Camera & def); + * Section 'cameras', depends on 'nodes'. + */ + void ProcessCamera(RigDef::Camera &def); /** - * Section 'cinecam', depends on 'nodes'. - */ - void ProcessCinecam(RigDef::Cinecam & def); + * Section 'cinecam', depends on 'nodes'. + */ + void ProcessCinecam(RigDef::Cinecam &def); /** - * Section 'collisionboxes' - */ - void ProcessCollisionBox(RigDef::CollisionBox & def); + * Section 'collisionboxes' + */ + void ProcessCollisionBox(RigDef::CollisionBox &def); /** - * Processes sections 'commands' and 'commands2' (unified). - */ - void ProcessCommand(RigDef::Command2 & def); + * Processes sections 'commands' and 'commands2' (unified). + */ + void ProcessCommand(RigDef::Command2 &def); /** - * Section 'contacters'. - */ - void ProcessContacter(RigDef::Node::Ref & node_ref); + * Section 'contacters'. + */ + void ProcessContacter(RigDef::Node::Ref &node_ref); /** - * Section 'cruisecontrol' in any module. - */ - void ProcessCruiseControl(RigDef::CruiseControl & def); + * Section 'cruisecontrol' in any module. + */ + void ProcessCruiseControl(RigDef::CruiseControl &def); /** - * Section 'engine' in any module. - */ - void ProcessEngine(RigDef::Engine & def); + * Section 'engine' in any module. + */ + void ProcessEngine(RigDef::Engine &def); /** - * Section 'engoption' in any module. - */ - void ProcessEngoption(RigDef::Engoption & def); + * Section 'engoption' in any module. + */ + void ProcessEngoption(RigDef::Engoption &def); /** - * Section 'engturbo' in any module. - */ - void ProcessEngturbo(RigDef::Engturbo & def); + * Section 'engturbo' in any module. + */ + void ProcessEngturbo(RigDef::Engturbo &def); /** - * Section 'exhausts'. - */ - void ProcessExhaust(RigDef::Exhaust & def); + * Section 'exhausts'. + */ + void ProcessExhaust(RigDef::Exhaust &def); /** - * Inline-section 'extcamera'. - */ - void ProcessExtCamera(RigDef::ExtCamera & def); + * Inline-section 'extcamera'. + */ + void ProcessExtCamera(RigDef::ExtCamera &def); /** - * Section 'fixes' - */ + * Section 'fixes' + */ void ProcessFixedNode(RigDef::Node::Ref node_ref); /** - * Sections 'flares' and 'flares2'. - */ - void ProcessFlare2(RigDef::Flare2 & def); + * Sections 'flares' and 'flares2'. + */ + void ProcessFlare2(RigDef::Flare2 &def); /** - * Section 'flexbodies'. - */ + * Section 'flexbodies'. + */ void ProcessFlexbody(std::shared_ptr def); /** - * Section 'flexbodywheels'. - */ - void ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def); + * Section 'flexbodywheels'. + */ + void ProcessFlexBodyWheel(RigDef::FlexBodyWheel &def); /** - * Section 'fusedrag'. - */ - void ProcessFusedrag(RigDef::Fusedrag & def); + * Section 'fusedrag'. + */ + void ProcessFusedrag(RigDef::Fusedrag &def); /** - * Section 'gobals' in any module - */ - void ProcessGlobals(RigDef::Globals & def); + * Section 'gobals' in any module + */ + void ProcessGlobals(RigDef::Globals &def); /** - * Section 'guisettings'. - */ - void ProcessGuiSettings(RigDef::GuiSettings & def); + * Section 'guisettings'. + */ + void ProcessGuiSettings(RigDef::GuiSettings &def); void ProcessHelp(); /** - * Depends on 'nodes' - */ - void ProcessHook(RigDef::Hook & def); + * Depends on 'nodes' + */ + void ProcessHook(RigDef::Hook &def); - void ProcessHydro(RigDef::Hydro & def); + void ProcessHydro(RigDef::Hydro &def); /** - * Section 'interaxles'. - */ - void ProcessInterAxle(RigDef::InterAxle & def); + * Section 'interaxles'. + */ + void ProcessInterAxle(RigDef::InterAxle &def); /** - * Depends on section 'nodes' - */ - void ProcessLockgroup(RigDef::Lockgroup & lockgroup); + * Depends on section 'nodes' + */ + void ProcessLockgroup(RigDef::Lockgroup &lockgroup); /** - * Section 'managedmaterials' - */ - void ProcessManagedMaterial(RigDef::ManagedMaterial & def); + * Section 'managedmaterials' + */ + void ProcessManagedMaterial(RigDef::ManagedMaterial &def); /** - * Section 'meshwheels'. - */ - void ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def); + * Section 'meshwheels'. + */ + void ProcessMeshWheel(RigDef::MeshWheel &meshwheel_def); /** - * Section 'meshwheels2'. - */ - void ProcessMeshWheel2(RigDef::MeshWheel & def); + * Section 'meshwheels2'. + */ + void ProcessMeshWheel2(RigDef::MeshWheel &def); /** - * Section 'minimass'. - */ + * Section 'minimass'. + */ void ProcessMinimassInAnyModule(); - void ProcessNode(RigDef::Node & def); + void ProcessNode(RigDef::Node &def); /** - * Section 'particles'. - */ - void ProcessParticle(RigDef::Particle & def); + * Section 'particles'. + */ + void ProcessParticle(RigDef::Particle &def); /** - * Section 'pistonprops'. - */ - void ProcessPistonprop(RigDef::Pistonprop & def); + * Section 'pistonprops'. + */ + void ProcessPistonprop(RigDef::Pistonprop &def); /** - * Section 'props'. - */ - void ProcessProp(RigDef::Prop & def); + * Section 'props'. + */ + void ProcessProp(RigDef::Prop &def); /** - * Section 'railgroups'. - */ - void ProcessRailGroup(RigDef::RailGroup & def); + * Section 'railgroups'. + */ + void ProcessRailGroup(RigDef::RailGroup &def); /** - * Section 'ropables'. - */ - void ProcessRopable(RigDef::Ropable & def); + * Section 'ropables'. + */ + void ProcessRopable(RigDef::Ropable &def); /** - * Section 'ropes'. - */ - void ProcessRope(RigDef::Rope & def); + * Section 'ropes'. + */ + void ProcessRope(RigDef::Rope &def); - void ProcessRotator(RigDef::Rotator & def); + void ProcessRotator(RigDef::Rotator &def); - void ProcessRotator2(RigDef::Rotator2 & def); + void ProcessRotator2(RigDef::Rotator2 &def); - void ProcessScrewprop(RigDef::Screwprop & def); + void ProcessScrewprop(RigDef::Screwprop &def); /** - * Section 'shocks'. - */ - void ProcessShock(RigDef::Shock & def); + * Section 'shocks'. + */ + void ProcessShock(RigDef::Shock &def); /** - * Add a shock absorber (section 'shocks2') to the rig. - */ - void ProcessShock2(RigDef::Shock2 & def); + * Add a shock absorber (section 'shocks2') to the rig. + */ + void ProcessShock2(RigDef::Shock2 &def); /** - * Add a shock absorber (section 'shocks3') to the rig. - */ - void ProcessShock3(RigDef::Shock3 & def); + * Add a shock absorber (section 'shocks3') to the rig. + */ + void ProcessShock3(RigDef::Shock3 &def); /** - * Section 'slidenodes'. Depends on 'railgroups' - */ - void ProcessSlidenode(RigDef::SlideNode & def); + * Section 'slidenodes'. Depends on 'railgroups' + */ + void ProcessSlidenode(RigDef::SlideNode &def); /** - * Section 'SlopeBrake' in any module. - */ - void ProcessSlopeBrake(RigDef::SlopeBrake & def); + * Section 'SlopeBrake' in any module. + */ + void ProcessSlopeBrake(RigDef::SlopeBrake &def); /** - * Section 'soundsources'. - */ - void ProcessSoundSource(RigDef::SoundSource & def); + * Section 'soundsources'. + */ + void ProcessSoundSource(RigDef::SoundSource &def); /** - * Section 'soundsources2'. - */ - void ProcessSoundSource2(RigDef::SoundSource2 & def); + * Section 'soundsources2'. + */ + void ProcessSoundSource2(RigDef::SoundSource2 &def); /** - * Section 'submeshes'. - */ - void ProcessSubmesh(RigDef::Submesh & def); + * Section 'submeshes'. + */ + void ProcessSubmesh(RigDef::Submesh &def); /** - * Section 'ties'. - */ - void ProcessTie(RigDef::Tie & def); + * Section 'ties'. + */ + void ProcessTie(RigDef::Tie &def); /** - * Section 'torquecurve' in any module. Depends on 'engine'. - */ - void ProcessTorqueCurve(RigDef::TorqueCurve & def); + * Section 'torquecurve' in any module. Depends on 'engine'. + */ + void ProcessTorqueCurve(RigDef::TorqueCurve &def); /** - * Section 'TractionControl' in any module. - */ - void ProcessTractionControl(RigDef::TractionControl & def); + * Section 'TractionControl' in any module. + */ + void ProcessTractionControl(RigDef::TractionControl &def); /** - * Section 'transfercase'. - */ - void ProcessTransferCase(RigDef::TransferCase & def); + * Section 'transfercase'. + */ + void ProcessTransferCase(RigDef::TransferCase &def); - void ProcessTrigger(RigDef::Trigger & def); + void ProcessTrigger(RigDef::Trigger &def); - void ProcessTurbojet(RigDef::Turbojet & def); + void ProcessTurbojet(RigDef::Turbojet &def); /** - * Sections 'turboprops' and 'turboprops2' - */ - void ProcessTurboprop2(RigDef::Turboprop2 & def); + * Sections 'turboprops' and 'turboprops2' + */ + void ProcessTurboprop2(RigDef::Turboprop2 &def); /** - * Section 'wheeldetachers' in all modules. - */ - void ProcessWheelDetacher(RigDef::WheelDetacher & def); + * Section 'wheeldetachers' in all modules. + */ + void ProcessWheelDetacher(RigDef::WheelDetacher &def); /** - * Section 'wheels' in all modules. - */ - void ProcessWheel(RigDef::Wheel & def); + * Section 'wheels' in all modules. + */ + void ProcessWheel(RigDef::Wheel &def); /** - * Section 'wheels2' in all modules. - * @author Pierre-Michel Ricordel - * @author Thomas Fischer - */ - void ProcessWheel2(RigDef::Wheel2 & def); + * Section 'wheels2' in all modules. + * @author Pierre-Michel Ricordel + * @author Thomas Fischer + */ + void ProcessWheel2(RigDef::Wheel2 &def); /** - * Section 'wings'. - * @author - */ - void ProcessWing(RigDef::Wing & def); + * Section 'wings'. + * @author + */ + void ProcessWing(RigDef::Wing &def); -/* -------------------------------------------------------------------------- */ -/* Partial processing functions. */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Partial processing functions. */ + /* -------------------------------------------------------------------------- */ - void BuildAerialEngine( - int ref_node_index, - int back_node_index, - int blade_1_node_index, - int blade_2_node_index, - int blade_3_node_index, - int blade_4_node_index, - int couplenode_index, - bool is_turboprops, - Ogre::String const & airfoil, - float power, - float pitch - ); + void BuildAerialEngine(int ref_node_index, int back_node_index, int blade_1_node_index, int blade_2_node_index, + int blade_3_node_index, int blade_4_node_index, int couplenode_index, bool is_turboprops, + Ogre::String const &airfoil, float power, float pitch); /** - * Fetches free beam and sets up defaults. - */ - beam_t & AddBeam( - node_t & node_1, - node_t & node_2, - std::shared_ptr & defaults, - int detacher_group - ); + * Fetches free beam and sets up defaults. + */ + beam_t &AddBeam(node_t &node_1, node_t &node_2, std::shared_ptr &defaults, int detacher_group); /** - * Adds complete wheel (section 'wheels') to the rig. - * @return wheel index in rig_t::wheels array. - */ - unsigned int AddWheel(RigDef::Wheel & wheel); + * Adds complete wheel (section 'wheels') to the rig. + * @return wheel index in rig_t::wheels array. + */ + unsigned int AddWheel(RigDef::Wheel &wheel); /** - * Adds wheel from section 'wheels2'. - * @return wheel index. - */ - unsigned int AddWheel2(RigDef::Wheel2 & wheel_2_def); + * Adds wheel from section 'wheels2'. + * @return wheel index. + */ + unsigned int AddWheel2(RigDef::Wheel2 &wheel_2_def); - void CreateBeamVisuals(beam_t const& beam, int beam_index, bool visible, std::shared_ptr const& beam_defaults, std::string material_override=""); + void CreateBeamVisuals(beam_t const &beam, int beam_index, bool visible, + std::shared_ptr const &beam_defaults, std::string material_override = ""); - RailGroup *CreateRail(std::vector & node_ranges); + RailGroup *CreateRail(std::vector &node_ranges); static void AddSoundSource(Actor *vehicle, SoundScriptInstance *sound_script, int node_index, int type = -2); - static void AddSoundSourceInstance(Actor *vehicle, Ogre::String const & sound_script_name, int node_index, int type = -2); + static void AddSoundSourceInstance(Actor *vehicle, Ogre::String const &sound_script_name, int node_index, int type = -2); -/* -------------------------------------------------------------------------- */ -/* Limits. */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Limits. */ + /* -------------------------------------------------------------------------- */ /** - * Checks there is still space left in rig_t::ar_custom_particles array. - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::ar_custom_particles array. + * @param count Required number of free slots. + * @return True if there is space left. + */ bool CheckParticleLimit(unsigned int count); - + /** - * Checks there is still space left in rig_t::axles array. - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::axles array. + * @param count Required number of free slots. + * @return True if there is space left. + */ bool CheckAxleLimit(unsigned int count); /** - * Checks there is still space left in rig_t::subtexcoords, rig_t::subcabs and rig_t::subisback arrays. - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::subtexcoords, rig_t::subcabs and rig_t::subisback arrays. + * @param count Required number of free slots. + * @return True if there is space left. + */ bool CheckSubmeshLimit(unsigned int count); /** - * Checks there is still space left in rig_t::texcoords array. - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::texcoords array. + * @param count Required number of free slots. + * @return True if there is space left. + */ bool CheckTexcoordLimit(unsigned int count); /** - * Checks there is still space left in rig_t::cabs array. - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::cabs array. + * @param count Required number of free slots. + * @return True if there is space left. + */ bool CheckCabLimit(unsigned int count); /** - * Checks there is still space left in rig_t::ar_camera_rail array. - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::ar_camera_rail array. + * @param count Required number of free slots. + * @return True if there is space left. + */ bool CheckCameraRailLimit(unsigned int count); /** - * Checks there is still space left in rig_t::soundsources array (static version). - * @param count Required number of free slots. - * @return True if there is space left. - */ + * Checks there is still space left in rig_t::soundsources array (static version). + * @param count Required number of free slots. + * @return True if there is space left. + */ static bool CheckSoundScriptLimit(Actor *vehicle, unsigned int count); /** - * Checks there is still space left in rig_t::aeroengines array. - * @param count Required number of free slots. - * @return True if there is enough space left. - */ + * Checks there is still space left in rig_t::aeroengines array. + * @param count Required number of free slots. + * @return True if there is enough space left. + */ bool CheckAeroEngineLimit(unsigned int count); /** - * Checks there is still space left in rig_t::screwprops array. - * @param count Required number of free slots. - * @return True if there is enough space left. - */ + * Checks there is still space left in rig_t::screwprops array. + * @param count Required number of free slots. + * @return True if there is enough space left. + */ bool CheckScrewpropLimit(unsigned int count); -/* -------------------------------------------------------------------------- */ -/* Utility functions. */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Utility functions. */ + /* -------------------------------------------------------------------------- */ /** - * Seeks node. - * @return Pointer to node, or nullptr if not found. - */ - node_t* GetBeamNodePointer(RigDef::Node::Ref const & node_ref); + * Seeks node. + * @return Pointer to node, or nullptr if not found. + */ + node_t *GetBeamNodePointer(RigDef::Node::Ref const &node_ref); /** - * Seeks node in both RigDef::File definition and rig_t generated rig. - * @return Node index or -1 if the node was not found. - */ - int FindNodeIndex(RigDef::Node::Ref & node_ref, bool silent = false); + * Seeks node in both RigDef::File definition and rig_t generated rig. + * @return Node index or -1 if the node was not found. + */ + int FindNodeIndex(RigDef::Node::Ref &node_ref, bool silent = false); /** - * Finds wheel with given axle nodes and returns it's index. - * @param _out_axle_wheel Index of the found wheel. - * @return True if wheel was found, false if not. - */ - bool AssignWheelToAxle(int & _out_axle_wheel, node_t *axis_node_1, node_t *axis_node_2); + * Finds wheel with given axle nodes and returns it's index. + * @param _out_axle_wheel Index of the found wheel. + * @return True if wheel was found, false if not. + */ + bool AssignWheelToAxle(int &_out_axle_wheel, node_t *axis_node_1, node_t *axis_node_2); - float ComputeWingArea( - Ogre::Vector3 const & ref, - Ogre::Vector3 const & x, - Ogre::Vector3 const & y, - Ogre::Vector3 const & aref - ); + float ComputeWingArea(Ogre::Vector3 const &ref, Ogre::Vector3 const &x, Ogre::Vector3 const &y, Ogre::Vector3 const &aref); /** - * Adds a node to the rig. - * @return First: node index, second: True if the node was inserted, false if duplicate. - */ - std::pair AddNode(RigDef::Node::Id & id); + * Adds a node to the rig. + * @return First: node index, second: True if the node was inserted, false if duplicate. + */ + std::pair AddNode(RigDef::Node::Id &id); /** - * Adds a message to internal log. - */ - void AddMessage(Message::Type type, Ogre::String const & text); + * Adds a message to internal log. + */ + void AddMessage(Message::Type type, Ogre::String const &text); - void AddExhaust( - unsigned int emitter_node_idx, - unsigned int direction_node_idx - ); + void AddExhaust(unsigned int emitter_node_idx, unsigned int direction_node_idx); /** - * Finds existing node by Node::Ref - * @return First: Index of existing node; Second: true if node was found. - */ - std::pair GetNodeIndex(RigDef::Node::Ref const & node_ref, bool quiet = false); + * Finds existing node by Node::Ref + * @return First: Index of existing node; Second: true if node was found. + */ + std::pair GetNodeIndex(RigDef::Node::Ref const &node_ref, bool quiet = false); /** - * Finds existing node by Node::Ref - * @return Pointer to node or nullptr if not found. - */ - node_t* GetNodePointer(RigDef::Node::Ref const & node_ref); + * Finds existing node by Node::Ref + * @return Pointer to node or nullptr if not found. + */ + node_t *GetNodePointer(RigDef::Node::Ref const &node_ref); /** - * Finds existing node by Node::Ref - * @return Pointer to node - * @throws Exception If the node isn't found. - */ - node_t* GetNodePointerOrThrow(RigDef::Node::Ref const & node_ref); + * Finds existing node by Node::Ref + * @return Pointer to node + * @throws Exception If the node isn't found. + */ + node_t *GetNodePointerOrThrow(RigDef::Node::Ref const &node_ref); /** - * Finds existing node by Node::Ref; throws an exception if the node doesn't exist. - * @return Reference to existing node. - * @throws Exception If the node isn't found. - */ - node_t & GetNodeOrThrow(RigDef::Node::Ref const & node_ref); + * Finds existing node by Node::Ref; throws an exception if the node doesn't exist. + * @return Reference to existing node. + * @throws Exception If the node isn't found. + */ + node_t &GetNodeOrThrow(RigDef::Node::Ref const &node_ref); /** - * Finds existing pointer by Node::Id - * @return Ref. to node. - */ - node_t & GetNode(RigDef::Node::Ref & node_ref) + * Finds existing pointer by Node::Id + * @return Ref. to node. + */ + node_t &GetNode(RigDef::Node::Ref &node_ref) { - node_t * node = GetNodePointer(node_ref); - if (node == nullptr) - { - throw Exception(std::string("Failed to retrieve node from reference: ") + node_ref.ToString()); - } - return * node; + node_t *node = GetNodePointer(node_ref); + if (node == nullptr) { throw Exception(std::string("Failed to retrieve node from reference: ") + node_ref.ToString()); } + return *node; } /** - * Finds existing node by index. - * @return Pointer to node or nullptr if not found. - */ - node_t & GetNode(unsigned int node_index); + * Finds existing node by index. + * @return Pointer to node or nullptr if not found. + */ + node_t &GetNode(unsigned int node_index); /** - * Sets up defaults & position of a node. - */ - void InitNode(node_t & node, Ogre::Vector3 const & position); + * Sets up defaults & position of a node. + */ + void InitNode(node_t &node, Ogre::Vector3 const &position); /** - * Sets up defaults & position of a node. - */ - void InitNode(unsigned int node_index, Ogre::Vector3 const & position); + * Sets up defaults & position of a node. + */ + void InitNode(unsigned int node_index, Ogre::Vector3 const &position); /** - * Sets up defaults & position of a node. - */ - void InitNode( - node_t & node, - Ogre::Vector3 const & position, - std::shared_ptr node_defaults - ); + * Sets up defaults & position of a node. + */ + void InitNode(node_t &node, Ogre::Vector3 const &position, std::shared_ptr node_defaults); /** - * Setter. - */ + * Setter. + */ void SetCurrentKeyword(RigDef::File::Keyword keyword) { m_current_keyword = keyword; } - beam_t & GetBeam(unsigned int index); + beam_t &GetBeam(unsigned int index); /** - * Parses list of node-ranges into list of individual nodes. - * @return False if some nodes could not be found and thus the lookup wasn't completed. - */ - bool CollectNodesFromRanges( - std::vector & node_ranges, - std::vector & out_node_indices - ); + * Parses list of node-ranges into list of individual nodes. + * @return False if some nodes could not be found and thus the lookup wasn't completed. + */ + bool CollectNodesFromRanges(std::vector &node_ranges, std::vector &out_node_indices); /** - * Gets a free node slot; checks limits, sets it's array position and updates 'free_node' index. - * @return A reference to node slot. - */ - node_t & GetFreeNode(); + * Gets a free node slot; checks limits, sets it's array position and updates 'free_node' index. + * @return A reference to node slot. + */ + node_t &GetFreeNode(); /** - * Gets a free beam slot; checks limits, sets it's array position and updates 'free_beam' index. - * @return A reference to beam slot. - */ - beam_t & GetFreeBeam(); + * Gets a free beam slot; checks limits, sets it's array position and updates 'free_beam' index. + * @return A reference to beam slot. + */ + beam_t &GetFreeBeam(); /** - * Gets a free beam slot; Sets up defaults & position of a node. - * @return A reference to node slot. - */ - node_t & GetAndInitFreeNode(Ogre::Vector3 const & position); + * Gets a free beam slot; Sets up defaults & position of a node. + * @return A reference to node slot. + */ + node_t &GetAndInitFreeNode(Ogre::Vector3 const &position); /** - * Gets a free beam slot; checks limits, sets it's array position and updates 'rig_t::free_beam' index. - * @return A reference to beam slot. - */ - beam_t & GetAndInitFreeBeam(node_t & node_1, node_t & node_2); + * Gets a free beam slot; checks limits, sets it's array position and updates 'rig_t::free_beam' index. + * @return A reference to beam slot. + */ + beam_t &GetAndInitFreeBeam(node_t &node_1, node_t &node_2); - shock_t & GetFreeShock(); + shock_t &GetFreeShock(); /** - * Sets up nodes & length of a beam. - */ - void InitBeam(beam_t & beam, node_t *node_1, node_t *node_2); + * Sets up nodes & length of a beam. + */ + void InitBeam(beam_t &beam, node_t *node_1, node_t *node_2); - void CalculateBeamLength(beam_t & beam); + void CalculateBeamLength(beam_t &beam); - void SetBeamStrength(beam_t & beam, float strength); + void SetBeamStrength(beam_t &beam, float strength); - void SetBeamSpring(beam_t & beam, float spring); + void SetBeamSpring(beam_t &beam, float spring); - void SetBeamDamping(beam_t & beam, float damping); + void SetBeamDamping(beam_t &beam, float damping); beam_t *FindBeamInRig(unsigned int node_a, unsigned int node_b); - void SetBeamDeformationThreshold(beam_t & beam, std::shared_ptr beam_defaults); + void SetBeamDeformationThreshold(beam_t &beam, std::shared_ptr beam_defaults); void UpdateCollcabContacterNodes(); wheel_t::BrakeCombo TranslateBrakingDef(RigDef::Wheels::Braking def); /** - * Checks a section only appears in one module and reports a warning if not. - */ - void CheckSectionSingleModule( - Ogre::String const & section_name, - std::list> & found_items - ); + * Checks a section only appears in one module and reports a warning if not. + */ + void CheckSectionSingleModule(Ogre::String const & section_name, + std::list> &found_items); /** - * Creates beam pre-configured for use as rim with section 'wheels2'. - */ - unsigned int AddWheelRimBeam(RigDef::Wheel2 & wheel_2_def, node_t *node_1, node_t *node_2); + * Creates beam pre-configured for use as rim with section 'wheels2'. + */ + unsigned int AddWheelRimBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2); /** - * Creates beam pre-configured for use as tyre with section 'wheels2'. - */ - unsigned int AddTyreBeam(RigDef::Wheel2 & wheel_2_def, node_t *node_1, node_t *node_2); + * Creates beam pre-configured for use as tyre with section 'wheels2'. + */ + unsigned int AddTyreBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2); /** - * Creates beam partially configured for use with section 'wheels2'. - */ - unsigned int _SectionWheels2AddBeam(RigDef::Wheel2 & wheel_2_def, node_t *node_1, node_t *node_2); + * Creates beam partially configured for use with section 'wheels2'. + */ + unsigned int _SectionWheels2AddBeam(RigDef::Wheel2 &wheel_2_def, node_t *node_1, node_t *node_2); /** - * Builds complete wheel visuals (sections 'wheels', 'wheels2'). - * @param rim_ratio Percentual size of the rim. - */ - void CreateWheelVisuals( - unsigned int wheel_index, - unsigned int node_base_index, - unsigned int def_num_rays, - Ogre::String const & rim_material_name, - Ogre::String const & band_material_name, - bool separate_rim, - float rim_ratio = 1.f - ); + * Builds complete wheel visuals (sections 'wheels', 'wheels2'). + * @param rim_ratio Percentual size of the rim. + */ + void CreateWheelVisuals(unsigned int wheel_index, unsigned int node_base_index, unsigned int def_num_rays, + Ogre::String const &rim_material_name, Ogre::String const &band_material_name, bool separate_rim, + float rim_ratio = 1.f); void CreateWheelSkidmarks(unsigned int wheel_index); /** - * Performs full material setup for a new entity. - * RULE: Each actor must have it's own material instances (a lookup table is kept for OrigName->CustomName) - * - * Setup routine: - * - * 1. If "SimpleMaterials" (plain color surfaces denoting component type) are enabled in config file, - * material is generated (not saved to lookup table) and processing ends. - * 2. If the material name is 'mirror', it's a special prop - rear view mirror. - * material is generated, added to lookup table under generated name (special case) and processing ends. - * 3. If the material is a 'videocamera' of any subtype, material is created, added to lookup table and processing ends. - * 4 'materialflarebindngs' are resolved -> binding is persisted in lookup table. - * 5 SkinZIP _material replacements_ are queried. If match is found, it's added to lookup table and processing ends. - * 6. ManagedMaterials are queried. If match is found, it's added to lookup table and processing ends. - * 7. Orig. material is cloned to create substitute. - * 8. SkinZIP _texture replacements_ are queried. If match is found, substitute material is updated. - * 9. Material is added to lookup table, processing ends. - */ - void SetupNewEntity(Ogre::Entity* e, Ogre::ColourValue simple_color); + * Performs full material setup for a new entity. + * RULE: Each actor must have it's own material instances (a lookup table is kept for OrigName->CustomName) + * + * Setup routine: + * + * 1. If "SimpleMaterials" (plain color surfaces denoting component type) are enabled in config file, + * material is generated (not saved to lookup table) and processing ends. + * 2. If the material name is 'mirror', it's a special prop - rear view mirror. + * material is generated, added to lookup table under generated name (special case) and processing ends. + * 3. If the material is a 'videocamera' of any subtype, material is created, added to lookup table and processing ends. + * 4 'materialflarebindngs' are resolved -> binding is persisted in lookup table. + * 5 SkinZIP _material replacements_ are queried. If match is found, it's added to lookup table and processing ends. + * 6. ManagedMaterials are queried. If match is found, it's added to lookup table and processing ends. + * 7. Orig. material is cloned to create substitute. + * 8. SkinZIP _texture replacements_ are queried. If match is found, substitute material is updated. + * 9. Material is added to lookup table, processing ends. + */ + void SetupNewEntity(Ogre::Entity *e, Ogre::ColourValue simple_color); void CreateGfxActor(); /** - * Factory of GfxActor; invoke after all gfx setup was done. - */ + * Factory of GfxActor; invoke after all gfx setup was done. + */ void FinalizeGfxSetup(); /** - * Validator for the rotator reference structure - */ + * Validator for the rotator reference structure + */ void ValidateRotator(int id, int axis1, int axis2, int *nodes1, int *nodes2); /** - * Helper for 'SetupNewEntity()' - see it's doc. - */ + * Helper for 'SetupNewEntity()' - see it's doc. + */ Ogre::MaterialPtr FindOrCreateCustomizedMaterial(std::string orig_name); Ogre::MaterialPtr CreateSimpleMaterial(Ogre::ColourValue color); - Ogre::ParticleSystem* CreateParticleSystem(std::string const & name, std::string const & template_name); + Ogre::ParticleSystem *CreateParticleSystem(std::string const &name, std::string const &template_name); - RigDef::MaterialFlareBinding* FindFlareBindingForMaterial(std::string const & material_name); ///< Returns NULL if none found + RigDef::MaterialFlareBinding *FindFlareBindingForMaterial(std::string const &material_name); ///< Returns NULL if none found - RigDef::VideoCamera* FindVideoCameraByMaterial(std::string const & material_name); ///< Returns NULL if none found + RigDef::VideoCamera *FindVideoCameraByMaterial(std::string const &material_name); ///< Returns NULL if none found - void CreateVideoCamera(RigDef::VideoCamera* def); - void CreateMirrorPropVideoCam(Ogre::MaterialPtr custom_mat, CustomMaterial::MirrorPropType type, Ogre::SceneNode* prop_scenenode); + void CreateVideoCamera(RigDef::VideoCamera *def); + void CreateMirrorPropVideoCam(Ogre::MaterialPtr custom_mat, CustomMaterial::MirrorPropType type, + Ogre::SceneNode *prop_scenenode); /** - * Creates name containing actor ID token, i.e. "Object_1@Actor_2" - */ - std::string ComposeName(const char* base, int number); + * Creates name containing actor ID token, i.e. "Object_1@Actor_2" + */ + std::string ComposeName(const char *base, int number); /** - * Sets up wheel and builds nodes for sections 'wheels', 'meshwheels' and 'meshwheels2'. - * @param wheel_width Width of the wheel (used in section 'wheels'). Use negative value to calculate width from axis beam. - * @return Wheel index. - */ - unsigned int BuildWheelObjectAndNodes( - unsigned int num_rays, - node_t *axis_node_1, - node_t *axis_node_2, - node_t *reference_arm_node, - unsigned int reserve_nodes, - unsigned int reserve_beams, - float wheel_radius, - RigDef::Wheels::Propulsion propulsion, - RigDef::Wheels::Braking braking, - std::shared_ptr node_defaults, - float wheel_mass, - float wheel_width = -1.f - ); + * Sets up wheel and builds nodes for sections 'wheels', 'meshwheels' and 'meshwheels2'. + * @param wheel_width Width of the wheel (used in section 'wheels'). Use negative value to calculate width from axis beam. + * @return Wheel index. + */ + unsigned int BuildWheelObjectAndNodes(unsigned int num_rays, node_t *axis_node_1, node_t *axis_node_2, + node_t *reference_arm_node, unsigned int reserve_nodes, unsigned int reserve_beams, + float wheel_radius, RigDef::Wheels::Propulsion propulsion, + RigDef::Wheels::Braking braking, std::shared_ptr node_defaults, + float wheel_mass, float wheel_width = -1.f); /** - * Adds beams to wheels from 'wheels', 'meshwheels' - */ - void BuildWheelBeams( - unsigned int num_rays, - unsigned int base_node_index, - node_t *axis_node_1, - node_t *axis_node_2, - float tyre_spring, - float tyre_damping, - float rim_spring, - float rim_damping, - std::shared_ptr beam_defaults, - RigDef::Node::Ref const & rigidity_node_id, - float max_extension = 0.f - ); + * Adds beams to wheels from 'wheels', 'meshwheels' + */ + void BuildWheelBeams(unsigned int num_rays, unsigned int base_node_index, node_t *axis_node_1, node_t *axis_node_2, + float tyre_spring, float tyre_damping, float rim_spring, float rim_damping, + std::shared_ptr beam_defaults, RigDef::Node::Ref const &rigidity_node_id, + float max_extension = 0.f); /** - * Creates beam for wheels 'wheels', 'meshwheels', 'meshwheels2' - */ - unsigned int AddWheelBeam( - node_t *node_1, - node_t *node_2, - float spring, - float damping, - std::shared_ptr beam_defaults, - float max_contraction = -1.f, - float max_extension = -1.f, - int type = BEAM_NORMAL /* Anonymous enum in BeamData.h */ + * Creates beam for wheels 'wheels', 'meshwheels', 'meshwheels2' + */ + unsigned int AddWheelBeam(node_t *node_1, node_t *node_2, float spring, float damping, + std::shared_ptr beam_defaults, float max_contraction = -1.f, + float max_extension = -1.f, int type = BEAM_NORMAL /* Anonymous enum in BeamData.h */ ); /** - * Builds wheel visuals (sections 'meshwheels', 'meshwheels2'). - */ - void BuildMeshWheelVisuals( - unsigned int wheel_index, - unsigned int base_node_index, - unsigned int axis_node_1_index, - unsigned int axis_node_2_index, - unsigned int num_rays, - Ogre::String mesh_name, - Ogre::String material_name, - float rim_radius, - bool rim_reverse - ); + * Builds wheel visuals (sections 'meshwheels', 'meshwheels2'). + */ + void BuildMeshWheelVisuals(unsigned int wheel_index, unsigned int base_node_index, unsigned int axis_node_1_index, + unsigned int axis_node_2_index, unsigned int num_rays, Ogre::String mesh_name, + Ogre::String material_name, float rim_radius, bool rim_reverse); /** - * From SerializedRig::wash_calculator() - */ + * From SerializedRig::wash_calculator() + */ void WashCalculator(); - void FetchAxisNodes( - node_t* & axis_node_1, - node_t* & axis_node_2, - RigDef::Node::Ref const & axis_node_1_id, - RigDef::Node::Ref const & axis_node_2_id - ); + void FetchAxisNodes(node_t *&axis_node_1, node_t *&axis_node_2, RigDef::Node::Ref const &axis_node_1_id, + RigDef::Node::Ref const &axis_node_2_id); - void _ProcessKeyInertia( - RigDef::Inertia & inertia, - RigDef::Inertia & inertia_defaults, - RoR::CmdKeyInertia& contract_key, - RoR::CmdKeyInertia& extend_key - ); + void _ProcessKeyInertia(RigDef::Inertia &inertia, RigDef::Inertia &inertia_defaults, RoR::CmdKeyInertia &contract_key, + RoR::CmdKeyInertia &extend_key); - /** - * For specified nodes - */ - void AdjustNodeBuoyancy(node_t & node, RigDef::Node & node_def, std::shared_ptr defaults); + /** + * For specified nodes + */ + void AdjustNodeBuoyancy(node_t &node, RigDef::Node &node_def, std::shared_ptr defaults); - /** - * For generated nodes - */ - void AdjustNodeBuoyancy(node_t & node, std::shared_ptr defaults); + /** + * For generated nodes + */ + void AdjustNodeBuoyancy(node_t &node, std::shared_ptr defaults); /** - * Ported from SerializedRig::loadTruck() [v0.4.0.7] - */ + * Ported from SerializedRig::loadTruck() [v0.4.0.7] + */ void FinalizeRig(); /** - * Ported from SerializedRig::SerializedRig() [v0.4.0.7] - */ + * Ported from SerializedRig::SerializedRig() [v0.4.0.7] + */ void InitializeRig(); - void CalcMemoryRequirements(ActorMemoryRequirements& req, RigDef::File::Module* module_def); + void CalcMemoryRequirements(ActorMemoryRequirements &req, RigDef::File::Module *module_def); void HandleException(); @@ -1072,40 +1000,41 @@ class ActorSpawner int m_messages_num_other; // Spawn - Actor* m_actor; //!< The output actor. - Ogre::Vector3 m_spawn_position; - bool m_apply_simple_materials; - std::string m_cab_material_name; ///< Original name defined in truckfile/globals. - std::string m_custom_resource_group; - float m_wing_area; - int m_airplane_left_light; - int m_airplane_right_light; - RoR::FlexFactory m_flex_factory; - Ogre::MaterialPtr m_placeholder_managedmat; - Ogre::SceneNode* m_particles_parent_scenenode; - Ogre::MaterialPtr m_cab_trans_material; - Ogre::MaterialPtr m_simple_material_base; - RoR::Renderdash* m_oldstyle_renderdash; - float m_fuse_z_min; - float m_fuse_z_max; - float m_fuse_y_min; - float m_fuse_y_max; - bool m_generate_wing_position_lights; - int m_first_wing_index; - Ogre::SceneNode* m_curr_mirror_prop_scenenode; - std::vector m_props; - int m_driverseat_prop_index; - std::vector m_oldstyle_cab_texcoords; - std::vector m_oldstyle_cab_submeshes; - ActorMemoryRequirements m_memory_requirements; - std::vector m_gfx_nodes; - CustomMaterial::MirrorPropType m_curr_mirror_prop_type; - std::shared_ptr m_file; //!< The parsed input file. - std::map m_named_nodes; - std::map m_material_substitutions; //!< Maps original material names (shared) to their actor-specific substitutes; There's 1 substitute per 1 material, regardless of user count. - std::vector m_beam_visuals_queue; //!< We want to spawn visuals asynchronously in the future - std::vector m_wheel_visuals_queue; //!< We want to spawn visuals asynchronously in the future - std::map m_managed_materials; - std::list> m_selected_modules; - + Actor * m_actor; //!< The output actor. + Ogre::Vector3 m_spawn_position; + bool m_apply_simple_materials; + std::string m_cab_material_name; ///< Original name defined in truckfile/globals. + std::string m_custom_resource_group; + float m_wing_area; + int m_airplane_left_light; + int m_airplane_right_light; + RoR::FlexFactory m_flex_factory; + Ogre::MaterialPtr m_placeholder_managedmat; + Ogre::SceneNode * m_particles_parent_scenenode; + Ogre::MaterialPtr m_cab_trans_material; + Ogre::MaterialPtr m_simple_material_base; + RoR::Renderdash * m_oldstyle_renderdash; + float m_fuse_z_min; + float m_fuse_z_max; + float m_fuse_y_min; + float m_fuse_y_max; + bool m_generate_wing_position_lights; + int m_first_wing_index; + Ogre::SceneNode * m_curr_mirror_prop_scenenode; + std::vector m_props; + int m_driverseat_prop_index; + std::vector m_oldstyle_cab_texcoords; + std::vector m_oldstyle_cab_submeshes; + ActorMemoryRequirements m_memory_requirements; + std::vector m_gfx_nodes; + CustomMaterial::MirrorPropType m_curr_mirror_prop_type; + std::shared_ptr m_file; //!< The parsed input file. + std::map m_named_nodes; + std::map + m_material_substitutions; //!< Maps original material names (shared) to their actor-specific substitutes; There's 1 + //!< substitute per 1 material, regardless of user count. + std::vector m_beam_visuals_queue; //!< We want to spawn visuals asynchronously in the future + std::vector m_wheel_visuals_queue; //!< We want to spawn visuals asynchronously in the future + std::map m_managed_materials; + std::list> m_selected_modules; }; diff --git a/source/main/physics/RigSpawner_ProcessControl.cpp b/source/main/physics/RigSpawner_ProcessControl.cpp index 503cd96f4f..f0fe902796 100644 --- a/source/main/physics/RigSpawner_ProcessControl.cpp +++ b/source/main/physics/RigSpawner_ProcessControl.cpp @@ -26,49 +26,50 @@ @date 12/2013 */ -#include "RigSpawner.h" - #include "Beam.h" #include "Renderdash.h" +#include "RigSpawner.h" -#define PROCESS_SECTION_IN_ANY_MODULE(_KEYWORD_, _FIELD_, _FUNCTION_) \ -{ \ - this->SetCurrentKeyword(_KEYWORD_); \ - for (auto& m: m_selected_modules) \ - { \ - if (m->_FIELD_ != nullptr) \ - { \ - try { \ - _FUNCTION_(*(m->_FIELD_)); \ - } \ - catch (...) \ - { \ - this->HandleException(); \ - } \ - break; \ - } \ - } \ - this->SetCurrentKeyword(RigDef::File::KEYWORD_INVALID); \ -} +#define PROCESS_SECTION_IN_ANY_MODULE(_KEYWORD_, _FIELD_, _FUNCTION_) \ + { \ + this->SetCurrentKeyword(_KEYWORD_); \ + for (auto &m : m_selected_modules) \ + { \ + if (m->_FIELD_ != nullptr) \ + { \ + try \ + { \ + _FUNCTION_(*(m->_FIELD_)); \ + } \ + catch (...) \ + { \ + this->HandleException(); \ + } \ + break; \ + } \ + } \ + this->SetCurrentKeyword(RigDef::File::KEYWORD_INVALID); \ + } -#define PROCESS_SECTION_IN_ALL_MODULES(_KEYWORD_, _FIELD_, _FUNCTION_) \ -{ \ - this->SetCurrentKeyword(_KEYWORD_); \ - for (auto& m: m_selected_modules) \ - { \ - for (auto& entry: m->_FIELD_) \ - { \ - try { \ - _FUNCTION_(entry); \ - } \ - catch (...) \ - { \ - this->HandleException(); \ - } \ - } \ - } \ - this->SetCurrentKeyword(RigDef::File::KEYWORD_INVALID); \ -} +#define PROCESS_SECTION_IN_ALL_MODULES(_KEYWORD_, _FIELD_, _FUNCTION_) \ + { \ + this->SetCurrentKeyword(_KEYWORD_); \ + for (auto &m : m_selected_modules) \ + { \ + for (auto &entry : m->_FIELD_) \ + { \ + try \ + { \ + _FUNCTION_(entry); \ + } \ + catch (...) \ + { \ + this->HandleException(); \ + } \ + } \ + } \ + this->SetCurrentKeyword(RigDef::File::KEYWORD_INVALID); \ + } Actor *ActorSpawner::SpawnActor() { @@ -81,21 +82,18 @@ Actor *ActorSpawner::SpawnActor() m_actor->ar_filehash = m_file->hash; // Flags in root module - m_actor->ar_forward_commands = m_file->forward_commands; - m_actor->ar_import_commands = m_file->import_commands; - m_actor->ar_rescuer_flag = m_file->rescuer; - m_actor->m_disable_default_sounds = m_file->disable_default_sounds; - m_actor->ar_hide_in_actor_list = m_file->hide_in_chooser; - m_actor->ar_collision_range = m_file->collision_range; + m_actor->ar_forward_commands = m_file->forward_commands; + m_actor->ar_import_commands = m_file->import_commands; + m_actor->ar_rescuer_flag = m_file->rescuer; + m_actor->m_disable_default_sounds = m_file->disable_default_sounds; + m_actor->ar_hide_in_actor_list = m_file->hide_in_chooser; + m_actor->ar_collision_range = m_file->collision_range; // Section 'authors' in root module ProcessAuthors(); // Section 'guid' in root module: unused for gameplay - if (m_file->guid.empty()) - { - this->AddMessage(Message::TYPE_WARNING, "vehicle uses no GUID, skinning will be impossible"); - } + if (m_file->guid.empty()) { this->AddMessage(Message::TYPE_WARNING, "vehicle uses no GUID, skinning will be impossible"); } // Section 'description' m_actor->description.assign(m_file->description.begin(), m_file->description.end()); @@ -136,9 +134,7 @@ Actor *ActorSpawner::SpawnActor() // Old-format exhaust (defined by flags 'x/y' in section 'nodes', one per vehicle) if (m_actor->ar_exhaust_pos_node != 0 && m_actor->ar_exhaust_dir_node != 0) - { - AddExhaust(m_actor->ar_exhaust_pos_node, m_actor->ar_exhaust_dir_node); - } + { AddExhaust(m_actor->ar_exhaust_pos_node, m_actor->ar_exhaust_dir_node); } // ---------------------------- Node generating sections ---------------------------- @@ -154,9 +150,9 @@ Actor *ActorSpawner::SpawnActor() PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_WHEELS2, wheels_2, ProcessWheel2); // Sections 'meshwheels' and 'meshwheels2' - for (auto& m : m_selected_modules) + for (auto &m : m_selected_modules) { - for (auto& def : m->mesh_wheels) + for (auto &def : m->mesh_wheels) { if (def._is_meshwheel2) { @@ -212,7 +208,7 @@ Actor *ActorSpawner::SpawnActor() PROCESS_SECTION_IN_ANY_MODULE(RigDef::File::KEYWORD_ANTI_LOCK_BRAKES, anti_lock_brakes, ProcessAntiLockBrakes); // Section 'SlopeBrake' in any module (feature removed). - + // Sections 'flares' and 'flares2' PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_FLARES2, flares_2, ProcessFlare2); @@ -235,7 +231,7 @@ Actor *ActorSpawner::SpawnActor() PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_CAMERAS, cameras, ProcessCamera); // Section 'hooks' - PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_HOOKS, hooks, ProcessHook); + PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_HOOKS, hooks, ProcessHook); // Section 'ties' PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_TIES, ties, ProcessTie); @@ -254,10 +250,12 @@ Actor *ActorSpawner::SpawnActor() // Create the built-in "renderdash" material for use in meshes. // Must be done before 'props' are processed because those traditionally use it. - // Must be always created, there is no mechanism to declare the need for it. It can be acessed from any mesh, not only dashboard-prop. Example content: https://github.com/RigsOfRods/rigs-of-rods/files/3044343/45fc291a9d2aa5faaa36cca6df9571cd6d1f1869_Actros_8x8-englisch.zip + // Must be always created, there is no mechanism to declare the need for it. It can be acessed from any mesh, not only + // dashboard-prop. Example content: + // https://github.com/RigsOfRods/rigs-of-rods/files/3044343/45fc291a9d2aa5faaa36cca6df9571cd6d1f1869_Actros_8x8-englisch.zip // TODO: Move setup to GfxActor - m_oldstyle_renderdash = new RoR::Renderdash( - m_custom_resource_group, this->ComposeName("RenderdashTex", 0), this->ComposeName("RenderdashCam", 0)); + m_oldstyle_renderdash = new RoR::Renderdash(m_custom_resource_group, this->ComposeName("RenderdashTex", 0), + this->ComposeName("RenderdashCam", 0)); // Section 'props' PROCESS_SECTION_IN_ALL_MODULES(RigDef::File::KEYWORD_PROPS, props, ProcessProp); @@ -288,9 +286,9 @@ Actor *ActorSpawner::SpawnActor() // Section 'speedlimiter' in any module. this->SetCurrentKeyword(RigDef::File::KEYWORD_SPEEDLIMITER); - for (auto& m : m_selected_modules) + for (auto &m : m_selected_modules) { - m_actor->sl_enabled = m->speed_limiter.is_enabled; + m_actor->sl_enabled = m->speed_limiter.is_enabled; m_actor->sl_speed_limit = m->speed_limiter.max_speed; } @@ -344,6 +342,6 @@ Actor *ActorSpawner::SpawnActor() // Pass ownership Actor *rig = m_actor; - m_actor = nullptr; + m_actor = nullptr; return rig; } diff --git a/source/main/physics/Savegame.cpp b/source/main/physics/Savegame.cpp index 38f683dc59..110be4f694 100644 --- a/source/main/physics/Savegame.cpp +++ b/source/main/physics/Savegame.cpp @@ -19,8 +19,6 @@ along with Rigs of Rods. If not, see . */ -#include "RoRPrerequisites.h" - #include "AeroEngine.h" #include "Application.h" #include "Beam.h" @@ -32,17 +30,18 @@ #include "Language.h" #include "PlatformUtils.h" #include "RoRFrameListener.h" +#include "RoRPrerequisites.h" #include "ScrewProp.h" #include "Skidmark.h" #include "SkinManager.h" #include "SkyManager.h" #include "TerrainManager.h" +#include #include #include #include #include -#include #define SAVEGAME_FILE_FORMAT 2 @@ -51,10 +50,7 @@ using namespace RoR; Ogre::String ActorManager::GetQuicksaveFilename(Ogre::String terrain_name) { - if (terrain_name.empty()) - { - terrain_name = App::sim_terrain_name.GetActive(); - } + if (terrain_name.empty()) { terrain_name = App::sim_terrain_name.GetActive(); } String mp = (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) ? "_mp" : ""; @@ -63,13 +59,13 @@ Ogre::String ActorManager::GetQuicksaveFilename(Ogre::String terrain_name) Ogre::String ActorManager::ExtractSceneName(Ogre::String filename) { - std::ifstream ifs(PathCombine(App::sys_savegames_dir.GetActive(), filename)); + std::ifstream ifs(PathCombine(App::sys_savegames_dir.GetActive(), filename)); rapidjson::IStreamWrapper isw(ifs); - rapidjson::Document j_doc; + rapidjson::Document j_doc; j_doc.ParseStream(isw); if (!j_doc.IsObject() || !j_doc.HasMember("format_version") || !j_doc["format_version"].IsNumber() || - !j_doc.HasMember("scene_name") || !j_doc["scene_name"].IsString()) + !j_doc.HasMember("scene_name") || !j_doc["scene_name"].IsString()) return ""; return j_doc["scene_name"].GetString(); @@ -81,9 +77,9 @@ bool ActorManager::LoadScene(Ogre::String filename) String path = PathCombine(App::sys_savegames_dir.GetActive(), filename); RoR::LogFormat("[RoR|Savegame] Reading savegame from file '%s' ...", path.c_str()); - std::ifstream ifs(path); + std::ifstream ifs(path); rapidjson::IStreamWrapper isw(ifs); - rapidjson::Document j_doc; + rapidjson::Document j_doc; j_doc.ParseStream(isw); if (!j_doc.IsObject() || !j_doc.HasMember("format_version") || !j_doc["format_version"].IsNumber()) { @@ -105,8 +101,7 @@ bool ActorManager::LoadScene(Ogre::String filename) if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { - if (filename == "autosave.sav") - return false; + if (filename == "autosave.sav") return false; if (terrain_name != App::sim_terrain_name.GetActive()) { RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Error while loading scene: Terrain mismatch")); @@ -141,10 +136,7 @@ bool ActorManager::LoadScene(Ogre::String filename) #ifdef USE_CAELUM if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) { - if (j_doc.HasMember("daytime")) - { - App::GetSimTerrain()->getSkyManager()->SetTime(j_doc["daytime"].GetDouble()); - } + if (j_doc.HasMember("daytime")) { App::GetSimTerrain()->getSkyManager()->SetTime(j_doc["daytime"].GetDouble()); } } #endif // USE_CAELUM } @@ -152,19 +144,19 @@ bool ActorManager::LoadScene(Ogre::String filename) // Character if (m_savegame_terrain_has_changed) { - auto data = j_doc["player_position"].GetArray(); + auto data = j_doc["player_position"].GetArray(); Vector3 position = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat()); gEnv->player->setPosition(position); gEnv->player->setRotation(Radian(j_doc["player_rotation"].GetFloat())); } // Actors - auto actors_changed = false; - auto player_actor = App::GetSimController()->GetPlayerActor(); - auto prev_player_actor = App::GetSimController()->GetPrevPlayerActor(); - std::vector actors; - std::vector x_actors = GetLocalActors(); - for (rapidjson::Value& j_entry: j_doc["actors"].GetArray()) + auto actors_changed = false; + auto player_actor = App::GetSimController()->GetPlayerActor(); + auto prev_player_actor = App::GetSimController()->GetPrevPlayerActor(); + std::vector actors; + std::vector x_actors = GetLocalActors(); + for (rapidjson::Value &j_entry : j_doc["actors"].GetArray()) { String filename = j_entry["filename"].GetString(); if (!App::GetCacheSystem()->CheckResourceLoaded(filename)) @@ -174,26 +166,20 @@ bool ActorManager::LoadScene(Ogre::String filename) continue; } - CacheEntry* skin = nullptr; - if (j_entry.HasMember("skin")) - { - skin = App::GetCacheSystem()->FetchSkinByName(j_entry["skin"].GetString()); - } + CacheEntry *skin = nullptr; + if (j_entry.HasMember("skin")) { skin = App::GetCacheSystem()->FetchSkinByName(j_entry["skin"].GetString()); } String section_config = j_entry["section_config"].GetString(); - Actor* actor = nullptr; - int index = static_cast(actors.size()); + Actor *actor = nullptr; + int index = static_cast(actors.size()); if (index < x_actors.size()) { if (j_entry["filename"].GetString() != x_actors[index]->ar_filename || - (skin != nullptr && skin->dname != x_actors[index]->m_used_skin_entry->dname) || - section_config != x_actors[index]->GetSectionConfig()) + (skin != nullptr && skin->dname != x_actors[index]->m_used_skin_entry->dname) || + section_config != x_actors[index]->GetSectionConfig()) { - if (x_actors[index] == player_actor) - { - App::GetSimController()->ChangePlayerActor(nullptr); - } + if (x_actors[index] == player_actor) { App::GetSimController()->ChangePlayerActor(nullptr); } else if (x_actors[index] == prev_player_actor) { App::GetSimController()->SetPrevPlayerActorInternal(nullptr); @@ -218,22 +204,19 @@ bool ActorManager::LoadScene(Ogre::String filename) rq.asr_position.y = preloaded ? j_entry["position"][1].GetFloat() : j_entry["min_height"].GetFloat(); rq.asr_position.z = j_entry["position"][2].GetFloat(); rq.asr_rotation = Quaternion(Degree(270) - Radian(j_entry["rotation"].GetFloat()), Vector3::UNIT_Y); - rq.asr_skin_entry = skin; + rq.asr_skin_entry = skin; rq.asr_config = section_config; rq.asr_origin = preloaded ? ActorSpawnRequest::Origin::TERRN_DEF : ActorSpawnRequest::Origin::SAVEGAME; rq.asr_free_position = preloaded; actor = App::GetSimController()->SpawnActorDirectly(rq); - actors_changed = true; + actors_changed = true; } actors.push_back(actor); } for (size_t index = actors.size(); index < x_actors.size(); index++) { - if (x_actors[index] == player_actor) - { - App::GetSimController()->ChangePlayerActor(nullptr); - } + if (x_actors[index] == player_actor) { App::GetSimController()->ChangePlayerActor(nullptr); } else if (x_actors[index] == prev_player_actor) { App::GetSimController()->SetPrevPlayerActorInternal(nullptr); @@ -245,38 +228,34 @@ bool ActorManager::LoadScene(Ogre::String filename) const int num_actors = static_cast(j_doc["actors"].Size()); for (int index = 0; index < num_actors; index++) { - if (actors[index] == nullptr) - continue; + if (actors[index] == nullptr) continue; - Actor* actor = actors[index]; - rapidjson::Value& j_entry = j_doc["actors"][index]; + Actor * actor = actors[index]; + rapidjson::Value &j_entry = j_doc["actors"][index]; - actor->m_spawn_rotation = j_entry["spawn_rotation"].GetFloat(); - actor->ar_sim_state = static_cast(j_entry["sim_state"].GetInt()); + actor->m_spawn_rotation = j_entry["spawn_rotation"].GetFloat(); + actor->ar_sim_state = static_cast(j_entry["sim_state"].GetInt()); actor->ar_physics_paused = j_entry["physics_paused"].GetBool(); if (j_entry["player_actor"].GetBool()) { if (actors_changed || player_actor != App::GetSimController()->GetPlayerActor()) - { - App::GetSimController()->SetPendingPlayerActor(actor); - } - } else if (j_entry["prev_player_actor"].GetBool()) + { App::GetSimController()->SetPendingPlayerActor(actor); } + } + else if (j_entry["prev_player_actor"].GetBool()) { if (actors_changed || prev_player_actor != App::GetSimController()->GetPrevPlayerActor()) - { - App::GetSimController()->SetPrevPlayerActorInternal(actor); - } + { App::GetSimController()->SetPrevPlayerActorInternal(actor); } } if (actor->ar_engine) { - int gear = j_entry["engine_gear"].GetInt(); - float rpm = j_entry["engine_rpm"].GetFloat(); - int automode = j_entry["engine_auto_mode"].GetInt(); - int autoselect = j_entry["engine_auto_select"].GetInt(); - bool running = j_entry["engine_is_running"].GetBool(); - bool contact = j_entry["engine_has_contact"].GetBool(); + int gear = j_entry["engine_gear"].GetInt(); + float rpm = j_entry["engine_rpm"].GetFloat(); + int automode = j_entry["engine_auto_mode"].GetInt(); + int autoselect = j_entry["engine_auto_select"].GetInt(); + bool running = j_entry["engine_is_running"].GetBool(); + bool contact = j_entry["engine_has_contact"].GetBool(); if (running != actor->ar_engine->IsRunning()) { if (running) @@ -286,32 +265,26 @@ bool ActorManager::LoadScene(Ogre::String filename) } actor->ar_engine->PushNetworkState(rpm, 0.0f, 0.0f, gear, running, contact, automode, autoselect); actor->ar_engine->SetWheelSpin(j_entry["wheel_spin"].GetFloat() * RAD_PER_SEC_TO_RPM); - actor->alb_mode = j_entry["alb_mode"].GetBool(); - actor->tc_mode = j_entry["tc_mode"].GetBool(); - actor->cc_mode = j_entry["cc_mode"].GetBool(); - actor->cc_target_rpm = j_entry["cc_target_rpm"].GetFloat(); + actor->alb_mode = j_entry["alb_mode"].GetBool(); + actor->tc_mode = j_entry["tc_mode"].GetBool(); + actor->cc_mode = j_entry["cc_mode"].GetBool(); + actor->cc_target_rpm = j_entry["cc_target_rpm"].GetFloat(); actor->cc_target_speed = j_entry["cc_target_speed"].GetFloat(); } - actor->ar_hydro_dir_state = j_entry["hydro_dir_state"].GetFloat(); - actor->ar_hydro_aileron_state = j_entry["hydro_aileron_state"].GetFloat(); - actor->ar_hydro_rudder_state = j_entry["hydro_rudder_state"].GetFloat(); - actor->ar_hydro_elevator_state = j_entry["hydro_elevator_state"].GetFloat(); - actor->ar_parking_brake = j_entry["parking_brake"].GetBool(); + actor->ar_hydro_dir_state = j_entry["hydro_dir_state"].GetFloat(); + actor->ar_hydro_aileron_state = j_entry["hydro_aileron_state"].GetFloat(); + actor->ar_hydro_rudder_state = j_entry["hydro_rudder_state"].GetFloat(); + actor->ar_hydro_elevator_state = j_entry["hydro_elevator_state"].GetFloat(); + actor->ar_parking_brake = j_entry["parking_brake"].GetBool(); actor->ar_trailer_parking_brake = j_entry["trailer_parking_brake"].GetBool(); - actor->ar_avg_wheel_speed = j_entry["avg_wheel_speed"].GetFloat(); - actor->ar_wheel_speed = j_entry["wheel_speed"].GetFloat(); - actor->ar_wheel_spin = j_entry["wheel_spin"].GetFloat(); + actor->ar_avg_wheel_speed = j_entry["avg_wheel_speed"].GetFloat(); + actor->ar_wheel_speed = j_entry["wheel_speed"].GetFloat(); + actor->ar_wheel_spin = j_entry["wheel_spin"].GetFloat(); - if (actor->ar_lights != j_entry["lights"].GetInt()) - { - actor->ToggleLights(); - } + if (actor->ar_lights != j_entry["lights"].GetInt()) { actor->ToggleLights(); } actor->m_beacon_light_is_active = j_entry["beacon_light"].GetBool(); - if (actor->m_custom_particles_enabled != j_entry["custom_particles"].GetBool()) - { - actor->ToggleCustomParticles(); - } + if (actor->m_custom_particles_enabled != j_entry["custom_particles"].GetBool()) { actor->ToggleCustomParticles(); } auto flares = j_entry["flares"].GetArray(); for (int i = 0; i < static_cast(actor->ar_flares.size()); i++) @@ -319,10 +292,7 @@ bool ActorManager::LoadScene(Ogre::String filename) actor->ar_flares[i].controltoggle_status = flares[i].GetBool(); } - if (actor->m_buoyance) - { - actor->m_buoyance->sink = j_entry["buoyance_sink"].GetBool(); - } + if (actor->m_buoyance) { actor->m_buoyance->sink = j_entry["buoyance_sink"].GetBool(); } auto aeroengines = j_entry["aeroengines"].GetArray(); for (int i = 0; i < actor->ar_num_aeroengines; i++) @@ -347,10 +317,7 @@ bool ActorManager::LoadScene(Ogre::String filename) for (int i = 0; i < actor->ar_num_wheels; i++) { - if (actor->m_skid_trails[i]) - { - actor->m_skid_trails[i]->reset(); - } + if (actor->m_skid_trails[i]) { actor->m_skid_trails[i]->reset(); } actor->ar_wheels[i].wh_is_detached = j_entry["wheels"][i].GetBool(); } @@ -385,13 +352,13 @@ bool ActorManager::LoadScene(Ogre::String filename) auto commands = j_entry["commands"].GetArray(); for (int i = 0; i < MAX_COMMANDS; i++) { - auto& command_key = actor->ar_command_key[i]; - command_key.commandValue = commands[i][0].GetFloat(); + auto &command_key = actor->ar_command_key[i]; + command_key.commandValue = commands[i][0].GetFloat(); command_key.triggerInputValue = commands[i][1].GetFloat(); - auto command_beams = commands[i][2].GetArray(); + auto command_beams = commands[i][2].GetArray(); for (int j = 0; j < (int)command_key.beams.size(); j++) { - command_key.beams[j].cmb_state->auto_moving_mode = command_beams[j][0].GetInt(); + command_key.beams[j].cmb_state->auto_moving_mode = command_beams[j][0].GetInt(); command_key.beams[j].cmb_state->pressed_center_mode = command_beams[j][1].GetBool(); } } @@ -399,7 +366,7 @@ bool ActorManager::LoadScene(Ogre::String filename) auto nodes = j_entry["nodes"].GetArray(); for (rapidjson::SizeType i = 0; i < nodes.Size(); i++) { - auto data = nodes[i].GetArray(); + auto data = nodes[i].GetArray(); actor->ar_nodes[i].AbsPosition = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat()); actor->ar_nodes[i].RelPosition = actor->ar_nodes[i].AbsPosition - actor->ar_origin; actor->ar_nodes[i].Velocity = Vector3(data[3].GetFloat(), data[4].GetFloat(), data[5].GetFloat()); @@ -409,7 +376,7 @@ bool ActorManager::LoadScene(Ogre::String filename) auto beams = j_entry["beams"].GetArray(); for (rapidjson::SizeType i = 0; i < beams.Size(); i++) { - auto data = beams[i].GetArray(); + auto data = beams[i].GetArray(); actor->ar_beams[i].maxposstress = data[0].GetFloat(); actor->ar_beams[i].maxnegstress = data[1].GetFloat(); actor->ar_beams[i].minmaxposnegstress = data[2].GetFloat(); @@ -420,37 +387,33 @@ bool ActorManager::LoadScene(Ogre::String filename) actor->ar_beams[i].bm_inter_actor = data[7].GetBool(); int locked_actor = data[8].GetInt(); if (locked_actor != -1 && actors[locked_actor] != nullptr) - { - actor->AddInterActorBeam(&actor->ar_beams[i], actor, actors[locked_actor]); - } + { actor->AddInterActorBeam(&actor->ar_beams[i], actor, actors[locked_actor]); } } auto hooks = j_entry["hooks"].GetArray(); for (int i = 0; i < actor->ar_hooks.size(); i++) { - int lock_node = hooks[i]["lock_node"].GetInt(); + int lock_node = hooks[i]["lock_node"].GetInt(); int locked_actor = hooks[i]["locked_actor"].GetInt(); if (lock_node != -1 && locked_actor != -1 && actors[locked_actor] != nullptr) { - actor->ar_hooks[i].hk_locked = hooks[i]["locked"].GetInt(); + actor->ar_hooks[i].hk_locked = hooks[i]["locked"].GetInt(); actor->ar_hooks[i].hk_locked_actor = actors[locked_actor]; - actor->ar_hooks[i].hk_lock_node = &actors[locked_actor]->ar_nodes[lock_node]; + actor->ar_hooks[i].hk_lock_node = &actors[locked_actor]->ar_nodes[lock_node]; if (actor->ar_hooks[i].hk_beam->bm_inter_actor) - { - actor->ar_hooks[i].hk_beam->p2 = actor->ar_hooks[i].hk_lock_node; - } + { actor->ar_hooks[i].hk_beam->p2 = actor->ar_hooks[i].hk_lock_node; } } } auto ropes = j_entry["ropes"].GetArray(); for (int i = 0; i < actor->ar_ropes.size(); i++) { - int ropable = ropes[i]["locked_ropable"].GetInt(); + int ropable = ropes[i]["locked_ropable"].GetInt(); int locked_actor = ropes[i]["locked_actor"].GetInt(); if (ropable != -1 && locked_actor != -1 && actors[locked_actor] != nullptr) { - actor->ar_ropes[i].rp_locked = ropes[i]["locked"].GetInt(); - actor->ar_ropes[i].rp_locked_actor = actors[locked_actor]; + actor->ar_ropes[i].rp_locked = ropes[i]["locked"].GetInt(); + actor->ar_ropes[i].rp_locked_actor = actors[locked_actor]; actor->ar_ropes[i].rp_locked_ropable = &actors[locked_actor]->ar_ropables[ropable]; } } @@ -458,18 +421,16 @@ bool ActorManager::LoadScene(Ogre::String filename) auto ties = j_entry["ties"].GetArray(); for (int i = 0; i < actor->ar_ties.size(); i++) { - int ropable = ties[i]["locked_ropable"].GetInt(); + int ropable = ties[i]["locked_ropable"].GetInt(); int locked_actor = ties[i]["locked_actor"].GetInt(); if (ropable != -1 && locked_actor != -1 && actors[locked_actor] != nullptr) { - actor->ar_ties[i].ti_tied = ties[i]["tied"].GetBool(); - actor->ar_ties[i].ti_tying = ties[i]["tying"].GetBool(); - actor->ar_ties[i].ti_locked_actor = actors[locked_actor]; + actor->ar_ties[i].ti_tied = ties[i]["tied"].GetBool(); + actor->ar_ties[i].ti_tying = ties[i]["tying"].GetBool(); + actor->ar_ties[i].ti_locked_actor = actors[locked_actor]; actor->ar_ties[i].ti_locked_ropable = &actors[locked_actor]->ar_ropables[ropable]; if (actor->ar_ties[i].ti_beam->bm_inter_actor) - { - actor->ar_ties[i].ti_beam->p2 = actor->ar_ties[i].ti_locked_ropable->node; - } + { actor->ar_ties[i].ti_beam->p2 = actor->ar_ties[i].ti_locked_ropable->node; } } } @@ -481,10 +442,7 @@ bool ActorManager::LoadScene(Ogre::String filename) } actor->resetSlideNodes(); - if (actor->m_slidenodes_locked != j_entry["slidenodes_locked"].GetBool()) - { - actor->ToggleSlideNodeLock(); - } + if (actor->m_slidenodes_locked != j_entry["slidenodes_locked"].GetBool()) { actor->ToggleSlideNodeLock(); } actor->UpdateBoundingBoxes(); actor->calculateAveragePosition(); @@ -494,22 +452,18 @@ bool ActorManager::LoadScene(Ogre::String filename) App::sim_load_savegame.SetActive(false); m_savegame_terrain_has_changed = false; - if (filename != "autosave.sav") - { - RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Scene loaded")); - } + if (filename != "autosave.sav") { RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Scene loaded")); } return true; } bool ActorManager::SaveScene(Ogre::String filename) { - std::vector x_actors = GetLocalActors(); + std::vector x_actors = GetLocalActors(); if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { - if (filename == "autosave.sav") - return false; + if (filename == "autosave.sav") return false; if (x_actors.size() > 3) { RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Error while saving scene: Too many vehicles")); @@ -523,7 +477,7 @@ bool ActorManager::SaveScene(Ogre::String filename) // Pretty name String pretty_name = App::GetCacheSystem()->GetPrettyName(App::sim_terrain_name.GetActive()); - String scene_name = StringUtil::format("%s [%d]", pretty_name.c_str(), x_actors.size()); + String scene_name = StringUtil::format("%s [%d]", pretty_name.c_str(), x_actors.size()); j_doc.AddMember("scene_name", rapidjson::StringRef(scene_name.c_str()), j_doc.GetAllocator()); // Terrain @@ -531,9 +485,7 @@ bool ActorManager::SaveScene(Ogre::String filename) #ifdef USE_CAELUM if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) - { - j_doc.AddMember("daytime", App::GetSimTerrain()->getSkyManager()->GetTime(), j_doc.GetAllocator()); - } + { j_doc.AddMember("daytime", App::GetSimTerrain()->getSkyManager()->GetTime(), j_doc.GetAllocator()); } #endif // USE_CAELUM j_doc.AddMember("forced_awake", m_forced_awake, j_doc.GetAllocator()); @@ -552,12 +504,9 @@ bool ActorManager::SaveScene(Ogre::String filename) for (auto actor : m_actors) { vector_index_lookup[actor->ar_vector_index] = -1; - auto search = std::find_if(x_actors.begin(), x_actors.end(), [actor](Actor* b) - { return actor->ar_instance_id == b->ar_instance_id; }); - if (search != x_actors.end()) - { - vector_index_lookup[actor->ar_vector_index] = std::distance(x_actors.begin(), search); - } + auto search = std::find_if(x_actors.begin(), x_actors.end(), + [actor](Actor *b) { return actor->ar_instance_id == b->ar_instance_id; }); + if (search != x_actors.end()) { vector_index_lookup[actor->ar_vector_index] = std::distance(x_actors.begin(), search); } } // Actors @@ -578,13 +527,11 @@ bool ActorManager::SaveScene(Ogre::String filename) j_entry.AddMember("preloaded_with_terrain", actor->isPreloadedWithTerrain(), j_doc.GetAllocator()); j_entry.AddMember("sim_state", static_cast(actor->ar_sim_state), j_doc.GetAllocator()); j_entry.AddMember("physics_paused", actor->ar_physics_paused, j_doc.GetAllocator()); - j_entry.AddMember("player_actor", actor==App::GetSimController()->GetPlayerActor(), j_doc.GetAllocator()); - j_entry.AddMember("prev_player_actor", actor==App::GetSimController()->GetPrevPlayerActor(), j_doc.GetAllocator()); + j_entry.AddMember("player_actor", actor == App::GetSimController()->GetPlayerActor(), j_doc.GetAllocator()); + j_entry.AddMember("prev_player_actor", actor == App::GetSimController()->GetPrevPlayerActor(), j_doc.GetAllocator()); if (actor->m_used_skin_entry) - { - j_entry.AddMember("skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator()); - } + { j_entry.AddMember("skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator()); } j_entry.AddMember("section_config", rapidjson::StringRef(actor->m_section_config.c_str()), j_doc.GetAllocator()); @@ -621,16 +568,13 @@ bool ActorManager::SaveScene(Ogre::String filename) // Flares rapidjson::Value j_flares(rapidjson::kArrayType); - for (const auto& flare : actor->ar_flares) + for (const auto &flare : actor->ar_flares) { j_flares.PushBack(flare.controltoggle_status, j_doc.GetAllocator()); } j_entry.AddMember("flares", j_flares, j_doc.GetAllocator()); - if (actor->m_buoyance) - { - j_entry.AddMember("buoyance_sink", actor->m_buoyance->sink, j_doc.GetAllocator()); - } + if (actor->m_buoyance) { j_entry.AddMember("buoyance_sink", actor->m_buoyance->sink, j_doc.GetAllocator()); } // Turboprops / Turbojets rapidjson::Value j_aeroengines(rapidjson::kArrayType); @@ -709,7 +653,7 @@ bool ActorManager::SaveScene(Ogre::String filename) for (int j = 0; j < (int)actor->ar_command_key[i].beams.size(); j++) { rapidjson::Value j_cmb(rapidjson::kArrayType); - auto& beam = actor->ar_command_key[i].beams[j]; + auto & beam = actor->ar_command_key[i].beams[j]; j_cmb.PushBack(beam.cmb_state->auto_moving_mode, j_doc.GetAllocator()); j_cmb.PushBack(beam.cmb_state->pressed_center_mode, j_doc.GetAllocator()); j_command_beams.PushBack(j_cmb, j_doc.GetAllocator()); @@ -722,11 +666,11 @@ bool ActorManager::SaveScene(Ogre::String filename) // Hooks rapidjson::Value j_hooks(rapidjson::kArrayType); - for (const auto& h : actor->ar_hooks) + for (const auto &h : actor->ar_hooks) { rapidjson::Value j_hook(rapidjson::kObjectType); - int lock_node = h.hk_lock_node ? h.hk_lock_node->pos : -1; - int locked_actor = h.hk_locked_actor ? vector_index_lookup[h.hk_locked_actor->ar_vector_index] : -1; + int lock_node = h.hk_lock_node ? h.hk_lock_node->pos : -1; + int locked_actor = h.hk_locked_actor ? vector_index_lookup[h.hk_locked_actor->ar_vector_index] : -1; j_hook.AddMember("locked", h.hk_locked, j_doc.GetAllocator()); j_hook.AddMember("lock_node", lock_node, j_doc.GetAllocator()); j_hook.AddMember("locked_actor", locked_actor, j_doc.GetAllocator()); @@ -736,11 +680,11 @@ bool ActorManager::SaveScene(Ogre::String filename) // Ropes rapidjson::Value j_ropes(rapidjson::kArrayType); - for (const auto& r : actor->ar_ropes) + for (const auto &r : actor->ar_ropes) { rapidjson::Value j_rope(rapidjson::kObjectType); - int locked_ropable = r.rp_locked_ropable ? r.rp_locked_ropable->pos : -1; - int locked_actor = r.rp_locked_actor ? vector_index_lookup[r.rp_locked_actor->ar_vector_index] : -1; + int locked_ropable = r.rp_locked_ropable ? r.rp_locked_ropable->pos : -1; + int locked_actor = r.rp_locked_actor ? vector_index_lookup[r.rp_locked_actor->ar_vector_index] : -1; j_rope.AddMember("locked", r.rp_locked, j_doc.GetAllocator()); j_rope.AddMember("locked_ropable", locked_ropable, j_doc.GetAllocator()); j_rope.AddMember("locked_actor", locked_actor, j_doc.GetAllocator()); @@ -750,11 +694,11 @@ bool ActorManager::SaveScene(Ogre::String filename) // Ties rapidjson::Value j_ties(rapidjson::kArrayType); - for (const auto& t : actor->ar_ties) + for (const auto &t : actor->ar_ties) { rapidjson::Value j_tie(rapidjson::kObjectType); - int locked_ropable = t.ti_locked_ropable ? t.ti_locked_ropable->pos : -1; - int locked_actor = t.ti_locked_actor ? vector_index_lookup[t.ti_locked_actor->ar_vector_index] : -1; + int locked_ropable = t.ti_locked_ropable ? t.ti_locked_ropable->pos : -1; + int locked_actor = t.ti_locked_actor ? vector_index_lookup[t.ti_locked_actor->ar_vector_index] : -1; j_tie.AddMember("tied", t.ti_tied, j_doc.GetAllocator()); j_tie.AddMember("tying", t.ti_tying, j_doc.GetAllocator()); j_tie.AddMember("locked_ropable", locked_ropable, j_doc.GetAllocator()); @@ -765,7 +709,7 @@ bool ActorManager::SaveScene(Ogre::String filename) // Ropables rapidjson::Value j_ropables(rapidjson::kArrayType); - for (const auto& r : actor->ar_ropables) + for (const auto &r : actor->ar_ropables) { rapidjson::Value j_ropable(rapidjson::kObjectType); j_ropable.AddMember("attached_ties", r.attached_ties, j_doc.GetAllocator()); @@ -815,7 +759,7 @@ bool ActorManager::SaveScene(Ogre::String filename) j_beam.PushBack(actor->ar_beams[i].bm_broken, j_doc.GetAllocator()); j_beam.PushBack(actor->ar_beams[i].bm_disabled, j_doc.GetAllocator()); j_beam.PushBack(actor->ar_beams[i].bm_inter_actor, j_doc.GetAllocator()); - Actor* locked_actor = actor->ar_beams[i].bm_locked_actor; + Actor *locked_actor = actor->ar_beams[i].bm_locked_actor; j_beam.PushBack(locked_actor ? vector_index_lookup[locked_actor->ar_vector_index] : -1, j_doc.GetAllocator()); j_beams.PushBack(j_beam, j_doc.GetAllocator()); @@ -830,10 +774,11 @@ bool ActorManager::SaveScene(Ogre::String filename) String path = PathCombine(App::sys_savegames_dir.GetActive(), filename); RoR::LogFormat("[RoR|Savegame] Writing savegame to file '%s' ...", path.c_str()); - std::ofstream ofs(path); + std::ofstream ofs(path); rapidjson::OStreamWrapper j_ofs(ofs); rapidjson::Writer, rapidjson::UTF8<>, rapidjson::CrtAllocator, - rapidjson::kWriteNanAndInfFlag> j_writer(j_ofs); + rapidjson::kWriteNanAndInfFlag> + j_writer(j_ofs); if (!j_doc.Accept(j_writer)) { RoR::LogFormat("[RoR|Savegame] Error writing '%s'", path.c_str()); @@ -841,10 +786,7 @@ bool ActorManager::SaveScene(Ogre::String filename) return false; } - if (filename != "autosave.sav") - { - RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Scene saved")); - } + if (filename != "autosave.sav") { RoR::App::GetGuiManager()->PushNotification("Notice:", _L("Scene saved")); } return true; } diff --git a/source/main/physics/SlideNode.cpp b/source/main/physics/SlideNode.cpp index 16b3424a4f..1117afe437 100644 --- a/source/main/physics/SlideNode.cpp +++ b/source/main/physics/SlideNode.cpp @@ -45,11 +45,11 @@ * @param tp end point of beam being projected * @return point is space from origin */ -Ogre::Vector3 NearestPointOnLine(const Ogre::Vector3& pt1, const Ogre::Vector3& pt2, const Ogre::Vector3& tp) +Ogre::Vector3 NearestPointOnLine(const Ogre::Vector3 &pt1, const Ogre::Vector3 &pt2, const Ogre::Vector3 &tp) { - Ogre::Vector3 a = tp - pt1; - Ogre::Vector3 b = pt2 - pt1; - Ogre::Real len = b.normalise(); + Ogre::Vector3 a = tp - pt1; + Ogre::Vector3 b = pt2 - pt1; + Ogre::Real len = b.normalise(); len = std::max(0.0f, std::min(a.dotProduct(b), len)); @@ -57,61 +57,43 @@ Ogre::Vector3 NearestPointOnLine(const Ogre::Vector3& pt1, const Ogre::Vector3& } // SLIDE NODES IMPLEMENTATION ////////////////////////////////////////////////// -SlideNode::SlideNode(node_t* slidingNode, RailGroup* slidingRail): - - m_sliding_node(slidingNode), - m_sliding_beam(NULL), - m_initial_railgroup(slidingRail), - m_cur_railgroup(m_initial_railgroup), - m_cur_rail_seg(NULL), - m_node_forces_ratio(0.0f), - - m_initial_threshold(0.0f), - m_cur_threshold(0.0f), - m_spring_rate(9000000), - m_break_force(std::numeric_limits::infinity()), // beam won't break - - m_attach_rate(1.0f), - m_attach_distance(0.1f), - sn_attach_foreign(false), - sn_attach_self(false), - sn_slide_broken(false) +SlideNode::SlideNode(node_t *slidingNode, RailGroup *slidingRail) + : + + m_sliding_node(slidingNode), m_sliding_beam(NULL), m_initial_railgroup(slidingRail), m_cur_railgroup(m_initial_railgroup), + m_cur_rail_seg(NULL), m_node_forces_ratio(0.0f), + + m_initial_threshold(0.0f), m_cur_threshold(0.0f), m_spring_rate(9000000), + m_break_force(std::numeric_limits::infinity()), // beam won't break + + m_attach_rate(1.0f), m_attach_distance(0.1f), sn_attach_foreign(false), sn_attach_self(false), sn_slide_broken(false) { // make sure they exist - MYASSERT( m_sliding_node ); + MYASSERT(m_sliding_node); } void SlideNode::UpdateForces(float dt) { // only do calcs if we have a beam to slide on - if (!m_sliding_beam || m_sliding_beam->bm_broken || sn_slide_broken) - { - return; - } + if (!m_sliding_beam || m_sliding_beam->bm_broken || sn_slide_broken) { return; } // the threshold changes when attaching a node to a beam, if it's more than // the initial amount then then we're still attaching. - if (m_cur_threshold > m_initial_threshold) - { - m_cur_threshold -= (m_attach_rate * dt); - } + if (m_cur_threshold > m_initial_threshold) { m_cur_threshold -= (m_attach_rate * dt); } Ogre::Vector3 perpForces = this->CalcCorrectiveForces(); // perpendicular Forces are distributed according to the position along the Beam - if (perpForces.length() > m_break_force) - { - sn_slide_broken = true; - } + if (perpForces.length() > m_break_force) { sn_slide_broken = true; } m_sliding_node->Forces += -perpForces; m_sliding_beam->p1->Forces += perpForces * (1 - m_node_forces_ratio); m_sliding_beam->p2->Forces += perpForces * m_node_forces_ratio; } -RailSegment* RailGroup::FindClosestSegment(const Ogre::Vector3& point) +RailSegment *RailGroup::FindClosestSegment(const Ogre::Vector3 &point) { - float closest_dist_sq = SlideNode::getLenTo(&this->rg_segments[0], point); - size_t closest_seg = 0; + float closest_dist_sq = SlideNode::getLenTo(&this->rg_segments[0], point); + size_t closest_seg = 0; for (size_t i = 1; i < this->rg_segments.size(); ++i) { @@ -119,24 +101,24 @@ RailSegment* RailGroup::FindClosestSegment(const Ogre::Vector3& point) if (dist_sq < closest_dist_sq) { closest_dist_sq = dist_sq; - closest_seg = i; + closest_seg = i; } } return &this->rg_segments[closest_seg]; } -RailSegment* RailSegment::CheckCurSlideSegment(const Ogre::Vector3& point) +RailSegment *RailSegment::CheckCurSlideSegment(const Ogre::Vector3 &point) { - float closest_dist_sq = SlideNode::getLenTo(this, point); - RailSegment* closest_seg = this; + float closest_dist_sq = SlideNode::getLenTo(this, point); + RailSegment *closest_seg = this; if (this->rs_prev != nullptr) { const float dist_sq = SlideNode::getLenTo(this->rs_prev, point); if (dist_sq < closest_dist_sq) { - closest_seg = this->rs_prev; + closest_seg = this->rs_prev; closest_dist_sq = dist_sq; } } @@ -144,10 +126,7 @@ RailSegment* RailSegment::CheckCurSlideSegment(const Ogre::Vector3& point) if (this->rs_next != nullptr) { const float dist_sq = SlideNode::getLenTo(this->rs_next, point); - if (dist_sq < closest_dist_sq) - { - closest_seg = this->rs_next; - } + if (dist_sq < closest_dist_sq) { closest_seg = this->rs_next; } } return closest_seg; @@ -182,14 +161,14 @@ void SlideNode::UpdatePosition() // constrain Value between the two end points const Ogre::Real len = std::max(0.0f, std::min(aDotBUnit, bLen)); - m_ideal_position = m_sliding_beam->p1->AbsPosition + b * len; + m_ideal_position = m_sliding_beam->p1->AbsPosition + b * len; // calculate(cache) the ratio between the the two end points, // if bLen = 0.0f it means the beam is zero length so pick an end point m_node_forces_ratio = (bLen > 0.0f) ? len / bLen : 0.0f; } -const Ogre::Vector3& SlideNode::GetSlideNodePosition() const +const Ogre::Vector3 &SlideNode::GetSlideNodePosition() const { return m_sliding_node->AbsPosition; } @@ -204,49 +183,46 @@ void SlideNode::ResetPositions() } } -Ogre::Real SlideNode::getLenTo(const RailGroup* group, const Ogre::Vector3& point) +Ogre::Real SlideNode::getLenTo(const RailGroup *group, const Ogre::Vector3 &point) { - if (!group) - return std::numeric_limits::infinity(); + if (!group) return std::numeric_limits::infinity(); return getLenTo(&group->rg_segments[0], point); } -Ogre::Real SlideNode::getLenTo(const RailSegment* rail, const Ogre::Vector3& point) +Ogre::Real SlideNode::getLenTo(const RailSegment *rail, const Ogre::Vector3 &point) { - if (!rail) - return std::numeric_limits::infinity(); + if (!rail) return std::numeric_limits::infinity(); return getLenTo(rail->rs_beam, point); } -Ogre::Real SlideNode::getLenTo(const beam_t* beam, const Ogre::Vector3& point) +Ogre::Real SlideNode::getLenTo(const beam_t *beam, const Ogre::Vector3 &point) { - if (!beam) - return std::numeric_limits::infinity(); + if (!beam) return std::numeric_limits::infinity(); return (NearestPointOnLine(beam->p1->AbsPosition, beam->p2->AbsPosition, point) - point).length(); } -Ogre::Real SlideNode::getLenTo(const RailGroup* group) const +Ogre::Real SlideNode::getLenTo(const RailGroup *group) const { return getLenTo(group, m_sliding_node->AbsPosition); } -Ogre::Real SlideNode::getLenTo(const RailSegment* rail) const +Ogre::Real SlideNode::getLenTo(const RailSegment *rail) const { return getLenTo(rail, m_sliding_node->AbsPosition); } -Ogre::Real SlideNode::getLenTo(const beam_t* beam) const +Ogre::Real SlideNode::getLenTo(const beam_t *beam) const { return getLenTo(beam, m_sliding_node->AbsPosition); } Ogre::Vector3 SlideNode::CalcCorrectiveForces() { - Ogre::Vector3 force = (m_ideal_position - m_sliding_node->AbsPosition); - const Ogre::Real beamLen = std::max(0.0f, force.normalise() - m_cur_threshold); + Ogre::Vector3 force = (m_ideal_position - m_sliding_node->AbsPosition); + const Ogre::Real beamLen = std::max(0.0f, force.normalise() - m_cur_threshold); const Ogre::Real forceLen = -m_spring_rate * beamLen; return (force * forceLen); } diff --git a/source/main/physics/SlideNode.h b/source/main/physics/SlideNode.h index a12d3bdf01..37ec672839 100644 --- a/source/main/physics/SlideNode.h +++ b/source/main/physics/SlideNode.h @@ -33,22 +33,26 @@ struct RailSegment //!< A single beam in a chain { - RailSegment(beam_t* beam): rs_prev(nullptr), rs_next(nullptr), rs_beam(beam) {} + RailSegment(beam_t *beam) : rs_prev(nullptr), rs_next(nullptr), rs_beam(beam) + { + } /// Check if the slidenode should skip to a neighbour rail segment - RailSegment* CheckCurSlideSegment(Ogre::Vector3 const& point ); + RailSegment *CheckCurSlideSegment(Ogre::Vector3 const &point); - RailSegment* rs_prev; - RailSegment* rs_next; - beam_t* rs_beam; + RailSegment *rs_prev; + RailSegment *rs_next; + beam_t * rs_beam; }; struct RailGroup //!< A series of RailSegment-s for SlideNode to slide along. Can be closed in a loop. { - RailGroup(): rg_id(-1) {} + RailGroup() : rg_id(-1) + { + } /// Search for closest rail segment (the one with closest node in it) in the entire RailGroup - RailSegment* FindClosestSegment(Ogre::Vector3 const& point ); + RailSegment *FindClosestSegment(Ogre::Vector3 const &point); std::vector rg_segments; int rg_id; //!< Spawn context - matching separately defined rails with slidenodes. @@ -56,10 +60,10 @@ struct RailGroup //!< A series of RailSegment-s for SlideNode to slide along. Ca class SlideNode { -public: + public: /// @param sliding_node valid pointer to the node acting as a slide node /// @param rail initial RailGroup to slide on, or NULL. - SlideNode(node_t* sliding_node, RailGroup* rail); + SlideNode(node_t *sliding_node, RailGroup *rail); /// Returns the node index of the slide node int GetSlideNodeId(); @@ -72,7 +76,7 @@ class SlideNode void UpdatePosition(); /// Sets rail to initially use when spawned or reset - void SetDefaultRail(RailGroup* rail) + void SetDefaultRail(RailGroup *rail) { m_initial_railgroup = m_cur_railgroup = rail; this->ResetPositions(); @@ -89,48 +93,66 @@ class SlideNode this->ResetPositions(); } - void SetCorThreshold(float threshold ) { m_initial_threshold = m_cur_threshold = fabs( threshold ); } //!< Distance from a beam before corrective forces take effect - void SetSpringRate(float rate ) { m_spring_rate = fabs( rate); } //!< Spring force used to calculate corrective forces - void SetBreakForce(float breakRate ) { m_break_force = fabs( breakRate); } //!< Force required to break the Node from the Rail - void SetAttachmentRate(float rate ) { m_attach_rate = fabs( rate); } //!< How long it will take for springs to fully attach to the Rail - void SetAttachmentDistance(float dist ) { m_attach_distance = fabs( dist); } //!< Maximum distance this spring node is allowed to reach out for a Rail - float GetAttachmentDistance() const { return m_attach_distance; } //!< Maximum distance this spring node is allowed to reach out for a Rail + void SetCorThreshold(float threshold) + { + m_initial_threshold = m_cur_threshold = fabs(threshold); + } //!< Distance from a beam before corrective forces take effect + void SetSpringRate(float rate) + { + m_spring_rate = fabs(rate); + } //!< Spring force used to calculate corrective forces + void SetBreakForce(float breakRate) + { + m_break_force = fabs(breakRate); + } //!< Force required to break the Node from the Rail + void SetAttachmentRate(float rate) + { + m_attach_rate = fabs(rate); + } //!< How long it will take for springs to fully attach to the Rail + void SetAttachmentDistance(float dist) + { + m_attach_distance = fabs(dist); + } //!< Maximum distance this spring node is allowed to reach out for a Rail + float GetAttachmentDistance() const + { + return m_attach_distance; + } //!< Maximum distance this spring node is allowed to reach out for a Rail - bool sn_attach_self:1; //!< Attach/detach to rails on the current vehicle only - bool sn_attach_foreign:1; //!< Attach/detach to rails only on other vehicles - bool sn_slide_broken:1; //!< The slidenode was pulled away from the rail + bool sn_attach_self : 1; //!< Attach/detach to rails on the current vehicle only + bool sn_attach_foreign : 1; //!< Attach/detach to rails only on other vehicles + bool sn_slide_broken : 1; //!< The slidenode was pulled away from the rail -private: + private: /// Calculate forces between the ideal and actual position of the sliding node. Ogre::Vector3 CalcCorrectiveForces(); - node_t* m_sliding_node; //!< Pointer to node that is sliding - beam_t* m_sliding_beam; //!< Pointer to current beam sliding on - RailGroup* m_initial_railgroup; //!< Initial Rail group on spawn - RailGroup* m_cur_railgroup; //!< Current Rail group, used for attachments - RailSegment* m_cur_rail_seg; //!< Current rail segment we are sliding on - float m_node_forces_ratio; //!< Ratio of length along the slide beam where the virtual node is "0.0f = p1, 1.0f = p2" - Ogre::Vector3 m_ideal_position; //!< Where the node SHOULD be. (World, m) - float m_initial_threshold; //!< Distance from beam calculating corrective forces (m) - float m_cur_threshold; //!< Distance away from beam before corrective forces begin to act on the node (m) - float m_spring_rate; //!< Spring rate holding node to rail (N/m) - float m_break_force; //!< Force at which Slide Node breaks away from the rail (N) - float m_attach_rate; //!< How fast the cur threshold changes when attaching (i.e. how long it will take for springs to fully attach to the Rail) (m/s) - float m_attach_distance; //!< Maximum distance slide node will attach to a beam (m) - -// Methods //////////////////////////// TO BE SORTED ///////////////////////////////////////// -public: - + node_t * m_sliding_node; //!< Pointer to node that is sliding + beam_t * m_sliding_beam; //!< Pointer to current beam sliding on + RailGroup * m_initial_railgroup; //!< Initial Rail group on spawn + RailGroup * m_cur_railgroup; //!< Current Rail group, used for attachments + RailSegment * m_cur_rail_seg; //!< Current rail segment we are sliding on + float m_node_forces_ratio; //!< Ratio of length along the slide beam where the virtual node is "0.0f = p1, 1.0f = p2" + Ogre::Vector3 m_ideal_position; //!< Where the node SHOULD be. (World, m) + float m_initial_threshold; //!< Distance from beam calculating corrective forces (m) + float m_cur_threshold; //!< Distance away from beam before corrective forces begin to act on the node (m) + float m_spring_rate; //!< Spring rate holding node to rail (N/m) + float m_break_force; //!< Force at which Slide Node breaks away from the rail (N) + float m_attach_rate; //!< How fast the cur threshold changes when attaching (i.e. how long it will take for springs to fully + //!< attach to the Rail) (m/s) + float m_attach_distance; //!< Maximum distance slide node will attach to a beam (m) + + // Methods //////////////////////////// TO BE SORTED ///////////////////////////////////////// + public: /** * @return The current position of the SlideNode */ - const Ogre::Vector3& GetSlideNodePosition() const; + const Ogre::Vector3 &GetSlideNodePosition() const; /** * @param toAttach Which rail to attach to, Pass NULL to detach this * SlideNode from any rail. */ - void AttachToRail(RailGroup* toAttach) + void AttachToRail(RailGroup *toAttach) { m_cur_railgroup = toAttach; this->ResetPositions(); @@ -142,40 +164,38 @@ class SlideNode * @param point * @return value is always positive, if group is null return infinity. */ - static Ogre::Real getLenTo( const RailGroup* group, const Ogre::Vector3& point ); + static Ogre::Real getLenTo(const RailGroup *group, const Ogre::Vector3 &point); /** * @param rail * @param point * @return value is always positive, if rail is null return infinity. */ - static Ogre::Real getLenTo( const RailSegment* rail, const Ogre::Vector3& point ); + static Ogre::Real getLenTo(const RailSegment *rail, const Ogre::Vector3 &point); /** * @param beam * @param point * @return value is always positive, if beam is null return infinity */ - static Ogre::Real getLenTo( const beam_t* beam, const Ogre::Vector3& point ); - + static Ogre::Real getLenTo(const beam_t *beam, const Ogre::Vector3 &point); /** * @param group * @return value is always positive, if group is null return infinity. */ - Ogre::Real getLenTo( const RailGroup* group ) const; + Ogre::Real getLenTo(const RailGroup *group) const; /** * @param rail * @return value is always positive, if rail is null return infinity. */ - Ogre::Real getLenTo( const RailSegment* rail ) const; + Ogre::Real getLenTo(const RailSegment *rail) const; /** * * @param beam * @return value is always positive, if beam is null return infinity */ - Ogre::Real getLenTo( const beam_t* beam) const; + Ogre::Real getLenTo(const beam_t *beam) const; }; - diff --git a/source/main/physics/air/AeroEngine.h b/source/main/physics/air/AeroEngine.h index 7d373e1a92..356ef2227f 100644 --- a/source/main/physics/air/AeroEngine.h +++ b/source/main/physics/air/AeroEngine.h @@ -24,41 +24,43 @@ class AeroEngine { -public: + public: enum { AEROENGINE_TYPE_TURBOPROP, AEROENGINE_TYPE_TURBOJET }; - virtual ~AeroEngine() {} + virtual ~AeroEngine() + { + } - virtual void updateVisuals(RoR::GfxActor* gfx_actor) =0; - virtual void updateForces(float dt, int doUpdate) =0; + virtual void updateVisuals(RoR::GfxActor *gfx_actor) = 0; + virtual void updateForces(float dt, int doUpdate) = 0; - virtual void setThrottle(float val) =0; + virtual void setThrottle(float val) = 0; - virtual float getThrottle() =0; + virtual float getThrottle() = 0; - virtual void reset() =0; + virtual void reset() = 0; - virtual void toggleReverse() =0; + virtual void toggleReverse() = 0; - virtual void setReverse(bool val) =0; - virtual bool getReverse() =0; + virtual void setReverse(bool val) = 0; + virtual bool getReverse() = 0; - virtual void flipStart() =0; + virtual void flipStart() = 0; - virtual float getRPMpc() =0; - virtual float getRPM() =0; - virtual void setRPM(float _rpm) =0; - virtual float getpropwash() =0; - virtual Ogre::Vector3 getAxis() =0; - virtual bool isFailed() =0; - virtual int getType() =0; - virtual bool getIgnition() =0; - virtual void setIgnition(bool val) =0; - virtual int getNoderef() =0; - virtual bool getWarmup() =0; - virtual float getRadius() =0; + virtual float getRPMpc() = 0; + virtual float getRPM() = 0; + virtual void setRPM(float _rpm) = 0; + virtual float getpropwash() = 0; + virtual Ogre::Vector3 getAxis() = 0; + virtual bool isFailed() = 0; + virtual int getType() = 0; + virtual bool getIgnition() = 0; + virtual void setIgnition(bool val) = 0; + virtual int getNoderef() = 0; + virtual bool getWarmup() = 0; + virtual float getRadius() = 0; }; diff --git a/source/main/physics/air/AirBrake.cpp b/source/main/physics/air/AirBrake.cpp index f4bd754d5f..611768645b 100644 --- a/source/main/physics/air/AirBrake.cpp +++ b/source/main/physics/air/AirBrake.cpp @@ -20,47 +20,48 @@ #include "AirBrake.h" -#include "BeamData.h" #include "Beam.h" // class Actor +#include "BeamData.h" #include "GfxActor.h" #include using namespace Ogre; -Airbrake::Airbrake(Actor* actor, const char* basename, int num, node_t* ndref, node_t* ndx, node_t* ndy, node_t* nda, Vector3 pos, float width, float length, float maxang, std::string const & texname, float tx1, float ty1, float tx2, float ty2, float lift_coef) +Airbrake::Airbrake(Actor *actor, const char *basename, int num, node_t *ndref, node_t *ndx, node_t *ndy, node_t *nda, Vector3 pos, + float width, float length, float maxang, std::string const &texname, float tx1, float ty1, float tx2, + float ty2, float lift_coef) { - snode = 0; - noderef = ndref; - nodex = ndx; - nodey = ndy; - nodea = nda; - offset = pos; + snode = 0; + noderef = ndref; + nodex = ndx; + nodey = ndy; + nodea = nda; + offset = pos; maxangle = maxang; - area = width * length * lift_coef; + area = width * length * lift_coef; char meshname[256]; sprintf(meshname, "airbrakemesh-%s-%i", basename, num); /// Create the mesh via the MeshManager msh = MeshManager::getSingleton().createManual(meshname, actor->GetGfxActor()->GetResourceGroup()); - union - { - float* vertices; - CoVertice_t* covertices; + union { + float * vertices; + CoVertice_t *covertices; }; /// Create submesh - SubMesh* sub = msh->createSubMesh(); + SubMesh *sub = msh->createSubMesh(); - //materials + // materials sub->setMaterialName(texname); /// Define the vertices size_t nVertices = 4; size_t vbufCount = (2 * 3 + 2) * nVertices; - vertices = (float*)malloc(vbufCount * sizeof(float)); + vertices = (float *)malloc(vbufCount * sizeof(float)); - //textures coordinates + // textures coordinates covertices[0].texcoord = Vector2(tx1, ty1); covertices[1].texcoord = Vector2(tx2, ty1); covertices[2].texcoord = Vector2(tx2, ty2); @@ -68,22 +69,22 @@ Airbrake::Airbrake(Actor* actor, const char* basename, int num, node_t* ndref, n /// Define triangles /// The values in this table refer to vertices in the above table - size_t ibufCount = 3 * 4; - unsigned short* faces = (unsigned short*)malloc(ibufCount * sizeof(unsigned short)); - faces[0] = 0; - faces[1] = 1; - faces[2] = 2; - faces[3] = 0; - faces[4] = 2; - faces[5] = 3; - faces[6] = 0; - faces[7] = 2; - faces[8] = 1; - faces[9] = 0; - faces[10] = 3; - faces[11] = 2; - - //set coords + size_t ibufCount = 3 * 4; + unsigned short *faces = (unsigned short *)malloc(ibufCount * sizeof(unsigned short)); + faces[0] = 0; + faces[1] = 1; + faces[2] = 2; + faces[3] = 0; + faces[4] = 2; + faces[5] = 3; + faces[6] = 0; + faces[7] = 2; + faces[8] = 1; + faces[9] = 0; + faces[10] = 3; + faces[11] = 2; + + // set coords covertices[0].vertex = Vector3(0, 0, 0); covertices[1].vertex = Vector3(width, 0, 0); covertices[2].vertex = Vector3(width, 0, length); @@ -95,12 +96,12 @@ Airbrake::Airbrake(Actor* actor, const char* basename, int num, node_t* ndref, n covertices[3].normal = Vector3(0, 1, 0); /// Create vertex data structure for vertices shared between submeshes - msh->sharedVertexData = new VertexData(); + msh->sharedVertexData = new VertexData(); msh->sharedVertexData->vertexCount = nVertices; /// Create declaration (memory format) of vertex data - VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration; - size_t offset = 0; + VertexDeclaration *decl = msh->sharedVertexData->vertexDeclaration; + size_t offset = 0; decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL); @@ -112,36 +113,32 @@ Airbrake::Airbrake(Actor* actor, const char* basename, int num, node_t* ndref, n /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) - HardwareVertexBufferSharedPtr vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer - VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; + VertexBufferBinding *bind = msh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); /// Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - ibufCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, ibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card faceibuf->writeData(0, faceibuf->getSizeInBytes(), faces, true); /// Set parameters of the submesh - sub->useSharedVertices = true; + sub->useSharedVertices = true; sub->indexData->indexBuffer = faceibuf; - sub->indexData->indexCount = ibufCount; - sub->indexData->indexStart = 0; + sub->indexData->indexCount = ibufCount; + sub->indexData->indexStart = 0; /// Set bounding information (for culling) msh->_setBounds(AxisAlignedBox(-1, -1, 0, 1, 1, 0), true); - //msh->_setBoundingSphereRadius(Math::Sqrt(1*1+1*1)); + // msh->_setBoundingSphereRadius(Math::Sqrt(1*1+1*1)); /// Notify Mesh object that it has been loaded msh->load(); @@ -149,7 +146,7 @@ Airbrake::Airbrake(Actor* actor, const char* basename, int num, node_t* ndref, n // create the entity and scene node char entname[256]; sprintf(entname, "airbrakenode-%s-%i", basename, num); - ec = gEnv->sceneManager->createEntity(entname, meshname, actor->GetGfxActor()->GetResourceGroup()); + ec = gEnv->sceneManager->createEntity(entname, meshname, actor->GetGfxActor()->GetResourceGroup()); snode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); snode->attachObject(ec); @@ -167,16 +164,16 @@ void Airbrake::updatePosition(float amount) void Airbrake::applyForce() { - //tropospheric model valid up to 11.000m (33.000ft) + // tropospheric model valid up to 11.000m (33.000ft) float altitude = noderef->AbsPosition.y; - //float sea_level_temperature=273.15+15.0; //in Kelvin - float sea_level_pressure = 101325; //in Pa - //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin - float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa - float airdensity = airpressure * 0.0000120896;//1.225 at sea level - - Vector3 wind = -noderef->Velocity; - float wspeed = wind.length(); + // float sea_level_temperature=273.15+15.0; //in Kelvin + float sea_level_pressure = 101325; // in Pa + // float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin + float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896; // 1.225 at sea level + + Vector3 wind = -noderef->Velocity; + float wspeed = wind.length(); Vector3 drag = (1.2 * area * sin(fabs(ratio * maxangle / 57.3)) * 0.5 * airdensity * wspeed / 4.0) * wind; noderef->Forces += drag; diff --git a/source/main/physics/air/AirBrake.h b/source/main/physics/air/AirBrake.h index 14f9277f76..a2aa63f567 100644 --- a/source/main/physics/air/AirBrake.h +++ b/source/main/physics/air/AirBrake.h @@ -28,8 +28,7 @@ class Airbrake : public ZeroedMemoryAllocator { friend class RoR::GfxActor; // Takes over the initialized OGRE objects -private: - + private: struct CoVertice_t { Ogre::Vector3 vertex; @@ -37,22 +36,26 @@ class Airbrake : public ZeroedMemoryAllocator Ogre::Vector2 texcoord; }; - Ogre::MeshPtr msh; - Ogre::SceneNode* snode; - node_t* noderef; - node_t* nodex; - node_t* nodey; - node_t* nodea; - Ogre::Vector3 offset; //!< gfx attribute - float ratio; //!< Current state - float maxangle; //!< attribute from truckfile - float area; //!< Attribute set at spawn - - Ogre::Entity* ec; - -public: - Airbrake(Actor* actor, const char* basename, int num, node_t* ndref, node_t* ndx, node_t* ndy, node_t* nda, Ogre::Vector3 pos, float width, float length, float maxang, std::string const & texname, float tx1, float tx2, float tx3, float tx4, float lift_coef); - ~Airbrake() {} // Cleanup of visuals is done by GfxActor + Ogre::MeshPtr msh; + Ogre::SceneNode *snode; + node_t * noderef; + node_t * nodex; + node_t * nodey; + node_t * nodea; + Ogre::Vector3 offset; //!< gfx attribute + float ratio; //!< Current state + float maxangle; //!< attribute from truckfile + float area; //!< Attribute set at spawn + + Ogre::Entity *ec; + + public: + Airbrake(Actor *actor, const char *basename, int num, node_t *ndref, node_t *ndx, node_t *ndy, node_t *nda, Ogre::Vector3 pos, + float width, float length, float maxang, std::string const &texname, float tx1, float tx2, float tx3, float tx4, + float lift_coef); + ~Airbrake() + { + } // Cleanup of visuals is done by GfxActor void updatePosition(float amount); void applyForce(); diff --git a/source/main/physics/air/Airfoil.cpp b/source/main/physics/air/Airfoil.cpp index 6dbfb2fc31..5f4d554f51 100644 --- a/source/main/physics/air/Airfoil.cpp +++ b/source/main/physics/air/Airfoil.cpp @@ -26,20 +26,20 @@ using namespace Ogre; -Airfoil::Airfoil(Ogre::String const& fname) +Airfoil::Airfoil(Ogre::String const &fname) { - for (int i = 0; i < 3601; i++) //init in case of bad things + for (int i = 0; i < 3601; i++) // init in case of bad things { cl[i] = 0; cd[i] = 0; cm[i] = 0; } char line[1024]; - //we load directly X-Plane AFL file format!!! - bool process = false; - bool neg = true; - int lastia = -1; - ResourceGroupManager& rgm = ResourceGroupManager::getSingleton(); + // we load directly X-Plane AFL file format!!! + bool process = false; + bool neg = true; + int lastia = -1; + ResourceGroupManager &rgm = ResourceGroupManager::getSingleton(); String group = ""; try @@ -51,7 +51,7 @@ Airfoil::Airfoil(Ogre::String const& fname) } if (group == "") { - LOG(String("Airfoil error: could not load airfoil ")+fname); + LOG(String("Airfoil error: could not load airfoil ") + fname); return; } @@ -59,8 +59,7 @@ Airfoil::Airfoil(Ogre::String const& fname) while (!ds->eof()) { size_t ll = ds->readLine(line, 1023); - if (ll == 0) - continue; + if (ll == 0) continue; // fscanf(fd," %[^\n\r]",line); if (!strncmp("alpha", line, 5)) { @@ -70,12 +69,10 @@ Airfoil::Airfoil(Ogre::String const& fname) if (process) { float l, d, m; - int a, b; + int a, b; sscanf(line, "%i.%i %f %f %f", &a, &b, &l, &d, &m); - if (neg) - b = -b; - if (a == 0 && b == 0) - neg = false; + if (neg) b = -b; + if (a == 0 && b == 0) neg = false; int ia = (a * 10 + b) + 1800; if (ia == 3600) { process = false; }; cl[ia] = l; @@ -83,7 +80,7 @@ Airfoil::Airfoil(Ogre::String const& fname) cm[ia] = m; if (lastia != -1 && ia - lastia > 1) { - //we have to interpolate previous elements (linear interpolation) + // we have to interpolate previous elements (linear interpolation) int i; for (i = 0; i < ia - lastia - 1; i++) { @@ -101,26 +98,21 @@ Airfoil::~Airfoil() { } -void Airfoil::getparams(float a, float cratio, float cdef, float* ocl, float* ocd, float* ocm) +void Airfoil::getparams(float a, float cratio, float cdef, float *ocl, float *ocd, float *ocm) { int ta = (int)(a / 360.0); // float va=360.0f*fmod(a, 360.0f); FMOD IS TOTALLY UNRELIABLE HERE : fmod(-180.0f, 360.0f)=-180.0f!!!!! float va = a - (float)(ta * 360); - if (va > 180.0f) - va -= 360.0f; - if (va < -180.0f) - va += 360.0f; + if (va > 180.0f) va -= 360.0f; + if (va < -180.0f) va += 360.0f; int ia = (int)((va + 180.0f) * 10.0f); - //drag shift + // drag shift float dva = va + 1.15 * (1.0 - cratio) * cdef; - if (dva > 180.0f) - dva -= 360.0f; - if (dva < -180.0f) - dva += 360.0f; - int dia = (int)((dva + 180.0f) * 10.0f); + if (dva > 180.0f) dva -= 360.0f; + if (dva < -180.0f) dva += 360.0f; + int dia = (int)((dva + 180.0f) * 10.0f); float sign = 1.0; - if (cdef < 0) - sign = -1.0; + if (cdef < 0) sign = -1.0; *ocl = cl[ia] - 0.66 * sign * (1.0 - cratio) * sqrt(fabs(cdef)); *ocd = cd[dia] + 0.00015 * (1.0 - cratio) * cdef * cdef; *ocm = cm[ia] + 0.20 * sign * (1.0 - cratio) * sqrt(fabs(cdef)); diff --git a/source/main/physics/air/Airfoil.h b/source/main/physics/air/Airfoil.h index bcaf32bc8b..21f41930fd 100644 --- a/source/main/physics/air/Airfoil.h +++ b/source/main/physics/air/Airfoil.h @@ -25,17 +25,15 @@ /// Represents an airfoil http://en.wikipedia.org/wiki/Airfoil class Airfoil : public ZeroedMemoryAllocator { -public: - + public: /// Parses the airfoil from file. /// @param fname File name (X-Plane's .AFL file format) - Airfoil(Ogre::String const& fname); + Airfoil(Ogre::String const &fname); ~Airfoil(); - void getparams(float a, float cratio, float cdef, float* ocl, float* ocd, float* ocm); - -private: + void getparams(float a, float cratio, float cdef, float *ocl, float *ocd, float *ocm); + private: float cl[3601]; float cd[3601]; float cm[3601]; diff --git a/source/main/physics/air/TurboJet.cpp b/source/main/physics/air/TurboJet.cpp index 88a6aaa5fc..d06e65197a 100644 --- a/source/main/physics/air/TurboJet.cpp +++ b/source/main/physics/air/TurboJet.cpp @@ -21,80 +21,125 @@ #include "TurboJet.h" -#include - #include "Beam.h" // class Actor #include "BeamData.h" #include "GfxActor.h" #include "SoundScriptManager.h" +#include + using namespace Ogre; -Turbojet::Turbojet(Actor* actor, int tnodefront, int tnodeback, int tnoderef, RigDef::Turbojet & def) +Turbojet::Turbojet(Actor *actor, int tnodefront, int tnodeback, int tnoderef, RigDef::Turbojet &def) { m_actor = actor; #ifdef USE_OPENAL switch (actor->ar_num_aeroengines) { - case 0: m_sound_mod = SS_MOD_AEROENGINE1; m_sound_src = SS_TRIG_AEROENGINE1; m_sound_thr = SS_MOD_THROTTLE1; m_sound_ab = SS_TRIG_AFTERBURNER1; break; - case 1: m_sound_mod = SS_MOD_AEROENGINE2; m_sound_src = SS_TRIG_AEROENGINE2; m_sound_thr = SS_MOD_THROTTLE2; m_sound_ab = SS_TRIG_AFTERBURNER2; break; - case 2: m_sound_mod = SS_MOD_AEROENGINE3; m_sound_src = SS_TRIG_AEROENGINE3; m_sound_thr = SS_MOD_THROTTLE3; m_sound_ab = SS_TRIG_AFTERBURNER3; break; - case 3: m_sound_mod = SS_MOD_AEROENGINE4; m_sound_src = SS_TRIG_AEROENGINE4; m_sound_thr = SS_MOD_THROTTLE4; m_sound_ab = SS_TRIG_AFTERBURNER4; break; - case 4: m_sound_mod = SS_MOD_AEROENGINE5; m_sound_src = SS_TRIG_AEROENGINE5; m_sound_thr = SS_MOD_THROTTLE5; m_sound_ab = SS_TRIG_AFTERBURNER5; break; - case 5: m_sound_mod = SS_MOD_AEROENGINE6; m_sound_src = SS_TRIG_AEROENGINE6; m_sound_thr = SS_MOD_THROTTLE6; m_sound_ab = SS_TRIG_AFTERBURNER6; break; - case 6: m_sound_mod = SS_MOD_AEROENGINE7; m_sound_src = SS_TRIG_AEROENGINE7; m_sound_thr = SS_MOD_THROTTLE7; m_sound_ab = SS_TRIG_AFTERBURNER7; break; - case 7: m_sound_mod = SS_MOD_AEROENGINE8; m_sound_src = SS_TRIG_AEROENGINE8; m_sound_thr = SS_MOD_THROTTLE8; m_sound_ab = SS_TRIG_AFTERBURNER8; break; - default: m_sound_mod = SS_MOD_NONE; m_sound_src = SS_TRIG_NONE; m_sound_thr = SS_MOD_NONE; m_sound_ab = SS_TRIG_NONE; + case 0: + m_sound_mod = SS_MOD_AEROENGINE1; + m_sound_src = SS_TRIG_AEROENGINE1; + m_sound_thr = SS_MOD_THROTTLE1; + m_sound_ab = SS_TRIG_AFTERBURNER1; + break; + case 1: + m_sound_mod = SS_MOD_AEROENGINE2; + m_sound_src = SS_TRIG_AEROENGINE2; + m_sound_thr = SS_MOD_THROTTLE2; + m_sound_ab = SS_TRIG_AFTERBURNER2; + break; + case 2: + m_sound_mod = SS_MOD_AEROENGINE3; + m_sound_src = SS_TRIG_AEROENGINE3; + m_sound_thr = SS_MOD_THROTTLE3; + m_sound_ab = SS_TRIG_AFTERBURNER3; + break; + case 3: + m_sound_mod = SS_MOD_AEROENGINE4; + m_sound_src = SS_TRIG_AEROENGINE4; + m_sound_thr = SS_MOD_THROTTLE4; + m_sound_ab = SS_TRIG_AFTERBURNER4; + break; + case 4: + m_sound_mod = SS_MOD_AEROENGINE5; + m_sound_src = SS_TRIG_AEROENGINE5; + m_sound_thr = SS_MOD_THROTTLE5; + m_sound_ab = SS_TRIG_AFTERBURNER5; + break; + case 5: + m_sound_mod = SS_MOD_AEROENGINE6; + m_sound_src = SS_TRIG_AEROENGINE6; + m_sound_thr = SS_MOD_THROTTLE6; + m_sound_ab = SS_TRIG_AFTERBURNER6; + break; + case 6: + m_sound_mod = SS_MOD_AEROENGINE7; + m_sound_src = SS_TRIG_AEROENGINE7; + m_sound_thr = SS_MOD_THROTTLE7; + m_sound_ab = SS_TRIG_AFTERBURNER7; + break; + case 7: + m_sound_mod = SS_MOD_AEROENGINE8; + m_sound_src = SS_TRIG_AEROENGINE8; + m_sound_thr = SS_MOD_THROTTLE8; + m_sound_ab = SS_TRIG_AFTERBURNER8; + break; + default: + m_sound_mod = SS_MOD_NONE; + m_sound_src = SS_TRIG_NONE; + m_sound_thr = SS_MOD_NONE; + m_sound_ab = SS_TRIG_NONE; } #endif - m_node_back = tnodeback; - m_node_front = tnodefront; - m_node_ref = tnoderef; - tjet_afterburnable = (def.wet_thrust > 0.f); - m_reversable = def.is_reversable != 0; - m_max_dry_thrust = def.dry_thrust; - m_afterburn_thrust = def.wet_thrust; + m_node_back = tnodeback; + m_node_front = tnodefront; + m_node_ref = tnoderef; + tjet_afterburnable = (def.wet_thrust > 0.f); + m_reversable = def.is_reversable != 0; + m_max_dry_thrust = def.dry_thrust; + m_afterburn_thrust = def.wet_thrust; m_afterburner_active = false; - m_timer = 0; - m_warmup_time = 15.0; - m_last_flip = 0; - m_radius = def.back_diameter / 2.f; - m_area = 2 * 3.14159 * m_radius * 0.6 * m_radius * 0.6; - m_exhaust_velocity = 0; - m_axis = m_actor->ar_nodes[m_node_front].RelPosition - m_actor->ar_nodes[m_node_back].RelPosition; - m_reflen = m_axis.length(); - m_axis = m_axis / m_reflen; + m_timer = 0; + m_warmup_time = 15.0; + m_last_flip = 0; + m_radius = def.back_diameter / 2.f; + m_area = 2 * 3.14159 * m_radius * 0.6 * m_radius * 0.6; + m_exhaust_velocity = 0; + m_axis = m_actor->ar_nodes[m_node_front].RelPosition - m_actor->ar_nodes[m_node_back].RelPosition; + m_reflen = m_axis.length(); + m_axis = m_axis / m_reflen; reset(); } -void TurbojetVisual::SetupVisuals(RigDef::Turbojet & def, int num, std::string const& propname, Ogre::Entity* nozzle, Ogre::Entity* afterburner_flame, bool disable_smoke) +void TurbojetVisual::SetupVisuals(RigDef::Turbojet &def, int num, std::string const &propname, Ogre::Entity *nozzle, + Ogre::Entity *afterburner_flame, bool disable_smoke) { m_radius = def.back_diameter / 2.0; m_number = num; - m_nozzle_entity = nozzle; + m_nozzle_entity = nozzle; m_nozzle_scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_nozzle_scenenode->attachObject(m_nozzle_entity); m_nozzle_scenenode->setScale(def.nozzle_length, def.back_diameter, def.back_diameter); if (afterburner_flame != nullptr) { - m_flame_entity = afterburner_flame; + m_flame_entity = afterburner_flame; m_flame_scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_flame_scenenode->attachObject(m_flame_entity); m_flame_scenenode->setScale(1.0, def.back_diameter, def.back_diameter); m_flame_scenenode->setVisible(false); } - //smoke visual + // smoke visual if (disable_smoke) { m_smoke_scenenode = 0; - m_smoke_particle = 0; + m_smoke_particle = 0; } else { m_smoke_scenenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - m_smoke_particle = gEnv->sceneManager->createParticleSystem("SmokeParticle-"+propname, "tracks/TurbopropSmoke"); + m_smoke_particle = gEnv->sceneManager->createParticleSystem("SmokeParticle-" + propname, "tracks/TurbopropSmoke"); if (m_smoke_particle) { m_smoke_particle->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap @@ -113,7 +158,7 @@ void TurbojetVisual::SetNodes(int front, int back, int ref) Turbojet::~Turbojet() { - //A fast work around + // A fast work around // SOUND_MODULATE(m_actor, m_sound_thr, 0); SOUND_MODULATE(m_actor, m_sound_mod, 0); @@ -123,60 +168,50 @@ Turbojet::~Turbojet() TurbojetVisual::~TurbojetVisual() { - if (m_flame_entity != nullptr) - { - m_flame_entity->setVisible(false); - } + if (m_flame_entity != nullptr) { m_flame_entity->setVisible(false); } - if (m_nozzle_entity != nullptr) - { - m_nozzle_entity->setVisible(false); - } + if (m_nozzle_entity != nullptr) { m_nozzle_entity->setVisible(false); } - if (m_smoke_particle != nullptr) - { - m_smoke_particle->removeAllEmitters(); - } + if (m_smoke_particle != nullptr) { m_smoke_particle->removeAllEmitters(); } } -void Turbojet::updateVisuals(RoR::GfxActor* gfx_actor) +void Turbojet::updateVisuals(RoR::GfxActor *gfx_actor) { this->tjet_visual.UpdateVisuals(gfx_actor); } -void TurbojetVisual::UpdateVisuals(RoR::GfxActor* gfx_actor) +void TurbojetVisual::UpdateVisuals(RoR::GfxActor *gfx_actor) { - RoR::GfxActor::NodeData* node_buf = gfx_actor->GetSimNodeBuffer(); - RoR::GfxActor::SimBuffer::AeroEngineSB& ae_buf - = gfx_actor->GetSimDataBuffer().simbuf_aeroengines.at(m_number); + RoR::GfxActor::NodeData * node_buf = gfx_actor->GetSimNodeBuffer(); + RoR::GfxActor::SimBuffer::AeroEngineSB &ae_buf = gfx_actor->GetSimDataBuffer().simbuf_aeroengines.at(m_number); - //nozzle + // nozzle m_nozzle_scenenode->setPosition(node_buf[m_node_back].AbsPosition); - //build a local system + // build a local system Vector3 laxis = node_buf[m_node_front].AbsPosition - node_buf[m_node_back].AbsPosition; laxis.normalise(); Vector3 paxis = Plane(laxis, 0).projectVector(node_buf[m_node_ref].AbsPosition - node_buf[m_node_back].AbsPosition); paxis.normalise(); - Vector3 taxis = laxis.crossProduct(paxis); - Quaternion dir = Quaternion(laxis, paxis, taxis); + Vector3 taxis = laxis.crossProduct(paxis); + Quaternion dir = Quaternion(laxis, paxis, taxis); m_nozzle_scenenode->setOrientation(dir); - //afterburner + // afterburner if (ae_buf.simbuf_tj_afterburn) { m_flame_scenenode->setVisible(true); float flamelength = (ae_buf.simbuf_tj_ab_thrust / 15.0) * (ae_buf.simbuf_ae_rpmpc / 100.0); - flamelength = flamelength * (1.0 + (((Real)rand() / (Real)RAND_MAX) - 0.5) / 10.0); + flamelength = flamelength * (1.0 + (((Real)rand() / (Real)RAND_MAX) - 0.5) / 10.0); m_flame_scenenode->setScale(flamelength, m_radius * 2.0, m_radius * 2.0); m_flame_scenenode->setPosition(node_buf[m_node_back].AbsPosition + dir * Vector3(-0.2, 0.0, 0.0)); m_flame_scenenode->setOrientation(dir); } else m_flame_scenenode->setVisible(false); - //smoke + // smoke if (m_smoke_scenenode) { m_smoke_scenenode->setPosition(node_buf[m_node_back].AbsPosition); - ParticleEmitter* emit = m_smoke_particle->getEmitter(0); + ParticleEmitter *emit = m_smoke_particle->getEmitter(0); emit->setDirection(-laxis); emit->setParticleVelocity(ae_buf.simbuf_tj_exhaust_velo); if (!ae_buf.simbuf_ae_failed) @@ -205,46 +240,39 @@ void TurbojetVisual::UpdateVisuals(RoR::GfxActor* gfx_actor) void Turbojet::updateForces(float dt, int doUpdate) { - if (doUpdate) - { - SOUND_MODULATE(m_actor, m_sound_mod, m_rpm_percent); - } + if (doUpdate) { SOUND_MODULATE(m_actor, m_sound_mod, m_rpm_percent); } m_timer += dt; - m_axis = m_actor->ar_nodes[m_node_front].RelPosition - m_actor->ar_nodes[m_node_back].RelPosition; + m_axis = m_actor->ar_nodes[m_node_front].RelPosition - m_actor->ar_nodes[m_node_back].RelPosition; float axlen = m_axis.length(); - m_axis = m_axis / axlen; //normalize + m_axis = m_axis / axlen; // normalize if (fabs(m_reflen - axlen) > 0.1) { m_rpm_percent = 0; - m_is_failed = true; - }; //check for broken + m_is_failed = true; + }; // check for broken float warmupfactor = 1.0; if (m_warmup) { warmupfactor = (m_timer - m_warmup_start) / m_warmup_time; - if (warmupfactor >= 1.0) - m_warmup = false; + if (warmupfactor >= 1.0) m_warmup = false; } - //turbine RPM - //braking (compression) - if (m_rpm_percent < 0) - m_rpm_percent = 0; + // turbine RPM + // braking (compression) + if (m_rpm_percent < 0) m_rpm_percent = 0; float torque = -m_rpm_percent / 100.0; - //powering with limiter - if (m_rpm_percent < 100.0 && !m_is_failed && m_ignition) - torque += ((0.2 + m_throtle * 0.8) * warmupfactor); - //integration + // powering with limiter + if (m_rpm_percent < 100.0 && !m_is_failed && m_ignition) torque += ((0.2 + m_throtle * 0.8) * warmupfactor); + // integration m_rpm_percent += (double)dt * torque * 30.0; float enginethrust = 0; if (!m_is_failed && m_ignition) { - enginethrust = m_max_dry_thrust * m_rpm_percent / 100.0; + enginethrust = m_max_dry_thrust * m_rpm_percent / 100.0; m_afterburner_active = (tjet_afterburnable && m_throtle > 0.95 && m_rpm_percent > 80); - if (m_afterburner_active) - enginethrust += (m_afterburn_thrust - m_max_dry_thrust); + if (m_afterburner_active) enginethrust += (m_afterburn_thrust - m_max_dry_thrust); } else m_afterburner_active = false; @@ -260,11 +288,9 @@ void Turbojet::updateForces(float dt, int doUpdate) void Turbojet::setThrottle(float val) { - if (val > 1.0) - val = 1.0; + if (val > 1.0) val = 1.0; - if (val < 0.0) - val = 0.0; + if (val < 0.0) val = 0.0; m_throtle = val; SOUND_MODULATE(m_actor, m_sound_thr, val); @@ -283,17 +309,16 @@ void Turbojet::setRPM(float _rpm) void Turbojet::reset() { m_rpm_percent = 0; - m_throtle = 0; - m_propwash = 0; - m_is_failed = false; - m_ignition = false; - m_reverse = false; + m_throtle = 0; + m_propwash = 0; + m_is_failed = false; + m_ignition = false; + m_reverse = false; } void Turbojet::toggleReverse() { - if (!m_reversable) - return; + if (!m_reversable) return; m_throtle = 0; m_reverse = !m_reverse; } @@ -305,12 +330,11 @@ void Turbojet::setReverse(bool val) void Turbojet::flipStart() { - if (m_timer - m_last_flip < 0.3) - return; + if (m_timer - m_last_flip < 0.3) return; m_ignition = !m_ignition; if (m_ignition && !m_is_failed) { - m_warmup = true; + m_warmup = true; m_warmup_start = m_timer; SOUND_START(m_actor, m_sound_src); } diff --git a/source/main/physics/air/TurboJet.h b/source/main/physics/air/TurboJet.h index e563af5126..177335af50 100644 --- a/source/main/physics/air/TurboJet.h +++ b/source/main/physics/air/TurboJet.h @@ -20,25 +20,26 @@ #pragma once -#include "RoRPrerequisites.h" #include "AeroEngine.h" #include "RigDef_File.h" +#include "RoRPrerequisites.h" class TurbojetVisual { -public: + public: ~TurbojetVisual(); - void SetupVisuals(RigDef::Turbojet & def, int num, std::string const& propname, Ogre::Entity* nozzle, Ogre::Entity* afterburner_flame, bool disable_smoke); + void SetupVisuals(RigDef::Turbojet &def, int num, std::string const &propname, Ogre::Entity *nozzle, + Ogre::Entity *afterburner_flame, bool disable_smoke); void SetNodes(int front, int back, int ref); - void UpdateVisuals(RoR::GfxActor* gfx_actor); + void UpdateVisuals(RoR::GfxActor *gfx_actor); -private: - Ogre::SceneNode* m_smoke_scenenode; - Ogre::ParticleSystem* m_smoke_particle; - Ogre::Entity* m_flame_entity; - Ogre::SceneNode* m_flame_scenenode; - Ogre::Entity* m_nozzle_entity; - Ogre::SceneNode* m_nozzle_scenenode; + private: + Ogre::SceneNode * m_smoke_scenenode; + Ogre::ParticleSystem *m_smoke_particle; + Ogre::Entity * m_flame_entity; + Ogre::SceneNode * m_flame_scenenode; + Ogre::Entity * m_nozzle_entity; + Ogre::SceneNode * m_nozzle_scenenode; int m_number; float m_radius; @@ -47,12 +48,11 @@ class TurbojetVisual uint16_t m_node_ref; }; -class Turbojet: public AeroEngine, public ZeroedMemoryAllocator +class Turbojet : public AeroEngine, public ZeroedMemoryAllocator { -public: - - Turbojet(Actor* actor, int tnodefront, int tnodeback, int tnoderef, RigDef::Turbojet & def); + public: + Turbojet(Actor *actor, int tnodefront, int tnodeback, int tnoderef, RigDef::Turbojet &def); ~Turbojet(); void flipStart(); @@ -61,57 +61,102 @@ class Turbojet: public AeroEngine, public ZeroedMemoryAllocator void setThrottle(float val); void toggleReverse(); void setReverse(bool val); - bool getReverse() { return m_reverse; }; + bool getReverse() + { + return m_reverse; + }; void updateForces(float dt, int doUpdate); - void updateVisuals(RoR::GfxActor* gfx_actor) override; - - Ogre::Vector3 getAxis() { return m_axis; }; - - bool getIgnition() { return m_ignition; }; - void setIgnition(bool val) { m_ignition = val; }; - bool getWarmup() { return m_warmup; }; - bool isFailed() { return m_is_failed; }; - float getAfterburner() { return (float)m_afterburner_active; }; - float getAfterburnThrust() const { return m_afterburn_thrust; } - float getExhaustVelocity() const { return m_exhaust_velocity; } - float getRPM() { return m_rpm_percent; }; // FIXME - bad func name - float getRPMpc() { return m_rpm_percent; }; - float getRadius() { return m_radius; }; + void updateVisuals(RoR::GfxActor *gfx_actor) override; + + Ogre::Vector3 getAxis() + { + return m_axis; + }; + + bool getIgnition() + { + return m_ignition; + }; + void setIgnition(bool val) + { + m_ignition = val; + }; + bool getWarmup() + { + return m_warmup; + }; + bool isFailed() + { + return m_is_failed; + }; + float getAfterburner() + { + return (float)m_afterburner_active; + }; + float getAfterburnThrust() const + { + return m_afterburn_thrust; + } + float getExhaustVelocity() const + { + return m_exhaust_velocity; + } + float getRPM() + { + return m_rpm_percent; + }; // FIXME - bad func name + float getRPMpc() + { + return m_rpm_percent; + }; + float getRadius() + { + return m_radius; + }; float getThrottle(); - float getpropwash() { return m_propwash; }; - int getNoderef() { return m_node_back; }; - int getType() { return AEROENGINE_TYPE_TURBOJET; }; - - bool tjet_afterburnable; + float getpropwash() + { + return m_propwash; + }; + int getNoderef() + { + return m_node_back; + }; + int getType() + { + return AEROENGINE_TYPE_TURBOJET; + }; + + bool tjet_afterburnable; TurbojetVisual tjet_visual; -private: - Actor* m_actor; + private: + Actor * m_actor; Ogre::Vector3 m_axis; - bool m_afterburner_active; - bool m_is_failed; - bool m_ignition; - bool m_reversable; - bool m_reverse; - bool m_warmup; - float m_afterburn_thrust; //!< in kN - float m_area; - float m_exhaust_velocity; //!< in m/s - float m_last_flip; - float m_max_dry_thrust; //!< in kN - float m_propwash; - float m_radius; - float m_reflen; - float m_rpm_percent; //!< in percent! - float m_throtle; - float m_timer; - float m_warmup_start; - float m_warmup_time; - int m_sound_ab; - int m_sound_mod; - int m_node_back; - int m_node_front; - int m_node_ref; - int m_sound_src; - int m_sound_thr; + bool m_afterburner_active; + bool m_is_failed; + bool m_ignition; + bool m_reversable; + bool m_reverse; + bool m_warmup; + float m_afterburn_thrust; //!< in kN + float m_area; + float m_exhaust_velocity; //!< in m/s + float m_last_flip; + float m_max_dry_thrust; //!< in kN + float m_propwash; + float m_radius; + float m_reflen; + float m_rpm_percent; //!< in percent! + float m_throtle; + float m_timer; + float m_warmup_start; + float m_warmup_time; + int m_sound_ab; + int m_sound_mod; + int m_node_back; + int m_node_front; + int m_node_ref; + int m_sound_src; + int m_sound_thr; }; diff --git a/source/main/physics/air/TurboProp.cpp b/source/main/physics/air/TurboProp.cpp index c079440f43..0ece3b842d 100644 --- a/source/main/physics/air/TurboProp.cpp +++ b/source/main/physics/air/TurboProp.cpp @@ -20,75 +20,94 @@ #include "TurboProp.h" -#include - #include "Airfoil.h" +#include "BeamData.h" #include "GfxActor.h" #include "Scripting.h" #include "SoundScriptManager.h" -#include "BeamData.h" + +#include using namespace Ogre; -Turboprop::Turboprop( - const char* propname, - node_t* nd, - int nr, - int nb, - int np1, - int np2, - int np3, - int np4, - int tqn, - float power, - Ogre::String const& propfoilname, - int mnumber, - int trucknum, - bool disable_smoke, - bool ispiston, - float fpitch -) +Turboprop::Turboprop(const char *propname, node_t *nd, int nr, int nb, int np1, int np2, int np3, int np4, int tqn, float power, + Ogre::String const &propfoilname, int mnumber, int trucknum, bool disable_smoke, bool ispiston, float fpitch) { - failed = false; - failedold = false; - number = mnumber; + failed = false; + failedold = false; + number = mnumber; this->trucknum = trucknum; #ifdef USE_OPENAL switch (number) { - case 0: mod_id = SS_MOD_AEROENGINE1; src_id = SS_TRIG_AEROENGINE1; thr_id = SS_MOD_THROTTLE1; break; - case 1: mod_id = SS_MOD_AEROENGINE2; src_id = SS_TRIG_AEROENGINE2; thr_id = SS_MOD_THROTTLE2; break; - case 2: mod_id = SS_MOD_AEROENGINE3; src_id = SS_TRIG_AEROENGINE3; thr_id = SS_MOD_THROTTLE3; break; - case 3: mod_id = SS_MOD_AEROENGINE4; src_id = SS_TRIG_AEROENGINE4; thr_id = SS_MOD_THROTTLE4; break; - case 4: mod_id = SS_MOD_AEROENGINE5; src_id = SS_TRIG_AEROENGINE5; thr_id = SS_MOD_THROTTLE5; break; - case 5: mod_id = SS_MOD_AEROENGINE6; src_id = SS_TRIG_AEROENGINE6; thr_id = SS_MOD_THROTTLE6; break; - case 6: mod_id = SS_MOD_AEROENGINE7; src_id = SS_TRIG_AEROENGINE7; thr_id = SS_MOD_THROTTLE7; break; - case 7: mod_id = SS_MOD_AEROENGINE8; src_id = SS_TRIG_AEROENGINE8; thr_id = SS_MOD_THROTTLE8; break; - default: mod_id = SS_MOD_NONE; src_id = SS_TRIG_NONE; thr_id = SS_MOD_NONE; + case 0: + mod_id = SS_MOD_AEROENGINE1; + src_id = SS_TRIG_AEROENGINE1; + thr_id = SS_MOD_THROTTLE1; + break; + case 1: + mod_id = SS_MOD_AEROENGINE2; + src_id = SS_TRIG_AEROENGINE2; + thr_id = SS_MOD_THROTTLE2; + break; + case 2: + mod_id = SS_MOD_AEROENGINE3; + src_id = SS_TRIG_AEROENGINE3; + thr_id = SS_MOD_THROTTLE3; + break; + case 3: + mod_id = SS_MOD_AEROENGINE4; + src_id = SS_TRIG_AEROENGINE4; + thr_id = SS_MOD_THROTTLE4; + break; + case 4: + mod_id = SS_MOD_AEROENGINE5; + src_id = SS_TRIG_AEROENGINE5; + thr_id = SS_MOD_THROTTLE5; + break; + case 5: + mod_id = SS_MOD_AEROENGINE6; + src_id = SS_TRIG_AEROENGINE6; + thr_id = SS_MOD_THROTTLE6; + break; + case 6: + mod_id = SS_MOD_AEROENGINE7; + src_id = SS_TRIG_AEROENGINE7; + thr_id = SS_MOD_THROTTLE7; + break; + case 7: + mod_id = SS_MOD_AEROENGINE8; + src_id = SS_TRIG_AEROENGINE8; + thr_id = SS_MOD_THROTTLE8; + break; + default: + mod_id = SS_MOD_NONE; + src_id = SS_TRIG_NONE; + thr_id = SS_MOD_NONE; } -#endif //OPENAL - is_piston = ispiston; +#endif // OPENAL + is_piston = ispiston; fixed_pitch = fpitch; - torquenode = tqn; - rotenergy = 0; - pitchspeed = 5.0; //in degree/sec - numblades = 4; + torquenode = tqn; + rotenergy = 0; + pitchspeed = 5.0; // in degree/sec + numblades = 4; twistmap[0] = 2; twistmap[1] = 6; twistmap[2] = 10; twistmap[3] = 19; twistmap[4] = 32; - nodes = nd; - noderef = nr; - nodeback = nb; - nodep[0] = np1; - nodep[1] = np2; + nodes = nd; + noderef = nr; + nodeback = nb; + nodep[0] = np1; + nodep[1] = np2; if (torquenode != -1) { - Plane pplane = Plane((nd[nr].RelPosition - nd[nb].RelPosition).normalisedCopy(), 0.0); - Vector3 apos = pplane.projectVector(nd[nr].RelPosition); - Vector3 tpos = pplane.projectVector(nd[tqn].RelPosition); - torquedist = (apos - tpos).length(); + Plane pplane = Plane((nd[nr].RelPosition - nd[nb].RelPosition).normalisedCopy(), 0.0); + Vector3 apos = pplane.projectVector(nd[nr].RelPosition); + Vector3 tpos = pplane.projectVector(nd[tqn].RelPosition); + torquedist = (apos - tpos).length(); } else torquedist = 1.0; @@ -102,36 +121,36 @@ Turboprop::Turboprop( else nodep[3] = np4; } - propwash = 0; - timer = 0; - lastflip = 0; - warmupstart = 0.0; - warmuptime = 14.0; - warmup = false; - airfoil = new Airfoil(propfoilname); - fullpower = power; - max_torque = 9549.3 * fullpower / 1000.0; + propwash = 0; + timer = 0; + lastflip = 0; + warmupstart = 0.0; + warmuptime = 14.0; + warmup = false; + airfoil = new Airfoil(propfoilname); + fullpower = power; + max_torque = 9549.3 * fullpower / 1000.0; indicated_torque = 0.0; - radius = (nodes[noderef].RelPosition - nodes[nodep[0]].RelPosition).length(); - //bladewidth=radius/5.75; + radius = (nodes[noderef].RelPosition - nodes[nodep[0]].RelPosition).length(); + // bladewidth=radius/5.75; bladewidth = 0.4; - proparea = 3.14159 * radius * radius; + proparea = 3.14159 * radius * radius; airdensity = 1.225; // regspeed=245.0*60.0/(2.0*3.14159*radius);//1010.0 //compute regulated speed for a tip speed of 245m/s - regspeed = 1010; + regspeed = 1010; maxrevpitch = -5.0; - //smoke visual + // smoke visual if (disable_smoke) { smokeNode = 0; - smokePS = 0; + smokePS = 0; } else { char dename[256]; sprintf(dename, "%s-smoke", propname); smokeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - smokePS = gEnv->sceneManager->createParticleSystem(dename, "tracks/TurbopropSmoke"); + smokePS = gEnv->sceneManager->createParticleSystem(dename, "tracks/TurbopropSmoke"); if (smokePS) { smokePS->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap @@ -145,33 +164,27 @@ Turboprop::Turboprop( Turboprop::~Turboprop() { - //A fast work around + // A fast work around // SOUND_MODULATE(trucknum, thr_id, 0); SOUND_MODULATE(trucknum, mod_id, 0); SOUND_STOP(trucknum, src_id); - if (airfoil != nullptr) - { - delete airfoil; - } + if (airfoil != nullptr) { delete airfoil; } - if (smokePS != nullptr) - { - smokePS->removeAllEmitters(); - } + if (smokePS != nullptr) { smokePS->removeAllEmitters(); } } -void Turboprop::updateVisuals(RoR::GfxActor* gfx_actor) +void Turboprop::updateVisuals(RoR::GfxActor *gfx_actor) { - RoR::GfxActor::NodeData* node_buf = gfx_actor->GetSimNodeBuffer(); + RoR::GfxActor::NodeData *node_buf = gfx_actor->GetSimNodeBuffer(); - //smoke + // smoke if (smokeNode) { smokeNode->setPosition(node_buf[nodeback].AbsPosition); - ParticleEmitter* emit = smokePS->getEmitter(0); - Vector3 dir = node_buf[nodeback].AbsPosition - node_buf[noderef].AbsPosition; + ParticleEmitter *emit = smokePS->getEmitter(0); + Vector3 dir = node_buf[nodeback].AbsPosition - node_buf[noderef].AbsPosition; emit->setDirection(dir); emit->setParticleVelocity(propwash - propwash / 10, propwash + propwash / 10); if (!failed) @@ -210,51 +223,45 @@ void Turboprop::updateForces(float dt, int doUpdate) { if (doUpdate) { - //tropospheric model valid up to 11.000m (33.000ft) + // tropospheric model valid up to 11.000m (33.000ft) float altitude = nodes[noderef].AbsPosition.y; - //float sea_level_temperature=273.15+15.0; //in Kelvin - float sea_level_pressure = 101325; //in Pa - //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin - float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa - airdensity = airpressure * 0.0000120896;//1.225 at sea level + // float sea_level_temperature=273.15+15.0; //in Kelvin + float sea_level_pressure = 101325; // in Pa + // float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin + float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + airdensity = airpressure * 0.0000120896; // 1.225 at sea level SOUND_MODULATE(trucknum, mod_id, rpm); } timer += dt; - //evaluate the rotation speed + // evaluate the rotation speed float velacc = 0; for (int i = 0; i < numblades; i++) { velacc += (nodes[nodep[i]].Velocity - nodes[noderef].Velocity).length(); } rpm = (velacc / numblades) * RAD_PER_SEC_TO_RPM / radius; - //check for broken prop + // check for broken prop Vector3 avg = Vector3::ZERO; for (int i = 0; i < numblades; i++) { avg += nodes[nodep[i]].RelPosition; } avg = avg / numblades; - if ((avg - nodes[noderef].RelPosition).length() > 0.4) - { - failed = true; - } - //evaluate engine power - float enginepower = 0; //in kilo-Watt + if ((avg - nodes[noderef].RelPosition).length() > 0.4) { failed = true; } + // evaluate engine power + float enginepower = 0; // in kilo-Watt float warmupfactor = 1.0; if (warmup) { warmupfactor = (timer - warmupstart) / warmuptime; - if (warmupfactor >= 1.0) - warmup = false; + if (warmupfactor >= 1.0) warmup = false; } float revpenalty = 1.0; - if (reverse) - revpenalty = 0.5; - if (!failed && ignition) - enginepower = (0.0575 + throtle * revpenalty * 0.9425) * fullpower * warmupfactor; - //the magic formula - float enginecouple = 0.0; //in N.m + if (reverse) revpenalty = 0.5; + if (!failed && ignition) enginepower = (0.0575 + throtle * revpenalty * 0.9425) * fullpower * warmupfactor; + // the magic formula + float enginecouple = 0.0; // in N.m if (rpm > 10.0) enginecouple = 9549.3 * enginepower / rpm; else @@ -264,17 +271,17 @@ void Turboprop::updateForces(float dt, int doUpdate) if (torquenode != -1) { Vector3 along = nodes[noderef].RelPosition - nodes[nodeback].RelPosition; - Plane ppl = Plane(along, 0); - Vector3 orth = ppl.projectVector(nodes[noderef].RelPosition) - ppl.projectVector(nodes[torquenode].RelPosition); - Vector3 cdir = orth.crossProduct(along); + Plane ppl = Plane(along, 0); + Vector3 orth = ppl.projectVector(nodes[noderef].RelPosition) - ppl.projectVector(nodes[torquenode].RelPosition); + Vector3 cdir = orth.crossProduct(along); cdir.normalise(); nodes[torquenode].Forces += (enginecouple / torquedist) * cdir; } float tipforce = (enginecouple / radius) / numblades; - //okay, now we know the contribution from the engine + // okay, now we know the contribution from the engine - //pitch + // pitch if (fixed_pitch > 0) pitch = fixed_pitch; else @@ -283,21 +290,16 @@ void Turboprop::updateForces(float dt, int doUpdate) { if (throtle < 0.01) { - //beta range - if (pitch > 0 && rpm < regspeed * 1.4) - pitch -= pitchspeed * dt; - if (rpm > regspeed * 1.4) - pitch += pitchspeed * dt; + // beta range + if (pitch > 0 && rpm < regspeed * 1.4) pitch -= pitchspeed * dt; + if (rpm > regspeed * 1.4) pitch += pitchspeed * dt; } else { float dpitch = rpm - regspeed; - if (dpitch > pitchspeed) - dpitch = pitchspeed; - if (dpitch < -pitchspeed) - dpitch = -pitchspeed; - if (!(dpitch < 0 && pitch < 0) && !(dpitch > 0 && pitch > 45)) - pitch += dpitch * dt; + if (dpitch > pitchspeed) dpitch = pitchspeed; + if (dpitch < -pitchspeed) dpitch = -pitchspeed; + if (!(dpitch < 0 && pitch < 0) && !(dpitch > 0 && pitch > 45)) pitch += dpitch * dt; } } else @@ -309,10 +311,7 @@ void Turboprop::updateForces(float dt, int doUpdate) else pitch -= pitchspeed * dt; } - if (rpm > regspeed * 1.11) - { - pitch -= pitchspeed * dt; - } + if (rpm > regspeed * 1.11) { pitch -= pitchspeed * dt; } } } if (!failed) @@ -320,9 +319,10 @@ void Turboprop::updateForces(float dt, int doUpdate) axis = nodes[noderef].RelPosition - nodes[nodeback].RelPosition; axis.normalise(); } - //estimate amount of energy - float estrotenergy = 0.5 * numblades * nodes[nodep[0]].mass * radius * radius * (rpm / RAD_PER_SEC_TO_RPM) * (rpm / RAD_PER_SEC_TO_RPM); - //for each blade + // estimate amount of energy + float estrotenergy = + 0.5 * numblades * nodes[nodep[0]].mass * radius * radius * (rpm / RAD_PER_SEC_TO_RPM) * (rpm / RAD_PER_SEC_TO_RPM); + // for each blade float totthrust = 0; float tottorque = 0; for (int i = 0; i < numblades; i++) @@ -330,105 +330,100 @@ void Turboprop::updateForces(float dt, int doUpdate) if (!failed && ignition) { Vector3 totaltipforce = Vector3::ZERO; - //span vector, left to right + // span vector, left to right Vector3 spanv = (nodes[nodep[i]].RelPosition - nodes[noderef].RelPosition); spanv.normalise(); - //chord vector, front to back + // chord vector, front to back Vector3 refchordv = -axis.crossProduct(spanv); - //grab this for propulsive forces + // grab this for propulsive forces Vector3 tipf = -refchordv; - totaltipforce += (tipforce - rpm / 10.0) * tipf; //add a bit of mechanical friction - //for each blade segment (there are 6 elements) - for (int j = 0; j < 5; j++) //outer to inner, the 6th blade element is ignored + totaltipforce += (tipforce - rpm / 10.0) * tipf; // add a bit of mechanical friction + // for each blade segment (there are 6 elements) + for (int j = 0; j < 5; j++) // outer to inner, the 6th blade element is ignored { - //proportion + // proportion float proport = ((float)j + 0.5) / 6.0; - //evaluate wind direction - Vector3 wind = -(nodes[nodep[i]].Velocity * (1.0 - proport) + nodes[noderef].Velocity * proport); - float wspeed = wind.length(); + // evaluate wind direction + Vector3 wind = -(nodes[nodep[i]].Velocity * (1.0 - proport) + nodes[noderef].Velocity * proport); + float wspeed = wind.length(); Vector3 liftv = spanv.crossProduct(-wind); liftv.normalise(); - //rotate according to pitch + // rotate according to pitch Vector3 chordv = Quaternion(Degree(pitch + twistmap[j] - 7.0), spanv) * refchordv; - //wing normal + // wing normal Vector3 normv = chordv.crossProduct(spanv); - //calculate angle of attack + // calculate angle of attack Vector3 pwind = Plane(Vector3::ZERO, normv, chordv).projectVector(wind); Vector3 dumb; - Degree daoa; + Degree daoa; chordv.getRotationTo(pwind).ToAngleAxis(daoa, dumb); - float aoa = daoa.valueDegrees(); + float aoa = daoa.valueDegrees(); float raoa = daoa.valueRadians(); if (dumb.dotProduct(spanv) > 0) { - aoa = -aoa; + aoa = -aoa; raoa = -raoa; }; - //get airfoil data + // get airfoil data float cz, cx, cm; airfoil->getparams(aoa, 1.0, 0.0, &cz, &cx, &cm); - //surface computation + // surface computation float s = radius * bladewidth / 6.0; - //drag - //wforce=(8.0*cx+cx*cx/(3.14159*radius/0.4))*0.5*airdensity*wspeed*s*wind; + // drag + // wforce=(8.0*cx+cx*cx/(3.14159*radius/0.4))*0.5*airdensity*wspeed*s*wind; Vector3 eforce = (4.0 * cx + cx * cx / (3.14159 * radius / bladewidth)) * 0.5 * airdensity * wspeed * s * wind; - //lift + // lift float lift = cz * 0.5 * airdensity * wspeed * wspeed * s; eforce += lift * liftv; totthrust += eforce.dotProduct(axis); - //apply forces + // apply forces nodes[noderef].Forces += eforce * proport; totaltipforce += eforce * (1.0 - proport); } tottorque += tipf.dotProduct(totaltipforce) * radius; - //correct amount of energy + // correct amount of energy float correctfactor = 0; - if (rpm > 100) - correctfactor = (rotenergy - estrotenergy) / (numblades * radius * dt * rpm / RAD_PER_SEC_TO_RPM); - if (correctfactor > 1000.0) - correctfactor = 1000.0; - if (correctfactor < -1000.0) - correctfactor = -1000.0; + if (rpm > 100) correctfactor = (rotenergy - estrotenergy) / (numblades * radius * dt * rpm / RAD_PER_SEC_TO_RPM); + if (correctfactor > 1000.0) correctfactor = 1000.0; + if (correctfactor < -1000.0) correctfactor = -1000.0; nodes[nodep[i]].Forces += totaltipforce + correctfactor * tipf; } else if (!nodes[noderef].Velocity.isZeroLength()) { - //failed case - //add drag + // failed case + // add drag Vector3 wind = -nodes[nodep[i]].Velocity; - // determine nodes speed and divide by engines speed (with some magic numbers for tuning) to keep it rotating longer when shutoff in flight and stop after a while when plane is stopped (on the ground) + // determine nodes speed and divide by engines speed (with some magic numbers for tuning) to keep it rotating longer + // when shutoff in flight and stop after a while when plane is stopped (on the ground) float wspeed = (wind.length() / 15.0f) / (nodes[noderef].Velocity.length() / 2.0f); nodes[nodep[i]].Forces += airdensity * wspeed * wind; } } - //compute the next energy level + // compute the next energy level rotenergy += (double)tottorque * dt * rpm / RAD_PER_SEC_TO_RPM; - // sprintf(debug, "pitch %i thrust %i totenergy=%i apparentenergy=%i", (int)pitch, (int)totthrust, (int)rotenergy, (int)estrotenergy); - //prop wash - float speed = nodes[noderef].Velocity.length(); + // sprintf(debug, "pitch %i thrust %i totenergy=%i apparentenergy=%i", (int)pitch, (int)totthrust, (int)rotenergy, + //(int)estrotenergy); prop wash + float speed = nodes[noderef].Velocity.length(); float thrsign = 1.0; if (totthrust < 0) { - thrsign = -0.1; + thrsign = -0.1; totthrust = -totthrust; }; if (!failed) propwash = thrsign * sqrt(totthrust / (0.5 * airdensity * proparea) + speed * speed) - speed; else propwash = 0; - if (propwash < 0) - propwash = 0; + if (propwash < 0) propwash = 0; } void Turboprop::setThrottle(float val) { - if (val > 1.0) - val = 1.0; - if (val < 0.0) - val = 0.0; + if (val > 1.0) val = 1.0; + if (val < 0.0) val = 0.0; throtle = val; SOUND_MODULATE(trucknum, thr_id, val); } @@ -445,12 +440,12 @@ void Turboprop::setRPM(float _rpm) void Turboprop::reset() { - rpm = 0; - throtle = 0; - failed = false; - ignition = false; - reverse = false; - pitch = 0; + rpm = 0; + throtle = 0; + failed = false; + ignition = false; + reverse = false; + pitch = 0; rotenergy = 0; } @@ -458,7 +453,7 @@ void Turboprop::toggleReverse() { throtle = 0; reverse = !reverse; - pitch = 0; + pitch = 0; } void Turboprop::setReverse(bool val) @@ -468,12 +463,11 @@ void Turboprop::setReverse(bool val) void Turboprop::flipStart() { - if (timer - lastflip < 0.3) - return; + if (timer - lastflip < 0.3) return; ignition = !ignition; if (ignition && !failed) { - warmup = true; + warmup = true; warmupstart = timer; SOUND_START(trucknum, src_id); } diff --git a/source/main/physics/air/TurboProp.h b/source/main/physics/air/TurboProp.h index 4fc03089eb..9e3008f5b4 100644 --- a/source/main/physics/air/TurboProp.h +++ b/source/main/physics/air/TurboProp.h @@ -20,40 +20,22 @@ #pragma once -#include "RoRPrerequisites.h" - #include "AeroEngine.h" +#include "RoRPrerequisites.h" -class Turboprop: public AeroEngine, public ZeroedMemoryAllocator +class Turboprop : public AeroEngine, public ZeroedMemoryAllocator { -public: - - bool is_piston; + public: + bool is_piston; float pitch; float indicated_torque; float max_torque; - Turboprop( - const char* propname, - node_t* nd, - int nr, - int nb, - int np1, - int np2, - int np3, - int np4, - int tqn, - float power, - Ogre::String const& propfoilname, - int mnumber, - int trucknum, - bool disable_smoke, - bool ispiston, - float fpitch - ); + Turboprop(const char *propname, node_t *nd, int nr, int nb, int np1, int np2, int np3, int np4, int tqn, float power, + Ogre::String const &propfoilname, int mnumber, int trucknum, bool disable_smoke, bool ispiston, float fpitch); ~Turboprop(); - void updateVisuals(RoR::GfxActor* gfx_actor) override; + void updateVisuals(RoR::GfxActor *gfx_actor) override; void updateForces(float dt, int doUpdate); void setThrottle(float val); @@ -64,64 +46,99 @@ class Turboprop: public AeroEngine, public ZeroedMemoryAllocator void toggleReverse(); void setReverse(bool val); - bool getReverse() { return reverse; }; + bool getReverse() + { + return reverse; + }; void flipStart(); - float getRPM() { return rpm; }; - float getRPMpc() { return rpm / 10.0f; }; - void setRPM(float _rpm); - float getpropwash() { return propwash; }; - Ogre::Vector3 getAxis() { return axis; }; - bool isFailed() { return failed; }; - int getType() { return AEROENGINE_TYPE_TURBOPROP; }; - bool getIgnition() { return ignition; }; - void setIgnition(bool val) { ignition = val; }; - int getNoderef() { return noderef; }; - bool getWarmup() { return warmup; }; - float getRadius() { return radius; }; - -private: - - node_t* nodes; - int nodeback; - int nodep[4]; - int torquenode; - float torquedist; - Airfoil* airfoil; - float fullpower; //!< in kW - float proparea; - float airdensity; - float timer; - float lastflip; - float warmupstart; - float warmuptime; - int number; - int numblades; - float bladewidth; - float pitchspeed; - float maxrevpitch; - float regspeed; - Ogre::ParticleSystem* smokePS; - Ogre::SceneNode* smokeNode; - float twistmap[5]; - double rotenergy; - float fixed_pitch; - - bool reverse; - bool warmup; - bool ignition; - float radius; - bool failed; - bool failedold; - float rpm; - float throtle; - int noderef; - char debug[256]; - float propwash; + float getRPM() + { + return rpm; + }; + float getRPMpc() + { + return rpm / 10.0f; + }; + void setRPM(float _rpm); + float getpropwash() + { + return propwash; + }; + Ogre::Vector3 getAxis() + { + return axis; + }; + bool isFailed() + { + return failed; + }; + int getType() + { + return AEROENGINE_TYPE_TURBOPROP; + }; + bool getIgnition() + { + return ignition; + }; + void setIgnition(bool val) + { + ignition = val; + }; + int getNoderef() + { + return noderef; + }; + bool getWarmup() + { + return warmup; + }; + float getRadius() + { + return radius; + }; + + private: + node_t * nodes; + int nodeback; + int nodep[4]; + int torquenode; + float torquedist; + Airfoil * airfoil; + float fullpower; //!< in kW + float proparea; + float airdensity; + float timer; + float lastflip; + float warmupstart; + float warmuptime; + int number; + int numblades; + float bladewidth; + float pitchspeed; + float maxrevpitch; + float regspeed; + Ogre::ParticleSystem *smokePS; + Ogre::SceneNode * smokeNode; + float twistmap[5]; + double rotenergy; + float fixed_pitch; + + bool reverse; + bool warmup; + bool ignition; + float radius; + bool failed; + bool failedold; + float rpm; + float throtle; + int noderef; + char debug[256]; + float propwash; Ogre::Vector3 axis; - int trucknum; - int mod_id; - int src_id; - int thr_id; + int trucknum; + int mod_id; + int src_id; + int thr_id; }; diff --git a/source/main/physics/collision/CartesianToTriangleTransform.h b/source/main/physics/collision/CartesianToTriangleTransform.h index b7926c472b..f8106054a5 100644 --- a/source/main/physics/collision/CartesianToTriangleTransform.h +++ b/source/main/physics/collision/CartesianToTriangleTransform.h @@ -24,7 +24,6 @@ #include #include - /// Defines a linear transformation from cartesian coordinates to local (barycentric) coordinates of a specified triangle. /** * The barycentric coordinate system of the triangle is defined in terms of its three vertices @@ -35,30 +34,34 @@ * In addition, the shortest (signed) distance \f$d\f$ between the point \f$\mathbf{p}\f$ and the triangle * plane is returned by this transformation. * - * The transformation is evaluated lazily, i.e. creating new instances of CartesianToTriangleTransform is + * The transformation is evaluated lazily, i.e. creating new instances of CartesianToTriangleTransform is * relatively cheap. Actual calculations are deferred until the transformation is applied to a point for * the first time. */ class CartesianToTriangleTransform { -public: + public: /// Return type of CartesianToTriangleTransform transformation. /** * Describes the position of a three-dimensional point relative to a triangle. * The position on the triangle plane is defined by the barycentric coordinates #alpha, #beta and #gamma. * The perpendicular offset of the point from this plane is given by the value of #distance. */ - struct TriangleCoord { - const struct { - Ogre::Real alpha, ///< Barycentric coordinate - beta, ///< Barycentric coordinate - gamma; ///< Barycentric coordinate + struct TriangleCoord + { + const struct + { + Ogre::Real alpha, ///< Barycentric coordinate + beta, ///< Barycentric coordinate + gamma; ///< Barycentric coordinate } barycentric; - const Ogre::Real distance; ///< Shortest (signed) distance to triangle plane + const Ogre::Real distance; ///< Shortest (signed) distance to triangle plane }; /// Construct transformation for specified triangle. - explicit CartesianToTriangleTransform(const Triangle &triangle) : m_triangle{triangle}, m_initialized{false} {} + explicit CartesianToTriangleTransform(const Triangle &triangle) : m_triangle{triangle}, m_initialized{false} + { + } /// Transform point into local triangle coordinates. /** @@ -105,10 +108,11 @@ class CartesianToTriangleTransform * \f$\gamma\f$ can be immediately calculated from known values \f$\alpha\f$ and \f$\beta\f$ because * \f$\alpha + \beta + \gamma = 1\f$ always holds. */ - TriangleCoord operator() (const Ogre::Vector3 &p) const + TriangleCoord operator()(const Ogre::Vector3 &p) const { // lazy initialization of transformation matrix - if (!m_initialized) { + if (!m_initialized) + { InitMatrix(); m_initialized = true; } @@ -118,21 +122,20 @@ class CartesianToTriangleTransform return {result[0], result[1], (1.f - result[0] - result[1]), result[2]}; } -private: + private: /// Initialize the transformation matrix - void InitMatrix() const { + void InitMatrix() const + { // determine span and normal vectors const Ogre::Vector3 u = m_triangle.u; const Ogre::Vector3 v = m_triangle.v; const Ogre::Vector3 n = m_triangle.normal(); - + // construct and invert matrix - m_matrix = Ogre::Matrix3{ u[0], v[0], n[0], - u[1], v[1], n[1], - u[2], v[2], n[2] }.Inverse(); + m_matrix = Ogre::Matrix3{u[0], v[0], n[0], u[1], v[1], n[1], u[2], v[2], n[2]}.Inverse(); } - const Triangle m_triangle; //< The triangle on which the transformation is based. - mutable bool m_initialized; - mutable Ogre::Matrix3 m_matrix; ///< Cached transformation matrix. + const Triangle m_triangle; //< The triangle on which the transformation is based. + mutable bool m_initialized; + mutable Ogre::Matrix3 m_matrix; ///< Cached transformation matrix. }; diff --git a/source/main/physics/collision/Collisions.cpp b/source/main/physics/collision/Collisions.cpp index 6afd9b92e3..8d95aea02c 100644 --- a/source/main/physics/collision/Collisions.cpp +++ b/source/main/physics/collision/Collisions.cpp @@ -36,100 +36,56 @@ // some gcc fixes #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif //OGRE_PLATFORM_LINUX - -//hash function SBOX -//from http://home.comcast.net/~bretm/hash/10.html -unsigned int sbox[] = -{ - 0xF53E1837, 0x5F14C86B, 0x9EE3964C, 0xFA796D53, - 0x32223FC3, 0x4D82BC98, 0xA0C7FA62, 0x63E2C982, - 0x24994A5B, 0x1ECE7BEE, 0x292B38EF, 0xD5CD4E56, - 0x514F4303, 0x7BE12B83, 0x7192F195, 0x82DC7300, - 0x084380B4, 0x480B55D3, 0x5F430471, 0x13F75991, - 0x3F9CF22C, 0x2FE0907A, 0xFD8E1E69, 0x7B1D5DE8, - 0xD575A85C, 0xAD01C50A, 0x7EE00737, 0x3CE981E8, - 0x0E447EFA, 0x23089DD6, 0xB59F149F, 0x13600EC7, - 0xE802C8E6, 0x670921E4, 0x7207EFF0, 0xE74761B0, - 0x69035234, 0xBFA40F19, 0xF63651A0, 0x29E64C26, - 0x1F98CCA7, 0xD957007E, 0xE71DDC75, 0x3E729595, - 0x7580B7CC, 0xD7FAF60B, 0x92484323, 0xA44113EB, - 0xE4CBDE08, 0x346827C9, 0x3CF32AFA, 0x0B29BCF1, - 0x6E29F7DF, 0xB01E71CB, 0x3BFBC0D1, 0x62EDC5B8, - 0xB7DE789A, 0xA4748EC9, 0xE17A4C4F, 0x67E5BD03, - 0xF3B33D1A, 0x97D8D3E9, 0x09121BC0, 0x347B2D2C, - 0x79A1913C, 0x504172DE, 0x7F1F8483, 0x13AC3CF6, - 0x7A2094DB, 0xC778FA12, 0xADF7469F, 0x21786B7B, - 0x71A445D0, 0xA8896C1B, 0x656F62FB, 0x83A059B3, - 0x972DFE6E, 0x4122000C, 0x97D9DA19, 0x17D5947B, - 0xB1AFFD0C, 0x6EF83B97, 0xAF7F780B, 0x4613138A, - 0x7C3E73A6, 0xCF15E03D, 0x41576322, 0x672DF292, - 0xB658588D, 0x33EBEFA9, 0x938CBF06, 0x06B67381, - 0x07F192C6, 0x2BDA5855, 0x348EE0E8, 0x19DBB6E3, - 0x3222184B, 0xB69D5DBA, 0x7E760B88, 0xAF4D8154, - 0x007A51AD, 0x35112500, 0xC9CD2D7D, 0x4F4FB761, - 0x694772E3, 0x694C8351, 0x4A7E3AF5, 0x67D65CE1, - 0x9287DE92, 0x2518DB3C, 0x8CB4EC06, 0xD154D38F, - 0xE19A26BB, 0x295EE439, 0xC50A1104, 0x2153C6A7, - 0x82366656, 0x0713BC2F, 0x6462215A, 0x21D9BFCE, - 0xBA8EACE6, 0xAE2DF4C1, 0x2A8D5E80, 0x3F7E52D1, - 0x29359399, 0xFEA1D19C, 0x18879313, 0x455AFA81, - 0xFADFE838, 0x62609838, 0xD1028839, 0x0736E92F, - 0x3BCA22A3, 0x1485B08A, 0x2DA7900B, 0x852C156D, - 0xE8F24803, 0x00078472, 0x13F0D332, 0x2ACFD0CF, - 0x5F747F5C, 0x87BB1E2F, 0xA7EFCB63, 0x23F432F0, - 0xE6CE7C5C, 0x1F954EF6, 0xB609C91B, 0x3B4571BF, - 0xEED17DC0, 0xE556CDA0, 0xA7846A8D, 0xFF105F94, - 0x52B7CCDE, 0x0E33E801, 0x664455EA, 0xF2C70414, - 0x73E7B486, 0x8F830661, 0x8B59E826, 0xBB8AEDCA, - 0xF3D70AB9, 0xD739F2B9, 0x4A04C34A, 0x88D0F089, - 0xE02191A2, 0xD89D9C78, 0x192C2749, 0xFC43A78F, - 0x0AAC88CB, 0x9438D42D, 0x9E280F7A, 0x36063802, - 0x38E8D018, 0x1C42A9CB, 0x92AAFF6C, 0xA24820C5, - 0x007F077F, 0xCE5BC543, 0x69668D58, 0x10D6FF74, - 0xBE00F621, 0x21300BBE, 0x2E9E8F46, 0x5ACEA629, - 0xFA1F86C7, 0x52F206B8, 0x3EDF1A75, 0x6DA8D843, - 0xCF719928, 0x73E3891F, 0xB4B95DD6, 0xB2A42D27, - 0xEDA20BBF, 0x1A58DBDF, 0xA449AD03, 0x6DDEF22B, - 0x900531E6, 0x3D3BFF35, 0x5B24ABA2, 0x472B3E4C, - 0x387F2D75, 0x4D8DBA36, 0x71CB5641, 0xE3473F3F, - 0xF6CD4B7F, 0xBF7D1428, 0x344B64D0, 0xC5CDFCB6, - 0xFE2E0182, 0x2C37A673, 0xDE4EB7A3, 0x63FDC933, - 0x01DC4063, 0x611F3571, 0xD167BFAF, 0x4496596F, - 0x3DEE0689, 0xD8704910, 0x7052A114, 0x068C9EC5, - 0x75D0E766, 0x4D54CC20, 0xB44ECDE2, 0x4ABC653E, - 0x2C550A21, 0x1A52C0DB, 0xCFED03D0, 0x119BAFE2, - 0x876A6133, 0xBC232088, 0x435BA1B2, 0xAE99BBFA, - 0xBB4F08E4, 0xA62B5F49, 0x1DA4B695, 0x336B84DE, - 0xDC813D31, 0x00C134FB, 0x397A98E6, 0x151F0E64, - 0xD9EB3E69, 0xD3C7DF60, 0xD2F2C336, 0x2DDD067B, - 0xBD122835, 0xB0B3BD3A, 0xB0D54E46, 0x8641F1E4, - 0xA0B38F96, 0x51D39199, 0x37A6AD75, 0xDF84EE41, - 0x3C034CBA, 0xACDA62FC, 0x11923B8B, 0x45EF170A, + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif // OGRE_PLATFORM_LINUX + +// hash function SBOX +// from http://home.comcast.net/~bretm/hash/10.html +unsigned int sbox[] = { + 0xF53E1837, 0x5F14C86B, 0x9EE3964C, 0xFA796D53, 0x32223FC3, 0x4D82BC98, 0xA0C7FA62, 0x63E2C982, 0x24994A5B, 0x1ECE7BEE, + 0x292B38EF, 0xD5CD4E56, 0x514F4303, 0x7BE12B83, 0x7192F195, 0x82DC7300, 0x084380B4, 0x480B55D3, 0x5F430471, 0x13F75991, + 0x3F9CF22C, 0x2FE0907A, 0xFD8E1E69, 0x7B1D5DE8, 0xD575A85C, 0xAD01C50A, 0x7EE00737, 0x3CE981E8, 0x0E447EFA, 0x23089DD6, + 0xB59F149F, 0x13600EC7, 0xE802C8E6, 0x670921E4, 0x7207EFF0, 0xE74761B0, 0x69035234, 0xBFA40F19, 0xF63651A0, 0x29E64C26, + 0x1F98CCA7, 0xD957007E, 0xE71DDC75, 0x3E729595, 0x7580B7CC, 0xD7FAF60B, 0x92484323, 0xA44113EB, 0xE4CBDE08, 0x346827C9, + 0x3CF32AFA, 0x0B29BCF1, 0x6E29F7DF, 0xB01E71CB, 0x3BFBC0D1, 0x62EDC5B8, 0xB7DE789A, 0xA4748EC9, 0xE17A4C4F, 0x67E5BD03, + 0xF3B33D1A, 0x97D8D3E9, 0x09121BC0, 0x347B2D2C, 0x79A1913C, 0x504172DE, 0x7F1F8483, 0x13AC3CF6, 0x7A2094DB, 0xC778FA12, + 0xADF7469F, 0x21786B7B, 0x71A445D0, 0xA8896C1B, 0x656F62FB, 0x83A059B3, 0x972DFE6E, 0x4122000C, 0x97D9DA19, 0x17D5947B, + 0xB1AFFD0C, 0x6EF83B97, 0xAF7F780B, 0x4613138A, 0x7C3E73A6, 0xCF15E03D, 0x41576322, 0x672DF292, 0xB658588D, 0x33EBEFA9, + 0x938CBF06, 0x06B67381, 0x07F192C6, 0x2BDA5855, 0x348EE0E8, 0x19DBB6E3, 0x3222184B, 0xB69D5DBA, 0x7E760B88, 0xAF4D8154, + 0x007A51AD, 0x35112500, 0xC9CD2D7D, 0x4F4FB761, 0x694772E3, 0x694C8351, 0x4A7E3AF5, 0x67D65CE1, 0x9287DE92, 0x2518DB3C, + 0x8CB4EC06, 0xD154D38F, 0xE19A26BB, 0x295EE439, 0xC50A1104, 0x2153C6A7, 0x82366656, 0x0713BC2F, 0x6462215A, 0x21D9BFCE, + 0xBA8EACE6, 0xAE2DF4C1, 0x2A8D5E80, 0x3F7E52D1, 0x29359399, 0xFEA1D19C, 0x18879313, 0x455AFA81, 0xFADFE838, 0x62609838, + 0xD1028839, 0x0736E92F, 0x3BCA22A3, 0x1485B08A, 0x2DA7900B, 0x852C156D, 0xE8F24803, 0x00078472, 0x13F0D332, 0x2ACFD0CF, + 0x5F747F5C, 0x87BB1E2F, 0xA7EFCB63, 0x23F432F0, 0xE6CE7C5C, 0x1F954EF6, 0xB609C91B, 0x3B4571BF, 0xEED17DC0, 0xE556CDA0, + 0xA7846A8D, 0xFF105F94, 0x52B7CCDE, 0x0E33E801, 0x664455EA, 0xF2C70414, 0x73E7B486, 0x8F830661, 0x8B59E826, 0xBB8AEDCA, + 0xF3D70AB9, 0xD739F2B9, 0x4A04C34A, 0x88D0F089, 0xE02191A2, 0xD89D9C78, 0x192C2749, 0xFC43A78F, 0x0AAC88CB, 0x9438D42D, + 0x9E280F7A, 0x36063802, 0x38E8D018, 0x1C42A9CB, 0x92AAFF6C, 0xA24820C5, 0x007F077F, 0xCE5BC543, 0x69668D58, 0x10D6FF74, + 0xBE00F621, 0x21300BBE, 0x2E9E8F46, 0x5ACEA629, 0xFA1F86C7, 0x52F206B8, 0x3EDF1A75, 0x6DA8D843, 0xCF719928, 0x73E3891F, + 0xB4B95DD6, 0xB2A42D27, 0xEDA20BBF, 0x1A58DBDF, 0xA449AD03, 0x6DDEF22B, 0x900531E6, 0x3D3BFF35, 0x5B24ABA2, 0x472B3E4C, + 0x387F2D75, 0x4D8DBA36, 0x71CB5641, 0xE3473F3F, 0xF6CD4B7F, 0xBF7D1428, 0x344B64D0, 0xC5CDFCB6, 0xFE2E0182, 0x2C37A673, + 0xDE4EB7A3, 0x63FDC933, 0x01DC4063, 0x611F3571, 0xD167BFAF, 0x4496596F, 0x3DEE0689, 0xD8704910, 0x7052A114, 0x068C9EC5, + 0x75D0E766, 0x4D54CC20, 0xB44ECDE2, 0x4ABC653E, 0x2C550A21, 0x1A52C0DB, 0xCFED03D0, 0x119BAFE2, 0x876A6133, 0xBC232088, + 0x435BA1B2, 0xAE99BBFA, 0xBB4F08E4, 0xA62B5F49, 0x1DA4B695, 0x336B84DE, 0xDC813D31, 0x00C134FB, 0x397A98E6, 0x151F0E64, + 0xD9EB3E69, 0xD3C7DF60, 0xD2F2C336, 0x2DDD067B, 0xBD122835, 0xB0B3BD3A, 0xB0D54E46, 0x8641F1E4, 0xA0B38F96, 0x51D39199, + 0x37A6AD75, 0xDF84EE41, 0x3C034CBA, 0xACDA62FC, 0x11923B8B, 0x45EF170A, }; using namespace Ogre; using namespace RoR; -Collisions::Collisions(): - debugMode(false) - , debugmo(nullptr) - , forcecam(false) - , free_eventsource(0) - , hashmask(0) - , landuse(0) - , m_terrain_size(App::GetSimTerrain()->getMaxTerrainSize()) +Collisions::Collisions() + : debugMode(false), debugmo(nullptr), forcecam(false), free_eventsource(0), hashmask(0), landuse(0), + m_terrain_size(App::GetSimTerrain()->getMaxTerrainSize()) { debugMode = RoR::App::diag_collisions.GetActive(); // TODO: make interactive - do not copy the value, use GVar directly - for (int i=0; i < HASH_POWER; i++) + for (int i = 0; i < HASH_POWER; i++) { hashmask = hashmask << 1; hashmask++; } loadDefaultModels(); - defaultgm = getGroundModelByString("concrete"); + defaultgm = getGroundModelByString("concrete"); defaultgroundgm = getGroundModelByString("gravel"); if (debugMode) @@ -170,7 +126,7 @@ int Collisions::loadGroundModelsConfigFile(Ogre::String filename) else cfg.loadFromResourceSystem(filename, group, "\x09:=", true); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { ErrorUtils::ShowError("Error while loading ground model", e.getFullDescription()); return 1; @@ -181,7 +137,7 @@ int Collisions::loadGroundModelsConfigFile(Ogre::String filename) // after it was parsed, resolve the dependencies std::map::iterator it; - for (it=ground_models.begin(); it!=ground_models.end(); it++) + for (it = ground_models.begin(); it != ground_models.end(); it++) { if (!strlen(it->second.basename)) continue; // no base, normal material String bname = String(it->second.basename); @@ -198,13 +154,14 @@ int Collisions::loadGroundModelsConfigFile(Ogre::String filename) // check the version if (this->collision_version != LATEST_GROUND_MODEL_VERSION) { - ErrorUtils::ShowError(_L("Configuration error"), _L("Your ground configuration is too old, please copy skeleton/config/ground_models.cfg to My Documents/Rigs of Rods/config")); + ErrorUtils::ShowError(_L("Configuration error"), + _L("Your ground configuration is too old, please copy skeleton/config/ground_models.cfg to My " + "Documents/Rigs of Rods/config")); exit(124); } return 0; } - void Collisions::parseGroundConfig(Ogre::ConfigFile *cfg, String groundModel) { Ogre::ConfigFile::SectionIterator seci = cfg->getSectionIterator(); @@ -212,7 +169,7 @@ void Collisions::parseGroundConfig(Ogre::ConfigFile *cfg, String groundModel) Ogre::String secName, kname, kvalue; while (seci.hasMoreElements()) { - secName = seci.peekNextKey(); + secName = seci.peekNextKey(); Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); if (!groundModel.empty() && secName != groundModel) continue; @@ -220,14 +177,15 @@ void Collisions::parseGroundConfig(Ogre::ConfigFile *cfg, String groundModel) Ogre::ConfigFile::SettingsMultiMap::iterator i; for (i = settings->begin(); i != settings->end(); ++i) { - kname = i->first; + kname = i->first; kvalue = i->second; // we got all the data available now, processing now if (secName == "general" || secName == "config") { // set some class properties accoring to the information in this section if (kname == "version") this->collision_version = StringConverter::parseInt(kvalue); - } else + } + else { // we assume that all other sections are separate ground types! if (ground_models.find(secName) == ground_models.end()) @@ -237,28 +195,35 @@ void Collisions::parseGroundConfig(Ogre::ConfigFile *cfg, String groundModel) // clear it memset(&ground_models[secName], 0, sizeof(ground_model_t)); // set some default values - ground_models[secName].alpha = 2.0f; + ground_models[secName].alpha = 2.0f; ground_models[secName].strength = 1.0f; // some fx defaults - ground_models[secName].fx_particle_amount = 20; - ground_models[secName].fx_particle_min_velo = 5; - ground_models[secName].fx_particle_max_velo = 99999; + ground_models[secName].fx_particle_amount = 20; + ground_models[secName].fx_particle_min_velo = 5; + ground_models[secName].fx_particle_max_velo = 99999; ground_models[secName].fx_particle_velo_factor = 0.7f; - ground_models[secName].fx_particle_fade = -1; - ground_models[secName].fx_particle_timedelta = 1; - ground_models[secName].fx_particle_ttl = 2; + ground_models[secName].fx_particle_fade = -1; + ground_models[secName].fx_particle_timedelta = 1; + ground_models[secName].fx_particle_ttl = 2; strncpy(ground_models[secName].name, secName.c_str(), 255); - } - if (kname == "adhesion velocity") ground_models[secName].va = StringConverter::parseReal(kvalue); - else if (kname == "static friction coefficient") ground_models[secName].ms = StringConverter::parseReal(kvalue); - else if (kname == "sliding friction coefficient") ground_models[secName].mc = StringConverter::parseReal(kvalue); - else if (kname == "hydrodynamic friction") ground_models[secName].t2 = StringConverter::parseReal(kvalue); - else if (kname == "stribeck velocity") ground_models[secName].vs = StringConverter::parseReal(kvalue); - else if (kname == "alpha") ground_models[secName].alpha = StringConverter::parseReal(kvalue); - else if (kname == "strength") ground_models[secName].strength = StringConverter::parseReal(kvalue); - else if (kname == "base") strncpy(ground_models[secName].basename, kvalue.c_str(), 255); + if (kname == "adhesion velocity") + ground_models[secName].va = StringConverter::parseReal(kvalue); + else if (kname == "static friction coefficient") + ground_models[secName].ms = StringConverter::parseReal(kvalue); + else if (kname == "sliding friction coefficient") + ground_models[secName].mc = StringConverter::parseReal(kvalue); + else if (kname == "hydrodynamic friction") + ground_models[secName].t2 = StringConverter::parseReal(kvalue); + else if (kname == "stribeck velocity") + ground_models[secName].vs = StringConverter::parseReal(kvalue); + else if (kname == "alpha") + ground_models[secName].alpha = StringConverter::parseReal(kvalue); + else if (kname == "strength") + ground_models[secName].strength = StringConverter::parseReal(kvalue); + else if (kname == "base") + strncpy(ground_models[secName].basename, kvalue.c_str(), 255); else if (kname == "fx_type") { if (kvalue == "PARTICLE") @@ -270,23 +235,35 @@ void Collisions::parseGroundConfig(Ogre::ConfigFile *cfg, String groundModel) else if (kvalue == "CLUMPY") ground_models[secName].fx_type = FX_CLUMPY; } - else if (kname == "fx_particle_name") strncpy(ground_models[secName].particle_name, kvalue.c_str(), 255); - else if (kname == "fx_colour") ground_models[secName].fx_colour = StringConverter::parseColourValue(kvalue); - else if (kname == "fx_particle_amount") ground_models[secName].fx_particle_amount = StringConverter::parseInt(kvalue); - else if (kname == "fx_particle_min_velo") ground_models[secName].fx_particle_min_velo = StringConverter::parseReal(kvalue); - else if (kname == "fx_particle_max_velo") ground_models[secName].fx_particle_max_velo = StringConverter::parseReal(kvalue); - else if (kname == "fx_particle_fade") ground_models[secName].fx_particle_fade = StringConverter::parseReal(kvalue); - else if (kname == "fx_particle_timedelta") ground_models[secName].fx_particle_timedelta = StringConverter::parseReal(kvalue); - else if (kname == "fx_particle_velo_factor") ground_models[secName].fx_particle_velo_factor = StringConverter::parseReal(kvalue); - else if (kname == "fx_particle_ttl") ground_models[secName].fx_particle_ttl = StringConverter::parseReal(kvalue); - - - else if (kname == "fluid density") ground_models[secName].fluid_density = StringConverter::parseReal(kvalue); - else if (kname == "flow consistency index") ground_models[secName].flow_consistency_index = StringConverter::parseReal(kvalue); - else if (kname == "flow behavior index") ground_models[secName].flow_behavior_index = StringConverter::parseReal(kvalue); - else if (kname == "solid ground level") ground_models[secName].solid_ground_level = StringConverter::parseReal(kvalue); - else if (kname == "drag anisotropy") ground_models[secName].drag_anisotropy = StringConverter::parseReal(kvalue); - + else if (kname == "fx_particle_name") + strncpy(ground_models[secName].particle_name, kvalue.c_str(), 255); + else if (kname == "fx_colour") + ground_models[secName].fx_colour = StringConverter::parseColourValue(kvalue); + else if (kname == "fx_particle_amount") + ground_models[secName].fx_particle_amount = StringConverter::parseInt(kvalue); + else if (kname == "fx_particle_min_velo") + ground_models[secName].fx_particle_min_velo = StringConverter::parseReal(kvalue); + else if (kname == "fx_particle_max_velo") + ground_models[secName].fx_particle_max_velo = StringConverter::parseReal(kvalue); + else if (kname == "fx_particle_fade") + ground_models[secName].fx_particle_fade = StringConverter::parseReal(kvalue); + else if (kname == "fx_particle_timedelta") + ground_models[secName].fx_particle_timedelta = StringConverter::parseReal(kvalue); + else if (kname == "fx_particle_velo_factor") + ground_models[secName].fx_particle_velo_factor = StringConverter::parseReal(kvalue); + else if (kname == "fx_particle_ttl") + ground_models[secName].fx_particle_ttl = StringConverter::parseReal(kvalue); + + else if (kname == "fluid density") + ground_models[secName].fluid_density = StringConverter::parseReal(kvalue); + else if (kname == "flow consistency index") + ground_models[secName].flow_consistency_index = StringConverter::parseReal(kvalue); + else if (kname == "flow behavior index") + ground_models[secName].flow_behavior_index = StringConverter::parseReal(kvalue); + else if (kname == "solid ground level") + ground_models[secName].solid_ground_level = StringConverter::parseReal(kvalue); + else if (kname == "drag anisotropy") + ground_models[secName].drag_anisotropy = StringConverter::parseReal(kvalue); } } @@ -294,41 +271,46 @@ void Collisions::parseGroundConfig(Ogre::ConfigFile *cfg, String groundModel) } } -Ogre::Vector3 Collisions::calcCollidedSide(const Ogre::Vector3& pos, const Ogre::Vector3& lo, const Ogre::Vector3& hi) -{ - Ogre::Real min = pos.x - lo.x; +Ogre::Vector3 Collisions::calcCollidedSide(const Ogre::Vector3 &pos, const Ogre::Vector3 &lo, const Ogre::Vector3 &hi) +{ + Ogre::Real min = pos.x - lo.x; Ogre::Vector3 newPos = Ogre::Vector3(lo.x, pos.y, pos.z); - + Ogre::Real t = pos.y - lo.y; - if (t < min) { - min=t; + if (t < min) + { + min = t; newPos = Ogre::Vector3(pos.x, lo.y, pos.z); } - + t = pos.z - lo.z; - if (t < min) { - min=t; + if (t < min) + { + min = t; newPos = Ogre::Vector3(pos.x, pos.y, lo.z); } - + t = hi.x - pos.x; - if (t < min) { - min=t; + if (t < min) + { + min = t; newPos = Ogre::Vector3(hi.x, pos.y, pos.z); } - + t = hi.y - pos.y; - if (t < min) { - min=t; + if (t < min) + { + min = t; newPos = Ogre::Vector3(pos.x, hi.y, pos.z); } - + t = hi.z - pos.z; - if (t < min) { - min=t; + if (t < min) + { + min = t; newPos = Ogre::Vector3(pos.x, pos.y, hi.z); } - + return newPos; } @@ -344,9 +326,7 @@ void Collisions::removeCollisionBox(int number) { m_collision_boxes[number].enabled = false; if (m_collision_boxes[number].eventsourcenum >= 0 && m_collision_boxes[number].eventsourcenum < free_eventsource) - { - eventsources[m_collision_boxes[number].eventsourcenum].enabled = false; - } + { eventsources[m_collision_boxes[number].eventsourcenum].enabled = false; } // Is it worth to update the hashmap? ~ ulteq 01/19 } } @@ -362,8 +342,7 @@ void Collisions::removeCollisionTri(int number) ground_model_t *Collisions::getGroundModelByString(const String name) { - if (!ground_models.size() || ground_models.find(name) == ground_models.end()) - return 0; + if (!ground_models.size() || ground_models.find(name) == ground_models.end()) return 0; return &ground_models[name]; } @@ -371,18 +350,18 @@ ground_model_t *Collisions::getGroundModelByString(const String name) unsigned int Collisions::hashfunc(unsigned int cellid) { unsigned int hash = 0; - for (int i=0; i < 4; i++) + for (int i = 0; i < 4; i++) { - hash ^= sbox[((unsigned char*)&cellid)[i]]; + hash ^= sbox[((unsigned char *)&cellid)[i]]; hash *= 3; } - return hash&hashmask; + return hash & hashmask; } void Collisions::hash_add(int cell_x, int cell_z, int value, float h) { unsigned int cell_id = (cell_x << 16) + cell_z; - unsigned int pos = hashfunc(cell_id); + unsigned int pos = hashfunc(cell_id); hashtable[pos].emplace_back(cell_id, value); hashtable_height[pos] = std::max(hashtable_height[pos], h); @@ -396,44 +375,49 @@ int Collisions::hash_find(int cell_x, int cell_z) return static_cast(pos); } -int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vector3 pos, Ogre::Vector3 rot, Ogre::Vector3 l, Ogre::Vector3 h, Ogre::Vector3 sr, const Ogre::String &eventname, const Ogre::String &instancename, bool forcecam, Ogre::Vector3 campos, Ogre::Vector3 sc /* = Vector3::UNIT_SCALE */, Ogre::Vector3 dr /* = Vector3::ZERO */, int event_filter /* = EVENT_ALL */, int scripthandler /* = -1 */) +int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vector3 pos, Ogre::Vector3 rot, Ogre::Vector3 l, + Ogre::Vector3 h, Ogre::Vector3 sr, const Ogre::String &eventname, + const Ogre::String &instancename, bool forcecam, Ogre::Vector3 campos, + Ogre::Vector3 sc /* = Vector3::UNIT_SCALE */, Ogre::Vector3 dr /* = Vector3::ZERO */, + int event_filter /* = EVENT_ALL */, int scripthandler /* = -1 */) { - Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); - Quaternion direction = Quaternion(Degree(dr.x), Vector3::UNIT_X) * Quaternion(Degree(dr.y), Vector3::UNIT_Y) * Quaternion(Degree(dr.z), Vector3::UNIT_Z); - int coll_box_index = this->GetNumCollisionBoxes(); + Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z); + Quaternion direction = Quaternion(Degree(dr.x), Vector3::UNIT_X) * Quaternion(Degree(dr.y), Vector3::UNIT_Y) * + Quaternion(Degree(dr.z), Vector3::UNIT_Z); + int coll_box_index = this->GetNumCollisionBoxes(); collision_box_t coll_box; coll_box.enabled = true; - + // set refined box anyway - coll_box.relo = l*sc; - coll_box.rehi = h*sc; + coll_box.relo = l * sc; + coll_box.rehi = h * sc; // calculate selfcenter anyway - coll_box.selfcenter = coll_box.relo; + coll_box.selfcenter = coll_box.relo; coll_box.selfcenter += coll_box.rehi; coll_box.selfcenter *= 0.5; - + // and center too (we need it) - coll_box.center = pos; - coll_box.virt = virt; + coll_box.center = pos; + coll_box.virt = virt; coll_box.event_filter = event_filter; // camera stuff coll_box.camforced = forcecam; - if (forcecam) - { - coll_box.campos = coll_box.center + rotation * campos; - } + if (forcecam) { coll_box.campos = coll_box.center + rotation * campos; } // first, self-rotate if (rotating) { // we have a self-rotated block coll_box.selfrotated = true; - coll_box.selfrot = Quaternion(Degree(sr.x), Vector3::UNIT_X) * Quaternion(Degree(sr.y), Vector3::UNIT_Y) * Quaternion(Degree(sr.z), Vector3::UNIT_Z); - coll_box.selfunrot = coll_box.selfrot.Inverse(); - } else + coll_box.selfrot = Quaternion(Degree(sr.x), Vector3::UNIT_X) * Quaternion(Degree(sr.y), Vector3::UNIT_Y) * + Quaternion(Degree(sr.z), Vector3::UNIT_Z); + coll_box.selfunrot = coll_box.selfrot.Inverse(); + } + else { coll_box.selfrotated = false; } @@ -442,16 +426,16 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec if (!eventname.empty()) { - //LOG("COLL: adding "+TOSTRING(free_eventsource)+" "+String(instancename)+" "+String(eventname)); + // LOG("COLL: adding "+TOSTRING(free_eventsource)+" "+String(instancename)+" "+String(eventname)); // this is event-generating strcpy(eventsources[free_eventsource].boxname, eventname.c_str()); strcpy(eventsources[free_eventsource].instancename, instancename.c_str()); eventsources[free_eventsource].scripthandler = scripthandler; - eventsources[free_eventsource].cbox = coll_box_index; - eventsources[free_eventsource].snode = tenode; - eventsources[free_eventsource].direction = direction; - eventsources[free_eventsource].enabled = true; - coll_box.eventsourcenum = free_eventsource; + eventsources[free_eventsource].cbox = coll_box_index; + eventsources[free_eventsource].snode = tenode; + eventsources[free_eventsource].direction = direction; + eventsources[free_eventsource].enabled = true; + coll_box.eventsourcenum = free_eventsource; free_eventsource++; } @@ -460,7 +444,8 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec { // unrefined box coll_box.refined = false; - } else + } + else { // refined box coll_box.refined = true; @@ -470,11 +455,8 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec } SceneNode *debugsn = 0; - - if (debugMode) - { - debugsn = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - } + + if (debugMode) { debugsn = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); } // set raw box // 8 points of a cube @@ -489,61 +471,74 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec cube_points[5] = Ogre::Vector3(h.x, l.y, h.z) * sc; cube_points[6] = Ogre::Vector3(l.x, h.y, h.z) * sc; cube_points[7] = Ogre::Vector3(h.x, h.y, h.z) * sc; - + // rotate box if (coll_box.selfrotated) - for (int i=0; i < 8; i++) - { - cube_points[i]=cube_points[i]-coll_box.selfcenter; - cube_points[i]=coll_box.selfrot*cube_points[i]; - cube_points[i]=cube_points[i]+coll_box.selfcenter; - } - if (coll_box.refined) + for (int i = 0; i < 8; i++) { - for (int i=0; i < 8; i++) - { - cube_points[i] = coll_box.rot * cube_points[i]; - } + cube_points[i] = cube_points[i] - coll_box.selfcenter; + cube_points[i] = coll_box.selfrot * cube_points[i]; + cube_points[i] = cube_points[i] + coll_box.selfcenter; } - // find min/max - coll_box.lo = cube_points[0]; - coll_box.hi = cube_points[0]; - for (int i=1; i < 8; i++) + if (coll_box.refined) + { + for (int i = 0; i < 8; i++) { - coll_box.lo.makeFloor(cube_points[i]); - coll_box.hi.makeCeil(cube_points[i]); + cube_points[i] = coll_box.rot * cube_points[i]; } - // set absolute coords - coll_box.lo += pos; - coll_box.hi += pos; - } else + } + // find min/max + coll_box.lo = cube_points[0]; + coll_box.hi = cube_points[0]; + for (int i = 1; i < 8; i++) + { + coll_box.lo.makeFloor(cube_points[i]); + coll_box.hi.makeCeil(cube_points[i]); + } + // set absolute coords + coll_box.lo += pos; + coll_box.hi += pos; + } + else { // unrefined box - coll_box.lo = pos + coll_box.relo; - coll_box.hi = pos + coll_box.rehi; - Vector3 d = (coll_box.rehi - coll_box.relo); + coll_box.lo = pos + coll_box.relo; + coll_box.hi = pos + coll_box.rehi; + Vector3 d = (coll_box.rehi - coll_box.relo); cube_points[0] = coll_box.relo; - cube_points[1] = coll_box.relo; cube_points[1].x += d.x; - cube_points[2] = coll_box.relo; cube_points[2].y += d.y; - cube_points[3] = coll_box.relo; cube_points[3].x += d.x; cube_points[3].y += d.y; - cube_points[4] = coll_box.relo; cube_points[4].z += d.z; - cube_points[5] = coll_box.relo; cube_points[5].x += d.x; cube_points[5].z += d.z; - cube_points[6] = coll_box.relo; cube_points[6].y += d.y; cube_points[6].z += d.z; - cube_points[7] = coll_box.relo; cube_points[7].x += d.x; cube_points[7].y += d.y; cube_points[7].z += d.z; + cube_points[1] = coll_box.relo; + cube_points[1].x += d.x; + cube_points[2] = coll_box.relo; + cube_points[2].y += d.y; + cube_points[3] = coll_box.relo; + cube_points[3].x += d.x; + cube_points[3].y += d.y; + cube_points[4] = coll_box.relo; + cube_points[4].z += d.z; + cube_points[5] = coll_box.relo; + cube_points[5].x += d.x; + cube_points[5].z += d.z; + cube_points[6] = coll_box.relo; + cube_points[6].y += d.y; + cube_points[6].z += d.z; + cube_points[7] = coll_box.relo; + cube_points[7].x += d.x; + cube_points[7].y += d.y; + cube_points[7].z += d.z; } if (debugsn) { debugsn->setPosition(pos); // box content - ManualObject *mo = gEnv->sceneManager->createManualObject(); - String matName = "tracks/debug/collision/box"; + ManualObject *mo = gEnv->sceneManager->createManualObject(); + String matName = "tracks/debug/collision/box"; if (virt && scripthandler == -1) matName = "tracks/debug/eventbox/unused"; else if (virt) matName = "tracks/debug/eventbox/used"; AxisAlignedBox *aa = new AxisAlignedBox(); - for (int i=0; i < 8; i++) + for (int i = 0; i < 8; i++) { aa->merge(cube_points[i]); } @@ -558,23 +553,23 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec mo->position(cube_points[7]); // front - mo->triangle(0,1,2); - mo->triangle(1,3,2); + mo->triangle(0, 1, 2); + mo->triangle(1, 3, 2); // right side - mo->triangle(3,1,5); - mo->triangle(5,7,3); + mo->triangle(3, 1, 5); + mo->triangle(5, 7, 3); // left side - mo->triangle(6,4,0); - mo->triangle(0,2,6); + mo->triangle(6, 4, 0); + mo->triangle(0, 2, 6); // back side - mo->triangle(7,5,4); - mo->triangle(4,6,7); + mo->triangle(7, 5, 4); + mo->triangle(4, 6, 7); // bottom - mo->triangle(5,4,1); - mo->triangle(4,0,1); + mo->triangle(5, 4, 1); + mo->triangle(4, 0, 1); // top - mo->triangle(2,3,6); - mo->triangle(3,7,6); + mo->triangle(2, 3, 6); + mo->triangle(3, 7, 6); mo->end(); mo->setBoundingBox(*aa); @@ -592,29 +587,56 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec mo->position(cube_points[5]); mo->position(cube_points[6]); mo->position(cube_points[7]); - //front - mo->index(0);mo->index(1); mo->index(1);mo->index(3); mo->index(3);mo->index(2); mo->index(2);mo->index(0); + // front + mo->index(0); + mo->index(1); + mo->index(1); + mo->index(3); + mo->index(3); + mo->index(2); + mo->index(2); + mo->index(0); // right side - mo->index(1);mo->index(5); mo->index(5);mo->index(7); mo->index(7);mo->index(3); mo->index(3);mo->index(1); + mo->index(1); + mo->index(5); + mo->index(5); + mo->index(7); + mo->index(7); + mo->index(3); + mo->index(3); + mo->index(1); // left side - mo->index(0);mo->index(2); mo->index(2);mo->index(6); mo->index(6);mo->index(4); mo->index(4);mo->index(0); + mo->index(0); + mo->index(2); + mo->index(2); + mo->index(6); + mo->index(6); + mo->index(4); + mo->index(4); + mo->index(0); // back side - mo->index(5);mo->index(4); mo->index(4);mo->index(6); mo->index(6);mo->index(7); mo->index(7);mo->index(5); + mo->index(5); + mo->index(4); + mo->index(4); + mo->index(6); + mo->index(6); + mo->index(7); + mo->index(7); + mo->index(5); // bottom and top not needed mo->end(); mo->setBoundingBox(*aa); debugsn->attachObject(mo); mo->setRenderingDistance(200); - delete(aa); + delete (aa); // label // setup a label if (virt) { - String labelName = "collision_box_label_"+TOSTRING(coll_box_index); - String labelCaption = "EVENTBOX\nevent:"+String(eventname) + "\ninstance:" + String(instancename); - if (scripthandler != -1) - labelCaption += "\nhandler:" + TOSTRING(scripthandler); + String labelName = "collision_box_label_" + TOSTRING(coll_box_index); + String labelCaption = "EVENTBOX\nevent:" + String(eventname) + "\ninstance:" + String(instancename); + if (scripthandler != -1) labelCaption += "\nhandler:" + TOSTRING(scripthandler); MovableText *mt = new MovableText(labelName, labelCaption); mt->setTextAlignment(MovableText::H_CENTER, MovableText::V_ABOVE); mt->setFontName("CyberbitEnglish"); @@ -632,7 +654,7 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec // register this collision box in the index Vector3 ilo = Ogre::Vector3(coll_box.lo / Ogre::Real(CELL_SIZE)); Vector3 ihi = Ogre::Vector3(coll_box.hi / Ogre::Real(CELL_SIZE)); - + // clamp between 0 and MAXIMUM_CELL; ilo.makeCeil(Ogre::Vector3(0.0f)); ilo.makeFloor(Ogre::Vector3(MAXIMUM_CELL)); @@ -643,7 +665,7 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec { for (int j = ilo.z; j <= ihi.z; j++) { - hash_add(i, j, coll_box_index,coll_box.hi.y); + hash_add(i, j, coll_box_index, coll_box.hi.y); } } @@ -652,26 +674,26 @@ int Collisions::addCollisionBox(SceneNode *tenode, bool rotating, bool virt, Vec return coll_box_index; } -int Collisions::addCollisionTri(Vector3 p1, Vector3 p2, Vector3 p3, ground_model_t* gm) +int Collisions::addCollisionTri(Vector3 p1, Vector3 p2, Vector3 p3, ground_model_t *gm) { - int new_tri_index = this->GetNumCollisionTris(); + int new_tri_index = this->GetNumCollisionTris(); collision_tri_t new_tri; - new_tri.a=p1; - new_tri.b=p2; - new_tri.c=p3; - new_tri.gm=gm; - new_tri.enabled=true; + new_tri.a = p1; + new_tri.b = p2; + new_tri.c = p3; + new_tri.gm = gm; + new_tri.enabled = true; // compute transformations // base construction - Vector3 bx=p2-p1; - Vector3 by=p3-p1; - Vector3 bz=bx.crossProduct(by); + Vector3 bx = p2 - p1; + Vector3 by = p3 - p1; + Vector3 bz = bx.crossProduct(by); bz.normalise(); // coordinates change matrix new_tri.reverse.SetColumn(0, bx); new_tri.reverse.SetColumn(1, by); new_tri.reverse.SetColumn(2, bz); - new_tri.forward=new_tri.reverse.Inverse(); + new_tri.forward = new_tri.reverse.Inverse(); // compute tri AAB new_tri.aab.merge(p1); @@ -679,25 +701,25 @@ int Collisions::addCollisionTri(Vector3 p1, Vector3 p2, Vector3 p3, ground_model new_tri.aab.merge(p3); new_tri.aab.setMinimum(new_tri.aab.getMinimum() - 0.1f); new_tri.aab.setMaximum(new_tri.aab.getMaximum() + 0.1f); - + // register this collision tri in the index Ogre::Vector3 ilo(new_tri.aab.getMinimum() / Ogre::Real(CELL_SIZE)); Ogre::Vector3 ihi(new_tri.aab.getMaximum() / Ogre::Real(CELL_SIZE)); - + // clamp between 0 and MAXIMUM_CELL; ilo.makeCeil(Ogre::Vector3(0.0f)); ilo.makeFloor(Ogre::Vector3(MAXIMUM_CELL)); ihi.makeCeil(Ogre::Vector3(0.0f)); ihi.makeFloor(Ogre::Vector3(MAXIMUM_CELL)); - + for (int i = ilo.x; i <= ihi.x; i++) { - for (int j = ilo.z; j<=ihi.z; j++) + for (int j = ilo.z; j <= ihi.z; j++) { hash_add(i, j, new_tri_index + hash_coll_element_t::ELEMENT_TRI_BASE_INDEX, new_tri.aab.getMaximum().y); } } - + if (debugMode) { debugmo->position(p1); @@ -716,18 +738,18 @@ bool Collisions::envokeScriptCallback(collision_box_t *cbox, node_t *node) #ifdef USE_ANGELSCRIPT // check if this box is active anymore - if (!eventsources[cbox->eventsourcenum].enabled) - return false; - + if (!eventsources[cbox->eventsourcenum].enabled) return false; + std::lock_guard lock(m_scriptcallback_mutex); // this prevents that the same callback gets called at 2k FPS all the time, serious hit on FPS ... if (std::find(std::begin(m_last_called_cboxes), std::end(m_last_called_cboxes), cbox) == m_last_called_cboxes.end()) { - if (!ScriptEngine::getSingleton().envokeCallback(eventsources[cbox->eventsourcenum].scripthandler, &eventsources[cbox->eventsourcenum], node)) + if (!ScriptEngine::getSingleton().envokeCallback(eventsources[cbox->eventsourcenum].scripthandler, + &eventsources[cbox->eventsourcenum], node)) handled = true; m_last_called_cboxes.push_back(cbox); } -#endif //USE_ANGELSCRIPT +#endif // USE_ANGELSCRIPT return handled; } @@ -747,8 +769,7 @@ std::pair Collisions::intersectsTris(Ogre::Ray ray) int refz = (int)(pos.z / (float)CELL_SIZE); int hash = hash_find(refx, refz); - if (hash == lhash) - continue; + if (hash == lhash) continue; lhash = hash; @@ -757,17 +778,13 @@ std::pair Collisions::intersectsTris(Ogre::Ray ray) { if (hashtable[hash][k].IsCollisionTri()) { - const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; - collision_tri_t *ctri = &m_collision_tris[ctri_index]; + const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; + collision_tri_t *ctri = &m_collision_tris[ctri_index]; - if (!ctri->enabled) - continue; + if (!ctri->enabled) continue; auto result = Ogre::Math::intersects(ray, ctri->a, ctri->b, ctri->c); - if (result.first && result.second < 1.0f) - { - return result; - } + if (result.first && result.second < 1.0f) { return result; } } } } @@ -790,17 +807,16 @@ float Collisions::getSurfaceHeightBelow(float x, float z, float height) int hash = hash_find(refx, refz); Vector3 origin = Vector3(x, hashtable_height[hash], z); - Ray ray(origin, -Vector3::UNIT_Y); + Ray ray(origin, -Vector3::UNIT_Y); size_t num_elements = hashtable[hash].size(); for (size_t k = 0; k < num_elements; k++) { if (hashtable[hash][k].IsCollisionBox()) { - collision_box_t* cbox = &m_collision_boxes[hashtable[hash][k].element_index]; + collision_box_t *cbox = &m_collision_boxes[hashtable[hash][k].element_index]; - if (!cbox->enabled) - continue; + if (!cbox->enabled) continue; if (!cbox->virt && surface_height < cbox->hi.y) { @@ -824,45 +840,30 @@ float Collisions::getSurfaceHeightBelow(float x, float z, float height) if (result.first) { Vector3 hit = pos + dir * result.second; - if (cbox->selfrotated) - { - hit = cbox->selfrot * hit; - } - if (cbox->refined) - { - hit = cbox->rot * hit; - } + if (cbox->selfrotated) { hit = cbox->selfrot * hit; } + if (cbox->refined) { hit = cbox->rot * hit; } hit += cbox->center; - if (hit.y < height) - { - surface_height = std::max(surface_height, hit.y); - } + if (hit.y < height) { surface_height = std::max(surface_height, hit.y); } } } } } else // The element is a triangle { - const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; - collision_tri_t *ctri = &m_collision_tris[ctri_index]; + const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; + collision_tri_t *ctri = &m_collision_tris[ctri_index]; - if (!ctri->enabled) - continue; + if (!ctri->enabled) continue; auto lo = ctri->aab.getMinimum(); auto hi = ctri->aab.getMaximum(); - if (surface_height >= hi.y) - continue; - if (x < lo.x || z < lo.z || x > hi.x || z > hi.z) - continue; + if (surface_height >= hi.y) continue; + if (x < lo.x || z < lo.z || x > hi.x || z > hi.z) continue; auto result = Ogre::Math::intersects(ray, ctri->a, ctri->b, ctri->c); if (result.first) { - if (origin.y - result.second < height) - { - surface_height = std::max(surface_height, origin.y - result.second); - } + if (origin.y - result.second < height) { surface_height = std::max(surface_height, origin.y - result.second); } } } } @@ -877,14 +878,13 @@ bool Collisions::collisionCorrect(Vector3 *refpos, bool envokeScriptCallbacks) int refz = (int)(refpos->z / (float)CELL_SIZE); int hash = hash_find(refx, refz); - if (refpos->y > hashtable_height[hash]) - return false; + if (refpos->y > hashtable_height[hash]) return false; - collision_tri_t *minctri = 0; - float minctridist = 100.0f; - Vector3 minctripoint; + collision_tri_t *minctri = 0; + float minctridist = 100.0f; + Vector3 minctripoint; - bool contacted = false; + bool contacted = false; bool isScriptCallbackEnvoked = false; size_t num_elements = hashtable[hash].size(); @@ -892,21 +892,16 @@ bool Collisions::collisionCorrect(Vector3 *refpos, bool envokeScriptCallbacks) { if (hashtable[hash][k].IsCollisionBox()) { - collision_box_t* cbox = &m_collision_boxes[hashtable[hash][k].element_index]; + collision_box_t *cbox = &m_collision_boxes[hashtable[hash][k].element_index]; - if (!cbox->enabled) - continue; - if (!(*refpos > cbox->lo && *refpos < cbox->hi)) - continue; + if (!cbox->enabled) continue; + if (!(*refpos > cbox->lo && *refpos < cbox->hi)) continue; if (cbox->refined || cbox->selfrotated) { // we may have a collision, do a change of repere Vector3 Pos = *refpos - cbox->center; - if (cbox->refined) - { - Pos = cbox->unrot * Pos; - } + if (cbox->refined) { Pos = cbox->unrot * Pos; } if (cbox->selfrotated) { Pos = Pos - cbox->selfcenter; @@ -916,14 +911,14 @@ bool Collisions::collisionCorrect(Vector3 *refpos, bool envokeScriptCallbacks) // now test with the inner box if (Pos > cbox->relo && Pos < cbox->rehi) { - if (cbox->eventsourcenum!=-1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) + if (cbox->eventsourcenum != -1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) { envokeScriptCallback(cbox); isScriptCallbackEnvoked = true; } if (cbox->camforced && !forcecam) { - forcecam = true; + forcecam = true; forcecampos = cbox->campos; } if (!cbox->virt) @@ -933,7 +928,7 @@ bool Collisions::collisionCorrect(Vector3 *refpos, bool envokeScriptCallbacks) contacted = true; // determine which side collided Pos = calcCollidedSide(Pos, cbox->relo, cbox->rehi); - + // resume repere if (cbox->selfrotated) { @@ -941,24 +936,21 @@ bool Collisions::collisionCorrect(Vector3 *refpos, bool envokeScriptCallbacks) Pos = cbox->selfrot * Pos; Pos = Pos + cbox->selfcenter; } - if (cbox->refined) - { - Pos = cbox->rot * Pos; - } + if (cbox->refined) { Pos = cbox->rot * Pos; } *refpos = Pos + cbox->center; } } - - } else + } + else { - if (cbox->eventsourcenum!=-1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) + if (cbox->eventsourcenum != -1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) { envokeScriptCallback(cbox); isScriptCallbackEnvoked = true; } if (cbox->camforced && !forcecam) { - forcecam = true; + forcecam = true; forcecampos = cbox->campos; } if (!cbox->virt) @@ -972,30 +964,27 @@ bool Collisions::collisionCorrect(Vector3 *refpos, bool envokeScriptCallbacks) } else // The element is a triangle { - const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; - collision_tri_t *ctri = &m_collision_tris[ctri_index]; - if (!ctri->enabled) - continue; - if (!ctri->aab.contains(*refpos)) - continue; + const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; + collision_tri_t *ctri = &m_collision_tris[ctri_index]; + if (!ctri->enabled) continue; + if (!ctri->aab.contains(*refpos)) continue; // check if this tri is minimal // transform - Vector3 point = ctri->forward * (*refpos-ctri->a); + Vector3 point = ctri->forward * (*refpos - ctri->a); // test if within tri collision volume (potential cause of bug!) if (point.x >= 0 && point.y >= 0 && (point.x + point.y) <= 1.0 && point.z < 0 && point.z > -0.1) { if (-point.z < minctridist) { - minctri = ctri; - minctridist = -point.z; + minctri = ctri; + minctridist = -point.z; minctripoint = point; } } } } - if (envokeScriptCallbacks && !isScriptCallbackEnvoked) - clearEventCache(); + if (envokeScriptCallbacks && !isScriptCallbackEnvoked) clearEventCache(); // process minctri collision if (minctri) @@ -1016,65 +1005,50 @@ bool Collisions::permitEvent(int filter) switch (filter) { - case EVENT_ALL: - return true; - case EVENT_AVATAR: - return !b; - case EVENT_TRUCK: - return b && b->ar_driveable == TRUCK; - case EVENT_AIRPLANE: - return b && b->ar_driveable == AIRPLANE; - case EVENT_BOAT: - return b && b->ar_driveable == BOAT; - case EVENT_DELETE: - return !b; - default: - return false; + case EVENT_ALL: return true; + case EVENT_AVATAR: return !b; + case EVENT_TRUCK: return b && b->ar_driveable == TRUCK; + case EVENT_AIRPLANE: return b && b->ar_driveable == AIRPLANE; + case EVENT_BOAT: return b && b->ar_driveable == BOAT; + case EVENT_DELETE: return !b; + default: return false; } } bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallbacks) { // find the correct cell - int refx = (int)(node->AbsPosition.x / CELL_SIZE); - int refz = (int)(node->AbsPosition.z / CELL_SIZE); - int hash = hash_find(refx, refz); + int refx = (int)(node->AbsPosition.x / CELL_SIZE); + int refz = (int)(node->AbsPosition.z / CELL_SIZE); + int hash = hash_find(refx, refz); unsigned int cell_id = (refx << 16) + refz; - if (node->AbsPosition.y > hashtable_height[hash]) - return false; + if (node->AbsPosition.y > hashtable_height[hash]) return false; - collision_tri_t *minctri = 0; - float minctridist = 100.0; - Vector3 minctripoint; + collision_tri_t *minctri = 0; + float minctridist = 100.0; + Vector3 minctripoint; - bool contacted = false; + bool contacted = false; bool isScriptCallbackEnvoked = false; size_t num_elements = hashtable[hash].size(); - for (size_t k=0; k < num_elements; k++) + for (size_t k = 0; k < num_elements; k++) { - if (hashtable[hash][k].cell_id != cell_id) - { - continue; - } + if (hashtable[hash][k].cell_id != cell_id) { continue; } else if (hashtable[hash][k].IsCollisionBox()) { collision_box_t *cbox = &m_collision_boxes[hashtable[hash][k].element_index]; - if (!cbox->enabled) - continue; + if (!cbox->enabled) continue; if (node->AbsPosition > cbox->lo && node->AbsPosition < cbox->hi) { if (cbox->refined || cbox->selfrotated) { // we may have a collision, do a change of repere - Vector3 Pos = node->AbsPosition-cbox->center; - if (cbox->refined) - { - Pos = cbox->unrot * Pos; - } + Vector3 Pos = node->AbsPosition - cbox->center; + if (cbox->refined) { Pos = cbox->unrot * Pos; } if (cbox->selfrotated) { Pos = Pos - cbox->selfcenter; @@ -1084,14 +1058,14 @@ bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallback // now test with the inner box if (Pos > cbox->relo && Pos < cbox->rehi) { - if (cbox->eventsourcenum!=-1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) + if (cbox->eventsourcenum != -1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) { envokeScriptCallback(cbox, node); isScriptCallbackEnvoked = true; } if (cbox->camforced && !forcecam) { - forcecam = true; + forcecam = true; forcecampos = cbox->campos; } if (!cbox->virt && !envokeScriptCallbacks) @@ -1100,18 +1074,38 @@ bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallback // we have a collision contacted = true; // determine which side collided - float t = cbox->rehi.z - Pos.z; - float min = Pos.z - cbox->relo.z; + float t = cbox->rehi.z - Pos.z; + float min = Pos.z - cbox->relo.z; Vector3 normal = Vector3(0, 0, -1); - if (t < min) { min = t; normal = Vector3(0,0,1);}; //north + if (t < min) + { + min = t; + normal = Vector3(0, 0, 1); + }; // north t = Pos.x - cbox->relo.x; - if (t < min) { min = t; normal = Vector3(-1,0,0);}; //west + if (t < min) + { + min = t; + normal = Vector3(-1, 0, 0); + }; // west t = cbox->rehi.x - Pos.x; - if (t < min) { min = t; normal = Vector3(1,0,0);}; //east + if (t < min) + { + min = t; + normal = Vector3(1, 0, 0); + }; // east t = Pos.y - cbox->relo.y; - if (t < min) { min = t; normal = Vector3(0,-1,0);}; //down + if (t < min) + { + min = t; + normal = Vector3(0, -1, 0); + }; // down t = cbox->rehi.y - Pos.y; - if (t < min) { min = t; normal = Vector3(0,1,0);}; //up + if (t < min) + { + min = t; + normal = Vector3(0, 1, 0); + }; // up // resume repere for the normal if (cbox->selfrotated) normal = cbox->selfrot * normal; @@ -1122,35 +1116,56 @@ bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallback node->nd_last_collision_gm = defaultgm; } } - } else + } + else { - if (cbox->eventsourcenum!=-1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) + if (cbox->eventsourcenum != -1 && permitEvent(cbox->event_filter) && envokeScriptCallbacks) { envokeScriptCallback(cbox, node); isScriptCallbackEnvoked = true; } if (cbox->camforced && !forcecam) { - forcecam = true; + forcecam = true; forcecampos = cbox->campos; } if (!cbox->virt && !envokeScriptCallbacks) { // we have a collision - contacted=true; + contacted = true; // determine which side collided - float t = cbox->hi.z - node->AbsPosition.z; - float min = node->AbsPosition.z - cbox->lo.z; + float t = cbox->hi.z - node->AbsPosition.z; + float min = node->AbsPosition.z - cbox->lo.z; Vector3 normal = Vector3(0, 0, -1); - if (t < min) {min = t; normal = Vector3(0,0,1);}; //north + if (t < min) + { + min = t; + normal = Vector3(0, 0, 1); + }; // north t = node->AbsPosition.x - cbox->lo.x; - if (t < min) {min = t; normal = Vector3(-1,0,0);}; //west + if (t < min) + { + min = t; + normal = Vector3(-1, 0, 0); + }; // west t = cbox->hi.x - node->AbsPosition.x; - if (t < min) {min = t; normal = Vector3(1,0,0);}; //east + if (t < min) + { + min = t; + normal = Vector3(1, 0, 0); + }; // east t = node->AbsPosition.y - cbox->lo.y; - if (t < min) {min = t; normal = Vector3(0,-1,0);}; //down + if (t < min) + { + min = t; + normal = Vector3(0, -1, 0); + }; // down t = cbox->hi.y - node->AbsPosition.y; - if (t < min) {min = t; normal = Vector3(0,1,0);}; //up + if (t < min) + { + min = t; + normal = Vector3(0, 1, 0); + }; // up // resume repere for the normal if (cbox->selfrotated) normal = cbox->selfrot * normal; @@ -1166,10 +1181,9 @@ bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallback else { // tri collision - const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; - collision_tri_t *ctri = &m_collision_tris[ctri_index]; - if (!ctri->enabled) - continue; + const int ctri_index = hashtable[hash][k].element_index - hash_coll_element_t::ELEMENT_TRI_BASE_INDEX; + collision_tri_t *ctri = &m_collision_tris[ctri_index]; + if (!ctri->enabled) continue; if (node->AbsPosition.y > ctri->aab.getMaximum().y || node->AbsPosition.y < ctri->aab.getMinimum().y || node->AbsPosition.x > ctri->aab.getMaximum().x || node->AbsPosition.x < ctri->aab.getMinimum().x || node->AbsPosition.z > ctri->aab.getMaximum().z || node->AbsPosition.z < ctri->aab.getMinimum().z) @@ -1182,22 +1196,21 @@ bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallback { if (-point.z < minctridist) { - minctri = ctri; - minctridist = -point.z; + minctri = ctri; + minctridist = -point.z; minctripoint = point; } } } } - if (envokeScriptCallbacks && !isScriptCallbackEnvoked) - clearEventCache(); + if (envokeScriptCallbacks && !isScriptCallbackEnvoked) clearEventCache(); // process minctri collision if (minctri && !envokeScriptCallbacks) { // we have a contact - contacted=true; + contacted = true; // we need the normal // resume repere for the normal Vector3 normal = minctri->reverse * Vector3::UNIT_Z; @@ -1208,14 +1221,14 @@ bool Collisions::nodeCollision(node_t *node, float dt, bool envokeScriptCallback return contacted; } - Vector3 Collisions::getPosition(const Ogre::String &inst, const Ogre::String &box) { - for (int i=0; i cbox->lo - && pos - border < cbox->hi) + + if (pos + border > cbox->lo && pos - border < cbox->hi) { if (cbox->refined || cbox->selfrotated) { // we may have a collision, do a change of repere Vector3 rpos = pos - cbox->center; - if (cbox->refined) - { - rpos = cbox->unrot * rpos; - } + if (cbox->refined) { rpos = cbox->unrot * rpos; } if (cbox->selfrotated) { rpos = rpos - cbox->selfcenter; rpos = cbox->selfunrot * rpos; rpos = rpos + cbox->selfcenter; } - + // now test with the inner box - if (rpos > cbox->relo - && rpos < cbox->rehi) - { - return true; - } - } else + if (rpos > cbox->relo && rpos < cbox->rehi) { return true; } + } + else { return true; } @@ -1293,7 +1295,7 @@ bool Collisions::groundCollision(node_t *node, float dt) Real v = App::GetSimTerrain()->GetHeightAt(node->AbsPosition.x, node->AbsPosition.z); if (v > node->AbsPosition.y) { - ground_model_t* ogm = landuse ? landuse->getGroundModelAt(node->AbsPosition.x, node->AbsPosition.z) : nullptr; + ground_model_t *ogm = landuse ? landuse->getGroundModelAt(node->AbsPosition.x, node->AbsPosition.z) : nullptr; // when landuse fails or we don't have it, use the default value if (!ogm) ogm = defaultgroundgm; Ogre::Vector3 normal = App::GetSimTerrain()->GetNormalAt(node->AbsPosition.x, v, node->AbsPosition.z); @@ -1304,11 +1306,12 @@ bool Collisions::groundCollision(node_t *node, float dt) return false; } -Vector3 primitiveCollision(node_t *node, Vector3 velocity, float mass, Vector3 normal, float dt, ground_model_t* gm, float penetration) +Vector3 primitiveCollision(node_t *node, Vector3 velocity, float mass, Vector3 normal, float dt, ground_model_t *gm, + float penetration) { - Vector3 force = Vector3::ZERO; - float Vnormal = velocity.dotProduct(normal); - float Fnormal = node->Forces.dotProduct(normal); + Vector3 force = Vector3::ZERO; + float Vnormal = velocity.dotProduct(normal); + float Fnormal = node->Forces.dotProduct(normal); // if we are inside the fluid (solid ground is below us) if (gm->solid_ground_level != 0.0f && penetration >= 0) @@ -1339,10 +1342,7 @@ Vector3 primitiveCollision(node_t *node, Vector3 velocity, float mass, Vector3 n float Fboyancy = gm->fluid_density * penetration * (-DEFAULT_GRAVITY) * node->volume_coef; if (gm->flow_behavior_index < 1.0f && Vnormal >= 0.0f) { - if (Fnormal < 0 && Fboyancy>-Fnormal) - { - Fboyancy = -Fnormal; - } + if (Fnormal < 0 && Fboyancy > -Fnormal) { Fboyancy = -Fnormal; } } force += Fboyancy * normal; } @@ -1361,28 +1361,29 @@ Vector3 primitiveCollision(node_t *node, Vector3 velocity, float mass, Vector3 n if (Freaction > 0) { Vector3 slipf = node->Forces - Fnormal * normal; - Vector3 slip = velocity - Vnormal * normal; - float slipv = slip.normalise(); + Vector3 slip = velocity - Vnormal * normal; + float slipv = slip.normalise(); // If the velocity that we slip is lower than adhesion velocity and // we have a downforce and the slip forces are lower than static friction // forces then it's time to go into static friction physics mode. // This code is a direct translation of textbook static friction physics - float Greaction = Freaction * gm->strength * node->friction_coef; //General moderated reaction + float Greaction = Freaction * gm->strength * node->friction_coef; // General moderated reaction float msGreaction = gm->ms * Greaction; if (slipv < gm->va && Greaction > 0.0f && slipf.squaredLength() <= msGreaction * msGreaction) { // Static friction model (with a little smoothing to help the integrator deal with it) float ff = -msGreaction * (1.0f - approx_exp(-slipv / gm->va)); force += Freaction * normal + ff * slip - slipf; - } else + } + else { // Stribek model. It also comes directly from textbooks. - float g = gm->mc + (gm->ms - gm->mc) * approx_exp(-approx_pow(slipv / gm->vs, gm->alpha)); + float g = gm->mc + (gm->ms - gm->mc) * approx_exp(-approx_pow(slipv / gm->vs, gm->alpha)); float ff = -(g + std::min(gm->t2 * slipv, 5.0f)) * Greaction; force += Freaction * normal + ff * slip; } - node->nd_avg_collision_slip = node->nd_avg_collision_slip * 0.995 + slipv * 0.005f; - node->nd_last_collision_slip = slipv * slip; + node->nd_avg_collision_slip = node->nd_avg_collision_slip * 0.995 + slipv * 0.005f; + node->nd_last_collision_slip = slipv * slip; node->nd_last_collision_force = std::min(-Freaction, 0.0f) * normal; } } @@ -1399,16 +1400,18 @@ int Collisions::createCollisionDebugVisualization() if (loaded != 0) return -1; // create materials - int i = 0; + int i = 0; char bname[256]; - for (i=0;i<=100;i++) + for (i = 0; i <= 100; i++) { // register a material for skeleton view sprintf(bname, "mat-coll-dbg-%d", i); - MaterialPtr mat=(MaterialPtr)(MaterialManager::getSingleton().create(bname, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)); - float f = fabs(((float)i)/100); + MaterialPtr mat = + (MaterialPtr)(MaterialManager::getSingleton().create(bname, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)); + float f = fabs(((float)i) / 100); Pass *p = mat->getTechnique(0)->getPass(0); // - p->createTextureUnitState()->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, ColourValue(f*2.0, 2.0*(1.0-f), 0.2, 0.7)); + p->createTextureUnitState()->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, + ColourValue(f * 2.0, 2.0 * (1.0 - f), 0.2, 0.7)); p->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); p->setLightingEnabled(false); p->setDepthWriteEnabled(false); @@ -1425,28 +1428,27 @@ int Collisions::createCollisionDebugVisualization() TextureUnitState *tus2 = p2->createTextureUnitState(); tus2->setTextureName("tile.png"); - mat->setLightingEnabled(false); mat->setReceiveShadows(false); } - for (int x=0; x<(int)(m_terrain_size.x); x+=(int)CELL_SIZE) + for (int x = 0; x < (int)(m_terrain_size.x); x += (int)CELL_SIZE) { - for (int z=0; z<(int)(m_terrain_size.z); z+=(int)CELL_SIZE) + for (int z = 0; z < (int)(m_terrain_size.z); z += (int)CELL_SIZE) { - int cellx = (int)(x/(float)CELL_SIZE); - int cellz = (int)(z/(float)CELL_SIZE); - const int hash = hash_find(cellx, cellz); + int cellx = (int)(x / (float)CELL_SIZE); + int cellz = (int)(z / (float)CELL_SIZE); + const int hash = hash_find(cellx, cellz); bool used = std::find_if(hashtable[hash].begin(), hashtable[hash].end(), [&](hash_coll_element_t const &c) { - return c.cell_id == (cellx << 16) + cellz; - }) != hashtable[hash].end(); + return c.cell_id == (cellx << 16) + cellz; + }) != hashtable[hash].end(); if (used) { float groundheight = -9999; - float x2 = x+CELL_SIZE; - float z2 = z+CELL_SIZE; + float x2 = x + CELL_SIZE; + float z2 = z + CELL_SIZE; // find a good ground height for all corners of the cell ... groundheight = std::max(groundheight, App::GetSimTerrain()->GetHeightAt(x, z)); @@ -1458,33 +1460,34 @@ int Collisions::createCollisionDebugVisualization() float percentd = static_cast(hashtable[hash].size()) / static_cast(CELL_BLOCKSIZE); if (percentd > 1) percentd = 1; - String matName = "mat-coll-dbg-"+TOSTRING((int)(percentd*100)); - String cell_name="("+TOSTRING(cellx)+","+ TOSTRING(cellz)+")"; + String matName = "mat-coll-dbg-" + TOSTRING((int)(percentd * 100)); + String cell_name = "(" + TOSTRING(cellx) + "," + TOSTRING(cellz) + ")"; - ManualObject *mo = gEnv->sceneManager->createManualObject("collisionDebugVisualization"+cell_name); - SceneNode *mo_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode("collisionDebugVisualization_node"+cell_name); + ManualObject *mo = gEnv->sceneManager->createManualObject("collisionDebugVisualization" + cell_name); + SceneNode * mo_node = + gEnv->sceneManager->getRootSceneNode()->createChildSceneNode("collisionDebugVisualization_node" + cell_name); mo->begin(matName, Ogre::RenderOperation::OT_TRIANGLE_LIST); // 1st tri - mo->position(-CELL_SIZE/(float)2.0, 0, -CELL_SIZE/(float)2.0); - mo->textureCoord(0,0); + mo->position(-CELL_SIZE / (float)2.0, 0, -CELL_SIZE / (float)2.0); + mo->textureCoord(0, 0); - mo->position(CELL_SIZE/(float)2.0, 0, CELL_SIZE/(float)2.0); - mo->textureCoord(1,1); + mo->position(CELL_SIZE / (float)2.0, 0, CELL_SIZE / (float)2.0); + mo->textureCoord(1, 1); - mo->position(CELL_SIZE/(float)2.0, 0, -CELL_SIZE/(float)2.0); - mo->textureCoord(1,0); + mo->position(CELL_SIZE / (float)2.0, 0, -CELL_SIZE / (float)2.0); + mo->textureCoord(1, 0); // 2nd tri - mo->position(-CELL_SIZE/(float)2.0, 0, CELL_SIZE/(float)2.0); - mo->textureCoord(0,1); + mo->position(-CELL_SIZE / (float)2.0, 0, CELL_SIZE / (float)2.0); + mo->textureCoord(0, 1); - mo->position(CELL_SIZE/(float)2.0, 0, CELL_SIZE/(float)2.0); - mo->textureCoord(1,1); + mo->position(CELL_SIZE / (float)2.0, 0, CELL_SIZE / (float)2.0); + mo->textureCoord(1, 1); - mo->position(-CELL_SIZE/(float)2.0, 0, -CELL_SIZE/(float)2.0); - mo->textureCoord(0,0); + mo->position(-CELL_SIZE / (float)2.0, 0, -CELL_SIZE / (float)2.0); + mo->textureCoord(0, 0); mo->end(); mo->setBoundingBox(AxisAlignedBox(0, 0, 0, CELL_SIZE, 1, CELL_SIZE)); @@ -1504,7 +1507,7 @@ int Collisions::createCollisionDebugVisualization() #endif mo_node->setVisible(true); - mo_node->setPosition(Vector3(x+CELL_SIZE/(float)2.0, groundheight, z+CELL_SIZE/(float)2.0)); + mo_node->setPosition(Vector3(x + CELL_SIZE / (float)2.0, groundheight, z + CELL_SIZE / (float)2.0)); } } } @@ -1513,124 +1516,118 @@ int Collisions::createCollisionDebugVisualization() return 0; } -int Collisions::addCollisionMesh(Ogre::String meshname, Ogre::Vector3 pos, Ogre::Quaternion q, Ogre::Vector3 scale, ground_model_t *gm, std::vector *collTris) +int Collisions::addCollisionMesh(Ogre::String meshname, Ogre::Vector3 pos, Ogre::Quaternion q, Ogre::Vector3 scale, + ground_model_t *gm, std::vector *collTris) { // normal, non virtual collision box Entity *ent = gEnv->sceneManager->createEntity(meshname); ent->setMaterialName("tracks/debug/collision/mesh"); - if (!gm) - { - gm = getGroundModelByString("concrete"); - } + if (!gm) { gm = getGroundModelByString("concrete"); } - size_t vertex_count,index_count; - Vector3* vertices; - unsigned* indices; + size_t vertex_count, index_count; + Vector3 * vertices; + unsigned *indices; - getMeshInformation(ent->getMesh().getPointer(),vertex_count,vertices,index_count,indices, pos, q, scale); + getMeshInformation(ent->getMesh().getPointer(), vertex_count, vertices, index_count, indices, pos, q, scale); - //LOG(LML_NORMAL,"Vertices in mesh: %u",vertex_count); - //LOG(LML_NORMAL,"Triangles in mesh: %u",index_count / 3); - for (int i=0; i<(int)index_count/3; i++) + // LOG(LML_NORMAL,"Vertices in mesh: %u",vertex_count); + // LOG(LML_NORMAL,"Triangles in mesh: %u",index_count / 3); + for (int i = 0; i < (int)index_count / 3; i++) { - int triID = addCollisionTri(vertices[indices[i*3]], vertices[indices[i*3+1]], vertices[indices[i*3+2]], gm); - if (collTris) - collTris->push_back(triID); + int triID = addCollisionTri(vertices[indices[i * 3]], vertices[indices[i * 3 + 1]], vertices[indices[i * 3 + 2]], gm); + if (collTris) collTris->push_back(triID); } delete[] vertices; delete[] indices; - if (!debugMode) + if (!debugMode) { gEnv->sceneManager->destroyEntity(ent); } + else { - gEnv->sceneManager->destroyEntity(ent); - } else - { - SceneNode *n=gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + SceneNode *n = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); n->attachObject(ent); n->setPosition(pos); n->setScale(scale); n->setOrientation(q); - - String labelName = "collision_mesh_label_"+TOSTRING(this->GetNumCollisionTris()); - String labelCaption = "COLLMESH\nmeshname:"+meshname + "\ngroundmodel:" + String(gm->name); - MovableText *mt = new MovableText(labelName, labelCaption); + + String labelName = "collision_mesh_label_" + TOSTRING(this->GetNumCollisionTris()); + String labelCaption = "COLLMESH\nmeshname:" + meshname + "\ngroundmodel:" + String(gm->name); + MovableText *mt = new MovableText(labelName, labelCaption); mt->setTextAlignment(MovableText::H_CENTER, MovableText::V_ABOVE); mt->setFontName("CyberbitEnglish"); mt->setAdditionalHeight(1); mt->setCharacterHeight(0.3); mt->setColor(ColourValue::Black); mt->setRenderingDistance(200); - + n->attachObject(mt); } return 0; } -void Collisions::getMeshInformation(Mesh* mesh,size_t &vertex_count,Vector3* &vertices, - size_t &index_count, unsigned* &indices, - const Vector3 &position, - const Quaternion &orient,const Vector3 &scale) +void Collisions::getMeshInformation(Mesh *mesh, size_t &vertex_count, Vector3 *&vertices, size_t &index_count, unsigned *&indices, + const Vector3 &position, const Quaternion &orient, const Vector3 &scale) { vertex_count = index_count = 0; - bool added_shared = false; + bool added_shared = false; size_t current_offset = vertex_count; - size_t shared_offset = vertex_count; - size_t next_offset = vertex_count; - size_t index_offset = index_count; - //size_t prev_vert = vertex_count; - //size_t prev_ind = index_count; + size_t shared_offset = vertex_count; + size_t next_offset = vertex_count; + size_t index_offset = index_count; + // size_t prev_vert = vertex_count; + // size_t prev_ind = index_count; // Calculate how many vertices and indices we're going to need - for (int i = 0;i < mesh->getNumSubMeshes();i++) + for (int i = 0; i < mesh->getNumSubMeshes(); i++) { - SubMesh* submesh = mesh->getSubMesh(i); + SubMesh *submesh = mesh->getSubMesh(i); // We only need to add the shared vertices once if (submesh->useSharedVertices) { if (!added_shared) { - VertexData* vertex_data = mesh->sharedVertexData; + VertexData *vertex_data = mesh->sharedVertexData; vertex_count += vertex_data->vertexCount; added_shared = true; } - } else + } + else { - VertexData* vertex_data = submesh->vertexData; + VertexData *vertex_data = submesh->vertexData; vertex_count += vertex_data->vertexCount; } // Add the indices - Ogre::IndexData* index_data = submesh->indexData; + Ogre::IndexData *index_data = submesh->indexData; index_count += index_data->indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertex_count]; - indices = new unsigned[index_count]; + indices = new unsigned[index_count]; added_shared = false; // Run through the sub-meshes again, adding the data into the arrays - for (int i = 0;i < mesh->getNumSubMeshes();i++) + for (int i = 0; i < mesh->getNumSubMeshes(); i++) { - SubMesh* submesh = mesh->getSubMesh(i); + SubMesh *submesh = mesh->getSubMesh(i); - Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; - if ((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared)) + Ogre::VertexData *vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; + if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared)) { if (submesh->useSharedVertices) { - added_shared = true; + added_shared = true; shared_offset = current_offset; } - const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + const Ogre::VertexElement *posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); - unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); - Ogre::Real* pReal; + unsigned char *vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + Ogre::Real * pReal; for (size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { @@ -1652,29 +1649,29 @@ void Collisions::getMeshInformation(Mesh* mesh,size_t &vertex_count,Vector3* &ve next_offset += vertex_data->vertexCount; } - Ogre::IndexData* index_data = submesh->indexData; + Ogre::IndexData *index_data = submesh->indexData; + + size_t numTris = index_data->indexCount / 3; + unsigned short * pShort = 0; + unsigned int * pInt = 0; + Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; - size_t numTris = index_data->indexCount / 3; - unsigned short* pShort = 0; - unsigned int* pInt = 0; - Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; - bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); if (use32bitindexes) - pInt = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + pInt = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else - pShort = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + pShort = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for (size_t k = 0; k < numTris; ++k) { - size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset; + size_t offset = (submesh->useSharedVertices) ? shared_offset : current_offset; - unsigned int vindex = use32bitindexes? *pInt++ : *pShort++; + unsigned int vindex = use32bitindexes ? *pInt++ : *pShort++; indices[index_offset + 0] = vindex + (unsigned int)offset; - vindex = use32bitindexes? *pInt++ : *pShort++; + vindex = use32bitindexes ? *pInt++ : *pShort++; indices[index_offset + 1] = vindex + (unsigned int)offset; - vindex = use32bitindexes? *pInt++ : *pShort++; + vindex = use32bitindexes ? *pInt++ : *pShort++; indices[index_offset + 2] = vindex + (unsigned int)offset; index_offset += 3; diff --git a/source/main/physics/collision/Collisions.h b/source/main/physics/collision/Collisions.h index 21c67bb993..d572984081 100644 --- a/source/main/physics/collision/Collisions.h +++ b/source/main/physics/collision/Collisions.h @@ -22,40 +22,37 @@ #pragma once -#include "RoRPrerequisites.h" - #include "BeamData.h" // for collision_box_t +#include "RoRPrerequisites.h" #include struct eventsource_t { - char instancename[256]; - char boxname[256]; - Ogre::SceneNode* snode; + char instancename[256]; + char boxname[256]; + Ogre::SceneNode *snode; Ogre::Quaternion direction; - int scripthandler; - int cbox; - bool enabled; + int scripthandler; + int cbox; + bool enabled; }; class Landusemap; class Collisions : public ZeroedMemoryAllocator { -public: - + public: enum SurfaceType { FX_NONE, - FX_HARD, // hard surface: rubber burning and sparks - FX_DUSTY, // dusty surface (with dust colour) + FX_HARD, // hard surface: rubber burning and sparks + FX_DUSTY, // dusty surface (with dust colour) FX_CLUMPY, // throws clumps (e.g. snow, grass) with colour FX_PARTICLE }; -private: - + private: /// Static collision object lookup system /// ------------------------------------- /// Terrain is split into equal-size 'cells' of dimension CELL_SIZE, identified by CellID @@ -64,10 +61,18 @@ class Collisions : public ZeroedMemoryAllocator { static const int ELEMENT_TRI_BASE_INDEX = 1000000; // Effectively a maximum number of collision boxes - inline hash_coll_element_t(unsigned int cell_id_, int value): cell_id(cell_id_), element_index(value) {} + inline hash_coll_element_t(unsigned int cell_id_, int value) : cell_id(cell_id_), element_index(value) + { + } - inline bool IsCollisionBox() const { return element_index < ELEMENT_TRI_BASE_INDEX; } - inline bool IsCollisionTri() const { return element_index >= ELEMENT_TRI_BASE_INDEX; } + inline bool IsCollisionBox() const + { + return element_index < ELEMENT_TRI_BASE_INDEX; + } + inline bool IsCollisionTri() const + { + return element_index >= ELEMENT_TRI_BASE_INDEX; + } unsigned int cell_id; @@ -78,33 +83,33 @@ class Collisions : public ZeroedMemoryAllocator struct collision_tri_t { - Ogre::Vector3 a; - Ogre::Vector3 b; - Ogre::Vector3 c; + Ogre::Vector3 a; + Ogre::Vector3 b; + Ogre::Vector3 c; Ogre::AxisAlignedBox aab; - Ogre::Matrix3 forward; - Ogre::Matrix3 reverse; - ground_model_t* gm; - bool enabled; + Ogre::Matrix3 forward; + Ogre::Matrix3 reverse; + ground_model_t * gm; + bool enabled; }; static const int LATEST_GROUND_MODEL_VERSION = 3; - static const int MAX_EVENT_SOURCE = 500; + static const int MAX_EVENT_SOURCE = 500; // this is a power of two, change with caution static const int HASH_POWER = 20; - static const int HASH_SIZE = 1 << HASH_POWER; + static const int HASH_SIZE = 1 << HASH_POWER; // how many elements per cell? power of 2 minus 2 is better static const int CELL_BLOCKSIZE = 126; // terrain size is limited to 327km x 327km: - static const int CELL_SIZE = 2.0; // we divide through this + static const int CELL_SIZE = 2.0; // we divide through this static const int MAXIMUM_CELL = 0x7FFF; // collision boxes pool - std::vector m_collision_boxes; // Formerly MAX_COLLISION_BOXES = 5000 - std::vector m_last_called_cboxes; + std::vector m_collision_boxes; // Formerly MAX_COLLISION_BOXES = 5000 + std::vector m_last_called_cboxes; // collision tris pool; std::vector m_collision_tris; // Formerly MAX_COLLISION_TRIS = 100000 @@ -112,7 +117,7 @@ class Collisions : public ZeroedMemoryAllocator Ogre::AxisAlignedBox m_collision_aab; // Tight bounding box around all collision meshes // collision hashtable - Ogre::Real hashtable_height[HASH_SIZE]; + Ogre::Real hashtable_height[HASH_SIZE]; std::vector hashtable[HASH_SIZE]; // ground models @@ -120,76 +125,95 @@ class Collisions : public ZeroedMemoryAllocator // event sources eventsource_t eventsources[MAX_EVENT_SOURCE]; - int free_eventsource; + int free_eventsource; bool permitEvent(int filter); - bool envokeScriptCallback(collision_box_t* cbox, node_t* node = 0); - - Landusemap* landuse; - Ogre::ManualObject* debugmo; - bool debugMode; - int collision_version; - inline int GetNumCollisionTris() const { return static_cast(m_collision_tris.size()); } - inline int GetNumCollisionBoxes() const { return static_cast(m_collision_boxes.size()); } + bool envokeScriptCallback(collision_box_t *cbox, node_t *node = 0); + + Landusemap * landuse; + Ogre::ManualObject *debugmo; + bool debugMode; + int collision_version; + inline int GetNumCollisionTris() const + { + return static_cast(m_collision_tris.size()); + } + inline int GetNumCollisionBoxes() const + { + return static_cast(m_collision_boxes.size()); + } unsigned int hashmask; const Ogre::Vector3 m_terrain_size; - void hash_add(int cell_x, int cell_z, int value, float h); - int hash_find(int cell_x, int cell_z); /// Returns index to 'hashtable' + void hash_add(int cell_x, int cell_z, int value, float h); + int hash_find(int cell_x, int cell_z); /// Returns index to 'hashtable' unsigned int hashfunc(unsigned int cellid); - void parseGroundConfig(Ogre::ConfigFile* cfg, Ogre::String groundModel = ""); + void parseGroundConfig(Ogre::ConfigFile *cfg, Ogre::String groundModel = ""); - Ogre::Vector3 calcCollidedSide(const Ogre::Vector3& pos, const Ogre::Vector3& lo, const Ogre::Vector3& hi); - -public: + Ogre::Vector3 calcCollidedSide(const Ogre::Vector3 &pos, const Ogre::Vector3 &lo, const Ogre::Vector3 &hi); + public: std::mutex m_scriptcallback_mutex; - bool forcecam; - Ogre::Vector3 forcecampos; + bool forcecam; + Ogre::Vector3 forcecampos; ground_model_t *defaultgm, *defaultgroundgm; Collisions(); ~Collisions(); - Ogre::Vector3 getPosition(const Ogre::String& inst, const Ogre::String& box); - Ogre::Quaternion getDirection(const Ogre::String& inst, const Ogre::String& box); - collision_box_t* getBox(const Ogre::String& inst, const Ogre::String& box); + Ogre::Vector3 getPosition(const Ogre::String &inst, const Ogre::String &box); + Ogre::Quaternion getDirection(const Ogre::String &inst, const Ogre::String &box); + collision_box_t *getBox(const Ogre::String &inst, const Ogre::String &box); std::pair intersectsTris(Ogre::Ray ray); float getSurfaceHeight(float x, float z); float getSurfaceHeightBelow(float x, float z, float height); - bool collisionCorrect(Ogre::Vector3* refpos, bool envokeScriptCallbacks = true); - bool groundCollision(node_t* node, float dt); - bool isInside(Ogre::Vector3 pos, const Ogre::String& inst, const Ogre::String& box, float border = 0); - bool isInside(Ogre::Vector3 pos, collision_box_t* cbox, float border = 0); - bool nodeCollision(node_t* node, float dt, bool envokeScriptCallbacks = true); + bool collisionCorrect(Ogre::Vector3 *refpos, bool envokeScriptCallbacks = true); + bool groundCollision(node_t *node, float dt); + bool isInside(Ogre::Vector3 pos, const Ogre::String &inst, const Ogre::String &box, float border = 0); + bool isInside(Ogre::Vector3 pos, collision_box_t *cbox, float border = 0); + bool nodeCollision(node_t *node, float dt, bool envokeScriptCallbacks = true); void finishLoadingTerrain(); - int addCollisionBox(Ogre::SceneNode* tenode, bool rotating, bool virt, Ogre::Vector3 pos, Ogre::Vector3 rot, Ogre::Vector3 l, Ogre::Vector3 h, Ogre::Vector3 sr, const Ogre::String& eventname, const Ogre::String& instancename, bool forcecam, Ogre::Vector3 campos, Ogre::Vector3 sc = Ogre::Vector3::UNIT_SCALE, Ogre::Vector3 dr = Ogre::Vector3::ZERO, int event_filter = EVENT_ALL, int scripthandler = -1); - int addCollisionMesh(Ogre::String meshname, Ogre::Vector3 pos, Ogre::Quaternion q, Ogre::Vector3 scale, ground_model_t* gm = 0, std::vector* collTris = 0); - int addCollisionTri(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, ground_model_t* gm); - int createCollisionDebugVisualization(); + int addCollisionBox(Ogre::SceneNode *tenode, bool rotating, bool virt, Ogre::Vector3 pos, Ogre::Vector3 rot, Ogre::Vector3 l, + Ogre::Vector3 h, Ogre::Vector3 sr, const Ogre::String &eventname, const Ogre::String &instancename, + bool forcecam, Ogre::Vector3 campos, Ogre::Vector3 sc = Ogre::Vector3::UNIT_SCALE, + Ogre::Vector3 dr = Ogre::Vector3::ZERO, int event_filter = EVENT_ALL, int scripthandler = -1); + int addCollisionMesh(Ogre::String meshname, Ogre::Vector3 pos, Ogre::Quaternion q, Ogre::Vector3 scale, + ground_model_t *gm = 0, std::vector *collTris = 0); + int addCollisionTri(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, ground_model_t *gm); + int createCollisionDebugVisualization(); void removeCollisionBox(int number); void removeCollisionTri(int number); - void clearEventCache() { m_last_called_cboxes.clear(); } + void clearEventCache() + { + m_last_called_cboxes.clear(); + } - Ogre::AxisAlignedBox getCollisionAAB() { return m_collision_aab; }; + Ogre::AxisAlignedBox getCollisionAAB() + { + return m_collision_aab; + }; // ground models things - int loadDefaultModels(); - int loadGroundModelsConfigFile(Ogre::String filename); - std::map* getGroundModels() { return &ground_models; }; - void setupLandUse(const char* configfile); - ground_model_t* getGroundModelByString(const Ogre::String name); - - void getMeshInformation(Ogre::Mesh* mesh, size_t& vertex_count, Ogre::Vector3* & vertices, - size_t& index_count, unsigned* & indices, - const Ogre::Vector3& position = Ogre::Vector3::ZERO, - const Ogre::Quaternion& orient = Ogre::Quaternion::IDENTITY, const Ogre::Vector3& scale = Ogre::Vector3::UNIT_SCALE); + int loadDefaultModels(); + int loadGroundModelsConfigFile(Ogre::String filename); + std::map *getGroundModels() + { + return &ground_models; + }; + void setupLandUse(const char *configfile); + ground_model_t *getGroundModelByString(const Ogre::String name); + + void getMeshInformation(Ogre::Mesh *mesh, size_t &vertex_count, Ogre::Vector3 *&vertices, size_t &index_count, + unsigned *&indices, const Ogre::Vector3 &position = Ogre::Vector3::ZERO, + const Ogre::Quaternion &orient = Ogre::Quaternion::IDENTITY, + const Ogre::Vector3 & scale = Ogre::Vector3::UNIT_SCALE); }; -Ogre::Vector3 primitiveCollision(node_t* node, Ogre::Vector3 velocity, float mass, Ogre::Vector3 normal, float dt, ground_model_t* gm, float penetration = 0); +Ogre::Vector3 primitiveCollision(node_t *node, Ogre::Vector3 velocity, float mass, Ogre::Vector3 normal, float dt, + ground_model_t *gm, float penetration = 0); diff --git a/source/main/physics/collision/DynamicCollisions.cpp b/source/main/physics/collision/DynamicCollisions.cpp index 4790a4803f..0d56c27c4c 100644 --- a/source/main/physics/collision/DynamicCollisions.cpp +++ b/source/main/physics/collision/DynamicCollisions.cpp @@ -42,27 +42,26 @@ using namespace Ogre; * @param normal Surface normal of the triangle. * @param surface_point Arbitrary point within the triangle plane. * @param neighbour_node_ids Indices of neighbouring nodes connected to the colliding node. - * @param nodes + * @param nodes */ -static bool BackfaceCollisionTest(const float distance, - const Vector3 &normal, - const node_t &surface_point, - const std::vector &neighbour_node_ids, - const node_t nodes[]) +static bool BackfaceCollisionTest(const float distance, const Vector3 &normal, const node_t &surface_point, + const std::vector &neighbour_node_ids, const node_t nodes[]) { - auto sign = [](float x){ return (x >= 0) ? 1 : -1; }; + auto sign = [](float x) { return (x >= 0) ? 1 : -1; }; // Summarize over the collision node and its connected neighbour nodes to infer on which side // of the collision plane most of these nodes are located. // Nodes in front contribute positively, nodes on the backface contribute negatively. // the contribution of the collision node itself has triple weight in this heuristic - const int weight = 3; - int face_indicator = weight * sign(distance); + const int weight = 3; + int face_indicator = weight * sign(distance); // calculate the contribution of neighbouring nodes (if it can still change the final outcome) - if (neighbour_node_ids.size() > weight) { - for (auto id : neighbour_node_ids) { + if (neighbour_node_ids.size() > weight) + { + for (auto id : neighbour_node_ids) + { const auto neighbour_distance = normal.dotProduct(nodes[id].AbsPosition - surface_point.AbsPosition); face_indicator += sign(neighbour_distance); } @@ -72,7 +71,6 @@ static bool BackfaceCollisionTest(const float distance, return (face_indicator < 0); } - /// Test if a point given in triangle local coordinates lies within the triangle itself. /** * A point (within in the triangle plane) is located inside the triangle if its barycentric coordinates @@ -90,36 +88,28 @@ static bool InsideTriangleTest(const CartesianToTriangleTransform::TriangleCoord return (coord.alpha >= 0) && (coord.beta >= 0) && (coord.gamma >= 0) && (std::abs(distance) <= margin); } - /// Calculate collision forces and apply them to the collision node and the three vertex nodes of the collision triangle. -void ResolveCollisionForces(const float penetration_depth, - node_t &hitnode, node_t &na, node_t &nb, node_t &no, - const float alpha, const float beta, const float gamma, - const Vector3 &normal, - const float dt, - const bool remote, - ground_model_t &submesh_ground_model) +void ResolveCollisionForces(const float penetration_depth, node_t &hitnode, node_t &na, node_t &nb, node_t &no, const float alpha, + const float beta, const float gamma, const Vector3 &normal, const float dt, const bool remote, + ground_model_t &submesh_ground_model) { - const auto velocity = hitnode.Velocity - (na.Velocity * alpha + nb.Velocity * beta + no.Velocity * gamma); - const float tr_mass = na.mass * alpha + nb.mass * beta + no.mass * gamma; - const float mass = remote ? hitnode.mass : (hitnode.mass * tr_mass) / (hitnode.mass + tr_mass); + const auto velocity = hitnode.Velocity - (na.Velocity * alpha + nb.Velocity * beta + no.Velocity * gamma); + const float tr_mass = na.mass * alpha + nb.mass * beta + no.mass * gamma; + const float mass = remote ? hitnode.mass : (hitnode.mass * tr_mass) / (hitnode.mass + tr_mass); auto forcevec = primitiveCollision(&hitnode, velocity, mass, normal, dt, &submesh_ground_model, penetration_depth); hitnode.Forces += forcevec; - na.Forces -= forcevec * alpha; - nb.Forces -= forcevec * beta; - no.Forces -= forcevec * gamma; + na.Forces -= forcevec * alpha; + nb.Forces -= forcevec * beta; + no.Forces -= forcevec * gamma; } - -void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, - const int free_collcab, int collcabs[], int cabs[], - collcab_rate_t inter_collcabrate[], node_t nodes[], - const float collrange, - ground_model_t &submesh_ground_model) +void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, const int free_collcab, int collcabs[], + int cabs[], collcab_rate_t inter_collcabrate[], node_t nodes[], const float collrange, + ground_model_t &submesh_ground_model) { - for (int i=0; i 0) { @@ -127,28 +117,26 @@ void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, inter_collcabrate[i].rate--; continue; } - inter_collcabrate[i].rate = std::min(inter_collcabrate[i].distance, 12); + inter_collcabrate[i].rate = std::min(inter_collcabrate[i].distance, 12); inter_collcabrate[i].distance = 0; - int tmpv = collcabs[i]*3; - const auto no = &nodes[cabs[tmpv]]; - const auto na = &nodes[cabs[tmpv+1]]; - const auto nb = &nodes[cabs[tmpv+2]]; + int tmpv = collcabs[i] * 3; + const auto no = &nodes[cabs[tmpv]]; + const auto na = &nodes[cabs[tmpv + 1]]; + const auto nb = &nodes[cabs[tmpv + 2]]; - interPointCD.query(no->AbsPosition - , na->AbsPosition - , nb->AbsPosition, collrange); + interPointCD.query(no->AbsPosition, na->AbsPosition, nb->AbsPosition, collrange); if (!interPointCD.hit_list.empty()) { // setup transformation of points to triangle local coordinates - const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); + const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); const CartesianToTriangleTransform transform(triangle); for (auto h : interPointCD.hit_list) { const auto hit_actor = h->actor; - const auto hitnode = &hit_actor->ar_nodes[h->node_id]; + const auto hitnode = &hit_actor->ar_nodes[h->node_id]; // transform point to triangle local coordinates const auto local_point = transform(hitnode->AbsPosition); @@ -159,13 +147,14 @@ void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, { inter_collcabrate[i].rate = 0; - const auto coord = local_point.barycentric; - auto distance = local_point.distance; - auto normal = triangle.normal(); + const auto coord = local_point.barycentric; + auto distance = local_point.distance; + auto normal = triangle.normal(); // adapt in case the collision is occuring on the backface of the triangle const auto neighbour_node_ids = hit_actor->ar_node_to_node_connections[h->node_id]; - const bool is_backface = BackfaceCollisionTest(distance, normal, *no, neighbour_node_ids, hit_actor->ar_nodes); + const bool is_backface = + BackfaceCollisionTest(distance, normal, *no, neighbour_node_ids, hit_actor->ar_nodes); if (is_backface) { // flip surface normal and distance to triangle plane @@ -177,14 +166,14 @@ void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, const bool remote = (hit_actor->ar_sim_state == Actor::SimState::NETWORKED_OK); - ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, - coord.beta, coord.gamma, normal, dt, remote, submesh_ground_model); + ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, coord.beta, coord.gamma, + normal, dt, remote, submesh_ground_model); hitnode->nd_last_collision_gm = &submesh_ground_model; - hitnode->nd_has_mesh_contact = true; - na->nd_has_mesh_contact = true; - nb->nd_has_mesh_contact = true; - no->nd_has_mesh_contact = true; + hitnode->nd_has_mesh_contact = true; + na->nd_has_mesh_contact = true; + nb->nd_has_mesh_contact = true; + no->nd_has_mesh_contact = true; } } } @@ -195,14 +184,11 @@ void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, } } - -void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, - const int free_collcab, int collcabs[], int cabs[], - collcab_rate_t intra_collcabrate[], node_t nodes[], - const float collrange, - ground_model_t &submesh_ground_model) +void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, const int free_collcab, int collcabs[], + int cabs[], collcab_rate_t intra_collcabrate[], node_t nodes[], const float collrange, + ground_model_t &submesh_ground_model) { - for (int i=0; i 0) { @@ -212,32 +198,30 @@ void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, } if (intra_collcabrate[i].distance > 0) { - intra_collcabrate[i].rate = std::min(intra_collcabrate[i].distance, 12); + intra_collcabrate[i].rate = std::min(intra_collcabrate[i].distance, 12); intra_collcabrate[i].distance = 0; } - int tmpv = collcabs[i]*3; - const auto no = &nodes[cabs[tmpv]]; - const auto na = &nodes[cabs[tmpv+1]]; - const auto nb = &nodes[cabs[tmpv+2]]; + int tmpv = collcabs[i] * 3; + const auto no = &nodes[cabs[tmpv]]; + const auto na = &nodes[cabs[tmpv + 1]]; + const auto nb = &nodes[cabs[tmpv + 2]]; - intraPointCD.query(no->AbsPosition - , na->AbsPosition - , nb->AbsPosition, collrange); + intraPointCD.query(no->AbsPosition, na->AbsPosition, nb->AbsPosition, collrange); bool collision = false; if (!intraPointCD.hit_list.empty()) { // setup transformation of points to triangle local coordinates - const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); + const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); const CartesianToTriangleTransform transform(triangle); for (auto h : intraPointCD.hit_list) { const auto hitnode = &nodes[h->node_id]; - //ignore wheel/chassis self contact + // ignore wheel/chassis self contact if (hitnode->nd_tyre_node) continue; if (no == hitnode || na == hitnode || nb == hitnode) continue; @@ -250,12 +234,12 @@ void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, { collision = true; - const auto coord = local_point.barycentric; - auto distance = local_point.distance; - auto normal = triangle.normal(); + const auto coord = local_point.barycentric; + auto distance = local_point.distance; + auto normal = triangle.normal(); // adapt in case the collision is occuring on the backface of the triangle - if (distance < 0) + if (distance < 0) { // flip surface normal and distance to triangle plane normal = -normal; @@ -264,16 +248,13 @@ void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, const auto penetration_depth = collrange - distance; - ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, - coord.beta, coord.gamma, normal, dt, false, submesh_ground_model); + ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, coord.beta, coord.gamma, + normal, dt, false, submesh_ground_model); } } } - if (collision) - { - intra_collcabrate[i].rate = -20000; - } + if (collision) { intra_collcabrate[i].rate = -20000; } else { intra_collcabrate[i].rate++; diff --git a/source/main/physics/collision/DynamicCollisions.h b/source/main/physics/collision/DynamicCollisions.h index 254f0545d4..d50b70381d 100644 --- a/source/main/physics/collision/DynamicCollisions.h +++ b/source/main/physics/collision/DynamicCollisions.h @@ -21,18 +21,13 @@ #pragma once -#include "ForwardDeclarations.h" #include "BeamData.h" +#include "ForwardDeclarations.h" -void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, - const int free_collcab, int collcabs[], int cabs[], - collcab_rate_t inter_collcabrate[], node_t nodes[], - const float collrange, - ground_model_t &submesh_ground_model); - -void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, - const int free_collcab, int collcabs[], int cabs[], - collcab_rate_t intra_collcabrate[], node_t nodes[], - const float collrange, - ground_model_t &submesh_ground_model); +void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, const int free_collcab, int collcabs[], + int cabs[], collcab_rate_t inter_collcabrate[], node_t nodes[], const float collrange, + ground_model_t &submesh_ground_model); +void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, const int free_collcab, int collcabs[], + int cabs[], collcab_rate_t intra_collcabrate[], node_t nodes[], const float collrange, + ground_model_t &submesh_ground_model); diff --git a/source/main/physics/collision/PointColDetector.cpp b/source/main/physics/collision/PointColDetector.cpp index 2a6df304ab..636f29b033 100644 --- a/source/main/physics/collision/PointColDetector.cpp +++ b/source/main/physics/collision/PointColDetector.cpp @@ -33,25 +33,25 @@ void PointColDetector::UpdateIntraPoint(bool contactables) if (contacters_size != m_object_list_size) { m_collision_partners = {m_actor}; - m_object_list_size = contacters_size; + m_object_list_size = contacters_size; update_structures_for_contacters(contactables); } - m_kdtree[0].ref = NULL; + m_kdtree[0].ref = NULL; m_kdtree[0].begin = 0; - m_kdtree[0].end = -m_object_list_size; + m_kdtree[0].end = -m_object_list_size; } void PointColDetector::UpdateInterPoint(bool ignorestate) { m_linked_actors = m_actor->GetAllLinkedActors(); - int contacters_size = 0; - std::vector collision_partners; + int contacters_size = 0; + std::vector collision_partners; for (auto actor : RoR::App::GetSimController()->GetActors()) { if (actor != m_actor && (ignorestate || actor->ar_update_physics) && - m_actor->ar_bounding_box.intersects(actor->ar_bounding_box)) + m_actor->ar_bounding_box.intersects(actor->ar_bounding_box)) { collision_partners.push_back(actor); bool is_linked = std::find(m_linked_actors.begin(), m_linked_actors.end(), actor) != m_linked_actors.end(); @@ -77,13 +77,13 @@ void PointColDetector::UpdateInterPoint(bool ignorestate) if (collision_partners != m_collision_partners || contacters_size != m_object_list_size) { m_collision_partners = collision_partners; - m_object_list_size = contacters_size; + m_object_list_size = contacters_size; update_structures_for_contacters(false); } - m_kdtree[0].ref = NULL; + m_kdtree[0].ref = NULL; m_kdtree[0].begin = 0; - m_kdtree[0].end = -m_object_list_size; + m_kdtree[0].end = -m_object_list_size; } void PointColDetector::update_structures_for_contacters(bool ignoreinternal) @@ -95,16 +95,16 @@ void PointColDetector::update_structures_for_contacters(bool ignoreinternal) int refi = 0; for (auto actor : m_collision_partners) { - bool is_linked = std::find(m_linked_actors.begin(), m_linked_actors.end(), actor) != m_linked_actors.end(); + bool is_linked = std::find(m_linked_actors.begin(), m_linked_actors.end(), actor) != m_linked_actors.end(); bool internal_collision = !ignoreinternal && ((actor == m_actor) || is_linked); for (int i = 0; i < actor->ar_num_nodes; i++) { if (actor->ar_nodes[i].nd_contacter || (!internal_collision && actor->ar_nodes[i].nd_contactable)) { - m_pointid_list[refi].actor = actor; + m_pointid_list[refi].actor = actor; m_pointid_list[refi].node_id = i; - m_ref_list[refi].pidref = &m_pointid_list[refi]; - m_ref_list[refi].point = actor->ar_nodes[i].AbsPosition.ptr(); + m_ref_list[refi].pidref = &m_pointid_list[refi]; + m_ref_list[refi].point = actor->ar_nodes[i].AbsPosition.ptr(); refi++; } } @@ -149,106 +149,80 @@ void PointColDetector::queryrec(int kdindex, int axis) { for (;;) { - if (m_kdtree[kdindex].end < 0) - { - build_kdtree_incr(axis, kdindex); - } + if (m_kdtree[kdindex].end < 0) { build_kdtree_incr(axis, kdindex); } if (m_kdtree[kdindex].ref != NULL) { const float *point = m_kdtree[kdindex].ref->point; - if (point[0] >= m_bbmin.x && point[0] <= m_bbmax.x && - point[1] >= m_bbmin.y && point[1] <= m_bbmax.y && + if (point[0] >= m_bbmin.x && point[0] <= m_bbmax.x && point[1] >= m_bbmin.y && point[1] <= m_bbmax.y && point[2] >= m_bbmin.z && point[2] <= m_bbmax.z) - { - hit_list.push_back(m_kdtree[kdindex].ref->pidref); - } + { hit_list.push_back(m_kdtree[kdindex].ref->pidref); } return; } if (m_bbmax[axis] >= m_kdtree[kdindex].middle) { - if (m_bbmin[axis] > m_kdtree[kdindex].max) - { - return; - } + if (m_bbmin[axis] > m_kdtree[kdindex].max) { return; } int newaxis = axis + 1; - if (newaxis >= 3) - { - newaxis = 0; - } + if (newaxis >= 3) { newaxis = 0; } int newindex = kdindex + kdindex + 1; - if (m_bbmin[axis] <= m_kdtree[kdindex].middle) - { - queryrec(newindex, newaxis); - } + if (m_bbmin[axis] <= m_kdtree[kdindex].middle) { queryrec(newindex, newaxis); } kdindex = newindex + 1; - axis = newaxis; + axis = newaxis; } else { - if (m_bbmax[axis] < m_kdtree[kdindex].min) - { - return; - } + if (m_bbmax[axis] < m_kdtree[kdindex].min) { return; } kdindex = 2 * kdindex + 1; axis++; - if (axis >= 3) - { - axis = 0; - } + if (axis >= 3) { axis = 0; } } } } void PointColDetector::build_kdtree_incr(int axis, int index) { - int end = -m_kdtree[index].end; + int end = -m_kdtree[index].end; m_kdtree[index].end = end; - int begin = m_kdtree[index].begin; + int begin = m_kdtree[index].begin; int median; int slice_size = end - begin; if (slice_size != 1) { - int newindex=index+index+1; + int newindex = index + index + 1; if (slice_size == 2) { - median = begin+1; + median = begin + 1; if (m_ref_list[begin].point[axis] > m_ref_list[median].point[axis]) - { - std::swap(m_ref_list[begin], m_ref_list[median]); - } + { std::swap(m_ref_list[begin], m_ref_list[median]); } - m_kdtree[index].min = m_ref_list[begin].point[axis]; - m_kdtree[index].max = m_ref_list[median].point[axis]; + m_kdtree[index].min = m_ref_list[begin].point[axis]; + m_kdtree[index].max = m_ref_list[median].point[axis]; m_kdtree[index].middle = m_kdtree[index].max; - m_kdtree[index].ref = NULL; + m_kdtree[index].ref = NULL; axis++; - if (axis >= 3) - { - axis = 0; - } + if (axis >= 3) { axis = 0; } - m_kdtree[newindex].ref = &m_ref_list[begin]; + m_kdtree[newindex].ref = &m_ref_list[begin]; m_kdtree[newindex].middle = m_kdtree[newindex].ref->point[axis]; - m_kdtree[newindex].min = m_kdtree[newindex].middle; - m_kdtree[newindex].max = m_kdtree[newindex].middle; - m_kdtree[newindex].end = median; + m_kdtree[newindex].min = m_kdtree[newindex].middle; + m_kdtree[newindex].max = m_kdtree[newindex].middle; + m_kdtree[newindex].end = median; newindex++; - m_kdtree[newindex].ref = &m_ref_list[median]; + m_kdtree[newindex].ref = &m_ref_list[median]; m_kdtree[newindex].middle = m_kdtree[newindex].ref->point[axis]; - m_kdtree[newindex].min = m_kdtree[newindex].middle; - m_kdtree[newindex].max = m_kdtree[newindex].middle; - m_kdtree[newindex].end = end; + m_kdtree[newindex].min = m_kdtree[newindex].middle; + m_kdtree[newindex].max = m_kdtree[newindex].middle; + m_kdtree[newindex].end = end; return; } else @@ -258,22 +232,21 @@ void PointColDetector::build_kdtree_incr(int axis, int index) } m_kdtree[index].middle = m_ref_list[median].point[axis]; - m_kdtree[index].ref = NULL; + m_kdtree[index].ref = NULL; m_kdtree[newindex].begin = begin; - m_kdtree[newindex].end = -median; + m_kdtree[newindex].end = -median; newindex++; m_kdtree[newindex].begin = median; - m_kdtree[newindex].end = -end; - + m_kdtree[newindex].end = -end; } else { - m_kdtree[index].ref = &m_ref_list[begin]; + m_kdtree[index].ref = &m_ref_list[begin]; m_kdtree[index].middle = m_kdtree[index].ref->point[axis]; - m_kdtree[index].min = m_kdtree[index].middle; - m_kdtree[index].max = m_kdtree[index].middle; + m_kdtree[index].min = m_kdtree[index].middle; + m_kdtree[index].max = m_kdtree[index].middle; } } @@ -281,8 +254,8 @@ void PointColDetector::partintwo(const int start, const int median, const int en { int i, j, l, m; int k = median; - l = start; - m = end - 1; + l = start; + m = end - 1; float x = m_ref_list[k].point[axis]; while (l < m) @@ -304,14 +277,8 @@ void PointColDetector::partintwo(const int start, const int median, const int en i++; j--; } - if (j < k) - { - l = i; - } - if (k < i) - { - m = j; - } + if (j < k) { l = i; } + if (k < i) { m = j; } x = m_ref_list[k].point[axis]; } @@ -321,7 +288,7 @@ void PointColDetector::partintwo(const int start, const int median, const int en { minex = std::min(m_ref_list[i].point[axis], minex); } - for (int i = median+1; i < end; ++i) + for (int i = median + 1; i < end; ++i) { maxex = std::max(maxex, m_ref_list[i].point[axis]); } diff --git a/source/main/physics/collision/PointColDetector.h b/source/main/physics/collision/PointColDetector.h index 292207d499..4770d93439 100644 --- a/source/main/physics/collision/PointColDetector.h +++ b/source/main/physics/collision/PointColDetector.h @@ -23,43 +23,41 @@ class PointColDetector : public ZeroedMemoryAllocator { -public: - + public: struct pointid_t { - Actor* actor; - short node_id; + Actor *actor; + short node_id; }; - std::vector hit_list; + std::vector hit_list; - PointColDetector(Actor* actor): m_actor(actor), m_object_list_size(-1) {}; + PointColDetector(Actor *actor) : m_actor(actor), m_object_list_size(-1){}; void UpdateIntraPoint(bool contactables = false); void UpdateInterPoint(bool ignorestate = false); - void query(const Ogre::Vector3& vec1, const Ogre::Vector3& vec2, const Ogre::Vector3& vec3, const float enlargeBB); - -private: + void query(const Ogre::Vector3 &vec1, const Ogre::Vector3 &vec2, const Ogre::Vector3 &vec3, const float enlargeBB); + private: struct refelem_t { - pointid_t* pidref; - const float* point; + pointid_t * pidref; + const float *point; }; struct kdnode_t { - float min; - int end; - float max; - refelem_t* ref; - float middle; - int begin; + float min; + int end; + float max; + refelem_t *ref; + float middle; + int begin; }; - Actor* m_actor; - std::vector m_linked_actors; - std::vector m_collision_partners; + Actor * m_actor; + std::vector m_linked_actors; + std::vector m_collision_partners; std::vector m_ref_list; std::vector m_pointid_list; std::vector m_kdtree; @@ -69,6 +67,6 @@ class PointColDetector : public ZeroedMemoryAllocator void queryrec(int kdindex, int axis); void build_kdtree_incr(int axis, int index); - void partintwo(const int start, const int median, const int end, const int axis, float& minex, float& maxex); + void partintwo(const int start, const int median, const int end, const int axis, float &minex, float &maxex); void update_structures_for_contacters(bool ignoreinternal); }; diff --git a/source/main/physics/collision/Triangle.h b/source/main/physics/collision/Triangle.h index acfb6ada32..0b248d5d77 100644 --- a/source/main/physics/collision/Triangle.h +++ b/source/main/physics/collision/Triangle.h @@ -28,9 +28,9 @@ /// triangle lies. class Triangle { -public: + public: /// Construct triangle from three given vertices. - explicit Triangle(const Ogre::Vector3& a, const Ogre::Vector3& b, const Ogre::Vector3& c) + explicit Triangle(const Ogre::Vector3 &a, const Ogre::Vector3 &b, const Ogre::Vector3 &c) : a{a}, b{b}, c{c}, u{a - c}, v{b - c}, m_initialized{false} { } @@ -51,13 +51,13 @@ class Triangle } const Ogre::Vector3 a, ///< Vertex a - b, ///< Vertex b - c; ///< Vertex c + b, ///< Vertex b + c; ///< Vertex c const Ogre::Vector3 u, ///< Span vector u - v; ///< Span vector v + v; ///< Span vector v -private: - mutable bool m_initialized; + private: + mutable bool m_initialized; mutable Ogre::Vector3 m_normal; ///< Cached normal vector }; diff --git a/source/main/physics/flex/FlexAirfoil.cpp b/source/main/physics/flex/FlexAirfoil.cpp index 0a2dbe5781..a7f68a1c49 100644 --- a/source/main/physics/flex/FlexAirfoil.cpp +++ b/source/main/physics/flex/FlexAirfoil.cpp @@ -27,93 +27,75 @@ #include "BeamData.h" #include "GfxActor.h" -float refairfoilpos[90]={ - 0.00, 0.50, 0.00, - 1.00, 0.50, 0.00, - - 0.00, 0.70, 0.03, - 1.00, 0.70, 0.03, - 0.00, 0.30, 0.03, - 1.00, 0.30, 0.03, - - 0.00, 0.90, 0.10, - 1.00, 0.90, 0.10, - 0.00, 0.10, 0.10, - 1.00, 0.10, 0.10, - - 0.00, 1.00, 0.25, - 1.00, 1.00, 0.25, - 0.00, 0.00, 0.25, - 1.00, 0.00, 0.25, - - 0.00, 1.00, 0.50, - 1.00, 1.00, 0.50, - 0.00, 0.00, 0.50, - 1.00, 0.00, 0.50, - - //updated with control surface chord ratio - 0.00, 0.75, 0.75, - 1.00, 0.75, 0.75, - 0.00, 0.25, 0.75, - 1.00, 0.25, 0.75, - - 0.00, 0.75, 0.75, - 1.00, 0.75, 0.75, - 0.00, 0.25, 0.75, - 1.00, 0.25, 0.75, - - //moving with control surface - 0.00, 0.50, 1.00, - 1.00, 0.50, 1.00, - - 0.00, 0.50, 1.00, - 1.00, 0.50, 1.00 - }; +float refairfoilpos[90] = {0.00, 0.50, 0.00, 1.00, 0.50, 0.00, + + 0.00, 0.70, 0.03, 1.00, 0.70, 0.03, 0.00, 0.30, 0.03, 1.00, 0.30, 0.03, + + 0.00, 0.90, 0.10, 1.00, 0.90, 0.10, 0.00, 0.10, 0.10, 1.00, 0.10, 0.10, + + 0.00, 1.00, 0.25, 1.00, 1.00, 0.25, 0.00, 0.00, 0.25, 1.00, 0.00, 0.25, + + 0.00, 1.00, 0.50, 1.00, 1.00, 0.50, 0.00, 0.00, 0.50, 1.00, 0.00, 0.50, + + // updated with control surface chord ratio + 0.00, 0.75, 0.75, 1.00, 0.75, 0.75, 0.00, 0.25, 0.75, 1.00, 0.25, 0.75, + + 0.00, 0.75, 0.75, 1.00, 0.75, 0.75, 0.00, 0.25, 0.75, 1.00, 0.25, 0.75, + + // moving with control surface + 0.00, 0.50, 1.00, 1.00, 0.50, 1.00, + + 0.00, 0.50, 1.00, 1.00, 0.50, 1.00}; using namespace Ogre; -FlexAirfoil::FlexAirfoil(Ogre::String const & name, Actor* actor, int pnfld, int pnfrd, int pnflu, int pnfru, int pnbld, int pnbrd, int pnblu, int pnbru, std::string const & texband, Vector2 texlf, Vector2 texrf, Vector2 texlb, Vector2 texrb, char mtype, float controlratio, float mind, float maxd, Ogre::String const & afname, float lift_coef, bool break_able) +FlexAirfoil::FlexAirfoil(Ogre::String const &name, Actor *actor, int pnfld, int pnfrd, int pnflu, int pnfru, int pnbld, int pnbrd, + int pnblu, int pnbru, std::string const &texband, Vector2 texlf, Vector2 texrf, Vector2 texlb, + Vector2 texrb, char mtype, float controlratio, float mind, float maxd, Ogre::String const &afname, + float lift_coef, bool break_able) { - liftcoef=lift_coef; - breakable=break_able; - broken=false; - free_wash=0; - aeroengines=actor->ar_aeroengines; - nodes=actor->ar_nodes; - useInducedDrag=false; - nfld=pnfld; - nfrd=pnfrd; - nflu=pnflu; - nfru=pnfru; - nbld=pnbld; - nbrd=pnbrd; - nblu=pnblu; - nbru=pnbru; - mindef=mind; - maxdef=maxd; - airfoil=new Airfoil(afname); + liftcoef = lift_coef; + breakable = break_able; + broken = false; + free_wash = 0; + aeroengines = actor->ar_aeroengines; + nodes = actor->ar_nodes; + useInducedDrag = false; + nfld = pnfld; + nfrd = pnfrd; + nflu = pnflu; + nfru = pnfru; + nbld = pnbld; + nbrd = pnbrd; + nblu = pnblu; + nbru = pnbru; + mindef = mind; + maxdef = maxd; + airfoil = new Airfoil(afname); int i; - for (i=0; i<90; i++) airfoilpos[i]=refairfoilpos[i]; - type=mtype; - hascontrol=(mtype!='n' && mtype!='S'&& mtype!='T' && mtype!='U'&& mtype!='V'); - isstabilator=(mtype=='S' || mtype=='T' || mtype=='U' || mtype=='V'); - stabilleft=(mtype=='T' || mtype=='V'); - deflection=0.0; - chordratio=controlratio; + for (i = 0; i < 90; i++) + airfoilpos[i] = refairfoilpos[i]; + type = mtype; + hascontrol = (mtype != 'n' && mtype != 'S' && mtype != 'T' && mtype != 'U' && mtype != 'V'); + isstabilator = (mtype == 'S' || mtype == 'T' || mtype == 'U' || mtype == 'V'); + stabilleft = (mtype == 'T' || mtype == 'V'); + deflection = 0.0; + chordratio = controlratio; if (hascontrol) { - //setup control surface - airfoilpos[56]=controlratio; - airfoilpos[56+3]=controlratio; - airfoilpos[56+6]=controlratio; - airfoilpos[56+9]=controlratio; - - airfoilpos[55]=-controlratio+1.5; - airfoilpos[55+3]=-controlratio+1.5; - airfoilpos[55+6]=controlratio-0.5; - airfoilpos[55+9]=controlratio-0.5; - for (i=0; i<12; i++) airfoilpos[54+12+i]=airfoilpos[54+i]; + // setup control surface + airfoilpos[56] = controlratio; + airfoilpos[56 + 3] = controlratio; + airfoilpos[56 + 6] = controlratio; + airfoilpos[56 + 9] = controlratio; + + airfoilpos[55] = -controlratio + 1.5; + airfoilpos[55 + 3] = -controlratio + 1.5; + airfoilpos[55 + 6] = controlratio - 0.5; + airfoilpos[55 + 9] = controlratio - 0.5; + for (i = 0; i < 12; i++) + airfoilpos[54 + 12 + i] = airfoilpos[54 + i]; } /// Create the mesh via the MeshManager msh = MeshManager::getSingleton().createManual(name, actor->GetGfxActor()->GetResourceGroup()); @@ -121,429 +103,434 @@ FlexAirfoil::FlexAirfoil(Ogre::String const & name, Actor* actor, int pnfld, int /// Create submeshes subface = msh->createSubMesh(); subband = msh->createSubMesh(); - subcup = msh->createSubMesh(); - subcdn = msh->createSubMesh(); + subcup = msh->createSubMesh(); + subcdn = msh->createSubMesh(); - //materials + // materials subface->setMaterialName(texband); subband->setMaterialName(texband); subcup->setMaterialName(texband); subcdn->setMaterialName(texband); /// Define the vertices - nVertices = 24*2+4+2; - vbufCount = (2*3+2)*nVertices; - vertices=(float*)malloc(vbufCount*sizeof(float)); - - //textures coordinates - covertices[0].texcoord=texlf; - covertices[1].texcoord=texrf; - - covertices[2].texcoord=texlf+(texlb-texlf)*0.03; - covertices[3].texcoord=texrf+(texrb-texrf)*0.03; - covertices[4].texcoord=texlf+(texlb-texlf)*0.03; - covertices[5].texcoord=texrf+(texrb-texrf)*0.03; - - covertices[6].texcoord=texlf+(texlb-texlf)*0.10; - covertices[7].texcoord=texrf+(texrb-texrf)*0.10; - covertices[8].texcoord=texlf+(texlb-texlf)*0.10; - covertices[9].texcoord=texrf+(texrb-texrf)*0.10; - - covertices[10].texcoord=texlf+(texlb-texlf)*0.25; - covertices[11].texcoord=texrf+(texrb-texrf)*0.25; - covertices[12].texcoord=texlf+(texlb-texlf)*0.25; - covertices[13].texcoord=texrf+(texrb-texrf)*0.25; - - covertices[14].texcoord=texlf+(texlb-texlf)*0.45; - covertices[15].texcoord=texrf+(texrb-texrf)*0.45; - covertices[16].texcoord=texlf+(texlb-texlf)*0.45; - covertices[17].texcoord=texrf+(texrb-texrf)*0.45; - - covertices[18].texcoord=texlf+(texlb-texlf)*airfoilpos[56]; - covertices[19].texcoord=texrf+(texrb-texrf)*airfoilpos[56]; - covertices[20].texcoord=texlf+(texlb-texlf)*airfoilpos[56]; - covertices[21].texcoord=texrf+(texrb-texrf)*airfoilpos[56]; - - covertices[22].texcoord=covertices[18].texcoord; - covertices[23].texcoord=covertices[19].texcoord; - covertices[24].texcoord=covertices[20].texcoord; - covertices[25].texcoord=covertices[21].texcoord; - - covertices[26].texcoord=texlb; - covertices[27].texcoord=texrb; - covertices[28].texcoord=texlb; - covertices[29].texcoord=texrb; - - for (i=0; i<24; i++) covertices[i+30].texcoord=covertices[i].texcoord; + nVertices = 24 * 2 + 4 + 2; + vbufCount = (2 * 3 + 2) * nVertices; + vertices = (float *)malloc(vbufCount * sizeof(float)); + + // textures coordinates + covertices[0].texcoord = texlf; + covertices[1].texcoord = texrf; + + covertices[2].texcoord = texlf + (texlb - texlf) * 0.03; + covertices[3].texcoord = texrf + (texrb - texrf) * 0.03; + covertices[4].texcoord = texlf + (texlb - texlf) * 0.03; + covertices[5].texcoord = texrf + (texrb - texrf) * 0.03; + + covertices[6].texcoord = texlf + (texlb - texlf) * 0.10; + covertices[7].texcoord = texrf + (texrb - texrf) * 0.10; + covertices[8].texcoord = texlf + (texlb - texlf) * 0.10; + covertices[9].texcoord = texrf + (texrb - texrf) * 0.10; + + covertices[10].texcoord = texlf + (texlb - texlf) * 0.25; + covertices[11].texcoord = texrf + (texrb - texrf) * 0.25; + covertices[12].texcoord = texlf + (texlb - texlf) * 0.25; + covertices[13].texcoord = texrf + (texrb - texrf) * 0.25; + + covertices[14].texcoord = texlf + (texlb - texlf) * 0.45; + covertices[15].texcoord = texrf + (texrb - texrf) * 0.45; + covertices[16].texcoord = texlf + (texlb - texlf) * 0.45; + covertices[17].texcoord = texrf + (texrb - texrf) * 0.45; + + covertices[18].texcoord = texlf + (texlb - texlf) * airfoilpos[56]; + covertices[19].texcoord = texrf + (texrb - texrf) * airfoilpos[56]; + covertices[20].texcoord = texlf + (texlb - texlf) * airfoilpos[56]; + covertices[21].texcoord = texrf + (texrb - texrf) * airfoilpos[56]; + + covertices[22].texcoord = covertices[18].texcoord; + covertices[23].texcoord = covertices[19].texcoord; + covertices[24].texcoord = covertices[20].texcoord; + covertices[25].texcoord = covertices[21].texcoord; + + covertices[26].texcoord = texlb; + covertices[27].texcoord = texrb; + covertices[28].texcoord = texlb; + covertices[29].texcoord = texrb; + + for (i = 0; i < 24; i++) + covertices[i + 30].texcoord = covertices[i].texcoord; /// Define triangles /// The values in this table refer to vertices in the above table - bandibufCount = 3*20; - faceibufCount = 3*20; - cupibufCount=3*2; - cdnibufCount=3*2; - facefaces=(unsigned short*)malloc(faceibufCount*sizeof(unsigned short)); - bandfaces=(unsigned short*)malloc(bandibufCount*sizeof(unsigned short)); - cupfaces=(unsigned short*)malloc(cupibufCount*sizeof(unsigned short)); - cdnfaces=(unsigned short*)malloc(cdnibufCount*sizeof(unsigned short)); - - //attack - bandfaces[0]=0; - bandfaces[1]=2; - bandfaces[2]=1; - - bandfaces[3]=2; - bandfaces[4]=3; - bandfaces[5]=1; - - bandfaces[6]=0; - bandfaces[7]=1; - bandfaces[8]=4; - - bandfaces[9]=4; - bandfaces[10]=1; - bandfaces[11]=5; - for (i=0; i<5; i++) + bandibufCount = 3 * 20; + faceibufCount = 3 * 20; + cupibufCount = 3 * 2; + cdnibufCount = 3 * 2; + facefaces = (unsigned short *)malloc(faceibufCount * sizeof(unsigned short)); + bandfaces = (unsigned short *)malloc(bandibufCount * sizeof(unsigned short)); + cupfaces = (unsigned short *)malloc(cupibufCount * sizeof(unsigned short)); + cdnfaces = (unsigned short *)malloc(cdnibufCount * sizeof(unsigned short)); + + // attack + bandfaces[0] = 0; + bandfaces[1] = 2; + bandfaces[2] = 1; + + bandfaces[3] = 2; + bandfaces[4] = 3; + bandfaces[5] = 1; + + bandfaces[6] = 0; + bandfaces[7] = 1; + bandfaces[8] = 4; + + bandfaces[9] = 4; + bandfaces[10] = 1; + bandfaces[11] = 5; + for (i = 0; i < 5; i++) { - //band - int v=i*4+2; - if (i!=4) + // band + int v = i * 4 + 2; + if (i != 4) { - bandfaces[i*12+12]=v; - bandfaces[i*12+13]=v+4; - bandfaces[i*12+14]=v+1; + bandfaces[i * 12 + 12] = v; + bandfaces[i * 12 + 13] = v + 4; + bandfaces[i * 12 + 14] = v + 1; - bandfaces[i*12+15]=v+4; - bandfaces[i*12+16]=v+5; - bandfaces[i*12+17]=v+1; + bandfaces[i * 12 + 15] = v + 4; + bandfaces[i * 12 + 16] = v + 5; + bandfaces[i * 12 + 17] = v + 1; - bandfaces[i*12+18]=v+2; - bandfaces[i*12+19]=v+3; - bandfaces[i*12+20]=v+6; + bandfaces[i * 12 + 18] = v + 2; + bandfaces[i * 12 + 19] = v + 3; + bandfaces[i * 12 + 20] = v + 6; - bandfaces[i*12+21]=v+6; - bandfaces[i*12+22]=v+3; - bandfaces[i*12+23]=v+7; + bandfaces[i * 12 + 21] = v + 6; + bandfaces[i * 12 + 22] = v + 3; + bandfaces[i * 12 + 23] = v + 7; } - //sides - facefaces[i*12]=30+0; - facefaces[i*12+1]=30+v+4; - facefaces[i*12+2]=30+v; + // sides + facefaces[i * 12] = 30 + 0; + facefaces[i * 12 + 1] = 30 + v + 4; + facefaces[i * 12 + 2] = 30 + v; - facefaces[i*12+3]=30+0; - facefaces[i*12+4]=30+v+2; - facefaces[i*12+5]=30+v+6; + facefaces[i * 12 + 3] = 30 + 0; + facefaces[i * 12 + 4] = 30 + v + 2; + facefaces[i * 12 + 5] = 30 + v + 6; - facefaces[i*12+6]=30+1; - facefaces[i*12+7]=30+v+1; - facefaces[i*12+8]=30+v+5; + facefaces[i * 12 + 6] = 30 + 1; + facefaces[i * 12 + 7] = 30 + v + 1; + facefaces[i * 12 + 8] = 30 + v + 5; - facefaces[i*12+9]=30+1; - facefaces[i*12+10]=30+v+7; - facefaces[i*12+11]=30+v+3; - if (i==4) + facefaces[i * 12 + 9] = 30 + 1; + facefaces[i * 12 + 10] = 30 + v + 7; + facefaces[i * 12 + 11] = 30 + v + 3; + if (i == 4) { - facefaces[i*12]=30+0; - facefaces[i*12+1]=30+v+2; - facefaces[i*12+2]=30+v; + facefaces[i * 12] = 30 + 0; + facefaces[i * 12 + 1] = 30 + v + 2; + facefaces[i * 12 + 2] = 30 + v; - facefaces[i*12+3]=30+v+4; - facefaces[i*12+4]=30+v; - facefaces[i*12+5]=30+v+2; + facefaces[i * 12 + 3] = 30 + v + 4; + facefaces[i * 12 + 4] = 30 + v; + facefaces[i * 12 + 5] = 30 + v + 2; - facefaces[i*12+6]=30+1; - facefaces[i*12+7]=30+v+1; - facefaces[i*12+8]=30+v+3; + facefaces[i * 12 + 6] = 30 + 1; + facefaces[i * 12 + 7] = 30 + v + 1; + facefaces[i * 12 + 8] = 30 + v + 3; - facefaces[i*12+9]=30+v+5; - facefaces[i*12+10]=30+v+3; - facefaces[i*12+11]=30+v+1; + facefaces[i * 12 + 9] = 30 + v + 5; + facefaces[i * 12 + 10] = 30 + v + 3; + facefaces[i * 12 + 11] = 30 + v + 1; } - } - cupfaces[0]=22; - cupfaces[1]=26; - cupfaces[2]=23; - cupfaces[3]=26; - cupfaces[4]=27; - cupfaces[5]=23; - - cdnfaces[0]=24; - cdnfaces[1]=25; - cdnfaces[2]=29; - cdnfaces[3]=24; - cdnfaces[4]=29; - cdnfaces[5]=28; - - float tsref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbld].RelPosition-nodes[nfld].RelPosition).length(); - sref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbrd].RelPosition-nodes[nfrd].RelPosition).length(); - if (tsref>sref) sref=tsref; - sref=sref*sref; - - lratio=(nodes[nfld].RelPosition-nodes[nflu].RelPosition).length()/(nodes[nfld].RelPosition-nodes[nbld].RelPosition).length(); - rratio=(nodes[nfrd].RelPosition-nodes[nfru].RelPosition).length()/(nodes[nfrd].RelPosition-nodes[nbrd].RelPosition).length(); - - thickness=(nodes[nfld].RelPosition-nodes[nflu].RelPosition).length(); - - //update coords + cupfaces[0] = 22; + cupfaces[1] = 26; + cupfaces[2] = 23; + cupfaces[3] = 26; + cupfaces[4] = 27; + cupfaces[5] = 23; + + cdnfaces[0] = 24; + cdnfaces[1] = 25; + cdnfaces[2] = 29; + cdnfaces[3] = 24; + cdnfaces[4] = 29; + cdnfaces[5] = 28; + + float tsref = 2.0 * (nodes[nfrd].RelPosition - nodes[nfld].RelPosition) + .crossProduct(nodes[nbld].RelPosition - nodes[nfld].RelPosition) + .length(); + sref = 2.0 * (nodes[nfrd].RelPosition - nodes[nfld].RelPosition) + .crossProduct(nodes[nbrd].RelPosition - nodes[nfrd].RelPosition) + .length(); + if (tsref > sref) sref = tsref; + sref = sref * sref; + + lratio = (nodes[nfld].RelPosition - nodes[nflu].RelPosition).length() / + (nodes[nfld].RelPosition - nodes[nbld].RelPosition).length(); + rratio = (nodes[nfrd].RelPosition - nodes[nfru].RelPosition).length() / + (nodes[nfrd].RelPosition - nodes[nbrd].RelPosition).length(); + + thickness = (nodes[nfld].RelPosition - nodes[nflu].RelPosition).length(); + + // update coords this->updateVerticesPhysics(); this->updateVerticesGfx(actor->GetGfxActor()); /// Create vertex data structure for 8 vertices shared between submeshes - msh->sharedVertexData = new VertexData(); + msh->sharedVertexData = new VertexData(); msh->sharedVertexData->vertexCount = nVertices; /// Create declaration (memory format) of vertex data - decl = msh->sharedVertexData->vertexDeclaration; + decl = msh->sharedVertexData->vertexDeclaration; size_t offset = 0; decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); -// decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE); -// offset += VertexElement::getTypeSize(VET_FLOAT3); + // decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE); + // offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) - vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(offset, msh->sharedVertexData->vertexCount, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer - VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; + VertexBufferBinding *bind = msh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); - //for the face + // for the face /// Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - faceibufCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, faceibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card faceibuf->writeData(0, faceibuf->getSizeInBytes(), facefaces, true); /// Set parameters of the submesh - subface->useSharedVertices = true; + subface->useSharedVertices = true; subface->indexData->indexBuffer = faceibuf; - subface->indexData->indexCount = faceibufCount; - subface->indexData->indexStart = 0; + subface->indexData->indexCount = faceibufCount; + subface->indexData->indexStart = 0; - //for the band + // for the band /// Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - bandibufCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, bandibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card bandibuf->writeData(0, bandibuf->getSizeInBytes(), bandfaces, true); /// Set parameters of the submesh - subband->useSharedVertices = true; + subband->useSharedVertices = true; subband->indexData->indexBuffer = bandibuf; - subband->indexData->indexCount = bandibufCount; - subband->indexData->indexStart = 0; + subband->indexData->indexCount = bandibufCount; + subband->indexData->indexStart = 0; - //for the aileron up + // for the aileron up /// Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr cupibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - cupibufCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr cupibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, cupibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card cupibuf->writeData(0, cupibuf->getSizeInBytes(), cupfaces, true); /// Set parameters of the submesh - subcup->useSharedVertices = true; + subcup->useSharedVertices = true; subcup->indexData->indexBuffer = cupibuf; - subcup->indexData->indexCount = cupibufCount; - subcup->indexData->indexStart = 0; + subcup->indexData->indexCount = cupibufCount; + subcup->indexData->indexStart = 0; - //for the aileron down + // for the aileron down /// Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr cdnibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - cdnibufCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr cdnibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, cdnibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card cdnibuf->writeData(0, cdnibuf->getSizeInBytes(), cdnfaces, true); /// Set parameters of the submesh - subcdn->useSharedVertices = true; + subcdn->useSharedVertices = true; subcdn->indexData->indexBuffer = cdnibuf; - subcdn->indexData->indexCount = cdnibufCount; - subcdn->indexData->indexStart = 0; + subcdn->indexData->indexCount = cdnibufCount; + subcdn->indexData->indexStart = 0; /// Set bounding information (for culling) - msh->_setBounds(AxisAlignedBox(-20,-20,-20,20,20,20), true); - //msh->_setBoundingSphereRadius(20.0); + msh->_setBounds(AxisAlignedBox(-20, -20, -20, 20, 20, 20), true); + // msh->_setBoundingSphereRadius(20.0); /// Notify Mesh object that it has been loaded - //MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(false); - //msh->prepareForShadowVolume(); + // MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(false); + // msh->prepareForShadowVolume(); msh->load(); - //MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes() + // MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes() } void FlexAirfoil::updateVerticesPhysics() { Vector3 center; - center=nodes[nfld].AbsPosition; + center = nodes[nfld].AbsPosition; - Vector3 vx=nodes[nfrd].AbsPosition-nodes[nfld].AbsPosition; - Vector3 vyl=nodes[nflu].AbsPosition-nodes[nfld].AbsPosition; - Vector3 vzl=nodes[nbld].AbsPosition-nodes[nfld].AbsPosition; - Vector3 vyr=nodes[nfru].AbsPosition-nodes[nfrd].AbsPosition; - Vector3 vzr=nodes[nbrd].AbsPosition-nodes[nfrd].AbsPosition; + Vector3 vx = nodes[nfrd].AbsPosition - nodes[nfld].AbsPosition; + Vector3 vyl = nodes[nflu].AbsPosition - nodes[nfld].AbsPosition; + Vector3 vzl = nodes[nbld].AbsPosition - nodes[nfld].AbsPosition; + Vector3 vyr = nodes[nfru].AbsPosition - nodes[nfrd].AbsPosition; + Vector3 vzr = nodes[nbrd].AbsPosition - nodes[nfrd].AbsPosition; - if (breakable) {broken=broken || (vx.crossProduct(vzl).squaredLength()>sref)||(vx.crossProduct(vzr).squaredLength()>sref);} - else {broken=(vx.crossProduct(vzl).squaredLength()>sref)||(vx.crossProduct(vzr).squaredLength()>sref);} + if (breakable) + { broken = broken || (vx.crossProduct(vzl).squaredLength() > sref) || (vx.crossProduct(vzr).squaredLength() > sref); } + else + { + broken = (vx.crossProduct(vzl).squaredLength() > sref) || (vx.crossProduct(vzr).squaredLength() > sref); + } - //control surface + // control surface if (hascontrol) { - float radius=1.0-chordratio; - airfoilpos[82]=0.5+radius*sin(deflection/57.0)/rratio; - airfoilpos[79]=0.5+radius*sin(deflection/57.0)/lratio; - airfoilpos[83]=chordratio+radius*cos(deflection/57.0); - airfoilpos[80]=airfoilpos[83]; - airfoilpos[89]=airfoilpos[83]; - airfoilpos[88]=airfoilpos[82]; - airfoilpos[86]=airfoilpos[80]; - airfoilpos[85]=airfoilpos[79]; + float radius = 1.0 - chordratio; + airfoilpos[82] = 0.5 + radius * sin(deflection / 57.0) / rratio; + airfoilpos[79] = 0.5 + radius * sin(deflection / 57.0) / lratio; + airfoilpos[83] = chordratio + radius * cos(deflection / 57.0); + airfoilpos[80] = airfoilpos[83]; + airfoilpos[89] = airfoilpos[83]; + airfoilpos[88] = airfoilpos[82]; + airfoilpos[86] = airfoilpos[80]; + airfoilpos[85] = airfoilpos[79]; } } -Vector3 FlexAirfoil::updateVerticesGfx(RoR::GfxActor* gfx_actor) +Vector3 FlexAirfoil::updateVerticesGfx(RoR::GfxActor *gfx_actor) { - auto gfx_nodes = gfx_actor->GetSimNodeBuffer(); - int i; + auto gfx_nodes = gfx_actor->GetSimNodeBuffer(); + int i; Vector3 center; - center=gfx_nodes[nfld].AbsPosition; + center = gfx_nodes[nfld].AbsPosition; - Vector3 vx=gfx_nodes[nfrd].AbsPosition-gfx_nodes[nfld].AbsPosition; - Vector3 vyl=gfx_nodes[nflu].AbsPosition-gfx_nodes[nfld].AbsPosition; - Vector3 vzl=gfx_nodes[nbld].AbsPosition-gfx_nodes[nfld].AbsPosition; - Vector3 vyr=gfx_nodes[nfru].AbsPosition-gfx_nodes[nfrd].AbsPosition; - Vector3 vzr=gfx_nodes[nbrd].AbsPosition-gfx_nodes[nfrd].AbsPosition; + Vector3 vx = gfx_nodes[nfrd].AbsPosition - gfx_nodes[nfld].AbsPosition; + Vector3 vyl = gfx_nodes[nflu].AbsPosition - gfx_nodes[nfld].AbsPosition; + Vector3 vzl = gfx_nodes[nbld].AbsPosition - gfx_nodes[nfld].AbsPosition; + Vector3 vyr = gfx_nodes[nfru].AbsPosition - gfx_nodes[nfrd].AbsPosition; + Vector3 vzr = gfx_nodes[nbrd].AbsPosition - gfx_nodes[nfrd].AbsPosition; - Vector3 facenormal=vx; + Vector3 facenormal = vx; facenormal.normalise(); if (!broken) { - for (i=0; i<30; i++) + for (i = 0; i < 30; i++) { - if (i%2) - covertices[i].vertex=airfoilpos[i*3]*vx+airfoilpos[i*3+1]*vyr+airfoilpos[i*3+2]*vzr; + if (i % 2) + covertices[i].vertex = airfoilpos[i * 3] * vx + airfoilpos[i * 3 + 1] * vyr + airfoilpos[i * 3 + 2] * vzr; else - covertices[i].vertex=airfoilpos[i*3]*vx+airfoilpos[i*3+1]*vyl+airfoilpos[i*3+2]*vzl; - if (i<22) covertices[i+30].vertex=covertices[i].vertex; + covertices[i].vertex = airfoilpos[i * 3] * vx + airfoilpos[i * 3 + 1] * vyl + airfoilpos[i * 3 + 2] * vzl; + if (i < 22) covertices[i + 30].vertex = covertices[i].vertex; } - covertices[30+22].vertex=covertices[28].vertex; - covertices[30+23].vertex=covertices[29].vertex; + covertices[30 + 22].vertex = covertices[28].vertex; + covertices[30 + 23].vertex = covertices[29].vertex; } else { - for (i=0; i<30; i++) + for (i = 0; i < 30; i++) { - if (i%2) - covertices[i].vertex=airfoilpos[i*3]*Vector3(0.01,0,0)+airfoilpos[i*3+1]*Vector3(0,0.01,0)+airfoilpos[i*3+2]*Vector3(0,0,0.01); + if (i % 2) + covertices[i].vertex = airfoilpos[i * 3] * Vector3(0.01, 0, 0) + airfoilpos[i * 3 + 1] * Vector3(0, 0.01, 0) + + airfoilpos[i * 3 + 2] * Vector3(0, 0, 0.01); else - covertices[i].vertex=airfoilpos[i*3]*Vector3(0.01,0,0)+airfoilpos[i*3+1]*Vector3(0,0.01,0)+airfoilpos[i*3+2]*Vector3(0,0,0.01); - if (i<22) covertices[i+30].vertex=covertices[i].vertex; + covertices[i].vertex = airfoilpos[i * 3] * Vector3(0.01, 0, 0) + airfoilpos[i * 3 + 1] * Vector3(0, 0.01, 0) + + airfoilpos[i * 3 + 2] * Vector3(0, 0, 0.01); + if (i < 22) covertices[i + 30].vertex = covertices[i].vertex; } - covertices[30+22].vertex=covertices[28].vertex; - covertices[30+23].vertex=covertices[29].vertex; + covertices[30 + 22].vertex = covertices[28].vertex; + covertices[30 + 23].vertex = covertices[29].vertex; } if (isstabilator) { - //rotate stabilator + // rotate stabilator Vector3 rcent, raxis; if (!stabilleft) { - rcent=((gfx_nodes[nflu].AbsPosition+gfx_nodes[nbld].AbsPosition)/2.0+(gfx_nodes[nflu].AbsPosition-gfx_nodes[nblu].AbsPosition)/4.0)-center; - raxis=(gfx_nodes[nflu].AbsPosition-gfx_nodes[nfld].AbsPosition).crossProduct(gfx_nodes[nflu].AbsPosition-gfx_nodes[nblu].AbsPosition); + rcent = ((gfx_nodes[nflu].AbsPosition + gfx_nodes[nbld].AbsPosition) / 2.0 + + (gfx_nodes[nflu].AbsPosition - gfx_nodes[nblu].AbsPosition) / 4.0) - + center; + raxis = (gfx_nodes[nflu].AbsPosition - gfx_nodes[nfld].AbsPosition) + .crossProduct(gfx_nodes[nflu].AbsPosition - gfx_nodes[nblu].AbsPosition); } else { - rcent=((gfx_nodes[nfru].AbsPosition+gfx_nodes[nbrd].AbsPosition)/2.0+(gfx_nodes[nfru].AbsPosition-gfx_nodes[nbru].AbsPosition)/4.0)-center; - raxis=(gfx_nodes[nfru].AbsPosition-gfx_nodes[nfrd].AbsPosition).crossProduct(gfx_nodes[nfru].AbsPosition-gfx_nodes[nbru].AbsPosition); + rcent = ((gfx_nodes[nfru].AbsPosition + gfx_nodes[nbrd].AbsPosition) / 2.0 + + (gfx_nodes[nfru].AbsPosition - gfx_nodes[nbru].AbsPosition) / 4.0) - + center; + raxis = (gfx_nodes[nfru].AbsPosition - gfx_nodes[nfrd].AbsPosition) + .crossProduct(gfx_nodes[nfru].AbsPosition - gfx_nodes[nbru].AbsPosition); } raxis.normalise(); - Quaternion rot=Quaternion(Degree(deflection), raxis); - for (i=0; i<54; i++) + Quaternion rot = Quaternion(Degree(deflection), raxis); + for (i = 0; i < 54; i++) { - covertices[i].vertex=rcent+rot*(covertices[i].vertex-rcent); + covertices[i].vertex = rcent + rot * (covertices[i].vertex - rcent); } } - //init normals - for (i=0; i<(int)nVertices; i++) + // init normals + for (i = 0; i < (int)nVertices; i++) { - covertices[i].normal=Vector3::ZERO; + covertices[i].normal = Vector3::ZERO; } - //normals - //accumulate normals per triangle - for (i=0; i<(int)bandibufCount/3; i++) + // normals + // accumulate normals per triangle + for (i = 0; i < (int)bandibufCount / 3; i++) { Vector3 v1, v2; - v1=covertices[bandfaces[i*3+1]].vertex-covertices[bandfaces[i*3]].vertex; - v2=covertices[bandfaces[i*3+2]].vertex-covertices[bandfaces[i*3]].vertex; - v1=v1.crossProduct(v2); + v1 = covertices[bandfaces[i * 3 + 1]].vertex - covertices[bandfaces[i * 3]].vertex; + v2 = covertices[bandfaces[i * 3 + 2]].vertex - covertices[bandfaces[i * 3]].vertex; + v1 = v1.crossProduct(v2); v1.normalise(); - covertices[bandfaces[i*3]].normal+=v1; - covertices[bandfaces[i*3+1]].normal+=v1; - covertices[bandfaces[i*3+2]].normal+=v1; + covertices[bandfaces[i * 3]].normal += v1; + covertices[bandfaces[i * 3 + 1]].normal += v1; + covertices[bandfaces[i * 3 + 2]].normal += v1; } - for (i=0; i<(int)cupibufCount/3; i++) + for (i = 0; i < (int)cupibufCount / 3; i++) { Vector3 v1, v2; - v1=covertices[cupfaces[i*3+1]].vertex-covertices[cupfaces[i*3]].vertex; - v2=covertices[cupfaces[i*3+2]].vertex-covertices[cupfaces[i*3]].vertex; - v1=v1.crossProduct(v2); + v1 = covertices[cupfaces[i * 3 + 1]].vertex - covertices[cupfaces[i * 3]].vertex; + v2 = covertices[cupfaces[i * 3 + 2]].vertex - covertices[cupfaces[i * 3]].vertex; + v1 = v1.crossProduct(v2); v1.normalise(); - covertices[cupfaces[i*3]].normal+=v1; - covertices[cupfaces[i*3+1]].normal+=v1; - covertices[cupfaces[i*3+2]].normal+=v1; + covertices[cupfaces[i * 3]].normal += v1; + covertices[cupfaces[i * 3 + 1]].normal += v1; + covertices[cupfaces[i * 3 + 2]].normal += v1; } - for (i=0; i<(int)cdnibufCount/3; i++) + for (i = 0; i < (int)cdnibufCount / 3; i++) { Vector3 v1, v2; - v1=covertices[cdnfaces[i*3+1]].vertex-covertices[cdnfaces[i*3]].vertex; - v2=covertices[cdnfaces[i*3+2]].vertex-covertices[cdnfaces[i*3]].vertex; - v1=v1.crossProduct(v2); + v1 = covertices[cdnfaces[i * 3 + 1]].vertex - covertices[cdnfaces[i * 3]].vertex; + v2 = covertices[cdnfaces[i * 3 + 2]].vertex - covertices[cdnfaces[i * 3]].vertex; + v1 = v1.crossProduct(v2); v1.normalise(); - covertices[cdnfaces[i*3]].normal+=v1; - covertices[cdnfaces[i*3+1]].normal+=v1; - covertices[cdnfaces[i*3+2]].normal+=v1; + covertices[cdnfaces[i * 3]].normal += v1; + covertices[cdnfaces[i * 3 + 1]].normal += v1; + covertices[cdnfaces[i * 3 + 2]].normal += v1; } - //normalize - for (i=0; i<30; i++) + // normalize + for (i = 0; i < 30; i++) { covertices[i].normal.normalise(); } - //for the faces - for (i=0; i<24; i++) - if (i%2) - covertices[i+30].normal=facenormal; + // for the faces + for (i = 0; i < 24; i++) + if (i % 2) + covertices[i + 30].normal = facenormal; else - covertices[i+30].normal=-facenormal; + covertices[i + 30].normal = -facenormal; return center; } @@ -553,25 +540,26 @@ void FlexAirfoil::uploadVertices() vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); } - void FlexAirfoil::setControlDeflection(float val) { - if (val<0) deflection=-val*mindef; - else deflection=val*maxdef; + if (val < 0) + deflection = -val * mindef; + else + deflection = val * maxdef; } void FlexAirfoil::enableInducedDrag(float span, float area, bool l) { - idSpan=span; - idArea=area; - useInducedDrag=true; - idLeft=l; + idSpan = span; + idArea = area; + useInducedDrag = true; + idLeft = l; } void FlexAirfoil::addwash(int propid, float ratio) { - washpropnum[free_wash]=propid; - washpropratio[free_wash]=ratio; + washpropnum[free_wash] = propid; + washpropratio[free_wash] = ratio; free_wash++; } @@ -580,91 +568,95 @@ void FlexAirfoil::updateForces() if (!airfoil) return; if (broken) return; - //evaluate wind direction - Vector3 wind=-(nodes[nfld].Velocity+nodes[nfrd].Velocity)/2.0; - //add wash + // evaluate wind direction + Vector3 wind = -(nodes[nfld].Velocity + nodes[nfrd].Velocity) / 2.0; + // add wash int i; - for (i=0; igetpropwash())*aeroengines[washpropnum[i]]->getAxis(); - float wspeed=wind.length(); - //chord vector, front to back - Vector3 chordv=((nodes[nbld].RelPosition-nodes[nfld].RelPosition)+(nodes[nbrd].RelPosition-nodes[nfrd].RelPosition))/2.0; - float chord=chordv.length(); - //span vector, left to right - Vector3 spanv=((nodes[nfrd].RelPosition-nodes[nfld].RelPosition)+(nodes[nbrd].RelPosition-nodes[nbld].RelPosition))/2.0; - float span=spanv.length(); - //lift vector - Vector3 liftv=spanv.crossProduct(-wind); - - //wing normal - float s=span*chord; - Vector3 normv=chordv.crossProduct(spanv); + for (i = 0; i < free_wash; i++) + wind -= (0.5 * washpropratio[i] * aeroengines[washpropnum[i]]->getpropwash()) * aeroengines[washpropnum[i]]->getAxis(); + float wspeed = wind.length(); + // chord vector, front to back + Vector3 chordv = + ((nodes[nbld].RelPosition - nodes[nfld].RelPosition) + (nodes[nbrd].RelPosition - nodes[nfrd].RelPosition)) / 2.0; + float chord = chordv.length(); + // span vector, left to right + Vector3 spanv = + ((nodes[nfrd].RelPosition - nodes[nfld].RelPosition) + (nodes[nbrd].RelPosition - nodes[nbld].RelPosition)) / 2.0; + float span = spanv.length(); + // lift vector + Vector3 liftv = spanv.crossProduct(-wind); + + // wing normal + float s = span * chord; + Vector3 normv = chordv.crossProduct(spanv); normv.normalise(); - //calculate angle of attack + // calculate angle of attack Vector3 pwind; - pwind=Plane(Vector3::ZERO, normv, chordv).projectVector(-wind); + pwind = Plane(Vector3::ZERO, normv, chordv).projectVector(-wind); Vector3 dumb; - Degree daoa; + Degree daoa; chordv.getRotationTo(-pwind).ToAngleAxis(daoa, dumb); - aoa=daoa.valueDegrees(); - float raoa=daoa.valueRadians(); - if (dumb.dotProduct(spanv)>0) {aoa=-aoa; raoa=-raoa;}; + aoa = daoa.valueDegrees(); + float raoa = daoa.valueRadians(); + if (dumb.dotProduct(spanv) > 0) + { + aoa = -aoa; + raoa = -raoa; + }; - //get airfoil data + // get airfoil data float cz, cx, cm; if (isstabilator) - airfoil->getparams(aoa-deflection, chordratio, 0, &cz, &cx, &cm); + airfoil->getparams(aoa - deflection, chordratio, 0, &cz, &cx, &cm); else airfoil->getparams(aoa, chordratio, deflection, &cz, &cx, &cm); + // tropospheric model valid up to 11.000m (33.000ft) + float altitude = nodes[nfld].AbsPosition.y; + float sea_level_pressure = 101325; // in Pa + float airpressure = sea_level_pressure * approx_pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); // in Pa + float airdensity = airpressure * 0.0000120896; // 1.225 at sea level - //tropospheric model valid up to 11.000m (33.000ft) - float altitude=nodes[nfld].AbsPosition.y; - float sea_level_pressure=101325; //in Pa - float airpressure=sea_level_pressure*approx_pow(1.0-0.0065*altitude/288.15, 5.24947); //in Pa - float airdensity=airpressure*0.0000120896;//1.225 at sea level + Vector3 wforce = Vector3::ZERO; + // drag + wforce = (cx * 0.5 * airdensity * wspeed * s) * wind; - Vector3 wforce=Vector3::ZERO; - //drag - wforce=(cx*0.5*airdensity*wspeed*s)*wind; - - //induced drag + // induced drag if (useInducedDrag) { - Vector3 idf=(cx*cx*0.25*airdensity*wspeed*idArea*idArea/(3.14159*idSpan*idSpan))*wind; + Vector3 idf = (cx * cx * 0.25 * airdensity * wspeed * idArea * idArea / (3.14159 * idSpan * idSpan)) * wind; if (idLeft) { - nodes[nblu].Forces+=idf; - nodes[nbld].Forces+=idf; + nodes[nblu].Forces += idf; + nodes[nbld].Forces += idf; } else { - nodes[nbru].Forces+=idf; - nodes[nbrd].Forces+=idf; + nodes[nbru].Forces += idf; + nodes[nbrd].Forces += idf; } } - //lift - wforce+=(cz*0.5*airdensity*wspeed*chord)*liftv; - - //moment - float moment=-cm*0.5*airdensity*wspeed*wspeed*s;//*chord; - //apply forces - - Vector3 f1=wforce*(liftcoef * 0.75/4.0f)+normv*(liftcoef *moment/(4.0f*0.25f)); - Vector3 f2=wforce*(liftcoef *0.25/4.0f)-normv*(liftcoef *moment/(4.0f*0.75f)); - - //focal at 0.25 chord - nodes[nfld].Forces+=f1; - nodes[nflu].Forces+=f1; - nodes[nfrd].Forces+=f1; - nodes[nfru].Forces+=f1; - nodes[nbld].Forces+=f2; - nodes[nblu].Forces+=f2; - nodes[nbrd].Forces+=f2; - nodes[nbru].Forces+=f2; - + // lift + wforce += (cz * 0.5 * airdensity * wspeed * chord) * liftv; + + // moment + float moment = -cm * 0.5 * airdensity * wspeed * wspeed * s; //*chord; + // apply forces + + Vector3 f1 = wforce * (liftcoef * 0.75 / 4.0f) + normv * (liftcoef * moment / (4.0f * 0.25f)); + Vector3 f2 = wforce * (liftcoef * 0.25 / 4.0f) - normv * (liftcoef * moment / (4.0f * 0.75f)); + + // focal at 0.25 chord + nodes[nfld].Forces += f1; + nodes[nflu].Forces += f1; + nodes[nfrd].Forces += f1; + nodes[nfru].Forces += f1; + nodes[nbld].Forces += f2; + nodes[nblu].Forces += f2; + nodes[nbrd].Forces += f2; + nodes[nbru].Forces += f2; } FlexAirfoil::~FlexAirfoil() @@ -674,12 +666,12 @@ FlexAirfoil::~FlexAirfoil() { msh->unload(); Ogre::MeshManager::getSingleton().remove(msh->getHandle()); // Necessary to truly erase manually created resource. - msh.setNull(); // Important! It's a shared pointer. + msh.setNull(); // Important! It's a shared pointer. } - if (vertices != nullptr) { free (vertices); } - if (facefaces != nullptr) { free (facefaces); } - if (bandfaces != nullptr) { free (bandfaces); } - if (cupfaces != nullptr) { free (cupfaces); } - if (cdnfaces != nullptr) { free (cdnfaces); } + if (vertices != nullptr) { free(vertices); } + if (facefaces != nullptr) { free(facefaces); } + if (bandfaces != nullptr) { free(bandfaces); } + if (cupfaces != nullptr) { free(cupfaces); } + if (cdnfaces != nullptr) { free(cdnfaces); } } diff --git a/source/main/physics/flex/FlexAirfoil.h b/source/main/physics/flex/FlexAirfoil.h index e0ddba65bd..10d7933b24 100644 --- a/source/main/physics/flex/FlexAirfoil.h +++ b/source/main/physics/flex/FlexAirfoil.h @@ -20,29 +20,27 @@ #pragma once -#include - -#include "RoRPrerequisites.h" #include "BeamData.h" // For MAX_AEROENGINES +#include "RoRPrerequisites.h" + +#include class FlexAirfoil : public ZeroedMemoryAllocator { friend class RigInspector; // Debug utility class -public: - - FlexAirfoil(Ogre::String const& wname, Actor* actor, - int pnfld, int pnfrd, int pnflu, int pnfru, int pnbld, int pnbrd, int pnblu, int pnbru, - std::string const & texname, - Ogre::Vector2 texlf, Ogre::Vector2 texrf, Ogre::Vector2 texlb, Ogre::Vector2 texrb, - char mtype, float controlratio, float mind, float maxd, Ogre::String const& afname, float lift_coef, bool break_able); + public: + FlexAirfoil(Ogre::String const &wname, Actor *actor, int pnfld, int pnfrd, int pnflu, int pnfru, int pnbld, int pnbrd, + int pnblu, int pnbru, std::string const &texname, Ogre::Vector2 texlf, Ogre::Vector2 texrf, Ogre::Vector2 texlb, + Ogre::Vector2 texrb, char mtype, float controlratio, float mind, float maxd, Ogre::String const &afname, + float lift_coef, bool break_able); ~FlexAirfoil(); // DEV NOTE: original `updateVertices()` updated both physics state + visuals. - void updateVerticesPhysics(); - Ogre::Vector3 updateVerticesGfx(RoR::GfxActor* gfx_actor); - void uploadVertices(); + void updateVerticesPhysics(); + Ogre::Vector3 updateVerticesGfx(RoR::GfxActor *gfx_actor); + void uploadVertices(); void setControlDeflection(float val); @@ -53,22 +51,21 @@ class FlexAirfoil : public ZeroedMemoryAllocator void updateForces(); float aoa; - char type; - int nfld; - int nfrd; - int nflu; - int nfru; - int nbld; - int nbrd; - int nblu; - int nbru; - - bool broken; - bool breakable; + char type; + int nfld; + int nfrd; + int nflu; + int nfru; + int nbld; + int nbrd; + int nblu; + int nbru; + + bool broken; + bool breakable; float liftcoef; -private: - + private: float airfoilpos[90]; typedef struct @@ -79,55 +76,54 @@ class FlexAirfoil : public ZeroedMemoryAllocator Ogre::Vector2 texcoord; } CoVertice_t; - Ogre::MeshPtr msh; - Ogre::SubMesh* subface; - Ogre::SubMesh* subband; + Ogre::MeshPtr msh; + Ogre::SubMesh *subface; + Ogre::SubMesh *subband; - Ogre::SubMesh* subcup; - Ogre::SubMesh* subcdn; + Ogre::SubMesh *subcup; + Ogre::SubMesh *subcdn; - Ogre::VertexDeclaration* decl; + Ogre::VertexDeclaration * decl; Ogre::HardwareVertexBufferSharedPtr vbuf; size_t nVertices; size_t vbufCount; - union - { - float* vertices; - CoVertice_t* covertices; + union { + float * vertices; + CoVertice_t *covertices; }; - size_t faceibufCount; - size_t bandibufCount; - size_t cupibufCount; - size_t cdnibufCount; - unsigned short* facefaces; - unsigned short* bandfaces; - unsigned short* cupfaces; - unsigned short* cdnfaces; - node_t* nodes; + size_t faceibufCount; + size_t bandibufCount; + size_t cupibufCount; + size_t cdnibufCount; + unsigned short *facefaces; + unsigned short *bandfaces; + unsigned short *cupfaces; + unsigned short *cdnfaces; + node_t * nodes; float sref; float deflection; float chordratio; - bool hascontrol; - bool isstabilator; - bool stabilleft; + bool hascontrol; + bool isstabilator; + bool stabilleft; float lratio; float rratio; float mindef; float maxdef; float thickness; - bool useInducedDrag; + bool useInducedDrag; float idSpan; float idArea; - bool idLeft; + bool idLeft; - Airfoil* airfoil; - AeroEngine** aeroengines; - int free_wash; - int washpropnum[MAX_AEROENGINES]; - float washpropratio[MAX_AEROENGINES]; + Airfoil * airfoil; + AeroEngine **aeroengines; + int free_wash; + int washpropnum[MAX_AEROENGINES]; + float washpropratio[MAX_AEROENGINES]; }; diff --git a/source/main/physics/flex/FlexBody.cpp b/source/main/physics/flex/FlexBody.cpp index 2fb85432d9..a1de85c4ef 100644 --- a/source/main/physics/flex/FlexBody.cpp +++ b/source/main/physics/flex/FlexBody.cpp @@ -32,48 +32,27 @@ using namespace Ogre; -FlexBody::FlexBody( - RigDef::Flexbody* def, - RoR::FlexBodyCacheData* preloaded_from_cache, - RoR::GfxActor* gfx_actor, - Ogre::Entity* ent, - int ref, - int nx, - int ny, - Ogre::Quaternion const & rot, - std::vector & node_indices -): - m_camera_mode(-2) - , m_center_offset(def->offset) - , m_node_center(ref) - , m_node_x(nx) - , m_node_y(ny) - , m_has_texture_blend(true) - , m_scene_node(nullptr) - , m_scene_entity(ent) - , m_shared_buf_num_verts(0) - , m_has_texture(true) - , m_blend_changed(false) - , m_locators(nullptr) - , m_src_normals(nullptr) - , m_dst_normals(nullptr) - , m_dst_pos(nullptr) - , m_src_colors(nullptr) - , m_gfx_actor(gfx_actor) +FlexBody::FlexBody(RigDef::Flexbody *def, RoR::FlexBodyCacheData *preloaded_from_cache, RoR::GfxActor *gfx_actor, + Ogre::Entity *ent, int ref, int nx, int ny, Ogre::Quaternion const &rot, + std::vector &node_indices) + : m_camera_mode(-2), m_center_offset(def->offset), m_node_center(ref), m_node_x(nx), m_node_y(ny), m_has_texture_blend(true), + m_scene_node(nullptr), m_scene_entity(ent), m_shared_buf_num_verts(0), m_has_texture(true), m_blend_changed(false), + m_locators(nullptr), m_src_normals(nullptr), m_dst_normals(nullptr), m_dst_pos(nullptr), m_src_colors(nullptr), + m_gfx_actor(gfx_actor) { - Ogre::Vector3* vertices = nullptr; + Ogre::Vector3 *vertices = nullptr; - Vector3 normal = Vector3::UNIT_Y; - Vector3 position = Vector3::ZERO; + Vector3 normal = Vector3::UNIT_Y; + Vector3 position = Vector3::ZERO; Quaternion orientation = Quaternion::ZERO; - RoR::GfxActor::NodeData* nodes = m_gfx_actor->GetSimNodeBuffer(); + RoR::GfxActor::NodeData *nodes = m_gfx_actor->GetSimNodeBuffer(); if (ref >= 0) { - Vector3 diffX = nodes[nx].AbsPosition-nodes[ref].AbsPosition; - Vector3 diffY = nodes[ny].AbsPosition-nodes[ref].AbsPosition; + Vector3 diffX = nodes[nx].AbsPosition - nodes[ref].AbsPosition; + Vector3 diffY = nodes[ny].AbsPosition - nodes[ref].AbsPosition; normal = (diffY.crossProduct(diffX)).normalisedCopy(); @@ -89,60 +68,56 @@ FlexBody::FlexBody( else { // special case! - normal = Vector3::UNIT_Y; - position = nodes[0].AbsPosition + def->offset; + normal = Vector3::UNIT_Y; + position = nodes[0].AbsPosition + def->offset; orientation = rot; } - Ogre::MeshPtr mesh=ent->getMesh(); - int num_submeshes = static_cast(mesh->getNumSubMeshes()); + Ogre::MeshPtr mesh = ent->getMesh(); + int num_submeshes = static_cast(mesh->getNumSubMeshes()); if (preloaded_from_cache == nullptr) { - //determine if we have texture coordinates everywhere - if (mesh->sharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES)==0) + // determine if we have texture coordinates everywhere + if (mesh->sharedVertexData && + mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES) == 0) + { m_has_texture = false; } + for (int i = 0; i < num_submeshes; i++) { - m_has_texture=false; - } - for (int i=0; igetSubMesh(i)->useSharedVertices && mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES)==0) - { - m_has_texture=false; - } + if (!mesh->getSubMesh(i)->useSharedVertices && + mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES) == 0) + { m_has_texture = false; } } if (!m_has_texture) { LOG("FLEXBODY Warning: at least one part of this mesh does not have texture coordinates, switching off texturing!"); - m_has_texture_blend=false; + m_has_texture_blend = false; } - //detect the anomalous case where a mesh is exported without normal vectors - bool havenormal=true; - if (mesh->sharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)==0) - { - havenormal=false; - } - for (int i=0; isharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL) == 0) + { havenormal = false; } + for (int i = 0; i < num_submeshes; i++) { - if (!mesh->getSubMesh(i)->useSharedVertices && mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)==0) - { - havenormal=false; - } + if (!mesh->getSubMesh(i)->useSharedVertices && + mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL) == 0) + { havenormal = false; } } if (!havenormal) { - LOG("FLEXBODY Error: at least one part of this mesh does not have normal vectors, export your mesh with normal vectors! Disabling flexbody"); + LOG("FLEXBODY Error: at least one part of this mesh does not have normal vectors, export your mesh with normal " + "vectors! Disabling flexbody"); // NOTE: Intentionally not disabling, for compatibility with v0.4.0.7 } } else { - m_has_texture = preloaded_from_cache->header.HasTexture(); - m_has_texture_blend = preloaded_from_cache->header.HasTextureBlend(); + m_has_texture = preloaded_from_cache->header.HasTexture(); + m_has_texture_blend = preloaded_from_cache->header.HasTextureBlend(); } - //create optimal VertexDeclaration - VertexDeclaration* optimalVD=HardwareBufferManager::getSingleton().createVertexDeclaration(); + // create optimal VertexDeclaration + VertexDeclaration *optimalVD = HardwareBufferManager::getSingleton().createVertexDeclaration(); optimalVD->addElement(0, 0, VET_FLOAT3, VES_POSITION); optimalVD->addElement(1, 0, VET_FLOAT3, VES_NORMAL); if (m_has_texture_blend) optimalVD->addElement(2, 0, VET_COLOUR_ARGB, VES_DIFFUSE); @@ -155,45 +130,48 @@ FlexBody::FlexBody( optimalBufferUsages.push_back(HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); } - //adding color buffers, well get the reference later + // adding color buffers, well get the reference later if (m_has_texture_blend) { if (mesh->sharedVertexData) { - if (mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)==0) + if (mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) == 0) { - //add buffer - int index=mesh->sharedVertexData->vertexDeclaration->getMaxSource()+1; + // add buffer + int index = mesh->sharedVertexData->vertexDeclaration->getMaxSource() + 1; mesh->sharedVertexData->vertexDeclaration->addElement(index, 0, VET_COLOUR_ARGB, VES_DIFFUSE); mesh->sharedVertexData->vertexDeclaration->sort(); - index=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); - HardwareVertexBufferSharedPtr vbuf=HardwareBufferManager::getSingleton().createVertexBuffer(VertexElement::getTypeSize(VET_COLOUR_ARGB), mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + index = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); + HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_COLOUR_ARGB), mesh->sharedVertexData->vertexCount, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); mesh->sharedVertexData->vertexBufferBinding->setBinding(index, vbuf); } } - for (int i=0; igetSubMesh(i)->useSharedVertices) { - Ogre::VertexData* vertex_data = mesh->getSubMesh(i)->vertexData; - Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration; - if (vertex_decl->findElementBySemantic(VES_DIFFUSE)==0) + Ogre::VertexData * vertex_data = mesh->getSubMesh(i)->vertexData; + Ogre::VertexDeclaration *vertex_decl = vertex_data->vertexDeclaration; + if (vertex_decl->findElementBySemantic(VES_DIFFUSE) == 0) { - //add buffer - int index = vertex_decl->getMaxSource()+1; + // add buffer + int index = vertex_decl->getMaxSource() + 1; vertex_decl->addElement(index, 0, VET_COLOUR_ARGB, VES_DIFFUSE); vertex_decl->sort(); vertex_decl->findElementBySemantic(VES_DIFFUSE)->getSource(); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( - VertexElement::getTypeSize(VET_COLOUR_ARGB), vertex_data->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + VertexElement::getTypeSize(VET_COLOUR_ARGB), vertex_data->vertexCount, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); vertex_data->vertexBufferBinding->setBinding(index, vbuf); } } } } - //reorg - //LOG("FLEXBODY reorganizing buffers"); + // reorg + // LOG("FLEXBODY reorganizing buffers"); if (mesh->sharedVertexData) { mesh->sharedVertexData->reorganiseBuffers(optimalVD, optimalBufferUsages); @@ -203,7 +181,7 @@ FlexBody::FlexBody( Mesh::SubMeshIterator smIt = mesh->getSubMeshIterator(); while (smIt.hasMoreElements()) { - SubMesh* sm = smIt.getNext(); + SubMesh *sm = smIt.getNext(); if (!sm->useSharedVertices) { sm->vertexData->reorganiseBuffers(optimalVD->clone(), optimalBufferUsages); @@ -212,86 +190,82 @@ FlexBody::FlexBody( } } - //print mesh information - //LOG("FLEXBODY Printing modififed mesh informations:"); - //printMeshInfo(ent->getMesh().getPointer()); + // print mesh information + // LOG("FLEXBODY Printing modififed mesh informations:"); + // printMeshInfo(ent->getMesh().getPointer()); - //get the buffers - //getMeshInformation(ent->getMesh().getPointer(),m_vertex_count,vertices,index_count,indices, position, orientation, Vector3(1,1,1)); + // get the buffers + // getMeshInformation(ent->getMesh().getPointer(),m_vertex_count,vertices,index_count,indices, position, orientation, + // Vector3(1,1,1)); - //getting vertex counts + // getting vertex counts if (preloaded_from_cache == nullptr) { - m_vertex_count=0; - m_uses_shared_vertex_data=false; - m_num_submesh_vbufs=0; + m_vertex_count = 0; + m_uses_shared_vertex_data = false; + m_num_submesh_vbufs = 0; if (mesh->sharedVertexData) { - m_vertex_count+=mesh->sharedVertexData->vertexCount; - m_uses_shared_vertex_data=true; + m_vertex_count += mesh->sharedVertexData->vertexCount; + m_uses_shared_vertex_data = true; } - for (int i=0; igetSubMesh(i)->useSharedVertices) { - m_vertex_count+=mesh->getSubMesh(i)->vertexData->vertexCount; + m_vertex_count += mesh->getSubMesh(i)->vertexData->vertexCount; m_num_submesh_vbufs++; } } - } else + } + else { m_vertex_count = preloaded_from_cache->header.vertex_count; m_uses_shared_vertex_data = preloaded_from_cache->header.UsesSharedVertexData(); m_num_submesh_vbufs = preloaded_from_cache->header.num_submesh_vbufs; } - + // Profiler data double stat_manual_buffers_created_time = -1; - double stat_transformed_time = -1; - double stat_located_time = -1; + double stat_transformed_time = -1; + double stat_located_time = -1; if (preloaded_from_cache != nullptr) { m_dst_pos = preloaded_from_cache->dst_pos; m_src_normals = preloaded_from_cache->src_normals; m_locators = preloaded_from_cache->locators; - m_dst_normals = (Vector3*)malloc(sizeof(Vector3)*m_vertex_count); // Use malloc() for compatibility + m_dst_normals = (Vector3 *)malloc(sizeof(Vector3) * m_vertex_count); // Use malloc() for compatibility - if (m_has_texture_blend) - { - m_src_colors = preloaded_from_cache->src_colors; - } + if (m_has_texture_blend) { m_src_colors = preloaded_from_cache->src_colors; } if (mesh->sharedVertexData) { - m_shared_buf_num_verts=(int)mesh->sharedVertexData->vertexCount; - - //vertices - int source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); - m_shared_vbuf_pos=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); - //normals - source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); - m_shared_vbuf_norm=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); - //colors + m_shared_buf_num_verts = (int)mesh->sharedVertexData->vertexCount; + + // vertices + int source = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); + m_shared_vbuf_pos = mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); + // normals + source = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); + m_shared_vbuf_norm = mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); + // colors if (m_has_texture_blend) { - source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); - m_shared_vbuf_color=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); + source = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); + m_shared_vbuf_color = mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); } } unsigned int curr_submesh_idx = 0; - for (int i=0; igetSubMesh(i); - if (submesh->useSharedVertices) - { - continue; - } - const Ogre::VertexData* vertex_data = submesh->vertexData; + const Ogre::SubMesh *submesh = mesh->getSubMesh(i); + if (submesh->useSharedVertices) { continue; } + const Ogre::VertexData *vertex_data = submesh->vertexData; m_submesh_vbufs_vertex_counts[curr_submesh_idx] = (int)vertex_data->vertexCount; int source_pos = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); int source_norm = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); - m_submesh_vbufs_pos [curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_pos); + m_submesh_vbufs_pos[curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_pos); m_submesh_vbufs_norm[curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_norm); if (m_has_texture_blend) @@ -304,161 +278,155 @@ FlexBody::FlexBody( } else { - vertices=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count); - m_dst_pos=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count); - m_src_normals=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count); - m_dst_normals=(Vector3*)malloc(sizeof(Vector3)*m_vertex_count); + vertices = (Vector3 *)malloc(sizeof(Vector3) * m_vertex_count); + m_dst_pos = (Vector3 *)malloc(sizeof(Vector3) * m_vertex_count); + m_src_normals = (Vector3 *)malloc(sizeof(Vector3) * m_vertex_count); + m_dst_normals = (Vector3 *)malloc(sizeof(Vector3) * m_vertex_count); if (m_has_texture_blend) { - m_src_colors=(ARGB*)malloc(sizeof(ARGB)*m_vertex_count); - for (int i=0; i<(int)m_vertex_count; i++) m_src_colors[i]=0x00000000; + m_src_colors = (ARGB *)malloc(sizeof(ARGB) * m_vertex_count); + for (int i = 0; i < (int)m_vertex_count; i++) + m_src_colors[i] = 0x00000000; } - Vector3* vpt=vertices; - Vector3* npt=m_src_normals; + Vector3 *vpt = vertices; + Vector3 *npt = m_src_normals; if (mesh->sharedVertexData) { - m_shared_buf_num_verts=(int)mesh->sharedVertexData->vertexCount; - //vertices - int source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); - m_shared_vbuf_pos=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); - m_shared_vbuf_pos->readData(0, mesh->sharedVertexData->vertexCount*sizeof(Vector3), (void*)vpt); - vpt+=mesh->sharedVertexData->vertexCount; - //normals - source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); - m_shared_vbuf_norm=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); - m_shared_vbuf_norm->readData(0, mesh->sharedVertexData->vertexCount*sizeof(Vector3), (void*)npt); - npt+=mesh->sharedVertexData->vertexCount; - //colors + m_shared_buf_num_verts = (int)mesh->sharedVertexData->vertexCount; + // vertices + int source = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); + m_shared_vbuf_pos = mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); + m_shared_vbuf_pos->readData(0, mesh->sharedVertexData->vertexCount * sizeof(Vector3), (void *)vpt); + vpt += mesh->sharedVertexData->vertexCount; + // normals + source = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); + m_shared_vbuf_norm = mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); + m_shared_vbuf_norm->readData(0, mesh->sharedVertexData->vertexCount * sizeof(Vector3), (void *)npt); + npt += mesh->sharedVertexData->vertexCount; + // colors if (m_has_texture_blend) { - source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); - m_shared_vbuf_color=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); - m_shared_vbuf_color->writeData(0, mesh->sharedVertexData->vertexCount*sizeof(ARGB), (void*)m_src_colors); + source = mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); + m_shared_vbuf_color = mesh->sharedVertexData->vertexBufferBinding->getBuffer(source); + m_shared_vbuf_color->writeData(0, mesh->sharedVertexData->vertexCount * sizeof(ARGB), (void *)m_src_colors); } } - int cursubmesh=0; - for (int i=0; igetSubMesh(i); - if (submesh->useSharedVertices) - { - continue; - } - const Ogre::VertexData* vertex_data = submesh->vertexData; - int vertex_count = (int)vertex_data->vertexCount; + const Ogre::SubMesh *submesh = mesh->getSubMesh(i); + if (submesh->useSharedVertices) { continue; } + const Ogre::VertexData *vertex_data = submesh->vertexData; + int vertex_count = (int)vertex_data->vertexCount; m_submesh_vbufs_vertex_counts[cursubmesh] = vertex_count; - //vertices - int source = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); - m_submesh_vbufs_pos[cursubmesh]=vertex_data->vertexBufferBinding->getBuffer(source); - m_submesh_vbufs_pos[cursubmesh]->readData(0, vertex_count*sizeof(Vector3), (void*)vpt); + // vertices + int source = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); + m_submesh_vbufs_pos[cursubmesh] = vertex_data->vertexBufferBinding->getBuffer(source); + m_submesh_vbufs_pos[cursubmesh]->readData(0, vertex_count * sizeof(Vector3), (void *)vpt); vpt += vertex_count; - //normals - source = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); - m_submesh_vbufs_norm[cursubmesh]=vertex_data->vertexBufferBinding->getBuffer(source); - m_submesh_vbufs_norm[cursubmesh]->readData(0, vertex_count*sizeof(Vector3), (void*)npt); + // normals + source = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource(); + m_submesh_vbufs_norm[cursubmesh] = vertex_data->vertexBufferBinding->getBuffer(source); + m_submesh_vbufs_norm[cursubmesh]->readData(0, vertex_count * sizeof(Vector3), (void *)npt); npt += vertex_count; - //colors + // colors if (m_has_texture_blend) { source = vertex_data->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource(); m_submesh_vbufs_color[cursubmesh] = vertex_data->vertexBufferBinding->getBuffer(source); - m_submesh_vbufs_color[cursubmesh]->writeData(0, vertex_count*sizeof(ARGB), (void*)m_src_colors); + m_submesh_vbufs_color[cursubmesh]->writeData(0, vertex_count * sizeof(ARGB), (void *)m_src_colors); } cursubmesh++; } - //transform - for (int i=0; i<(int)m_vertex_count; i++) + // transform + for (int i = 0; i < (int)m_vertex_count; i++) { - vertices[i]=(orientation*vertices[i])+position; + vertices[i] = (orientation * vertices[i]) + position; } m_locators = new Locator_t[m_vertex_count]; - for (int i=0; i<(int)m_vertex_count; i++) + for (int i = 0; i < (int)m_vertex_count; i++) { - //search nearest node as the local origin + // search nearest node as the local origin float closest_node_distance = std::numeric_limits::max(); - int closest_node_index = -1; + int closest_node_index = -1; for (auto node_index : node_indices) { float node_distance = vertices[i].squaredDistance(nodes[node_index].AbsPosition); if (node_distance < closest_node_distance) { closest_node_distance = node_distance; - closest_node_index = node_index; + closest_node_index = node_index; } } if (closest_node_index == -1) { - LOG("FLEXBODY ERROR on mesh "+def->mesh_name+": REF node not found"); + LOG("FLEXBODY ERROR on mesh " + def->mesh_name + ": REF node not found"); closest_node_index = 0; } - m_locators[i].ref=closest_node_index; + m_locators[i].ref = closest_node_index; - //search the second nearest node as the X vector + // search the second nearest node as the X vector closest_node_distance = std::numeric_limits::max(); - closest_node_index = -1; + closest_node_index = -1; for (auto node_index : node_indices) { - if (node_index == m_locators[i].ref) - { - continue; - } + if (node_index == m_locators[i].ref) { continue; } float node_distance = vertices[i].squaredDistance(nodes[node_index].AbsPosition); if (node_distance < closest_node_distance) { closest_node_distance = node_distance; - closest_node_index = node_index; + closest_node_index = node_index; } } if (closest_node_index == -1) { - LOG("FLEXBODY ERROR on mesh "+def->mesh_name+": VX node not found"); + LOG("FLEXBODY ERROR on mesh " + def->mesh_name + ": VX node not found"); closest_node_index = 0; } - m_locators[i].nx=closest_node_index; + m_locators[i].nx = closest_node_index; - //search another close, orthogonal node as the Y vector + // search another close, orthogonal node as the Y vector closest_node_distance = std::numeric_limits::max(); - closest_node_index = -1; - Vector3 vx = (nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition).normalisedCopy(); + closest_node_index = -1; + Vector3 vx = (nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition).normalisedCopy(); for (auto node_index : node_indices) { - if (node_index == m_locators[i].ref || node_index == m_locators[i].nx) - { - continue; - } + if (node_index == m_locators[i].ref || node_index == m_locators[i].nx) { continue; } float node_distance = vertices[i].squaredDistance(nodes[node_index].AbsPosition); if (node_distance < closest_node_distance) { - Vector3 vt = (nodes[node_index].AbsPosition - nodes[m_locators[i].ref].AbsPosition).normalisedCopy(); - float cost = vx.dotProduct(vt); + Vector3 vt = (nodes[node_index].AbsPosition - nodes[m_locators[i].ref].AbsPosition).normalisedCopy(); + float cost = vx.dotProduct(vt); if (std::abs(cost) > std::sqrt(2.0f) / 2.0f) { - continue; //rejection, fails the orthogonality criterion (+-45 degree) + continue; // rejection, fails the orthogonality criterion (+-45 degree) } closest_node_distance = node_distance; - closest_node_index = node_index; + closest_node_index = node_index; } } if (closest_node_index == -1) { - LOG("FLEXBODY ERROR on mesh "+def->mesh_name+": VY node not found"); + LOG("FLEXBODY ERROR on mesh " + def->mesh_name + ": VY node not found"); closest_node_index = 0; } - m_locators[i].ny=closest_node_index; + m_locators[i].ny = closest_node_index; Matrix3 mat; - Vector3 diffX = nodes[m_locators[i].nx].AbsPosition-nodes[m_locators[i].ref].AbsPosition; - Vector3 diffY = nodes[m_locators[i].ny].AbsPosition-nodes[m_locators[i].ref].AbsPosition; + Vector3 diffX = nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition; + Vector3 diffY = nodes[m_locators[i].ny].AbsPosition - nodes[m_locators[i].ref].AbsPosition; mat.SetColumn(0, diffX); mat.SetColumn(1, diffY); - mat.SetColumn(2, (diffX.crossProduct(diffY)).normalisedCopy()); // Old version: mat.SetColumn(2, nodes[loc.nz].AbsPosition-nodes[loc.ref].AbsPosition); + mat.SetColumn( + 2, (diffX.crossProduct(diffY)) + .normalisedCopy()); // Old version: mat.SetColumn(2, nodes[loc.nz].AbsPosition-nodes[loc.ref].AbsPosition); mat = mat.Inverse(); - //compute coordinates in the newly formed Euclidean basis + // compute coordinates in the newly formed Euclidean basis m_locators[i].coords = mat * (vertices[i] - nodes[m_locators[i].ref].AbsPosition); // that's it! @@ -466,44 +434,46 @@ FlexBody::FlexBody( } // if (preloaded_from_cache == nullptr) - //adjusting bounds - AxisAlignedBox aab=mesh->getBounds(); - Vector3 v=aab.getMinimum(); - float mi=v.x; - if (v.yma) ma=mi; - aab.setMinimum(Vector3(-ma,-ma,-ma)); - aab.setMaximum(Vector3(ma,ma,ma)); + // adjusting bounds + AxisAlignedBox aab = mesh->getBounds(); + Vector3 v = aab.getMinimum(); + float mi = v.x; + if (v.y < mi) mi = v.y; + if (v.z < mi) mi = v.z; + mi = fabs(mi); + v = aab.getMaximum(); + float ma = v.x; + if (ma < v.y) ma = v.y; + if (ma < v.z) ma = v.z; + ma = fabs(ma); + if (mi > ma) ma = mi; + aab.setMinimum(Vector3(-ma, -ma, -ma)); + aab.setMaximum(Vector3(ma, ma, ma)); mesh->_setBounds(aab, true); - //okay, show the mesh now - m_scene_node=gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + // okay, show the mesh now + m_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_scene_node->attachObject(ent); m_scene_node->setPosition(position); if (preloaded_from_cache == nullptr) { - for (int i=0; i<(int)m_vertex_count; i++) + for (int i = 0; i < (int)m_vertex_count; i++) { Matrix3 mat; - Vector3 diffX = nodes[m_locators[i].nx].AbsPosition-nodes[m_locators[i].ref].AbsPosition; - Vector3 diffY = nodes[m_locators[i].ny].AbsPosition-nodes[m_locators[i].ref].AbsPosition; + Vector3 diffX = nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition; + Vector3 diffY = nodes[m_locators[i].ny].AbsPosition - nodes[m_locators[i].ref].AbsPosition; mat.SetColumn(0, diffX); mat.SetColumn(1, diffY); - mat.SetColumn(2, diffX.crossProduct(diffY).normalisedCopy()); // Old version: mat.SetColumn(2, nodes[loc.nz].AbsPosition-nodes[loc.ref].AbsPosition); + mat.SetColumn( + 2, diffX.crossProduct(diffY) + .normalisedCopy()); // Old version: mat.SetColumn(2, nodes[loc.nz].AbsPosition-nodes[loc.ref].AbsPosition); mat = mat.Inverse(); // compute coordinates in the Euclidean basis - m_src_normals[i] = mat*(orientation * m_src_normals[i]); + m_src_normals[i] = mat * (orientation * m_src_normals[i]); } } @@ -511,21 +481,21 @@ FlexBody::FlexBody( #ifdef FLEXBODY_LOG_LOADING_TIMES char stats[1000]; - sprintf(stats, "FLEXBODY (%s) ready, stats:" - "\n\tmesh loaded: %f sec" - "\n\tmesh ready: %f sec" - "\n\tmesh scanned: %f sec" - "\n\tOgre vertexbuffers created: %f sec" - "\n\tOgre vertexbuffers reorganised: %f sec" - "\n\tmanual vertexbuffers created: %f sec" - "\n\tmanual vertexbuffers transformed: %f sec" - "\n\tnodes located: %f sec" - "\n\tmesh displayed: %f sec" - "\n\tnormals calculated: %f sec", - meshname.c_str(), stat_mesh_loaded_time, stat_mesh_ready_time, stat_mesh_scanned_time, - stat_vertexbuffers_created_time, stat_buffers_reorganised_time, - stat_manual_buffers_created_time, stat_transformed_time, stat_located_time, - stat_showmesh_time, stat_euclidean2_time); + sprintf(stats, + "FLEXBODY (%s) ready, stats:" + "\n\tmesh loaded: %f sec" + "\n\tmesh ready: %f sec" + "\n\tmesh scanned: %f sec" + "\n\tOgre vertexbuffers created: %f sec" + "\n\tOgre vertexbuffers reorganised: %f sec" + "\n\tmanual vertexbuffers created: %f sec" + "\n\tmanual vertexbuffers transformed: %f sec" + "\n\tnodes located: %f sec" + "\n\tmesh displayed: %f sec" + "\n\tnormals calculated: %f sec", + meshname.c_str(), stat_mesh_loaded_time, stat_mesh_ready_time, stat_mesh_scanned_time, + stat_vertexbuffers_created_time, stat_buffers_reorganised_time, stat_manual_buffers_created_time, + stat_transformed_time, stat_located_time, stat_showmesh_time, stat_euclidean2_time); LOG(stats); #endif } @@ -537,8 +507,8 @@ FlexBody::~FlexBody() // Stuff using malloc() if (m_src_normals != nullptr) { free(m_src_normals); } if (m_dst_normals != nullptr) { free(m_dst_normals); } - if (m_dst_pos != nullptr) { free(m_dst_pos ); } - if (m_src_colors != nullptr) { free(m_src_colors ); } + if (m_dst_pos != nullptr) { free(m_dst_pos); } + if (m_src_colors != nullptr) { free(m_src_colors); } // OGRE resource - scene node m_scene_node->getParentSceneNode()->removeChild(m_scene_node); @@ -556,8 +526,7 @@ FlexBody::~FlexBody() void FlexBody::setVisible(bool visible) { - if (m_scene_node) - m_scene_node->setVisible(visible); + if (m_scene_node) m_scene_node->setVisible(visible); } void FlexBody::SetFlexbodyCastShadow(bool val) @@ -565,40 +534,40 @@ void FlexBody::SetFlexbodyCastShadow(bool val) m_scene_entity->setCastShadows(val); } -void FlexBody::printMeshInfo(Mesh* mesh) +void FlexBody::printMeshInfo(Mesh *mesh) { if (mesh->sharedVertexData) { LOG("FLEXBODY Mesh has Shared Vertices:"); - VertexData* vt=mesh->sharedVertexData; - LOG("FLEXBODY element count:"+TOSTRING(vt->vertexDeclaration->getElementCount())); - for (int j=0; j<(int)vt->vertexDeclaration->getElementCount(); j++) + VertexData *vt = mesh->sharedVertexData; + LOG("FLEXBODY element count:" + TOSTRING(vt->vertexDeclaration->getElementCount())); + for (int j = 0; j < (int)vt->vertexDeclaration->getElementCount(); j++) { - const VertexElement* ve=vt->vertexDeclaration->getElement(j); - LOG("FLEXBODY element "+TOSTRING(j)+" source "+TOSTRING(ve->getSource())); - LOG("FLEXBODY element "+TOSTRING(j)+" offset "+TOSTRING(ve->getOffset())); - LOG("FLEXBODY element "+TOSTRING(j)+" type "+TOSTRING(ve->getType())); - LOG("FLEXBODY element "+TOSTRING(j)+" semantic "+TOSTRING(ve->getSemantic())); - LOG("FLEXBODY element "+TOSTRING(j)+" size "+TOSTRING(ve->getSize())); + const VertexElement *ve = vt->vertexDeclaration->getElement(j); + LOG("FLEXBODY element " + TOSTRING(j) + " source " + TOSTRING(ve->getSource())); + LOG("FLEXBODY element " + TOSTRING(j) + " offset " + TOSTRING(ve->getOffset())); + LOG("FLEXBODY element " + TOSTRING(j) + " type " + TOSTRING(ve->getType())); + LOG("FLEXBODY element " + TOSTRING(j) + " semantic " + TOSTRING(ve->getSemantic())); + LOG("FLEXBODY element " + TOSTRING(j) + " size " + TOSTRING(ve->getSize())); } } - LOG("FLEXBODY Mesh has "+TOSTRING(mesh->getNumSubMeshes())+" submesh(es)"); - for (int i=0; igetNumSubMeshes(); i++) + LOG("FLEXBODY Mesh has " + TOSTRING(mesh->getNumSubMeshes()) + " submesh(es)"); + for (int i = 0; i < mesh->getNumSubMeshes(); i++) { - SubMesh* submesh = mesh->getSubMesh(i); - LOG("FLEXBODY SubMesh "+TOSTRING(i)+": uses shared?:"+TOSTRING(submesh->useSharedVertices)); + SubMesh *submesh = mesh->getSubMesh(i); + LOG("FLEXBODY SubMesh " + TOSTRING(i) + ": uses shared?:" + TOSTRING(submesh->useSharedVertices)); if (!submesh->useSharedVertices) { - VertexData* vt=submesh->vertexData; - LOG("FLEXBODY element count:"+TOSTRING(vt->vertexDeclaration->getElementCount())); - for (int j=0; j<(int)vt->vertexDeclaration->getElementCount(); j++) + VertexData *vt = submesh->vertexData; + LOG("FLEXBODY element count:" + TOSTRING(vt->vertexDeclaration->getElementCount())); + for (int j = 0; j < (int)vt->vertexDeclaration->getElementCount(); j++) { - const VertexElement* ve=vt->vertexDeclaration->getElement(j); - LOG("FLEXBODY element "+TOSTRING(j)+" source "+TOSTRING(ve->getSource())); - LOG("FLEXBODY element "+TOSTRING(j)+" offset "+TOSTRING(ve->getOffset())); - LOG("FLEXBODY element "+TOSTRING(j)+" type "+TOSTRING(ve->getType())); - LOG("FLEXBODY element "+TOSTRING(j)+" semantic "+TOSTRING(ve->getSemantic())); - LOG("FLEXBODY element "+TOSTRING(j)+" size "+TOSTRING(ve->getSize())); + const VertexElement *ve = vt->vertexDeclaration->getElement(j); + LOG("FLEXBODY element " + TOSTRING(j) + " source " + TOSTRING(ve->getSource())); + LOG("FLEXBODY element " + TOSTRING(j) + " offset " + TOSTRING(ve->getOffset())); + LOG("FLEXBODY element " + TOSTRING(j) + " type " + TOSTRING(ve->getType())); + LOG("FLEXBODY element " + TOSTRING(j) + " semantic " + TOSTRING(ve->getSemantic())); + LOG("FLEXBODY element " + TOSTRING(j) + " size " + TOSTRING(ve->getSize())); } } } @@ -608,7 +577,7 @@ void FlexBody::ComputeFlexbody() { if (m_has_texture_blend) updateBlend(); - RoR::GfxActor::NodeData* nodes = m_gfx_actor->GetSimNodeBuffer(); + RoR::GfxActor::NodeData *nodes = m_gfx_actor->GetSimNodeBuffer(); // compute the local center Ogre::Vector3 flexit_normal; @@ -624,15 +593,15 @@ void FlexBody::ComputeFlexbody() } else { - flexit_normal = Vector3::UNIT_Y; + flexit_normal = Vector3::UNIT_Y; m_flexit_center = nodes[0].AbsPosition; } - for (int i=0; i<(int)m_vertex_count; i++) + for (int i = 0; i < (int)m_vertex_count; i++) { - Vector3 diffX = nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition; - Vector3 diffY = nodes[m_locators[i].ny].AbsPosition - nodes[m_locators[i].ref].AbsPosition; - Vector3 nCross = fast_normalise(diffX.crossProduct(diffY)); //nCross.normalise(); + Vector3 diffX = nodes[m_locators[i].nx].AbsPosition - nodes[m_locators[i].ref].AbsPosition; + Vector3 diffY = nodes[m_locators[i].ny].AbsPosition - nodes[m_locators[i].ref].AbsPosition; + Vector3 nCross = fast_normalise(diffX.crossProduct(diffY)); // nCross.normalise(); m_dst_pos[i].x = diffX.x * m_locators[i].coords.x + diffY.x * m_locators[i].coords.y + nCross.x * m_locators[i].coords.z; m_dst_pos[i].y = diffX.y * m_locators[i].coords.x + diffY.y * m_locators[i].coords.y + nCross.y * m_locators[i].coords.z; @@ -654,16 +623,16 @@ void FlexBody::UpdateFlexbodyVertexBuffers() Vector3 *npt = m_dst_normals; if (m_uses_shared_vertex_data) { - m_shared_vbuf_pos->writeData(0, m_shared_buf_num_verts*sizeof(Vector3), ppt, true); + m_shared_vbuf_pos->writeData(0, m_shared_buf_num_verts * sizeof(Vector3), ppt, true); ppt += m_shared_buf_num_verts; - m_shared_vbuf_norm->writeData(0, m_shared_buf_num_verts*sizeof(Vector3), npt, true); + m_shared_vbuf_norm->writeData(0, m_shared_buf_num_verts * sizeof(Vector3), npt, true); npt += m_shared_buf_num_verts; } - for (int i=0; iwriteData(0, m_submesh_vbufs_vertex_counts[i]*sizeof(Vector3), ppt, true); + m_submesh_vbufs_pos[i]->writeData(0, m_submesh_vbufs_vertex_counts[i] * sizeof(Vector3), ppt, true); ppt += m_submesh_vbufs_vertex_counts[i]; - m_submesh_vbufs_norm[i]->writeData(0, m_submesh_vbufs_vertex_counts[i]*sizeof(Vector3), npt, true); + m_submesh_vbufs_norm[i]->writeData(0, m_submesh_vbufs_vertex_counts[i] * sizeof(Vector3), npt, true); npt += m_submesh_vbufs_vertex_counts[i]; } @@ -680,7 +649,8 @@ void FlexBody::reset() { if (m_has_texture_blend) { - for (int i=0; i<(int)m_vertex_count; i++) m_src_colors[i]=0x00000000; + for (int i = 0; i < (int)m_vertex_count; i++) + m_src_colors[i] = 0x00000000; writeBlend(); } } @@ -691,33 +661,32 @@ void FlexBody::writeBlend() ARGB *cpt = m_src_colors; if (m_uses_shared_vertex_data) { - m_shared_vbuf_color->writeData(0, m_shared_buf_num_verts*sizeof(ARGB), (void*)cpt, true); - cpt+=m_shared_buf_num_verts; + m_shared_vbuf_color->writeData(0, m_shared_buf_num_verts * sizeof(ARGB), (void *)cpt, true); + cpt += m_shared_buf_num_verts; } - for (int i=0; iwriteData(0, m_submesh_vbufs_vertex_counts[i]*sizeof(ARGB), (void*)cpt, true); - cpt+=m_submesh_vbufs_vertex_counts[i]; + m_submesh_vbufs_color[i]->writeData(0, m_submesh_vbufs_vertex_counts[i] * sizeof(ARGB), (void *)cpt, true); + cpt += m_submesh_vbufs_vertex_counts[i]; } } -void FlexBody::updateBlend() //so easy! +void FlexBody::updateBlend() // so easy! { - RoR::GfxActor::NodeData* nodes = m_gfx_actor->GetSimNodeBuffer(); - for (int i=0; i<(int)m_vertex_count; i++) + RoR::GfxActor::NodeData *nodes = m_gfx_actor->GetSimNodeBuffer(); + for (int i = 0; i < (int)m_vertex_count; i++) { - RoR::GfxActor::NodeData *nd = &nodes[m_locators[i].ref]; - ARGB col = m_src_colors[i]; - if (nd->nd_has_contact && !(col&0xFF000000)) + RoR::GfxActor::NodeData *nd = &nodes[m_locators[i].ref]; + ARGB col = m_src_colors[i]; + if (nd->nd_has_contact && !(col & 0xFF000000)) { - m_src_colors[i]=col|0xFF000000; + m_src_colors[i] = col | 0xFF000000; m_blend_changed = true; } - if (nd->nd_is_wet ^ ((col&0x000000FF)>0)) + if (nd->nd_is_wet ^ ((col & 0x000000FF) > 0)) { - m_src_colors[i]=(col&0xFFFFFF00)+0x000000FF*nd->nd_is_wet; + m_src_colors[i] = (col & 0xFFFFFF00) + 0x000000FF * nd->nd_is_wet; m_blend_changed = true; } } } - diff --git a/source/main/physics/flex/FlexBody.h b/source/main/physics/flex/FlexBody.h index 7682ea2812..3910975bd6 100644 --- a/source/main/physics/flex/FlexBody.h +++ b/source/main/physics/flex/FlexBody.h @@ -21,15 +21,15 @@ #pragma once -#include "RigDef_Prerequisites.h" -#include "RoRPrerequisites.h" #include "Flexable.h" #include "Locator_t.h" +#include "RigDef_Prerequisites.h" +#include "RoRPrerequisites.h" -#include -#include #include #include +#include +#include /// Flexbody = A deformable mesh; updated on CPU every frame, then uploaded to video memory class FlexBody @@ -38,31 +38,31 @@ class FlexBody friend class RoR::FlexBodyFileIO; FlexBody( // Private, for FlexFactory - RigDef::Flexbody* def, - RoR::FlexBodyCacheData* preloaded_from_cache, - RoR::GfxActor* gfx_actor, - Ogre::Entity* entity, - int ref, - int nx, - int ny, - Ogre::Quaternion const & rot, - std::vector & node_indices - ); - -public: + RigDef::Flexbody *def, RoR::FlexBodyCacheData *preloaded_from_cache, RoR::GfxActor *gfx_actor, Ogre::Entity *entity, + int ref, int nx, int ny, Ogre::Quaternion const &rot, std::vector &node_indices); + public: ~FlexBody(); - void printMeshInfo(Ogre::Mesh* mesh); - void reset(); - void updateBlend(); - void writeBlend(); - Ogre::SceneNode *getSceneNode() { return m_scene_node; }; + void printMeshInfo(Ogre::Mesh *mesh); + void reset(); + void updateBlend(); + void writeBlend(); + Ogre::SceneNode *getSceneNode() + { + return m_scene_node; + }; - /// Visibility control + /// Visibility control /// @param mode {-2 = always, -1 = 3rdPerson only, 0+ = cinecam index} - void setCameraMode(int mode) { m_camera_mode = mode; }; - int getCameraMode() { return m_camera_mode; }; + void setCameraMode(int mode) + { + m_camera_mode = mode; + }; + int getCameraMode() + { + return m_camera_mode; + }; void ComputeFlexbody(); //!< Updates mesh deformation; works on CPU using local copy of vertex data. void UpdateFlexbodyVertexBuffers(); @@ -71,27 +71,29 @@ class FlexBody void SetFlexbodyCastShadow(bool val); - int size() { return static_cast(m_vertex_count); }; - -private: - - RoR::GfxActor* m_gfx_actor; - size_t m_vertex_count; - Ogre::Vector3 m_flexit_center; ///< Updated per frame - - Ogre::Vector3* m_dst_pos; - Ogre::Vector3* m_src_normals; - Ogre::Vector3* m_dst_normals; - Ogre::ARGB* m_src_colors; - Locator_t* m_locators; ///< 1 loc per vertex - - int m_node_center; - int m_node_x; - int m_node_y; - Ogre::Vector3 m_center_offset; - Ogre::SceneNode* m_scene_node; - Ogre::Entity* m_scene_entity; - int m_camera_mode; ///< Visibility control {-2 = always, -1 = 3rdPerson only, 0+ = cinecam index} + int size() + { + return static_cast(m_vertex_count); + }; + + private: + RoR::GfxActor *m_gfx_actor; + size_t m_vertex_count; + Ogre::Vector3 m_flexit_center; ///< Updated per frame + + Ogre::Vector3 *m_dst_pos; + Ogre::Vector3 *m_src_normals; + Ogre::Vector3 *m_dst_normals; + Ogre::ARGB * m_src_colors; + Locator_t * m_locators; ///< 1 loc per vertex + + int m_node_center; + int m_node_x; + int m_node_y; + Ogre::Vector3 m_center_offset; + Ogre::SceneNode *m_scene_node; + Ogre::Entity * m_scene_entity; + int m_camera_mode; ///< Visibility control {-2 = always, -1 = 3rdPerson only, 0+ = cinecam index} int m_shared_buf_num_verts; Ogre::HardwareVertexBufferSharedPtr m_shared_vbuf_pos; diff --git a/source/main/physics/flex/FlexFactory.cpp b/source/main/physics/flex/FlexFactory.cpp index 0d1b36d003..34629e9ac8 100644 --- a/source/main/physics/flex/FlexFactory.cpp +++ b/source/main/physics/flex/FlexFactory.cpp @@ -33,55 +33,45 @@ #include "RigDef_File.h" #include "RigSpawner.h" +#include #include #include -#include //#define FLEXFACTORY_DEBUG_LOGGING #ifdef FLEXFACTORY_DEBUG_LOGGING -# include "RoRPrerequisites.h" -# define FLEX_DEBUG_LOG(TEXT) LOG("FlexFactory | " TEXT) + #include "RoRPrerequisites.h" + #define FLEX_DEBUG_LOG(TEXT) LOG("FlexFactory | " TEXT) #else -# define FLEX_DEBUG_LOG(TEXT) + #define FLEX_DEBUG_LOG(TEXT) #endif // FLEXFACTORY_DEBUG_LOGGING using namespace RoR; // Static -const char * FlexBodyFileIO::SIGNATURE = "RoR FlexBody"; +const char *FlexBodyFileIO::SIGNATURE = "RoR FlexBody"; -FlexFactory::FlexFactory(ActorSpawner* rig_spawner): - m_rig_spawner(rig_spawner), - m_is_flexbody_cache_loaded(false), - m_is_flexbody_cache_enabled(App::gfx_flexbody_cache.GetActive()), - m_flexbody_cache_next_index(0) +FlexFactory::FlexFactory(ActorSpawner *rig_spawner) + : m_rig_spawner(rig_spawner), m_is_flexbody_cache_loaded(false), + m_is_flexbody_cache_enabled(App::gfx_flexbody_cache.GetActive()), m_flexbody_cache_next_index(0) { } -FlexBody* FlexFactory::CreateFlexBody( - RigDef::Flexbody* def, - const int ref_node, - const int x_node, - const int y_node, - Ogre::Quaternion const & rot, - std::vector & node_indices, - std::string resource_group_name) +FlexBody *FlexFactory::CreateFlexBody(RigDef::Flexbody *def, const int ref_node, const int x_node, const int y_node, + Ogre::Quaternion const &rot, std::vector &node_indices, + std::string resource_group_name) { - Ogre::MeshPtr common_mesh = Ogre::MeshManager::getSingleton().load(def->mesh_name, resource_group_name); - int flexbody_id = m_rig_spawner->GetActor()->GetGfxActor()->GetNumFlexbodies(); + Ogre::MeshPtr common_mesh = Ogre::MeshManager::getSingleton().load(def->mesh_name, resource_group_name); + int flexbody_id = m_rig_spawner->GetActor()->GetGfxActor()->GetNumFlexbodies(); const std::string mesh_unique_name = m_rig_spawner->ComposeName("FlexbodyMesh", flexbody_id); - Ogre::MeshPtr mesh = common_mesh->clone(mesh_unique_name); - if (App::gfx_flexbody_lods.GetActive()) - { - this->ResolveFlexbodyLOD(def->mesh_name, mesh); - } + Ogre::MeshPtr mesh = common_mesh->clone(mesh_unique_name); + if (App::gfx_flexbody_lods.GetActive()) { this->ResolveFlexbodyLOD(def->mesh_name, mesh); } const std::string flexbody_name = m_rig_spawner->ComposeName("Flexbody", flexbody_id); - Ogre::Entity* entity = gEnv->sceneManager->createEntity(flexbody_name, mesh_unique_name, resource_group_name); + Ogre::Entity * entity = gEnv->sceneManager->createEntity(flexbody_name, mesh_unique_name, resource_group_name); m_rig_spawner->SetupNewEntity(entity, Ogre::ColourValue(0.5, 0.5, 1)); FLEX_DEBUG_LOG(__FUNCTION__); - FlexBodyCacheData* from_cache = nullptr; + FlexBodyCacheData *from_cache = nullptr; if (m_is_flexbody_cache_loaded) { FLEX_DEBUG_LOG(__FUNCTION__ " >> Get entry from cache "); @@ -89,58 +79,40 @@ FlexBody* FlexFactory::CreateFlexBody( m_flexbody_cache_next_index++; } - FlexBody* new_flexbody = new FlexBody( - def, - from_cache, - m_rig_spawner->GetActor()->GetGfxActor(), - entity, - ref_node, - x_node, - y_node, - rot, - node_indices); + FlexBody *new_flexbody = new FlexBody(def, from_cache, m_rig_spawner->GetActor()->GetGfxActor(), entity, ref_node, x_node, + y_node, rot, node_indices); - if (m_is_flexbody_cache_enabled) - { - m_flexbody_cache.AddItemToSave(new_flexbody); - } + if (m_is_flexbody_cache_enabled) { m_flexbody_cache.AddItemToSave(new_flexbody); } return new_flexbody; } -FlexMeshWheel* FlexFactory::CreateFlexMeshWheel( - unsigned int wheel_index, - int axis_node_1_index, - int axis_node_2_index, - int nstart, - int nrays, - float rim_radius, - bool rim_reverse, - std::string const & rim_mesh_name, - std::string const & tire_material_name) +FlexMeshWheel *FlexFactory::CreateFlexMeshWheel(unsigned int wheel_index, int axis_node_1_index, int axis_node_2_index, + int nstart, int nrays, float rim_radius, bool rim_reverse, + std::string const &rim_mesh_name, std::string const &tire_material_name) { const std::string rg_name = m_rig_spawner->GetActor()->GetGfxActor()->GetResourceGroup(); // Load+instantiate static mesh for rim const std::string rim_entity_name = m_rig_spawner->ComposeName("MeshWheelRim", wheel_index); - Ogre::Entity* rim_prop_entity = gEnv->sceneManager->createEntity(rim_entity_name, rim_mesh_name, rg_name); + Ogre::Entity * rim_prop_entity = gEnv->sceneManager->createEntity(rim_entity_name, rim_mesh_name, rg_name); m_rig_spawner->SetupNewEntity(rim_prop_entity, Ogre::ColourValue(0, 0.5, 0.8)); // Create dynamic mesh for tire const std::string tire_mesh_name = m_rig_spawner->ComposeName("MWheelTireMesh", wheel_index); - FlexMeshWheel* flex_mesh_wheel = new FlexMeshWheel( - rim_prop_entity, m_rig_spawner->GetActor()->GetGfxActor(), axis_node_1_index, axis_node_2_index, nstart, nrays, - tire_mesh_name, tire_material_name, rim_radius, rim_reverse); + FlexMeshWheel * flex_mesh_wheel = + new FlexMeshWheel(rim_prop_entity, m_rig_spawner->GetActor()->GetGfxActor(), axis_node_1_index, axis_node_2_index, nstart, + nrays, tire_mesh_name, tire_material_name, rim_radius, rim_reverse); // Instantiate the dynamic tire mesh const std::string tire_instance_name = m_rig_spawner->ComposeName("MWheelTireEntity", wheel_index); - Ogre::Entity *tire_entity = gEnv->sceneManager->createEntity(tire_instance_name, tire_mesh_name, rg_name); + Ogre::Entity * tire_entity = gEnv->sceneManager->createEntity(tire_instance_name, tire_mesh_name, rg_name); m_rig_spawner->SetupNewEntity(tire_entity, Ogre::ColourValue(0, 0.5, 0.8)); flex_mesh_wheel->m_tire_entity = tire_entity; // Friend access. return flex_mesh_wheel; } -void FlexBodyFileIO::WriteToFile(void* source, size_t length) +void FlexBodyFileIO::WriteToFile(void *source, size_t length) { size_t num_written = fwrite(source, length, 1, m_file); if (num_written != 1) @@ -150,7 +122,7 @@ void FlexBodyFileIO::WriteToFile(void* source, size_t length) } } -void FlexBodyFileIO::ReadFromFile(void* dest, size_t length) +void FlexBodyFileIO::ReadFromFile(void *dest, size_t length) { size_t num_written = fread(dest, length, 1, m_file); if (num_written != 1) @@ -163,147 +135,132 @@ void FlexBodyFileIO::ReadFromFile(void* dest, size_t length) void FlexBodyFileIO::WriteSignature() { FLEX_DEBUG_LOG(__FUNCTION__); - WriteToFile((void*)SIGNATURE, (strlen(SIGNATURE) + 1) * sizeof(char)); + WriteToFile((void *)SIGNATURE, (strlen(SIGNATURE) + 1) * sizeof(char)); } void FlexBodyFileIO::ReadAndCheckSignature() { FLEX_DEBUG_LOG(__FUNCTION__); char signature[25]; - this->ReadFromFile((void*)&signature, (strlen(SIGNATURE) + 1) * sizeof(char)); - if (strcmp(SIGNATURE, signature) != 0) - { - throw RESULT_CODE_ERR_SIGNATURE_MISMATCH; - } + this->ReadFromFile((void *)&signature, (strlen(SIGNATURE) + 1) * sizeof(char)); + if (strcmp(SIGNATURE, signature) != 0) { throw RESULT_CODE_ERR_SIGNATURE_MISMATCH; } } void FlexBodyFileIO::WriteMetadata() { FLEX_DEBUG_LOG(__FUNCTION__); FlexBodyFileMetadata meta; - meta.file_format_version = FILE_FORMAT_VERSION; + meta.file_format_version = FILE_FORMAT_VERSION; meta.num_flexbodies = static_cast(m_items_to_save.size()); - this->WriteToFile((void*)&meta, sizeof(FlexBodyFileMetadata)); + this->WriteToFile((void *)&meta, sizeof(FlexBodyFileMetadata)); } -void FlexBodyFileIO::ReadMetadata(FlexBodyFileMetadata* meta) +void FlexBodyFileIO::ReadMetadata(FlexBodyFileMetadata *meta) { FLEX_DEBUG_LOG(__FUNCTION__); assert(meta != nullptr); - this->ReadFromFile((void*)meta, sizeof(FlexBodyFileMetadata)); + this->ReadFromFile((void *)meta, sizeof(FlexBodyFileMetadata)); } -void FlexBodyFileIO::WriteFlexbodyHeader(FlexBody* flexbody) +void FlexBodyFileIO::WriteFlexbodyHeader(FlexBody *flexbody) { FLEX_DEBUG_LOG(__FUNCTION__); FlexBodyRecordHeader header; - header.vertex_count = static_cast(flexbody->m_vertex_count); - header.node_center = flexbody->m_node_center ; - header.node_x = flexbody->m_node_x ; - header.node_y = flexbody->m_node_y ; - header.center_offset = flexbody->m_center_offset ; - header.camera_mode = flexbody->m_camera_mode ; - header.shared_buf_num_verts = flexbody->m_shared_buf_num_verts ; - header.num_submesh_vbufs = flexbody->m_num_submesh_vbufs ; - header.SetUsesSharedVertexData (flexbody->m_uses_shared_vertex_data); - header.SetHasTexture (flexbody->m_has_texture ); - header.SetHasTextureBlend (flexbody->m_has_texture_blend ); - - this->WriteToFile((void*)&header, sizeof(FlexBodyRecordHeader)); + header.vertex_count = static_cast(flexbody->m_vertex_count); + header.node_center = flexbody->m_node_center; + header.node_x = flexbody->m_node_x; + header.node_y = flexbody->m_node_y; + header.center_offset = flexbody->m_center_offset; + header.camera_mode = flexbody->m_camera_mode; + header.shared_buf_num_verts = flexbody->m_shared_buf_num_verts; + header.num_submesh_vbufs = flexbody->m_num_submesh_vbufs; + header.SetUsesSharedVertexData(flexbody->m_uses_shared_vertex_data); + header.SetHasTexture(flexbody->m_has_texture); + header.SetHasTextureBlend(flexbody->m_has_texture_blend); + + this->WriteToFile((void *)&header, sizeof(FlexBodyRecordHeader)); } -void FlexBodyFileIO::ReadFlexbodyHeader(FlexBodyCacheData* data) +void FlexBodyFileIO::ReadFlexbodyHeader(FlexBodyCacheData *data) { FLEX_DEBUG_LOG(__FUNCTION__); - this->ReadFromFile((void*)&data->header, sizeof(FlexBodyRecordHeader)); + this->ReadFromFile((void *)&data->header, sizeof(FlexBodyRecordHeader)); } - -void FlexBodyFileIO::WriteFlexbodyLocatorList(FlexBody* flexbody) +void FlexBodyFileIO::WriteFlexbodyLocatorList(FlexBody *flexbody) { FLEX_DEBUG_LOG(__FUNCTION__); - this->WriteToFile((void*)flexbody->m_locators, sizeof(Locator_t) * flexbody->m_vertex_count); + this->WriteToFile((void *)flexbody->m_locators, sizeof(Locator_t) * flexbody->m_vertex_count); } -void FlexBodyFileIO::ReadFlexbodyLocatorList(FlexBodyCacheData* data) +void FlexBodyFileIO::ReadFlexbodyLocatorList(FlexBodyCacheData *data) { FLEX_DEBUG_LOG(__FUNCTION__); // Alloc. Use - experiment data->locators = new Locator_t[data->header.vertex_count]; // Read - this->ReadFromFile((void*)data->locators, sizeof(Locator_t) * data->header.vertex_count); + this->ReadFromFile((void *)data->locators, sizeof(Locator_t) * data->header.vertex_count); } -void FlexBodyFileIO::WriteFlexbodyNormalsBuffer(FlexBody* flexbody) +void FlexBodyFileIO::WriteFlexbodyNormalsBuffer(FlexBody *flexbody) { FLEX_DEBUG_LOG(__FUNCTION__); - this->WriteToFile((void*)flexbody->m_src_normals, sizeof(Ogre::Vector3) * flexbody->m_vertex_count); + this->WriteToFile((void *)flexbody->m_src_normals, sizeof(Ogre::Vector3) * flexbody->m_vertex_count); } -void FlexBodyFileIO::ReadFlexbodyNormalsBuffer(FlexBodyCacheData* data) +void FlexBodyFileIO::ReadFlexbodyNormalsBuffer(FlexBodyCacheData *data) { FLEX_DEBUG_LOG(__FUNCTION__); const int vertex_count = data->header.vertex_count; // Alloc. Use malloc() because that's how flexbodies were implemented. - data->src_normals=(Ogre::Vector3*)malloc(sizeof(Ogre::Vector3) * vertex_count); + data->src_normals = (Ogre::Vector3 *)malloc(sizeof(Ogre::Vector3) * vertex_count); // Read - this->ReadFromFile((void*)data->src_normals, sizeof(Ogre::Vector3) * vertex_count); + this->ReadFromFile((void *)data->src_normals, sizeof(Ogre::Vector3) * vertex_count); } -void FlexBodyFileIO::WriteFlexbodyPositionsBuffer(FlexBody* flexbody) +void FlexBodyFileIO::WriteFlexbodyPositionsBuffer(FlexBody *flexbody) { FLEX_DEBUG_LOG(__FUNCTION__); - this->WriteToFile((void*)flexbody->m_dst_pos, sizeof(Ogre::Vector3) * flexbody->m_vertex_count); + this->WriteToFile((void *)flexbody->m_dst_pos, sizeof(Ogre::Vector3) * flexbody->m_vertex_count); } -void FlexBodyFileIO::ReadFlexbodyPositionsBuffer(FlexBodyCacheData* data) +void FlexBodyFileIO::ReadFlexbodyPositionsBuffer(FlexBodyCacheData *data) { FLEX_DEBUG_LOG(__FUNCTION__); const int vertex_count = data->header.vertex_count; // Alloc. Use malloc() because that's how flexbodies were implemented. - data->dst_pos=(Ogre::Vector3*)malloc(sizeof(Ogre::Vector3) * vertex_count); + data->dst_pos = (Ogre::Vector3 *)malloc(sizeof(Ogre::Vector3) * vertex_count); // Read - this->ReadFromFile((void*)data->dst_pos, sizeof(Ogre::Vector3) * vertex_count); + this->ReadFromFile((void *)data->dst_pos, sizeof(Ogre::Vector3) * vertex_count); } -void FlexBodyFileIO::WriteFlexbodyColorsBuffer(FlexBody* flexbody) +void FlexBodyFileIO::WriteFlexbodyColorsBuffer(FlexBody *flexbody) { FLEX_DEBUG_LOG(__FUNCTION__); if (flexbody->m_has_texture_blend) - { - this->WriteToFile((void*)flexbody->m_src_colors, sizeof(Ogre::ARGB) * flexbody->m_vertex_count); - } + { this->WriteToFile((void *)flexbody->m_src_colors, sizeof(Ogre::ARGB) * flexbody->m_vertex_count); } } -void FlexBodyFileIO::ReadFlexbodyColorsBuffer(FlexBodyCacheData* data) +void FlexBodyFileIO::ReadFlexbodyColorsBuffer(FlexBodyCacheData *data) { FLEX_DEBUG_LOG(__FUNCTION__); - if (! data->header.HasTextureBlend()) - { - return; - } + if (!data->header.HasTextureBlend()) { return; } const int vertex_count = data->header.vertex_count; // Alloc. Use malloc() because that's how flexbodies were implemented. - data->src_colors=(Ogre::ARGB*)malloc(sizeof(Ogre::ARGB) * vertex_count); + data->src_colors = (Ogre::ARGB *)malloc(sizeof(Ogre::ARGB) * vertex_count); // Read - this->ReadFromFile((void*)data->src_colors, sizeof(Ogre::ARGB) * vertex_count); + this->ReadFromFile((void *)data->src_colors, sizeof(Ogre::ARGB) * vertex_count); } -void FlexBodyFileIO::OpenFile(const char* fopen_mode) +void FlexBodyFileIO::OpenFile(const char *fopen_mode) { FLEX_DEBUG_LOG(__FUNCTION__); - if (m_cache_entry_number == -1) - { - throw RESULT_CODE_ERR_CACHE_NUMBER_UNDEFINED; - } + if (m_cache_entry_number == -1) { throw RESULT_CODE_ERR_CACHE_NUMBER_UNDEFINED; } char path[500]; sprintf(path, "%s%cflexbodies_mod_%00d.dat", App::sys_cache_dir.GetActive(), RoR::PATH_SLASH, m_cache_entry_number); m_file = fopen(path, fopen_mode); - if (m_file == nullptr) - { - throw RESULT_CODE_ERR_FOPEN_FAILED; - } + if (m_file == nullptr) { throw RESULT_CODE_ERR_FOPEN_FAILED; } } FlexBodyFileIO::ResultCode FlexBodyFileIO::SaveFile() @@ -325,13 +282,13 @@ FlexBodyFileIO::ResultCode FlexBodyFileIO::SaveFile() auto end = m_items_to_save.end(); for (; itor != end; ++itor) { - FlexBody* flexbody = *itor; + FlexBody *flexbody = *itor; this->WriteFlexbodyHeader(flexbody); - this->WriteFlexbodyLocatorList (flexbody); + this->WriteFlexbodyLocatorList(flexbody); this->WriteFlexbodyPositionsBuffer(flexbody); - this->WriteFlexbodyNormalsBuffer (flexbody); - this->WriteFlexbodyColorsBuffer (flexbody); + this->WriteFlexbodyNormalsBuffer(flexbody); + this->WriteFlexbodyColorsBuffer(flexbody); } this->CloseFile(); FLEX_DEBUG_LOG(__FUNCTION__ " >> OK "); @@ -348,7 +305,7 @@ FlexBodyFileIO::ResultCode FlexBodyFileIO::SaveFile() FlexBodyFileIO::ResultCode FlexBodyFileIO::LoadFile() { FLEX_DEBUG_LOG(__FUNCTION__); - try + try { this->OpenFile("rb"); this->ReadAndCheckSignature(); @@ -356,22 +313,19 @@ FlexBodyFileIO::ResultCode FlexBodyFileIO::LoadFile() FlexBodyFileMetadata meta; this->ReadMetadata(&meta); m_fileformat_version = meta.file_format_version; - if (m_fileformat_version != FILE_FORMAT_VERSION) - { - throw RESULT_CODE_ERR_VERSION_MISMATCH; - } + if (m_fileformat_version != FILE_FORMAT_VERSION) { throw RESULT_CODE_ERR_VERSION_MISMATCH; } m_loaded_items.resize(meta.num_flexbodies); for (unsigned int i = 0; i < meta.num_flexbodies; ++i) { - FlexBodyCacheData* data = & m_loaded_items[i]; + FlexBodyCacheData *data = &m_loaded_items[i]; this->ReadFlexbodyHeader(data); if (!data->header.IsFaulty()) { - this->ReadFlexbodyLocatorList (data); + this->ReadFlexbodyLocatorList(data); this->ReadFlexbodyPositionsBuffer(data); - this->ReadFlexbodyNormalsBuffer (data); - this->ReadFlexbodyColorsBuffer (data); + this->ReadFlexbodyNormalsBuffer(data); + this->ReadFlexbodyColorsBuffer(data); } } @@ -387,20 +341,17 @@ FlexBodyFileIO::ResultCode FlexBodyFileIO::LoadFile() } } -FlexBodyFileIO::FlexBodyFileIO(): - m_file(nullptr), - m_fileformat_version(0), - m_cache_entry_number(-1) // flexbody cache disabled (shouldn't be based on the cache entry number ...) ~ ulteq 01/19 - {} +FlexBodyFileIO::FlexBodyFileIO() + : m_file(nullptr), m_fileformat_version(0), + m_cache_entry_number(-1) // flexbody cache disabled (shouldn't be based on the cache entry number ...) ~ ulteq 01/19 +{ +} void FlexFactory::CheckAndLoadFlexbodyCache() { FLEX_DEBUG_LOG(__FUNCTION__); if (m_is_flexbody_cache_enabled) - { - m_is_flexbody_cache_loaded = - (m_flexbody_cache.LoadFile() == FlexBodyFileIO::RESULT_CODE_OK); - } + { m_is_flexbody_cache_loaded = (m_flexbody_cache.LoadFile() == FlexBodyFileIO::RESULT_CODE_OK); } } void FlexFactory::SaveFlexbodiesToCache() @@ -417,18 +368,17 @@ void FlexFactory::ResolveFlexbodyLOD(std::string meshname, Ogre::MeshPtr newmesh { std::string basename, ext; Ogre::StringUtil::splitBaseFilename(meshname, basename, ext); - for (int i=0; i<4;i++) + for (int i = 0; i < 4; i++) { const std::string fn = basename + "_" + TOSTRING(i) + ".mesh"; - if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(fn)) - continue; + if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(fn)) continue; float distance = 3; if (i == 1) distance = 20; if (i == 2) distance = 50; if (i == 3) distance = 200; - //newmesh->createManualLodLevel(distance, fn); + // newmesh->createManualLodLevel(distance, fn); Ogre::MeshLodGenerator::getSingleton().generateAutoconfiguredLodLevels(newmesh); } } diff --git a/source/main/physics/flex/FlexFactory.h b/source/main/physics/flex/FlexFactory.h index c5831db7f4..d7ca994f3e 100644 --- a/source/main/physics/flex/FlexFactory.h +++ b/source/main/physics/flex/FlexFactory.h @@ -19,12 +19,10 @@ along with Rigs of Rods. If not, see . */ - /// @file /// @author Petr Ohlidal /// @date 05/2015 - #pragma once #include "BitFlags.h" @@ -32,8 +30,8 @@ #include "Locator_t.h" #include "RigDef_Prerequisites.h" -#include #include +#include #include class FlexMeshWheel; // Forward decl. @@ -41,165 +39,160 @@ class FlexMeshWheel; // Forward decl. namespace RoR { -struct FlexBodyRecordHeader -{ - FlexBodyRecordHeader(): - flags(0) - {} - - int vertex_count; - int node_center; - int node_x; - int node_y; - Ogre::Vector3 center_offset; - int camera_mode; - int shared_buf_num_verts; - int num_submesh_vbufs; - unsigned char flags; - - BITMASK_PROPERTY(flags, 1, IS_FAULTY, IsFaulty , SetIsFaulty ); - BITMASK_PROPERTY(flags, 2, USES_SHARED_VERTEX_DATA,UsesSharedVertexData, SetUsesSharedVertexData ); - BITMASK_PROPERTY(flags, 3, HAS_TEXTURE, HasTexture , SetHasTexture ); - BITMASK_PROPERTY(flags, 4, HAS_TEXTURE_BLEND, HasTextureBlend , SetHasTextureBlend ); -}; - -struct FlexBodyCacheData -{ - FlexBodyCacheData(): - dst_pos(nullptr), - src_normals(nullptr), - src_colors(nullptr), - locators(nullptr) - {} - - // NOTE: No freeing of memory needed, pointers will be copied to FlexBody instances. - - FlexBodyRecordHeader header; - - Ogre::Vector3* dst_pos; - Ogre::Vector3* src_normals; - Ogre::ARGB* src_colors; - Locator_t* locators; //!< 1 loc per vertex -}; - -/// Enables saving and loading flexbodies from/to binary file. -/// -/// FILE STRUCTURE: -/// 1. Signature -/// 2. Metadata @see FlexBodyFileMetadata -/// 3. Flexbodies -/// a. Header @see FlexBodyRecordHeader -/// b. Data (not present if flexbody has flags IS_FAULTY==true or IS_ENABLED==false) -/// 1. Locator list -/// 2. Positions buffer -/// 3. Normals buffer -/// 4. Colors buffer (only present if flag HAS_TEXTURE_BLEND == true) -class FlexBodyFileIO -{ -public: - enum ResultCode + struct FlexBodyRecordHeader { - RESULT_CODE_OK, - RESULT_CODE_GENERAL_ERROR, - RESULT_CODE_ERR_FOPEN_FAILED, - RESULT_CODE_ERR_SIGNATURE_MISMATCH, - RESULT_CODE_ERR_VERSION_MISMATCH, - RESULT_CODE_ERR_CACHE_NUMBER_UNDEFINED, - RESULT_CODE_FREAD_OUTPUT_INCOMPLETE, - RESULT_CODE_FWRITE_OUTPUT_INCOMPLETE + FlexBodyRecordHeader() : flags(0) + { + } + + int vertex_count; + int node_center; + int node_x; + int node_y; + Ogre::Vector3 center_offset; + int camera_mode; + int shared_buf_num_verts; + int num_submesh_vbufs; + unsigned char flags; + + BITMASK_PROPERTY(flags, 1, IS_FAULTY, IsFaulty, SetIsFaulty); + BITMASK_PROPERTY(flags, 2, USES_SHARED_VERTEX_DATA, UsesSharedVertexData, SetUsesSharedVertexData); + BITMASK_PROPERTY(flags, 3, HAS_TEXTURE, HasTexture, SetHasTexture); + BITMASK_PROPERTY(flags, 4, HAS_TEXTURE_BLEND, HasTextureBlend, SetHasTextureBlend); }; - static const char* SIGNATURE; - static const unsigned int FILE_FORMAT_VERSION = 1; + struct FlexBodyCacheData + { + FlexBodyCacheData() : dst_pos(nullptr), src_normals(nullptr), src_colors(nullptr), locators(nullptr) + { + } - FlexBodyFileIO(); + // NOTE: No freeing of memory needed, pointers will be copied to FlexBody instances. - std::vector & GetList(); - inline void AddItemToSave(FlexBody* fb) { m_items_to_save.push_back(fb); } - inline FlexBodyCacheData* GetLoadedItem(unsigned index) { return & m_loaded_items[index]; } - ResultCode SaveFile(); - ResultCode LoadFile(); + FlexBodyRecordHeader header; -private: - struct FlexBodyFileMetadata - { - unsigned int file_format_version; - unsigned int num_flexbodies; + Ogre::Vector3 *dst_pos; + Ogre::Vector3 *src_normals; + Ogre::ARGB * src_colors; + Locator_t * locators; //!< 1 loc per vertex }; - void OpenFile(const char* fopen_mode); - void WriteToFile(void* source, size_t length); - void ReadFromFile(void* dest, size_t length); - inline void CloseFile() { if (m_file != nullptr) { fclose(m_file); } } - - void WriteSignature(); - void ReadAndCheckSignature(); + /// Enables saving and loading flexbodies from/to binary file. + /// + /// FILE STRUCTURE: + /// 1. Signature + /// 2. Metadata @see FlexBodyFileMetadata + /// 3. Flexbodies + /// a. Header @see FlexBodyRecordHeader + /// b. Data (not present if flexbody has flags IS_FAULTY==true or IS_ENABLED==false) + /// 1. Locator list + /// 2. Positions buffer + /// 3. Normals buffer + /// 4. Colors buffer (only present if flag HAS_TEXTURE_BLEND == true) + class FlexBodyFileIO + { + public: + enum ResultCode + { + RESULT_CODE_OK, + RESULT_CODE_GENERAL_ERROR, + RESULT_CODE_ERR_FOPEN_FAILED, + RESULT_CODE_ERR_SIGNATURE_MISMATCH, + RESULT_CODE_ERR_VERSION_MISMATCH, + RESULT_CODE_ERR_CACHE_NUMBER_UNDEFINED, + RESULT_CODE_FREAD_OUTPUT_INCOMPLETE, + RESULT_CODE_FWRITE_OUTPUT_INCOMPLETE + }; + + static const char * SIGNATURE; + static const unsigned int FILE_FORMAT_VERSION = 1; + + FlexBodyFileIO(); + + std::vector &GetList(); + inline void AddItemToSave(FlexBody *fb) + { + m_items_to_save.push_back(fb); + } + inline FlexBodyCacheData *GetLoadedItem(unsigned index) + { + return &m_loaded_items[index]; + } + ResultCode SaveFile(); + ResultCode LoadFile(); + + private: + struct FlexBodyFileMetadata + { + unsigned int file_format_version; + unsigned int num_flexbodies; + }; + + void OpenFile(const char *fopen_mode); + void WriteToFile(void *source, size_t length); + void ReadFromFile(void *dest, size_t length); + inline void CloseFile() + { + if (m_file != nullptr) { fclose(m_file); } + } + + void WriteSignature(); + void ReadAndCheckSignature(); + + void WriteMetadata(); + void ReadMetadata(FlexBodyFileMetadata *meta); + + void WriteFlexbodyHeader(FlexBody *flexbody); + void ReadFlexbodyHeader(FlexBodyCacheData *flexbody); + + void WriteFlexbodyLocatorList(FlexBody *flexbody); + void ReadFlexbodyLocatorList(FlexBodyCacheData *flexbody); + + void WriteFlexbodyNormalsBuffer(FlexBody *flexbody); + void ReadFlexbodyNormalsBuffer(FlexBodyCacheData *flexbody); + + void WriteFlexbodyPositionsBuffer(FlexBody *flexbody); + void ReadFlexbodyPositionsBuffer(FlexBodyCacheData *flexbody); + + void WriteFlexbodyColorsBuffer(FlexBody *flexbody); + void ReadFlexbodyColorsBuffer(FlexBodyCacheData *flexbody); + + std::vector m_items_to_save; + std::vector m_loaded_items; + FILE * m_file; + unsigned int m_fileformat_version; + int m_cache_entry_number; + }; - void WriteMetadata(); - void ReadMetadata(FlexBodyFileMetadata* meta); + class FlexFactory + { + public: + FlexFactory() + { + } - void WriteFlexbodyHeader(FlexBody* flexbody); - void ReadFlexbodyHeader(FlexBodyCacheData* flexbody); + FlexFactory(ActorSpawner *spawner); - void WriteFlexbodyLocatorList(FlexBody* flexbody); - void ReadFlexbodyLocatorList(FlexBodyCacheData* flexbody); + FlexBody *CreateFlexBody(RigDef::Flexbody *def, const int ref_node, const int x_node, const int y_node, + Ogre::Quaternion const &rot, std::vector &node_indices, + std::string resource_group_name); - void WriteFlexbodyNormalsBuffer(FlexBody* flexbody); - void ReadFlexbodyNormalsBuffer(FlexBodyCacheData* flexbody); + FlexMeshWheel *CreateFlexMeshWheel(unsigned int wheel_index, int axis_node_1_index, int axis_node_2_index, int nstart, + int nrays, float rim_radius, bool rim_reverse, std::string const &rim_mesh_name, + std::string const &tire_material_name); - void WriteFlexbodyPositionsBuffer(FlexBody* flexbody); - void ReadFlexbodyPositionsBuffer(FlexBodyCacheData* flexbody); + void CheckAndLoadFlexbodyCache(); + void SaveFlexbodiesToCache(); - void WriteFlexbodyColorsBuffer(FlexBody* flexbody); - void ReadFlexbodyColorsBuffer(FlexBodyCacheData* flexbody); + private: + void ResolveFlexbodyLOD(std::string meshname, Ogre::MeshPtr newmesh); - std::vector m_items_to_save; - std::vector m_loaded_items; - FILE* m_file; - unsigned int m_fileformat_version; - int m_cache_entry_number; -}; + ActorSpawner *m_rig_spawner; -class FlexFactory -{ -public: - FlexFactory() {} - - FlexFactory(ActorSpawner* spawner); - - FlexBody* CreateFlexBody( - RigDef::Flexbody* def, - const int ref_node, - const int x_node, - const int y_node, - Ogre::Quaternion const & rot, - std::vector & node_indices, - std::string resource_group_name); - - FlexMeshWheel* CreateFlexMeshWheel( - unsigned int wheel_index, - int axis_node_1_index, - int axis_node_2_index, - int nstart, - int nrays, - float rim_radius, - bool rim_reverse, - std::string const & rim_mesh_name, - std::string const & tire_material_name); - - void CheckAndLoadFlexbodyCache(); - void SaveFlexbodiesToCache(); - -private: - - void ResolveFlexbodyLOD(std::string meshname, Ogre::MeshPtr newmesh); - - ActorSpawner* m_rig_spawner; - - FlexBodyFileIO m_flexbody_cache; - bool m_is_flexbody_cache_enabled; - bool m_is_flexbody_cache_loaded; - unsigned int m_flexbody_cache_next_index; -}; + FlexBodyFileIO m_flexbody_cache; + bool m_is_flexbody_cache_enabled; + bool m_is_flexbody_cache_loaded; + unsigned int m_flexbody_cache_next_index; + }; } // namespace RoR diff --git a/source/main/physics/flex/FlexMesh.cpp b/source/main/physics/flex/FlexMesh.cpp index 917534f155..351ff67ef5 100644 --- a/source/main/physics/flex/FlexMesh.cpp +++ b/source/main/physics/flex/FlexMesh.cpp @@ -21,29 +21,17 @@ #include "FlexMesh.h" -#include - #include "ApproxMath.h" #include "BeamData.h" #include "GfxActor.h" +#include + using namespace Ogre; -FlexMesh::FlexMesh( - Ogre::String const & name, - RoR::GfxActor* gfx_actor, - int n1, - int n2, - int nstart, - int nrays, - Ogre::String const & face_material_name, - Ogre::String const & band_material_name, - bool rimmed, - float rim_ratio -) : - m_is_rimmed(rimmed) - , m_num_rays(nrays) - , m_gfx_actor(gfx_actor) +FlexMesh::FlexMesh(Ogre::String const &name, RoR::GfxActor *gfx_actor, int n1, int n2, int nstart, int nrays, + Ogre::String const &face_material_name, Ogre::String const &band_material_name, bool rimmed, float rim_ratio) + : m_is_rimmed(rimmed), m_num_rays(nrays), m_gfx_actor(gfx_actor) { // Create the mesh via the MeshManager m_mesh = MeshManager::getSingleton().createManual(name, gfx_actor->GetResourceGroup()); @@ -52,178 +40,193 @@ FlexMesh::FlexMesh( m_submesh_wheelface = m_mesh->createSubMesh(); m_submesh_tiretread = m_mesh->createSubMesh(); - //materials + // materials m_submesh_wheelface->setMaterialName(face_material_name); m_submesh_tiretread->setMaterialName(band_material_name); // Define the vertices - size_t vertex_count = 4*nrays+2; // each ray needs 4 verts (2 for sidewalls and 2 for band). The axis needs an extra 2. - if (m_is_rimmed) // For truckfile sections "[mesh]wheels2". + size_t vertex_count = 4 * nrays + 2; // each ray needs 4 verts (2 for sidewalls and 2 for band). The axis needs an extra 2. + if (m_is_rimmed) // For truckfile sections "[mesh]wheels2". { - vertex_count+=2*nrays; // 1 extra vertex for each sidewall. + vertex_count += 2 * nrays; // 1 extra vertex for each sidewall. } - m_vertices = new FlexMeshVertex[vertex_count]; - m_vertex_nodes=(int*)malloc(vertex_count*sizeof(int)); + m_vertices = new FlexMeshVertex[vertex_count]; + m_vertex_nodes = (int *)malloc(vertex_count * sizeof(int)); - //define node ids - m_vertex_nodes[0]=n1; - m_vertex_nodes[1]=n2; + // define node ids + m_vertex_nodes[0] = n1; + m_vertex_nodes[1] = n2; int i; - for (i=0; isharedVertexData = new VertexData(); + m_mesh->sharedVertexData = new VertexData(); m_mesh->sharedVertexData->vertexCount = vertex_count; // Create declaration (memory format) of vertex data m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration; - size_t offset = 0; + size_t offset = 0; m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); -// m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE); -// offset += VertexElement::getTypeSize(VET_FLOAT3); + // m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE); + // offset += VertexElement::getTypeSize(VET_FLOAT3); m_vertex_format->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); // Allocate vertex buffer of the requested number of vertices (vertexCount) // and bytes per vertex (offset) - m_hw_vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - offset, m_mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + m_hw_vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(offset, m_mesh->sharedVertexData->vertexCount, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); // Upload the vertex data to the card m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices, true); // Set vertex buffer binding so buffer 0 is bound to our vertex buffer - VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding; + VertexBufferBinding *bind = m_mesh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, m_hw_vbuf); - //for the sideface + // for the sideface // Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - wheelface_num_indices, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, wheelface_num_indices, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the index data to the card faceibuf->writeData(0, faceibuf->getSizeInBytes(), m_wheelface_indices, true); // Set parameters of the submesh - m_submesh_wheelface->useSharedVertices = true; + m_submesh_wheelface->useSharedVertices = true; m_submesh_wheelface->indexData->indexBuffer = faceibuf; - m_submesh_wheelface->indexData->indexCount = wheelface_num_indices; - m_submesh_wheelface->indexData->indexStart = 0; + m_submesh_wheelface->indexData->indexCount = wheelface_num_indices; + m_submesh_wheelface->indexData->indexStart = 0; - //for the band + // for the band // Allocate index buffer of the requested number of vertices (ibufCount) - HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - tiretread_num_indices, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, tiretread_num_indices, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the index data to the card bandibuf->writeData(0, bandibuf->getSizeInBytes(), m_tiretread_indices, true); // Set parameters of the submesh - m_submesh_tiretread->useSharedVertices = true; + m_submesh_tiretread->useSharedVertices = true; m_submesh_tiretread->indexData->indexBuffer = bandibuf; - m_submesh_tiretread->indexData->indexCount = tiretread_num_indices; - m_submesh_tiretread->indexData->indexStart = 0; + m_submesh_tiretread->indexData->indexCount = tiretread_num_indices; + m_submesh_tiretread->indexData->indexStart = 0; // Set bounding information (for culling) - m_mesh->_setBounds(AxisAlignedBox(-1,-1,0,1,1,0), true); + m_mesh->_setBounds(AxisAlignedBox(-1, -1, 0, 1, 1, 0), true); m_mesh->load(); } @@ -236,57 +239,63 @@ FlexMesh::~FlexMesh() m_mesh.setNull(); } - if (m_vertices != nullptr) { delete m_vertices; } - if (m_vertex_nodes != nullptr) { free (m_vertex_nodes); } - if (m_wheelface_indices != nullptr) { free (m_wheelface_indices); } - if (m_tiretread_indices != nullptr) { free (m_tiretread_indices); } + if (m_vertices != nullptr) { delete m_vertices; } + if (m_vertex_nodes != nullptr) { free(m_vertex_nodes); } + if (m_wheelface_indices != nullptr) { free(m_wheelface_indices); } + if (m_tiretread_indices != nullptr) { free(m_tiretread_indices); } } Vector3 FlexMesh::updateVertices() { - RoR::GfxActor::NodeData* all_nodes = m_gfx_actor->GetSimNodeBuffer(); - Vector3 center = (all_nodes[m_vertex_nodes[0]].AbsPosition + all_nodes[m_vertex_nodes[1]].AbsPosition) / 2.0; + RoR::GfxActor::NodeData *all_nodes = m_gfx_actor->GetSimNodeBuffer(); + Vector3 center = (all_nodes[m_vertex_nodes[0]].AbsPosition + all_nodes[m_vertex_nodes[1]].AbsPosition) / 2.0; - //optimization possible here : just copy bands on face + // optimization possible here : just copy bands on face - m_vertices[0].position=all_nodes[m_vertex_nodes[0]].AbsPosition-center; - //normals - m_vertices[0].normal=approx_normalise(all_nodes[m_vertex_nodes[0]].AbsPosition-all_nodes[m_vertex_nodes[1]].AbsPosition); + m_vertices[0].position = all_nodes[m_vertex_nodes[0]].AbsPosition - center; + // normals + m_vertices[0].normal = approx_normalise(all_nodes[m_vertex_nodes[0]].AbsPosition - all_nodes[m_vertex_nodes[1]].AbsPosition); - m_vertices[1].position=all_nodes[m_vertex_nodes[1]].AbsPosition-center; - //normals - m_vertices[1].normal=-m_vertices[0].normal; + m_vertices[1].position = all_nodes[m_vertex_nodes[1]].AbsPosition - center; + // normals + m_vertices[1].normal = -m_vertices[0].normal; - for (int i=0; i #include -#include +#include #include +#include #include -#include +#include -class FlexMesh: public Flexable +class FlexMesh : public Flexable { -public: - - FlexMesh( - Ogre::String const& name, - RoR::GfxActor* gfx_actor, - int n1, - int n2, - int nstart, - int nrays, - Ogre::String const& face_material_name, - Ogre::String const& band_material_name, - bool rimmed = false, - float rimratio = 1.f - ); + public: + FlexMesh(Ogre::String const &name, RoR::GfxActor *gfx_actor, int n1, int n2, int nstart, int nrays, + Ogre::String const &face_material_name, Ogre::String const &band_material_name, bool rimmed = false, + float rimratio = 1.f); ~FlexMesh(); Ogre::Vector3 updateVertices(); // Flexable - bool flexitPrepare() { return true; }; - void flexitCompute(); + bool flexitPrepare() + { + return true; + }; + void flexitCompute(); Ogre::Vector3 flexitFinal(); - void setVisible(bool visible) {} // Nothing to do here - -private: + void setVisible(bool visible) + { + } // Nothing to do here + private: struct FlexMeshVertex { Ogre::Vector3 position; @@ -70,23 +63,23 @@ class FlexMesh: public Flexable }; // Wheel - Ogre::Vector3 m_flexit_center; - RoR::GfxActor* m_gfx_actor; - int m_num_rays; - bool m_is_rimmed; + Ogre::Vector3 m_flexit_center; + RoR::GfxActor *m_gfx_actor; + int m_num_rays; + bool m_is_rimmed; // Meshes - Ogre::MeshPtr m_mesh; - Ogre::SubMesh* m_submesh_wheelface; - Ogre::SubMesh* m_submesh_tiretread; - Ogre::VertexDeclaration* m_vertex_format; + Ogre::MeshPtr m_mesh; + Ogre::SubMesh * m_submesh_wheelface; + Ogre::SubMesh * m_submesh_tiretread; + Ogre::VertexDeclaration * m_vertex_format; Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf; // Vertices - FlexMeshVertex* m_vertices; - int* m_vertex_nodes; + FlexMeshVertex *m_vertices; + int * m_vertex_nodes; // Indices - unsigned short* m_wheelface_indices; - unsigned short* m_tiretread_indices; + unsigned short *m_wheelface_indices; + unsigned short *m_tiretread_indices; }; diff --git a/source/main/physics/flex/FlexMeshWheel.cpp b/source/main/physics/flex/FlexMeshWheel.cpp index aed0059e01..117b5c467b 100644 --- a/source/main/physics/flex/FlexMeshWheel.cpp +++ b/source/main/physics/flex/FlexMeshWheel.cpp @@ -28,28 +28,14 @@ using namespace Ogre; -FlexMeshWheel::FlexMeshWheel( - Ogre::Entity* rim_prop_entity, - RoR::GfxActor* gfx_actor, - int axis_node_1_index, - int axis_node_2_index, - int nstart, - int nrays, - std::string const& tire_mesh_name, - std::string const& tire_material_name, - float rimradius, - bool rimreverse -) : - m_axis_node0_idx(axis_node_1_index) - , m_axis_node1_idx(axis_node_2_index) - , m_start_node_idx(nstart) - , m_num_rays(static_cast(nrays)) - , m_gfx_actor(gfx_actor) - , m_is_rim_reverse(rimreverse) - , m_rim_radius(rimradius) +FlexMeshWheel::FlexMeshWheel(Ogre::Entity *rim_prop_entity, RoR::GfxActor *gfx_actor, int axis_node_1_index, + int axis_node_2_index, int nstart, int nrays, std::string const &tire_mesh_name, + std::string const &tire_material_name, float rimradius, bool rimreverse) + : m_axis_node0_idx(axis_node_1_index), m_axis_node1_idx(axis_node_2_index), m_start_node_idx(nstart), + m_num_rays(static_cast(nrays)), m_gfx_actor(gfx_actor), m_is_rim_reverse(rimreverse), m_rim_radius(rimradius) { - m_rim_entity = rim_prop_entity; - m_rim_scene_node=gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + m_rim_entity = rim_prop_entity; + m_rim_scene_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); m_rim_scene_node->attachObject(m_rim_entity); // Create the tire mesh via the MeshManager @@ -58,62 +44,84 @@ FlexMeshWheel::FlexMeshWheel( // Create submeshes m_submesh = m_mesh->createSubMesh(); - //materials + // materials m_submesh->setMaterialName(tire_material_name); // Define the vertices - m_vertex_count = 6*(nrays+1); - m_vertices = new FlexMeshWheelVertex[m_vertex_count]; + m_vertex_count = 6 * (nrays + 1); + m_vertices = new FlexMeshWheelVertex[m_vertex_count]; int i; - //textures coordinates - for (i=0; isharedVertexData = new VertexData(); + m_mesh->sharedVertexData = new VertexData(); m_mesh->sharedVertexData->vertexCount = m_vertex_count; // Create declaration (memory format) of position data m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration; - size_t offset = 0; + size_t offset = 0; m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL); @@ -123,37 +131,32 @@ FlexMeshWheel::FlexMeshWheel( // Allocate position buffer of the requested number of vertices (vertexCount) // and bytes per position (offset) - m_hw_vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - offset, m_mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + m_hw_vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(offset, m_mesh->sharedVertexData->vertexCount, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); // Upload the position data to the card m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices, true); // Set position buffer binding so buffer 0 is bound to our position buffer - VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding; + VertexBufferBinding *bind = m_mesh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, m_hw_vbuf); - //for the face + // for the face // Allocate index buffer of the requested number of vertices (m_index_count) - HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - m_index_count, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, m_index_count, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the index data to the card ibuf->writeData(0, ibuf->getSizeInBytes(), m_indices, true); // Set parameters of the submesh - m_submesh->useSharedVertices = true; + m_submesh->useSharedVertices = true; m_submesh->indexData->indexBuffer = ibuf; - m_submesh->indexData->indexCount = m_index_count; - m_submesh->indexData->indexStart = 0; - + m_submesh->indexData->indexCount = m_index_count; + m_submesh->indexData->indexStart = 0; // Set bounding information (for culling) - m_mesh->_setBounds(AxisAlignedBox(-1,-1,0,1,1,0), true); + m_mesh->_setBounds(AxisAlignedBox(-1, -1, 0, 1, 1, 0), true); m_mesh->load(); } @@ -161,7 +164,7 @@ FlexMeshWheel::FlexMeshWheel( FlexMeshWheel::~FlexMeshWheel() { if (m_vertices != nullptr) { delete m_vertices; } - if (m_indices != nullptr) { free (m_indices); } + if (m_indices != nullptr) { free(m_indices); } // Rim: we own both Entity and SceneNode m_rim_scene_node->detachAllObjects(); @@ -182,44 +185,60 @@ FlexMeshWheel::~FlexMeshWheel() Vector3 FlexMeshWheel::updateVertices() { - RoR::GfxActor::NodeData* all_nodes = m_gfx_actor->GetSimNodeBuffer(); - Vector3 center = (all_nodes[m_axis_node0_idx].AbsPosition + all_nodes[m_axis_node1_idx].AbsPosition) / 2.0; - Vector3 ray = all_nodes[m_start_node_idx].AbsPosition - all_nodes[m_axis_node0_idx].AbsPosition; - Vector3 axis = all_nodes[m_axis_node0_idx].AbsPosition - all_nodes[m_axis_node1_idx].AbsPosition; + RoR::GfxActor::NodeData *all_nodes = m_gfx_actor->GetSimNodeBuffer(); + Vector3 center = (all_nodes[m_axis_node0_idx].AbsPosition + all_nodes[m_axis_node1_idx].AbsPosition) / 2.0; + Vector3 ray = all_nodes[m_start_node_idx].AbsPosition - all_nodes[m_axis_node0_idx].AbsPosition; + Vector3 axis = all_nodes[m_axis_node0_idx].AbsPosition - all_nodes[m_axis_node1_idx].AbsPosition; axis.normalise(); - - for (size_t i=0; iGetSimNodeBuffer(); - Vector3 center = (all_nodes[m_axis_node0_idx].AbsPosition + all_nodes[m_axis_node1_idx].AbsPosition) / 2.0; + RoR::GfxActor::NodeData *all_nodes = m_gfx_actor->GetSimNodeBuffer(); + Vector3 center = (all_nodes[m_axis_node0_idx].AbsPosition + all_nodes[m_axis_node1_idx].AbsPosition) / 2.0; m_rim_scene_node->setPosition(center); Vector3 axis = all_nodes[m_axis_node0_idx].AbsPosition - all_nodes[m_axis_node1_idx].AbsPosition; axis.normalise(); if (m_is_rim_reverse) axis = -axis; - Vector3 ray = all_nodes[m_start_node_idx].AbsPosition - all_nodes[m_axis_node0_idx].AbsPosition; + Vector3 ray = all_nodes[m_start_node_idx].AbsPosition - all_nodes[m_axis_node0_idx].AbsPosition; Vector3 onormal = axis.crossProduct(ray); onormal.normalise(); ray = axis.crossProduct(onormal); diff --git a/source/main/physics/flex/FlexMeshWheel.h b/source/main/physics/flex/FlexMeshWheel.h index fe1a02fc07..2dacd5c1df 100644 --- a/source/main/physics/flex/FlexMeshWheel.h +++ b/source/main/physics/flex/FlexMeshWheel.h @@ -21,50 +21,45 @@ #pragma once -#include "ForwardDeclarations.h" #include "FlexMesh.h" +#include "ForwardDeclarations.h" -#include +#include #include #include -#include +#include #include /// Consists of static mesh, representing the rim, and dynamic mesh, representing the tire. -class FlexMeshWheel: public Flexable +class FlexMeshWheel : public Flexable { friend class RoR::FlexFactory; -public: - + public: ~FlexMeshWheel(); - Ogre::Entity* getRimEntity() { return m_rim_entity; }; - Ogre::Entity* GetTireEntity() { return m_tire_entity; } + Ogre::Entity *getRimEntity() + { + return m_rim_entity; + }; + Ogre::Entity *GetTireEntity() + { + return m_tire_entity; + } Ogre::Vector3 updateVertices(); // Flexable - bool flexitPrepare(); - void flexitCompute(); + bool flexitPrepare(); + void flexitCompute(); Ogre::Vector3 flexitFinal(); void setVisible(bool visible); -private: - + private: FlexMeshWheel( // Use FlexFactory - Ogre::Entity* rim_prop_entity, - RoR::GfxActor* gfx_actor, - int axis_node_1_index, - int axis_node_2_index, - int nstart, - int nrays, - std::string const& tire_mesh_name, - std::string const& tire_material_name, - float rimradius, - bool rimreverse - ); + Ogre::Entity *rim_prop_entity, RoR::GfxActor *gfx_actor, int axis_node_1_index, int axis_node_2_index, int nstart, + int nrays, std::string const &tire_mesh_name, std::string const &tire_material_name, float rimradius, bool rimreverse); struct FlexMeshWheelVertex { @@ -74,30 +69,30 @@ class FlexMeshWheel: public Flexable }; // Wheel - size_t m_num_rays; - float m_rim_radius; - RoR::GfxActor* m_gfx_actor; - int m_axis_node0_idx; - int m_axis_node1_idx; - int m_start_node_idx; ///< First node (lowest index) belonging to this wheel. + size_t m_num_rays; + float m_rim_radius; + RoR::GfxActor *m_gfx_actor; + int m_axis_node0_idx; + int m_axis_node1_idx; + int m_start_node_idx; ///< First node (lowest index) belonging to this wheel. // Meshes Ogre::Vector3 m_flexit_center; Ogre::MeshPtr m_mesh; - Ogre::SubMesh* m_submesh; + Ogre::SubMesh * m_submesh; bool m_is_rim_reverse; - Ogre::Entity* m_rim_entity; - Ogre::Entity* m_tire_entity; // Assigned by friend FlexFactory - Ogre::SceneNode* m_rim_scene_node; + Ogre::Entity * m_rim_entity; + Ogre::Entity * m_tire_entity; // Assigned by friend FlexFactory + Ogre::SceneNode *m_rim_scene_node; // Vertices - float m_norm_y; - size_t m_vertex_count; - FlexMeshWheelVertex* m_vertices; - Ogre::VertexDeclaration* m_vertex_format; + float m_norm_y; + size_t m_vertex_count; + FlexMeshWheelVertex * m_vertices; + Ogre::VertexDeclaration * m_vertex_format; Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf; // Indices - size_t m_index_count; - unsigned short* m_indices; + size_t m_index_count; + unsigned short *m_indices; }; diff --git a/source/main/physics/flex/FlexObj.cpp b/source/main/physics/flex/FlexObj.cpp index 6a50a46952..8ce534c187 100644 --- a/source/main/physics/flex/FlexObj.cpp +++ b/source/main/physics/flex/FlexObj.cpp @@ -28,10 +28,10 @@ using namespace Ogre; -FlexObj::FlexObj(RoR::GfxActor* gfx_actor, node_t* all_nodes, std::vector& texcoords, int numtriangles, - int* triangles, std::vector& submesh_defs, - char* texname, const char* name, char* backtexname, char* transtexname): - m_gfx_actor(gfx_actor) +FlexObj::FlexObj(RoR::GfxActor *gfx_actor, node_t *all_nodes, std::vector &texcoords, int numtriangles, + int *triangles, std::vector &submesh_defs, char *texname, const char *name, char *backtexname, + char *transtexname) + : m_gfx_actor(gfx_actor) { m_triangle_count = numtriangles; @@ -40,57 +40,57 @@ FlexObj::FlexObj(RoR::GfxActor* gfx_actor, node_t* all_nodes, std::vectorcreateSubMesh(); + Ogre::SubMesh *submesh = m_mesh->createSubMesh(); switch (submesh_defs[j].backmesh_type) { - case CabSubmesh::BACKMESH_OPAQUE: submesh->setMaterialName(backtexname); break; + case CabSubmesh::BACKMESH_OPAQUE: submesh->setMaterialName(backtexname); break; case CabSubmesh::BACKMESH_TRANSPARENT: submesh->setMaterialName(transtexname); break; - default: submesh->setMaterialName(texname); + default: submesh->setMaterialName(texname); } m_submeshes.push_back(submesh); }; // Define the m_vertices_raw (8 vertices, each consisting of 3 groups of 3 floats m_vertex_count = texcoords.size(); - m_vertices_raw=(float*)malloc(((2*3+2)*m_vertex_count)*sizeof(float)); - m_vertex_nodes=(int*)malloc(m_vertex_count*sizeof(int)); - - for (size_t i=0; i(i/3), triangles[i], submesh_defs); + m_indices[i] = ComputeVertexPos(static_cast(i / 3), triangles[i], submesh_defs); } - m_s_ref=(float*)malloc(numtriangles*sizeof(float)); + m_s_ref = (float *)malloc(numtriangles * sizeof(float)); - for (size_t i=0; i<(unsigned int)numtriangles;i++) + for (size_t i = 0; i < (unsigned int)numtriangles; i++) { - Ogre::Vector3 base_pos = all_nodes[m_vertex_nodes[m_indices[i*3]]].RelPosition; - Ogre::Vector3 v1 = all_nodes[m_vertex_nodes[m_indices[i*3+1]]].RelPosition - base_pos; - Ogre::Vector3 v2 = all_nodes[m_vertex_nodes[m_indices[i*3+2]]].RelPosition - base_pos; - m_s_ref[i]=v1.crossProduct(v2).length()*2.0; + Ogre::Vector3 base_pos = all_nodes[m_vertex_nodes[m_indices[i * 3]]].RelPosition; + Ogre::Vector3 v1 = all_nodes[m_vertex_nodes[m_indices[i * 3 + 1]]].RelPosition - base_pos; + Ogre::Vector3 v2 = all_nodes[m_vertex_nodes[m_indices[i * 3 + 2]]].RelPosition - base_pos; + m_s_ref[i] = v1.crossProduct(v2).length() * 2.0; } this->UpdateMesh(); // Initialize the dynamic mesh // Create vertex data structure for vertices shared between submeshes - m_mesh->sharedVertexData = new VertexData(); + m_mesh->sharedVertexData = new VertexData(); m_mesh->sharedVertexData->vertexCount = m_vertex_count; // Create declaration (memory format) of vertex data m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration; - size_t offset = 0; + size_t offset = 0; m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL); @@ -100,46 +100,44 @@ FlexObj::FlexObj(RoR::GfxActor* gfx_actor, node_t* all_nodes, std::vectorsharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + m_hw_vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(offset, m_mesh->sharedVertexData->vertexCount, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); // Upload the vertex data to the card m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices_raw, true); // Set vertex buffer binding so buffer 0 is bound to our vertex buffer - VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding; + VertexBufferBinding *bind = m_mesh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, m_hw_vbuf); // Set parameters of the submeshes - for (size_t j=0; juseSharedVertices = true; HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - index_count, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); + HardwareIndexBuffer::IT_16BIT, index_count, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the index data to the card - unsigned short* faces_ptr; + unsigned short *faces_ptr; if (j == 0) faces_ptr = &m_indices[0]; else - faces_ptr = &m_indices[submesh_defs[j-1].cabs_pos * 3]; + faces_ptr = &m_indices[submesh_defs[j - 1].cabs_pos * 3]; ibuf->writeData(0, ibuf->getSizeInBytes(), faces_ptr, true); m_submeshes[j]->indexData->indexBuffer = ibuf; - m_submeshes[j]->indexData->indexCount = index_count; - m_submeshes[j]->indexData->indexStart = 0; + m_submeshes[j]->indexData->indexCount = index_count; + m_submeshes[j]->indexData->indexStart = 0; } // Set bounding information (for culling) - m_mesh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100), true); + m_mesh->_setBounds(AxisAlignedBox(-100, -100, -100, 100, 100, 100), true); // Notify Mesh object that it has been loaded m_mesh->load(); @@ -147,14 +145,14 @@ FlexObj::FlexObj(RoR::GfxActor* gfx_actor, node_t* all_nodes, std::vector& submeshes) +int FlexObj::ComputeVertexPos(int tidx, int v, std::vector &submeshes) { // --- NOTE: The following logic is arcane, I'm keeping it mostly like I found it for stability ~ only_a_ptr, 08/2017 @@ -171,12 +169,15 @@ int FlexObj::ComputeVertexPos(int tidx, int v, std::vector& submeshe } // Find the vertex itself - int i_min = (context < 0) ? 0 : static_cast(submeshes[context].texcoords_pos); // Fix for single-submesh case... It seems to have worked with a negative index until now ~ only_a_ptr, 08/2017 + int i_min = + (context < 0) + ? 0 + : static_cast(submeshes[context].texcoords_pos); // Fix for single-submesh case... It seems to have worked with a + // negative index until now ~ only_a_ptr, 08/2017 int i_max = static_cast(submeshes[context + 1].texcoords_pos); for (int i = i_min; i < i_max; ++i) { - if (m_vertex_nodes[i] == v) - return i; + if (m_vertex_nodes[i] == v) return i; } return 0; @@ -184,41 +185,42 @@ int FlexObj::ComputeVertexPos(int tidx, int v, std::vector& submeshe Vector3 FlexObj::UpdateMesh() { - RoR::GfxActor::NodeData* all_nodes = m_gfx_actor->GetSimNodeBuffer(); - Ogre::Vector3 center=(all_nodes[m_vertex_nodes[0]].AbsPosition+all_nodes[m_vertex_nodes[1]].AbsPosition)/2.0; - for (size_t i=0; iGetSimNodeBuffer(); + Ogre::Vector3 center = (all_nodes[m_vertex_nodes[0]].AbsPosition + all_nodes[m_vertex_nodes[1]].AbsPosition) / 2.0; + for (size_t i = 0; i < m_vertex_count; i++) { - //set position - m_vertices[i].position=all_nodes[m_vertex_nodes[i]].AbsPosition-center; - //reset normals - m_vertices[i].normal=Vector3::ZERO; + // set position + m_vertices[i].position = all_nodes[m_vertex_nodes[i]].AbsPosition - center; + // reset normals + m_vertices[i].normal = Vector3::ZERO; } - //accumulate normals per triangle - for (size_t i=0; im_s_ref[i]) + v1 = + all_nodes[m_vertex_nodes[m_indices[i * 3 + 1]]].AbsPosition - all_nodes[m_vertex_nodes[m_indices[i * 3]]].AbsPosition; + v2 = + all_nodes[m_vertex_nodes[m_indices[i * 3 + 2]]].AbsPosition - all_nodes[m_vertex_nodes[m_indices[i * 3]]].AbsPosition; + v1 = v1.crossProduct(v2); + float s = v1.length(); + + // avoid large tris + if (s > m_s_ref[i]) { - m_vertices[m_indices[i*3+1]].position=m_vertices[m_indices[i*3]].position+Vector3(0.1,0,0); - m_vertices[m_indices[i*3+2]].position=m_vertices[m_indices[i*3]].position+Vector3(0,0,0.1); + m_vertices[m_indices[i * 3 + 1]].position = m_vertices[m_indices[i * 3]].position + Vector3(0.1, 0, 0); + m_vertices[m_indices[i * 3 + 2]].position = m_vertices[m_indices[i * 3]].position + Vector3(0, 0, 0.1); } - if (s == 0) - continue; + if (s == 0) continue; - v1=v1/s; - m_vertices[m_indices[i*3]].normal+=v1; - m_vertices[m_indices[i*3+1]].normal+=v1; - m_vertices[m_indices[i*3+2]].normal+=v1; + v1 = v1 / s; + m_vertices[m_indices[i * 3]].normal += v1; + m_vertices[m_indices[i * 3 + 1]].normal += v1; + m_vertices[m_indices[i * 3 + 2]].normal += v1; } - //normalize - for (size_t i=0; i +#include #include #include -#include +#include /// Texture coordinates for old-style actor body (the "cab") struct CabTexcoord { - int node_id; - float texcoord_u; - float texcoord_v; + int node_id; + float texcoord_u; + float texcoord_v; }; /// Submesh for old-style actor body (the "cab") struct CabSubmesh { - enum BackmeshType { BACKMESH_NONE, BACKMESH_OPAQUE, BACKMESH_TRANSPARENT }; + enum BackmeshType + { + BACKMESH_NONE, + BACKMESH_OPAQUE, + BACKMESH_TRANSPARENT + }; - CabSubmesh(): backmesh_type(BACKMESH_NONE), texcoords_pos(0), cabs_pos(0) {} + CabSubmesh() : backmesh_type(BACKMESH_NONE), texcoords_pos(0), cabs_pos(0) + { + } - BackmeshType backmesh_type; - size_t texcoords_pos; - size_t cabs_pos; + BackmeshType backmesh_type; + size_t texcoords_pos; + size_t cabs_pos; }; /// A visual mesh, forming a chassis for softbody actor /// At most one instance is created per actor. class FlexObj : public ZeroedMemoryAllocator { -public: - - FlexObj( - RoR::GfxActor* gfx_actor, - node_t* all_nodes, // For initial setup only, pointer is not stored - std::vector& texcoords, - int numtriangles, - int* triangles, - std::vector& submeshes, - char* texname, - const char* name, - char* backtexname, - char* transtexname); + public: + FlexObj(RoR::GfxActor * gfx_actor, + node_t * all_nodes, // For initial setup only, pointer is not stored + std::vector &texcoords, int numtriangles, int *triangles, std::vector &submeshes, + char *texname, const char *name, char *backtexname, char *transtexname); ~FlexObj(); - Ogre::Vector3 UpdateFlexObj(); - void ScaleFlexObj(float factor); - -private: + Ogre::Vector3 UpdateFlexObj(); + void ScaleFlexObj(float factor); + private: struct FlexObjVertex { Ogre::Vector3 position; @@ -83,25 +80,24 @@ class FlexObj : public ZeroedMemoryAllocator }; /// Compute vertex position in the vertexbuffer (0-based offset) for node `v` of triangle `tidx` - int ComputeVertexPos(int tidx, int v, std::vector& submeshes); - Ogre::Vector3 UpdateMesh(); + int ComputeVertexPos(int tidx, int v, std::vector &submeshes); + Ogre::Vector3 UpdateMesh(); - Ogre::MeshPtr m_mesh; - std::vector m_submeshes; - RoR::GfxActor* m_gfx_actor; - float* m_s_ref; + Ogre::MeshPtr m_mesh; + std::vector m_submeshes; + RoR::GfxActor * m_gfx_actor; + float * m_s_ref; - size_t m_vertex_count; - int* m_vertex_nodes; - Ogre::VertexDeclaration* m_vertex_format; + size_t m_vertex_count; + int * m_vertex_nodes; + Ogre::VertexDeclaration * m_vertex_format; Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf; - union - { - float* m_vertices_raw; - FlexObjVertex* m_vertices; + union { + float * m_vertices_raw; + FlexObjVertex *m_vertices; }; - size_t m_index_count; - unsigned short* m_indices; - int m_triangle_count; + size_t m_index_count; + unsigned short *m_indices; + int m_triangle_count; }; diff --git a/source/main/physics/flex/Flexable.h b/source/main/physics/flex/Flexable.h index d3c9ba8006..d494d78c7a 100644 --- a/source/main/physics/flex/Flexable.h +++ b/source/main/physics/flex/Flexable.h @@ -26,12 +26,14 @@ class Flexable { -public: - virtual ~Flexable() {} - - virtual bool flexitPrepare() = 0; - virtual void flexitCompute() = 0; - virtual Ogre::Vector3 flexitFinal() = 0; + public: + virtual ~Flexable() + { + } + + virtual bool flexitPrepare() = 0; + virtual void flexitCompute() = 0; + virtual Ogre::Vector3 flexitFinal() = 0; virtual void setVisible(bool visible) = 0; }; diff --git a/source/main/physics/flex/Locator_t.h b/source/main/physics/flex/Locator_t.h index 79081e9230..c1bdc1c733 100644 --- a/source/main/physics/flex/Locator_t.h +++ b/source/main/physics/flex/Locator_t.h @@ -4,9 +4,9 @@ struct Locator_t { - int ref; - int nx; - int ny; - int nz; + int ref; + int nx; + int ny; + int nz; Ogre::Vector3 coords; }; diff --git a/source/main/physics/water/Buoyance.cpp b/source/main/physics/water/Buoyance.cpp index f71bbf2115..4a30ead8e6 100644 --- a/source/main/physics/water/Buoyance.cpp +++ b/source/main/physics/water/Buoyance.cpp @@ -23,19 +23,15 @@ #include "Application.h" #include "BeamData.h" #include "BeamFactory.h" -#include "GfxScene.h" #include "DustPool.h" +#include "GfxScene.h" #include "TerrainManager.h" #include "Water.h" using namespace Ogre; using namespace RoR; -Buoyance::Buoyance(DustPool* splash, DustPool* ripple) : - splashp(splash), - ripplep(ripple), - sink(0), - update(false) +Buoyance::Buoyance(DustPool *splash, DustPool *ripple) : splashp(splash), ripplep(ripple), sink(0), update(false) { } @@ -43,32 +39,31 @@ Buoyance::~Buoyance() { } -//compute tetrahedron volume +// compute tetrahedron volume inline float Buoyance::computeVolume(Vector3 o, Vector3 a, Vector3 b, Vector3 c) { return ((a - o).dotProduct((b - o).crossProduct(c - o))) / 6.0; } -//compute pressure and drag force on a submerged triangle +// compute pressure and drag force on a submerged triangle Vector3 Buoyance::computePressureForceSub(Vector3 a, Vector3 b, Vector3 c, Vector3 vel, int type) { - //compute normal vector + // compute normal vector Vector3 normal = (b - a).crossProduct(c - a); - float surf = normal.length(); - if (surf < 0.00001) - return Vector3::ZERO; - normal = normal / surf; //normalize - surf = surf / 2.0; //surface + float surf = normal.length(); + if (surf < 0.00001) return Vector3::ZERO; + normal = normal / surf; // normalize + surf = surf / 2.0; // surface float vol = 0.0; if (type != BUOY_DRAGONLY) { - //compute pression prism points + // compute pression prism points Vector3 ap = a + (App::GetSimTerrain()->getWater()->CalcWavesHeight(a) - a.y) * 9810 * normal; Vector3 bp = b + (App::GetSimTerrain()->getWater()->CalcWavesHeight(b) - b.y) * 9810 * normal; Vector3 cp = c + (App::GetSimTerrain()->getWater()->CalcWavesHeight(c) - c.y) * 9810 * normal; - //find centroid + // find centroid Vector3 ctd = (a + b + c + ap + bp + cp) / 6.0; - //compute volume + // compute volume vol += computeVolume(ctd, a, b, c); vol += computeVolume(ctd, a, ap, bp); vol += computeVolume(ctd, a, bp, b); @@ -81,27 +76,25 @@ Vector3 Buoyance::computePressureForceSub(Vector3 a, Vector3 b, Vector3 c, Vecto Vector3 drg = Vector3::ZERO; if (type != BUOY_DRAGLESS) { - //now, the drag - //take in account the wave speed - //compute center + // now, the drag + // take in account the wave speed + // compute center Vector3 tc = (a + b + c) / 3.0; - vel = vel - App::GetSimTerrain()->getWater()->CalcWavesVelocity(tc); + vel = vel - App::GetSimTerrain()->getWater()->CalcWavesVelocity(tc); float vell = vel.length(); if (vell > 0.01) { float cosaoa = fabs(normal.dotProduct(vel / vell)); // drg=(-500.0*surf*vell*cosaoa)*vel; drg = (-500.0 * surf * vell * vell * cosaoa) * normal; - if (normal.dotProduct(vel / vell) < 0) - drg = -drg; + if (normal.dotProduct(vel / vell) < 0) drg = -drg; if (update && splashp) { float fxl = vell * cosaoa * surf; - if (fxl > 1.5) //if enough pushing drag + if (fxl > 1.5) // if enough pushing drag { Vector3 fxdir = fxl * normal; - if (fxdir.y < 0) - fxdir.y = -fxdir.y; + if (fxdir.y < 0) fxdir.y = -fxdir.y; if (App::GetSimTerrain()->getWater()->CalcWavesHeight(a) - a.y < 0.1) splashp->malloc(a, fxdir); @@ -115,68 +108,69 @@ Vector3 Buoyance::computePressureForceSub(Vector3 a, Vector3 b, Vector3 c, Vecto } } } - //okay - if (sink) - return drg; + // okay + if (sink) return drg; return vol * normal + drg; } -//compute pressure and drag forces on a random triangle +// compute pressure and drag forces on a random triangle Vector3 Buoyance::computePressureForce(Vector3 a, Vector3 b, Vector3 c, Vector3 vel, int type) { float wha = App::GetSimTerrain()->getWater()->CalcWavesHeight((a + b + c) / 3.0); - //check if fully emerged - if (a.y > wha && b.y > wha && c.y > wha) - return Vector3::ZERO; - //check if semi emerged + // check if fully emerged + if (a.y > wha && b.y > wha && c.y > wha) return Vector3::ZERO; + // check if semi emerged if (a.y > wha || b.y > wha || c.y > wha) { - //okay, several cases - //one dip + // okay, several cases + // one dip if (a.y < wha && b.y > wha && c.y > wha) { - return computePressureForceSub(a, a + (wha - a.y) / (b.y - a.y) * (b - a), a + (wha - a.y) / (c.y - a.y) * (c - a), vel, type); + return computePressureForceSub(a, a + (wha - a.y) / (b.y - a.y) * (b - a), a + (wha - a.y) / (c.y - a.y) * (c - a), + vel, type); } if (b.y < wha && c.y > wha && a.y > wha) { - return computePressureForceSub(b, b + (wha - b.y) / (c.y - b.y) * (c - b), b + (wha - b.y) / (a.y - b.y) * (a - b), vel, type); + return computePressureForceSub(b, b + (wha - b.y) / (c.y - b.y) * (c - b), b + (wha - b.y) / (a.y - b.y) * (a - b), + vel, type); } if (c.y < wha && a.y > wha && b.y > wha) { - return computePressureForceSub(c, c + (wha - c.y) / (a.y - c.y) * (a - c), c + (wha - c.y) / (b.y - c.y) * (b - c), vel, type); + return computePressureForceSub(c, c + (wha - c.y) / (a.y - c.y) * (a - c), c + (wha - c.y) / (b.y - c.y) * (b - c), + vel, type); } - //two dips + // two dips if (a.y > wha && b.y < wha && c.y < wha) { Vector3 tb = a + (wha - a.y) / (b.y - a.y) * (b - a); Vector3 tc = a + (wha - a.y) / (c.y - a.y) * (c - a); - Vector3 f = computePressureForceSub(tb, b, tc, vel, type); + Vector3 f = computePressureForceSub(tb, b, tc, vel, type); return f + computePressureForceSub(tc, b, c, vel, type); } if (b.y > wha && c.y < wha && a.y < wha) { Vector3 tc = b + (wha - b.y) / (c.y - b.y) * (c - b); Vector3 ta = b + (wha - b.y) / (a.y - b.y) * (a - b); - Vector3 f = computePressureForceSub(tc, c, ta, vel, type); + Vector3 f = computePressureForceSub(tc, c, ta, vel, type); return f + computePressureForceSub(ta, c, a, vel, type); } if (c.y > wha && a.y < wha && b.y < wha) { Vector3 ta = c + (wha - c.y) / (a.y - c.y) * (a - c); Vector3 tb = c + (wha - c.y) / (b.y - c.y) * (b - c); - Vector3 f = computePressureForceSub(ta, a, tb, vel, type); + Vector3 f = computePressureForceSub(ta, a, tb, vel, type); return f + computePressureForceSub(tb, a, b, vel, type); } return Vector3::ZERO; } else { - //fully submerged case + // fully submerged case return computePressureForceSub(a, b, c, vel, type); } } -void Buoyance::computeNodeForce(node_t* a, node_t* b, node_t* c, bool doUpdate, int type) +void Buoyance::computeNodeForce(node_t *a, node_t *b, node_t *c, bool doUpdate, int type) { if (a->AbsPosition.y > App::GetSimTerrain()->getWater()->CalcWavesHeight(a->AbsPosition) && b->AbsPosition.y > App::GetSimTerrain()->getWater()->CalcWavesHeight(b->AbsPosition) && @@ -185,7 +179,7 @@ void Buoyance::computeNodeForce(node_t* a, node_t* b, node_t* c, bool doUpdate, update = doUpdate; - //compute center + // compute center Vector3 m = (a->AbsPosition + b->AbsPosition + c->AbsPosition) / 3.0; #if 0 @@ -198,14 +192,17 @@ void Buoyance::computeNodeForce(node_t* a, node_t* b, node_t* c, bool doUpdate, Vector3 mca = (tmp.dotProduct(m-c->Position) / tmp.squaredLength()) * tmp; #endif - //suboptimal + // suboptimal Vector3 mab = (a->AbsPosition + b->AbsPosition) / 2.0; Vector3 mbc = (b->AbsPosition + c->AbsPosition) / 2.0; Vector3 mca = (c->AbsPosition + a->AbsPosition) / 2.0; Vector3 vel = (a->Velocity + b->Velocity + c->Velocity) / 3.0; - //apply forces - a->Forces += computePressureForce(a->AbsPosition, mab, m, vel, type) + computePressureForce(a->AbsPosition, m, mca, vel, type); - b->Forces += computePressureForce(b->AbsPosition, mbc, m, vel, type) + computePressureForce(b->AbsPosition, m, mab, vel, type); - c->Forces += computePressureForce(c->AbsPosition, mca, m, vel, type) + computePressureForce(c->AbsPosition, m, mbc, vel, type); + // apply forces + a->Forces += + computePressureForce(a->AbsPosition, mab, m, vel, type) + computePressureForce(a->AbsPosition, m, mca, vel, type); + b->Forces += + computePressureForce(b->AbsPosition, mbc, m, vel, type) + computePressureForce(b->AbsPosition, m, mab, vel, type); + c->Forces += + computePressureForce(c->AbsPosition, mca, m, vel, type) + computePressureForce(c->AbsPosition, m, mbc, vel, type); } diff --git a/source/main/physics/water/Buoyance.h b/source/main/physics/water/Buoyance.h index 5740a8858d..fa37b636b0 100644 --- a/source/main/physics/water/Buoyance.h +++ b/source/main/physics/water/Buoyance.h @@ -24,29 +24,31 @@ class Buoyance { -public: - - Buoyance(DustPool* splash, DustPool* ripple); + public: + Buoyance(DustPool *splash, DustPool *ripple); ~Buoyance(); void computeNodeForce(node_t *a, node_t *b, node_t *c, bool doUpdate, int type); - enum { BUOY_NORMAL, BUOY_DRAGONLY, BUOY_DRAGLESS }; + enum + { + BUOY_NORMAL, + BUOY_DRAGONLY, + BUOY_DRAGLESS + }; bool sink; -private: - - //compute tetrahedron volume + private: + // compute tetrahedron volume inline float computeVolume(Ogre::Vector3 o, Ogre::Vector3 a, Ogre::Vector3 b, Ogre::Vector3 c); - //compute pressure and drag force on a submerged triangle + // compute pressure and drag force on a submerged triangle Ogre::Vector3 computePressureForceSub(Ogre::Vector3 a, Ogre::Vector3 b, Ogre::Vector3 c, Ogre::Vector3 vel, int type); - - //compute pressure and drag forces on a random triangle + + // compute pressure and drag forces on a random triangle Ogre::Vector3 computePressureForce(Ogre::Vector3 a, Ogre::Vector3 b, Ogre::Vector3 c, Ogre::Vector3 vel, int type); - + DustPool *splashp, *ripplep; - bool update; + bool update; }; - diff --git a/source/main/physics/water/ScrewProp.cpp b/source/main/physics/water/ScrewProp.cpp index 711a872505..941670f212 100644 --- a/source/main/physics/water/ScrewProp.cpp +++ b/source/main/physics/water/ScrewProp.cpp @@ -33,13 +33,8 @@ using namespace Ogre; using namespace RoR; -Screwprop::Screwprop(node_t* nodes, int noderef, int nodeback, int nodeup, float fullpower, int trucknum) : - nodes(nodes) - , noderef(noderef) - , nodeback(nodeback) - , nodeup(nodeup) - , fullpower(fullpower) - , trucknum(trucknum) +Screwprop::Screwprop(node_t *nodes, int noderef, int nodeback, int nodeup, float fullpower, int trucknum) + : nodes(nodes), noderef(noderef), nodeback(nodeback), nodeup(nodeup), fullpower(fullpower), trucknum(trucknum) { splashp = RoR::App::GetSimController()->GetGfxScene().GetDustPool("splash"); ripplep = RoR::App::GetSimController()->GetGfxScene().GetDustPool("ripple"); @@ -48,17 +43,14 @@ Screwprop::Screwprop(node_t* nodes, int noderef, int nodeback, int nodeup, float void Screwprop::updateForces(int update) { - if (!App::GetSimTerrain()->getWater()) - return; + if (!App::GetSimTerrain()->getWater()) return; float depth = App::GetSimTerrain()->getWater()->CalcWavesHeight(nodes[noderef].AbsPosition) - nodes[noderef].AbsPosition.y; - if (depth < 0) - return; //out of water! - Vector3 dir = nodes[nodeback].RelPosition - nodes[noderef].RelPosition; + if (depth < 0) return; // out of water! + Vector3 dir = nodes[nodeback].RelPosition - nodes[noderef].RelPosition; Vector3 rudaxis = nodes[noderef].RelPosition - nodes[nodeup].RelPosition; dir.normalise(); - if (reverse) - dir = -dir; + if (reverse) dir = -dir; rudaxis.normalise(); dir = (throtle * fullpower) * (Quaternion(Degree(rudder), rudaxis) * dir); nodes[noderef].Forces += dir; @@ -75,23 +67,19 @@ void Screwprop::updateForces(int update) void Screwprop::setThrottle(float val) { - if (val > 1.0) - val = 1.0; - if (val < -1.0) - val = -1.0; + if (val > 1.0) val = 1.0; + if (val < -1.0) val = -1.0; throtle = fabs(val); reverse = (val < 0); - //pseudo-rpm + // pseudo-rpm float prpm = (0.5 + fabs(val) / 2.0) * 100.0; SOUND_MODULATE(trucknum, SS_MOD_ENGINE, prpm); } void Screwprop::setRudder(float val) { - if (val > 1.0) - val = 1.0; - if (val < -1.0) - val = -1.0; + if (val > 1.0) val = 1.0; + if (val < -1.0) val = -1.0; rudder = val * 45.0; } @@ -111,7 +99,7 @@ float Screwprop::getRudder() void Screwprop::reset() { setThrottle(0); - rudder = 0; + rudder = 0; reverse = false; } diff --git a/source/main/physics/water/ScrewProp.h b/source/main/physics/water/ScrewProp.h index 46285907f4..559c0e1142 100644 --- a/source/main/physics/water/ScrewProp.h +++ b/source/main/physics/water/ScrewProp.h @@ -26,30 +26,26 @@ class Screwprop : public ZeroedMemoryAllocator { friend class RigInspector; -public: + public: + Screwprop(node_t *nd, int nr, int nb, int nu, float power, int trucknum); - Screwprop( node_t *nd, int nr, int nb, int nu, float power, int trucknum); - - void updateForces(int update); - void setThrottle(float val); - void setRudder(float val); + void updateForces(int update); + void setThrottle(float val); + void setRudder(float val); float getThrottle(); float getRudder(); - void reset(); - void toggleReverse(); - -private: + void reset(); + void toggleReverse(); + private: DustPool *splashp, *ripplep; - bool reverse; - float fullpower; //!< in HP - float rudder; - float throtle; - int nodeback; - int noderef; - int nodeup; - int trucknum; - node_t *nodes; - + bool reverse; + float fullpower; //!< in HP + float rudder; + float throtle; + int nodeback; + int noderef; + int nodeup; + int trucknum; + node_t * nodes; }; - diff --git a/source/main/resource.h b/source/main/resource.h index 55f99402a0..770d28995b 100644 --- a/source/main/resource.h +++ b/source/main/resource.h @@ -2,15 +2,15 @@ // Microsoft Visual C++ generated include file. // Used by icon.rc // -#define IDI_ICON1 101 +#define IDI_ICON1 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif + #ifndef APSTUDIO_READONLY_SYMBOLS + #define _APS_NEXT_RESOURCE_VALUE 102 + #define _APS_NEXT_COMMAND_VALUE 40001 + #define _APS_NEXT_CONTROL_VALUE 1000 + #define _APS_NEXT_SYMED_VALUE 101 + #endif #endif diff --git a/source/main/resources/CacheSystem.cpp b/source/main/resources/CacheSystem.cpp index b314f041ae..f9dad0155e 100644 --- a/source/main/resources/CacheSystem.cpp +++ b/source/main/resources/CacheSystem.cpp @@ -25,13 +25,12 @@ #include "CacheSystem.h" -#include #include "Application.h" #include "BeamData.h" #include "ContentManager.h" #include "ErrorUtils.h" -#include "GUI_LoadingWindow.h" #include "GUIManager.h" +#include "GUI_LoadingWindow.h" #include "GfxActor.h" #include "Language.h" #include "PlatformUtils.h" @@ -43,56 +42,26 @@ #include "Terrn2Fileformat.h" #include "Utils.h" +#include #include +#include #include #include #include #include -#include using namespace Ogre; using namespace RoR; -CacheEntry::CacheEntry() : - addtimestamp(0), - beamcount(0), - categoryid(0), - commandscount(0), - custom_particles(false), - customtach(false), - deleted(false), - driveable(0), // driveable = 0 = NOT_DRIVEABLE - enginetype('t'), // enginetype = t = truck is default - exhaustscount(0), - fileformatversion(0), - filetime(0), - fixescount(0), - flarescount(0), - flexbodiescount(0), - forwardcommands(false), - hasSubmeshs(false), - hydroscount(0), - importcommands(false), - loadmass(0), - maxrpm(0), - minrpm(0), - nodecount(0), - number(0), - numgears(0), - propscount(0), - propwheelcount(0), - rescuer(false), - rotatorscount(0), - shockcount(0), - soundsourcescount(0), - torque(0), - truckmass(0), - turbojetcount(0), - turbopropscount(0), - usagecounter(0), - version(0), - wheelcount(0), - wingscount(0) +CacheEntry::CacheEntry() + : addtimestamp(0), beamcount(0), categoryid(0), commandscount(0), custom_particles(false), customtach(false), deleted(false), + driveable(0), // driveable = 0 = NOT_DRIVEABLE + enginetype('t'), // enginetype = t = truck is default + exhaustscount(0), fileformatversion(0), filetime(0), fixescount(0), flarescount(0), flexbodiescount(0), + forwardcommands(false), hasSubmeshs(false), hydroscount(0), importcommands(false), loadmass(0), maxrpm(0), minrpm(0), + nodecount(0), number(0), numgears(0), propscount(0), propwheelcount(0), rescuer(false), rotatorscount(0), shockcount(0), + soundsourcescount(0), torque(0), truckmass(0), turbojetcount(0), turbopropscount(0), usagecounter(0), version(0), + wheelcount(0), wingscount(0) { } @@ -153,24 +122,23 @@ void CacheSystem::LoadModCache(CacheValidityState validity) RoR::Log("[RoR|ModCache] Cache loaded"); } -CacheEntry* CacheSystem::FindEntryByFilename(std::string filename) +CacheEntry *CacheSystem::FindEntryByFilename(std::string filename) { StringUtil::toLowerCase(filename); - for (CacheEntry& entry : m_entries) + for (CacheEntry &entry : m_entries) { - String fname = entry.fname; + String fname = entry.fname; String fname_without_uid = entry.fname_without_uid; StringUtil::toLowerCase(fname); StringUtil::toLowerCase(fname_without_uid); - if (fname == filename || fname_without_uid == filename) - return &entry; + if (fname == filename || fname_without_uid == filename) return &entry; } return nullptr; } void CacheSystem::UnloadActorFromMemory(std::string filename) { - CacheEntry* cache_entry = this->FindEntryByFilename(filename); + CacheEntry *cache_entry = this->FindEntryByFilename(filename); if (cache_entry != nullptr) { cache_entry->actor_def.reset(); @@ -205,17 +173,16 @@ CacheSystem::CacheValidityState CacheSystem::EvaluateCacheValidity() this->GenerateHashFromFilenames(); // First, open cache file and get hash for quick update check - std::ifstream ifs(this->GetCacheConfigFilename()); // TODO: Load using OGRE resource system ~ only_a_ptr, 10/2018 + std::ifstream ifs(this->GetCacheConfigFilename()); // TODO: Load using OGRE resource system ~ only_a_ptr, 10/2018 rapidjson::IStreamWrapper isw(ifs); - rapidjson::Document j_doc; + rapidjson::Document j_doc; j_doc.ParseStream(isw); - if (!j_doc.IsObject() || - !j_doc.HasMember("global_hash") || !j_doc["global_hash"].IsString() || - !j_doc.HasMember("format_version") ||!j_doc["format_version"].IsNumber() || - !j_doc.HasMember("entries") || !j_doc["entries"].IsArray()) + if (!j_doc.IsObject() || !j_doc.HasMember("global_hash") || !j_doc["global_hash"].IsString() || + !j_doc.HasMember("format_version") || !j_doc["format_version"].IsNumber() || !j_doc.HasMember("entries") || + !j_doc["entries"].IsArray()) { RoR::Log("[RoR|ModCache] Invalid or missing cache file"); - return CACHE_NEEDS_REBUILD; + return CACHE_NEEDS_REBUILD; } if (j_doc["format_version"].GetInt() != CACHE_FILE_FORMAT) @@ -246,22 +213,22 @@ CacheSystem::CacheValidityState CacheSystem::EvaluateCacheValidity() return CACHE_VALID; } -void CacheSystem::ImportEntryFromJson(rapidjson::Value& j_entry, CacheEntry & out_entry) +void CacheSystem::ImportEntryFromJson(rapidjson::Value &j_entry, CacheEntry &out_entry) { // Common details - out_entry.usagecounter = j_entry["usagecounter"].GetInt(); - out_entry.addtimestamp = j_entry["addtimestamp"].GetInt(); - out_entry.resource_bundle_type = j_entry["resource_bundle_type"].GetString(); - out_entry.resource_bundle_path = j_entry["resource_bundle_path"].GetString(); - out_entry.fpath = j_entry["fpath"].GetString(); - out_entry.fname = j_entry["fname"].GetString(); - out_entry.fname_without_uid = j_entry["fname_without_uid"].GetString(); - out_entry.fext = j_entry["fext"].GetString(); - out_entry.filetime = j_entry["filetime"].GetInt(); - out_entry.dname = j_entry["dname"].GetString(); - out_entry.uniqueid = j_entry["uniqueid"].GetString(); - out_entry.version = j_entry["version"].GetInt(); - out_entry.filecachename = j_entry["filecachename"].GetString(); + out_entry.usagecounter = j_entry["usagecounter"].GetInt(); + out_entry.addtimestamp = j_entry["addtimestamp"].GetInt(); + out_entry.resource_bundle_type = j_entry["resource_bundle_type"].GetString(); + out_entry.resource_bundle_path = j_entry["resource_bundle_path"].GetString(); + out_entry.fpath = j_entry["fpath"].GetString(); + out_entry.fname = j_entry["fname"].GetString(); + out_entry.fname_without_uid = j_entry["fname_without_uid"].GetString(); + out_entry.fext = j_entry["fext"].GetString(); + out_entry.filetime = j_entry["filetime"].GetInt(); + out_entry.dname = j_entry["dname"].GetString(); + out_entry.uniqueid = j_entry["uniqueid"].GetString(); + out_entry.version = j_entry["version"].GetInt(); + out_entry.filecachename = j_entry["filecachename"].GetString(); out_entry.guid = j_entry["guid"].GetString(); Ogre::StringUtil::trim(out_entry.guid); @@ -270,65 +237,65 @@ void CacheSystem::ImportEntryFromJson(rapidjson::Value& j_entry, CacheEntry & ou if (m_categories.find(category_id) != m_categories.end()) { out_entry.categoryname = m_categories[category_id]; - out_entry.categoryid = category_id; + out_entry.categoryid = category_id; } else { - out_entry.categoryid = -1; + out_entry.categoryid = -1; out_entry.categoryname = "Unsorted"; } - - // Common - Authors - for (rapidjson::Value& j_author: j_entry["authors"].GetArray()) + + // Common - Authors + for (rapidjson::Value &j_author : j_entry["authors"].GetArray()) { AuthorInfo author; - author.type = j_author["type"].GetString(); - author.name = j_author["name"].GetString(); - author.email = j_author["email"].GetString(); - author.id = j_author["id"].GetInt(); + author.type = j_author["type"].GetString(); + author.name = j_author["name"].GetString(); + author.email = j_author["email"].GetString(); + author.id = j_author["id"].GetInt(); out_entry.authors.push_back(author); } // Vehicle details - out_entry.description = j_entry["description"].GetString(); - out_entry.tags = j_entry["tags"].GetString(); + out_entry.description = j_entry["description"].GetString(); + out_entry.tags = j_entry["tags"].GetString(); out_entry.fileformatversion = j_entry["fileformatversion"].GetInt(); - out_entry.hasSubmeshs = j_entry["hasSubmeshs"].GetBool(); - out_entry.nodecount = j_entry["nodecount"].GetInt(); - out_entry.beamcount = j_entry["beamcount"].GetInt(); - out_entry.shockcount = j_entry["shockcount"].GetInt(); - out_entry.fixescount = j_entry["fixescount"].GetInt(); - out_entry.hydroscount = j_entry["hydroscount"].GetInt(); - out_entry.wheelcount = j_entry["wheelcount"].GetInt(); - out_entry.propwheelcount = j_entry["propwheelcount"].GetInt(); - out_entry.commandscount = j_entry["commandscount"].GetInt(); - out_entry.flarescount = j_entry["flarescount"].GetInt(); - out_entry.propscount = j_entry["propscount"].GetInt(); - out_entry.wingscount = j_entry["wingscount"].GetInt(); - out_entry.turbopropscount = j_entry["turbopropscount"].GetInt(); - out_entry.turbojetcount = j_entry["turbojetcount"].GetInt(); - out_entry.rotatorscount = j_entry["rotatorscount"].GetInt(); - out_entry.exhaustscount = j_entry["exhaustscount"].GetInt(); - out_entry.flexbodiescount = j_entry["flexbodiescount"].GetInt(); + out_entry.hasSubmeshs = j_entry["hasSubmeshs"].GetBool(); + out_entry.nodecount = j_entry["nodecount"].GetInt(); + out_entry.beamcount = j_entry["beamcount"].GetInt(); + out_entry.shockcount = j_entry["shockcount"].GetInt(); + out_entry.fixescount = j_entry["fixescount"].GetInt(); + out_entry.hydroscount = j_entry["hydroscount"].GetInt(); + out_entry.wheelcount = j_entry["wheelcount"].GetInt(); + out_entry.propwheelcount = j_entry["propwheelcount"].GetInt(); + out_entry.commandscount = j_entry["commandscount"].GetInt(); + out_entry.flarescount = j_entry["flarescount"].GetInt(); + out_entry.propscount = j_entry["propscount"].GetInt(); + out_entry.wingscount = j_entry["wingscount"].GetInt(); + out_entry.turbopropscount = j_entry["turbopropscount"].GetInt(); + out_entry.turbojetcount = j_entry["turbojetcount"].GetInt(); + out_entry.rotatorscount = j_entry["rotatorscount"].GetInt(); + out_entry.exhaustscount = j_entry["exhaustscount"].GetInt(); + out_entry.flexbodiescount = j_entry["flexbodiescount"].GetInt(); out_entry.soundsourcescount = j_entry["soundsourcescount"].GetInt(); - out_entry.truckmass = j_entry["truckmass"].GetFloat(); - out_entry.loadmass = j_entry["loadmass"].GetFloat(); - out_entry.minrpm = j_entry["minrpm"].GetFloat(); - out_entry.maxrpm = j_entry["maxrpm"].GetFloat(); - out_entry.torque = j_entry["torque"].GetFloat(); - out_entry.customtach = j_entry["customtach"].GetBool(); - out_entry.custom_particles = j_entry["custom_particles"].GetBool(); - out_entry.forwardcommands = j_entry["forwardcommands"].GetBool(); - out_entry.importcommands = j_entry["importcommands"].GetBool(); - out_entry.rescuer = j_entry["rescuer"].GetBool(); - out_entry.driveable = j_entry["driveable"].GetInt(); - out_entry.numgears = j_entry["numgears"].GetInt(); - out_entry.enginetype = static_cast(j_entry["enginetype"].GetInt()); + out_entry.truckmass = j_entry["truckmass"].GetFloat(); + out_entry.loadmass = j_entry["loadmass"].GetFloat(); + out_entry.minrpm = j_entry["minrpm"].GetFloat(); + out_entry.maxrpm = j_entry["maxrpm"].GetFloat(); + out_entry.torque = j_entry["torque"].GetFloat(); + out_entry.customtach = j_entry["customtach"].GetBool(); + out_entry.custom_particles = j_entry["custom_particles"].GetBool(); + out_entry.forwardcommands = j_entry["forwardcommands"].GetBool(); + out_entry.importcommands = j_entry["importcommands"].GetBool(); + out_entry.rescuer = j_entry["rescuer"].GetBool(); + out_entry.driveable = j_entry["driveable"].GetInt(); + out_entry.numgears = j_entry["numgears"].GetInt(); + out_entry.enginetype = static_cast(j_entry["enginetype"].GetInt()); // Vehicle 'section-configs' (aka Modules in RigDef namespace) - for (rapidjson::Value& j_module_name: j_entry["sectionconfigs"].GetArray()) + for (rapidjson::Value &j_module_name : j_entry["sectionconfigs"].GetArray()) { out_entry.sectionconfigs.push_back(j_module_name.GetString()); } @@ -339,9 +306,9 @@ void CacheSystem::LoadCacheFileJson() // Clear existing entries m_entries.clear(); - std::ifstream ifs(this->GetCacheConfigFilename()); // TODO: Load using OGRE resource system ~ only_a_ptr, 10/2018 + std::ifstream ifs(this->GetCacheConfigFilename()); // TODO: Load using OGRE resource system ~ only_a_ptr, 10/2018 rapidjson::IStreamWrapper isw(ifs); - rapidjson::Document j_doc; + rapidjson::Document j_doc; j_doc.ParseStream(isw); if (!j_doc.IsObject() || !j_doc.HasMember("entries") || !j_doc["entries"].IsArray()) @@ -350,7 +317,7 @@ void CacheSystem::LoadCacheFileJson() return; } - for (rapidjson::Value& j_entry: j_doc["entries"].GetArray()) + for (rapidjson::Value &j_entry : j_doc["entries"].GetArray()) { CacheEntry entry; this->ImportEntryFromJson(j_entry, entry); @@ -364,13 +331,10 @@ void CacheSystem::PruneCache() this->LoadCacheFileJson(); std::vector paths; - for (auto& entry : m_entries) + for (auto &entry : m_entries) { std::string fn = entry.resource_bundle_path; - if (entry.resource_bundle_type == "FileSystem") - { - fn = PathCombine(fn, entry.fname); - } + if (entry.resource_bundle_type == "FileSystem") { fn = PathCombine(fn, entry.fname); } if (!RoR::FileExists(fn.c_str()) || (entry.filetime != RoR::GetFileLastModifiedTime(fn))) { @@ -396,10 +360,9 @@ void CacheSystem::DetectDuplicates() { RoR::Log("[RoR|ModCache] Searching for duplicates ..."); std::map possible_duplicates; - for (int i=0; i " + m_entries[j].fpath + m_entries[j].fname); + LOG("- duplicate: " + m_entries[i].fpath + m_entries[i].fname + " <--> " + m_entries[j].fpath + + m_entries[j].fname); LOG(" - " + m_entries[j].resource_bundle_path); - int idx = m_entries[i].fpath.size() < m_entries[j].fpath.size() ? i : j; + int idx = m_entries[i].fpath.size() < m_entries[j].fpath.size() ? i : j; m_entries[idx].deleted = true; } else @@ -460,12 +419,11 @@ void CacheSystem::DetectDuplicates() } } -CacheEntry* CacheSystem::GetEntry(int modid) +CacheEntry *CacheSystem::GetEntry(int modid) { for (std::vector::iterator it = m_entries.begin(); it != m_entries.end(); it++) { - if (modid == it->number) - return &(*it); + if (modid == it->number) return &(*it); } return 0; } @@ -474,87 +432,86 @@ String CacheSystem::GetPrettyName(String fname) { for (std::vector::iterator it = m_entries.begin(); it != m_entries.end(); it++) { - if (fname == it->fname) - return it->dname; + if (fname == it->fname) return it->dname; } return ""; } -void CacheSystem::ExportEntryToJson(rapidjson::Value& j_entries, rapidjson::Document& j_doc, CacheEntry const & entry) +void CacheSystem::ExportEntryToJson(rapidjson::Value &j_entries, rapidjson::Document &j_doc, CacheEntry const &entry) { rapidjson::Value j_entry(rapidjson::kObjectType); // Common details - j_entry.AddMember("usagecounter", entry.usagecounter, j_doc.GetAllocator()); - j_entry.AddMember("addtimestamp", static_cast(entry.addtimestamp), j_doc.GetAllocator()); - j_entry.AddMember("resource_bundle_type", rapidjson::StringRef(entry.resource_bundle_type.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("resource_bundle_path", rapidjson::StringRef(entry.resource_bundle_path.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("fpath", rapidjson::StringRef(entry.fpath.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("fname", rapidjson::StringRef(entry.fname.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("fname_without_uid", rapidjson::StringRef(entry.fname_without_uid.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("fext", rapidjson::StringRef(entry.fext.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("filetime", static_cast(entry.filetime), j_doc.GetAllocator()); - j_entry.AddMember("dname", rapidjson::StringRef(entry.dname.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("categoryid", entry.categoryid, j_doc.GetAllocator()); - j_entry.AddMember("uniqueid", rapidjson::StringRef(entry.uniqueid.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("guid", rapidjson::StringRef(entry.guid.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("version", entry.version, j_doc.GetAllocator()); - j_entry.AddMember("filecachename", rapidjson::StringRef(entry.filecachename.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("usagecounter", entry.usagecounter, j_doc.GetAllocator()); + j_entry.AddMember("addtimestamp", static_cast(entry.addtimestamp), j_doc.GetAllocator()); + j_entry.AddMember("resource_bundle_type", rapidjson::StringRef(entry.resource_bundle_type.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("resource_bundle_path", rapidjson::StringRef(entry.resource_bundle_path.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("fpath", rapidjson::StringRef(entry.fpath.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("fname", rapidjson::StringRef(entry.fname.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("fname_without_uid", rapidjson::StringRef(entry.fname_without_uid.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("fext", rapidjson::StringRef(entry.fext.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("filetime", static_cast(entry.filetime), j_doc.GetAllocator()); + j_entry.AddMember("dname", rapidjson::StringRef(entry.dname.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("categoryid", entry.categoryid, j_doc.GetAllocator()); + j_entry.AddMember("uniqueid", rapidjson::StringRef(entry.uniqueid.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("guid", rapidjson::StringRef(entry.guid.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("version", entry.version, j_doc.GetAllocator()); + j_entry.AddMember("filecachename", rapidjson::StringRef(entry.filecachename.c_str()), j_doc.GetAllocator()); // Common - Authors rapidjson::Value j_authors(rapidjson::kArrayType); - for (AuthorInfo const& author: entry.authors) + for (AuthorInfo const &author : entry.authors) { rapidjson::Value j_author(rapidjson::kObjectType); - j_author.AddMember("type", rapidjson::StringRef(author.type.c_str()), j_doc.GetAllocator()); - j_author.AddMember("name", rapidjson::StringRef(author.name.c_str()), j_doc.GetAllocator()); - j_author.AddMember("email", rapidjson::StringRef(author.email.c_str()), j_doc.GetAllocator()); - j_author.AddMember("id", author.id, j_doc.GetAllocator()); + j_author.AddMember("type", rapidjson::StringRef(author.type.c_str()), j_doc.GetAllocator()); + j_author.AddMember("name", rapidjson::StringRef(author.name.c_str()), j_doc.GetAllocator()); + j_author.AddMember("email", rapidjson::StringRef(author.email.c_str()), j_doc.GetAllocator()); + j_author.AddMember("id", author.id, j_doc.GetAllocator()); j_authors.PushBack(j_author, j_doc.GetAllocator()); } j_entry.AddMember("authors", j_authors, j_doc.GetAllocator()); // Vehicle details - j_entry.AddMember("description", rapidjson::StringRef(entry.description.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("tags", rapidjson::StringRef(entry.tags.c_str()), j_doc.GetAllocator()); - j_entry.AddMember("fileformatversion", entry.fileformatversion, j_doc.GetAllocator()); - j_entry.AddMember("hasSubmeshs", entry.hasSubmeshs, j_doc.GetAllocator()); - j_entry.AddMember("nodecount", entry.nodecount, j_doc.GetAllocator()); - j_entry.AddMember("beamcount", entry.beamcount, j_doc.GetAllocator()); - j_entry.AddMember("shockcount", entry.shockcount, j_doc.GetAllocator()); - j_entry.AddMember("fixescount", entry.fixescount, j_doc.GetAllocator()); - j_entry.AddMember("hydroscount", entry.hydroscount, j_doc.GetAllocator()); - j_entry.AddMember("wheelcount", entry.wheelcount, j_doc.GetAllocator()); - j_entry.AddMember("propwheelcount", entry.propwheelcount, j_doc.GetAllocator()); - j_entry.AddMember("commandscount", entry.commandscount, j_doc.GetAllocator()); - j_entry.AddMember("flarescount", entry.flarescount, j_doc.GetAllocator()); - j_entry.AddMember("propscount", entry.propscount, j_doc.GetAllocator()); - j_entry.AddMember("wingscount", entry.wingscount, j_doc.GetAllocator()); - j_entry.AddMember("turbopropscount", entry.turbopropscount, j_doc.GetAllocator()); - j_entry.AddMember("turbojetcount", entry.turbojetcount, j_doc.GetAllocator()); - j_entry.AddMember("rotatorscount", entry.rotatorscount, j_doc.GetAllocator()); - j_entry.AddMember("exhaustscount", entry.exhaustscount, j_doc.GetAllocator()); - j_entry.AddMember("flexbodiescount", entry.flexbodiescount, j_doc.GetAllocator()); - j_entry.AddMember("soundsourcescount", entry.soundsourcescount, j_doc.GetAllocator()); - j_entry.AddMember("truckmass", entry.truckmass, j_doc.GetAllocator()); - j_entry.AddMember("loadmass", entry.loadmass, j_doc.GetAllocator()); - j_entry.AddMember("minrpm", entry.minrpm, j_doc.GetAllocator()); - j_entry.AddMember("maxrpm", entry.maxrpm, j_doc.GetAllocator()); - j_entry.AddMember("torque", entry.torque, j_doc.GetAllocator()); - j_entry.AddMember("customtach", entry.customtach, j_doc.GetAllocator()); - j_entry.AddMember("custom_particles", entry.custom_particles, j_doc.GetAllocator()); - j_entry.AddMember("forwardcommands", entry.forwardcommands, j_doc.GetAllocator()); - j_entry.AddMember("importcommands", entry.importcommands, j_doc.GetAllocator()); - j_entry.AddMember("rescuer", entry.rescuer, j_doc.GetAllocator()); - j_entry.AddMember("driveable", entry.driveable, j_doc.GetAllocator()); - j_entry.AddMember("numgears", entry.numgears, j_doc.GetAllocator()); - j_entry.AddMember("enginetype", entry.enginetype, j_doc.GetAllocator()); + j_entry.AddMember("description", rapidjson::StringRef(entry.description.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("tags", rapidjson::StringRef(entry.tags.c_str()), j_doc.GetAllocator()); + j_entry.AddMember("fileformatversion", entry.fileformatversion, j_doc.GetAllocator()); + j_entry.AddMember("hasSubmeshs", entry.hasSubmeshs, j_doc.GetAllocator()); + j_entry.AddMember("nodecount", entry.nodecount, j_doc.GetAllocator()); + j_entry.AddMember("beamcount", entry.beamcount, j_doc.GetAllocator()); + j_entry.AddMember("shockcount", entry.shockcount, j_doc.GetAllocator()); + j_entry.AddMember("fixescount", entry.fixescount, j_doc.GetAllocator()); + j_entry.AddMember("hydroscount", entry.hydroscount, j_doc.GetAllocator()); + j_entry.AddMember("wheelcount", entry.wheelcount, j_doc.GetAllocator()); + j_entry.AddMember("propwheelcount", entry.propwheelcount, j_doc.GetAllocator()); + j_entry.AddMember("commandscount", entry.commandscount, j_doc.GetAllocator()); + j_entry.AddMember("flarescount", entry.flarescount, j_doc.GetAllocator()); + j_entry.AddMember("propscount", entry.propscount, j_doc.GetAllocator()); + j_entry.AddMember("wingscount", entry.wingscount, j_doc.GetAllocator()); + j_entry.AddMember("turbopropscount", entry.turbopropscount, j_doc.GetAllocator()); + j_entry.AddMember("turbojetcount", entry.turbojetcount, j_doc.GetAllocator()); + j_entry.AddMember("rotatorscount", entry.rotatorscount, j_doc.GetAllocator()); + j_entry.AddMember("exhaustscount", entry.exhaustscount, j_doc.GetAllocator()); + j_entry.AddMember("flexbodiescount", entry.flexbodiescount, j_doc.GetAllocator()); + j_entry.AddMember("soundsourcescount", entry.soundsourcescount, j_doc.GetAllocator()); + j_entry.AddMember("truckmass", entry.truckmass, j_doc.GetAllocator()); + j_entry.AddMember("loadmass", entry.loadmass, j_doc.GetAllocator()); + j_entry.AddMember("minrpm", entry.minrpm, j_doc.GetAllocator()); + j_entry.AddMember("maxrpm", entry.maxrpm, j_doc.GetAllocator()); + j_entry.AddMember("torque", entry.torque, j_doc.GetAllocator()); + j_entry.AddMember("customtach", entry.customtach, j_doc.GetAllocator()); + j_entry.AddMember("custom_particles", entry.custom_particles, j_doc.GetAllocator()); + j_entry.AddMember("forwardcommands", entry.forwardcommands, j_doc.GetAllocator()); + j_entry.AddMember("importcommands", entry.importcommands, j_doc.GetAllocator()); + j_entry.AddMember("rescuer", entry.rescuer, j_doc.GetAllocator()); + j_entry.AddMember("driveable", entry.driveable, j_doc.GetAllocator()); + j_entry.AddMember("numgears", entry.numgears, j_doc.GetAllocator()); + j_entry.AddMember("enginetype", entry.enginetype, j_doc.GetAllocator()); // Vehicle 'section-configs' (aka Modules in RigDef namespace) rapidjson::Value j_sectionconfigs(rapidjson::kArrayType); - for (std::string const & module_name: entry.sectionconfigs) + for (std::string const &module_name : entry.sectionconfigs) { j_sectionconfigs.PushBack(rapidjson::StringRef(module_name.c_str()), j_doc.GetAllocator()); } @@ -574,28 +531,23 @@ void CacheSystem::WriteCacheFileJson() // Entries rapidjson::Value j_entries(rapidjson::kArrayType); - for (CacheEntry const& entry : m_entries) + for (CacheEntry const &entry : m_entries) { - if (!entry.deleted) - { - this->ExportEntryToJson(j_entries, j_doc, entry); - } + if (!entry.deleted) { this->ExportEntryToJson(j_entries, j_doc, entry); } } j_doc.AddMember("entries", j_entries, j_doc.GetAllocator()); // Write to file String path = GetCacheConfigFilename(); - LOG("writing cache to file ("+path+")..."); + LOG("writing cache to file (" + path + ")..."); - std::ofstream ofs(path); + std::ofstream ofs(path); rapidjson::OStreamWrapper j_ofs(ofs); - rapidjson::Writer, rapidjson::UTF8<>, rapidjson::CrtAllocator, - rapidjson::kWriteNanAndInfFlag> j_writer(j_ofs); + rapidjson::Writer, rapidjson::UTF8<>, rapidjson::CrtAllocator, + rapidjson::kWriteNanAndInfFlag> + j_writer(j_ofs); const bool written_ok = j_doc.Accept(j_writer); - if (written_ok) - { - RoR::LogFormat("[RoR|ModCache] File '%s' written OK", path.c_str()); - } + if (written_ok) { RoR::LogFormat("[RoR|ModCache] File '%s' written OK", path.c_str()); } else { RoR::LogFormat("[RoR|ModCache] Error writing '%s'", path.c_str()); @@ -605,7 +557,7 @@ void CacheSystem::WriteCacheFileJson() void CacheSystem::ClearCache() { std::remove(this->GetCacheConfigFilename().c_str()); - for (auto& entry : m_entries) + for (auto &entry : m_entries) { String group = entry.resource_group; if (!group.empty()) @@ -629,8 +581,7 @@ Ogre::String CacheSystem::StripUIDfromString(Ogre::String uidstr) Ogre::String CacheSystem::StripSHA1fromString(Ogre::String sha1str) { size_t pos = sha1str.find_first_of("-_"); - if (pos != String::npos && pos >= 20) - return sha1str.substr(pos + 1, sha1str.length() - pos); + if (pos != String::npos && pos >= 20) return sha1str.substr(pos + 1, sha1str.length() - pos); return sha1str; } @@ -639,8 +590,9 @@ void CacheSystem::AddFile(String group, Ogre::FileInfo f, String ext) String type = f.archive ? f.archive->getType() : "FileSystem"; String path = f.archive ? f.archive->getName() : ""; - if (std::find_if(m_entries.begin(), m_entries.end(), [&](CacheEntry& e) - { return !e.deleted && e.fname == f.filename && e.resource_bundle_path == path; }) != m_entries.end()) + if (std::find_if(m_entries.begin(), m_entries.end(), [&](CacheEntry &e) { + return !e.deleted && e.fname == f.filename && e.resource_bundle_path == path; + }) != m_entries.end()) return; RoR::LogFormat("[RoR|CacheSystem] Preparing to add file '%f'", f.filename.c_str()); @@ -659,13 +611,13 @@ void CacheSystem::AddFile(String group, Ogre::FileInfo f, String ext) else if (ext == "skin") { auto new_skins = RoR::SkinParser::ParseSkins(ds); - for (auto skin_def: new_skins) + for (auto skin_def : new_skins) { CacheEntry entry; if (!skin_def->author_name.empty()) { AuthorInfo a; - a.id = skin_def->author_id; + a.id = skin_def->author_id; a.name = skin_def->author_name; entry.authors.push_back(a); } @@ -685,37 +637,34 @@ void CacheSystem::AddFile(String group, Ogre::FileInfo f, String ext) FillTruckDetailInfo(new_entries.back(), ds, f.filename, group); } - for (auto& entry: new_entries) + for (auto &entry : new_entries) { Ogre::StringUtil::toLowerCase(entry.guid); // Important for comparsion - entry.fpath = f.path; - entry.fname = f.filename; + entry.fpath = f.path; + entry.fname = f.filename; entry.fname_without_uid = StripUIDfromString(f.filename); - entry.fext = ext; - if (type == "Zip") - { - entry.filetime = RoR::GetFileLastModifiedTime(path); - } + entry.fext = ext; + if (type == "Zip") { entry.filetime = RoR::GetFileLastModifiedTime(path); } else { entry.filetime = RoR::GetFileLastModifiedTime(PathCombine(path, f.filename)); } entry.resource_bundle_type = type; entry.resource_bundle_path = path; - entry.number = static_cast(m_entries.size() + 1); // Let's number mods from 1 - entry.addtimestamp = m_update_time; + entry.number = static_cast(m_entries.size() + 1); // Let's number mods from 1 + entry.addtimestamp = m_update_time; this->GenerateFileCache(entry, group); m_entries.push_back(entry); } } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - RoR::LogFormat("[RoR|CacheSystem] Error processing file '%s', message :%s", - f.filename.c_str(), e.getFullDescription().c_str()); + RoR::LogFormat("[RoR|CacheSystem] Error processing file '%s', message :%s", f.filename.c_str(), + e.getFullDescription().c_str()); } } -void CacheSystem::FillTruckDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr stream, String file_name, String group) +void CacheSystem::FillTruckDetailInfo(CacheEntry &entry, Ogre::DataStreamPtr stream, String file_name, String group) { /* LOAD AND PARSE THE VEHICLE */ RigDef::Parser parser; @@ -735,21 +684,13 @@ void CacheSystem::FillTruckDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr str { switch (iter->type) { - case (RigDef::Parser::Message::TYPE_FATAL_ERROR): - report << "FATAL_ERROR"; - break; + case (RigDef::Parser::Message::TYPE_FATAL_ERROR): report << "FATAL_ERROR"; break; - case (RigDef::Parser::Message::TYPE_ERROR): - report << "ERROR"; - break; + case (RigDef::Parser::Message::TYPE_ERROR): report << "ERROR"; break; - case (RigDef::Parser::Message::TYPE_WARNING): - report << "WARNING"; - break; + case (RigDef::Parser::Message::TYPE_WARNING): report << "WARNING"; break; - default: - report << "INFO"; - break; + default: report << "INFO"; break; } report << " (Section " << RigDef::File::SectionToString(iter->section) << ")" << std::endl; report << "\tLine (# " << iter->line_number << "): " << iter->line << std::endl; @@ -786,9 +727,9 @@ void CacheSystem::FillTruckDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr str { AuthorInfo author; author.email = author_itor->email; - author.id = (author_itor->_has_forum_account) ? static_cast(author_itor->forum_account_id) : -1; - author.name = author_itor->name; - author.type = author_itor->type; + author.id = (author_itor->_has_forum_account) ? static_cast(author_itor->forum_account_id) : -1; + author.name = author_itor->name; + author.type = author_itor->type; entry.authors.push_back(author); } @@ -805,30 +746,27 @@ void CacheSystem::FillTruckDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr str if (def->root_module->engine != nullptr) { std::shared_ptr engine = def->root_module->engine; - entry.numgears = static_cast(engine->gear_ratios.size()); - entry.minrpm = engine->shift_down_rpm; - entry.maxrpm = engine->shift_up_rpm; - entry.torque = engine->torque; - entry.enginetype = 't'; /* Truck (default) */ - if (def->root_module->engoption != nullptr - && def->root_module->engoption->type == RigDef::Engoption::ENGINE_TYPE_c_CAR) - { - entry.enginetype = 'c'; - } + entry.numgears = static_cast(engine->gear_ratios.size()); + entry.minrpm = engine->shift_down_rpm; + entry.maxrpm = engine->shift_up_rpm; + entry.torque = engine->torque; + entry.enginetype = 't'; /* Truck (default) */ + if (def->root_module->engoption != nullptr && def->root_module->engoption->type == RigDef::Engoption::ENGINE_TYPE_c_CAR) + { entry.enginetype = 'c'; } } /* File info */ if (def->file_info != nullptr) { - entry.uniqueid = def->file_info->unique_id; + entry.uniqueid = def->file_info->unique_id; entry.categoryid = static_cast(def->file_info->category_id); - entry.version = static_cast(def->file_info->file_version); + entry.version = static_cast(def->file_info->file_version); } else { - entry.uniqueid = "-1"; + entry.uniqueid = "-1"; entry.categoryid = -1; - entry.version = -1; + entry.version = -1; } /* Vehicle type */ @@ -836,34 +774,30 @@ void CacheSystem::FillTruckDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr str This is a temporary solution which has undefined results for mixed-type vehicles. */ int vehicle_type = NOT_DRIVEABLE; - module_itor = def->user_modules.begin(); + module_itor = def->user_modules.begin(); for (; module_itor != def->user_modules.end(); module_itor++) { - if (module_itor->second->engine != nullptr) - { - vehicle_type = TRUCK; - } + if (module_itor->second->engine != nullptr) { vehicle_type = TRUCK; } else if (module_itor->second->screwprops.size() > 0) { vehicle_type = BOAT; } /* Note: Sections 'turboprops' and 'turboprops2' are unified in TruckParser2013 */ - else if (module_itor->second->turbojets.size() > 0 || module_itor->second->pistonprops.size() > 0 || module_itor->second->turboprops_2.size() > 0) + else if (module_itor->second->turbojets.size() > 0 || module_itor->second->pistonprops.size() > 0 || + module_itor->second->turboprops_2.size() > 0) { vehicle_type = AIRPLANE; } } /* Root module */ - if (def->root_module->engine != nullptr) - { - vehicle_type = TRUCK; - } + if (def->root_module->engine != nullptr) { vehicle_type = TRUCK; } else if (def->root_module->screwprops.size() > 0) { vehicle_type = BOAT; } /* Note: Sections 'turboprops' and 'turboprops2' are unified in TruckParser2013 */ - else if (def->root_module->turbojets.size() > 0 || def->root_module->pistonprops.size() > 0 || def->root_module->turboprops_2.size() > 0) + else if (def->root_module->turbojets.size() > 0 || def->root_module->pistonprops.size() > 0 || + def->root_module->turboprops_2.size() > 0) { vehicle_type = AIRPLANE; } @@ -871,83 +805,73 @@ void CacheSystem::FillTruckDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr str if (def->root_module->globals) { entry.truckmass = def->root_module->globals->dry_mass; - entry.loadmass = def->root_module->globals->cargo_mass; + entry.loadmass = def->root_module->globals->cargo_mass; } - - entry.forwardcommands = def->forward_commands; - entry.importcommands = def->import_commands; - entry.rescuer = def->rescuer; - entry.guid = def->guid; + + entry.forwardcommands = def->forward_commands; + entry.importcommands = def->import_commands; + entry.rescuer = def->rescuer; + entry.guid = def->guid; entry.fileformatversion = def->file_format_version; - entry.hasSubmeshs = static_cast(def->root_module->submeshes.size() > 0); - entry.nodecount = static_cast(def->root_module->nodes.size()); - entry.beamcount = static_cast(def->root_module->beams.size()); - entry.shockcount = static_cast(def->root_module->shocks.size() + def->root_module->shocks_2.size()); - entry.fixescount = static_cast(def->root_module->fixes.size()); - entry.hydroscount = static_cast(def->root_module->hydros.size()); - entry.driveable = vehicle_type; - entry.commandscount = static_cast(def->root_module->commands_2.size()); - entry.flarescount = static_cast(def->root_module->flares_2.size()); - entry.propscount = static_cast(def->root_module->props.size()); - entry.wingscount = static_cast(def->root_module->wings.size()); - entry.turbopropscount = static_cast(def->root_module->turboprops_2.size()); - entry.rotatorscount = static_cast(def->root_module->rotators.size() + def->root_module->rotators_2.size()); - entry.exhaustscount = static_cast(def->root_module->exhausts.size()); - entry.custom_particles = def->root_module->particles.size() > 0; - entry.turbojetcount = static_cast(def->root_module->turbojets.size()); - entry.flexbodiescount = static_cast(def->root_module->flexbodies.size()); + entry.hasSubmeshs = static_cast(def->root_module->submeshes.size() > 0); + entry.nodecount = static_cast(def->root_module->nodes.size()); + entry.beamcount = static_cast(def->root_module->beams.size()); + entry.shockcount = static_cast(def->root_module->shocks.size() + def->root_module->shocks_2.size()); + entry.fixescount = static_cast(def->root_module->fixes.size()); + entry.hydroscount = static_cast(def->root_module->hydros.size()); + entry.driveable = vehicle_type; + entry.commandscount = static_cast(def->root_module->commands_2.size()); + entry.flarescount = static_cast(def->root_module->flares_2.size()); + entry.propscount = static_cast(def->root_module->props.size()); + entry.wingscount = static_cast(def->root_module->wings.size()); + entry.turbopropscount = static_cast(def->root_module->turboprops_2.size()); + entry.rotatorscount = static_cast(def->root_module->rotators.size() + def->root_module->rotators_2.size()); + entry.exhaustscount = static_cast(def->root_module->exhausts.size()); + entry.custom_particles = def->root_module->particles.size() > 0; + entry.turbojetcount = static_cast(def->root_module->turbojets.size()); + entry.flexbodiescount = static_cast(def->root_module->flexbodies.size()); entry.soundsourcescount = static_cast(def->root_module->soundsources.size() + def->root_module->soundsources.size()); - entry.wheelcount = 0; + entry.wheelcount = 0; entry.propwheelcount = 0; - for (const auto& w : def->root_module->wheels) + for (const auto &w : def->root_module->wheels) { entry.wheelcount++; - if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) - entry.propwheelcount++; + if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) entry.propwheelcount++; } - for (const auto& w : def->root_module->wheels_2) + for (const auto &w : def->root_module->wheels_2) { entry.wheelcount++; - if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) - entry.propwheelcount++; + if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) entry.propwheelcount++; } - for (const auto& w : def->root_module->mesh_wheels) + for (const auto &w : def->root_module->mesh_wheels) { entry.wheelcount++; - if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) - entry.propwheelcount++; + if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) entry.propwheelcount++; } - for (const auto& w : def->root_module->flex_body_wheels) + for (const auto &w : def->root_module->flex_body_wheels) { entry.wheelcount++; - if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) - entry.propwheelcount++; + if (w.propulsion != RigDef::Wheels::PROPULSION_NONE) entry.propwheelcount++; } - if (!def->root_module->axles.empty()) - { - entry.propwheelcount = static_cast(def->root_module->axles.size() * 2); - } + if (!def->root_module->axles.empty()) { entry.propwheelcount = static_cast(def->root_module->axles.size() * 2); } /* NOTE: std::shared_ptr cleans everything up. */ } Ogre::String detectMiniType(String filename, String group) { - if (ResourceGroupManager::getSingleton().resourceExists(group, filename + "dds")) - return "dds"; + if (ResourceGroupManager::getSingleton().resourceExists(group, filename + "dds")) return "dds"; - if (ResourceGroupManager::getSingleton().resourceExists(group, filename + "png")) - return "png"; + if (ResourceGroupManager::getSingleton().resourceExists(group, filename + "png")) return "png"; - if (ResourceGroupManager::getSingleton().resourceExists(group, filename + "jpg")) - return "jpg"; + if (ResourceGroupManager::getSingleton().resourceExists(group, filename + "jpg")) return "jpg"; return ""; } -void CacheSystem::RemoveFileCache(CacheEntry& entry) +void CacheSystem::RemoveFileCache(CacheEntry &entry) { if (!entry.filecachename.empty()) { @@ -956,10 +880,9 @@ void CacheSystem::RemoveFileCache(CacheEntry& entry) } } -void CacheSystem::GenerateFileCache(CacheEntry& entry, String group) +void CacheSystem::GenerateFileCache(CacheEntry &entry, String group) { - if (entry.fname.empty()) - return; + if (entry.fname.empty()) return; String bundle_basename, bundle_path; StringUtil::splitFilename(entry.resource_bundle_path, bundle_basename, bundle_path); @@ -968,8 +891,7 @@ void CacheSystem::GenerateFileCache(CacheEntry& entry, String group) String dst_path; if (entry.fext == "skin") { - if (entry.skin_def->thumbnail.empty()) - return; + if (entry.skin_def->thumbnail.empty()) return; src_path = entry.skin_def->thumbnail; String mini_fbase, minitype; StringUtil::splitBaseFilename(entry.skin_def->thumbnail, mini_fbase, minitype); @@ -979,27 +901,26 @@ void CacheSystem::GenerateFileCache(CacheEntry& entry, String group) { String fbase, fext; StringUtil::splitBaseFilename(entry.fname, fbase, fext); - String minifn = fbase + "-mini."; + String minifn = fbase + "-mini."; String minitype = detectMiniType(minifn, group); - if (minitype.empty()) - return; + if (minitype.empty()) return; src_path = minifn + minitype; dst_path = bundle_basename + "_" + entry.fname + ".mini." + minitype; } try { - DataStreamPtr src_ds = ResourceGroupManager::getSingleton().openResource(src_path, group); - DataStreamPtr dst_ds = ResourceGroupManager::getSingleton().createResource(dst_path, RGN_CACHE, true); + DataStreamPtr src_ds = ResourceGroupManager::getSingleton().openResource(src_path, group); + DataStreamPtr dst_ds = ResourceGroupManager::getSingleton().createResource(dst_path, RGN_CACHE, true); std::vector buf(src_ds->size()); - size_t read = src_ds->read(buf.data(), src_ds->size()); + size_t read = src_ds->read(buf.data(), src_ds->size()); if (read > 0) { - dst_ds->write(buf.data(), read); + dst_ds->write(buf.data(), read); entry.filecachename = dst_path; } } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { LOG("error while generating file cache: " + e.getFullDescription()); } @@ -1009,17 +930,17 @@ void CacheSystem::GenerateFileCache(CacheEntry& entry, String group) void CacheSystem::ParseZipArchives(String group) { - auto files = ResourceGroupManager::getSingleton().findResourceFileInfo(group, "*.zip"); + auto files = ResourceGroupManager::getSingleton().findResourceFileInfo(group, "*.zip"); auto skinzips = ResourceGroupManager::getSingleton().findResourceFileInfo(group, "*.skinzip"); - for (const auto& skinzip : *skinzips) + for (const auto &skinzip : *skinzips) files->push_back(skinzip); int i = 0, count = static_cast(files->size()); - for (const auto& file : *files) + for (const auto &file : *files) { - int progress = ((float)i++ / (float)count) * 100; - UTFString tmp = _L("Loading zips in group ") + ANSI_TO_UTF(group) + L"\n" + - ANSI_TO_UTF(file.filename) + L"\n" + ANSI_TO_UTF(TOSTRING(i)) + L"/" + ANSI_TO_UTF(TOSTRING(count)); + int progress = ((float)i++ / (float)count) * 100; + UTFString tmp = _L("Loading zips in group ") + ANSI_TO_UTF(group) + L"\n" + ANSI_TO_UTF(file.filename) + L"\n" + + ANSI_TO_UTF(TOSTRING(i)) + L"/" + ANSI_TO_UTF(TOSTRING(count)); RoR::App::GetGuiManager()->GetLoadingWindow()->setProgress(progress, tmp, false); String path = PathCombine(file.archive->getName(), file.filename); @@ -1038,12 +959,9 @@ void CacheSystem::ParseSingleZip(String path) try { ResourceGroupManager::getSingleton().addResourceLocation(path, "Zip", RGN_TEMP); - if (ParseKnownFiles(RGN_TEMP)) - { - LOG("No usable content in: '" + path + "'"); - } + if (ParseKnownFiles(RGN_TEMP)) { LOG("No usable content in: '" + path + "'"); } } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { LOG("Error while opening archive: '" + path + "': " + e.getFullDescription()); } @@ -1058,7 +976,7 @@ bool CacheSystem::ParseKnownFiles(Ogre::String group) for (auto ext : m_known_extensions) { auto files = ResourceGroupManager::getSingleton().findResourceFileInfo(group, "*." + ext); - for (const auto& file : *files) + for (const auto &file : *files) { this->AddFile(group, file, ext); empty = false; @@ -1070,19 +988,19 @@ bool CacheSystem::ParseKnownFiles(Ogre::String group) void CacheSystem::GenerateHashFromFilenames() { std::string filenames = App::GetContentManager()->ListAllUserContent(); - m_filenames_hash = HashData(filenames.c_str(), static_cast(filenames.size())); + m_filenames_hash = HashData(filenames.c_str(), static_cast(filenames.size())); } -void CacheSystem::FillTerrainDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr ds, Ogre::String fname) +void CacheSystem::FillTerrainDetailInfo(CacheEntry &entry, Ogre::DataStreamPtr ds, Ogre::String fname) { - Terrn2Def def; + Terrn2Def def; Terrn2Parser parser; parser.LoadTerrn2(def, ds); - for (Terrn2Author& author : def.authors) + for (Terrn2Author &author : def.authors) { AuthorInfo a; - a.id = -1; + a.id = -1; a.name = author.name; a.type = author.type; entry.authors.push_back(a); @@ -1094,13 +1012,13 @@ void CacheSystem::FillTerrainDetailInfo(CacheEntry& entry, Ogre::DataStreamPtr d entry.version = def.version; } -bool CacheSystem::CheckResourceLoaded(Ogre::String & filename) +bool CacheSystem::CheckResourceLoaded(Ogre::String &filename) { Ogre::String group = ""; return CheckResourceLoaded(filename, group); } -bool CacheSystem::CheckResourceLoaded(Ogre::String & filename, Ogre::String& group) +bool CacheSystem::CheckResourceLoaded(Ogre::String &filename, Ogre::String &group) { // check if we already loaded it via ogre ... if (ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(filename)) @@ -1109,10 +1027,10 @@ bool CacheSystem::CheckResourceLoaded(Ogre::String & filename, Ogre::String& gro return true; } - for (auto& entry : m_entries) + for (auto &entry : m_entries) { // case insensitive comparison - String fname = entry.fname; + String fname = entry.fname; String fname_without_uid = entry.fname_without_uid; StringUtil::toLowerCase(fname); StringUtil::toLowerCase(filename); @@ -1122,7 +1040,7 @@ bool CacheSystem::CheckResourceLoaded(Ogre::String & filename, Ogre::String& gro // we found the file, load it LoadResource(entry); filename = entry.fname; - group = entry.resource_group; + group = entry.resource_group; return !group.empty() && ResourceGroupManager::getSingleton().resourceExists(group, filename); } } @@ -1130,7 +1048,7 @@ bool CacheSystem::CheckResourceLoaded(Ogre::String & filename, Ogre::String& gro return false; } -void CacheSystem::LoadResource(CacheEntry& t) +void CacheSystem::LoadResource(CacheEntry &t) { if (!m_loaded_resource_bundles[t.resource_bundle_path].empty()) { @@ -1139,7 +1057,7 @@ void CacheSystem::LoadResource(CacheEntry& t) } static int rg_counter = 0; - String group = std::to_string(rg_counter++) + "-" + t.fname; + String group = std::to_string(rg_counter++) + "-" + t.fname; try { @@ -1171,72 +1089,60 @@ void CacheSystem::LoadResource(CacheEntry& t) ResourceGroupManager::getSingleton().initialiseResourceGroup(group); - t.resource_group = group; + t.resource_group = group; m_loaded_resource_bundles[t.resource_bundle_path] = group; } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - RoR::LogFormat("[RoR] Error while loading '%s', message: %s", - t.resource_bundle_path.c_str(), e.getFullDescription().c_str()); + RoR::LogFormat("[RoR] Error while loading '%s', message: %s", t.resource_bundle_path.c_str(), + e.getFullDescription().c_str()); if (ResourceGroupManager::getSingleton().resourceGroupExists(group)) - { - ResourceGroupManager::getSingleton().destroyResourceGroup(group); - } + { ResourceGroupManager::getSingleton().destroyResourceGroup(group); } } } -const std::vector CacheSystem::GetUsableSkins(std::string const & guid) const +const std::vector CacheSystem::GetUsableSkins(std::string const &guid) const { - if (guid.empty()) - return std::vector(); + if (guid.empty()) return std::vector(); std::vector result; - for (CacheEntry const& entry: m_entries) + for (CacheEntry const &entry : m_entries) { - if (entry.guid == guid && entry.fext == "skin") - { - result.push_back(entry); - } + if (entry.guid == guid && entry.fext == "skin") { result.push_back(entry); } } return result; } -CacheEntry* CacheSystem::FetchSkinByName(std::string const & skin_name) +CacheEntry *CacheSystem::FetchSkinByName(std::string const &skin_name) { - for (CacheEntry & entry: m_entries) + for (CacheEntry &entry : m_entries) { - if (entry.dname == skin_name && entry.fext == "skin") - { - return &entry; - } + if (entry.dname == skin_name && entry.fext == "skin") { return &entry; } } return nullptr; } -std::shared_ptr CacheSystem::FetchSkinDef(CacheEntry* cache_entry) +std::shared_ptr CacheSystem::FetchSkinDef(CacheEntry *cache_entry) { if (cache_entry->skin_def != nullptr) // If already parsed, re-use - { - return cache_entry->skin_def; - } + { return cache_entry->skin_def; } try { App::GetCacheSystem()->LoadResource(*cache_entry); // Load if not already - Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton() - .openResource(cache_entry->fname, cache_entry->resource_group); + Ogre::DataStreamPtr ds = + Ogre::ResourceGroupManager::getSingleton().openResource(cache_entry->fname, cache_entry->resource_group); auto new_skins = RoR::SkinParser::ParseSkins(ds); // Load the '.skin' file - for (auto def: new_skins) + for (auto def : new_skins) { - for (CacheEntry& e: m_entries) + for (CacheEntry &e : m_entries) { - if (e.resource_bundle_path == cache_entry->resource_bundle_path - && e.resource_bundle_type == cache_entry->resource_bundle_type - && e.fname == cache_entry->fname - && e.dname == def->name) + if (e.resource_bundle_path == cache_entry->resource_bundle_path && + e.resource_bundle_type == cache_entry->resource_bundle_type && e.fname == cache_entry->fname && + e.dname == def->name) { - e.skin_def = def; + e.skin_def = def; e.resource_group = cache_entry->resource_group; } } @@ -1244,18 +1150,15 @@ std::shared_ptr CacheSystem::FetchSkinDef(CacheEntry* cache_entry) if (cache_entry->skin_def == nullptr) { - RoR::LogFormat("Definition of skin '%s' was not found in file '%s'", - cache_entry->dname.c_str(), cache_entry->fname.c_str()); + RoR::LogFormat("Definition of skin '%s' was not found in file '%s'", cache_entry->dname.c_str(), + cache_entry->fname.c_str()); } return cache_entry->skin_def; } - catch (Ogre::Exception& oex) + catch (Ogre::Exception &oex) { - RoR::LogFormat("[RoR] Error loading skin file '%s', message: %s", - cache_entry->fname.c_str(), oex.getFullDescription().c_str()); + RoR::LogFormat("[RoR] Error loading skin file '%s', message: %s", cache_entry->fname.c_str(), + oex.getFullDescription().c_str()); return nullptr; } } - - - diff --git a/source/main/resources/CacheSystem.h b/source/main/resources/CacheSystem.h index c5244c5d81..dd85b00ea6 100644 --- a/source/main/resources/CacheSystem.h +++ b/source/main/resources/CacheSystem.h @@ -26,8 +26,8 @@ #pragma once -#include "RoRPrerequisites.h" #include "RigDef_File.h" +#include "RoRPrerequisites.h" #include @@ -36,7 +36,7 @@ struct AuthorInfo { - int id; + int id; Ogre::String type; Ogre::String name; Ogre::String email; @@ -45,35 +45,34 @@ struct AuthorInfo class CacheEntry { -public: - + public: /** default constructor resets the data. */ CacheEntry(); - Ogre::String fpath; //!< filepath relative to the .zip file - Ogre::String fname; //!< filename - Ogre::String fname_without_uid; //!< filename - Ogre::String dname; //!< name parsed from the file + Ogre::String fpath; //!< filepath relative to the .zip file + Ogre::String fname; //!< filename + Ogre::String fname_without_uid; //!< filename + Ogre::String dname; //!< name parsed from the file - int categoryid; //!< category id - Ogre::String categoryname; //!< category name + int categoryid; //!< category id + Ogre::String categoryname; //!< category name - std::time_t addtimestamp; //!< timestamp when this file was added to the cache + std::time_t addtimestamp; //!< timestamp when this file was added to the cache - Ogre::String uniqueid; //!< file's unique id - Ogre::String guid; //!< global unique id - int version; //!< file's version - Ogre::String fext; //!< file's extension - std::string resource_bundle_type; //!< Archive type recognized by OGRE resource system: 'FileSystem' or 'Zip' - std::string resource_bundle_path; //!< Path of ZIP or directory which contains the media. - int number; //!< Sequential number, assigned internally, used by Selector-GUI - std::time_t filetime; //!< filetime - bool deleted; //!< is this mod deleted? - int usagecounter; //!< how much it was used already - std::vector authors; //!< authors - Ogre::String filecachename; //!< preview image filename + Ogre::String uniqueid; //!< file's unique id + Ogre::String guid; //!< global unique id + int version; //!< file's version + Ogre::String fext; //!< file's extension + std::string resource_bundle_type; //!< Archive type recognized by OGRE resource system: 'FileSystem' or 'Zip' + std::string resource_bundle_path; //!< Path of ZIP or directory which contains the media. + int number; //!< Sequential number, assigned internally, used by Selector-GUI + std::time_t filetime; //!< filetime + bool deleted; //!< is this mod deleted? + int usagecounter; //!< how much it was used already + std::vector authors; //!< authors + Ogre::String filecachename; //!< preview image filename - Ogre::String resource_group; //!< the name of the resource group this entry belongs to + Ogre::String resource_group; //!< the name of the resource group this entry belongs to std::shared_ptr actor_def; //!< Cached actor definition (aka truckfile) after first spawn std::shared_ptr skin_def; //!< Cached skin info, added on first use or during cache rebuild @@ -81,40 +80,40 @@ class CacheEntry // following all TRUCK detail information: Ogre::String description; Ogre::String tags; - int fileformatversion; - bool hasSubmeshs; - int nodecount; - int beamcount; - int shockcount; - int fixescount; - int hydroscount; - int wheelcount; - int propwheelcount; - int commandscount; - int flarescount; - int propscount; - int wingscount; - int turbopropscount; - int turbojetcount; - int rotatorscount; - int exhaustscount; - int flexbodiescount; - int soundsourcescount; + int fileformatversion; + bool hasSubmeshs; + int nodecount; + int beamcount; + int shockcount; + int fixescount; + int hydroscount; + int wheelcount; + int propwheelcount; + int commandscount; + int flarescount; + int propscount; + int wingscount; + int turbopropscount; + int turbojetcount; + int rotatorscount; + int exhaustscount; + int flexbodiescount; + int soundsourcescount; float truckmass; float loadmass; float minrpm; float maxrpm; float torque; - bool customtach; - bool custom_particles; - bool forwardcommands; - bool importcommands; - bool rescuer; - - int driveable; - int numgears; - char enginetype; + bool customtach; + bool custom_particles; + bool forwardcommands; + bool importcommands; + bool rescuer; + + int driveable; + int numgears; + char enginetype; std::vector sectionconfigs; }; @@ -124,12 +123,12 @@ class CacheEntry /// HOW IT WORKS: /// For each recognized resource type (vehicle, terrain, skin...) an instance of 'CacheEntry' is created. /// These entries are persisted in file CACHE_FILE (see above) -/// Associated media live in a "resource bundle" (ZIP archive or subdirectory) in content directories (ROR_HOME/vehicles, ROR_HOME/terrains etc...) +/// Associated media live in a "resource bundle" (ZIP archive or subdirectory) in content directories (ROR_HOME/vehicles, +/// ROR_HOME/terrains etc...) /// Bundles are shared among cache entries and loaded only once, when related CacheEntry is loaded. class CacheSystem : public ZeroedMemoryAllocator { -public: - + public: CacheSystem(); enum CacheValidityState @@ -141,37 +140,53 @@ class CacheSystem : public ZeroedMemoryAllocator CACHE_STATE_UNKNOWN = 0xFFFFFFFF }; - void LoadModCache(CacheValidityState validity); - CacheEntry* FindEntryByFilename(std::string filename); // &GetCategories() const { return m_categories; } - const std::vector &GetEntries() const { return m_entries; } + const std::map &GetCategories() const + { + return m_categories; + } + const std::vector &GetEntries() const + { + return m_entries; + } - const std::vector GetUsableSkins(std::string const & guid) const; - std::shared_ptr FetchSkinDef(CacheEntry* cache_entry); //!< Loads+parses the .skin file once + const std::vector GetUsableSkins(std::string const &guid) const; + std::shared_ptr FetchSkinDef(CacheEntry *cache_entry); //!< Loads+parses the .skin file once - CacheEntry *GetEntry(int modid); + CacheEntry * GetEntry(int modid); Ogre::String GetPrettyName(Ogre::String fname); - enum CategoryID {CID_Max=9000, CID_Unsorted=9990, CID_All=9991, CID_Fresh=9992, CID_Hidden=9993, CID_SearchResults=9994}; - -private: + enum CategoryID + { + CID_Max = 9000, + CID_Unsorted = 9990, + CID_All = 9991, + CID_Fresh = 9992, + CID_Hidden = 9993, + CID_SearchResults = 9994 + }; + private: void WriteCacheFileJson(); - void ExportEntryToJson(rapidjson::Value& j_entries, rapidjson::Document& j_doc, CacheEntry const & entry); + void ExportEntryToJson(rapidjson::Value &j_entries, rapidjson::Document &j_doc, CacheEntry const &entry); void LoadCacheFileJson(); - void ImportEntryFromJson(rapidjson::Value& j_entry, CacheEntry & out_entry); + void ImportEntryFromJson(rapidjson::Value &j_entry, CacheEntry &out_entry); Ogre::String GetCacheConfigFilename(); // returns absolute path of the cache file - static Ogre::String StripUIDfromString(Ogre::String uidstr); + static Ogre::String StripUIDfromString(Ogre::String uidstr); static Ogre::String StripSHA1fromString(Ogre::String sha1str); void ParseZipArchives(Ogre::String group); @@ -188,65 +203,63 @@ class CacheSystem : public ZeroedMemoryAllocator void FillTerrainDetailInfo(CacheEntry &entry, Ogre::DataStreamPtr ds, Ogre::String fname); void FillTruckDetailInfo(CacheEntry &entry, Ogre::DataStreamPtr ds, Ogre::String fname, Ogre::String group); - void GenerateHashFromFilenames(); //!< For quick detection of added/removed content + void GenerateHashFromFilenames(); //!< For quick detection of added/removed content void GenerateFileCache(CacheEntry &entry, Ogre::String group); void RemoveFileCache(CacheEntry &entry); - std::time_t m_update_time; //!< Ensures that all inserted files share the same timestamp - std::string m_filenames_hash; //!< stores hash over the content, for quick update detection + std::time_t m_update_time; //!< Ensures that all inserted files share the same timestamp + std::string m_filenames_hash; //!< stores hash over the content, for quick update detection std::map m_loaded_resource_bundles; //!< Assosiates resource path with resource group std::vector m_entries; std::vector m_known_extensions; //!< the extensions we track in the cache system std::set m_resource_paths; //!< A temporary list of existing resource paths - std::map m_categories = { - // these are the category numbers from the repository. do not modify them! + std::map m_categories = {// these are the category numbers from the repository. do not modify them! - // vehicles - {108, "Other Land Vehicles"}, + // vehicles + {108, "Other Land Vehicles"}, - {146, "Street Cars"}, - {147, "Light Racing Cars"}, - {148, "Offroad Cars"}, - {149, "Fantasy Cars"}, - {150, "Bikes"}, - {155, "Crawlers"}, + {146, "Street Cars"}, + {147, "Light Racing Cars"}, + {148, "Offroad Cars"}, + {149, "Fantasy Cars"}, + {150, "Bikes"}, + {155, "Crawlers"}, - {152, "Towercranes"}, - {153, "Mobile Cranes"}, - {154, "Other cranes"}, + {152, "Towercranes"}, + {153, "Mobile Cranes"}, + {154, "Other cranes"}, - {107, "Buses"}, - {151, "Tractors"}, - {156, "Forklifts"}, - {159, "Fantasy Trucks"}, - {160, "Transport Trucks"}, - {161, "Racing Trucks"}, - {162, "Offroad Trucks"}, + {107, "Buses"}, + {151, "Tractors"}, + {156, "Forklifts"}, + {159, "Fantasy Trucks"}, + {160, "Transport Trucks"}, + {161, "Racing Trucks"}, + {162, "Offroad Trucks"}, - {110, "Boats"}, + {110, "Boats"}, - {113, "Helicopters"}, - {114, "Aircraft"}, + {113, "Helicopters"}, + {114, "Aircraft"}, - {117, "Trailers"}, - {118, "Other Loads"}, + {117, "Trailers"}, + {118, "Other Loads"}, - // terrains - {129, "Addon Terrains"}, + // terrains + {129, "Addon Terrains"}, - {859, "Container"}, + {859, "Container"}, - {875, "Submarine"}, + {875, "Submarine"}, - // note: these categories are NOT in the repository: - {5000, "Official Terrains"}, - {5001, "Night Terrains"}, + // note: these categories are NOT in the repository: + {5000, "Official Terrains"}, + {5001, "Night Terrains"}, - // do not use category numbers above 9000! - {9990, "Unsorted"}, - {9991, "All"}, - {9992, "Fresh"}, - {9993, "Hidden"} - }; + // do not use category numbers above 9000! + {9990, "Unsorted"}, + {9991, "All"}, + {9992, "Fresh"}, + {9993, "Hidden"}}; }; diff --git a/source/main/resources/ContentManager.cpp b/source/main/resources/ContentManager.cpp index 5a12760fe4..bacd9867dc 100644 --- a/source/main/resources/ContentManager.cpp +++ b/source/main/resources/ContentManager.cpp @@ -21,33 +21,29 @@ #include "ContentManager.h" - -#include -#include -#include - - #include "Application.h" -#include "Settings.h" +#include "CacheSystem.h" #include "ColoredTextAreaOverlayElementFactory.h" #include "ErrorUtils.h" -#include "SoundScriptManager.h" -#include "SkinManager.h" #include "Language.h" +#include "OgreShaderParticleRenderer.h" #include "PlatformUtils.h" +#include "Settings.h" +#include "SkinManager.h" +#include "SoundScriptManager.h" -#include "CacheSystem.h" - -#include "OgreShaderParticleRenderer.h" +#include +#include +#include -// Removed by Skybon as part of OGRE 1.9 port +// Removed by Skybon as part of OGRE 1.9 port // Disabling temporarily for 1.8.1 as well. ~ only_a_ptr, 2015-11 // TODO: Study the system, then re-enable or remove entirely. //#include "OgreBoxEmitterFactory.h" #ifdef USE_ANGELSCRIPT -#include "FireExtinguisherAffectorFactory.h" -#include "ExtinguishableFireAffectorFactory.h" + #include "ExtinguishableFireAffectorFactory.h" + #include "FireExtinguisherAffectorFactory.h" #endif // USE_ANGELSCRIPT #include "Utils.h" @@ -63,45 +59,43 @@ using namespace RoR; // Static variables // ================================================================================ -#define DECLARE_RESOURCE_PACK(_FIELD_, _NAME_, _RESOURCE_GROUP_) \ +#define DECLARE_RESOURCE_PACK(_FIELD_, _NAME_, _RESOURCE_GROUP_) \ const ContentManager::ResourcePack ContentManager::ResourcePack::_FIELD_(_NAME_, _RESOURCE_GROUP_); -DECLARE_RESOURCE_PACK( OGRE_CORE, "OgreCore", "OgreCoreRG"); -DECLARE_RESOURCE_PACK( WALLPAPERS, "wallpapers", "Wallpapers"); -DECLARE_RESOURCE_PACK( AIRFOILS, "airfoils", "AirfoilsRG"); -DECLARE_RESOURCE_PACK( CAELUM, "caelum", "CaelumRG"); -DECLARE_RESOURCE_PACK( CUBEMAPS, "cubemaps", "CubemapsRG"); -DECLARE_RESOURCE_PACK( DASHBOARDS, "dashboards", "DashboardsRG"); -DECLARE_RESOURCE_PACK( FAMICONS, "famicons", "FamiconsRG"); -DECLARE_RESOURCE_PACK( FLAGS, "flags", "FlagsRG"); -DECLARE_RESOURCE_PACK( HYDRAX, "hydrax", "HydraxRG"); -DECLARE_RESOURCE_PACK( ICONS, "icons", "IconsRG"); -DECLARE_RESOURCE_PACK( MATERIALS, "materials", "MaterialsRG"); -DECLARE_RESOURCE_PACK( MESHES, "meshes", "MeshesRG"); -DECLARE_RESOURCE_PACK( MYGUI, "mygui", "MyGuiRG"); -DECLARE_RESOURCE_PACK( OVERLAYS, "overlays", "OverlaysRG"); -DECLARE_RESOURCE_PACK( PAGED, "paged", "PagedRG"); -DECLARE_RESOURCE_PACK( PARTICLES, "particles", "ParticlesRG"); -DECLARE_RESOURCE_PACK( PSSM, "pssm", "PssmRG"); -DECLARE_RESOURCE_PACK( RTSHADER, "rtshader", "RtShaderRG"); -DECLARE_RESOURCE_PACK( SCRIPTS, "scripts", "ScriptsRG"); -DECLARE_RESOURCE_PACK( SOUNDS, "sounds", "SoundsRG"); -DECLARE_RESOURCE_PACK( TEXTURES, "textures", "TexturesRG"); -DECLARE_RESOURCE_PACK( SKYX, "SkyX", "SkyXRG"); +DECLARE_RESOURCE_PACK(OGRE_CORE, "OgreCore", "OgreCoreRG"); +DECLARE_RESOURCE_PACK(WALLPAPERS, "wallpapers", "Wallpapers"); +DECLARE_RESOURCE_PACK(AIRFOILS, "airfoils", "AirfoilsRG"); +DECLARE_RESOURCE_PACK(CAELUM, "caelum", "CaelumRG"); +DECLARE_RESOURCE_PACK(CUBEMAPS, "cubemaps", "CubemapsRG"); +DECLARE_RESOURCE_PACK(DASHBOARDS, "dashboards", "DashboardsRG"); +DECLARE_RESOURCE_PACK(FAMICONS, "famicons", "FamiconsRG"); +DECLARE_RESOURCE_PACK(FLAGS, "flags", "FlagsRG"); +DECLARE_RESOURCE_PACK(HYDRAX, "hydrax", "HydraxRG"); +DECLARE_RESOURCE_PACK(ICONS, "icons", "IconsRG"); +DECLARE_RESOURCE_PACK(MATERIALS, "materials", "MaterialsRG"); +DECLARE_RESOURCE_PACK(MESHES, "meshes", "MeshesRG"); +DECLARE_RESOURCE_PACK(MYGUI, "mygui", "MyGuiRG"); +DECLARE_RESOURCE_PACK(OVERLAYS, "overlays", "OverlaysRG"); +DECLARE_RESOURCE_PACK(PAGED, "paged", "PagedRG"); +DECLARE_RESOURCE_PACK(PARTICLES, "particles", "ParticlesRG"); +DECLARE_RESOURCE_PACK(PSSM, "pssm", "PssmRG"); +DECLARE_RESOURCE_PACK(RTSHADER, "rtshader", "RtShaderRG"); +DECLARE_RESOURCE_PACK(SCRIPTS, "scripts", "ScriptsRG"); +DECLARE_RESOURCE_PACK(SOUNDS, "sounds", "SoundsRG"); +DECLARE_RESOURCE_PACK(TEXTURES, "textures", "TexturesRG"); +DECLARE_RESOURCE_PACK(SKYX, "SkyX", "SkyXRG"); // ================================================================================ // Functions // ================================================================================ -void ContentManager::AddResourcePack(ResourcePack const& resource_pack, std::string const& override_rgn) +void ContentManager::AddResourcePack(ResourcePack const &resource_pack, std::string const &override_rgn) { - Ogre::ResourceGroupManager& rgm = Ogre::ResourceGroupManager::getSingleton(); + Ogre::ResourceGroupManager &rgm = Ogre::ResourceGroupManager::getSingleton(); Ogre::String rg_name; if (!override_rgn.empty()) // Custom RG defined? - { - rg_name = override_rgn; - } + { rg_name = override_rgn; } else // Use default RG { if (rgm.resourceGroupExists(resource_pack.resource_group_name)) // Already loaded? @@ -114,7 +108,7 @@ void ContentManager::AddResourcePack(ResourcePack const& resource_pack, std::str std::stringstream log_msg; log_msg << "[RoR|ContentManager] Loading resource pack \"" << resource_pack.name << "\" to group \"" << rg_name << "\""; Ogre::String resources_dir = Ogre::String(App::sys_resources_dir.GetActive()) + PATH_SLASH; - Ogre::String zip_path = resources_dir + resource_pack.name + Ogre::String(".zip"); + Ogre::String zip_path = resources_dir + resource_pack.name + Ogre::String(".zip"); if (FileExists(zip_path)) { log_msg << " (ZIP archive)"; @@ -138,9 +132,7 @@ void ContentManager::AddResourcePack(ResourcePack const& resource_pack, std::str } if (override_rgn.empty()) // Only init the default RG - { - rgm.initialiseResourceGroup(rg_name); - } + { rgm.initialiseResourceGroup(rg_name); } } void ContentManager::InitContentManager() @@ -160,28 +152,26 @@ void ContentManager::InitContentManager() // by default, display everything in the depth map Ogre::MovableObject::setDefaultVisibilityFlags(DEPTHMAP_ENABLED); - this->AddResourcePack(ResourcePack::MYGUI); this->AddResourcePack(ResourcePack::DASHBOARDS); - #ifdef _WIN32 // TODO: FIX UNDER LINUX! // register particle classes LOG("RoR|ContentManager: Registering Particle Box Emitter"); - ParticleSystemRendererFactory* mParticleSystemRendererFact = OGRE_NEW ShaderParticleRendererFactory(); + ParticleSystemRendererFactory *mParticleSystemRendererFact = OGRE_NEW ShaderParticleRendererFactory(); ParticleSystemManager::getSingleton().addRendererFactory(mParticleSystemRendererFact); - // Removed by Skybon as part of OGRE 1.9 port + // Removed by Skybon as part of OGRE 1.9 port // Disabling temporarily for 1.8.1 as well. ~ only_a_ptr, 2015-11 - //ParticleEmitterFactory *mParticleEmitterFact = OGRE_NEW BoxEmitterFactory(); - //ParticleSystemManager::getSingleton().addEmitterFactory(mParticleEmitterFact); + // ParticleEmitterFactory *mParticleEmitterFact = OGRE_NEW BoxEmitterFactory(); + // ParticleSystemManager::getSingleton().addEmitterFactory(mParticleEmitterFact); #endif // _WIN32 #ifdef USE_ANGELSCRIPT // FireExtinguisherAffector - ParticleAffectorFactory* pAffFact = OGRE_NEW FireExtinguisherAffectorFactory(); + ParticleAffectorFactory *pAffFact = OGRE_NEW FireExtinguisherAffectorFactory(); ParticleSystemManager::getSingleton().addAffectorFactory(pAffFact); // ExtinguishableFireAffector @@ -201,27 +191,28 @@ void ContentManager::InitContentManager() LOG("RoR|ContentManager: Loading filesystems"); // config, flat - ResourceGroupManager::getSingleton().addResourceLocation(std::string(RoR::App::sys_config_dir.GetActive()), "FileSystem", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + ResourceGroupManager::getSingleton().addResourceLocation(std::string(RoR::App::sys_config_dir.GetActive()), "FileSystem", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // packs, to be processed later by the cache system // add scripts folder - ResourceGroupManager::getSingleton().addResourceLocation(std::string(App::sys_user_dir.GetActive()) + PATH_SLASH + "scripts", "FileSystem", "Scripts"); + ResourceGroupManager::getSingleton().addResourceLocation(std::string(App::sys_user_dir.GetActive()) + PATH_SLASH + "scripts", + "FileSystem", "Scripts"); LOG("RoR|ContentManager: Registering colored text overlay factory"); - ColoredTextAreaOverlayElementFactory* pCT = new ColoredTextAreaOverlayElementFactory(); + ColoredTextAreaOverlayElementFactory *pCT = new ColoredTextAreaOverlayElementFactory(); OverlayManager::getSingleton().addOverlayElementFactory(pCT); // set default mipmap level (NB some APIs ignore this) - if (TextureManager::getSingletonPtr()) - TextureManager::getSingleton().setDefaultNumMipmaps(5); + if (TextureManager::getSingletonPtr()) TextureManager::getSingleton().setDefaultNumMipmaps(5); TextureFilterOptions tfo = TFO_NONE; switch (App::gfx_texture_filter.GetActive()) { - case GfxTexFilter::ANISOTROPIC: tfo = TFO_ANISOTROPIC; break; - case GfxTexFilter::TRILINEAR: tfo = TFO_TRILINEAR; break; - case GfxTexFilter::BILINEAR: tfo = TFO_BILINEAR; break; - case GfxTexFilter::NONE: tfo = TFO_NONE; break; + case GfxTexFilter::ANISOTROPIC: tfo = TFO_ANISOTROPIC; break; + case GfxTexFilter::TRILINEAR: tfo = TFO_TRILINEAR; break; + case GfxTexFilter::BILINEAR: tfo = TFO_BILINEAR; break; + case GfxTexFilter::NONE: tfo = TFO_NONE; break; } MaterialManager::getSingleton().setDefaultAnisotropy(Math::Clamp(App::gfx_anisotropy.GetActive(), 1, 16)); MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); @@ -232,7 +223,7 @@ void ContentManager::InitContentManager() { ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { LOG("RoR|ContentManager: catched error while initializing Resource groups: " + e.getFullDescription()); } @@ -243,40 +234,40 @@ void ContentManager::InitContentManager() void ContentManager::InitModCache() { - ResourceGroupManager::getSingleton().addResourceLocation(App::sys_cache_dir.GetActive(), "FileSystem", RGN_CACHE, false, false); + ResourceGroupManager::getSingleton().addResourceLocation(App::sys_cache_dir.GetActive(), "FileSystem", RGN_CACHE, false, + false); - std::string user = App::sys_user_dir.GetActive(); - std::string base = App::sys_process_dir.GetActive(); + std::string user = App::sys_user_dir.GetActive(); + std::string base = App::sys_process_dir.GetActive(); std::string objects = PathCombine("resources", "beamobjects.zip"); if (!App::app_extra_mod_path.IsActiveEmpty()) { std::string extra_mod_path = App::app_extra_mod_path.GetActive(); - ResourceGroupManager::getSingleton().addResourceLocation(extra_mod_path , "FileSystem", RGN_CONTENT); + ResourceGroupManager::getSingleton().addResourceLocation(extra_mod_path, "FileSystem", RGN_CONTENT); } - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "mods") , "FileSystem", RGN_CONTENT); - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "packs") , "FileSystem", RGN_CONTENT); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "mods"), "FileSystem", RGN_CONTENT); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "packs"), "FileSystem", RGN_CONTENT); ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "terrains"), "FileSystem", RGN_CONTENT); ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "vehicles"), "FileSystem", RGN_CONTENT); - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(base, "content") , "FileSystem", RGN_CONTENT); - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(base, objects) , "Zip" , RGN_CONTENT); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(base, "content"), "FileSystem", RGN_CONTENT); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(base, objects), "Zip", RGN_CONTENT); ResourceGroupManager::getSingleton().createResourceGroup(RGN_TEMP, false); if (!App::app_extra_mod_path.IsActiveEmpty()) { std::string extra_mod_path = App::app_extra_mod_path.GetActive(); - ResourceGroupManager::getSingleton().addResourceLocation(extra_mod_path , "FileSystem", RGN_TEMP, true); + ResourceGroupManager::getSingleton().addResourceLocation(extra_mod_path, "FileSystem", RGN_TEMP, true); } - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "mods") , "FileSystem", RGN_TEMP, true); - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "packs") , "FileSystem", RGN_TEMP, true); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "mods"), "FileSystem", RGN_TEMP, true); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "packs"), "FileSystem", RGN_TEMP, true); ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "terrains"), "FileSystem", RGN_TEMP, true); ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(user, "vehicles"), "FileSystem", RGN_TEMP, true); - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(base, "content") , "FileSystem", RGN_TEMP, true); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(base, "content"), "FileSystem", RGN_TEMP, true); FileInfoListPtr files = ResourceGroupManager::getSingleton().findResourceFileInfo(RGN_TEMP, "*", true); - for (const auto& file : *files) + for (const auto &file : *files) { - if (!file.archive) - continue; + if (!file.archive) continue; String fullpath = PathCombine(file.archive->getName(), file.filename); ResourceGroupManager::getSingleton().addResourceLocation(fullpath, "FileSystem", RGN_CONTENT); } @@ -284,27 +275,29 @@ void ContentManager::InitModCache() CacheSystem::CacheValidityState validity = m_mod_cache.EvaluateCacheValidity(); m_mod_cache.LoadModCache(validity); - App::SetCacheSystem(&m_mod_cache); // Temporary solution until Modcache+ContentManager are fully merged and `App::GetCacheSystem()` is removed ~ only_a_ptr, 10/2018 + App::SetCacheSystem(&m_mod_cache); // Temporary solution until Modcache+ContentManager are fully merged and + // `App::GetCacheSystem()` is removed ~ only_a_ptr, 10/2018 ResourceGroupManager::getSingleton().destroyResourceGroup(RGN_CONTENT); } -Ogre::DataStreamPtr ContentManager::resourceLoading(const Ogre::String& name, const Ogre::String& group, Ogre::Resource* resource) +Ogre::DataStreamPtr ContentManager::resourceLoading(const Ogre::String &name, const Ogre::String &group, Ogre::Resource *resource) { return Ogre::DataStreamPtr(); } -void ContentManager::resourceStreamOpened(const Ogre::String& name, const Ogre::String& group, Ogre::Resource* resource, Ogre::DataStreamPtr& dataStream) +void ContentManager::resourceStreamOpened(const Ogre::String &name, const Ogre::String &group, Ogre::Resource *resource, + Ogre::DataStreamPtr &dataStream) { } -bool ContentManager::resourceCollision(Ogre::Resource* resource, Ogre::ResourceManager* resourceManager) +bool ContentManager::resourceCollision(Ogre::Resource *resource, Ogre::ResourceManager *resourceManager) { // RoR loads each resource bundle (see CacheSystem.h for info) // into dedicated resource group outside the global pool [see CacheSystem::LoadResource()] // This means resource collision is entirely content creator's fault. - RoR::LogFormat("[RoR|ContentManager] Skipping resource with duplicate name: '%s' (origin: '%s')", - resource->getName().c_str(), resource->getOrigin().c_str()); + RoR::LogFormat("[RoR|ContentManager] Skipping resource with duplicate name: '%s' (origin: '%s')", resource->getName().c_str(), + resource->getOrigin().c_str()); return false; // Instruct OGRE to drop the new resource and keep the original. } @@ -314,11 +307,11 @@ bool ContentManager::handleEvent(ScriptCompiler *compiler, ScriptCompilerEvent * { // Workaround for OGRE script compiler not properly checking that material name is not empty. // See https://github.com/RigsOfRods/rigs-of-rods/issues/2349 - auto* matEvent = static_cast(evt); + auto *matEvent = static_cast(evt); if (matEvent->mName.empty()) { RoR::LogFormat("[RoR] Got malformed material (empty name) from file: '%s' - forcing OGRE to fail loading.", - matEvent->mFile.c_str()); + matEvent->mFile.c_str()); // Report "handled" but create nothing -> OGRE will interrupt the loading // with message "failed to find or create material" [in MaterialTranslator::translate()] return true; @@ -328,12 +321,12 @@ bool ContentManager::handleEvent(ScriptCompiler *compiler, ScriptCompilerEvent * { // Workaround for OGRE ignoring resource groups when registering particle templates // See https://github.com/RigsOfRods/rigs-of-rods/pull/2398 - auto* particleEvent = static_cast(evt); + auto *particleEvent = static_cast(evt); if (Ogre::ParticleSystemManager::getSingleton().getTemplate(particleEvent->mName) != nullptr) { // Duplicate name -> OGRE would throw exception and fail initializing whole resource group RoR::LogFormat("[RoR] Duplicate particle system name '%s' in file: '%s' - forcing OGRE to fail loading.", - particleEvent->mName.c_str(), particleEvent->mFile.c_str()); + particleEvent->mName.c_str(), particleEvent->mFile.c_str()); return true; // Instruct OGRE to skip the particle system } } @@ -341,25 +334,29 @@ bool ContentManager::handleEvent(ScriptCompiler *compiler, ScriptCompilerEvent * return false; // Report "not handled" } -void ContentManager::InitManagedMaterials(std::string const & rg_name) +void ContentManager::InitManagedMaterials(std::string const &rg_name) { Ogre::String managed_materials_dir = PathCombine(App::sys_resources_dir.GetActive(), "managed_materials"); - //Dirty, needs to be improved + // Dirty, needs to be improved if (App::gfx_shadow_type.GetActive() == GfxShadowType::PSSM) { if (rg_name == RGN_MANAGED_MATS) // Only load shared resources on startup { - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/on/shared"), "FileSystem", rg_name); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/on/shared"), + "FileSystem", rg_name); } - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/on"), "FileSystem", rg_name); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/on"), + "FileSystem", rg_name); } else { - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir,"shadows/pssm/off"), "FileSystem", rg_name); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/off"), + "FileSystem", rg_name); } - ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "texture"), "FileSystem", rg_name); + ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "texture"), "FileSystem", + rg_name); // Last ResourceGroupManager::getSingleton().addResourceLocation(managed_materials_dir, "FileSystem", rg_name); @@ -384,14 +381,11 @@ void ContentManager::LoadGameplayResources() m_base_resource_loaded = true; } - if (App::gfx_water_mode.GetActive() == GfxWaterMode::HYDRAX) - this->AddResourcePack(ContentManager::ResourcePack::HYDRAX); + if (App::gfx_water_mode.GetActive() == GfxWaterMode::HYDRAX) this->AddResourcePack(ContentManager::ResourcePack::HYDRAX); - if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) - this->AddResourcePack(ContentManager::ResourcePack::CAELUM); + if (App::gfx_sky_mode.GetActive() == GfxSkyMode::CAELUM) this->AddResourcePack(ContentManager::ResourcePack::CAELUM); - if (App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX) - this->AddResourcePack(ContentManager::ResourcePack::SKYX); + if (App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX) this->AddResourcePack(ContentManager::ResourcePack::SKYX); if (App::gfx_vegetation_mode.GetActive() != RoR::GfxVegetation::NONE) this->AddResourcePack(ContentManager::ResourcePack::PAGED); @@ -402,7 +396,7 @@ std::string ContentManager::ListAllUserContent() std::stringstream buf; auto dir_list = Ogre::ResourceGroupManager::getSingleton().listResourceFileInfo(RGN_CONTENT, true); - for (auto dir: *dir_list) + for (auto dir : *dir_list) { buf << dir.filename << std::endl; } @@ -411,14 +405,10 @@ std::string ContentManager::ListAllUserContent() std::regex file_whitelist("^.\\.(airplane|boat|car|fixed|load|machine|skin|terrn2|train|truck)$", std::regex::icase); auto file_list = Ogre::ResourceGroupManager::getSingleton().listResourceFileInfo(RGN_CONTENT, false); - for (auto file: *file_list) + for (auto file : *file_list) { - if ((file.archive != nullptr) || std::regex_match(file.filename, file_whitelist)) - { - buf << file.filename << std::endl; - } + if ((file.archive != nullptr) || std::regex_match(file.filename, file_whitelist)) { buf << file.filename << std::endl; } } return buf.str(); } - diff --git a/source/main/resources/ContentManager.h b/source/main/resources/ContentManager.h index b3c4b50860..9afb5a1009 100644 --- a/source/main/resources/ContentManager.h +++ b/source/main/resources/ContentManager.h @@ -34,69 +34,70 @@ #define RGN_CONTENT "Content" #define RGN_MANAGED_MATS "ManagedMaterials" -namespace RoR { - -class ContentManager: - public Ogre::ResourceLoadingListener, // Ogre::ResourceGroupManager::getSingleton().setLoadingListener() - public Ogre::ScriptCompilerListener // Ogre::ScriptCompilerManager::getSingleton().setListener() +namespace RoR { -public: - struct ResourcePack + class ContentManager + : public Ogre::ResourceLoadingListener, // Ogre::ResourceGroupManager::getSingleton().setLoadingListener() + public Ogre::ScriptCompilerListener // Ogre::ScriptCompilerManager::getSingleton().setListener() { - ResourcePack(const char* name, const char* resource_group_name): - name(name), resource_group_name(resource_group_name) - {} - - static const ResourcePack OGRE_CORE; - static const ResourcePack WALLPAPERS; - static const ResourcePack AIRFOILS; - static const ResourcePack BEAM_OBJECTS; - static const ResourcePack CAELUM; - static const ResourcePack CUBEMAPS; - static const ResourcePack DASHBOARDS; - static const ResourcePack FAMICONS; - static const ResourcePack FLAGS; - static const ResourcePack HYDRAX; - static const ResourcePack ICONS; - static const ResourcePack MATERIALS; - static const ResourcePack MESHES; - static const ResourcePack MYGUI; - static const ResourcePack OVERLAYS; - static const ResourcePack PAGED; - static const ResourcePack PARTICLES; - static const ResourcePack PSSM; - static const ResourcePack SKYX; - static const ResourcePack RTSHADER; - static const ResourcePack SCRIPTS; - static const ResourcePack SOUNDS; - static const ResourcePack TEXTURES; - - const char* name; - const char* resource_group_name; + public: + struct ResourcePack + { + ResourcePack(const char *name, const char *resource_group_name) : name(name), resource_group_name(resource_group_name) + { + } + + static const ResourcePack OGRE_CORE; + static const ResourcePack WALLPAPERS; + static const ResourcePack AIRFOILS; + static const ResourcePack BEAM_OBJECTS; + static const ResourcePack CAELUM; + static const ResourcePack CUBEMAPS; + static const ResourcePack DASHBOARDS; + static const ResourcePack FAMICONS; + static const ResourcePack FLAGS; + static const ResourcePack HYDRAX; + static const ResourcePack ICONS; + static const ResourcePack MATERIALS; + static const ResourcePack MESHES; + static const ResourcePack MYGUI; + static const ResourcePack OVERLAYS; + static const ResourcePack PAGED; + static const ResourcePack PARTICLES; + static const ResourcePack PSSM; + static const ResourcePack SKYX; + static const ResourcePack RTSHADER; + static const ResourcePack SCRIPTS; + static const ResourcePack SOUNDS; + static const ResourcePack TEXTURES; + + const char *name; + const char *resource_group_name; + }; + + /// Loads resources if not already loaded + /// @param override_rg If not set, the ResourcePack's RG is used -> resources won't unload until shutdown + void AddResourcePack(ResourcePack const &resource_pack, std::string const &override_rgn = ""); + void InitManagedMaterials(std::string const &rg_name); + void InitContentManager(); + void InitModCache(); + void LoadGameplayResources(); //!< Checks GVar settings and loads required resources. + std::string ListAllUserContent(); //!< Used by ModCache for quick detection of added/removed content + + private: + // Ogre::ResourceLoadingListener + Ogre::DataStreamPtr resourceLoading(const Ogre::String &name, const Ogre::String &group, + Ogre::Resource *resource) override; + void resourceStreamOpened(const Ogre::String &name, const Ogre::String &group, Ogre::Resource *resource, + Ogre::DataStreamPtr &dataStream) override; + bool resourceCollision(Ogre::Resource *resource, Ogre::ResourceManager *resourceManager) override; + + // Ogre::ScriptCompilerListener + bool handleEvent(Ogre::ScriptCompiler *compiler, Ogre::ScriptCompilerEvent *evt, void *retval) override; + + CacheSystem m_mod_cache; //!< Database of addon content + bool m_base_resource_loaded; }; - /// Loads resources if not already loaded - /// @param override_rg If not set, the ResourcePack's RG is used -> resources won't unload until shutdown - void AddResourcePack(ResourcePack const& resource_pack, std::string const& override_rgn = ""); - void InitManagedMaterials(std::string const & rg_name); - void InitContentManager(); - void InitModCache(); - void LoadGameplayResources(); //!< Checks GVar settings and loads required resources. - std::string ListAllUserContent(); //!< Used by ModCache for quick detection of added/removed content - -private: - - // Ogre::ResourceLoadingListener - Ogre::DataStreamPtr resourceLoading(const Ogre::String& name, const Ogre::String& group, Ogre::Resource* resource) override; - void resourceStreamOpened(const Ogre::String& name, const Ogre::String& group, Ogre::Resource* resource, Ogre::DataStreamPtr& dataStream) override; - bool resourceCollision(Ogre::Resource* resource, Ogre::ResourceManager* resourceManager) override; - - // Ogre::ScriptCompilerListener - bool handleEvent(Ogre::ScriptCompiler *compiler, Ogre::ScriptCompilerEvent *evt, void *retval) override; - - CacheSystem m_mod_cache; //!< Database of addon content - bool m_base_resource_loaded; -}; - } // namespace RoR diff --git a/source/main/resources/otc_fileformat/OTCFileformat.cpp b/source/main/resources/otc_fileformat/OTCFileformat.cpp index 0739e6f75a..417b463aa0 100644 --- a/source/main/resources/otc_fileformat/OTCFileformat.cpp +++ b/source/main/resources/otc_fileformat/OTCFileformat.cpp @@ -27,15 +27,14 @@ #include "ConfigFile.h" #include "Utils.h" -#include #include +#include -RoR::OTCParser::OTCParser() : - m_def(std::make_shared()) +RoR::OTCParser::OTCParser() : m_def(std::make_shared()) { } -bool RoR::OTCParser::LoadMasterConfig(Ogre::DataStreamPtr &ds, const char* filename) +bool RoR::OTCParser::LoadMasterConfig(Ogre::DataStreamPtr &ds, const char *filename) { std::string file_basename, file_ext; Ogre::StringUtil::splitBaseFilename(filename, file_basename, file_ext); @@ -44,33 +43,33 @@ bool RoR::OTCParser::LoadMasterConfig(Ogre::DataStreamPtr &ds, const char* filen { cfg.load(ds, "\t:=", false); - m_def->disable_cache = cfg.GetBool ("disableCaching", false); - m_def->world_size_x = cfg.GetInt ("WorldSizeX", 1024); - m_def->world_size_y = cfg.GetInt ("WorldSizeY", 50); - m_def->world_size_z = cfg.GetInt ("WorldSizeZ", 1024); - m_def->page_size = cfg.GetInt ("PageSize", 1025); - m_def->pages_max_x = cfg.GetInt ("PagesX", 0); - m_def->pages_max_z = cfg.GetInt ("PagesZ", 0); - m_def->page_filename_format = cfg.GetString("PageFileFormat", file_basename + "-page-{X}-{Z}.otc"); - m_def->is_flat = cfg.GetBool ("Flat", false); - m_def->max_pixel_error = cfg.GetInt ("MaxPixelError", 5); - m_def->batch_size_min = cfg.GetInt ("minBatchSize", 33); - m_def->batch_size_max = cfg.GetInt ("maxBatchSize", 65); - m_def->lightmap_enabled = cfg.GetBool ("LightmapEnabled", false); - m_def->norm_map_enabled = cfg.GetBool ("NormalMappingEnabled", false); - m_def->spec_map_enabled = cfg.GetBool ("SpecularMappingEnabled", false); - m_def->parallax_enabled = cfg.GetBool ("ParallaxMappingEnabled", false); - m_def->blendmap_dbg_enabled = cfg.GetBool ("DebugBlendMaps", false); - m_def->global_colormap_enabled = cfg.GetBool ("GlobalColourMapEnabled", false); - m_def->recv_dyn_shadows_depth = cfg.GetBool ("ReceiveDynamicShadowsDepth", false); - m_def->composite_map_distance = cfg.GetInt ("CompositeMapDistance", 4000); - m_def->layer_blendmap_size = cfg.GetInt ("LayerBlendMapSize", 1024); - m_def->composite_map_size = cfg.GetInt ("CompositeMapSize", 1024); - m_def->lightmap_size = cfg.GetInt ("LightMapSize", 1024); - m_def->skirt_size = cfg.GetInt ("SkirtSize", 30); - - m_def->world_size = std::max(m_def->world_size_x, m_def->world_size_z); - m_def->origin_pos = Ogre::Vector3(m_def->world_size_x / 2.0f, 0.0f, m_def->world_size_z / 2.0f); + m_def->disable_cache = cfg.GetBool("disableCaching", false); + m_def->world_size_x = cfg.GetInt("WorldSizeX", 1024); + m_def->world_size_y = cfg.GetInt("WorldSizeY", 50); + m_def->world_size_z = cfg.GetInt("WorldSizeZ", 1024); + m_def->page_size = cfg.GetInt("PageSize", 1025); + m_def->pages_max_x = cfg.GetInt("PagesX", 0); + m_def->pages_max_z = cfg.GetInt("PagesZ", 0); + m_def->page_filename_format = cfg.GetString("PageFileFormat", file_basename + "-page-{X}-{Z}.otc"); + m_def->is_flat = cfg.GetBool("Flat", false); + m_def->max_pixel_error = cfg.GetInt("MaxPixelError", 5); + m_def->batch_size_min = cfg.GetInt("minBatchSize", 33); + m_def->batch_size_max = cfg.GetInt("maxBatchSize", 65); + m_def->lightmap_enabled = cfg.GetBool("LightmapEnabled", false); + m_def->norm_map_enabled = cfg.GetBool("NormalMappingEnabled", false); + m_def->spec_map_enabled = cfg.GetBool("SpecularMappingEnabled", false); + m_def->parallax_enabled = cfg.GetBool("ParallaxMappingEnabled", false); + m_def->blendmap_dbg_enabled = cfg.GetBool("DebugBlendMaps", false); + m_def->global_colormap_enabled = cfg.GetBool("GlobalColourMapEnabled", false); + m_def->recv_dyn_shadows_depth = cfg.GetBool("ReceiveDynamicShadowsDepth", false); + m_def->composite_map_distance = cfg.GetInt("CompositeMapDistance", 4000); + m_def->layer_blendmap_size = cfg.GetInt("LayerBlendMapSize", 1024); + m_def->composite_map_size = cfg.GetInt("CompositeMapSize", 1024); + m_def->lightmap_size = cfg.GetInt("LightMapSize", 1024); + m_def->skirt_size = cfg.GetInt("SkirtSize", 30); + + m_def->world_size = std::max(m_def->world_size_x, m_def->world_size_z); + m_def->origin_pos = Ogre::Vector3(m_def->world_size_x / 2.0f, 0.0f, m_def->world_size_z / 2.0f); m_def->cache_filename_base = file_basename; for (int x = 0; x <= m_def->pages_max_x; ++x) @@ -78,16 +77,20 @@ bool RoR::OTCParser::LoadMasterConfig(Ogre::DataStreamPtr &ds, const char* filen for (int z = 0; z <= m_def->pages_max_z; ++z) { std::string filename = m_def->page_filename_format; - filename = Ogre::StringUtil::replaceAll(filename, "{X}", TOSTRING(x)); - filename = Ogre::StringUtil::replaceAll(filename, "{Z}", TOSTRING(z)); + filename = Ogre::StringUtil::replaceAll(filename, "{X}", TOSTRING(x)); + filename = Ogre::StringUtil::replaceAll(filename, "{Z}", TOSTRING(z)); char base[50], key[75]; snprintf(base, 50, "Heightmap.%d.%d", x, z); - snprintf(key, 75, "%s.raw.size", base); int raw_size = cfg.GetInt(key, 1025); - snprintf(key, 75, "%s.raw.bpp", base); int raw_bpp = cfg.GetInt(key, 2); - snprintf(key, 75, "%s.flipX", base); bool flip_x = cfg.GetBool(key, false); - snprintf(key, 75, "%s.flipY", base); bool flip_y = cfg.GetBool(key, false); + snprintf(key, 75, "%s.raw.size", base); + int raw_size = cfg.GetInt(key, 1025); + snprintf(key, 75, "%s.raw.bpp", base); + int raw_bpp = cfg.GetInt(key, 2); + snprintf(key, 75, "%s.flipX", base); + bool flip_x = cfg.GetBool(key, false); + snprintf(key, 75, "%s.flipY", base); + bool flip_y = cfg.GetBool(key, false); m_def->pages.emplace_back(x, z, filename, flip_x, flip_y, raw_size, raw_bpp); } @@ -101,7 +104,7 @@ bool RoR::OTCParser::LoadMasterConfig(Ogre::DataStreamPtr &ds, const char* filen return true; } -bool RoR::OTCParser::LoadPageConfig(Ogre::DataStreamPtr &ds, RoR::OTCPage& page, const char* filename) +bool RoR::OTCParser::LoadPageConfig(Ogre::DataStreamPtr &ds, RoR::OTCPage &page, const char *filename) { try { @@ -113,10 +116,7 @@ bool RoR::OTCParser::LoadPageConfig(Ogre::DataStreamPtr &ds, RoR::OTCPage& page, while (!ds->eof()) { std::string line_sane = RoR::Utils::SanitizeUtf8String(ds->getLine()); - if (line_sane.empty() || line_sane[0] == ';' || line_sane[0] == '/') - { - continue; - } + if (line_sane.empty() || line_sane[0] == ';' || line_sane[0] == '/') { continue; } Ogre::StringVector args = Ogre::StringUtil::split(line_sane, ","); if (args.size() < 1) @@ -127,39 +127,22 @@ bool RoR::OTCParser::LoadPageConfig(Ogre::DataStreamPtr &ds, RoR::OTCPage& page, OTCLayer layer; layer.world_size = PARSEREAL(args[0]); - if (args.size() > 2) - { - layer.diffusespecular_filename = Utils::TrimStr(args[1]); - } - if (args.size() > 1) - { - layer.normalheight_filename = Utils::TrimStr(args[2]); - } - if (args.size() > 3) - { - layer.blendmap_filename = Utils::TrimStr(args[3]); - } - if (args.size() > 4) - { - layer.blend_mode = Utils::TrimStr(args[4])[0]; - } - if (args.size() > 5) - { - layer.alpha = PARSEREAL(args[5]); - } + if (args.size() > 2) { layer.diffusespecular_filename = Utils::TrimStr(args[1]); } + if (args.size() > 1) { layer.normalheight_filename = Utils::TrimStr(args[2]); } + if (args.size() > 3) { layer.blendmap_filename = Utils::TrimStr(args[3]); } + if (args.size() > 4) { layer.blend_mode = Utils::TrimStr(args[4])[0]; } + if (args.size() > 5) { layer.alpha = PARSEREAL(args[5]); } page.layers.push_back(layer); } - if (page.heightmap_filename.find(".raw") != std::string::npos) - { - page.is_heightmap_raw = true; - } + if (page.heightmap_filename.find(".raw") != std::string::npos) { page.is_heightmap_raw = true; } int actual_num_layers = static_cast(page.layers.size()); if (page.num_layers != actual_num_layers) { - LogFormat("[RoR|Terrain] Warning: File \"%s\" declares %d layers but defines %d. Correcting declared layer count to %d", + LogFormat( + "[RoR|Terrain] Warning: File \"%s\" declares %d layers but defines %d. Correcting declared layer count to %d", filename, page.num_layers, actual_num_layers, actual_num_layers); page.num_layers = actual_num_layers; } @@ -172,41 +155,37 @@ bool RoR::OTCParser::LoadPageConfig(Ogre::DataStreamPtr &ds, RoR::OTCPage& page, return true; } -void RoR::OTCParser::HandleException(const char* filename) +void RoR::OTCParser::HandleException(const char *filename) { - try { throw; } // Rethrow - catch (Ogre::Exception& e) + try + { + throw; + } // Rethrow + catch (Ogre::Exception &e) { LOG(std::string("[RoR|Terrain] Error reading OTC file '") + filename + "', message: " + e.getFullDescription()); } - catch (std::exception& e) + catch (std::exception &e) { LOG(std::string("[RoR|Terrain] Error reading OTC file '") + filename + "', Message: " + e.what()); } } -RoR::OTCFile::OTCFile(): - world_size_x(0), world_size_y(0), world_size_z(0), world_size(0), - page_size(0), pages_max_x(0), pages_max_z(0), - origin_pos(Ogre::Vector3::ZERO), - batch_size_min(0), batch_size_max(0), - layer_blendmap_size(0), max_pixel_error(0), composite_map_size(0), composite_map_distance(0), - skirt_size(0), lightmap_size(0), - lightmap_enabled(false), norm_map_enabled(false), spec_map_enabled(false), parallax_enabled(false), - global_colormap_enabled(false), recv_dyn_shadows_depth(false), disable_cache(false), is_flat(true) +RoR::OTCFile::OTCFile() + : world_size_x(0), world_size_y(0), world_size_z(0), world_size(0), page_size(0), pages_max_x(0), pages_max_z(0), + origin_pos(Ogre::Vector3::ZERO), batch_size_min(0), batch_size_max(0), layer_blendmap_size(0), max_pixel_error(0), + composite_map_size(0), composite_map_distance(0), skirt_size(0), lightmap_size(0), lightmap_enabled(false), + norm_map_enabled(false), spec_map_enabled(false), parallax_enabled(false), global_colormap_enabled(false), + recv_dyn_shadows_depth(false), disable_cache(false), is_flat(true) +{ +} + +RoR::OTCPage::OTCPage(int x_pos, int z_pos, std::string const &conf_filename, bool flipX, bool flipY, int rawsize, int rawbpp) + : pageconf_filename(conf_filename), pos_x(x_pos), pos_z(z_pos), is_heightmap_raw(false), raw_flip_x(flipX), raw_flip_y(flipY), + raw_size(rawsize), raw_bpp(rawbpp), num_layers(0) { } -RoR::OTCPage::OTCPage(int x_pos, int z_pos, std::string const & conf_filename, bool flipX, bool flipY, int rawsize, int rawbpp): - pageconf_filename(conf_filename), - pos_x(x_pos), pos_z(z_pos), - is_heightmap_raw(false), raw_flip_x(flipX), raw_flip_y(flipY), - raw_size(rawsize), raw_bpp(rawbpp), - num_layers(0) -{} - -RoR::OTCLayer::OTCLayer(): - blend_mode('R'), - alpha(static_cast('R')) // Backwards compatibility, probably old typo +RoR::OTCLayer::OTCLayer() : blend_mode('R'), alpha(static_cast('R')) // Backwards compatibility, probably old typo { } diff --git a/source/main/resources/otc_fileformat/OTCFileformat.h b/source/main/resources/otc_fileformat/OTCFileformat.h index 435b384343..86fb343441 100644 --- a/source/main/resources/otc_fileformat/OTCFileformat.h +++ b/source/main/resources/otc_fileformat/OTCFileformat.h @@ -25,84 +25,87 @@ #include #include #include - -#include #include #include +#include -namespace RoR { - -struct OTCLayer -{ - OTCLayer(); - - std::string blendmap_filename; - std::string diffusespecular_filename; - std::string normalheight_filename; - char blend_mode; - float alpha; - float world_size; -}; - -struct OTCPage -{ - OTCPage(int pos_x, int pos_z, std::string const & conf_filename, bool flipX, bool flipY, int rawsize, int rawbpp); - - std::string pageconf_filename; - std::string heightmap_filename; - int num_layers; - int pos_x, pos_z; - bool is_heightmap_raw, raw_flip_x, raw_flip_y; - int raw_size, raw_bpp; - - std::list layers; -}; - -/// Rembember OGRE coordinates are {X = right/left, Y = up/down, Z = front/back} -struct OTCFile +namespace RoR { - OTCFile(); - - std::string page_filename_format; - std::string cache_filename_base; - std::list pages; - Ogre::Vector3 origin_pos; - - int world_size_x, world_size_y, world_size_z; - int page_size; - int world_size; - int pages_max_x, pages_max_z; ///< Highest page index - int max_pixel_error; - int batch_size_min, batch_size_max; - int layer_blendmap_size; - int composite_map_size; - int composite_map_distance; - int skirt_size; - int lightmap_size; - bool lightmap_enabled; - bool norm_map_enabled; - bool spec_map_enabled; - bool parallax_enabled; - bool global_colormap_enabled; - bool recv_dyn_shadows_depth; - bool blendmap_dbg_enabled; - bool disable_cache; - bool is_flat; -}; - -class OTCParser -{ -public: - OTCParser(); - - bool LoadMasterConfig(Ogre::DataStreamPtr &ds, const char* filename); - bool LoadPageConfig(Ogre::DataStreamPtr &ds, OTCPage& page, const char* filename); - std::shared_ptr GetDefinition() { return m_def; }; - -private: - void HandleException(const char* filename); - std::shared_ptr m_def; -}; + struct OTCLayer + { + OTCLayer(); + + std::string blendmap_filename; + std::string diffusespecular_filename; + std::string normalheight_filename; + char blend_mode; + float alpha; + float world_size; + }; + + struct OTCPage + { + OTCPage(int pos_x, int pos_z, std::string const &conf_filename, bool flipX, bool flipY, int rawsize, int rawbpp); + + std::string pageconf_filename; + std::string heightmap_filename; + int num_layers; + int pos_x, pos_z; + bool is_heightmap_raw, raw_flip_x, raw_flip_y; + int raw_size, raw_bpp; + + std::list layers; + }; + + /// Rembember OGRE coordinates are {X = right/left, Y = up/down, Z = front/back} + struct OTCFile + { + OTCFile(); + + std::string page_filename_format; + std::string cache_filename_base; + std::list pages; + Ogre::Vector3 origin_pos; + + int world_size_x, world_size_y, world_size_z; + int page_size; + int world_size; + int pages_max_x, pages_max_z; ///< Highest page index + int max_pixel_error; + int batch_size_min, batch_size_max; + int layer_blendmap_size; + int composite_map_size; + int composite_map_distance; + int skirt_size; + int lightmap_size; + bool lightmap_enabled; + bool norm_map_enabled; + bool spec_map_enabled; + bool parallax_enabled; + bool global_colormap_enabled; + bool recv_dyn_shadows_depth; + bool blendmap_dbg_enabled; + bool disable_cache; + bool is_flat; + }; + + class OTCParser + { + public: + OTCParser(); + + bool LoadMasterConfig(Ogre::DataStreamPtr &ds, const char *filename); + bool LoadPageConfig(Ogre::DataStreamPtr &ds, OTCPage &page, const char *filename); + std::shared_ptr GetDefinition() + { + return m_def; + }; + + private: + void HandleException(const char *filename); + + std::shared_ptr m_def; + }; } // namespace RoR diff --git a/source/main/resources/rig_def_fileformat/RigDef_File.cpp b/source/main/resources/rig_def_fileformat/RigDef_File.cpp index 298043c80f..8792570e73 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_File.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_File.cpp @@ -24,12 +24,13 @@ /// @date 12/2013 #include "RigDef_File.h" + #include "BeamConstants.h" namespace RigDef { -const char* ROOT_MODULE_NAME = "_Root_"; // Static + const char *ROOT_MODULE_NAME = "_Root_"; // Static #ifndef _WIN32 /* These definitions are needed because the variables are declared but not defined in Axle */ @@ -39,637 +40,375 @@ const char* ROOT_MODULE_NAME = "_Root_"; // Static const char Axle::OPTION_s_VISCOUS; #endif // !_WIN32 -/* -------------------------------------------------------------------------- */ -/* Sections */ -/* */ -/* This is the place to set defaults. */ -/* -------------------------------------------------------------------------- */ - -Airbrake::Airbrake(): - offset(Ogre::Vector3::ZERO), - width(0), - height(0), - max_inclination_angle(0), - texcoord_x1(0), - texcoord_x2(0), - texcoord_y1(0), - texcoord_y2(0), - lift_coefficient(1.f) // This is default -{} - -AntiLockBrakes::AntiLockBrakes(): - regulation_force(0), - min_speed(0), - pulse_per_sec(0), - attr_is_on(true), - attr_no_dashboard(false), - attr_no_toggle(false) -{} - -Command2::Command2(): - shorten_rate(0), - lengthen_rate(0), - max_contraction(0), - max_extension(0), - contract_key(0), - extend_key(0), - _format_version(1), /* 1 = 'commands', 2 = 'commands2' */ - affect_engine(1), - detacher_group(0), - needs_engine(true), - plays_sound(true), - option_i_invisible(false), - option_r_rope(false), - option_c_auto_center(false), - option_f_not_faster(false), - option_p_1press(false), - option_o_1press_center(false) -{} - -Engoption::Engoption(): - inertia(10.f), - clutch_force(-1.f), - shift_time(-1.f), - clutch_time(-1.f), - type(ENGINE_TYPE_t_TRUCK), - post_shift_time(-1.f), - idle_rpm(-1.f), - stall_rpm(-1.f), - max_idle_mixture(-1.f), - min_idle_mixture(-1.f), - braking_torque(-1.f) -{} - -Engturbo::Engturbo() : -tinertiaFactor(1), -nturbos(1), -param1(9999), //used for default values -param2(9999), -param3(9999), -param4(9999), -param5(9999), -param6(9999), -param7(9999), -param8(9999), -param9(9999), -param10(9999), -param11(9999) -{} - -Fusedrag::Fusedrag(): - autocalc(false), - approximate_width(0), - area_coefficient(1.f), // Default - airfoil_name("NACA0009.afl") -{} - -Hook::Hook(): - flag_self_lock (false), - flag_auto_lock (false), - flag_no_disable(false), - flag_no_rope (false), - flag_visible (false), - option_hook_range(HOOK_RANGE_DEFAULT), - option_speed_coef(1.0f), - option_max_force(HOOK_FORCE_DEFAULT), - option_hookgroup(-1), - option_lockgroup(NODE_LOCKGROUP_DEFAULT), - option_timer(HOOK_LOCK_TIMER_DEFAULT), - option_min_range_meters(0.f) -{} - -NodeDefaults::NodeDefaults(): - load_weight(-1.f), - friction(1), - volume(1), - surface(1), - options(0) -{} - -Shock::Shock(): - spring_rate(0), - damping(0), - short_bound(0), - long_bound(0), - precompression(1), - options(0), - detacher_group(0) -{} - -Shock2::Shock2(): - spring_in(0), - damp_in(0), - progress_factor_spring_in(0), - progress_factor_damp_in(0), - spring_out(0), - damp_out(0), - progress_factor_spring_out(0), - progress_factor_damp_out(0), - short_bound(0), - long_bound(0), - precompression(0), - options(0), - detacher_group(0) -{} - -Shock3::Shock3(): - spring_in(0), - damp_in(0), - damp_in_slow(0), - split_vel_in(0), - damp_in_fast(0), - spring_out(0), - damp_out(0), - damp_out_slow(0), - split_vel_out(0), - damp_out_fast(0), - short_bound(0), - long_bound(0), - precompression(0), - options(0), - detacher_group(0) -{} - -SlideNode::SlideNode(): - spring_rate(9000000), - break_force(0), - tolerance(0), - railgroup_id(-1), - _railgroup_id_set(false), - attachment_rate(1.f), - max_attachment_distance(0.1f), - constraint_flags(0), - _break_force_set(false) -{ - rail_node_ranges.reserve(25); -} - -Tie::Tie(): - max_reach_length(0), - auto_shorten_rate(0), - min_length(0), - max_length(0), - is_invisible(false), - disable_self_lock(false), - max_stress(100000.0f), // default, hardcoded in legacy SerializedRig.cpp, BTS_TIES - detacher_group(0), // Global detacher group - group(-1) // = group not set -{} - -TractionControl::TractionControl(): - regulation_force(0), - wheel_slip(0), - fade_speed(0), - pulse_per_sec(0), - attr_is_on(false), - attr_no_dashboard(false), - attr_no_toggle(false) -{} - -Trigger::Trigger(): - shortbound_trigger_action(0), - longbound_trigger_action(0), - contraction_trigger_limit(0), - expansion_trigger_limit(0), - options(0), - boundary_timer(1.f), /* Default */ - detacher_group(0) -{} - -VideoCamera::VideoCamera(): - offset(Ogre::Vector3::ZERO), - rotation(Ogre::Vector3::ZERO), - field_of_view(0), - texture_width(0), - texture_height(0), - min_clip_distance(0), - max_clip_distance(0), - camera_role(0), - camera_mode(0) -{} - -const std::string Wing::CONTROL_LEGAL_FLAGS("nabferSTcdghUVij"); // Static member init - -Wing::Wing(): - control_surface(CONTROL_n_NONE), - chord_point(-1.f), - min_deflection(-1.f), - max_deflection(-1.f), - efficacy_coef(1.f) // So-called 'liftcoef'. Default = 1 -{ - tex_coords[0] = 0.f; - tex_coords[1] = 0.f; - tex_coords[2] = 0.f; - tex_coords[3] = 0.f; - tex_coords[4] = 0.f; - tex_coords[5] = 0.f; - tex_coords[6] = 0.f; - tex_coords[7] = 0.f; -} - -void Animation::AddMotorSource(unsigned int source, unsigned int motor) -{ - Animation::MotorSource motor_source; - motor_source.source = source; - motor_source.motor = motor; - this->motor_sources.push_back(motor_source); -} + /* -------------------------------------------------------------------------- */ + /* Sections */ + /* */ + /* This is the place to set defaults. */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* File */ -/* -------------------------------------------------------------------------- */ + Airbrake::Airbrake() + : offset(Ogre::Vector3::ZERO), width(0), height(0), max_inclination_angle(0), texcoord_x1(0), texcoord_x2(0), + texcoord_y1(0), texcoord_y2(0), lift_coefficient(1.f) // This is default + { + } -const char * File::SectionToString(File::Section section) -{ - switch (section) + AntiLockBrakes::AntiLockBrakes() + : regulation_force(0), min_speed(0), pulse_per_sec(0), attr_is_on(true), attr_no_dashboard(false), attr_no_toggle(false) { - case (File::SECTION_AIRBRAKES): - return "airbrakes"; - case (File::SECTION_ANIMATORS): - return "animators"; - case (File::SECTION_ANTI_LOCK_BRAKES): - return "AntiLockBrakes"; - case (File::SECTION_AUTHOR): - return "author"; - case (File::SECTION_AXLES): - return "axles"; - case (File::SECTION_BEAMS): - return "beams"; - case (File::SECTION_BRAKES): - return "brakes"; - case (File::SECTION_CAMERAS): - return "cameras"; - case (File::SECTION_CAMERA_RAIL): - return "camerarail"; - case (File::SECTION_CINECAM): - return "cinecam"; - case (File::SECTION_COLLISION_BOXES): - return "collisionboxes"; - case (File::SECTION_COMMANDS): - return "commands"; - case (File::SECTION_COMMANDS_2): - return "commands2"; - case (File::SECTION_CONTACTERS): - return "contacters"; - case (File::SECTION_ENGINE): - return "engine"; - case (File::SECTION_ENGOPTION): - return "engoption"; - case (File::SECTION_ENGTURBO) : - return "engturbo"; - case (File::SECTION_EXHAUSTS): - return "exhausts"; - case (File::SECTION_FIXES): - return "fixes"; - case (File::SECTION_FLARES): - return "flares"; - case (File::SECTION_FLARES_2): - return "flares2"; - case (File::SECTION_FLEXBODIES): - return "flexbodies"; - case (File::SECTION_FLEX_BODY_WHEELS): - return "flexbodywheels"; - case (File::SECTION_FUSEDRAG): - return "fusedrag"; - case (File::SECTION_GLOBALS): - return "globals"; - case (File::SECTION_GUI_SETTINGS): - return "guisettings"; - case (File::SECTION_HYDROS): - return "hydros"; - case (File::SECTION_HELP): - return "help"; - case (File::SECTION_HOOKS): - return "hooks"; - case (File::SECTION_INTERAXLES): - return "interaxles"; - case (File::SECTION_LOCKGROUPS): - return "lockgroups"; - case (File::SECTION_MANAGED_MATERIALS): - return "managedmaterials"; - case (File::SECTION_MAT_FLARE_BINDINGS): - return "materialflarebindings"; - case (File::SECTION_MESH_WHEELS): - return "meshwheels"; - case (File::SECTION_MESH_WHEELS_2): - return "meshwheels2"; - case (File::SECTION_MINIMASS): - return "minimass"; - case (File::SECTION_NODES): - return "nodes"; - case (File::SECTION_NODES_2): - return "nodes2"; - case (File::SECTION_PARTICLES): - return "particles"; - case (File::SECTION_PISTONPROPS): - return "pistonprops"; - case (File::SECTION_PROPS): - return "props"; - case (File::SECTION_RAILGROUPS): - return "railgroups"; - case (File::SECTION_ROPABLES): - return "ropables"; - case (File::SECTION_ROPES): - return "ropes"; - case (File::SECTION_ROTATORS): - return "rotators"; - case (File::SECTION_ROTATORS_2): - return "rotators_2"; - case (File::SECTION_SCREWPROPS): - return "screwprops"; - case (File::SECTION_SHOCKS): - return "shocks"; - case (File::SECTION_SHOCKS_2): - return "shocks2"; - case (File::SECTION_SHOCKS_3): - return "shocks3"; - case (File::SECTION_SLIDENODES): - return "slidenodes"; - case (File::SECTION_SOUNDSOURCES): - return "soundsources"; - case (File::SECTION_SOUNDSOURCES2): - return "soundsources2"; - case (File::SECTION_SLOPE_BRAKE): - return "SlopeBrake"; - case (File::SECTION_SUBMESH): - return "submesh"; - case (File::SECTION_TIES): - return "ties"; - case (File::SECTION_TORQUE_CURVE): - return "torquecurve"; - case (File::SECTION_TRACTION_CONTROL): - return "TractionControl"; - case (File::SECTION_TRANSFER_CASE): - return "transfercase"; - case (File::SECTION_TRIGGERS): - return "triggers"; - case (File::SECTION_TRUCK_NAME): - return ""; - case (File::SECTION_TURBOJETS): - return "turbojets"; - case (File::SECTION_TURBOPROPS): - return "turboprops"; - case (File::SECTION_TURBOPROPS_2): - return "turboprops"; - case (File::SECTION_VIDEO_CAMERA): - return "videocamera"; - case (File::SECTION_WHEELS): - return "wheels"; - case (File::SECTION_WHEELS_2): - return "wheels2"; - case (File::SECTION_WINGS): - return "wings"; - - case (File::SECTION_NONE): - return "SECTION_NONE"; - default: - return ""; } -} -const char * File::SubsectionToString(File::Subsection subsection) -{ - switch (subsection) + Command2::Command2() + : shorten_rate(0), lengthen_rate(0), max_contraction(0), max_extension(0), contract_key(0), extend_key(0), + _format_version(1), /* 1 = 'commands', 2 = 'commands2' */ + affect_engine(1), detacher_group(0), needs_engine(true), plays_sound(true), option_i_invisible(false), + option_r_rope(false), option_c_auto_center(false), option_f_not_faster(false), option_p_1press(false), + option_o_1press_center(false) { - case (File::SUBSECTION_NONE): - return "SUBSECTION_NONE"; - case (File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE): - return "SUBSECTION_PROPLIKE_LINE"; - case (File::SUBSECTION__FLEXBODIES__FORSET_LINE): - return "SUBSECTION_FORSET_LINE"; - case (File::SUBSECTION__SUBMESH__TEXCOORDS): - return "SUBSECTION_TEXCOORDS"; - case (File::SUBSECTION__SUBMESH__CAB): - return "SUBSECTION_CAB"; - default: - return "~ UNKNOWN SUBSECTION ~"; } -} -const char * File::KeywordToString(File::Keyword keyword) -{ - /* NOTE: Maintain alphabetical order! */ + Engoption::Engoption() + : inertia(10.f), clutch_force(-1.f), shift_time(-1.f), clutch_time(-1.f), type(ENGINE_TYPE_t_TRUCK), + post_shift_time(-1.f), idle_rpm(-1.f), stall_rpm(-1.f), max_idle_mixture(-1.f), min_idle_mixture(-1.f), + braking_torque(-1.f) + { + } - switch (keyword) + Engturbo::Engturbo() + : tinertiaFactor(1), nturbos(1), param1(9999), // used for default values + param2(9999), param3(9999), param4(9999), param5(9999), param6(9999), param7(9999), param8(9999), param9(9999), + param10(9999), param11(9999) { - case (File::KEYWORD_AIRBRAKES): - return "airbrakes"; - case (File::KEYWORD_ANIMATORS): - return "animators"; - case (File::KEYWORD_ANTI_LOCK_BRAKES): - return "AntiLockBrakes"; - case (File::KEYWORD_AUTHOR): - return "author"; - case (File::KEYWORD_AXLES): - return "axles"; - case (File::KEYWORD_BEAMS): - return "beams"; - case (File::KEYWORD_BRAKES): - return "brakes"; - case (File::KEYWORD_CAB): - return "submesh >> cab"; - case (File::KEYWORD_CAMERAS): - return "cameras"; - case (File::KEYWORD_CAMERARAIL): - return "camerarail"; - case (File::KEYWORD_CINECAM): - return "cinecam"; - case (File::KEYWORD_COLLISIONBOXES): - return "collisionboxes"; - case (File::KEYWORD_COMMANDS): - return "commands"; - case (File::KEYWORD_COMMANDS2): - return "commands2"; - case (File::KEYWORD_CONTACTERS): - return "contacters"; - case (File::KEYWORD_CRUISECONTROL): - return "cruisecontrol"; - case (File::KEYWORD_DESCRIPTION): - return "description"; - case (File::KEYWORD_ENGINE): - return "engine"; - case (File::KEYWORD_ENGOPTION): - return "engoption"; - case (File::KEYWORD_ENGTURBO) : - return "engturbo"; - case (File::KEYWORD_EXHAUSTS): - return "exhausts"; - case (File::KEYWORD_FILEINFO): - return "fileinfo"; - case (File::KEYWORD_FILEFORMATVERSION): - return "fileformatversion"; - case (File::KEYWORD_FIXES): - return "fixes"; - case (File::KEYWORD_FLARES): - return "flares"; - case (File::KEYWORD_FLARES2): - return "flares2"; - case (File::KEYWORD_FLEXBODIES): - return "flexbodies"; - case (File::KEYWORD_FLEXBODYWHEELS): - return "flexbodywheels"; - case (File::KEYWORD_FUSEDRAG): - return "fusedrag"; - case (File::KEYWORD_GLOBALS): - return "globals"; - case (File::KEYWORD_GUISETTINGS): - return "guisettings"; - case (File::KEYWORD_HELP): - return "help"; - case (File::KEYWORD_HOOKS): - return "hooks"; - case (File::KEYWORD_HYDROS): - return "hydros"; - case (File::KEYWORD_INTERAXLES): - return "interaxles"; - case (File::KEYWORD_MANAGEDMATERIALS): - return "managedmaterials"; - case (File::KEYWORD_MATERIALFLAREBINDINGS): - return "materialflarebindings"; - case (File::KEYWORD_MESHWHEELS): - return "meshwheels"; - case (File::KEYWORD_MESHWHEELS2): - return "meshwheels2"; - case (File::KEYWORD_MINIMASS): - return "minimass"; - case (File::KEYWORD_NODES): - return "nodes"; - case (File::KEYWORD_NODES2): - return "nodes2"; - case (File::KEYWORD_PARTICLES): - return "particles"; - case (File::KEYWORD_PISTONPROPS): - return "pistonprops"; - case (File::KEYWORD_PROPS): - return "props"; - case (File::KEYWORD_RAILGROUPS): - return "railgroups"; - case (File::KEYWORD_ROPABLES): - return "ropables"; - case (File::KEYWORD_ROPES): - return "ropes"; - case (File::KEYWORD_ROTATORS): - return "rotators"; - case (File::KEYWORD_ROTATORS2): - return "rotators_2"; - case (File::KEYWORD_SCREWPROPS): - return "screwprops"; - case (File::KEYWORD_SHOCKS): - return "shocks"; - case (File::KEYWORD_SHOCKS2): - return "shocks2"; - case (File::KEYWORD_SHOCKS3): - return "shocks3"; - case (File::KEYWORD_SLIDENODES): - return "slidenodes"; - case (File::KEYWORD_SLOPE_BRAKE): - return "SlopeBrake"; - case (File::KEYWORD_SOUNDSOURCES): - return "soundsources"; - case (File::KEYWORD_SOUNDSOURCES2): - return "soundsources2"; - case (File::KEYWORD_SUBMESH) : - return "submesh"; - case (File::KEYWORD_TEXCOORDS): - return "submesh >> texcoords"; - case (File::KEYWORD_TIES): - return "ties"; - case (File::KEYWORD_TORQUECURVE): - return "torquecurve"; - case (File::KEYWORD_TRACTION_CONTROL): - return "TractionControl"; - case (File::KEYWORD_TRANSFER_CASE): - return "transfercase"; - case (File::KEYWORD_TRIGGERS): - return "triggers"; - case (File::KEYWORD_TURBOJETS): - return "turbojets"; - case (File::KEYWORD_TURBOPROPS): - return "turboprops"; - case (File::KEYWORD_TURBOPROPS2): - return "turboprops2"; - case (File::KEYWORD_VIDEOCAMERA): - return "videocamera"; - case (File::KEYWORD_WHEELS): - return "wheels"; - case (File::KEYWORD_WHEELS2): - return "wheels2"; - case (File::KEYWORD_WINGS): - return "wings"; - - default: - return "~Unknown~"; } -} -File::Module::Module(Ogre::String const & name): - name(name) -{ - /* Pre-allocate */ - airbrakes.reserve(10); - animators.reserve(50); - axles.reserve(10); - beams.reserve(1000); - cameras.reserve(10); - camera_rails.reserve(10); - collision_boxes.reserve(10); - commands_2.reserve(35); - exhausts.reserve(6); - flares_2.reserve(10); - flexbodies.reserve(15); - hooks.reserve(10); - hydros.reserve(25); - lockgroups.reserve(10); - managed_materials.reserve(25); - material_flare_bindings.reserve(10); - mesh_wheels.reserve(10); - nodes.reserve(2000); - node_collisions.reserve(100); - particles.reserve(25); - pistonprops.reserve(25); - props.reserve(50); - railgroups.reserve(10); - ropables.reserve(50); - ropes.reserve(25); - rotators.reserve(15); - rotators_2.reserve(15); - screwprops.reserve(10); - shocks.reserve(50); - shocks_2.reserve(50); - slidenodes.reserve(25); - soundsources.reserve(20); - soundsources2.reserve(20); - submeshes.reserve(50); - ties.reserve(25); - triggers.reserve(25); - turbojets.reserve(15); - turboprops_2.reserve(15); - videocameras.reserve(10); - wheels.reserve(6); - wheels_2.reserve(8); - wings.reserve(10); -} - -File::File(): - file_format_version(0), // Default = unset - hide_in_chooser(false), - enable_advanced_deformation(false), - rollon(false), - forward_commands(false), - import_commands(false), - lockgroup_default_nolock(false), - rescuer(false), - disable_default_sounds(false), - slide_nodes_connect_instantly(false), - collision_range(DEFAULT_COLLISION_RANGE), - minimass_skip_loaded_nodes(false), - report_num_errors(0), - report_num_warnings(0), - report_num_other(0) -{ - authors.reserve(10); - description.reserve(20); - root_module = std::make_shared(ROOT_MODULE_NAME); // Required to exist. -} + Fusedrag::Fusedrag() + : autocalc(false), approximate_width(0), area_coefficient(1.f), // Default + airfoil_name("NACA0009.afl") + { + } + + Hook::Hook() + : flag_self_lock(false), flag_auto_lock(false), flag_no_disable(false), flag_no_rope(false), flag_visible(false), + option_hook_range(HOOK_RANGE_DEFAULT), option_speed_coef(1.0f), option_max_force(HOOK_FORCE_DEFAULT), + option_hookgroup(-1), option_lockgroup(NODE_LOCKGROUP_DEFAULT), option_timer(HOOK_LOCK_TIMER_DEFAULT), + option_min_range_meters(0.f) + { + } + + NodeDefaults::NodeDefaults() : load_weight(-1.f), friction(1), volume(1), surface(1), options(0) + { + } + + Shock::Shock() : spring_rate(0), damping(0), short_bound(0), long_bound(0), precompression(1), options(0), detacher_group(0) + { + } + + Shock2::Shock2() + : spring_in(0), damp_in(0), progress_factor_spring_in(0), progress_factor_damp_in(0), spring_out(0), damp_out(0), + progress_factor_spring_out(0), progress_factor_damp_out(0), short_bound(0), long_bound(0), precompression(0), + options(0), detacher_group(0) + { + } + + Shock3::Shock3() + : spring_in(0), damp_in(0), damp_in_slow(0), split_vel_in(0), damp_in_fast(0), spring_out(0), damp_out(0), + damp_out_slow(0), split_vel_out(0), damp_out_fast(0), short_bound(0), long_bound(0), precompression(0), options(0), + detacher_group(0) + { + } + + SlideNode::SlideNode() + : spring_rate(9000000), break_force(0), tolerance(0), railgroup_id(-1), _railgroup_id_set(false), attachment_rate(1.f), + max_attachment_distance(0.1f), constraint_flags(0), _break_force_set(false) + { + rail_node_ranges.reserve(25); + } + + Tie::Tie() + : max_reach_length(0), auto_shorten_rate(0), min_length(0), max_length(0), is_invisible(false), disable_self_lock(false), + max_stress(100000.0f), // default, hardcoded in legacy SerializedRig.cpp, BTS_TIES + detacher_group(0), // Global detacher group + group(-1) // = group not set + { + } + + TractionControl::TractionControl() + : regulation_force(0), wheel_slip(0), fade_speed(0), pulse_per_sec(0), attr_is_on(false), attr_no_dashboard(false), + attr_no_toggle(false) + { + } + + Trigger::Trigger() + : shortbound_trigger_action(0), longbound_trigger_action(0), contraction_trigger_limit(0), expansion_trigger_limit(0), + options(0), boundary_timer(1.f), /* Default */ + detacher_group(0) + { + } + + VideoCamera::VideoCamera() + : offset(Ogre::Vector3::ZERO), rotation(Ogre::Vector3::ZERO), field_of_view(0), texture_width(0), texture_height(0), + min_clip_distance(0), max_clip_distance(0), camera_role(0), camera_mode(0) + { + } + + const std::string Wing::CONTROL_LEGAL_FLAGS("nabferSTcdghUVij"); // Static member init + + Wing::Wing() + : control_surface(CONTROL_n_NONE), chord_point(-1.f), min_deflection(-1.f), max_deflection(-1.f), + efficacy_coef(1.f) // So-called 'liftcoef'. Default = 1 + { + tex_coords[0] = 0.f; + tex_coords[1] = 0.f; + tex_coords[2] = 0.f; + tex_coords[3] = 0.f; + tex_coords[4] = 0.f; + tex_coords[5] = 0.f; + tex_coords[6] = 0.f; + tex_coords[7] = 0.f; + } + + void Animation::AddMotorSource(unsigned int source, unsigned int motor) + { + Animation::MotorSource motor_source; + motor_source.source = source; + motor_source.motor = motor; + this->motor_sources.push_back(motor_source); + } + + /* -------------------------------------------------------------------------- */ + /* File */ + /* -------------------------------------------------------------------------- */ + + const char *File::SectionToString(File::Section section) + { + switch (section) + { + case (File::SECTION_AIRBRAKES): return "airbrakes"; + case (File::SECTION_ANIMATORS): return "animators"; + case (File::SECTION_ANTI_LOCK_BRAKES): return "AntiLockBrakes"; + case (File::SECTION_AUTHOR): return "author"; + case (File::SECTION_AXLES): return "axles"; + case (File::SECTION_BEAMS): return "beams"; + case (File::SECTION_BRAKES): return "brakes"; + case (File::SECTION_CAMERAS): return "cameras"; + case (File::SECTION_CAMERA_RAIL): return "camerarail"; + case (File::SECTION_CINECAM): return "cinecam"; + case (File::SECTION_COLLISION_BOXES): return "collisionboxes"; + case (File::SECTION_COMMANDS): return "commands"; + case (File::SECTION_COMMANDS_2): return "commands2"; + case (File::SECTION_CONTACTERS): return "contacters"; + case (File::SECTION_ENGINE): return "engine"; + case (File::SECTION_ENGOPTION): return "engoption"; + case (File::SECTION_ENGTURBO): return "engturbo"; + case (File::SECTION_EXHAUSTS): return "exhausts"; + case (File::SECTION_FIXES): return "fixes"; + case (File::SECTION_FLARES): return "flares"; + case (File::SECTION_FLARES_2): return "flares2"; + case (File::SECTION_FLEXBODIES): return "flexbodies"; + case (File::SECTION_FLEX_BODY_WHEELS): return "flexbodywheels"; + case (File::SECTION_FUSEDRAG): return "fusedrag"; + case (File::SECTION_GLOBALS): return "globals"; + case (File::SECTION_GUI_SETTINGS): return "guisettings"; + case (File::SECTION_HYDROS): return "hydros"; + case (File::SECTION_HELP): return "help"; + case (File::SECTION_HOOKS): return "hooks"; + case (File::SECTION_INTERAXLES): return "interaxles"; + case (File::SECTION_LOCKGROUPS): return "lockgroups"; + case (File::SECTION_MANAGED_MATERIALS): return "managedmaterials"; + case (File::SECTION_MAT_FLARE_BINDINGS): return "materialflarebindings"; + case (File::SECTION_MESH_WHEELS): return "meshwheels"; + case (File::SECTION_MESH_WHEELS_2): return "meshwheels2"; + case (File::SECTION_MINIMASS): return "minimass"; + case (File::SECTION_NODES): return "nodes"; + case (File::SECTION_NODES_2): return "nodes2"; + case (File::SECTION_PARTICLES): return "particles"; + case (File::SECTION_PISTONPROPS): return "pistonprops"; + case (File::SECTION_PROPS): return "props"; + case (File::SECTION_RAILGROUPS): return "railgroups"; + case (File::SECTION_ROPABLES): return "ropables"; + case (File::SECTION_ROPES): return "ropes"; + case (File::SECTION_ROTATORS): return "rotators"; + case (File::SECTION_ROTATORS_2): return "rotators_2"; + case (File::SECTION_SCREWPROPS): return "screwprops"; + case (File::SECTION_SHOCKS): return "shocks"; + case (File::SECTION_SHOCKS_2): return "shocks2"; + case (File::SECTION_SHOCKS_3): return "shocks3"; + case (File::SECTION_SLIDENODES): return "slidenodes"; + case (File::SECTION_SOUNDSOURCES): return "soundsources"; + case (File::SECTION_SOUNDSOURCES2): return "soundsources2"; + case (File::SECTION_SLOPE_BRAKE): return "SlopeBrake"; + case (File::SECTION_SUBMESH): return "submesh"; + case (File::SECTION_TIES): return "ties"; + case (File::SECTION_TORQUE_CURVE): return "torquecurve"; + case (File::SECTION_TRACTION_CONTROL): return "TractionControl"; + case (File::SECTION_TRANSFER_CASE): return "transfercase"; + case (File::SECTION_TRIGGERS): return "triggers"; + case (File::SECTION_TRUCK_NAME): return ""; + case (File::SECTION_TURBOJETS): return "turbojets"; + case (File::SECTION_TURBOPROPS): return "turboprops"; + case (File::SECTION_TURBOPROPS_2): return "turboprops"; + case (File::SECTION_VIDEO_CAMERA): return "videocamera"; + case (File::SECTION_WHEELS): return "wheels"; + case (File::SECTION_WHEELS_2): return "wheels2"; + case (File::SECTION_WINGS): return "wings"; + + case (File::SECTION_NONE): return "SECTION_NONE"; + default: return ""; + } + } + + const char *File::SubsectionToString(File::Subsection subsection) + { + switch (subsection) + { + case (File::SUBSECTION_NONE): return "SUBSECTION_NONE"; + case (File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE): return "SUBSECTION_PROPLIKE_LINE"; + case (File::SUBSECTION__FLEXBODIES__FORSET_LINE): return "SUBSECTION_FORSET_LINE"; + case (File::SUBSECTION__SUBMESH__TEXCOORDS): return "SUBSECTION_TEXCOORDS"; + case (File::SUBSECTION__SUBMESH__CAB): return "SUBSECTION_CAB"; + default: return "~ UNKNOWN SUBSECTION ~"; + } + } + + const char *File::KeywordToString(File::Keyword keyword) + { + /* NOTE: Maintain alphabetical order! */ + + switch (keyword) + { + case (File::KEYWORD_AIRBRAKES): return "airbrakes"; + case (File::KEYWORD_ANIMATORS): return "animators"; + case (File::KEYWORD_ANTI_LOCK_BRAKES): return "AntiLockBrakes"; + case (File::KEYWORD_AUTHOR): return "author"; + case (File::KEYWORD_AXLES): return "axles"; + case (File::KEYWORD_BEAMS): return "beams"; + case (File::KEYWORD_BRAKES): return "brakes"; + case (File::KEYWORD_CAB): return "submesh >> cab"; + case (File::KEYWORD_CAMERAS): return "cameras"; + case (File::KEYWORD_CAMERARAIL): return "camerarail"; + case (File::KEYWORD_CINECAM): return "cinecam"; + case (File::KEYWORD_COLLISIONBOXES): return "collisionboxes"; + case (File::KEYWORD_COMMANDS): return "commands"; + case (File::KEYWORD_COMMANDS2): return "commands2"; + case (File::KEYWORD_CONTACTERS): return "contacters"; + case (File::KEYWORD_CRUISECONTROL): return "cruisecontrol"; + case (File::KEYWORD_DESCRIPTION): return "description"; + case (File::KEYWORD_ENGINE): return "engine"; + case (File::KEYWORD_ENGOPTION): return "engoption"; + case (File::KEYWORD_ENGTURBO): return "engturbo"; + case (File::KEYWORD_EXHAUSTS): return "exhausts"; + case (File::KEYWORD_FILEINFO): return "fileinfo"; + case (File::KEYWORD_FILEFORMATVERSION): return "fileformatversion"; + case (File::KEYWORD_FIXES): return "fixes"; + case (File::KEYWORD_FLARES): return "flares"; + case (File::KEYWORD_FLARES2): return "flares2"; + case (File::KEYWORD_FLEXBODIES): return "flexbodies"; + case (File::KEYWORD_FLEXBODYWHEELS): return "flexbodywheels"; + case (File::KEYWORD_FUSEDRAG): return "fusedrag"; + case (File::KEYWORD_GLOBALS): return "globals"; + case (File::KEYWORD_GUISETTINGS): return "guisettings"; + case (File::KEYWORD_HELP): return "help"; + case (File::KEYWORD_HOOKS): return "hooks"; + case (File::KEYWORD_HYDROS): return "hydros"; + case (File::KEYWORD_INTERAXLES): return "interaxles"; + case (File::KEYWORD_MANAGEDMATERIALS): return "managedmaterials"; + case (File::KEYWORD_MATERIALFLAREBINDINGS): return "materialflarebindings"; + case (File::KEYWORD_MESHWHEELS): return "meshwheels"; + case (File::KEYWORD_MESHWHEELS2): return "meshwheels2"; + case (File::KEYWORD_MINIMASS): return "minimass"; + case (File::KEYWORD_NODES): return "nodes"; + case (File::KEYWORD_NODES2): return "nodes2"; + case (File::KEYWORD_PARTICLES): return "particles"; + case (File::KEYWORD_PISTONPROPS): return "pistonprops"; + case (File::KEYWORD_PROPS): return "props"; + case (File::KEYWORD_RAILGROUPS): return "railgroups"; + case (File::KEYWORD_ROPABLES): return "ropables"; + case (File::KEYWORD_ROPES): return "ropes"; + case (File::KEYWORD_ROTATORS): return "rotators"; + case (File::KEYWORD_ROTATORS2): return "rotators_2"; + case (File::KEYWORD_SCREWPROPS): return "screwprops"; + case (File::KEYWORD_SHOCKS): return "shocks"; + case (File::KEYWORD_SHOCKS2): return "shocks2"; + case (File::KEYWORD_SHOCKS3): return "shocks3"; + case (File::KEYWORD_SLIDENODES): return "slidenodes"; + case (File::KEYWORD_SLOPE_BRAKE): return "SlopeBrake"; + case (File::KEYWORD_SOUNDSOURCES): return "soundsources"; + case (File::KEYWORD_SOUNDSOURCES2): return "soundsources2"; + case (File::KEYWORD_SUBMESH): return "submesh"; + case (File::KEYWORD_TEXCOORDS): return "submesh >> texcoords"; + case (File::KEYWORD_TIES): return "ties"; + case (File::KEYWORD_TORQUECURVE): return "torquecurve"; + case (File::KEYWORD_TRACTION_CONTROL): return "TractionControl"; + case (File::KEYWORD_TRANSFER_CASE): return "transfercase"; + case (File::KEYWORD_TRIGGERS): return "triggers"; + case (File::KEYWORD_TURBOJETS): return "turbojets"; + case (File::KEYWORD_TURBOPROPS): return "turboprops"; + case (File::KEYWORD_TURBOPROPS2): return "turboprops2"; + case (File::KEYWORD_VIDEOCAMERA): return "videocamera"; + case (File::KEYWORD_WHEELS): return "wheels"; + case (File::KEYWORD_WHEELS2): return "wheels2"; + case (File::KEYWORD_WINGS): return "wings"; + + default: return "~Unknown~"; + } + } + + File::Module::Module(Ogre::String const &name) : name(name) + { + /* Pre-allocate */ + airbrakes.reserve(10); + animators.reserve(50); + axles.reserve(10); + beams.reserve(1000); + cameras.reserve(10); + camera_rails.reserve(10); + collision_boxes.reserve(10); + commands_2.reserve(35); + exhausts.reserve(6); + flares_2.reserve(10); + flexbodies.reserve(15); + hooks.reserve(10); + hydros.reserve(25); + lockgroups.reserve(10); + managed_materials.reserve(25); + material_flare_bindings.reserve(10); + mesh_wheels.reserve(10); + nodes.reserve(2000); + node_collisions.reserve(100); + particles.reserve(25); + pistonprops.reserve(25); + props.reserve(50); + railgroups.reserve(10); + ropables.reserve(50); + ropes.reserve(25); + rotators.reserve(15); + rotators_2.reserve(15); + screwprops.reserve(10); + shocks.reserve(50); + shocks_2.reserve(50); + slidenodes.reserve(25); + soundsources.reserve(20); + soundsources2.reserve(20); + submeshes.reserve(50); + ties.reserve(25); + triggers.reserve(25); + turbojets.reserve(15); + turboprops_2.reserve(15); + videocameras.reserve(10); + wheels.reserve(6); + wheels_2.reserve(8); + wings.reserve(10); + } + + File::File() + : file_format_version(0), // Default = unset + hide_in_chooser(false), enable_advanced_deformation(false), rollon(false), forward_commands(false), + import_commands(false), lockgroup_default_nolock(false), rescuer(false), disable_default_sounds(false), + slide_nodes_connect_instantly(false), collision_range(DEFAULT_COLLISION_RANGE), minimass_skip_loaded_nodes(false), + report_num_errors(0), report_num_warnings(0), report_num_other(0) + { + authors.reserve(10); + description.reserve(20); + root_module = std::make_shared(ROOT_MODULE_NAME); // Required to exist. + } } /* namespace RigDef */ diff --git a/source/main/resources/rig_def_fileformat/RigDef_File.h b/source/main/resources/rig_def_fileformat/RigDef_File.h index a94c411514..c1cc217d33 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_File.h +++ b/source/main/resources/rig_def_fileformat/RigDef_File.h @@ -19,2350 +19,2337 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file RigDef_File.h @author Petr Ohlidal @date 12/2013 - @brief Structures which represent a rig-definition file (1:1 match) + @brief Structures which represent a rig-definition file (1:1 match) Values are initialised to their defaults, or 0 if there's no default. NOTE ON ARCHITECTURE: - These structs were designed for a single purpose - to bring data - from rig def. file. Do not use them for any other purpose, don't + These structs were designed for a single purpose - to bring data + from rig def. file. Do not use them for any other purpose, don't modify them beyond their original purpose. Avoid modifying their contents, only Parser should do that; use them only for reading; - NOTES: + NOTES: * Since these are open structs, the m_ prefix for member variables is not used. * Members prefixed by _ are helper flags which mark special values or missing values. */ #pragma once +#include "BeamConstants.h" #include "BitFlags.h" - #include "RigDef_Node.h" -#include "BeamConstants.h" +#include +#include +#include #include #include -#include #include -#include -#include -#include +#include -namespace RigDef { +namespace RigDef +{ -extern const char* ROOT_MODULE_NAME; + extern const char *ROOT_MODULE_NAME; -/* -------------------------------------------------------------------------- */ -/* Utility */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Utility */ + /* -------------------------------------------------------------------------- */ -struct CameraSettings -{ - CameraSettings(): - mode(MODE_ALWAYS), - cinecam_index(0) - {} + struct CameraSettings + { + CameraSettings() : mode(MODE_ALWAYS), cinecam_index(0) + { + } - enum Mode + enum Mode + { + MODE_ALWAYS = -2, + MODE_EXTERNAL = -1, + MODE_CINECAM = 1, + + MODE_INVALID = 0xFFFFFFFF + }; + + Mode mode; + unsigned int cinecam_index; + }; + + /* -------------------------------------------------------------------------- */ + /* Directive SET_NODE_DEFAULTS */ + /* -------------------------------------------------------------------------- */ + + struct NodeDefaults { - MODE_ALWAYS = -2, - MODE_EXTERNAL = -1, - MODE_CINECAM = 1, + NodeDefaults(); - MODE_INVALID = 0xFFFFFFFF + float load_weight; + float friction; + float volume; + float surface; + unsigned int options; ///< Bit flags }; - Mode mode; - unsigned int cinecam_index; -}; + /* -------------------------------------------------------------------------- */ + /* Directive SET_BEAM_DEFAULTS_SCALE */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Directive SET_NODE_DEFAULTS */ -/* -------------------------------------------------------------------------- */ + struct BeamDefaultsScale + { + BeamDefaultsScale() + : springiness(1), damping_constant(1), deformation_threshold_constant(1), breaking_threshold_constant(1) + { + } -struct NodeDefaults -{ - NodeDefaults(); + float springiness; + float damping_constant; + float deformation_threshold_constant; + float breaking_threshold_constant; + }; - float load_weight; - float friction; - float volume; - float surface; - unsigned int options; ///< Bit flags -}; + /* -------------------------------------------------------------------------- */ + /* Directive SET_BEAM_DEFAULTS */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Directive SET_BEAM_DEFAULTS_SCALE */ -/* -------------------------------------------------------------------------- */ + struct BeamDefaults + { + BeamDefaults() + : // NOTE: -1.f is 'empty value'; replaced by constant in parser. + springiness(-1.f), damping_constant(-1.f), deformation_threshold(-1.f), visual_beam_diameter(-1.f), + beam_material_name("tracks/beam"), plastic_deform_coef(0.f), // This is a default + breaking_threshold(-1.f), _enable_advanced_deformation(false), _is_plastic_deform_coef_user_defined(false), + _is_user_defined(false) + { + } -struct BeamDefaultsScale -{ - BeamDefaultsScale(): - springiness(1), - damping_constant(1), - deformation_threshold_constant(1), - breaking_threshold_constant(1) - {} - - float springiness; - float damping_constant; - float deformation_threshold_constant; - float breaking_threshold_constant; -}; - -/* -------------------------------------------------------------------------- */ -/* Directive SET_BEAM_DEFAULTS */ -/* -------------------------------------------------------------------------- */ - -struct BeamDefaults -{ - BeamDefaults(): // NOTE: -1.f is 'empty value'; replaced by constant in parser. - springiness(-1.f), - damping_constant(-1.f), - deformation_threshold(-1.f), - visual_beam_diameter(-1.f), - beam_material_name("tracks/beam"), - plastic_deform_coef(0.f), // This is a default - breaking_threshold(-1.f), - _enable_advanced_deformation(false), - _is_plastic_deform_coef_user_defined(false), - _is_user_defined(false) - {} - - float GetScaledSpringiness() - { - return springiness * scale.springiness; - } - - float GetScaledDamping() - { - return damping_constant * scale.damping_constant; - } - - float GetScaledBreakingThreshold() - { - return breaking_threshold * scale.breaking_threshold_constant; - } - - inline float GetScaledDeformThreshold() const - { - return deformation_threshold * scale.deformation_threshold_constant; - } - - float springiness; - float damping_constant; - float deformation_threshold; - float breaking_threshold; - float visual_beam_diameter; - Ogre::String beam_material_name; - float plastic_deform_coef; - bool _enable_advanced_deformation; ///< Informs whether "enable_advanced_deformation" directive preceded these defaults. - bool _is_plastic_deform_coef_user_defined; - bool _is_user_defined; ///< Informs whether these data were read from "set_beam_defaults" directive or filled in by the parser on startup. - BeamDefaultsScale scale; -}; - -/* -------------------------------------------------------------------------- */ -/* Hybrid section MINIMASS */ -/* -------------------------------------------------------------------------- */ - -struct MinimassPreset -{ - enum Option + float GetScaledSpringiness() + { + return springiness * scale.springiness; + } + + float GetScaledDamping() + { + return damping_constant * scale.damping_constant; + } + + float GetScaledBreakingThreshold() + { + return breaking_threshold * scale.breaking_threshold_constant; + } + + inline float GetScaledDeformThreshold() const + { + return deformation_threshold * scale.deformation_threshold_constant; + } + + float springiness; + float damping_constant; + float deformation_threshold; + float breaking_threshold; + float visual_beam_diameter; + Ogre::String beam_material_name; + float plastic_deform_coef; + bool _enable_advanced_deformation; ///< Informs whether "enable_advanced_deformation" directive preceded these defaults. + bool _is_plastic_deform_coef_user_defined; + bool _is_user_defined; ///< Informs whether these data were read from "set_beam_defaults" directive or filled in by the + ///< parser on startup. + BeamDefaultsScale scale; + }; + + /* -------------------------------------------------------------------------- */ + /* Hybrid section MINIMASS */ + /* -------------------------------------------------------------------------- */ + + struct MinimassPreset { - OPTION_n_FILLER = 'n', //!< Updates the global minimass - OPTION_l_SKIP_LOADED = 'l' //!< Only apply minimum mass to nodes without "L" option. + enum Option + { + OPTION_n_FILLER = 'n', //!< Updates the global minimass + OPTION_l_SKIP_LOADED = 'l' //!< Only apply minimum mass to nodes without "L" option. + }; + + MinimassPreset() : min_mass(DEFAULT_MINIMASS) + { + } + + explicit MinimassPreset(float m) : min_mass(m) + { + } + + float min_mass; //!< minimum node mass in Kg }; - MinimassPreset(): min_mass(DEFAULT_MINIMASS) - {} + /* -------------------------------------------------------------------------- */ + /* Directive SET_DEFAULT_INERTIA */ + /* -------------------------------------------------------------------------- */ - explicit MinimassPreset(float m): min_mass(m) - {} + /** Common base for DefaultInertia and Command2Inertia */ + struct Inertia + { + Inertia() : start_delay_factor(0), stop_delay_factor(0) + { + } - float min_mass; //!< minimum node mass in Kg -}; + float start_delay_factor; + float stop_delay_factor; + Ogre::String start_function; + Ogre::String stop_function; + }; -/* -------------------------------------------------------------------------- */ -/* Directive SET_DEFAULT_INERTIA */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Directive SET_MANAGEDMATERIALS_OPTIONS */ + /* -------------------------------------------------------------------------- */ -/** Common base for DefaultInertia and Command2Inertia */ -struct Inertia -{ - Inertia(): - start_delay_factor(0), - stop_delay_factor(0) - {} - - float start_delay_factor; - float stop_delay_factor; - Ogre::String start_function; - Ogre::String stop_function; -}; - -/* -------------------------------------------------------------------------- */ -/* Directive SET_MANAGEDMATERIALS_OPTIONS */ -/* -------------------------------------------------------------------------- */ - -struct ManagedMaterialsOptions -{ - ManagedMaterialsOptions(): - double_sided(false) - {} + struct ManagedMaterialsOptions + { + ManagedMaterialsOptions() : double_sided(false) + { + } - bool double_sided; -}; + bool double_sided; + }; -/* -------------------------------------------------------------------------- */ -/* Directive SET_SHADOWS */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Directive SET_SHADOWS */ + /* -------------------------------------------------------------------------- */ -struct ShadowOptions -{ - ShadowOptions(): - shadow_mode(0) - {} + struct ShadowOptions + { + ShadowOptions() : shadow_mode(0) + { + } - int shadow_mode; -}; + int shadow_mode; + }; -/* -------------------------------------------------------------------------- */ -/* Section GLOBALS */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section GLOBALS */ + /* -------------------------------------------------------------------------- */ -struct Globals -{ - Globals(): - dry_mass(0), /* The default */ - cargo_mass(0) /* The default */ - {} + struct Globals + { + Globals() + : dry_mass(0), /* The default */ + cargo_mass(0) /* The default */ + { + } - float dry_mass; - float cargo_mass; - Ogre::String material_name; -}; + float dry_mass; + float cargo_mass; + Ogre::String material_name; + }; -/* -------------------------------------------------------------------------- */ -/* Section GUISETTINGS */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section GUISETTINGS */ + /* -------------------------------------------------------------------------- */ -struct GuiSettings -{ - GuiSettings(): - speedo_highest_kph(DEFAULT_SPEEDO_MAX), - use_max_rpm(false), /* This is default */ - interactive_overview_map_mode(MAP_MODE_OFF) - {} + struct GuiSettings + { + GuiSettings() + : speedo_highest_kph(DEFAULT_SPEEDO_MAX), use_max_rpm(false), /* This is default */ + interactive_overview_map_mode(MAP_MODE_OFF) + { + } + + enum MapMode + { + MAP_MODE_OFF = 1, + MAP_MODE_SIMPLE, + MAP_MODE_ZOOM, + + MAP_MODE_INVALID = 0xFFFFFFFF, + }; + + const static unsigned int DEFAULT_SPEEDO_MAX = 140; - enum MapMode + std::string tacho_material; + std::string speedo_material; + unsigned int speedo_highest_kph; + bool use_max_rpm; + Ogre::String help_material; + MapMode interactive_overview_map_mode; + std::list dashboard_layouts; + std::list rtt_dashboard_layouts; + }; + + /* -------------------------------------------------------------------------- */ + /* Section AIRBRAKES */ + /* -------------------------------------------------------------------------- */ + + struct Airbrake { - MAP_MODE_OFF = 1, - MAP_MODE_SIMPLE, - MAP_MODE_ZOOM, + Airbrake(); - MAP_MODE_INVALID = 0xFFFFFFFF, + Node::Ref reference_node; + Node::Ref x_axis_node; + Node::Ref y_axis_node; + Node::Ref aditional_node; + Ogre::Vector3 offset; + float width; + float height; + float max_inclination_angle; + float texcoord_x1; + float texcoord_x2; + float texcoord_y1; + float texcoord_y2; + float lift_coefficient; }; - const static unsigned int DEFAULT_SPEEDO_MAX = 140; + /* -------------------------------------------------------------------------- */ + /* Directive ADD_ANIMATION */ + /* -------------------------------------------------------------------------- */ + + struct Animation + { + struct MotorSource + { + MotorSource() : source(0), motor(0) + { + } + + static const unsigned int SOURCE_AERO_THROTTLE = BITMASK(1); + static const unsigned int SOURCE_AERO_RPM = BITMASK(2); + static const unsigned int SOURCE_AERO_TORQUE = BITMASK(3); + static const unsigned int SOURCE_AERO_PITCH = BITMASK(4); + static const unsigned int SOURCE_AERO_STATUS = BITMASK(5); + + unsigned int source; + unsigned int motor; + }; - std::string tacho_material; - std::string speedo_material; - unsigned int speedo_highest_kph; - bool use_max_rpm; - Ogre::String help_material; - MapMode interactive_overview_map_mode; - std::list dashboard_layouts; - std::list rtt_dashboard_layouts; -}; + Animation() : ratio(0), lower_limit(-1.f), upper_limit(-1.f), source(0), mode(0) + { + } + + BITMASK_PROPERTY(source, 1, SOURCE_AIRSPEED, HasSource_AirSpeed, SetHasSource_AirSpeed) + BITMASK_PROPERTY(source, 2, SOURCE_VERTICAL_VELOCITY, HasSource_VerticalVelocity, SetHasSource_VerticalVelocity) + BITMASK_PROPERTY(source, 3, SOURCE_ALTIMETER_100K, HasSource_AltiMeter100k, SetHasSource_AltiMeter100k) + BITMASK_PROPERTY(source, 4, SOURCE_ALTIMETER_10K, HasSource_AltiMeter10k, SetHasSource_AltiMeter10k) + BITMASK_PROPERTY(source, 5, SOURCE_ALTIMETER_1K, HasSource_AltiMeter1k, SetHasSource_AltiMeter1k) + BITMASK_PROPERTY(source, 6, SOURCE_ANGLE_OF_ATTACK, HasSource_AOA, SetHasSource_AOA) + BITMASK_PROPERTY(source, 7, SOURCE_FLAP, HasSource_Flap, SetHasSource_Flap) + BITMASK_PROPERTY(source, 8, SOURCE_AIR_BRAKE, HasSource_AirBrake, SetHasSource_AirBrake) + BITMASK_PROPERTY(source, 9, SOURCE_ROLL, HasSource_Roll, SetHasSource_Roll) + BITMASK_PROPERTY(source, 10, SOURCE_PITCH, HasSource_Pitch, SetHasSource_Pitch) + BITMASK_PROPERTY(source, 11, SOURCE_BRAKES, HasSource_Brakes, SetHasSource_Brakes) + BITMASK_PROPERTY(source, 12, SOURCE_ACCEL, HasSource_Accel, SetHasSource_Accel) + BITMASK_PROPERTY(source, 13, SOURCE_CLUTCH, HasSource_Clutch, SetHasSource_Clutch) + BITMASK_PROPERTY(source, 14, SOURCE_SPEEDO, HasSource_Speedo, SetHasSource_Speedo) + BITMASK_PROPERTY(source, 15, SOURCE_TACHO, HasSource_Tacho, SetHasSource_Tacho) + BITMASK_PROPERTY(source, 16, SOURCE_TURBO, HasSource_Turbo, SetHasSource_Turbo) + BITMASK_PROPERTY(source, 17, SOURCE_PARKING, HasSource_ParkingBrake, SetHasSource_ParkingBrake) + BITMASK_PROPERTY(source, 18, SOURCE_SHIFT_LEFT_RIGHT, HasSource_ManuShiftLeftRight, SetHasSource_ManuShiftLeftRight) + BITMASK_PROPERTY(source, 19, SOURCE_SHIFT_BACK_FORTH, HasSource_ManuShiftBackForth, SetHasSource_ManuShiftBackForth) + BITMASK_PROPERTY(source, 20, SOURCE_SEQUENTIAL_SHIFT, HasSource_SeqentialShift, SetHasSource_SeqentialShift) + BITMASK_PROPERTY(source, 21, SOURCE_SHIFTERLIN, HasSource_ShifterLin, SetHasSource_ShifterLin) + BITMASK_PROPERTY(source, 22, SOURCE_TORQUE, HasSource_Torque, SetHasSource_Torque) + BITMASK_PROPERTY(source, 23, SOURCE_HEADING, HasSource_Heading, SetHasSource_Heading) + BITMASK_PROPERTY(source, 24, SOURCE_DIFFLOCK, HasSource_DiffLock, SetHasSource_DiffLock) + BITMASK_PROPERTY(source, 25, SOURCE_BOAT_RUDDER, HasSource_BoatRudder, SetHasSource_BoatRudder) + BITMASK_PROPERTY(source, 26, SOURCE_BOAT_THROTTLE, HasSource_BoatThrottle, SetHasSource_BoatThrottle) + BITMASK_PROPERTY(source, 27, SOURCE_STEERING_WHEEL, HasSource_SteeringWheel, SetHasSource_SteeringWheel) + BITMASK_PROPERTY(source, 28, SOURCE_AILERON, HasSource_Aileron, SetHasSource_Aileron) + BITMASK_PROPERTY(source, 29, SOURCE_ELEVATOR, HasSource_Elevator, SetHasSource_Elevator) + BITMASK_PROPERTY(source, 30, SOURCE_AIR_RUDDER, HasSource_AerialRudder, SetHasSource_AerialRudder) + BITMASK_PROPERTY(source, 31, SOURCE_PERMANENT, HasSource_Permanent, SetHasSource_Permanent) + BITMASK_PROPERTY(source, 32, SOURCE_EVENT, HasSource_Event, SetHasSource_Event) // Full house32 + + static const unsigned int MODE_ROTATION_X = BITMASK(1); + static const unsigned int MODE_ROTATION_Y = BITMASK(2); + static const unsigned int MODE_ROTATION_Z = BITMASK(3); + static const unsigned int MODE_OFFSET_X = BITMASK(4); + static const unsigned int MODE_OFFSET_Y = BITMASK(5); + static const unsigned int MODE_OFFSET_Z = BITMASK(6); + static const unsigned int MODE_AUTO_ANIMATE = BITMASK(7); + static const unsigned int MODE_NO_FLIP = BITMASK(8); + static const unsigned int MODE_BOUNCE = BITMASK(9); + static const unsigned int MODE_EVENT_LOCK = BITMASK(10); + + float ratio; + float lower_limit; + float upper_limit; + unsigned int source; + std::list motor_sources; + unsigned int mode; + + // NOTE: MSVC highlights 'event' as keyword: http://msdn.microsoft.com/en-us/library/4b612y2s%28v=vs.100%29.aspx + // But it's ok to use as identifier in this context: http://msdn.microsoft.com/en-us/library/8d7y7wz6%28v=vs.100%29.aspx + Ogre::String event; + + void AddMotorSource(unsigned int source, unsigned int motor); + }; -/* -------------------------------------------------------------------------- */ -/* Section AIRBRAKES */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section AXLES */ + /* -------------------------------------------------------------------------- */ -struct Airbrake -{ - Airbrake(); - - Node::Ref reference_node; - Node::Ref x_axis_node; - Node::Ref y_axis_node; - Node::Ref aditional_node; - Ogre::Vector3 offset; - float width; - float height; - float max_inclination_angle; - float texcoord_x1; - float texcoord_x2; - float texcoord_y1; - float texcoord_y2; - float lift_coefficient; -}; - -/* -------------------------------------------------------------------------- */ -/* Directive ADD_ANIMATION */ -/* -------------------------------------------------------------------------- */ - -struct Animation -{ - struct MotorSource + struct Axle { - MotorSource(): - source(0), - motor(0) - {} + Axle() : options(0) + { + } - static const unsigned int SOURCE_AERO_THROTTLE = BITMASK(1); - static const unsigned int SOURCE_AERO_RPM = BITMASK(2); - static const unsigned int SOURCE_AERO_TORQUE = BITMASK(3); - static const unsigned int SOURCE_AERO_PITCH = BITMASK(4); - static const unsigned int SOURCE_AERO_STATUS = BITMASK(5); + static const char OPTION_o_OPEN = 'o'; + static const char OPTION_l_LOCKED = 'l'; + static const char OPTION_s_SPLIT = 's'; + static const char OPTION_s_VISCOUS = 'v'; - unsigned int source; - unsigned int motor; + Node::Ref wheels[2][2]; + std::vector options; //!< Order matters! }; - Animation(): - ratio(0), - lower_limit(-1.f), - upper_limit(-1.f), - source(0), - mode(0) - {} - - BITMASK_PROPERTY( source, 1, SOURCE_AIRSPEED , HasSource_AirSpeed , SetHasSource_AirSpeed ) - BITMASK_PROPERTY( source, 2, SOURCE_VERTICAL_VELOCITY , HasSource_VerticalVelocity , SetHasSource_VerticalVelocity ) - BITMASK_PROPERTY( source, 3, SOURCE_ALTIMETER_100K , HasSource_AltiMeter100k , SetHasSource_AltiMeter100k ) - BITMASK_PROPERTY( source, 4, SOURCE_ALTIMETER_10K , HasSource_AltiMeter10k , SetHasSource_AltiMeter10k ) - BITMASK_PROPERTY( source, 5, SOURCE_ALTIMETER_1K , HasSource_AltiMeter1k , SetHasSource_AltiMeter1k ) - BITMASK_PROPERTY( source, 6, SOURCE_ANGLE_OF_ATTACK , HasSource_AOA , SetHasSource_AOA ) - BITMASK_PROPERTY( source, 7, SOURCE_FLAP , HasSource_Flap , SetHasSource_Flap ) - BITMASK_PROPERTY( source, 8, SOURCE_AIR_BRAKE , HasSource_AirBrake , SetHasSource_AirBrake ) - BITMASK_PROPERTY( source, 9, SOURCE_ROLL , HasSource_Roll , SetHasSource_Roll ) - BITMASK_PROPERTY( source, 10, SOURCE_PITCH , HasSource_Pitch , SetHasSource_Pitch ) - BITMASK_PROPERTY( source, 11, SOURCE_BRAKES , HasSource_Brakes , SetHasSource_Brakes ) - BITMASK_PROPERTY( source, 12, SOURCE_ACCEL , HasSource_Accel , SetHasSource_Accel ) - BITMASK_PROPERTY( source, 13, SOURCE_CLUTCH , HasSource_Clutch , SetHasSource_Clutch ) - BITMASK_PROPERTY( source, 14, SOURCE_SPEEDO , HasSource_Speedo , SetHasSource_Speedo ) - BITMASK_PROPERTY( source, 15, SOURCE_TACHO , HasSource_Tacho , SetHasSource_Tacho ) - BITMASK_PROPERTY( source, 16, SOURCE_TURBO , HasSource_Turbo , SetHasSource_Turbo ) - BITMASK_PROPERTY( source, 17, SOURCE_PARKING , HasSource_ParkingBrake , SetHasSource_ParkingBrake ) - BITMASK_PROPERTY( source, 18, SOURCE_SHIFT_LEFT_RIGHT , HasSource_ManuShiftLeftRight , SetHasSource_ManuShiftLeftRight ) - BITMASK_PROPERTY( source, 19, SOURCE_SHIFT_BACK_FORTH , HasSource_ManuShiftBackForth , SetHasSource_ManuShiftBackForth ) - BITMASK_PROPERTY( source, 20, SOURCE_SEQUENTIAL_SHIFT , HasSource_SeqentialShift , SetHasSource_SeqentialShift ) - BITMASK_PROPERTY( source, 21, SOURCE_SHIFTERLIN , HasSource_ShifterLin , SetHasSource_ShifterLin ) - BITMASK_PROPERTY( source, 22, SOURCE_TORQUE , HasSource_Torque , SetHasSource_Torque ) - BITMASK_PROPERTY( source, 23, SOURCE_HEADING , HasSource_Heading , SetHasSource_Heading ) - BITMASK_PROPERTY( source, 24, SOURCE_DIFFLOCK , HasSource_DiffLock , SetHasSource_DiffLock ) - BITMASK_PROPERTY( source, 25, SOURCE_BOAT_RUDDER , HasSource_BoatRudder , SetHasSource_BoatRudder ) - BITMASK_PROPERTY( source, 26, SOURCE_BOAT_THROTTLE , HasSource_BoatThrottle , SetHasSource_BoatThrottle ) - BITMASK_PROPERTY( source, 27, SOURCE_STEERING_WHEEL , HasSource_SteeringWheel , SetHasSource_SteeringWheel ) - BITMASK_PROPERTY( source, 28, SOURCE_AILERON , HasSource_Aileron , SetHasSource_Aileron ) - BITMASK_PROPERTY( source, 29, SOURCE_ELEVATOR , HasSource_Elevator , SetHasSource_Elevator ) - BITMASK_PROPERTY( source, 30, SOURCE_AIR_RUDDER , HasSource_AerialRudder , SetHasSource_AerialRudder ) - BITMASK_PROPERTY( source, 31, SOURCE_PERMANENT , HasSource_Permanent , SetHasSource_Permanent ) - BITMASK_PROPERTY( source, 32, SOURCE_EVENT , HasSource_Event , SetHasSource_Event ) // Full house32 - - static const unsigned int MODE_ROTATION_X = BITMASK(1); - static const unsigned int MODE_ROTATION_Y = BITMASK(2); - static const unsigned int MODE_ROTATION_Z = BITMASK(3); - static const unsigned int MODE_OFFSET_X = BITMASK(4); - static const unsigned int MODE_OFFSET_Y = BITMASK(5); - static const unsigned int MODE_OFFSET_Z = BITMASK(6); - static const unsigned int MODE_AUTO_ANIMATE = BITMASK(7); - static const unsigned int MODE_NO_FLIP = BITMASK(8); - static const unsigned int MODE_BOUNCE = BITMASK(9); - static const unsigned int MODE_EVENT_LOCK = BITMASK(10); - - float ratio; - float lower_limit; - float upper_limit; - unsigned int source; - std::list motor_sources; - unsigned int mode; - - // NOTE: MSVC highlights 'event' as keyword: http://msdn.microsoft.com/en-us/library/4b612y2s%28v=vs.100%29.aspx - // But it's ok to use as identifier in this context: http://msdn.microsoft.com/en-us/library/8d7y7wz6%28v=vs.100%29.aspx - Ogre::String event; - - void AddMotorSource(unsigned int source, unsigned int motor); -}; - -/* -------------------------------------------------------------------------- */ -/* Section AXLES */ -/* -------------------------------------------------------------------------- */ - -struct Axle -{ - Axle(): - options(0) - {} + /* -------------------------------------------------------------------------- */ + /* Section INTERAXLES */ + /* -------------------------------------------------------------------------- */ - static const char OPTION_o_OPEN = 'o'; - static const char OPTION_l_LOCKED = 'l'; - static const char OPTION_s_SPLIT = 's'; - static const char OPTION_s_VISCOUS = 'v'; + struct InterAxle + { + InterAxle() : a1(0), a2(0), options(0) + { + } - Node::Ref wheels[2][2]; - std::vector options; //!< Order matters! -}; + static const char OPTION_o_OPEN = 'o'; + static const char OPTION_l_LOCKED = 'l'; + static const char OPTION_s_SPLIT = 's'; + static const char OPTION_s_VISCOUS = 'v'; -/* -------------------------------------------------------------------------- */ -/* Section INTERAXLES */ -/* -------------------------------------------------------------------------- */ + int a1; + int a2; + std::vector options; //!< Order matters! + }; -struct InterAxle -{ - InterAxle(): - a1(0), - a2(0), - options(0) - {} - - static const char OPTION_o_OPEN = 'o'; - static const char OPTION_l_LOCKED = 'l'; - static const char OPTION_s_SPLIT = 's'; - static const char OPTION_s_VISCOUS = 'v'; - - int a1; - int a2; - std::vector options; //!< Order matters! -}; - -/* -------------------------------------------------------------------------- */ -/* Section TRANSFER_CASE */ -/* -------------------------------------------------------------------------- */ - -struct TransferCase -{ - TransferCase(): - a1(0), - a2(-1), - has_2wd(true), - has_2wd_lo(false), - gear_ratios({1.0f}) - {} - - int a1; - int a2; - bool has_2wd; - bool has_2wd_lo; - std::vector gear_ratios; -}; - -/* -------------------------------------------------------------------------- */ -/* Section BEAMS */ -/* -------------------------------------------------------------------------- */ - -struct Beam -{ - Beam(): - options(0), - extension_break_limit(0), /* This is default */ - _has_extension_break_limit(false), - detacher_group(0) /* 0 = Default detacher group */ - {} - - BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE, HasFlag_i_Invisible, SetFlag_i_Invisible); - BITMASK_PROPERTY(options, 2, OPTION_r_ROPE , HasFlag_r_Rope , SetFlag_r_Rope ); - BITMASK_PROPERTY(options, 3, OPTION_s_SUPPORT , HasFlag_s_Support , SetFlag_s_Support ); - - Node::Ref nodes[2]; - unsigned int options; ///< Bit flags - float extension_break_limit; - bool _has_extension_break_limit; - int detacher_group; - std::shared_ptr defaults; -}; - -/* -------------------------------------------------------------------------- */ -/* Section CAMERAS */ -/* -------------------------------------------------------------------------- */ - -struct Camera -{ - Node::Ref center_node; - Node::Ref back_node; - Node::Ref left_node; -}; + /* -------------------------------------------------------------------------- */ + /* Section TRANSFER_CASE */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section CAMERARAIL */ -/* -------------------------------------------------------------------------- */ + struct TransferCase + { + TransferCase() : a1(0), a2(-1), has_2wd(true), has_2wd_lo(false), gear_ratios({1.0f}) + { + } -struct CameraRail -{ - CameraRail() + int a1; + int a2; + bool has_2wd; + bool has_2wd_lo; + std::vector gear_ratios; + }; + + /* -------------------------------------------------------------------------- */ + /* Section BEAMS */ + /* -------------------------------------------------------------------------- */ + + struct Beam { - nodes.reserve(25); - } + Beam() + : options(0), extension_break_limit(0), /* This is default */ + _has_extension_break_limit(false), detacher_group(0) /* 0 = Default detacher group */ + { + } + + BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE, HasFlag_i_Invisible, SetFlag_i_Invisible); + BITMASK_PROPERTY(options, 2, OPTION_r_ROPE, HasFlag_r_Rope, SetFlag_r_Rope); + BITMASK_PROPERTY(options, 3, OPTION_s_SUPPORT, HasFlag_s_Support, SetFlag_s_Support); + + Node::Ref nodes[2]; + unsigned int options; ///< Bit flags + float extension_break_limit; + bool _has_extension_break_limit; + int detacher_group; + std::shared_ptr defaults; + }; - std::vector nodes; -}; + /* -------------------------------------------------------------------------- */ + /* Section CAMERAS */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section CINECAM */ -/* -------------------------------------------------------------------------- */ + struct Camera + { + Node::Ref center_node; + Node::Ref back_node; + Node::Ref left_node; + }; -struct Cinecam -{ - Cinecam(): - position(Ogre::Vector3::ZERO), - spring(8000.f), - damping(800.f), - node_mass(20.f) - {} - - Ogre::Vector3 position; - Node::Ref nodes[8]; - float spring; - float damping; - float node_mass; - std::shared_ptr beam_defaults; - std::shared_ptr node_defaults; -}; - -/* -------------------------------------------------------------------------- */ -/* Section COLLISIONBOXES */ -/* -------------------------------------------------------------------------- */ - -struct CollisionBox -{ - CollisionBox() + /* -------------------------------------------------------------------------- */ + /* Section CAMERARAIL */ + /* -------------------------------------------------------------------------- */ + + struct CameraRail { - nodes.reserve(25); - } + CameraRail() + { + nodes.reserve(25); + } - std::vector nodes; -}; + std::vector nodes; + }; -/* -------------------------------------------------------------------------- */ -/* Section CRUISECONTROL */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section CINECAM */ + /* -------------------------------------------------------------------------- */ -struct CruiseControl -{ - CruiseControl(): - min_speed(0), - autobrake(0) - {} + struct Cinecam + { + Cinecam() : position(Ogre::Vector3::ZERO), spring(8000.f), damping(800.f), node_mass(20.f) + { + } + + Ogre::Vector3 position; + Node::Ref nodes[8]; + float spring; + float damping; + float node_mass; + std::shared_ptr beam_defaults; + std::shared_ptr node_defaults; + }; + + /* -------------------------------------------------------------------------- */ + /* Section COLLISIONBOXES */ + /* -------------------------------------------------------------------------- */ - float min_speed; - int autobrake; -}; + struct CollisionBox + { + CollisionBox() + { + nodes.reserve(25); + } -/* -------------------------------------------------------------------------- */ -/* Section AUTHOR */ -/* -------------------------------------------------------------------------- */ + std::vector nodes; + }; -struct Author -{ - Author(): - forum_account_id(0), - _has_forum_account(false) - {} - - Ogre::String type; - unsigned int forum_account_id; - Ogre::String name; - Ogre::String email; - bool _has_forum_account; -}; - -/* -------------------------------------------------------------------------- */ -/* Inline - section FILEINFO */ -/* -------------------------------------------------------------------------- */ - -struct Fileinfo -{ - Fileinfo(): - category_id(-1), - file_version(0) /* Default */ - {} + /* -------------------------------------------------------------------------- */ + /* Section CRUISECONTROL */ + /* -------------------------------------------------------------------------- */ - Ogre::String unique_id; - int category_id; - int file_version; -}; + struct CruiseControl + { + CruiseControl() : min_speed(0), autobrake(0) + { + } -/* -------------------------------------------------------------------------- */ -/* Section ENGINE */ -/* -------------------------------------------------------------------------- */ + float min_speed; + int autobrake; + }; -struct Engine -{ - Engine(): - shift_down_rpm(0), - shift_up_rpm(0), - torque(0), - global_gear_ratio(0), - reverse_gear_ratio(0), - neutral_gear_ratio(0) - { - gear_ratios.reserve(5); - } - - float shift_down_rpm; - float shift_up_rpm; - float torque; - float global_gear_ratio; - float reverse_gear_ratio; - float neutral_gear_ratio; - std::vector gear_ratios; -}; - -/* -------------------------------------------------------------------------- */ -/* Section ENGOPTION */ -/* -------------------------------------------------------------------------- */ - -struct Engoption -{ - Engoption(); - - enum EngineType - { - ENGINE_TYPE_c_CAR = 'c', - ENGINE_TYPE_e_ECAR = 'e', - ENGINE_TYPE_t_TRUCK = 't', - - ENGINE_TYPE_INVALID = 0xFFFFFFFF - }; - - float inertia; - EngineType type; - float clutch_force; - float shift_time; ///< Seconds - float clutch_time; ///< Seconds - float post_shift_time; ///< Seconds - float idle_rpm; - float stall_rpm; - float max_idle_mixture; - float min_idle_mixture; - float braking_torque; -}; - -/* -------------------------------------------------------------------------- */ -/* Section ENGTURBO */ -/* -------------------------------------------------------------------------- */ - -struct Engturbo -{ - Engturbo(); - - int version; - float tinertiaFactor; - int nturbos; - float param1; - float param2; - float param3; - float param4; - float param5; - float param6; - float param7; - float param8; - float param9; - float param10; - float param11; -}; - -/* -------------------------------------------------------------------------- */ -/* Section EXHAUSTS */ -/* -------------------------------------------------------------------------- */ - -struct Exhaust -{ - Node::Ref reference_node; - Node::Ref direction_node; - Ogre::String particle_name; -}; + /* -------------------------------------------------------------------------- */ + /* Section AUTHOR */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section EXTCAMERA */ -/* -------------------------------------------------------------------------- */ + struct Author + { + Author() : forum_account_id(0), _has_forum_account(false) + { + } -struct ExtCamera -{ - ExtCamera(): - mode(MODE_CLASSIC) - {} + Ogre::String type; + unsigned int forum_account_id; + Ogre::String name; + Ogre::String email; + bool _has_forum_account; + }; - enum Mode + /* -------------------------------------------------------------------------- */ + /* Inline - section FILEINFO */ + /* -------------------------------------------------------------------------- */ + + struct Fileinfo { - MODE_CLASSIC = 0, // Hardcoded in simulation code, do not change - MODE_CINECAM = 1, // Hardcoded in simulation code, do not change - MODE_NODE = 2, // Hardcoded in simulation code, do not change + Fileinfo() : category_id(-1), file_version(0) /* Default */ + { + } - MODE_INVALID = 0xFFFFFFFF + Ogre::String unique_id; + int category_id; + int file_version; }; - Mode mode; - Node::Ref node; -}; + /* -------------------------------------------------------------------------- */ + /* Section ENGINE */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section BRAKES */ -/* -------------------------------------------------------------------------- */ + struct Engine + { + Engine() + : shift_down_rpm(0), shift_up_rpm(0), torque(0), global_gear_ratio(0), reverse_gear_ratio(0), neutral_gear_ratio(0) + { + gear_ratios.reserve(5); + } + + float shift_down_rpm; + float shift_up_rpm; + float torque; + float global_gear_ratio; + float reverse_gear_ratio; + float neutral_gear_ratio; + std::vector gear_ratios; + }; -struct Brakes -{ - Brakes(): - default_braking_force(30000), // Default - parking_brake_force(-1.f) // Empty value - {} + /* -------------------------------------------------------------------------- */ + /* Section ENGOPTION */ + /* -------------------------------------------------------------------------- */ - float default_braking_force; - float parking_brake_force; -}; + struct Engoption + { + Engoption(); -/* -------------------------------------------------------------------------- */ -/* Section ANTI_LOCK_BRAKES */ -/* -------------------------------------------------------------------------- */ + enum EngineType + { + ENGINE_TYPE_c_CAR = 'c', + ENGINE_TYPE_e_ECAR = 'e', + ENGINE_TYPE_t_TRUCK = 't', -struct AntiLockBrakes -{ - AntiLockBrakes(); + ENGINE_TYPE_INVALID = 0xFFFFFFFF + }; - float regulation_force; - unsigned int min_speed; - float pulse_per_sec; - bool attr_is_on; - bool attr_no_dashboard; - bool attr_no_toggle; -}; + float inertia; + EngineType type; + float clutch_force; + float shift_time; ///< Seconds + float clutch_time; ///< Seconds + float post_shift_time; ///< Seconds + float idle_rpm; + float stall_rpm; + float max_idle_mixture; + float min_idle_mixture; + float braking_torque; + }; -/* -------------------------------------------------------------------------- */ -/* Section TRACTION_CONTROL */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section ENGTURBO */ + /* -------------------------------------------------------------------------- */ -struct TractionControl -{ - TractionControl(); - - float regulation_force; - float wheel_slip; - float fade_speed; - float pulse_per_sec; - bool attr_is_on; - bool attr_no_dashboard; - bool attr_no_toggle; -}; - -/* -------------------------------------------------------------------------- */ -/* Inline-section SLOPE_BRAKE */ -/* -------------------------------------------------------------------------- */ - -struct SlopeBrake -{ - SlopeBrake(): - regulating_force(6.f), - attach_angle(5.f), - release_angle(10.f) - {} + struct Engturbo + { + Engturbo(); + + int version; + float tinertiaFactor; + int nturbos; + float param1; + float param2; + float param3; + float param4; + float param5; + float param6; + float param7; + float param8; + float param9; + float param10; + float param11; + }; + + /* -------------------------------------------------------------------------- */ + /* Section EXHAUSTS */ + /* -------------------------------------------------------------------------- */ + + struct Exhaust + { + Node::Ref reference_node; + Node::Ref direction_node; + Ogre::String particle_name; + }; - static float GetDefaultRegulatingForce() + /* -------------------------------------------------------------------------- */ + /* Section EXTCAMERA */ + /* -------------------------------------------------------------------------- */ + + struct ExtCamera { - return 6.f; - } + ExtCamera() : mode(MODE_CLASSIC) + { + } + + enum Mode + { + MODE_CLASSIC = 0, // Hardcoded in simulation code, do not change + MODE_CINECAM = 1, // Hardcoded in simulation code, do not change + MODE_NODE = 2, // Hardcoded in simulation code, do not change + + MODE_INVALID = 0xFFFFFFFF + }; + + Mode mode; + Node::Ref node; + }; + + /* -------------------------------------------------------------------------- */ + /* Section BRAKES */ + /* -------------------------------------------------------------------------- */ - static float GetDefaultAttachAngle() + struct Brakes { - return 5.f; - } + Brakes() + : default_braking_force(30000), // Default + parking_brake_force(-1.f) // Empty value + { + } - static float GetDefaultReleaseAngle() + float default_braking_force; + float parking_brake_force; + }; + + /* -------------------------------------------------------------------------- */ + /* Section ANTI_LOCK_BRAKES */ + /* -------------------------------------------------------------------------- */ + + struct AntiLockBrakes { - return 10.f; - } + AntiLockBrakes(); + + float regulation_force; + unsigned int min_speed; + float pulse_per_sec; + bool attr_is_on; + bool attr_no_dashboard; + bool attr_no_toggle; + }; - float regulating_force; - float attach_angle; - float release_angle; -}; + /* -------------------------------------------------------------------------- */ + /* Section TRACTION_CONTROL */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section WHEELDETACHERS */ -/* -------------------------------------------------------------------------- */ + struct TractionControl + { + TractionControl(); + + float regulation_force; + float wheel_slip; + float fade_speed; + float pulse_per_sec; + bool attr_is_on; + bool attr_no_dashboard; + bool attr_no_toggle; + }; -struct WheelDetacher -{ - WheelDetacher(): - wheel_id(0), - detacher_group(0) - {} + /* -------------------------------------------------------------------------- */ + /* Inline-section SLOPE_BRAKE */ + /* -------------------------------------------------------------------------- */ - int wheel_id; - int detacher_group; -}; + struct SlopeBrake + { + SlopeBrake() : regulating_force(6.f), attach_angle(5.f), release_angle(10.f) + { + } -/* -------------------------------------------------------------------------- */ -/* Section WHEELS */ -/* -------------------------------------------------------------------------- */ + static float GetDefaultRegulatingForce() + { + return 6.f; + } -/** Syntax-sugar struct to hold enums */ -struct Wheels -{ - enum Braking + static float GetDefaultAttachAngle() + { + return 5.f; + } + + static float GetDefaultReleaseAngle() + { + return 10.f; + } + + float regulating_force; + float attach_angle; + float release_angle; + }; + + /* -------------------------------------------------------------------------- */ + /* Section WHEELDETACHERS */ + /* -------------------------------------------------------------------------- */ + + struct WheelDetacher { - BRAKING_NO = 0, - BRAKING_YES = 1, - BRAKING_DIRECTIONAL_LEFT = 2, - BRAKING_DIRECTIONAL_RIGHT = 3, - BRAKING_ONLY_FOOT = 4, + WheelDetacher() : wheel_id(0), detacher_group(0) + { + } - BRAKING_INVALID = 0xFFFFFFFF + int wheel_id; + int detacher_group; }; - enum Propulsion + /* -------------------------------------------------------------------------- */ + /* Section WHEELS */ + /* -------------------------------------------------------------------------- */ + + /** Syntax-sugar struct to hold enums */ + struct Wheels { - PROPULSION_NONE = 0, - PROPULSION_FORWARD = 1, - PROPULSION_BACKWARD = 2, + enum Braking + { + BRAKING_NO = 0, + BRAKING_YES = 1, + BRAKING_DIRECTIONAL_LEFT = 2, + BRAKING_DIRECTIONAL_RIGHT = 3, + BRAKING_ONLY_FOOT = 4, + + BRAKING_INVALID = 0xFFFFFFFF + }; - PROPULSION_INVALID = 0xFFFFFFFF + enum Propulsion + { + PROPULSION_NONE = 0, + PROPULSION_FORWARD = 1, + PROPULSION_BACKWARD = 2, + + PROPULSION_INVALID = 0xFFFFFFFF + }; }; -}; -/** Attributes common to all wheel definitions */ -struct BaseWheel -{ - BaseWheel(): - width(0), - num_rays(0), - braking(Wheels::BRAKING_NO), - mass(0) - {} - - virtual ~BaseWheel() - {} - - float width; - unsigned int num_rays; - Node::Ref nodes[2]; - Node::Ref rigidity_node; - Wheels::Braking braking; - Wheels::Propulsion propulsion; - Node::Ref reference_arm_node; - float mass; - std::shared_ptr node_defaults; - std::shared_ptr beam_defaults; -}; - -/** The actual wheel */ -struct Wheel: BaseWheel -{ - Wheel(): - BaseWheel(), - radius(0), - face_material_name("tracks/wheelface"), - band_material_name("tracks/wheelband1") - {} - - float radius; - float springiness; - float damping; - Ogre::String face_material_name; - Ogre::String band_material_name; -}; - -/* -------------------------------------------------------------------------- */ -/* Section WHEELS_2 */ -/* -------------------------------------------------------------------------- */ - -/** Attributes common to WHEELS_2 and newer definitions */ -struct BaseWheel2: BaseWheel -{ - BaseWheel2(): - BaseWheel(), - rim_radius(0), - tyre_radius(0), - tyre_springiness(0), - tyre_damping(0) - {} - - float rim_radius; - float tyre_radius; - float tyre_springiness; - float tyre_damping; -}; - -struct Wheel2: BaseWheel2 -{ - Wheel2(): - BaseWheel2(), - rim_springiness(0), - rim_damping(0), - face_material_name("tracks/wheelface"), - band_material_name("tracks/wheelband1") - {} - - Ogre::String face_material_name; - Ogre::String band_material_name; - float rim_springiness; - float rim_damping; -}; - -/* -------------------------------------------------------------------------- */ -/* Section MESHWHEELS */ -/* -------------------------------------------------------------------------- */ - -struct MeshWheel: BaseWheel -{ - MeshWheel(): - BaseWheel(), - side(SIDE_INVALID), - rim_radius(0), - tyre_radius(0), - _is_meshwheel2(false) - {} - - enum Side - { - SIDE_INVALID = 0, - SIDE_RIGHT = 'r', - SIDE_LEFT = 'l' - }; - - Side side; - Ogre::String mesh_name; - Ogre::String material_name; - float rim_radius; - float tyre_radius; - float spring; - float damping; - bool _is_meshwheel2; -}; - -/* -------------------------------------------------------------------------- */ -/* Section FLARES FLARES2 */ -/* -------------------------------------------------------------------------- */ - -/** Used for both 'flares' and 'flares_2' sections -*/ -struct Flare2 -{ - Flare2(): - offset(0, 0, 1), /* Section 'flares(1)' has offset.z hardcoded to 1 */ - type(TYPE_f_HEADLIGHT), - control_number(-1), - blink_delay_milis(-2), - size(-1) - {} - - enum Type - { - TYPE_f_HEADLIGHT = 'f', - TYPE_b_BRAKELIGHT = 'b', - TYPE_l_LEFT_BLINKER = 'l', - TYPE_r_RIGHT_BLINKER = 'r', - TYPE_R_REVERSE_LIGHT = 'R', - TYPE_u_USER = 'u', - - TYPE_INVALID = 0xFFFFFFFF - }; - - Node::Ref reference_node; - Node::Ref node_axis_x; - Node::Ref node_axis_y; - Ogre::Vector3 offset; - Type type; - int control_number; - int blink_delay_milis; - float size; - Ogre::String material_name; -}; - -/* -------------------------------------------------------------------------- */ -/* Section FLEXBODIES */ -/* -------------------------------------------------------------------------- */ - -struct Flexbody -{ - Flexbody(): - offset(Ogre::Vector3::ZERO), - rotation(Ogre::Vector3::ZERO) - { - } - - Node::Ref reference_node; - Node::Ref x_axis_node; - Node::Ref y_axis_node; - Ogre::Vector3 offset; - Ogre::Vector3 rotation; - Ogre::String mesh_name; - std::list animations; - std::vector node_list_to_import; //< Node ranges are disallowed in fileformatversion >=450 - std::vector node_list; - CameraSettings camera_settings; -}; - -/* -------------------------------------------------------------------------- */ -/* Section FLEX_BODY_WHEELS */ -/* -------------------------------------------------------------------------- */ - -struct FlexBodyWheel: BaseWheel2 -{ - FlexBodyWheel(): - side(MeshWheel::SIDE_INVALID), - rim_springiness(0), - rim_damping(0) - {} + /** Attributes common to all wheel definitions */ + struct BaseWheel + { + BaseWheel() : width(0), num_rays(0), braking(Wheels::BRAKING_NO), mass(0) + { + } - MeshWheel::Side side; + virtual ~BaseWheel() + { + } + + float width; + unsigned int num_rays; + Node::Ref nodes[2]; + Node::Ref rigidity_node; + Wheels::Braking braking; + Wheels::Propulsion propulsion; + Node::Ref reference_arm_node; + float mass; + std::shared_ptr node_defaults; + std::shared_ptr beam_defaults; + }; - float rim_springiness; - float rim_damping; - Ogre::String rim_mesh_name; - Ogre::String tyre_mesh_name; -}; + /** The actual wheel */ + struct Wheel : BaseWheel + { + Wheel() : BaseWheel(), radius(0), face_material_name("tracks/wheelface"), band_material_name("tracks/wheelband1") + { + } -/* -------------------------------------------------------------------------- */ -/* Section FUSEDRAG */ -/* -------------------------------------------------------------------------- */ + float radius; + float springiness; + float damping; + Ogre::String face_material_name; + Ogre::String band_material_name; + }; -struct Fusedrag -{ - Fusedrag(); + /* -------------------------------------------------------------------------- */ + /* Section WHEELS_2 */ + /* -------------------------------------------------------------------------- */ - bool autocalc; - Node::Ref front_node; - Node::Ref rear_node; - float approximate_width; - Ogre::String airfoil_name; - float area_coefficient; -}; + /** Attributes common to WHEELS_2 and newer definitions */ + struct BaseWheel2 : BaseWheel + { + BaseWheel2() : BaseWheel(), rim_radius(0), tyre_radius(0), tyre_springiness(0), tyre_damping(0) + { + } -/* -------------------------------------------------------------------------- */ -/* Section HOOKS */ -/* -------------------------------------------------------------------------- */ + float rim_radius; + float tyre_radius; + float tyre_springiness; + float tyre_damping; + }; -struct Hook -{ - Hook(); - - Node::Ref node; - float option_hook_range; - float option_speed_coef; - float option_max_force; - int option_hookgroup; - int option_lockgroup; - float option_timer; - float option_min_range_meters; - bool flag_self_lock :1; - bool flag_auto_lock :1; - bool flag_no_disable:1; - bool flag_no_rope :1; - bool flag_visible :1; -}; - -/* -------------------------------------------------------------------------- */ -/* Section SHOCKS */ -/* -------------------------------------------------------------------------- */ - -struct Shock -{ - Shock(); - - BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE , HasOption_i_Invisible, SetOption_i_Invisible) - // Stability active suspension can be made with "L" for suspension on the truck's left and "R" for suspension on the truck's right. - BITMASK_PROPERTY(options, 2, OPTION_L_ACTIVE_LEFT , HasOption_L_ActiveLeft, SetOption_L_ActiveLeft) - // Stability active suspension can be made with "L" for suspension on the truck's left and "R" for suspension on the truck's right. - BITMASK_PROPERTY(options, 3, OPTION_R_ACTIVE_RIGHT , HasOption_R_ActiveRight, SetOption_R_ActiveRight) - BITMASK_PROPERTY(options, 4, OPTION_m_METRIC , HasOption_m_Metric, SetOption_m_Metric) - - Node::Ref nodes[2]; - float spring_rate; ///< The 'stiffness' of the shock. The higher the value, the less the shock will move for a given bump. - float damping; ///< The 'resistance to motion' of the shock. The best value is given by this equation: 2 * sqrt(suspended mass * springness) - float short_bound; ///< Maximum contraction. The shortest length the shock can be, as a proportion of its original length. "0" means the shock will not be able to contract at all, "1" will let it contract all the way to zero length. If the shock tries to shorten more than this value allows, it will become as rigid as a normal beam. - float long_bound; ///< Maximum extension. The longest length a shock can be, as a proportion of its original length. "0" means the shock will not be able to extend at all. "1" means the shock will be able to double its length. Higher values allow for longer extension. - float precompression; ///< Changes compression or extension of the suspension when the truck spawns. This can be used to "level" the suspension of a truck if it sags in game. The default value is 1.0. - unsigned int options; ///< Bit flags. - std::shared_ptr beam_defaults; - int detacher_group; -}; - -/* -------------------------------------------------------------------------- */ -/* Section SHOCKS_2 */ -/* -------------------------------------------------------------------------- */ - -struct Shock2 -{ - Shock2(); - - BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE , HasOption_i_Invisible, SetOption_i_Invisible) - // soft bump boundaries, use when shocks reach limiters too often and "jumprebound" (default is hard bump boundaries) - BITMASK_PROPERTY(options, 2, OPTION_s_SOFT_BUMP_BOUNDS, HasOption_s_SoftBumpBounds, SetOption_s_SoftBumpBounds) - // metric values for shortbound/longbound applying to the length of the beam. - BITMASK_PROPERTY(options, 3, OPTION_m_METRIC , HasOption_m_Metric, SetOption_m_Metric) - // Absolute metric values for shortbound/longbound, settings apply without regarding to the original length of the beam.(Use with caution, check ror.log for errors) - BITMASK_PROPERTY(options, 4, OPTION_M_ABSOLUTE_METRIC , HasOption_M_AbsoluteMetric, SetOption_M_AbsoluteMetric) - - Node::Ref nodes[2]; - float spring_in; ///< Spring value applied when the shock is compressing. - float damp_in; ///< Damping value applied when the shock is compressing. - float progress_factor_spring_in; ///< Progression factor for springin. A value of 0 disables this option. 1...x as multipliers, example:maximum springrate == springrate + (factor*springrate) - float progress_factor_damp_in; ///< Progression factor for dampin. 0 = disabled, 1...x as multipliers, example:maximum dampingrate == springrate + (factor*dampingrate) - float spring_out; ///< spring value applied when shock extending - float damp_out; ///< damping value applied when shock extending - float progress_factor_spring_out; ///< Progression factor springout, 0 = disabled, 1...x as multipliers, example:maximum springrate == springrate + (factor*springrate) - float progress_factor_damp_out; ///< Progression factor dampout, 0 = disabled, 1...x as multipliers, example:maximum dampingrate == springrate + (factor*dampingrate) - float short_bound; ///< Maximum contraction limit, in percentage ( 1.00 = 100% ) - float long_bound; ///< Maximum extension limit, in percentage ( 1.00 = 100% ) - float precompression; ///< Changes compression or extension of the suspension when the truck spawns. This can be used to "level" the suspension of a truck if it sags in game. The default value is 1.0. - unsigned int options; ///< Bit flags. - std::shared_ptr beam_defaults; - int detacher_group; -}; - -/* -------------------------------------------------------------------------- */ -/* Section SHOCKS_2 */ -/* -------------------------------------------------------------------------- */ - -struct Shock3 -{ - Shock3(); - - BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE , HasOption_i_Invisible, SetOption_i_Invisible) - // metric values for shortbound/longbound applying to the length of the beam. - BITMASK_PROPERTY(options, 2, OPTION_m_METRIC , HasOption_m_Metric, SetOption_m_Metric) - // Absolute metric values for shortbound/longbound, settings apply without regarding to the original length of the beam.(Use with caution, check ror.log for errors) - BITMASK_PROPERTY(options, 3, OPTION_M_ABSOLUTE_METRIC , HasOption_M_AbsoluteMetric, SetOption_M_AbsoluteMetric) - - Node::Ref nodes[2]; - float spring_in; ///< Spring value applied when the shock is compressing. - float damp_in; ///< Damping value applied when the shock is compressing. - float spring_out; ///< Spring value applied when shock extending - float damp_out; ///< Damping value applied when shock extending - float damp_in_slow; ///< Damping value applied when shock is commpressing slower than split in velocity - float split_vel_in; ///< Split velocity in (m/s) - threshold for slow / fast damping during compression - float damp_in_fast; ///< Damping value applied when shock is commpressing faster than split in velocity - float damp_out_slow; ///< Damping value applied when shock is commpressing slower than split out velocity - float split_vel_out; ///< Split velocity in (m/s) - threshold for slow / fast damping during extension - float damp_out_fast; ///< Damping value applied when shock is commpressing faster than split out velocity - float short_bound; ///< Maximum contraction limit, in percentage ( 1.00 = 100% ) - float long_bound; ///< Maximum extension limit, in percentage ( 1.00 = 100% ) - float precompression; ///< Changes compression or extension of the suspension when the truck spawns. This can be used to "level" the suspension of a truck if it sags in game. The default value is 1.0. - unsigned int options; ///< Bit flags. - std::shared_ptr beam_defaults; - int detacher_group; -}; - -/* -------------------------------------------------------------------------- */ -/* Inline-section SET_SKELETON_DISPLAY */ -/* -------------------------------------------------------------------------- */ - -struct SkeletonSettings -{ - SkeletonSettings(): - visibility_range_meters(150.f), - beam_thickness_meters(BEAM_SKELETON_DIAMETER) - {} + struct Wheel2 : BaseWheel2 + { + Wheel2() + : BaseWheel2(), rim_springiness(0), rim_damping(0), face_material_name("tracks/wheelface"), + band_material_name("tracks/wheelband1") + { + } - float visibility_range_meters; - float beam_thickness_meters; -}; + Ogre::String face_material_name; + Ogre::String band_material_name; + float rim_springiness; + float rim_damping; + }; -/* -------------------------------------------------------------------------- */ -/* Section HYDROS */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section MESHWHEELS */ + /* -------------------------------------------------------------------------- */ -struct Hydro -{ - Hydro(): - lenghtening_factor(0), - detacher_group(0) - {} - - static const char OPTION_n_NORMAL = 'n'; - static const char OPTION_i_INVISIBLE = 'i'; - - /* Useful for trucks */ - - static const char OPTION_s_DISABLE_ON_HIGH_SPEED = 's'; - - /* Useful for planes: These can be used to control flight surfaces, or to create a thrust vectoring system. */ - - static const char OPTION_a_INPUT_AILERON = 'a'; - static const char OPTION_r_INPUT_RUDDER = 'r'; - static const char OPTION_e_INPUT_ELEVATOR = 'e'; - static const char OPTION_u_INPUT_AILERON_ELEVATOR = 'u'; - static const char OPTION_v_INPUT_InvAILERON_ELEVATOR = 'v'; - static const char OPTION_x_INPUT_AILERON_RUDDER = 'x'; - static const char OPTION_y_INPUT_InvAILERON_RUDDER = 'y'; - static const char OPTION_g_INPUT_ELEVATOR_RUDDER = 'g'; - static const char OPTION_h_INPUT_InvELEVATOR_RUDDER = 'h'; - - inline bool HasFlag_a() { return options.find(RigDef::Hydro::OPTION_a_INPUT_AILERON) != std::string::npos; } - inline bool HasFlag_e() { return options.find(RigDef::Hydro::OPTION_e_INPUT_ELEVATOR) != std::string::npos; } - inline bool HasFlag_g() { return options.find(RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER) != std::string::npos; } - inline bool HasFlag_h() { return options.find(RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER) != std::string::npos; } - inline bool HasFlag_i() { return options.find(RigDef::Hydro::OPTION_i_INVISIBLE) != std::string::npos; } - inline bool HasFlag_r() { return options.find(RigDef::Hydro::OPTION_r_INPUT_RUDDER) != std::string::npos; } - inline bool HasFlag_s() { return options.find(RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED) != std::string::npos; } - inline bool HasFlag_u() { return options.find(RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR) != std::string::npos; } - inline bool HasFlag_v() { return options.find(RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR) != std::string::npos; } - inline bool HasFlag_x() { return options.find(RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER) != std::string::npos; } - inline bool HasFlag_y() { return options.find(RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER) != std::string::npos; } - - inline void AddFlag(char flag) { options += flag; } - - Node::Ref nodes[2]; - float lenghtening_factor; - std::string options; - Inertia inertia; - std::shared_ptr inertia_defaults; - std::shared_ptr beam_defaults; - int detacher_group; -}; - -/* -------------------------------------------------------------------------- */ -/* Section ANIMATORS */ -/* -------------------------------------------------------------------------- */ - -struct AeroAnimator -{ - AeroAnimator(): - flags(0), - motor(0) - {} - - static const unsigned int OPTION_THROTTLE = BITMASK(1); - static const unsigned int OPTION_RPM = BITMASK(2); - static const unsigned int OPTION_TORQUE = BITMASK(3); - static const unsigned int OPTION_PITCH = BITMASK(4); - static const unsigned int OPTION_STATUS = BITMASK(5); - - unsigned int flags; - unsigned int motor; -}; - -struct Animator -{ - Animator(): - lenghtening_factor(0), - flags(0), - short_limit(0), - long_limit(0), - detacher_group(0) - {} - - static const unsigned int OPTION_VISIBLE = BITMASK(1); - static const unsigned int OPTION_INVISIBLE = BITMASK(2); - static const unsigned int OPTION_AIRSPEED = BITMASK(3); - static const unsigned int OPTION_VERTICAL_VELOCITY = BITMASK(4); - static const unsigned int OPTION_ALTIMETER_100K = BITMASK(5); - static const unsigned int OPTION_ALTIMETER_10K = BITMASK(6); - static const unsigned int OPTION_ALTIMETER_1K = BITMASK(7); - static const unsigned int OPTION_ANGLE_OF_ATTACK = BITMASK(8); - static const unsigned int OPTION_FLAP = BITMASK(9); - static const unsigned int OPTION_AIR_BRAKE = BITMASK(10); - static const unsigned int OPTION_ROLL = BITMASK(11); - static const unsigned int OPTION_PITCH = BITMASK(12); - static const unsigned int OPTION_BRAKES = BITMASK(13); - static const unsigned int OPTION_ACCEL = BITMASK(14); - static const unsigned int OPTION_CLUTCH = BITMASK(15); - static const unsigned int OPTION_SPEEDO = BITMASK(16); - static const unsigned int OPTION_TACHO = BITMASK(17); - static const unsigned int OPTION_TURBO = BITMASK(18); - static const unsigned int OPTION_PARKING = BITMASK(19); - static const unsigned int OPTION_SHIFT_LEFT_RIGHT = BITMASK(20); - static const unsigned int OPTION_SHIFT_BACK_FORTH = BITMASK(21); - static const unsigned int OPTION_SEQUENTIAL_SHIFT = BITMASK(22); - static const unsigned int OPTION_GEAR_SELECT = BITMASK(23); - static const unsigned int OPTION_TORQUE = BITMASK(24); - static const unsigned int OPTION_DIFFLOCK = BITMASK(25); - static const unsigned int OPTION_BOAT_RUDDER = BITMASK(26); - static const unsigned int OPTION_BOAT_THROTTLE = BITMASK(27); - static const unsigned int OPTION_SHORT_LIMIT = BITMASK(28); - static const unsigned int OPTION_LONG_LIMIT = BITMASK(29); - - Node::Ref nodes[2]; - float lenghtening_factor; - unsigned int flags; - float short_limit; - float long_limit; - AeroAnimator aero_animator; - std::shared_ptr inertia_defaults; - std::shared_ptr beam_defaults; - int detacher_group; -}; - -/* -------------------------------------------------------------------------- */ -/* Section COMMANDS & COMMANDS_2 (unified) */ -/* -------------------------------------------------------------------------- */ - -struct Command2 -{ - Command2(); - - unsigned int _format_version; - Node::Ref nodes[2]; - float shorten_rate; - float lengthen_rate; - float max_contraction; - float max_extension; - unsigned int contract_key; - unsigned int extend_key; - Ogre::String description; - Inertia inertia; - float affect_engine; - bool needs_engine; - bool plays_sound; - std::shared_ptr beam_defaults; - std::shared_ptr inertia_defaults; - int detacher_group; - - bool option_i_invisible; - bool option_r_rope; - bool option_c_auto_center; - bool option_f_not_faster; - bool option_p_1press; - bool option_o_1press_center; -}; - -/* -------------------------------------------------------------------------- */ -/* Section ROTATORS */ -/* -------------------------------------------------------------------------- */ - -struct Rotator -{ - Rotator(): - rate(0), - spin_left_key(0), - spin_right_key(0), - engine_coupling(1), /* Default */ - needs_engine(false) /* Default */ - {} - - Node::Ref axis_nodes[2]; - Node::Ref base_plate_nodes[4]; - Node::Ref rotating_plate_nodes[4]; - - float rate; - unsigned int spin_left_key; - unsigned int spin_right_key; - Inertia inertia; - std::shared_ptr inertia_defaults; - float engine_coupling; - bool needs_engine; -}; - -/* -------------------------------------------------------------------------- */ -/* Section ROTATORS_2 */ -/* -------------------------------------------------------------------------- */ - -struct Rotator2: public Rotator -{ - Rotator2(): - Rotator(), - rotating_force(10000000), /* Default */ - tolerance(0) - {} - - float rotating_force; - float tolerance; - Ogre::String description; -}; - -/* -------------------------------------------------------------------------- */ -/* Section TRIGGERS */ -/* -------------------------------------------------------------------------- */ - -struct Trigger -{ - struct EngineTrigger + struct MeshWheel : BaseWheel { - enum Function + MeshWheel() : BaseWheel(), side(SIDE_INVALID), rim_radius(0), tyre_radius(0), _is_meshwheel2(false) { - ENGINE_TRIGGER_FUNCTION_CLUTCH = 0, - ENGINE_TRIGGER_FUNCTION_BRAKE = 1, - ENGINE_TRIGGER_FUNCTION_ACCELERATOR = 2, - ENGINE_TRIGGER_FUNCTION_RPM_CONTROL = 3, - ENGINE_TRIGGER_FUNCTION_SHIFT_UP = 4, ///< Do not mix with OPTION_t_CONTINUOUS - ENGINE_TRIGGER_FUNCTION_SHIFT_DOWN = 5, ///< Do not mix with OPTION_t_CONTINUOUS + } - ENGINE_TRIGGER_FUNCTION_INVALID = 0xFFFFFFFF + enum Side + { + SIDE_INVALID = 0, + SIDE_RIGHT = 'r', + SIDE_LEFT = 'l' }; - Function function; - unsigned int motor_index; + Side side; + Ogre::String mesh_name; + Ogre::String material_name; + float rim_radius; + float tyre_radius; + float spring; + float damping; + bool _is_meshwheel2; }; - struct CommandKeyTrigger + /* -------------------------------------------------------------------------- */ + /* Section FLARES FLARES2 */ + /* -------------------------------------------------------------------------- */ + + /** Used for both 'flares' and 'flares_2' sections + */ + struct Flare2 { - unsigned int contraction_trigger_key; - unsigned int extension_trigger_key; + Flare2() + : offset(0, 0, 1), /* Section 'flares(1)' has offset.z hardcoded to 1 */ + type(TYPE_f_HEADLIGHT), control_number(-1), blink_delay_milis(-2), size(-1) + { + } + + enum Type + { + TYPE_f_HEADLIGHT = 'f', + TYPE_b_BRAKELIGHT = 'b', + TYPE_l_LEFT_BLINKER = 'l', + TYPE_r_RIGHT_BLINKER = 'r', + TYPE_R_REVERSE_LIGHT = 'R', + TYPE_u_USER = 'u', + + TYPE_INVALID = 0xFFFFFFFF + }; + + Node::Ref reference_node; + Node::Ref node_axis_x; + Node::Ref node_axis_y; + Ogre::Vector3 offset; + Type type; + int control_number; + int blink_delay_milis; + float size; + Ogre::String material_name; }; - struct HookToggleTrigger + /* -------------------------------------------------------------------------- */ + /* Section FLEXBODIES */ + /* -------------------------------------------------------------------------- */ + + struct Flexbody { - int contraction_trigger_hookgroup_id; - int extension_trigger_hookgroup_id; + Flexbody() : offset(Ogre::Vector3::ZERO), rotation(Ogre::Vector3::ZERO) + { + } + + Node::Ref reference_node; + Node::Ref x_axis_node; + Node::Ref y_axis_node; + Ogre::Vector3 offset; + Ogre::Vector3 rotation; + Ogre::String mesh_name; + std::list animations; + std::vector node_list_to_import; //< Node ranges are disallowed in fileformatversion >=450 + std::vector node_list; + CameraSettings camera_settings; }; - Trigger(); + /* -------------------------------------------------------------------------- */ + /* Section FLEX_BODY_WHEELS */ + /* -------------------------------------------------------------------------- */ - BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE , HasFlag_i_Invisible, SetFlag_i_Invisible ) - BITMASK_PROPERTY(options, 2, OPTION_c_COMMAND_STYLE , HasFlag_c_CommandStyle, SetFlag_c_CommandStyle ) - BITMASK_PROPERTY(options, 3, OPTION_x_START_OFF , HasFlag_x_StartDisabled, SetFlag_x_StartDisabled ) - BITMASK_PROPERTY(options, 4, OPTION_b_BLOCK_KEYS , HasFlag_b_KeyBlocker, SetFlag_b_KeyBlocker ) - BITMASK_PROPERTY(options, 5, OPTION_B_BLOCK_TRIGGERS , HasFlag_B_TriggerBlocker, SetFlag_B_TriggerBlocker ) - BITMASK_PROPERTY(options, 6, OPTION_A_INV_BLOCK_TRIGGERS , HasFlag_A_InvTriggerBlocker, SetFlag_A_InvTriggerBlocker ) - BITMASK_PROPERTY(options, 7, OPTION_s_SWITCH_CMD_NUM , HasFlag_s_CmdNumSwitch, SetFlag_s_CmdNumSwitch ) - BITMASK_PROPERTY(options, 8, OPTION_h_UNLOCK_HOOKGROUPS_KEY , HasFlag_h_UnlocksHookGroup, SetFlag_h_UnlocksHookGroup ) - BITMASK_PROPERTY(options, 9, OPTION_H_LOCK_HOOKGROUPS_KEY , HasFlag_H_LocksHookGroup, SetFlag_H_LocksHookGroup ) - BITMASK_PROPERTY(options, 10, OPTION_t_CONTINUOUS , HasFlag_t_Continuous, SetFlag_t_Continuous ) - BITMASK_PROPERTY(options, 11, OPTION_E_ENGINE_TRIGGER , HasFlag_E_EngineTrigger, SetFlag_E_EngineTrigger ) + struct FlexBodyWheel : BaseWheel2 + { + FlexBodyWheel() : side(MeshWheel::SIDE_INVALID), rim_springiness(0), rim_damping(0) + { + } - inline bool IsHookToggleTrigger() { return HasFlag_H_LocksHookGroup() || HasFlag_h_UnlocksHookGroup(); } + MeshWheel::Side side; + + float rim_springiness; + float rim_damping; + Ogre::String rim_mesh_name; + Ogre::String tyre_mesh_name; + }; - inline bool IsTriggerBlockerAnyType() { return HasFlag_B_TriggerBlocker() || HasFlag_A_InvTriggerBlocker(); } + /* -------------------------------------------------------------------------- */ + /* Section FUSEDRAG */ + /* -------------------------------------------------------------------------- */ - inline void SetEngineTrigger(Trigger::EngineTrigger const & trig) + struct Fusedrag { - shortbound_trigger_action = (int) trig.function; - longbound_trigger_action = (int) trig.motor_index; - } + Fusedrag(); + + bool autocalc; + Node::Ref front_node; + Node::Ref rear_node; + float approximate_width; + Ogre::String airfoil_name; + float area_coefficient; + }; + + /* -------------------------------------------------------------------------- */ + /* Section HOOKS */ + /* -------------------------------------------------------------------------- */ - inline Trigger::EngineTrigger GetEngineTrigger() const + struct Hook { - assert(HasFlag_E_EngineTrigger()); - EngineTrigger trig; - trig.function = static_cast(shortbound_trigger_action); - trig.motor_index = static_cast(longbound_trigger_action); - return trig; - } + Hook(); + + Node::Ref node; + float option_hook_range; + float option_speed_coef; + float option_max_force; + int option_hookgroup; + int option_lockgroup; + float option_timer; + float option_min_range_meters; + bool flag_self_lock : 1; + bool flag_auto_lock : 1; + bool flag_no_disable : 1; + bool flag_no_rope : 1; + bool flag_visible : 1; + }; + + /* -------------------------------------------------------------------------- */ + /* Section SHOCKS */ + /* -------------------------------------------------------------------------- */ - inline void SetCommandKeyTrigger(CommandKeyTrigger const & trig) + struct Shock { - shortbound_trigger_action = (int) trig.contraction_trigger_key; - longbound_trigger_action = (int) trig.extension_trigger_key; - } + Shock(); + + BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE, HasOption_i_Invisible, SetOption_i_Invisible) + // Stability active suspension can be made with "L" for suspension on the truck's left and "R" for suspension on the + // truck's right. + BITMASK_PROPERTY(options, 2, OPTION_L_ACTIVE_LEFT, HasOption_L_ActiveLeft, SetOption_L_ActiveLeft) + // Stability active suspension can be made with "L" for suspension on the truck's left and "R" for suspension on the + // truck's right. + BITMASK_PROPERTY(options, 3, OPTION_R_ACTIVE_RIGHT, HasOption_R_ActiveRight, SetOption_R_ActiveRight) + BITMASK_PROPERTY(options, 4, OPTION_m_METRIC, HasOption_m_Metric, SetOption_m_Metric) + + Node::Ref nodes[2]; + float spring_rate; ///< The 'stiffness' of the shock. The higher the value, the less the shock will move for a given bump. + float damping; ///< The 'resistance to motion' of the shock. The best value is given by this equation: 2 * sqrt(suspended + ///< mass * springness) + float short_bound; ///< Maximum contraction. The shortest length the shock can be, as a proportion of its original length. + ///< "0" means the shock will not be able to contract at all, "1" will let it contract all the way to + ///< zero length. If the shock tries to shorten more than this value allows, it will become as rigid as + ///< a normal beam. + float long_bound; ///< Maximum extension. The longest length a shock can be, as a proportion of its original length. "0" + ///< means the shock will not be able to extend at all. "1" means the shock will be able to double its + ///< length. Higher values allow for longer extension. + float precompression; ///< Changes compression or extension of the suspension when the truck spawns. This can be used to + ///< "level" the suspension of a truck if it sags in game. The default value is 1.0. + unsigned int options; ///< Bit flags. + std::shared_ptr beam_defaults; + int detacher_group; + }; + + /* -------------------------------------------------------------------------- */ + /* Section SHOCKS_2 */ + /* -------------------------------------------------------------------------- */ - inline CommandKeyTrigger GetCommandKeyTrigger() const + struct Shock2 { - assert(BITMASK_IS_0(options, OPTION_B_BLOCK_TRIGGERS | OPTION_A_INV_BLOCK_TRIGGERS - | OPTION_h_UNLOCK_HOOKGROUPS_KEY | OPTION_H_LOCK_HOOKGROUPS_KEY | OPTION_E_ENGINE_TRIGGER)); - CommandKeyTrigger out; - out.contraction_trigger_key = static_cast(shortbound_trigger_action); - out.extension_trigger_key = static_cast(longbound_trigger_action); - return out; - } + Shock2(); + + BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE, HasOption_i_Invisible, SetOption_i_Invisible) + // soft bump boundaries, use when shocks reach limiters too often and "jumprebound" (default is hard bump boundaries) + BITMASK_PROPERTY(options, 2, OPTION_s_SOFT_BUMP_BOUNDS, HasOption_s_SoftBumpBounds, SetOption_s_SoftBumpBounds) + // metric values for shortbound/longbound applying to the length of the beam. + BITMASK_PROPERTY(options, 3, OPTION_m_METRIC, HasOption_m_Metric, SetOption_m_Metric) + // Absolute metric values for shortbound/longbound, settings apply without regarding to the original length of the + // beam.(Use with caution, check ror.log for errors) + BITMASK_PROPERTY(options, 4, OPTION_M_ABSOLUTE_METRIC, HasOption_M_AbsoluteMetric, SetOption_M_AbsoluteMetric) + + Node::Ref nodes[2]; + float spring_in; ///< Spring value applied when the shock is compressing. + float damp_in; ///< Damping value applied when the shock is compressing. + float progress_factor_spring_in; ///< Progression factor for springin. A value of 0 disables this option. 1...x as + ///< multipliers, example:maximum springrate == springrate + (factor*springrate) + float progress_factor_damp_in; ///< Progression factor for dampin. 0 = disabled, 1...x as multipliers, example:maximum + ///< dampingrate == springrate + (factor*dampingrate) + float spring_out; ///< spring value applied when shock extending + float damp_out; ///< damping value applied when shock extending + float progress_factor_spring_out; ///< Progression factor springout, 0 = disabled, 1...x as multipliers, example:maximum + ///< springrate == springrate + (factor*springrate) + float progress_factor_damp_out; ///< Progression factor dampout, 0 = disabled, 1...x as multipliers, example:maximum + ///< dampingrate == springrate + (factor*dampingrate) + float short_bound; ///< Maximum contraction limit, in percentage ( 1.00 = 100% ) + float long_bound; ///< Maximum extension limit, in percentage ( 1.00 = 100% ) + float precompression; ///< Changes compression or extension of the suspension when the truck spawns. This can be used to + ///< "level" the suspension of a truck if it sags in game. The default value is 1.0. + unsigned int options; ///< Bit flags. + std::shared_ptr beam_defaults; + int detacher_group; + }; - inline void SetHookToggleTrigger(HookToggleTrigger const & trig) + /* -------------------------------------------------------------------------- */ + /* Section SHOCKS_2 */ + /* -------------------------------------------------------------------------- */ + + struct Shock3 { - shortbound_trigger_action = trig.contraction_trigger_hookgroup_id; - longbound_trigger_action = trig.extension_trigger_hookgroup_id; - } + Shock3(); + + BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE, HasOption_i_Invisible, SetOption_i_Invisible) + // metric values for shortbound/longbound applying to the length of the beam. + BITMASK_PROPERTY(options, 2, OPTION_m_METRIC, HasOption_m_Metric, SetOption_m_Metric) + // Absolute metric values for shortbound/longbound, settings apply without regarding to the original length of the + // beam.(Use with caution, check ror.log for errors) + BITMASK_PROPERTY(options, 3, OPTION_M_ABSOLUTE_METRIC, HasOption_M_AbsoluteMetric, SetOption_M_AbsoluteMetric) + + Node::Ref nodes[2]; + float spring_in; ///< Spring value applied when the shock is compressing. + float damp_in; ///< Damping value applied when the shock is compressing. + float spring_out; ///< Spring value applied when shock extending + float damp_out; ///< Damping value applied when shock extending + float damp_in_slow; ///< Damping value applied when shock is commpressing slower than split in velocity + float split_vel_in; ///< Split velocity in (m/s) - threshold for slow / fast damping during compression + float damp_in_fast; ///< Damping value applied when shock is commpressing faster than split in velocity + float damp_out_slow; ///< Damping value applied when shock is commpressing slower than split out velocity + float split_vel_out; ///< Split velocity in (m/s) - threshold for slow / fast damping during extension + float damp_out_fast; ///< Damping value applied when shock is commpressing faster than split out velocity + float short_bound; ///< Maximum contraction limit, in percentage ( 1.00 = 100% ) + float long_bound; ///< Maximum extension limit, in percentage ( 1.00 = 100% ) + float precompression; ///< Changes compression or extension of the suspension when the truck spawns. This can be used to + ///< "level" the suspension of a truck if it sags in game. The default value is 1.0. + unsigned int options; ///< Bit flags. + std::shared_ptr beam_defaults; + int detacher_group; + }; - inline HookToggleTrigger GetHookToggleTrigger() const + /* -------------------------------------------------------------------------- */ + /* Inline-section SET_SKELETON_DISPLAY */ + /* -------------------------------------------------------------------------- */ + + struct SkeletonSettings { - assert(HasFlag_h_UnlocksHookGroup() || HasFlag_H_LocksHookGroup()); - HookToggleTrigger trig; - trig.contraction_trigger_hookgroup_id = shortbound_trigger_action; - trig.extension_trigger_hookgroup_id = longbound_trigger_action; - return trig; - } + SkeletonSettings() : visibility_range_meters(150.f), beam_thickness_meters(BEAM_SKELETON_DIAMETER) + { + } - Node::Ref nodes[2]; - float contraction_trigger_limit; - float expansion_trigger_limit; - unsigned int options; - float boundary_timer; - std::shared_ptr beam_defaults; - int detacher_group; - int shortbound_trigger_action; - int longbound_trigger_action; -}; + float visibility_range_meters; + float beam_thickness_meters; + }; -/* -------------------------------------------------------------------------- */ -/* Section LOCKGROUPS */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section HYDROS */ + /* -------------------------------------------------------------------------- */ -struct Lockgroup -{ - Lockgroup() - : number(0) + struct Hydro { - nodes.reserve(20); - } + Hydro() : lenghtening_factor(0), detacher_group(0) + { + } - static const int LOCKGROUP_DEFAULT = -1; - static const int LOCKGROUP_NOLOCK = 9999; + static const char OPTION_n_NORMAL = 'n'; + static const char OPTION_i_INVISIBLE = 'i'; - int number; - std::vector nodes; -}; + /* Useful for trucks */ -/* -------------------------------------------------------------------------- */ -/* Section MANAGEDMATERIALS */ -/* -------------------------------------------------------------------------- */ + static const char OPTION_s_DISABLE_ON_HIGH_SPEED = 's'; -struct ManagedMaterial -{ - /* IMPORTANT! Order of these values must match Regexes::IDENTIFY_MANAGED_MATERIAL_TYPE enum from Regexes.h */ - enum Type + /* Useful for planes: These can be used to control flight surfaces, or to create a thrust vectoring system. */ + + static const char OPTION_a_INPUT_AILERON = 'a'; + static const char OPTION_r_INPUT_RUDDER = 'r'; + static const char OPTION_e_INPUT_ELEVATOR = 'e'; + static const char OPTION_u_INPUT_AILERON_ELEVATOR = 'u'; + static const char OPTION_v_INPUT_InvAILERON_ELEVATOR = 'v'; + static const char OPTION_x_INPUT_AILERON_RUDDER = 'x'; + static const char OPTION_y_INPUT_InvAILERON_RUDDER = 'y'; + static const char OPTION_g_INPUT_ELEVATOR_RUDDER = 'g'; + static const char OPTION_h_INPUT_InvELEVATOR_RUDDER = 'h'; + + inline bool HasFlag_a() + { + return options.find(RigDef::Hydro::OPTION_a_INPUT_AILERON) != std::string::npos; + } + inline bool HasFlag_e() + { + return options.find(RigDef::Hydro::OPTION_e_INPUT_ELEVATOR) != std::string::npos; + } + inline bool HasFlag_g() + { + return options.find(RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER) != std::string::npos; + } + inline bool HasFlag_h() + { + return options.find(RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER) != std::string::npos; + } + inline bool HasFlag_i() + { + return options.find(RigDef::Hydro::OPTION_i_INVISIBLE) != std::string::npos; + } + inline bool HasFlag_r() + { + return options.find(RigDef::Hydro::OPTION_r_INPUT_RUDDER) != std::string::npos; + } + inline bool HasFlag_s() + { + return options.find(RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED) != std::string::npos; + } + inline bool HasFlag_u() + { + return options.find(RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR) != std::string::npos; + } + inline bool HasFlag_v() + { + return options.find(RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR) != std::string::npos; + } + inline bool HasFlag_x() + { + return options.find(RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER) != std::string::npos; + } + inline bool HasFlag_y() + { + return options.find(RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER) != std::string::npos; + } + + inline void AddFlag(char flag) + { + options += flag; + } + + Node::Ref nodes[2]; + float lenghtening_factor; + std::string options; + Inertia inertia; + std::shared_ptr inertia_defaults; + std::shared_ptr beam_defaults; + int detacher_group; + }; + + /* -------------------------------------------------------------------------- */ + /* Section ANIMATORS */ + /* -------------------------------------------------------------------------- */ + + struct AeroAnimator { - TYPE_FLEXMESH_STANDARD = 1, - TYPE_FLEXMESH_TRANSPARENT, - TYPE_MESH_STANDARD, - TYPE_MESH_TRANSPARENT, + AeroAnimator() : flags(0), motor(0) + { + } + + static const unsigned int OPTION_THROTTLE = BITMASK(1); + static const unsigned int OPTION_RPM = BITMASK(2); + static const unsigned int OPTION_TORQUE = BITMASK(3); + static const unsigned int OPTION_PITCH = BITMASK(4); + static const unsigned int OPTION_STATUS = BITMASK(5); - TYPE_INVALID = 0xFFFFFFFF + unsigned int flags; + unsigned int motor; }; - Ogre::String name; - - /* Attributes */ - Type type; - ManagedMaterialsOptions options; - - /* Textures */ - Ogre::String diffuse_map; - Ogre::String damaged_diffuse_map; - Ogre::String specular_map; + struct Animator + { + Animator() : lenghtening_factor(0), flags(0), short_limit(0), long_limit(0), detacher_group(0) + { + } + + static const unsigned int OPTION_VISIBLE = BITMASK(1); + static const unsigned int OPTION_INVISIBLE = BITMASK(2); + static const unsigned int OPTION_AIRSPEED = BITMASK(3); + static const unsigned int OPTION_VERTICAL_VELOCITY = BITMASK(4); + static const unsigned int OPTION_ALTIMETER_100K = BITMASK(5); + static const unsigned int OPTION_ALTIMETER_10K = BITMASK(6); + static const unsigned int OPTION_ALTIMETER_1K = BITMASK(7); + static const unsigned int OPTION_ANGLE_OF_ATTACK = BITMASK(8); + static const unsigned int OPTION_FLAP = BITMASK(9); + static const unsigned int OPTION_AIR_BRAKE = BITMASK(10); + static const unsigned int OPTION_ROLL = BITMASK(11); + static const unsigned int OPTION_PITCH = BITMASK(12); + static const unsigned int OPTION_BRAKES = BITMASK(13); + static const unsigned int OPTION_ACCEL = BITMASK(14); + static const unsigned int OPTION_CLUTCH = BITMASK(15); + static const unsigned int OPTION_SPEEDO = BITMASK(16); + static const unsigned int OPTION_TACHO = BITMASK(17); + static const unsigned int OPTION_TURBO = BITMASK(18); + static const unsigned int OPTION_PARKING = BITMASK(19); + static const unsigned int OPTION_SHIFT_LEFT_RIGHT = BITMASK(20); + static const unsigned int OPTION_SHIFT_BACK_FORTH = BITMASK(21); + static const unsigned int OPTION_SEQUENTIAL_SHIFT = BITMASK(22); + static const unsigned int OPTION_GEAR_SELECT = BITMASK(23); + static const unsigned int OPTION_TORQUE = BITMASK(24); + static const unsigned int OPTION_DIFFLOCK = BITMASK(25); + static const unsigned int OPTION_BOAT_RUDDER = BITMASK(26); + static const unsigned int OPTION_BOAT_THROTTLE = BITMASK(27); + static const unsigned int OPTION_SHORT_LIMIT = BITMASK(28); + static const unsigned int OPTION_LONG_LIMIT = BITMASK(29); + + Node::Ref nodes[2]; + float lenghtening_factor; + unsigned int flags; + float short_limit; + float long_limit; + AeroAnimator aero_animator; + std::shared_ptr inertia_defaults; + std::shared_ptr beam_defaults; + int detacher_group; + }; - bool HasDamagedDiffuseMap() + /* -------------------------------------------------------------------------- */ + /* Section COMMANDS & COMMANDS_2 (unified) */ + /* -------------------------------------------------------------------------- */ + + struct Command2 { - return (damaged_diffuse_map.length() != 0 && damaged_diffuse_map[0] != '-'); - } + Command2(); + + unsigned int _format_version; + Node::Ref nodes[2]; + float shorten_rate; + float lengthen_rate; + float max_contraction; + float max_extension; + unsigned int contract_key; + unsigned int extend_key; + Ogre::String description; + Inertia inertia; + float affect_engine; + bool needs_engine; + bool plays_sound; + std::shared_ptr beam_defaults; + std::shared_ptr inertia_defaults; + int detacher_group; + + bool option_i_invisible; + bool option_r_rope; + bool option_c_auto_center; + bool option_f_not_faster; + bool option_p_1press; + bool option_o_1press_center; + }; + + /* -------------------------------------------------------------------------- */ + /* Section ROTATORS */ + /* -------------------------------------------------------------------------- */ - bool HasSpecularMap() + struct Rotator { - return (specular_map.length() != 0 && specular_map[0] != '-'); - } -}; + Rotator() + : rate(0), spin_left_key(0), spin_right_key(0), engine_coupling(1), /* Default */ + needs_engine(false) /* Default */ + { + } + + Node::Ref axis_nodes[2]; + Node::Ref base_plate_nodes[4]; + Node::Ref rotating_plate_nodes[4]; + + float rate; + unsigned int spin_left_key; + unsigned int spin_right_key; + Inertia inertia; + std::shared_ptr inertia_defaults; + float engine_coupling; + bool needs_engine; + }; -/* -------------------------------------------------------------------------- */ -/* Section MATERIALFLAREBINDINGS */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section ROTATORS_2 */ + /* -------------------------------------------------------------------------- */ -struct MaterialFlareBinding -{ - MaterialFlareBinding(): - flare_number(0) - {} + struct Rotator2 : public Rotator + { + Rotator2() + : Rotator(), rotating_force(10000000), /* Default */ + tolerance(0) + { + } - unsigned int flare_number; - Ogre::String material_name; -}; + float rotating_force; + float tolerance; + Ogre::String description; + }; -/* -------------------------------------------------------------------------- */ -/* Section NODECOLLISION */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section TRIGGERS */ + /* -------------------------------------------------------------------------- */ -struct NodeCollision -{ - NodeCollision(): - radius(0) - {} + struct Trigger + { + struct EngineTrigger + { + enum Function + { + ENGINE_TRIGGER_FUNCTION_CLUTCH = 0, + ENGINE_TRIGGER_FUNCTION_BRAKE = 1, + ENGINE_TRIGGER_FUNCTION_ACCELERATOR = 2, + ENGINE_TRIGGER_FUNCTION_RPM_CONTROL = 3, + ENGINE_TRIGGER_FUNCTION_SHIFT_UP = 4, ///< Do not mix with OPTION_t_CONTINUOUS + ENGINE_TRIGGER_FUNCTION_SHIFT_DOWN = 5, ///< Do not mix with OPTION_t_CONTINUOUS + + ENGINE_TRIGGER_FUNCTION_INVALID = 0xFFFFFFFF + }; + + Function function; + unsigned int motor_index; + }; - Node::Ref node; - float radius; -}; + struct CommandKeyTrigger + { + unsigned int contraction_trigger_key; + unsigned int extension_trigger_key; + }; -/* -------------------------------------------------------------------------- */ -/* Section PARTICLES */ -/* -------------------------------------------------------------------------- */ + struct HookToggleTrigger + { + int contraction_trigger_hookgroup_id; + int extension_trigger_hookgroup_id; + }; -struct Particle -{ - Node::Ref emitter_node; - Node::Ref reference_node; - Ogre::String particle_system_name; -}; + Trigger(); + + BITMASK_PROPERTY(options, 1, OPTION_i_INVISIBLE, HasFlag_i_Invisible, SetFlag_i_Invisible) + BITMASK_PROPERTY(options, 2, OPTION_c_COMMAND_STYLE, HasFlag_c_CommandStyle, SetFlag_c_CommandStyle) + BITMASK_PROPERTY(options, 3, OPTION_x_START_OFF, HasFlag_x_StartDisabled, SetFlag_x_StartDisabled) + BITMASK_PROPERTY(options, 4, OPTION_b_BLOCK_KEYS, HasFlag_b_KeyBlocker, SetFlag_b_KeyBlocker) + BITMASK_PROPERTY(options, 5, OPTION_B_BLOCK_TRIGGERS, HasFlag_B_TriggerBlocker, SetFlag_B_TriggerBlocker) + BITMASK_PROPERTY(options, 6, OPTION_A_INV_BLOCK_TRIGGERS, HasFlag_A_InvTriggerBlocker, SetFlag_A_InvTriggerBlocker) + BITMASK_PROPERTY(options, 7, OPTION_s_SWITCH_CMD_NUM, HasFlag_s_CmdNumSwitch, SetFlag_s_CmdNumSwitch) + BITMASK_PROPERTY(options, 8, OPTION_h_UNLOCK_HOOKGROUPS_KEY, HasFlag_h_UnlocksHookGroup, SetFlag_h_UnlocksHookGroup) + BITMASK_PROPERTY(options, 9, OPTION_H_LOCK_HOOKGROUPS_KEY, HasFlag_H_LocksHookGroup, SetFlag_H_LocksHookGroup) + BITMASK_PROPERTY(options, 10, OPTION_t_CONTINUOUS, HasFlag_t_Continuous, SetFlag_t_Continuous) + BITMASK_PROPERTY(options, 11, OPTION_E_ENGINE_TRIGGER, HasFlag_E_EngineTrigger, SetFlag_E_EngineTrigger) + + inline bool IsHookToggleTrigger() + { + return HasFlag_H_LocksHookGroup() || HasFlag_h_UnlocksHookGroup(); + } -/* -------------------------------------------------------------------------- */ -/* Section PISTONPROPS */ -/* -------------------------------------------------------------------------- */ + inline bool IsTriggerBlockerAnyType() + { + return HasFlag_B_TriggerBlocker() || HasFlag_A_InvTriggerBlocker(); + } -struct Pistonprop -{ - Pistonprop(): - turbine_power_kW(0), - pitch(0) - {} - - Node::Ref reference_node; - Node::Ref axis_node; - Node::Ref blade_tip_nodes[4]; - Node::Ref couple_node; - float turbine_power_kW; - float pitch; - Ogre::String airfoil; -}; - -/* -------------------------------------------------------------------------- */ -/* Section PROPS */ -/* -------------------------------------------------------------------------- */ - -struct Prop -{ - struct DashboardSpecial + inline void SetEngineTrigger(Trigger::EngineTrigger const &trig) + { + shortbound_trigger_action = (int)trig.function; + longbound_trigger_action = (int)trig.motor_index; + } + + inline Trigger::EngineTrigger GetEngineTrigger() const + { + assert(HasFlag_E_EngineTrigger()); + EngineTrigger trig; + trig.function = static_cast(shortbound_trigger_action); + trig.motor_index = static_cast(longbound_trigger_action); + return trig; + } + + inline void SetCommandKeyTrigger(CommandKeyTrigger const &trig) + { + shortbound_trigger_action = (int)trig.contraction_trigger_key; + longbound_trigger_action = (int)trig.extension_trigger_key; + } + + inline CommandKeyTrigger GetCommandKeyTrigger() const + { + assert(BITMASK_IS_0(options, OPTION_B_BLOCK_TRIGGERS | OPTION_A_INV_BLOCK_TRIGGERS | OPTION_h_UNLOCK_HOOKGROUPS_KEY | + OPTION_H_LOCK_HOOKGROUPS_KEY | OPTION_E_ENGINE_TRIGGER)); + CommandKeyTrigger out; + out.contraction_trigger_key = static_cast(shortbound_trigger_action); + out.extension_trigger_key = static_cast(longbound_trigger_action); + return out; + } + + inline void SetHookToggleTrigger(HookToggleTrigger const &trig) + { + shortbound_trigger_action = trig.contraction_trigger_hookgroup_id; + longbound_trigger_action = trig.extension_trigger_hookgroup_id; + } + + inline HookToggleTrigger GetHookToggleTrigger() const + { + assert(HasFlag_h_UnlocksHookGroup() || HasFlag_H_LocksHookGroup()); + HookToggleTrigger trig; + trig.contraction_trigger_hookgroup_id = shortbound_trigger_action; + trig.extension_trigger_hookgroup_id = longbound_trigger_action; + return trig; + } + + Node::Ref nodes[2]; + float contraction_trigger_limit; + float expansion_trigger_limit; + unsigned int options; + float boundary_timer; + std::shared_ptr beam_defaults; + int detacher_group; + int shortbound_trigger_action; + int longbound_trigger_action; + }; + + /* -------------------------------------------------------------------------- */ + /* Section LOCKGROUPS */ + /* -------------------------------------------------------------------------- */ + + struct Lockgroup { - DashboardSpecial(): - offset(Ogre::Vector3::ZERO), // Default depends on right/left-hand dashboard placement - rotation_angle(160.f), - _offset_is_set(false), - mesh_name("dirwheel.mesh") - {} + Lockgroup() : number(0) + { + nodes.reserve(20); + } - Ogre::Vector3 offset; - bool _offset_is_set; - float rotation_angle; - Ogre::String mesh_name; + static const int LOCKGROUP_DEFAULT = -1; + static const int LOCKGROUP_NOLOCK = 9999; + + int number; + std::vector nodes; }; - struct BeaconSpecial + /* -------------------------------------------------------------------------- */ + /* Section MANAGEDMATERIALS */ + /* -------------------------------------------------------------------------- */ + + struct ManagedMaterial { - BeaconSpecial(): - color(1.0, 0.5, 0.0), - flare_material_name("tracks/beaconflare") - {} + /* IMPORTANT! Order of these values must match Regexes::IDENTIFY_MANAGED_MATERIAL_TYPE enum from Regexes.h */ + enum Type + { + TYPE_FLEXMESH_STANDARD = 1, + TYPE_FLEXMESH_TRANSPARENT, + TYPE_MESH_STANDARD, + TYPE_MESH_TRANSPARENT, + + TYPE_INVALID = 0xFFFFFFFF + }; + + Ogre::String name; + + /* Attributes */ + Type type; + ManagedMaterialsOptions options; + + /* Textures */ + Ogre::String diffuse_map; + Ogre::String damaged_diffuse_map; + Ogre::String specular_map; - Ogre::String flare_material_name; - Ogre::ColourValue color; + bool HasDamagedDiffuseMap() + { + return (damaged_diffuse_map.length() != 0 && damaged_diffuse_map[0] != '-'); + } + + bool HasSpecularMap() + { + return (specular_map.length() != 0 && specular_map[0] != '-'); + } }; - Prop(): - offset(Ogre::Vector3::ZERO), - rotation(Ogre::Vector3::ZERO), - special(SPECIAL_INVALID) - {} + /* -------------------------------------------------------------------------- */ + /* Section MATERIALFLAREBINDINGS */ + /* -------------------------------------------------------------------------- */ - /* IMPORTANT! Values must match results from Regexes::SPECIAL_PROPS */ - enum Special + struct MaterialFlareBinding { - SPECIAL_MIRROR_LEFT = 1, - SPECIAL_MIRROR_RIGHT, - SPECIAL_DASHBOARD_LEFT, - SPECIAL_DASHBOARD_RIGHT, - SPECIAL_AERO_PROP_SPIN, - SPECIAL_AERO_PROP_BLADE, - SPECIAL_DRIVER_SEAT, - SPECIAL_DRIVER_SEAT_2, - SPECIAL_BEACON, - SPECIAL_REDBEACON, - SPECIAL_LIGHTBAR, + MaterialFlareBinding() : flare_number(0) + { + } - SPECIAL_INVALID = 0xFFFFFFFF + unsigned int flare_number; + Ogre::String material_name; }; - Node::Ref reference_node; - Node::Ref x_axis_node; - Node::Ref y_axis_node; - Ogre::Vector3 offset; - Ogre::Vector3 rotation; - Ogre::String mesh_name; - std::list animations; - CameraSettings camera_settings; - Special special; - BeaconSpecial special_prop_beacon; - DashboardSpecial special_prop_dashboard; -}; + /* -------------------------------------------------------------------------- */ + /* Section NODECOLLISION */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section RAILGROUPS */ -/* -------------------------------------------------------------------------- */ + struct NodeCollision + { + NodeCollision() : radius(0) + { + } -struct RailGroup -{ - RailGroup(): - id(0) - {} + Node::Ref node; + float radius; + }; - unsigned int id; - std::vector node_list; -}; + /* -------------------------------------------------------------------------- */ + /* Section PARTICLES */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section Ropables */ -/* -------------------------------------------------------------------------- */ + struct Particle + { + Node::Ref emitter_node; + Node::Ref reference_node; + Ogre::String particle_system_name; + }; -struct Ropable -{ - Ropable(): - group(-1), // = value not set - has_multilock(false) - {} + /* -------------------------------------------------------------------------- */ + /* Section PISTONPROPS */ + /* -------------------------------------------------------------------------- */ - Node::Ref node; - int group; - bool has_multilock; -}; + struct Pistonprop + { + Pistonprop() : turbine_power_kW(0), pitch(0) + { + } + + Node::Ref reference_node; + Node::Ref axis_node; + Node::Ref blade_tip_nodes[4]; + Node::Ref couple_node; + float turbine_power_kW; + float pitch; + Ogre::String airfoil; + }; -/* -------------------------------------------------------------------------- */ -/* Section ROPES */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* Section PROPS */ + /* -------------------------------------------------------------------------- */ -struct Rope -{ - Rope(): - invisible(false), - detacher_group(0) /* Global detacher group */ - {} - - Node::Ref root_node; - Node::Ref end_node; - bool invisible; - std::shared_ptr beam_defaults; - int detacher_group; -}; - -/* -------------------------------------------------------------------------- */ -/* Section SCREWPROPS */ -/* -------------------------------------------------------------------------- */ - -struct Screwprop -{ - Screwprop(): - power(0) - {} + struct Prop + { + struct DashboardSpecial + { + DashboardSpecial() + : offset(Ogre::Vector3::ZERO), // Default depends on right/left-hand dashboard placement + rotation_angle(160.f), _offset_is_set(false), mesh_name("dirwheel.mesh") + { + } + + Ogre::Vector3 offset; + bool _offset_is_set; + float rotation_angle; + Ogre::String mesh_name; + }; - Node::Ref prop_node; - Node::Ref back_node; - Node::Ref top_node; - float power; -}; + struct BeaconSpecial + { + BeaconSpecial() : color(1.0, 0.5, 0.0), flare_material_name("tracks/beaconflare") + { + } -/* -------------------------------------------------------------------------- */ -/* Section SLIDENODES */ -/* -------------------------------------------------------------------------- */ + Ogre::String flare_material_name; + Ogre::ColourValue color; + }; -struct SlideNode -{ - SlideNode(); - - BITMASK_PROPERTY( constraint_flags, 1, CONSTRAINT_ATTACH_ALL , HasConstraint_a_AttachAll , SetConstraint_a_AttachAll ) - BITMASK_PROPERTY( constraint_flags, 2, CONSTRAINT_ATTACH_FOREIGN , HasConstraint_f_AttachForeign , SetConstraint_f_AttachForeign ) - BITMASK_PROPERTY( constraint_flags, 3, CONSTRAINT_ATTACH_SELF , HasConstraint_s_AttachSelf , SetConstraint_s_AttachSelf ) - BITMASK_PROPERTY( constraint_flags, 4, CONSTRAINT_ATTACH_NONE , HasConstraint_n_AttachNone , SetConstraint_n_AttachNone ) - - Node::Ref slide_node; - std::vector rail_node_ranges; - float spring_rate; - float break_force; - float tolerance; - int railgroup_id; - bool _railgroup_id_set; - float attachment_rate; - float max_attachment_distance; - bool _break_force_set; - unsigned int constraint_flags; -}; - -/* -------------------------------------------------------------------------- */ -/* Section SOUNDSOURCES */ -/* -------------------------------------------------------------------------- */ - -struct SoundSource -{ - Node::Ref node; - Ogre::String sound_script_name; -}; + Prop() : offset(Ogre::Vector3::ZERO), rotation(Ogre::Vector3::ZERO), special(SPECIAL_INVALID) + { + } + + /* IMPORTANT! Values must match results from Regexes::SPECIAL_PROPS */ + enum Special + { + SPECIAL_MIRROR_LEFT = 1, + SPECIAL_MIRROR_RIGHT, + SPECIAL_DASHBOARD_LEFT, + SPECIAL_DASHBOARD_RIGHT, + SPECIAL_AERO_PROP_SPIN, + SPECIAL_AERO_PROP_BLADE, + SPECIAL_DRIVER_SEAT, + SPECIAL_DRIVER_SEAT_2, + SPECIAL_BEACON, + SPECIAL_REDBEACON, + SPECIAL_LIGHTBAR, + + SPECIAL_INVALID = 0xFFFFFFFF + }; -/* -------------------------------------------------------------------------- */ -/* Section SOUNDSOURCES2 */ -/* -------------------------------------------------------------------------- */ + Node::Ref reference_node; + Node::Ref x_axis_node; + Node::Ref y_axis_node; + Ogre::Vector3 offset; + Ogre::Vector3 rotation; + Ogre::String mesh_name; + std::list animations; + CameraSettings camera_settings; + Special special; + BeaconSpecial special_prop_beacon; + DashboardSpecial special_prop_dashboard; + }; -struct SoundSource2: SoundSource -{ - enum Mode + /* -------------------------------------------------------------------------- */ + /* Section RAILGROUPS */ + /* -------------------------------------------------------------------------- */ + + struct RailGroup { - MODE_ALWAYS = -2, - MODE_OUTSIDE = -1, - MODE_CINECAM = 1, + RailGroup() : id(0) + { + } - MODE_INVALID = 0xFFFFFFFF + unsigned int id; + std::vector node_list; }; - SoundSource2(): - mode(MODE_INVALID), - cinecam_index(0) - {} + /* -------------------------------------------------------------------------- */ + /* Section Ropables */ + /* -------------------------------------------------------------------------- */ - Mode mode; - unsigned int cinecam_index; -}; + struct Ropable + { + Ropable() + : group(-1), // = value not set + has_multilock(false) + { + } -/* -------------------------------------------------------------------------- */ -/* Section SPEEDLIMITER */ -/* -------------------------------------------------------------------------- */ + Node::Ref node; + int group; + bool has_multilock; + }; -struct SpeedLimiter -{ - SpeedLimiter(): - max_speed(0.f), - is_enabled(false) - {} + /* -------------------------------------------------------------------------- */ + /* Section ROPES */ + /* -------------------------------------------------------------------------- */ - float max_speed; - bool is_enabled; -}; + struct Rope + { + Rope() : invisible(false), detacher_group(0) /* Global detacher group */ + { + } -/* -------------------------------------------------------------------------- */ -/* Section SUBMESH */ -/* -------------------------------------------------------------------------- */ + Node::Ref root_node; + Node::Ref end_node; + bool invisible; + std::shared_ptr beam_defaults; + int detacher_group; + }; -struct Cab -{ - Cab(): - options(0) - {} + /* -------------------------------------------------------------------------- */ + /* Section SCREWPROPS */ + /* -------------------------------------------------------------------------- */ - bool GetOption_D_ContactBuoyant() + struct Screwprop { - return BITMASK_IS_1(options, OPTION_b_BUOYANT) && BITMASK_IS_1(options, OPTION_c_CONTACT); - } + Screwprop() : power(0) + { + } + + Node::Ref prop_node; + Node::Ref back_node; + Node::Ref top_node; + float power; + }; + + /* -------------------------------------------------------------------------- */ + /* Section SLIDENODES */ + /* -------------------------------------------------------------------------- */ - bool GetOption_F_10xTougherBuoyant() + struct SlideNode { - return BITMASK_IS_1(options, OPTION_b_BUOYANT) && BITMASK_IS_1(options, OPTION_p_10xTOUGHER); - } + SlideNode(); + + BITMASK_PROPERTY(constraint_flags, 1, CONSTRAINT_ATTACH_ALL, HasConstraint_a_AttachAll, SetConstraint_a_AttachAll) + BITMASK_PROPERTY(constraint_flags, 2, CONSTRAINT_ATTACH_FOREIGN, HasConstraint_f_AttachForeign, + SetConstraint_f_AttachForeign) + BITMASK_PROPERTY(constraint_flags, 3, CONSTRAINT_ATTACH_SELF, HasConstraint_s_AttachSelf, SetConstraint_s_AttachSelf) + BITMASK_PROPERTY(constraint_flags, 4, CONSTRAINT_ATTACH_NONE, HasConstraint_n_AttachNone, SetConstraint_n_AttachNone) + + Node::Ref slide_node; + std::vector rail_node_ranges; + float spring_rate; + float break_force; + float tolerance; + int railgroup_id; + bool _railgroup_id_set; + float attachment_rate; + float max_attachment_distance; + bool _break_force_set; + unsigned int constraint_flags; + }; + + /* -------------------------------------------------------------------------- */ + /* Section SOUNDSOURCES */ + /* -------------------------------------------------------------------------- */ - bool GetOption_S_UnpenetrableBuoyant() + struct SoundSource { - return BITMASK_IS_1(options, OPTION_b_BUOYANT) && BITMASK_IS_1(options, OPTION_u_INVULNERABLE); - } + Node::Ref node; + Ogre::String sound_script_name; + }; - static const unsigned int OPTION_c_CONTACT = BITMASK(1); - static const unsigned int OPTION_b_BUOYANT = BITMASK(2); - static const unsigned int OPTION_p_10xTOUGHER = BITMASK(3); - static const unsigned int OPTION_u_INVULNERABLE = BITMASK(4); - static const unsigned int OPTION_s_BUOYANT_NO_DRAG = BITMASK(5); - static const unsigned int OPTION_r_BUOYANT_ONLY_DRAG = BITMASK(6); + /* -------------------------------------------------------------------------- */ + /* Section SOUNDSOURCES2 */ + /* -------------------------------------------------------------------------- */ - Node::Ref nodes[3]; - unsigned int options; -}; + struct SoundSource2 : SoundSource + { + enum Mode + { + MODE_ALWAYS = -2, + MODE_OUTSIDE = -1, + MODE_CINECAM = 1, -struct Texcoord -{ - Texcoord(): - u(0), - v(0) - {} + MODE_INVALID = 0xFFFFFFFF + }; - Node::Ref node; - float u; - float v; -}; + SoundSource2() : mode(MODE_INVALID), cinecam_index(0) + { + } -struct Submesh -{ - Submesh(): - backmesh(false) - {} + Mode mode; + unsigned int cinecam_index; + }; - bool backmesh; - std::vector texcoords; - std::vector cab_triangles; -}; + /* -------------------------------------------------------------------------- */ + /* Section SPEEDLIMITER */ + /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* Section TIES */ -/* -------------------------------------------------------------------------- */ + struct SpeedLimiter + { + SpeedLimiter() : max_speed(0.f), is_enabled(false) + { + } -struct Tie -{ - Tie(); - - static const char OPTION_n_FILLER = 'n'; - static const char OPTION_v_FILLER = 'v'; - static const char OPTION_i_INVISIBLE = 'i'; - static const char OPTION_s_NO_SELF_LOCK = 's'; - - Node::Ref root_node; - float max_reach_length; - float auto_shorten_rate; - float min_length; - float max_length; - bool is_invisible; - bool disable_self_lock; - float max_stress; - std::shared_ptr beam_defaults; - int detacher_group; - int group; -}; - -/* -------------------------------------------------------------------------- */ -/* Section TORQUECURVE */ -/* -------------------------------------------------------------------------- */ - -struct TorqueCurve -{ - TorqueCurve() - {} + float max_speed; + bool is_enabled; + }; + + /* -------------------------------------------------------------------------- */ + /* Section SUBMESH */ + /* -------------------------------------------------------------------------- */ - struct Sample + struct Cab { - Sample(): - power(0), - torque_percent(0) - {} + Cab() : options(0) + { + } + + bool GetOption_D_ContactBuoyant() + { + return BITMASK_IS_1(options, OPTION_b_BUOYANT) && BITMASK_IS_1(options, OPTION_c_CONTACT); + } + + bool GetOption_F_10xTougherBuoyant() + { + return BITMASK_IS_1(options, OPTION_b_BUOYANT) && BITMASK_IS_1(options, OPTION_p_10xTOUGHER); + } - float power; - float torque_percent; + bool GetOption_S_UnpenetrableBuoyant() + { + return BITMASK_IS_1(options, OPTION_b_BUOYANT) && BITMASK_IS_1(options, OPTION_u_INVULNERABLE); + } + + static const unsigned int OPTION_c_CONTACT = BITMASK(1); + static const unsigned int OPTION_b_BUOYANT = BITMASK(2); + static const unsigned int OPTION_p_10xTOUGHER = BITMASK(3); + static const unsigned int OPTION_u_INVULNERABLE = BITMASK(4); + static const unsigned int OPTION_s_BUOYANT_NO_DRAG = BITMASK(5); + static const unsigned int OPTION_r_BUOYANT_ONLY_DRAG = BITMASK(6); + + Node::Ref nodes[3]; + unsigned int options; }; - std::vector samples; - Ogre::String predefined_func_name; -}; + struct Texcoord + { + Texcoord() : u(0), v(0) + { + } -/* -------------------------------------------------------------------------- */ -/* Section TURBOJETS */ -/* -------------------------------------------------------------------------- */ + Node::Ref node; + float u; + float v; + }; -struct Turbojet -{ - Turbojet(): - is_reversable(0), - dry_thrust(0), - wet_thrust(0), - front_diameter(0), - back_diameter(0), - nozzle_length(0) - {} - - Node::Ref front_node; - Node::Ref back_node; - Node::Ref side_node; - int is_reversable; - float dry_thrust; - float wet_thrust; - float front_diameter; - float back_diameter; - float nozzle_length; -}; - -/* -------------------------------------------------------------------------- */ -/* Section TURBOPROPS, TURBOPROPS2 */ -/* -------------------------------------------------------------------------- */ - -struct Turboprop2 -{ - Turboprop2(): - turbine_power_kW(0), - _format_version(2) - {} - - Node::Ref reference_node; - Node::Ref axis_node; - Node::Ref blade_tip_nodes[4]; - float turbine_power_kW; - Ogre::String airfoil; - Node::Ref couple_node; - unsigned int _format_version; -}; - -/* -------------------------------------------------------------------------- */ -/* Section VIDEOCAMERA */ -/* -------------------------------------------------------------------------- */ - -struct VideoCamera -{ - VideoCamera(); - - Node::Ref reference_node; - Node::Ref left_node; - Node::Ref bottom_node; - Node::Ref alt_reference_node; - Node::Ref alt_orientation_node; - Ogre::Vector3 offset; - Ogre::Vector3 rotation; - float field_of_view; - unsigned int texture_width; - unsigned int texture_height; - float min_clip_distance; - float max_clip_distance; - int camera_role; - int camera_mode; - Ogre::String material_name; - Ogre::String camera_name; -}; - -/* -------------------------------------------------------------------------- */ -/* Section WINGS */ -/* -------------------------------------------------------------------------- */ - -struct Wing -{ - static const std::string CONTROL_LEGAL_FLAGS; - - Wing(); - - enum Control - { - CONTROL_n_NONE = 'n', - CONTROL_a_RIGHT_AILERON = 'a', - CONTROL_b_LEFT_AILERON = 'b', - CONTROL_f_FLAP = 'f', - CONTROL_e_ELEVATOR = 'e', - CONTROL_r_RUDDER = 'r', - CONTROL_S_RIGHT_HAND_STABILATOR = 'S', - CONTROL_T_LEFT_HAND_STABILATOR = 'T', - CONTROL_c_RIGHT_ELEVON = 'c', - CONTROL_d_LEFT_ELEVON = 'd', - CONTROL_g_RIGHT_FLAPERON = 'g', - CONTROL_h_LEFT_FLAPERON = 'h', - CONTROL_U_RIGHT_HAND_TAILERON = 'U', - CONTROL_V_LEFT_HAND_TAILERON = 'V', - CONTROL_i_RIGHT_RUDDERVATOR = 'i', - CONTROL_j_LEFT_RUDDERVATOR = 'j', - - CONTROL_INVALID = 0xFFFFFFFF - }; - - Node::Ref nodes[8]; - float tex_coords[8]; - Control control_surface; - float chord_point; - float min_deflection; - float max_deflection; - Ogre::String airfoil; - float efficacy_coef; -}; - -/* -------------------------------------------------------------------------- */ -/* Root document */ -/* -------------------------------------------------------------------------- */ - -struct File -{ - /** Modular part of vehicle (part of file wrapped in 'section ~ end_section' tags) - */ - struct Module + struct Submesh { - Module(Ogre::String const & name); + Submesh() : backmesh(false) + { + } - Ogre::String name; + bool backmesh; + std::vector texcoords; + std::vector cab_triangles; + }; + + /* -------------------------------------------------------------------------- */ + /* Section TIES */ + /* -------------------------------------------------------------------------- */ - Ogre::String help_panel_material_name; - std::vector contacter_nodes; - - /* Sections*/ - std::vector airbrakes; - std::vector animators; - std::shared_ptr anti_lock_brakes; - std::vector axles; - std::vector beams; - std::shared_ptr brakes; - std::vector cameras; - std::vector camera_rails; - std::vector collision_boxes; - std::vector cinecam; - std::vector commands_2; /* sections 'commands' & 'commands2' are unified */ - std::shared_ptr cruise_control; - std::vector contacters; - std::shared_ptr engine; - std::shared_ptr engoption; - std::shared_ptr engturbo; - std::vector exhausts; - std::shared_ptr ext_camera; - std::vector fixes; - std::vector flares_2; - std::vector> flexbodies; - std::vector flex_body_wheels; - std::vector fusedrag; - std::shared_ptr globals; - std::shared_ptr gui_settings; - std::vector hooks; - std::vector hydros; - std::vector interaxles; - std::vector lockgroups; - std::vector managed_materials; - std::vector material_flare_bindings; - std::vector mesh_wheels; - std::vector nodes; /* Nodes and Nodes2 are unified in this parser */ - std::vector node_collisions; - std::vector particles; - std::vector pistonprops; - std::vector props; - std::vector railgroups; - std::vector ropables; - std::vector ropes; - std::vector rotators; - std::vector rotators_2; - std::vector screwprops; - std::vector shocks; - std::vector shocks_2; - std::vector shocks_3; - SkeletonSettings skeleton_settings; - std::vector slidenodes; - std::shared_ptr slope_brake; - std::vector soundsources; - std::vector soundsources2; - SpeedLimiter speed_limiter; - Ogre::String submeshes_ground_model_name; - std::vector submeshes; - std::vector ties; - std::shared_ptr torque_curve; - std::shared_ptr traction_control; - std::shared_ptr transfer_case; - std::vector triggers; - std::vector turbojets; - std::vector turboprops_2; - std::vector videocameras; - std::vector wheeldetachers; - std::vector wheels; - std::vector wheels_2; - std::vector wings; - }; - - File(); - - /** IMPORTANT! If you add a value here, you must also modify Regexes::IDENTIFY_KEYWORD, it relies on numeric values of this enum. */ - enum Keyword - { - KEYWORD_ADD_ANIMATION = 1, - //KEYWORD_ADVDRAG, // not supported yet - KEYWORD_AIRBRAKES, - KEYWORD_ANIMATORS, - KEYWORD_ANTI_LOCK_BRAKES, - KEYWORD_AXLES, - KEYWORD_AUTHOR, - KEYWORD_BACKMESH, - KEYWORD_BEAMS, - KEYWORD_BRAKES, - KEYWORD_CAB, - KEYWORD_CAMERARAIL, - KEYWORD_CAMERAS, - KEYWORD_CINECAM, - KEYWORD_COLLISIONBOXES, - KEYWORD_COMMANDS, - KEYWORD_COMMANDS2, - KEYWORD_CONTACTERS, - KEYWORD_CRUISECONTROL, - KEYWORD_DESCRIPTION, - KEYWORD_DETACHER_GROUP, - KEYWORD_DISABLEDEFAULTSOUNDS, - KEYWORD_ENABLE_ADVANCED_DEFORM, - KEYWORD_END, - KEYWORD_END_SECTION, - KEYWORD_ENGINE, - KEYWORD_ENGOPTION, - KEYWORD_ENGTURBO, - KEYWORD_ENVMAP, - KEYWORD_EXHAUSTS, - KEYWORD_EXTCAMERA, - KEYWORD_FILEFORMATVERSION, - KEYWORD_FILEINFO, - KEYWORD_FIXES, - KEYWORD_FLARES, - KEYWORD_FLARES2, - KEYWORD_FLEXBODIES, - KEYWORD_FLEXBODY_CAMERA_MODE, - KEYWORD_FLEXBODYWHEELS, - KEYWORD_FORWARDCOMMANDS, - KEYWORD_FUSEDRAG, - KEYWORD_GLOBALS, - KEYWORD_GUID, - KEYWORD_GUISETTINGS, - KEYWORD_HELP, - KEYWORD_HIDE_IN_CHOOSER, - KEYWORD_HOOKGROUP, // obsolete, ignored - KEYWORD_HOOKS, - KEYWORD_HYDROS, - KEYWORD_IMPORTCOMMANDS, - KEYWORD_INTERAXLES, - KEYWORD_LOCKGROUPS, - KEYWORD_LOCKGROUP_DEFAULT_NOLOCK, - KEYWORD_MANAGEDMATERIALS, - KEYWORD_MATERIALFLAREBINDINGS, - KEYWORD_MESHWHEELS, - KEYWORD_MESHWHEELS2, - KEYWORD_MINIMASS, - KEYWORD_NODECOLLISION, - KEYWORD_NODES, - KEYWORD_NODES2, - KEYWORD_PARTICLES, - KEYWORD_PISTONPROPS, - KEYWORD_PROP_CAMERA_MODE, - KEYWORD_PROPS, - KEYWORD_RAILGROUPS, - KEYWORD_RESCUER, - KEYWORD_RIGIDIFIERS, - KEYWORD_ROLLON, - KEYWORD_ROPABLES, - KEYWORD_ROPES, - KEYWORD_ROTATORS, - KEYWORD_ROTATORS2, - KEYWORD_SCREWPROPS, - KEYWORD_SECTION, - KEYWORD_SECTIONCONFIG, - KEYWORD_SET_BEAM_DEFAULTS, - KEYWORD_SET_BEAM_DEFAULTS_SCALE, - KEYWORD_SET_COLLISION_RANGE, - KEYWORD_SET_DEFAULT_MINIMASS, - KEYWORD_SET_INERTIA_DEFAULTS, - KEYWORD_SET_MANAGEDMATS_OPTIONS, - KEYWORD_SET_NODE_DEFAULTS, - KEYWORD_SET_SHADOWS, - KEYWORD_SET_SKELETON_SETTINGS, - KEYWORD_SHOCKS, - KEYWORD_SHOCKS2, - KEYWORD_SHOCKS3, - KEYWORD_SLIDENODE_CONNECT_INSTANT, - KEYWORD_SLIDENODES, - KEYWORD_SLOPE_BRAKE, - KEYWORD_SOUNDSOURCES, - KEYWORD_SOUNDSOURCES2, - //KEYWORD_SOUNDSOURCES3, // not supported yet - KEYWORD_SPEEDLIMITER, - KEYWORD_SUBMESH, - KEYWORD_SUBMESH_GROUNDMODEL, - KEYWORD_TEXCOORDS, - KEYWORD_TIES, - KEYWORD_TORQUECURVE, - KEYWORD_TRACTION_CONTROL, - KEYWORD_TRANSFER_CASE, - KEYWORD_TRIGGERS, - KEYWORD_TURBOJETS, - KEYWORD_TURBOPROPS, - KEYWORD_TURBOPROPS2, - KEYWORD_VIDEOCAMERA, - KEYWORD_WHEELDETACHERS, - KEYWORD_WHEELS, - KEYWORD_WHEELS2, - KEYWORD_WINGS, - - KEYWORD_INVALID = 0xFFFFFFFF - }; - - enum Section - { - SECTION_AIRBRAKES, - SECTION_AUTHOR, - SECTION_ANIMATORS, - SECTION_ANTI_LOCK_BRAKES, - SECTION_AXLES, - SECTION_BEAMS, - SECTION_BRAKES, - SECTION_CAMERAS, - SECTION_CAMERA_RAIL, - SECTION_CINECAM, - SECTION_COLLISION_BOXES, - SECTION_COMMANDS, - SECTION_COMMANDS_2, - SECTION_CONTACTERS, - SECTION_ENGINE, - SECTION_ENGOPTION, - SECTION_ENGTURBO, - SECTION_EXHAUSTS, - SECTION_FIXES, - SECTION_FLARES, - SECTION_FLARES_2, - SECTION_FLEXBODIES, - SECTION_FLEX_BODY_WHEELS, - SECTION_FUSEDRAG, - SECTION_GLOBALS, - SECTION_GUI_SETTINGS, - SECTION_HELP, - SECTION_HOOKS, - SECTION_HYDROS, - SECTION_INTERAXLES, - SECTION_LOCKGROUPS, - SECTION_MANAGED_MATERIALS, - SECTION_MAT_FLARE_BINDINGS, - SECTION_MESH_WHEELS, - SECTION_MESH_WHEELS_2, - SECTION_MINIMASS, - SECTION_NODES, - SECTION_NODES_2, - SECTION_NODE_COLLISION, - SECTION_PARTICLES, - SECTION_PISTONPROPS, - SECTION_PROPS, - SECTION_RAILGROUPS, - SECTION_ROPABLES, - SECTION_ROPES, - SECTION_ROTATORS, - SECTION_ROTATORS_2, - SECTION_SCREWPROPS, - SECTION_SHOCKS, - SECTION_SHOCKS_2, - SECTION_SHOCKS_3, - SECTION_SLIDENODES, - SECTION_SOUNDSOURCES, - SECTION_SOUNDSOURCES2, - SECTION_SUBMESH, - SECTION_SLOPE_BRAKE, - SECTION_TIES, - SECTION_TORQUE_CURVE, - SECTION_TRACTION_CONTROL, - SECTION_TRANSFER_CASE, - SECTION_TRIGGERS, - SECTION_TRUCK_NAME, ///< The very start of file - SECTION_TURBOJETS, - SECTION_TURBOPROPS, - SECTION_TURBOPROPS_2, - SECTION_VIDEO_CAMERA, - SECTION_WHEELDETACHERS, - SECTION_WHEELS, - SECTION_WHEELS_2, - SECTION_WINGS, - - SECTION_NONE, ///< Right after rig name, for example. - - SECTION_INVALID = 0xFFFFFFFF - }; - - enum Subsection - { - SUBSECTION_NONE = 0, - - SUBSECTION__FLEXBODIES__PROPLIKE_LINE, - SUBSECTION__FLEXBODIES__FORSET_LINE, - - SUBSECTION__SUBMESH__TEXCOORDS, - SUBSECTION__SUBMESH__CAB, - - SUBSECTION_INVALID = 0xFFFFFFFF - }; - - static const char * SubsectionToString(Subsection subsection); - - static const char * SectionToString(Section section); - - static const char * KeywordToString(Keyword keyword); - - unsigned int file_format_version; - Ogre::String guid; - std::vector description; - bool hide_in_chooser; - bool enable_advanced_deformation; - bool slide_nodes_connect_instantly; - bool rollon; - bool forward_commands; - bool import_commands; - bool lockgroup_default_nolock; - bool rescuer; - bool disable_default_sounds; - Ogre::String name; - float collision_range; - - // Report - std::string loading_report; - int report_num_errors; - int report_num_warnings; - int report_num_other; - - // File hash - std::string hash; - - // Vehicle modules (caled 'sections' in truckfile doc) - std::shared_ptr root_module; ///< Required to exist. `shared_ptr` is used for unified handling with other modules. - std::map< Ogre::String, std::shared_ptr > user_modules; - - // File sections - std::vector authors; - std::shared_ptr file_info; - std::shared_ptr global_minimass; - bool minimass_skip_loaded_nodes; //!< Only apply minimum mass to nodes without "L" option. Global effect. -}; + struct Tie + { + Tie(); + + static const char OPTION_n_FILLER = 'n'; + static const char OPTION_v_FILLER = 'v'; + static const char OPTION_i_INVISIBLE = 'i'; + static const char OPTION_s_NO_SELF_LOCK = 's'; + + Node::Ref root_node; + float max_reach_length; + float auto_shorten_rate; + float min_length; + float max_length; + bool is_invisible; + bool disable_self_lock; + float max_stress; + std::shared_ptr beam_defaults; + int detacher_group; + int group; + }; + + /* -------------------------------------------------------------------------- */ + /* Section TORQUECURVE */ + /* -------------------------------------------------------------------------- */ + + struct TorqueCurve + { + TorqueCurve() + { + } + + struct Sample + { + Sample() : power(0), torque_percent(0) + { + } + + float power; + float torque_percent; + }; + + std::vector samples; + Ogre::String predefined_func_name; + }; + + /* -------------------------------------------------------------------------- */ + /* Section TURBOJETS */ + /* -------------------------------------------------------------------------- */ + + struct Turbojet + { + Turbojet() : is_reversable(0), dry_thrust(0), wet_thrust(0), front_diameter(0), back_diameter(0), nozzle_length(0) + { + } + + Node::Ref front_node; + Node::Ref back_node; + Node::Ref side_node; + int is_reversable; + float dry_thrust; + float wet_thrust; + float front_diameter; + float back_diameter; + float nozzle_length; + }; + + /* -------------------------------------------------------------------------- */ + /* Section TURBOPROPS, TURBOPROPS2 */ + /* -------------------------------------------------------------------------- */ + + struct Turboprop2 + { + Turboprop2() : turbine_power_kW(0), _format_version(2) + { + } + + Node::Ref reference_node; + Node::Ref axis_node; + Node::Ref blade_tip_nodes[4]; + float turbine_power_kW; + Ogre::String airfoil; + Node::Ref couple_node; + unsigned int _format_version; + }; + + /* -------------------------------------------------------------------------- */ + /* Section VIDEOCAMERA */ + /* -------------------------------------------------------------------------- */ + + struct VideoCamera + { + VideoCamera(); + + Node::Ref reference_node; + Node::Ref left_node; + Node::Ref bottom_node; + Node::Ref alt_reference_node; + Node::Ref alt_orientation_node; + Ogre::Vector3 offset; + Ogre::Vector3 rotation; + float field_of_view; + unsigned int texture_width; + unsigned int texture_height; + float min_clip_distance; + float max_clip_distance; + int camera_role; + int camera_mode; + Ogre::String material_name; + Ogre::String camera_name; + }; + + /* -------------------------------------------------------------------------- */ + /* Section WINGS */ + /* -------------------------------------------------------------------------- */ + + struct Wing + { + static const std::string CONTROL_LEGAL_FLAGS; + + Wing(); + + enum Control + { + CONTROL_n_NONE = 'n', + CONTROL_a_RIGHT_AILERON = 'a', + CONTROL_b_LEFT_AILERON = 'b', + CONTROL_f_FLAP = 'f', + CONTROL_e_ELEVATOR = 'e', + CONTROL_r_RUDDER = 'r', + CONTROL_S_RIGHT_HAND_STABILATOR = 'S', + CONTROL_T_LEFT_HAND_STABILATOR = 'T', + CONTROL_c_RIGHT_ELEVON = 'c', + CONTROL_d_LEFT_ELEVON = 'd', + CONTROL_g_RIGHT_FLAPERON = 'g', + CONTROL_h_LEFT_FLAPERON = 'h', + CONTROL_U_RIGHT_HAND_TAILERON = 'U', + CONTROL_V_LEFT_HAND_TAILERON = 'V', + CONTROL_i_RIGHT_RUDDERVATOR = 'i', + CONTROL_j_LEFT_RUDDERVATOR = 'j', + + CONTROL_INVALID = 0xFFFFFFFF + }; + + Node::Ref nodes[8]; + float tex_coords[8]; + Control control_surface; + float chord_point; + float min_deflection; + float max_deflection; + Ogre::String airfoil; + float efficacy_coef; + }; + + /* -------------------------------------------------------------------------- */ + /* Root document */ + /* -------------------------------------------------------------------------- */ + + struct File + { + /** Modular part of vehicle (part of file wrapped in 'section ~ end_section' tags) + */ + struct Module + { + Module(Ogre::String const &name); + + Ogre::String name; + + Ogre::String help_panel_material_name; + std::vector contacter_nodes; + + /* Sections*/ + std::vector airbrakes; + std::vector animators; + std::shared_ptr anti_lock_brakes; + std::vector axles; + std::vector beams; + std::shared_ptr brakes; + std::vector cameras; + std::vector camera_rails; + std::vector collision_boxes; + std::vector cinecam; + std::vector commands_2; /* sections 'commands' & 'commands2' are unified */ + std::shared_ptr cruise_control; + std::vector contacters; + std::shared_ptr engine; + std::shared_ptr engoption; + std::shared_ptr engturbo; + std::vector exhausts; + std::shared_ptr ext_camera; + std::vector fixes; + std::vector flares_2; + std::vector> flexbodies; + std::vector flex_body_wheels; + std::vector fusedrag; + std::shared_ptr globals; + std::shared_ptr gui_settings; + std::vector hooks; + std::vector hydros; + std::vector interaxles; + std::vector lockgroups; + std::vector managed_materials; + std::vector material_flare_bindings; + std::vector mesh_wheels; + std::vector nodes; /* Nodes and Nodes2 are unified in this parser */ + std::vector node_collisions; + std::vector particles; + std::vector pistonprops; + std::vector props; + std::vector railgroups; + std::vector ropables; + std::vector ropes; + std::vector rotators; + std::vector rotators_2; + std::vector screwprops; + std::vector shocks; + std::vector shocks_2; + std::vector shocks_3; + SkeletonSettings skeleton_settings; + std::vector slidenodes; + std::shared_ptr slope_brake; + std::vector soundsources; + std::vector soundsources2; + SpeedLimiter speed_limiter; + Ogre::String submeshes_ground_model_name; + std::vector submeshes; + std::vector ties; + std::shared_ptr torque_curve; + std::shared_ptr traction_control; + std::shared_ptr transfer_case; + std::vector triggers; + std::vector turbojets; + std::vector turboprops_2; + std::vector videocameras; + std::vector wheeldetachers; + std::vector wheels; + std::vector wheels_2; + std::vector wings; + }; + + File(); + + /** IMPORTANT! If you add a value here, you must also modify Regexes::IDENTIFY_KEYWORD, it relies on numeric values of + * this enum. */ + enum Keyword + { + KEYWORD_ADD_ANIMATION = 1, + // KEYWORD_ADVDRAG, // not supported yet + KEYWORD_AIRBRAKES, + KEYWORD_ANIMATORS, + KEYWORD_ANTI_LOCK_BRAKES, + KEYWORD_AXLES, + KEYWORD_AUTHOR, + KEYWORD_BACKMESH, + KEYWORD_BEAMS, + KEYWORD_BRAKES, + KEYWORD_CAB, + KEYWORD_CAMERARAIL, + KEYWORD_CAMERAS, + KEYWORD_CINECAM, + KEYWORD_COLLISIONBOXES, + KEYWORD_COMMANDS, + KEYWORD_COMMANDS2, + KEYWORD_CONTACTERS, + KEYWORD_CRUISECONTROL, + KEYWORD_DESCRIPTION, + KEYWORD_DETACHER_GROUP, + KEYWORD_DISABLEDEFAULTSOUNDS, + KEYWORD_ENABLE_ADVANCED_DEFORM, + KEYWORD_END, + KEYWORD_END_SECTION, + KEYWORD_ENGINE, + KEYWORD_ENGOPTION, + KEYWORD_ENGTURBO, + KEYWORD_ENVMAP, + KEYWORD_EXHAUSTS, + KEYWORD_EXTCAMERA, + KEYWORD_FILEFORMATVERSION, + KEYWORD_FILEINFO, + KEYWORD_FIXES, + KEYWORD_FLARES, + KEYWORD_FLARES2, + KEYWORD_FLEXBODIES, + KEYWORD_FLEXBODY_CAMERA_MODE, + KEYWORD_FLEXBODYWHEELS, + KEYWORD_FORWARDCOMMANDS, + KEYWORD_FUSEDRAG, + KEYWORD_GLOBALS, + KEYWORD_GUID, + KEYWORD_GUISETTINGS, + KEYWORD_HELP, + KEYWORD_HIDE_IN_CHOOSER, + KEYWORD_HOOKGROUP, // obsolete, ignored + KEYWORD_HOOKS, + KEYWORD_HYDROS, + KEYWORD_IMPORTCOMMANDS, + KEYWORD_INTERAXLES, + KEYWORD_LOCKGROUPS, + KEYWORD_LOCKGROUP_DEFAULT_NOLOCK, + KEYWORD_MANAGEDMATERIALS, + KEYWORD_MATERIALFLAREBINDINGS, + KEYWORD_MESHWHEELS, + KEYWORD_MESHWHEELS2, + KEYWORD_MINIMASS, + KEYWORD_NODECOLLISION, + KEYWORD_NODES, + KEYWORD_NODES2, + KEYWORD_PARTICLES, + KEYWORD_PISTONPROPS, + KEYWORD_PROP_CAMERA_MODE, + KEYWORD_PROPS, + KEYWORD_RAILGROUPS, + KEYWORD_RESCUER, + KEYWORD_RIGIDIFIERS, + KEYWORD_ROLLON, + KEYWORD_ROPABLES, + KEYWORD_ROPES, + KEYWORD_ROTATORS, + KEYWORD_ROTATORS2, + KEYWORD_SCREWPROPS, + KEYWORD_SECTION, + KEYWORD_SECTIONCONFIG, + KEYWORD_SET_BEAM_DEFAULTS, + KEYWORD_SET_BEAM_DEFAULTS_SCALE, + KEYWORD_SET_COLLISION_RANGE, + KEYWORD_SET_DEFAULT_MINIMASS, + KEYWORD_SET_INERTIA_DEFAULTS, + KEYWORD_SET_MANAGEDMATS_OPTIONS, + KEYWORD_SET_NODE_DEFAULTS, + KEYWORD_SET_SHADOWS, + KEYWORD_SET_SKELETON_SETTINGS, + KEYWORD_SHOCKS, + KEYWORD_SHOCKS2, + KEYWORD_SHOCKS3, + KEYWORD_SLIDENODE_CONNECT_INSTANT, + KEYWORD_SLIDENODES, + KEYWORD_SLOPE_BRAKE, + KEYWORD_SOUNDSOURCES, + KEYWORD_SOUNDSOURCES2, + // KEYWORD_SOUNDSOURCES3, // not supported yet + KEYWORD_SPEEDLIMITER, + KEYWORD_SUBMESH, + KEYWORD_SUBMESH_GROUNDMODEL, + KEYWORD_TEXCOORDS, + KEYWORD_TIES, + KEYWORD_TORQUECURVE, + KEYWORD_TRACTION_CONTROL, + KEYWORD_TRANSFER_CASE, + KEYWORD_TRIGGERS, + KEYWORD_TURBOJETS, + KEYWORD_TURBOPROPS, + KEYWORD_TURBOPROPS2, + KEYWORD_VIDEOCAMERA, + KEYWORD_WHEELDETACHERS, + KEYWORD_WHEELS, + KEYWORD_WHEELS2, + KEYWORD_WINGS, + + KEYWORD_INVALID = 0xFFFFFFFF + }; + + enum Section + { + SECTION_AIRBRAKES, + SECTION_AUTHOR, + SECTION_ANIMATORS, + SECTION_ANTI_LOCK_BRAKES, + SECTION_AXLES, + SECTION_BEAMS, + SECTION_BRAKES, + SECTION_CAMERAS, + SECTION_CAMERA_RAIL, + SECTION_CINECAM, + SECTION_COLLISION_BOXES, + SECTION_COMMANDS, + SECTION_COMMANDS_2, + SECTION_CONTACTERS, + SECTION_ENGINE, + SECTION_ENGOPTION, + SECTION_ENGTURBO, + SECTION_EXHAUSTS, + SECTION_FIXES, + SECTION_FLARES, + SECTION_FLARES_2, + SECTION_FLEXBODIES, + SECTION_FLEX_BODY_WHEELS, + SECTION_FUSEDRAG, + SECTION_GLOBALS, + SECTION_GUI_SETTINGS, + SECTION_HELP, + SECTION_HOOKS, + SECTION_HYDROS, + SECTION_INTERAXLES, + SECTION_LOCKGROUPS, + SECTION_MANAGED_MATERIALS, + SECTION_MAT_FLARE_BINDINGS, + SECTION_MESH_WHEELS, + SECTION_MESH_WHEELS_2, + SECTION_MINIMASS, + SECTION_NODES, + SECTION_NODES_2, + SECTION_NODE_COLLISION, + SECTION_PARTICLES, + SECTION_PISTONPROPS, + SECTION_PROPS, + SECTION_RAILGROUPS, + SECTION_ROPABLES, + SECTION_ROPES, + SECTION_ROTATORS, + SECTION_ROTATORS_2, + SECTION_SCREWPROPS, + SECTION_SHOCKS, + SECTION_SHOCKS_2, + SECTION_SHOCKS_3, + SECTION_SLIDENODES, + SECTION_SOUNDSOURCES, + SECTION_SOUNDSOURCES2, + SECTION_SUBMESH, + SECTION_SLOPE_BRAKE, + SECTION_TIES, + SECTION_TORQUE_CURVE, + SECTION_TRACTION_CONTROL, + SECTION_TRANSFER_CASE, + SECTION_TRIGGERS, + SECTION_TRUCK_NAME, ///< The very start of file + SECTION_TURBOJETS, + SECTION_TURBOPROPS, + SECTION_TURBOPROPS_2, + SECTION_VIDEO_CAMERA, + SECTION_WHEELDETACHERS, + SECTION_WHEELS, + SECTION_WHEELS_2, + SECTION_WINGS, + + SECTION_NONE, ///< Right after rig name, for example. + + SECTION_INVALID = 0xFFFFFFFF + }; + + enum Subsection + { + SUBSECTION_NONE = 0, + + SUBSECTION__FLEXBODIES__PROPLIKE_LINE, + SUBSECTION__FLEXBODIES__FORSET_LINE, + + SUBSECTION__SUBMESH__TEXCOORDS, + SUBSECTION__SUBMESH__CAB, + + SUBSECTION_INVALID = 0xFFFFFFFF + }; + + static const char *SubsectionToString(Subsection subsection); + + static const char *SectionToString(Section section); + + static const char *KeywordToString(Keyword keyword); + + unsigned int file_format_version; + Ogre::String guid; + std::vector description; + bool hide_in_chooser; + bool enable_advanced_deformation; + bool slide_nodes_connect_instantly; + bool rollon; + bool forward_commands; + bool import_commands; + bool lockgroup_default_nolock; + bool rescuer; + bool disable_default_sounds; + Ogre::String name; + float collision_range; + + // Report + std::string loading_report; + int report_num_errors; + int report_num_warnings; + int report_num_other; + + // File hash + std::string hash; + + // Vehicle modules (caled 'sections' in truckfile doc) + std::shared_ptr root_module; ///< Required to exist. `shared_ptr` is used for unified handling with other modules. + std::map> user_modules; + + // File sections + std::vector authors; + std::shared_ptr file_info; + std::shared_ptr global_minimass; + bool minimass_skip_loaded_nodes; //!< Only apply minimum mass to nodes without "L" option. Global effect. + }; } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Node.cpp b/source/main/resources/rig_def_fileformat/RigDef_Node.cpp index d1cad2a5be..0796441367 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Node.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_Node.cpp @@ -31,21 +31,16 @@ using namespace RigDef; // Ctors -Node::Id::Id(): - m_id_num(0), - m_flags(0) -{} - -Node::Id::Id(unsigned int num): - m_id_num(num), - m_flags(0) +Node::Id::Id() : m_id_num(0), m_flags(0) { - this->SetNum(num); } -Node::Id::Id(std::string const & id_str): - m_id_num(0), - m_flags(0) +Node::Id::Id(unsigned int num) : m_id_num(num), m_flags(0) +{ + this->SetNum(num); +} + +Node::Id::Id(std::string const &id_str) : m_id_num(0), m_flags(0) { this->SetStr(id_str); } @@ -60,7 +55,7 @@ void Node::Id::SetNum(unsigned int num) BITMASK_SET_1(m_flags, IS_TYPE_NUMBERED | IS_VALID); } -void Node::Id::SetStr(std::string const & id_str) +void Node::Id::SetStr(std::string const &id_str) { m_id_num = 0; m_id_str = id_str; @@ -76,19 +71,14 @@ void Node::Id::Invalidate() m_flags = 0; } -Node::Ref::Ref(std::string const & id_str, unsigned int id_num, unsigned flags, unsigned line_number): - m_flags(0), - m_line_number(line_number), - m_id_as_number(id_num) +Node::Ref::Ref(std::string const &id_str, unsigned int id_num, unsigned flags, unsigned line_number) + : m_flags(0), m_line_number(line_number), m_id_as_number(id_num) { m_id = id_str; BITMASK_SET_1(m_flags, flags); } -Node::Ref::Ref(): - m_flags(0), - m_id_as_number(0), - m_line_number(0) +Node::Ref::Ref() : m_flags(0), m_id_as_number(0), m_line_number(0) { } @@ -96,32 +86,28 @@ void Node::Ref::Invalidate() { m_id_as_number = 0; m_id.clear(); - m_flags = 0; + m_flags = 0; m_line_number = 0; } std::string Node::Ref::ToString() const { std::stringstream msg; - msg << "Node::Ref(id:" << m_id - << ", src line:"; - if (m_line_number != 0) - { - msg << m_line_number; - } + msg << "Node::Ref(id:" << m_id << ", src line:"; + if (m_line_number != 0) { msg << m_line_number; } else { msg << "?"; } msg << ", import flags:["; - if(GetImportState_IsValid ()) { msg << " VALID" ; } - if(GetImportState_MustCheckNamedFirst ()) { msg << " CHECK_NAMED_FIRST"; } - if(GetImportState_IsResolvedNamed ()) { msg << " RESOLVED_NAMED" ; } - if(GetImportState_IsResolvedNumbered ()) { msg << " RESOLVED_NUMBERED"; } + if (GetImportState_IsValid()) { msg << " VALID"; } + if (GetImportState_MustCheckNamedFirst()) { msg << " CHECK_NAMED_FIRST"; } + if (GetImportState_IsResolvedNamed()) { msg << " RESOLVED_NAMED"; } + if (GetImportState_IsResolvedNumbered()) { msg << " RESOLVED_NUMBERED"; } msg << "], regular flags:["; - if(GetRegularState_IsValid ()) { msg << " VALID" ; } - if(GetRegularState_IsNamed ()) { msg << " NAMED" ; } - if(GetRegularState_IsNumbered ()) { msg << " NUMBERED" ; } + if (GetRegularState_IsValid()) { msg << " VALID"; } + if (GetRegularState_IsNamed()) { msg << " NAMED"; } + if (GetRegularState_IsNumbered()) { msg << " NUMBERED"; } msg << "])"; return msg.str(); } diff --git a/source/main/resources/rig_def_fileformat/RigDef_Node.h b/source/main/resources/rig_def_fileformat/RigDef_Node.h index 839beedee8..3e081c88a2 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Node.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Node.h @@ -26,145 +26,170 @@ #pragma once #include "BitFlags.h" - #include "RigDef_Prerequisites.h" -#include #include +#include #include namespace RigDef { -struct Node -{ - /// Abstract node ID (numbered or named) - /// Node name is always available. For numbered nodes, it's the number converted to string. - /// Node number is only available for explicitly numbered nodes (legacy). - class Id - { - public: - BITMASK_PROPERTY_GET (m_flags, 1, IS_VALID, IsValid); - BITMASK_PROPERTY_GET (m_flags, 2, IS_TYPE_NUMBERED, IsTypeNumbered); - BITMASK_PROPERTY_GET (m_flags, 3, IS_TYPE_NAMED, IsTypeNamed); - - // Constructors - Id(); - Id(unsigned int id_num); - Id(std::string const & id_str); - - // Setters - void SetNum(unsigned int id_num); - void SetStr(std::string const & id_str); - - // Getters - inline std::string const & Str() const { return m_id_str; } - inline unsigned int Num() const { return m_id_num; } - - // Util - void Invalidate(); - std::string ToString() const; - - private: - - unsigned int m_id_num; - std::string m_id_str; - unsigned int m_flags; - }; - - /// Legacy parser resolved references on-the-fly and the condition to check named nodes was "are there any named nodes defined at this point?" - /// The new parser defers node resolution, so every ref. must keep track whether named nodes were already defined at that point. - class Ref - { - public: - // Since fileformatversion is not known from the beginning of parsing, 2 states must be kept - // at the same time: IMPORT_STATE and REGULAR_STATE. The outer logic must make the right pick. - BITMASK_PROPERTY (m_flags, 1, IMPORT_STATE_IS_VALID, GetImportState_IsValid, SetImportState_IsValid); - BITMASK_PROPERTY_GET (m_flags, 2, IMPORT_STATE_MUST_CHECK_NAMED_FIRST, GetImportState_MustCheckNamedFirst); - BITMASK_PROPERTY_GET (m_flags, 3, IMPORT_STATE_IS_RESOLVED_NAMED, GetImportState_IsResolvedNamed); - BITMASK_PROPERTY_GET (m_flags, 4, IMPORT_STATE_IS_RESOLVED_NUMBERED, GetImportState_IsResolvedNumbered); - - BITMASK_PROPERTY (m_flags, 5, REGULAR_STATE_IS_VALID, GetRegularState_IsValid, SetRegularState_IsValid); - BITMASK_PROPERTY_GET (m_flags, 6, REGULAR_STATE_IS_NAMED, GetRegularState_IsNamed); - BITMASK_PROPERTY_GET (m_flags, 7, REGULAR_STATE_IS_NUMBERED, GetRegularState_IsNumbered); - - Ref(std::string const & id_str, unsigned int id_num, unsigned flags, unsigned line_number_defined); - Ref(); - - inline std::string const & Str() const { return m_id; } - inline unsigned int Num() const { return m_id_as_number; } - - inline bool Compare (Ref const & rhs) const { return m_id == rhs.m_id; } - inline bool operator==(Ref const & rhs) const { return Compare(rhs); } - inline bool operator!=(Ref const & rhs) const { return ! Compare(rhs); } - - inline bool IsValidAnyState() const { return GetImportState_IsValid() || GetRegularState_IsValid(); } - inline unsigned GetLineNumber() const { return m_line_number; } - - void Invalidate(); - std::string ToString() const; - - private: - std::string m_id; - unsigned int m_id_as_number; - unsigned int m_flags; - unsigned int m_line_number; - }; - - struct Range + struct Node { - Range(Node::Ref const & start, Node::Ref const & end): - start(start), - end(end) - {} - - Range(Node::Ref const & single): - start(single), - end(single) - {} - - inline bool IsRange() const { return start != end; } - - void SetSingle(Node::Ref const & ref) + /// Abstract node ID (numbered or named) + /// Node name is always available. For numbered nodes, it's the number converted to string. + /// Node number is only available for explicitly numbered nodes (legacy). + class Id + { + public: + BITMASK_PROPERTY_GET(m_flags, 1, IS_VALID, IsValid); + BITMASK_PROPERTY_GET(m_flags, 2, IS_TYPE_NUMBERED, IsTypeNumbered); + BITMASK_PROPERTY_GET(m_flags, 3, IS_TYPE_NAMED, IsTypeNamed); + + // Constructors + Id(); + Id(unsigned int id_num); + Id(std::string const &id_str); + + // Setters + void SetNum(unsigned int id_num); + void SetStr(std::string const &id_str); + + // Getters + inline std::string const &Str() const + { + return m_id_str; + } + inline unsigned int Num() const + { + return m_id_num; + } + + // Util + void Invalidate(); + std::string ToString() const; + + private: + unsigned int m_id_num; + std::string m_id_str; + unsigned int m_flags; + }; + + /// Legacy parser resolved references on-the-fly and the condition to check named nodes was "are there any named nodes + /// defined at this point?" The new parser defers node resolution, so every ref. must keep track whether named nodes were + /// already defined at that point. + class Ref + { + public: + // Since fileformatversion is not known from the beginning of parsing, 2 states must be kept + // at the same time: IMPORT_STATE and REGULAR_STATE. The outer logic must make the right pick. + BITMASK_PROPERTY(m_flags, 1, IMPORT_STATE_IS_VALID, GetImportState_IsValid, SetImportState_IsValid); + BITMASK_PROPERTY_GET(m_flags, 2, IMPORT_STATE_MUST_CHECK_NAMED_FIRST, GetImportState_MustCheckNamedFirst); + BITMASK_PROPERTY_GET(m_flags, 3, IMPORT_STATE_IS_RESOLVED_NAMED, GetImportState_IsResolvedNamed); + BITMASK_PROPERTY_GET(m_flags, 4, IMPORT_STATE_IS_RESOLVED_NUMBERED, GetImportState_IsResolvedNumbered); + + BITMASK_PROPERTY(m_flags, 5, REGULAR_STATE_IS_VALID, GetRegularState_IsValid, SetRegularState_IsValid); + BITMASK_PROPERTY_GET(m_flags, 6, REGULAR_STATE_IS_NAMED, GetRegularState_IsNamed); + BITMASK_PROPERTY_GET(m_flags, 7, REGULAR_STATE_IS_NUMBERED, GetRegularState_IsNumbered); + + Ref(std::string const &id_str, unsigned int id_num, unsigned flags, unsigned line_number_defined); + Ref(); + + inline std::string const &Str() const + { + return m_id; + } + inline unsigned int Num() const + { + return m_id_as_number; + } + + inline bool Compare(Ref const &rhs) const + { + return m_id == rhs.m_id; + } + inline bool operator==(Ref const &rhs) const + { + return Compare(rhs); + } + inline bool operator!=(Ref const &rhs) const + { + return !Compare(rhs); + } + + inline bool IsValidAnyState() const + { + return GetImportState_IsValid() || GetRegularState_IsValid(); + } + inline unsigned GetLineNumber() const + { + return m_line_number; + } + + void Invalidate(); + std::string ToString() const; + + private: + std::string m_id; + unsigned int m_id_as_number; + unsigned int m_flags; + unsigned int m_line_number; + }; + + struct Range + { + Range(Node::Ref const &start, Node::Ref const &end) : start(start), end(end) + { + } + + Range(Node::Ref const &single) : start(single), end(single) + { + } + + inline bool IsRange() const + { + return start != end; + } + + void SetSingle(Node::Ref const &ref) + { + start = ref; + end = ref; + } + + Node::Ref start; + Node::Ref end; + }; + + Node() + : position(Ogre::Vector3::ZERO), options(0), load_weight_override(0), _has_load_weight_override(false), + detacher_group(0) /* Global detacher group */ { - start = ref; - end = ref; } - Node::Ref start; - Node::Ref end; + BITMASK_PROPERTY(options, 1, OPTION_n_MOUSE_GRAB, HasFlag_n, SetFlag_n) + BITMASK_PROPERTY(options, 2, OPTION_m_NO_MOUSE_GRAB, HasFlag_m, SetFlag_m) + BITMASK_PROPERTY(options, 3, OPTION_f_NO_SPARKS, HasFlag_f, SetFlag_f) + BITMASK_PROPERTY(options, 4, OPTION_x_EXHAUST_POINT, HasFlag_x, SetFlag_x) + BITMASK_PROPERTY(options, 5, OPTION_y_EXHAUST_DIRECTION, HasFlag_y, SetFlag_y) + BITMASK_PROPERTY(options, 6, OPTION_c_NO_GROUND_CONTACT, HasFlag_c, SetFlag_c) + BITMASK_PROPERTY(options, 7, OPTION_h_HOOK_POINT, HasFlag_h, SetFlag_h) + BITMASK_PROPERTY(options, 8, OPTION_e_TERRAIN_EDIT_POINT, HasFlag_e, SetFlag_e) + BITMASK_PROPERTY(options, 9, OPTION_b_EXTRA_BUOYANCY, HasFlag_b, SetFlag_b) + BITMASK_PROPERTY(options, 10, OPTION_p_NO_PARTICLES, HasFlag_p, SetFlag_p) + BITMASK_PROPERTY(options, 11, OPTION_L_LOG, HasFlag_L, SetFlag_L) + BITMASK_PROPERTY(options, 12, OPTION_l_LOAD_WEIGHT, HasFlag_l, SetFlag_l) + + Id id; + Ogre::Vector3 position; + unsigned int options; ///< Bit flags + float load_weight_override; + bool _has_load_weight_override; + std::shared_ptr node_defaults; + std::shared_ptr node_minimass; + std::shared_ptr beam_defaults; /* Needed for hook */ + int detacher_group; }; - Node(): - position(Ogre::Vector3::ZERO), - options(0), - load_weight_override(0), - _has_load_weight_override(false), - detacher_group(0) /* Global detacher group */ - {} - - BITMASK_PROPERTY( options, 1, OPTION_n_MOUSE_GRAB , HasFlag_n, SetFlag_n) - BITMASK_PROPERTY( options, 2, OPTION_m_NO_MOUSE_GRAB , HasFlag_m, SetFlag_m) - BITMASK_PROPERTY( options, 3, OPTION_f_NO_SPARKS , HasFlag_f, SetFlag_f) - BITMASK_PROPERTY( options, 4, OPTION_x_EXHAUST_POINT , HasFlag_x, SetFlag_x) - BITMASK_PROPERTY( options, 5, OPTION_y_EXHAUST_DIRECTION , HasFlag_y, SetFlag_y) - BITMASK_PROPERTY( options, 6, OPTION_c_NO_GROUND_CONTACT , HasFlag_c, SetFlag_c) - BITMASK_PROPERTY( options, 7, OPTION_h_HOOK_POINT , HasFlag_h, SetFlag_h) - BITMASK_PROPERTY( options, 8, OPTION_e_TERRAIN_EDIT_POINT, HasFlag_e, SetFlag_e) - BITMASK_PROPERTY( options, 9, OPTION_b_EXTRA_BUOYANCY , HasFlag_b, SetFlag_b) - BITMASK_PROPERTY( options, 10, OPTION_p_NO_PARTICLES , HasFlag_p, SetFlag_p) - BITMASK_PROPERTY( options, 11, OPTION_L_LOG , HasFlag_L, SetFlag_L) - BITMASK_PROPERTY( options, 12, OPTION_l_LOAD_WEIGHT , HasFlag_l, SetFlag_l) - - Id id; - Ogre::Vector3 position; - unsigned int options; ///< Bit flags - float load_weight_override; - bool _has_load_weight_override; - std::shared_ptr node_defaults; - std::shared_ptr node_minimass; - std::shared_ptr beam_defaults; /* Needed for hook */ - int detacher_group; -}; - -} //namespace RigDef +} // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp b/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp index add6658456..39c7a06d78 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp @@ -27,596 +27,602 @@ #include "Application.h" #include "BeamConstants.h" +#include "BitFlags.h" #include "CacheSystem.h" #include "RigDef_File.h" #include "RigDef_Regexes.h" -#include "BitFlags.h" #include "RoRPrerequisites.h" #include "Utils.h" #include #include -#include #include +#include namespace RigDef { -inline bool IsWhitespace(char c) -{ - return (c == ' ') || (c == '\t'); -} + inline bool IsWhitespace(char c) + { + return (c == ' ') || (c == '\t'); + } -inline bool IsSeparator(char c) -{ - return IsWhitespace(c) || (c == ':') || (c == '|') || (c == ','); -} + inline bool IsSeparator(char c) + { + return IsWhitespace(c) || (c == ':') || (c == '|') || (c == ','); + } -inline bool StrEqualsNocase(std::string const & s1, std::string const & s2) -{ - if (s1.size() != s2.size()) { return false; } - for (size_t i = 0; i < s1.size(); ++i) + inline bool StrEqualsNocase(std::string const &s1, std::string const &s2) { - if (tolower(s1[i]) != tolower(s2[i])) { return false; } + if (s1.size() != s2.size()) { return false; } + for (size_t i = 0; i < s1.size(); ++i) + { + if (tolower(s1[i]) != tolower(s2[i])) { return false; } + } + return true; } - return true; -} -#define STR_PARSE_INT(_STR_) Ogre::StringConverter::parseInt(_STR_) +#define STR_PARSE_INT(_STR_) Ogre::StringConverter::parseInt(_STR_) #define STR_PARSE_REAL(_STR_) Ogre::StringConverter::parseReal(_STR_) #define STR_PARSE_BOOL(_STR_) Ogre::StringConverter::parseBool(_STR_) -Parser::Parser() -{ - // Push defaults - m_ror_default_inertia = std::shared_ptr(new Inertia); - m_ror_node_defaults = std::shared_ptr(new NodeDefaults); - m_ror_minimass = std::shared_ptr(new MinimassPreset); -} + Parser::Parser() + { + // Push defaults + m_ror_default_inertia = std::shared_ptr(new Inertia); + m_ror_node_defaults = std::shared_ptr(new NodeDefaults); + m_ror_minimass = std::shared_ptr(new MinimassPreset); + } -void Parser::ProcessCurrentLine() -{ - if (m_in_block_comment) + void Parser::ProcessCurrentLine() { - if (StrEqualsNocase(m_current_line, "end_comment")) + if (m_in_block_comment) { - m_in_block_comment = false; + if (StrEqualsNocase(m_current_line, "end_comment")) { m_in_block_comment = false; } + return; } - return; - } - else if (StrEqualsNocase(m_current_line, "comment")) - { - m_in_block_comment = true; - return; - } - else if (m_in_description_section) // Enter logic is below in 'keywords' - { - if (StrEqualsNocase(m_current_line, "end_description")) + else if (StrEqualsNocase(m_current_line, "comment")) { - m_in_description_section = false; + m_in_block_comment = true; + return; } - else + else if (m_in_description_section) // Enter logic is below in 'keywords' { - m_definition->description.push_back(m_current_line); + if (StrEqualsNocase(m_current_line, "end_description")) { m_in_description_section = false; } + else + { + m_definition->description.push_back(m_current_line); + } + return; + } + else if ((m_current_line[0] == ';') || (m_current_line[0] == '/')) + { + return; } - return; - } - else if ((m_current_line[0] == ';') || (m_current_line[0] == '/')) - { - return; - } - this->TokenizeCurrentLine(); + this->TokenizeCurrentLine(); - // Detect keywords on current line - File::Keyword keyword = IdentifyKeywordInCurrentLine(); - switch (keyword) - { + // Detect keywords on current line + File::Keyword keyword = IdentifyKeywordInCurrentLine(); + switch (keyword) + { case File::KEYWORD_INVALID: break; // No new section - carry on with processing data - case File::KEYWORD_ADD_ANIMATION: this->ParseDirectiveAddAnimation(); return; - case File::KEYWORD_AIRBRAKES: this->ChangeSection(File::SECTION_AIRBRAKES); return; - case File::KEYWORD_ANIMATORS: this->ChangeSection(File::SECTION_ANIMATORS); return; - case File::KEYWORD_ANTI_LOCK_BRAKES: this->ParseAntiLockBrakes(); return; - case File::KEYWORD_AXLES: this->ChangeSection(File::SECTION_AXLES); return; - case File::KEYWORD_AUTHOR: this->ParseAuthor(); return; - case File::KEYWORD_BACKMESH: this->ParseDirectiveBackmesh(); return; - case File::KEYWORD_BEAMS: this->ChangeSection(File::SECTION_BEAMS); return; - case File::KEYWORD_BRAKES: this->ChangeSection(File::SECTION_BRAKES); return; - case File::KEYWORD_CAB: this->ProcessKeywordCab(); return; - case File::KEYWORD_CAMERAS: this->ChangeSection(File::SECTION_CAMERAS); return; - case File::KEYWORD_CAMERARAIL: this->ChangeSection(File::SECTION_CAMERA_RAIL); return; - case File::KEYWORD_CINECAM: this->ChangeSection(File::SECTION_CINECAM); return; - case File::KEYWORD_COLLISIONBOXES: this->ChangeSection(File::SECTION_COLLISION_BOXES); return; - case File::KEYWORD_COMMANDS: this->ChangeSection(File::SECTION_COMMANDS); return; - case File::KEYWORD_COMMANDS2: this->ChangeSection(File::SECTION_COMMANDS_2); return; - case File::KEYWORD_CONTACTERS: this->ChangeSection(File::SECTION_CONTACTERS); return; - case File::KEYWORD_CRUISECONTROL: this->ParseCruiseControl(); return; - case File::KEYWORD_DESCRIPTION: this->ChangeSection(File::SECTION_NONE); m_in_description_section = true; return; - case File::KEYWORD_DETACHER_GROUP: this->ParseDirectiveDetacherGroup(); return; - case File::KEYWORD_DISABLEDEFAULTSOUNDS: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_ENABLE_ADVANCED_DEFORM: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_END: this->ChangeSection(File::SECTION_NONE); return; - case File::KEYWORD_END_SECTION: this->ProcessChangeModuleLine(keyword); return; - case File::KEYWORD_ENGINE: this->ChangeSection(File::SECTION_ENGINE); return; - case File::KEYWORD_ENGOPTION: this->ChangeSection(File::SECTION_ENGOPTION); return; - case File::KEYWORD_ENGTURBO: this->ChangeSection(File::SECTION_ENGTURBO); return; - case File::KEYWORD_ENVMAP: /* Ignored */ return; - case File::KEYWORD_EXHAUSTS: this->ChangeSection(File::SECTION_EXHAUSTS); return; - case File::KEYWORD_EXTCAMERA: this->ParseExtCamera(); return; - case File::KEYWORD_FILEFORMATVERSION: this->ParseFileFormatVersion(); return; - case File::KEYWORD_FILEINFO: this->ParseFileinfo(); return; - case File::KEYWORD_FIXES: this->ChangeSection(File::SECTION_FIXES); return; - case File::KEYWORD_FLARES: this->ChangeSection(File::SECTION_FLARES); return; - case File::KEYWORD_FLARES2: this->ChangeSection(File::SECTION_FLARES_2); return; - case File::KEYWORD_FLEXBODIES: this->ChangeSection(File::SECTION_FLEXBODIES); return; - case File::KEYWORD_FLEXBODY_CAMERA_MODE: this->ParseDirectiveFlexbodyCameraMode(); return; - case File::KEYWORD_FLEXBODYWHEELS: this->ChangeSection(File::SECTION_FLEX_BODY_WHEELS); return; - case File::KEYWORD_FORWARDCOMMANDS: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_FUSEDRAG: this->ChangeSection(File::SECTION_FUSEDRAG); return; - case File::KEYWORD_GLOBALS: this->ChangeSection(File::SECTION_GLOBALS); return; - case File::KEYWORD_GUID: this->ParseGuid(); return; - case File::KEYWORD_GUISETTINGS: this->ChangeSection(File::SECTION_GUI_SETTINGS); return; - case File::KEYWORD_HELP: this->ChangeSection(File::SECTION_HELP); return; - case File::KEYWORD_HIDE_IN_CHOOSER: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_HOOKGROUP: /* Obsolete, ignored */ return; - case File::KEYWORD_HOOKS: this->ChangeSection(File::SECTION_HOOKS); return; - case File::KEYWORD_HYDROS: this->ChangeSection(File::SECTION_HYDROS); return; - case File::KEYWORD_IMPORTCOMMANDS: m_definition->import_commands = true; return; - case File::KEYWORD_INTERAXLES: this->ChangeSection(File::SECTION_INTERAXLES); return; - case File::KEYWORD_LOCKGROUPS: this->ChangeSection(File::SECTION_LOCKGROUPS); return; - case File::KEYWORD_LOCKGROUP_DEFAULT_NOLOCK: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_MANAGEDMATERIALS: this->ChangeSection(File::SECTION_MANAGED_MATERIALS); return; - case File::KEYWORD_MATERIALFLAREBINDINGS: this->ChangeSection(File::SECTION_MAT_FLARE_BINDINGS); return; - case File::KEYWORD_MESHWHEELS: this->ChangeSection(File::SECTION_MESH_WHEELS); return; - case File::KEYWORD_MESHWHEELS2: this->ChangeSection(File::SECTION_MESH_WHEELS_2); return; - case File::KEYWORD_MINIMASS: this->ChangeSection(File::SECTION_MINIMASS); return; - case File::KEYWORD_NODECOLLISION: this->ChangeSection(File::SECTION_NODE_COLLISION); return; - case File::KEYWORD_NODES: this->ChangeSection(File::SECTION_NODES); return; - case File::KEYWORD_NODES2: this->ChangeSection(File::SECTION_NODES_2); return; - case File::KEYWORD_PARTICLES: this->ChangeSection(File::SECTION_PARTICLES); return; - case File::KEYWORD_PISTONPROPS: this->ChangeSection(File::SECTION_PISTONPROPS); return; - case File::KEYWORD_PROP_CAMERA_MODE: this->ParseDirectivePropCameraMode(); return; - case File::KEYWORD_PROPS: this->ChangeSection(File::SECTION_PROPS); return; - case File::KEYWORD_RAILGROUPS: this->ChangeSection(File::SECTION_RAILGROUPS); return; - case File::KEYWORD_RESCUER: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_RIGIDIFIERS: this->AddMessage(Message::TYPE_WARNING, "Rigidifiers are not supported, ignoring..."); return; - case File::KEYWORD_ROLLON: this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_ROPABLES: this->ChangeSection(File::SECTION_ROPABLES); return; - case File::KEYWORD_ROPES: this->ChangeSection(File::SECTION_ROPES); return; - case File::KEYWORD_ROTATORS: this->ChangeSection(File::SECTION_ROTATORS); return; - case File::KEYWORD_ROTATORS2: this->ChangeSection(File::SECTION_ROTATORS_2); return; - case File::KEYWORD_SCREWPROPS: this->ChangeSection(File::SECTION_SCREWPROPS); return; - case File::KEYWORD_SECTION: this->ProcessChangeModuleLine(keyword); return; - case File::KEYWORD_SECTIONCONFIG: /* Ignored */ return; - case File::KEYWORD_SET_BEAM_DEFAULTS: this->ParseDirectiveSetBeamDefaults(); return; - case File::KEYWORD_SET_BEAM_DEFAULTS_SCALE: this->ParseDirectiveSetBeamDefaultsScale(); return; - case File::KEYWORD_SET_COLLISION_RANGE: this->ParseSetCollisionRange(); return; - case File::KEYWORD_SET_DEFAULT_MINIMASS: this->ParseDirectiveSetDefaultMinimass(); return; - case File::KEYWORD_SET_INERTIA_DEFAULTS: this->ParseDirectiveSetInertiaDefaults(); return; - case File::KEYWORD_SET_MANAGEDMATS_OPTIONS: this->ParseDirectiveSetManagedMaterialsOptions(); return; - case File::KEYWORD_SET_NODE_DEFAULTS: this->ParseDirectiveSetNodeDefaults(); return; - case File::KEYWORD_SET_SKELETON_SETTINGS: this->ParseSetSkeletonSettings(); return; - case File::KEYWORD_SHOCKS: this->ChangeSection(File::SECTION_SHOCKS); return; - case File::KEYWORD_SHOCKS2: this->ChangeSection(File::SECTION_SHOCKS_2); return; - case File::KEYWORD_SHOCKS3: this->ChangeSection(File::SECTION_SHOCKS_3); return; - case File::KEYWORD_SLIDENODE_CONNECT_INSTANT:this->ProcessGlobalDirective(keyword); return; - case File::KEYWORD_SLIDENODES: this->ChangeSection(File::SECTION_SLIDENODES); return; - case File::KEYWORD_SLOPE_BRAKE: this->ParseSlopeBrake(); return; - case File::KEYWORD_SOUNDSOURCES: this->ChangeSection(File::SECTION_SOUNDSOURCES); return; - case File::KEYWORD_SOUNDSOURCES2: this->ChangeSection(File::SECTION_SOUNDSOURCES2); return; - case File::KEYWORD_SPEEDLIMITER: this->ParseSpeedLimiter(); return; - case File::KEYWORD_SUBMESH_GROUNDMODEL: this->ParseSubmeshGroundModel(); return; - case File::KEYWORD_SUBMESH: this->ChangeSection(File::SECTION_SUBMESH); return; - case File::KEYWORD_TEXCOORDS: this->ProcessKeywordTexcoords(); return; - case File::KEYWORD_TIES: this->ChangeSection(File::SECTION_TIES); return; - case File::KEYWORD_TORQUECURVE: this->ChangeSection(File::SECTION_TORQUE_CURVE); return; - case File::KEYWORD_TRACTION_CONTROL: this->ParseTractionControl(); return; - case File::KEYWORD_TRANSFER_CASE: this->ChangeSection(File::SECTION_TRANSFER_CASE); return; - case File::KEYWORD_TRIGGERS: this->ChangeSection(File::SECTION_TRIGGERS); return; - case File::KEYWORD_TURBOJETS: this->ChangeSection(File::SECTION_TURBOJETS); return; - case File::KEYWORD_TURBOPROPS: this->ChangeSection(File::SECTION_TURBOPROPS); return; - case File::KEYWORD_TURBOPROPS2: this->ChangeSection(File::SECTION_TURBOPROPS_2); return; - case File::KEYWORD_VIDEOCAMERA: this->ChangeSection(File::SECTION_VIDEO_CAMERA); return; - case File::KEYWORD_WHEELDETACHERS: this->ChangeSection(File::SECTION_WHEELDETACHERS); return; - case File::KEYWORD_WHEELS: this->ChangeSection(File::SECTION_WHEELS); return; - case File::KEYWORD_WHEELS2: this->ChangeSection(File::SECTION_WHEELS_2); return; - case File::KEYWORD_WINGS: this->ChangeSection(File::SECTION_WINGS); return; - } - - // Parse current section, if any - switch (m_current_section) - { - case (File::SECTION_AIRBRAKES): this->ParseAirbrakes(); return; - case (File::SECTION_ANIMATORS): this->ParseAnimator(); return; - case (File::SECTION_AXLES): this->ParseAxles(); return; - case (File::SECTION_TRUCK_NAME): this->ParseActorNameLine(); return; - case (File::SECTION_BEAMS): this->ParseBeams(); return; - case (File::SECTION_BRAKES): this->ParseBrakes(); return; - case (File::SECTION_CAMERAS): this->ParseCameras(); return; - case (File::SECTION_CAMERA_RAIL): this->ParseCameraRails(); return; - case (File::SECTION_CINECAM): this->ParseCinecam(); return; + case File::KEYWORD_ADD_ANIMATION: this->ParseDirectiveAddAnimation(); return; + case File::KEYWORD_AIRBRAKES: this->ChangeSection(File::SECTION_AIRBRAKES); return; + case File::KEYWORD_ANIMATORS: this->ChangeSection(File::SECTION_ANIMATORS); return; + case File::KEYWORD_ANTI_LOCK_BRAKES: this->ParseAntiLockBrakes(); return; + case File::KEYWORD_AXLES: this->ChangeSection(File::SECTION_AXLES); return; + case File::KEYWORD_AUTHOR: this->ParseAuthor(); return; + case File::KEYWORD_BACKMESH: this->ParseDirectiveBackmesh(); return; + case File::KEYWORD_BEAMS: this->ChangeSection(File::SECTION_BEAMS); return; + case File::KEYWORD_BRAKES: this->ChangeSection(File::SECTION_BRAKES); return; + case File::KEYWORD_CAB: this->ProcessKeywordCab(); return; + case File::KEYWORD_CAMERAS: this->ChangeSection(File::SECTION_CAMERAS); return; + case File::KEYWORD_CAMERARAIL: this->ChangeSection(File::SECTION_CAMERA_RAIL); return; + case File::KEYWORD_CINECAM: this->ChangeSection(File::SECTION_CINECAM); return; + case File::KEYWORD_COLLISIONBOXES: this->ChangeSection(File::SECTION_COLLISION_BOXES); return; + case File::KEYWORD_COMMANDS: this->ChangeSection(File::SECTION_COMMANDS); return; + case File::KEYWORD_COMMANDS2: this->ChangeSection(File::SECTION_COMMANDS_2); return; + case File::KEYWORD_CONTACTERS: this->ChangeSection(File::SECTION_CONTACTERS); return; + case File::KEYWORD_CRUISECONTROL: this->ParseCruiseControl(); return; + case File::KEYWORD_DESCRIPTION: + this->ChangeSection(File::SECTION_NONE); + m_in_description_section = true; + return; + case File::KEYWORD_DETACHER_GROUP: this->ParseDirectiveDetacherGroup(); return; + case File::KEYWORD_DISABLEDEFAULTSOUNDS: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_ENABLE_ADVANCED_DEFORM: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_END: this->ChangeSection(File::SECTION_NONE); return; + case File::KEYWORD_END_SECTION: this->ProcessChangeModuleLine(keyword); return; + case File::KEYWORD_ENGINE: this->ChangeSection(File::SECTION_ENGINE); return; + case File::KEYWORD_ENGOPTION: this->ChangeSection(File::SECTION_ENGOPTION); return; + case File::KEYWORD_ENGTURBO: this->ChangeSection(File::SECTION_ENGTURBO); return; + case File::KEYWORD_ENVMAP: /* Ignored */ return; + case File::KEYWORD_EXHAUSTS: this->ChangeSection(File::SECTION_EXHAUSTS); return; + case File::KEYWORD_EXTCAMERA: this->ParseExtCamera(); return; + case File::KEYWORD_FILEFORMATVERSION: this->ParseFileFormatVersion(); return; + case File::KEYWORD_FILEINFO: this->ParseFileinfo(); return; + case File::KEYWORD_FIXES: this->ChangeSection(File::SECTION_FIXES); return; + case File::KEYWORD_FLARES: this->ChangeSection(File::SECTION_FLARES); return; + case File::KEYWORD_FLARES2: this->ChangeSection(File::SECTION_FLARES_2); return; + case File::KEYWORD_FLEXBODIES: this->ChangeSection(File::SECTION_FLEXBODIES); return; + case File::KEYWORD_FLEXBODY_CAMERA_MODE: this->ParseDirectiveFlexbodyCameraMode(); return; + case File::KEYWORD_FLEXBODYWHEELS: this->ChangeSection(File::SECTION_FLEX_BODY_WHEELS); return; + case File::KEYWORD_FORWARDCOMMANDS: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_FUSEDRAG: this->ChangeSection(File::SECTION_FUSEDRAG); return; + case File::KEYWORD_GLOBALS: this->ChangeSection(File::SECTION_GLOBALS); return; + case File::KEYWORD_GUID: this->ParseGuid(); return; + case File::KEYWORD_GUISETTINGS: this->ChangeSection(File::SECTION_GUI_SETTINGS); return; + case File::KEYWORD_HELP: this->ChangeSection(File::SECTION_HELP); return; + case File::KEYWORD_HIDE_IN_CHOOSER: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_HOOKGROUP: /* Obsolete, ignored */ return; + case File::KEYWORD_HOOKS: this->ChangeSection(File::SECTION_HOOKS); return; + case File::KEYWORD_HYDROS: this->ChangeSection(File::SECTION_HYDROS); return; + case File::KEYWORD_IMPORTCOMMANDS: m_definition->import_commands = true; return; + case File::KEYWORD_INTERAXLES: this->ChangeSection(File::SECTION_INTERAXLES); return; + case File::KEYWORD_LOCKGROUPS: this->ChangeSection(File::SECTION_LOCKGROUPS); return; + case File::KEYWORD_LOCKGROUP_DEFAULT_NOLOCK: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_MANAGEDMATERIALS: this->ChangeSection(File::SECTION_MANAGED_MATERIALS); return; + case File::KEYWORD_MATERIALFLAREBINDINGS: this->ChangeSection(File::SECTION_MAT_FLARE_BINDINGS); return; + case File::KEYWORD_MESHWHEELS: this->ChangeSection(File::SECTION_MESH_WHEELS); return; + case File::KEYWORD_MESHWHEELS2: this->ChangeSection(File::SECTION_MESH_WHEELS_2); return; + case File::KEYWORD_MINIMASS: this->ChangeSection(File::SECTION_MINIMASS); return; + case File::KEYWORD_NODECOLLISION: this->ChangeSection(File::SECTION_NODE_COLLISION); return; + case File::KEYWORD_NODES: this->ChangeSection(File::SECTION_NODES); return; + case File::KEYWORD_NODES2: this->ChangeSection(File::SECTION_NODES_2); return; + case File::KEYWORD_PARTICLES: this->ChangeSection(File::SECTION_PARTICLES); return; + case File::KEYWORD_PISTONPROPS: this->ChangeSection(File::SECTION_PISTONPROPS); return; + case File::KEYWORD_PROP_CAMERA_MODE: this->ParseDirectivePropCameraMode(); return; + case File::KEYWORD_PROPS: this->ChangeSection(File::SECTION_PROPS); return; + case File::KEYWORD_RAILGROUPS: this->ChangeSection(File::SECTION_RAILGROUPS); return; + case File::KEYWORD_RESCUER: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_RIGIDIFIERS: + this->AddMessage(Message::TYPE_WARNING, "Rigidifiers are not supported, ignoring..."); + return; + case File::KEYWORD_ROLLON: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_ROPABLES: this->ChangeSection(File::SECTION_ROPABLES); return; + case File::KEYWORD_ROPES: this->ChangeSection(File::SECTION_ROPES); return; + case File::KEYWORD_ROTATORS: this->ChangeSection(File::SECTION_ROTATORS); return; + case File::KEYWORD_ROTATORS2: this->ChangeSection(File::SECTION_ROTATORS_2); return; + case File::KEYWORD_SCREWPROPS: this->ChangeSection(File::SECTION_SCREWPROPS); return; + case File::KEYWORD_SECTION: this->ProcessChangeModuleLine(keyword); return; + case File::KEYWORD_SECTIONCONFIG: /* Ignored */ return; + case File::KEYWORD_SET_BEAM_DEFAULTS: this->ParseDirectiveSetBeamDefaults(); return; + case File::KEYWORD_SET_BEAM_DEFAULTS_SCALE: this->ParseDirectiveSetBeamDefaultsScale(); return; + case File::KEYWORD_SET_COLLISION_RANGE: this->ParseSetCollisionRange(); return; + case File::KEYWORD_SET_DEFAULT_MINIMASS: this->ParseDirectiveSetDefaultMinimass(); return; + case File::KEYWORD_SET_INERTIA_DEFAULTS: this->ParseDirectiveSetInertiaDefaults(); return; + case File::KEYWORD_SET_MANAGEDMATS_OPTIONS: this->ParseDirectiveSetManagedMaterialsOptions(); return; + case File::KEYWORD_SET_NODE_DEFAULTS: this->ParseDirectiveSetNodeDefaults(); return; + case File::KEYWORD_SET_SKELETON_SETTINGS: this->ParseSetSkeletonSettings(); return; + case File::KEYWORD_SHOCKS: this->ChangeSection(File::SECTION_SHOCKS); return; + case File::KEYWORD_SHOCKS2: this->ChangeSection(File::SECTION_SHOCKS_2); return; + case File::KEYWORD_SHOCKS3: this->ChangeSection(File::SECTION_SHOCKS_3); return; + case File::KEYWORD_SLIDENODE_CONNECT_INSTANT: this->ProcessGlobalDirective(keyword); return; + case File::KEYWORD_SLIDENODES: this->ChangeSection(File::SECTION_SLIDENODES); return; + case File::KEYWORD_SLOPE_BRAKE: this->ParseSlopeBrake(); return; + case File::KEYWORD_SOUNDSOURCES: this->ChangeSection(File::SECTION_SOUNDSOURCES); return; + case File::KEYWORD_SOUNDSOURCES2: this->ChangeSection(File::SECTION_SOUNDSOURCES2); return; + case File::KEYWORD_SPEEDLIMITER: this->ParseSpeedLimiter(); return; + case File::KEYWORD_SUBMESH_GROUNDMODEL: this->ParseSubmeshGroundModel(); return; + case File::KEYWORD_SUBMESH: this->ChangeSection(File::SECTION_SUBMESH); return; + case File::KEYWORD_TEXCOORDS: this->ProcessKeywordTexcoords(); return; + case File::KEYWORD_TIES: this->ChangeSection(File::SECTION_TIES); return; + case File::KEYWORD_TORQUECURVE: this->ChangeSection(File::SECTION_TORQUE_CURVE); return; + case File::KEYWORD_TRACTION_CONTROL: this->ParseTractionControl(); return; + case File::KEYWORD_TRANSFER_CASE: this->ChangeSection(File::SECTION_TRANSFER_CASE); return; + case File::KEYWORD_TRIGGERS: this->ChangeSection(File::SECTION_TRIGGERS); return; + case File::KEYWORD_TURBOJETS: this->ChangeSection(File::SECTION_TURBOJETS); return; + case File::KEYWORD_TURBOPROPS: this->ChangeSection(File::SECTION_TURBOPROPS); return; + case File::KEYWORD_TURBOPROPS2: this->ChangeSection(File::SECTION_TURBOPROPS_2); return; + case File::KEYWORD_VIDEOCAMERA: this->ChangeSection(File::SECTION_VIDEO_CAMERA); return; + case File::KEYWORD_WHEELDETACHERS: this->ChangeSection(File::SECTION_WHEELDETACHERS); return; + case File::KEYWORD_WHEELS: this->ChangeSection(File::SECTION_WHEELS); return; + case File::KEYWORD_WHEELS2: this->ChangeSection(File::SECTION_WHEELS_2); return; + case File::KEYWORD_WINGS: this->ChangeSection(File::SECTION_WINGS); return; + } + + // Parse current section, if any + switch (m_current_section) + { + case (File::SECTION_AIRBRAKES): this->ParseAirbrakes(); return; + case (File::SECTION_ANIMATORS): this->ParseAnimator(); return; + case (File::SECTION_AXLES): this->ParseAxles(); return; + case (File::SECTION_TRUCK_NAME): this->ParseActorNameLine(); return; + case (File::SECTION_BEAMS): this->ParseBeams(); return; + case (File::SECTION_BRAKES): this->ParseBrakes(); return; + case (File::SECTION_CAMERAS): this->ParseCameras(); return; + case (File::SECTION_CAMERA_RAIL): this->ParseCameraRails(); return; + case (File::SECTION_CINECAM): this->ParseCinecam(); return; case (File::SECTION_COMMANDS): - case (File::SECTION_COMMANDS_2): this->ParseCommandsUnified(); return; - case (File::SECTION_COLLISION_BOXES): this->ParseCollisionBox(); return; - case (File::SECTION_CONTACTERS): this->ParseContacter(); return; - case (File::SECTION_ENGINE): this->ParseEngine(); return; - case (File::SECTION_ENGOPTION): this->ParseEngoption(); return; - case (File::SECTION_ENGTURBO) : this->ParseEngturbo(); return; - case (File::SECTION_EXHAUSTS): this->ParseExhaust(); return; - case (File::SECTION_FIXES): this->ParseFixes(); return; + case (File::SECTION_COMMANDS_2): this->ParseCommandsUnified(); return; + case (File::SECTION_COLLISION_BOXES): this->ParseCollisionBox(); return; + case (File::SECTION_CONTACTERS): this->ParseContacter(); return; + case (File::SECTION_ENGINE): this->ParseEngine(); return; + case (File::SECTION_ENGOPTION): this->ParseEngoption(); return; + case (File::SECTION_ENGTURBO): this->ParseEngturbo(); return; + case (File::SECTION_EXHAUSTS): this->ParseExhaust(); return; + case (File::SECTION_FIXES): this->ParseFixes(); return; case (File::SECTION_FLARES): - case (File::SECTION_FLARES_2): this->ParseFlaresUnified(); return; - case (File::SECTION_FLEXBODIES): this->ParseFlexbody(); return; - case (File::SECTION_FLEX_BODY_WHEELS): this->ParseFlexBodyWheel(); return; - case (File::SECTION_FUSEDRAG): this->ParseFusedrag(); return; - case (File::SECTION_GLOBALS): this->ParseGlobals(); return; - case (File::SECTION_GUI_SETTINGS): this->ParseGuiSettings(); return; - case (File::SECTION_HELP): this->ParseHelp(); return; - case (File::SECTION_HOOKS): this->ParseHook(); return; - case (File::SECTION_HYDROS): this->ParseHydros(); return; - case (File::SECTION_INTERAXLES): this->ParseInterAxles(); return; - case (File::SECTION_LOCKGROUPS): this->ParseLockgroups(); return; - case (File::SECTION_MANAGED_MATERIALS): this->ParseManagedMaterials(); return; - case (File::SECTION_MAT_FLARE_BINDINGS): this->ParseMaterialFlareBindings(); return; + case (File::SECTION_FLARES_2): this->ParseFlaresUnified(); return; + case (File::SECTION_FLEXBODIES): this->ParseFlexbody(); return; + case (File::SECTION_FLEX_BODY_WHEELS): this->ParseFlexBodyWheel(); return; + case (File::SECTION_FUSEDRAG): this->ParseFusedrag(); return; + case (File::SECTION_GLOBALS): this->ParseGlobals(); return; + case (File::SECTION_GUI_SETTINGS): this->ParseGuiSettings(); return; + case (File::SECTION_HELP): this->ParseHelp(); return; + case (File::SECTION_HOOKS): this->ParseHook(); return; + case (File::SECTION_HYDROS): this->ParseHydros(); return; + case (File::SECTION_INTERAXLES): this->ParseInterAxles(); return; + case (File::SECTION_LOCKGROUPS): this->ParseLockgroups(); return; + case (File::SECTION_MANAGED_MATERIALS): this->ParseManagedMaterials(); return; + case (File::SECTION_MAT_FLARE_BINDINGS): this->ParseMaterialFlareBindings(); return; case (File::SECTION_MESH_WHEELS): - case (File::SECTION_MESH_WHEELS_2): this->ParseMeshWheelUnified(); return; - case (File::SECTION_MINIMASS): this->ParseMinimass(); return; - case (File::SECTION_NODE_COLLISION): this->ParseNodeCollision(); return; + case (File::SECTION_MESH_WHEELS_2): this->ParseMeshWheelUnified(); return; + case (File::SECTION_MINIMASS): this->ParseMinimass(); return; + case (File::SECTION_NODE_COLLISION): this->ParseNodeCollision(); return; case (File::SECTION_NODES): - case (File::SECTION_NODES_2): this->ParseNodesUnified(); return; - case (File::SECTION_PARTICLES): this->ParseParticles(); return; - case (File::SECTION_PISTONPROPS): this->ParsePistonprops(); return; - case (File::SECTION_PROPS): this->ParseProps(); return; - case (File::SECTION_RAILGROUPS): this->ParseRailGroups(); return; - case (File::SECTION_ROPABLES): this->ParseRopables(); return; - case (File::SECTION_ROPES): this->ParseRopes(); return; + case (File::SECTION_NODES_2): this->ParseNodesUnified(); return; + case (File::SECTION_PARTICLES): this->ParseParticles(); return; + case (File::SECTION_PISTONPROPS): this->ParsePistonprops(); return; + case (File::SECTION_PROPS): this->ParseProps(); return; + case (File::SECTION_RAILGROUPS): this->ParseRailGroups(); return; + case (File::SECTION_ROPABLES): this->ParseRopables(); return; + case (File::SECTION_ROPES): this->ParseRopes(); return; case (File::SECTION_ROTATORS): - case (File::SECTION_ROTATORS_2): this->ParseRotatorsUnified(); return; - case (File::SECTION_SCREWPROPS): this->ParseScrewprops(); return; - case (File::SECTION_SHOCKS): this->ParseShock(); return; - case (File::SECTION_SHOCKS_2): this->ParseShock2(); return; - case (File::SECTION_SHOCKS_3): this->ParseShock3(); return; - case (File::SECTION_SLIDENODES): this->ParseSlidenodes(); return; - case (File::SECTION_SOUNDSOURCES): this->ParseSoundsources(); return; - case (File::SECTION_SOUNDSOURCES2): this->ParseSoundsources2(); return; - case (File::SECTION_SUBMESH): this->ParseSubmesh(); return; - case (File::SECTION_TIES): this->ParseTies(); return; - case (File::SECTION_TORQUE_CURVE): this->ParseTorqueCurve(); return; - case (File::SECTION_TRANSFER_CASE): this->ParseTransferCase(); return; - case (File::SECTION_TRIGGERS): this->ParseTriggers(); return; - case (File::SECTION_TURBOJETS): this->ParseTurbojets(); return; - case (File::SECTION_TURBOPROPS): - case (File::SECTION_TURBOPROPS_2): this->ParseTurbopropsUnified(); return; - case (File::SECTION_VIDEO_CAMERA): this->ParseVideoCamera(); return; - case (File::SECTION_WHEELDETACHERS): this->ParseWheelDetachers(); return; - case (File::SECTION_WHEELS): this->ParseWheel(); return; - case (File::SECTION_WHEELS_2): this->ParseWheel2(); return; - case (File::SECTION_WINGS): this->ParseWing(); return; + case (File::SECTION_ROTATORS_2): this->ParseRotatorsUnified(); return; + case (File::SECTION_SCREWPROPS): this->ParseScrewprops(); return; + case (File::SECTION_SHOCKS): this->ParseShock(); return; + case (File::SECTION_SHOCKS_2): this->ParseShock2(); return; + case (File::SECTION_SHOCKS_3): this->ParseShock3(); return; + case (File::SECTION_SLIDENODES): this->ParseSlidenodes(); return; + case (File::SECTION_SOUNDSOURCES): this->ParseSoundsources(); return; + case (File::SECTION_SOUNDSOURCES2): this->ParseSoundsources2(); return; + case (File::SECTION_SUBMESH): this->ParseSubmesh(); return; + case (File::SECTION_TIES): this->ParseTies(); return; + case (File::SECTION_TORQUE_CURVE): this->ParseTorqueCurve(); return; + case (File::SECTION_TRANSFER_CASE): this->ParseTransferCase(); return; + case (File::SECTION_TRIGGERS): this->ParseTriggers(); return; + case (File::SECTION_TURBOJETS): this->ParseTurbojets(); return; + case (File::SECTION_TURBOPROPS): + case (File::SECTION_TURBOPROPS_2): this->ParseTurbopropsUnified(); return; + case (File::SECTION_VIDEO_CAMERA): this->ParseVideoCamera(); return; + case (File::SECTION_WHEELDETACHERS): this->ParseWheelDetachers(); return; + case (File::SECTION_WHEELS): this->ParseWheel(); return; + case (File::SECTION_WHEELS_2): this->ParseWheel2(); return; + case (File::SECTION_WINGS): this->ParseWing(); return; default:; - }; -} + }; + } -bool Parser::CheckNumArguments(int num_required_args) -{ - if (num_required_args > m_num_args) + bool Parser::CheckNumArguments(int num_required_args) { - char msg[200]; - snprintf(msg, 200, "Not enough arguments, %d required, got %d. Skipping line.", num_required_args, m_num_args); - this->AddMessage(Message::TYPE_WARNING, msg); - return false; + if (num_required_args > m_num_args) + { + char msg[200]; + snprintf(msg, 200, "Not enough arguments, %d required, got %d. Skipping line.", num_required_args, m_num_args); + this->AddMessage(Message::TYPE_WARNING, msg); + return false; + } + return true; } - return true; -} -// -------------------------------------------------------------------------- -// Parsing individual keywords -// -------------------------------------------------------------------------- - -void Parser::ParseActorNameLine() -{ - m_definition->name = m_current_line; // Already trimmed - this->ChangeSection(File::SECTION_NONE); -} + // -------------------------------------------------------------------------- + // Parsing individual keywords + // -------------------------------------------------------------------------- -void Parser::ParseWing() -{ - if (!this->CheckNumArguments(16)) { return; } + void Parser::ParseActorNameLine() + { + m_definition->name = m_current_line; // Already trimmed + this->ChangeSection(File::SECTION_NONE); + } - Wing wing; + void Parser::ParseWing() + { + if (!this->CheckNumArguments(16)) { return; } - for (int i = 0; i < 8; i++) { wing.nodes[i] = this->GetArgNodeRef (i); } - for (int i = 8; i < 16; i++) { wing.tex_coords[i-8] = this->GetArgFloat (i); } + Wing wing; - if (m_num_args > 16) { wing.control_surface = this->GetArgWingSurface (16); } - if (m_num_args > 17) { wing.chord_point = this->GetArgFloat (17); } - if (m_num_args > 18) { wing.min_deflection = this->GetArgFloat (18); } - if (m_num_args > 19) { wing.max_deflection = this->GetArgFloat (19); } - if (m_num_args > 20) { wing.airfoil = this->GetArgStr (20); } - if (m_num_args > 21) { wing.efficacy_coef = this->GetArgFloat (21); } + for (int i = 0; i < 8; i++) + { + wing.nodes[i] = this->GetArgNodeRef(i); + } + for (int i = 8; i < 16; i++) + { + wing.tex_coords[i - 8] = this->GetArgFloat(i); + } - m_current_module->wings.push_back(wing); -} + if (m_num_args > 16) { wing.control_surface = this->GetArgWingSurface(16); } + if (m_num_args > 17) { wing.chord_point = this->GetArgFloat(17); } + if (m_num_args > 18) { wing.min_deflection = this->GetArgFloat(18); } + if (m_num_args > 19) { wing.max_deflection = this->GetArgFloat(19); } + if (m_num_args > 20) { wing.airfoil = this->GetArgStr(20); } + if (m_num_args > 21) { wing.efficacy_coef = this->GetArgFloat(21); } -void Parser::ParseSetCollisionRange() -{ - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg + m_current_module->wings.push_back(wing); + } - float value = this->GetArgFloat(1); - if (value >= 0) + void Parser::ParseSetCollisionRange() { - m_definition->collision_range = value; + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg + + float value = this->GetArgFloat(1); + if (value >= 0) { m_definition->collision_range = value; } } -} -void Parser::ParseWheel2() -{ - if (!this->CheckNumArguments(17)) { return; } - - Wheel2 wheel_2; - wheel_2.node_defaults = m_user_node_defaults; - wheel_2.beam_defaults = m_user_beam_defaults; - - wheel_2.rim_radius = this->GetArgFloat ( 0); - wheel_2.tyre_radius = this->GetArgFloat ( 1); - wheel_2.width = this->GetArgFloat ( 2); - wheel_2.num_rays = this->GetArgInt ( 3); - wheel_2.nodes[0] = this->GetArgNodeRef ( 4); - wheel_2.nodes[1] = this->GetArgNodeRef ( 5); - wheel_2.rigidity_node = this->GetArgRigidityNode ( 6); - wheel_2.braking = this->GetArgBraking ( 7); - wheel_2.propulsion = this->GetArgPropulsion ( 8); - wheel_2.reference_arm_node = this->GetArgNodeRef ( 9); - wheel_2.mass = this->GetArgFloat (10); - wheel_2.rim_springiness = this->GetArgFloat (11); - wheel_2.rim_damping = this->GetArgFloat (12); - wheel_2.tyre_springiness = this->GetArgFloat (13); - wheel_2.tyre_damping = this->GetArgFloat (14); - wheel_2.face_material_name = this->GetArgStr (15); - wheel_2.band_material_name = this->GetArgStr (16); - - if (m_sequential_importer.IsEnabled()) - { - m_sequential_importer.GenerateNodesForWheel(File::KEYWORD_WHEELS2, wheel_2.num_rays, wheel_2.rigidity_node.IsValidAnyState()); - } - - m_current_module->wheels_2.push_back(wheel_2); -} - -void Parser::ParseWheel() -{ - if (! this->CheckNumArguments(14)) { return; } + void Parser::ParseWheel2() + { + if (!this->CheckNumArguments(17)) { return; } - Wheel wheel; - wheel.node_defaults = m_user_node_defaults; - wheel.beam_defaults = m_user_beam_defaults; + Wheel2 wheel_2; + wheel_2.node_defaults = m_user_node_defaults; + wheel_2.beam_defaults = m_user_beam_defaults; - wheel.radius = this->GetArgFloat ( 0); - wheel.width = this->GetArgFloat ( 1); - wheel.num_rays = this->GetArgInt ( 2); - wheel.nodes[0] = this->GetArgNodeRef ( 3); - wheel.nodes[1] = this->GetArgNodeRef ( 4); - wheel.rigidity_node = this->GetArgRigidityNode ( 5); - wheel.braking = this->GetArgBraking ( 6); - wheel.propulsion = this->GetArgPropulsion ( 7); - wheel.reference_arm_node = this->GetArgNodeRef ( 8); - wheel.mass = this->GetArgFloat ( 9); - wheel.springiness = this->GetArgFloat (10); - wheel.damping = this->GetArgFloat (11); - wheel.face_material_name = this->GetArgStr (12); - wheel.band_material_name = this->GetArgStr (13); + wheel_2.rim_radius = this->GetArgFloat(0); + wheel_2.tyre_radius = this->GetArgFloat(1); + wheel_2.width = this->GetArgFloat(2); + wheel_2.num_rays = this->GetArgInt(3); + wheel_2.nodes[0] = this->GetArgNodeRef(4); + wheel_2.nodes[1] = this->GetArgNodeRef(5); + wheel_2.rigidity_node = this->GetArgRigidityNode(6); + wheel_2.braking = this->GetArgBraking(7); + wheel_2.propulsion = this->GetArgPropulsion(8); + wheel_2.reference_arm_node = this->GetArgNodeRef(9); + wheel_2.mass = this->GetArgFloat(10); + wheel_2.rim_springiness = this->GetArgFloat(11); + wheel_2.rim_damping = this->GetArgFloat(12); + wheel_2.tyre_springiness = this->GetArgFloat(13); + wheel_2.tyre_damping = this->GetArgFloat(14); + wheel_2.face_material_name = this->GetArgStr(15); + wheel_2.band_material_name = this->GetArgStr(16); - if (m_sequential_importer.IsEnabled()) - { - m_sequential_importer.GenerateNodesForWheel(File::KEYWORD_WHEELS, wheel.num_rays, wheel.rigidity_node.IsValidAnyState()); + if (m_sequential_importer.IsEnabled()) + { + m_sequential_importer.GenerateNodesForWheel(File::KEYWORD_WHEELS2, wheel_2.num_rays, + wheel_2.rigidity_node.IsValidAnyState()); + } + + m_current_module->wheels_2.push_back(wheel_2); } - m_current_module->wheels.push_back(wheel); -} + void Parser::ParseWheel() + { + if (!this->CheckNumArguments(14)) { return; } -void Parser::ParseWheelDetachers() -{ - if (! this->CheckNumArguments(2)) { return; } + Wheel wheel; + wheel.node_defaults = m_user_node_defaults; + wheel.beam_defaults = m_user_beam_defaults; - WheelDetacher wheeldetacher; + wheel.radius = this->GetArgFloat(0); + wheel.width = this->GetArgFloat(1); + wheel.num_rays = this->GetArgInt(2); + wheel.nodes[0] = this->GetArgNodeRef(3); + wheel.nodes[1] = this->GetArgNodeRef(4); + wheel.rigidity_node = this->GetArgRigidityNode(5); + wheel.braking = this->GetArgBraking(6); + wheel.propulsion = this->GetArgPropulsion(7); + wheel.reference_arm_node = this->GetArgNodeRef(8); + wheel.mass = this->GetArgFloat(9); + wheel.springiness = this->GetArgFloat(10); + wheel.damping = this->GetArgFloat(11); + wheel.face_material_name = this->GetArgStr(12); + wheel.band_material_name = this->GetArgStr(13); - wheeldetacher.wheel_id = this->GetArgInt(0); - wheeldetacher.detacher_group = this->GetArgInt(1); + if (m_sequential_importer.IsEnabled()) + { + m_sequential_importer.GenerateNodesForWheel(File::KEYWORD_WHEELS, wheel.num_rays, + wheel.rigidity_node.IsValidAnyState()); + } - m_current_module->wheeldetachers.push_back(wheeldetacher); -} + m_current_module->wheels.push_back(wheel); + } -void Parser::ParseTractionControl() -{ - Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 15, ","); // "TractionControl" = 15 characters - if (tokens.size() < 2) + void Parser::ParseWheelDetachers() { - this->AddMessage(Message::TYPE_ERROR, "Too few arguments"); - return; - } + if (!this->CheckNumArguments(2)) { return; } - TractionControl tc; - tc.regulation_force = this->ParseArgFloat(tokens[0].c_str()); - tc.wheel_slip = this->ParseArgFloat(tokens[1].c_str()); - if (tokens.size() > 2) { tc.fade_speed = this->ParseArgFloat(tokens[2].c_str()); } - if (tokens.size() > 3) { tc.pulse_per_sec = this->ParseArgFloat(tokens[3].c_str()); } + WheelDetacher wheeldetacher; - for (unsigned int i=4; iGetArgInt(0); + wheeldetacher.detacher_group = this->GetArgInt(1); + + m_current_module->wheeldetachers.push_back(wheeldetacher); + } + + void Parser::ParseTractionControl() { - Ogre::StringVector args2 = Ogre::StringUtil::split(tokens[i], ":"); - Ogre::StringUtil::trim(args2[0]); - Ogre::StringUtil::toLowerCase(args2[0]); + Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 15, ","); // "TractionControl" = 15 characters + if (tokens.size() < 2) + { + this->AddMessage(Message::TYPE_ERROR, "Too few arguments"); + return; + } - if (args2[0] == "mode" && args2.size() == 2) + TractionControl tc; + tc.regulation_force = this->ParseArgFloat(tokens[0].c_str()); + tc.wheel_slip = this->ParseArgFloat(tokens[1].c_str()); + if (tokens.size() > 2) { tc.fade_speed = this->ParseArgFloat(tokens[2].c_str()); } + if (tokens.size() > 3) { tc.pulse_per_sec = this->ParseArgFloat(tokens[3].c_str()); } + + for (unsigned int i = 4; i < tokens.size(); i++) { - Ogre::StringVector attrs = Ogre::StringUtil::split(args2[1], "&"); - auto itor = attrs.begin(); - auto endi = attrs.end(); - for (; itor != endi; ++itor) + Ogre::StringVector args2 = Ogre::StringUtil::split(tokens[i], ":"); + Ogre::StringUtil::trim(args2[0]); + Ogre::StringUtil::toLowerCase(args2[0]); + + if (args2[0] == "mode" && args2.size() == 2) + { + Ogre::StringVector attrs = Ogre::StringUtil::split(args2[1], "&"); + auto itor = attrs.begin(); + auto endi = attrs.end(); + for (; itor != endi; ++itor) + { + std::string attr = *itor; + Ogre::StringUtil::trim(attr); + Ogre::StringUtil::toLowerCase(attr); + if (strncmp(attr.c_str(), "nodash", 6) == 0) { tc.attr_no_dashboard = true; } + else if (strncmp(attr.c_str(), "notoggle", 8) == 0) + { + tc.attr_no_toggle = true; + } + else if (strncmp(attr.c_str(), "on", 2) == 0) + { + tc.attr_is_on = true; + } + else if (strncmp(attr.c_str(), "off", 3) == 0) + { + tc.attr_is_on = false; + } + } + } + else { - std::string attr = *itor; - Ogre::StringUtil::trim(attr); - Ogre::StringUtil::toLowerCase(attr); - if (strncmp(attr.c_str(), "nodash", 6) == 0) { tc.attr_no_dashboard = true; } - else if (strncmp(attr.c_str(), "notoggle", 8) == 0) { tc.attr_no_toggle = true; } - else if (strncmp(attr.c_str(), "on", 2) == 0) { tc.attr_is_on = true; } - else if (strncmp(attr.c_str(), "off", 3) == 0) { tc.attr_is_on = false; } + this->AddMessage(Message::TYPE_ERROR, "TractionControl Mode: missing"); + tc.attr_no_dashboard = false; + tc.attr_no_toggle = false; + tc.attr_is_on = true; } } - else + + if (m_current_module->traction_control != nullptr) { - this->AddMessage(Message::TYPE_ERROR, "TractionControl Mode: missing"); - tc.attr_no_dashboard = false; - tc.attr_no_toggle = false; - tc.attr_is_on = true; + this->AddMessage(Message::TYPE_WARNING, "Multiple inline-sections 'TractionControl' in a module, using last one ..."); } + + m_current_module->traction_control = std::shared_ptr(new TractionControl(tc)); } - if (m_current_module->traction_control != nullptr) + void Parser::ParseTransferCase() { - this->AddMessage(Message::TYPE_WARNING, "Multiple inline-sections 'TractionControl' in a module, using last one ..."); - } + if (!this->CheckNumArguments(2)) { return; } - m_current_module->traction_control = std::shared_ptr( new TractionControl(tc) ); -} + TransferCase tc; -void Parser::ParseTransferCase() -{ - if (! this->CheckNumArguments(2)) { return; } + tc.a1 = this->GetArgInt(0) - 1; + tc.a2 = this->GetArgInt(1) - 1; + if (m_num_args > 2) { tc.has_2wd = this->GetArgInt(2); } + if (m_num_args > 3) { tc.has_2wd_lo = this->GetArgInt(3); } + for (int i = 4; i < m_num_args; i++) + { + tc.gear_ratios.push_back(this->GetArgFloat(i)); + } - TransferCase tc; + if (m_current_module->transfer_case != nullptr) + { this->AddMessage(Message::TYPE_WARNING, "Multiple inline-sections 'transfercase' in a module, using last one ..."); } - tc.a1 = this->GetArgInt(0) - 1; - tc.a2 = this->GetArgInt(1) - 1; - if (m_num_args > 2) { tc.has_2wd = this->GetArgInt(2); } - if (m_num_args > 3) { tc.has_2wd_lo = this->GetArgInt(3); } - for (int i = 4; i < m_num_args; i++) { tc.gear_ratios.push_back(this->GetArgFloat(i)); } + m_current_module->transfer_case = std::shared_ptr(new TransferCase(tc)); + } - if (m_current_module->transfer_case != nullptr) + void Parser::ParseSubmeshGroundModel() { - this->AddMessage(Message::TYPE_WARNING, "Multiple inline-sections 'transfercase' in a module, using last one ..."); - } + if (!this->CheckNumArguments(2)) { return; } // Items: keyword, arg - m_current_module->transfer_case = std::shared_ptr( new TransferCase(tc) ); -} + m_current_module->submeshes_ground_model_name = this->GetArgStr(1); + } -void Parser::ParseSubmeshGroundModel() -{ - if (!this->CheckNumArguments(2)) { return; } // Items: keyword, arg + void Parser::ParseSpeedLimiter() + { + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg - m_current_module->submeshes_ground_model_name = this->GetArgStr(1); -} + SpeedLimiter &sl = m_current_module->speed_limiter; + if (sl.is_enabled) + { this->AddMessage(Message::TYPE_WARNING, "Multiple inline-sections 'speedlimiter' in a module, using last one ..."); } -void Parser::ParseSpeedLimiter() -{ - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg + sl.is_enabled = true; + sl.max_speed = this->GetArgFloat(1); + if (sl.max_speed <= 0.f) + { + char msg[200]; + snprintf(msg, 200, "Invalid 'max_speed' (%f), must be > 0.0. Using it anyway (compatibility)", sl.max_speed); + this->AddMessage(Message::TYPE_WARNING, msg); + } + } - SpeedLimiter& sl = m_current_module->speed_limiter; - if (sl.is_enabled) + void Parser::ParseSlopeBrake() { - this->AddMessage(Message::TYPE_WARNING, "Multiple inline-sections 'speedlimiter' in a module, using last one ..."); + if (m_current_module->slope_brake != nullptr) + { this->AddMessage(Message::TYPE_WARNING, "Multiple definitions 'SlopeBrake' in a module, using last one ..."); } + m_current_module->slope_brake = std::shared_ptr(new SlopeBrake()); + + SlopeBrake *sb = m_current_module->slope_brake.get(); + if (m_num_args > 1) { sb->regulating_force = this->GetArgFloat(1); } + if (m_num_args > 2) { sb->attach_angle = this->GetArgFloat(2); } + if (m_num_args > 3) { sb->release_angle = this->GetArgFloat(3); } } - sl.is_enabled = true; - sl.max_speed = this->GetArgFloat(1); - if (sl.max_speed <= 0.f) + void Parser::ParseSetSkeletonSettings() { - char msg[200]; - snprintf(msg, 200, "Invalid 'max_speed' (%f), must be > 0.0. Using it anyway (compatibility)", sl.max_speed); - this->AddMessage(Message::TYPE_WARNING, msg); + if (!this->CheckNumArguments(2)) { return; } + + SkeletonSettings &skel = m_current_module->skeleton_settings; + skel.visibility_range_meters = this->GetArgFloat(1); + if (m_num_args > 2) { skel.beam_thickness_meters = this->GetArgFloat(2); } + + // Defaults + if (skel.visibility_range_meters < 0.f) { skel.visibility_range_meters = 150.f; } + if (skel.beam_thickness_meters < 0.f) { skel.beam_thickness_meters = BEAM_SKELETON_DIAMETER; } } -} -void Parser::ParseSlopeBrake() -{ - if (m_current_module->slope_brake != nullptr) + void Parser::LogParsedDirectiveSetNodeDefaultsData(float load_weight, float friction, float volume, float surface, + unsigned int options) { - this->AddMessage(Message::TYPE_WARNING, "Multiple definitions 'SlopeBrake' in a module, using last one ..."); - } - m_current_module->slope_brake = std::shared_ptr( new SlopeBrake() ); - - SlopeBrake* sb = m_current_module->slope_brake.get(); - if (m_num_args > 1) { sb->regulating_force = this->GetArgFloat(1); } - if (m_num_args > 2) { sb->attach_angle = this->GetArgFloat(2); } - if (m_num_args > 3) { sb->release_angle = this->GetArgFloat(3); } -} + std::stringstream msg; + msg << "Parsed data for verification:" + << "\n\tLoadWeight: " << load_weight << "\n\t Friction: " << friction << "\n\t Volume: " << volume + << "\n\t Surface: " << surface << "\n\t Options: "; -void Parser::ParseSetSkeletonSettings() -{ - if (! this->CheckNumArguments(2)) { return; } - - SkeletonSettings& skel = m_current_module->skeleton_settings; - skel.visibility_range_meters = this->GetArgFloat(1); - if (m_num_args > 2) { skel.beam_thickness_meters = this->GetArgFloat(2); } - - // Defaults - if (skel.visibility_range_meters < 0.f) { skel.visibility_range_meters = 150.f; } - if (skel.beam_thickness_meters < 0.f) { skel.beam_thickness_meters = BEAM_SKELETON_DIAMETER; } -} - -void Parser::LogParsedDirectiveSetNodeDefaultsData(float load_weight, float friction, float volume, float surface, unsigned int options) -{ - std::stringstream msg; - msg << "Parsed data for verification:" - << "\n\tLoadWeight: " << load_weight - << "\n\t Friction: " << friction - << "\n\t Volume: " << volume - << "\n\t Surface: " << surface - << "\n\t Options: "; - - if (BITMASK_IS_1(options, Node::OPTION_l_LOAD_WEIGHT) ) { msg << " l_LOAD_WEIGHT"; } - if (BITMASK_IS_1(options, Node::OPTION_n_MOUSE_GRAB) ) { msg << " n_MOUSE_GRAB"; } - if (BITMASK_IS_1(options, Node::OPTION_m_NO_MOUSE_GRAB) ) { msg << " m_NO_MOUSE_GRAB"; } - if (BITMASK_IS_1(options, Node::OPTION_f_NO_SPARKS) ) { msg << " f_NO_SPARKS"; } - if (BITMASK_IS_1(options, Node::OPTION_x_EXHAUST_POINT) ) { msg << " x_EXHAUST_POINT"; } - if (BITMASK_IS_1(options, Node::OPTION_y_EXHAUST_DIRECTION) ) { msg << " y_EXHAUST_DIRECTION"; } - if (BITMASK_IS_1(options, Node::OPTION_c_NO_GROUND_CONTACT) ) { msg << " c_NO_GROUND_CONTACT"; } - if (BITMASK_IS_1(options, Node::OPTION_h_HOOK_POINT) ) { msg << " h_HOOK_POINT"; } - if (BITMASK_IS_1(options, Node::OPTION_e_TERRAIN_EDIT_POINT)) { msg << " e_TERRAIN_EDIT_POINT"; } - if (BITMASK_IS_1(options, Node::OPTION_b_EXTRA_BUOYANCY) ) { msg << " b_EXTRA_BUOYANCY"; } - if (BITMASK_IS_1(options, Node::OPTION_p_NO_PARTICLES) ) { msg << " p_NO_PARTICLES"; } - if (BITMASK_IS_1(options, Node::OPTION_L_LOG) ) { msg << " L_LOG"; } - - this->AddMessage(m_current_line, Message::TYPE_WARNING, msg.str()); -} - -void Parser::ParseDirectiveSetNodeDefaults() -{ - if (!this->CheckNumArguments(2)) { return; } + if (BITMASK_IS_1(options, Node::OPTION_l_LOAD_WEIGHT)) { msg << " l_LOAD_WEIGHT"; } + if (BITMASK_IS_1(options, Node::OPTION_n_MOUSE_GRAB)) { msg << " n_MOUSE_GRAB"; } + if (BITMASK_IS_1(options, Node::OPTION_m_NO_MOUSE_GRAB)) { msg << " m_NO_MOUSE_GRAB"; } + if (BITMASK_IS_1(options, Node::OPTION_f_NO_SPARKS)) { msg << " f_NO_SPARKS"; } + if (BITMASK_IS_1(options, Node::OPTION_x_EXHAUST_POINT)) { msg << " x_EXHAUST_POINT"; } + if (BITMASK_IS_1(options, Node::OPTION_y_EXHAUST_DIRECTION)) { msg << " y_EXHAUST_DIRECTION"; } + if (BITMASK_IS_1(options, Node::OPTION_c_NO_GROUND_CONTACT)) { msg << " c_NO_GROUND_CONTACT"; } + if (BITMASK_IS_1(options, Node::OPTION_h_HOOK_POINT)) { msg << " h_HOOK_POINT"; } + if (BITMASK_IS_1(options, Node::OPTION_e_TERRAIN_EDIT_POINT)) { msg << " e_TERRAIN_EDIT_POINT"; } + if (BITMASK_IS_1(options, Node::OPTION_b_EXTRA_BUOYANCY)) { msg << " b_EXTRA_BUOYANCY"; } + if (BITMASK_IS_1(options, Node::OPTION_p_NO_PARTICLES)) { msg << " p_NO_PARTICLES"; } + if (BITMASK_IS_1(options, Node::OPTION_L_LOG)) { msg << " L_LOG"; } - float load_weight = this->GetArgFloat(1); - float friction = (m_num_args > 2) ? this->GetArgFloat(2) : -1; - float volume = (m_num_args > 3) ? this->GetArgFloat(3) : -1; - float surface = (m_num_args > 4) ? this->GetArgFloat(4) : -1; - std::string opt_str = (m_num_args > 5) ? this->GetArgStr (5) : ""; + this->AddMessage(m_current_line, Message::TYPE_WARNING, msg.str()); + } - m_user_node_defaults = std::shared_ptr( new NodeDefaults(*m_user_node_defaults) ); + void Parser::ParseDirectiveSetNodeDefaults() + { + if (!this->CheckNumArguments(2)) { return; } - m_user_node_defaults->load_weight = (load_weight < 0) ? m_ror_node_defaults->load_weight : load_weight; - m_user_node_defaults->friction = (friction < 0) ? m_ror_node_defaults->friction : friction; - m_user_node_defaults->volume = (volume < 0) ? m_ror_node_defaults->volume : volume; - m_user_node_defaults->surface = (surface < 0) ? m_ror_node_defaults->surface : surface; + float load_weight = this->GetArgFloat(1); + float friction = (m_num_args > 2) ? this->GetArgFloat(2) : -1; + float volume = (m_num_args > 3) ? this->GetArgFloat(3) : -1; + float surface = (m_num_args > 4) ? this->GetArgFloat(4) : -1; + std::string opt_str = (m_num_args > 5) ? this->GetArgStr(5) : ""; - this->_ParseNodeOptions(m_user_node_defaults->options, opt_str); + m_user_node_defaults = std::shared_ptr(new NodeDefaults(*m_user_node_defaults)); - // Disabled until someone wants it back - //this->LogParsedDirectiveSetNodeDefaultsData(load_weight, friction, volume, surface, m_user_node_defaults->options); -} + m_user_node_defaults->load_weight = (load_weight < 0) ? m_ror_node_defaults->load_weight : load_weight; + m_user_node_defaults->friction = (friction < 0) ? m_ror_node_defaults->friction : friction; + m_user_node_defaults->volume = (volume < 0) ? m_ror_node_defaults->volume : volume; + m_user_node_defaults->surface = (surface < 0) ? m_ror_node_defaults->surface : surface; -void Parser::_ParseNodeOptions(unsigned int & options, const std::string & options_str) -{ - options = 0; + this->_ParseNodeOptions(m_user_node_defaults->options, opt_str); - for (unsigned int i = 0; i < options_str.length(); i++) + // Disabled until someone wants it back + // this->LogParsedDirectiveSetNodeDefaultsData(load_weight, friction, volume, surface, m_user_node_defaults->options); + } + + void Parser::_ParseNodeOptions(unsigned int &options, const std::string &options_str) { - const char c = options_str.at(i); - switch(c) + options = 0; + + for (unsigned int i = 0; i < options_str.length(); i++) { - case 'l': - BITMASK_SET_1(options, Node::OPTION_l_LOAD_WEIGHT); - break; + const char c = options_str.at(i); + switch (c) + { + case 'l': BITMASK_SET_1(options, Node::OPTION_l_LOAD_WEIGHT); break; case 'n': BITMASK_SET_1(options, Node::OPTION_n_MOUSE_GRAB); BITMASK_SET_0(options, Node::OPTION_m_NO_MOUSE_GRAB); @@ -625,3122 +631,3240 @@ void Parser::_ParseNodeOptions(unsigned int & options, const std::string & optio BITMASK_SET_1(options, Node::OPTION_m_NO_MOUSE_GRAB); BITMASK_SET_0(options, Node::OPTION_n_MOUSE_GRAB); break; - case 'f': - BITMASK_SET_1(options, Node::OPTION_f_NO_SPARKS); - break; - case 'x': - BITMASK_SET_1(options, Node::OPTION_x_EXHAUST_POINT); - break; - case 'y': - BITMASK_SET_1(options, Node::OPTION_y_EXHAUST_DIRECTION); - break; - case 'c': - BITMASK_SET_1(options, Node::OPTION_c_NO_GROUND_CONTACT); - break; - case 'h': - BITMASK_SET_1(options, Node::OPTION_h_HOOK_POINT); - break; - case 'e': - BITMASK_SET_1(options, Node::OPTION_e_TERRAIN_EDIT_POINT); - break; - case 'b': - BITMASK_SET_1(options, Node::OPTION_b_EXTRA_BUOYANCY); - break; - case 'p': - BITMASK_SET_1(options, Node::OPTION_p_NO_PARTICLES); - break; - case 'L': - BITMASK_SET_1(options, Node::OPTION_L_LOG); - break; - - default: - this->AddMessage(options_str, Message::TYPE_WARNING, std::string("Ignoring invalid option: ") + c); - break; + case 'f': BITMASK_SET_1(options, Node::OPTION_f_NO_SPARKS); break; + case 'x': BITMASK_SET_1(options, Node::OPTION_x_EXHAUST_POINT); break; + case 'y': BITMASK_SET_1(options, Node::OPTION_y_EXHAUST_DIRECTION); break; + case 'c': BITMASK_SET_1(options, Node::OPTION_c_NO_GROUND_CONTACT); break; + case 'h': BITMASK_SET_1(options, Node::OPTION_h_HOOK_POINT); break; + case 'e': BITMASK_SET_1(options, Node::OPTION_e_TERRAIN_EDIT_POINT); break; + case 'b': BITMASK_SET_1(options, Node::OPTION_b_EXTRA_BUOYANCY); break; + case 'p': BITMASK_SET_1(options, Node::OPTION_p_NO_PARTICLES); break; + case 'L': BITMASK_SET_1(options, Node::OPTION_L_LOG); break; + + default: this->AddMessage(options_str, Message::TYPE_WARNING, std::string("Ignoring invalid option: ") + c); break; + } } } -} -void Parser::ParseDirectiveSetManagedMaterialsOptions() -{ - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg - - // This is what v0.3x's parser did. - char c = this->GetArgChar(1); - m_current_managed_material_options.double_sided = (c != '0'); - - if (c != '0' && c != '1') + void Parser::ParseDirectiveSetManagedMaterialsOptions() { - this->AddMessage(Message::TYPE_WARNING, - "Param 'doublesided' should be only 1 or 0, got '" + this->GetArgStr(1) + "', parsing as 0"); - } -} + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg -void Parser::ParseDirectiveSetBeamDefaultsScale() -{ - if (! this->CheckNumArguments(5)) { return; } - - BeamDefaults* b = new BeamDefaults(*m_user_beam_defaults); - b->scale.springiness = this->GetArgFloat(1); - - if (m_num_args > 2) { b->scale.damping_constant = this->GetArgFloat(2); } - if (m_num_args > 3) { b->scale.deformation_threshold_constant = this->GetArgFloat(3); } - if (m_num_args > 4) { b->scale.breaking_threshold_constant = this->GetArgFloat(4); } - - m_user_beam_defaults = std::shared_ptr(b); -} - -void Parser::ParseDirectiveSetBeamDefaults() -{ - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg + // This is what v0.3x's parser did. + char c = this->GetArgChar(1); + m_current_managed_material_options.double_sided = (c != '0'); - BeamDefaults d(*m_user_beam_defaults); + if (c != '0' && c != '1') + { + this->AddMessage(Message::TYPE_WARNING, + "Param 'doublesided' should be only 1 or 0, got '" + this->GetArgStr(1) + "', parsing as 0"); + } + } - // What's the state of "enable_advanced_deformation" feature at this point? - // Directive "enable_advanced_deformation" alters the effects of BeamDefaults - // Since the old parser worked on-the-fly, only BeamDefaults defined after the directive were affected + void Parser::ParseDirectiveSetBeamDefaultsScale() + { + if (!this->CheckNumArguments(5)) { return; } - d._enable_advanced_deformation = m_definition->enable_advanced_deformation; + BeamDefaults *b = new BeamDefaults(*m_user_beam_defaults); + b->scale.springiness = this->GetArgFloat(1); - d._is_user_defined = true; //The "_enable_advanced_deformation" must only be aplied to user-defined values, not defaults. - d.springiness = this->GetArgFloat(1); + if (m_num_args > 2) { b->scale.damping_constant = this->GetArgFloat(2); } + if (m_num_args > 3) { b->scale.deformation_threshold_constant = this->GetArgFloat(3); } + if (m_num_args > 4) { b->scale.breaking_threshold_constant = this->GetArgFloat(4); } - if (m_num_args > 2) { d.damping_constant = this->GetArgFloat(2); } - if (m_num_args > 3) { d.deformation_threshold = this->GetArgFloat(3); } - if (m_num_args > 4) { d.breaking_threshold = this->GetArgFloat(4); } - if (m_num_args > 5) { d.visual_beam_diameter = this->GetArgFloat(5); } - if (m_num_args > 6) { d.beam_material_name = this->GetArgStr (6); } - if (m_num_args > 7) { d.plastic_deform_coef = this->GetArgFloat(7); } + m_user_beam_defaults = std::shared_ptr(b); + } - if (m_num_args > 7 && d.plastic_deform_coef >= 0.0f) { d._is_plastic_deform_coef_user_defined = true; } + void Parser::ParseDirectiveSetBeamDefaults() + { + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg - if (d.springiness < 0.f) { d.springiness = DEFAULT_SPRING; } - if (d.damping_constant < 0.f) { d.damping_constant = DEFAULT_DAMP; } - if (d.deformation_threshold < 0.f) { d.deformation_threshold = BEAM_DEFORM; } - if (d.breaking_threshold < 0.f) { d.breaking_threshold = BEAM_BREAK; } - if (d.visual_beam_diameter < 0.f) { d.visual_beam_diameter = DEFAULT_BEAM_DIAMETER; } - if (d.plastic_deform_coef < 0.f) { d.plastic_deform_coef = (*m_user_beam_defaults).plastic_deform_coef; } + BeamDefaults d(*m_user_beam_defaults); - m_user_beam_defaults = std::shared_ptr( new BeamDefaults(d) ); - return; -} + // What's the state of "enable_advanced_deformation" feature at this point? + // Directive "enable_advanced_deformation" alters the effects of BeamDefaults + // Since the old parser worked on-the-fly, only BeamDefaults defined after the directive were affected -void Parser::ParseDirectivePropCameraMode() -{ - assert(m_current_module != nullptr); - if (m_current_module->props.size() == 0) - { - this->AddMessage(Message::TYPE_ERROR, "Directive 'prop_camera_mode' found but no 'prop' defined, ignoring..."); - return; - } + d._enable_advanced_deformation = m_definition->enable_advanced_deformation; - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg + d._is_user_defined = true; // The "_enable_advanced_deformation" must only be aplied to user-defined values, not defaults. + d.springiness = this->GetArgFloat(1); - this->_ParseCameraSettings(m_current_module->props.back().camera_settings, this->GetArgStr(1)); -} + if (m_num_args > 2) { d.damping_constant = this->GetArgFloat(2); } + if (m_num_args > 3) { d.deformation_threshold = this->GetArgFloat(3); } + if (m_num_args > 4) { d.breaking_threshold = this->GetArgFloat(4); } + if (m_num_args > 5) { d.visual_beam_diameter = this->GetArgFloat(5); } + if (m_num_args > 6) { d.beam_material_name = this->GetArgStr(6); } + if (m_num_args > 7) { d.plastic_deform_coef = this->GetArgFloat(7); } -void Parser::ParseDirectiveBackmesh() -{ - if (m_current_section == File::SECTION_SUBMESH) - { - m_current_submesh->backmesh = true; - } - else - { - this->AddMessage(Message::TYPE_ERROR, "Misplaced sub-directive 'backmesh' (belongs in section 'submesh'), ignoring..."); - } -} + if (m_num_args > 7 && d.plastic_deform_coef >= 0.0f) { d._is_plastic_deform_coef_user_defined = true; } -void Parser::ProcessKeywordTexcoords() -{ - if (m_current_section == File::SECTION_SUBMESH) - { - m_current_subsection = File::SUBSECTION__SUBMESH__TEXCOORDS; - } - else - { - this->AddMessage(Message::TYPE_WARNING, "Misplaced sub-section 'texcoords' (belongs in section 'submesh'), falling back to classic unsafe parsing method."); - this->ChangeSection(File::SECTION_SUBMESH); - } -} + if (d.springiness < 0.f) { d.springiness = DEFAULT_SPRING; } + if (d.damping_constant < 0.f) { d.damping_constant = DEFAULT_DAMP; } + if (d.deformation_threshold < 0.f) { d.deformation_threshold = BEAM_DEFORM; } + if (d.breaking_threshold < 0.f) { d.breaking_threshold = BEAM_BREAK; } + if (d.visual_beam_diameter < 0.f) { d.visual_beam_diameter = DEFAULT_BEAM_DIAMETER; } + if (d.plastic_deform_coef < 0.f) { d.plastic_deform_coef = (*m_user_beam_defaults).plastic_deform_coef; } -void Parser::ProcessKeywordCab() -{ - m_current_subsection = File::SUBSECTION__SUBMESH__CAB; - if (m_current_section != File::SECTION_SUBMESH) - { - this->AddMessage(Message::TYPE_WARNING, "Misplaced sub-section 'cab' (belongs in section 'submesh')"); - this->ChangeSection(File::SECTION_SUBMESH); + m_user_beam_defaults = std::shared_ptr(new BeamDefaults(d)); + return; } -} -void Parser::ProcessGlobalDirective(File::Keyword keyword) // Directives that should only appear in root module -{ - this->VerifyModuleIsRoot(keyword); // Reports warning message if we're not in root module - - switch (keyword) + void Parser::ParseDirectivePropCameraMode() { - case File::KEYWORD_DISABLEDEFAULTSOUNDS: m_definition->disable_default_sounds = true; return; - case File::KEYWORD_ENABLE_ADVANCED_DEFORM: m_definition->enable_advanced_deformation = true; return; - case File::KEYWORD_FORWARDCOMMANDS: m_definition->forward_commands = true; return; - case File::KEYWORD_HIDE_IN_CHOOSER: m_definition->hide_in_chooser = true; return; - case File::KEYWORD_LOCKGROUP_DEFAULT_NOLOCK: m_definition->lockgroup_default_nolock = true; return; - case File::KEYWORD_RESCUER: m_definition->rescuer = true; return; - case File::KEYWORD_ROLLON: m_definition->rollon = true; return; - case File::KEYWORD_SLIDENODE_CONNECT_INSTANT: m_definition->slide_nodes_connect_instantly = true; return; + assert(m_current_module != nullptr); + if (m_current_module->props.size() == 0) + { + this->AddMessage(Message::TYPE_ERROR, "Directive 'prop_camera_mode' found but no 'prop' defined, ignoring..."); + return; + } + + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg - default: this->AddMessage(Message::TYPE_ERROR, "INTERNAL ERROR: '" - + std::string(File::KeywordToString(keyword)) + "' is not a global directive"); return; + this->_ParseCameraSettings(m_current_module->props.back().camera_settings, this->GetArgStr(1)); } -} -void Parser::VerifyModuleIsRoot(File::Keyword keyword) -{ - if (m_current_module != m_root_module) + void Parser::ParseDirectiveBackmesh() { - char buf[200]; - snprintf(buf, 200, "Keyword '%s' has global effect and should not appear in a module", File::KeywordToString(keyword)); - this->AddMessage(Message::TYPE_WARNING, buf); + if (m_current_section == File::SECTION_SUBMESH) { m_current_submesh->backmesh = true; } + else + { + this->AddMessage(Message::TYPE_ERROR, + "Misplaced sub-directive 'backmesh' (belongs in section 'submesh'), ignoring..."); + } } -} -void Parser::ParseMeshWheelUnified() -{ - if (! this->CheckNumArguments(16)) { return; } - - MeshWheel mesh_wheel; - mesh_wheel._is_meshwheel2 = (m_current_section == File::SECTION_MESH_WHEELS_2); - mesh_wheel.node_defaults = m_user_node_defaults; - mesh_wheel.beam_defaults = m_user_beam_defaults; - - mesh_wheel.tyre_radius = this->GetArgFloat ( 0); - mesh_wheel.rim_radius = this->GetArgFloat ( 1); - mesh_wheel.width = this->GetArgFloat ( 2); - mesh_wheel.num_rays = this->GetArgInt ( 3); - mesh_wheel.nodes[0] = this->GetArgNodeRef ( 4); - mesh_wheel.nodes[1] = this->GetArgNodeRef ( 5); - mesh_wheel.rigidity_node = this->GetArgRigidityNode ( 6); - mesh_wheel.braking = this->GetArgBraking ( 7); - mesh_wheel.propulsion = this->GetArgPropulsion ( 8); - mesh_wheel.reference_arm_node = this->GetArgNodeRef ( 9); - mesh_wheel.mass = this->GetArgFloat (10); - mesh_wheel.spring = this->GetArgFloat (11); - mesh_wheel.damping = this->GetArgFloat (12); - mesh_wheel.side = this->GetArgWheelSide (13); - mesh_wheel.mesh_name = this->GetArgStr (14); - mesh_wheel.material_name = this->GetArgStr (15); - - if (m_sequential_importer.IsEnabled()) - { - File::Keyword keyword = (mesh_wheel._is_meshwheel2) - ? File::KEYWORD_MESHWHEELS2 - : File::KEYWORD_MESHWHEELS; - m_sequential_importer.GenerateNodesForWheel(keyword, mesh_wheel.num_rays, mesh_wheel.rigidity_node.IsValidAnyState()); - } - - m_current_module->mesh_wheels.push_back(mesh_wheel); -} - -void Parser::ParseHook() -{ - if (! this->CheckNumArguments(1)) { return; } - - Hook hook; - hook.node = this->GetArgNodeRef(0); - - int i = 1; - while (i < m_num_args) - { - std::string attr = this->GetArgStr(i); - Ogre::StringUtil::trim(attr); - const bool has_value = (i < (m_num_args - 1)); - - // Values - if (has_value && (attr == "hookrange") ) { hook.option_hook_range = this->GetArgFloat(++i); } - else if (has_value && (attr == "speedcoef") ) { hook.option_speed_coef = this->GetArgFloat(++i); } - else if (has_value && (attr == "maxforce") ) { hook.option_max_force = this->GetArgFloat(++i); } - else if (has_value && (attr == "timer") ) { hook.option_timer = this->GetArgFloat(++i); } - else if (has_value && (attr == "hookgroup" || attr == "hgroup") ) { hook.option_hookgroup = this->GetArgInt (++i); } - else if (has_value && (attr == "lockgroup" || attr == "lgroup") ) { hook.option_lockgroup = this->GetArgInt (++i); } - else if (has_value && (attr == "shortlimit" || attr == "short_limit")) { hook.option_min_range_meters = this->GetArgFloat(++i); } - // Flags - else if ((attr == "selflock") ||(attr == "self-lock") ||(attr == "self_lock") ) { hook.flag_self_lock = true; } - else if ((attr == "autolock") ||(attr == "auto-lock") ||(attr == "auto_lock") ) { hook.flag_auto_lock = true; } - else if ((attr == "nodisable")||(attr == "no-disable")||(attr == "no_disable")) { hook.flag_no_disable = true; } - else if ((attr == "norope") ||(attr == "no-rope") ||(attr == "no_rope") ) { hook.flag_no_rope = true; } - else if ((attr == "visible") ||(attr == "vis") ) { hook.flag_visible = true; } + void Parser::ProcessKeywordTexcoords() + { + if (m_current_section == File::SECTION_SUBMESH) { m_current_subsection = File::SUBSECTION__SUBMESH__TEXCOORDS; } else { - std::string msg = "Ignoring invalid option: " + attr; - this->AddMessage(Message::TYPE_ERROR, msg.c_str()); + this->AddMessage(Message::TYPE_WARNING, "Misplaced sub-section 'texcoords' (belongs in section 'submesh'), falling " + "back to classic unsafe parsing method."); + this->ChangeSection(File::SECTION_SUBMESH); } - i++; } - m_current_module->hooks.push_back(hook); -} - -void Parser::ParseHelp() -{ - if (! m_current_module->help_panel_material_name.empty()) + void Parser::ProcessKeywordCab() { - this->AddMessage(Message::TYPE_WARNING, "Secton defined more than once."); + m_current_subsection = File::SUBSECTION__SUBMESH__CAB; + if (m_current_section != File::SECTION_SUBMESH) + { + this->AddMessage(Message::TYPE_WARNING, "Misplaced sub-section 'cab' (belongs in section 'submesh')"); + this->ChangeSection(File::SECTION_SUBMESH); + } } - m_current_module->help_panel_material_name = m_current_line; - Ogre::StringUtil::trim(m_current_module->help_panel_material_name); -} - -void Parser::ParseGuiSettings() -{ - if (! this->CheckNumArguments(2)) { return; } - - GuiSettings* gui_settings = m_current_module->gui_settings.get(); - - std::string key = this->GetArgStr(0); - - if (key == "debugBeams") {} // Obsolete, ignored - - else if (key == "tachoMaterial") { gui_settings->tacho_material = this->GetArgStr(1); } - else if (key == "speedoMaterial") { gui_settings->speedo_material = this->GetArgStr(1); } - else if (key == "ar_speedo_max_kph") { gui_settings->speedo_highest_kph = this->GetArgInt(1); } - else if (key == "useMaxRPM") { gui_settings->use_max_rpm = (this->GetArgInt(1) == 1); } - else if (key == "helpMaterial") { gui_settings->help_material = this->GetArgStr(1); } - - else if (key == "dashboard") { gui_settings->dashboard_layouts .push_back(this->GetArgStr(1)); } - else if (key == "texturedashboard") { gui_settings->rtt_dashboard_layouts.push_back(this->GetArgStr(1)); } - - else if (key == "interactiveOverviewMap") - { - std::string val = this->GetArgStr(1); - - if (val == "off" ) { gui_settings->interactive_overview_map_mode = GuiSettings::MAP_MODE_OFF; } - else if (val == "simple") { gui_settings->interactive_overview_map_mode = GuiSettings::MAP_MODE_SIMPLE; } - else if (val == "zoom" ) { gui_settings->interactive_overview_map_mode = GuiSettings::MAP_MODE_ZOOM; } - - else { this->AddMessage(Message::TYPE_ERROR, "Unknown map mode [" + val + "], ignoring..."); } - } - else - { - this->AddMessage(Message::TYPE_ERROR, "Unknown setting [" + key + "], ignoring..."); - } -} - -void Parser::ParseGuid() -{ - if (! this->CheckNumArguments(2)) { return; } - - if (! m_definition->guid.empty()) + void Parser::ProcessGlobalDirective(File::Keyword keyword) // Directives that should only appear in root module { - this->AddMessage(Message::TYPE_WARNING, "Guid defined multiple times."); - } + this->VerifyModuleIsRoot(keyword); // Reports warning message if we're not in root module - m_definition->guid = this->GetArgStr(1); -} + switch (keyword) + { + case File::KEYWORD_DISABLEDEFAULTSOUNDS: m_definition->disable_default_sounds = true; return; + case File::KEYWORD_ENABLE_ADVANCED_DEFORM: m_definition->enable_advanced_deformation = true; return; + case File::KEYWORD_FORWARDCOMMANDS: m_definition->forward_commands = true; return; + case File::KEYWORD_HIDE_IN_CHOOSER: m_definition->hide_in_chooser = true; return; + case File::KEYWORD_LOCKGROUP_DEFAULT_NOLOCK: m_definition->lockgroup_default_nolock = true; return; + case File::KEYWORD_RESCUER: m_definition->rescuer = true; return; + case File::KEYWORD_ROLLON: m_definition->rollon = true; return; + case File::KEYWORD_SLIDENODE_CONNECT_INSTANT: m_definition->slide_nodes_connect_instantly = true; return; -void Parser::ParseGlobals() -{ - if (! this->CheckNumArguments(2)) { return; } + default: + this->AddMessage(Message::TYPE_ERROR, + "INTERNAL ERROR: '" + std::string(File::KeywordToString(keyword)) + "' is not a global directive"); + return; + } + } - if (m_current_module->globals != nullptr) + void Parser::VerifyModuleIsRoot(File::Keyword keyword) { - this->AddMessage(Message::TYPE_WARNING, "Globals defined more than once."); + if (m_current_module != m_root_module) + { + char buf[200]; + snprintf(buf, 200, "Keyword '%s' has global effect and should not appear in a module", + File::KeywordToString(keyword)); + this->AddMessage(Message::TYPE_WARNING, buf); + } } - Globals globals; - globals.dry_mass = this->GetArgFloat(0); - globals.cargo_mass = this->GetArgFloat(1); - - if (m_num_args > 2) { globals.material_name = this->GetArgStr(2); } - - m_current_module->globals = std::shared_ptr( new Globals(globals) ); -} + void Parser::ParseMeshWheelUnified() + { + if (!this->CheckNumArguments(16)) { return; } + + MeshWheel mesh_wheel; + mesh_wheel._is_meshwheel2 = (m_current_section == File::SECTION_MESH_WHEELS_2); + mesh_wheel.node_defaults = m_user_node_defaults; + mesh_wheel.beam_defaults = m_user_beam_defaults; + + mesh_wheel.tyre_radius = this->GetArgFloat(0); + mesh_wheel.rim_radius = this->GetArgFloat(1); + mesh_wheel.width = this->GetArgFloat(2); + mesh_wheel.num_rays = this->GetArgInt(3); + mesh_wheel.nodes[0] = this->GetArgNodeRef(4); + mesh_wheel.nodes[1] = this->GetArgNodeRef(5); + mesh_wheel.rigidity_node = this->GetArgRigidityNode(6); + mesh_wheel.braking = this->GetArgBraking(7); + mesh_wheel.propulsion = this->GetArgPropulsion(8); + mesh_wheel.reference_arm_node = this->GetArgNodeRef(9); + mesh_wheel.mass = this->GetArgFloat(10); + mesh_wheel.spring = this->GetArgFloat(11); + mesh_wheel.damping = this->GetArgFloat(12); + mesh_wheel.side = this->GetArgWheelSide(13); + mesh_wheel.mesh_name = this->GetArgStr(14); + mesh_wheel.material_name = this->GetArgStr(15); -void Parser::ParseFusedrag() -{ - if (! this->CheckNumArguments(3)) { return; } + if (m_sequential_importer.IsEnabled()) + { + File::Keyword keyword = (mesh_wheel._is_meshwheel2) ? File::KEYWORD_MESHWHEELS2 : File::KEYWORD_MESHWHEELS; + m_sequential_importer.GenerateNodesForWheel(keyword, mesh_wheel.num_rays, mesh_wheel.rigidity_node.IsValidAnyState()); + } - Fusedrag fusedrag; - fusedrag.front_node = this->GetArgNodeRef(0); - fusedrag.rear_node = this->GetArgNodeRef(1); + m_current_module->mesh_wheels.push_back(mesh_wheel); + } - if (this->GetArgStr(2) == "autocalc") + void Parser::ParseHook() { - fusedrag.autocalc = true; + if (!this->CheckNumArguments(1)) { return; } - // Fusedrag autocalculation from truck size - if (m_num_args > 3) { fusedrag.area_coefficient = this->GetArgFloat(3); } - if (m_num_args > 4) { fusedrag.airfoil_name = this->GetArgStr (4); } - } - else - { - // Original calculation - fusedrag.approximate_width = this->GetArgFloat(2); - - if (m_num_args > 3) { fusedrag.airfoil_name = this->GetArgStr(3); } - } + Hook hook; + hook.node = this->GetArgNodeRef(0); - m_current_module->fusedrag.push_back(fusedrag); -} + int i = 1; + while (i < m_num_args) + { + std::string attr = this->GetArgStr(i); + Ogre::StringUtil::trim(attr); + const bool has_value = (i < (m_num_args - 1)); -void Parser::_ParseCameraSettings(CameraSettings & camera_settings, Ogre::String input_str) -{ - int input = STR_PARSE_INT(input_str); - if (input >= 0) - { - camera_settings.mode = CameraSettings::MODE_CINECAM; - camera_settings.cinecam_index = input; - } - else if (input >= -2) - { - camera_settings.mode = CameraSettings::Mode(input); + // Values + if (has_value && (attr == "hookrange")) { hook.option_hook_range = this->GetArgFloat(++i); } + else if (has_value && (attr == "speedcoef")) + { + hook.option_speed_coef = this->GetArgFloat(++i); + } + else if (has_value && (attr == "maxforce")) + { + hook.option_max_force = this->GetArgFloat(++i); + } + else if (has_value && (attr == "timer")) + { + hook.option_timer = this->GetArgFloat(++i); + } + else if (has_value && (attr == "hookgroup" || attr == "hgroup")) + { + hook.option_hookgroup = this->GetArgInt(++i); + } + else if (has_value && (attr == "lockgroup" || attr == "lgroup")) + { + hook.option_lockgroup = this->GetArgInt(++i); + } + else if (has_value && (attr == "shortlimit" || attr == "short_limit")) + { + hook.option_min_range_meters = this->GetArgFloat(++i); + } + // Flags + else if ((attr == "selflock") || (attr == "self-lock") || (attr == "self_lock")) + { + hook.flag_self_lock = true; + } + else if ((attr == "autolock") || (attr == "auto-lock") || (attr == "auto_lock")) + { + hook.flag_auto_lock = true; + } + else if ((attr == "nodisable") || (attr == "no-disable") || (attr == "no_disable")) + { + hook.flag_no_disable = true; + } + else if ((attr == "norope") || (attr == "no-rope") || (attr == "no_rope")) + { + hook.flag_no_rope = true; + } + else if ((attr == "visible") || (attr == "vis")) + { + hook.flag_visible = true; + } + else + { + std::string msg = "Ignoring invalid option: " + attr; + this->AddMessage(Message::TYPE_ERROR, msg.c_str()); + } + i++; + } + + m_current_module->hooks.push_back(hook); } - else + + void Parser::ParseHelp() { - AddMessage(input_str, Message::TYPE_ERROR, "Invalid value of camera setting, ignoring..."); - return; + if (!m_current_module->help_panel_material_name.empty()) + { this->AddMessage(Message::TYPE_WARNING, "Secton defined more than once."); } + + m_current_module->help_panel_material_name = m_current_line; + Ogre::StringUtil::trim(m_current_module->help_panel_material_name); } -} -void Parser::ParseDirectiveFlexbodyCameraMode() -{ - if (m_last_flexbody == nullptr) + void Parser::ParseGuiSettings() { - this->AddMessage(Message::TYPE_ERROR, "No flexbody to update, ignoring..."); - return; - } + if (!this->CheckNumArguments(2)) { return; } - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg + GuiSettings *gui_settings = m_current_module->gui_settings.get(); - this->_ParseCameraSettings(m_last_flexbody->camera_settings, this->GetArgStr(1)); -} + std::string key = this->GetArgStr(0); -void Parser::ParseSubmesh() -{ - if (m_current_subsection == File::SUBSECTION__SUBMESH__CAB) - { - if (! this->CheckNumArguments(3)) { return; } + if (key == "debugBeams") {} // Obsolete, ignored - Cab cab; - cab.nodes[0] = this->GetArgNodeRef(0); - cab.nodes[1] = this->GetArgNodeRef(1); - cab.nodes[2] = this->GetArgNodeRef(2); - if (m_num_args > 3) + else if (key == "tachoMaterial") { - cab.options = 0; - std::string options_str = this->GetArgStr(3); - for (unsigned int i = 0; i < options_str.length(); i++) + gui_settings->tacho_material = this->GetArgStr(1); + } + else if (key == "speedoMaterial") + { + gui_settings->speedo_material = this->GetArgStr(1); + } + else if (key == "ar_speedo_max_kph") + { + gui_settings->speedo_highest_kph = this->GetArgInt(1); + } + else if (key == "useMaxRPM") + { + gui_settings->use_max_rpm = (this->GetArgInt(1) == 1); + } + else if (key == "helpMaterial") + { + gui_settings->help_material = this->GetArgStr(1); + } + + else if (key == "dashboard") + { + gui_settings->dashboard_layouts.push_back(this->GetArgStr(1)); + } + else if (key == "texturedashboard") + { + gui_settings->rtt_dashboard_layouts.push_back(this->GetArgStr(1)); + } + + else if (key == "interactiveOverviewMap") + { + std::string val = this->GetArgStr(1); + + if (val == "off") { gui_settings->interactive_overview_map_mode = GuiSettings::MAP_MODE_OFF; } + else if (val == "simple") { - switch (options_str.at(i)) - { - case 'c': cab.options |= Cab::OPTION_c_CONTACT; break; - case 'b': cab.options |= Cab::OPTION_b_BUOYANT; break; - case 'D': cab.options |= (Cab::OPTION_c_CONTACT | Cab::OPTION_b_BUOYANT); break; - case 'p': cab.options |= Cab::OPTION_p_10xTOUGHER; break; - case 'u': cab.options |= Cab::OPTION_u_INVULNERABLE; break; - case 'F': cab.options |= (Cab::OPTION_p_10xTOUGHER | Cab::OPTION_b_BUOYANT); break; - case 'S': cab.options |= (Cab::OPTION_u_INVULNERABLE | Cab::OPTION_b_BUOYANT); break; - case 'n': break; // Placeholder, does nothing + gui_settings->interactive_overview_map_mode = GuiSettings::MAP_MODE_SIMPLE; + } + else if (val == "zoom") + { + gui_settings->interactive_overview_map_mode = GuiSettings::MAP_MODE_ZOOM; + } - default: - char msg[200] = ""; - snprintf(msg, 200, "'submesh/cab' Ignoring invalid option '%c'...", options_str.at(i)); - this->AddMessage(Message::TYPE_WARNING, msg); - break; - } + else + { + this->AddMessage(Message::TYPE_ERROR, "Unknown map mode [" + val + "], ignoring..."); } } - - m_current_submesh->cab_triangles.push_back(cab); + else + { + this->AddMessage(Message::TYPE_ERROR, "Unknown setting [" + key + "], ignoring..."); + } } - else if (m_current_subsection == File::SUBSECTION__SUBMESH__TEXCOORDS) + + void Parser::ParseGuid() { - if (! this->CheckNumArguments(3)) { return; } + if (!this->CheckNumArguments(2)) { return; } - Texcoord texcoord; - texcoord.node = this->GetArgNodeRef(0); - texcoord.u = this->GetArgFloat (1); - texcoord.v = this->GetArgFloat (2); + if (!m_definition->guid.empty()) { this->AddMessage(Message::TYPE_WARNING, "Guid defined multiple times."); } - m_current_submesh->texcoords.push_back(texcoord); - } - else - { - AddMessage(Message::TYPE_ERROR, "Section submesh has no subsection defined, line not parsed."); + m_definition->guid = this->GetArgStr(1); } -} -void Parser::ParseFlexbody() -{ - if (m_current_subsection == File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE) + void Parser::ParseGlobals() { - if (! this->CheckNumArguments(10)) { return; } + if (!this->CheckNumArguments(2)) { return; } - Flexbody flexbody; - flexbody.reference_node = this->GetArgNodeRef (0); - flexbody.x_axis_node = this->GetArgNodeRef (1); - flexbody.y_axis_node = this->GetArgNodeRef (2); - flexbody.offset.x = this->GetArgFloat (3); - flexbody.offset.y = this->GetArgFloat (4); - flexbody.offset.z = this->GetArgFloat (5); - flexbody.rotation.x = this->GetArgFloat (6); - flexbody.rotation.y = this->GetArgFloat (7); - flexbody.rotation.z = this->GetArgFloat (8); - flexbody.mesh_name = this->GetArgStr (9); + if (m_current_module->globals != nullptr) { this->AddMessage(Message::TYPE_WARNING, "Globals defined more than once."); } - m_last_flexbody = std::shared_ptr( new Flexbody(flexbody) ); - m_current_module->flexbodies.push_back(m_last_flexbody); + Globals globals; + globals.dry_mass = this->GetArgFloat(0); + globals.cargo_mass = this->GetArgFloat(1); - // Switch subsection - m_current_subsection = File::SUBSECTION__FLEXBODIES__FORSET_LINE; + if (m_num_args > 2) { globals.material_name = this->GetArgStr(2); } + + m_current_module->globals = std::shared_ptr(new Globals(globals)); } - else if (m_current_subsection == File::SUBSECTION__FLEXBODIES__FORSET_LINE) + + void Parser::ParseFusedrag() { - // Syntax: "forset", followed by space/comma, followed by ","-separated items. - // Acceptable item forms: - // * Single node number / node name - // * Pair of node numbers:" 123 - 456 ". Whitespace is optional. + if (!this->CheckNumArguments(3)) { return; } - char setdef[LINE_BUFFER_LENGTH] = ""; // strtok() is destructive, we need own buffer. - strncpy(setdef, m_current_line + 6, LINE_BUFFER_LENGTH - 6); // Cut away "forset" - const char* item = std::strtok(setdef, ","); + Fusedrag fusedrag; + fusedrag.front_node = this->GetArgNodeRef(0); + fusedrag.rear_node = this->GetArgNodeRef(1); - // TODO: Add error reporting - // It appears strtoul() sets no ERRNO for input 'x1' (parsed -> '0') + if (this->GetArgStr(2) == "autocalc") + { + fusedrag.autocalc = true; - const ptrdiff_t MAX_ITEM_LEN = 200; - while (item != nullptr) + // Fusedrag autocalculation from truck size + if (m_num_args > 3) { fusedrag.area_coefficient = this->GetArgFloat(3); } + if (m_num_args > 4) { fusedrag.airfoil_name = this->GetArgStr(4); } + } + else { - const char* hyphen = strchr(item, '-'); - if (hyphen != nullptr) - { - unsigned a = 0; - char* a_end = nullptr; - std::string a_text; - std::string b_text; - if (hyphen != item) - { - a = ::strtoul(item, &a_end, 10); - size_t length = std::min(a_end - item, MAX_ITEM_LEN); - a_text = std::string(item, length); - } - char* b_end = nullptr; - const char* item2 = hyphen + 1; - unsigned b = ::strtoul(item2, &b_end, 10); - size_t length = std::min(b_end - item2, MAX_ITEM_LEN); - b_text = std::string(item2, length); - - // Add interval [a-b] - m_last_flexbody->node_list_to_import.push_back( - Node::Range( - Node::Ref(a_text, a, Node::Ref::IMPORT_STATE_IS_VALID, m_current_line_number), - Node::Ref(b_text, b, Node::Ref::IMPORT_STATE_IS_VALID, m_current_line_number))); - } - else - { - errno = 0; - unsigned a = 0; - a = ::strtoul(item, nullptr, 10); - // Add interval [a-a] - Node::Range range_a = Node::Range(Node::Ref(std::string(item), a, Node::Ref::IMPORT_STATE_IS_VALID, m_current_line_number)); - m_last_flexbody->node_list_to_import.push_back(range_a); - } - item = strtok(nullptr, ","); + // Original calculation + fusedrag.approximate_width = this->GetArgFloat(2); + + if (m_num_args > 3) { fusedrag.airfoil_name = this->GetArgStr(3); } } - // Switch subsection - m_current_subsection = File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE; + m_current_module->fusedrag.push_back(fusedrag); } - else + + void Parser::_ParseCameraSettings(CameraSettings &camera_settings, Ogre::String input_str) { - AddMessage(Message::TYPE_FATAL_ERROR, "Internal parser failure, section 'flexbodies' not parsed."); + int input = STR_PARSE_INT(input_str); + if (input >= 0) + { + camera_settings.mode = CameraSettings::MODE_CINECAM; + camera_settings.cinecam_index = input; + } + else if (input >= -2) + { + camera_settings.mode = CameraSettings::Mode(input); + } + else + { + AddMessage(input_str, Message::TYPE_ERROR, "Invalid value of camera setting, ignoring..."); + return; + } } -} -void Parser::ParseFlaresUnified() -{ - const bool is_flares2 = (m_current_section == File::SECTION_FLARES_2); - if (! this->CheckNumArguments(is_flares2 ? 6 : 5)) { return; } + void Parser::ParseDirectiveFlexbodyCameraMode() + { + if (m_last_flexbody == nullptr) + { + this->AddMessage(Message::TYPE_ERROR, "No flexbody to update, ignoring..."); + return; + } - Flare2 flare2; - int pos = 0; - flare2.reference_node = this->GetArgNodeRef(pos++); - flare2.node_axis_x = this->GetArgNodeRef(pos++); - flare2.node_axis_y = this->GetArgNodeRef(pos++); - flare2.offset.x = this->GetArgFloat (pos++); - flare2.offset.y = this->GetArgFloat (pos++); + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, arg - if (m_current_section == File::SECTION_FLARES_2) - { - flare2.offset.z = this->GetArgFloat(pos++); + this->_ParseCameraSettings(m_last_flexbody->camera_settings, this->GetArgStr(1)); } - if (m_num_args > pos) { flare2.type = this->GetArgFlareType(pos++); } - if (m_num_args > pos) { flare2.control_number = this->GetArgInt (pos++); } - if (m_num_args > pos) { flare2.blink_delay_milis = this->GetArgInt (pos++); } - if (m_num_args > pos) { flare2.size = this->GetArgFloat (pos++); } - if (m_num_args > pos) { flare2.material_name = this->GetArgStr (pos++); } + void Parser::ParseSubmesh() + { + if (m_current_subsection == File::SUBSECTION__SUBMESH__CAB) + { + if (!this->CheckNumArguments(3)) { return; } - m_current_module->flares_2.push_back(flare2); -} + Cab cab; + cab.nodes[0] = this->GetArgNodeRef(0); + cab.nodes[1] = this->GetArgNodeRef(1); + cab.nodes[2] = this->GetArgNodeRef(2); + if (m_num_args > 3) + { + cab.options = 0; + std::string options_str = this->GetArgStr(3); + for (unsigned int i = 0; i < options_str.length(); i++) + { + switch (options_str.at(i)) + { + case 'c': cab.options |= Cab::OPTION_c_CONTACT; break; + case 'b': cab.options |= Cab::OPTION_b_BUOYANT; break; + case 'D': cab.options |= (Cab::OPTION_c_CONTACT | Cab::OPTION_b_BUOYANT); break; + case 'p': cab.options |= Cab::OPTION_p_10xTOUGHER; break; + case 'u': cab.options |= Cab::OPTION_u_INVULNERABLE; break; + case 'F': cab.options |= (Cab::OPTION_p_10xTOUGHER | Cab::OPTION_b_BUOYANT); break; + case 'S': cab.options |= (Cab::OPTION_u_INVULNERABLE | Cab::OPTION_b_BUOYANT); break; + case 'n': break; // Placeholder, does nothing + + default: + char msg[200] = ""; + snprintf(msg, 200, "'submesh/cab' Ignoring invalid option '%c'...", options_str.at(i)); + this->AddMessage(Message::TYPE_WARNING, msg); + break; + } + } + } -void Parser::ParseFixes() -{ - m_current_module->fixes.push_back(this->GetArgNodeRef(0)); -} + m_current_submesh->cab_triangles.push_back(cab); + } + else if (m_current_subsection == File::SUBSECTION__SUBMESH__TEXCOORDS) + { + if (!this->CheckNumArguments(3)) { return; } -void Parser::ParseExtCamera() -{ - if (! this->CheckNumArguments(2)) { return; } - - if (m_current_module->ext_camera == nullptr) - { - m_current_module->ext_camera = std::shared_ptr( new RigDef::ExtCamera() ); - } - ExtCamera* extcam = m_current_module->ext_camera.get(); - - auto mode_str = this->GetArgStr(1); - if (mode_str == "classic") - { - extcam->mode = ExtCamera::MODE_CLASSIC; + Texcoord texcoord; + texcoord.node = this->GetArgNodeRef(0); + texcoord.u = this->GetArgFloat(1); + texcoord.v = this->GetArgFloat(2); + + m_current_submesh->texcoords.push_back(texcoord); + } + else + { + AddMessage(Message::TYPE_ERROR, "Section submesh has no subsection defined, line not parsed."); + } } - else if (mode_str == "cinecam") + + void Parser::ParseFlexbody() { - extcam->mode = ExtCamera::MODE_CINECAM; + if (m_current_subsection == File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE) + { + if (!this->CheckNumArguments(10)) { return; } + + Flexbody flexbody; + flexbody.reference_node = this->GetArgNodeRef(0); + flexbody.x_axis_node = this->GetArgNodeRef(1); + flexbody.y_axis_node = this->GetArgNodeRef(2); + flexbody.offset.x = this->GetArgFloat(3); + flexbody.offset.y = this->GetArgFloat(4); + flexbody.offset.z = this->GetArgFloat(5); + flexbody.rotation.x = this->GetArgFloat(6); + flexbody.rotation.y = this->GetArgFloat(7); + flexbody.rotation.z = this->GetArgFloat(8); + flexbody.mesh_name = this->GetArgStr(9); + + m_last_flexbody = std::shared_ptr(new Flexbody(flexbody)); + m_current_module->flexbodies.push_back(m_last_flexbody); + + // Switch subsection + m_current_subsection = File::SUBSECTION__FLEXBODIES__FORSET_LINE; + } + else if (m_current_subsection == File::SUBSECTION__FLEXBODIES__FORSET_LINE) + { + // Syntax: "forset", followed by space/comma, followed by ","-separated items. + // Acceptable item forms: + // * Single node number / node name + // * Pair of node numbers:" 123 - 456 ". Whitespace is optional. + + char setdef[LINE_BUFFER_LENGTH] = ""; // strtok() is destructive, we need own buffer. + strncpy(setdef, m_current_line + 6, LINE_BUFFER_LENGTH - 6); // Cut away "forset" + const char *item = std::strtok(setdef, ","); + + // TODO: Add error reporting + // It appears strtoul() sets no ERRNO for input 'x1' (parsed -> '0') + + const ptrdiff_t MAX_ITEM_LEN = 200; + while (item != nullptr) + { + const char *hyphen = strchr(item, '-'); + if (hyphen != nullptr) + { + unsigned a = 0; + char * a_end = nullptr; + std::string a_text; + std::string b_text; + if (hyphen != item) + { + a = ::strtoul(item, &a_end, 10); + size_t length = std::min(a_end - item, MAX_ITEM_LEN); + a_text = std::string(item, length); + } + char * b_end = nullptr; + const char *item2 = hyphen + 1; + unsigned b = ::strtoul(item2, &b_end, 10); + size_t length = std::min(b_end - item2, MAX_ITEM_LEN); + b_text = std::string(item2, length); + + // Add interval [a-b] + m_last_flexbody->node_list_to_import.push_back( + Node::Range(Node::Ref(a_text, a, Node::Ref::IMPORT_STATE_IS_VALID, m_current_line_number), + Node::Ref(b_text, b, Node::Ref::IMPORT_STATE_IS_VALID, m_current_line_number))); + } + else + { + errno = 0; + unsigned a = 0; + a = ::strtoul(item, nullptr, 10); + // Add interval [a-a] + Node::Range range_a = + Node::Range(Node::Ref(std::string(item), a, Node::Ref::IMPORT_STATE_IS_VALID, m_current_line_number)); + m_last_flexbody->node_list_to_import.push_back(range_a); + } + item = strtok(nullptr, ","); + } + + // Switch subsection + m_current_subsection = File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE; + } + else + { + AddMessage(Message::TYPE_FATAL_ERROR, "Internal parser failure, section 'flexbodies' not parsed."); + } } - else if ((mode_str == "node") && (m_num_args > 2)) + + void Parser::ParseFlaresUnified() { - extcam->mode = ExtCamera::MODE_NODE; - extcam->node = this->GetArgNodeRef(2); - } -} + const bool is_flares2 = (m_current_section == File::SECTION_FLARES_2); + if (!this->CheckNumArguments(is_flares2 ? 6 : 5)) { return; } -void Parser::ParseExhaust() -{ - if (! this->CheckNumArguments(2)) { return; } + Flare2 flare2; + int pos = 0; + flare2.reference_node = this->GetArgNodeRef(pos++); + flare2.node_axis_x = this->GetArgNodeRef(pos++); + flare2.node_axis_y = this->GetArgNodeRef(pos++); + flare2.offset.x = this->GetArgFloat(pos++); + flare2.offset.y = this->GetArgFloat(pos++); - Exhaust exhaust; - exhaust.reference_node = this->GetArgNodeRef(0); - exhaust.direction_node = this->GetArgNodeRef(1); - - // Param [2] is unused - if (m_num_args > 3) { exhaust.particle_name = this->GetArgStr(3); } + if (m_current_section == File::SECTION_FLARES_2) { flare2.offset.z = this->GetArgFloat(pos++); } - m_current_module->exhausts.push_back(exhaust); -} + if (m_num_args > pos) { flare2.type = this->GetArgFlareType(pos++); } + if (m_num_args > pos) { flare2.control_number = this->GetArgInt(pos++); } + if (m_num_args > pos) { flare2.blink_delay_milis = this->GetArgInt(pos++); } + if (m_num_args > pos) { flare2.size = this->GetArgFloat(pos++); } + if (m_num_args > pos) { flare2.material_name = this->GetArgStr(pos++); } -void Parser::ParseFileFormatVersion() -{ - if (! this->CheckNumArguments(2)) { return; } + m_current_module->flares_2.push_back(flare2); + } - if (m_current_module != m_root_module) + void Parser::ParseFixes() { - this->AddMessage(Message::TYPE_WARNING, "Inline section 'fileformatversion' has global effect and should not appear in a module"); + m_current_module->fixes.push_back(this->GetArgNodeRef(0)); } - m_definition->file_format_version = this->GetArgUint(1); - - if (m_definition->file_format_version >= 450) + void Parser::ParseExtCamera() { - m_sequential_importer.Disable(); - } + if (!this->CheckNumArguments(2)) { return; } - this->ChangeSection(File::SECTION_NONE); -} + if (m_current_module->ext_camera == nullptr) + { m_current_module->ext_camera = std::shared_ptr(new RigDef::ExtCamera()); } + ExtCamera *extcam = m_current_module->ext_camera.get(); -void Parser::ParseDirectiveDetacherGroup() -{ - if (! this->CheckNumArguments(2)) { return; } // 2 items: keyword, param + auto mode_str = this->GetArgStr(1); + if (mode_str == "classic") { extcam->mode = ExtCamera::MODE_CLASSIC; } + else if (mode_str == "cinecam") + { + extcam->mode = ExtCamera::MODE_CINECAM; + } + else if ((mode_str == "node") && (m_num_args > 2)) + { + extcam->mode = ExtCamera::MODE_NODE; + extcam->node = this->GetArgNodeRef(2); + } + } - if (this->GetArgStr(1) == "end") + void Parser::ParseExhaust() { - m_current_detacher_group = 0; + if (!this->CheckNumArguments(2)) { return; } + + Exhaust exhaust; + exhaust.reference_node = this->GetArgNodeRef(0); + exhaust.direction_node = this->GetArgNodeRef(1); + + // Param [2] is unused + if (m_num_args > 3) { exhaust.particle_name = this->GetArgStr(3); } + + m_current_module->exhausts.push_back(exhaust); } - else + + void Parser::ParseFileFormatVersion() { - m_current_detacher_group = this->GetArgInt(1); - } -} + if (!this->CheckNumArguments(2)) { return; } -void Parser::ParseCruiseControl() -{ - if (! this->CheckNumArguments(3)) { return; } // keyword + 2 params + if (m_current_module != m_root_module) + { + this->AddMessage(Message::TYPE_WARNING, + "Inline section 'fileformatversion' has global effect and should not appear in a module"); + } - CruiseControl cruise_control; - cruise_control.min_speed = this->GetArgFloat(1); - cruise_control.autobrake = this->GetArgInt(2); + m_definition->file_format_version = this->GetArgUint(1); - if (m_current_module->cruise_control != nullptr) - { - this->AddMessage(Message::TYPE_WARNING, "Directive 'CruiseControl' used multiple times."); + if (m_definition->file_format_version >= 450) { m_sequential_importer.Disable(); } + + this->ChangeSection(File::SECTION_NONE); } - m_current_module->cruise_control = std::shared_ptr( new CruiseControl(cruise_control) ); -} -void Parser::ParseDirectiveAddAnimation() -{ - if (m_current_module->props.size() == 0) + void Parser::ParseDirectiveDetacherGroup() { - AddMessage(Message::TYPE_ERROR, "Directive 'add_animation' has no prop to animate, ignoring..."); - return; - } + if (!this->CheckNumArguments(2)) { return; } // 2 items: keyword, param - Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 14, ","); // "add_animation " = 14 characters + if (this->GetArgStr(1) == "end") { m_current_detacher_group = 0; } + else + { + m_current_detacher_group = this->GetArgInt(1); + } + } - if (tokens.size() < 4) + void Parser::ParseCruiseControl() { - AddMessage(Message::TYPE_ERROR, "Not enough arguments, skipping..."); - return; - } + if (!this->CheckNumArguments(3)) { return; } // keyword + 2 params - Animation animation; - animation.ratio = this->ParseArgFloat(tokens[0].c_str()); - animation.lower_limit = this->ParseArgFloat(tokens[1].c_str()); - animation.upper_limit = this->ParseArgFloat(tokens[2].c_str()); + CruiseControl cruise_control; + cruise_control.min_speed = this->GetArgFloat(1); + cruise_control.autobrake = this->GetArgInt(2); - for (auto itor = tokens.begin() + 3; itor != tokens.end(); ++itor) + if (m_current_module->cruise_control != nullptr) + { this->AddMessage(Message::TYPE_WARNING, "Directive 'CruiseControl' used multiple times."); } + m_current_module->cruise_control = std::shared_ptr(new CruiseControl(cruise_control)); + } + + void Parser::ParseDirectiveAddAnimation() { - Ogre::StringVector entry = Ogre::StringUtil::split(*itor, ":"); - Ogre::StringUtil::trim(entry[0]); - if (entry.size() > 1) Ogre::StringUtil::trim(entry[1]); + if (m_current_module->props.size() == 0) + { + AddMessage(Message::TYPE_ERROR, "Directive 'add_animation' has no prop to animate, ignoring..."); + return; + } - const int WARN_LEN = 500; - char warn_msg[WARN_LEN] = ""; + Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 14, ","); // "add_animation " = 14 characters - if (entry.size() == 1) // Single keyword + if (tokens.size() < 4) { - if (entry[0] == "autoanimate") { animation.mode |= Animation::MODE_AUTO_ANIMATE; } - else if (entry[0] == "noflip") { animation.mode |= Animation::MODE_NO_FLIP; } - else if (entry[0] == "bounce") { animation.mode |= Animation::MODE_BOUNCE; } - else if (entry[0] == "eventlock") { animation.mode |= Animation::MODE_EVENT_LOCK; } - - else { snprintf(warn_msg, WARN_LEN, "Invalid keyword: %s", entry[0].c_str()); } + AddMessage(Message::TYPE_ERROR, "Not enough arguments, skipping..."); + return; } - else if (entry.size() == 2 && (entry[0] == "mode" || entry[0] == "event" || entry[0] == "source")) + + Animation animation; + animation.ratio = this->ParseArgFloat(tokens[0].c_str()); + animation.lower_limit = this->ParseArgFloat(tokens[1].c_str()); + animation.upper_limit = this->ParseArgFloat(tokens[2].c_str()); + + for (auto itor = tokens.begin() + 3; itor != tokens.end(); ++itor) { - Ogre::StringVector values = Ogre::StringUtil::split(entry[1], "|"); - if (entry[0] == "mode") + Ogre::StringVector entry = Ogre::StringUtil::split(*itor, ":"); + Ogre::StringUtil::trim(entry[0]); + if (entry.size() > 1) Ogre::StringUtil::trim(entry[1]); + + const int WARN_LEN = 500; + char warn_msg[WARN_LEN] = ""; + + if (entry.size() == 1) // Single keyword { - for (auto itor = values.begin(); itor != values.end(); ++itor) + if (entry[0] == "autoanimate") { animation.mode |= Animation::MODE_AUTO_ANIMATE; } + else if (entry[0] == "noflip") { - std::string value = *itor; - Ogre::StringUtil::trim(value); - - if (value == "x-rotation") { animation.mode |= Animation::MODE_ROTATION_X; } - else if (value == "y-rotation") { animation.mode |= Animation::MODE_ROTATION_Y; } - else if (value == "z-rotation") { animation.mode |= Animation::MODE_ROTATION_Z; } - else if (value == "x-offset" ) { animation.mode |= Animation::MODE_OFFSET_X; } - else if (value == "y-offset" ) { animation.mode |= Animation::MODE_OFFSET_Y; } - else if (value == "z-offset" ) { animation.mode |= Animation::MODE_OFFSET_Z; } + animation.mode |= Animation::MODE_NO_FLIP; + } + else if (entry[0] == "bounce") + { + animation.mode |= Animation::MODE_BOUNCE; + } + else if (entry[0] == "eventlock") + { + animation.mode |= Animation::MODE_EVENT_LOCK; + } - else { snprintf(warn_msg, WARN_LEN, "Invalid 'mode': %s, ignoring...", entry[1].c_str()); } + else + { + snprintf(warn_msg, WARN_LEN, "Invalid keyword: %s", entry[0].c_str()); } } - else if (entry[0] == "event") - { - animation.event = entry[1]; - Ogre::StringUtil::trim(animation.event); - Ogre::StringUtil::toUpperCase(animation.event); - } - else if (entry[0] == "source") + else if (entry.size() == 2 && (entry[0] == "mode" || entry[0] == "event" || entry[0] == "source")) { - for (auto itor = values.begin(); itor != values.end(); ++itor) + Ogre::StringVector values = Ogre::StringUtil::split(entry[1], "|"); + if (entry[0] == "mode") { - std::string value = *itor; - Ogre::StringUtil::trim(value); - - if (value == "airspeed") { animation.source |= Animation::SOURCE_AIRSPEED; } - else if (value == "vvi") { animation.source |= Animation::SOURCE_VERTICAL_VELOCITY; } - else if (value == "altimeter100k") { animation.source |= Animation::SOURCE_ALTIMETER_100K; } - else if (value == "altimeter10k") { animation.source |= Animation::SOURCE_ALTIMETER_10K; } - else if (value == "altimeter1k") { animation.source |= Animation::SOURCE_ALTIMETER_1K; } - else if (value == "aoa") { animation.source |= Animation::SOURCE_ANGLE_OF_ATTACK; } - else if (value == "flap") { animation.source |= Animation::SOURCE_FLAP; } - else if (value == "airbrake") { animation.source |= Animation::SOURCE_AIR_BRAKE; } - else if (value == "roll") { animation.source |= Animation::SOURCE_ROLL; } - else if (value == "pitch") { animation.source |= Animation::SOURCE_PITCH; } - else if (value == "brakes") { animation.source |= Animation::SOURCE_BRAKES; } - else if (value == "accel") { animation.source |= Animation::SOURCE_ACCEL; } - else if (value == "clutch") { animation.source |= Animation::SOURCE_CLUTCH; } - else if (value == "speedo") { animation.source |= Animation::SOURCE_SPEEDO; } - else if (value == "tacho") { animation.source |= Animation::SOURCE_TACHO; } - else if (value == "turbo") { animation.source |= Animation::SOURCE_TURBO; } - else if (value == "parking") { animation.source |= Animation::SOURCE_PARKING; } - else if (value == "shifterman1") { animation.source |= Animation::SOURCE_SHIFT_LEFT_RIGHT; } - else if (value == "shifterman2") { animation.source |= Animation::SOURCE_SHIFT_BACK_FORTH; } - else if (value == "sequential") { animation.source |= Animation::SOURCE_SEQUENTIAL_SHIFT; } - else if (value == "shifterlin") { animation.source |= Animation::SOURCE_SHIFTERLIN; } - else if (value == "torque") { animation.source |= Animation::SOURCE_TORQUE; } - else if (value == "heading") { animation.source |= Animation::SOURCE_HEADING; } - else if (value == "difflock") { animation.source |= Animation::SOURCE_DIFFLOCK; } - else if (value == "rudderboat") { animation.source |= Animation::SOURCE_BOAT_RUDDER; } - else if (value == "throttleboat") { animation.source |= Animation::SOURCE_BOAT_THROTTLE; } - else if (value == "steeringwheel") { animation.source |= Animation::SOURCE_STEERING_WHEEL; } - else if (value == "aileron") { animation.source |= Animation::SOURCE_AILERON; } - else if (value == "elevator") { animation.source |= Animation::SOURCE_ELEVATOR; } - else if (value == "rudderair") { animation.source |= Animation::SOURCE_AIR_RUDDER; } - else if (value == "permanent") { animation.source |= Animation::SOURCE_PERMANENT; } - else if (value == "event") { animation.source |= Animation::SOURCE_EVENT; } + for (auto itor = values.begin(); itor != values.end(); ++itor) + { + std::string value = *itor; + Ogre::StringUtil::trim(value); - else + if (value == "x-rotation") { animation.mode |= Animation::MODE_ROTATION_X; } + else if (value == "y-rotation") + { + animation.mode |= Animation::MODE_ROTATION_Y; + } + else if (value == "z-rotation") + { + animation.mode |= Animation::MODE_ROTATION_Z; + } + else if (value == "x-offset") + { + animation.mode |= Animation::MODE_OFFSET_X; + } + else if (value == "y-offset") + { + animation.mode |= Animation::MODE_OFFSET_Y; + } + else if (value == "z-offset") + { + animation.mode |= Animation::MODE_OFFSET_Z; + } + + else + { + snprintf(warn_msg, WARN_LEN, "Invalid 'mode': %s, ignoring...", entry[1].c_str()); + } + } + } + else if (entry[0] == "event") + { + animation.event = entry[1]; + Ogre::StringUtil::trim(animation.event); + Ogre::StringUtil::toUpperCase(animation.event); + } + else if (entry[0] == "source") + { + for (auto itor = values.begin(); itor != values.end(); ++itor) { - Animation::MotorSource motor_source; - if (entry[1].compare(0, 8, "throttle") == 0) + std::string value = *itor; + Ogre::StringUtil::trim(value); + + if (value == "airspeed") { animation.source |= Animation::SOURCE_AIRSPEED; } + else if (value == "vvi") + { + animation.source |= Animation::SOURCE_VERTICAL_VELOCITY; + } + else if (value == "altimeter100k") + { + animation.source |= Animation::SOURCE_ALTIMETER_100K; + } + else if (value == "altimeter10k") { - motor_source.source = Animation::MotorSource::SOURCE_AERO_THROTTLE; - motor_source.motor = this->ParseArgUint(entry[1].substr(8)); + animation.source |= Animation::SOURCE_ALTIMETER_10K; } - else if (entry[1].compare(0, 3, "rpm") == 0) + else if (value == "altimeter1k") { - motor_source.source = Animation::MotorSource::SOURCE_AERO_RPM; - motor_source.motor = this->ParseArgUint(entry[1].substr(3)); + animation.source |= Animation::SOURCE_ALTIMETER_1K; } - else if (entry[1].compare(0, 8, "aerotorq") == 0) + else if (value == "aoa") { - motor_source.source = Animation::MotorSource::SOURCE_AERO_TORQUE; - motor_source.motor = this->ParseArgUint(entry[1].substr(8)); + animation.source |= Animation::SOURCE_ANGLE_OF_ATTACK; } - else if (entry[1].compare(0, 7, "aeropit") == 0) + else if (value == "flap") { - motor_source.source = Animation::MotorSource::SOURCE_AERO_PITCH; - motor_source.motor = this->ParseArgUint(entry[1].substr(7)); + animation.source |= Animation::SOURCE_FLAP; } - else if (entry[1].compare(0, 10, "aerostatus") == 0) + else if (value == "airbrake") { - motor_source.source = Animation::MotorSource::SOURCE_AERO_STATUS; - motor_source.motor = this->ParseArgUint(entry[1].substr(10)); + animation.source |= Animation::SOURCE_AIR_BRAKE; } + else if (value == "roll") + { + animation.source |= Animation::SOURCE_ROLL; + } + else if (value == "pitch") + { + animation.source |= Animation::SOURCE_PITCH; + } + else if (value == "brakes") + { + animation.source |= Animation::SOURCE_BRAKES; + } + else if (value == "accel") + { + animation.source |= Animation::SOURCE_ACCEL; + } + else if (value == "clutch") + { + animation.source |= Animation::SOURCE_CLUTCH; + } + else if (value == "speedo") + { + animation.source |= Animation::SOURCE_SPEEDO; + } + else if (value == "tacho") + { + animation.source |= Animation::SOURCE_TACHO; + } + else if (value == "turbo") + { + animation.source |= Animation::SOURCE_TURBO; + } + else if (value == "parking") + { + animation.source |= Animation::SOURCE_PARKING; + } + else if (value == "shifterman1") + { + animation.source |= Animation::SOURCE_SHIFT_LEFT_RIGHT; + } + else if (value == "shifterman2") + { + animation.source |= Animation::SOURCE_SHIFT_BACK_FORTH; + } + else if (value == "sequential") + { + animation.source |= Animation::SOURCE_SEQUENTIAL_SHIFT; + } + else if (value == "shifterlin") + { + animation.source |= Animation::SOURCE_SHIFTERLIN; + } + else if (value == "torque") + { + animation.source |= Animation::SOURCE_TORQUE; + } + else if (value == "heading") + { + animation.source |= Animation::SOURCE_HEADING; + } + else if (value == "difflock") + { + animation.source |= Animation::SOURCE_DIFFLOCK; + } + else if (value == "rudderboat") + { + animation.source |= Animation::SOURCE_BOAT_RUDDER; + } + else if (value == "throttleboat") + { + animation.source |= Animation::SOURCE_BOAT_THROTTLE; + } + else if (value == "steeringwheel") + { + animation.source |= Animation::SOURCE_STEERING_WHEEL; + } + else if (value == "aileron") + { + animation.source |= Animation::SOURCE_AILERON; + } + else if (value == "elevator") + { + animation.source |= Animation::SOURCE_ELEVATOR; + } + else if (value == "rudderair") + { + animation.source |= Animation::SOURCE_AIR_RUDDER; + } + else if (value == "permanent") + { + animation.source |= Animation::SOURCE_PERMANENT; + } + else if (value == "event") + { + animation.source |= Animation::SOURCE_EVENT; + } + else { - snprintf(warn_msg, WARN_LEN, "Invalid 'source': %s, ignoring...", entry[1].c_str()); - continue; + Animation::MotorSource motor_source; + if (entry[1].compare(0, 8, "throttle") == 0) + { + motor_source.source = Animation::MotorSource::SOURCE_AERO_THROTTLE; + motor_source.motor = this->ParseArgUint(entry[1].substr(8)); + } + else if (entry[1].compare(0, 3, "rpm") == 0) + { + motor_source.source = Animation::MotorSource::SOURCE_AERO_RPM; + motor_source.motor = this->ParseArgUint(entry[1].substr(3)); + } + else if (entry[1].compare(0, 8, "aerotorq") == 0) + { + motor_source.source = Animation::MotorSource::SOURCE_AERO_TORQUE; + motor_source.motor = this->ParseArgUint(entry[1].substr(8)); + } + else if (entry[1].compare(0, 7, "aeropit") == 0) + { + motor_source.source = Animation::MotorSource::SOURCE_AERO_PITCH; + motor_source.motor = this->ParseArgUint(entry[1].substr(7)); + } + else if (entry[1].compare(0, 10, "aerostatus") == 0) + { + motor_source.source = Animation::MotorSource::SOURCE_AERO_STATUS; + motor_source.motor = this->ParseArgUint(entry[1].substr(10)); + } + else + { + snprintf(warn_msg, WARN_LEN, "Invalid 'source': %s, ignoring...", entry[1].c_str()); + continue; + } + animation.motor_sources.push_back(motor_source); } - animation.motor_sources.push_back(motor_source); } } + else + { + snprintf(warn_msg, WARN_LEN, "Invalid keyword: %s, ignoring...", entry[0].c_str()); + } } else { - snprintf(warn_msg, WARN_LEN, "Invalid keyword: %s, ignoring...", entry[0].c_str()); + snprintf(warn_msg, WARN_LEN, "Invalid item: %s, ignoring...", entry[0].c_str()); } - } - else - { - snprintf(warn_msg, WARN_LEN, "Invalid item: %s, ignoring...", entry[0].c_str()); - } - if (warn_msg[0] != '\0') - { - char msg[WARN_LEN + 100]; - snprintf(msg, WARN_LEN + 100, "Invalid token: %s (%s) ignoring....", itor->c_str(), warn_msg); - this->AddMessage(Message::TYPE_WARNING, msg); + if (warn_msg[0] != '\0') + { + char msg[WARN_LEN + 100]; + snprintf(msg, WARN_LEN + 100, "Invalid token: %s (%s) ignoring....", itor->c_str(), warn_msg); + this->AddMessage(Message::TYPE_WARNING, msg); + } } - } - m_current_module->props.back().animations.push_back(animation); -} + m_current_module->props.back().animations.push_back(animation); + } -void Parser::ParseAntiLockBrakes() -{ - AntiLockBrakes alb; - Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 15, ","); // "AntiLockBrakes " = 15 characters - if (tokens.size() < 2) + void Parser::ParseAntiLockBrakes() { - this->AddMessage(Message::TYPE_ERROR, "Too few arguments for `AntiLockBrakes`"); - return; - } + AntiLockBrakes alb; + Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line + 15, ","); // "AntiLockBrakes " = 15 characters + if (tokens.size() < 2) + { + this->AddMessage(Message::TYPE_ERROR, "Too few arguments for `AntiLockBrakes`"); + return; + } - alb.regulation_force = this->ParseArgFloat(tokens[0].c_str()); - alb.min_speed = this->ParseArgInt (tokens[1].c_str()); + alb.regulation_force = this->ParseArgFloat(tokens[0].c_str()); + alb.min_speed = this->ParseArgInt(tokens[1].c_str()); - if (tokens.size() > 3) { alb.pulse_per_sec = this->ParseArgFloat(tokens[2].c_str()); } + if (tokens.size() > 3) { alb.pulse_per_sec = this->ParseArgFloat(tokens[2].c_str()); } - for (unsigned int i=3; iAddMessage(Message::TYPE_ERROR, "Antilockbrakes Mode: missing"); + alb.attr_no_dashboard = false; + alb.attr_no_toggle = false; + alb.attr_is_on = true; } } - else - { - this->AddMessage(Message::TYPE_ERROR, "Antilockbrakes Mode: missing"); - alb.attr_no_dashboard = false; - alb.attr_no_toggle = false; - alb.attr_is_on = true; - } + + if (m_current_module->anti_lock_brakes != nullptr) + { this->AddMessage(Message::TYPE_WARNING, "Found multiple sections 'AntiLockBrakes' in one module, using last one."); } + m_current_module->anti_lock_brakes = std::shared_ptr(new AntiLockBrakes(alb)); } - if (m_current_module->anti_lock_brakes != nullptr) + void Parser::ParseEngoption() { - this->AddMessage(Message::TYPE_WARNING, "Found multiple sections 'AntiLockBrakes' in one module, using last one."); - } - m_current_module->anti_lock_brakes = std::shared_ptr( new AntiLockBrakes(alb) ); -} + if (!this->CheckNumArguments(1)) { return; } -void Parser::ParseEngoption() -{ - if (! this->CheckNumArguments(1)) { return; } + Engoption engoption; + engoption.inertia = this->GetArgFloat(0); - Engoption engoption; - engoption.inertia = this->GetArgFloat(0); + if (m_num_args > 1) { engoption.type = Engoption::EngineType(this->GetArgChar(1)); } - if (m_num_args > 1) - { - engoption.type = Engoption::EngineType(this->GetArgChar(1)); + if (m_num_args > 2) { engoption.clutch_force = this->GetArgFloat(2); } + if (m_num_args > 3) { engoption.shift_time = this->GetArgFloat(3); } + if (m_num_args > 4) { engoption.clutch_time = this->GetArgFloat(4); } + if (m_num_args > 5) { engoption.post_shift_time = this->GetArgFloat(5); } + if (m_num_args > 6) { engoption.stall_rpm = this->GetArgFloat(6); } + if (m_num_args > 7) { engoption.idle_rpm = this->GetArgFloat(7); } + if (m_num_args > 8) { engoption.max_idle_mixture = this->GetArgFloat(8); } + if (m_num_args > 9) { engoption.min_idle_mixture = this->GetArgFloat(9); } + if (m_num_args > 10) { engoption.braking_torque = this->GetArgFloat(10); } + + m_current_module->engoption = std::shared_ptr(new Engoption(engoption)); } - if (m_num_args > 2) { engoption.clutch_force = this->GetArgFloat(2); } - if (m_num_args > 3) { engoption.shift_time = this->GetArgFloat(3); } - if (m_num_args > 4) { engoption.clutch_time = this->GetArgFloat(4); } - if (m_num_args > 5) { engoption.post_shift_time = this->GetArgFloat(5); } - if (m_num_args > 6) { engoption.stall_rpm = this->GetArgFloat(6); } - if (m_num_args > 7) { engoption.idle_rpm = this->GetArgFloat(7); } - if (m_num_args > 8) { engoption.max_idle_mixture = this->GetArgFloat(8); } - if (m_num_args > 9) { engoption.min_idle_mixture = this->GetArgFloat(9); } - if (m_num_args > 10){ engoption.braking_torque = this->GetArgFloat(10);} + void Parser::ParseEngturbo() + { + if (!this->CheckNumArguments(4)) { return; } - m_current_module->engoption = std::shared_ptr( new Engoption(engoption) ); -} + Engturbo engturbo; + engturbo.version = this->GetArgInt(0); + engturbo.tinertiaFactor = this->GetArgFloat(1); + engturbo.nturbos = this->GetArgInt(2); + engturbo.param1 = this->GetArgFloat(3); -void Parser::ParseEngturbo() -{ - if (! this->CheckNumArguments(4)) { return; } + if (m_num_args > 4) { engturbo.param2 = this->GetArgFloat(4); } + if (m_num_args > 5) { engturbo.param3 = this->GetArgFloat(5); } + if (m_num_args > 6) { engturbo.param4 = this->GetArgFloat(6); } + if (m_num_args > 7) { engturbo.param5 = this->GetArgFloat(7); } + if (m_num_args > 8) { engturbo.param6 = this->GetArgFloat(8); } + if (m_num_args > 9) { engturbo.param7 = this->GetArgFloat(9); } + if (m_num_args > 10) { engturbo.param8 = this->GetArgFloat(10); } + if (m_num_args > 11) { engturbo.param9 = this->GetArgFloat(11); } + if (m_num_args > 12) { engturbo.param10 = this->GetArgFloat(12); } + if (m_num_args > 13) { engturbo.param11 = this->GetArgFloat(13); } - Engturbo engturbo; - engturbo.version = this->GetArgInt ( 0); - engturbo.tinertiaFactor = this->GetArgFloat( 1); - engturbo.nturbos = this->GetArgInt ( 2); - engturbo.param1 = this->GetArgFloat( 3); + if (engturbo.nturbos > 4) + { + this->AddMessage(Message::TYPE_WARNING, "You cannot have more than 4 turbos. Fallback: using 4 instead."); + engturbo.nturbos = 4; + } - if (m_num_args > 4) { engturbo.param2 = this->GetArgFloat( 4); } - if (m_num_args > 5) { engturbo.param3 = this->GetArgFloat( 5); } - if (m_num_args > 6) { engturbo.param4 = this->GetArgFloat( 6); } - if (m_num_args > 7) { engturbo.param5 = this->GetArgFloat( 7); } - if (m_num_args > 8) { engturbo.param6 = this->GetArgFloat( 8); } - if (m_num_args > 9) { engturbo.param7 = this->GetArgFloat( 9); } - if (m_num_args > 10) { engturbo.param8 = this->GetArgFloat(10); } - if (m_num_args > 11) { engturbo.param9 = this->GetArgFloat(11); } - if (m_num_args > 12) { engturbo.param10 = this->GetArgFloat(12); } - if (m_num_args > 13) { engturbo.param11 = this->GetArgFloat(13); } + m_current_module->engturbo = std::shared_ptr(new Engturbo(engturbo)); + } - if (engturbo.nturbos > 4) + void Parser::ParseEngine() { - this->AddMessage(Message::TYPE_WARNING, "You cannot have more than 4 turbos. Fallback: using 4 instead."); - engturbo.nturbos = 4; - } + if (!this->CheckNumArguments(6)) { return; } - m_current_module->engturbo = std::shared_ptr(new Engturbo(engturbo)); -} + Engine engine; + engine.shift_down_rpm = this->GetArgFloat(0); + engine.shift_up_rpm = this->GetArgFloat(1); + engine.torque = this->GetArgFloat(2); + engine.global_gear_ratio = this->GetArgFloat(3); + engine.reverse_gear_ratio = this->GetArgFloat(4); + engine.neutral_gear_ratio = this->GetArgFloat(5); -void Parser::ParseEngine() -{ - if (! this->CheckNumArguments(6)) { return; } + // Forward gears (max 21) + int gear_index = 0; + while ((gear_index < 21) && (m_num_args > (6 + gear_index))) + { + float ratio = this->GetArgFloat(gear_index + 6); + if (ratio < 0.f) { break; } // Optional terminator argument + engine.gear_ratios.push_back(ratio); + ++gear_index; + } - Engine engine; - engine.shift_down_rpm = this->GetArgFloat(0); - engine.shift_up_rpm = this->GetArgFloat(1); - engine.torque = this->GetArgFloat(2); - engine.global_gear_ratio = this->GetArgFloat(3); - engine.reverse_gear_ratio = this->GetArgFloat(4); - engine.neutral_gear_ratio = this->GetArgFloat(5); + if (engine.gear_ratios.size() == 0) + { + AddMessage(Message::TYPE_ERROR, "Engine has no forward gear, ignoring..."); + return; + } - // Forward gears (max 21) - int gear_index = 0; - while ((gear_index < 21) && (m_num_args > (6 + gear_index))) - { - float ratio = this->GetArgFloat(gear_index + 6); - if (ratio < 0.f) { break; } // Optional terminator argument - engine.gear_ratios.push_back(ratio); - ++gear_index; + m_current_module->engine = std::shared_ptr(new Engine(engine)); } - if (engine.gear_ratios.size() == 0) + void Parser::ParseContacter() { - AddMessage(Message::TYPE_ERROR, "Engine has no forward gear, ignoring..."); - return; + if (!this->CheckNumArguments(1)) { return; } + + m_current_module->contacters.push_back(this->GetArgNodeRef(0)); } - m_current_module->engine = std::shared_ptr( new Engine(engine) ); -} + void Parser::ParseCommandsUnified() + { + const bool is_commands2 = (m_current_section == File::SECTION_COMMANDS_2); + const int max_args = (is_commands2 ? 8 : 7); + if (!this->CheckNumArguments(max_args)) { return; } -void Parser::ParseContacter() -{ - if (! this->CheckNumArguments(1)) { return; } + Command2 command2; + command2.beam_defaults = m_user_beam_defaults; + command2.detacher_group = m_current_detacher_group; + command2._format_version = (is_commands2) ? 2 : 1; + command2.inertia_defaults = m_user_default_inertia; - m_current_module->contacters.push_back(this->GetArgNodeRef(0)); -} + int pos = 0; + command2.nodes[0] = this->GetArgNodeRef(pos++); + command2.nodes[1] = this->GetArgNodeRef(pos++); + command2.shorten_rate = this->GetArgFloat(pos++); -void Parser::ParseCommandsUnified() -{ - const bool is_commands2 = (m_current_section == File::SECTION_COMMANDS_2); - const int max_args = (is_commands2 ? 8 : 7); - if (! this->CheckNumArguments(max_args)) { return; } + if (is_commands2) { command2.lengthen_rate = this->GetArgFloat(pos++); } + else + { + command2.lengthen_rate = command2.shorten_rate; + } - Command2 command2; - command2.beam_defaults = m_user_beam_defaults; - command2.detacher_group = m_current_detacher_group; - command2._format_version = (is_commands2) ? 2 : 1; - command2.inertia_defaults = m_user_default_inertia; + command2.max_contraction = this->GetArgFloat(pos++); + command2.max_extension = this->GetArgFloat(pos++); + command2.contract_key = this->GetArgInt(pos++); + command2.extend_key = this->GetArgInt(pos++); - int pos = 0; - command2.nodes[0] = this->GetArgNodeRef(pos++); - command2.nodes[1] = this->GetArgNodeRef(pos++); - command2.shorten_rate = this->GetArgFloat (pos++); + if (m_num_args <= max_args) // No more args? + { + m_current_module->commands_2.push_back(command2); + return; + } - if (is_commands2) - { - command2.lengthen_rate = this->GetArgFloat(pos++); - } - else - { - command2.lengthen_rate = command2.shorten_rate; - } + // Parse options + const int WARN_LEN = 200; + char warn_msg[WARN_LEN] = ""; + std::string options_str = this->GetArgStr(pos++); + char winner = 0; + for (auto itor = options_str.begin(); itor != options_str.end(); ++itor) + { + const char c = *itor; + if ((winner == 0) && (c == 'o' || c == 'p' || c == 'c')) { winner = c; } - command2.max_contraction = this->GetArgFloat(pos++); - command2.max_extension = this->GetArgFloat(pos++); - command2.contract_key = this->GetArgInt (pos++); - command2.extend_key = this->GetArgInt (pos++); + if (c == 'n') {} // Filler, does nothing + else if (c == 'i') + { + command2.option_i_invisible = true; + } + else if (c == 'r') + { + command2.option_r_rope = true; + } + else if (c == 'f') + { + command2.option_f_not_faster = true; + } + else if (c == 'c') + { + command2.option_c_auto_center = true; + } + else if (c == 'p') + { + command2.option_p_1press = true; + } + else if (c == 'o') + { + command2.option_o_1press_center = true; + } + else + { + snprintf(warn_msg, WARN_LEN, "Ignoring unknown flag '%c'", c); + this->AddMessage(Message::TYPE_WARNING, warn_msg); + } + } - if (m_num_args <= max_args) // No more args? - { - m_current_module->commands_2.push_back(command2); - return; - } + // Resolve option conflicts + if (command2.option_c_auto_center && winner != 'c' && winner != 0) + { + AddMessage(Message::TYPE_WARNING, + "Command cannot be one-pressed and self centering at the same time, ignoring flag 'c'"); + command2.option_c_auto_center = false; + } + char ignored = '\0'; + if (command2.option_o_1press_center && winner != 'o' && winner != 0) + { + command2.option_o_1press_center = false; + ignored = 'o'; + } + else if (command2.option_p_1press && winner != 'p' && winner != 0) + { + command2.option_p_1press = false; + ignored = 'p'; + } - // Parse options - const int WARN_LEN = 200; - char warn_msg[WARN_LEN] = ""; - std::string options_str = this->GetArgStr(pos++); - char winner = 0; - for (auto itor = options_str.begin(); itor != options_str.end(); ++itor) - { - const char c = *itor; - if ((winner == 0) && (c == 'o' || c == 'p' || c == 'c')) { winner = c; } - - if (c == 'n') {} // Filler, does nothing - else if (c == 'i') { command2.option_i_invisible = true; } - else if (c == 'r') { command2.option_r_rope = true; } - else if (c == 'f') { command2.option_f_not_faster = true; } - else if (c == 'c') { command2.option_c_auto_center = true; } - else if (c == 'p') { command2.option_p_1press = true; } - else if (c == 'o') { command2.option_o_1press_center = true; } - else + // Report conflicts + if (ignored != 0 && winner == 'c') { - snprintf(warn_msg, WARN_LEN, "Ignoring unknown flag '%c'", c); - this->AddMessage(Message::TYPE_WARNING, warn_msg); + snprintf(warn_msg, WARN_LEN, "Command cannot be one-pressed and self centering at the same time, ignoring flag '%c'", + ignored); + AddMessage(Message::TYPE_WARNING, warn_msg); + } + else if (ignored != 0 && (winner == 'o' || winner == 'p')) + { + snprintf(warn_msg, WARN_LEN, "Command already has a one-pressed c.mode, ignoring flag '%c'", ignored); + AddMessage(Message::TYPE_WARNING, warn_msg); } - } - // Resolve option conflicts - if (command2.option_c_auto_center && winner != 'c' && winner != 0) - { - AddMessage(Message::TYPE_WARNING, "Command cannot be one-pressed and self centering at the same time, ignoring flag 'c'"); - command2.option_c_auto_center = false; - } - char ignored = '\0'; - if (command2.option_o_1press_center && winner != 'o' && winner != 0) - { - command2.option_o_1press_center = false; - ignored = 'o'; - } - else if (command2.option_p_1press && winner != 'p' && winner != 0) - { - command2.option_p_1press = false; - ignored = 'p'; + if (m_num_args > pos) { command2.description = this->GetArgStr(pos++); } + + if (m_num_args > pos) + { + ParseOptionalInertia(command2.inertia, pos); + pos += 4; + } + + if (m_num_args > pos) { command2.affect_engine = this->GetArgFloat(pos++); } + if (m_num_args > pos) { command2.needs_engine = this->GetArgBool(pos++); } + if (m_num_args > pos) { command2.plays_sound = this->GetArgBool(pos++); } + + m_current_module->commands_2.push_back(command2); } - // Report conflicts - if (ignored != 0 && winner == 'c') + void Parser::ParseCollisionBox() { - snprintf(warn_msg, WARN_LEN, "Command cannot be one-pressed and self centering at the same time, ignoring flag '%c'", ignored); - AddMessage(Message::TYPE_WARNING, warn_msg); + CollisionBox collisionbox; + + Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line, ","); + Ogre::StringVector::iterator iter = tokens.begin(); + for (; iter != tokens.end(); iter++) + { + collisionbox.nodes.push_back(this->_ParseNodeRef(*iter)); + } + + m_current_module->collision_boxes.push_back(collisionbox); } - else if (ignored != 0 && (winner == 'o' || winner == 'p')) + + void Parser::ParseCinecam() { - snprintf(warn_msg, WARN_LEN, "Command already has a one-pressed c.mode, ignoring flag '%c'", ignored); - AddMessage(Message::TYPE_WARNING, warn_msg); - } + if (!this->CheckNumArguments(11)) { return; } - if (m_num_args > pos) { command2.description = this->GetArgStr (pos++);} + Cinecam cinecam; + cinecam.beam_defaults = m_user_beam_defaults; + cinecam.node_defaults = m_user_node_defaults; - if (m_num_args > pos) { ParseOptionalInertia(command2.inertia, pos); pos += 4; } + // Required arguments + cinecam.position.x = this->GetArgFloat(0); + cinecam.position.y = this->GetArgFloat(1); + cinecam.position.z = this->GetArgFloat(2); + cinecam.nodes[0] = this->GetArgNodeRef(3); + cinecam.nodes[1] = this->GetArgNodeRef(4); + cinecam.nodes[2] = this->GetArgNodeRef(5); + cinecam.nodes[3] = this->GetArgNodeRef(6); + cinecam.nodes[4] = this->GetArgNodeRef(7); + cinecam.nodes[5] = this->GetArgNodeRef(8); + cinecam.nodes[6] = this->GetArgNodeRef(9); + cinecam.nodes[7] = this->GetArgNodeRef(10); - if (m_num_args > pos) { command2.affect_engine = this->GetArgFloat(pos++);} - if (m_num_args > pos) { command2.needs_engine = this->GetArgBool (pos++);} - if (m_num_args > pos) { command2.plays_sound = this->GetArgBool (pos++);} + // Optional arguments + if (m_num_args > 11) { cinecam.spring = this->GetArgFloat(11); } + if (m_num_args > 12) { cinecam.damping = this->GetArgFloat(12); } - m_current_module->commands_2.push_back(command2); -} + if (m_num_args > 13) + { + float value = this->GetArgFloat(13); + if (value > 0.f) // Invalid input (for example illegal trailing ";pseudo-comment") parses as 0 + cinecam.node_mass = value; + } -void Parser::ParseCollisionBox() -{ - CollisionBox collisionbox; + if (m_sequential_importer.IsEnabled()) { m_sequential_importer.AddGeneratedNode(File::KEYWORD_CINECAM); } - Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line, ","); - Ogre::StringVector::iterator iter = tokens.begin(); - for ( ; iter != tokens.end(); iter++) - { - collisionbox.nodes.push_back( this->_ParseNodeRef(*iter) ); + m_current_module->cinecam.push_back(cinecam); } - m_current_module->collision_boxes.push_back(collisionbox); -} - -void Parser::ParseCinecam() -{ - if (! this->CheckNumArguments(11)) { return; } + void Parser::ParseCameraRails() + { + m_current_camera_rail->nodes.push_back(this->GetArgNodeRef(0)); + } - Cinecam cinecam; - cinecam.beam_defaults = m_user_beam_defaults; - cinecam.node_defaults = m_user_node_defaults; + void Parser::ParseBrakes() + { + if (!this->CheckNumArguments(1)) { return; } - // Required arguments - cinecam.position.x = this->GetArgFloat ( 0); - cinecam.position.y = this->GetArgFloat ( 1); - cinecam.position.z = this->GetArgFloat ( 2); - cinecam.nodes[0] = this->GetArgNodeRef( 3); - cinecam.nodes[1] = this->GetArgNodeRef( 4); - cinecam.nodes[2] = this->GetArgNodeRef( 5); - cinecam.nodes[3] = this->GetArgNodeRef( 6); - cinecam.nodes[4] = this->GetArgNodeRef( 7); - cinecam.nodes[5] = this->GetArgNodeRef( 8); - cinecam.nodes[6] = this->GetArgNodeRef( 9); - cinecam.nodes[7] = this->GetArgNodeRef(10); + if (m_current_module->brakes == nullptr) { m_current_module->brakes = std::shared_ptr(new Brakes()); } - // Optional arguments - if (m_num_args > 11) { cinecam.spring = this->GetArgFloat(11); } - if (m_num_args > 12) { cinecam.damping = this->GetArgFloat(12); } + m_current_module->brakes->default_braking_force = this->GetArgFloat(0); - if (m_num_args > 13) - { - float value = this->GetArgFloat(13); - if (value > 0.f) // Invalid input (for example illegal trailing ";pseudo-comment") parses as 0 - cinecam.node_mass = value; + if (m_num_args > 1) { m_current_module->brakes->parking_brake_force = this->GetArgFloat(1); } } - if (m_sequential_importer.IsEnabled()) + void Parser::ParseAxles() { - m_sequential_importer.AddGeneratedNode(File::KEYWORD_CINECAM); - } + Axle axle; - m_current_module->cinecam.push_back(cinecam); -} + Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line, ","); + Ogre::StringVector::iterator iter = tokens.begin(); + for (; iter != tokens.end(); iter++) + { + std::smatch results; + if (!std::regex_search(*iter, results, Regexes::SECTION_AXLES_PROPERTY)) + { + this->AddMessage(Message::TYPE_ERROR, "Invalid property, ignoring whole line..."); + return; + } + // NOTE: Positions in 'results' array match E_CAPTURE*() positions (starting with 1) in the respective regex. -void Parser::ParseCameraRails() -{ - m_current_camera_rail->nodes.push_back( this->GetArgNodeRef(0) ); -} + if (results[1].matched) + { + unsigned int wheel_index = STR_PARSE_INT(results[2]) - 1; + axle.wheels[wheel_index][0] = _ParseNodeRef(results[3]); + axle.wheels[wheel_index][1] = _ParseNodeRef(results[4]); + } + else if (results[5].matched) + { + std::string options_str = results[6].str(); + for (unsigned int i = 0; i < options_str.length(); i++) + { + switch (options_str.at(i)) + { + case 'o': axle.options.push_back(Axle::OPTION_o_OPEN); break; + case 'l': axle.options.push_back(Axle::OPTION_l_LOCKED); break; + case 's': axle.options.push_back(Axle::OPTION_s_SPLIT); break; + case 'v': axle.options.push_back(Axle::OPTION_s_VISCOUS); break; -void Parser::ParseBrakes() -{ - if (!this->CheckNumArguments(1)) { return; } + default: // No check needed, regex takes care of that + break; + } + } + } + } - if (m_current_module->brakes == nullptr) - { - m_current_module->brakes = std::shared_ptr( new Brakes() ); + m_current_module->axles.push_back(axle); } - m_current_module->brakes->default_braking_force = this->GetArgFloat(0); - - if (m_num_args > 1) + void Parser::ParseInterAxles() { - m_current_module->brakes->parking_brake_force = this->GetArgFloat(1); - } -} + auto args = Ogre::StringUtil::split(m_current_line, ","); + if (args.size() < 2) { return; } -void Parser::ParseAxles() -{ - Axle axle; + InterAxle interaxle; + + interaxle.a1 = this->ParseArgInt(args[0].c_str()) - 1; + interaxle.a2 = this->ParseArgInt(args[1].c_str()) - 1; - Ogre::StringVector tokens = Ogre::StringUtil::split(m_current_line, ","); - Ogre::StringVector::iterator iter = tokens.begin(); - for ( ; iter != tokens.end(); iter++) - { std::smatch results; - if (! std::regex_search(*iter, results, Regexes::SECTION_AXLES_PROPERTY)) + if (!std::regex_search(args[2], results, Regexes::SECTION_AXLES_PROPERTY)) { this->AddMessage(Message::TYPE_ERROR, "Invalid property, ignoring whole line..."); return; } - // NOTE: Positions in 'results' array match E_CAPTURE*() positions (starting with 1) in the respective regex. + // NOTE: Positions in 'results' array match E_CAPTURE*() positions (starting with 1) in the respective regex. - if (results[1].matched) - { - unsigned int wheel_index = STR_PARSE_INT(results[2]) - 1; - axle.wheels[wheel_index][0] = _ParseNodeRef(results[3]); - axle.wheels[wheel_index][1] = _ParseNodeRef(results[4]); - } - else if (results[5].matched) + if (results[5].matched) { std::string options_str = results[6].str(); for (unsigned int i = 0; i < options_str.length(); i++) { - switch(options_str.at(i)) + switch (options_str.at(i)) { - case 'o': - axle.options.push_back(Axle::OPTION_o_OPEN); - break; - case 'l': - axle.options.push_back(Axle::OPTION_l_LOCKED); - break; - case 's': - axle.options.push_back(Axle::OPTION_s_SPLIT); - break; - case 'v': - axle.options.push_back(Axle::OPTION_s_VISCOUS); - break; + case 'o': interaxle.options.push_back(Axle::OPTION_o_OPEN); break; + case 'l': interaxle.options.push_back(Axle::OPTION_l_LOCKED); break; + case 's': interaxle.options.push_back(Axle::OPTION_s_SPLIT); break; + case 'v': interaxle.options.push_back(Axle::OPTION_s_VISCOUS); break; - default: // No check needed, regex takes care of that - break; + default: // No check needed, regex takes care of that + break; } } } - } - m_current_module->axles.push_back(axle); -} + m_current_module->interaxles.push_back(interaxle); + } -void Parser::ParseInterAxles() -{ - auto args = Ogre::StringUtil::split(m_current_line, ","); - if (args.size() < 2) { return; } + void Parser::ParseAirbrakes() + { + if (!this->CheckNumArguments(14)) { return; } - InterAxle interaxle; + Airbrake airbrake; + airbrake.reference_node = this->GetArgNodeRef(0); + airbrake.x_axis_node = this->GetArgNodeRef(1); + airbrake.y_axis_node = this->GetArgNodeRef(2); + airbrake.aditional_node = this->GetArgNodeRef(3); + airbrake.offset.x = this->GetArgFloat(4); + airbrake.offset.y = this->GetArgFloat(5); + airbrake.offset.z = this->GetArgFloat(6); + airbrake.width = this->GetArgFloat(7); + airbrake.height = this->GetArgFloat(8); + airbrake.max_inclination_angle = this->GetArgFloat(9); + airbrake.texcoord_x1 = this->GetArgFloat(10); + airbrake.texcoord_y1 = this->GetArgFloat(11); + airbrake.texcoord_x2 = this->GetArgFloat(12); + airbrake.texcoord_y2 = this->GetArgFloat(13); - interaxle.a1 = this->ParseArgInt(args[0].c_str()) - 1; - interaxle.a2 = this->ParseArgInt(args[1].c_str()) - 1; + m_current_module->airbrakes.push_back(airbrake); + } - std::smatch results; - if (! std::regex_search(args[2], results, Regexes::SECTION_AXLES_PROPERTY)) + void Parser::ParseVideoCamera() { - this->AddMessage(Message::TYPE_ERROR, "Invalid property, ignoring whole line..."); - return; + if (!this->CheckNumArguments(19)) { return; } + + VideoCamera videocamera; + + videocamera.reference_node = this->GetArgNodeRef(0); + videocamera.left_node = this->GetArgNodeRef(1); + videocamera.bottom_node = this->GetArgNodeRef(2); + videocamera.alt_reference_node = this->GetArgNullableNode(3); + videocamera.alt_orientation_node = this->GetArgNullableNode(4); + videocamera.offset.x = this->GetArgFloat(5); + videocamera.offset.y = this->GetArgFloat(6); + videocamera.offset.z = this->GetArgFloat(7); + videocamera.rotation.x = this->GetArgFloat(8); + videocamera.rotation.y = this->GetArgFloat(9); + videocamera.rotation.z = this->GetArgFloat(10); + videocamera.field_of_view = this->GetArgFloat(11); + videocamera.texture_width = this->GetArgInt(12); + videocamera.texture_height = this->GetArgInt(13); + videocamera.min_clip_distance = this->GetArgFloat(14); + videocamera.max_clip_distance = this->GetArgFloat(15); + videocamera.camera_role = this->GetArgInt(16); + videocamera.camera_mode = this->GetArgInt(17); + videocamera.material_name = this->GetArgStr(18); + + if (m_num_args > 19) { videocamera.camera_name = this->GetArgStr(19); } + + m_current_module->videocameras.push_back(videocamera); } - // NOTE: Positions in 'results' array match E_CAPTURE*() positions (starting with 1) in the respective regex. - if (results[5].matched) + void Parser::ParseCameras() { - std::string options_str = results[6].str(); - for (unsigned int i = 0; i < options_str.length(); i++) - { - switch(options_str.at(i)) - { - case 'o': - interaxle.options.push_back(Axle::OPTION_o_OPEN); - break; - case 'l': - interaxle.options.push_back(Axle::OPTION_l_LOCKED); - break; - case 's': - interaxle.options.push_back(Axle::OPTION_s_SPLIT); - break; - case 'v': - interaxle.options.push_back(Axle::OPTION_s_VISCOUS); - break; + if (!this->CheckNumArguments(3)) { return; } - default: // No check needed, regex takes care of that - break; - } - } + Camera camera; + camera.center_node = this->GetArgNodeRef(0); + camera.back_node = this->GetArgNodeRef(1); + camera.left_node = this->GetArgNodeRef(2); + + m_current_module->cameras.push_back(camera); } - m_current_module->interaxles.push_back(interaxle); -} + void Parser::ParseTurbopropsUnified() + { + bool is_turboprop_2 = m_current_section == File::SECTION_TURBOPROPS_2; -void Parser::ParseAirbrakes() -{ - if (! this->CheckNumArguments(14)) { return; } - - Airbrake airbrake; - airbrake.reference_node = this->GetArgNodeRef( 0); - airbrake.x_axis_node = this->GetArgNodeRef( 1); - airbrake.y_axis_node = this->GetArgNodeRef( 2); - airbrake.aditional_node = this->GetArgNodeRef( 3); - airbrake.offset.x = this->GetArgFloat ( 4); - airbrake.offset.y = this->GetArgFloat ( 5); - airbrake.offset.z = this->GetArgFloat ( 6); - airbrake.width = this->GetArgFloat ( 7); - airbrake.height = this->GetArgFloat ( 8); - airbrake.max_inclination_angle = this->GetArgFloat ( 9); - airbrake.texcoord_x1 = this->GetArgFloat (10); - airbrake.texcoord_y1 = this->GetArgFloat (11); - airbrake.texcoord_x2 = this->GetArgFloat (12); - airbrake.texcoord_y2 = this->GetArgFloat (13); - - m_current_module->airbrakes.push_back(airbrake); -} - -void Parser::ParseVideoCamera() -{ - if (! this->CheckNumArguments(19)) { return; } - - VideoCamera videocamera; - - videocamera.reference_node = this->GetArgNodeRef ( 0); - videocamera.left_node = this->GetArgNodeRef ( 1); - videocamera.bottom_node = this->GetArgNodeRef ( 2); - videocamera.alt_reference_node = this->GetArgNullableNode( 3); - videocamera.alt_orientation_node = this->GetArgNullableNode( 4); - videocamera.offset.x = this->GetArgFloat ( 5); - videocamera.offset.y = this->GetArgFloat ( 6); - videocamera.offset.z = this->GetArgFloat ( 7); - videocamera.rotation.x = this->GetArgFloat ( 8); - videocamera.rotation.y = this->GetArgFloat ( 9); - videocamera.rotation.z = this->GetArgFloat (10); - videocamera.field_of_view = this->GetArgFloat (11); - videocamera.texture_width = this->GetArgInt (12); - videocamera.texture_height = this->GetArgInt (13); - videocamera.min_clip_distance = this->GetArgFloat (14); - videocamera.max_clip_distance = this->GetArgFloat (15); - videocamera.camera_role = this->GetArgInt (16); - videocamera.camera_mode = this->GetArgInt (17); - videocamera.material_name = this->GetArgStr (18); - - if (m_num_args > 19) { videocamera.camera_name = this->GetArgStr(19); } - - m_current_module->videocameras.push_back(videocamera); -} - -void Parser::ParseCameras() -{ - if (! this->CheckNumArguments(3)) { return; } + if (!this->CheckNumArguments(is_turboprop_2 ? 9 : 8)) { return; } - Camera camera; - camera.center_node = this->GetArgNodeRef(0); - camera.back_node = this->GetArgNodeRef(1); - camera.left_node = this->GetArgNodeRef(2); + Turboprop2 turboprop; - m_current_module->cameras.push_back(camera); -} + turboprop.reference_node = this->GetArgNodeRef(0); + turboprop.axis_node = this->GetArgNodeRef(1); + turboprop.blade_tip_nodes[0] = this->GetArgNodeRef(2); + turboprop.blade_tip_nodes[1] = this->GetArgNodeRef(3); + turboprop.blade_tip_nodes[2] = this->GetArgNullableNode(4); + turboprop.blade_tip_nodes[3] = this->GetArgNullableNode(5); -void Parser::ParseTurbopropsUnified() -{ - bool is_turboprop_2 = m_current_section == File::SECTION_TURBOPROPS_2; + int offset = 0; + + if (is_turboprop_2) + { + turboprop.couple_node = this->GetArgNullableNode(6); - if (! this->CheckNumArguments(is_turboprop_2 ? 9 : 8)) { return; } + offset = 1; + } - Turboprop2 turboprop; - - turboprop.reference_node = this->GetArgNodeRef(0); - turboprop.axis_node = this->GetArgNodeRef(1); - turboprop.blade_tip_nodes[0] = this->GetArgNodeRef(2); - turboprop.blade_tip_nodes[1] = this->GetArgNodeRef(3); - turboprop.blade_tip_nodes[2] = this->GetArgNullableNode(4); - turboprop.blade_tip_nodes[3] = this->GetArgNullableNode(5); + turboprop.turbine_power_kW = this->GetArgFloat(6 + offset); + turboprop.airfoil = this->GetArgStr(7 + offset); - int offset = 0; + m_current_module->turboprops_2.push_back(turboprop); + } - if (is_turboprop_2) + void Parser::ParseTurbojets() { - turboprop.couple_node = this->GetArgNullableNode(6); + if (!this->CheckNumArguments(9)) { return; } + + Turbojet turbojet; + turbojet.front_node = this->GetArgNodeRef(0); + turbojet.back_node = this->GetArgNodeRef(1); + turbojet.side_node = this->GetArgNodeRef(2); + turbojet.is_reversable = this->GetArgInt(3); + turbojet.dry_thrust = this->GetArgFloat(4); + turbojet.wet_thrust = this->GetArgFloat(5); + turbojet.front_diameter = this->GetArgFloat(6); + turbojet.back_diameter = this->GetArgFloat(7); + turbojet.nozzle_length = this->GetArgFloat(8); - offset = 1; + m_current_module->turbojets.push_back(turbojet); } - turboprop.turbine_power_kW = this->GetArgFloat (6 + offset); - turboprop.airfoil = this->GetArgStr (7 + offset); - - m_current_module->turboprops_2.push_back(turboprop); -} + void Parser::ParseTriggers() + { + if (!this->CheckNumArguments(6)) { return; } -void Parser::ParseTurbojets() -{ - if (! this->CheckNumArguments(9)) { return; } - - Turbojet turbojet; - turbojet.front_node = this->GetArgNodeRef(0); - turbojet.back_node = this->GetArgNodeRef(1); - turbojet.side_node = this->GetArgNodeRef(2); - turbojet.is_reversable = this->GetArgInt (3); - turbojet.dry_thrust = this->GetArgFloat (4); - turbojet.wet_thrust = this->GetArgFloat (5); - turbojet.front_diameter = this->GetArgFloat (6); - turbojet.back_diameter = this->GetArgFloat (7); - turbojet.nozzle_length = this->GetArgFloat (8); - - m_current_module->turbojets.push_back(turbojet); -} - -void Parser::ParseTriggers() -{ - if (! this->CheckNumArguments(6)) { return; } - - Trigger trigger; - trigger.beam_defaults = m_user_beam_defaults; - trigger.detacher_group = m_current_detacher_group; - trigger.nodes[0] = this->GetArgNodeRef(0); - trigger.nodes[1] = this->GetArgNodeRef(1); - trigger.contraction_trigger_limit = this->GetArgFloat (2); - trigger.expansion_trigger_limit = this->GetArgFloat (3); - - int shortbound_trigger_action = this->GetArgInt(4); - int longbound_trigger_action = this->GetArgInt(5); - if (m_num_args > 6) - { - std::string options_str = this->GetArgStr(6); - for (unsigned int i = 0; i < options_str.length(); i++) + Trigger trigger; + trigger.beam_defaults = m_user_beam_defaults; + trigger.detacher_group = m_current_detacher_group; + trigger.nodes[0] = this->GetArgNodeRef(0); + trigger.nodes[1] = this->GetArgNodeRef(1); + trigger.contraction_trigger_limit = this->GetArgFloat(2); + trigger.expansion_trigger_limit = this->GetArgFloat(3); + + int shortbound_trigger_action = this->GetArgInt(4); + int longbound_trigger_action = this->GetArgInt(5); + if (m_num_args > 6) { - switch(options_str.at(i)) + std::string options_str = this->GetArgStr(6); + for (unsigned int i = 0; i < options_str.length(); i++) { - case 'i': trigger.options |= Trigger::OPTION_i_INVISIBLE; break; - case 'c': trigger.options |= Trigger::OPTION_c_COMMAND_STYLE; break; - case 'x': trigger.options |= Trigger::OPTION_x_START_OFF; break; - case 'b': trigger.options |= Trigger::OPTION_b_BLOCK_KEYS; break; - case 'B': trigger.options |= Trigger::OPTION_B_BLOCK_TRIGGERS; break; - case 'A': trigger.options |= Trigger::OPTION_A_INV_BLOCK_TRIGGERS; break; - case 's': trigger.options |= Trigger::OPTION_s_SWITCH_CMD_NUM; break; + switch (options_str.at(i)) + { + case 'i': trigger.options |= Trigger::OPTION_i_INVISIBLE; break; + case 'c': trigger.options |= Trigger::OPTION_c_COMMAND_STYLE; break; + case 'x': trigger.options |= Trigger::OPTION_x_START_OFF; break; + case 'b': trigger.options |= Trigger::OPTION_b_BLOCK_KEYS; break; + case 'B': trigger.options |= Trigger::OPTION_B_BLOCK_TRIGGERS; break; + case 'A': trigger.options |= Trigger::OPTION_A_INV_BLOCK_TRIGGERS; break; + case 's': trigger.options |= Trigger::OPTION_s_SWITCH_CMD_NUM; break; case 'h': trigger.options |= Trigger::OPTION_h_UNLOCK_HOOKGROUPS_KEY; break; - case 'H': trigger.options |= Trigger::OPTION_H_LOCK_HOOKGROUPS_KEY; break; - case 't': trigger.options |= Trigger::OPTION_t_CONTINUOUS; break; - case 'E': trigger.options |= Trigger::OPTION_E_ENGINE_TRIGGER; break; + case 'H': trigger.options |= Trigger::OPTION_H_LOCK_HOOKGROUPS_KEY; break; + case 't': trigger.options |= Trigger::OPTION_t_CONTINUOUS; break; + case 'E': trigger.options |= Trigger::OPTION_E_ENGINE_TRIGGER; break; - default: - this->AddMessage(Message::TYPE_WARNING, Ogre::String("Invalid trigger option: " + options_str.at(i))); + default: this->AddMessage(Message::TYPE_WARNING, Ogre::String("Invalid trigger option: " + options_str.at(i))); + } } } - } - if (m_num_args > 7) - { - float boundary_timer = this->GetArgFloat(7); - if (boundary_timer > 0.0f) - trigger.boundary_timer = boundary_timer; - } + if (m_num_args > 7) + { + float boundary_timer = this->GetArgFloat(7); + if (boundary_timer > 0.0f) trigger.boundary_timer = boundary_timer; + } - // Handle actions - if (trigger.IsHookToggleTrigger()) - { - Trigger::HookToggleTrigger hook_toggle; - hook_toggle.contraction_trigger_hookgroup_id = shortbound_trigger_action; - hook_toggle.extension_trigger_hookgroup_id = longbound_trigger_action; - trigger.SetHookToggleTrigger(hook_toggle); - } - else if (trigger.HasFlag_E_EngineTrigger()) - { - Trigger::EngineTrigger engine_trigger; - engine_trigger.function = Trigger::EngineTrigger::Function(shortbound_trigger_action); - engine_trigger.motor_index = longbound_trigger_action; - trigger.SetEngineTrigger(engine_trigger); + // Handle actions + if (trigger.IsHookToggleTrigger()) + { + Trigger::HookToggleTrigger hook_toggle; + hook_toggle.contraction_trigger_hookgroup_id = shortbound_trigger_action; + hook_toggle.extension_trigger_hookgroup_id = longbound_trigger_action; + trigger.SetHookToggleTrigger(hook_toggle); + } + else if (trigger.HasFlag_E_EngineTrigger()) + { + Trigger::EngineTrigger engine_trigger; + engine_trigger.function = Trigger::EngineTrigger::Function(shortbound_trigger_action); + engine_trigger.motor_index = longbound_trigger_action; + trigger.SetEngineTrigger(engine_trigger); + } + else + { + Trigger::CommandKeyTrigger command_keys; + command_keys.contraction_trigger_key = shortbound_trigger_action; + command_keys.extension_trigger_key = longbound_trigger_action; + trigger.SetCommandKeyTrigger(command_keys); + } + + m_current_module->triggers.push_back(trigger); } - else + + void Parser::ParseTorqueCurve() { - Trigger::CommandKeyTrigger command_keys; - command_keys.contraction_trigger_key = shortbound_trigger_action; - command_keys.extension_trigger_key = longbound_trigger_action; - trigger.SetCommandKeyTrigger(command_keys); - } + if (m_current_module->torque_curve == nullptr) + { m_current_module->torque_curve = std::shared_ptr(new RigDef::TorqueCurve()); } - m_current_module->triggers.push_back(trigger); -} + Ogre::StringVector args = Ogre::StringUtil::split(m_current_line, ","); -void Parser::ParseTorqueCurve() -{ - if (m_current_module->torque_curve == nullptr) - { - m_current_module->torque_curve = std::shared_ptr(new RigDef::TorqueCurve()); + if (args.size() == 1u) { m_current_module->torque_curve->predefined_func_name = args[0]; } + else if (args.size() == 2u) + { + TorqueCurve::Sample sample; + sample.power = this->ParseArgFloat(args[0].c_str()); + sample.torque_percent = this->ParseArgFloat(args[1].c_str()); + m_current_module->torque_curve->samples.push_back(sample); + } + else + { + // Consistent with 0.38's parser. + this->AddMessage(Message::TYPE_ERROR, "Invalid line, too many arguments"); + } } - Ogre::StringVector args = Ogre::StringUtil::split(m_current_line, ","); - - if (args.size() == 1u) - { - m_current_module->torque_curve->predefined_func_name = args[0]; - } - else if (args.size() == 2u) + void Parser::ParseTies() { - TorqueCurve::Sample sample; - sample.power = this->ParseArgFloat(args[0].c_str()); - sample.torque_percent = this->ParseArgFloat(args[1].c_str()); - m_current_module->torque_curve->samples.push_back(sample); - } - else - { - // Consistent with 0.38's parser. - this->AddMessage(Message::TYPE_ERROR, "Invalid line, too many arguments"); - } -} + if (!this->CheckNumArguments(5)) { return; } -void Parser::ParseTies() -{ - if (! this->CheckNumArguments(5)) { return; } - - Tie tie; - tie.beam_defaults = m_user_beam_defaults; - tie.detacher_group = m_current_detacher_group; + Tie tie; + tie.beam_defaults = m_user_beam_defaults; + tie.detacher_group = m_current_detacher_group; - tie.root_node = this->GetArgNodeRef(0); - tie.max_reach_length = this->GetArgFloat (1); - tie.auto_shorten_rate = this->GetArgFloat (2); - tie.min_length = this->GetArgFloat (3); - tie.max_length = this->GetArgFloat (4); + tie.root_node = this->GetArgNodeRef(0); + tie.max_reach_length = this->GetArgFloat(1); + tie.auto_shorten_rate = this->GetArgFloat(2); + tie.min_length = this->GetArgFloat(3); + tie.max_length = this->GetArgFloat(4); - if (m_num_args > 5) - { - for (char c: this->GetArgStr(5)) + if (m_num_args > 5) { - switch (c) + for (char c : this->GetArgStr(5)) { - case Tie::OPTION_n_FILLER: - case Tie::OPTION_v_FILLER: - break; + switch (c) + { + case Tie::OPTION_n_FILLER: + case Tie::OPTION_v_FILLER: break; - case Tie::OPTION_i_INVISIBLE: - tie.is_invisible = true; - break; + case Tie::OPTION_i_INVISIBLE: tie.is_invisible = true; break; - case Tie::OPTION_s_NO_SELF_LOCK: - tie.disable_self_lock = true; - break; + case Tie::OPTION_s_NO_SELF_LOCK: tie.disable_self_lock = true; break; - default: - this->AddMessage(Message::TYPE_WARNING, std::string("Invalid option: ") + c + ", ignoring..."); - break; + default: this->AddMessage(Message::TYPE_WARNING, std::string("Invalid option: ") + c + ", ignoring..."); break; + } } } - } - if (m_num_args > 6) { tie.max_stress = this->GetArgFloat (6); } - if (m_num_args > 7) { tie.group = this->GetArgInt (7); } + if (m_num_args > 6) { tie.max_stress = this->GetArgFloat(6); } + if (m_num_args > 7) { tie.group = this->GetArgInt(7); } - m_current_module->ties.push_back(tie); -} + m_current_module->ties.push_back(tie); + } -void Parser::ParseSoundsources() -{ - if (! this->CheckNumArguments(2)) { return; } - - SoundSource soundsource; - soundsource.node = this->GetArgNodeRef(0); - soundsource.sound_script_name = this->GetArgStr(1); + void Parser::ParseSoundsources() + { + if (!this->CheckNumArguments(2)) { return; } - m_current_module->soundsources.push_back(soundsource); -} + SoundSource soundsource; + soundsource.node = this->GetArgNodeRef(0); + soundsource.sound_script_name = this->GetArgStr(1); -void Parser::ParseSoundsources2() -{ - if (! this->CheckNumArguments(3)) { return; } - - SoundSource2 soundsource2; - soundsource2.node = this->GetArgNodeRef(0); - soundsource2.sound_script_name = this->GetArgStr(2); + m_current_module->soundsources.push_back(soundsource); + } - int mode = this->GetArgInt(1); - if (mode < 0) + void Parser::ParseSoundsources2() { - if (mode < -2) + if (!this->CheckNumArguments(3)) { return; } + + SoundSource2 soundsource2; + soundsource2.node = this->GetArgNodeRef(0); + soundsource2.sound_script_name = this->GetArgStr(2); + + int mode = this->GetArgInt(1); + if (mode < 0) + { + if (mode < -2) + { + std::string msg = this->GetArgStr(1) + " is invalid soundsources2.mode, falling back to default -2"; + this->AddMessage(Message::TYPE_ERROR, msg.c_str()); + mode = -2; + } + soundsource2.mode = SoundSource2::Mode(mode); + } + else { - std::string msg = this->GetArgStr(1) + " is invalid soundsources2.mode, falling back to default -2"; - this->AddMessage(Message::TYPE_ERROR, msg.c_str()); - mode = -2; + soundsource2.mode = SoundSource2::MODE_CINECAM; + soundsource2.cinecam_index = mode; } - soundsource2.mode = SoundSource2::Mode(mode); + + m_current_module->soundsources2.push_back(soundsource2); } - else + + void Parser::ParseSlidenodes() { - soundsource2.mode = SoundSource2::MODE_CINECAM; - soundsource2.cinecam_index = mode; - } + Ogre::StringVector args = Ogre::StringUtil::split(m_current_line, ", "); + if (args.size() < 2u) { this->AddMessage(Message::TYPE_ERROR, "Too few arguments"); } - m_current_module->soundsources2.push_back(soundsource2); -} + SlideNode slidenode; + slidenode.slide_node = this->_ParseNodeRef(args[0]); -void Parser::ParseSlidenodes() -{ - Ogre::StringVector args = Ogre::StringUtil::split(m_current_line, ", "); - if (args.size() < 2u) - { - this->AddMessage(Message::TYPE_ERROR, "Too few arguments"); - } - - SlideNode slidenode; - slidenode.slide_node = this->_ParseNodeRef(args[0]); - - bool in_rail_node_list = true; - - for (auto itor = args.begin() + 1; itor != args.end(); ++itor) - { - char c = toupper(itor->at(0)); - switch (c) - { - case 'S': - slidenode.spring_rate = this->ParseArgFloat(itor->substr(1)); - in_rail_node_list = false; - break; - case 'B': - slidenode.break_force = this->ParseArgFloat(itor->substr(1)); - slidenode._break_force_set = true; - in_rail_node_list = false; - break; - case 'T': - slidenode.tolerance = this->ParseArgFloat(itor->substr(1)); - in_rail_node_list = false; - break; - case 'R': - slidenode.attachment_rate = this->ParseArgFloat(itor->substr(1)); - in_rail_node_list = false; - break; - case 'G': - slidenode.railgroup_id = this->ParseArgFloat(itor->substr(1)); - slidenode._railgroup_id_set = true; - in_rail_node_list = false; - break; - case 'D': - slidenode.max_attachment_distance = this->ParseArgFloat(itor->substr(1)); - in_rail_node_list = false; - break; - case 'C': - switch (itor->at(1)) - { - case 'a': - BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_ALL); + bool in_rail_node_list = true; + + for (auto itor = args.begin() + 1; itor != args.end(); ++itor) + { + char c = toupper(itor->at(0)); + switch (c) + { + case 'S': + slidenode.spring_rate = this->ParseArgFloat(itor->substr(1)); + in_rail_node_list = false; break; - case 'f': - BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_FOREIGN); + case 'B': + slidenode.break_force = this->ParseArgFloat(itor->substr(1)); + slidenode._break_force_set = true; + in_rail_node_list = false; break; - case 's': - BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_SELF); + case 'T': + slidenode.tolerance = this->ParseArgFloat(itor->substr(1)); + in_rail_node_list = false; break; - case 'n': - BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_NONE); + case 'R': + slidenode.attachment_rate = this->ParseArgFloat(itor->substr(1)); + in_rail_node_list = false; + break; + case 'G': + slidenode.railgroup_id = this->ParseArgFloat(itor->substr(1)); + slidenode._railgroup_id_set = true; + in_rail_node_list = false; + break; + case 'D': + slidenode.max_attachment_distance = this->ParseArgFloat(itor->substr(1)); + in_rail_node_list = false; + break; + case 'C': + switch (itor->at(1)) + { + case 'a': BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_ALL); break; + case 'f': BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_FOREIGN); break; + case 's': BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_SELF); break; + case 'n': BITMASK_SET_1(slidenode.constraint_flags, SlideNode::CONSTRAINT_ATTACH_NONE); break; + default: this->AddMessage(Message::TYPE_WARNING, std::string("Ignoring invalid option: ") + itor->at(1)); break; + } + in_rail_node_list = false; break; default: - this->AddMessage(Message::TYPE_WARNING, std::string("Ignoring invalid option: ") + itor->at(1)); + if (in_rail_node_list) slidenode.rail_node_ranges.push_back(_ParseNodeRef(*itor)); break; } - in_rail_node_list = false; - break; - default: - if (in_rail_node_list) - slidenode.rail_node_ranges.push_back( _ParseNodeRef(*itor)); - break; } + + m_current_module->slidenodes.push_back(slidenode); } - - m_current_module->slidenodes.push_back(slidenode); -} -void Parser::ParseShock3() -{ - if (! this->CheckNumArguments(15)) { return; } - - Shock3 shock_3; - shock_3.beam_defaults = m_user_beam_defaults; - shock_3.detacher_group = m_current_detacher_group; - - shock_3.nodes[0] = this->GetArgNodeRef( 0); - shock_3.nodes[1] = this->GetArgNodeRef( 1); - shock_3.spring_in = this->GetArgFloat ( 2); - shock_3.damp_in = this->GetArgFloat ( 3); - shock_3.damp_in_slow = this->GetArgFloat ( 4); - shock_3.split_vel_in = this->GetArgFloat ( 5); - shock_3.damp_in_fast = this->GetArgFloat ( 6); - shock_3.spring_out = this->GetArgFloat ( 7); - shock_3.damp_out = this->GetArgFloat ( 8); - shock_3.damp_out_slow = this->GetArgFloat ( 9); - shock_3.split_vel_out = this->GetArgFloat (10); - shock_3.damp_out_fast = this->GetArgFloat (11); - shock_3.short_bound = this->GetArgFloat (12); - shock_3.long_bound = this->GetArgFloat (13); - shock_3.precompression = this->GetArgFloat (14); - - shock_3.options = 0u; - if (m_num_args > 15) - { - std::string options_str = this->GetArgStr(15); - auto itor = options_str.begin(); - auto endi = options_str.end(); - while (itor != endi) - { - char c = *itor++; // ++ - switch (c) + void Parser::ParseShock3() + { + if (!this->CheckNumArguments(15)) { return; } + + Shock3 shock_3; + shock_3.beam_defaults = m_user_beam_defaults; + shock_3.detacher_group = m_current_detacher_group; + + shock_3.nodes[0] = this->GetArgNodeRef(0); + shock_3.nodes[1] = this->GetArgNodeRef(1); + shock_3.spring_in = this->GetArgFloat(2); + shock_3.damp_in = this->GetArgFloat(3); + shock_3.damp_in_slow = this->GetArgFloat(4); + shock_3.split_vel_in = this->GetArgFloat(5); + shock_3.damp_in_fast = this->GetArgFloat(6); + shock_3.spring_out = this->GetArgFloat(7); + shock_3.damp_out = this->GetArgFloat(8); + shock_3.damp_out_slow = this->GetArgFloat(9); + shock_3.split_vel_out = this->GetArgFloat(10); + shock_3.damp_out_fast = this->GetArgFloat(11); + shock_3.short_bound = this->GetArgFloat(12); + shock_3.long_bound = this->GetArgFloat(13); + shock_3.precompression = this->GetArgFloat(14); + + shock_3.options = 0u; + if (m_num_args > 15) + { + std::string options_str = this->GetArgStr(15); + auto itor = options_str.begin(); + auto endi = options_str.end(); + while (itor != endi) { - case 'n': - case 'v': - break; // Placeholder, does nothing. - case 'i': BITMASK_SET_1(shock_3.options, Shock3::OPTION_i_INVISIBLE); - break; - case 'm': BITMASK_SET_1(shock_3.options, Shock3::OPTION_m_METRIC); - break; - case 'M': BITMASK_SET_1(shock_3.options, Shock3::OPTION_M_ABSOLUTE_METRIC); - break; - default: { - char msg[100] = ""; - snprintf(msg, 100, "Invalid option: '%c', ignoring...", c); - AddMessage(Message::TYPE_WARNING, msg); - } - break; + char c = *itor++; // ++ + switch (c) + { + case 'n': + case 'v': break; // Placeholder, does nothing. + case 'i': BITMASK_SET_1(shock_3.options, Shock3::OPTION_i_INVISIBLE); break; + case 'm': BITMASK_SET_1(shock_3.options, Shock3::OPTION_m_METRIC); break; + case 'M': BITMASK_SET_1(shock_3.options, Shock3::OPTION_M_ABSOLUTE_METRIC); break; + default: + { + char msg[100] = ""; + snprintf(msg, 100, "Invalid option: '%c', ignoring...", c); + AddMessage(Message::TYPE_WARNING, msg); + } + break; + } } } + + m_current_module->shocks_3.push_back(shock_3); } - m_current_module->shocks_3.push_back(shock_3); -} + void Parser::ParseShock2() + { + if (!this->CheckNumArguments(13)) { return; } -void Parser::ParseShock2() -{ - if (! this->CheckNumArguments(13)) { return; } - - Shock2 shock_2; - shock_2.beam_defaults = m_user_beam_defaults; - shock_2.detacher_group = m_current_detacher_group; - - shock_2.nodes[0] = this->GetArgNodeRef( 0); - shock_2.nodes[1] = this->GetArgNodeRef( 1); - shock_2.spring_in = this->GetArgFloat ( 2); - shock_2.damp_in = this->GetArgFloat ( 3); - shock_2.progress_factor_spring_in = this->GetArgFloat ( 4); - shock_2.progress_factor_damp_in = this->GetArgFloat ( 5); - shock_2.spring_out = this->GetArgFloat ( 6); - shock_2.damp_out = this->GetArgFloat ( 7); - shock_2.progress_factor_spring_out = this->GetArgFloat ( 8); - shock_2.progress_factor_damp_out = this->GetArgFloat ( 9); - shock_2.short_bound = this->GetArgFloat (10); - shock_2.long_bound = this->GetArgFloat (11); - shock_2.precompression = this->GetArgFloat (12); - - shock_2.options = 0u; - if (m_num_args > 13) - { - std::string options_str = this->GetArgStr(13); - auto itor = options_str.begin(); - auto endi = options_str.end(); - while (itor != endi) - { - char c = *itor++; // ++ - switch (c) + Shock2 shock_2; + shock_2.beam_defaults = m_user_beam_defaults; + shock_2.detacher_group = m_current_detacher_group; + + shock_2.nodes[0] = this->GetArgNodeRef(0); + shock_2.nodes[1] = this->GetArgNodeRef(1); + shock_2.spring_in = this->GetArgFloat(2); + shock_2.damp_in = this->GetArgFloat(3); + shock_2.progress_factor_spring_in = this->GetArgFloat(4); + shock_2.progress_factor_damp_in = this->GetArgFloat(5); + shock_2.spring_out = this->GetArgFloat(6); + shock_2.damp_out = this->GetArgFloat(7); + shock_2.progress_factor_spring_out = this->GetArgFloat(8); + shock_2.progress_factor_damp_out = this->GetArgFloat(9); + shock_2.short_bound = this->GetArgFloat(10); + shock_2.long_bound = this->GetArgFloat(11); + shock_2.precompression = this->GetArgFloat(12); + + shock_2.options = 0u; + if (m_num_args > 13) + { + std::string options_str = this->GetArgStr(13); + auto itor = options_str.begin(); + auto endi = options_str.end(); + while (itor != endi) { - case 'n': - case 'v': - break; // Placeholder, does nothing. - case 'i': BITMASK_SET_1(shock_2.options, Shock2::OPTION_i_INVISIBLE); - break; - case 'm': BITMASK_SET_1(shock_2.options, Shock2::OPTION_m_METRIC); - break; - case 'M': BITMASK_SET_1(shock_2.options, Shock2::OPTION_M_ABSOLUTE_METRIC); - break; - case 's': BITMASK_SET_1(shock_2.options, Shock2::OPTION_s_SOFT_BUMP_BOUNDS); - break; - default: { - char msg[100] = ""; - snprintf(msg, 100, "Invalid option: '%c', ignoring...", c); - AddMessage(Message::TYPE_WARNING, msg); - } - break; + char c = *itor++; // ++ + switch (c) + { + case 'n': + case 'v': break; // Placeholder, does nothing. + case 'i': BITMASK_SET_1(shock_2.options, Shock2::OPTION_i_INVISIBLE); break; + case 'm': BITMASK_SET_1(shock_2.options, Shock2::OPTION_m_METRIC); break; + case 'M': BITMASK_SET_1(shock_2.options, Shock2::OPTION_M_ABSOLUTE_METRIC); break; + case 's': BITMASK_SET_1(shock_2.options, Shock2::OPTION_s_SOFT_BUMP_BOUNDS); break; + default: + { + char msg[100] = ""; + snprintf(msg, 100, "Invalid option: '%c', ignoring...", c); + AddMessage(Message::TYPE_WARNING, msg); + } + break; + } } } - } - m_current_module->shocks_2.push_back(shock_2); -} + m_current_module->shocks_2.push_back(shock_2); + } -void Parser::ParseShock() -{ - if (! this->CheckNumArguments(7)) { return; } + void Parser::ParseShock() + { + if (!this->CheckNumArguments(7)) { return; } - Shock shock; - shock.beam_defaults = m_user_beam_defaults; - shock.detacher_group = m_current_detacher_group; + Shock shock; + shock.beam_defaults = m_user_beam_defaults; + shock.detacher_group = m_current_detacher_group; - shock.nodes[0] = this->GetArgNodeRef(0); - shock.nodes[1] = this->GetArgNodeRef(1); - shock.spring_rate = this->GetArgFloat (2); - shock.damping = this->GetArgFloat (3); - shock.short_bound = this->GetArgFloat (4); - shock.long_bound = this->GetArgFloat (5); - shock.precompression = this->GetArgFloat (6); + shock.nodes[0] = this->GetArgNodeRef(0); + shock.nodes[1] = this->GetArgNodeRef(1); + shock.spring_rate = this->GetArgFloat(2); + shock.damping = this->GetArgFloat(3); + shock.short_bound = this->GetArgFloat(4); + shock.long_bound = this->GetArgFloat(5); + shock.precompression = this->GetArgFloat(6); - shock.options = 0u; - if (m_num_args > 7) - { - std::string options_str = this->GetArgStr(7); - auto itor = options_str.begin(); - auto endi = options_str.end(); - while (itor != endi) + shock.options = 0u; + if (m_num_args > 7) { - char c = *itor++; - switch (c) + std::string options_str = this->GetArgStr(7); + auto itor = options_str.begin(); + auto endi = options_str.end(); + while (itor != endi) { + char c = *itor++; + switch (c) + { case 'n': - case 'v': - break; // Placeholder, does nothing. - case 'i': BITMASK_SET_1(shock.options, Shock::OPTION_i_INVISIBLE); - break; - case 'm': BITMASK_SET_1(shock.options, Shock::OPTION_m_METRIC); - break; + case 'v': break; // Placeholder, does nothing. + case 'i': BITMASK_SET_1(shock.options, Shock::OPTION_i_INVISIBLE); break; + case 'm': BITMASK_SET_1(shock.options, Shock::OPTION_m_METRIC); break; case 'r': - case 'R': BITMASK_SET_1(shock.options, Shock::OPTION_R_ACTIVE_RIGHT); - break; + case 'R': BITMASK_SET_1(shock.options, Shock::OPTION_R_ACTIVE_RIGHT); break; case 'l': - case 'L': BITMASK_SET_1(shock.options, Shock::OPTION_L_ACTIVE_LEFT); - break; - default: { + case 'L': BITMASK_SET_1(shock.options, Shock::OPTION_L_ACTIVE_LEFT); break; + default: + { char msg[100] = ""; snprintf(msg, 100, "Invalid option: '%c', ignoring...", c); AddMessage(Message::TYPE_WARNING, msg); } break; + } } } + m_current_module->shocks.push_back(shock); } - m_current_module->shocks.push_back(shock); -} -void Parser::_CheckInvalidTrailingText(Ogre::String const & line, std::smatch const & results, unsigned int index) -{ - if (results[index].matched) // Invalid trailing text + void Parser::_CheckInvalidTrailingText(Ogre::String const &line, std::smatch const &results, unsigned int index) { - std::stringstream msg; - msg << "Invalid text after parameters: '" << results[index] << "'. Please remove. Ignoring..."; - AddMessage(line, Message::TYPE_WARNING, msg.str()); + if (results[index].matched) // Invalid trailing text + { + std::stringstream msg; + msg << "Invalid text after parameters: '" << results[index] << "'. Please remove. Ignoring..."; + AddMessage(line, Message::TYPE_WARNING, msg.str()); + } } -} -Node::Ref Parser::_ParseNodeRef(std::string const & node_id_str) -{ - if (m_sequential_importer.IsEnabled()) + Node::Ref Parser::_ParseNodeRef(std::string const &node_id_str) { - // Import of legacy fileformatversion - int node_id_num = STR_PARSE_INT(node_id_str); - if (node_id_num < 0) + if (m_sequential_importer.IsEnabled()) { - std::stringstream msg; - msg << "Encountered node with illegal negative number: '" << node_id_num - << "', parsing as positive '" << node_id_num * -1 << "' for backwards compatibility. Please fix as soon as possible."; - AddMessage(node_id_str, Message::TYPE_WARNING, msg.str()); - node_id_num *= -1; + // Import of legacy fileformatversion + int node_id_num = STR_PARSE_INT(node_id_str); + if (node_id_num < 0) + { + std::stringstream msg; + msg << "Encountered node with illegal negative number: '" << node_id_num << "', parsing as positive '" + << node_id_num * -1 << "' for backwards compatibility. Please fix as soon as possible."; + AddMessage(node_id_str, Message::TYPE_WARNING, msg.str()); + node_id_num *= -1; + } + // Since fileformatversion is not known from the beginning of parsing, 2 states must be kept + // at the same time: IMPORT_STATE and REGULAR_STATE. The outer logic must make the right pick. + unsigned int flags = Node::Ref::IMPORT_STATE_IS_VALID | // Import state + Node::Ref::REGULAR_STATE_IS_VALID | + Node::Ref::REGULAR_STATE_IS_NAMED; // Regular state (fileformatversion >= 450) + if (m_any_named_node_defined) { flags |= Node::Ref::IMPORT_STATE_MUST_CHECK_NAMED_FIRST; } + return Node::Ref(node_id_str, node_id_num, flags, m_current_line_number); } - // Since fileformatversion is not known from the beginning of parsing, 2 states must be kept - // at the same time: IMPORT_STATE and REGULAR_STATE. The outer logic must make the right pick. - unsigned int flags = Node::Ref::IMPORT_STATE_IS_VALID | // Import state - Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NAMED; // Regular state (fileformatversion >= 450) - if (m_any_named_node_defined) + else { - flags |= Node::Ref::IMPORT_STATE_MUST_CHECK_NAMED_FIRST; + // fileformatversion >= 450, use named-only nodes + return Node::Ref(node_id_str, 0, Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NAMED, + m_current_line_number); } - return Node::Ref(node_id_str, node_id_num, flags, m_current_line_number); } - else + + void Parser::ParseDirectiveSetDefaultMinimass() { - // fileformatversion >= 450, use named-only nodes - return Node::Ref(node_id_str, 0, Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NAMED, m_current_line_number); + if (!this->CheckNumArguments(2)) { return; } // Directive name + parameter + + m_user_minimass = std::shared_ptr(new MinimassPreset(this->GetArgFloat(1))); } -} -void Parser::ParseDirectiveSetDefaultMinimass() -{ - if (! this->CheckNumArguments(2)) { return; } // Directive name + parameter + void Parser::ParseDirectiveSetInertiaDefaults() + { + if (!this->CheckNumArguments(2)) { return; } - m_user_minimass = std::shared_ptr(new MinimassPreset(this->GetArgFloat(1))); -} + float start_delay = this->GetArgFloat(1); + float stop_delay = 0; + if (m_num_args > 2) { stop_delay = this->GetArgFloat(2); } -void Parser::ParseDirectiveSetInertiaDefaults() -{ - if (! this->CheckNumArguments(2)) { return; } + if (start_delay < 0 || stop_delay < 0) + { + m_user_default_inertia = m_ror_default_inertia; // Reset and return + return; + } - float start_delay = this->GetArgFloat(1); - float stop_delay = 0; - if (m_num_args > 2) { stop_delay = this->GetArgFloat(2); } + // Create + Inertia *i = new Inertia(*m_user_default_inertia.get()); + i->start_delay_factor = start_delay; + i->stop_delay_factor = stop_delay; - if (start_delay < 0 || stop_delay < 0) - { - m_user_default_inertia = m_ror_default_inertia; // Reset and return - return; + if (m_num_args > 3) { i->start_function = this->GetArgStr(3); } + if (m_num_args > 4) { i->stop_function = this->GetArgStr(4); } + + m_user_default_inertia = std::shared_ptr(i); } - // Create - Inertia* i = new Inertia(*m_user_default_inertia.get()); - i->start_delay_factor = start_delay; - i->stop_delay_factor = stop_delay; - - if (m_num_args > 3) { i->start_function = this->GetArgStr(3); } - if (m_num_args > 4) { i->stop_function = this->GetArgStr(4); } - - m_user_default_inertia = std::shared_ptr(i); -} + void Parser::ParseScrewprops() + { + if (!this->CheckNumArguments(4)) { return; } -void Parser::ParseScrewprops() -{ - if (! this->CheckNumArguments(4)) { return; } - - Screwprop screwprop; + Screwprop screwprop; - screwprop.prop_node = this->GetArgNodeRef(0); - screwprop.back_node = this->GetArgNodeRef(1); - screwprop.top_node = this->GetArgNodeRef(2); - screwprop.power = this->GetArgFloat (3); + screwprop.prop_node = this->GetArgNodeRef(0); + screwprop.back_node = this->GetArgNodeRef(1); + screwprop.top_node = this->GetArgNodeRef(2); + screwprop.power = this->GetArgFloat(3); - m_current_module->screwprops.push_back(screwprop); -} + m_current_module->screwprops.push_back(screwprop); + } -void Parser::ParseRotatorsUnified() -{ - if (! this->CheckNumArguments(13)) { return; } - - Rotator2 rotator; - rotator.inertia_defaults = m_user_default_inertia; - - rotator.axis_nodes[0] = this->GetArgNodeRef( 0); - rotator.axis_nodes[1] = this->GetArgNodeRef( 1); - rotator.base_plate_nodes[0] = this->GetArgNodeRef( 2); - rotator.base_plate_nodes[1] = this->GetArgNodeRef( 3); - rotator.base_plate_nodes[2] = this->GetArgNodeRef( 4); - rotator.base_plate_nodes[3] = this->GetArgNodeRef( 5); - rotator.rotating_plate_nodes[0] = this->GetArgNodeRef( 6); - rotator.rotating_plate_nodes[1] = this->GetArgNodeRef( 7); - rotator.rotating_plate_nodes[2] = this->GetArgNodeRef( 8); - rotator.rotating_plate_nodes[3] = this->GetArgNodeRef( 9); - rotator.rate = this->GetArgFloat (10); - rotator.spin_left_key = this->GetArgInt (11); - rotator.spin_right_key = this->GetArgInt (12); - - int offset = 0; - - if (m_current_section == File::SECTION_ROTATORS_2) - { - if (! this->CheckNumArguments(16)) { return; } - if (m_num_args > 13) { rotator.rotating_force = this->GetArgFloat(13); } - if (m_num_args > 14) { rotator.tolerance = this->GetArgFloat(14); } - if (m_num_args > 15) { rotator.description = this->GetArgStr (15); } - - offset = 3; - } - - this->ParseOptionalInertia(rotator.inertia, 13 + offset); - if (m_num_args > 17 + offset) { rotator.engine_coupling = this->GetArgFloat(17 + offset); } - if (m_num_args > 18 + offset) { rotator.needs_engine = this->GetArgBool (18 + offset); } + void Parser::ParseRotatorsUnified() + { + if (!this->CheckNumArguments(13)) { return; } + + Rotator2 rotator; + rotator.inertia_defaults = m_user_default_inertia; + + rotator.axis_nodes[0] = this->GetArgNodeRef(0); + rotator.axis_nodes[1] = this->GetArgNodeRef(1); + rotator.base_plate_nodes[0] = this->GetArgNodeRef(2); + rotator.base_plate_nodes[1] = this->GetArgNodeRef(3); + rotator.base_plate_nodes[2] = this->GetArgNodeRef(4); + rotator.base_plate_nodes[3] = this->GetArgNodeRef(5); + rotator.rotating_plate_nodes[0] = this->GetArgNodeRef(6); + rotator.rotating_plate_nodes[1] = this->GetArgNodeRef(7); + rotator.rotating_plate_nodes[2] = this->GetArgNodeRef(8); + rotator.rotating_plate_nodes[3] = this->GetArgNodeRef(9); + rotator.rate = this->GetArgFloat(10); + rotator.spin_left_key = this->GetArgInt(11); + rotator.spin_right_key = this->GetArgInt(12); + + int offset = 0; if (m_current_section == File::SECTION_ROTATORS_2) { - m_current_module->rotators_2.push_back(rotator); + if (!this->CheckNumArguments(16)) { return; } + if (m_num_args > 13) { rotator.rotating_force = this->GetArgFloat(13); } + if (m_num_args > 14) { rotator.tolerance = this->GetArgFloat(14); } + if (m_num_args > 15) { rotator.description = this->GetArgStr(15); } + + offset = 3; } + + this->ParseOptionalInertia(rotator.inertia, 13 + offset); + if (m_num_args > 17 + offset) { rotator.engine_coupling = this->GetArgFloat(17 + offset); } + if (m_num_args > 18 + offset) { rotator.needs_engine = this->GetArgBool(18 + offset); } + + if (m_current_section == File::SECTION_ROTATORS_2) { m_current_module->rotators_2.push_back(rotator); } else { m_current_module->rotators.push_back(rotator); } -} - -void Parser::ParseFileinfo() -{ - if (! this->CheckNumArguments(2)) { return; } + } - if (m_current_module != m_root_module) + void Parser::ParseFileinfo() { - this->AddMessage(Message::TYPE_WARNING, "Inline-section 'fileinfo' has global effect and should not appear in a module"); - } + if (!this->CheckNumArguments(2)) { return; } + + if (m_current_module != m_root_module) + { + this->AddMessage(Message::TYPE_WARNING, + "Inline-section 'fileinfo' has global effect and should not appear in a module"); + } - Fileinfo fileinfo; + Fileinfo fileinfo; - fileinfo.unique_id = this->GetArgStr(1); - Ogre::StringUtil::trim(fileinfo.unique_id); + fileinfo.unique_id = this->GetArgStr(1); + Ogre::StringUtil::trim(fileinfo.unique_id); - if (m_num_args > 2) { fileinfo.category_id = this->GetArgInt(2); } - if (m_num_args > 3) { fileinfo.file_version = this->GetArgInt(3); } + if (m_num_args > 2) { fileinfo.category_id = this->GetArgInt(2); } + if (m_num_args > 3) { fileinfo.file_version = this->GetArgInt(3); } - m_definition->file_info = std::shared_ptr( new Fileinfo(fileinfo) ); + m_definition->file_info = std::shared_ptr(new Fileinfo(fileinfo)); - this->ChangeSection(File::SECTION_NONE); -} + this->ChangeSection(File::SECTION_NONE); + } -void Parser::ParseRopes() -{ - if (! this->CheckNumArguments(2)) { return; } - - Rope rope; - rope.beam_defaults = m_user_beam_defaults; - rope.detacher_group = m_current_detacher_group; - rope.root_node = this->GetArgNodeRef(0); - rope.end_node = this->GetArgNodeRef(1); - - if (m_num_args > 2) { rope.invisible = (this->GetArgChar(2) == 'i'); } - - m_current_module->ropes.push_back(rope); -} - -void Parser::ParseRopables() -{ - if (! this->CheckNumArguments(1)) { return; } + void Parser::ParseRopes() + { + if (!this->CheckNumArguments(2)) { return; } - Ropable ropable; - ropable.node = this->GetArgNodeRef(0); - - if (m_num_args > 1) { ropable.group = this->GetArgInt(1); } - if (m_num_args > 2) { ropable.has_multilock = (this->GetArgInt(2) == 1); } + Rope rope; + rope.beam_defaults = m_user_beam_defaults; + rope.detacher_group = m_current_detacher_group; + rope.root_node = this->GetArgNodeRef(0); + rope.end_node = this->GetArgNodeRef(1); - m_current_module->ropables.push_back(ropable); -} + if (m_num_args > 2) { rope.invisible = (this->GetArgChar(2) == 'i'); } -void Parser::ParseRailGroups() -{ - Ogre::StringVector args = Ogre::StringUtil::split(m_current_line, ","); - if (args.size() < 3u) - { - this->AddMessage(Message::TYPE_ERROR, "Not enough parameters"); - return; + m_current_module->ropes.push_back(rope); } - RailGroup railgroup; - railgroup.id = this->ParseArgInt(args[0].c_str()); - - for (auto itor = args.begin() + 1; itor != args.end(); itor++) + void Parser::ParseRopables() { - railgroup.node_list.push_back( this->_ParseNodeRef(*itor)); - } + if (!this->CheckNumArguments(1)) { return; } - m_current_module->railgroups.push_back(railgroup); -} + Ropable ropable; + ropable.node = this->GetArgNodeRef(0); -void Parser::ParseProps() -{ - if (! this->CheckNumArguments(10)) { return; } - - Prop prop; - prop.reference_node = this->GetArgNodeRef(0); - prop.x_axis_node = this->GetArgNodeRef(1); - prop.y_axis_node = this->GetArgNodeRef(2); - prop.offset.x = this->GetArgFloat (3); - prop.offset.y = this->GetArgFloat (4); - prop.offset.z = this->GetArgFloat (5); - prop.rotation.x = this->GetArgFloat (6); - prop.rotation.y = this->GetArgFloat (7); - prop.rotation.z = this->GetArgFloat (8); - prop.mesh_name = this->GetArgStr (9); - - bool is_dash = false; - if (prop.mesh_name.find("leftmirror" ) != std::string::npos) { prop.special = Prop::SPECIAL_MIRROR_LEFT; } - else if (prop.mesh_name.find("rightmirror" ) != std::string::npos) { prop.special = Prop::SPECIAL_MIRROR_RIGHT; } - else if (prop.mesh_name.find("dashboard-rh") != std::string::npos) { prop.special = Prop::SPECIAL_DASHBOARD_RIGHT; is_dash = true; } - else if (prop.mesh_name.find("dashboard" ) != std::string::npos) { prop.special = Prop::SPECIAL_DASHBOARD_LEFT; is_dash = true; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "spinprop", false) ) { prop.special = Prop::SPECIAL_AERO_PROP_SPIN; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "pale", false) ) { prop.special = Prop::SPECIAL_AERO_PROP_BLADE; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "seat", false) ) { prop.special = Prop::SPECIAL_DRIVER_SEAT; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "seat2", false) ) { prop.special = Prop::SPECIAL_DRIVER_SEAT_2; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "beacon", false) ) { prop.special = Prop::SPECIAL_BEACON; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "redbeacon", false)) { prop.special = Prop::SPECIAL_REDBEACON; } - else if (Ogre::StringUtil::startsWith(prop.mesh_name, "lightb", false) ) { prop.special = Prop::SPECIAL_LIGHTBAR; } // Previously: 'strncmp("lightbar", meshname, 6)' - - if ((prop.special == Prop::SPECIAL_BEACON) && (m_num_args >= 14)) - { - prop.special_prop_beacon.flare_material_name = this->GetArgStr(10); - Ogre::StringUtil::trim(prop.special_prop_beacon.flare_material_name); - - prop.special_prop_beacon.color = Ogre::ColourValue( - this->GetArgFloat(11), this->GetArgFloat(12), this->GetArgFloat(13)); - } - else if (is_dash) - { - if (m_num_args > 10) prop.special_prop_dashboard.mesh_name = this->GetArgStr(10); - if (m_num_args > 13) - { - prop.special_prop_dashboard.offset = Ogre::Vector3(this->GetArgFloat(11), this->GetArgFloat(12), this->GetArgFloat(13)); - prop.special_prop_dashboard._offset_is_set = true; - } - if (m_num_args > 14) prop.special_prop_dashboard.rotation_angle = this->GetArgFloat(14); + if (m_num_args > 1) { ropable.group = this->GetArgInt(1); } + if (m_num_args > 2) { ropable.has_multilock = (this->GetArgInt(2) == 1); } + + m_current_module->ropables.push_back(ropable); } - m_current_module->props.push_back(prop); -} + void Parser::ParseRailGroups() + { + Ogre::StringVector args = Ogre::StringUtil::split(m_current_line, ","); + if (args.size() < 3u) + { + this->AddMessage(Message::TYPE_ERROR, "Not enough parameters"); + return; + } -void Parser::ParsePistonprops() -{ - if (!this->CheckNumArguments(10)) { return; } + RailGroup railgroup; + railgroup.id = this->ParseArgInt(args[0].c_str()); - Pistonprop pistonprop; - pistonprop.reference_node = this->GetArgNodeRef (0); - pistonprop.axis_node = this->GetArgNodeRef (1); - pistonprop.blade_tip_nodes[0] = this->GetArgNodeRef (2); - pistonprop.blade_tip_nodes[1] = this->GetArgNodeRef (3); - pistonprop.blade_tip_nodes[2] = this->GetArgNullableNode(4); - pistonprop.blade_tip_nodes[3] = this->GetArgNullableNode(5); - pistonprop.couple_node = this->GetArgNullableNode(6); - pistonprop.turbine_power_kW = this->GetArgFloat (7); - pistonprop.pitch = this->GetArgFloat (8); - pistonprop.airfoil = this->GetArgStr (9); + for (auto itor = args.begin() + 1; itor != args.end(); itor++) + { + railgroup.node_list.push_back(this->_ParseNodeRef(*itor)); + } - m_current_module->pistonprops.push_back(pistonprop); + m_current_module->railgroups.push_back(railgroup); + } -} + void Parser::ParseProps() + { + if (!this->CheckNumArguments(10)) { return; } -void Parser::ParseParticles() -{ - if (!this->CheckNumArguments(3)) { return; } + Prop prop; + prop.reference_node = this->GetArgNodeRef(0); + prop.x_axis_node = this->GetArgNodeRef(1); + prop.y_axis_node = this->GetArgNodeRef(2); + prop.offset.x = this->GetArgFloat(3); + prop.offset.y = this->GetArgFloat(4); + prop.offset.z = this->GetArgFloat(5); + prop.rotation.x = this->GetArgFloat(6); + prop.rotation.y = this->GetArgFloat(7); + prop.rotation.z = this->GetArgFloat(8); + prop.mesh_name = this->GetArgStr(9); - Particle particle; - particle.emitter_node = this->GetArgNodeRef(0); - particle.reference_node = this->GetArgNodeRef(1); - particle.particle_system_name = this->GetArgStr (2); + bool is_dash = false; + if (prop.mesh_name.find("leftmirror") != std::string::npos) { prop.special = Prop::SPECIAL_MIRROR_LEFT; } + else if (prop.mesh_name.find("rightmirror") != std::string::npos) + { + prop.special = Prop::SPECIAL_MIRROR_RIGHT; + } + else if (prop.mesh_name.find("dashboard-rh") != std::string::npos) + { + prop.special = Prop::SPECIAL_DASHBOARD_RIGHT; + is_dash = true; + } + else if (prop.mesh_name.find("dashboard") != std::string::npos) + { + prop.special = Prop::SPECIAL_DASHBOARD_LEFT; + is_dash = true; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "spinprop", false)) + { + prop.special = Prop::SPECIAL_AERO_PROP_SPIN; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "pale", false)) + { + prop.special = Prop::SPECIAL_AERO_PROP_BLADE; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "seat", false)) + { + prop.special = Prop::SPECIAL_DRIVER_SEAT; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "seat2", false)) + { + prop.special = Prop::SPECIAL_DRIVER_SEAT_2; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "beacon", false)) + { + prop.special = Prop::SPECIAL_BEACON; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "redbeacon", false)) + { + prop.special = Prop::SPECIAL_REDBEACON; + } + else if (Ogre::StringUtil::startsWith(prop.mesh_name, "lightb", false)) + { + prop.special = Prop::SPECIAL_LIGHTBAR; + } // Previously: 'strncmp("lightbar", meshname, 6)' - m_current_module->particles.push_back(particle); -} + if ((prop.special == Prop::SPECIAL_BEACON) && (m_num_args >= 14)) + { + prop.special_prop_beacon.flare_material_name = this->GetArgStr(10); + Ogre::StringUtil::trim(prop.special_prop_beacon.flare_material_name); -// Static -void Parser::_TrimTrailingComments(std::string const & line_in, std::string & line_out) -{ - // Trim trailing comment - // We need to handle a case of lines as [keyword 1, 2, 3 ;;///// Comment!] - int comment_start = static_cast(line_in.find_first_of(";")); - if (comment_start != Ogre::String::npos) - { - line_out = line_in.substr(0, comment_start); - return; - } - // The [//Comment] is harder - the '/' character may also be present in DESCRIPTION arguments! - comment_start = static_cast(line_in.find_last_of("/")); - if (comment_start != Ogre::String::npos) - { - while (comment_start >= 0) + prop.special_prop_beacon.color = + Ogre::ColourValue(this->GetArgFloat(11), this->GetArgFloat(12), this->GetArgFloat(13)); + } + else if (is_dash) { - char c = line_in[comment_start - 1]; - if (c != '/' && c != ' ' && c != '\t') + if (m_num_args > 10) prop.special_prop_dashboard.mesh_name = this->GetArgStr(10); + if (m_num_args > 13) { - break; // Start of comment found + prop.special_prop_dashboard.offset = + Ogre::Vector3(this->GetArgFloat(11), this->GetArgFloat(12), this->GetArgFloat(13)); + prop.special_prop_dashboard._offset_is_set = true; } - --comment_start; + if (m_num_args > 14) prop.special_prop_dashboard.rotation_angle = this->GetArgFloat(14); } - line_out = line_in.substr(0, comment_start); - return; + + m_current_module->props.push_back(prop); } - // No comment found - line_out = line_in; -} -void Parser::_PrintNodeDataForVerification(Ogre::String& line, Ogre::StringVector& args, int num_args, Node& node) -{ - std::stringstream msg; - msg << "Data print for verification:"; - msg << "\n\tPosition X: " << node.position.x << " (input text: \"" << args[1] << "\""; - msg << "\n\tPosition Y: " << node.position.y << " (input text: \"" << args[2] << "\""; - msg << "\n\tPosition Z: " << node.position.z << " (input text: \"" << args[3] << "\""; - if (num_args > 4) // Has options? + void Parser::ParsePistonprops() { - msg << "\n\tOptions: "; - if (BITMASK_IS_1(node.options, Node::OPTION_l_LOAD_WEIGHT)) { msg << "l_LOAD_WEIGHT "; } - if (BITMASK_IS_1(node.options, Node::OPTION_n_MOUSE_GRAB)) { msg << "n_MOUSE_GRAB "; } - if (BITMASK_IS_1(node.options, Node::OPTION_m_NO_MOUSE_GRAB)) { msg << "m_NO_MOUSE_GRAB "; } - if (BITMASK_IS_1(node.options, Node::OPTION_f_NO_SPARKS)) { msg << "f_NO_SPARKS "; } - if (BITMASK_IS_1(node.options, Node::OPTION_x_EXHAUST_POINT)) { msg << "x_EXHAUST_POINT "; } - if (BITMASK_IS_1(node.options, Node::OPTION_y_EXHAUST_DIRECTION)) { msg << "y_EXHAUST_DIRECTION "; } - if (BITMASK_IS_1(node.options, Node::OPTION_c_NO_GROUND_CONTACT)) { msg << "c_NO_GROUND_CONTACT "; } - if (BITMASK_IS_1(node.options, Node::OPTION_h_HOOK_POINT)) { msg << "h_HOOK_POINT "; } - if (BITMASK_IS_1(node.options, Node::OPTION_e_TERRAIN_EDIT_POINT)) { msg << "e_TERRAIN_EDIT_POINT "; } - if (BITMASK_IS_1(node.options, Node::OPTION_b_EXTRA_BUOYANCY)) { msg << "b_EXTRA_BUOYANCY "; } - if (BITMASK_IS_1(node.options, Node::OPTION_p_NO_PARTICLES)) { msg << "p_NO_PARTICLES "; } - if (BITMASK_IS_1(node.options, Node::OPTION_L_LOG)) { msg << "L_LOG "; } - msg << "(input text:\"" << args[4] << "\""; + if (!this->CheckNumArguments(10)) { return; } + + Pistonprop pistonprop; + pistonprop.reference_node = this->GetArgNodeRef(0); + pistonprop.axis_node = this->GetArgNodeRef(1); + pistonprop.blade_tip_nodes[0] = this->GetArgNodeRef(2); + pistonprop.blade_tip_nodes[1] = this->GetArgNodeRef(3); + pistonprop.blade_tip_nodes[2] = this->GetArgNullableNode(4); + pistonprop.blade_tip_nodes[3] = this->GetArgNullableNode(5); + pistonprop.couple_node = this->GetArgNullableNode(6); + pistonprop.turbine_power_kW = this->GetArgFloat(7); + pistonprop.pitch = this->GetArgFloat(8); + pistonprop.airfoil = this->GetArgStr(9); + + m_current_module->pistonprops.push_back(pistonprop); } - if (num_args > 5) // Has load weight override? + + void Parser::ParseParticles() { - msg << "\n\tLoad weight overide: " << node.load_weight_override << " (input text: \"" << args[5] << "\""; + if (!this->CheckNumArguments(3)) { return; } + + Particle particle; + particle.emitter_node = this->GetArgNodeRef(0); + particle.reference_node = this->GetArgNodeRef(1); + particle.particle_system_name = this->GetArgStr(2); + + m_current_module->particles.push_back(particle); } - if (num_args > 6) // Is there invalid trailing text? + + // Static + void Parser::_TrimTrailingComments(std::string const &line_in, std::string &line_out) { - msg << "\n\t~Invalid trailing text: "; - for (int i = 6; i < num_args; ++i) + // Trim trailing comment + // We need to handle a case of lines as [keyword 1, 2, 3 ;;///// Comment!] + int comment_start = static_cast(line_in.find_first_of(";")); + if (comment_start != Ogre::String::npos) { - msg << args[i]; + line_out = line_in.substr(0, comment_start); + return; + } + // The [//Comment] is harder - the '/' character may also be present in DESCRIPTION arguments! + comment_start = static_cast(line_in.find_last_of("/")); + if (comment_start != Ogre::String::npos) + { + while (comment_start >= 0) + { + char c = line_in[comment_start - 1]; + if (c != '/' && c != ' ' && c != '\t') + { + break; // Start of comment found + } + --comment_start; + } + line_out = line_in.substr(0, comment_start); + return; } + // No comment found + line_out = line_in; } - this->AddMessage(line, Message::TYPE_WARNING, msg.str()); -} -void Parser::ParseNodesUnified() -{ - if (! this->CheckNumArguments(4)) { return; } - - Node node; - node.node_defaults = m_user_node_defaults; - node.beam_defaults = m_user_beam_defaults; - node.node_minimass = m_user_minimass; - node.detacher_group = m_current_detacher_group; - - if (m_current_section == File::SECTION_NODES_2) + void Parser::_PrintNodeDataForVerification(Ogre::String &line, Ogre::StringVector &args, int num_args, Node &node) { - std::string node_name = this->GetArgStr(0); - node.id.SetStr(node_name); - if (m_sequential_importer.IsEnabled()) + std::stringstream msg; + msg << "Data print for verification:"; + msg << "\n\tPosition X: " << node.position.x << " (input text: \"" << args[1] << "\""; + msg << "\n\tPosition Y: " << node.position.y << " (input text: \"" << args[2] << "\""; + msg << "\n\tPosition Z: " << node.position.z << " (input text: \"" << args[3] << "\""; + if (num_args > 4) // Has options? { - m_sequential_importer.AddNamedNode(node_name); + msg << "\n\tOptions: "; + if (BITMASK_IS_1(node.options, Node::OPTION_l_LOAD_WEIGHT)) { msg << "l_LOAD_WEIGHT "; } + if (BITMASK_IS_1(node.options, Node::OPTION_n_MOUSE_GRAB)) { msg << "n_MOUSE_GRAB "; } + if (BITMASK_IS_1(node.options, Node::OPTION_m_NO_MOUSE_GRAB)) { msg << "m_NO_MOUSE_GRAB "; } + if (BITMASK_IS_1(node.options, Node::OPTION_f_NO_SPARKS)) { msg << "f_NO_SPARKS "; } + if (BITMASK_IS_1(node.options, Node::OPTION_x_EXHAUST_POINT)) { msg << "x_EXHAUST_POINT "; } + if (BITMASK_IS_1(node.options, Node::OPTION_y_EXHAUST_DIRECTION)) { msg << "y_EXHAUST_DIRECTION "; } + if (BITMASK_IS_1(node.options, Node::OPTION_c_NO_GROUND_CONTACT)) { msg << "c_NO_GROUND_CONTACT "; } + if (BITMASK_IS_1(node.options, Node::OPTION_h_HOOK_POINT)) { msg << "h_HOOK_POINT "; } + if (BITMASK_IS_1(node.options, Node::OPTION_e_TERRAIN_EDIT_POINT)) { msg << "e_TERRAIN_EDIT_POINT "; } + if (BITMASK_IS_1(node.options, Node::OPTION_b_EXTRA_BUOYANCY)) { msg << "b_EXTRA_BUOYANCY "; } + if (BITMASK_IS_1(node.options, Node::OPTION_p_NO_PARTICLES)) { msg << "p_NO_PARTICLES "; } + if (BITMASK_IS_1(node.options, Node::OPTION_L_LOG)) { msg << "L_LOG "; } + msg << "(input text:\"" << args[4] << "\""; } - m_any_named_node_defined = true; // For import logic - } - else - { - const unsigned int node_num = this->GetArgUint(0); - node.id.SetNum(node_num); - if (m_sequential_importer.IsEnabled()) + if (num_args > 5) // Has load weight override? + { msg << "\n\tLoad weight overide: " << node.load_weight_override << " (input text: \"" << args[5] << "\""; } + if (num_args > 6) // Is there invalid trailing text? { - m_sequential_importer.AddNumberedNode(node_num); + msg << "\n\t~Invalid trailing text: "; + for (int i = 6; i < num_args; ++i) + { + msg << args[i]; + } } + this->AddMessage(line, Message::TYPE_WARNING, msg.str()); } - node.position.x = this->GetArgFloat(1); - node.position.y = this->GetArgFloat(2); - node.position.z = this->GetArgFloat(3); - if (m_num_args > 4) - { - this->_ParseNodeOptions(node.options, this->GetArgStr(4)); - } - if (m_num_args > 5) + void Parser::ParseNodesUnified() { - if (node.options & Node::OPTION_l_LOAD_WEIGHT) + if (!this->CheckNumArguments(4)) { return; } + + Node node; + node.node_defaults = m_user_node_defaults; + node.beam_defaults = m_user_beam_defaults; + node.node_minimass = m_user_minimass; + node.detacher_group = m_current_detacher_group; + + if (m_current_section == File::SECTION_NODES_2) { - node.load_weight_override = this->GetArgFloat(5); - node._has_load_weight_override = true; + std::string node_name = this->GetArgStr(0); + node.id.SetStr(node_name); + if (m_sequential_importer.IsEnabled()) { m_sequential_importer.AddNamedNode(node_name); } + m_any_named_node_defined = true; // For import logic } else { - this->AddMessage(Message::TYPE_WARNING, - "Node has load-weight-override value specified, but option 'l' is not present. Ignoring value..."); + const unsigned int node_num = this->GetArgUint(0); + node.id.SetNum(node_num); + if (m_sequential_importer.IsEnabled()) { m_sequential_importer.AddNumberedNode(node_num); } + } + + node.position.x = this->GetArgFloat(1); + node.position.y = this->GetArgFloat(2); + node.position.z = this->GetArgFloat(3); + if (m_num_args > 4) { this->_ParseNodeOptions(node.options, this->GetArgStr(4)); } + if (m_num_args > 5) + { + if (node.options & Node::OPTION_l_LOAD_WEIGHT) + { + node.load_weight_override = this->GetArgFloat(5); + node._has_load_weight_override = true; + } + else + { + this->AddMessage( + Message::TYPE_WARNING, + "Node has load-weight-override value specified, but option 'l' is not present. Ignoring value..."); + } } + + m_current_module->nodes.push_back(node); } - m_current_module->nodes.push_back(node); -} + void Parser::ParseNodeCollision() + { + if (!this->CheckNumArguments(2)) { return; } + + NodeCollision node_collision; + node_collision.node = this->GetArgNodeRef(0); + node_collision.radius = this->GetArgFloat(1); -void Parser::ParseNodeCollision() -{ - if (! this->CheckNumArguments(2)) { return; } - - NodeCollision node_collision; - node_collision.node = this->GetArgNodeRef(0); - node_collision.radius = this->GetArgFloat (1); - - m_current_module->node_collisions.push_back(node_collision); -} - -void Parser::ParseMinimass() -{ - const float minimass = this->GetArgFloat(0); - if (m_num_args > 1) + m_current_module->node_collisions.push_back(node_collision); + } + + void Parser::ParseMinimass() { - const std::string options_str = this->GetArgStr(1); - for (char c: options_str) + const float minimass = this->GetArgFloat(0); + if (m_num_args > 1) { - switch (c) + const std::string options_str = this->GetArgStr(1); + for (char c : options_str) { - case '\0': // Terminator NULL character - case (MinimassPreset::OPTION_n_FILLER): - break; + switch (c) + { + case '\0': // Terminator NULL character + case (MinimassPreset::OPTION_n_FILLER): break; - case (MinimassPreset::OPTION_l_SKIP_LOADED): - m_definition->minimass_skip_loaded_nodes = true; - break; + case (MinimassPreset::OPTION_l_SKIP_LOADED): m_definition->minimass_skip_loaded_nodes = true; break; - default: - this->AddMessage(Message::TYPE_WARNING, std::string("Unknown option: ") + c); - break; + default: this->AddMessage(Message::TYPE_WARNING, std::string("Unknown option: ") + c); break; + } } } + + m_ror_minimass->min_mass = minimass; + + this->ChangeSection(File::SECTION_NONE); } - m_ror_minimass->min_mass = minimass; + void Parser::ParseFlexBodyWheel() + { + if (!this->CheckNumArguments(16)) { return; } - this->ChangeSection(File::SECTION_NONE); -} + FlexBodyWheel flexbody_wheel; + flexbody_wheel.node_defaults = m_user_node_defaults; + flexbody_wheel.beam_defaults = m_user_beam_defaults; -void Parser::ParseFlexBodyWheel() -{ - if (! this->CheckNumArguments(16)) { return; } + flexbody_wheel.tyre_radius = this->GetArgFloat(0); + flexbody_wheel.rim_radius = this->GetArgFloat(1); + flexbody_wheel.width = this->GetArgFloat(2); + flexbody_wheel.num_rays = this->GetArgInt(3); + flexbody_wheel.nodes[0] = this->GetArgNodeRef(4); + flexbody_wheel.nodes[1] = this->GetArgNodeRef(5); + flexbody_wheel.rigidity_node = this->GetArgRigidityNode(6); + flexbody_wheel.braking = this->GetArgBraking(7); + flexbody_wheel.propulsion = this->GetArgPropulsion(8); + flexbody_wheel.reference_arm_node = this->GetArgNodeRef(9); + flexbody_wheel.mass = this->GetArgFloat(10); + flexbody_wheel.tyre_springiness = this->GetArgFloat(11); + flexbody_wheel.tyre_damping = this->GetArgFloat(12); + flexbody_wheel.rim_springiness = this->GetArgFloat(13); + flexbody_wheel.rim_damping = this->GetArgFloat(14); + flexbody_wheel.side = this->GetArgWheelSide(15); - FlexBodyWheel flexbody_wheel; - flexbody_wheel.node_defaults = m_user_node_defaults; - flexbody_wheel.beam_defaults = m_user_beam_defaults; + if (m_num_args > 16) { flexbody_wheel.rim_mesh_name = this->GetArgStr(16); } + if (m_num_args > 17) { flexbody_wheel.tyre_mesh_name = this->GetArgStr(17); } - flexbody_wheel.tyre_radius = this->GetArgFloat ( 0); - flexbody_wheel.rim_radius = this->GetArgFloat ( 1); - flexbody_wheel.width = this->GetArgFloat ( 2); - flexbody_wheel.num_rays = this->GetArgInt ( 3); - flexbody_wheel.nodes[0] = this->GetArgNodeRef ( 4); - flexbody_wheel.nodes[1] = this->GetArgNodeRef ( 5); - flexbody_wheel.rigidity_node = this->GetArgRigidityNode ( 6); - flexbody_wheel.braking = this->GetArgBraking ( 7); - flexbody_wheel.propulsion = this->GetArgPropulsion ( 8); - flexbody_wheel.reference_arm_node = this->GetArgNodeRef ( 9); - flexbody_wheel.mass = this->GetArgFloat (10); - flexbody_wheel.tyre_springiness = this->GetArgFloat (11); - flexbody_wheel.tyre_damping = this->GetArgFloat (12); - flexbody_wheel.rim_springiness = this->GetArgFloat (13); - flexbody_wheel.rim_damping = this->GetArgFloat (14); - flexbody_wheel.side = this->GetArgWheelSide (15); + if (m_sequential_importer.IsEnabled()) + { + m_sequential_importer.GenerateNodesForWheel(File::KEYWORD_FLEXBODYWHEELS, flexbody_wheel.num_rays, + flexbody_wheel.rigidity_node.IsValidAnyState()); + } - if (m_num_args > 16) { flexbody_wheel.rim_mesh_name = this->GetArgStr(16); } - if (m_num_args > 17) { flexbody_wheel.tyre_mesh_name = this->GetArgStr(17); } + m_current_module->flex_body_wheels.push_back(flexbody_wheel); + } - if (m_sequential_importer.IsEnabled()) + void Parser::ParseMaterialFlareBindings() { - m_sequential_importer.GenerateNodesForWheel(File::KEYWORD_FLEXBODYWHEELS, flexbody_wheel.num_rays, flexbody_wheel.rigidity_node.IsValidAnyState()); + if (!this->CheckNumArguments(2)) { return; } + + MaterialFlareBinding binding; + binding.flare_number = this->GetArgInt(0); + binding.material_name = this->GetArgStr(1); + + m_current_module->material_flare_bindings.push_back(binding); } - m_current_module->flex_body_wheels.push_back(flexbody_wheel); -} + void Parser::ParseManagedMaterials() + { + if (!this->CheckNumArguments(2)) { return; } -void Parser::ParseMaterialFlareBindings() -{ - if (! this->CheckNumArguments(2)) { return; } + ManagedMaterial managed_mat; - MaterialFlareBinding binding; - binding.flare_number = this->GetArgInt(0); - binding.material_name = this->GetArgStr(1); - - m_current_module->material_flare_bindings.push_back(binding); -} + managed_mat.options = m_current_managed_material_options; + managed_mat.name = this->GetArgStr(0); -void Parser::ParseManagedMaterials() -{ - if (! this->CheckNumArguments(2)) { return; } + const std::string type_str = this->GetArgStr(1); + if (type_str == "mesh_standard" || type_str == "mesh_transparent") + { + if (!this->CheckNumArguments(3)) { return; } - ManagedMaterial managed_mat; - - managed_mat.options = m_current_managed_material_options; - managed_mat.name = this->GetArgStr(0); + managed_mat.type = + (type_str == "mesh_standard") ? ManagedMaterial::TYPE_MESH_STANDARD : ManagedMaterial::TYPE_MESH_TRANSPARENT; - const std::string type_str = this->GetArgStr(1); - if (type_str == "mesh_standard" || type_str == "mesh_transparent") - { - if (! this->CheckNumArguments(3)) { return; } + managed_mat.diffuse_map = this->GetArgStr(2); - managed_mat.type = (type_str == "mesh_standard") - ? ManagedMaterial::TYPE_MESH_STANDARD - : ManagedMaterial::TYPE_MESH_TRANSPARENT; - - managed_mat.diffuse_map = this->GetArgStr(2); - - if (m_num_args > 3) { managed_mat.specular_map = this->GetArgManagedTex(3); } - } - else if (type_str == "flexmesh_standard" || type_str == "flexmesh_transparent") - { - if (! this->CheckNumArguments(3)) { return; } + if (m_num_args > 3) { managed_mat.specular_map = this->GetArgManagedTex(3); } + } + else if (type_str == "flexmesh_standard" || type_str == "flexmesh_transparent") + { + if (!this->CheckNumArguments(3)) { return; } - managed_mat.type = (type_str == "flexmesh_standard") - ? ManagedMaterial::TYPE_FLEXMESH_STANDARD - : ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT; - - managed_mat.diffuse_map = this->GetArgStr(2); - - if (m_num_args > 3) { managed_mat.damaged_diffuse_map = this->GetArgManagedTex(3); } - if (m_num_args > 4) { managed_mat.specular_map = this->GetArgManagedTex(4); } - } - else - { - this->AddMessage(Message::TYPE_WARNING, type_str + " is an unkown effect"); - return; - } + managed_mat.type = (type_str == "flexmesh_standard") ? ManagedMaterial::TYPE_FLEXMESH_STANDARD + : ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT; - Ogre::ResourceGroupManager& rgm = Ogre::ResourceGroupManager::getSingleton(); + managed_mat.diffuse_map = this->GetArgStr(2); - if (!rgm.resourceExists(m_resource_group, managed_mat.diffuse_map)) - { - this->AddMessage(Message::TYPE_WARNING, "Missing texture file: " + managed_mat.diffuse_map); - return; - } - if (managed_mat.HasDamagedDiffuseMap() && !rgm.resourceExists(m_resource_group, managed_mat.damaged_diffuse_map)) - { - this->AddMessage(Message::TYPE_WARNING, "Missing texture file: " + managed_mat.damaged_diffuse_map); - managed_mat.damaged_diffuse_map = "-"; - } - if (managed_mat.HasSpecularMap() && !rgm.resourceExists(m_resource_group, managed_mat.specular_map)) - { - this->AddMessage(Message::TYPE_WARNING, "Missing texture file: " + managed_mat.specular_map); - managed_mat.specular_map = "-"; - } + if (m_num_args > 3) { managed_mat.damaged_diffuse_map = this->GetArgManagedTex(3); } + if (m_num_args > 4) { managed_mat.specular_map = this->GetArgManagedTex(4); } + } + else + { + this->AddMessage(Message::TYPE_WARNING, type_str + " is an unkown effect"); + return; + } - m_current_module->managed_materials.push_back(managed_mat); -} + Ogre::ResourceGroupManager &rgm = Ogre::ResourceGroupManager::getSingleton(); -void Parser::ParseLockgroups() -{ - if (! this->CheckNumArguments(2)) { return; } // Lockgroup num. + at least 1 node... + if (!rgm.resourceExists(m_resource_group, managed_mat.diffuse_map)) + { + this->AddMessage(Message::TYPE_WARNING, "Missing texture file: " + managed_mat.diffuse_map); + return; + } + if (managed_mat.HasDamagedDiffuseMap() && !rgm.resourceExists(m_resource_group, managed_mat.damaged_diffuse_map)) + { + this->AddMessage(Message::TYPE_WARNING, "Missing texture file: " + managed_mat.damaged_diffuse_map); + managed_mat.damaged_diffuse_map = "-"; + } + if (managed_mat.HasSpecularMap() && !rgm.resourceExists(m_resource_group, managed_mat.specular_map)) + { + this->AddMessage(Message::TYPE_WARNING, "Missing texture file: " + managed_mat.specular_map); + managed_mat.specular_map = "-"; + } + + m_current_module->managed_materials.push_back(managed_mat); + } - Lockgroup lockgroup; - lockgroup.number = this->GetArgInt(0); - - for (int i = 1; i < m_num_args; ++i) + void Parser::ParseLockgroups() { - lockgroup.nodes.push_back(this->GetArgNodeRef(i)); - } - - m_current_module->lockgroups.push_back(lockgroup); -} + if (!this->CheckNumArguments(2)) { return; } // Lockgroup num. + at least 1 node... -void Parser::ParseHydros() -{ - if (! this->CheckNumArguments(3)) { return; } - - Hydro hydro; - hydro.inertia_defaults = m_user_default_inertia; - hydro.detacher_group = m_current_detacher_group; - hydro.beam_defaults = m_user_beam_defaults; - - hydro.nodes[0] = this->GetArgNodeRef(0); - hydro.nodes[1] = this->GetArgNodeRef(1); - hydro.lenghtening_factor = this->GetArgFloat (2); - - if (m_num_args > 3) { hydro.options = this->GetArgStr(3); } - - this->ParseOptionalInertia(hydro.inertia, 4); - - m_current_module->hydros.push_back(hydro); -} - -void Parser::ParseOptionalInertia(Inertia & inertia, int index) -{ - if (m_num_args > index) { inertia.start_delay_factor = this->GetArgFloat(index++); } - if (m_num_args > index) { inertia.stop_delay_factor = this->GetArgFloat(index++); } - if (m_num_args > index) { inertia.start_function = this->GetArgStr (index++); } - if (m_num_args > index) { inertia.stop_function = this->GetArgStr (index++); } -} + Lockgroup lockgroup; + lockgroup.number = this->GetArgInt(0); -void Parser::ParseBeams() -{ - if (! this->CheckNumArguments(2)) { return; } - - Beam beam; - beam.defaults = m_user_beam_defaults; - beam.detacher_group = m_current_detacher_group; - - beam.nodes[0] = this->GetArgNodeRef(0); - beam.nodes[1] = this->GetArgNodeRef(1); - - // Flags - if (m_num_args > 2) - { - std::string options_str = this->GetArgStr(2); - for (auto itor = options_str.begin(); itor != options_str.end(); ++itor) + for (int i = 1; i < m_num_args; ++i) { - if (*itor == 'v') { continue; } // Dummy flag - else if (*itor == 'i') { beam.options |= Beam::OPTION_i_INVISIBLE; } - else if (*itor == 'r') { beam.options |= Beam::OPTION_r_ROPE; } - else if (*itor == 's') { beam.options |= Beam::OPTION_s_SUPPORT; } - else - { - char msg[200] = ""; - sprintf(msg, "Invalid flag: %c", *itor); - this->AddMessage(Message::TYPE_WARNING, msg); - } + lockgroup.nodes.push_back(this->GetArgNodeRef(i)); } + + m_current_module->lockgroups.push_back(lockgroup); } - - if ((m_num_args > 3) && (beam.options & Beam::OPTION_s_SUPPORT)) + + void Parser::ParseHydros() { - float support_break_limit = 0.0f; - float support_break_factor = this->GetArgInt(3); - if (support_break_factor > 0.0f) - { - support_break_limit = support_break_factor; - } - beam.extension_break_limit = support_break_limit; - beam._has_extension_break_limit = true; - } + if (!this->CheckNumArguments(3)) { return; } - m_current_module->beams.push_back(beam); -} + Hydro hydro; + hydro.inertia_defaults = m_user_default_inertia; + hydro.detacher_group = m_current_detacher_group; + hydro.beam_defaults = m_user_beam_defaults; -void Parser::ParseAnimator() -{ - auto args = Ogre::StringUtil::split(m_current_line, ","); - if (args.size() < 4) { return; } + hydro.nodes[0] = this->GetArgNodeRef(0); + hydro.nodes[1] = this->GetArgNodeRef(1); + hydro.lenghtening_factor = this->GetArgFloat(2); - Animator animator; - animator.inertia_defaults = m_user_default_inertia; - animator.beam_defaults = m_user_beam_defaults; - animator.detacher_group = m_current_detacher_group; + if (m_num_args > 3) { hydro.options = this->GetArgStr(3); } - animator.nodes[0] = this->_ParseNodeRef(args[0]); - animator.nodes[1] = this->_ParseNodeRef(args[1]); - animator.lenghtening_factor = this->ParseArgFloat(args[2]); + this->ParseOptionalInertia(hydro.inertia, 4); - // Parse options; Just use the split/trim/compare method - Ogre::StringVector attrs = Ogre::StringUtil::split(args[3], "|"); + m_current_module->hydros.push_back(hydro); + } - auto itor = attrs.begin(); - auto endi = attrs.end(); - for (; itor != endi; ++itor) + void Parser::ParseOptionalInertia(Inertia &inertia, int index) { - Ogre::String token = *itor; - Ogre::StringUtil::trim(token); - std::smatch results; - bool is_shortlimit = false; + if (m_num_args > index) { inertia.start_delay_factor = this->GetArgFloat(index++); } + if (m_num_args > index) { inertia.stop_delay_factor = this->GetArgFloat(index++); } + if (m_num_args > index) { inertia.start_function = this->GetArgStr(index++); } + if (m_num_args > index) { inertia.stop_function = this->GetArgStr(index++); } + } - // Numbered keywords - if (std::regex_search(token, results, Regexes::PARSE_ANIMATORS_NUMBERED_KEYWORD)) - { - if (results[1] == "throttle") animator.aero_animator.flags |= AeroAnimator::OPTION_THROTTLE; - else if (results[1] == "rpm") animator.aero_animator.flags |= AeroAnimator::OPTION_RPM; - else if (results[1] == "aerotorq") animator.aero_animator.flags |= AeroAnimator::OPTION_TORQUE; - else if (results[1] == "aeropit") animator.aero_animator.flags |= AeroAnimator::OPTION_PITCH; - else if (results[1] == "aerostatus") animator.aero_animator.flags |= AeroAnimator::OPTION_STATUS; + void Parser::ParseBeams() + { + if (!this->CheckNumArguments(2)) { return; } - animator.aero_animator.motor = this->ParseArgInt(results[2].str().c_str()); - } - else if ((is_shortlimit = (token.compare(0, 10, "shortlimit") == 0)) || (token.compare(0, 9, "longlimit") == 0)) + Beam beam; + beam.defaults = m_user_beam_defaults; + beam.detacher_group = m_current_detacher_group; + + beam.nodes[0] = this->GetArgNodeRef(0); + beam.nodes[1] = this->GetArgNodeRef(1); + + // Flags + if (m_num_args > 2) { - Ogre::StringVector fields = Ogre::StringUtil::split(token, ":"); - if (fields.size() > 1) + std::string options_str = this->GetArgStr(2); + for (auto itor = options_str.begin(); itor != options_str.end(); ++itor) { - if (is_shortlimit) + if (*itor == 'v') { continue; } // Dummy flag + else if (*itor == 'i') + { + beam.options |= Beam::OPTION_i_INVISIBLE; + } + else if (*itor == 'r') { - animator.short_limit = std::strtod(fields[1].c_str(), nullptr); - animator.flags |= Animator::OPTION_SHORT_LIMIT; + beam.options |= Beam::OPTION_r_ROPE; + } + else if (*itor == 's') + { + beam.options |= Beam::OPTION_s_SUPPORT; } else { - animator.long_limit = std::strtod(fields[1].c_str(), nullptr); - animator.flags |= Animator::OPTION_LONG_LIMIT; + char msg[200] = ""; + sprintf(msg, "Invalid flag: %c", *itor); + this->AddMessage(Message::TYPE_WARNING, msg); } } } - else + + if ((m_num_args > 3) && (beam.options & Beam::OPTION_s_SUPPORT)) { - // Standalone keywords - if (token == "vis") animator.flags |= Animator::OPTION_VISIBLE; - else if (token == "inv") animator.flags |= Animator::OPTION_INVISIBLE; - else if (token == "airspeed") animator.flags |= Animator::OPTION_AIRSPEED; - else if (token == "vvi") animator.flags |= Animator::OPTION_VERTICAL_VELOCITY; - else if (token == "altimeter100k") animator.flags |= Animator::OPTION_ALTIMETER_100K; - else if (token == "altimeter10k") animator.flags |= Animator::OPTION_ALTIMETER_10K; - else if (token == "altimeter1k") animator.flags |= Animator::OPTION_ALTIMETER_1K; - else if (token == "aoa") animator.flags |= Animator::OPTION_ANGLE_OF_ATTACK; - else if (token == "flap") animator.flags |= Animator::OPTION_FLAP; - else if (token == "airbrake") animator.flags |= Animator::OPTION_AIR_BRAKE; - else if (token == "roll") animator.flags |= Animator::OPTION_ROLL; - else if (token == "pitch") animator.flags |= Animator::OPTION_PITCH; - else if (token == "brakes") animator.flags |= Animator::OPTION_BRAKES; - else if (token == "accel") animator.flags |= Animator::OPTION_ACCEL; - else if (token == "clutch") animator.flags |= Animator::OPTION_CLUTCH; - else if (token == "speedo") animator.flags |= Animator::OPTION_SPEEDO; - else if (token == "tacho") animator.flags |= Animator::OPTION_TACHO; - else if (token == "turbo") animator.flags |= Animator::OPTION_TURBO; - else if (token == "parking") animator.flags |= Animator::OPTION_PARKING; - else if (token == "shifterman1") animator.flags |= Animator::OPTION_SHIFT_LEFT_RIGHT; - else if (token == "shifterman2") animator.flags |= Animator::OPTION_SHIFT_BACK_FORTH; - else if (token == "sequential") animator.flags |= Animator::OPTION_SEQUENTIAL_SHIFT; - else if (token == "shifterlin") animator.flags |= Animator::OPTION_GEAR_SELECT; - else if (token == "torque") animator.flags |= Animator::OPTION_TORQUE; - else if (token == "difflock") animator.flags |= Animator::OPTION_DIFFLOCK; - else if (token == "rudderboat") animator.flags |= Animator::OPTION_BOAT_RUDDER; - else if (token == "throttleboat") animator.flags |= Animator::OPTION_BOAT_THROTTLE; - } - } - - m_current_module->animators.push_back(animator); -} - -void Parser::ParseAuthor() -{ - if (m_current_module != m_root_module) - { - this->AddMessage(Message::TYPE_WARNING, "Inline-section 'author' has global effect and should not appear in a module"); + float support_break_limit = 0.0f; + float support_break_factor = this->GetArgInt(3); + if (support_break_factor > 0.0f) { support_break_limit = support_break_factor; } + beam.extension_break_limit = support_break_limit; + beam._has_extension_break_limit = true; + } + + m_current_module->beams.push_back(beam); } - if (! this->CheckNumArguments(2)) { return; } + void Parser::ParseAnimator() + { + auto args = Ogre::StringUtil::split(m_current_line, ","); + if (args.size() < 4) { return; } - Author author; - if (m_num_args > 1) { author.type = this->GetArgStr(1); } - if (m_num_args > 2) { author.forum_account_id = this->GetArgInt(2); author._has_forum_account = true; } - if (m_num_args > 3) { author.name = this->GetArgStr(3); } - if (m_num_args > 4) { author.email = this->GetArgStr(4); } - m_definition->authors.push_back(author); + Animator animator; + animator.inertia_defaults = m_user_default_inertia; + animator.beam_defaults = m_user_beam_defaults; + animator.detacher_group = m_current_detacher_group; - this->ChangeSection(File::SECTION_NONE); -} + animator.nodes[0] = this->_ParseNodeRef(args[0]); + animator.nodes[1] = this->_ParseNodeRef(args[1]); + animator.lenghtening_factor = this->ParseArgFloat(args[2]); -// -------------------------------------------------------------------------- -// Utilities -// -------------------------------------------------------------------------- + // Parse options; Just use the split/trim/compare method + Ogre::StringVector attrs = Ogre::StringUtil::split(args[3], "|"); -void Parser::AddMessage(std::string const & line, Message::Type type, std::string const & message) -{ - // Push and then access to avoid copy-constructing strings - m_messages.push_back(Message()); - - m_messages.back().line = line; - m_messages.back().line_number = m_current_line_number; - m_messages.back().message = message; - m_messages.back().type = type; - m_messages.back().section = m_current_section; - m_messages.back().subsection = m_current_subsection; - m_messages.back().module = m_current_module->name; - - switch (type) - { - case Message::TYPE_ERROR: - case Message::TYPE_FATAL_ERROR: - ++m_messages_num_errors; - break; - case Message::TYPE_WARNING: - ++m_messages_num_warnings; - break; - default: - ++m_messages_num_other; - break; - } -} - -File::Keyword Parser::IdentifyKeywordInCurrentLine() -{ - // Quick check - keyword always starts with ASCII letter - char c = tolower(m_current_line[0]); // Note: line comes in trimmed - if (c > 'z' || c < 'a') - { - return File::KEYWORD_INVALID; - } + auto itor = attrs.begin(); + auto endi = attrs.end(); + for (; itor != endi; ++itor) + { + Ogre::String token = *itor; + Ogre::StringUtil::trim(token); + std::smatch results; + bool is_shortlimit = false; - // Search with correct lettercase - std::smatch results; - std::string line(m_current_line); - std::regex_search(line, results, Regexes::IDENTIFY_KEYWORD_RESPECT_CASE); // Always returns true. - File::Keyword keyword = FindKeywordMatch(results); - if (keyword != File::KEYWORD_INVALID) - { - return keyword; + // Numbered keywords + if (std::regex_search(token, results, Regexes::PARSE_ANIMATORS_NUMBERED_KEYWORD)) + { + if (results[1] == "throttle") + animator.aero_animator.flags |= AeroAnimator::OPTION_THROTTLE; + else if (results[1] == "rpm") + animator.aero_animator.flags |= AeroAnimator::OPTION_RPM; + else if (results[1] == "aerotorq") + animator.aero_animator.flags |= AeroAnimator::OPTION_TORQUE; + else if (results[1] == "aeropit") + animator.aero_animator.flags |= AeroAnimator::OPTION_PITCH; + else if (results[1] == "aerostatus") + animator.aero_animator.flags |= AeroAnimator::OPTION_STATUS; + + animator.aero_animator.motor = this->ParseArgInt(results[2].str().c_str()); + } + else if ((is_shortlimit = (token.compare(0, 10, "shortlimit") == 0)) || (token.compare(0, 9, "longlimit") == 0)) + { + Ogre::StringVector fields = Ogre::StringUtil::split(token, ":"); + if (fields.size() > 1) + { + if (is_shortlimit) + { + animator.short_limit = std::strtod(fields[1].c_str(), nullptr); + animator.flags |= Animator::OPTION_SHORT_LIMIT; + } + else + { + animator.long_limit = std::strtod(fields[1].c_str(), nullptr); + animator.flags |= Animator::OPTION_LONG_LIMIT; + } + } + } + else + { + // Standalone keywords + if (token == "vis") + animator.flags |= Animator::OPTION_VISIBLE; + else if (token == "inv") + animator.flags |= Animator::OPTION_INVISIBLE; + else if (token == "airspeed") + animator.flags |= Animator::OPTION_AIRSPEED; + else if (token == "vvi") + animator.flags |= Animator::OPTION_VERTICAL_VELOCITY; + else if (token == "altimeter100k") + animator.flags |= Animator::OPTION_ALTIMETER_100K; + else if (token == "altimeter10k") + animator.flags |= Animator::OPTION_ALTIMETER_10K; + else if (token == "altimeter1k") + animator.flags |= Animator::OPTION_ALTIMETER_1K; + else if (token == "aoa") + animator.flags |= Animator::OPTION_ANGLE_OF_ATTACK; + else if (token == "flap") + animator.flags |= Animator::OPTION_FLAP; + else if (token == "airbrake") + animator.flags |= Animator::OPTION_AIR_BRAKE; + else if (token == "roll") + animator.flags |= Animator::OPTION_ROLL; + else if (token == "pitch") + animator.flags |= Animator::OPTION_PITCH; + else if (token == "brakes") + animator.flags |= Animator::OPTION_BRAKES; + else if (token == "accel") + animator.flags |= Animator::OPTION_ACCEL; + else if (token == "clutch") + animator.flags |= Animator::OPTION_CLUTCH; + else if (token == "speedo") + animator.flags |= Animator::OPTION_SPEEDO; + else if (token == "tacho") + animator.flags |= Animator::OPTION_TACHO; + else if (token == "turbo") + animator.flags |= Animator::OPTION_TURBO; + else if (token == "parking") + animator.flags |= Animator::OPTION_PARKING; + else if (token == "shifterman1") + animator.flags |= Animator::OPTION_SHIFT_LEFT_RIGHT; + else if (token == "shifterman2") + animator.flags |= Animator::OPTION_SHIFT_BACK_FORTH; + else if (token == "sequential") + animator.flags |= Animator::OPTION_SEQUENTIAL_SHIFT; + else if (token == "shifterlin") + animator.flags |= Animator::OPTION_GEAR_SELECT; + else if (token == "torque") + animator.flags |= Animator::OPTION_TORQUE; + else if (token == "difflock") + animator.flags |= Animator::OPTION_DIFFLOCK; + else if (token == "rudderboat") + animator.flags |= Animator::OPTION_BOAT_RUDDER; + else if (token == "throttleboat") + animator.flags |= Animator::OPTION_BOAT_THROTTLE; + } + } + + m_current_module->animators.push_back(animator); } - // Search and ignore lettercase - std::regex_search(line, results, Regexes::IDENTIFY_KEYWORD_IGNORE_CASE); // Always returns true. - keyword = FindKeywordMatch(results); - if (keyword != File::KEYWORD_INVALID) + void Parser::ParseAuthor() { - this->AddMessage(line, Message::TYPE_WARNING, - "Keyword has invalid lettercase. Correct form is: " + std::string(File::KeywordToString(keyword))); - } - return keyword; -} + if (m_current_module != m_root_module) + { + this->AddMessage(Message::TYPE_WARNING, + "Inline-section 'author' has global effect and should not appear in a module"); + } -File::Keyword Parser::FindKeywordMatch(std::smatch& search_results) -{ - // The 'results' array contains a complete match at positon [0] and sub-matches starting with [1], - // so we get exact positions in Regexes::IDENTIFY_KEYWORD, which again match File::Keyword enum members + if (!this->CheckNumArguments(2)) { return; } - for (unsigned int i = 1; i < search_results.size(); i++) - { - std::ssub_match sub = search_results[i]; - if (sub.matched) + Author author; + if (m_num_args > 1) { author.type = this->GetArgStr(1); } + if (m_num_args > 2) { - // Build enum value directly from result offset - return File::Keyword(i); + author.forum_account_id = this->GetArgInt(2); + author._has_forum_account = true; } + if (m_num_args > 3) { author.name = this->GetArgStr(3); } + if (m_num_args > 4) { author.email = this->GetArgStr(4); } + m_definition->authors.push_back(author); + + this->ChangeSection(File::SECTION_NONE); } - return File::KEYWORD_INVALID; -} -void Parser::Prepare() -{ - m_current_section = File::SECTION_TRUCK_NAME; - m_current_subsection = File::SUBSECTION_NONE; - m_current_line_number = 1; - m_definition = std::shared_ptr(new File()); - m_in_block_comment = false; - m_in_description_section = false; - m_any_named_node_defined = false; - m_last_flexbody.reset(); // Set to nullptr - m_current_detacher_group = 0; // Global detacher group - - m_user_default_inertia = m_ror_default_inertia; - m_user_node_defaults = m_ror_node_defaults; - m_user_minimass = m_ror_minimass; - m_current_managed_material_options = ManagedMaterialsOptions(); - - m_user_beam_defaults = std::shared_ptr(new BeamDefaults); - m_user_beam_defaults->springiness = DEFAULT_SPRING; - m_user_beam_defaults->damping_constant = DEFAULT_DAMP; - m_user_beam_defaults->deformation_threshold = BEAM_DEFORM; - m_user_beam_defaults->breaking_threshold = BEAM_BREAK; - m_user_beam_defaults->visual_beam_diameter = DEFAULT_BEAM_DIAMETER; - - m_root_module = m_definition->root_module; - m_current_module = m_definition->root_module; - - m_sequential_importer.Init(true); // Enabled=true - - m_messages_num_errors = 0; - m_messages_num_warnings = 0; - m_messages_num_other = 0; -} - -void Parser::ChangeSection(RigDef::File::Section new_section) -{ - // ## Section-specific switch logic ## + // -------------------------------------------------------------------------- + // Utilities + // -------------------------------------------------------------------------- - if (m_current_submesh != nullptr) + void Parser::AddMessage(std::string const &line, Message::Type type, std::string const &message) { - m_current_module->submeshes.push_back(*m_current_submesh); - m_current_submesh.reset(); // Set to nullptr - m_current_subsection = File::SUBSECTION_NONE; - } + // Push and then access to avoid copy-constructing strings + m_messages.push_back(Message()); - if (m_current_camera_rail != nullptr) - { - if (m_current_camera_rail->nodes.size() == 0) - { - this->AddMessage(Message::TYPE_WARNING, "Empty section 'camerarail', ignoring..."); - } - else + m_messages.back().line = line; + m_messages.back().line_number = m_current_line_number; + m_messages.back().message = message; + m_messages.back().type = type; + m_messages.back().section = m_current_section; + m_messages.back().subsection = m_current_subsection; + m_messages.back().module = m_current_module->name; + + switch (type) { - m_current_module->camera_rails.push_back(*m_current_camera_rail); - m_current_camera_rail.reset(); + case Message::TYPE_ERROR: + case Message::TYPE_FATAL_ERROR: ++m_messages_num_errors; break; + case Message::TYPE_WARNING: ++m_messages_num_warnings; break; + default: ++m_messages_num_other; break; } } - if (m_current_section == File::SECTION_FLEXBODIES) + File::Keyword Parser::IdentifyKeywordInCurrentLine() { - m_current_subsection = File::SUBSECTION_NONE; - } + // Quick check - keyword always starts with ASCII letter + char c = tolower(m_current_line[0]); // Note: line comes in trimmed + if (c > 'z' || c < 'a') { return File::KEYWORD_INVALID; } - // Enter sections - m_current_section = new_section; - if (new_section == File::SECTION_SUBMESH) - { - m_current_submesh = std::shared_ptr( new Submesh() ); + // Search with correct lettercase + std::smatch results; + std::string line(m_current_line); + std::regex_search(line, results, Regexes::IDENTIFY_KEYWORD_RESPECT_CASE); // Always returns true. + File::Keyword keyword = FindKeywordMatch(results); + if (keyword != File::KEYWORD_INVALID) { return keyword; } + + // Search and ignore lettercase + std::regex_search(line, results, Regexes::IDENTIFY_KEYWORD_IGNORE_CASE); // Always returns true. + keyword = FindKeywordMatch(results); + if (keyword != File::KEYWORD_INVALID) + { + this->AddMessage(line, Message::TYPE_WARNING, + "Keyword has invalid lettercase. Correct form is: " + std::string(File::KeywordToString(keyword))); + } + return keyword; } - else if (new_section == File::SECTION_CAMERA_RAIL) + + File::Keyword Parser::FindKeywordMatch(std::smatch &search_results) { - m_current_camera_rail = std::shared_ptr( new CameraRail() ); + // The 'results' array contains a complete match at positon [0] and sub-matches starting with [1], + // so we get exact positions in Regexes::IDENTIFY_KEYWORD, which again match File::Keyword enum members + + for (unsigned int i = 1; i < search_results.size(); i++) + { + std::ssub_match sub = search_results[i]; + if (sub.matched) + { + // Build enum value directly from result offset + return File::Keyword(i); + } + } + return File::KEYWORD_INVALID; } - else if (new_section == File::SECTION_FLEXBODIES) + + void Parser::Prepare() { - m_current_subsection = File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE; + m_current_section = File::SECTION_TRUCK_NAME; + m_current_subsection = File::SUBSECTION_NONE; + m_current_line_number = 1; + m_definition = std::shared_ptr(new File()); + m_in_block_comment = false; + m_in_description_section = false; + m_any_named_node_defined = false; + m_last_flexbody.reset(); // Set to nullptr + m_current_detacher_group = 0; // Global detacher group + + m_user_default_inertia = m_ror_default_inertia; + m_user_node_defaults = m_ror_node_defaults; + m_user_minimass = m_ror_minimass; + m_current_managed_material_options = ManagedMaterialsOptions(); + + m_user_beam_defaults = std::shared_ptr(new BeamDefaults); + m_user_beam_defaults->springiness = DEFAULT_SPRING; + m_user_beam_defaults->damping_constant = DEFAULT_DAMP; + m_user_beam_defaults->deformation_threshold = BEAM_DEFORM; + m_user_beam_defaults->breaking_threshold = BEAM_BREAK; + m_user_beam_defaults->visual_beam_diameter = DEFAULT_BEAM_DIAMETER; + + m_root_module = m_definition->root_module; + m_current_module = m_definition->root_module; + + m_sequential_importer.Init(true); // Enabled=true + + m_messages_num_errors = 0; + m_messages_num_warnings = 0; + m_messages_num_other = 0; } - else if (new_section == File::SECTION_GUI_SETTINGS) + + void Parser::ChangeSection(RigDef::File::Section new_section) { - if (m_current_module->gui_settings == nullptr) + // ## Section-specific switch logic ## + + if (m_current_submesh != nullptr) { - m_current_module->gui_settings = std::shared_ptr ( new GuiSettings() ); + m_current_module->submeshes.push_back(*m_current_submesh); + m_current_submesh.reset(); // Set to nullptr + m_current_subsection = File::SUBSECTION_NONE; } - } -} -void Parser::ProcessChangeModuleLine(File::Keyword keyword) -{ - // Determine and verify new module - std::string new_module_name; - if (keyword == File::KEYWORD_END_SECTION) - { - if (m_current_module == m_root_module) + if (m_current_camera_rail != nullptr) { - this->AddMessage(Message::TYPE_ERROR, "Misplaced keyword 'end_section' (already in root module), ignoring..."); - return; + if (m_current_camera_rail->nodes.size() == 0) + { this->AddMessage(Message::TYPE_WARNING, "Empty section 'camerarail', ignoring..."); } + else + { + m_current_module->camera_rails.push_back(*m_current_camera_rail); + m_current_camera_rail.reset(); + } + } + + if (m_current_section == File::SECTION_FLEXBODIES) { m_current_subsection = File::SUBSECTION_NONE; } + + // Enter sections + m_current_section = new_section; + if (new_section == File::SECTION_SUBMESH) { m_current_submesh = std::shared_ptr(new Submesh()); } + else if (new_section == File::SECTION_CAMERA_RAIL) + { + m_current_camera_rail = std::shared_ptr(new CameraRail()); + } + else if (new_section == File::SECTION_FLEXBODIES) + { + m_current_subsection = File::SUBSECTION__FLEXBODIES__PROPLIKE_LINE; + } + else if (new_section == File::SECTION_GUI_SETTINGS) + { + if (m_current_module->gui_settings == nullptr) + { m_current_module->gui_settings = std::shared_ptr(new GuiSettings()); } } - new_module_name = ROOT_MODULE_NAME; } - else if (keyword == File::KEYWORD_SECTION) + + void Parser::ProcessChangeModuleLine(File::Keyword keyword) { - if (!this->CheckNumArguments(3)) // Syntax: "section VERSION NAME"; VERSION is unused + // Determine and verify new module + std::string new_module_name; + if (keyword == File::KEYWORD_END_SECTION) + { + if (m_current_module == m_root_module) + { + this->AddMessage(Message::TYPE_ERROR, "Misplaced keyword 'end_section' (already in root module), ignoring..."); + return; + } + new_module_name = ROOT_MODULE_NAME; + } + else if (keyword == File::KEYWORD_SECTION) { - return; // Error already reported + if (!this->CheckNumArguments(3)) // Syntax: "section VERSION NAME"; VERSION is unused + { + return; // Error already reported + } + + new_module_name = this->GetArgStr(2); + if (new_module_name == m_current_module->name) + { + this->AddMessage(Message::TYPE_ERROR, "Attempt to re-enter current module, ignoring..."); + return; + } } - new_module_name = this->GetArgStr(2); - if (new_module_name == m_current_module->name) + // Perform the switch + this->ChangeSection(RigDef::File::SECTION_NONE); + m_last_flexbody.reset(); // Set to nullptr + + if (new_module_name == ROOT_MODULE_NAME) { - this->AddMessage(Message::TYPE_ERROR, "Attempt to re-enter current module, ignoring..."); + m_current_module = m_root_module; return; } - } - - // Perform the switch - this->ChangeSection(RigDef::File::SECTION_NONE); - m_last_flexbody.reset(); // Set to nullptr - if (new_module_name == ROOT_MODULE_NAME) - { - m_current_module = m_root_module; - return; + auto search_itor = m_definition->user_modules.find(new_module_name); + if (search_itor != m_definition->user_modules.end()) { m_current_module = search_itor->second; } + else + { + m_current_module = std::make_shared(new_module_name); + m_definition->user_modules.insert(std::make_pair(new_module_name, m_current_module)); + } } - auto search_itor = m_definition->user_modules.find(new_module_name); - if (search_itor != m_definition->user_modules.end()) - { - m_current_module = search_itor->second; - } - else + void Parser::Finalize() { - m_current_module = std::make_shared(new_module_name); - m_definition->user_modules.insert(std::make_pair(new_module_name, m_current_module)); - } -} - -void Parser::Finalize() -{ - this->ChangeSection(File::SECTION_NONE); - m_definition->global_minimass = m_ror_minimass; + this->ChangeSection(File::SECTION_NONE); + m_definition->global_minimass = m_ror_minimass; - if (m_sequential_importer.IsEnabled()) - { - m_sequential_importer.Process( m_definition ); + if (m_sequential_importer.IsEnabled()) { m_sequential_importer.Process(m_definition); } } -} -std::string Parser::ProcessMessagesToString() -{ - if (this->GetMessages().size() == 0) + std::string Parser::ProcessMessagesToString() { - std::string msg(" == Parsing done OK, nothing to report"); - return msg; - } + if (this->GetMessages().size() == 0) + { + std::string msg(" == Parsing done OK, nothing to report"); + return msg; + } - std::stringstream report; - report << " == Parsing done, report:" << std::endl <type) + auto itor = m_messages.begin(); + auto end = m_messages.end(); + for (; itor != end; ++itor) { - case (RigDef::Parser::Message::TYPE_FATAL_ERROR): - report << "#FF3300 FATAL_ERROR #FFFFFF"; - break; + switch (itor->type) + { + case (RigDef::Parser::Message::TYPE_FATAL_ERROR): report << "#FF3300 FATAL_ERROR #FFFFFF"; break; - case (RigDef::Parser::Message::TYPE_ERROR): - report << "#FF3300 ERROR #FFFFFF"; - break; + case (RigDef::Parser::Message::TYPE_ERROR): report << "#FF3300 ERROR #FFFFFF"; break; - case (RigDef::Parser::Message::TYPE_WARNING): - report << "#FFFF00 WARNING #FFFFFF"; - break; + case (RigDef::Parser::Message::TYPE_WARNING): report << "#FFFF00 WARNING #FFFFFF"; break; - default: - report << "INFO"; - break; + default: report << "INFO"; break; + } + report << " (Section " << RigDef::File::SectionToString(itor->section) << ")" << std::endl; + report << "\tLine (" << itor->line_number << "): " << itor->line << std::endl; + report << "\tMessage: " << itor->message << std::endl; } - report << " (Section " << RigDef::File::SectionToString(itor->section) << ")" << std::endl; - report << "\tLine (" << itor->line_number << "): " << itor->line << std::endl; - report << "\tMessage: " << itor->message << std::endl; + + return report.str(); } - return report.str(); -} + std::string Parser::GetArgStr(int index) + { + return std::string(m_args[index].start, m_args[index].length); + } -std::string Parser::GetArgStr(int index) -{ - return std::string(m_args[index].start, m_args[index].length); -} + char Parser::GetArgChar(int index) + { + return *(m_args[index].start); + } -char Parser::GetArgChar(int index) -{ - return *(m_args[index].start); -} + MeshWheel::Side Parser::GetArgWheelSide(int index) + { + char side_char = this->GetArgChar(index); + if (side_char != 'r') + { + if (side_char != 'l') + { + char msg[200] = ""; + snprintf(msg, 200, "Bad arg~%d 'side' (value: %c), parsing as 'l' for backwards compatibility.", index + 1, + side_char); + this->AddMessage(Message::TYPE_WARNING, msg); + } + return MeshWheel::SIDE_LEFT; + } + return MeshWheel::SIDE_RIGHT; + } -MeshWheel::Side Parser::GetArgWheelSide(int index) -{ - char side_char = this->GetArgChar(index); - if (side_char != 'r') + long Parser::GetArgLong(int index) { - if (side_char != 'l') + errno = 0; + char * out_end = nullptr; + const int MSG_LEN = 200; + char msg[MSG_LEN]; + long res = std::strtol(m_args[index].start, &out_end, 10); + if (errno != 0) + { + snprintf(msg, MSG_LEN, "Cannot parse argument [%d] as integer, errno: %d", index + 1, errno); + this->AddMessage(Message::TYPE_ERROR, msg); + return 0; // Compatibility + } + if (out_end == m_args[index].start) + { + snprintf(msg, MSG_LEN, "Argument [%d] is not valid integer", index + 1); + this->AddMessage(Message::TYPE_ERROR, msg); + return 0; // Compatibility + } + else if (out_end != (m_args[index].start + m_args[index].length)) { - char msg[200] = ""; - snprintf(msg, 200, "Bad arg~%d 'side' (value: %c), parsing as 'l' for backwards compatibility.", index + 1, side_char); + snprintf(msg, MSG_LEN, "Integer argument [%d] has invalid trailing characters", index + 1); this->AddMessage(Message::TYPE_WARNING, msg); } - return MeshWheel::SIDE_LEFT; + return res; } - return MeshWheel::SIDE_RIGHT; -} -long Parser::GetArgLong(int index) -{ - errno = 0; - char* out_end = nullptr; - const int MSG_LEN = 200; - char msg[MSG_LEN]; - long res = std::strtol(m_args[index].start, &out_end, 10); - if (errno != 0) + int Parser::GetArgInt(int index) { - snprintf(msg, MSG_LEN, "Cannot parse argument [%d] as integer, errno: %d", index + 1, errno); - this->AddMessage(Message::TYPE_ERROR, msg); - return 0; // Compatibility + return static_cast(this->GetArgLong(index)); } - if (out_end == m_args[index].start) + + Node::Ref Parser::GetArgRigidityNode(int index) { - snprintf(msg, MSG_LEN, "Argument [%d] is not valid integer", index + 1); - this->AddMessage(Message::TYPE_ERROR, msg); - return 0; // Compatibility + std::string rigidity_node = this->GetArgStr(index); + if (rigidity_node != "9999") // Special null value + { return this->GetArgNodeRef(index); } + return Node::Ref(); // Defaults to invalid ref } - else if (out_end != (m_args[index].start + m_args[index].length)) + + Wheels::Propulsion Parser::GetArgPropulsion(int index) { - snprintf(msg, MSG_LEN, "Integer argument [%d] has invalid trailing characters", index + 1); - this->AddMessage(Message::TYPE_WARNING, msg); + int propulsion = this->GetArgInt(index); + if (propulsion < 0 || propulsion > 2) + { + char msg[100] = ""; + snprintf(msg, 100, "Bad value of param ~%d (propulsion), using 0 (no propulsion)", index + 1); + this->AddMessage(Message::TYPE_ERROR, msg); + return Wheels::PROPULSION_NONE; + } + return Wheels::Propulsion(propulsion); } - return res; -} - -int Parser::GetArgInt(int index) -{ - return static_cast(this->GetArgLong(index)); -} -Node::Ref Parser::GetArgRigidityNode(int index) -{ - std::string rigidity_node = this->GetArgStr(index); - if (rigidity_node != "9999") // Special null value + Wheels::Braking Parser::GetArgBraking(int index) { - return this->GetArgNodeRef(index); + int braking = this->GetArgInt(index); + if (braking < 0 || braking > 4) + { + char msg[100] = ""; + snprintf(msg, 100, "Bad value of param ~%d (braking), using 0 (no braking)", index + 1); + return Wheels::BRAKING_NO; + } + return Wheels::Braking(braking); } - return Node::Ref(); // Defaults to invalid ref -} -Wheels::Propulsion Parser::GetArgPropulsion(int index) -{ - int propulsion = this->GetArgInt(index); - if (propulsion < 0 || propulsion > 2) + Node::Ref Parser::GetArgNodeRef(int index) { - char msg[100] = ""; - snprintf(msg, 100, "Bad value of param ~%d (propulsion), using 0 (no propulsion)", index + 1); - this->AddMessage(Message::TYPE_ERROR, msg); - return Wheels::PROPULSION_NONE; + return this->_ParseNodeRef(this->GetArgStr(index)); } - return Wheels::Propulsion(propulsion); -} -Wheels::Braking Parser::GetArgBraking(int index) -{ - int braking = this->GetArgInt(index); - if (braking < 0 || braking > 4) + Node::Ref Parser::GetArgNullableNode(int index) { - char msg[100] = ""; - snprintf(msg, 100, "Bad value of param ~%d (braking), using 0 (no braking)", index + 1); - return Wheels::BRAKING_NO; + if (!(Ogre::StringConverter::parseReal(this->GetArgStr(index)) == -1.f)) { return this->GetArgNodeRef(index); } + return Node::Ref(); // Defaults to empty ref. } - return Wheels::Braking(braking); -} - -Node::Ref Parser::GetArgNodeRef(int index) -{ - return this->_ParseNodeRef(this->GetArgStr(index)); -} -Node::Ref Parser::GetArgNullableNode(int index) -{ - if (! (Ogre::StringConverter::parseReal(this->GetArgStr(index)) == -1.f)) + unsigned Parser::GetArgUint(int index) { - return this->GetArgNodeRef(index); + return static_cast(this->GetArgLong(index)); } - return Node::Ref(); // Defaults to empty ref. -} -unsigned Parser::GetArgUint(int index) -{ - return static_cast(this->GetArgLong(index)); -} - -Flare2::Type Parser::GetArgFlareType(int index) -{ - char in = this->GetArgChar(index); - if (in != 'f' && in != 'b' && in != 'l' && in != 'r' && in != 'R' && in != 'u') + Flare2::Type Parser::GetArgFlareType(int index) { - char msg[100]; - snprintf(msg, 100, "Invalid flare type '%c', falling back to type 'f' (front light)...", in); - AddMessage(Message::TYPE_WARNING, msg); + char in = this->GetArgChar(index); + if (in != 'f' && in != 'b' && in != 'l' && in != 'r' && in != 'R' && in != 'u') + { + char msg[100]; + snprintf(msg, 100, "Invalid flare type '%c', falling back to type 'f' (front light)...", in); + AddMessage(Message::TYPE_WARNING, msg); - in = 'f'; + in = 'f'; + } + return Flare2::Type(in); } - return Flare2::Type(in); -} -float Parser::GetArgFloat(int index) -{ - errno = 0; - char* out_end = nullptr; - float res = std::strtod(m_args[index].start, &out_end); - const int MSG_LEN = LINE_BUFFER_LENGTH +100; - char msg_buf[MSG_LEN]; - if (errno != 0) + float Parser::GetArgFloat(int index) { - snprintf(msg_buf, MSG_LEN, "Cannot parse argument [%d] as float, errno: %d", index + 1, errno); - this->AddMessage(Message::TYPE_ERROR, msg_buf); - return 0.f; // Compatibility + errno = 0; + char * out_end = nullptr; + float res = std::strtod(m_args[index].start, &out_end); + const int MSG_LEN = LINE_BUFFER_LENGTH + 100; + char msg_buf[MSG_LEN]; + if (errno != 0) + { + snprintf(msg_buf, MSG_LEN, "Cannot parse argument [%d] as float, errno: %d", index + 1, errno); + this->AddMessage(Message::TYPE_ERROR, msg_buf); + return 0.f; // Compatibility + } + if (out_end == m_args[index].start) + { + char arg[LINE_BUFFER_LENGTH] = ""; + strncpy(arg, m_args[index].start, m_args[index].length); + snprintf(msg_buf, MSG_LEN, "Argument [%d] (\"%s\") is not valid float", index + 1, arg); + this->AddMessage(Message::TYPE_ERROR, msg_buf); + return 0.f; // Compatibility + } + else if (out_end != (m_args[index].start + m_args[index].length)) + { + char arg[LINE_BUFFER_LENGTH] = ""; + ptrdiff_t offset = (out_end - m_args[index].start); + strncpy(arg, out_end, m_args[index].length - offset); + snprintf(msg_buf, MSG_LEN, "Argument [%d] (type: float) has invalid trailing characters (\"%s\")", index + 1, arg); + this->AddMessage(Message::TYPE_WARNING, msg_buf); + } + return static_cast(res); } - if (out_end == m_args[index].start) + + float Parser::ParseArgFloat(const char *str) { - char arg[LINE_BUFFER_LENGTH] = ""; - strncpy(arg, m_args[index].start, m_args[index].length); - snprintf(msg_buf, MSG_LEN, "Argument [%d] (\"%s\") is not valid float", index + 1, arg); - this->AddMessage(Message::TYPE_ERROR, msg_buf); - return 0.f; // Compatibility + errno = 0; + float res = std::strtod(str, nullptr); + if (errno != 0) + { + char msg[100]; + snprintf(msg, 100, "Cannot parse argument '%s' as float, errno: %d", str, errno); + this->AddMessage(Message::TYPE_ERROR, msg); + return 0.f; // Compatibility + } + return static_cast(res); } - else if (out_end != (m_args[index].start + m_args[index].length)) + + float Parser::ParseArgFloat(std::string const &str) { - char arg[LINE_BUFFER_LENGTH] = ""; - ptrdiff_t offset = (out_end - m_args[index].start); - strncpy(arg, out_end, m_args[index].length - offset); - snprintf(msg_buf, MSG_LEN, "Argument [%d] (type: float) has invalid trailing characters (\"%s\")", index + 1, arg); - this->AddMessage(Message::TYPE_WARNING, msg_buf); + return this->ParseArgFloat(str.c_str()); } - return static_cast(res); -} -float Parser::ParseArgFloat(const char* str) -{ - errno = 0; - float res = std::strtod(str, nullptr); - if (errno != 0) + unsigned Parser::ParseArgUint(const char *str) { - char msg[100]; - snprintf(msg, 100, "Cannot parse argument '%s' as float, errno: %d", str, errno); - this->AddMessage(Message::TYPE_ERROR, msg); - return 0.f; // Compatibility + errno = 0; + long res = std::strtol(str, nullptr, 10); + if (errno != 0) + { + char msg[200]; + snprintf(msg, 200, "Cannot parse argument '%s' as int, errno: %d", str, errno); + this->AddMessage(Message::TYPE_ERROR, msg); + return 0.f; // Compatibility + } + return static_cast(res); } - return static_cast(res); -} - -float Parser::ParseArgFloat(std::string const & str) -{ - return this->ParseArgFloat(str.c_str()); -} -unsigned Parser::ParseArgUint(const char* str) -{ - errno = 0; - long res = std::strtol(str, nullptr, 10); - if (errno != 0) + unsigned Parser::ParseArgUint(std::string const &str) { - char msg[200]; - snprintf(msg, 200, "Cannot parse argument '%s' as int, errno: %d", str, errno); - this->AddMessage(Message::TYPE_ERROR, msg); - return 0.f; // Compatibility + return this->ParseArgUint(str.c_str()); } - return static_cast(res); -} - -unsigned Parser::ParseArgUint(std::string const & str) -{ - return this->ParseArgUint(str.c_str()); -} -int Parser::ParseArgInt(const char* str) -{ - return static_cast(this->ParseArgUint(str)); -} - -bool Parser::GetArgBool(int index) -{ - return Ogre::StringConverter::parseBool(this->GetArgStr(index)); -} - -Wing::Control Parser::GetArgWingSurface(int index) -{ - std::string str = this->GetArgStr(index); - size_t bad_pos = str.find_first_not_of(Wing::CONTROL_LEGAL_FLAGS); - const int MSG_LEN = 300; - char msg_buf[MSG_LEN] = ""; - if (bad_pos == 0) + int Parser::ParseArgInt(const char *str) { - snprintf(msg_buf, MSG_LEN, "Invalid argument ~%d 'control surface' (value: %s), allowed are: <%s>, ignoring...", - index + 1, str.c_str(), Wing::CONTROL_LEGAL_FLAGS.c_str()); - this->AddMessage(Message::TYPE_ERROR, msg_buf); - return Wing::CONTROL_n_NONE; + return static_cast(this->ParseArgUint(str)); } - if (str.size() > 1) + + bool Parser::GetArgBool(int index) { - snprintf(msg_buf, MSG_LEN, "Argument ~%d 'control surface' (value: %s), should be only 1 letter.", index, str.c_str()); - this->AddMessage(Message::TYPE_WARNING, msg_buf); + return Ogre::StringConverter::parseBool(this->GetArgStr(index)); } - return Wing::Control(str.at(0)); -} - -std::string Parser::GetArgManagedTex(int index) -{ - std::string tex_name = this->GetArgStr(index); - return (tex_name.at(0) != '-') ? tex_name : ""; -} -int Parser::TokenizeCurrentLine() -{ - int cur_arg = 0; - const char* cur_char = m_current_line; - int arg_len = 0; - while ((*cur_char != '\0') && (cur_arg < Parser::LINE_MAX_ARGS)) + Wing::Control Parser::GetArgWingSurface(int index) { - const bool is_arg = !IsSeparator(*cur_char); - if ((arg_len == 0) && is_arg) - { - m_args[cur_arg].start = cur_char; - arg_len = 1; - } - else if ((arg_len > 0) && !is_arg) + std::string str = this->GetArgStr(index); + size_t bad_pos = str.find_first_not_of(Wing::CONTROL_LEGAL_FLAGS); + const int MSG_LEN = 300; + char msg_buf[MSG_LEN] = ""; + if (bad_pos == 0) { - m_args[cur_arg].length = arg_len; - arg_len = 0; - ++cur_arg; + snprintf(msg_buf, MSG_LEN, "Invalid argument ~%d 'control surface' (value: %s), allowed are: <%s>, ignoring...", + index + 1, str.c_str(), Wing::CONTROL_LEGAL_FLAGS.c_str()); + this->AddMessage(Message::TYPE_ERROR, msg_buf); + return Wing::CONTROL_n_NONE; } - else if (is_arg) + if (str.size() > 1) { - ++arg_len; + snprintf(msg_buf, MSG_LEN, "Argument ~%d 'control surface' (value: %s), should be only 1 letter.", index, + str.c_str()); + this->AddMessage(Message::TYPE_WARNING, msg_buf); } - ++cur_char; + return Wing::Control(str.at(0)); } - if (arg_len > 0) + + std::string Parser::GetArgManagedTex(int index) { - m_args[cur_arg].length = arg_len; - ++cur_arg; + std::string tex_name = this->GetArgStr(index); + return (tex_name.at(0) != '-') ? tex_name : ""; } - m_num_args = cur_arg; - return cur_arg; -} - -void Parser::ProcessOgreStream(Ogre::DataStream* stream, Ogre::String resource_group) -{ - m_resource_group = resource_group; - - char raw_line_buf[LINE_BUFFER_LENGTH]; - while (!stream->eof()) + int Parser::TokenizeCurrentLine() { - try + int cur_arg = 0; + const char *cur_char = m_current_line; + int arg_len = 0; + while ((*cur_char != '\0') && (cur_arg < Parser::LINE_MAX_ARGS)) { - stream->readLine(raw_line_buf, LINE_BUFFER_LENGTH); + const bool is_arg = !IsSeparator(*cur_char); + if ((arg_len == 0) && is_arg) + { + m_args[cur_arg].start = cur_char; + arg_len = 1; + } + else if ((arg_len > 0) && !is_arg) + { + m_args[cur_arg].length = arg_len; + arg_len = 0; + ++cur_arg; + } + else if (is_arg) + { + ++arg_len; + } + ++cur_char; } - catch (Ogre::Exception &ex) + if (arg_len > 0) { - std::string msg = "Error reading truckfile! Message:\n"; - msg += ex.getFullDescription(); - this->AddMessage(Message::TYPE_FATAL_ERROR, msg.c_str()); - break; + m_args[cur_arg].length = arg_len; + ++cur_arg; } - this->ProcessRawLine(raw_line_buf); + m_num_args = cur_arg; + return cur_arg; } -} - -void Parser::ProcessRawLine(const char* raw_line_buf) -{ - const char* raw_start = raw_line_buf; - const char* raw_end = raw_line_buf + strnlen(raw_line_buf, LINE_BUFFER_LENGTH); - // Trim leading whitespace - while (IsWhitespace(*raw_start) && (raw_start != raw_end)) + void Parser::ProcessOgreStream(Ogre::DataStream *stream, Ogre::String resource_group) { - ++raw_start; + m_resource_group = resource_group; + + char raw_line_buf[LINE_BUFFER_LENGTH]; + while (!stream->eof()) + { + try + { + stream->readLine(raw_line_buf, LINE_BUFFER_LENGTH); + } + catch (Ogre::Exception &ex) + { + std::string msg = "Error reading truckfile! Message:\n"; + msg += ex.getFullDescription(); + this->AddMessage(Message::TYPE_FATAL_ERROR, msg.c_str()); + break; + } + + this->ProcessRawLine(raw_line_buf); + } } - // Skip empty/comment lines - if ((raw_start == raw_end) || (*raw_start == ';') || (*raw_start == '/')) + void Parser::ProcessRawLine(const char *raw_line_buf) { - ++m_current_line_number; - return; - } + const char *raw_start = raw_line_buf; + const char *raw_end = raw_line_buf + strnlen(raw_line_buf, LINE_BUFFER_LENGTH); + + // Trim leading whitespace + while (IsWhitespace(*raw_start) && (raw_start != raw_end)) + { + ++raw_start; + } + + // Skip empty/comment lines + if ((raw_start == raw_end) || (*raw_start == ';') || (*raw_start == '/')) + { + ++m_current_line_number; + return; + } - // Sanitize UTF-8 - memset(m_current_line, 0, LINE_BUFFER_LENGTH); - char* out_start = m_current_line; - utf8::replace_invalid(raw_start, raw_end, out_start, '?'); + // Sanitize UTF-8 + memset(m_current_line, 0, LINE_BUFFER_LENGTH); + char *out_start = m_current_line; + utf8::replace_invalid(raw_start, raw_end, out_start, '?'); - // Process - this->ProcessCurrentLine(); - ++m_current_line_number; -} + // Process + this->ProcessCurrentLine(); + ++m_current_line_number; + } } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Parser.h b/source/main/resources/rig_def_fileformat/RigDef_Parser.h index daf0315da7..90a24e1eeb 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Parser.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Parser.h @@ -25,301 +25,312 @@ #pragma once -#include "RigDef_Prerequisites.h" #include "RigDef_File.h" +#include "RigDef_Prerequisites.h" #include "RigDef_SequentialImporter.h" #include -#include #include +#include namespace RigDef { -/// @class Parser -/// @author Petr Ohlidal -/// -/// @brief Checks the rig-def file syntax and pulls data to File object -/// -/// For every section/directive, there is a data-container struct defined in File.h. -/// The Parser should preferably only read data as-is, without validation. -/// -/// Every time a line of a particular section is parsed, an instance of the struct -/// is saved into an array container in struct RigDef::File. There are exceptions to this rule. -/// -/// Keywords 'set_[node|beam|inertia]_defaults' are 'presets' and are managed by dyn. allocated -/// objects. For every preset, there are 2 pointers: -/// * 'ror_*' represents game defaults as specified in documentation. Needed for resetting. -/// * 'user_*' represent the last defaults specified in the .truck file. -class Parser -{ - -public: + /// @class Parser + /// @author Petr Ohlidal + /// + /// @brief Checks the rig-def file syntax and pulls data to File object + /// + /// For every section/directive, there is a data-container struct defined in File.h. + /// The Parser should preferably only read data as-is, without validation. + /// + /// Every time a line of a particular section is parsed, an instance of the struct + /// is saved into an array container in struct RigDef::File. There are exceptions to this rule. + /// + /// Keywords 'set_[node|beam|inertia]_defaults' are 'presets' and are managed by dyn. allocated + /// objects. For every preset, there are 2 pointers: + /// * 'ror_*' represents game defaults as specified in documentation. Needed for resetting. + /// * 'user_*' represent the last defaults specified in the .truck file. + class Parser + { - static const int LINE_BUFFER_LENGTH = 2000; - static const int LINE_MAX_ARGS = 100; + public: + static const int LINE_BUFFER_LENGTH = 2000; + static const int LINE_MAX_ARGS = 100; - struct Message - { - enum Type + struct Message { - TYPE_WARNING, - TYPE_ERROR, - TYPE_FATAL_ERROR, + enum Type + { + TYPE_WARNING, + TYPE_ERROR, + TYPE_FATAL_ERROR, + + TYPE_INVALID = 0xFFFFFFFF + }; + + std::string line; + unsigned int line_number; + std::string message; + File::Section section; + File::Subsection subsection; + Type type; + Ogre::String module; + }; - TYPE_INVALID = 0xFFFFFFFF + struct Token + { + const char *start; + int length; }; - std::string line; - unsigned int line_number; - std::string message; - File::Section section; - File::Subsection subsection; - Type type; - Ogre::String module; - }; + Parser(); - struct Token - { - const char* start; - int length; - }; + void Prepare(); + void Finalize(); + void ProcessOgreStream(Ogre::DataStream *stream, Ogre::String resource_group); + void ProcessRawLine(const char *line); - Parser(); + std::list const &GetMessages() + { + return m_messages; + } - void Prepare(); - void Finalize(); - void ProcessOgreStream(Ogre::DataStream* stream, Ogre::String resource_group); - void ProcessRawLine(const char* line); + std::shared_ptr GetFile() + { + return m_definition; + } - std::list const & GetMessages() - { - return m_messages; - } + SequentialImporter *GetSequentialImporter() + { + return &m_sequential_importer; + } - std::shared_ptr GetFile() - { - return m_definition; - } - - SequentialImporter* GetSequentialImporter() { return &m_sequential_importer; } - - std::string ProcessMessagesToString(); - - int GetMessagesNumErrors() const { return m_messages_num_errors; } - int GetMessagesNumWarnings() const { return m_messages_num_warnings; } - int GetMessagesNumOther() const { return m_messages_num_other; } - -private: - -// -------------------------------------------------------------------------- -// Directive parsers -// -------------------------------------------------------------------------- - - void ProcessGlobalDirective(File::Keyword keyword); ///< Directives that should only appear in root module - void ParseDirectiveAddAnimation(); - void ParseDirectiveBackmesh(); - void ParseDirectiveDetacherGroup(); - void ParseDirectiveFlexbodyCameraMode(); - void ParseDirectivePropCameraMode(); - void ParseDirectiveSetBeamDefaults(); - void ParseDirectiveSetBeamDefaultsScale(); - void ParseDirectiveSetDefaultMinimass(); - void ParseDirectiveSetInertiaDefaults(); - void ParseDirectiveSetManagedMaterialsOptions(); - void ParseDirectiveSetNodeDefaults(); - void LogParsedDirectiveSetNodeDefaultsData(float loadweight, float friction, float volume, float surface, unsigned int options); - -// -------------------------------------------------------------------------- -// Section parsers -// -------------------------------------------------------------------------- - - void ParseActorNameLine(); - void ParseAirbrakes(); - void ParseAnimator(); - void ParseAntiLockBrakes(); - void ParseAuthor(); - void ParseAxles(); - void ParseBeams(); - void ParseBrakes(); - void ProcessKeywordCab(); - void ParseCameras(); - void ParseCameraRails(); - void ParseCinecam(); - void ParseCollisionBox(); - void ParseCommandsUnified(); - void ParseContacter(); - void ParseCruiseControl(); - void ParseEngine(); - void ParseEngoption(); - void ParseEngturbo(); - void ParseExhaust(); - void ParseExtCamera(); - void ParseFileFormatVersion(); - void ParseFileinfo(); - void ParseFixes(); - void ParseFlaresUnified(); - void ParseFlexbody(); - void ParseFlexBodyWheel(); - void ParseFusedrag(); - void ParseGlobals(); - void ParseGuid(); - void ParseGuiSettings(); - void ParseHelp(); - void ParseHook(); - void ParseHydros(); - void ParseInterAxles(); - void ParseLockgroups(); - void ParseManagedMaterials(); - void ParseMaterialFlareBindings(); - void ParseMeshWheelUnified(); - void ParseMinimass(); - void ParseNodesUnified(); - void ParseNodeCollision(); - void ParseParticles(); - void ParsePistonprops(); - void ParseProps(); - void ParseRailGroups(); - void ParseRopables(); - void ParseRopes(); - void ParseRotatorsUnified(); - void ParseScrewprops(); - void ParseSetCollisionRange(); - void ParseSetSkeletonSettings(); - void ParseShock(); - void ParseShock2(); - void ParseShock3(); - void ParseSlidenodes(); - void ParseSlopeBrake(); - void ParseSoundsources(); - void ParseSoundsources2(); - void ParseSpeedLimiter(); - void ParseSubmesh(); - void ParseSubmeshGroundModel(); - void ProcessKeywordTexcoords(); - void ParseTies(); - void ParseTorqueCurve(); - void ParseTractionControl(); - void ParseTransferCase(); - void ParseTriggers(); - void ParseTurbojets(); - void ParseTurbopropsUnified(); - void ParseVideoCamera(); - void ParseWheelDetachers(); - void ParseWheel(); - void ParseWheel2(); - void ParseWing(); - -// -------------------------------------------------------------------------- -// Utilities -// -------------------------------------------------------------------------- - - void ProcessCurrentLine(); - int TokenizeCurrentLine(); - bool CheckNumArguments(int num_required_args); - void ChangeSection(RigDef::File::Section new_section); - void ProcessChangeModuleLine(File::Keyword keyword); - - std::string GetArgStr (int index); - int GetArgInt (int index); - unsigned GetArgUint (int index); - long GetArgLong (int index); - float GetArgFloat (int index); - char GetArgChar (int index); - bool GetArgBool (int index); - Wheels::Propulsion GetArgPropulsion (int index); - Wheels::Braking GetArgBraking (int index); - Node::Ref GetArgNodeRef (int index); - Node::Ref GetArgRigidityNode (int index); - Node::Ref GetArgNullableNode (int index); - MeshWheel::Side GetArgWheelSide (int index); - Wing::Control GetArgWingSurface (int index); - Flare2::Type GetArgFlareType (int index); - std::string GetArgManagedTex (int index); - - float ParseArgFloat (const char* str); - int ParseArgInt (const char* str); - unsigned ParseArgUint (const char* str); - - unsigned ParseArgUint (const std::string& s); - float ParseArgFloat (const std::string& s); - - void _CheckInvalidTrailingText(Ogre::String const & line, std::smatch const & results, unsigned int index); - - /// Keyword scan function. - File::Keyword IdentifyKeywordInCurrentLine(); - - /// Keyword scan utility function. - File::Keyword FindKeywordMatch(std::smatch& search_results); - - /// Adds a message to parser report. - void AddMessage(std::string const & line, Message::Type type, std::string const & message); - void AddMessage(Message::Type type, const char* msg) - { - this->AddMessage(m_current_line, type, msg); - } - void AddMessage(Message::Type type, std::string const & msg) - { - this->AddMessage(m_current_line, type, msg); - } - void VerifyModuleIsRoot(File::Keyword keyword); ///< Reports warning message if we're not in root module + std::string ProcessMessagesToString(); - /// Print a log INFO message. - void _PrintNodeDataForVerification(Ogre::String& line, Ogre::StringVector& args, int num_args, Node& node); + int GetMessagesNumErrors() const + { + return m_messages_num_errors; + } + int GetMessagesNumWarnings() const + { + return m_messages_num_warnings; + } + int GetMessagesNumOther() const + { + return m_messages_num_other; + } + + private: + // -------------------------------------------------------------------------- + // Directive parsers + // -------------------------------------------------------------------------- + + void ProcessGlobalDirective(File::Keyword keyword); ///< Directives that should only appear in root module + void ParseDirectiveAddAnimation(); + void ParseDirectiveBackmesh(); + void ParseDirectiveDetacherGroup(); + void ParseDirectiveFlexbodyCameraMode(); + void ParseDirectivePropCameraMode(); + void ParseDirectiveSetBeamDefaults(); + void ParseDirectiveSetBeamDefaultsScale(); + void ParseDirectiveSetDefaultMinimass(); + void ParseDirectiveSetInertiaDefaults(); + void ParseDirectiveSetManagedMaterialsOptions(); + void ParseDirectiveSetNodeDefaults(); + void LogParsedDirectiveSetNodeDefaultsData(float loadweight, float friction, float volume, float surface, + unsigned int options); + + // -------------------------------------------------------------------------- + // Section parsers + // -------------------------------------------------------------------------- + + void ParseActorNameLine(); + void ParseAirbrakes(); + void ParseAnimator(); + void ParseAntiLockBrakes(); + void ParseAuthor(); + void ParseAxles(); + void ParseBeams(); + void ParseBrakes(); + void ProcessKeywordCab(); + void ParseCameras(); + void ParseCameraRails(); + void ParseCinecam(); + void ParseCollisionBox(); + void ParseCommandsUnified(); + void ParseContacter(); + void ParseCruiseControl(); + void ParseEngine(); + void ParseEngoption(); + void ParseEngturbo(); + void ParseExhaust(); + void ParseExtCamera(); + void ParseFileFormatVersion(); + void ParseFileinfo(); + void ParseFixes(); + void ParseFlaresUnified(); + void ParseFlexbody(); + void ParseFlexBodyWheel(); + void ParseFusedrag(); + void ParseGlobals(); + void ParseGuid(); + void ParseGuiSettings(); + void ParseHelp(); + void ParseHook(); + void ParseHydros(); + void ParseInterAxles(); + void ParseLockgroups(); + void ParseManagedMaterials(); + void ParseMaterialFlareBindings(); + void ParseMeshWheelUnified(); + void ParseMinimass(); + void ParseNodesUnified(); + void ParseNodeCollision(); + void ParseParticles(); + void ParsePistonprops(); + void ParseProps(); + void ParseRailGroups(); + void ParseRopables(); + void ParseRopes(); + void ParseRotatorsUnified(); + void ParseScrewprops(); + void ParseSetCollisionRange(); + void ParseSetSkeletonSettings(); + void ParseShock(); + void ParseShock2(); + void ParseShock3(); + void ParseSlidenodes(); + void ParseSlopeBrake(); + void ParseSoundsources(); + void ParseSoundsources2(); + void ParseSpeedLimiter(); + void ParseSubmesh(); + void ParseSubmeshGroundModel(); + void ProcessKeywordTexcoords(); + void ParseTies(); + void ParseTorqueCurve(); + void ParseTractionControl(); + void ParseTransferCase(); + void ParseTriggers(); + void ParseTurbojets(); + void ParseTurbopropsUnified(); + void ParseVideoCamera(); + void ParseWheelDetachers(); + void ParseWheel(); + void ParseWheel2(); + void ParseWing(); + + // -------------------------------------------------------------------------- + // Utilities + // -------------------------------------------------------------------------- + + void ProcessCurrentLine(); + int TokenizeCurrentLine(); + bool CheckNumArguments(int num_required_args); + void ChangeSection(RigDef::File::Section new_section); + void ProcessChangeModuleLine(File::Keyword keyword); + + std::string GetArgStr(int index); + int GetArgInt(int index); + unsigned GetArgUint(int index); + long GetArgLong(int index); + float GetArgFloat(int index); + char GetArgChar(int index); + bool GetArgBool(int index); + Wheels::Propulsion GetArgPropulsion(int index); + Wheels::Braking GetArgBraking(int index); + Node::Ref GetArgNodeRef(int index); + Node::Ref GetArgRigidityNode(int index); + Node::Ref GetArgNullableNode(int index); + MeshWheel::Side GetArgWheelSide(int index); + Wing::Control GetArgWingSurface(int index); + Flare2::Type GetArgFlareType(int index); + std::string GetArgManagedTex(int index); + + float ParseArgFloat(const char *str); + int ParseArgInt(const char *str); + unsigned ParseArgUint(const char *str); + + unsigned ParseArgUint(const std::string &s); + float ParseArgFloat(const std::string &s); + + void _CheckInvalidTrailingText(Ogre::String const &line, std::smatch const &results, unsigned int index); + + /// Keyword scan function. + File::Keyword IdentifyKeywordInCurrentLine(); + + /// Keyword scan utility function. + File::Keyword FindKeywordMatch(std::smatch &search_results); + + /// Adds a message to parser report. + void AddMessage(std::string const &line, Message::Type type, std::string const &message); + void AddMessage(Message::Type type, const char *msg) + { + this->AddMessage(m_current_line, type, msg); + } + void AddMessage(Message::Type type, std::string const &msg) + { + this->AddMessage(m_current_line, type, msg); + } + void VerifyModuleIsRoot(File::Keyword keyword); ///< Reports warning message if we're not in root module + + /// Print a log INFO message. + void _PrintNodeDataForVerification(Ogre::String &line, Ogre::StringVector &args, int num_args, Node &node); - static void _TrimTrailingComments(std::string const & line_in, std::string & line_out); + static void _TrimTrailingComments(std::string const &line_in, std::string &line_out); - Node::Ref _ParseNodeRef(std::string const & node_id_str); + Node::Ref _ParseNodeRef(std::string const &node_id_str); - void _ParseCameraSettings(CameraSettings & camera_settings, Ogre::String input_str); + void _ParseCameraSettings(CameraSettings &camera_settings, Ogre::String input_str); - void _ParseNodeOptions(unsigned int & options, const std::string & options_str); + void _ParseNodeOptions(unsigned int &options, const std::string &options_str); - void ParseOptionalInertia(Inertia& inertia, int index); + void ParseOptionalInertia(Inertia &inertia, int index); -// -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - // RoR defaults + // RoR defaults - std::shared_ptr m_ror_default_inertia; - std::shared_ptr m_ror_node_defaults; - std::shared_ptr m_ror_minimass; + std::shared_ptr m_ror_default_inertia; + std::shared_ptr m_ror_node_defaults; + std::shared_ptr m_ror_minimass; - // Data from user directives - // Each affected section-struct has a shared_ptr to it's respective defaults - std::shared_ptr m_user_default_inertia; - std::shared_ptr m_user_beam_defaults; - std::shared_ptr m_user_node_defaults; - std::shared_ptr m_user_minimass; - int m_current_detacher_group; - ManagedMaterialsOptions m_current_managed_material_options; + // Data from user directives + // Each affected section-struct has a shared_ptr to it's respective defaults + std::shared_ptr m_user_default_inertia; + std::shared_ptr m_user_beam_defaults; + std::shared_ptr m_user_node_defaults; + std::shared_ptr m_user_minimass; + int m_current_detacher_group; + ManagedMaterialsOptions m_current_managed_material_options; - // Parser state - std::shared_ptr m_root_module; - std::shared_ptr m_current_module; + // Parser state + std::shared_ptr m_root_module; + std::shared_ptr m_current_module; - unsigned int m_current_line_number; - char m_current_line[LINE_BUFFER_LENGTH]; - Token m_args[LINE_MAX_ARGS]; ///< Tokens of current line. - int m_num_args; ///< Number of tokens on current line. - File::Section m_current_section; ///< Parser state. - File::Subsection m_current_subsection; ///< Parser state. - bool m_in_block_comment; ///< Parser state. - bool m_in_description_section; ///< Parser state. - bool m_any_named_node_defined; ///< Parser state. - std::shared_ptr m_current_submesh; ///< Parser state. - std::shared_ptr m_current_camera_rail; ///< Parser state. - std::shared_ptr m_last_flexbody; + unsigned int m_current_line_number; + char m_current_line[LINE_BUFFER_LENGTH]; + Token m_args[LINE_MAX_ARGS]; ///< Tokens of current line. + int m_num_args; ///< Number of tokens on current line. + File::Section m_current_section; ///< Parser state. + File::Subsection m_current_subsection; ///< Parser state. + bool m_in_block_comment; ///< Parser state. + bool m_in_description_section; ///< Parser state. + bool m_any_named_node_defined; ///< Parser state. + std::shared_ptr m_current_submesh; ///< Parser state. + std::shared_ptr m_current_camera_rail; ///< Parser state. + std::shared_ptr m_last_flexbody; - SequentialImporter m_sequential_importer; + SequentialImporter m_sequential_importer; - Ogre::String m_resource_group; + Ogre::String m_resource_group; - std::shared_ptr m_definition; - std::list m_messages; - int m_messages_num_errors; - int m_messages_num_warnings; - int m_messages_num_other; -}; + std::shared_ptr m_definition; + std::list m_messages; + int m_messages_num_errors; + int m_messages_num_warnings; + int m_messages_num_other; + }; } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Prerequisites.h b/source/main/resources/rig_def_fileformat/RigDef_Prerequisites.h index a417a57865..d79dbe0a7c 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Prerequisites.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Prerequisites.h @@ -28,60 +28,61 @@ namespace Ogre class DataStream; } -namespace RigDef { +namespace RigDef +{ -// File structures declarations -// TODO: Complete list + // File structures declarations + // TODO: Complete list -struct AeroAnimator; -struct Airbrake; -struct Animation; -struct AntiLockBrakes; -struct Axle; -struct Beam; -struct BeamDefaults; -struct BeamDefaultsScale; -struct Brakes; -struct Cab; -struct CameraRail; -struct CameraSettings; -struct Cinecam; -struct CollisionBox; -struct Command2; -struct CruiseControl; -struct Engine; -struct Engoption; -struct Engturbo; -struct ExtCamera; -struct File; -struct Flare; -struct Flare2; -struct Flexbody; -struct FlexBodyWheel; -struct Fusedrag; -struct Globals; -struct GuiSettings; -struct Hook; -struct Hydro; -struct Inertia; -struct Lockgroup; -struct ManagedMaterialsOptions; -struct MeshWheel; -struct MinimassPreset; -struct Node; -struct NodeDefaults; -struct Particle; -struct Pistonprop; -struct Prop; -struct RailGroup; -struct Ropable; -struct ShadowOptions; -struct VideoCamera; + struct AeroAnimator; + struct Airbrake; + struct Animation; + struct AntiLockBrakes; + struct Axle; + struct Beam; + struct BeamDefaults; + struct BeamDefaultsScale; + struct Brakes; + struct Cab; + struct CameraRail; + struct CameraSettings; + struct Cinecam; + struct CollisionBox; + struct Command2; + struct CruiseControl; + struct Engine; + struct Engoption; + struct Engturbo; + struct ExtCamera; + struct File; + struct Flare; + struct Flare2; + struct Flexbody; + struct FlexBodyWheel; + struct Fusedrag; + struct Globals; + struct GuiSettings; + struct Hook; + struct Hydro; + struct Inertia; + struct Lockgroup; + struct ManagedMaterialsOptions; + struct MeshWheel; + struct MinimassPreset; + struct Node; + struct NodeDefaults; + struct Particle; + struct Pistonprop; + struct Prop; + struct RailGroup; + struct Ropable; + struct ShadowOptions; + struct VideoCamera; -// Parser classes + // Parser classes -class Parser; -class Validator; -class SequentialImporter; + class Parser; + class Validator; + class SequentialImporter; } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Regexes.h b/source/main/resources/rig_def_fileformat/RigDef_Regexes.h index 7f3dd9dec5..f448cdc394 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Regexes.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Regexes.h @@ -37,7 +37,8 @@ something? Match something 0 or 1 times (stuff) Subsection. Can be manipulates as 'something'. Also works as a Capture | Alternation character. (abc|cba) means abc OR cba. - [:some_type:] A POSIX character class. Read this: http://www.boost.org/doc/libs/1_54_0/libs/regex/doc/html/boost_regex/syntax/character_classes.html + [:some_type:] A POSIX character class. Read this: + http://www.boost.org/doc/libs/1_54_0/libs/regex/doc/html/boost_regex/syntax/character_classes.html REGEX NAMING CONVENTION: E_* ~ Re-usable regexes or macros. @@ -55,23 +56,23 @@ namespace RigDef { -namespace Regexes -{ + namespace Regexes + { -// -------------------------------------------------------------------------- // -// Repeatedly used bits of regular expressions // -// Using #define-s instead of const vars to utilize C-string concatenation // -// REMEMBER! Do not use captures () - they would mess up result order. Use | // -// REMEMBER! Expressions using | MUST be enclosed in E_CAPTURE() // -// -------------------------------------------------------------------------- // + // -------------------------------------------------------------------------- // + // Repeatedly used bits of regular expressions // + // Using #define-s instead of const vars to utilize C-string concatenation // + // REMEMBER! Do not use captures () - they would mess up result order. Use | // + // REMEMBER! Expressions using | MUST be enclosed in E_CAPTURE() // + // -------------------------------------------------------------------------- // -// CHARACTERS + // CHARACTERS #define E_BACKSLASH "\\\\" // Each backslash \ must be escaped in C++ (\\) and then in regex (\\\\) #define E_SLASH "\\/" -// NUMBERS + // NUMBERS #define E_DECIMAL_NUMBER "-?[[:digit:]]+" @@ -83,19 +84,17 @@ namespace Regexes #define E_REAL_NUMBER_WITH_EXPONENT_NO_FRACTION "-?[[:digit:]]*[eE][-+]?[[:digit:]]+" -// NOTE: Intentionally accepting format "1." for backwards compatibility, observed in http://www.rigsofrods.org/repository/view/2389 +// NOTE: Intentionally accepting format "1." for backwards compatibility, observed in +// http://www.rigsofrods.org/repository/view/2389 #define E_REAL_NUMBER_SIMPLE "-?[[:digit:]]*\\.[[:digit:]]*" -//NOTE: Uses |, MUST be enclosed in E_CAPTURE() -#define E_REAL_NUMBER \ - E_REAL_NUMBER_WITH_EXPONENT E_OR \ - E_REAL_NUMBER_WITH_EXPONENT_NO_FRACTION E_OR \ - E_REAL_NUMBER_SIMPLE E_OR \ - E_DECIMAL_NUMBER +// NOTE: Uses |, MUST be enclosed in E_CAPTURE() +#define E_REAL_NUMBER \ + E_REAL_NUMBER_WITH_EXPONENT E_OR E_REAL_NUMBER_WITH_EXPONENT_NO_FRACTION E_OR E_REAL_NUMBER_SIMPLE E_OR E_DECIMAL_NUMBER -#define E_MINUS_ONE_REAL "-1\\.[0]*|-1" // Uses |, MUST be enclosed in E_CAPTURE() +#define E_MINUS_ONE_REAL "-1\\.[0]*|-1" // Uses |, MUST be enclosed in E_CAPTURE() -// STRINGS + // STRINGS #define E_ILLEGAL_TRAILING_STRING "[^[:blank:]]+.*" @@ -111,7 +110,7 @@ namespace Regexes #define E_OPTIONAL_SPACE "[[:blank:]]*" -// DELIMITERS + // DELIMITERS #define E_OR "|" @@ -129,7 +128,7 @@ namespace Regexes // Multiple delimiters in row are merged into one (backwards compatibility) #define E_DELIMITER "[[:blank:],]+" -// VALUE TYPES + // VALUE TYPES #define E_BOOLEAN "true|yes|1|false|no|0" // Uses |, MUST be enclosed in E_CAPTURE() @@ -140,242 +139,198 @@ namespace Regexes #define E_INERTIA_FUNCTION E_STRING_ALNUM_HYPHENS_USCORES_ONLY // -------------------------------------------------------------------------- -// Macros +// Macros // -------------------------------------------------------------------------- /// Encloses expression in 'capture' marks. -#define E_CAPTURE(_REGEXP_) \ - "(" _REGEXP_ ")" +#define E_CAPTURE(_REGEXP_) "(" _REGEXP_ ")" /// Encloses expression in 'capture' marks with ? (zero or one time) mark. -#define E_CAPTURE_OPTIONAL(_REGEXP_) \ - "(" _REGEXP_ ")?" +#define E_CAPTURE_OPTIONAL(_REGEXP_) "(" _REGEXP_ ")?" /// A keyword which should be on it's own line. Used in IDENTIFY_KEYWORD. -#define E_KEYWORD_BLOCK(_NAME_) \ - "(^" _NAME_ "[[:blank:]]*$)?" +#define E_KEYWORD_BLOCK(_NAME_) "(^" _NAME_ "[[:blank:]]*$)?" /// A keyword which should have values following it. Used in IDENTIFY_KEYWORD. -#define E_KEYWORD_INLINE(_NAME_) \ - "(^" _NAME_ E_DELIMITER_SPACE ".*$)?" - +#define E_KEYWORD_INLINE(_NAME_) "(^" _NAME_ E_DELIMITER_SPACE ".*$)?" + /// Inline keyword, tolerant version: keyword and values can be delimited by either space or comma -#define E_KEYWORD_INLINE_TOLERANT(_NAME_) \ - "(^" _NAME_ "[[:blank:],]+" ".*$)?" - -#define E_DELIMITED_LIST( _VALUE_, _DELIMITER_ ) \ - E_CAPTURE( \ - E_OPTIONAL_SPACE \ - _VALUE_ \ - E_OPTIONAL_SPACE \ - _DELIMITER_ \ - ) "*" \ - E_CAPTURE( \ - E_OPTIONAL_SPACE \ - _VALUE_ \ - E_OPTIONAL_SPACE \ - ) "+" +#define E_KEYWORD_INLINE_TOLERANT(_NAME_) \ + "(^" _NAME_ "[[:blank:],]+" \ + ".*$)?" + +#define E_DELIMITED_LIST(_VALUE_, _DELIMITER_) \ + E_CAPTURE(E_OPTIONAL_SPACE _VALUE_ E_OPTIONAL_SPACE _DELIMITER_) "*" E_CAPTURE(E_OPTIONAL_SPACE _VALUE_ E_OPTIONAL_SPACE) "+" /// Actual regex definition macro. -#define DEFINE_REGEX(_NAME_,_REGEXP_) \ - const std::regex _NAME_ = std::regex( _REGEXP_, std::regex::ECMAScript); +#define DEFINE_REGEX(_NAME_, _REGEXP_) const std::regex _NAME_ = std::regex(_REGEXP_, std::regex::ECMAScript); -#define DEFINE_REGEX_IGNORECASE(_NAME_,_REGEXP_) \ - const std::regex _NAME_ = std::regex( _REGEXP_, std::regex::ECMAScript | std::regex::icase); +#define DEFINE_REGEX_IGNORECASE(_NAME_, _REGEXP_) \ + const std::regex _NAME_ = std::regex(_REGEXP_, std::regex::ECMAScript | std::regex::icase); // -------------------------------------------------------------------------- // // Utility regexes // // -------------------------------------------------------------------------- // // IMPORTANT! If you add a value here, you must also modify File::Keywords enum, it relies on positions in this regex -#define IDENTIFY_KEYWORD_REGEX_STRING \ - /* E_KEYWORD_BLOCK("advdrag") ~~ Not supported yet */ \ - E_KEYWORD_INLINE_TOLERANT("add_animation") /* Position 1 */ \ - E_KEYWORD_BLOCK("airbrakes") /* Position 2 */ \ - E_KEYWORD_BLOCK("animators") /* Position 3 etc... */ \ - E_KEYWORD_INLINE("AntiLockBrakes") \ - E_KEYWORD_BLOCK("axles") \ - E_KEYWORD_INLINE("author") \ - E_KEYWORD_BLOCK("backmesh") \ - E_KEYWORD_BLOCK("beams") \ - E_KEYWORD_BLOCK("brakes") \ - E_KEYWORD_BLOCK("cab") \ - E_KEYWORD_BLOCK("camerarail") \ - E_KEYWORD_BLOCK("cameras") \ - E_KEYWORD_BLOCK("cinecam") \ - E_KEYWORD_BLOCK("collisionboxes") \ - E_KEYWORD_BLOCK("commands") \ - E_KEYWORD_BLOCK("commands2") \ - E_KEYWORD_BLOCK("contacters") \ - E_KEYWORD_INLINE("cruisecontrol") \ - E_KEYWORD_BLOCK("description") \ - E_KEYWORD_INLINE("detacher_group") \ - E_KEYWORD_BLOCK("disabledefaultsounds") \ - E_KEYWORD_BLOCK("enable_advanced_deformation") \ - E_KEYWORD_BLOCK("end") \ - E_KEYWORD_BLOCK("end_section") \ - E_KEYWORD_BLOCK("engine") \ - E_KEYWORD_BLOCK("engoption") \ - E_KEYWORD_BLOCK("engturbo") \ - E_KEYWORD_BLOCK("envmap") \ - E_KEYWORD_BLOCK("exhausts") \ - E_KEYWORD_INLINE("extcamera") \ - E_KEYWORD_INLINE("fileformatversion") \ - E_KEYWORD_INLINE("fileinfo") \ - E_KEYWORD_BLOCK("fixes") \ - E_KEYWORD_BLOCK("flares") \ - E_KEYWORD_BLOCK("flares2") \ - E_KEYWORD_BLOCK("flexbodies") \ - E_KEYWORD_INLINE("flexbody_camera_mode") \ - E_KEYWORD_BLOCK("flexbodywheels") \ - E_KEYWORD_BLOCK("forwardcommands") \ - E_KEYWORD_BLOCK("fusedrag") \ - E_KEYWORD_BLOCK("globals") \ - E_KEYWORD_INLINE("guid") \ - E_KEYWORD_BLOCK("guisettings") \ - E_KEYWORD_BLOCK("help") \ - E_KEYWORD_BLOCK("hideInChooser") \ - E_KEYWORD_BLOCK("hookgroup") \ - E_KEYWORD_BLOCK("hooks") \ - E_KEYWORD_BLOCK("hydros") \ - E_KEYWORD_BLOCK("importcommands") \ - E_KEYWORD_BLOCK("interaxles") \ - E_KEYWORD_BLOCK("lockgroups") \ - E_KEYWORD_BLOCK("lockgroup_default_nolock") \ - E_KEYWORD_BLOCK("managedmaterials") \ - E_KEYWORD_BLOCK("materialflarebindings") \ - E_KEYWORD_BLOCK("meshwheels") \ - E_KEYWORD_BLOCK("meshwheels2") \ - E_KEYWORD_BLOCK("minimass") \ - E_KEYWORD_BLOCK("nodecollision") \ - E_KEYWORD_BLOCK("nodes") \ - E_KEYWORD_BLOCK("nodes2") \ - E_KEYWORD_BLOCK("particles") \ - E_KEYWORD_BLOCK("pistonprops") \ - E_KEYWORD_INLINE("prop_camera_mode") \ - E_KEYWORD_BLOCK("props") \ - E_KEYWORD_BLOCK("railgroups") \ - E_KEYWORD_BLOCK("rescuer") \ - E_KEYWORD_BLOCK("rigidifiers") \ - E_KEYWORD_BLOCK("rollon") \ - E_KEYWORD_BLOCK("ropables") \ - E_KEYWORD_BLOCK("ropes") \ - E_KEYWORD_BLOCK("rotators") \ - E_KEYWORD_BLOCK("rotators2") \ - E_KEYWORD_BLOCK("screwprops") \ - E_KEYWORD_INLINE("section") \ - E_KEYWORD_INLINE("sectionconfig") \ - E_KEYWORD_INLINE("set_beam_defaults") \ - E_KEYWORD_INLINE("set_beam_defaults_scale") \ - E_KEYWORD_INLINE("set_collision_range") \ - E_KEYWORD_INLINE("set_default_minimass") \ - E_KEYWORD_INLINE("set_inertia_defaults") \ - E_KEYWORD_INLINE("set_managedmaterials_options") \ - E_KEYWORD_INLINE("set_node_defaults") \ - E_KEYWORD_BLOCK("set_shadows") \ - E_KEYWORD_INLINE("set_skeleton_settings") \ - E_KEYWORD_BLOCK("shocks") \ - E_KEYWORD_BLOCK("shocks2") \ - E_KEYWORD_BLOCK("shocks3") \ - E_KEYWORD_BLOCK("slidenode_connect_instantly") \ - E_KEYWORD_BLOCK("slidenodes") \ - E_KEYWORD_INLINE("SlopeBrake") \ - E_KEYWORD_BLOCK("soundsources") \ - E_KEYWORD_BLOCK("soundsources2") \ - E_KEYWORD_INLINE("speedlimiter") \ - /* E_KEYWORD_BLOCK("soundsources3") ~~ Not supported yet */ \ - E_KEYWORD_BLOCK("submesh") \ - E_KEYWORD_INLINE("submesh_groundmodel") \ - E_KEYWORD_BLOCK("texcoords") \ - E_KEYWORD_BLOCK("ties") \ - E_KEYWORD_BLOCK("torquecurve") \ - E_KEYWORD_INLINE("TractionControl") \ - E_KEYWORD_BLOCK("transfercase") \ - E_KEYWORD_BLOCK("triggers") \ - E_KEYWORD_BLOCK("turbojets") \ - E_KEYWORD_BLOCK("turboprops") \ - E_KEYWORD_BLOCK("turboprops2") \ - E_KEYWORD_BLOCK("videocamera") \ - E_KEYWORD_BLOCK("wheeldetachers") \ - E_KEYWORD_BLOCK("wheels") \ - E_KEYWORD_BLOCK("wheels2") \ +#define IDENTIFY_KEYWORD_REGEX_STRING \ + /* E_KEYWORD_BLOCK("advdrag") ~~ Not supported yet */ \ + E_KEYWORD_INLINE_TOLERANT("add_animation") /* Position 1 */ \ + E_KEYWORD_BLOCK("airbrakes") /* Position 2 */ \ + E_KEYWORD_BLOCK("animators") /* Position 3 etc... */ \ + E_KEYWORD_INLINE("AntiLockBrakes") \ + E_KEYWORD_BLOCK("axles") \ + E_KEYWORD_INLINE("author") \ + E_KEYWORD_BLOCK("backmesh") \ + E_KEYWORD_BLOCK("beams") \ + E_KEYWORD_BLOCK("brakes") \ + E_KEYWORD_BLOCK("cab") \ + E_KEYWORD_BLOCK("camerarail") \ + E_KEYWORD_BLOCK("cameras") \ + E_KEYWORD_BLOCK("cinecam") \ + E_KEYWORD_BLOCK("collisionboxes") \ + E_KEYWORD_BLOCK("commands") \ + E_KEYWORD_BLOCK("commands2") \ + E_KEYWORD_BLOCK("contacters") \ + E_KEYWORD_INLINE("cruisecontrol") \ + E_KEYWORD_BLOCK("description") \ + E_KEYWORD_INLINE("detacher_group") \ + E_KEYWORD_BLOCK("disabledefaultsounds") \ + E_KEYWORD_BLOCK("enable_advanced_deformation") \ + E_KEYWORD_BLOCK("end") \ + E_KEYWORD_BLOCK("end_section") \ + E_KEYWORD_BLOCK("engine") \ + E_KEYWORD_BLOCK("engoption") \ + E_KEYWORD_BLOCK("engturbo") \ + E_KEYWORD_BLOCK("envmap") \ + E_KEYWORD_BLOCK("exhausts") \ + E_KEYWORD_INLINE("extcamera") \ + E_KEYWORD_INLINE("fileformatversion") \ + E_KEYWORD_INLINE("fileinfo") \ + E_KEYWORD_BLOCK("fixes") \ + E_KEYWORD_BLOCK("flares") \ + E_KEYWORD_BLOCK("flares2") \ + E_KEYWORD_BLOCK("flexbodies") \ + E_KEYWORD_INLINE("flexbody_camera_mode") \ + E_KEYWORD_BLOCK("flexbodywheels") \ + E_KEYWORD_BLOCK("forwardcommands") \ + E_KEYWORD_BLOCK("fusedrag") \ + E_KEYWORD_BLOCK("globals") \ + E_KEYWORD_INLINE("guid") \ + E_KEYWORD_BLOCK("guisettings") \ + E_KEYWORD_BLOCK("help") \ + E_KEYWORD_BLOCK("hideInChooser") \ + E_KEYWORD_BLOCK("hookgroup") \ + E_KEYWORD_BLOCK("hooks") \ + E_KEYWORD_BLOCK("hydros") \ + E_KEYWORD_BLOCK("importcommands") \ + E_KEYWORD_BLOCK("interaxles") \ + E_KEYWORD_BLOCK("lockgroups") \ + E_KEYWORD_BLOCK("lockgroup_default_nolock") \ + E_KEYWORD_BLOCK("managedmaterials") \ + E_KEYWORD_BLOCK("materialflarebindings") \ + E_KEYWORD_BLOCK("meshwheels") \ + E_KEYWORD_BLOCK("meshwheels2") \ + E_KEYWORD_BLOCK("minimass") \ + E_KEYWORD_BLOCK("nodecollision") \ + E_KEYWORD_BLOCK("nodes") \ + E_KEYWORD_BLOCK("nodes2") \ + E_KEYWORD_BLOCK("particles") \ + E_KEYWORD_BLOCK("pistonprops") \ + E_KEYWORD_INLINE("prop_camera_mode") \ + E_KEYWORD_BLOCK("props") \ + E_KEYWORD_BLOCK("railgroups") \ + E_KEYWORD_BLOCK("rescuer") \ + E_KEYWORD_BLOCK("rigidifiers") \ + E_KEYWORD_BLOCK("rollon") \ + E_KEYWORD_BLOCK("ropables") \ + E_KEYWORD_BLOCK("ropes") \ + E_KEYWORD_BLOCK("rotators") \ + E_KEYWORD_BLOCK("rotators2") \ + E_KEYWORD_BLOCK("screwprops") \ + E_KEYWORD_INLINE("section") \ + E_KEYWORD_INLINE("sectionconfig") \ + E_KEYWORD_INLINE("set_beam_defaults") \ + E_KEYWORD_INLINE("set_beam_defaults_scale") \ + E_KEYWORD_INLINE("set_collision_range") \ + E_KEYWORD_INLINE("set_default_minimass") \ + E_KEYWORD_INLINE("set_inertia_defaults") \ + E_KEYWORD_INLINE("set_managedmaterials_options") \ + E_KEYWORD_INLINE("set_node_defaults") \ + E_KEYWORD_BLOCK("set_shadows") \ + E_KEYWORD_INLINE("set_skeleton_settings") \ + E_KEYWORD_BLOCK("shocks") \ + E_KEYWORD_BLOCK("shocks2") \ + E_KEYWORD_BLOCK("shocks3") \ + E_KEYWORD_BLOCK("slidenode_connect_instantly") \ + E_KEYWORD_BLOCK("slidenodes") \ + E_KEYWORD_INLINE("SlopeBrake") \ + E_KEYWORD_BLOCK("soundsources") \ + E_KEYWORD_BLOCK("soundsources2") \ + E_KEYWORD_INLINE("speedlimiter") \ + /* E_KEYWORD_BLOCK("soundsources3") ~~ Not supported yet */ \ + E_KEYWORD_BLOCK("submesh") \ + E_KEYWORD_INLINE("submesh_groundmodel") \ + E_KEYWORD_BLOCK("texcoords") \ + E_KEYWORD_BLOCK("ties") \ + E_KEYWORD_BLOCK("torquecurve") \ + E_KEYWORD_INLINE("TractionControl") \ + E_KEYWORD_BLOCK("transfercase") \ + E_KEYWORD_BLOCK("triggers") \ + E_KEYWORD_BLOCK("turbojets") \ + E_KEYWORD_BLOCK("turboprops") \ + E_KEYWORD_BLOCK("turboprops2") \ + E_KEYWORD_BLOCK("videocamera") \ + E_KEYWORD_BLOCK("wheeldetachers") \ + E_KEYWORD_BLOCK("wheels") \ + E_KEYWORD_BLOCK("wheels2") \ E_KEYWORD_BLOCK("wings") -DEFINE_REGEX( IDENTIFY_KEYWORD_RESPECT_CASE, IDENTIFY_KEYWORD_REGEX_STRING ) -DEFINE_REGEX_IGNORECASE( IDENTIFY_KEYWORD_IGNORE_CASE, IDENTIFY_KEYWORD_REGEX_STRING ) + DEFINE_REGEX(IDENTIFY_KEYWORD_RESPECT_CASE, IDENTIFY_KEYWORD_REGEX_STRING) + DEFINE_REGEX_IGNORECASE(IDENTIFY_KEYWORD_IGNORE_CASE, IDENTIFY_KEYWORD_REGEX_STRING) -DEFINE_REGEX( POSITIVE_DECIMAL_NUMBER, E_POSITIVE_DECIMAL_NUMBER ); + DEFINE_REGEX(POSITIVE_DECIMAL_NUMBER, E_POSITIVE_DECIMAL_NUMBER); -DEFINE_REGEX( NEGATIVE_DECIMAL_NUMBER, E_NEGATIVE_DECIMAL_NUMBER ); + DEFINE_REGEX(NEGATIVE_DECIMAL_NUMBER, E_NEGATIVE_DECIMAL_NUMBER); -DEFINE_REGEX( DECIMAL_NUMBER, E_DECIMAL_NUMBER ); + DEFINE_REGEX(DECIMAL_NUMBER, E_DECIMAL_NUMBER); -DEFINE_REGEX( MINUS_ONE_REAL, E_MINUS_ONE_REAL ); + DEFINE_REGEX(MINUS_ONE_REAL, E_MINUS_ONE_REAL); -DEFINE_REGEX( REAL_NUMBER, E_REAL_NUMBER ); + DEFINE_REGEX(REAL_NUMBER, E_REAL_NUMBER); -DEFINE_REGEX( NODE_ID_OPTIONAL, - E_LEADING_WHITESPACE - E_CAPTURE_OPTIONAL( E_POSITIVE_DECIMAL_NUMBER ) // Numeric Id - E_CAPTURE_OPTIONAL( E_MINUS_ONE_REAL ) // -1 = use default - E_CAPTURE_OPTIONAL( E_STRING_ALNUM_HYPHENS_USCORES_ONLY ) // String Id - E_CAPTURE_OPTIONAL( E_TRAILING_WHITESPACE ) - ); + DEFINE_REGEX(NODE_ID_OPTIONAL, + E_LEADING_WHITESPACE E_CAPTURE_OPTIONAL(E_POSITIVE_DECIMAL_NUMBER) // Numeric Id + E_CAPTURE_OPTIONAL(E_MINUS_ONE_REAL) // -1 = use default + E_CAPTURE_OPTIONAL(E_STRING_ALNUM_HYPHENS_USCORES_ONLY) // String Id + E_CAPTURE_OPTIONAL(E_TRAILING_WHITESPACE)); -#define E_2xCAPTURE_TRAILING_COMMENT \ - E_OPTIONAL_SPACE \ - E_CAPTURE_OPTIONAL( \ - E_CAPTURE( \ - ";" \ - E_OR \ - E_SLASH E_SLASH \ - ) \ - ".*" \ - ) \ +#define E_2xCAPTURE_TRAILING_COMMENT \ + E_OPTIONAL_SPACE \ + E_CAPTURE_OPTIONAL(E_CAPTURE(";" E_OR E_SLASH E_SLASH) ".*") \ "$" -// -------------------------------------------------------------------------- // -// Regexes for parsing sections // -// -------------------------------------------------------------------------- // + // -------------------------------------------------------------------------- // + // Regexes for parsing sections // + // -------------------------------------------------------------------------- // -DEFINE_REGEX( PARSE_ANIMATORS_NUMBERED_KEYWORD, - E_LEADING_WHITESPACE - E_CAPTURE( "throttle|rpm|aerotorq|aeropit|aerostatus" ) - E_CAPTURE( "[[:digit:]]" ) - E_TRAILING_WHITESPACE - ); - -DEFINE_REGEX( SECTION_AXLES_PROPERTY, - E_LEADING_WHITESPACE - E_CAPTURE_OPTIONAL( // #1 - E_OPTIONAL_SPACE - "w(1|2)" // #2 wheel number - "\\(" - E_CAPTURE( E_NODE_ID ) // #3 Node 1 - E_DELIMITER_SPACE - E_CAPTURE( E_NODE_ID ) // #4 Node 2 - "\\)" - E_OPTIONAL_SPACE - ) - E_CAPTURE_OPTIONAL( // #5 - E_OPTIONAL_SPACE - "d\\(" - E_CAPTURE( "[olsv]*" ) // #6 Differential modes - "\\)" - E_OPTIONAL_SPACE - ) - E_2xCAPTURE_TRAILING_COMMENT - ); - -DEFINE_REGEX( SECTION_COLLISIONBOXES, - E_LEADING_WHITESPACE - E_DELIMITED_LIST( E_NODE_ID, "," ) - E_TRAILING_WHITESPACE - ); + DEFINE_REGEX(PARSE_ANIMATORS_NUMBERED_KEYWORD, E_LEADING_WHITESPACE E_CAPTURE("throttle|rpm|aerotorq|aeropit|aerostatus") + E_CAPTURE("[[:digit:]]") E_TRAILING_WHITESPACE); -// -------------------------------------------------------------------------- // -// Cleanup // -// -------------------------------------------------------------------------- // + DEFINE_REGEX(SECTION_AXLES_PROPERTY, + E_LEADING_WHITESPACE E_CAPTURE_OPTIONAL( // #1 + E_OPTIONAL_SPACE "w(1|2)" // #2 wheel number + "\\(" E_CAPTURE(E_NODE_ID) // #3 Node 1 + E_DELIMITER_SPACE E_CAPTURE(E_NODE_ID) // #4 Node 2 + "\\)" E_OPTIONAL_SPACE) E_CAPTURE_OPTIONAL( // #5 + E_OPTIONAL_SPACE "d\\(" E_CAPTURE("[olsv]*") // #6 Differential modes + "\\)" E_OPTIONAL_SPACE) E_2xCAPTURE_TRAILING_COMMENT); + + DEFINE_REGEX(SECTION_COLLISIONBOXES, E_LEADING_WHITESPACE E_DELIMITED_LIST(E_NODE_ID, ",") E_TRAILING_WHITESPACE); + + // -------------------------------------------------------------------------- // + // Cleanup // + // -------------------------------------------------------------------------- // #undef E_BACKSLASH #undef E_SLASH @@ -408,6 +363,6 @@ DEFINE_REGEX( SECTION_COLLISIONBOXES, #undef E_2xCAPTURE_TRAILING_COMMENT -} // namespace Regexes + } // namespace Regexes } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.cpp b/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.cpp index 82e02d027b..f790852910 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.cpp @@ -23,12 +23,13 @@ /// @author Petr Ohlidal /// @date 04/2015 -#include #include "RigDef_SequentialImporter.h" #include "RigDef_Parser.h" #include "RoRPrerequisites.h" +#include + using namespace RigDef; void SequentialImporter::Init(bool enabled) @@ -39,9 +40,9 @@ void SequentialImporter::Init(bool enabled) m_current_keyword = File::KEYWORD_INVALID; m_current_module.reset(); m_messages.clear(); - m_messages_num_errors = 0; + m_messages_num_errors = 0; m_messages_num_warnings = 0; - m_messages_num_other = 0; + m_messages_num_other = 0; m_num_numbered_nodes = 0; m_num_named_nodes = 0; @@ -60,7 +61,7 @@ void SequentialImporter::GenerateNodesForWheel(File::Keyword generated_from, int // // Section | Function() | Generated nodes // ------------------------------------------------------------------------------------------- - // wheels | addWheel() | Tyre nodes: A, B, A, B... (num_rays*2) + // wheels | addWheel() | Tyre nodes: A, B, A, B... (num_rays*2) // wheels2 | addWheel2() | Rim nodes: A, B, A, B... (num_rays*2), Tyre nodes: A, B, A, B... (num_rays*2) // meshwheels | addWheel() | Tyre nodes: A, B, A, B... (num_rays*2) // meshwheels2 | addWheel() | Tyre nodes: A, B, A, B... (num_rays*2) @@ -70,14 +71,14 @@ void SequentialImporter::GenerateNodesForWheel(File::Keyword generated_from, int if (generated_from == File::KEYWORD_FLEXBODYWHEELS || generated_from == File::KEYWORD_WHEELS2) { // Rim nodes - for (int i = 0; i < num_rays*2; ++i) + for (int i = 0; i < num_rays * 2; ++i) { detail = (i % 2 == 0) ? NodeMapEntry::DETAIL_WHEEL_RIM_A : NodeMapEntry::DETAIL_WHEEL_RIM_B; this->AddGeneratedNode(generated_from, detail); } } // Tyre nodes - for (int i = 0; i < num_rays*2; ++i) + for (int i = 0; i < num_rays * 2; ++i) { detail = (i % 2 == 0) ? NodeMapEntry::DETAIL_WHEEL_TYRE_A : NodeMapEntry::DETAIL_WHEEL_TYRE_B; this->AddGeneratedNode(generated_from, detail); @@ -90,7 +91,7 @@ void SequentialImporter::Process(std::shared_ptr def) auto end = def->user_modules.end(); auto itor = def->user_modules.begin(); - for (;itor != end; ++itor) + for (; itor != end; ++itor) { this->ProcessModule((*itor).second); } @@ -100,26 +101,17 @@ void SequentialImporter::AddMessage(Message::Type msg_type, std::string text) { Message m; m.keyword = m_current_keyword; - m.type = msg_type; + m.type = msg_type; m.message = text; - if (m_current_module.get() != nullptr) - { - m.module_name = m_current_module->name; - } + if (m_current_module.get() != nullptr) { m.module_name = m_current_module->name; } m_messages.push_back(m); switch (msg_type) { - case Message::TYPE_ERROR: - case Message::TYPE_FATAL_ERROR: - ++m_messages_num_errors; - break; - case Message::TYPE_WARNING: - ++m_messages_num_warnings; - break; - default: - ++m_messages_num_other; - break; + case Message::TYPE_ERROR: + case Message::TYPE_FATAL_ERROR: ++m_messages_num_errors; break; + case Message::TYPE_WARNING: ++m_messages_num_warnings; break; + default: ++m_messages_num_other; break; } } @@ -130,14 +122,14 @@ unsigned SequentialImporter::GetNodeArrayOffset(File::Keyword keyword) unsigned out_offset = 0; switch (keyword) { - case File::KEYWORD_FLEXBODYWHEELS: out_offset += m_num_meshwheels2_nodes; // NO break! - case File::KEYWORD_MESHWHEELS2: out_offset += m_num_meshwheels_nodes; // NO break! - case File::KEYWORD_MESHWHEELS: out_offset += m_num_wheels2_nodes; // NO break! - case File::KEYWORD_WHEELS2: out_offset += m_num_wheels_nodes; // NO break! - case File::KEYWORD_WHEELS: out_offset += m_num_cinecam_nodes; // NO break! - case File::KEYWORD_CINECAM: out_offset += m_num_named_nodes; // NO break! - case File::KEYWORD_NODES2: out_offset += m_num_numbered_nodes; // NO break! - case File::KEYWORD_NODES: break; // Starts at 0 + case File::KEYWORD_FLEXBODYWHEELS: out_offset += m_num_meshwheels2_nodes; // NO break! + case File::KEYWORD_MESHWHEELS2: out_offset += m_num_meshwheels_nodes; // NO break! + case File::KEYWORD_MESHWHEELS: out_offset += m_num_wheels2_nodes; // NO break! + case File::KEYWORD_WHEELS2: out_offset += m_num_wheels_nodes; // NO break! + case File::KEYWORD_WHEELS: out_offset += m_num_cinecam_nodes; // NO break! + case File::KEYWORD_CINECAM: out_offset += m_num_named_nodes; // NO break! + case File::KEYWORD_NODES2: out_offset += m_num_numbered_nodes; // NO break! + case File::KEYWORD_NODES: break; // Starts at 0 default: break; } return out_offset; @@ -148,19 +140,20 @@ Node::Ref SequentialImporter::ResolveNodeByIndex(unsigned int index_in, unsigned if (index_in >= m_all_nodes.size()) { std::stringstream msg; - msg << "Cannot resolve node by index [" << index_in << "], node is not defined, highest available number is: " << m_all_nodes.size() - 1; + msg << "Cannot resolve node by index [" << index_in + << "], node is not defined, highest available number is: " << m_all_nodes.size() - 1; this->AddMessage(Message::TYPE_ERROR, msg.str()); return Node::Ref(); // Invalid reference } NodeMapEntry node_entry = m_all_nodes[index_in]; - unsigned index_out = this->GetNodeArrayOffset(node_entry.origin_keyword) + node_entry.node_sub_index; + unsigned index_out = this->GetNodeArrayOffset(node_entry.origin_keyword) + node_entry.node_sub_index; if (index_out != index_in) { std::stringstream msg; - msg << "Node resolved by index.\n\tSource: [" << index_in << "]\n\tResult: [" << index_out << "]"; + msg << "Node resolved by index.\n\tSource: [" << index_in << "]\n\tResult: [" << index_out << "]"; if (node_entry.origin_keyword != File::KEYWORD_NODES && node_entry.origin_keyword != File::KEYWORD_NODES2) { - msg << " (generated by: " << File::KeywordToString(node_entry.origin_keyword) + msg << " (generated by: " << File::KeywordToString(node_entry.origin_keyword) << ", sub-index: " << node_entry.node_sub_index << ")"; } this->AddMessage(Message::TYPE_INFO, msg.str()); @@ -169,16 +162,14 @@ Node::Ref SequentialImporter::ResolveNodeByIndex(unsigned int index_in, unsigned { ++m_num_resolved_to_self; // The happy statistic -> nodes which resolved to the same index. } - return Node::Ref(TOSTRING(index_out), index_out, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NUMBERED, def_line_number); + return Node::Ref(TOSTRING(index_out), index_out, + Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NUMBERED, def_line_number); } -Node::Ref SequentialImporter::ResolveNode(Node::Ref const & noderef_in) +Node::Ref SequentialImporter::ResolveNode(Node::Ref const &noderef_in) { ++m_total_resolved; - if (!noderef_in.GetImportState_IsValid()) - { - return noderef_in; - } + if (!noderef_in.GetImportState_IsValid()) { return noderef_in; } // Work like legacy function SerializedRig::parse_node_number() // If node may be named, try resolving it as named first @@ -189,24 +180,28 @@ Node::Ref SequentialImporter::ResolveNode(Node::Ref const & noderef_in) auto result = m_named_nodes.find(noderef_in.Str()); if (result != m_named_nodes.end()) { - return Node::Ref(noderef_in.Str(), 0, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NAMED, noderef_in.GetLineNumber()); + return Node::Ref(noderef_in.Str(), 0, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NAMED, + noderef_in.GetLineNumber()); } } if (noderef_in.Num() >= m_all_nodes.size()) { // Return exactly what SerializedRig::parse_node_number() would return on this error, for compatibility. // This definitely isn't valid, but it behaves exactly as RoR 0.38, so it's perfectly IMPORT_VALID! :D - Node::Ref out_ref("0", 0, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NUMBERED, noderef_in.GetLineNumber()); + Node::Ref out_ref("0", 0, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NUMBERED, + noderef_in.GetLineNumber()); std::stringstream msg; - msg << "Cannot resolve " << noderef_in.ToString() << " - not a named node, and index is not defined (highest is: " - << m_all_nodes.size() - 1 << "). For backwards compatibility, converting to: " << out_ref.ToString(); + msg << "Cannot resolve " << noderef_in.ToString() + << " - not a named node, and index is not defined (highest is: " << m_all_nodes.size() - 1 + << "). For backwards compatibility, converting to: " << out_ref.ToString(); this->AddMessage(Message::TYPE_ERROR, msg.str()); return out_ref; // Invalid } auto entry = m_all_nodes[noderef_in.Num()]; if (entry.node_id.IsTypeNamed()) { - Node::Ref out_ref(entry.node_id.Str(), 0, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NAMED, noderef_in.GetLineNumber()); + Node::Ref out_ref(entry.node_id.Str(), 0, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NAMED, + noderef_in.GetLineNumber()); std::stringstream msg; msg << "Node resolved\n\tSource: " << noderef_in.ToString() << "\n\tResult: " << out_ref.ToString(); this->AddMessage(Message::TYPE_INFO, msg.str()); @@ -214,8 +209,10 @@ Node::Ref SequentialImporter::ResolveNode(Node::Ref const & noderef_in) } else if (entry.node_id.IsTypeNumbered()) { - unsigned out_index = this->GetNodeArrayOffset(entry.origin_keyword) + entry.node_sub_index; - Node::Ref out_ref(TOSTRING(out_index), out_index, Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NUMBERED, noderef_in.GetLineNumber()); + unsigned out_index = this->GetNodeArrayOffset(entry.origin_keyword) + entry.node_sub_index; + Node::Ref out_ref(TOSTRING(out_index), out_index, + Node::Ref::IMPORT_STATE_IS_VALID | Node::Ref::IMPORT_STATE_IS_RESOLVED_NUMBERED, + noderef_in.GetLineNumber()); std::stringstream msg; msg << "Node resolved\n\tSource: " << noderef_in.ToString() << "\n\tResult: " << out_ref.ToString() << "\n\tOrigin: " << RigDef::File::KeywordToString(entry.origin_keyword) << " SubIndex: " << entry.node_sub_index; @@ -231,13 +228,13 @@ Node::Ref SequentialImporter::ResolveNode(Node::Ref const & noderef_in) } } -void SequentialImporter::ResolveFlexbodyForset(std::vector& in_ranges, std::vector& out_nodes) +void SequentialImporter::ResolveFlexbodyForset(std::vector &in_ranges, std::vector &out_nodes) { auto range_itor = in_ranges.begin(); auto range_end = in_ranges.end(); - for ( ; range_itor != range_end; ++range_itor) + for (; range_itor != range_end; ++range_itor) { - Node::Range& range = *range_itor; + Node::Range &range = *range_itor; if (!range.IsRange()) { if (!range.start.GetImportState_IsValid()) @@ -248,17 +245,16 @@ void SequentialImporter::ResolveFlexbodyForset(std::vector& in_rang } else { - Node::Ref node_ref = this->ResolveNodeByIndex(range.start.Num(), range.start.GetLineNumber()); // Forset nodes are numbered-only - // Invalid nodes are simply thrown away, for backwards compatibility + Node::Ref node_ref = + this->ResolveNodeByIndex(range.start.Num(), range.start.GetLineNumber()); // Forset nodes are numbered-only + // Invalid nodes are simply thrown away, for backwards compatibility // (FlexBody loops through existing nodes first, and then evaluates if they are in the SET) - if (node_ref.IsValidAnyState()) - { - out_nodes.push_back(node_ref); - } + if (node_ref.IsValidAnyState()) { out_nodes.push_back(node_ref); } else { std::stringstream msg; - msg << "ResolveFlexbodyForset(): Stand-alone node [" << range.start.ToString() << "] resolved invalid, removing from FORSET"; + msg << "ResolveFlexbodyForset(): Stand-alone node [" << range.start.ToString() + << "] resolved invalid, removing from FORSET"; this->AddMessage(Message::TYPE_WARNING, msg.str()); } } @@ -268,32 +264,33 @@ void SequentialImporter::ResolveFlexbodyForset(std::vector& in_rang if (!range.start.GetImportState_IsValid() || !range.end.GetImportState_IsValid()) { std::stringstream msg; - msg << "ResolveFlexbodyForset(): Skipping range because some nodes are marked INVALID, start: [" << range.start.ToString() << "], end: [" << range.end.ToString() << "]"; + msg << "ResolveFlexbodyForset(): Skipping range because some nodes are marked INVALID, start: [" + << range.start.ToString() << "], end: [" << range.end.ToString() << "]"; this->AddMessage(Message::TYPE_ERROR, msg.str()); } else if (range.start.GetImportState_IsResolvedNamed() || range.end.GetImportState_IsResolvedNamed()) { std::stringstream msg; - msg << "ResolveFlexbodyForset(): Some nodes in range are already resolved as named, unable to process, start: [" << range.start.ToString() << "], end: [" << range.end.ToString() << "]"; + msg << "ResolveFlexbodyForset(): Some nodes in range are already resolved as named, unable to process, start: [" + << range.start.ToString() << "], end: [" << range.end.ToString() << "]"; this->AddMessage(Message::TYPE_ERROR, msg.str()); } else { unsigned int end_index = range.end.Num(); - unsigned int line_num = range.start.GetLineNumber(); + unsigned int line_num = range.start.GetLineNumber(); for (unsigned int i = range.start.Num(); i <= end_index; ++i) { Node::Ref node_ref = this->ResolveNodeByIndex(i, line_num); // Forset nodes are numbered-only - // Invalid nodes are simply thrown away, for backwards compatibility - // (FlexBody loops through existing nodes first, and then evaluates if they are in the SET -> invalid nodes are silently ignored) - if (node_ref.IsValidAnyState()) - { - out_nodes.push_back(node_ref); - } + // Invalid nodes are simply thrown away, for backwards compatibility + // (FlexBody loops through existing nodes first, and then evaluates if they are in the SET -> invalid nodes + // are silently ignored) + if (node_ref.IsValidAnyState()) { out_nodes.push_back(node_ref); } else { std::stringstream msg; - msg << "ResolveFlexbodyForset(): Node ["<AddMessage(Message::TYPE_WARNING, msg.str()); } } @@ -302,30 +299,29 @@ void SequentialImporter::ResolveFlexbodyForset(std::vector& in_rang } } -void SequentialImporter::ResolveNodeRanges(std::vector& ranges) +void SequentialImporter::ResolveNodeRanges(std::vector &ranges) { auto in_ranges = ranges; // Copy vector ranges.clear(); auto range_itor = in_ranges.begin(); auto range_end = in_ranges.end(); - for ( ; range_itor != range_end; ++range_itor) + for (; range_itor != range_end; ++range_itor) { - Node::Range& range = *range_itor; - if (!range.IsRange()) - { - ranges.push_back(Node::Range(this->ResolveNode(range.start))); - } + Node::Range &range = *range_itor; + if (!range.IsRange()) { ranges.push_back(Node::Range(this->ResolveNode(range.start))); } else if (!range.start.GetImportState_IsValid() || !range.end.GetImportState_IsValid()) { std::stringstream msg; - msg << "Some nodes in range are invalid, start: [" << range.start.ToString() << "], end: [" << range.end.ToString() << "]"; + msg << "Some nodes in range are invalid, start: [" << range.start.ToString() << "], end: [" << range.end.ToString() + << "]"; this->AddMessage(Message::TYPE_ERROR, msg.str()); } else if (range.start.GetImportState_IsResolvedNamed() || range.end.GetImportState_IsResolvedNamed()) { std::stringstream msg; - msg << "Some nodes in range are already resolved as named, unable to process, start: [" << range.start.ToString() << "], end: [" << range.end.ToString() << "]"; + msg << "Some nodes in range are already resolved as named, unable to process, start: [" << range.start.ToString() + << "], end: [" << range.end.ToString() << "]"; this->AddMessage(Message::TYPE_ERROR, msg.str()); } else @@ -339,39 +335,36 @@ void SequentialImporter::ResolveNodeRanges(std::vector& ranges) } } -#define RESOLVE_OPTIONAL_SECTION(KEYWORD, PTRNAME, BLOCK) \ -{ \ - m_current_keyword = KEYWORD; \ - if (PTRNAME) \ - { \ - BLOCK \ - } \ - m_current_keyword = File::KEYWORD_INVALID; \ -} +#define RESOLVE_OPTIONAL_SECTION(KEYWORD, PTRNAME, BLOCK) \ + { \ + m_current_keyword = KEYWORD; \ + if (PTRNAME) { BLOCK } \ + m_current_keyword = File::KEYWORD_INVALID; \ + } -#define FOR_EACH(KEYWORD, VECTOR, VARNAME, BLOCK) \ -{ \ - m_current_keyword = KEYWORD; \ - auto itor_ = VECTOR.begin(); \ - auto end_ = VECTOR.end(); \ - for (; itor_ != end_; ++itor_) \ - { \ - auto& VARNAME = *itor_; \ - BLOCK \ - } \ - m_current_keyword = File::KEYWORD_INVALID; \ -} +#define FOR_EACH(KEYWORD, VECTOR, VARNAME, BLOCK) \ + { \ + m_current_keyword = KEYWORD; \ + auto itor_ = VECTOR.begin(); \ + auto end_ = VECTOR.end(); \ + for (; itor_ != end_; ++itor_) \ + { \ + auto &VARNAME = *itor_; \ + BLOCK \ + } \ + m_current_keyword = File::KEYWORD_INVALID; \ + } #define RESOLVE(VARNAME) VARNAME = this->ResolveNode(VARNAME); -#define RESOLVE_VECTOR(VECTORNAME) \ -{ \ - auto end = VECTORNAME.end(); \ - for ( auto itor = VECTORNAME.begin(); itor != end; ++itor) \ - { \ - RESOLVE(*itor); \ - } \ -} +#define RESOLVE_VECTOR(VECTORNAME) \ + { \ + auto end = VECTORNAME.end(); \ + for (auto itor = VECTORNAME.begin(); itor != end; ++itor) \ + { \ + RESOLVE(*itor); \ + } \ + } // Support for named nodes in parsers [version 0.39, version 0.4.0.7] // airbrakes = yes,yes @@ -381,42 +374,34 @@ void SequentialImporter::ProcessModule(std::shared_ptr mod { m_current_module = module; - FOR_EACH (File::KEYWORD_AIRBRAKES, module->airbrakes, airbrake, - { + FOR_EACH(File::KEYWORD_AIRBRAKES, module->airbrakes, airbrake, { RESOLVE(airbrake.reference_node); - RESOLVE(airbrake.x_axis_node ); - RESOLVE(airbrake.y_axis_node ); + RESOLVE(airbrake.x_axis_node); + RESOLVE(airbrake.y_axis_node); RESOLVE(airbrake.aditional_node); }); - FOR_EACH (File::KEYWORD_AXLES, module->axles, axle, - { + FOR_EACH(File::KEYWORD_AXLES, module->axles, axle, { RESOLVE(axle.wheels[0][0]); RESOLVE(axle.wheels[0][1]); RESOLVE(axle.wheels[1][0]); RESOLVE(axle.wheels[1][1]); }); - FOR_EACH (File::KEYWORD_BEAMS, module->beams, beam, - { + FOR_EACH(File::KEYWORD_BEAMS, module->beams, beam, { RESOLVE(beam.nodes[0]); RESOLVE(beam.nodes[1]); }); - FOR_EACH (File::KEYWORD_CAMERAS, module->cameras, camera, - { + FOR_EACH(File::KEYWORD_CAMERAS, module->cameras, camera, { RESOLVE(camera.center_node); - RESOLVE(camera.back_node ); - RESOLVE(camera.left_node ); + RESOLVE(camera.back_node); + RESOLVE(camera.left_node); }); - FOR_EACH (File::KEYWORD_CAMERARAIL, module->camera_rails, rail, - { - RESOLVE_VECTOR(rail.nodes); - }); + FOR_EACH(File::KEYWORD_CAMERARAIL, module->camera_rails, rail, { RESOLVE_VECTOR(rail.nodes); }); - FOR_EACH (File::KEYWORD_CINECAM, module->cinecam, cinecam, - { + FOR_EACH(File::KEYWORD_CINECAM, module->cinecam, cinecam, { RESOLVE(cinecam.nodes[0]); RESOLVE(cinecam.nodes[1]); RESOLVE(cinecam.nodes[2]); @@ -427,190 +412,145 @@ void SequentialImporter::ProcessModule(std::shared_ptr mod RESOLVE(cinecam.nodes[7]); }); - FOR_EACH (File::KEYWORD_COLLISIONBOXES, module->collision_boxes, box, - { - RESOLVE_VECTOR(box.nodes); - }); + FOR_EACH(File::KEYWORD_COLLISIONBOXES, module->collision_boxes, box, { RESOLVE_VECTOR(box.nodes); }); - FOR_EACH (File::KEYWORD_COMMANDS2, module->commands_2, command, - { + FOR_EACH(File::KEYWORD_COMMANDS2, module->commands_2, command, { RESOLVE(command.nodes[0]); RESOLVE(command.nodes[1]); }); - FOR_EACH (File::KEYWORD_CONTACTERS, module->contacters, contacter_node, - { - RESOLVE(contacter_node); - }); + FOR_EACH(File::KEYWORD_CONTACTERS, module->contacters, contacter_node, { RESOLVE(contacter_node); }); - FOR_EACH (File::KEYWORD_EXHAUSTS, module->exhausts, exhaust, - { + FOR_EACH(File::KEYWORD_EXHAUSTS, module->exhausts, exhaust, { RESOLVE(exhaust.reference_node); RESOLVE(exhaust.direction_node); }); - RESOLVE_OPTIONAL_SECTION (File::KEYWORD_EXTCAMERA, module->ext_camera, - { - RESOLVE(module->ext_camera->node); - }); + RESOLVE_OPTIONAL_SECTION(File::KEYWORD_EXTCAMERA, module->ext_camera, { RESOLVE(module->ext_camera->node); }); - FOR_EACH (File::KEYWORD_FIXES, module->fixes, fixed_node, - { - RESOLVE(fixed_node); - }); + FOR_EACH(File::KEYWORD_FIXES, module->fixes, fixed_node, { RESOLVE(fixed_node); }); - FOR_EACH (File::KEYWORD_FLARES2, module->flares_2, flare2, - { + FOR_EACH(File::KEYWORD_FLARES2, module->flares_2, flare2, { RESOLVE(flare2.reference_node); - RESOLVE(flare2.node_axis_x ); - RESOLVE(flare2.node_axis_y ); + RESOLVE(flare2.node_axis_x); + RESOLVE(flare2.node_axis_y); }); - FOR_EACH (File::KEYWORD_FLEXBODIES, module->flexbodies, flexbody, - { + FOR_EACH(File::KEYWORD_FLEXBODIES, module->flexbodies, flexbody, { RESOLVE(flexbody->reference_node); - RESOLVE(flexbody->x_axis_node ); - RESOLVE(flexbody->y_axis_node ); + RESOLVE(flexbody->x_axis_node); + RESOLVE(flexbody->y_axis_node); ResolveFlexbodyForset(flexbody->node_list_to_import, flexbody->node_list); flexbody->node_list_to_import.clear(); }); - FOR_EACH (File::KEYWORD_FLEXBODYWHEELS, module->flex_body_wheels, flexbodywheel, - { - RESOLVE(flexbodywheel.nodes[0] ); - RESOLVE(flexbodywheel.nodes[1] ); - RESOLVE(flexbodywheel.rigidity_node ); + FOR_EACH(File::KEYWORD_FLEXBODYWHEELS, module->flex_body_wheels, flexbodywheel, { + RESOLVE(flexbodywheel.nodes[0]); + RESOLVE(flexbodywheel.nodes[1]); + RESOLVE(flexbodywheel.rigidity_node); RESOLVE(flexbodywheel.reference_arm_node); }); - FOR_EACH (File::KEYWORD_FUSEDRAG, module->fusedrag, fusedrag, - { + FOR_EACH(File::KEYWORD_FUSEDRAG, module->fusedrag, fusedrag, { RESOLVE(fusedrag.front_node); RESOLVE(fusedrag.rear_node); }); - FOR_EACH (File::KEYWORD_HOOKS, module->hooks, hook, - { - RESOLVE(hook.node); - }); + FOR_EACH(File::KEYWORD_HOOKS, module->hooks, hook, { RESOLVE(hook.node); }); - FOR_EACH (File::KEYWORD_HYDROS, module->hydros, hydro, - { + FOR_EACH(File::KEYWORD_HYDROS, module->hydros, hydro, { RESOLVE(hydro.nodes[0]); RESOLVE(hydro.nodes[1]); }); - FOR_EACH (File::KEYWORD_MESHWHEELS, module->mesh_wheels, meshwheel, // Also `meshwheels2` - { - RESOLVE(meshwheel.nodes[0] ); - RESOLVE(meshwheel.nodes[1] ); - RESOLVE(meshwheel.rigidity_node ); - RESOLVE(meshwheel.reference_arm_node); - }); + FOR_EACH(File::KEYWORD_MESHWHEELS, module->mesh_wheels, meshwheel, // Also `meshwheels2` + { + RESOLVE(meshwheel.nodes[0]); + RESOLVE(meshwheel.nodes[1]); + RESOLVE(meshwheel.rigidity_node); + RESOLVE(meshwheel.reference_arm_node); + }); - FOR_EACH (File::KEYWORD_PARTICLES, module->particles, particle, - { + FOR_EACH(File::KEYWORD_PARTICLES, module->particles, particle, { RESOLVE(particle.emitter_node); RESOLVE(particle.reference_node); }); - FOR_EACH (File::KEYWORD_PROPS, module->props, prop, - { + FOR_EACH(File::KEYWORD_PROPS, module->props, prop, { RESOLVE(prop.reference_node); - RESOLVE(prop.x_axis_node ); - RESOLVE(prop.y_axis_node ); + RESOLVE(prop.x_axis_node); + RESOLVE(prop.y_axis_node); }); - FOR_EACH (File::KEYWORD_RAILGROUPS, module->railgroups, railgroup, - { - ResolveNodeRanges(railgroup.node_list); - }); + FOR_EACH(File::KEYWORD_RAILGROUPS, module->railgroups, railgroup, { ResolveNodeRanges(railgroup.node_list); }); - FOR_EACH (File::KEYWORD_ROPABLES, module->ropables, ropable, - { - RESOLVE(ropable.node); - }); + FOR_EACH(File::KEYWORD_ROPABLES, module->ropables, ropable, { RESOLVE(ropable.node); }); - FOR_EACH (File::KEYWORD_ROPES, module->ropes, rope, - { + FOR_EACH(File::KEYWORD_ROPES, module->ropes, rope, { RESOLVE(rope.root_node); - RESOLVE(rope.end_node ); + RESOLVE(rope.end_node); }); - FOR_EACH (File::KEYWORD_ROTATORS, module->rotators, rotator, - { - RESOLVE(rotator.axis_nodes[0] ); - RESOLVE(rotator.axis_nodes[1] ); - RESOLVE(rotator.base_plate_nodes[0] ); - RESOLVE(rotator.base_plate_nodes[1] ); - RESOLVE(rotator.base_plate_nodes[2] ); - RESOLVE(rotator.base_plate_nodes[3] ); + FOR_EACH(File::KEYWORD_ROTATORS, module->rotators, rotator, { + RESOLVE(rotator.axis_nodes[0]); + RESOLVE(rotator.axis_nodes[1]); + RESOLVE(rotator.base_plate_nodes[0]); + RESOLVE(rotator.base_plate_nodes[1]); + RESOLVE(rotator.base_plate_nodes[2]); + RESOLVE(rotator.base_plate_nodes[3]); RESOLVE(rotator.rotating_plate_nodes[0]); RESOLVE(rotator.rotating_plate_nodes[1]); RESOLVE(rotator.rotating_plate_nodes[2]); RESOLVE(rotator.rotating_plate_nodes[3]); }); - FOR_EACH (File::KEYWORD_ROTATORS2, module->rotators_2, rotator2, - { - RESOLVE(rotator2.axis_nodes[0] ); - RESOLVE(rotator2.axis_nodes[1] ); - RESOLVE(rotator2.base_plate_nodes[0] ); - RESOLVE(rotator2.base_plate_nodes[1] ); - RESOLVE(rotator2.base_plate_nodes[2] ); - RESOLVE(rotator2.base_plate_nodes[3] ); + FOR_EACH(File::KEYWORD_ROTATORS2, module->rotators_2, rotator2, { + RESOLVE(rotator2.axis_nodes[0]); + RESOLVE(rotator2.axis_nodes[1]); + RESOLVE(rotator2.base_plate_nodes[0]); + RESOLVE(rotator2.base_plate_nodes[1]); + RESOLVE(rotator2.base_plate_nodes[2]); + RESOLVE(rotator2.base_plate_nodes[3]); RESOLVE(rotator2.rotating_plate_nodes[0]); RESOLVE(rotator2.rotating_plate_nodes[1]); RESOLVE(rotator2.rotating_plate_nodes[2]); RESOLVE(rotator2.rotating_plate_nodes[3]); }); - FOR_EACH (File::KEYWORD_SCREWPROPS, module->screwprops, screwprop, - { + FOR_EACH(File::KEYWORD_SCREWPROPS, module->screwprops, screwprop, { RESOLVE(screwprop.prop_node); RESOLVE(screwprop.back_node); - RESOLVE(screwprop.top_node ); + RESOLVE(screwprop.top_node); }); - FOR_EACH (File::KEYWORD_SHOCKS, module->shocks, shock, - { + FOR_EACH(File::KEYWORD_SHOCKS, module->shocks, shock, { RESOLVE(shock.nodes[0]); RESOLVE(shock.nodes[1]); }); - FOR_EACH (File::KEYWORD_SHOCKS2, module->shocks_2, shock2, - { + FOR_EACH(File::KEYWORD_SHOCKS2, module->shocks_2, shock2, { RESOLVE(shock2.nodes[0]); RESOLVE(shock2.nodes[1]); }); - FOR_EACH (File::KEYWORD_SHOCKS3, module->shocks_3, shock3, - { + FOR_EACH(File::KEYWORD_SHOCKS3, module->shocks_3, shock3, { RESOLVE(shock3.nodes[0]); RESOLVE(shock3.nodes[1]); }); - FOR_EACH (File::KEYWORD_SLIDENODES, module->slidenodes, slidenode, - { + FOR_EACH(File::KEYWORD_SLIDENODES, module->slidenodes, slidenode, { RESOLVE(slidenode.slide_node); ResolveNodeRanges(slidenode.rail_node_ranges); }); - FOR_EACH (File::KEYWORD_SOUNDSOURCES, module->soundsources, soundsource, - { - RESOLVE(soundsource.node); - }); + FOR_EACH(File::KEYWORD_SOUNDSOURCES, module->soundsources, soundsource, { RESOLVE(soundsource.node); }); - FOR_EACH (File::KEYWORD_SOUNDSOURCES2, module->soundsources2, soundsource2, - { - RESOLVE(soundsource2.node); - }); + FOR_EACH(File::KEYWORD_SOUNDSOURCES2, module->soundsources2, soundsource2, { RESOLVE(soundsource2.node); }); - FOR_EACH (File::KEYWORD_SUBMESH, module->submeshes, submesh, - { - m_current_keyword = File::KEYWORD_TEXCOORDS; + FOR_EACH(File::KEYWORD_SUBMESH, module->submeshes, submesh, { + m_current_keyword = File::KEYWORD_TEXCOORDS; auto texcoord_itor = submesh.texcoords.begin(); auto texcoord_end = submesh.texcoords.end(); for (; texcoord_itor != texcoord_end; ++texcoord_itor) @@ -619,8 +559,8 @@ void SequentialImporter::ProcessModule(std::shared_ptr mod } m_current_keyword = File::KEYWORD_CAB; - auto cab_itor = submesh.cab_triangles.begin(); - auto cab_end = submesh.cab_triangles.end(); + auto cab_itor = submesh.cab_triangles.begin(); + auto cab_end = submesh.cab_triangles.end(); for (; cab_itor != cab_end; ++cab_itor) { RESOLVE(cab_itor->nodes[0]); @@ -629,61 +569,51 @@ void SequentialImporter::ProcessModule(std::shared_ptr mod } }); - FOR_EACH (File::KEYWORD_TIES, module->ties, tie, - { - RESOLVE(tie.root_node); - }); + FOR_EACH(File::KEYWORD_TIES, module->ties, tie, { RESOLVE(tie.root_node); }); - FOR_EACH (File::KEYWORD_TRIGGERS, module->triggers, trigger, - { + FOR_EACH(File::KEYWORD_TRIGGERS, module->triggers, trigger, { RESOLVE(trigger.nodes[0]); RESOLVE(trigger.nodes[1]); }); - FOR_EACH (File::KEYWORD_TURBOJETS, module->turbojets, turbojet, - { + FOR_EACH(File::KEYWORD_TURBOJETS, module->turbojets, turbojet, { RESOLVE(turbojet.front_node); - RESOLVE(turbojet.back_node ); - RESOLVE(turbojet.side_node ); + RESOLVE(turbojet.back_node); + RESOLVE(turbojet.side_node); }); - FOR_EACH (File::KEYWORD_TURBOPROPS2, module->turboprops_2, turboprop2, - { - RESOLVE(turboprop2.reference_node ); - RESOLVE(turboprop2.axis_node ); + FOR_EACH(File::KEYWORD_TURBOPROPS2, module->turboprops_2, turboprop2, { + RESOLVE(turboprop2.reference_node); + RESOLVE(turboprop2.axis_node); RESOLVE(turboprop2.blade_tip_nodes[0]); RESOLVE(turboprop2.blade_tip_nodes[1]); RESOLVE(turboprop2.blade_tip_nodes[2]); RESOLVE(turboprop2.blade_tip_nodes[3]); }); - FOR_EACH (File::KEYWORD_WHEELS, module->wheels, wheel, - { - RESOLVE(wheel.nodes[0] ); - RESOLVE(wheel.nodes[1] ); - RESOLVE(wheel.rigidity_node ); + FOR_EACH(File::KEYWORD_WHEELS, module->wheels, wheel, { + RESOLVE(wheel.nodes[0]); + RESOLVE(wheel.nodes[1]); + RESOLVE(wheel.rigidity_node); RESOLVE(wheel.reference_arm_node); }); - FOR_EACH (File::KEYWORD_WHEELS2, module->wheels_2, wheel2, - { - RESOLVE(wheel2.nodes[0] ); - RESOLVE(wheel2.nodes[1] ); - RESOLVE(wheel2.rigidity_node ); + FOR_EACH(File::KEYWORD_WHEELS2, module->wheels_2, wheel2, { + RESOLVE(wheel2.nodes[0]); + RESOLVE(wheel2.nodes[1]); + RESOLVE(wheel2.rigidity_node); RESOLVE(wheel2.reference_arm_node); }); - FOR_EACH (File::KEYWORD_VIDEOCAMERA, module->videocameras, videocamera, - { - RESOLVE(videocamera.reference_node ); - RESOLVE(videocamera.left_node ); - RESOLVE(videocamera.bottom_node ); - RESOLVE(videocamera.alt_reference_node ); + FOR_EACH(File::KEYWORD_VIDEOCAMERA, module->videocameras, videocamera, { + RESOLVE(videocamera.reference_node); + RESOLVE(videocamera.left_node); + RESOLVE(videocamera.bottom_node); + RESOLVE(videocamera.alt_reference_node); RESOLVE(videocamera.alt_orientation_node); }); - FOR_EACH (File::KEYWORD_WINGS, module->wings, wing, - { + FOR_EACH(File::KEYWORD_WINGS, module->wings, wing, { RESOLVE(wing.nodes[0]); RESOLVE(wing.nodes[1]); RESOLVE(wing.nodes[2]); @@ -706,30 +636,22 @@ std::string SequentialImporter::ProcessMessagesToString() } std::stringstream report; - report << " == Sequential import (fileformatversion < 450) done, report:" <type) { - case (Message::TYPE_FATAL_ERROR): - report << "#FF3300 FATAL ERROR #FFFFFF"; - break; - case (Message::TYPE_ERROR): - report << "#FF3300 ERROR #FFFFFF"; - break; - case (Message::TYPE_WARNING): - report << "#FFFF00 WARNING #FFFFFF"; - break; - default: - report << "INFO"; - break; + case (Message::TYPE_FATAL_ERROR): report << "#FF3300 FATAL ERROR #FFFFFF"; break; + case (Message::TYPE_ERROR): report << "#FF3300 ERROR #FFFFFF"; break; + case (Message::TYPE_WARNING): report << "#FFFF00 WARNING #FFFFFF"; break; + default: report << "INFO"; break; } - report << " (module: " << itor->module_name << ", keyword: \"" - << File::KeywordToString(itor->keyword) << "\"): " << itor->message << std::endl; + report << " (module: " << itor->module_name << ", keyword: \"" << File::KeywordToString(itor->keyword) + << "\"): " << itor->message << std::endl; } return report.str(); @@ -740,19 +662,20 @@ bool SequentialImporter::AddNumberedNode(unsigned int number) if (number != m_all_nodes.size()) // Check node sync, like legacy parser did. { std::stringstream msg; - msg << "Lost sync in node numbers, got numbered node [" << number << "], expected [" << m_all_nodes.size() << "]. Ignoring node."; + msg << "Lost sync in node numbers, got numbered node [" << number << "], expected [" << m_all_nodes.size() + << "]. Ignoring node."; this->AddMessage(Message::TYPE_FATAL_ERROR, msg.str()); - return false; + return false; } - m_all_nodes.push_back( NodeMapEntry(File::KEYWORD_NODES, Node::Id(number), m_num_numbered_nodes) ); + m_all_nodes.push_back(NodeMapEntry(File::KEYWORD_NODES, Node::Id(number), m_num_numbered_nodes)); ++m_num_numbered_nodes; return true; } -bool SequentialImporter::AddNamedNode(std::string const & name) +bool SequentialImporter::AddNamedNode(std::string const &name) { auto node_entry = NodeMapEntry(File::KEYWORD_NODES2, Node::Id(name), m_num_named_nodes); - auto result = m_named_nodes.insert(std::make_pair(name, node_entry)); + auto result = m_named_nodes.insert(std::make_pair(name, node_entry)); if (!result.second) { std::stringstream msg; @@ -765,43 +688,48 @@ bool SequentialImporter::AddNamedNode(std::string const & name) return true; } -void SequentialImporter::AddGeneratedNode(File::Keyword generated_from, NodeMapEntry::OriginDetail detail /* = NodeMapEntry::DETAIL_UNDEFINED*/ ) +void SequentialImporter::AddGeneratedNode(File::Keyword generated_from, + NodeMapEntry::OriginDetail detail /* = NodeMapEntry::DETAIL_UNDEFINED*/) { - unsigned int new_number = static_cast(m_all_nodes.size()); + unsigned int new_number = static_cast(m_all_nodes.size()); unsigned int node_sub_index = 0; switch (generated_from) { - case File::KEYWORD_CINECAM: node_sub_index = m_num_cinecam_nodes ++; break; - case File::KEYWORD_WHEELS: node_sub_index = m_num_wheels_nodes ++; break; - case File::KEYWORD_WHEELS2: node_sub_index = m_num_wheels2_nodes ++; break; - case File::KEYWORD_MESHWHEELS: node_sub_index = m_num_meshwheels_nodes ++; break; - case File::KEYWORD_MESHWHEELS2: node_sub_index = m_num_meshwheels2_nodes ++; break; + case File::KEYWORD_CINECAM: node_sub_index = m_num_cinecam_nodes++; break; + case File::KEYWORD_WHEELS: node_sub_index = m_num_wheels_nodes++; break; + case File::KEYWORD_WHEELS2: node_sub_index = m_num_wheels2_nodes++; break; + case File::KEYWORD_MESHWHEELS: node_sub_index = m_num_meshwheels_nodes++; break; + case File::KEYWORD_MESHWHEELS2: node_sub_index = m_num_meshwheels2_nodes++; break; case File::KEYWORD_FLEXBODYWHEELS: node_sub_index = m_num_flexbodywheels_nodes++; break; default: break; } - m_all_nodes.push_back( NodeMapEntry(generated_from, Node::Id(new_number), node_sub_index, detail)); + m_all_nodes.push_back(NodeMapEntry(generated_from, Node::Id(new_number), node_sub_index, detail)); } -#define STAT_LINE(STREAM, TITLE, COUNT_VAR, KEYWORD) \ -{ \ - unsigned offset = this->GetNodeArrayOffset(KEYWORD); \ - STREAM << "\n\t" << TITLE << std::setw(4) << COUNT_VAR; \ - if (COUNT_VAR != 0) { STREAM << " (after conversion: start index = " << std::setw(4) << offset << ", end index = " << (offset + COUNT_VAR) - 1 << ")"; } \ -} +#define STAT_LINE(STREAM, TITLE, COUNT_VAR, KEYWORD) \ + { \ + unsigned offset = this->GetNodeArrayOffset(KEYWORD); \ + STREAM << "\n\t" << TITLE << std::setw(4) << COUNT_VAR; \ + if (COUNT_VAR != 0) \ + { \ + STREAM << " (after conversion: start index = " << std::setw(4) << offset \ + << ", end index = " << (offset + COUNT_VAR) - 1 << ")"; \ + } \ + } std::string SequentialImporter::GetNodeStatistics() { std::stringstream msg; msg << "~~~ Node statistics: ~~~" << "\n\tTotal: " << m_all_nodes.size(); - STAT_LINE(msg, " nodes: ", m_num_numbered_nodes , File::KEYWORD_NODES ); - STAT_LINE(msg, " nodes2: ", m_num_named_nodes , File::KEYWORD_NODES2 ); - STAT_LINE(msg, " cinecam: ", m_num_cinecam_nodes , File::KEYWORD_CINECAM ); - STAT_LINE(msg, " wheels: ", m_num_wheels_nodes , File::KEYWORD_WHEELS ); - STAT_LINE(msg, " wheels2: ", m_num_wheels2_nodes , File::KEYWORD_WHEELS2 ); - STAT_LINE(msg, " meshwheels: ", m_num_meshwheels_nodes , File::KEYWORD_MESHWHEELS ); - STAT_LINE(msg, " meshwheels2: ", m_num_meshwheels2_nodes , File::KEYWORD_MESHWHEELS2 ); - STAT_LINE(msg, "flexbodywheels: ", m_num_flexbodywheels_nodes, File::KEYWORD_FLEXBODYWHEELS); + STAT_LINE(msg, " nodes: ", m_num_numbered_nodes, File::KEYWORD_NODES); + STAT_LINE(msg, " nodes2: ", m_num_named_nodes, File::KEYWORD_NODES2); + STAT_LINE(msg, " cinecam: ", m_num_cinecam_nodes, File::KEYWORD_CINECAM); + STAT_LINE(msg, " wheels: ", m_num_wheels_nodes, File::KEYWORD_WHEELS); + STAT_LINE(msg, " wheels2: ", m_num_wheels2_nodes, File::KEYWORD_WHEELS2); + STAT_LINE(msg, " meshwheels: ", m_num_meshwheels_nodes, File::KEYWORD_MESHWHEELS); + STAT_LINE(msg, " meshwheels2: ", m_num_meshwheels2_nodes, File::KEYWORD_MESHWHEELS2); + STAT_LINE(msg, "flexbodywheels: ", m_num_flexbodywheels_nodes, File::KEYWORD_FLEXBODYWHEELS); return msg.str(); } @@ -809,12 +737,12 @@ std::string SequentialImporter::IterateAndPrintAllNodes() { std::stringstream report; report << "~~~ Iterating all nodes, in order as defined (total: " << m_all_nodes.size() << ") ~~~\n"; - auto itor = m_all_nodes.begin(); - auto end = m_all_nodes.end(); - int index = 0; + auto itor = m_all_nodes.begin(); + auto end = m_all_nodes.end(); + int index = 0; for (; itor != end; ++itor) { - NodeMapEntry& entry = *itor; + NodeMapEntry &entry = *itor; // Resolve type specifics bool is_wheel = false; switch (entry.origin_keyword) @@ -823,25 +751,21 @@ std::string SequentialImporter::IterateAndPrintAllNodes() case File::KEYWORD_WHEELS2: case File::KEYWORD_MESHWHEELS: case File::KEYWORD_MESHWHEELS2: - case File::KEYWORD_FLEXBODYWHEELS: - is_wheel = true; - break; - default: - break; + case File::KEYWORD_FLEXBODYWHEELS: is_wheel = true; break; + default: break; } // Add line entry - report << "\n\t" << std::setw(3) << index << ": " << entry.node_id.ToString() - << " (from=" << File::KeywordToString(entry.origin_keyword) - << ", sub-index=" << entry.node_sub_index; + report << "\n\t" << std::setw(3) << index << ": " << entry.node_id.ToString() + << " (from=" << File::KeywordToString(entry.origin_keyword) << ", sub-index=" << entry.node_sub_index; if (is_wheel) { switch (entry.origin_detail) { - case NodeMapEntry::DETAIL_WHEEL_RIM_A: report << "[rim, A]"; break; - case NodeMapEntry::DETAIL_WHEEL_RIM_B: report << "[rim, B]"; break; - case NodeMapEntry::DETAIL_WHEEL_TYRE_A: report << "[tyre, A]"; break; - case NodeMapEntry::DETAIL_WHEEL_TYRE_B: report << "[tyre, B]"; break; - default: break; + case NodeMapEntry::DETAIL_WHEEL_RIM_A: report << "[rim, A]"; break; + case NodeMapEntry::DETAIL_WHEEL_RIM_B: report << "[rim, B]"; break; + case NodeMapEntry::DETAIL_WHEEL_TYRE_A: report << "[tyre, A]"; break; + case NodeMapEntry::DETAIL_WHEEL_TYRE_B: report << "[tyre, B]"; break; + default: break; } } report << ")"; diff --git a/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.h b/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.h index df9cb61520..d7811bca61 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.h +++ b/source/main/resources/rig_def_fileformat/RigDef_SequentialImporter.h @@ -25,8 +25,8 @@ #pragma once -#include "RigDef_Prerequisites.h" #include "RigDef_File.h" +#include "RigDef_Prerequisites.h" #include #include @@ -34,154 +34,164 @@ namespace RigDef { -/* - @brief Legacy rig-file importer. - - RoR's physics work on this principle: - 1. There is a node array, pre-allocated to some 5000 items. - 2. As .truck file is parsed, defined nodes are reserved in this array and accessible through their - index. Alternatively, nodes can be defined "named"; in that case, a node index> translation - is performed and node can be addressed by both. - 3. Nodes are also generated by some sections (cinecam, wheels...). These can also be adressed by index. - - Traditionally, the order of nodes in nodes-array was determined by order of definitions in .truck file. - This approach had downsides: - 1. Nodes could be adressed before they were defined - This could be detected, but for compatibility reasons, parser emitted a warning only. - 2. Non-existent nodes could be adressed. - Due to pre-allocated nature of node-array, this passed unnoticed. - It could be explicitly detected, but parsers weren't equipped to do so in every case. - 3. Very hard to determine index of some nodes. - Creating rig was traditionally a manual process, and not every section supported named nodes (i.e. axles) - Knowing index of node was necessary, but with named/generated nodes, it was hard to tell. - 3. Unfeasible for visual editor with mouse controls. - This approach would, by nature, re-order definitions and make direct index-adressing impossible. - - To ease code maintenance, enable bullet-proof checking and prepare grounds for visual rig editor, - a new approach was applied: Truckfile would be loaded to RigDef::File structure in it's entirety, - and then parsed in pre-determined order. - Order (section name[number of nodes generated per line]): - 1. nodes[1] - 2. nodes2[1] - 3. cinecam[1] - 4. wheels[num_rays*2] - 5. wheels2[num_rays*4] - 6. meshwheels[num_rays*2] - 7. meshwheels2[num_rays*2] - 8. flexbodywheels[num_rays*4] - - Naturally, older truckfiles which rely on user-determined order of definitions needed to be converted - with index-references updated to match new node-array positions. This class does exactly that. - -*/ -class SequentialImporter -{ -public: - struct NodeMapEntry + /* + @brief Legacy rig-file importer. + + RoR's physics work on this principle: + 1. There is a node array, pre-allocated to some 5000 items. + 2. As .truck file is parsed, defined nodes are reserved in this array and accessible through their + index. Alternatively, nodes can be defined "named"; in that case, a node index> translation + is performed and node can be addressed by both. + 3. Nodes are also generated by some sections (cinecam, wheels...). These can also be adressed by index. + + Traditionally, the order of nodes in nodes-array was determined by order of definitions in .truck file. + This approach had downsides: + 1. Nodes could be adressed before they were defined + This could be detected, but for compatibility reasons, parser emitted a warning only. + 2. Non-existent nodes could be adressed. + Due to pre-allocated nature of node-array, this passed unnoticed. + It could be explicitly detected, but parsers weren't equipped to do so in every case. + 3. Very hard to determine index of some nodes. + Creating rig was traditionally a manual process, and not every section supported named nodes (i.e. axles) + Knowing index of node was necessary, but with named/generated nodes, it was hard to tell. + 3. Unfeasible for visual editor with mouse controls. + This approach would, by nature, re-order definitions and make direct index-adressing impossible. + + To ease code maintenance, enable bullet-proof checking and prepare grounds for visual rig editor, + a new approach was applied: Truckfile would be loaded to RigDef::File structure in it's entirety, + and then parsed in pre-determined order. + Order (section name[number of nodes generated per line]): + 1. nodes[1] + 2. nodes2[1] + 3. cinecam[1] + 4. wheels[num_rays*2] + 5. wheels2[num_rays*4] + 6. meshwheels[num_rays*2] + 7. meshwheels2[num_rays*2] + 8. flexbodywheels[num_rays*4] + + Naturally, older truckfiles which rely on user-determined order of definitions needed to be converted + with index-references updated to match new node-array positions. This class does exactly that. + + */ + class SequentialImporter { - enum OriginDetail + public: + struct NodeMapEntry { - DETAIL_WHEEL_TYRE_A, - DETAIL_WHEEL_TYRE_B, - DETAIL_WHEEL_RIM_A, - DETAIL_WHEEL_RIM_B, - - DETAIL_UNDEFINED = 0xFFFFFFFF + enum OriginDetail + { + DETAIL_WHEEL_TYRE_A, + DETAIL_WHEEL_TYRE_B, + DETAIL_WHEEL_RIM_A, + DETAIL_WHEEL_RIM_B, + + DETAIL_UNDEFINED = 0xFFFFFFFF + }; + + NodeMapEntry(File::Keyword keyword, Node::Id id, unsigned node_sub_index, + OriginDetail detail = NodeMapEntry::DETAIL_UNDEFINED) + : origin_keyword(keyword), origin_detail(detail), node_sub_index(node_sub_index), node_id(id) + { + } + + RigDef::File::Keyword origin_keyword; + OriginDetail origin_detail; + Node::Id node_id; + unsigned node_sub_index; }; - NodeMapEntry(File::Keyword keyword, Node::Id id, unsigned node_sub_index, OriginDetail detail=NodeMapEntry::DETAIL_UNDEFINED): - origin_keyword(keyword), - origin_detail(detail), - node_sub_index(node_sub_index), - node_id(id) - {} - - RigDef::File::Keyword origin_keyword; - OriginDetail origin_detail; - Node::Id node_id; - unsigned node_sub_index; - }; - - struct Message - { - enum Type + struct Message { - TYPE_INFO, - TYPE_WARNING, - TYPE_ERROR, - TYPE_FATAL_ERROR, - - TYPE_INVALID = 0xFFFFFFFF + enum Type + { + TYPE_INFO, + TYPE_WARNING, + TYPE_ERROR, + TYPE_FATAL_ERROR, + + TYPE_INVALID = 0xFFFFFFFF + }; + + std::string message; + File::Keyword keyword; + Type type; + std::string module_name; }; - std::string message; - File::Keyword keyword; - Type type; - std::string module_name; - }; - - void Init(bool enabled); - - void Disable() - { - m_enabled = false; - m_all_nodes.clear(); - } - - inline bool IsEnabled() const { return m_enabled; } - - bool AddNumberedNode(unsigned int number); - - bool AddNamedNode(std::string const & name); - - void AddGeneratedNode(File::Keyword generated_from, NodeMapEntry::OriginDetail detail = NodeMapEntry::DETAIL_UNDEFINED); - - void GenerateNodesForWheel(File::Keyword generated_from, int num_rays, bool has_rigidity_node); - - /// Traverse whole rig definition and resolve all node references - void Process(std::shared_ptr def); + void Init(bool enabled); - int GetMessagesNumErrors() const { return m_messages_num_errors; } - int GetMessagesNumWarnings() const { return m_messages_num_warnings; } - int GetMessagesNumOther() const { return m_messages_num_other; } + void Disable() + { + m_enabled = false; + m_all_nodes.clear(); + } - std::string ProcessMessagesToString(); - std::string GetNodeStatistics(); - std::string IterateAndPrintAllNodes(); + inline bool IsEnabled() const + { + return m_enabled; + } -private: + bool AddNumberedNode(unsigned int number); - void ProcessModule(std::shared_ptr module); + bool AddNamedNode(std::string const &name); - Node::Ref ResolveNode(Node::Ref const & noderef_in); - Node::Ref ResolveNodeByIndex(unsigned int index, unsigned int def_line_number); - unsigned GetNodeArrayOffset(File::Keyword keyword); - void ResolveNodeRanges(std::vector& ranges); - void ResolveFlexbodyForset(std::vector& ranges, std::vector& out_nodes); + void AddGeneratedNode(File::Keyword generated_from, NodeMapEntry::OriginDetail detail = NodeMapEntry::DETAIL_UNDEFINED); - void AddMessage(Message::Type msg_type, std::string text); + void GenerateNodesForWheel(File::Keyword generated_from, int num_rays, bool has_rigidity_node); - std::vector m_all_nodes; - std::map m_named_nodes; - unsigned m_num_numbered_nodes; - unsigned m_num_named_nodes; - unsigned m_num_cinecam_nodes; - unsigned m_num_wheels_nodes; - unsigned m_num_wheels2_nodes; - unsigned m_num_meshwheels_nodes; - unsigned m_num_meshwheels2_nodes; - unsigned m_num_flexbodywheels_nodes; - bool m_enabled; + /// Traverse whole rig definition and resolve all node references + void Process(std::shared_ptr def); - // Logging - int m_total_resolved; - int m_num_resolved_to_self; - File::Keyword m_current_keyword; - std::shared_ptr m_current_module; - std::list m_messages; - int m_messages_num_errors; - int m_messages_num_warnings; - int m_messages_num_other; -}; + int GetMessagesNumErrors() const + { + return m_messages_num_errors; + } + int GetMessagesNumWarnings() const + { + return m_messages_num_warnings; + } + int GetMessagesNumOther() const + { + return m_messages_num_other; + } + + std::string ProcessMessagesToString(); + std::string GetNodeStatistics(); + std::string IterateAndPrintAllNodes(); + + private: + void ProcessModule(std::shared_ptr module); + + Node::Ref ResolveNode(Node::Ref const &noderef_in); + Node::Ref ResolveNodeByIndex(unsigned int index, unsigned int def_line_number); + unsigned GetNodeArrayOffset(File::Keyword keyword); + void ResolveNodeRanges(std::vector &ranges); + void ResolveFlexbodyForset(std::vector &ranges, std::vector &out_nodes); + + void AddMessage(Message::Type msg_type, std::string text); + + std::vector m_all_nodes; + std::map m_named_nodes; + unsigned m_num_numbered_nodes; + unsigned m_num_named_nodes; + unsigned m_num_cinecam_nodes; + unsigned m_num_wheels_nodes; + unsigned m_num_wheels2_nodes; + unsigned m_num_meshwheels_nodes; + unsigned m_num_meshwheels2_nodes; + unsigned m_num_flexbodywheels_nodes; + bool m_enabled; + + // Logging + int m_total_resolved; + int m_num_resolved_to_self; + File::Keyword m_current_keyword; + std::shared_ptr m_current_module; + std::list m_messages; + int m_messages_num_errors; + int m_messages_num_warnings; + int m_messages_num_other; + }; } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp b/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp index 9bff2e3510..d1ae0cad25 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp @@ -27,26 +27,23 @@ #include "RigDef_File.h" -#include #include +#include #include using namespace RigDef; using namespace std; -Serializer::Serializer(std::shared_ptr def_file, Ogre::String const & file_path): - m_file_path(file_path), - m_rig_def(def_file), - m_node_id_width(5), - m_float_precision(6), - m_inertia_function_width(10), - m_bool_width(5), // strlen("false") == 5 - m_command_key_width(2), - m_float_width(10) -{} +Serializer::Serializer(std::shared_ptr def_file, Ogre::String const &file_path) + : m_file_path(file_path), m_rig_def(def_file), m_node_id_width(5), m_float_precision(6), m_inertia_function_width(10), + m_bool_width(5), // strlen("false") == 5 + m_command_key_width(2), m_float_width(10) +{ +} Serializer::~Serializer() -{} +{ +} void Serializer::Serialize() { @@ -58,18 +55,17 @@ void Serializer::Serialize() m_stream << m_rig_def->name << endl << endl; // Write banner - m_stream - << "; ---------------------------------------------------------------------------- ;" << endl - << "; Rigs of Rods project (www.rigsofrods.org) ;" << endl - << "; ========================================= ;" << endl - << "; ;" << endl - << "; This is a rig definition file. ;" << endl - << "; See http://www.rigsofrods.org/wiki/pages/Truck_Description_File for details. ;" << endl - << "; ---------------------------------------------------------------------------- ;" << endl - << endl; + m_stream << "; ---------------------------------------------------------------------------- ;" << endl + << "; Rigs of Rods project (www.rigsofrods.org) ;" << endl + << "; ========================================= ;" << endl + << "; ;" << endl + << "; This is a rig definition file. ;" << endl + << "; See http://www.rigsofrods.org/wiki/pages/Truck_Description_File for details. ;" << endl + << "; ---------------------------------------------------------------------------- ;" << endl + << endl; // Select source - File::Module* source_module = m_rig_def->root_module.get(); + File::Module *source_module = m_rig_def->root_module.get(); // Write individual elements ProcessDescription(); @@ -146,326 +142,214 @@ void Serializer::Serialize() // Marine ProcessScrewprops(source_module); - + // Finalize m_stream << "end" << endl; m_stream.close(); } -void Serializer::ProcessPistonprops(File::Module* module) +void Serializer::ProcessPistonprops(File::Module *module) { - if (module->pistonprops.empty()) - { - return; - } + if (module->pistonprops.empty()) { return; } m_stream << "pistonprops" << endl; auto end_itor = module->pistonprops.end(); for (auto itor = module->pistonprops.begin(); itor != end_itor; ++itor) { - auto & def = *itor; + auto &def = *itor; - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.axis_node.ToString() - << ", " << def.blade_tip_nodes[0].ToString() - << ", " << def.blade_tip_nodes[1].ToString() - << ", " << def.blade_tip_nodes[2].ToString() - << ", " << def.blade_tip_nodes[3].ToString() - << ", " << (def.couple_node.IsValidAnyState() ? def.couple_node.ToString() : "-1") - << ", " << def.turbine_power_kW - << ", " << def.pitch - << ", " << def.airfoil; + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.axis_node.ToString() << ", " + << def.blade_tip_nodes[0].ToString() << ", " << def.blade_tip_nodes[1].ToString() << ", " + << def.blade_tip_nodes[2].ToString() << ", " << def.blade_tip_nodes[3].ToString() << ", " + << (def.couple_node.IsValidAnyState() ? def.couple_node.ToString() : "-1") << ", " << def.turbine_power_kW + << ", " << def.pitch << ", " << def.airfoil; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessTurbojets(File::Module* module) +void Serializer::ProcessTurbojets(File::Module *module) { - if (module->turbojets.empty()) - { - return; - } + if (module->turbojets.empty()) { return; } m_stream << "turbojets" << endl; auto end_itor = module->turbojets.end(); for (auto itor = module->turbojets.begin(); itor != end_itor; ++itor) { - auto & def = *itor; + auto &def = *itor; - m_stream << "\n\t" << def.front_node.ToString() - << ", " << def.back_node.ToString() - << ", " << def.side_node.ToString() - << ", " << def.is_reversable - << ", " << def.dry_thrust - << ", " << def.wet_thrust - << ", " << def.front_diameter - << ", " << def.back_diameter - << ", " << def.nozzle_length; + m_stream << "\n\t" << def.front_node.ToString() << ", " << def.back_node.ToString() << ", " << def.side_node.ToString() + << ", " << def.is_reversable << ", " << def.dry_thrust << ", " << def.wet_thrust << ", " << def.front_diameter + << ", " << def.back_diameter << ", " << def.nozzle_length; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessScrewprops(File::Module* module) +void Serializer::ProcessScrewprops(File::Module *module) { - if (module->screwprops.empty()) - { - return; - } + if (module->screwprops.empty()) { return; } m_stream << "screwprops" << endl; auto end_itor = module->screwprops.end(); for (auto itor = module->screwprops.begin(); itor != end_itor; ++itor) { - auto & def = *itor; + auto &def = *itor; - m_stream << "\n\t" << def.prop_node.ToString() - << ", " << def.back_node.ToString() - << ", " << def.top_node.ToString() - << ", " << def.power; + m_stream << "\n\t" << def.prop_node.ToString() << ", " << def.back_node.ToString() << ", " << def.top_node.ToString() + << ", " << def.power; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessFusedrag(File::Module* module) +void Serializer::ProcessFusedrag(File::Module *module) { - + m_stream << ";fusedrag -- STUB" << endl; - + m_stream << endl << endl; // Empty line } -void Serializer::ProcessTurboprops(File::Module* module) +void Serializer::ProcessTurboprops(File::Module *module) { - if (module->turboprops_2.empty()) - { - return; - } + if (module->turboprops_2.empty()) { return; } m_stream << "turboprops" << endl; auto end_itor = module->turboprops_2.end(); for (auto itor = module->turboprops_2.begin(); itor != end_itor; ++itor) { - RigDef::Turboprop2 & def = *itor; + RigDef::Turboprop2 &def = *itor; - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.axis_node.ToString() - << ", " << def.blade_tip_nodes[0].ToString() - << ", " << def.blade_tip_nodes[1].ToString() - << ", " << def.blade_tip_nodes[2].ToString() - << ", " << def.blade_tip_nodes[3].ToString() - << ", " << def.turbine_power_kW - << ", " << def.airfoil; + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.axis_node.ToString() << ", " + << def.blade_tip_nodes[0].ToString() << ", " << def.blade_tip_nodes[1].ToString() << ", " + << def.blade_tip_nodes[2].ToString() << ", " << def.blade_tip_nodes[3].ToString() << ", " << def.turbine_power_kW + << ", " << def.airfoil; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessAirbrakes(File::Module* module) +void Serializer::ProcessAirbrakes(File::Module *module) { - if (module->airbrakes.empty()) - { - return; - } + if (module->airbrakes.empty()) { return; } m_stream << "airbrakes" << endl; auto end_itor = module->airbrakes.end(); for (auto itor = module->airbrakes.begin(); itor != end_itor; ++itor) { - RigDef::Airbrake & def = *itor; - - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.x_axis_node.ToString() - << ", " << def.y_axis_node.ToString() - << ", " << (def.aditional_node.IsValidAnyState() ? def.aditional_node.ToString() : "-1") - << ", " << def.offset.x - << ", " << def.offset.y - << ", " << def.offset.z - << ", " << def.width - << ", " << def.height - << ", " << def.max_inclination_angle - << ", " << def.texcoord_x1 - << ", " << def.texcoord_y1 - << ", " << def.texcoord_x2 - << ", " << def.texcoord_y2 - << ", " << def.lift_coefficient; + RigDef::Airbrake &def = *itor; + + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.x_axis_node.ToString() << ", " + << def.y_axis_node.ToString() << ", " + << (def.aditional_node.IsValidAnyState() ? def.aditional_node.ToString() : "-1") << ", " << def.offset.x << ", " + << def.offset.y << ", " << def.offset.z << ", " << def.width << ", " << def.height << ", " + << def.max_inclination_angle << ", " << def.texcoord_x1 << ", " << def.texcoord_y1 << ", " << def.texcoord_x2 + << ", " << def.texcoord_y2 << ", " << def.lift_coefficient; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessWings(File::Module* module) +void Serializer::ProcessWings(File::Module *module) { - if (module->wings.empty()) - { - return; - } + if (module->wings.empty()) { return; } m_stream << "wings" << endl; auto end_itor = module->wings.end(); for (auto itor = module->wings.begin(); itor != end_itor; ++itor) { - RigDef::Wing & def = *itor; - - m_stream << "\n\t" << def.nodes[0].ToString() - << ", " << def.nodes[1].ToString() - << ", " << def.nodes[2].ToString() - << ", " << def.nodes[3].ToString() - << ", " << def.nodes[4].ToString() - << ", " << def.nodes[5].ToString() - << ", " << def.nodes[6].ToString() - << ", " << def.nodes[7].ToString() - << ", " << def.tex_coords[0] - << ", " << def.tex_coords[1] - << ", " << def.tex_coords[2] - << ", " << def.tex_coords[3] - << ", " << def.tex_coords[4] - << ", " << def.tex_coords[5] - << ", " << def.tex_coords[6] - << ", " << def.tex_coords[7] - << ", " << def.control_surface - << ", " << def.chord_point - << ", " << def.min_deflection - << ", " << def.max_deflection - << ", " << def.airfoil - << ", " << def.efficacy_coef; + RigDef::Wing &def = *itor; + + m_stream << "\n\t" << def.nodes[0].ToString() << ", " << def.nodes[1].ToString() << ", " << def.nodes[2].ToString() + << ", " << def.nodes[3].ToString() << ", " << def.nodes[4].ToString() << ", " << def.nodes[5].ToString() << ", " + << def.nodes[6].ToString() << ", " << def.nodes[7].ToString() << ", " << def.tex_coords[0] << ", " + << def.tex_coords[1] << ", " << def.tex_coords[2] << ", " << def.tex_coords[3] << ", " << def.tex_coords[4] + << ", " << def.tex_coords[5] << ", " << def.tex_coords[6] << ", " << def.tex_coords[7] << ", " + << def.control_surface << ", " << def.chord_point << ", " << def.min_deflection << ", " << def.max_deflection + << ", " << def.airfoil << ", " << def.efficacy_coef; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessSoundsources(File::Module* module) +void Serializer::ProcessSoundsources(File::Module *module) { - if (module->soundsources.empty()) - { - return; - } + if (module->soundsources.empty()) { return; } m_stream << "soundsources" << endl; auto end_itor = module->soundsources.end(); for (auto itor = module->soundsources.begin(); itor != end_itor; ++itor) { - RigDef::SoundSource & def = *itor; + RigDef::SoundSource &def = *itor; m_stream << "\n\t" << def.node.ToString() << ", " << def.sound_script_name; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessSoundsources2(File::Module* module) +void Serializer::ProcessSoundsources2(File::Module *module) { - if (module->soundsources2.empty()) - { - return; - } + if (module->soundsources2.empty()) { return; } m_stream << "soundsources2" << endl; auto end_itor = module->soundsources2.end(); for (auto itor = module->soundsources2.begin(); itor != end_itor; ++itor) { - RigDef::SoundSource2 & def = *itor; + RigDef::SoundSource2 &def = *itor; - m_stream << "\n\t" << def.node.ToString() - << ", " << def.mode - << ", " << def.sound_script_name; + m_stream << "\n\t" << def.node.ToString() << ", " << def.mode << ", " << def.sound_script_name; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessExtCamera(File::Module* module) +void Serializer::ProcessExtCamera(File::Module *module) { - if (!module->ext_camera) - { - return; - } - RigDef::ExtCamera* def = module->ext_camera.get(); + if (!module->ext_camera) { return; } + RigDef::ExtCamera *def = module->ext_camera.get(); m_stream << "extcamera "; switch (def->mode) { - case ExtCamera::MODE_NODE: - m_stream << "node " << def->node.ToString(); - break; - case ExtCamera::MODE_CINECAM: - m_stream << "cinecam"; - break; + case ExtCamera::MODE_NODE: m_stream << "node " << def->node.ToString(); break; + case ExtCamera::MODE_CINECAM: m_stream << "cinecam"; break; case ExtCamera::MODE_CLASSIC: - default: - m_stream << "classic"; - break; + default: m_stream << "classic"; break; } - m_stream << "\n\n"; + m_stream << "\n\n"; } -void Serializer::ProcessVideocamera(File::Module* module) +void Serializer::ProcessVideocamera(File::Module *module) { - if (module->videocameras.empty()) - { - return; - } + if (module->videocameras.empty()) { return; } m_stream << "videocamera" << endl; auto end_itor = module->videocameras.end(); for (auto itor = module->videocameras.begin(); itor != end_itor; ++itor) { - RigDef::VideoCamera & def = *itor; - - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.left_node.ToString() - << ", " << def.bottom_node.ToString() - << ", " << (def.alt_reference_node.IsValidAnyState() ? def.alt_reference_node.ToString() : "-1") - << ", " << (def.alt_orientation_node.IsValidAnyState() ? def.alt_orientation_node.ToString() : "-1") - << ", " << def.offset.x - << ", " << def.offset.y - << ", " << def.offset.z - << ", " << def.rotation.x - << ", " << def.rotation.y - << ", " << def.rotation.z - << ", " << def.field_of_view - << ", " << def.texture_width - << ", " << def.texture_height - << ", " << def.min_clip_distance - << ", " << def.max_clip_distance - << ", " << def.camera_role - << ", " << def.camera_mode - << ", " << def.material_name; - if (!def.camera_name.empty()) - { - m_stream << ", " << def.camera_name; - } + RigDef::VideoCamera &def = *itor; + + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.left_node.ToString() << ", " + << def.bottom_node.ToString() << ", " + << (def.alt_reference_node.IsValidAnyState() ? def.alt_reference_node.ToString() : "-1") << ", " + << (def.alt_orientation_node.IsValidAnyState() ? def.alt_orientation_node.ToString() : "-1") << ", " + << def.offset.x << ", " << def.offset.y << ", " << def.offset.z << ", " << def.rotation.x << ", " + << def.rotation.y << ", " << def.rotation.z << ", " << def.field_of_view << ", " << def.texture_width << ", " + << def.texture_height << ", " << def.min_clip_distance << ", " << def.max_clip_distance << ", " + << def.camera_role << ", " << def.camera_mode << ", " << def.material_name; + if (!def.camera_name.empty()) { m_stream << ", " << def.camera_name; } } m_stream << endl << endl; // Empty line } -void Serializer::ProcessSetSkeletonSettings(File::Module* module) +void Serializer::ProcessSetSkeletonSettings(File::Module *module) { - RigDef::SkeletonSettings& def = module->skeleton_settings; + RigDef::SkeletonSettings &def = module->skeleton_settings; m_stream << "set_skeleton_settings " << def.visibility_range_meters << ", " << def.beam_thickness_meters << "\n\n"; } -void Serializer::ProcessGuiSettings(File::Module* module) +void Serializer::ProcessGuiSettings(File::Module *module) { - if (!module->gui_settings) - { - return; - } - RigDef::GuiSettings* def = module->gui_settings.get(); + if (!module->gui_settings) { return; } + RigDef::GuiSettings *def = module->gui_settings.get(); m_stream << "guisettings" - << "\n\tspeedoMax: " << def->speedo_highest_kph - << "\n\tuseMaxRPM: " << def->use_max_rpm; + << "\n\tspeedoMax: " << def->speedo_highest_kph << "\n\tuseMaxRPM: " << def->use_max_rpm; switch (def->interactive_overview_map_mode) { - case GuiSettings::MAP_MODE_OFF: - m_stream << "\n\tinteractiveOverviewMap: off"; - break; - case GuiSettings::MAP_MODE_SIMPLE: - m_stream << "\n\tinteractiveOverviewMap: simple"; - break; - case GuiSettings::MAP_MODE_ZOOM: - m_stream << "\n\tinteractiveOverviewMap: zoom"; - break; + case GuiSettings::MAP_MODE_OFF: m_stream << "\n\tinteractiveOverviewMap: off"; break; + case GuiSettings::MAP_MODE_SIMPLE: m_stream << "\n\tinteractiveOverviewMap: simple"; break; + case GuiSettings::MAP_MODE_ZOOM: m_stream << "\n\tinteractiveOverviewMap: zoom"; break; default:; } - if (!def->tacho_material.empty()) - { - m_stream << "\n\ttachoMaterial: " << def->tacho_material; - } - if (!def->speedo_material.empty()) - { - m_stream << "\n\tspeedoMaterial: " << def->speedo_material; - } - if (!def->help_material.empty()) - { - m_stream << "\n\thelpMaterial: " << def->help_material; - } + if (!def->tacho_material.empty()) { m_stream << "\n\ttachoMaterial: " << def->tacho_material; } + if (!def->speedo_material.empty()) { m_stream << "\n\tspeedoMaterial: " << def->speedo_material; } + if (!def->help_material.empty()) { m_stream << "\n\thelpMaterial: " << def->help_material; } auto end = def->dashboard_layouts.end(); for (auto itor = def->dashboard_layouts.begin(); itor != end; ++itor) { @@ -479,48 +363,40 @@ void Serializer::ProcessGuiSettings(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessExhausts(File::Module* module) +void Serializer::ProcessExhausts(File::Module *module) { - if (module->exhausts.empty()) - { - return; - } + if (module->exhausts.empty()) { return; } m_stream << "exhausts" << endl; auto end_itor = module->exhausts.end(); for (auto itor = module->exhausts.begin(); itor != end_itor; ++itor) { - RigDef::Exhaust & def = *itor; + RigDef::Exhaust &def = *itor; - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.direction_node.ToString() - << ", " << def.particle_name; + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.direction_node.ToString() << ", " << def.particle_name; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessSubmeshGroundmodel(File::Module* module) +void Serializer::ProcessSubmeshGroundmodel(File::Module *module) { // TODO - m_stream << ";submesh_groundmodel -- STUB"<< endl << endl; // Empty line + m_stream << ";submesh_groundmodel -- STUB" << endl << endl; // Empty line } -#define CAB_PRINT_OPTION_FLAG(VAR, FLAG, CHAR) \ +#define CAB_PRINT_OPTION_FLAG(VAR, FLAG, CHAR) \ if (BITMASK_IS_1(VAR, RigDef::Cab::FLAG)) { m_stream << CHAR; } -#define CAB_PRINT_OPTION_FUNC(DEF, FUNC, CHAR) \ +#define CAB_PRINT_OPTION_FUNC(DEF, FUNC, CHAR) \ if (DEF->FUNC()) { m_stream << CHAR; } -void Serializer::ProcessSubmesh(File::Module* module) +void Serializer::ProcessSubmesh(File::Module *module) { - if (module->submeshes.empty()) - { - return; - } + if (module->submeshes.empty()) { return; } m_stream << "submesh" << endl; auto end_itor = module->submeshes.end(); for (auto itor = module->submeshes.begin(); itor != end_itor; ++itor) { - RigDef::Submesh & def = *itor; + RigDef::Submesh &def = *itor; if (def.texcoords.size() > 0) { @@ -537,136 +413,113 @@ void Serializer::ProcessSubmesh(File::Module* module) auto cab_end = def.cab_triangles.end(); for (auto cab_itor = def.cab_triangles.begin(); cab_itor != cab_end; ++cab_itor) { - m_stream << "\n\t" << cab_itor->nodes[0].ToString() - << ", " << cab_itor->nodes[1].ToString() - << ", " << cab_itor->nodes[2].ToString() - << ", n"; + m_stream << "\n\t" << cab_itor->nodes[0].ToString() << ", " << cab_itor->nodes[1].ToString() << ", " + << cab_itor->nodes[2].ToString() << ", n"; // Options - CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_c_CONTACT , 'c') - CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_b_BUOYANT , 'b') - CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_p_10xTOUGHER , 'p') - CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_u_INVULNERABLE , 'u') - CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_s_BUOYANT_NO_DRAG , 's') - CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_r_BUOYANT_ONLY_DRAG , 'r') - CAB_PRINT_OPTION_FUNC(cab_itor, GetOption_D_ContactBuoyant , 'D') - CAB_PRINT_OPTION_FUNC(cab_itor, GetOption_F_10xTougherBuoyant , 'F') - CAB_PRINT_OPTION_FUNC(cab_itor, GetOption_S_UnpenetrableBuoyant , 'S') + CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_c_CONTACT, 'c') + CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_b_BUOYANT, 'b') + CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_p_10xTOUGHER, 'p') + CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_u_INVULNERABLE, 'u') + CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_s_BUOYANT_NO_DRAG, 's') + CAB_PRINT_OPTION_FLAG(cab_itor->options, OPTION_r_BUOYANT_ONLY_DRAG, 'r') + CAB_PRINT_OPTION_FUNC(cab_itor, GetOption_D_ContactBuoyant, 'D') + CAB_PRINT_OPTION_FUNC(cab_itor, GetOption_F_10xTougherBuoyant, 'F') + CAB_PRINT_OPTION_FUNC(cab_itor, GetOption_S_UnpenetrableBuoyant, 'S') } } - if (def.backmesh) - { - m_stream << "\n\tbackmesh"; - } + if (def.backmesh) { m_stream << "\n\tbackmesh"; } } m_stream << endl << endl; // Empty line } -#define PROP_ANIMATION_ADD_FLAG(FLAGS_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \ - if (AND_VAR) { m_stream << " | "; } \ - if (BITMASK_IS_1((FLAGS_VAR), RigDef::Animation::BITMASK_CONST)) { \ - AND_VAR = true; \ - m_stream << NAME_STR; \ +#define PROP_ANIMATION_ADD_FLAG(FLAGS_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \ + if (AND_VAR) { m_stream << " | "; } \ + if (BITMASK_IS_1((FLAGS_VAR), RigDef::Animation::BITMASK_CONST)) \ + { \ + AND_VAR = true; \ + m_stream << NAME_STR; \ } -void Serializer::ProcessDirectiveAddAnimation(RigDef::Animation & anim) +void Serializer::ProcessDirectiveAddAnimation(RigDef::Animation &anim) { - m_stream << "\n\tadd_animation " << anim.ratio - << ", " << anim.lower_limit - << ", " << anim.upper_limit - << ", source: "; - + m_stream << "\n\tadd_animation " << anim.ratio << ", " << anim.lower_limit << ", " << anim.upper_limit << ", source: "; + // Source flags - bool join = false; + bool join = false; unsigned int src_flags = anim.source; - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AIRSPEED , "airspeed"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AIRSPEED, "airspeed"); PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_VERTICAL_VELOCITY, "vvi"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ALTIMETER_100K , "altimeter100k"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ALTIMETER_10K , "altimeter10k"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ALTIMETER_1K , "altimeter1k"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ANGLE_OF_ATTACK , "aoa"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_FLAP , "flap"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AIR_BRAKE , "airbrake"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ROLL , "roll"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_PITCH , "pitch"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_BRAKES , "brakes"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ACCEL , "accel"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_CLUTCH , "clutch"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SPEEDO , "speedo"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_TACHO , "tacho"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_TURBO , "turbo"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_PARKING , "parking"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SHIFT_LEFT_RIGHT , "shifterman1"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SHIFT_BACK_FORTH , "shifterman2"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SEQUENTIAL_SHIFT , "sequential"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SHIFTERLIN , "shifterlin"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_TORQUE , "torque"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_HEADING , "heading"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_DIFFLOCK , "difflock"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_BOAT_RUDDER , "rudderboat"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_BOAT_THROTTLE , "throttleboat"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_STEERING_WHEEL , "steeringwheel"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AILERON , "aileron"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ELEVATOR , "elevator"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AIR_RUDDER , "rudderair"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_PERMANENT , "permanent"); - PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_EVENT , "event"); - + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ALTIMETER_100K, "altimeter100k"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ALTIMETER_10K, "altimeter10k"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ALTIMETER_1K, "altimeter1k"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ANGLE_OF_ATTACK, "aoa"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_FLAP, "flap"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AIR_BRAKE, "airbrake"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ROLL, "roll"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_PITCH, "pitch"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_BRAKES, "brakes"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ACCEL, "accel"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_CLUTCH, "clutch"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SPEEDO, "speedo"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_TACHO, "tacho"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_TURBO, "turbo"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_PARKING, "parking"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SHIFT_LEFT_RIGHT, "shifterman1"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SHIFT_BACK_FORTH, "shifterman2"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SEQUENTIAL_SHIFT, "sequential"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_SHIFTERLIN, "shifterlin"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_TORQUE, "torque"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_HEADING, "heading"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_DIFFLOCK, "difflock"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_BOAT_RUDDER, "rudderboat"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_BOAT_THROTTLE, "throttleboat"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_STEERING_WHEEL, "steeringwheel"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AILERON, "aileron"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_ELEVATOR, "elevator"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_AIR_RUDDER, "rudderair"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_PERMANENT, "permanent"); + PROP_ANIMATION_ADD_FLAG(src_flags, join, SOURCE_EVENT, "event"); + m_stream << ", mode: "; - join = false; + join = false; unsigned int mode_flags = anim.mode; - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_ROTATION_X , "x-rotation"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_ROTATION_Y , "y-rotation"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_ROTATION_Z , "z-rotation"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_OFFSET_X , "x-offset"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_OFFSET_Y , "y-offset"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_OFFSET_Z , "z-offset"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_ROTATION_X, "x-rotation"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_ROTATION_Y, "y-rotation"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_ROTATION_Z, "z-rotation"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_OFFSET_X, "x-offset"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_OFFSET_Y, "y-offset"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_OFFSET_Z, "z-offset"); PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_AUTO_ANIMATE, "autoanimate"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_NO_FLIP , "noflip"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_BOUNCE , "bounce"); - PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_EVENT_LOCK , "eventlock"); - - if (anim.HasSource_Event()) - { - m_stream << ", event: " << anim.event; - } + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_NO_FLIP, "noflip"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_BOUNCE, "bounce"); + PROP_ANIMATION_ADD_FLAG(mode_flags, join, MODE_EVENT_LOCK, "eventlock"); + + if (anim.HasSource_Event()) { m_stream << ", event: " << anim.event; } } -void Serializer::ProcessFlexbodies(File::Module* module) +void Serializer::ProcessFlexbodies(File::Module *module) { - if (module->flexbodies.empty()) - { - return; - } + if (module->flexbodies.empty()) { return; } m_stream << "flexbodies" << endl; auto end_itor = module->flexbodies.end(); for (auto itor = module->flexbodies.begin(); itor != end_itor; ++itor) { - RigDef::Flexbody* def = itor->get(); + RigDef::Flexbody *def = itor->get(); // Prop-like line - m_stream << "\n\t" << def->reference_node.ToString() - << ", " << def->x_axis_node.ToString() - << ", " << def->y_axis_node.ToString() - << ", " << def->offset.x - << ", " << def->offset.y - << ", " << def->offset.z - << ", " << def->rotation.x - << ", " << def->rotation.y - << ", " << def->rotation.z - << ", " << def->mesh_name; + m_stream << "\n\t" << def->reference_node.ToString() << ", " << def->x_axis_node.ToString() << ", " + << def->y_axis_node.ToString() << ", " << def->offset.x << ", " << def->offset.y << ", " << def->offset.z << ", " + << def->rotation.x << ", " << def->rotation.y << ", " << def->rotation.z << ", " << def->mesh_name; // Forset line m_stream << "\n\t\tforset (node list)"; - auto forset_end = def->node_list.end(); + auto forset_end = def->node_list.end(); auto forset_itor = def->node_list.begin(); - bool first = true; + bool first = true; for (; forset_itor != forset_end; ++forset_itor) { - if (!first) - { - m_stream << ", "; - } + if (!first) { m_stream << ", "; } m_stream << forset_itor->ToString(); first = false; } @@ -681,28 +534,18 @@ void Serializer::ProcessFlexbodies(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessPropsAndAnimations(File::Module* module) +void Serializer::ProcessPropsAndAnimations(File::Module *module) { - if (module->props.empty()) - { - return; - } + if (module->props.empty()) { return; } m_stream << "props" << endl; auto end_itor = module->props.end(); for (auto itor = module->props.begin(); itor != end_itor; ++itor) { - RigDef::Prop & def = *itor; - - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.x_axis_node.ToString() - << ", " << def.y_axis_node.ToString() - << ", " << def.offset.x - << ", " << def.offset.y - << ", " << def.offset.z - << ", " << def.rotation.x - << ", " << def.rotation.y - << ", " << def.rotation.z - << ", "; + RigDef::Prop &def = *itor; + + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.x_axis_node.ToString() << ", " + << def.y_axis_node.ToString() << ", " << def.offset.x << ", " << def.offset.y << ", " << def.offset.z << ", " + << def.rotation.x << ", " << def.rotation.y << ", " << def.rotation.z << ", "; if (def.special == Prop::SPECIAL_INVALID) { m_stream << def.mesh_name; @@ -712,19 +555,15 @@ void Serializer::ProcessPropsAndAnimations(File::Module* module) // Special props if (def.special == Prop::SPECIAL_BEACON) { - m_stream << def.mesh_name - << " " << def.special_prop_beacon.flare_material_name - << " " << def.special_prop_beacon.color.r - << ", " << def.special_prop_beacon.color.g - << ", " << def.special_prop_beacon.color.b; + m_stream << def.mesh_name << " " << def.special_prop_beacon.flare_material_name << " " + << def.special_prop_beacon.color.r << ", " << def.special_prop_beacon.color.g << ", " + << def.special_prop_beacon.color.b; } else if (def.special == Prop::SPECIAL_DASHBOARD_LEFT || def.special == Prop::SPECIAL_DASHBOARD_RIGHT) { - m_stream << " " << def.special_prop_dashboard.mesh_name - << " " << def.special_prop_dashboard.offset.x - << ", " << def.special_prop_dashboard.offset.y - << ", " << def.special_prop_dashboard.offset.z - << ", " << def.special_prop_dashboard.rotation_angle; + m_stream << " " << def.special_prop_dashboard.mesh_name << " " << def.special_prop_dashboard.offset.x << ", " + << def.special_prop_dashboard.offset.y << ", " << def.special_prop_dashboard.offset.z << ", " + << def.special_prop_dashboard.rotation_angle; } // Animations @@ -737,94 +576,67 @@ void Serializer::ProcessPropsAndAnimations(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessMaterialFlareBindings(File::Module* module) +void Serializer::ProcessMaterialFlareBindings(File::Module *module) { - if (module->material_flare_bindings.empty()) - { - return; - } + if (module->material_flare_bindings.empty()) { return; } m_stream << "materialflarebindings" << endl; auto end_itor = module->material_flare_bindings.end(); for (auto itor = module->material_flare_bindings.begin(); itor != end_itor; ++itor) { - RigDef::MaterialFlareBinding & def = *itor; + RigDef::MaterialFlareBinding &def = *itor; m_stream << "\n\t" << def.flare_number << ", " << def.material_name; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessFlares2(File::Module* module) +void Serializer::ProcessFlares2(File::Module *module) { - if (module->flares_2.empty()) - { - return; - } + if (module->flares_2.empty()) { return; } m_stream << "flares2" << endl; auto end_itor = module->flares_2.end(); for (auto itor = module->flares_2.begin(); itor != end_itor; ++itor) { - RigDef::Flare2 & def = *itor; + RigDef::Flare2 &def = *itor; - m_stream << "\n\t" << def.reference_node.ToString() - << ", " << def.node_axis_x.ToString() - << ", " << def.node_axis_y.ToString() - << ", " << def.offset.x - << ", " << def.offset.y - << ", " << def.type - << ", " << def.control_number - << ", " << def.blink_delay_milis - << ", " << def.size - << " " << def.material_name; + m_stream << "\n\t" << def.reference_node.ToString() << ", " << def.node_axis_x.ToString() << ", " + << def.node_axis_y.ToString() << ", " << def.offset.x << ", " << def.offset.y << ", " << def.type << ", " + << def.control_number << ", " << def.blink_delay_milis << ", " << def.size << " " << def.material_name; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessManagedMaterialsAndOptions(File::Module* module) +void Serializer::ProcessManagedMaterialsAndOptions(File::Module *module) { - if (module->managed_materials.empty()) - { - return; - } + if (module->managed_materials.empty()) { return; } m_stream << "managedmaterials" << endl; - auto end_itor = module->managed_materials.end(); - bool first = true; + auto end_itor = module->managed_materials.end(); + bool first = true; ManagedMaterialsOptions mm_options; for (auto itor = module->managed_materials.begin(); itor != end_itor; ++itor) { - RigDef::ManagedMaterial & def = *itor; + RigDef::ManagedMaterial &def = *itor; if (first || (mm_options.double_sided != def.options.double_sided)) { mm_options.double_sided = def.options.double_sided; - m_stream << "\n\tset_managedmaterials_options " << (int) mm_options.double_sided; + m_stream << "\n\tset_managedmaterials_options " << (int)mm_options.double_sided; } // Name m_stream << "\n\t" << def.name << " "; // Type switch (def.type) { - case ManagedMaterial::TYPE_FLEXMESH_STANDARD: - m_stream << "flexmesh_standard "; - break; - case ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT: - m_stream << "flexmesh_transparent "; - break; - case ManagedMaterial::TYPE_MESH_STANDARD: - m_stream << "mesh_standard "; - break; - case ManagedMaterial::TYPE_MESH_TRANSPARENT: - m_stream << "mesh_transparent "; - break; - default: - ; + case ManagedMaterial::TYPE_FLEXMESH_STANDARD: m_stream << "flexmesh_standard "; break; + case ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT: m_stream << "flexmesh_transparent "; break; + case ManagedMaterial::TYPE_MESH_STANDARD: m_stream << "mesh_standard "; break; + case ManagedMaterial::TYPE_MESH_TRANSPARENT: m_stream << "mesh_transparent "; break; + default:; } // Diffuse texture filename m_stream << def.diffuse_map << " "; // Diffuse damage-texture filename if (def.type == ManagedMaterial::TYPE_FLEXMESH_STANDARD || def.type == ManagedMaterial::TYPE_FLEXMESH_TRANSPARENT) - { - m_stream << (def.damaged_diffuse_map.empty() ? "-" : def.damaged_diffuse_map) << " "; - } + { m_stream << (def.damaged_diffuse_map.empty() ? "-" : def.damaged_diffuse_map) << " "; } // Specular texture m_stream << (def.specular_map.empty() ? "-" : def.specular_map); @@ -833,17 +645,14 @@ void Serializer::ProcessManagedMaterialsAndOptions(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessCollisionBoxes(File::Module* module) +void Serializer::ProcessCollisionBoxes(File::Module *module) { - if (module->collision_boxes.empty()) - { - return; - } + if (module->collision_boxes.empty()) { return; } m_stream << "collisionboxes" << endl; auto end_itor = module->collision_boxes.end(); for (auto itor = module->collision_boxes.begin(); itor != end_itor; ++itor) { - RigDef::CollisionBox & def = *itor; + RigDef::CollisionBox &def = *itor; auto nodes_end = def.nodes.end(); auto node_itor = def.nodes.begin(); @@ -857,22 +666,19 @@ void Serializer::ProcessCollisionBoxes(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessAxles(File::Module* module) +void Serializer::ProcessAxles(File::Module *module) { - if (module->axles.empty()) - { - return; - } + if (module->axles.empty()) { return; } m_stream << "axles" << endl; auto end_itor = module->axles.end(); for (auto itor = module->axles.begin(); itor != end_itor; ++itor) { - RigDef::Axle & def = *itor; + RigDef::Axle &def = *itor; m_stream << "\n\t" - << "w1(" << def.wheels[0][0].ToString() << " " << def.wheels[0][1].ToString() << "), " - << "w2(" << def.wheels[1][0].ToString() << " " << def.wheels[1][1].ToString() << ")"; - if (! def.options.empty()) + << "w1(" << def.wheels[0][0].ToString() << " " << def.wheels[0][1].ToString() << "), " + << "w2(" << def.wheels[1][0].ToString() << " " << def.wheels[1][1].ToString() << ")"; + if (!def.options.empty()) { m_stream << ", d("; auto end = def.options.end(); @@ -886,22 +692,17 @@ void Serializer::ProcessAxles(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessInterAxles(File::Module* module) +void Serializer::ProcessInterAxles(File::Module *module) { - if (module->interaxles.empty()) - { - return; - } + if (module->interaxles.empty()) { return; } m_stream << "interaxles" << endl; auto end_itor = module->interaxles.end(); for (auto itor = module->interaxles.begin(); itor != end_itor; ++itor) { - RigDef::InterAxle & def = *itor; + RigDef::InterAxle &def = *itor; - m_stream << "\n\t" - << def.a1 << ", " - << def.a2; - if (! def.options.empty()) + m_stream << "\n\t" << def.a1 << ", " << def.a2; + if (!def.options.empty()) { m_stream << ", d("; auto end = def.options.end(); @@ -915,58 +716,39 @@ void Serializer::ProcessInterAxles(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessTransferCase(File::Module* module) +void Serializer::ProcessTransferCase(File::Module *module) { - if (! module->transfer_case) + if (!module->transfer_case) { return; } + m_stream << "transfercase\t" << module->transfer_case->a1 << ", " << module->transfer_case->a2 << ", " + << module->transfer_case->has_2wd << ", " << module->transfer_case->has_2wd_lo; + for (float gear_ratio : module->transfer_case->gear_ratios) { - return; + m_stream << ", " << gear_ratio; } - m_stream << "transfercase\t" - << module->transfer_case->a1 << ", " - << module->transfer_case->a2 << ", " - << module->transfer_case->has_2wd << ", " - << module->transfer_case->has_2wd_lo; - for (float gear_ratio : module->transfer_case->gear_ratios) - { - m_stream << ", " << gear_ratio; - } - m_stream << endl << endl; + m_stream << endl << endl; } -void Serializer::ProcessCruiseControl(File::Module* module) +void Serializer::ProcessCruiseControl(File::Module *module) { - if (! module->cruise_control) - { - return; - } - m_stream << "cruisecontrol " - << module->cruise_control->min_speed << ", " - << (int) module->cruise_control->autobrake - << endl << endl; + if (!module->cruise_control) { return; } + m_stream << "cruisecontrol " << module->cruise_control->min_speed << ", " << (int)module->cruise_control->autobrake << endl + << endl; } -void Serializer::ProcessSpeedLimiter(File::Module* module) +void Serializer::ProcessSpeedLimiter(File::Module *module) { - if (! module->speed_limiter.is_enabled) - { - return; - } - m_stream << "speedlimiter " - << module->speed_limiter.max_speed - << endl << endl; + if (!module->speed_limiter.is_enabled) { return; } + m_stream << "speedlimiter " << module->speed_limiter.max_speed << endl << endl; } -void Serializer::ProcessTorqueCurve(File::Module* module) +void Serializer::ProcessTorqueCurve(File::Module *module) { - if (! module->torque_curve) - { - return; - } + if (!module->torque_curve) { return; } m_stream << "torquecurve" << endl; if (module->torque_curve->predefined_func_name.empty()) { auto itor_end = module->torque_curve->samples.end(); - auto itor = module->torque_curve->samples.begin(); + auto itor = module->torque_curve->samples.begin(); for (; itor != itor_end; ++itor) { m_stream << "\n\t" << itor->power << ", " << itor->torque_percent; @@ -979,75 +761,55 @@ void Serializer::ProcessTorqueCurve(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessParticles(File::Module* module) +void Serializer::ProcessParticles(File::Module *module) { - if (module->particles.empty()) - { - return; - } + if (module->particles.empty()) { return; } m_stream << "particles" << endl; auto end_itor = module->particles.end(); for (auto itor = module->particles.begin(); itor != end_itor; ++itor) { - RigDef::Particle & def = *itor; + RigDef::Particle &def = *itor; - m_stream << "\n\t" - << setw(m_node_id_width) << def.emitter_node.ToString() << ", " - << setw(m_node_id_width) << def.reference_node.ToString() << ", " - << def.particle_system_name; + m_stream << "\n\t" << setw(m_node_id_width) << def.emitter_node.ToString() << ", " << setw(m_node_id_width) + << def.reference_node.ToString() << ", " << def.particle_system_name; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessRopables(File::Module* module) +void Serializer::ProcessRopables(File::Module *module) { - if (module->ropables.empty()) - { - return; - } + if (module->ropables.empty()) { return; } m_stream << "ropables" << endl; auto end_itor = module->ropables.end(); for (auto itor = module->ropables.begin(); itor != end_itor; ++itor) { - RigDef::Ropable & def = *itor; + RigDef::Ropable &def = *itor; - m_stream << "\n\t" << def.node.ToString() - << ", " << def.group - << ", " << (int) def.has_multilock; + m_stream << "\n\t" << def.node.ToString() << ", " << def.group << ", " << (int)def.has_multilock; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessTies(File::Module* module) +void Serializer::ProcessTies(File::Module *module) { - if (module->ties.empty()) - { - return; - } + if (module->ties.empty()) { return; } m_stream << "ties" << endl; auto end_itor = module->ties.end(); for (auto itor = module->ties.begin(); itor != end_itor; ++itor) { - RigDef::Tie & def = *itor; + RigDef::Tie &def = *itor; - m_stream << "\n\t" << def.root_node.ToString() - << ", " << setw(m_float_width) << def.max_reach_length - << ", " << setw(m_float_width) << def.auto_shorten_rate - << ", " << setw(m_float_width) << def.min_length - << ", " << setw(m_float_width) << def.max_length - << ", " << (def.is_invisible ? "i" : "n") - << ", " << setw(m_float_width) << def.max_stress - << ", " << def.group; + m_stream << "\n\t" << def.root_node.ToString() << ", " << setw(m_float_width) << def.max_reach_length << ", " + << setw(m_float_width) << def.auto_shorten_rate << ", " << setw(m_float_width) << def.min_length << ", " + << setw(m_float_width) << def.max_length << ", " << (def.is_invisible ? "i" : "n") << ", " << setw(m_float_width) + << def.max_stress << ", " << def.group; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessFixes(File::Module* module) +void Serializer::ProcessFixes(File::Module *module) { - if (module->fixes.empty()) - { - return; - } + if (module->fixes.empty()) { return; } m_stream << "fixes" << endl; auto end_itor = module->fixes.end(); for (auto itor = module->fixes.begin(); itor != end_itor; ++itor) @@ -1057,89 +819,67 @@ void Serializer::ProcessFixes(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessRopes(File::Module* module) +void Serializer::ProcessRopes(File::Module *module) { - if (module->ropes.empty()) - { - return; - } + if (module->ropes.empty()) { return; } m_stream << "ropes" << endl; - auto end_itor = module->ropes.end(); - bool first = true; - BeamDefaults* beam_defaults = nullptr; + auto end_itor = module->ropes.end(); + bool first = true; + BeamDefaults *beam_defaults = nullptr; for (auto itor = module->ropes.begin(); itor != end_itor; ++itor) { - RigDef::Rope & def = *itor; + RigDef::Rope &def = *itor; - if (first || (def.beam_defaults.get() != beam_defaults)) - { - ProcessBeamDefaults(def.beam_defaults.get(), "\t"); - } + if (first || (def.beam_defaults.get() != beam_defaults)) { ProcessBeamDefaults(def.beam_defaults.get(), "\t"); } - m_stream << "\n\t" - << setw(m_node_id_width) << def.root_node.ToString() << ", " - << setw(m_node_id_width) << def.end_node.ToString(); - if (def.invisible) - { - m_stream << ", i"; - } + m_stream << "\n\t" << setw(m_node_id_width) << def.root_node.ToString() << ", " << setw(m_node_id_width) + << def.end_node.ToString(); + if (def.invisible) { m_stream << ", i"; } first = false; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessRailGroups(File::Module* module) +void Serializer::ProcessRailGroups(File::Module *module) { - if (module->railgroups.empty()) - { - return; - } + if (module->railgroups.empty()) { return; } m_stream << "railgroups" << endl << endl; auto end_itor = module->railgroups.end(); for (auto itor = module->railgroups.begin(); itor != end_itor; ++itor) { - RigDef::RailGroup & def = *itor; + RigDef::RailGroup &def = *itor; m_stream << "\n\t" << def.id; auto node_end = def.node_list.end(); for (auto node_itor = def.node_list.begin(); node_itor != node_end; ++node_itor) { m_stream << ", " << node_itor->start.ToString(); - if (node_itor->IsRange()) - { - m_stream << " - " << node_itor->end.ToString(); - } + if (node_itor->IsRange()) { m_stream << " - " << node_itor->end.ToString(); } } } m_stream << endl << endl; // Empty line } -void Serializer::ProcessSlideNodes(File::Module* module) +void Serializer::ProcessSlideNodes(File::Module *module) { - if (module->slidenodes.empty()) - { - return; - } + if (module->slidenodes.empty()) { return; } m_stream << "slidenodes" << endl << endl; auto end_itor = module->slidenodes.end(); for (auto itor = module->slidenodes.begin(); itor != end_itor; ++itor) { - RigDef::SlideNode & def = *itor; + RigDef::SlideNode &def = *itor; m_stream << "\n\t" << def.slide_node.ToString(); // Define rail - either list of nodes, or raigroup ID if (!def.rail_node_ranges.empty()) { - auto end = def.rail_node_ranges.end(); + auto end = def.rail_node_ranges.end(); auto itor = def.rail_node_ranges.begin(); for (; itor != end; ++itor) { m_stream << ", " << itor->start.ToString(); - if (itor->IsRange()) - { - m_stream << " - " << itor->end.ToString(); - } + if (itor->IsRange()) { m_stream << " - " << itor->end.ToString(); } } } else @@ -1148,67 +888,62 @@ void Serializer::ProcessSlideNodes(File::Module* module) } // Params - m_stream - << ", s" << def.spring_rate - << ", b" << def.break_force - << ", t" << def.tolerance - << ", r" << def.attachment_rate - << ", d" << def.max_attachment_distance; + m_stream << ", s" << def.spring_rate << ", b" << def.break_force << ", t" << def.tolerance << ", r" << def.attachment_rate + << ", d" << def.max_attachment_distance; // Constraint flags (cX) - if (def.HasConstraint_a_AttachAll()) { m_stream << ", ca"; } - else if (def.HasConstraint_f_AttachForeign()) { m_stream << ", cf"; } - else if (def.HasConstraint_s_AttachSelf()) { m_stream << ", cs"; } - else if (def.HasConstraint_n_AttachNone()) { m_stream << ", cn"; } + if (def.HasConstraint_a_AttachAll()) { m_stream << ", ca"; } + else if (def.HasConstraint_f_AttachForeign()) + { + m_stream << ", cf"; + } + else if (def.HasConstraint_s_AttachSelf()) + { + m_stream << ", cs"; + } + else if (def.HasConstraint_n_AttachNone()) + { + m_stream << ", cn"; + } } m_stream << endl << endl; // Empty line } -void Serializer::ProcessHooks(File::Module* module) +void Serializer::ProcessHooks(File::Module *module) { - if (module->hooks.empty()) - { - return; - } + if (module->hooks.empty()) { return; } m_stream << "hooks" << endl << endl; auto end_itor = module->hooks.end(); for (auto itor = module->hooks.begin(); itor != end_itor; ++itor) { - RigDef::Hook & def = *itor; + RigDef::Hook &def = *itor; m_stream << "\n\t" << def.node.ToString(); // Boolean options - if (def.flag_auto_lock) { m_stream << ", auto-lock"; } + if (def.flag_auto_lock) { m_stream << ", auto-lock"; } if (def.flag_no_disable) { m_stream << ", nodisable"; } - if (def.flag_no_rope) { m_stream << ", norope"; } - if (def.flag_self_lock) { m_stream << ", self-lock"; } - if (def.flag_visible) { m_stream << ", visible"; } + if (def.flag_no_rope) { m_stream << ", norope"; } + if (def.flag_self_lock) { m_stream << ", self-lock"; } + if (def.flag_visible) { m_stream << ", visible"; } // Key-value options - m_stream - << ", hookrange: " << def.option_hook_range - << ", speedcoef: " << def.option_speed_coef - << ", maxforce: " << def.option_max_force - << ", hookgroup: " << def.option_hookgroup - << ", lockgroup: " << def.option_lockgroup - << ", timer: " << def.option_timer - << ", shortlimit: "<< def.option_min_range_meters; + m_stream << ", hookrange: " << def.option_hook_range << ", speedcoef: " << def.option_speed_coef + << ", maxforce: " << def.option_max_force << ", hookgroup: " << def.option_hookgroup + << ", lockgroup: " << def.option_lockgroup << ", timer: " << def.option_timer + << ", shortlimit: " << def.option_min_range_meters; } m_stream << endl << endl; // Empty line } -void Serializer::ProcessLockgroups(File::Module* module) +void Serializer::ProcessLockgroups(File::Module *module) { - if (module->lockgroups.empty()) - { - return; - } + if (module->lockgroups.empty()) { return; } m_stream << "lockgroups" << endl << endl; auto end_itor = module->lockgroups.end(); for (auto itor = module->lockgroups.begin(); itor != end_itor; ++itor) { - RigDef::Lockgroup & def = *itor; + RigDef::Lockgroup &def = *itor; m_stream << "\n\t" << def.number; auto nodes_end = def.nodes.end(); @@ -1220,155 +955,135 @@ void Serializer::ProcessLockgroups(File::Module* module) m_stream << endl << endl; // Empty line } -void Serializer::ProcessTriggers(File::Module* module) +void Serializer::ProcessTriggers(File::Module *module) { - if (module->triggers.empty()) - { - return; - } + if (module->triggers.empty()) { return; } m_stream << "animators" << endl << endl; auto end_itor = module->triggers.end(); for (auto itor = module->triggers.begin(); itor != end_itor; ++itor) { - RigDef::Trigger & def = *itor; + RigDef::Trigger &def = *itor; - m_stream << "\n\t" - << def.nodes[0].ToString() << ", " - << def.nodes[1].ToString() << ", " - << def.contraction_trigger_limit << ", " - << def.expansion_trigger_limit << ", " - << def.shortbound_trigger_action << ", " - << def.longbound_trigger_action << ", "; - - if (def.HasFlag_i_Invisible() ) { m_stream << "i"; } - if (def.HasFlag_c_CommandStyle() ) { m_stream << "c"; } - if (def.HasFlag_x_StartDisabled() ) { m_stream << "x"; } - if (def.HasFlag_b_KeyBlocker() ) { m_stream << "b"; } - if (def.HasFlag_B_TriggerBlocker() ) { m_stream << "B"; } - if (def.HasFlag_A_InvTriggerBlocker() ) { m_stream << "A"; } - if (def.HasFlag_s_CmdNumSwitch() ) { m_stream << "s"; } - if (def.HasFlag_h_UnlocksHookGroup() ) { m_stream << "h"; } - if (def.HasFlag_H_LocksHookGroup() ) { m_stream << "H"; } - if (def.HasFlag_t_Continuous() ) { m_stream << "t"; } - if (def.HasFlag_E_EngineTrigger() ) { m_stream << "E"; } + m_stream << "\n\t" << def.nodes[0].ToString() << ", " << def.nodes[1].ToString() << ", " << def.contraction_trigger_limit + << ", " << def.expansion_trigger_limit << ", " << def.shortbound_trigger_action << ", " + << def.longbound_trigger_action << ", "; + + if (def.HasFlag_i_Invisible()) { m_stream << "i"; } + if (def.HasFlag_c_CommandStyle()) { m_stream << "c"; } + if (def.HasFlag_x_StartDisabled()) { m_stream << "x"; } + if (def.HasFlag_b_KeyBlocker()) { m_stream << "b"; } + if (def.HasFlag_B_TriggerBlocker()) { m_stream << "B"; } + if (def.HasFlag_A_InvTriggerBlocker()) { m_stream << "A"; } + if (def.HasFlag_s_CmdNumSwitch()) { m_stream << "s"; } + if (def.HasFlag_h_UnlocksHookGroup()) { m_stream << "h"; } + if (def.HasFlag_H_LocksHookGroup()) { m_stream << "H"; } + if (def.HasFlag_t_Continuous()) { m_stream << "t"; } + if (def.HasFlag_E_EngineTrigger()) { m_stream << "E"; } m_stream << " " << def.boundary_timer; } m_stream << endl << endl; // Empty line } -#define ANIMATOR_ADD_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \ - if (AND_VAR) { m_stream << " | "; } \ - if (BITMASK_IS_1((DEF_VAR).flags, RigDef::Animator::BITMASK_CONST)) { \ - AND_VAR = true; \ - m_stream << NAME_STR; \ +#define ANIMATOR_ADD_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \ + if (AND_VAR) { m_stream << " | "; } \ + if (BITMASK_IS_1((DEF_VAR).flags, RigDef::Animator::BITMASK_CONST)) \ + { \ + AND_VAR = true; \ + m_stream << NAME_STR; \ } -#define ANIMATOR_ADD_AERIAL_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \ - if (AND_VAR) { m_stream << " | "; } \ - if (BITMASK_IS_1((DEF_VAR).aero_animator.flags, RigDef::AeroAnimator::BITMASK_CONST)) { \ - AND_VAR = true; \ - m_stream << NAME_STR << DEF_VAR.aero_animator.motor; \ +#define ANIMATOR_ADD_AERIAL_FLAG(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR) \ + if (AND_VAR) { m_stream << " | "; } \ + if (BITMASK_IS_1((DEF_VAR).aero_animator.flags, RigDef::AeroAnimator::BITMASK_CONST)) \ + { \ + AND_VAR = true; \ + m_stream << NAME_STR << DEF_VAR.aero_animator.motor; \ } -#define ANIMATOR_ADD_LIMIT(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR, VALUE) \ - if (AND_VAR) { m_stream << " | "; } \ - if (BITMASK_IS_1((DEF_VAR).aero_animator.flags, RigDef::Animator::BITMASK_CONST)) { \ - AND_VAR = true; \ - m_stream << NAME_STR << ": " << VALUE; \ +#define ANIMATOR_ADD_LIMIT(DEF_VAR, AND_VAR, BITMASK_CONST, NAME_STR, VALUE) \ + if (AND_VAR) { m_stream << " | "; } \ + if (BITMASK_IS_1((DEF_VAR).aero_animator.flags, RigDef::Animator::BITMASK_CONST)) \ + { \ + AND_VAR = true; \ + m_stream << NAME_STR << ": " << VALUE; \ } -void Serializer::ProcessAnimators(File::Module* module) +void Serializer::ProcessAnimators(File::Module *module) { - if (module->animators.empty()) - { - return; - } + if (module->animators.empty()) { return; } m_stream << "animators" << endl << endl; auto end_itor = module->animators.end(); for (auto itor = module->animators.begin(); itor != end_itor; ++itor) { - RigDef::Animator & def = *itor; + RigDef::Animator &def = *itor; - m_stream << "\t" - << def.nodes[0].ToString() << ", " - << def.nodes[1].ToString() << ", " - << def.lenghtening_factor << ", "; + m_stream << "\t" << def.nodes[0].ToString() << ", " << def.nodes[1].ToString() << ", " << def.lenghtening_factor << ", "; // Options bool bAnd = false; - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_VISIBLE , "vis") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_INVISIBLE , "inv") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_AIRSPEED , "airspeed") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_VISIBLE, "vis") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_INVISIBLE, "inv") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_AIRSPEED, "airspeed") ANIMATOR_ADD_FLAG(def, bAnd, OPTION_VERTICAL_VELOCITY, "vvi") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_100K , "altimeter100k") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_10K , "altimeter10k") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_1K , "altimeter1k") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ANGLE_OF_ATTACK , "aoa") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_FLAP , "flap") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_AIR_BRAKE , "airbrake") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ROLL , "roll") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_PITCH , "pitch") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BRAKES , "brakes") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ACCEL , "accel") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_CLUTCH , "clutch") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SPEEDO , "speedo") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TACHO , "tacho") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TURBO , "turbo") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_PARKING , "parking") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHIFT_LEFT_RIGHT , "shifterman1") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHIFT_BACK_FORTH , "shifterman2") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SEQUENTIAL_SHIFT , "sequential") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_GEAR_SELECT , "shifterlin") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TORQUE , "torque") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_DIFFLOCK , "difflock") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BOAT_RUDDER , "rudderboat") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BOAT_THROTTLE , "throttleboat") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHORT_LIMIT , "shortlimit") - ANIMATOR_ADD_FLAG(def, bAnd, OPTION_LONG_LIMIT , "longlimit") - - ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_THROTTLE , "throttle") - ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_RPM , "rpm") - ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_TORQUE , "aerotorq") - ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_PITCH , "aeropit") - ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_STATUS , "aerostatus") - - ANIMATOR_ADD_LIMIT(def, bAnd, OPTION_SHORT_LIMIT , "shortlimit", def.short_limit) - ANIMATOR_ADD_LIMIT(def, bAnd, OPTION_LONG_LIMIT , "longlimit", def.long_limit) + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_100K, "altimeter100k") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_10K, "altimeter10k") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ALTIMETER_1K, "altimeter1k") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ANGLE_OF_ATTACK, "aoa") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_FLAP, "flap") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_AIR_BRAKE, "airbrake") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ROLL, "roll") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_PITCH, "pitch") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BRAKES, "brakes") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_ACCEL, "accel") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_CLUTCH, "clutch") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SPEEDO, "speedo") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TACHO, "tacho") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TURBO, "turbo") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_PARKING, "parking") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHIFT_LEFT_RIGHT, "shifterman1") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHIFT_BACK_FORTH, "shifterman2") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SEQUENTIAL_SHIFT, "sequential") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_GEAR_SELECT, "shifterlin") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_TORQUE, "torque") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_DIFFLOCK, "difflock") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BOAT_RUDDER, "rudderboat") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_BOAT_THROTTLE, "throttleboat") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_SHORT_LIMIT, "shortlimit") + ANIMATOR_ADD_FLAG(def, bAnd, OPTION_LONG_LIMIT, "longlimit") + + ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_THROTTLE, "throttle") + ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_RPM, "rpm") + ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_TORQUE, "aerotorq") + ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_PITCH, "aeropit") + ANIMATOR_ADD_AERIAL_FLAG(def, bAnd, OPTION_STATUS, "aerostatus") + + ANIMATOR_ADD_LIMIT(def, bAnd, OPTION_SHORT_LIMIT, "shortlimit", def.short_limit) + ANIMATOR_ADD_LIMIT(def, bAnd, OPTION_LONG_LIMIT, "longlimit", def.long_limit) } m_stream << endl << endl; // Empty line } -void Serializer::ProcessContacters(File::Module* module) +void Serializer::ProcessContacters(File::Module *module) { - if (module->contacters.empty()) - { - return; - } + if (module->contacters.empty()) { return; } m_stream << "contacters" << endl << endl; auto end_itor = module->rotators.end(); - for (auto itor = module->rotators.begin(); itor != end_itor; ++itor) - { - } + for (auto itor = module->rotators.begin(); itor != end_itor; ++itor) {} m_stream << endl << endl; // Empty line } -void Serializer::ProcessRotators(File::Module* module) +void Serializer::ProcessRotators(File::Module *module) { - if (module->rotators.empty()) - { - return; - } + if (module->rotators.empty()) { return; } m_stream << "rotators" << endl << endl; auto end_itor = module->rotators.end(); for (auto itor = module->rotators.begin(); itor != end_itor; ++itor) { - Rotator & def = *itor; + Rotator &def = *itor; // Axis nodes - m_stream - << def.axis_nodes[0].ToString() << ", " - << def.axis_nodes[1].ToString() << ", "; + m_stream << def.axis_nodes[0].ToString() << ", " << def.axis_nodes[1].ToString() << ", "; // Baseplate nodes for (int i = 0; i < 4; ++i) @@ -1381,38 +1096,29 @@ void Serializer::ProcessRotators(File::Module* module) { m_stream << def.rotating_plate_nodes[i].ToString() << ", "; } - + // Attributes m_stream << def.rate << ", " << def.spin_left_key << ", " << def.spin_right_key << ", "; // Inertia - m_stream - << def.inertia.start_delay_factor << ", " - << def.inertia.stop_delay_factor << ", " - << def.inertia.start_function << ", " - << def.inertia.stop_function << ", " - << def.engine_coupling << ", " - << (def.needs_engine ? "true" : "false"); + m_stream << def.inertia.start_delay_factor << ", " << def.inertia.stop_delay_factor << ", " << def.inertia.start_function + << ", " << def.inertia.stop_function << ", " << def.engine_coupling << ", " + << (def.needs_engine ? "true" : "false"); } m_stream << endl << endl; // Empty line } -void Serializer::ProcessRotators2(File::Module* module) +void Serializer::ProcessRotators2(File::Module *module) { - if (module->rotators_2.empty()) - { - return; - } + if (module->rotators_2.empty()) { return; } m_stream << "rotators2" << endl << endl; auto end_itor = module->rotators_2.end(); for (auto itor = module->rotators_2.begin(); itor != end_itor; ++itor) { - Rotator2 & def = *itor; + Rotator2 &def = *itor; // Axis nodes - m_stream - << def.axis_nodes[0].ToString() << ", " - << def.axis_nodes[1].ToString() << ", "; + m_stream << def.axis_nodes[0].ToString() << ", " << def.axis_nodes[1].ToString() << ", "; // Baseplate nodes for (int i = 0; i < 4; ++i) @@ -1425,135 +1131,99 @@ void Serializer::ProcessRotators2(File::Module* module) { m_stream << def.rotating_plate_nodes[i].ToString() << ", "; } - + // Attributes - m_stream - << def.rate << ", " - << def.spin_left_key << ", " - << def.spin_right_key << ", " - << def.rotating_force << ", " - << def.tolerance << ", " - << def.description << ", "; + m_stream << def.rate << ", " << def.spin_left_key << ", " << def.spin_right_key << ", " << def.rotating_force << ", " + << def.tolerance << ", " << def.description << ", "; // Inertia - m_stream - << def.inertia.start_delay_factor << ", " - << def.inertia.stop_delay_factor << ", " - << def.inertia.start_function << ", " - << def.inertia.stop_function << ", " - << def.engine_coupling << ", " - << (def.needs_engine ? "true" : "false"); + m_stream << def.inertia.start_delay_factor << ", " << def.inertia.stop_delay_factor << ", " << def.inertia.start_function + << ", " << def.inertia.stop_function << ", " << def.engine_coupling << ", " + << (def.needs_engine ? "true" : "false"); } m_stream << endl << endl; // Empty line } -void Serializer::ProcessFlexBodyWheels(File::Module* module) +void Serializer::ProcessFlexBodyWheels(File::Module *module) { - if (module->flex_body_wheels.empty()) - { - return; - } + if (module->flex_body_wheels.empty()) { return; } m_stream << "flexbodywheels" << endl << endl; auto end_itor = module->flex_body_wheels.end(); for (auto itor = module->flex_body_wheels.begin(); itor != end_itor; ++itor) { - m_stream << "\t" - << setw(m_float_width) << itor->tyre_radius << ", " - << setw(m_float_width) << itor->rim_radius << ", " - << setw(m_float_width) << itor->width << ", " - << setw(3) << itor->num_rays << ", " - << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " - << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " - << setw(3) << itor->braking << ", " - << setw(3) << itor->propulsion << ", " - << setw(m_node_id_width) << itor->reference_arm_node.ToString() << ", " - << setw(m_float_width) << itor->mass << ", " - << setw(m_float_width) << itor->tyre_springiness << ", " - << setw(m_float_width) << itor->tyre_damping << ", " - << (static_cast(itor->side)) << ", " - << itor->rim_mesh_name << " " // Separator = space! - << itor->tyre_mesh_name - << endl; + m_stream << "\t" << setw(m_float_width) << itor->tyre_radius << ", " << setw(m_float_width) << itor->rim_radius << ", " + << setw(m_float_width) << itor->width << ", " << setw(3) << itor->num_rays << ", " << setw(m_node_id_width) + << itor->nodes[0].ToString() << ", " << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " + << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " << setw(3) << itor->braking << ", " << setw(3) + << itor->propulsion << ", " << setw(m_node_id_width) << itor->reference_arm_node.ToString() << ", " + << setw(m_float_width) << itor->mass << ", " << setw(m_float_width) << itor->tyre_springiness << ", " + << setw(m_float_width) << itor->tyre_damping << ", " << (static_cast(itor->side)) << ", " + << itor->rim_mesh_name << " " // Separator = space! + << itor->tyre_mesh_name << endl; } m_stream << endl; // Empty line } -void Serializer::ProcessSlopeBrake(File::Module* module) +void Serializer::ProcessSlopeBrake(File::Module *module) { if (module->slope_brake) { - m_stream << "SlopeBrake " - << module->slope_brake->regulating_force << ", " - << module->slope_brake->attach_angle << ", " - << module->slope_brake->release_angle - << endl << endl; + m_stream << "SlopeBrake " << module->slope_brake->regulating_force << ", " << module->slope_brake->attach_angle << ", " + << module->slope_brake->release_angle << endl + << endl; } } -void Serializer::ProcessTractionControl(File::Module* module) +void Serializer::ProcessTractionControl(File::Module *module) { if (module->traction_control == nullptr) { return; } - RigDef::TractionControl* tc = module->traction_control.get(); + RigDef::TractionControl *tc = module->traction_control.get(); - m_stream << "TractionControl " - << tc->regulation_force << ", " - << tc->wheel_slip << ", " - << tc->fade_speed << ", " - << tc->pulse_per_sec << ", mode: " << (tc->attr_is_on ? "ON" : "OFF"); + m_stream << "TractionControl " << tc->regulation_force << ", " << tc->wheel_slip << ", " << tc->fade_speed << ", " + << tc->pulse_per_sec << ", mode: " << (tc->attr_is_on ? "ON" : "OFF"); // Modes - if (tc->attr_no_dashboard) { m_stream << " & NODASH "; } - if (tc->attr_no_toggle) { m_stream << " & NOTOGGLE "; } + if (tc->attr_no_dashboard) { m_stream << " & NODASH "; } + if (tc->attr_no_toggle) { m_stream << " & NOTOGGLE "; } } -void Serializer::ProcessBrakes(File::Module* module) +void Serializer::ProcessBrakes(File::Module *module) { - m_stream << "brakes\n\t" - << module->brakes->default_braking_force << ", " - << module->brakes->parking_brake_force; + m_stream << "brakes\n\t" << module->brakes->default_braking_force << ", " << module->brakes->parking_brake_force; } -void Serializer::ProcessAntiLockBrakes(File::Module* module) +void Serializer::ProcessAntiLockBrakes(File::Module *module) { if (module->anti_lock_brakes == nullptr) { return; } - RigDef::AntiLockBrakes* alb = module->anti_lock_brakes.get(); + RigDef::AntiLockBrakes *alb = module->anti_lock_brakes.get(); - m_stream << "AntiLockBrakes " - << alb->regulation_force << ", " - << alb->min_speed << ", " - << alb->pulse_per_sec << ", mode: " << (alb->attr_is_on ? "ON" : "OFF"); + m_stream << "AntiLockBrakes " << alb->regulation_force << ", " << alb->min_speed << ", " << alb->pulse_per_sec + << ", mode: " << (alb->attr_is_on ? "ON" : "OFF"); // Modes - if (alb->attr_no_dashboard) { m_stream << " & NODASH "; } - if (alb->attr_no_toggle) { m_stream << " & NOTOGGLE "; } + if (alb->attr_no_dashboard) { m_stream << " & NODASH "; } + if (alb->attr_no_toggle) { m_stream << " & NOTOGGLE "; } } -void Serializer::ProcessEngine(File::Module* module) +void Serializer::ProcessEngine(File::Module *module) { - if (module->engine.get() == nullptr) - { - return; - } - - m_stream << "engine" - "\n;\t" - "ShiftDownRPM," - " ShiftUpRPM," - " Torque," - " GlobalGear," - " ReverseGear," - " NeutralGear," - " Forward gears...\n\t" - << setw(12) << module->engine->shift_down_rpm << ", " - << setw(10) << module->engine->shift_up_rpm << ", " - << setw(10) << module->engine->torque << ", " - << setw(10) << module->engine->global_gear_ratio << ", " - << setw(11) << module->engine->reverse_gear_ratio << ", " - << setw(11) << module->engine->neutral_gear_ratio; - - auto itor = module->engine->gear_ratios.begin(); + if (module->engine.get() == nullptr) { return; } + + m_stream << "engine" + "\n;\t" + "ShiftDownRPM," + " ShiftUpRPM," + " Torque," + " GlobalGear," + " ReverseGear," + " NeutralGear," + " Forward gears...\n\t" + << setw(12) << module->engine->shift_down_rpm << ", " << setw(10) << module->engine->shift_up_rpm << ", " << setw(10) + << module->engine->torque << ", " << setw(10) << module->engine->global_gear_ratio << ", " << setw(11) + << module->engine->reverse_gear_ratio << ", " << setw(11) << module->engine->neutral_gear_ratio; + + auto itor = module->engine->gear_ratios.begin(); auto end = module->engine->gear_ratios.end(); for (; itor != end; ++itor) { @@ -1562,119 +1232,86 @@ void Serializer::ProcessEngine(File::Module* module) m_stream << ", -1.0" /*terminator*/ << endl << endl; } -void Serializer::ProcessEngoption(File::Module* module) +void Serializer::ProcessEngoption(File::Module *module) { - if (module->engoption.get() == nullptr) - { - return; - } - + if (module->engoption.get() == nullptr) { return; } + m_stream << "engoption" - "\n;\t" - "EngInertia," - " EngineType," - " ClutchForce," - " ShiftTime," - " ClutchTime," - " PostShiftTime," - " StallRPM," - " IdleRPM," - " MaxIdleMixture," - " MinIdleMixture" - " BrakingForce" - "\n\t" - << setw(10) << module->engoption->inertia << ", " - << setw(10) << (char)module->engoption->type << ", " - << setw(11) << module->engoption->clutch_force << ", " - << setw( 9) << module->engoption->shift_time << ", " - << setw(10) << module->engoption->clutch_time << ", " - << setw(13) << module->engoption->post_shift_time << ", " - << setw( 8) << module->engoption->stall_rpm << ", " - << setw( 7) << module->engoption->idle_rpm << ", " - << setw(14) << module->engoption->max_idle_mixture << ", " - << setw(14) << module->engoption->min_idle_mixture << ", " - << setw(15) << module->engoption->braking_torque; - + "\n;\t" + "EngInertia," + " EngineType," + " ClutchForce," + " ShiftTime," + " ClutchTime," + " PostShiftTime," + " StallRPM," + " IdleRPM," + " MaxIdleMixture," + " MinIdleMixture" + " BrakingForce" + "\n\t" + << setw(10) << module->engoption->inertia << ", " << setw(10) << (char)module->engoption->type << ", " << setw(11) + << module->engoption->clutch_force << ", " << setw(9) << module->engoption->shift_time << ", " << setw(10) + << module->engoption->clutch_time << ", " << setw(13) << module->engoption->post_shift_time << ", " << setw(8) + << module->engoption->stall_rpm << ", " << setw(7) << module->engoption->idle_rpm << ", " << setw(14) + << module->engoption->max_idle_mixture << ", " << setw(14) << module->engoption->min_idle_mixture << ", " << setw(15) + << module->engoption->braking_torque; + m_stream << endl << endl; } -void Serializer::ProcessHelp(File::Module* module) +void Serializer::ProcessHelp(File::Module *module) { - if (module->help_panel_material_name.empty()) - { - return; - } + if (module->help_panel_material_name.empty()) { return; } m_stream << "help\n\t" << module->help_panel_material_name << endl << endl; } -void Serializer::ProcessWheels2(File::Module* module) +void Serializer::ProcessWheels2(File::Module *module) { - if (module->wheels_2.empty()) - { - return; - } + if (module->wheels_2.empty()) { return; } m_stream << "wheels2" << endl << endl; auto end_itor = module->wheels_2.end(); for (auto itor = module->wheels_2.begin(); itor != end_itor; ++itor) { - m_stream << "\t" - << setw(m_float_width) << itor->tyre_radius << ", " - << setw(m_float_width) << itor->rim_radius << ", " - << setw(m_float_width) << itor->width << ", " - << setw(3) << itor->num_rays << ", " - << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " - << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " - << setw(3) << itor->braking << ", " - << setw(3) << itor->propulsion << ", " - << setw(m_node_id_width) << itor->reference_arm_node.ToString() << ", " - << setw(m_float_width) << itor->mass << ", " - << setw(m_float_width) << itor->rim_springiness << ", " - << setw(m_float_width) << itor->rim_damping << ", " - << setw(m_float_width) << itor->tyre_springiness << ", " - << setw(m_float_width) << itor->tyre_damping << ", " - << itor->face_material_name << " " // Separator = space! - << itor->band_material_name << " " // Separator = space! - ; + m_stream << "\t" << setw(m_float_width) << itor->tyre_radius << ", " << setw(m_float_width) << itor->rim_radius << ", " + << setw(m_float_width) << itor->width << ", " << setw(3) << itor->num_rays << ", " << setw(m_node_id_width) + << itor->nodes[0].ToString() << ", " << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " + << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " << setw(3) << itor->braking << ", " << setw(3) + << itor->propulsion << ", " << setw(m_node_id_width) << itor->reference_arm_node.ToString() << ", " + << setw(m_float_width) << itor->mass << ", " << setw(m_float_width) << itor->rim_springiness << ", " + << setw(m_float_width) << itor->rim_damping << ", " << setw(m_float_width) << itor->tyre_springiness << ", " + << setw(m_float_width) << itor->tyre_damping << ", " << itor->face_material_name << " " // Separator = space! + << itor->band_material_name << " " // Separator = space! + ; m_stream << endl; } m_stream << endl; // Empty line } -void Serializer::ProcessWheels(File::Module* module) +void Serializer::ProcessWheels(File::Module *module) { - if (module->wheels.empty()) - { - return; - } + if (module->wheels.empty()) { return; } m_stream << "wheels" << endl << endl; auto end_itor = module->wheels.end(); for (auto itor = module->wheels.begin(); itor != end_itor; ++itor) { - m_stream << "\t" - << setw(m_float_width) << itor->radius << ", " - << setw(m_float_width) << itor->width << ", " - << setw(3) << itor->num_rays << ", " - << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " - << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " - << setw(3) << itor->braking << ", " - << setw(3) << itor->propulsion << ", " - << setw(m_node_id_width) << itor->reference_arm_node.ToString() << ", " - << setw(m_float_width) << itor->mass << ", " - << setw(m_float_width) << itor->springiness << ", " - << setw(m_float_width) << itor->damping << ", " - << itor->face_material_name << " " // Separator = space! - << itor->band_material_name << " " // Separator = space! - ; + m_stream << "\t" << setw(m_float_width) << itor->radius << ", " << setw(m_float_width) << itor->width << ", " << setw(3) + << itor->num_rays << ", " << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " << setw(m_node_id_width) + << itor->nodes[1].ToString() << ", " << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " + << setw(3) << itor->braking << ", " << setw(3) << itor->propulsion << ", " << setw(m_node_id_width) + << itor->reference_arm_node.ToString() << ", " << setw(m_float_width) << itor->mass << ", " + << setw(m_float_width) << itor->springiness << ", " << setw(m_float_width) << itor->damping << ", " + << itor->face_material_name << " " // Separator = space! + << itor->band_material_name << " " // Separator = space! + ; m_stream << endl; } m_stream << endl; // Empty line } -void Serializer::ProcessMeshWheels(File::Module* module) +void Serializer::ProcessMeshWheels(File::Module *module) { if (module->mesh_wheels.empty()) { return; } @@ -1684,23 +1321,15 @@ void Serializer::ProcessMeshWheels(File::Module* module) auto end_itor = module->mesh_wheels.end(); for (auto itor = module->mesh_wheels.begin(); itor != end_itor; ++itor) { - m_stream << "\t" - << setw(m_float_width) << itor->tyre_radius << ", " - << setw(m_float_width) << itor->rim_radius << ", " - << setw(m_float_width) << itor->width << ", " - << setw(3) << itor->num_rays << ", " - << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " - << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " - << setw(3) << itor->braking << ", " - << setw(3) << itor->propulsion << ", " - << setw(m_node_id_width) << itor->reference_arm_node.ToString() << ", " - << setw(m_float_width) << itor->mass << ", " - << setw(m_float_width) << itor->spring << ", " - << setw(m_float_width) << itor->damping << ", " - << (static_cast(itor->side)) << ", " - << itor->mesh_name << " " // Separator = space! - << itor->material_name; + m_stream << "\t" << setw(m_float_width) << itor->tyre_radius << ", " << setw(m_float_width) << itor->rim_radius + << ", " << setw(m_float_width) << itor->width << ", " << setw(3) << itor->num_rays << ", " + << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " << setw(m_node_id_width) + << itor->nodes[1].ToString() << ", " << setw(m_node_id_width) << itor->rigidity_node.ToString() << ", " + << setw(3) << itor->braking << ", " << setw(3) << itor->propulsion << ", " << setw(m_node_id_width) + << itor->reference_arm_node.ToString() << ", " << setw(m_float_width) << itor->mass << ", " + << setw(m_float_width) << itor->spring << ", " << setw(m_float_width) << itor->damping << ", " + << (static_cast(itor->side)) << ", " << itor->mesh_name << " " // Separator = space! + << itor->material_name; m_stream << endl; } } @@ -1708,59 +1337,46 @@ void Serializer::ProcessMeshWheels(File::Module* module) m_stream << endl; // Empty line } -void Serializer::ProcessCinecam(File::Module* module) +void Serializer::ProcessCinecam(File::Module *module) { - if (module->cinecam.empty()) - { - return; - } + if (module->cinecam.empty()) { return; } m_stream << "cinecam" << endl << endl; for (auto itor = module->cinecam.begin(); itor != module->cinecam.end(); ++itor) { - m_stream << "\t" - << setw(m_float_width) << itor->position.x << ", " - << setw(m_float_width) << itor->position.y << ", " - << setw(m_float_width) << itor->position.z << ", "; - m_stream - << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[1].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[2].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[3].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[4].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[5].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[6].ToString() << ", " - << setw(m_node_id_width) << itor->nodes[7].ToString() << ", "; - m_stream - << setw(m_float_width) << itor->spring << ", " - << setw(m_float_width) << itor->damping; + m_stream << "\t" << setw(m_float_width) << itor->position.x << ", " << setw(m_float_width) << itor->position.y << ", " + << setw(m_float_width) << itor->position.z << ", "; + m_stream << setw(m_node_id_width) << itor->nodes[0].ToString() << ", " << setw(m_node_id_width) + << itor->nodes[1].ToString() << ", " << setw(m_node_id_width) << itor->nodes[2].ToString() << ", " + << setw(m_node_id_width) << itor->nodes[3].ToString() << ", " << setw(m_node_id_width) + << itor->nodes[4].ToString() << ", " << setw(m_node_id_width) << itor->nodes[5].ToString() << ", " + << setw(m_node_id_width) << itor->nodes[6].ToString() << ", " << setw(m_node_id_width) + << itor->nodes[7].ToString() << ", "; + m_stream << setw(m_float_width) << itor->spring << ", " << setw(m_float_width) << itor->damping; } m_stream << endl; // Empty line } -void Serializer::ProcessBeams(File::Module* module) +void Serializer::ProcessBeams(File::Module *module) { - if (module->beams.empty()) - { - return; - } + if (module->beams.empty()) { return; } // Group beams by presets - std::map< BeamDefaults*, std::vector > beams_by_preset; - auto itor_end = module->beams.end(); + std::map> beams_by_preset; + auto itor_end = module->beams.end(); for (auto itor = module->beams.begin(); itor != itor_end; ++itor) { - Beam & beam = *itor; - BeamDefaults* preset = beam.defaults.get(); + Beam & beam = *itor; + BeamDefaults *preset = beam.defaults.get(); // Ensure preset is in map auto found_itor = beams_by_preset.find(preset); if (found_itor == beams_by_preset.end()) { // Preset not in map, insert it and add beam. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&beam); beams_by_preset.insert(std::make_pair(preset, list)); @@ -1778,15 +1394,15 @@ void Serializer::ProcessBeams(File::Module* module) for (auto preset_itor = beams_by_preset.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - BeamDefaults* preset = preset_itor->first; + BeamDefaults *preset = preset_itor->first; ProcessBeamDefaults(preset); // Write beams - std::vector & beam_list = preset_itor->second; - auto beam_itor_end = beam_list.end(); + std::vector &beam_list = preset_itor->second; + auto beam_itor_end = beam_list.end(); for (auto beam_itor = beam_list.begin(); beam_itor != beam_itor_end; ++beam_itor) { - Beam & beam = *(*beam_itor); + Beam &beam = *(*beam_itor); ProcessBeam(beam); } } @@ -1795,27 +1411,24 @@ void Serializer::ProcessBeams(File::Module* module) m_stream << endl; } -void Serializer::ProcessShocks(File::Module* module) +void Serializer::ProcessShocks(File::Module *module) { - if (module->shocks.empty()) - { - return; - } + if (module->shocks.empty()) { return; } // Group beams by presets - std::map< BeamDefaults*, std::vector > shocks_by_preset; - auto itor_end = module->shocks.end(); + std::map> shocks_by_preset; + auto itor_end = module->shocks.end(); for (auto itor = module->shocks.begin(); itor != itor_end; ++itor) { - Shock & shock = *itor; - BeamDefaults* preset = shock.beam_defaults.get(); + Shock & shock = *itor; + BeamDefaults *preset = shock.beam_defaults.get(); // Ensure preset is in map auto found_itor = shocks_by_preset.find(preset); if (found_itor == shocks_by_preset.end()) { // Preset not in map, insert it and add shock. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&shock); shocks_by_preset.insert(std::make_pair(preset, list)); @@ -1833,15 +1446,15 @@ void Serializer::ProcessShocks(File::Module* module) for (auto preset_itor = shocks_by_preset.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - BeamDefaults* preset = preset_itor->first; + BeamDefaults *preset = preset_itor->first; ProcessBeamDefaults(preset); // Write shocks - auto shock_list = preset_itor->second; + auto shock_list = preset_itor->second; auto shock_itor_end = shock_list.end(); for (auto shock_itor = shock_list.begin(); shock_itor != shock_itor_end; ++shock_itor) { - Shock & shock = *(*shock_itor); + Shock &shock = *(*shock_itor); ProcessShock(shock); } } @@ -1850,27 +1463,24 @@ void Serializer::ProcessShocks(File::Module* module) m_stream << endl; } -void Serializer::ProcessShocks2(File::Module* module) +void Serializer::ProcessShocks2(File::Module *module) { - if (module->shocks_2.empty()) - { - return; - } + if (module->shocks_2.empty()) { return; } // Group beams by presets - std::map< BeamDefaults*, std::vector > shocks_by_preset; - auto itor_end = module->shocks_2.end(); + std::map> shocks_by_preset; + auto itor_end = module->shocks_2.end(); for (auto itor = module->shocks_2.begin(); itor != itor_end; ++itor) { - Shock2 & shock = *itor; - BeamDefaults* preset = shock.beam_defaults.get(); + Shock2 & shock = *itor; + BeamDefaults *preset = shock.beam_defaults.get(); // Ensure preset is in map auto found_itor = shocks_by_preset.find(preset); if (found_itor == shocks_by_preset.end()) { // Preset not in map, insert it and add shock. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&shock); shocks_by_preset.insert(std::make_pair(preset, list)); @@ -1888,15 +1498,15 @@ void Serializer::ProcessShocks2(File::Module* module) for (auto preset_itor = shocks_by_preset.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - BeamDefaults* preset = preset_itor->first; + BeamDefaults *preset = preset_itor->first; ProcessBeamDefaults(preset); // Write shocks - auto shock_list = preset_itor->second; + auto shock_list = preset_itor->second; auto shock_itor_end = shock_list.end(); for (auto shock_itor = shock_list.begin(); shock_itor != shock_itor_end; ++shock_itor) { - Shock2 & shock = *(*shock_itor); + Shock2 &shock = *(*shock_itor); ProcessShock2(shock); } } @@ -1905,27 +1515,24 @@ void Serializer::ProcessShocks2(File::Module* module) m_stream << endl; } -void Serializer::ProcessShocks3(File::Module* module) +void Serializer::ProcessShocks3(File::Module *module) { - if (module->shocks_3.empty()) - { - return; - } + if (module->shocks_3.empty()) { return; } // Group beams by presets - std::map< BeamDefaults*, std::vector > shocks_by_preset; - auto itor_end = module->shocks_3.end(); + std::map> shocks_by_preset; + auto itor_end = module->shocks_3.end(); for (auto itor = module->shocks_3.begin(); itor != itor_end; ++itor) { - Shock3 & shock = *itor; - BeamDefaults* preset = shock.beam_defaults.get(); + Shock3 & shock = *itor; + BeamDefaults *preset = shock.beam_defaults.get(); // Ensure preset is in map auto found_itor = shocks_by_preset.find(preset); if (found_itor == shocks_by_preset.end()) { // Preset not in map, insert it and add shock. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&shock); shocks_by_preset.insert(std::make_pair(preset, list)); @@ -1943,15 +1550,15 @@ void Serializer::ProcessShocks3(File::Module* module) for (auto preset_itor = shocks_by_preset.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - BeamDefaults* preset = preset_itor->first; + BeamDefaults *preset = preset_itor->first; ProcessBeamDefaults(preset); // Write shocks - auto shock_list = preset_itor->second; + auto shock_list = preset_itor->second; auto shock_itor_end = shock_list.end(); for (auto shock_itor = shock_list.begin(); shock_itor != shock_itor_end; ++shock_itor) { - Shock3 & shock = *(*shock_itor); + Shock3 &shock = *(*shock_itor); ProcessShock3(shock); } } @@ -1960,27 +1567,24 @@ void Serializer::ProcessShocks3(File::Module* module) m_stream << endl; } -void Serializer::ProcessHydros(File::Module* module) +void Serializer::ProcessHydros(File::Module *module) { - if (module->hydros.empty()) - { - return; - } + if (module->hydros.empty()) { return; } // Group by presets - std::map< BeamDefaults*, std::vector > grouped_by_preset; - auto itor_end = module->hydros.end(); + std::map> grouped_by_preset; + auto itor_end = module->hydros.end(); for (auto itor = module->hydros.begin(); itor != itor_end; ++itor) { - Hydro & hydro = *itor; - BeamDefaults* preset = hydro.beam_defaults.get(); + Hydro & hydro = *itor; + BeamDefaults *preset = hydro.beam_defaults.get(); // Ensure preset is in map auto found_itor = grouped_by_preset.find(preset); if (found_itor == grouped_by_preset.end()) { // Preset not in map, insert it and add hydro. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&hydro); grouped_by_preset.insert(std::make_pair(preset, list)); @@ -1998,15 +1602,15 @@ void Serializer::ProcessHydros(File::Module* module) for (auto preset_itor = grouped_by_preset.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - BeamDefaults* preset = preset_itor->first; + BeamDefaults *preset = preset_itor->first; ProcessBeamDefaults(preset); // Write hydros - auto hydro_list = preset_itor->second; + auto hydro_list = preset_itor->second; auto hydro_itor_end = hydro_list.end(); for (auto hydro_itor = hydro_list.begin(); hydro_itor != hydro_itor_end; ++hydro_itor) { - Hydro & hydro = *(*hydro_itor); + Hydro &hydro = *(*hydro_itor); ProcessHydro(hydro); } } @@ -2015,27 +1619,24 @@ void Serializer::ProcessHydros(File::Module* module) m_stream << endl << endl; } -void Serializer::ProcessCommands2(File::Module* module) +void Serializer::ProcessCommands2(File::Module *module) { - if (module->commands_2.empty()) - { - return; - } + if (module->commands_2.empty()) { return; } // Group by presets and _format_version - std::map< BeamDefaults*, std::vector > commands_by_preset; - auto itor_end = module->commands_2.end(); + std::map> commands_by_preset; + auto itor_end = module->commands_2.end(); for (auto itor = module->commands_2.begin(); itor != itor_end; ++itor) { - Command2 & command = *itor; - BeamDefaults* preset = command.beam_defaults.get(); + Command2 & command = *itor; + BeamDefaults *preset = command.beam_defaults.get(); // Ensure preset is in map auto found_itor = commands_by_preset.find(preset); if (found_itor == commands_by_preset.end()) { // Preset not in map, insert it and add command. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&command); commands_by_preset.insert(std::make_pair(preset, list)); @@ -2053,15 +1654,15 @@ void Serializer::ProcessCommands2(File::Module* module) for (auto preset_itor = commands_by_preset.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - BeamDefaults* preset = preset_itor->first; + BeamDefaults *preset = preset_itor->first; ProcessBeamDefaults(preset); // Write hydros - auto command_list = preset_itor->second; + auto command_list = preset_itor->second; auto command_itor_end = command_list.end(); for (auto command_itor = command_list.begin(); command_itor != command_itor_end; ++command_itor) { - Command2 & command = *(*command_itor); + Command2 &command = *(*command_itor); ProcessCommand2(command); } } @@ -2070,51 +1671,73 @@ void Serializer::ProcessCommands2(File::Module* module) m_stream << endl; } -void Serializer::ProcessCommand2(Command2 & def) +void Serializer::ProcessCommand2(Command2 &def) { - m_stream << "\t" - << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " - << std::setw(m_node_id_width) << def.nodes[1].ToString() << ", "; + m_stream << "\t" << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " << std::setw(m_node_id_width) + << def.nodes[1].ToString() << ", "; - m_stream << std::setw(m_float_width) << def.shorten_rate << ", "; - m_stream << std::setw(m_float_width) << def.lengthen_rate << ", "; - m_stream << std::setw(m_float_width) << def.max_contraction << ", "; // So-called 'shortbound' - m_stream << std::setw(m_float_width) << def.max_extension << ", "; // So-called 'longbound' - m_stream << std::setw(m_command_key_width) << def.contract_key << ", "; - m_stream << std::setw(m_command_key_width) << def.extend_key << ", "; + m_stream << std::setw(m_float_width) << def.shorten_rate << ", "; + m_stream << std::setw(m_float_width) << def.lengthen_rate << ", "; + m_stream << std::setw(m_float_width) << def.max_contraction << ", "; // So-called 'shortbound' + m_stream << std::setw(m_float_width) << def.max_extension << ", "; // So-called 'longbound' + m_stream << std::setw(m_command_key_width) << def.contract_key << ", "; + m_stream << std::setw(m_command_key_width) << def.extend_key << ", "; // Options bool dummy = true; - if (def.option_c_auto_center) { m_stream << "c"; dummy = false; } - if (def.option_f_not_faster) { m_stream << "f"; dummy = false; } - if (def.option_i_invisible) { m_stream << "i"; dummy = false; } - if (def.option_o_1press_center) { m_stream << "o"; dummy = false; } - if (def.option_p_1press) { m_stream << "p"; dummy = false; } - if (def.option_r_rope) { m_stream << "r"; dummy = false; } - if (dummy) { m_stream << "n"; } // Placeholder, does nothing + if (def.option_c_auto_center) + { + m_stream << "c"; + dummy = false; + } + if (def.option_f_not_faster) + { + m_stream << "f"; + dummy = false; + } + if (def.option_i_invisible) + { + m_stream << "i"; + dummy = false; + } + if (def.option_o_1press_center) + { + m_stream << "o"; + dummy = false; + } + if (def.option_p_1press) + { + m_stream << "p"; + dummy = false; + } + if (def.option_r_rope) + { + m_stream << "r"; + dummy = false; + } + if (dummy) { m_stream << "n"; } // Placeholder, does nothing m_stream << ", "; // Description m_stream << (def.description.length() > 0 ? def.description : "_") << ", "; - - // Inertia - m_stream << std::setw(m_float_width) << def.inertia.start_delay_factor << ", "; - m_stream << std::setw(m_float_width) << def.inertia.stop_delay_factor << ", "; + + // Inertia + m_stream << std::setw(m_float_width) << def.inertia.start_delay_factor << ", "; + m_stream << std::setw(m_float_width) << def.inertia.stop_delay_factor << ", "; m_stream << std::setw(m_inertia_function_width) << def.inertia.start_function << ", "; - m_stream << std::setw(m_inertia_function_width) << def.inertia.stop_function << ", "; - m_stream << std::setw(m_float_width) << def.affect_engine << ", "; + m_stream << std::setw(m_inertia_function_width) << def.inertia.stop_function << ", "; + m_stream << std::setw(m_float_width) << def.affect_engine << ", "; m_stream << std::setw(m_bool_width) << (def.needs_engine ? "true" : "false"); m_stream << endl; } -void Serializer::ProcessHydro(Hydro & def) +void Serializer::ProcessHydro(Hydro &def) { - m_stream << "\t" - << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " - << std::setw(m_node_id_width) << def.nodes[1].ToString() << ", "; + m_stream << "\t" << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " << std::setw(m_node_id_width) + << def.nodes[1].ToString() << ", "; - m_stream << std::setw(m_float_width) << def.lenghtening_factor << ", "; + m_stream << std::setw(m_float_width) << def.lenghtening_factor << ", "; if (def.options.empty()) { m_stream << "n"; // Placeholder, does nothing @@ -2126,30 +1749,26 @@ void Serializer::ProcessHydro(Hydro & def) m_stream << ", "; // Inertia - Inertia & inertia = def.inertia; - m_stream << std::setw(m_float_width) << inertia.start_delay_factor << ", "; + Inertia &inertia = def.inertia; + m_stream << std::setw(m_float_width) << inertia.start_delay_factor << ", "; m_stream << std::setw(m_float_width) << inertia.stop_delay_factor; if (!inertia.start_function.empty()) { m_stream << ", " << std::setw(m_inertia_function_width) << inertia.start_function; - if (!inertia.stop_function.empty()) - { - m_stream << ", " << std::setw(m_inertia_function_width) << inertia.stop_function; - } + if (!inertia.stop_function.empty()) { m_stream << ", " << std::setw(m_inertia_function_width) << inertia.stop_function; } } m_stream << endl; } -void Serializer::ProcessShock(Shock & def) +void Serializer::ProcessShock(Shock &def) { - m_stream << "\t" - << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " - << std::setw(m_node_id_width) << def.nodes[1].ToString() << ", "; - m_stream << std::setw(m_float_width) << def.spring_rate << ", "; - m_stream << std::setw(m_float_width) << def.damping << ", "; - m_stream << std::setw(m_float_width) << def.short_bound << ", "; - m_stream << std::setw(m_float_width) << def.long_bound << ", "; - m_stream << std::setw(m_float_width) << def.precompression << ", "; + m_stream << "\t" << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " << std::setw(m_node_id_width) + << def.nodes[1].ToString() << ", "; + m_stream << std::setw(m_float_width) << def.spring_rate << ", "; + m_stream << std::setw(m_float_width) << def.damping << ", "; + m_stream << std::setw(m_float_width) << def.short_bound << ", "; + m_stream << std::setw(m_float_width) << def.long_bound << ", "; + m_stream << std::setw(m_float_width) << def.precompression << ", "; // Options if (def.options == 0) @@ -2158,47 +1777,34 @@ void Serializer::ProcessShock(Shock & def) } else { - if (BITMASK_IS_1(def.options, Shock::OPTION_i_INVISIBLE)) - { - m_stream << "i"; - } - if (BITMASK_IS_1(def.options, Shock::OPTION_m_METRIC)) - { - m_stream << "m"; - } - if (BITMASK_IS_1(def.options, Shock::OPTION_L_ACTIVE_LEFT)) - { - m_stream << "L"; - } - if (BITMASK_IS_1(def.options, Shock::OPTION_R_ACTIVE_RIGHT)) - { - m_stream << "R"; - } + if (BITMASK_IS_1(def.options, Shock::OPTION_i_INVISIBLE)) { m_stream << "i"; } + if (BITMASK_IS_1(def.options, Shock::OPTION_m_METRIC)) { m_stream << "m"; } + if (BITMASK_IS_1(def.options, Shock::OPTION_L_ACTIVE_LEFT)) { m_stream << "L"; } + if (BITMASK_IS_1(def.options, Shock::OPTION_R_ACTIVE_RIGHT)) { m_stream << "R"; } } // Empty line m_stream << endl; } -void Serializer::ProcessShock2(Shock2 & def) +void Serializer::ProcessShock2(Shock2 &def) { - m_stream << "\t" - << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " - << std::setw(m_node_id_width) << def.nodes[1].ToString() << ", "; + m_stream << "\t" << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " << std::setw(m_node_id_width) + << def.nodes[1].ToString() << ", "; - m_stream << std::setw(m_float_width) << def.spring_in << ", "; - m_stream << std::setw(m_float_width) << def.damp_in << ", "; - m_stream << std::setw(m_float_width) << def.progress_factor_spring_in << ", "; - m_stream << std::setw(m_float_width) << def.progress_factor_damp_in << ", "; + m_stream << std::setw(m_float_width) << def.spring_in << ", "; + m_stream << std::setw(m_float_width) << def.damp_in << ", "; + m_stream << std::setw(m_float_width) << def.progress_factor_spring_in << ", "; + m_stream << std::setw(m_float_width) << def.progress_factor_damp_in << ", "; - m_stream << std::setw(m_float_width) << def.spring_out << ", "; - m_stream << std::setw(m_float_width) << def.damp_out << ", "; + m_stream << std::setw(m_float_width) << def.spring_out << ", "; + m_stream << std::setw(m_float_width) << def.damp_out << ", "; m_stream << std::setw(m_float_width) << def.progress_factor_spring_out << ", "; - m_stream << std::setw(m_float_width) << def.progress_factor_damp_out << ", "; + m_stream << std::setw(m_float_width) << def.progress_factor_damp_out << ", "; - m_stream << std::setw(m_float_width) << def.short_bound << ", "; - m_stream << std::setw(m_float_width) << def.long_bound << ", "; - m_stream << std::setw(m_float_width) << def.precompression << ", "; + m_stream << std::setw(m_float_width) << def.short_bound << ", "; + m_stream << std::setw(m_float_width) << def.long_bound << ", "; + m_stream << std::setw(m_float_width) << def.precompression << ", "; // Options if (def.options != 0) @@ -2207,49 +1813,36 @@ void Serializer::ProcessShock2(Shock2 & def) } else { - if (BITMASK_IS_1(def.options, Shock2::OPTION_i_INVISIBLE)) - { - m_stream << "i"; - } - if (BITMASK_IS_1(def.options, Shock2::OPTION_m_METRIC)) - { - m_stream << "m"; - } - if (BITMASK_IS_1(def.options, Shock2::OPTION_M_ABSOLUTE_METRIC)) - { - m_stream << "M"; - } - if (BITMASK_IS_1(def.options, Shock2::OPTION_s_SOFT_BUMP_BOUNDS)) - { - m_stream << "s"; - } + if (BITMASK_IS_1(def.options, Shock2::OPTION_i_INVISIBLE)) { m_stream << "i"; } + if (BITMASK_IS_1(def.options, Shock2::OPTION_m_METRIC)) { m_stream << "m"; } + if (BITMASK_IS_1(def.options, Shock2::OPTION_M_ABSOLUTE_METRIC)) { m_stream << "M"; } + if (BITMASK_IS_1(def.options, Shock2::OPTION_s_SOFT_BUMP_BOUNDS)) { m_stream << "s"; } } // Empty line m_stream << endl; } -void Serializer::ProcessShock3(Shock3 & def) +void Serializer::ProcessShock3(Shock3 &def) { - m_stream << "\t" - << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " - << std::setw(m_node_id_width) << def.nodes[1].ToString() << ", "; + m_stream << "\t" << std::setw(m_node_id_width) << def.nodes[0].ToString() << ", " << std::setw(m_node_id_width) + << def.nodes[1].ToString() << ", "; - m_stream << std::setw(m_float_width) << def.spring_in << ", "; - m_stream << std::setw(m_float_width) << def.damp_in << ", "; - m_stream << std::setw(m_float_width) << def.damp_in_slow << ", "; - m_stream << std::setw(m_float_width) << def.split_vel_in << ", "; - m_stream << std::setw(m_float_width) << def.damp_in_fast << ", "; + m_stream << std::setw(m_float_width) << def.spring_in << ", "; + m_stream << std::setw(m_float_width) << def.damp_in << ", "; + m_stream << std::setw(m_float_width) << def.damp_in_slow << ", "; + m_stream << std::setw(m_float_width) << def.split_vel_in << ", "; + m_stream << std::setw(m_float_width) << def.damp_in_fast << ", "; - m_stream << std::setw(m_float_width) << def.spring_out << ", "; - m_stream << std::setw(m_float_width) << def.damp_out << ", "; - m_stream << std::setw(m_float_width) << def.damp_out_slow << ", "; - m_stream << std::setw(m_float_width) << def.split_vel_out << ", "; - m_stream << std::setw(m_float_width) << def.damp_out_fast << ", "; + m_stream << std::setw(m_float_width) << def.spring_out << ", "; + m_stream << std::setw(m_float_width) << def.damp_out << ", "; + m_stream << std::setw(m_float_width) << def.damp_out_slow << ", "; + m_stream << std::setw(m_float_width) << def.split_vel_out << ", "; + m_stream << std::setw(m_float_width) << def.damp_out_fast << ", "; - m_stream << std::setw(m_float_width) << def.short_bound << ", "; - m_stream << std::setw(m_float_width) << def.long_bound << ", "; - m_stream << std::setw(m_float_width) << def.precompression << ", "; + m_stream << std::setw(m_float_width) << def.short_bound << ", "; + m_stream << std::setw(m_float_width) << def.long_bound << ", "; + m_stream << std::setw(m_float_width) << def.precompression << ", "; // Options if (def.options != 0) @@ -2258,54 +1851,33 @@ void Serializer::ProcessShock3(Shock3 & def) } else { - if (BITMASK_IS_1(def.options, Shock3::OPTION_i_INVISIBLE)) - { - m_stream << "i"; - } - if (BITMASK_IS_1(def.options, Shock3::OPTION_m_METRIC)) - { - m_stream << "m"; - } - if (BITMASK_IS_1(def.options, Shock3::OPTION_M_ABSOLUTE_METRIC)) - { - m_stream << "M"; - } + if (BITMASK_IS_1(def.options, Shock3::OPTION_i_INVISIBLE)) { m_stream << "i"; } + if (BITMASK_IS_1(def.options, Shock3::OPTION_m_METRIC)) { m_stream << "m"; } + if (BITMASK_IS_1(def.options, Shock3::OPTION_M_ABSOLUTE_METRIC)) { m_stream << "M"; } } // Empty line m_stream << endl; } -void Serializer::ProcessBeamDefaults(BeamDefaults* beam_defaults, const char* prefix) +void Serializer::ProcessBeamDefaults(BeamDefaults *beam_defaults, const char *prefix) { - if (beam_defaults == nullptr) - { - return; - } + if (beam_defaults == nullptr) { return; } m_stream << prefix << "set_beam_defaults " // Align with "set_beam_defaults_scale" - << beam_defaults->springiness << ", " - << beam_defaults->damping_constant << ", " - << beam_defaults->deformation_threshold << ", " - << beam_defaults->breaking_threshold << ", " - << beam_defaults->visual_beam_diameter << ", " - << beam_defaults->beam_material_name << ", " - << beam_defaults->plastic_deform_coef - << endl; - - BeamDefaultsScale & scale = beam_defaults->scale; - m_stream << prefix << "set_beam_defaults_scale " - << scale.springiness << ", " - << scale.damping_constant << ", " - << scale.deformation_threshold_constant << ", " - << scale.breaking_threshold_constant - << endl; -} - -void Serializer::ProcessBeam(Beam & beam) -{ - m_stream << "\t" - << std::setw(m_node_id_width) << beam.nodes[0].ToString() << ", " - << std::setw(m_node_id_width) << beam.nodes[1].ToString() << ", "; + << beam_defaults->springiness << ", " << beam_defaults->damping_constant << ", " + << beam_defaults->deformation_threshold << ", " << beam_defaults->breaking_threshold << ", " + << beam_defaults->visual_beam_diameter << ", " << beam_defaults->beam_material_name << ", " + << beam_defaults->plastic_deform_coef << endl; + + BeamDefaultsScale &scale = beam_defaults->scale; + m_stream << prefix << "set_beam_defaults_scale " << scale.springiness << ", " << scale.damping_constant << ", " + << scale.deformation_threshold_constant << ", " << scale.breaking_threshold_constant << endl; +} + +void Serializer::ProcessBeam(Beam &beam) +{ + m_stream << "\t" << std::setw(m_node_id_width) << beam.nodes[0].ToString() << ", " << std::setw(m_node_id_width) + << beam.nodes[1].ToString() << ", "; // Options if (beam.options == 0u) @@ -2314,63 +1886,45 @@ void Serializer::ProcessBeam(Beam & beam) } else { - if (BITMASK_IS_1(beam.options, Beam::OPTION_i_INVISIBLE)) - { - m_stream << "i"; - } - if (BITMASK_IS_1(beam.options, Beam::OPTION_r_ROPE)) - { - m_stream << "r"; - } - if (BITMASK_IS_1(beam.options, Beam::OPTION_s_SUPPORT)) - { - m_stream << "s"; - } + if (BITMASK_IS_1(beam.options, Beam::OPTION_i_INVISIBLE)) { m_stream << "i"; } + if (BITMASK_IS_1(beam.options, Beam::OPTION_r_ROPE)) { m_stream << "r"; } + if (BITMASK_IS_1(beam.options, Beam::OPTION_s_SUPPORT)) { m_stream << "s"; } } - if (beam._has_extension_break_limit) - { - m_stream << ", " << beam.extension_break_limit; - } - + if (beam._has_extension_break_limit) { m_stream << ", " << beam.extension_break_limit; } + m_stream << endl; } -void Serializer::ProcessNodes(File::Module* module) +void Serializer::ProcessNodes(File::Module *module) { - if (module->nodes.empty()) - { - return; - } + if (module->nodes.empty()) { return; } // Group nodes by presets + find node-zero // TODO: Handle minimass presets! - std::map< NodeDefaults*, std::vector > nodes_by_presets; - Node* node_zero = nullptr; - auto itor_end = module->nodes.end(); + std::map> nodes_by_presets; + Node * node_zero = nullptr; + auto itor_end = module->nodes.end(); for (auto itor = module->nodes.begin(); itor != itor_end; ++itor) { - Node & node = *itor; + Node &node = *itor; // Check zero node if (node.id.IsValid() && node.id.Str().empty() && node.id.Num() == 0) { - if (node_zero != nullptr) - { - throw std::runtime_error("FATAL: Multiple nodes zero!!!"); - } + if (node_zero != nullptr) { throw std::runtime_error("FATAL: Multiple nodes zero!!!"); } node_zero = &node; continue; } - NodeDefaults* preset = node.node_defaults.get(); + NodeDefaults *preset = node.node_defaults.get(); // Ensure preset is in map auto found_itor = nodes_by_presets.find(preset); if (found_itor == nodes_by_presets.end()) { // Preset not in map, insert it and add node. - std::vector list; + std::vector list; list.reserve(100); list.push_back(&node); nodes_by_presets.insert(std::make_pair(preset, list)); @@ -2386,10 +1940,7 @@ void Serializer::ProcessNodes(File::Module* module) m_stream << "nodes" << endl << endl; // Node zero first - if (node_zero == nullptr) - { - throw std::runtime_error("FATAL: Node zero not defined!!!"); - } + if (node_zero == nullptr) { throw std::runtime_error("FATAL: Node zero not defined!!!"); } ProcessNodeDefaults(node_zero->node_defaults.get()); ProcessNode(*node_zero); @@ -2398,19 +1949,17 @@ void Serializer::ProcessNodes(File::Module* module) for (auto preset_itor = nodes_by_presets.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - NodeDefaults* preset = preset_itor->first; + NodeDefaults *preset = preset_itor->first; ProcessNodeDefaults(preset); // Write nodes - std::vector & node_list = preset_itor->second; - auto node_itor_end = node_list.end(); + std::vector &node_list = preset_itor->second; + auto node_itor_end = node_list.end(); for (auto node_itor = node_list.begin(); node_itor != node_itor_end; ++node_itor) { - Node & node = *(*node_itor); + Node &node = *(*node_itor); if (node.id.Str().empty()) // Numbered nodes only - { - ProcessNode(node); - } + { ProcessNode(node); } } } @@ -2419,19 +1968,17 @@ void Serializer::ProcessNodes(File::Module* module) for (auto preset_itor = nodes_by_presets.begin(); preset_itor != preset_itor_end; ++preset_itor) { // Write preset - NodeDefaults* preset = preset_itor->first; + NodeDefaults *preset = preset_itor->first; ProcessNodeDefaults(preset); // Write nodes - std::vector & node_list = preset_itor->second; - auto node_itor_end = node_list.end(); + std::vector &node_list = preset_itor->second; + auto node_itor_end = node_list.end(); for (auto node_itor = node_list.begin(); node_itor != node_itor_end; ++node_itor) { - Node & node = *(*node_itor); + Node &node = *(*node_itor); if (!node.id.Str().empty() && node.id.Num() == 0) // Named nodes only - { - ProcessNode(node); - } + { ProcessNode(node); } } } @@ -2439,7 +1986,7 @@ void Serializer::ProcessNodes(File::Module* module) m_stream << endl; } -void Serializer::ProcessNodeDefaults(NodeDefaults* node_defaults) +void Serializer::ProcessNodeDefaults(NodeDefaults *node_defaults) { m_stream << "set_node_defaults "; if (node_defaults == nullptr) @@ -2448,11 +1995,8 @@ void Serializer::ProcessNodeDefaults(NodeDefaults* node_defaults) return; } - m_stream - << node_defaults->load_weight << ", " - << node_defaults->friction << ", " - << node_defaults->volume << ", " - << node_defaults->surface << ", "; + m_stream << node_defaults->load_weight << ", " << node_defaults->friction << ", " << node_defaults->volume << ", " + << node_defaults->surface << ", "; ProcessNodeOptions(node_defaults->options); @@ -2464,101 +2008,41 @@ void Serializer::ProcessNodeOptions(unsigned int options) // Mouse grab m_stream << (BITMASK_IS_1(options, Node::OPTION_m_NO_MOUSE_GRAB) ? "m" : "n"); - if (BITMASK_IS_1(options, Node::OPTION_b_EXTRA_BUOYANCY)) - { - m_stream << "b"; - } - if (BITMASK_IS_1(options, Node::OPTION_c_NO_GROUND_CONTACT)) - { - m_stream << "c"; - } - if (BITMASK_IS_1(options, Node::OPTION_f_NO_SPARKS)) - { - m_stream << "f"; - } - if (BITMASK_IS_1(options, Node::OPTION_h_HOOK_POINT)) - { - m_stream << "h"; - } - if (BITMASK_IS_1(options, Node::OPTION_l_LOAD_WEIGHT)) - { - m_stream << "l"; - } - if (BITMASK_IS_1(options, Node::OPTION_L_LOG)) - { - m_stream << "L"; - } - if (BITMASK_IS_1(options, Node::OPTION_p_NO_PARTICLES)) - { - m_stream << "p"; - } - if (BITMASK_IS_1(options, Node::OPTION_x_EXHAUST_POINT)) - { - m_stream << "x"; - } - if (BITMASK_IS_1(options, Node::OPTION_y_EXHAUST_DIRECTION)) - { - m_stream << "y"; - } + if (BITMASK_IS_1(options, Node::OPTION_b_EXTRA_BUOYANCY)) { m_stream << "b"; } + if (BITMASK_IS_1(options, Node::OPTION_c_NO_GROUND_CONTACT)) { m_stream << "c"; } + if (BITMASK_IS_1(options, Node::OPTION_f_NO_SPARKS)) { m_stream << "f"; } + if (BITMASK_IS_1(options, Node::OPTION_h_HOOK_POINT)) { m_stream << "h"; } + if (BITMASK_IS_1(options, Node::OPTION_l_LOAD_WEIGHT)) { m_stream << "l"; } + if (BITMASK_IS_1(options, Node::OPTION_L_LOG)) { m_stream << "L"; } + if (BITMASK_IS_1(options, Node::OPTION_p_NO_PARTICLES)) { m_stream << "p"; } + if (BITMASK_IS_1(options, Node::OPTION_x_EXHAUST_POINT)) { m_stream << "x"; } + if (BITMASK_IS_1(options, Node::OPTION_y_EXHAUST_DIRECTION)) { m_stream << "y"; } } -void Serializer::ProcessNode(Node & node) +void Serializer::ProcessNode(Node &node) { - m_stream - << "\t" - << std::setw(m_node_id_width) << node.id.ToString() << ", " - << std::setw(m_float_width) << node.position.x << ", " - << std::setw(m_float_width) << node.position.y << ", " - << std::setw(m_float_width) << node.position.z << ", "; - + m_stream << "\t" << std::setw(m_node_id_width) << node.id.ToString() << ", " << std::setw(m_float_width) << node.position.x + << ", " << std::setw(m_float_width) << node.position.y << ", " << std::setw(m_float_width) << node.position.z + << ", "; + ProcessNodeOptions(node.options); - + // Load mass - if (node._has_load_weight_override) - { - m_stream << " " << node.load_weight_override; - } + if (node._has_load_weight_override) { m_stream << " " << node.load_weight_override; } m_stream << endl; } void Serializer::WriteFlags() { - if (m_rig_def->enable_advanced_deformation) - { - m_stream << "enable_advanced_deformation" << endl << endl; - } - if (m_rig_def->hide_in_chooser) - { - m_stream << "hideInChooser" << endl << endl; - } - if (m_rig_def->slide_nodes_connect_instantly) - { - m_stream << "slidenode_connect_instantly" << endl << endl; - } - if (m_rig_def->lockgroup_default_nolock) - { - m_stream << "lockgroup_default_nolock" << endl << endl; - } - if (m_rig_def->rollon) - { - m_stream << "rollon" << endl << endl; - } - if (m_rig_def->rescuer) - { - m_stream << "rescuer" << endl << endl; - } - if (m_rig_def->disable_default_sounds) - { - m_stream << "disabledefaultsounds" << endl << endl; - } - if (m_rig_def->forward_commands) - { - m_stream << "forwardcommands" << endl << endl; - } - if (m_rig_def->import_commands) - { - m_stream << "importcommands" << endl << endl; - } + if (m_rig_def->enable_advanced_deformation) { m_stream << "enable_advanced_deformation" << endl << endl; } + if (m_rig_def->hide_in_chooser) { m_stream << "hideInChooser" << endl << endl; } + if (m_rig_def->slide_nodes_connect_instantly) { m_stream << "slidenode_connect_instantly" << endl << endl; } + if (m_rig_def->lockgroup_default_nolock) { m_stream << "lockgroup_default_nolock" << endl << endl; } + if (m_rig_def->rollon) { m_stream << "rollon" << endl << endl; } + if (m_rig_def->rescuer) { m_stream << "rescuer" << endl << endl; } + if (m_rig_def->disable_default_sounds) { m_stream << "disabledefaultsounds" << endl << endl; } + if (m_rig_def->forward_commands) { m_stream << "forwardcommands" << endl << endl; } + if (m_rig_def->import_commands) { m_stream << "importcommands" << endl << endl; } } void Serializer::ProcessFileinfo() @@ -2576,10 +2060,7 @@ void Serializer::ProcessFileinfo() void Serializer::ProcessGuid() { - if (! m_rig_def->guid.empty()) - { - m_stream << "guid " << m_rig_def->guid << endl << endl; - } + if (!m_rig_def->guid.empty()) { m_stream << "guid " << m_rig_def->guid << endl << endl; } } void Serializer::ProcessDescription() @@ -2600,34 +2081,23 @@ void Serializer::ProcessAuthors() { for (auto itor = m_rig_def->authors.begin(); itor != m_rig_def->authors.end(); ++itor) { - Author & def = *itor; + Author &def = *itor; m_stream << "author " << def.type << " "; - if (def._has_forum_account) - { - m_stream << def.forum_account_id << " "; - } + if (def._has_forum_account) { m_stream << def.forum_account_id << " "; } else { m_stream << "-1 "; } - m_stream << def.name << " " << def.email << endl; + m_stream << def.name << " " << def.email << endl; } m_stream << endl; } -void Serializer::ProcessGlobals(File::Module* module) +void Serializer::ProcessGlobals(File::Module *module) { - if (module->globals.get() == nullptr) - { - return; - } + if (module->globals.get() == nullptr) { return; } - m_stream << "globals\n\t" - << module->globals->dry_mass << ", " - << module->globals->cargo_mass; - if (!module->globals->material_name.empty()) - { - m_stream << ", " << module->globals->material_name; - } + m_stream << "globals\n\t" << module->globals->dry_mass << ", " << module->globals->cargo_mass; + if (!module->globals->material_name.empty()) { m_stream << ", " << module->globals->material_name; } m_stream << endl << endl; } diff --git a/source/main/resources/rig_def_fileformat/RigDef_Serializer.h b/source/main/resources/rig_def_fileformat/RigDef_Serializer.h index 57f64f9d48..672ae4ee52 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Serializer.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Serializer.h @@ -30,141 +30,137 @@ namespace RigDef { -/** - @class Serializer - @author Petr Ohlidal + /** + @class Serializer + @author Petr Ohlidal - @brief Serializes the RigDef::File data structure to file. -*/ -class Serializer -{ - -public: - - Serializer(std::shared_ptr rig_def, Ogre::String const & file_path); - - virtual ~Serializer(); - - void Serialize(); - -protected: - - void ProcessAuthors(); - void ProcessGlobals(File::Module* module); - void ProcessDescription(); - void ProcessGuid(); - void ProcessFileinfo(); - void WriteFlags(); - void ProcessHelp(File::Module* module); - - // Audio video - void ProcessCinecam(File::Module*); - - // Structure - void ProcessNodes(File::Module*); - void ProcessNode(Node & node); - void ProcessNodeDefaults(NodeDefaults* node_defaults); - void ProcessNodeOptions(unsigned int options); - - void ProcessBeams(File::Module*); - void ProcessBeamDefaults(BeamDefaults* beam_defaults, const char* prefix = ""); - void ProcessBeam(Beam & beam); - - void ProcessShocks(File::Module*); - void ProcessShocks2(File::Module*); - void ProcessShocks3(File::Module*); - void ProcessShock(Shock & def); - void ProcessShock2(Shock2 & def); - void ProcessShock3(Shock3 & def); - - void ProcessHydros(File::Module*); - void ProcessHydro(Hydro & def); - void ProcessRotators(File::Module* module); - void ProcessRotators2(File::Module* module); - - void ProcessCommands2(File::Module*); - void ProcessCommand2(Command2 & def); - void ProcessSlideNodes(File::Module* module); - void ProcessRopes(File::Module* module); - void ProcessFixes(File::Module* module); - void ProcessTies(File::Module* module); - - // Land vehicle - void ProcessEngine(File::Module* module); - void ProcessEngoption(File::Module* module); - void ProcessBrakes(File::Module* module); - void ProcessAntiLockBrakes(File::Module* module); - void ProcessTractionControl(File::Module* module); - void ProcessSlopeBrake(File::Module* module); - void ProcessTorqueCurve(File::Module* module); - void ProcessCruiseControl(File::Module* module); - void ProcessSpeedLimiter(File::Module* module); - void ProcessAxles(File::Module* module); - void ProcessTransferCase(File::Module* module); - void ProcessInterAxles(File::Module* module); - - // Wheels - void ProcessMeshWheels(File::Module* module); // And meshwheels2 - void ProcessWheels(File::Module* module); - void ProcessWheels2(File::Module* module); - void ProcessFlexBodyWheels(File::Module* module); - - // Features - void ProcessAnimators(File::Module* module); - void ProcessContacters(File::Module* module); - void ProcessTriggers(File::Module* module); - void ProcessLockgroups(File::Module* module); - void ProcessHooks(File::Module* module); - void ProcessRailGroups(File::Module* module); - void ProcessRopables(File::Module* module); - void ProcessParticles(File::Module* module); - void ProcessCollisionBoxes(File::Module* module); - void ProcessManagedMaterialsAndOptions(File::Module* module); - void ProcessFlares2(File::Module* module); - void ProcessMaterialFlareBindings(File::Module* module); - void ProcessPropsAndAnimations(File::Module* module); - void ProcessFlexbodies(File::Module* module); - void ProcessDirectiveAddAnimation(RigDef::Animation & anim); - /* TODO: - 5.5.17 Camerarail - 5.5.8 Flexbodies - 5.5.8.3 (sub-directive) disable_flexbody_shadow - 5.5.8.4 (sub-directive) flexbody_camera_mode + @brief Serializes the RigDef::File data structure to file. */ - - void ProcessSubmesh(File::Module* module); - void ProcessSubmeshGroundmodel(File::Module* module); // STUB!!! - void ProcessExhausts(File::Module* module); - void ProcessGuiSettings(File::Module* module); - void ProcessSetSkeletonSettings(File::Module* module); - void ProcessVideocamera(File::Module* module); - void ProcessExtCamera(File::Module* module); - void ProcessSoundsources(File::Module* module); - void ProcessSoundsources2(File::Module* module); - - // Aerial - void ProcessWings(File::Module* module); - void ProcessAirbrakes(File::Module* module); - void ProcessTurboprops(File::Module* module); - void ProcessFusedrag(File::Module* module); // STUB!!! - void ProcessTurbojets(File::Module* module); - void ProcessPistonprops(File::Module* module); - - // Marine - void ProcessScrewprops(File::Module* module); - -protected: - - std::ofstream m_stream; - Ogre::String m_file_path; - std::shared_ptr m_rig_def; - int m_float_precision; - int m_float_width; - int m_bool_width; - int m_node_id_width; - int m_command_key_width; - int m_inertia_function_width; - -}; + class Serializer + { + + public: + Serializer(std::shared_ptr rig_def, Ogre::String const &file_path); + + virtual ~Serializer(); + + void Serialize(); + + protected: + void ProcessAuthors(); + void ProcessGlobals(File::Module *module); + void ProcessDescription(); + void ProcessGuid(); + void ProcessFileinfo(); + void WriteFlags(); + void ProcessHelp(File::Module *module); + + // Audio video + void ProcessCinecam(File::Module *); + + // Structure + void ProcessNodes(File::Module *); + void ProcessNode(Node &node); + void ProcessNodeDefaults(NodeDefaults *node_defaults); + void ProcessNodeOptions(unsigned int options); + + void ProcessBeams(File::Module *); + void ProcessBeamDefaults(BeamDefaults *beam_defaults, const char *prefix = ""); + void ProcessBeam(Beam &beam); + + void ProcessShocks(File::Module *); + void ProcessShocks2(File::Module *); + void ProcessShocks3(File::Module *); + void ProcessShock(Shock &def); + void ProcessShock2(Shock2 &def); + void ProcessShock3(Shock3 &def); + + void ProcessHydros(File::Module *); + void ProcessHydro(Hydro &def); + void ProcessRotators(File::Module *module); + void ProcessRotators2(File::Module *module); + + void ProcessCommands2(File::Module *); + void ProcessCommand2(Command2 &def); + void ProcessSlideNodes(File::Module *module); + void ProcessRopes(File::Module *module); + void ProcessFixes(File::Module *module); + void ProcessTies(File::Module *module); + + // Land vehicle + void ProcessEngine(File::Module *module); + void ProcessEngoption(File::Module *module); + void ProcessBrakes(File::Module *module); + void ProcessAntiLockBrakes(File::Module *module); + void ProcessTractionControl(File::Module *module); + void ProcessSlopeBrake(File::Module *module); + void ProcessTorqueCurve(File::Module *module); + void ProcessCruiseControl(File::Module *module); + void ProcessSpeedLimiter(File::Module *module); + void ProcessAxles(File::Module *module); + void ProcessTransferCase(File::Module *module); + void ProcessInterAxles(File::Module *module); + + // Wheels + void ProcessMeshWheels(File::Module *module); // And meshwheels2 + void ProcessWheels(File::Module *module); + void ProcessWheels2(File::Module *module); + void ProcessFlexBodyWheels(File::Module *module); + + // Features + void ProcessAnimators(File::Module *module); + void ProcessContacters(File::Module *module); + void ProcessTriggers(File::Module *module); + void ProcessLockgroups(File::Module *module); + void ProcessHooks(File::Module *module); + void ProcessRailGroups(File::Module *module); + void ProcessRopables(File::Module *module); + void ProcessParticles(File::Module *module); + void ProcessCollisionBoxes(File::Module *module); + void ProcessManagedMaterialsAndOptions(File::Module *module); + void ProcessFlares2(File::Module *module); + void ProcessMaterialFlareBindings(File::Module *module); + void ProcessPropsAndAnimations(File::Module *module); + void ProcessFlexbodies(File::Module *module); + void ProcessDirectiveAddAnimation(RigDef::Animation &anim); + /* TODO: + 5.5.17 Camerarail + 5.5.8 Flexbodies + 5.5.8.3 (sub-directive) disable_flexbody_shadow + 5.5.8.4 (sub-directive) flexbody_camera_mode + */ + + void ProcessSubmesh(File::Module *module); + void ProcessSubmeshGroundmodel(File::Module *module); // STUB!!! + void ProcessExhausts(File::Module *module); + void ProcessGuiSettings(File::Module *module); + void ProcessSetSkeletonSettings(File::Module *module); + void ProcessVideocamera(File::Module *module); + void ProcessExtCamera(File::Module *module); + void ProcessSoundsources(File::Module *module); + void ProcessSoundsources2(File::Module *module); + + // Aerial + void ProcessWings(File::Module *module); + void ProcessAirbrakes(File::Module *module); + void ProcessTurboprops(File::Module *module); + void ProcessFusedrag(File::Module *module); // STUB!!! + void ProcessTurbojets(File::Module *module); + void ProcessPistonprops(File::Module *module); + + // Marine + void ProcessScrewprops(File::Module *module); + + protected: + std::ofstream m_stream; + Ogre::String m_file_path; + std::shared_ptr m_rig_def; + int m_float_precision; + int m_float_width; + int m_bool_width; + int m_node_id_width; + int m_command_key_width; + int m_inertia_function_width; + }; } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Validator.cpp b/source/main/resources/rig_def_fileformat/RigDef_Validator.cpp index 5f3163f94a..9ee5ab583c 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Validator.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_Validator.cpp @@ -27,604 +27,489 @@ #include "BeamConstants.h" -#define CHECK_SECTION_IN_ALL_MODULES(_CLASS_, _FIELD_, _FUNCTION_) \ -{ \ - std::list>::iterator module_itor = m_selected_modules.begin(); \ - for (; module_itor != m_selected_modules.end(); module_itor++) \ - { \ - std::vector<_CLASS_>::iterator section_itor = module_itor->get()->_FIELD_.begin(); \ - for (; section_itor != module_itor->get()->_FIELD_.end(); section_itor++) \ - { \ - if (! _FUNCTION_(*section_itor))\ - { \ - section_itor = module_itor->get()->_FIELD_.erase(section_itor); \ - if (section_itor == module_itor->get()->_FIELD_.end()) \ - { \ - break; \ - } \ - } \ - } \ - } \ -} +#define CHECK_SECTION_IN_ALL_MODULES(_CLASS_, _FIELD_, _FUNCTION_) \ + { \ + std::list>::iterator module_itor = m_selected_modules.begin(); \ + for (; module_itor != m_selected_modules.end(); module_itor++) \ + { \ + std::vector<_CLASS_>::iterator section_itor = module_itor->get()->_FIELD_.begin(); \ + for (; section_itor != module_itor->get()->_FIELD_.end(); section_itor++) \ + { \ + if (!_FUNCTION_(*section_itor)) \ + { \ + section_itor = module_itor->get()->_FIELD_.erase(section_itor); \ + if (section_itor == module_itor->get()->_FIELD_.end()) { break; } \ + } \ + } \ + } \ + } namespace RigDef { -bool Validator::Validate() -{ - bool valid = true; + bool Validator::Validate() + { + bool valid = true; - /* CHECK CONFIGURATION (SELECTED MODULES TOGETHER) */ + /* CHECK CONFIGURATION (SELECTED MODULES TOGETHER) */ - valid &= CheckSection(RigDef::File::KEYWORD_GLOBALS, true, true); /* Unique, required */ + valid &= CheckSection(RigDef::File::KEYWORD_GLOBALS, true, true); /* Unique, required */ - valid &= CheckSection(RigDef::File::KEYWORD_NODES, false, true); /* Required; sections nodes/nodes2 are unified here. */ + valid &= CheckSection(RigDef::File::KEYWORD_NODES, false, true); /* Required; sections nodes/nodes2 are unified here. */ - if (m_check_beams) - { - valid &= CheckSection(RigDef::File::KEYWORD_BEAMS, false, true); /* Required */ - } + if (m_check_beams) { valid &= CheckSection(RigDef::File::KEYWORD_BEAMS, false, true); /* Required */ } - valid &= CheckSection(RigDef::File::KEYWORD_ENGINE, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_ENGINE, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_ENGOPTION, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_ENGOPTION, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_ENGTURBO, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_ENGTURBO, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_TORQUECURVE, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_TORQUECURVE, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_SPEEDLIMITER, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_SPEEDLIMITER, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_MANAGEDMATERIALS, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_MANAGEDMATERIALS, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_GUISETTINGS, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_GUISETTINGS, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_EXTCAMERA, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_EXTCAMERA, true, false); /* Unique */ - valid &= CheckSection(RigDef::File::KEYWORD_FUSEDRAG, true, false); /* Unique */ + valid &= CheckSection(RigDef::File::KEYWORD_FUSEDRAG, true, false); /* Unique */ - valid &= CheckSectionSubmeshGroundmodel(); /* Unique */ + valid &= CheckSectionSubmeshGroundmodel(); /* Unique */ - valid &= CheckGearbox(); /* Min. 1 forward gear */ + valid &= CheckGearbox(); /* Min. 1 forward gear */ - /* CHECK INDIVIDUAL LINES (remove invalid entries) */ + /* CHECK INDIVIDUAL LINES (remove invalid entries) */ - CHECK_SECTION_IN_ALL_MODULES(Animator, animators, CheckAnimator); + CHECK_SECTION_IN_ALL_MODULES(Animator, animators, CheckAnimator); - CHECK_SECTION_IN_ALL_MODULES(Shock2, shocks_2, CheckShock2); + CHECK_SECTION_IN_ALL_MODULES(Shock2, shocks_2, CheckShock2); - CHECK_SECTION_IN_ALL_MODULES(Shock3, shocks_3, CheckShock3); + CHECK_SECTION_IN_ALL_MODULES(Shock3, shocks_3, CheckShock3); - CHECK_SECTION_IN_ALL_MODULES(Command2, commands_2, CheckCommand); + CHECK_SECTION_IN_ALL_MODULES(Command2, commands_2, CheckCommand); - CHECK_SECTION_IN_ALL_MODULES(Trigger, triggers, CheckTrigger); + CHECK_SECTION_IN_ALL_MODULES(Trigger, triggers, CheckTrigger); - CHECK_SECTION_IN_ALL_MODULES(Trigger, triggers, CheckTrigger); + CHECK_SECTION_IN_ALL_MODULES(Trigger, triggers, CheckTrigger); - CHECK_SECTION_IN_ALL_MODULES(Flare2, flares_2, CheckFlare2); + CHECK_SECTION_IN_ALL_MODULES(Flare2, flares_2, CheckFlare2); - return valid; -} + return valid; + } -void Validator::Setup(std::shared_ptr file) -{ - m_file = file; - m_selected_modules.push_back(file->root_module); - m_messages.clear(); - m_check_beams = true; - m_messages_num_errors = 0; - m_messages_num_warnings = 0; - m_messages_num_other = 0; -} - -void Validator::AddMessage(Validator::Message::Type type, Ogre::String const & text) -{ - m_messages.push_back(Message(type, text)); - switch (type) + void Validator::Setup(std::shared_ptr file) { - case Message::TYPE_ERROR: - case Message::TYPE_FATAL_ERROR: - ++m_messages_num_errors; - break; - case Message::TYPE_WARNING: - ++m_messages_num_warnings; - break; - default: - ++m_messages_num_other; - break; + m_file = file; + m_selected_modules.push_back(file->root_module); + m_messages.clear(); + m_check_beams = true; + m_messages_num_errors = 0; + m_messages_num_warnings = 0; + m_messages_num_other = 0; } -} -bool Validator::CheckSectionSubmeshGroundmodel() -{ - Ogre::String *containing_module_name = nullptr; + void Validator::AddMessage(Validator::Message::Type type, Ogre::String const &text) + { + m_messages.push_back(Message(type, text)); + switch (type) + { + case Message::TYPE_ERROR: + case Message::TYPE_FATAL_ERROR: ++m_messages_num_errors; break; + case Message::TYPE_WARNING: ++m_messages_num_warnings; break; + default: ++m_messages_num_other; break; + } + } - std::list>::iterator module_itor = m_selected_modules.begin(); - for (; module_itor != m_selected_modules.end(); module_itor++) + bool Validator::CheckSectionSubmeshGroundmodel() { - if (! module_itor->get()->submeshes_ground_model_name.empty()) + Ogre::String *containing_module_name = nullptr; + + std::list>::iterator module_itor = m_selected_modules.begin(); + for (; module_itor != m_selected_modules.end(); module_itor++) { - if (containing_module_name == nullptr) - { - containing_module_name = & module_itor->get()->name; - } - else + if (!module_itor->get()->submeshes_ground_model_name.empty()) { - std::stringstream text; - text << "Duplicate inline-section 'submesh_groundmodel'; found in modules: '" - << *containing_module_name << "' & '" << module_itor->get()->name << "'"; - AddMessage(Message::TYPE_FATAL_ERROR, text.str()); - return false; + if (containing_module_name == nullptr) { containing_module_name = &module_itor->get()->name; } + else + { + std::stringstream text; + text << "Duplicate inline-section 'submesh_groundmodel'; found in modules: '" << *containing_module_name + << "' & '" << module_itor->get()->name << "'"; + AddMessage(Message::TYPE_FATAL_ERROR, text.str()); + return false; + } } } - } - - return true; -} -bool Validator::CheckSection(RigDef::File::Keyword keyword, bool unique, bool required) -{ - Ogre::String *containing_module_name = nullptr; + return true; + } - std::list>::iterator module_itor = m_selected_modules.begin(); - for (; module_itor != m_selected_modules.end(); module_itor++) + bool Validator::CheckSection(RigDef::File::Keyword keyword, bool unique, bool required) { - if (HasModuleKeyword(*module_itor, keyword)) + Ogre::String *containing_module_name = nullptr; + + std::list>::iterator module_itor = m_selected_modules.begin(); + for (; module_itor != m_selected_modules.end(); module_itor++) { - if (containing_module_name == nullptr) - { - containing_module_name = & module_itor->get()->name; - } - else if (unique) + if (HasModuleKeyword(*module_itor, keyword)) { - std::stringstream text; - text << "Duplicate section '" << RigDef::File::KeywordToString(keyword) - << "'; found in modules: '" << *containing_module_name - << "' & '" << module_itor->get()->name << "'"; - AddMessage(Message::TYPE_FATAL_ERROR, text.str()); - return false; + if (containing_module_name == nullptr) { containing_module_name = &module_itor->get()->name; } + else if (unique) + { + std::stringstream text; + text << "Duplicate section '" << RigDef::File::KeywordToString(keyword) << "'; found in modules: '" + << *containing_module_name << "' & '" << module_itor->get()->name << "'"; + AddMessage(Message::TYPE_FATAL_ERROR, text.str()); + return false; + } } } - } - if (containing_module_name == nullptr && required) - { - std::stringstream text; - text << "Missing required section '" << RigDef::File::KeywordToString(keyword) <<"'"; - AddMessage(Message::TYPE_FATAL_ERROR, text.str()); - return false; + if (containing_module_name == nullptr && required) + { + std::stringstream text; + text << "Missing required section '" << RigDef::File::KeywordToString(keyword) << "'"; + AddMessage(Message::TYPE_FATAL_ERROR, text.str()); + return false; + } + return true; } - return true; -} - -bool Validator::HasModuleKeyword(std::shared_ptr module, RigDef::File::Keyword keyword) -{ - using namespace RigDef; - switch (keyword) + bool Validator::HasModuleKeyword(std::shared_ptr module, RigDef::File::Keyword keyword) { - /* Please maintain alphabetical order */ + using namespace RigDef; + + switch (keyword) + { + /* Please maintain alphabetical order */ - case (File::KEYWORD_BEAMS): - return ! module->beams.empty(); + case (File::KEYWORD_BEAMS): return !module->beams.empty(); - case (File::KEYWORD_ENGINE): - return (module->engine != nullptr); + case (File::KEYWORD_ENGINE): return (module->engine != nullptr); - case (File::KEYWORD_ENGOPTION): - return (module->engoption != nullptr); + case (File::KEYWORD_ENGOPTION): return (module->engoption != nullptr); - case (File::KEYWORD_ENGTURBO) : - return (module->engturbo != nullptr); + case (File::KEYWORD_ENGTURBO): return (module->engturbo != nullptr); - case (File::KEYWORD_EXTCAMERA): - return (module->ext_camera != nullptr); + case (File::KEYWORD_EXTCAMERA): return (module->ext_camera != nullptr); - case (File::KEYWORD_FUSEDRAG): - return ! module->fusedrag.empty(); + case (File::KEYWORD_FUSEDRAG): return !module->fusedrag.empty(); - case (File::KEYWORD_GLOBALS): - return (module->globals != nullptr); + case (File::KEYWORD_GLOBALS): return (module->globals != nullptr); - case (File::KEYWORD_GUISETTINGS): - return (module->gui_settings != nullptr); + case (File::KEYWORD_GUISETTINGS): return (module->gui_settings != nullptr); - case (File::KEYWORD_MANAGEDMATERIALS): - return ! module->managed_materials.empty(); + case (File::KEYWORD_MANAGEDMATERIALS): return !module->managed_materials.empty(); - case (File::KEYWORD_NODES): - return ! module->nodes.empty(); + case (File::KEYWORD_NODES): return !module->nodes.empty(); - case (File::KEYWORD_SPEEDLIMITER): - return (module->speed_limiter.is_enabled); + case (File::KEYWORD_SPEEDLIMITER): return (module->speed_limiter.is_enabled); case (File::KEYWORD_TORQUECURVE): return (module->torque_curve != nullptr); - - /* TEMPLATE - case (File::SECTION_): - return (module->globals != nullptr); - */ - default: - return false; - }; -} + /* TEMPLATE + case (File::SECTION_): + return (module->globals != nullptr); + */ -bool Validator::AddModule(Ogre::String const & module_name) -{ - std::map< Ogre::String, std::shared_ptr >::iterator result - = m_file->user_modules.find(module_name); + default: return false; + }; + } - if (result != m_file->user_modules.end()) + bool Validator::AddModule(Ogre::String const &module_name) { - m_selected_modules.push_back(result->second); - return true; + std::map>::iterator result = m_file->user_modules.find(module_name); + + if (result != m_file->user_modules.end()) + { + m_selected_modules.push_back(result->second); + return true; + } + return false; } - return false; -} -bool Validator::CheckGearbox() -{ - /* Find it */ - std::shared_ptr engine; - std::list>::iterator module_itor = m_selected_modules.begin(); - for (; module_itor != m_selected_modules.end(); module_itor++) + bool Validator::CheckGearbox() { - if (module_itor->get()->engine != nullptr) + /* Find it */ + std::shared_ptr engine; + std::list>::iterator module_itor = m_selected_modules.begin(); + for (; module_itor != m_selected_modules.end(); module_itor++) { - if (module_itor->get()->engine->gear_ratios.size() > 0) - { - return true; - } - else + if (module_itor->get()->engine != nullptr) { - AddMessage(Message::TYPE_FATAL_ERROR, "Engine must have at least 1 forward gear."); - return false; + if (module_itor->get()->engine->gear_ratios.size() > 0) { return true; } + else + { + AddMessage(Message::TYPE_FATAL_ERROR, "Engine must have at least 1 forward gear."); + return false; + } } } + return true; } - return true; -} - -bool Validator::CheckShock2(RigDef::Shock2 & shock2) -{ - std::list bad_fields; - /* Keep these in sync with wiki doc: http://www.rigsofrods.org/wiki/pages/Truck_Description_File#Shocks2 */ - /* We safely check for value -1.f */ - if (shock2.spring_in < -0.8f) - { - bad_fields.push_back("spring_in_rate"); - } - if (shock2.damp_in < -0.8f) - { - bad_fields.push_back("damping_in_rate"); - } - if (shock2.spring_out < -0.8f) - { - bad_fields.push_back("spring_out_rate"); - } - if (shock2.damp_out < -0.8f) - { - bad_fields.push_back("damping_out_rate"); - } - if (shock2.progress_factor_spring_in < -0.8f) - { - bad_fields.push_back("spring_in_progression_factor"); - } - if (shock2.progress_factor_damp_in < -0.8f) - { - bad_fields.push_back("damping_in_progression_factor"); - } - if (shock2.progress_factor_spring_out < -0.8f) - { - bad_fields.push_back("spring_out_progression_factor"); - } - if (shock2.progress_factor_damp_out < -0.8f) - { - bad_fields.push_back("damping_out_progression_factor"); - } - if (shock2.short_bound < -0.8f) - { - bad_fields.push_back("max_contraction"); - } - if (shock2.long_bound < -0.8f) - { - bad_fields.push_back("max_extension"); - } - if (shock2.precompression < -0.8f) + bool Validator::CheckShock2(RigDef::Shock2 &shock2) { - bad_fields.push_back("precompression"); - } + std::list bad_fields; - if (bad_fields.size() > 0) - { - std::stringstream msg; - msg << "Invalid values in section 'shocks2', fields: "; - std::list::iterator itor = bad_fields.begin(); - bool first = true; - for( ; itor != bad_fields.end(); itor++) + /* Keep these in sync with wiki doc: http://www.rigsofrods.org/wiki/pages/Truck_Description_File#Shocks2 */ + /* We safely check for value -1.f */ + if (shock2.spring_in < -0.8f) { bad_fields.push_back("spring_in_rate"); } + if (shock2.damp_in < -0.8f) { bad_fields.push_back("damping_in_rate"); } + if (shock2.spring_out < -0.8f) { bad_fields.push_back("spring_out_rate"); } + if (shock2.damp_out < -0.8f) { bad_fields.push_back("damping_out_rate"); } + if (shock2.progress_factor_spring_in < -0.8f) { bad_fields.push_back("spring_in_progression_factor"); } + if (shock2.progress_factor_damp_in < -0.8f) { bad_fields.push_back("damping_in_progression_factor"); } + if (shock2.progress_factor_spring_out < -0.8f) { bad_fields.push_back("spring_out_progression_factor"); } + if (shock2.progress_factor_damp_out < -0.8f) { bad_fields.push_back("damping_out_progression_factor"); } + if (shock2.short_bound < -0.8f) { bad_fields.push_back("max_contraction"); } + if (shock2.long_bound < -0.8f) { bad_fields.push_back("max_extension"); } + if (shock2.precompression < -0.8f) { bad_fields.push_back("precompression"); } + + if (bad_fields.size() > 0) { - msg << (first ? "" : ", ") << *itor; - first = false; - } + std::stringstream msg; + msg << "Invalid values in section 'shocks2', fields: "; + std::list::iterator itor = bad_fields.begin(); + bool first = true; + for (; itor != bad_fields.end(); itor++) + { + msg << (first ? "" : ", ") << *itor; + first = false; + } - AddMessage(Message::TYPE_ERROR, msg.str()); - return false; + AddMessage(Message::TYPE_ERROR, msg.str()); + return false; + } + return true; } - return true; -} - -bool Validator::CheckShock3(RigDef::Shock3 & shock3) -{ - std::list bad_fields; - /* Keep these in sync with wiki doc: http://www.rigsofrods.org/wiki/pages/Truck_Description_File#Shocks3 */ - /* We safely check for value -1.f */ - if (shock3.spring_in < -0.8f) - { - bad_fields.push_back("spring_in_rate"); - } - if (shock3.damp_in < -0.8f) - { - bad_fields.push_back("damping_in_rate"); - } - if (shock3.spring_out < -0.8f) - { - bad_fields.push_back("spring_out_rate"); - } - if (shock3.damp_out < -0.8f) - { - bad_fields.push_back("damping_out_rate"); - } - if (shock3.damp_in_slow < -0.8f) - { - bad_fields.push_back("damp_in_slow"); - } - if (shock3.split_vel_in < -0.8f) - { - bad_fields.push_back("split_in"); - } - if (shock3.damp_in_fast < -0.8f) - { - bad_fields.push_back("damp_in_fast"); - } - if (shock3.damp_out_slow < -0.8f) - { - bad_fields.push_back("damp_out_slow"); - } - if (shock3.split_vel_out < -0.8f) - { - bad_fields.push_back("split_out"); - } - if (shock3.damp_out_fast < -0.8f) - { - bad_fields.push_back("damp_out_fast"); - } - if (shock3.short_bound < -0.8f) + bool Validator::CheckShock3(RigDef::Shock3 &shock3) { - bad_fields.push_back("max_contraction"); - } - if (shock3.long_bound < -0.8f) - { - bad_fields.push_back("max_extension"); - } - if (shock3.precompression < -0.8f) - { - bad_fields.push_back("precompression"); + std::list bad_fields; + + /* Keep these in sync with wiki doc: http://www.rigsofrods.org/wiki/pages/Truck_Description_File#Shocks3 */ + /* We safely check for value -1.f */ + if (shock3.spring_in < -0.8f) { bad_fields.push_back("spring_in_rate"); } + if (shock3.damp_in < -0.8f) { bad_fields.push_back("damping_in_rate"); } + if (shock3.spring_out < -0.8f) { bad_fields.push_back("spring_out_rate"); } + if (shock3.damp_out < -0.8f) { bad_fields.push_back("damping_out_rate"); } + if (shock3.damp_in_slow < -0.8f) { bad_fields.push_back("damp_in_slow"); } + if (shock3.split_vel_in < -0.8f) { bad_fields.push_back("split_in"); } + if (shock3.damp_in_fast < -0.8f) { bad_fields.push_back("damp_in_fast"); } + if (shock3.damp_out_slow < -0.8f) { bad_fields.push_back("damp_out_slow"); } + if (shock3.split_vel_out < -0.8f) { bad_fields.push_back("split_out"); } + if (shock3.damp_out_fast < -0.8f) { bad_fields.push_back("damp_out_fast"); } + if (shock3.short_bound < -0.8f) { bad_fields.push_back("max_contraction"); } + if (shock3.long_bound < -0.8f) { bad_fields.push_back("max_extension"); } + if (shock3.precompression < -0.8f) { bad_fields.push_back("precompression"); } + + if (bad_fields.size() > 0) + { + std::stringstream msg; + msg << "Invalid values in section 'shocks3', fields: "; + std::list::iterator itor = bad_fields.begin(); + bool first = true; + for (; itor != bad_fields.end(); itor++) + { + msg << (first ? "" : ", ") << *itor; + first = false; + } + + AddMessage(Message::TYPE_ERROR, msg.str()); + return false; + } + return true; } - if (bad_fields.size() > 0) + bool Validator::CheckAnimator(RigDef::Animator &def) { - std::stringstream msg; - msg << "Invalid values in section 'shocks3', fields: "; - std::list::iterator itor = bad_fields.begin(); - bool first = true; - for( ; itor != bad_fields.end(); itor++) + unsigned int source_check = def.flags; + BITMASK_SET_0(source_check, RigDef::Animator::OPTION_SHORT_LIMIT); + BITMASK_SET_0(source_check, RigDef::Animator::OPTION_LONG_LIMIT); + if (source_check == 0) { - msg << (first ? "" : ", ") << *itor; - first = false; + AddMessage(Message::TYPE_ERROR, "Failed to identify animator source"); + return false; } - - AddMessage(Message::TYPE_ERROR, msg.str()); - return false; + return true; } - return true; -} -bool Validator::CheckAnimator(RigDef::Animator & def) -{ - unsigned int source_check = def.flags; - BITMASK_SET_0(source_check, RigDef::Animator::OPTION_SHORT_LIMIT); - BITMASK_SET_0(source_check, RigDef::Animator::OPTION_LONG_LIMIT); - if (source_check == 0) + bool Validator::CheckCommand(RigDef::Command2 &def) { - AddMessage(Message::TYPE_ERROR, "Failed to identify animator source"); - return false; - } - return true; -} + bool ok = true; -bool Validator::CheckCommand(RigDef::Command2 & def) -{ - bool ok = true; + if (def.extend_key > MAX_COMMANDS) + { + std::stringstream msg; + msg << "Section 'commands' or 'commands2': Invalid 'extend_key': "; + msg << def.extend_key; + msg << "; valid range is <0 - " << MAX_COMMANDS << ">"; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } - if (def.extend_key > MAX_COMMANDS) - { - std::stringstream msg; - msg << "Section 'commands' or 'commands2': Invalid 'extend_key': "; - msg << def.extend_key; - msg << "; valid range is <0 - " << MAX_COMMANDS << ">"; - AddMessage(Message::TYPE_ERROR, msg.str()); - ok = false; + if (def.contract_key > MAX_COMMANDS) + { + std::stringstream msg; + msg << "Section 'commands' or 'commands2': Invalid 'contract_key': "; + msg << def.contract_key; + msg << "; valid range is <0 - " << MAX_COMMANDS << ">"; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } + + return ok; } - if (def.contract_key > MAX_COMMANDS) + bool Validator::CheckFlare2(RigDef::Flare2 &def) { - std::stringstream msg; - msg << "Section 'commands' or 'commands2': Invalid 'contract_key': "; - msg << def.contract_key; - msg << "; valid range is <0 - " << MAX_COMMANDS << ">"; - AddMessage(Message::TYPE_ERROR, msg.str()); - ok = false; - } + bool ok = true; - return ok; -} + if (def.control_number < -1 || def.control_number > 500) + { + std::stringstream msg; + msg << "Wrong parameter 'control_number' (" << def.control_number << "), must be in range <-1, 500>"; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } -bool Validator::CheckFlare2(RigDef::Flare2 & def) -{ - bool ok = true; - - if (def.control_number < -1 || def.control_number > 500) - { - std::stringstream msg; - msg << "Wrong parameter 'control_number' (" << def.control_number << "), must be in range <-1, 500>"; - AddMessage(Message::TYPE_ERROR, msg.str()); - ok = false; - } + if (def.blink_delay_milis < -2 || def.blink_delay_milis > 60000) + { + std::stringstream msg; + msg << "Wrong parameter 'blink_delay_milis' (" << def.blink_delay_milis << "), must be in range <-2, 60000>"; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } - if (def.blink_delay_milis < -2 || def.blink_delay_milis > 60000) - { - std::stringstream msg; - msg << "Wrong parameter 'blink_delay_milis' (" << def.blink_delay_milis << "), must be in range <-2, 60000>"; - AddMessage(Message::TYPE_ERROR, msg.str()); - ok = false; + return ok; } - return ok; -} - -bool Validator::CheckTrigger(RigDef::Trigger & def) -{ - bool ok = true; + bool Validator::CheckTrigger(RigDef::Trigger &def) + { + bool ok = true; - bool hook_toggle = - BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_H_LOCK_HOOKGROUPS_KEY) - || BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_h_UNLOCK_HOOKGROUPS_KEY); + bool hook_toggle = BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_H_LOCK_HOOKGROUPS_KEY) || + BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_h_UNLOCK_HOOKGROUPS_KEY); - bool trigger_blocker = BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_B_BLOCK_TRIGGERS); - bool inv_trigger_blocker = BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_A_INV_BLOCK_TRIGGERS); + bool trigger_blocker = BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_B_BLOCK_TRIGGERS); + bool inv_trigger_blocker = BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_A_INV_BLOCK_TRIGGERS); - if (BITMASK_IS_0(def.options, RigDef::Trigger::OPTION_E_ENGINE_TRIGGER)) - { - if (! trigger_blocker && ! inv_trigger_blocker && ! hook_toggle ) + if (BITMASK_IS_0(def.options, RigDef::Trigger::OPTION_E_ENGINE_TRIGGER)) { - /* Make the full check */ - if (def.shortbound_trigger_action < 1 || def.shortbound_trigger_action > MAX_COMMANDS) + if (!trigger_blocker && !inv_trigger_blocker && !hook_toggle) { - std::stringstream msg; - msg << "Wrong parameter 'shortbound_trigger_action': " << def.shortbound_trigger_action; - msg << "; Alloved range is <0 - " << MAX_COMMANDS << ">. "; - msg << "Trigger deactivated."; - AddMessage(Message::TYPE_ERROR, msg.str()); - ok = false; + /* Make the full check */ + if (def.shortbound_trigger_action < 1 || def.shortbound_trigger_action > MAX_COMMANDS) + { + std::stringstream msg; + msg << "Wrong parameter 'shortbound_trigger_action': " << def.shortbound_trigger_action; + msg << "; Alloved range is <0 - " << MAX_COMMANDS << ">. "; + msg << "Trigger deactivated."; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } } - } - else if (! hook_toggle) - { - /* This is a Trigger-Blocker, make special check */ - if (def.shortbound_trigger_action < 0) + else if (!hook_toggle) { - std::stringstream msg; - msg << "Wrong parameter 'shortbound_trigger_action': " << def.shortbound_trigger_action; - msg << "; Alloved range is <0 - " << MAX_COMMANDS << ">. "; - msg << "Trigger deactivated."; - AddMessage(Message::TYPE_ERROR, msg.str()); - ok = false; + /* This is a Trigger-Blocker, make special check */ + if (def.shortbound_trigger_action < 0) + { + std::stringstream msg; + msg << "Wrong parameter 'shortbound_trigger_action': " << def.shortbound_trigger_action; + msg << "; Alloved range is <0 - " << MAX_COMMANDS << ">. "; + msg << "Trigger deactivated."; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } + if (def.longbound_trigger_action < 0) + { + std::stringstream msg; + msg << "Wrong parameter 'longbound_trigger_action': " << def.longbound_trigger_action; + msg << "; Alloved range is <0 - " << MAX_COMMANDS << ">. "; + msg << "Trigger deactivated."; + AddMessage(Message::TYPE_ERROR, msg.str()); + ok = false; + } } - if (def.longbound_trigger_action < 0) + } + else + { + /* Engine trigger */ + if (trigger_blocker || inv_trigger_blocker || hook_toggle || + BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_s_SWITCH_CMD_NUM)) { - std::stringstream msg; - msg << "Wrong parameter 'longbound_trigger_action': " << def.longbound_trigger_action; - msg << "; Alloved range is <0 - " << MAX_COMMANDS << ">. "; - msg << "Trigger deactivated."; - AddMessage(Message::TYPE_ERROR, msg.str()); + AddMessage(Message::TYPE_ERROR, "Wrong command-eventnumber. Engine trigger deactivated."); ok = false; } } + + return ok; } - else + + bool Validator::CheckVideoCamera(RigDef::VideoCamera &def) { - /* Engine trigger */ - if (trigger_blocker || inv_trigger_blocker || hook_toggle || BITMASK_IS_1(def.options, RigDef::Trigger::OPTION_s_SWITCH_CMD_NUM)) + bool ok = true; + + /* disabled isPowerOfTwo, as it can be a renderwindow now with custom resolution */ + if (def.texture_width <= 0 || def.texture_height <= 0) { - AddMessage(Message::TYPE_ERROR, "Wrong command-eventnumber. Engine trigger deactivated."); + AddMessage(Message::TYPE_ERROR, "Wrong texture size definition."); ok = false; } - } - - return ok; -} -bool Validator::CheckVideoCamera(RigDef::VideoCamera & def) -{ - bool ok = true; - - /* disabled isPowerOfTwo, as it can be a renderwindow now with custom resolution */ - if (def.texture_width <= 0 || def.texture_height <= 0) - { - AddMessage(Message::TYPE_ERROR, "Wrong texture size definition."); - ok = false; - } + if (def.min_clip_distance < 0 || def.min_clip_distance > def.max_clip_distance || def.max_clip_distance < 0) + { + AddMessage(Message::TYPE_ERROR, "Wrong clipping sizes definition."); + ok = false; + } - if (def.min_clip_distance < 0 || def.min_clip_distance > def.max_clip_distance || def.max_clip_distance < 0) - { - AddMessage(Message::TYPE_ERROR, "Wrong clipping sizes definition."); - ok = false; - } + if (def.camera_mode < -2) + { + AddMessage(Message::TYPE_ERROR, "Camera Mode setting incorrect."); + ok = false; + } - if (def.camera_mode < -2 ) - { - AddMessage(Message::TYPE_ERROR, "Camera Mode setting incorrect."); - ok = false; - } + if (def.camera_role < -1 || def.camera_role > 1) + { + AddMessage(Message::TYPE_ERROR, "Camera Role (camera, trace, mirror) setting incorrect."); + ok = false; + } - if (def.camera_role < -1 || def.camera_role >1) - { - AddMessage(Message::TYPE_ERROR, "Camera Role (camera, trace, mirror) setting incorrect."); - ok = false; + return ok; } - return ok; -} - -std::string Validator::ProcessMessagesToString() -{ - if (m_messages.empty()) + std::string Validator::ProcessMessagesToString() { - std::string msg(" == Validating done OK"); - return msg; - } + if (m_messages.empty()) + { + std::string msg(" == Validating done OK"); + return msg; + } - std::stringstream report; - report << " == Validating done, report:" <type) + auto itor = m_messages.begin(); + auto end = m_messages.end(); + for (; itor != end; ++itor) { - case (RigDef::Validator::Message::TYPE_FATAL_ERROR): - report << "#FF3300 FATAL ERROR #FFFFFF"; - break; - case (RigDef::Validator::Message::TYPE_ERROR): - report << "#FF3300 ERROR #FFFFFF"; - break; - case (RigDef::Validator::Message::TYPE_WARNING): - report << "#FFFF00 WARNING #FFFFFF"; - break; - default: - report << "INFO"; - break; + switch (itor->type) + { + case (RigDef::Validator::Message::TYPE_FATAL_ERROR): report << "#FF3300 FATAL ERROR #FFFFFF"; break; + case (RigDef::Validator::Message::TYPE_ERROR): report << "#FF3300 ERROR #FFFFFF"; break; + case (RigDef::Validator::Message::TYPE_WARNING): report << "#FFFF00 WARNING #FFFFFF"; break; + default: report << "INFO"; break; + } + + report << ": " << itor->text << std::endl; } - report << ": " << itor->text << std::endl; + return report.str(); } - return report.str(); -} - } // namespace RigDef diff --git a/source/main/resources/rig_def_fileformat/RigDef_Validator.h b/source/main/resources/rig_def_fileformat/RigDef_Validator.h index 5d753cc1b1..1708fc211f 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Validator.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Validator.h @@ -19,7 +19,7 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file RigDef_Validator.h @author Petr Ohlidal @date 12/2013 @@ -35,129 +35,134 @@ #include "RigDef_File.h" -#include #include +#include namespace RigDef { -/** -* Performs a formal validation of the file (missing required parts, conflicts of modules, etc...) -*/ -class Validator -{ -public: - - struct Message + /** + * Performs a formal validation of the file (missing required parts, conflicts of modules, etc...) + */ + class Validator { - enum Type + public: + struct Message { - TYPE_INFO, - TYPE_WARNING, - TYPE_ERROR, - TYPE_FATAL_ERROR, - - TYPE_INVALID = 0xFFFFFFFF + enum Type + { + TYPE_INFO, + TYPE_WARNING, + TYPE_ERROR, + TYPE_FATAL_ERROR, + + TYPE_INVALID = 0xFFFFFFFF + }; + + Message(Type type, Ogre::String const &message) : type(type), text(message) + { + } + + Type type; + Ogre::String text; }; - Message(Type type, Ogre::String const & message): - type(type), - text(message) - {} - - Type type; - Ogre::String text; - }; - - /** - * Prepares the validation. - */ - void Setup(std::shared_ptr file); - - /** - * Adds a vehicle module to the validated configuration. - * @param module_name A module from the validated rig-def file. - */ - bool AddModule(Ogre::String const & module_name); - - bool Validate(); + /** + * Prepares the validation. + */ + void Setup(std::shared_ptr file); - std::list & GetMessages() - { - return m_messages; - } + /** + * Adds a vehicle module to the validated configuration. + * @param module_name A module from the validated rig-def file. + */ + bool AddModule(Ogre::String const &module_name); - void SetCheckBeams(bool check_beams) - { - m_check_beams = check_beams; - } + bool Validate(); - int GetMessagesNumErrors() const { return m_messages_num_errors; } - int GetMessagesNumWarnings() const { return m_messages_num_warnings; } - int GetMessagesNumOther() const { return m_messages_num_other; } + std::list &GetMessages() + { + return m_messages; + } - std::string ProcessMessagesToString(); + void SetCheckBeams(bool check_beams) + { + m_check_beams = check_beams; + } -private: + int GetMessagesNumErrors() const + { + return m_messages_num_errors; + } + int GetMessagesNumWarnings() const + { + return m_messages_num_warnings; + } + int GetMessagesNumOther() const + { + return m_messages_num_other; + } - /** - * Finds section in configuration and performs checks. - * @param unique Is this section required to be unique? - * @param required Is this section required? - * @return True if all conditions were met. - */ - bool CheckSection(RigDef::File::Keyword keyword, bool unique, bool required); + std::string ProcessMessagesToString(); - /** - * Checks if a module contains a section. - */ - bool HasModuleKeyword(std::shared_ptr module, RigDef::File::Keyword keyword); + private: + /** + * Finds section in configuration and performs checks. + * @param unique Is this section required to be unique? + * @param required Is this section required? + * @return True if all conditions were met. + */ + bool CheckSection(RigDef::File::Keyword keyword, bool unique, bool required); - /** - * Inline-ection 'submesh_groundmodel', unique across all modules. - */ - bool CheckSectionSubmeshGroundmodel(); + /** + * Checks if a module contains a section. + */ + bool HasModuleKeyword(std::shared_ptr module, RigDef::File::Keyword keyword); - /** - * Checks there's at least 1 forward gear. - */ - bool CheckGearbox(); + /** + * Inline-ection 'submesh_groundmodel', unique across all modules. + */ + bool CheckSectionSubmeshGroundmodel(); - void AddMessage(Validator::Message::Type type, Ogre::String const & text); + /** + * Checks there's at least 1 forward gear. + */ + bool CheckGearbox(); -/* -------------------------------------------------------------------------- */ -/* Individual section checkers. */ -/* -------------------------------------------------------------------------- */ + void AddMessage(Validator::Message::Type type, Ogre::String const &text); - bool CheckShock2(RigDef::Shock2 & shock2); + /* -------------------------------------------------------------------------- */ + /* Individual section checkers. */ + /* -------------------------------------------------------------------------- */ - bool CheckShock3(RigDef::Shock3 & shock3); + bool CheckShock2(RigDef::Shock2 &shock2); - bool CheckAnimator(RigDef::Animator & def); + bool CheckShock3(RigDef::Shock3 &shock3); - bool CheckCommand(RigDef::Command2 & def); + bool CheckAnimator(RigDef::Animator &def); - bool CheckTrigger(RigDef::Trigger & def); + bool CheckCommand(RigDef::Command2 &def); - /** - * Section 'videocamera'. - */ - bool CheckVideoCamera(RigDef::VideoCamera & def); + bool CheckTrigger(RigDef::Trigger &def); - bool CheckFlare2(RigDef::Flare2 & def); + /** + * Section 'videocamera'. + */ + bool CheckVideoCamera(RigDef::VideoCamera &def); -/* -------------------------------------------------------------------------- */ -/* Properties */ -/* -------------------------------------------------------------------------- */ + bool CheckFlare2(RigDef::Flare2 &def); - std::list m_messages; - int m_messages_num_errors; - int m_messages_num_warnings; - int m_messages_num_other; - std::shared_ptr m_file; //!< The parsed input file. - std::list> m_selected_modules; - bool m_check_beams; + /* -------------------------------------------------------------------------- */ + /* Properties */ + /* -------------------------------------------------------------------------- */ -}; + std::list m_messages; + int m_messages_num_errors; + int m_messages_num_warnings; + int m_messages_num_other; + std::shared_ptr m_file; //!< The parsed input file. + std::list> m_selected_modules; + bool m_check_beams; + }; } // namespace RigDef diff --git a/source/main/resources/terrn2_fileformat/Terrn2Fileformat.cpp b/source/main/resources/terrn2_fileformat/Terrn2Fileformat.cpp index a157f25053..8cd521dd6b 100644 --- a/source/main/resources/terrn2_fileformat/Terrn2Fileformat.cpp +++ b/source/main/resources/terrn2_fileformat/Terrn2Fileformat.cpp @@ -21,18 +21,19 @@ /// @author Petr Ohlidal, 11/2016 #include "Terrn2Fileformat.h" + +#include "BeamConstants.h" #include "ConfigFile.h" #include "Utils.h" -#include "BeamConstants.h" #include using namespace RoR; using namespace Ogre; -const std::string VALUE_NOT_FOUND("@@NotFound!!"); +const std::string VALUE_NOT_FOUND("@@NotFound!!"); -bool Terrn2Parser::LoadTerrn2(Terrn2Def& def, Ogre::DataStreamPtr &ds) +bool Terrn2Parser::LoadTerrn2(Terrn2Def &def, Ogre::DataStreamPtr &ds) { RoR::ConfigFile file; file.load(ds, "\t:=", true); @@ -53,28 +54,29 @@ bool Terrn2Parser::LoadTerrn2(Terrn2Def& def, Ogre::DataStreamPtr &ds) return false; } - def.ambient_color = file.GetColourValue("AmbientColor", "General", ColourValue::White); - def.category_id = file.GetInt ("CategoryID", "General", 129); - def.guid = file.GetStringEx ("GUID", "General"); - def.version = file.GetInt ("Version", "General", 1); - def.gravity = file.GetFloat ("Gravity", "General", -9.81); - def.caelum_config = file.GetStringEx ("CaelumConfigFile", "General"); - def.cubemap_config = file.GetStringEx ("SandStormCubeMap", "General"); - def.caelum_fog_start = file.GetInt ("CaelumFogStart", "General", -1); - def.caelum_fog_end = file.GetInt ("CaelumFogEnd", "General", -1); - def.has_water = file.GetBool ("Water", "General", false); - def.hydrax_conf_file = file.GetStringEx ("HydraxConfigFile", "General"); - def.skyx_config = file.GetStringEx ("SkyXConfigFile", "General"); - def.traction_map_file = file.GetStringEx ("TractionMap", "General"); - def.water_height = file.GetFloat ("WaterLine", "General"); - def.water_bottom_height = file.GetFloat ("WaterBottomLine", "General"); - def.custom_material_name = file.GetStringEx ("CustomMaterial", "General"); - - def.start_position = StringConverter::parseVector3(file.GetStringEx("StartPosition", "General"), Vector3(512.0f, 0.0f, 512.0f)); + def.ambient_color = file.GetColourValue("AmbientColor", "General", ColourValue::White); + def.category_id = file.GetInt("CategoryID", "General", 129); + def.guid = file.GetStringEx("GUID", "General"); + def.version = file.GetInt("Version", "General", 1); + def.gravity = file.GetFloat("Gravity", "General", -9.81); + def.caelum_config = file.GetStringEx("CaelumConfigFile", "General"); + def.cubemap_config = file.GetStringEx("SandStormCubeMap", "General"); + def.caelum_fog_start = file.GetInt("CaelumFogStart", "General", -1); + def.caelum_fog_end = file.GetInt("CaelumFogEnd", "General", -1); + def.has_water = file.GetBool("Water", "General", false); + def.hydrax_conf_file = file.GetStringEx("HydraxConfigFile", "General"); + def.skyx_config = file.GetStringEx("SkyXConfigFile", "General"); + def.traction_map_file = file.GetStringEx("TractionMap", "General"); + def.water_height = file.GetFloat("WaterLine", "General"); + def.water_bottom_height = file.GetFloat("WaterBottomLine", "General"); + def.custom_material_name = file.GetStringEx("CustomMaterial", "General"); + + def.start_position = + StringConverter::parseVector3(file.GetStringEx("StartPosition", "General"), Vector3(512.0f, 0.0f, 512.0f)); if (file.HasSection("Authors")) { - for (auto& author: file.getSettings("Authors")) + for (auto &author : file.getSettings("Authors")) { String type = RoR::Utils::SanitizeUtf8String(author.first); // e.g. terrain String name = RoR::Utils::SanitizeUtf8String(author.second); // e.g. john doe @@ -91,7 +93,7 @@ bool Terrn2Parser::LoadTerrn2(Terrn2Def& def, Ogre::DataStreamPtr &ds) if (file.HasSection("Objects")) { - for (auto& tobj: file.getSettings("Objects")) + for (auto &tobj : file.getSettings("Objects")) { Ogre::String tobj_filename = RoR::Utils::SanitizeUtf8String(tobj.first); def.tobj_files.push_back(RoR::Utils::TrimStr(tobj_filename)); @@ -100,7 +102,7 @@ bool Terrn2Parser::LoadTerrn2(Terrn2Def& def, Ogre::DataStreamPtr &ds) if (file.HasSection("Scripts")) { - for (auto& script: file.getSettings("Scripts")) + for (auto &script : file.getSettings("Scripts")) { Ogre::String as_filename = RoR::Utils::SanitizeUtf8String(script.first); def.as_files.push_back(RoR::Utils::TrimStr(as_filename)); @@ -112,18 +114,18 @@ bool Terrn2Parser::LoadTerrn2(Terrn2Def& def, Ogre::DataStreamPtr &ds) return true; } -void Terrn2Parser::ProcessTeleport(Terrn2Def& def, RoR::ConfigFile* file) +void Terrn2Parser::ProcessTeleport(Terrn2Def &def, RoR::ConfigFile *file) { def.teleport_map_image = file->GetStringEx("NavigationMapImage", "Teleport"); unsigned int telepoint_number = 1; for (;;) { - char key_position [50]; - char key_name [50]; + char key_position[50]; + char key_name[50]; - snprintf(key_position, 50, "Telepoint%u/Position" , telepoint_number); - snprintf(key_name, 50, "Telepoint%u/Name" , telepoint_number); + snprintf(key_position, 50, "Telepoint%u/Position", telepoint_number); + snprintf(key_name, 50, "Telepoint%u/Name", telepoint_number); std::string pos_str = file->GetStringEx(key_position, "Teleport", VALUE_NOT_FOUND); if (pos_str == VALUE_NOT_FOUND) @@ -134,30 +136,22 @@ void Terrn2Parser::ProcessTeleport(Terrn2Def& def, RoR::ConfigFile* file) if (sscanf(pos_str.c_str(), "%f, %f, %f", &t_point.position.x, &t_point.position.y, &t_point.position.z) != 3) { char msg_buf[500]; - snprintf(msg_buf, 500, - "ERROR: Field '[Teleport]/%s' ('%s') is not valid XYZ position. Skipping telepoint %u.", - key_position, pos_str.c_str(), telepoint_number); + snprintf(msg_buf, 500, "ERROR: Field '[Teleport]/%s' ('%s') is not valid XYZ position. Skipping telepoint %u.", + key_position, pos_str.c_str(), telepoint_number); this->AddMessage(msg_buf); } else { - t_point.name = file->GetStringEx(key_name, "Teleport"); // Optional field - def.telepoints.push_back(t_point); // Persist the entry + t_point.name = file->GetStringEx(key_name, "Teleport"); // Optional field + def.telepoints.push_back(t_point); // Persist the entry } ++telepoint_number; } } -Terrn2Def::Terrn2Def(): - ambient_color(Ogre::ColourValue::Black), - category_id(-1), - start_position(Ogre::Vector3::ZERO), - version(1), - gravity(DEFAULT_GRAVITY), - water_height (0), - water_bottom_height(0), - caelum_fog_start (0), - caelum_fog_end (0), - has_water(false) -{} +Terrn2Def::Terrn2Def() + : ambient_color(Ogre::ColourValue::Black), category_id(-1), start_position(Ogre::Vector3::ZERO), version(1), + gravity(DEFAULT_GRAVITY), water_height(0), water_bottom_height(0), caelum_fog_start(0), caelum_fog_end(0), has_water(false) +{ +} diff --git a/source/main/resources/terrn2_fileformat/Terrn2Fileformat.h b/source/main/resources/terrn2_fileformat/Terrn2Fileformat.h index 3af93c4cda..2f605df287 100644 --- a/source/main/resources/terrn2_fileformat/Terrn2Fileformat.h +++ b/source/main/resources/terrn2_fileformat/Terrn2Fileformat.h @@ -24,67 +24,73 @@ #include "ForwardDeclarations.h" -#include -#include - #include #include #include +#include +#include -namespace RoR { - -struct Terrn2Author -{ - std::string type; - std::string name; -}; - -struct Terrn2Telepoint ///< Teleport drop location +namespace RoR { - Ogre::Vector3 position; - std::string name; -}; -struct Terrn2Def -{ - Terrn2Def(); - - std::string name; - std::string ogre_ter_conf_filename; - Ogre::ColourValue ambient_color; - int category_id; - Ogre::Vector3 start_position; - std::string guid; - int version; - float gravity; - float water_height; - float water_bottom_height; - std::list authors; - std::list tobj_files; - std::list as_files; - std::list telepoints; - std::string caelum_config; - int caelum_fog_start; - int caelum_fog_end; - std::string cubemap_config; - bool has_water; - std::string hydrax_conf_file; - std::string skyx_config; - std::string traction_map_file; - std::string custom_material_name; - std::string teleport_map_image; -}; - -class Terrn2Parser -{ -public: - bool LoadTerrn2(Terrn2Def& def, Ogre::DataStreamPtr &ds); - std::list const & GetMessages() const { return m_messages; } - -private: - void ProcessTeleport(Terrn2Def& def, RoR::ConfigFile* file); - void AddMessage(const char* msg) { m_messages.push_back(msg); } - std::list m_messages; -}; + struct Terrn2Author + { + std::string type; + std::string name; + }; + + struct Terrn2Telepoint ///< Teleport drop location + { + Ogre::Vector3 position; + std::string name; + }; + + struct Terrn2Def + { + Terrn2Def(); + + std::string name; + std::string ogre_ter_conf_filename; + Ogre::ColourValue ambient_color; + int category_id; + Ogre::Vector3 start_position; + std::string guid; + int version; + float gravity; + float water_height; + float water_bottom_height; + std::list authors; + std::list tobj_files; + std::list as_files; + std::list telepoints; + std::string caelum_config; + int caelum_fog_start; + int caelum_fog_end; + std::string cubemap_config; + bool has_water; + std::string hydrax_conf_file; + std::string skyx_config; + std::string traction_map_file; + std::string custom_material_name; + std::string teleport_map_image; + }; + + class Terrn2Parser + { + public: + bool LoadTerrn2(Terrn2Def &def, Ogre::DataStreamPtr &ds); + std::list const &GetMessages() const + { + return m_messages; + } + + private: + void ProcessTeleport(Terrn2Def &def, RoR::ConfigFile *file); + void AddMessage(const char *msg) + { + m_messages.push_back(msg); + } + std::list m_messages; + }; } // namespace RoR diff --git a/source/main/scripting/GameScript.cpp b/source/main/scripting/GameScript.cpp index 2805c1fce3..c58d00b447 100644 --- a/source/main/scripting/GameScript.cpp +++ b/source/main/scripting/GameScript.cpp @@ -22,9 +22,9 @@ #include "GameScript.h" #ifdef USE_CURL -# include -# include -#endif //USE_CURL + #include + #include +#endif // USE_CURL #include "OgreSubsystem.h" @@ -43,8 +43,8 @@ #include "Character.h" #include "ChatSystem.h" #include "Collisions.h" -#include "GUI_GameConsole.h" #include "GUIManager.h" +#include "GUI_GameConsole.h" #include "Language.h" #include "MainMenu.h" #include "Network.h" @@ -67,8 +67,7 @@ using namespace RoR; // --> Getter functions should silently return zero/empty value. // --> Functions performing simulation changes should log warning and do nothing. -GameScript::GameScript(ScriptEngine* se) : - mse(se) +GameScript::GameScript(ScriptEngine *se) : mse(se) { } @@ -76,20 +75,20 @@ GameScript::~GameScript() { } -void GameScript::log(const String& msg) +void GameScript::log(const String &msg) { ScriptEngine::getSingleton().SLOG(msg); } -void GameScript::logFormat(const char* format, ...) +void GameScript::logFormat(const char *format, ...) { char buffer[4000] = {}; sprintf(buffer, "[RoR|Script] "); // Length: 13 characters - char* buffer_pos = buffer + 13; + char *buffer_pos = buffer + 13; va_list args; va_start(args, format); - vsprintf(buffer_pos, format, args); + vsprintf(buffer_pos, format, args); va_end(args); ScriptEngine::getSingleton().SLOG(buffer); @@ -97,16 +96,14 @@ void GameScript::logFormat(const char* format, ...) void GameScript::activateAllVehicles() { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->GetBeamFactory()->WakeUpAllActors(); } void GameScript::SetTrucksForcedAwake(bool forceActive) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->GetBeamFactory()->SetTrucksForcedAwake(forceActive); } @@ -114,23 +111,20 @@ void GameScript::SetTrucksForcedAwake(bool forceActive) float GameScript::getTime() { float result = 0.f; - if (App::GetSimController()) - result = App::GetSimController()->getTime(); + if (App::GetSimController()) result = App::GetSimController()->getTime(); return result; } -void GameScript::setPersonPosition(const Vector3& vec) +void GameScript::setPersonPosition(const Vector3 &vec) { - if (!this->HavePlayerAvatar(__FUNCTION__)) - return; + if (!this->HavePlayerAvatar(__FUNCTION__)) return; gEnv->player->setPosition(vec); } -void GameScript::loadTerrain(const String& terrain) +void GameScript::loadTerrain(const String &terrain) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::sim_terrain_name.SetPending(terrain.c_str()); App::GetSimController()->LoadTerrain(); @@ -139,23 +133,20 @@ void GameScript::loadTerrain(const String& terrain) Vector3 GameScript::getPersonPosition() { Vector3 result(Vector3::ZERO); - if (gEnv->player) - result = gEnv->player->getPosition(); + if (gEnv->player) result = gEnv->player->getPosition(); return result; } -void GameScript::movePerson(const Vector3& vec) +void GameScript::movePerson(const Vector3 &vec) { - if (!this->HavePlayerAvatar(__FUNCTION__)) - return; + if (!this->HavePlayerAvatar(__FUNCTION__)) return; gEnv->player->move(vec); } -void GameScript::setPersonRotation(const Radian& rot) +void GameScript::setPersonRotation(const Radian &rot) { - if (!this->HavePlayerAvatar(__FUNCTION__)) - return; + if (!this->HavePlayerAvatar(__FUNCTION__)) return; gEnv->player->setRotation(rot); } @@ -163,8 +154,7 @@ void GameScript::setPersonRotation(const Radian& rot) Radian GameScript::getPersonRotation() { Radian result(0); - if (gEnv->player) - result = gEnv->player->getRotation(); + if (gEnv->player) result = gEnv->player->getRotation(); return result; } @@ -172,10 +162,7 @@ String GameScript::getCaelumTime() { String result = ""; #ifdef USE_CAELUM - if (App::GetSimTerrain()) - { - result = App::GetSimTerrain()->getSkyManager()->GetPrettyTime(); - } + if (App::GetSimTerrain()) { result = App::GetSimTerrain()->getSkyManager()->GetPrettyTime(); } #endif // USE_CAELUM return result; } @@ -183,8 +170,7 @@ String GameScript::getCaelumTime() void GameScript::setCaelumTime(float value) { #ifdef USE_CAELUM - if (!this->HaveSimTerrain(__FUNCTION__)) - return; + if (!this->HaveSimTerrain(__FUNCTION__)) return; App::GetSimTerrain()->getSkyManager()->SetSkyTimeFactor(value); #endif // USE_CAELUM @@ -194,63 +180,56 @@ bool GameScript::getCaelumAvailable() { bool result = false; #ifdef USE_CAELUM - if (App::GetSimTerrain()) - result = App::GetSimTerrain()->getSkyManager() != 0; + if (App::GetSimTerrain()) result = App::GetSimTerrain()->getSkyManager() != 0; #endif // USE_CAELUM return result; } void GameScript::stopTimer() { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->StopRaceTimer(); } void GameScript::startTimer(int id) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->StartRaceTimer(id); } void GameScript::setTimeDiff(float diff) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->SetRaceTimeDiff(diff); } void GameScript::setBestLapTime(float time) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->SetRaceBestTime(time); } void GameScript::setWaterHeight(float value) { - if (!this->HaveSimTerrain(__FUNCTION__)) - return; + if (!this->HaveSimTerrain(__FUNCTION__)) return; if (App::GetSimTerrain()->getWater()) { - IWater* water = App::GetSimTerrain()->getWater(); + IWater *water = App::GetSimTerrain()->getWater(); water->WaterSetCamera(gEnv->mainCamera); water->SetStaticWaterHeight(value); water->UpdateWater(); } } -float GameScript::getGroundHeight(Vector3& v) +float GameScript::getGroundHeight(Vector3 &v) { float result = -1.0f; - if (App::GetSimTerrain()) - result = App::GetSimTerrain()->GetHeightAt(v.x, v.z); + if (App::GetSimTerrain()) result = App::GetSimTerrain()->GetHeightAt(v.x, v.z); return result; } @@ -262,91 +241,79 @@ float GameScript::getWaterHeight() return result; } -Actor* GameScript::getCurrentTruck() +Actor *GameScript::getCurrentTruck() { - Actor* result = nullptr; - if (App::GetSimController()) - result = App::GetSimController()->GetPlayerActor(); + Actor *result = nullptr; + if (App::GetSimController()) result = App::GetSimController()->GetPlayerActor(); return result; } float GameScript::getGravity() { float result = 0.f; - if (App::GetSimTerrain()) - { - result = App::GetSimTerrain()->getGravity(); - } + if (App::GetSimTerrain()) { result = App::GetSimTerrain()->getGravity(); } return result; } void GameScript::setGravity(float value) { - if (!this->HaveSimTerrain(__FUNCTION__)) - return; + if (!this->HaveSimTerrain(__FUNCTION__)) return; App::GetSimTerrain()->setGravity(value); } -Actor* GameScript::getTruckByNum(int num) +Actor *GameScript::getTruckByNum(int num) { // TODO: Do we have to add a 'GetActorByIndex' method to keep this backwards compatible? - Actor* result = nullptr; - if (App::GetSimController()) - result = App::GetSimController()->GetActorById(num); + Actor *result = nullptr; + if (App::GetSimController()) result = App::GetSimController()->GetActorById(num); return result; } int GameScript::getNumTrucks() { int result = 0; - if (App::GetSimController()) - result = static_cast(App::GetSimController()->GetBeamFactory()->GetActors().size()); + if (App::GetSimController()) result = static_cast(App::GetSimController()->GetBeamFactory()->GetActors().size()); return result; } int GameScript::getNumTrucksByFlag(int flag) { - if (App::GetSimController() == nullptr) - return 0; + if (App::GetSimController() == nullptr) return 0; int result = 0; for (auto actor : App::GetSimController()->GetActors()) { - if (!flag || static_cast(actor->ar_sim_state) == flag) - result++; + if (!flag || static_cast(actor->ar_sim_state) == flag) result++; } return result; } int GameScript::GetPlayerActorId() { - if (App::GetSimController() == nullptr) - return -1; + if (App::GetSimController() == nullptr) return -1; - Actor* actor = App::GetSimController()->GetPlayerActor(); + Actor *actor = App::GetSimController()->GetPlayerActor(); return (actor != nullptr) ? actor->ar_instance_id : -1; } void GameScript::registerForEvent(int eventValue) { - if (mse) - mse->eventMask += eventValue; + if (mse) mse->eventMask += eventValue; } -void GameScript::flashMessage(String& txt, float time, float charHeight) +void GameScript::flashMessage(String &txt, float time, float charHeight) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_SCRIPT, Console::CONSOLE_SYSTEM_NOTICE, txt, "script_code_red.png"); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_SCRIPT, Console::CONSOLE_SYSTEM_NOTICE, txt, + "script_code_red.png"); RoR::App::GetGuiManager()->PushNotification("Script:", txt); } -void GameScript::message(String& txt, String& icon, float timeMilliseconds, bool forceVisible) +void GameScript::message(String &txt, String &icon, float timeMilliseconds, bool forceVisible) { - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_SCRIPT, Console::CONSOLE_SYSTEM_NOTICE, txt, icon, timeMilliseconds, forceVisible); - if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) - { - RoR::App::GetGuiManager()->pushMessageChatBox(txt); - } + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_SCRIPT, Console::CONSOLE_SYSTEM_NOTICE, txt, icon, + timeMilliseconds, forceVisible); + if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { RoR::App::GetGuiManager()->pushMessageChatBox(txt); } else { // TODO: Find a better solution for this @@ -354,103 +321,77 @@ void GameScript::message(String& txt, String& icon, float timeMilliseconds, bool } } -void GameScript::UpdateDirectionArrow(String& text, Vector3& vec) +void GameScript::UpdateDirectionArrow(String &text, Vector3 &vec) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; - App::GetSimController()->UpdateDirectionArrow(const_cast(text.c_str()), Vector3(vec.x, vec.y, vec.z)); + App::GetSimController()->UpdateDirectionArrow(const_cast(text.c_str()), Vector3(vec.x, vec.y, vec.z)); } int GameScript::getChatFontSize() { - return 0; //NETCHAT.getFontSize(); + return 0; // NETCHAT.getFontSize(); } void GameScript::setChatFontSize(int size) { - //NETCHAT.setFontSize(size); + // NETCHAT.setFontSize(size); } -void GameScript::showChooser(const String& type, const String& instance, const String& box) +void GameScript::showChooser(const String &type, const String &instance, const String &box) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; LoaderType ntype = LT_None; - if (type == "airplane") - ntype = LT_Airplane; - if (type == "all") - ntype = LT_AllBeam; - if (type == "boat") - ntype = LT_Boat; - if (type == "car") - ntype = LT_Car; - if (type == "extension") - ntype = LT_Extension; - if (type == "heli") - ntype = LT_Heli; - if (type == "load") - ntype = LT_Load; - if (type == "trailer") - ntype = LT_Trailer; - if (type == "train") - ntype = LT_Train; - if (type == "truck") - ntype = LT_Truck; - if (type == "vehicle") - ntype = LT_Vehicle; - - if (ntype != LT_None) - { - App::GetSimController()->ShowLoaderGUI(ntype, instance, box); - } + if (type == "airplane") ntype = LT_Airplane; + if (type == "all") ntype = LT_AllBeam; + if (type == "boat") ntype = LT_Boat; + if (type == "car") ntype = LT_Car; + if (type == "extension") ntype = LT_Extension; + if (type == "heli") ntype = LT_Heli; + if (type == "load") ntype = LT_Load; + if (type == "trailer") ntype = LT_Trailer; + if (type == "train") ntype = LT_Train; + if (type == "truck") ntype = LT_Truck; + if (type == "vehicle") ntype = LT_Vehicle; + if (ntype != LT_None) { App::GetSimController()->ShowLoaderGUI(ntype, instance, box); } } -void GameScript::repairVehicle(const String& instance, const String& box, bool keepPosition) +void GameScript::repairVehicle(const String &instance, const String &box, bool keepPosition) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->GetBeamFactory()->RepairActor(gEnv->collisions, instance, box, keepPosition); } -void GameScript::removeVehicle(const String& event_source_instance_name, const String& event_source_box_name) +void GameScript::removeVehicle(const String &event_source_instance_name, const String &event_source_box_name) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->RemoveActorByCollisionBox(event_source_instance_name, event_source_box_name); } -void GameScript::destroyObject(const String& instanceName) +void GameScript::destroyObject(const String &instanceName) { - if (!this->HaveSimTerrain(__FUNCTION__)) - return; + if (!this->HaveSimTerrain(__FUNCTION__)) return; - if (App::GetSimTerrain()->getObjectManager()) - { - App::GetSimTerrain()->getObjectManager()->unloadObject(instanceName); - } + if (App::GetSimTerrain()->getObjectManager()) { App::GetSimTerrain()->getObjectManager()->unloadObject(instanceName); } } -void GameScript::MoveTerrainObjectVisuals(const String& instanceName, const Vector3& pos) +void GameScript::MoveTerrainObjectVisuals(const String &instanceName, const Vector3 &pos) { - if (!this->HaveSimTerrain(__FUNCTION__)) - return; + if (!this->HaveSimTerrain(__FUNCTION__)) return; if (App::GetSimTerrain()->getObjectManager()) - { - App::GetSimTerrain()->getObjectManager()->MoveObjectVisuals(instanceName, pos); - } + { App::GetSimTerrain()->getObjectManager()->MoveObjectVisuals(instanceName, pos); } } -void GameScript::spawnObject(const String& objectName, const String& instanceName, const Vector3& pos, const Vector3& rot, const String& eventhandler, bool uniquifyMaterials) +void GameScript::spawnObject(const String &objectName, const String &instanceName, const Vector3 &pos, const Vector3 &rot, + const String &eventhandler, bool uniquifyMaterials) { - if (!this->HaveSimTerrain(__FUNCTION__)) - return; + if (!this->HaveSimTerrain(__FUNCTION__)) return; if ((App::GetSimTerrain()->getObjectManager() == nullptr)) { @@ -460,7 +401,7 @@ void GameScript::spawnObject(const String& objectName, const String& instanceNam try { - AngelScript::asIScriptModule* module = mse->getEngine()->GetModule(mse->moduleName, AngelScript::asGM_ONLY_IF_EXISTS); + AngelScript::asIScriptModule *module = mse->getEngine()->GetModule(mse->moduleName, AngelScript::asGM_ONLY_IF_EXISTS); if (module == nullptr) { this->logFormat("spawnObject(): Failed to fetch/create script module '%s'", mse->moduleName); @@ -470,23 +411,21 @@ void GameScript::spawnObject(const String& objectName, const String& instanceNam int handler_func_id = -1; // no function if (!eventhandler.empty()) { - AngelScript::asIScriptFunction* handler_func = module->GetFunctionByName(eventhandler.c_str()); - if (handler_func != nullptr) - { - handler_func_id = handler_func->GetId(); - } + AngelScript::asIScriptFunction *handler_func = module->GetFunctionByName(eventhandler.c_str()); + if (handler_func != nullptr) { handler_func_id = handler_func->GetId(); } else { this->logFormat("spawnObject(): Warning; Failed to find handler function '%s' in script module '%s'", - eventhandler.c_str(), mse->moduleName); + eventhandler.c_str(), mse->moduleName); } } - SceneNode* bakeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - const String type = ""; - App::GetSimTerrain()->getObjectManager()->LoadTerrainObject(objectName, pos, rot, bakeNode, instanceName, type, true, handler_func_id, uniquifyMaterials); + SceneNode * bakeNode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + const String type = ""; + App::GetSimTerrain()->getObjectManager()->LoadTerrainObject(objectName, pos, rot, bakeNode, instanceName, type, true, + handler_func_id, uniquifyMaterials); } - catch (std::exception& e) + catch (std::exception &e) { this->logFormat("spawnObject(): An exception occurred, message: %s", e.what()); return; @@ -495,22 +434,20 @@ void GameScript::spawnObject(const String& objectName, const String& instanceNam void GameScript::hideDirectionArrow() { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; App::GetSimController()->UpdateDirectionArrow(0, Vector3::ZERO); } -int GameScript::setMaterialAmbient(const String& materialName, float red, float green, float blue) +int GameScript::setMaterialAmbient(const String &materialName, float red, float green, float blue) { try { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName); - if (m.isNull()) - return 0; + if (m.isNull()) return 0; m->setAmbient(red, green, blue); } - catch (Exception& e) + catch (Exception &e) { this->log("Exception in setMaterialAmbient(): " + e.getFullDescription()); return 0; @@ -518,16 +455,15 @@ int GameScript::setMaterialAmbient(const String& materialName, float red, float return 1; } -int GameScript::setMaterialDiffuse(const String& materialName, float red, float green, float blue, float alpha) +int GameScript::setMaterialDiffuse(const String &materialName, float red, float green, float blue, float alpha) { try { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName); - if (m.isNull()) - return 0; + if (m.isNull()) return 0; m->setDiffuse(red, green, blue, alpha); } - catch (Exception& e) + catch (Exception &e) { this->log("Exception in setMaterialDiffuse(): " + e.getFullDescription()); return 0; @@ -535,16 +471,15 @@ int GameScript::setMaterialDiffuse(const String& materialName, float red, float return 1; } -int GameScript::setMaterialSpecular(const String& materialName, float red, float green, float blue, float alpha) +int GameScript::setMaterialSpecular(const String &materialName, float red, float green, float blue, float alpha) { try { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName); - if (m.isNull()) - return 0; + if (m.isNull()) return 0; m->setSpecular(red, green, blue, alpha); } - catch (Exception& e) + catch (Exception &e) { this->log("Exception in setMaterialSpecular(): " + e.getFullDescription()); return 0; @@ -552,16 +487,15 @@ int GameScript::setMaterialSpecular(const String& materialName, float red, float return 1; } -int GameScript::setMaterialEmissive(const String& materialName, float red, float green, float blue) +int GameScript::setMaterialEmissive(const String &materialName, float red, float green, float blue) { try { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName); - if (m.isNull()) - return 0; + if (m.isNull()) return 0; m->setSelfIllumination(red, green, blue); } - catch (Exception& e) + catch (Exception &e) { this->log("Exception in setMaterialEmissive(): " + e.getFullDescription()); return 0; @@ -569,49 +503,44 @@ int GameScript::setMaterialEmissive(const String& materialName, float red, float return 1; } -int GameScript::getSafeTextureUnitState(TextureUnitState** tu, const String materialName, int techniqueNum, int passNum, int textureUnitNum) +int GameScript::getSafeTextureUnitState(TextureUnitState **tu, const String materialName, int techniqueNum, int passNum, + int textureUnitNum) { try { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName); - if (m.isNull()) - return 1; + if (m.isNull()) return 1; // verify technique - if (techniqueNum < 0 || techniqueNum > m->getNumTechniques()) - return 2; - Technique* t = m->getTechnique(techniqueNum); - if (!t) - return 2; - - //verify pass - if (passNum < 0 || passNum > t->getNumPasses()) - return 3; - Pass* p = t->getPass(passNum); - if (!p) - return 3; - - //verify texture unit - if (textureUnitNum < 0 || textureUnitNum > p->getNumTextureUnitStates()) - return 4; - TextureUnitState* tut = p->getTextureUnitState(textureUnitNum); - if (!tut) - return 4; + if (techniqueNum < 0 || techniqueNum > m->getNumTechniques()) return 2; + Technique *t = m->getTechnique(techniqueNum); + if (!t) return 2; + + // verify pass + if (passNum < 0 || passNum > t->getNumPasses()) return 3; + Pass *p = t->getPass(passNum); + if (!p) return 3; + + // verify texture unit + if (textureUnitNum < 0 || textureUnitNum > p->getNumTextureUnitStates()) return 4; + TextureUnitState *tut = p->getTextureUnitState(textureUnitNum); + if (!tut) return 4; *tu = tut; return 0; } - catch (Exception& e) + catch (Exception &e) { this->log("Exception in getSafeTextureUnitState(): " + e.getFullDescription()); } return 1; } -int GameScript::setMaterialTextureName(const String& materialName, int techniqueNum, int passNum, int textureUnitNum, const String& textureName) +int GameScript::setMaterialTextureName(const String &materialName, int techniqueNum, int passNum, int textureUnitNum, + const String &textureName) { - TextureUnitState* tu = 0; - int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); + TextureUnitState *tu = 0; + int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); if (res == 0 && tu != 0) { // finally, set it @@ -620,36 +549,30 @@ int GameScript::setMaterialTextureName(const String& materialName, int technique return res; } -int GameScript::setMaterialTextureRotate(const String& materialName, int techniqueNum, int passNum, int textureUnitNum, float rotation) +int GameScript::setMaterialTextureRotate(const String &materialName, int techniqueNum, int passNum, int textureUnitNum, + float rotation) { - TextureUnitState* tu = 0; - int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); - if (res == 0 && tu != 0) - { - tu->setTextureRotate(Degree(rotation)); - } + TextureUnitState *tu = 0; + int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); + if (res == 0 && tu != 0) { tu->setTextureRotate(Degree(rotation)); } return res; } -int GameScript::setMaterialTextureScroll(const String& materialName, int techniqueNum, int passNum, int textureUnitNum, float sx, float sy) +int GameScript::setMaterialTextureScroll(const String &materialName, int techniqueNum, int passNum, int textureUnitNum, float sx, + float sy) { - TextureUnitState* tu = 0; - int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); - if (res == 0 && tu != 0) - { - tu->setTextureScroll(sx, sy); - } + TextureUnitState *tu = 0; + int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); + if (res == 0 && tu != 0) { tu->setTextureScroll(sx, sy); } return res; } -int GameScript::setMaterialTextureScale(const String& materialName, int techniqueNum, int passNum, int textureUnitNum, float u, float v) +int GameScript::setMaterialTextureScale(const String &materialName, int techniqueNum, int passNum, int textureUnitNum, float u, + float v) { - TextureUnitState* tu = 0; - int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); - if (res == 0 && tu != 0) - { - tu->setTextureScale(u, v); - } + TextureUnitState *tu = 0; + int res = getSafeTextureUnitState(&tu, materialName, techniqueNum, passNum, textureUnitNum); + if (res == 0 && tu != 0) { tu->setTextureScale(u, v); } return res; } @@ -658,14 +581,14 @@ float GameScript::rangeRandom(float from, float to) return Math::RangeRandom(from, to); } -int GameScript::getLoadedTerrain(String& result) +int GameScript::getLoadedTerrain(String &result) { String terrainName = ""; if (App::GetSimTerrain()) { terrainName = App::GetSimTerrain()->getTerrainName(); - result = terrainName; + result = terrainName; } return !terrainName.empty(); @@ -682,50 +605,44 @@ void GameScript::clearEventCache() gEnv->collisions->clearEventCache(); } -void GameScript::setCameraPosition(const Vector3& pos) +void GameScript::setCameraPosition(const Vector3 &pos) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->setPosition(Vector3(pos.x, pos.y, pos.z)); } -void GameScript::setCameraDirection(const Vector3& rot) +void GameScript::setCameraDirection(const Vector3 &rot) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->setDirection(Vector3(rot.x, rot.y, rot.z)); } -void GameScript::setCameraOrientation(const Quaternion& q) +void GameScript::setCameraOrientation(const Quaternion &q) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->setOrientation(Quaternion(q.w, q.x, q.y, q.z)); } void GameScript::setCameraYaw(float rotX) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->yaw(Degree(rotX)); } void GameScript::setCameraPitch(float rotY) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->pitch(Degree(rotY)); } void GameScript::setCameraRoll(float rotZ) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->roll(Degree(rotZ)); } @@ -733,52 +650,45 @@ void GameScript::setCameraRoll(float rotZ) Vector3 GameScript::getCameraPosition() { Vector3 result(Vector3::ZERO); - if (gEnv->mainCamera) - result = gEnv->mainCamera->getPosition(); + if (gEnv->mainCamera) result = gEnv->mainCamera->getPosition(); return result; } Vector3 GameScript::getCameraDirection() { Vector3 result(Vector3::ZERO); - if (gEnv->mainCamera) - result = gEnv->mainCamera->getDirection(); + if (gEnv->mainCamera) result = gEnv->mainCamera->getDirection(); return result; } Quaternion GameScript::getCameraOrientation() { Quaternion result(Quaternion::ZERO); - if (gEnv->mainCamera) - result = gEnv->mainCamera->getOrientation(); + if (gEnv->mainCamera) result = gEnv->mainCamera->getOrientation(); return result; } -void GameScript::cameraLookAt(const Vector3& pos) +void GameScript::cameraLookAt(const Vector3 &pos) { - if (!this->HaveMainCamera(__FUNCTION__)) - return; + if (!this->HaveMainCamera(__FUNCTION__)) return; gEnv->mainCamera->lookAt(Vector3(pos.x, pos.y, pos.z)); } -int GameScript::useOnlineAPI(const String& apiquery, const AngelScript::CScriptDictionary& dict, String& result) +int GameScript::useOnlineAPI(const String &apiquery, const AngelScript::CScriptDictionary &dict, String &result) { - if (!this->HaveSimController(__FUNCTION__)) - return 1; + if (!this->HaveSimController(__FUNCTION__)) return 1; - if (App::app_disable_online_api.GetActive()) - return 0; + if (App::app_disable_online_api.GetActive()) return 0; - Actor* player_actor = App::GetSimController()->GetPlayerActor(); + Actor *player_actor = App::GetSimController()->GetPlayerActor(); - if (player_actor == nullptr) - return 1; + if (player_actor == nullptr) return 1; std::string hashtok = Utils::Sha1Hash(App::mp_player_name.GetActive()); - std::string url = App::mp_api_url.GetActive() + apiquery; - std::string user = std::string("RoR-Api-User: ") + App::mp_player_name.GetActive(); - std::string token = std::string("RoR-Api-User-Token: ") + hashtok; + std::string url = App::mp_api_url.GetActive() + apiquery; + std::string user = std::string("RoR-Api-User: ") + App::mp_player_name.GetActive(); + std::string token = std::string("RoR-Api-User-Token: ") + hashtok; std::string terrain_name = App::GetSimTerrain()->getTerrainName(); @@ -818,50 +728,48 @@ int GameScript::useOnlineAPI(const String& apiquery, const AngelScript::CScriptD for (auto item : dict) { - const std::string& key = item.GetKey(); - const std::string* value = (std::string *)item.GetAddressOfValue(); + const std::string &key = item.GetKey(); + const std::string *value = (std::string *)item.GetAddressOfValue(); j_doc.AddMember(rapidjson::StringRef(key.c_str()), rapidjson::StringRef(value->c_str()), j_doc.GetAllocator()); } - rapidjson::StringBuffer buffer; + rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); j_doc.Accept(writer); std::string json = buffer.GetString(); - RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, - _L("using Online API..."), "information.png", 2000); + RoR::App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("using Online API..."), + "information.png", 2000); LOG("[RoR|GameScript] Submitting race results to '" + url + "'"); - std::thread([url, user, token, json]() - { - struct curl_slist *slist = NULL; - slist = curl_slist_append(slist, "Accept: application/json"); - slist = curl_slist_append(slist, "Content-Type: application/json"); - slist = curl_slist_append(slist, user.c_str()); - slist = curl_slist_append(slist, token.c_str()); - - CURL *curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); - curl_easy_perform(curl); - - curl_easy_cleanup(curl); - curl = nullptr; - curl_slist_free_all(slist); - slist = NULL; - }).detach(); + std::thread([url, user, token, json]() { + struct curl_slist *slist = NULL; + slist = curl_slist_append(slist, "Accept: application/json"); + slist = curl_slist_append(slist, "Content-Type: application/json"); + slist = curl_slist_append(slist, user.c_str()); + slist = curl_slist_append(slist, token.c_str()); + + CURL *curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); + curl_easy_perform(curl); + + curl_easy_cleanup(curl); + curl = nullptr; + curl_slist_free_all(slist); + slist = NULL; + }).detach(); return 0; } void GameScript::boostCurrentTruck(float factor) { - if (!this->HaveSimController(__FUNCTION__)) - return; + if (!this->HaveSimController(__FUNCTION__)) return; - Actor* actor = App::GetSimController()->GetPlayerActor(); + Actor *actor = App::GetSimController()->GetPlayerActor(); if (actor && actor->ar_engine) { float rpm = actor->ar_engine->GetEngineRpm(); @@ -870,37 +778,37 @@ void GameScript::boostCurrentTruck(float factor) } } -int GameScript::addScriptFunction(const String& arg) +int GameScript::addScriptFunction(const String &arg) { return mse->addFunction(arg); } -int GameScript::scriptFunctionExists(const String& arg) +int GameScript::scriptFunctionExists(const String &arg) { return mse->functionExists(arg); } -int GameScript::deleteScriptFunction(const String& arg) +int GameScript::deleteScriptFunction(const String &arg) { return mse->deleteFunction(arg); } -int GameScript::addScriptVariable(const String& arg) +int GameScript::addScriptVariable(const String &arg) { return mse->addVariable(arg); } -int GameScript::deleteScriptVariable(const String& arg) +int GameScript::deleteScriptVariable(const String &arg) { return mse->deleteVariable(arg); } -int GameScript::sendGameCmd(const String& message) +int GameScript::sendGameCmd(const String &message) { #ifdef USE_SOCKETW if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { - RoR::Networking::AddPacket(0, RoRnet::MSG2_GAME_CMD, (int)message.size(), const_cast(message.c_str())); + RoR::Networking::AddPacket(0, RoRnet::MSG2_GAME_CMD, (int)message.size(), const_cast(message.c_str())); return 0; } #endif // USE_SOCKETW @@ -908,56 +816,49 @@ int GameScript::sendGameCmd(const String& message) return -11; } -VehicleAI* GameScript::getCurrentTruckAI() +VehicleAI *GameScript::getCurrentTruckAI() { - VehicleAI* result = nullptr; + VehicleAI *result = nullptr; if (App::GetSimController()) { - Actor* actor = App::GetSimController()->GetPlayerActor(); - if (actor != nullptr) - result = actor->ar_vehicle_ai; + Actor *actor = App::GetSimController()->GetPlayerActor(); + if (actor != nullptr) result = actor->ar_vehicle_ai; } return result; } -VehicleAI* GameScript::getTruckAIByNum(int num) +VehicleAI *GameScript::getTruckAIByNum(int num) { - VehicleAI* result = nullptr; + VehicleAI *result = nullptr; if (App::GetSimController()) { - Actor* actor = App::GetSimController()->GetActorById(num); - if (actor != nullptr) - result = actor->ar_vehicle_ai; + Actor *actor = App::GetSimController()->GetActorById(num); + if (actor != nullptr) result = actor->ar_vehicle_ai; } return result; } -Actor* GameScript::spawnTruck(Ogre::String& truckName, Ogre::Vector3& pos, Ogre::Vector3& rot) +Actor *GameScript::spawnTruck(Ogre::String &truckName, Ogre::Vector3 &pos, Ogre::Vector3 &rot) { - if (!this->HaveSimController(__FUNCTION__)) - return nullptr; + if (!this->HaveSimController(__FUNCTION__)) return nullptr; ActorSpawnRequest rq; rq.asr_position = pos; - rq.asr_rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); + rq.asr_rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z); rq.asr_filename = truckName; return App::GetSimController()->SpawnActorDirectly(rq); } -void GameScript::showMessageBox(Ogre::String& title, Ogre::String& text, bool use_btn1, Ogre::String& btn1_text, bool allow_close, bool use_btn2, Ogre::String& btn2_text) +void GameScript::showMessageBox(Ogre::String &title, Ogre::String &text, bool use_btn1, Ogre::String &btn1_text, bool allow_close, + bool use_btn2, Ogre::String &btn2_text) { // Sanitize inputs - const char* btn1_cstr = nullptr; // = Button disabled - const char* btn2_cstr = nullptr; + const char *btn1_cstr = nullptr; // = Button disabled + const char *btn2_cstr = nullptr; - if (use_btn1) - { - btn1_cstr = (btn1_text.empty() ? "~1~" : btn1_text.c_str()); - } - if (use_btn2) - { - btn2_cstr = (btn2_text.empty() ? "~2~" : btn2_text.c_str()); - } + if (use_btn1) { btn1_cstr = (btn1_text.empty() ? "~1~" : btn1_text.c_str()); } + if (use_btn2) { btn2_cstr = (btn2_text.empty() ? "~2~" : btn2_text.c_str()); } RoR::App::GetGuiManager()->ShowMessageBox(title.c_str(), text.c_str(), allow_close, btn1_cstr, btn2_cstr); } @@ -982,7 +883,7 @@ float GameScript::getAvgFPS() return App::GetOgreSubsystem()->GetRenderWindow()->getStatistics().avgFPS; } -bool GameScript::HaveSimController(const char* func_name) +bool GameScript::HaveSimController(const char *func_name) { if (App::GetSimController() == nullptr) { @@ -992,7 +893,7 @@ bool GameScript::HaveSimController(const char* func_name) return true; } -bool GameScript::HaveSimTerrain(const char* func_name) +bool GameScript::HaveSimTerrain(const char *func_name) { if (App::GetSimTerrain() == nullptr) { @@ -1002,7 +903,7 @@ bool GameScript::HaveSimTerrain(const char* func_name) return true; } -bool GameScript::HavePlayerAvatar(const char* func_name) +bool GameScript::HavePlayerAvatar(const char *func_name) { if (gEnv->player == nullptr) { @@ -1012,7 +913,7 @@ bool GameScript::HavePlayerAvatar(const char* func_name) return true; } -bool GameScript::HaveMainCamera(const char* func_name) +bool GameScript::HaveMainCamera(const char *func_name) { if (gEnv->mainCamera == nullptr) { diff --git a/source/main/scripting/GameScript.h b/source/main/scripting/GameScript.h index 84243d119a..ab496c73da 100644 --- a/source/main/scripting/GameScript.h +++ b/source/main/scripting/GameScript.h @@ -26,14 +26,13 @@ #pragma once #include "RoRPrerequisites.h" - #include "ScriptEngine.h" #include struct curlMemoryStruct { - char* memory; + char * memory; size_t size; }; @@ -42,12 +41,12 @@ struct curlMemoryStruct */ class GameScript : public ZeroedMemoryAllocator { -public: + public: /** * constructor * @param se pointer to the ScriptEngine instance */ - GameScript(ScriptEngine* se); + GameScript(ScriptEngine *se); /** * destructor @@ -58,13 +57,13 @@ class GameScript : public ZeroedMemoryAllocator * writes a message to the games log (RoR.log) * @param msg string to log */ - void log(const Ogre::String& msg); + void log(const Ogre::String &msg); /** * writes a message to the games log (RoR.log) * @param msg string to log */ - void logFormat(const char* fmt, ...); + void logFormat(const char *fmt, ...); /** * moves the person relative @@ -84,27 +83,27 @@ class GameScript : public ZeroedMemoryAllocator */ float getTime(); - //anglescript test + // anglescript test void boostCurrentTruck(float factor); /** * sets the character position * @param vec position vector on the terrain */ - void setPersonPosition(const Ogre::Vector3& vec); + void setPersonPosition(const Ogre::Vector3 &vec); - void loadTerrain(const Ogre::String& terrain); + void loadTerrain(const Ogre::String &terrain); /** * moves the person relative * @param vec translation vector */ - void movePerson(const Ogre::Vector3& vec); + void movePerson(const Ogre::Vector3 &vec); /** * sets the character rotation * @param rot the character rotation */ - void setPersonRotation(const Ogre::Radian& rot); + void setPersonRotation(const Ogre::Radian &rot); /** * gets the character rotation @@ -130,7 +129,7 @@ class GameScript : public ZeroedMemoryAllocator */ float getWaterHeight(); - float getGroundHeight(Ogre::Vector3& v); + float getGroundHeight(Ogre::Vector3 &v); /** * sets the base water height @@ -142,13 +141,13 @@ class GameScript : public ZeroedMemoryAllocator * returns the current selected truck, 0 if in person mode * @return reference to Beam object that is currently in use */ - Actor* getCurrentTruck(); + Actor *getCurrentTruck(); /** * returns a truck by index, get max index by calling getNumTrucks * @return reference to Beam object that the selected slot */ - Actor* getTruckByNum(int num); + Actor *getTruckByNum(int num); /** * returns the current amount of loaded trucks @@ -184,18 +183,18 @@ class GameScript : public ZeroedMemoryAllocator * DEPRECATED: use message * shows a message to the user */ - void flashMessage(Ogre::String& txt, float time, float charHeight); + void flashMessage(Ogre::String &txt, float time, float charHeight); /** * shows a message to the user over the console system */ - void message(Ogre::String& txt, Ogre::String& icon, float timeMilliseconds, bool forceVisible); + void message(Ogre::String &txt, Ogre::String &icon, float timeMilliseconds, bool forceVisible); /** * set direction arrow * @param text text to be displayed. "" to hide the text */ - void UpdateDirectionArrow(Ogre::String& text, Ogre::Vector3& vec); + void UpdateDirectionArrow(Ogre::String &text, Ogre::Vector3 &vec); /** * returns the size of the font used by the chat box @@ -213,19 +212,19 @@ class GameScript : public ZeroedMemoryAllocator * Sets the camera's position. * @param pos The new position of the camera. */ - void setCameraPosition(const Ogre::Vector3& pos); + void setCameraPosition(const Ogre::Vector3 &pos); /** * Sets the camera's direction vector. * @param vec A vector representing the direction of the vector. */ - void setCameraDirection(const Ogre::Vector3& vec); + void setCameraDirection(const Ogre::Vector3 &vec); /** * Sets the camera's orientation. * @param vec A vector representing the direction of the vector. */ - void setCameraOrientation(const Ogre::Quaternion& q); + void setCameraOrientation(const Ogre::Quaternion &q); /** * Rolls the camera anticlockwise, around its local z axis. @@ -246,8 +245,8 @@ class GameScript : public ZeroedMemoryAllocator void setCameraPitch(float angle); /** - * Retrieves the camera's position. - * @return The current position of the camera + * Retrieves the camera's position. + * @return The current position of the camera */ Ogre::Vector3 getCameraPosition(); @@ -270,118 +269,125 @@ class GameScript : public ZeroedMemoryAllocator * direction vector for the camera, based on it's current position * and the supplied look-at point. * @param targetPoint A vector specifying the look at point. - */ - void cameraLookAt(const Ogre::Vector3& targetPoint); + */ + void cameraLookAt(const Ogre::Vector3 &targetPoint); /** * Adds a global function to the script * (Wrapper for ScriptEngine::addFunction) * @param arg A declaration for the function. - */ - int addScriptFunction(const Ogre::String& arg); + */ + int addScriptFunction(const Ogre::String &arg); /** * Checks if a global function exists in the script * (Wrapper for ScriptEngine::functionExists) * @param arg A declaration for the function. - */ - int scriptFunctionExists(const Ogre::String& arg); + */ + int scriptFunctionExists(const Ogre::String &arg); /** * Deletes a global function from the script * (Wrapper for ScriptEngine::deleteFunction) * @param arg A declaration for the function. - */ - int deleteScriptFunction(const Ogre::String& arg); + */ + int deleteScriptFunction(const Ogre::String &arg); /** * Adds a global variable to the script * (Wrapper for ScriptEngine::addVariable) * @param arg A declaration for the variable. - */ - int addScriptVariable(const Ogre::String& arg); + */ + int addScriptVariable(const Ogre::String &arg); /** * Deletes a global variable from the script * (Wrapper for ScriptEngine::deleteVariable) * @param arg A declaration for the variable. - */ - int deleteScriptVariable(const Ogre::String& arg); - - /** - * This spawns an object - * @param objectName The name of the object (~the name of the odef file, but without the .odef extension) - * @param instanceName A unique name for this object (you can choose one, but make sure that you don't use the same name twice) - * @param pos The position where the object should be spawned - * @param rot The rotation in which the object should be spawned - * @param eventhandler A name of a function that should be called when an event happens (events, as defined in the object definition file) - * @param uniquifyMaterials Set this to true if you need to uniquify the materials - */ - void spawnObject(const Ogre::String& objectName, const Ogre::String& instanceName, const Ogre::Vector3& pos, const Ogre::Vector3& rot, const Ogre::String& eventhandler, bool uniquifyMaterials); - /** - * This destroys an object - * @param instanceName The unique name that you chose when spawning this object - * @see spawnObject - */ - void destroyObject(const Ogre::String& instanceName); - /** - * This moves an object to a new position - * @note This doesn't update the collision box! - * @param instanceName The unique name that you chose when spawning this object - * @param pos The position where the object should be moved to - */ - void MoveTerrainObjectVisuals(const Ogre::String& instanceName, const Ogre::Vector3& pos); + */ + int deleteScriptVariable(const Ogre::String &arg); + + /** + * This spawns an object + * @param objectName The name of the object (~the name of the odef file, but without the .odef extension) + * @param instanceName A unique name for this object (you can choose one, but make sure that you don't use the same name + * twice) + * @param pos The position where the object should be spawned + * @param rot The rotation in which the object should be spawned + * @param eventhandler A name of a function that should be called when an event happens (events, as defined in the object + * definition file) + * @param uniquifyMaterials Set this to true if you need to uniquify the materials + */ + void spawnObject(const Ogre::String &objectName, const Ogre::String &instanceName, const Ogre::Vector3 &pos, + const Ogre::Vector3 &rot, const Ogre::String &eventhandler, bool uniquifyMaterials); + /** + * This destroys an object + * @param instanceName The unique name that you chose when spawning this object + * @see spawnObject + */ + void destroyObject(const Ogre::String &instanceName); + /** + * This moves an object to a new position + * @note This doesn't update the collision box! + * @param instanceName The unique name that you chose when spawning this object + * @param pos The position where the object should be moved to + */ + void MoveTerrainObjectVisuals(const Ogre::String &instanceName, const Ogre::Vector3 &pos); // new things, not documented yet - void showChooser(const Ogre::String& type, const Ogre::String& instance, const Ogre::String& box); - void repairVehicle(const Ogre::String& instance, const Ogre::String& box, bool keepPosition); - void removeVehicle(const Ogre::String& instance, const Ogre::String& box); - - int getNumTrucksByFlag(int flag); - bool getCaelumAvailable(); - void stopTimer(); - void startTimer(int id); - void setTimeDiff(float diff); - void setBestLapTime(float time); - Ogre::String getSetting(const Ogre::String& str); - void hideDirectionArrow(); - int setMaterialAmbient(const Ogre::String& materialName, float red, float green, float blue); - int setMaterialDiffuse(const Ogre::String& materialName, float red, float green, float blue, float alpha); - int setMaterialSpecular(const Ogre::String& materialName, float red, float green, float blue, float alpha); - int setMaterialEmissive(const Ogre::String& materialName, float red, float green, float blue); - int getSafeTextureUnitState(Ogre::TextureUnitState** tu, const Ogre::String materialName, int techniqueNum, int passNum, int textureUnitNum); - int setMaterialTextureName(const Ogre::String& materialName, int techniqueNum, int passNum, int textureUnitNum, const Ogre::String& textureName); - int setMaterialTextureRotate(const Ogre::String& materialName, int techniqueNum, int passNum, int textureUnitNum, float rotation); - int setMaterialTextureScroll(const Ogre::String& materialName, int techniqueNum, int passNum, int textureUnitNum, float sx, float sy); - int setMaterialTextureScale(const Ogre::String& materialName, int techniqueNum, int passNum, int textureUnitNum, float u, float v); + void showChooser(const Ogre::String &type, const Ogre::String &instance, const Ogre::String &box); + void repairVehicle(const Ogre::String &instance, const Ogre::String &box, bool keepPosition); + void removeVehicle(const Ogre::String &instance, const Ogre::String &box); + + int getNumTrucksByFlag(int flag); + bool getCaelumAvailable(); + void stopTimer(); + void startTimer(int id); + void setTimeDiff(float diff); + void setBestLapTime(float time); + Ogre::String getSetting(const Ogre::String &str); + void hideDirectionArrow(); + int setMaterialAmbient(const Ogre::String &materialName, float red, float green, float blue); + int setMaterialDiffuse(const Ogre::String &materialName, float red, float green, float blue, float alpha); + int setMaterialSpecular(const Ogre::String &materialName, float red, float green, float blue, float alpha); + int setMaterialEmissive(const Ogre::String &materialName, float red, float green, float blue); + int getSafeTextureUnitState(Ogre::TextureUnitState **tu, const Ogre::String materialName, int techniqueNum, int passNum, + int textureUnitNum); + int setMaterialTextureName(const Ogre::String &materialName, int techniqueNum, int passNum, int textureUnitNum, + const Ogre::String &textureName); + int setMaterialTextureRotate(const Ogre::String &materialName, int techniqueNum, int passNum, int textureUnitNum, + float rotation); + int setMaterialTextureScroll(const Ogre::String &materialName, int techniqueNum, int passNum, int textureUnitNum, float sx, + float sy); + int setMaterialTextureScale(const Ogre::String &materialName, int techniqueNum, int passNum, int textureUnitNum, float u, + float v); float rangeRandom(float from, float to); - int useOnlineAPI(const Ogre::String& apiquery, const AngelScript::CScriptDictionary& dict, Ogre::String& result); + int useOnlineAPI(const Ogre::String &apiquery, const AngelScript::CScriptDictionary &dict, Ogre::String &result); - int getLoadedTerrain(Ogre::String& result); + int getLoadedTerrain(Ogre::String &result); Ogre::Vector3 getPersonPosition(); void clearEventCache(); - int sendGameCmd(const Ogre::String& message); + int sendGameCmd(const Ogre::String &message); - VehicleAI* getCurrentTruckAI(); - VehicleAI* getTruckAIByNum(int num); + VehicleAI *getCurrentTruckAI(); + VehicleAI *getTruckAIByNum(int num); - Actor* spawnTruck(Ogre::String& truckName, Ogre::Vector3& pos, Ogre::Vector3& rot); + Actor *spawnTruck(Ogre::String &truckName, Ogre::Vector3 &pos, Ogre::Vector3 &rot); - void showMessageBox(Ogre::String& title, Ogre::String& text, bool use_btn1, Ogre::String& btn1_text, bool allow_close, bool use_btn2, Ogre::String& btn2_text); - void backToMenu(); - void quitGame(); + void showMessageBox(Ogre::String &title, Ogre::String &text, bool use_btn1, Ogre::String &btn1_text, bool allow_close, + bool use_btn2, Ogre::String &btn2_text); + void backToMenu(); + void quitGame(); float getFPS(); float getAvgFPS(); -private: + private: + bool HaveSimController(const char *func_name); //!< Helper; Check if SimController instance exists, log warning if not. + bool HaveSimTerrain(const char *func_name); //!< Helper; Check if SimController instance exists, log warning if not. + bool HavePlayerAvatar(const char *func_name); //!< Helper; Check if local Character instance exists, log warning if not. + bool HaveMainCamera(const char *func_name); //!< Helper; Check if main camera exists, log warning if not. - bool HaveSimController(const char* func_name); //!< Helper; Check if SimController instance exists, log warning if not. - bool HaveSimTerrain(const char* func_name); //!< Helper; Check if SimController instance exists, log warning if not. - bool HavePlayerAvatar(const char* func_name); //!< Helper; Check if local Character instance exists, log warning if not. - bool HaveMainCamera(const char* func_name); //!< Helper; Check if main camera exists, log warning if not. - - ScriptEngine* mse; //!< local script engine pointer, used as proxy mostly + ScriptEngine *mse; //!< local script engine pointer, used as proxy mostly }; - diff --git a/source/main/scripting/LocalStorage.cpp b/source/main/scripting/LocalStorage.cpp index 3aed229dea..1ce9783c49 100644 --- a/source/main/scripting/LocalStorage.cpp +++ b/source/main/scripting/LocalStorage.cpp @@ -30,23 +30,23 @@ int LocalStorage::refCount = 0; LocalStorage::LocalStorage(AngelScript::asIScriptEngine *engine_in, std::string fileName_in, const std::string §ionName_in) { refCount++; - cgflag=false; + cgflag = false; this->engine = engine_in; engine->NotifyGarbageCollectorOfNewObject(this, engine->GetTypeInfoByDecl("LocalStorage")); // inversed logic, better use a whitelist instead of a blacklist, so you are on the safe side ;) - tdev std::string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; - for (std::string::iterator it = fileName_in.begin() ; it < fileName_in.end() ; ++it){ - if ( allowedChars.find(*it) == std::string::npos ) - *it = '_'; + for (std::string::iterator it = fileName_in.begin(); it < fileName_in.end(); ++it) + { + if (allowedChars.find(*it) == std::string::npos) *it = '_'; } sectionName = sectionName_in.substr(0, sectionName_in.find(".", 0)); - - filename = RoR::PathCombine(RoR::App::sys_cache_dir.GetActive(), fileName_in + ".asdata"); + + filename = RoR::PathCombine(RoR::App::sys_cache_dir.GetActive(), fileName_in + ".asdata"); separators = "="; loadDict(); - + saved = true; } @@ -68,15 +68,14 @@ LocalStorage::~LocalStorage() void LocalStorage::AddRef() const { // We need to clear the GC flag - refCount ++; + refCount++; } void LocalStorage::Release() const { // We need to clear the GC flag - refCount --; - if ( refCount == 0 ) - delete this; + refCount--; + if (refCount == 0) delete this; } int LocalStorage::GetRefCount() @@ -86,7 +85,7 @@ int LocalStorage::GetRefCount() void LocalStorage::SetGCFlag() { - cgflag=true; + cgflag = true; } bool LocalStorage::GetGCFlag() @@ -94,19 +93,23 @@ bool LocalStorage::GetGCFlag() return cgflag; } -void LocalStorage::EnumReferences(AngelScript::asIScriptEngine *engine){} -void LocalStorage::ReleaseAllReferences(AngelScript::asIScriptEngine * /*engine*/){} +void LocalStorage::EnumReferences(AngelScript::asIScriptEngine *engine) +{ +} +void LocalStorage::ReleaseAllReferences(AngelScript::asIScriptEngine * /*engine*/) +{ +} -LocalStorage &LocalStorage::operator =(LocalStorage &other) +LocalStorage &LocalStorage::operator=(LocalStorage &other) { - filename = other.getFilename(); + filename = other.getFilename(); sectionName = other.getSection(); SettingsBySection::iterator secIt; - SettingsBySection osettings = other.getSettings(); - for (secIt = osettings.begin(); secIt!=osettings.end(); secIt++) + SettingsBySection osettings = other.getSettings(); + for (secIt = osettings.begin(); secIt != osettings.end(); secIt++) { SettingsMultiMap::iterator setIt; - for (setIt = secIt->second->begin(); setIt!=secIt->second->end(); setIt++) + for (setIt = secIt->second->begin(); setIt != secIt->second->end(); setIt++) { setSetting(setIt->first, setIt->second, secIt->first); } @@ -242,15 +245,13 @@ void LocalStorage::set(std::string &key, const Ogre::Degree &value) void LocalStorage::saveDict() { - if (!saved && save()) - saved = true; + if (!saved && save()) saved = true; } bool LocalStorage::loadDict() { std::ifstream ifile(filename.c_str()); - if ( !ifile ) - return false; + if (!ifile) return false; load(filename); saved = true; @@ -262,8 +263,7 @@ void LocalStorage::eraseKey(std::string &key) std::string sec; parseKey(key, sec); if (mSettingsPtr.find(sec) != mSettingsPtr.end() && mSettingsPtr[sec]->find(key) != mSettingsPtr[sec]->end()) - if (mSettingsPtr[sec]->erase(key) > 0) - saved = false; + if (mSettingsPtr[sec]->erase(key) > 0) saved = false; } void LocalStorage::deleteAll() @@ -274,14 +274,13 @@ void LocalStorage::deleteAll() void LocalStorage::parseKey(std::string &key, std::string §ion) { size_t dot = key.find(".", 0); - if ( dot != std::string::npos ) + if (dot != std::string::npos) { section = key.substr(0, dot); - if ( !section.length() ) - section = sectionName; + if (!section.length()) section = sectionName; - key.erase(0, dot+1); + key.erase(0, dot + 1); } else section = sectionName; @@ -296,84 +295,201 @@ bool LocalStorage::exists(std::string &key) void scriptLocalStorageFactory_Generic(AngelScript::asIScriptGeneric *gen) { - std::string filename = **(std::string**)gen->GetAddressOfArg(0); - std::string sectionname = **(std::string**)gen->GetAddressOfArg(1); - - *(LocalStorage**)gen->GetAddressOfReturnLocation() = new LocalStorage(gen->GetEngine(), filename, sectionname); + std::string filename = **(std::string **)gen->GetAddressOfArg(0); + std::string sectionname = **(std::string **)gen->GetAddressOfArg(1); + + *(LocalStorage **)gen->GetAddressOfReturnLocation() = new LocalStorage(gen->GetEngine(), filename, sectionname); } void scriptLocalStorageFactory2_Generic(AngelScript::asIScriptGeneric *gen) { - std::string filename = **(std::string**)gen->GetAddressOfArg(0); - *(LocalStorage**)gen->GetAddressOfReturnLocation() = new LocalStorage(gen->GetEngine(), filename, "common"); + std::string filename = **(std::string **)gen->GetAddressOfArg(0); + *(LocalStorage **)gen->GetAddressOfReturnLocation() = new LocalStorage(gen->GetEngine(), filename, "common"); } void scriptLocalStorageFactory3_Generic(AngelScript::asIScriptGeneric *gen) -{ - *(LocalStorage**)gen->GetAddressOfReturnLocation() = new LocalStorage(gen->GetEngine()); +{ + *(LocalStorage **)gen->GetAddressOfReturnLocation() = new LocalStorage(gen->GetEngine()); } void registerLocalStorage(AngelScript::asIScriptEngine *engine) { int r; - r = engine->RegisterObjectType("LocalStorage", sizeof(LocalStorage), AngelScript::asOBJ_REF | AngelScript::asOBJ_GC); MYASSERT( r >= 0 ); - // Use the generic interface to construct the object since we need the engine pointer, we could also have retrieved the engine pointer from the active context - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_FACTORY, "LocalStorage@ f(const string &in, const string &in)", AngelScript::asFUNCTION(scriptLocalStorageFactory_Generic), AngelScript::asCALL_GENERIC); MYASSERT( r>= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_FACTORY, "LocalStorage@ f(const string &in)", AngelScript::asFUNCTION(scriptLocalStorageFactory2_Generic), AngelScript::asCALL_GENERIC); MYASSERT( r>= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_FACTORY, "LocalStorage@ f()", AngelScript::asFUNCTION(scriptLocalStorageFactory3_Generic), AngelScript::asCALL_GENERIC); MYASSERT( r>= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_ADDREF, "void f()", AngelScript::asMETHOD(LocalStorage,AddRef), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_RELEASE, "void f()", AngelScript::asMETHOD(LocalStorage,Release), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "LocalStorage &opAssign(LocalStorage &in)", AngelScript::asMETHODPR(LocalStorage, operator=, (LocalStorage &), LocalStorage&), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void changeSection(const string &in)", AngelScript::asMETHODPR(LocalStorage,changeSection,(const std::string&), void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "string get(string &in)", AngelScript::asMETHODPR(LocalStorage,get,(std::string&), std::string), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "string getString(string &in)", AngelScript::asMETHODPR(LocalStorage,get,(std::string&), std::string), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const string &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const std::string&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setString(string &in, const string &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const std::string&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "float getFloat(string &in)", AngelScript::asMETHODPR(LocalStorage,getFloat,(std::string&), float), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, float)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const float),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setFloat(string &in, float)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const float),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "vector3 getVector3(string &in)", AngelScript::asMETHODPR(LocalStorage,getVector3,(std::string&), Ogre::Vector3), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const vector3 &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Vector3&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setVector3(string &in, const vector3 &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Vector3&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "radian getRadian(string &in)", AngelScript::asMETHODPR(LocalStorage,getRadian,(std::string&), Ogre::Radian), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const radian &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Radian&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setRadian(string &in, const radian &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Radian&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "degree getDegree(string &in)", AngelScript::asMETHODPR(LocalStorage,getDegree,(std::string&), Ogre::Degree), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const degree &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Degree&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setDegree(string &in, const degree &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Degree&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "quaternion getQuaternion(string &in)", AngelScript::asMETHODPR(LocalStorage,getQuaternion,(std::string&), Ogre::Quaternion), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const quaternion &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Quaternion&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setQuaternion(string &in, const quaternion &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const Ogre::Quaternion&),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "bool getBool(string &in)", AngelScript::asMETHODPR(LocalStorage,getBool,(std::string&), bool), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const bool &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const bool),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setBool(string &in, const bool &in)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const bool),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "int getInt(string &in)", AngelScript::asMETHODPR(LocalStorage,getInt,(std::string&), int), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "int getInteger(string &in)", AngelScript::asMETHODPR(LocalStorage,getInt,(std::string&), int), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, int)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const int),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setInt(string &in, int)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const int),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void setInteger(string &in, int)", AngelScript::asMETHODPR(LocalStorage,set,(std::string&, const int),void), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "void save()", AngelScript::asMETHOD(LocalStorage,saveDict), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "bool reload()", AngelScript::asMETHOD(LocalStorage,loadDict), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("LocalStorage", "bool exists(string &in) const", AngelScript::asMETHOD(LocalStorage,exists), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("LocalStorage", "void delete(string &in)", AngelScript::asMETHOD(LocalStorage,eraseKey), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); + r = engine->RegisterObjectType("LocalStorage", sizeof(LocalStorage), AngelScript::asOBJ_REF | AngelScript::asOBJ_GC); + MYASSERT(r >= 0); + // Use the generic interface to construct the object since we need the engine pointer, we could also have retrieved the engine + // pointer from the active context + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_FACTORY, + "LocalStorage@ f(const string &in, const string &in)", + AngelScript::asFUNCTION(scriptLocalStorageFactory_Generic), AngelScript::asCALL_GENERIC); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_FACTORY, "LocalStorage@ f(const string &in)", + AngelScript::asFUNCTION(scriptLocalStorageFactory2_Generic), AngelScript::asCALL_GENERIC); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_FACTORY, "LocalStorage@ f()", + AngelScript::asFUNCTION(scriptLocalStorageFactory3_Generic), AngelScript::asCALL_GENERIC); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_ADDREF, "void f()", + AngelScript::asMETHOD(LocalStorage, AddRef), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_RELEASE, "void f()", + AngelScript::asMETHOD(LocalStorage, Release), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "LocalStorage &opAssign(LocalStorage &in)", + AngelScript::asMETHODPR(LocalStorage, operator=,(LocalStorage &), LocalStorage &), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void changeSection(const string &in)", + AngelScript::asMETHODPR(LocalStorage, changeSection, (const std::string &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "string get(string &in)", + AngelScript::asMETHODPR(LocalStorage, get, (std::string &), std::string), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "string getString(string &in)", + AngelScript::asMETHODPR(LocalStorage, get, (std::string &), std::string), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const string &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const std::string &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setString(string &in, const string &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const std::string &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "float getFloat(string &in)", + AngelScript::asMETHODPR(LocalStorage, getFloat, (std::string &), float), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, float)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const float), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setFloat(string &in, float)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const float), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "vector3 getVector3(string &in)", + AngelScript::asMETHODPR(LocalStorage, getVector3, (std::string &), Ogre::Vector3), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const vector3 &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Vector3 &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setVector3(string &in, const vector3 &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Vector3 &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "radian getRadian(string &in)", + AngelScript::asMETHODPR(LocalStorage, getRadian, (std::string &), Ogre::Radian), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const radian &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Radian &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setRadian(string &in, const radian &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Radian &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "degree getDegree(string &in)", + AngelScript::asMETHODPR(LocalStorage, getDegree, (std::string &), Ogre::Degree), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const degree &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Degree &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setDegree(string &in, const degree &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Degree &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "quaternion getQuaternion(string &in)", + AngelScript::asMETHODPR(LocalStorage, getQuaternion, (std::string &), Ogre::Quaternion), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const quaternion &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Quaternion &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setQuaternion(string &in, const quaternion &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const Ogre::Quaternion &), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "bool getBool(string &in)", + AngelScript::asMETHODPR(LocalStorage, getBool, (std::string &), bool), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, const bool &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const bool), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setBool(string &in, const bool &in)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const bool), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "int getInt(string &in)", + AngelScript::asMETHODPR(LocalStorage, getInt, (std::string &), int), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "int getInteger(string &in)", + AngelScript::asMETHODPR(LocalStorage, getInt, (std::string &), int), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void set(string &in, int)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const int), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setInt(string &in, int)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const int), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void setInteger(string &in, int)", + AngelScript::asMETHODPR(LocalStorage, set, (std::string &, const int), void), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "void save()", AngelScript::asMETHOD(LocalStorage, saveDict), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "bool reload()", AngelScript::asMETHOD(LocalStorage, loadDict), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("LocalStorage", "bool exists(string &in) const", AngelScript::asMETHOD(LocalStorage, exists), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("LocalStorage", "void delete(string &in)", AngelScript::asMETHOD(LocalStorage, eraseKey), + AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); // Register GC behaviours - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_GETREFCOUNT, "int f()", AngelScript::asMETHOD(LocalStorage,GetRefCount), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_SETGCFLAG, "void f()", AngelScript::asMETHOD(LocalStorage,SetGCFlag), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_GETGCFLAG, "bool f()", AngelScript::asMETHOD(LocalStorage,GetGCFlag), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_ENUMREFS, "void f(int&in)", AngelScript::asMETHOD(LocalStorage,EnumReferences), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_RELEASEREFS, "void f(int&in)", AngelScript::asMETHOD(LocalStorage,ReleaseAllReferences), AngelScript::asCALL_THISCALL); MYASSERT( r >= 0 ); - + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_GETREFCOUNT, "int f()", + AngelScript::asMETHOD(LocalStorage, GetRefCount), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_SETGCFLAG, "void f()", + AngelScript::asMETHOD(LocalStorage, SetGCFlag), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_GETGCFLAG, "bool f()", + AngelScript::asMETHOD(LocalStorage, GetGCFlag), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_ENUMREFS, "void f(int&in)", + AngelScript::asMETHOD(LocalStorage, EnumReferences), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("LocalStorage", AngelScript::asBEHAVE_RELEASEREFS, "void f(int&in)", + AngelScript::asMETHOD(LocalStorage, ReleaseAllReferences), AngelScript::asCALL_THISCALL); + MYASSERT(r >= 0); } diff --git a/source/main/scripting/LocalStorage.h b/source/main/scripting/LocalStorage.h index e809a78f8a..d03fd61ad2 100644 --- a/source/main/scripting/LocalStorage.h +++ b/source/main/scripting/LocalStorage.h @@ -21,90 +21,99 @@ #pragma once +#include "ImprovedConfigFile.h" #include "RoRPrerequisites.h" + #include -#include "ImprovedConfigFile.h" -void registerLocalStorage(AngelScript::asIScriptEngine* engine); -void scriptLocalStorageFactory_Generic(AngelScript::asIScriptGeneric* gen); -void scriptLocalStorageFactory2_Generic(AngelScript::asIScriptGeneric* gen); -void scriptLocalStorageFactory3_Generic(AngelScript::asIScriptGeneric* gen); +void registerLocalStorage(AngelScript::asIScriptEngine *engine); +void scriptLocalStorageFactory_Generic(AngelScript::asIScriptGeneric *gen); +void scriptLocalStorageFactory2_Generic(AngelScript::asIScriptGeneric *gen); +void scriptLocalStorageFactory3_Generic(AngelScript::asIScriptGeneric *gen); /** * @brief A class that allows scripts to store data persistently */ class LocalStorage : public ImprovedConfigFile { -public: + public: // Memory management void AddRef() const; void Release() const; - LocalStorage(AngelScript::asIScriptEngine* engine, std::string fileName_in, const std::string& sectionName_in); - LocalStorage(AngelScript::asIScriptEngine* engine_in); + LocalStorage(AngelScript::asIScriptEngine *engine, std::string fileName_in, const std::string §ionName_in); + LocalStorage(AngelScript::asIScriptEngine *engine_in); ~LocalStorage(); - LocalStorage& operator =(LocalStorage& other); - void changeSection(const std::string& section); + LocalStorage &operator=(LocalStorage &other); + void changeSection(const std::string §ion); - std::string get(std::string& key); - void set(std::string& key, const std::string& value); + std::string get(std::string &key); + void set(std::string &key, const std::string &value); - int getInt(std::string& key); - void set(std::string& key, const int value); + int getInt(std::string &key); + void set(std::string &key, const int value); - float getFloat(std::string& key); - void set(std::string& key, const float value); + float getFloat(std::string &key); + void set(std::string &key, const float value); - bool getBool(std::string& key); - void set(std::string& key, const bool value); + bool getBool(std::string &key); + void set(std::string &key, const bool value); - Ogre::Vector3 getVector3(std::string& key); - void set(std::string& key, const Ogre::Vector3& value); + Ogre::Vector3 getVector3(std::string &key); + void set(std::string &key, const Ogre::Vector3 &value); - Ogre::Quaternion getQuaternion(std::string& key); - void set(std::string& key, const Ogre::Quaternion& value); + Ogre::Quaternion getQuaternion(std::string &key); + void set(std::string &key, const Ogre::Quaternion &value); - Ogre::Radian getRadian(std::string& key); - void set(std::string& key, const Ogre::Radian& value); + Ogre::Radian getRadian(std::string &key); + void set(std::string &key, const Ogre::Radian &value); - Ogre::Degree getDegree(std::string& key); - void set(std::string& key, const Ogre::Degree& value); + Ogre::Degree getDegree(std::string &key); + void set(std::string &key, const Ogre::Degree &value); void saveDict(); // int extendDict(); bool loadDict(); // removes a key and its associated value - void eraseKey(std::string& key); + void eraseKey(std::string &key); // Returns true if the key is set - bool exists(std::string& key); + bool exists(std::string &key); // Deletes all keys void deleteAll(); // parses a key - void parseKey(std::string& key, std::string& section); + void parseKey(std::string &key, std::string §ion); // Garbage collections behaviours - int GetRefCount(); + int GetRefCount(); void SetGCFlag(); bool GetGCFlag(); - void EnumReferences(AngelScript::asIScriptEngine* engine); - void ReleaseAllReferences(AngelScript::asIScriptEngine* engine); - - SettingsBySection getSettings() { return mSettingsPtr; } - std::string getFilename() { return filename; } - std::string getSection() { return sectionName; } - -protected: - bool saved; + void EnumReferences(AngelScript::asIScriptEngine *engine); + void ReleaseAllReferences(AngelScript::asIScriptEngine *engine); + + SettingsBySection getSettings() + { + return mSettingsPtr; + } + std::string getFilename() + { + return filename; + } + std::string getSection() + { + return sectionName; + } + + protected: + bool saved; std::string sectionName; // Our properties - AngelScript::asIScriptEngine* engine; - static int refCount; - bool cgflag; + AngelScript::asIScriptEngine *engine; + static int refCount; + bool cgflag; }; - diff --git a/source/main/scripting/OgreAngelscript.cpp b/source/main/scripting/OgreAngelscript.cpp index 8490cb2a80..4756ff6c61 100644 --- a/source/main/scripting/OgreAngelscript.cpp +++ b/source/main/scripting/OgreAngelscript.cpp @@ -31,32 +31,31 @@ using namespace AngelScript; // helper/wrapper functions first /***VECTOR3***/ -static void Vector3DefaultConstructor(Vector3* self) +static void Vector3DefaultConstructor(Vector3 *self) { - new(self) Vector3(); + new (self) Vector3(); } -static void Vector3CopyConstructor(const Vector3& other, Vector3* self) +static void Vector3CopyConstructor(const Vector3 &other, Vector3 *self) { - new(self) Vector3(other); + new (self) Vector3(other); } -static void Vector3InitConstructor(float x, float y, float z, Vector3* self) +static void Vector3InitConstructor(float x, float y, float z, Vector3 *self) { - new(self) Vector3(x, y, z); + new (self) Vector3(x, y, z); } -static void Vector3InitConstructorScaler(float s, Vector3* self) +static void Vector3InitConstructorScaler(float s, Vector3 *self) { - new(self) Vector3(s, s, s); + new (self) Vector3(s, s, s); } // not used -static int Vector3Cmp(const Vector3& a, const Vector3& b) +static int Vector3Cmp(const Vector3 &a, const Vector3 &b) { // If a is greater than b, then we return a positive number - if (a > b) - return 1; + if (a > b) return 1; // If a is smaller than b, then we return a negative number else if (a < b) return -1; @@ -69,22 +68,22 @@ static int Vector3Cmp(const Vector3& a, const Vector3& b) } /***RADIAN***/ -static void RadianDefaultConstructor(Radian* self) +static void RadianDefaultConstructor(Radian *self) { - new(self) Radian(); + new (self) Radian(); } -static void RadianCopyConstructor(const Radian& other, Radian* self) +static void RadianCopyConstructor(const Radian &other, Radian *self) { - new(self) Radian(other); + new (self) Radian(other); } -static void RadianInitConstructor(float r, Radian* self) +static void RadianInitConstructor(float r, Radian *self) { - new(self) Radian(r); + new (self) Radian(r); } -static int RadianCmp(const Radian& a, const Radian& b) +static int RadianCmp(const Radian &a, const Radian &b) { if (a > b) return 1; @@ -95,22 +94,22 @@ static int RadianCmp(const Radian& a, const Radian& b) } /***DEGREE***/ -static void DegreeDefaultConstructor(Degree* self) +static void DegreeDefaultConstructor(Degree *self) { - new(self) Degree(); + new (self) Degree(); } -static void DegreeCopyConstructor(const Degree& other, Degree* self) +static void DegreeCopyConstructor(const Degree &other, Degree *self) { - new(self) Degree(other); + new (self) Degree(other); } -static void DegreeInitConstructor(float r, Degree* self) +static void DegreeInitConstructor(float r, Degree *self) { - new(self) Degree(r); + new (self) Degree(r); } -static int DegreeCmp(const Degree& a, const Degree& b) +static int DegreeCmp(const Degree &a, const Degree &b) { if (a > b) return 1; @@ -121,64 +120,68 @@ static int DegreeCmp(const Degree& a, const Degree& b) } /***QUATERNION***/ -static void QuaternionDefaultConstructor(Quaternion* self) +static void QuaternionDefaultConstructor(Quaternion *self) { - new(self) Quaternion(); + new (self) Quaternion(); } -static void QuaternionCopyConstructor(const Quaternion& other, Quaternion* self) +static void QuaternionCopyConstructor(const Quaternion &other, Quaternion *self) { - new(self) Quaternion(other.w, other.x, other.y, other.z); + new (self) Quaternion(other.w, other.x, other.y, other.z); } -static void QuaternionInitConstructor1(const Radian& rfAngle, const Vector3& rkAxis, Quaternion* self) +static void QuaternionInitConstructor1(const Radian &rfAngle, const Vector3 &rkAxis, Quaternion *self) { - new(self) Quaternion(rfAngle, rkAxis); + new (self) Quaternion(rfAngle, rkAxis); } -static void QuaternionInitConstructor2(float w, float x, float y, float z, Quaternion* self) +static void QuaternionInitConstructor2(float w, float x, float y, float z, Quaternion *self) { - new(self) Quaternion(w, x, y, z); + new (self) Quaternion(w, x, y, z); } -static void QuaternionInitConstructor3(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis, Quaternion* self) +static void QuaternionInitConstructor3(const Vector3 &xaxis, const Vector3 &yaxis, const Vector3 &zaxis, Quaternion *self) { - new(self) Quaternion(xaxis, yaxis, zaxis); + new (self) Quaternion(xaxis, yaxis, zaxis); } // not used -static void QuaternionInitConstructor5(float val, Quaternion* self) +static void QuaternionInitConstructor5(float val, Quaternion *self) { - new(self) Quaternion((Ogre::Real *)&val); + new (self) Quaternion((Ogre::Real *)&val); } -static void QuaternionInitConstructorScaler(float s, Quaternion* self) +static void QuaternionInitConstructorScaler(float s, Quaternion *self) { - new(self) Quaternion(s, s, s, s); + new (self) Quaternion(s, s, s, s); } // main registration method -void registerOgreObjects(AngelScript::asIScriptEngine* engine) +void registerOgreObjects(AngelScript::asIScriptEngine *engine) { int r; // We start by registering some data types, so angelscript knows that they exist // Ogre::Degree - r = engine->RegisterObjectType("degree", sizeof(Degree), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectType("degree", sizeof(Degree), + asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); + MYASSERT(r >= 0); // Ogre::Radian - r = engine->RegisterObjectType("radian", sizeof(Radian), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectType("radian", sizeof(Radian), + asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); + MYASSERT(r >= 0); // Ogre::Vector3 - r = engine->RegisterObjectType("vector3", sizeof(Ogre::Vector3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectType("vector3", sizeof(Ogre::Vector3), + asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); + MYASSERT(r >= 0); // Ogre::Quaternion - r = engine->RegisterObjectType("quaternion", sizeof(Quaternion), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectType("quaternion", sizeof(Quaternion), + asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA | asOBJ_APP_CLASS_ALLFLOATS); + MYASSERT(r >= 0); registerOgreRadian(engine); registerOgreDegree(engine); @@ -187,383 +190,498 @@ void registerOgreObjects(AngelScript::asIScriptEngine* engine) } // register Ogre::Vector3 -void registerOgreVector3(AngelScript::asIScriptEngine* engine) +void registerOgreVector3(AngelScript::asIScriptEngine *engine) { int r; // Register the object properties r = engine->RegisterObjectProperty("vector3", "float x", offsetof(Ogre::Vector3, x)); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); r = engine->RegisterObjectProperty("vector3", "float y", offsetof(Ogre::Vector3, y)); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); r = engine->RegisterObjectProperty("vector3", "float z", offsetof(Ogre::Vector3, z)); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); // Register the object constructors - r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Vector3DefaultConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f(float, float, float)", asFUNCTION(Vector3InitConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f(const vector3 &in)", asFUNCTION(Vector3CopyConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(Vector3InitConstructorScaler), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Vector3DefaultConstructor), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f(float, float, float)", + asFUNCTION(Vector3InitConstructor), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f(const vector3 &in)", + asFUNCTION(Vector3CopyConstructor), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("vector3", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(Vector3InitConstructorScaler), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); // Register the object operators - r = engine->RegisterObjectMethod("vector3", "float opIndex(int) const", asMETHODPR(Vector3, operator[], (size_t) const, float), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 &f(const vector3 &in)", asMETHODPR(Vector3, operator =, (const Vector3 &), Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "bool opEquals(const vector3 &in) const", asMETHODPR(Vector3, operator==,(const Vector3&) const, bool), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "vector3 opAdd(const vector3 &in) const", asMETHODPR(Vector3, operator+,(const Vector3&) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 opSub(const vector3 &in) const", asMETHODPR(Vector3, operator-,(const Vector3&) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "vector3 opMul(float) const", asMETHODPR(Vector3, operator*,(const float) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 opMul(const vector3 &in) const", asMETHODPR(Vector3, operator*,(const Vector3&) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 opDiv(float) const", asMETHODPR(Vector3, operator/,(const float) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 opDiv(const vector3 &in) const", asMETHODPR(Vector3, operator/,(const Vector3&) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "vector3 opAdd() const", asMETHODPR(Vector3, operator+,() const, const Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 opSub() const", asMETHODPR(Vector3, operator-,() const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - //r = engine->RegisterObjectMethod("vector3", "vector3 opMul(float, const vector3 &in)", asMETHODPR(Vector3, operator*,(const float, const Vector3&), Vector3), asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "vector3 &opAddAssign(const vector3 &in)", asMETHODPR(Vector3,operator+=,(const Vector3 &),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 &opAddAssign(float)", asMETHODPR(Vector3,operator+=,(const float),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "vector3 &opSubAssign(const vector3 &in)", asMETHODPR(Vector3,operator-=,(const Vector3 &),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 &opSubAssign(float)", asMETHODPR(Vector3,operator-=,(const float),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "vector3 &opMulAssign(const vector3 &in)", asMETHODPR(Vector3,operator*=,(const Vector3 &),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 &opMulAssign(float)", asMETHODPR(Vector3,operator*=,(const float),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - //r = engine->RegisterObjectMethod("vector3", "vector3& operator @= ( const vector3& rkVector f( const Vector3& rkVector )", asMETHOD(Ogre::Vector3, f), asCALL_THISCALL); MYASSERT(r>=0); - - r = engine->RegisterObjectMethod("vector3", "vector3 &opDivAssign(const vector3 &in)", asMETHODPR(Vector3,operator/=,(const Vector3 &),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 &opDivAssign(float)", asMETHODPR(Vector3,operator/=,(const float),Vector3&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - // r = engine->RegisterObjectMethod("vector3", "int opCmp(const vector3 &in) const", asFUNCTION(Vector3Cmp), asCALL_CDECL_OBJFIRST); MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("vector3", "float opIndex(int) const", asMETHODPR(Vector3, operator[],(size_t) const, float), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 &f(const vector3 &in)", + asMETHODPR(Vector3, operator=,(const Vector3 &), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "bool opEquals(const vector3 &in) const", + asMETHODPR(Vector3, operator==,(const Vector3 &) const, bool), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "vector3 opAdd(const vector3 &in) const", + asMETHODPR(Vector3, operator+,(const Vector3 &) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 opSub(const vector3 &in) const", + asMETHODPR(Vector3, operator-,(const Vector3 &) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "vector3 opMul(float) const", + asMETHODPR(Vector3, operator*,(const float) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 opMul(const vector3 &in) const", + asMETHODPR(Vector3, operator*,(const Vector3 &) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 opDiv(float) const", + asMETHODPR(Vector3, operator/,(const float) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 opDiv(const vector3 &in) const", + asMETHODPR(Vector3, operator/,(const Vector3 &) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "vector3 opAdd() const", asMETHODPR(Vector3, operator+,() const, const Vector3 &), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 opSub() const", asMETHODPR(Vector3, operator-,() const, Vector3), + asCALL_THISCALL); + MYASSERT(r >= 0); + + // r = engine->RegisterObjectMethod("vector3", "vector3 opMul(float, const vector3 &in)", asMETHODPR(Vector3, operator*,(const + // float, const Vector3&), Vector3), asCALL_THISCALL); MYASSERT( r >= 0 ); + + r = engine->RegisterObjectMethod("vector3", "vector3 &opAddAssign(const vector3 &in)", + asMETHODPR(Vector3, operator+=,(const Vector3 &), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 &opAddAssign(float)", + asMETHODPR(Vector3, operator+=,(const float), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "vector3 &opSubAssign(const vector3 &in)", + asMETHODPR(Vector3, operator-=,(const Vector3 &), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 &opSubAssign(float)", + asMETHODPR(Vector3, operator-=,(const float), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "vector3 &opMulAssign(const vector3 &in)", + asMETHODPR(Vector3, operator*=,(const Vector3 &), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 &opMulAssign(float)", + asMETHODPR(Vector3, operator*=,(const float), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + + // r = engine->RegisterObjectMethod("vector3", "vector3& operator @= ( const vector3& rkVector f( const Vector3& rkVector )", + // asMETHOD(Ogre::Vector3, f), asCALL_THISCALL); MYASSERT(r>=0); + + r = engine->RegisterObjectMethod("vector3", "vector3 &opDivAssign(const vector3 &in)", + asMETHODPR(Vector3, operator/=,(const Vector3 &), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 &opDivAssign(float)", + asMETHODPR(Vector3, operator/=,(const float), Vector3 &), asCALL_THISCALL); + MYASSERT(r >= 0); + + // r = engine->RegisterObjectMethod("vector3", "int opCmp(const vector3 &in) const", asFUNCTION(Vector3Cmp), + // asCALL_CDECL_OBJFIRST); MYASSERT( r >= 0 ); // Register the object methods - // r = engine->RegisterObjectMethod("vector3", "void swap(vector3 &inout)", asMETHOD(Vector3,swap), asCALL_THISCALL); MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "float length() const", asMETHOD(Vector3,length), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "float squaredLength() const", asMETHOD(Vector3,squaredLength), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "float distance(const vector3 &in) const", asMETHOD(Vector3,distance), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "float squaredDistance(const vector3 &in) const", asMETHOD(Vector3,squaredDistance), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "float dotProduct(const vector3 &in) const", asMETHOD(Vector3,dotProduct), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "float absDotProduct(const vector3 &in) const", asMETHOD(Vector3,absDotProduct), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "float normalise()", asMETHOD(Vector3,normalise), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "float crossProduct(const vector3 &in) const", asMETHOD(Vector3,crossProduct), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 midPoint(const vector3 &in) const", asMETHOD(Vector3,midPoint), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "void makeFloor(const vector3 &in)", asMETHOD(Vector3,makeFloor), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "void makeCeil(const vector3 &in)", asMETHOD(Vector3,makeCeil), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 perpendicular() const", asMETHOD(Vector3,perpendicular), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 randomDeviant(const radian &in, const vector3 &in) const", asMETHOD(Vector3,randomDeviant), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "radian angleBetween(const vector3 &in)", asMETHOD(Vector3,angleBetween), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "quaternion getRotationTo(const vector3 &in, const vector3 &in) const", asMETHOD(Vector3,getRotationTo), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "bool isZeroLength() const", asMETHOD(Vector3,isZeroLength), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 normalisedCopy() const", asMETHOD(Vector3,normalisedCopy), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "vector3 reflect(const vector3 &in) const", asMETHOD(Vector3,reflect), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "bool positionEquals(const vector3 &in, float) const", asMETHOD(Vector3,positionEquals), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "bool positionCloses(const vector3 &in, float) const", asMETHOD(Vector3,positionCloses), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("vector3", "bool directionEquals(const vector3 &in, radian &in) const", asMETHOD(Vector3,directionEquals), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("vector3", "bool isNaN() const", asMETHOD(Vector3,isNaN), asCALL_THISCALL); - MYASSERT( r >= 0 ); + // r = engine->RegisterObjectMethod("vector3", "void swap(vector3 &inout)", asMETHOD(Vector3,swap), asCALL_THISCALL); + // MYASSERT( r >= 0 ); + + r = engine->RegisterObjectMethod("vector3", "float length() const", asMETHOD(Vector3, length), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "float squaredLength() const", asMETHOD(Vector3, squaredLength), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "float distance(const vector3 &in) const", asMETHOD(Vector3, distance), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "float squaredDistance(const vector3 &in) const", + asMETHOD(Vector3, squaredDistance), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "float dotProduct(const vector3 &in) const", asMETHOD(Vector3, dotProduct), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "float absDotProduct(const vector3 &in) const", asMETHOD(Vector3, absDotProduct), + asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "float normalise()", asMETHOD(Vector3, normalise), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "float crossProduct(const vector3 &in) const", asMETHOD(Vector3, crossProduct), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 midPoint(const vector3 &in) const", asMETHOD(Vector3, midPoint), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "void makeFloor(const vector3 &in)", asMETHOD(Vector3, makeFloor), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "void makeCeil(const vector3 &in)", asMETHOD(Vector3, makeCeil), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 perpendicular() const", asMETHOD(Vector3, perpendicular), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 randomDeviant(const radian &in, const vector3 &in) const", + asMETHOD(Vector3, randomDeviant), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "radian angleBetween(const vector3 &in)", asMETHOD(Vector3, angleBetween), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "quaternion getRotationTo(const vector3 &in, const vector3 &in) const", + asMETHOD(Vector3, getRotationTo), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "bool isZeroLength() const", asMETHOD(Vector3, isZeroLength), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 normalisedCopy() const", asMETHOD(Vector3, normalisedCopy), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "vector3 reflect(const vector3 &in) const", asMETHOD(Vector3, reflect), + asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "bool positionEquals(const vector3 &in, float) const", + asMETHOD(Vector3, positionEquals), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "bool positionCloses(const vector3 &in, float) const", + asMETHOD(Vector3, positionCloses), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("vector3", "bool directionEquals(const vector3 &in, radian &in) const", + asMETHOD(Vector3, directionEquals), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("vector3", "bool isNaN() const", asMETHOD(Vector3, isNaN), asCALL_THISCALL); + MYASSERT(r >= 0); } -void registerOgreRadian(AngelScript::asIScriptEngine* engine) +void registerOgreRadian(AngelScript::asIScriptEngine *engine) { int r; // Register the object constructors - r = engine->RegisterObjectBehaviour("radian", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(RadianDefaultConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("radian", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(RadianInitConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("radian", asBEHAVE_CONSTRUCT, "void f(const radian &in)", asFUNCTION(RadianCopyConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - - // Disabled during port to latest AngelScript because `asBEHAVE_IMPLICIT_VALUE_CAST` is deprecated. - // TODO: Research and restore it ~ only_a_ptr, 08/2017 - // // Register other object behaviours - // r = engine->RegisterObjectBehaviour("radian", asBEHAVE_IMPLICIT_VALUE_CAST, "float f() const", asMETHOD(Radian,valueRadians), asCALL_THISCALL); - // MYASSERT( r >= 0 ); - // r = engine->RegisterObjectBehaviour("radian", asBEHAVE_IMPLICIT_VALUE_CAST, "double f() const", asMETHOD(Radian,valueRadians), asCALL_THISCALL); - // MYASSERT( r >= 0 ); + r = engine->RegisterObjectBehaviour("radian", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(RadianDefaultConstructor), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("radian", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(RadianInitConstructor), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("radian", asBEHAVE_CONSTRUCT, "void f(const radian &in)", + asFUNCTION(RadianCopyConstructor), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + + // Disabled during port to latest AngelScript because `asBEHAVE_IMPLICIT_VALUE_CAST` is deprecated. + // TODO: Research and restore it ~ only_a_ptr, 08/2017 + // // Register other object behaviours + // r = engine->RegisterObjectBehaviour("radian", asBEHAVE_IMPLICIT_VALUE_CAST, "float f() const", + // asMETHOD(Radian,valueRadians), asCALL_THISCALL); MYASSERT( r >= 0 ); r = engine->RegisterObjectBehaviour("radian", + // asBEHAVE_IMPLICIT_VALUE_CAST, "double f() const", asMETHOD(Radian,valueRadians), asCALL_THISCALL); MYASSERT( r >= 0 ); // Register the object operators - r = engine->RegisterObjectMethod("radian", "radian &opAssign(const radian &in)", asMETHODPR(Radian, operator =, (const Radian &), Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian &opAssign(const float)", asMETHODPR(Radian, operator =, (const float &), Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian &opAssign(const degree &in)", asMETHODPR(Radian, operator =, (const Degree &), Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian opAdd() const", asMETHODPR(Radian, operator+,() const, const Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian opAdd(const radian &in) const", asMETHODPR(Radian, operator+,(const Radian&) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian opAdd(const degree &in) const", asMETHODPR(Radian, operator+,(const Degree&) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian &opAddAssign(const radian &in)", asMETHODPR(Radian,operator+=,(const Radian &),Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian &opAddAssign(const degree &in)", asMETHODPR(Radian,operator+=,(const Degree &),Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian opSub() const", asMETHODPR(Radian, operator-,() const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian opSub(const radian &in) const", asMETHODPR(Radian, operator-,(const Radian&) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian opSub(const degree &in) const", asMETHODPR(Radian, operator-,(const Degree&) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian &opSubAssign(const radian &in)", asMETHODPR(Radian,operator-=,(const Radian &),Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian &opSubAssign(const degree &in)", asMETHODPR(Radian,operator-=,(const Degree &),Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian opMul(float) const", asMETHODPR(Radian, operator*,(float) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "radian opMul(const radian &in) const", asMETHODPR(Radian, operator*,(const Radian&) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian &opMulAssign(float)", asMETHODPR(Radian,operator*=,(float),Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian opDiv(float) const", asMETHODPR(Radian, operator/,(float) const, Radian), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("radian", "radian &opDivAssign(float)", asMETHODPR(Radian,operator*=,(float),Radian&), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("radian", "radian &opAssign(const radian &in)", + asMETHODPR(Radian, operator=,(const Radian &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian &opAssign(const float)", + asMETHODPR(Radian, operator=,(const float &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian &opAssign(const degree &in)", + asMETHODPR(Radian, operator=,(const Degree &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian opAdd() const", asMETHODPR(Radian, operator+,() const, const Radian &), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian opAdd(const radian &in) const", + asMETHODPR(Radian, operator+,(const Radian &) const, Radian), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian opAdd(const degree &in) const", + asMETHODPR(Radian, operator+,(const Degree &) const, Radian), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian &opAddAssign(const radian &in)", + asMETHODPR(Radian, operator+=,(const Radian &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian &opAddAssign(const degree &in)", + asMETHODPR(Radian, operator+=,(const Degree &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian opSub() const", asMETHODPR(Radian, operator-,() const, Radian), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian opSub(const radian &in) const", + asMETHODPR(Radian, operator-,(const Radian &) const, Radian), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian opSub(const degree &in) const", + asMETHODPR(Radian, operator-,(const Degree &) const, Radian), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian &opSubAssign(const radian &in)", + asMETHODPR(Radian, operator-=,(const Radian &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian &opSubAssign(const degree &in)", + asMETHODPR(Radian, operator-=,(const Degree &), Radian &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian opMul(float) const", asMETHODPR(Radian, operator*,(float) const, Radian), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "radian opMul(const radian &in) const", + asMETHODPR(Radian, operator*,(const Radian &) const, Radian), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian &opMulAssign(float)", asMETHODPR(Radian, operator*=,(float), Radian &), + asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian opDiv(float) const", asMETHODPR(Radian, operator/,(float) const, Radian), + asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("radian", "radian &opDivAssign(float)", asMETHODPR(Radian, operator*=,(float), Radian &), + asCALL_THISCALL); + MYASSERT(r >= 0); r = engine->RegisterObjectMethod("radian", "int opCmp(const radian &in) const", asFUNCTION(RadianCmp), asCALL_CDECL_OBJFIRST); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); - r = engine->RegisterObjectMethod("radian", "bool opEquals(const radian &in) const", asMETHODPR(Radian, operator==,(const Radian&) const, bool), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("radian", "bool opEquals(const radian &in) const", + asMETHODPR(Radian, operator==,(const Radian &) const, bool), asCALL_THISCALL); + MYASSERT(r >= 0); // Register the object methods - r = engine->RegisterObjectMethod("radian", "float valueDegrees() const", asMETHOD(Radian,valueDegrees), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "float valueRadians() const", asMETHOD(Radian,valueRadians), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("radian", "float valueAngleUnits() const", asMETHOD(Radian,valueAngleUnits), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("radian", "float valueDegrees() const", asMETHOD(Radian, valueDegrees), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "float valueRadians() const", asMETHOD(Radian, valueRadians), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("radian", "float valueAngleUnits() const", asMETHOD(Radian, valueAngleUnits), + asCALL_THISCALL); + MYASSERT(r >= 0); } -void registerOgreDegree(AngelScript::asIScriptEngine* engine) +void registerOgreDegree(AngelScript::asIScriptEngine *engine) { int r; // Register the object constructors - r = engine->RegisterObjectBehaviour("degree", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(DegreeDefaultConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("degree", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(DegreeInitConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("degree", asBEHAVE_CONSTRUCT, "void f(const degree &in)", asFUNCTION(DegreeCopyConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - - // Disabled during port to latest AngelScript because `asBEHAVE_IMPLICIT_VALUE_CAST` is deprecated. - // TODO: Research and restore it ~ only_a_ptr, 08/2017 - // // Register other object behaviours - // r = engine->RegisterObjectBehaviour("degree", asBEHAVE_IMPLICIT_VALUE_CAST, "float f() const", asMETHOD(Degree,valueDegrees), asCALL_THISCALL); - // MYASSERT( r >= 0 ); - // r = engine->RegisterObjectBehaviour("degree", asBEHAVE_IMPLICIT_VALUE_CAST, "double f() const", asMETHOD(Degree,valueDegrees), asCALL_THISCALL); - // MYASSERT( r >= 0 ); + r = engine->RegisterObjectBehaviour("degree", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(DegreeDefaultConstructor), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("degree", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(DegreeInitConstructor), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("degree", asBEHAVE_CONSTRUCT, "void f(const degree &in)", + asFUNCTION(DegreeCopyConstructor), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + + // Disabled during port to latest AngelScript because `asBEHAVE_IMPLICIT_VALUE_CAST` is deprecated. + // TODO: Research and restore it ~ only_a_ptr, 08/2017 + // // Register other object behaviours + // r = engine->RegisterObjectBehaviour("degree", asBEHAVE_IMPLICIT_VALUE_CAST, "float f() const", + // asMETHOD(Degree,valueDegrees), asCALL_THISCALL); MYASSERT( r >= 0 ); r = engine->RegisterObjectBehaviour("degree", + // asBEHAVE_IMPLICIT_VALUE_CAST, "double f() const", asMETHOD(Degree,valueDegrees), asCALL_THISCALL); MYASSERT( r >= 0 ); // Register the object operators - r = engine->RegisterObjectMethod("degree", "degree &opAssign(const degree &in)", asMETHODPR(Degree, operator =, (const Degree &), Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree &opAssign(float)", asMETHODPR(Degree, operator =, (const float &), Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree &opAssign(const radian &in)", asMETHODPR(Degree, operator =, (const Radian &), Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree opAdd() const", asMETHODPR(Degree, operator+,() const, const Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree opAdd(const degree &in) const", asMETHODPR(Degree, operator+,(const Degree&) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree opAdd(const radian &in) const", asMETHODPR(Degree, operator+,(const Radian&) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree &opAddAssign(const degree &in)", asMETHODPR(Degree,operator+=,(const Degree &),Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree &opAddAssign(const radian &in)", asMETHODPR(Degree,operator+=,(const Radian &),Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree opSub() const", asMETHODPR(Degree, operator-,() const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree opSub(const degree &in) const", asMETHODPR(Degree, operator-,(const Degree&) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree opSub(const radian &in) const", asMETHODPR(Degree, operator-,(const Radian&) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree &opSubAssign(const degree &in)", asMETHODPR(Degree,operator-=,(const Degree &),Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree &opSubAssign(const radian &in)", asMETHODPR(Degree,operator-=,(const Radian &),Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree opMul(float) const", asMETHODPR(Degree, operator*,(float) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "degree opMul(const degree &in) const", asMETHODPR(Degree, operator*,(const Degree&) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree &opMulAssign(float)", asMETHODPR(Degree,operator*=,(float),Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree opDiv(float) const", asMETHODPR(Degree, operator/,(float) const, Degree), asCALL_THISCALL); - MYASSERT( r >= 0 ); - - r = engine->RegisterObjectMethod("degree", "degree &opDivAssign(float)", asMETHODPR(Degree,operator*=,(float),Degree&), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("degree", "degree &opAssign(const degree &in)", + asMETHODPR(Degree, operator=,(const Degree &), Degree &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree &opAssign(float)", asMETHODPR(Degree, operator=,(const float &), Degree &), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree &opAssign(const radian &in)", + asMETHODPR(Degree, operator=,(const Radian &), Degree &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree opAdd() const", asMETHODPR(Degree, operator+,() const, const Degree &), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree opAdd(const degree &in) const", + asMETHODPR(Degree, operator+,(const Degree &) const, Degree), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree opAdd(const radian &in) const", + asMETHODPR(Degree, operator+,(const Radian &) const, Degree), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree &opAddAssign(const degree &in)", + asMETHODPR(Degree, operator+=,(const Degree &), Degree &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree &opAddAssign(const radian &in)", + asMETHODPR(Degree, operator+=,(const Radian &), Degree &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree opSub() const", asMETHODPR(Degree, operator-,() const, Degree), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree opSub(const degree &in) const", + asMETHODPR(Degree, operator-,(const Degree &) const, Degree), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree opSub(const radian &in) const", + asMETHODPR(Degree, operator-,(const Radian &) const, Degree), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree &opSubAssign(const degree &in)", + asMETHODPR(Degree, operator-=,(const Degree &), Degree &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree &opSubAssign(const radian &in)", + asMETHODPR(Degree, operator-=,(const Radian &), Degree &), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree opMul(float) const", asMETHODPR(Degree, operator*,(float) const, Degree), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "degree opMul(const degree &in) const", + asMETHODPR(Degree, operator*,(const Degree &) const, Degree), asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree &opMulAssign(float)", asMETHODPR(Degree, operator*=,(float), Degree &), + asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree opDiv(float) const", asMETHODPR(Degree, operator/,(float) const, Degree), + asCALL_THISCALL); + MYASSERT(r >= 0); + + r = engine->RegisterObjectMethod("degree", "degree &opDivAssign(float)", asMETHODPR(Degree, operator*=,(float), Degree &), + asCALL_THISCALL); + MYASSERT(r >= 0); r = engine->RegisterObjectMethod("degree", "int opCmp(const degree &in) const", asFUNCTION(DegreeCmp), asCALL_CDECL_OBJFIRST); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); - r = engine->RegisterObjectMethod("degree", "bool opEquals(const degree &in) const", asMETHODPR(Degree, operator==,(const Degree&) const, bool), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("degree", "bool opEquals(const degree &in) const", + asMETHODPR(Degree, operator==,(const Degree &) const, bool), asCALL_THISCALL); + MYASSERT(r >= 0); // Register the object methods - r = engine->RegisterObjectMethod("degree", "float valueRadians() const", asMETHOD(Degree,valueRadians), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "float valueDegrees() const", asMETHOD(Degree,valueDegrees), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("degree", "float valueAngleUnits() const", asMETHOD(Degree,valueAngleUnits), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("degree", "float valueRadians() const", asMETHOD(Degree, valueRadians), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "float valueDegrees() const", asMETHOD(Degree, valueDegrees), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("degree", "float valueAngleUnits() const", asMETHOD(Degree, valueAngleUnits), + asCALL_THISCALL); + MYASSERT(r >= 0); } -void registerOgreQuaternion(AngelScript::asIScriptEngine* engine) +void registerOgreQuaternion(AngelScript::asIScriptEngine *engine) { int r; // Register the object properties r = engine->RegisterObjectProperty("quaternion", "float w", offsetof(Quaternion, w)); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); r = engine->RegisterObjectProperty("quaternion", "float x", offsetof(Quaternion, x)); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); r = engine->RegisterObjectProperty("quaternion", "float y", offsetof(Quaternion, y)); - MYASSERT( r >= 0 ); + MYASSERT(r >= 0); r = engine->RegisterObjectProperty("quaternion", "float z", offsetof(Quaternion, z)); - MYASSERT( r >= 0 ); - // r = engine->RegisterObjectProperty("quaternion", "float ms_fEpsilon", offsetof(Quaternion, ms_fEpsilon)); MYASSERT( r >= 0 ); - // r = engine->RegisterObjectProperty("quaternion", "quaternion ZERO", offsetof(Quaternion, ZERO)); MYASSERT( r >= 0 ); - // r = engine->RegisterObjectProperty("quaternion", "quaternion IDENTITY", offsetof(Quaternion, IDENTITY)); MYASSERT( r >= 0 ); + MYASSERT(r >= 0); + // r = engine->RegisterObjectProperty("quaternion", "float ms_fEpsilon", offsetof(Quaternion, ms_fEpsilon)); MYASSERT( r >= 0 + // ); r = engine->RegisterObjectProperty("quaternion", "quaternion ZERO", offsetof(Quaternion, ZERO)); MYASSERT( r >= 0 ); r = + // engine->RegisterObjectProperty("quaternion", "quaternion IDENTITY", offsetof(Quaternion, IDENTITY)); MYASSERT( r >= 0 ); // Register the object constructors - r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(QuaternionDefaultConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(const radian &in, const vector3 &in)", asFUNCTION(QuaternionInitConstructor1), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(float, float, float, float)", asFUNCTION(QuaternionInitConstructor2), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(const vector3 &in, const vector3 &in, const vector3 &in)", asFUNCTION(QuaternionInitConstructor3), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(QuaternionInitConstructorScaler), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(const quaternion &in)", asFUNCTION(QuaternionCopyConstructor), asCALL_CDECL_OBJLAST); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(QuaternionDefaultConstructor), + asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(const radian &in, const vector3 &in)", + asFUNCTION(QuaternionInitConstructor1), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(float, float, float, float)", + asFUNCTION(QuaternionInitConstructor2), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, + "void f(const vector3 &in, const vector3 &in, const vector3 &in)", + asFUNCTION(QuaternionInitConstructor3), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(float)", + asFUNCTION(QuaternionInitConstructorScaler), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); + r = engine->RegisterObjectBehaviour("quaternion", asBEHAVE_CONSTRUCT, "void f(const quaternion &in)", + asFUNCTION(QuaternionCopyConstructor), asCALL_CDECL_OBJLAST); + MYASSERT(r >= 0); // Register the object operators - r = engine->RegisterObjectMethod("quaternion", "float opIndex(int) const", asMETHODPR(Quaternion, operator[], (size_t) const, float), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion &opAssign(const quaternion &in)", asMETHODPR(Quaternion, operator =, (const Quaternion &), Quaternion&), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion opAdd(const quaternion &in) const", asMETHODPR(Quaternion, operator+,(const Quaternion&) const, Quaternion), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion opSub(const quaternion &in) const", asMETHODPR(Quaternion, operator-,(const Quaternion&) const, Quaternion), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion opMul(const quaternion &in) const", asMETHODPR(Quaternion, operator*,(const Quaternion&) const, Quaternion), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion opMul(float) const", asMETHODPR(Quaternion, operator*,(float) const, Quaternion), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion opSub() const", asMETHODPR(Quaternion, operator-,() const, Quaternion), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "bool opEquals(const quaternion &in) const", asMETHODPR(Quaternion, operator==,(const Quaternion&) const, bool), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "vector3 opMul(const vector3 &in) const", asMETHODPR(Quaternion, operator*,(const Vector3&) const, Vector3), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("quaternion", "float opIndex(int) const", + asMETHODPR(Quaternion, operator[],(size_t) const, float), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion &opAssign(const quaternion &in)", + asMETHODPR(Quaternion, operator=,(const Quaternion &), Quaternion &), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion opAdd(const quaternion &in) const", + asMETHODPR(Quaternion, operator+,(const Quaternion &) const, Quaternion), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion opSub(const quaternion &in) const", + asMETHODPR(Quaternion, operator-,(const Quaternion &) const, Quaternion), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion opMul(const quaternion &in) const", + asMETHODPR(Quaternion, operator*,(const Quaternion &) const, Quaternion), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion opMul(float) const", + asMETHODPR(Quaternion, operator*,(float) const, Quaternion), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion opSub() const", + asMETHODPR(Quaternion, operator-,() const, Quaternion), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "bool opEquals(const quaternion &in) const", + asMETHODPR(Quaternion, operator==,(const Quaternion &) const, bool), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "vector3 opMul(const vector3 &in) const", + asMETHODPR(Quaternion, operator*,(const Vector3 &) const, Vector3), asCALL_THISCALL); + MYASSERT(r >= 0); // Register the object methods - r = engine->RegisterObjectMethod("quaternion", "float Dot(const quaternion &in) const", asMETHOD(Quaternion,Dot), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "float Norm() const", asMETHOD(Quaternion,Norm), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "float normalise()", asMETHOD(Quaternion,normalise), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion Inverse() const", asMETHOD(Quaternion,Inverse), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion UnitInverse() const", asMETHOD(Quaternion,UnitInverse), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion Exp() const", asMETHOD(Quaternion,Exp), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "quaternion Log() const", asMETHOD(Quaternion,Log), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "radian getRoll(bool) const", asMETHOD(Quaternion,getRoll), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "radian getPitch(bool) const", asMETHOD(Quaternion,getPitch), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "radian getYaw(bool) const", asMETHOD(Quaternion,getYaw), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "bool equals(const quaternion &in, const radian &in) const", asMETHOD(Quaternion,equals), asCALL_THISCALL); - MYASSERT( r >= 0 ); - r = engine->RegisterObjectMethod("quaternion", "bool isNaN() const", asMETHOD(Quaternion,isNaN), asCALL_THISCALL); - MYASSERT( r >= 0 ); + r = engine->RegisterObjectMethod("quaternion", "float Dot(const quaternion &in) const", asMETHOD(Quaternion, Dot), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "float Norm() const", asMETHOD(Quaternion, Norm), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "float normalise()", asMETHOD(Quaternion, normalise), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion Inverse() const", asMETHOD(Quaternion, Inverse), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion UnitInverse() const", asMETHOD(Quaternion, UnitInverse), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion Exp() const", asMETHOD(Quaternion, Exp), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "quaternion Log() const", asMETHOD(Quaternion, Log), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "radian getRoll(bool) const", asMETHOD(Quaternion, getRoll), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "radian getPitch(bool) const", asMETHOD(Quaternion, getPitch), + asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "radian getYaw(bool) const", asMETHOD(Quaternion, getYaw), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "bool equals(const quaternion &in, const radian &in) const", + asMETHOD(Quaternion, equals), asCALL_THISCALL); + MYASSERT(r >= 0); + r = engine->RegisterObjectMethod("quaternion", "bool isNaN() const", asMETHOD(Quaternion, isNaN), asCALL_THISCALL); + MYASSERT(r >= 0); // Register some static methods - r = engine->RegisterGlobalFunction("quaternion Slerp(float, const quaternion &in, const quaternion &in, bool &in)", asFUNCTIONPR(Quaternion::Slerp,(Real fT, const Quaternion&, const Quaternion&, bool), Quaternion), asCALL_CDECL); - MYASSERT( r >= 0 ); - r = engine->RegisterGlobalFunction("quaternion SlerpExtraSpins(float, const quaternion &in, const quaternion &in, int &in)", asFUNCTION(Quaternion::SlerpExtraSpins), asCALL_CDECL); - MYASSERT( r >= 0 ); - r = engine->RegisterGlobalFunction("void Intermediate(const quaternion &in, const quaternion &in, const quaternion &in, const quaternion &in, const quaternion &in)", asFUNCTION(Quaternion::Intermediate), asCALL_CDECL); - MYASSERT( r >= 0 ); - r = engine->RegisterGlobalFunction("quaternion Squad(float, const quaternion &in, const quaternion &in, const quaternion &in, const quaternion &in, bool &in)", asFUNCTION(Quaternion::Squad), asCALL_CDECL); - MYASSERT( r >= 0 ); - r = engine->RegisterGlobalFunction("quaternion nlerp(float, const quaternion &in, const quaternion &in, bool &in)", asFUNCTION(Quaternion::nlerp), asCALL_CDECL); - MYASSERT( r >= 0 ); + r = engine->RegisterGlobalFunction( + "quaternion Slerp(float, const quaternion &in, const quaternion &in, bool &in)", + asFUNCTIONPR(Quaternion::Slerp, (Real fT, const Quaternion &, const Quaternion &, bool), Quaternion), asCALL_CDECL); + MYASSERT(r >= 0); + r = engine->RegisterGlobalFunction("quaternion SlerpExtraSpins(float, const quaternion &in, const quaternion &in, int &in)", + asFUNCTION(Quaternion::SlerpExtraSpins), asCALL_CDECL); + MYASSERT(r >= 0); + r = engine->RegisterGlobalFunction("void Intermediate(const quaternion &in, const quaternion &in, const quaternion &in, " + "const quaternion &in, const quaternion &in)", + asFUNCTION(Quaternion::Intermediate), asCALL_CDECL); + MYASSERT(r >= 0); + r = engine->RegisterGlobalFunction("quaternion Squad(float, const quaternion &in, const quaternion &in, const quaternion " + "&in, const quaternion &in, bool &in)", + asFUNCTION(Quaternion::Squad), asCALL_CDECL); + MYASSERT(r >= 0); + r = engine->RegisterGlobalFunction("quaternion nlerp(float, const quaternion &in, const quaternion &in, bool &in)", + asFUNCTION(Quaternion::nlerp), asCALL_CDECL); + MYASSERT(r >= 0); } diff --git a/source/main/scripting/OgreAngelscript.h b/source/main/scripting/OgreAngelscript.h index 6a765f0210..bfbebb2f80 100644 --- a/source/main/scripting/OgreAngelscript.h +++ b/source/main/scripting/OgreAngelscript.h @@ -27,22 +27,21 @@ #pragma once -#include -#include - #include "RoRPrerequisites.h" +#include +#include + // This function will register the following objects with the scriptengine: // - Ogre::Vector3 // - Ogre::Radian // - Ogre::Degree // - Ogre::Quaternion -void registerOgreObjects(AngelScript::asIScriptEngine* engine); +void registerOgreObjects(AngelScript::asIScriptEngine *engine); // The following functions shouldn't be called directly! // Use the registerOgreObjects function above instead. -void registerOgreVector3(AngelScript::asIScriptEngine* engine); -void registerOgreRadian(AngelScript::asIScriptEngine* engine); -void registerOgreDegree(AngelScript::asIScriptEngine* engine); -void registerOgreQuaternion(AngelScript::asIScriptEngine* engine); - +void registerOgreVector3(AngelScript::asIScriptEngine *engine); +void registerOgreRadian(AngelScript::asIScriptEngine *engine); +void registerOgreDegree(AngelScript::asIScriptEngine *engine); +void registerOgreQuaternion(AngelScript::asIScriptEngine *engine); diff --git a/source/main/scripting/OgreScriptBuilder.cpp b/source/main/scripting/OgreScriptBuilder.cpp index 0ecffc4c2e..d2f7e90bb9 100644 --- a/source/main/scripting/OgreScriptBuilder.cpp +++ b/source/main/scripting/OgreScriptBuilder.cpp @@ -30,21 +30,18 @@ #include -int OgreScriptBuilder::LoadScriptSection(const char* full_path_cstr) +int OgreScriptBuilder::LoadScriptSection(const char *full_path_cstr) { // Get filename - required to retrieve file from OGRe's resource system. // This function received filename in older AngelScript versions, but now receives full path // (reconstructed wrong by CScriptBuilder because it doesn't know about OGRE's ZIP files). - // TODO: Refactor the entire script building logic + // TODO: Refactor the entire script building logic // - create fully RoR-custom builder instead of hacked stock CScriptBuilder + our overload. ~ only_a_ptr, 08/2017 std::string full_path(full_path_cstr); std::string filename; - size_t slash_pos = full_path.rfind('/'); // AngelScript always uses forward slashes in paths. - if (slash_pos != std::string::npos) - { - filename = full_path.substr(slash_pos+1); - } + size_t slash_pos = full_path.rfind('/'); // AngelScript always uses forward slashes in paths. + if (slash_pos != std::string::npos) { filename = full_path.substr(slash_pos + 1); } else { filename = full_path; @@ -53,24 +50,27 @@ int OgreScriptBuilder::LoadScriptSection(const char* full_path_cstr) Ogre::DataStreamPtr ds; try { - ds = Ogre::ResourceGroupManager::getSingleton().openResource(filename, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); - //TODO: do not use `AUTODETECT_RESOURCE_GROUP_NAME`, use specific group, lookups are slow! - //see also https://github.com/OGRECave/ogre/blob/master/Docs/1.10-Notes.md#resourcemanager-strict-mode ~ only_a_ptr, 08/2017 + ds = Ogre::ResourceGroupManager::getSingleton().openResource(filename, + Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); + // TODO: do not use `AUTODETECT_RESOURCE_GROUP_NAME`, use specific group, lookups are slow! + // see also https://github.com/OGRECave/ogre/blob/master/Docs/1.10-Notes.md#resourcemanager-strict-mode ~ only_a_ptr, + // 08/2017 } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - LOG("[RoR|Scripting] exception upon loading script file '"+filename+"', message: " + e.getFullDescription()); + LOG("[RoR|Scripting] exception upon loading script file '" + filename + "', message: " + e.getFullDescription()); return -1; } - // In some cases (i.e. when fed a full path with '/'-s on Windows), `openResource()` will silently return NULL for datastream. ~ only_a_ptr, 08/2017 + // In some cases (i.e. when fed a full path with '/'-s on Windows), `openResource()` will silently return NULL for datastream. + // ~ only_a_ptr, 08/2017 if (ds.isNull()) { - LOG("[RoR|Scripting] Failed to load file '"+filename+"', reason unknown."); + LOG("[RoR|Scripting] Failed to load file '" + filename + "', reason unknown."); return -1; } - const std::string& code = ds->getAsString(); - hash = RoR::Utils::Sha1Hash(code); + const std::string &code = ds->getAsString(); + hash = RoR::Utils::Sha1Hash(code); return ProcessScriptSection(code.c_str(), static_cast(code.length()), filename.c_str(), 0); } diff --git a/source/main/scripting/OgreScriptBuilder.h b/source/main/scripting/OgreScriptBuilder.h index f9e695ed1b..2f35ba87b4 100644 --- a/source/main/scripting/OgreScriptBuilder.h +++ b/source/main/scripting/OgreScriptBuilder.h @@ -26,7 +26,6 @@ #pragma once #include "RoRPrerequisites.h" - #include "scriptbuilder/scriptbuilder.h" #include @@ -35,10 +34,13 @@ // to use the ogre resource system class OgreScriptBuilder : public AngelScript::CScriptBuilder, public ZeroedMemoryAllocator { -public: - Ogre::String GetHash() { return hash; }; -protected: + public: + Ogre::String GetHash() + { + return hash; + }; + + protected: Ogre::String hash; - int LoadScriptSection(const char* filename); + int LoadScriptSection(const char *filename); }; - diff --git a/source/main/scripting/ScriptEngine.cpp b/source/main/scripting/ScriptEngine.cpp index 2a4b4f4839..5ab31a21b4 100644 --- a/source/main/scripting/ScriptEngine.cpp +++ b/source/main/scripting/ScriptEngine.cpp @@ -26,19 +26,19 @@ #include "ScriptEngine.h" // AS addons start -#include "scriptstdstring/scriptstdstring.h" -#include "scriptmath/scriptmath.h" #include "scriptany/scriptany.h" #include "scriptarray/scriptarray.h" #include "scripthelper/scripthelper.h" +#include "scriptmath/scriptmath.h" +#include "scriptstdstring/scriptstdstring.h" // AS addons end #ifdef USE_CURL -#include -#include -//#include -#include -#endif //USE_CURL + #include + #include + //#include + #include +#endif // USE_CURL #include "Application.h" #include "Beam.h" @@ -69,17 +69,9 @@ void logString(const std::string &str) // the class implementation -ScriptEngine::ScriptEngine(Collisions *coll) : - coll(coll) - , context(0) - , defaultEventCallbackFunctionPtr(nullptr) - , engine(0) - , eventCallbackFunctionPtr(nullptr) - , eventMask(0) - , frameStepFunctionPtr(nullptr) - , scriptHash() - , scriptLog(0) - , scriptName() +ScriptEngine::ScriptEngine(Collisions *coll) + : coll(coll), context(0), defaultEventCallbackFunctionPtr(nullptr), engine(0), eventCallbackFunctionPtr(nullptr), + eventMask(0), frameStepFunctionPtr(nullptr), scriptHash(), scriptLog(0), scriptName() { setSingleton(this); @@ -93,21 +85,19 @@ ScriptEngine::ScriptEngine(Collisions *coll) : ScriptEngine::~ScriptEngine() { // Clean up - if (engine) engine->Release(); + if (engine) engine->Release(); if (context) context->Release(); } - - -void ScriptEngine::messageLogged( const String& message, LogMessageLevel lml, bool maskDebug, const String &logName, bool& skipThisMessage) +void ScriptEngine::messageLogged(const String &message, LogMessageLevel lml, bool maskDebug, const String &logName, + bool &skipThisMessage) { Console *c = RoR::App::GetConsole(); if (c) c->putMessage(Console::CONSOLE_MSGTYPE_SCRIPT, Console::CONSOLE_LOGMESSAGE_SCRIPT, message, "page_white_code.png"); - } -void AS_RequestActorReset(Actor* a, bool keep_position) // Substitute for removed `Actor` function +void AS_RequestActorReset(Actor *a, bool keep_position) // Substitute for removed `Actor` function { ActorModifyRequest rq; rq.amr_actor = a; @@ -128,7 +118,7 @@ void ScriptEngine::init() // It's recommended to do this right after the creation of the engine, because if // some registration fails the engine may send valuable information to the message // stream. - result = engine->SetMessageCallback(AngelScript::asMETHOD(ScriptEngine,msgCallback), this, AngelScript::asCALL_THISCALL); + result = engine->SetMessageCallback(AngelScript::asMETHOD(ScriptEngine, msgCallback), this, AngelScript::asCALL_THISCALL); if (result < 0) { if (result == AngelScript::asINVALID_ARG) @@ -164,226 +154,527 @@ void ScriptEngine::init() registerLocalStorage(engine); // some useful global functions - result = engine->RegisterGlobalFunction("void log(const string &in)", AngelScript::asFUNCTION(logString), AngelScript::asCALL_CDECL); MYASSERT( result >= 0 ); - result = engine->RegisterGlobalFunction("void print(const string &in)", AngelScript::asFUNCTION(logString), AngelScript::asCALL_CDECL); MYASSERT( result >= 0 ); - - result = engine->RegisterObjectType("BeamFactoryClass", sizeof(ActorManager), AngelScript::asOBJ_REF); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamFactoryClass", "void setSimulationSpeed(float)", AngelScript::asMETHOD(ActorManager,SetSimulationSpeed), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectBehaviour("BeamFactoryClass", AngelScript::asBEHAVE_ADDREF, "void f()", AngelScript::asMETHOD(ActorManager,AddRef), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectBehaviour("BeamFactoryClass", AngelScript::asBEHAVE_RELEASE, "void f()", AngelScript::asMETHOD(ActorManager,Release), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); + result = engine->RegisterGlobalFunction("void log(const string &in)", AngelScript::asFUNCTION(logString), + AngelScript::asCALL_CDECL); + MYASSERT(result >= 0); + result = engine->RegisterGlobalFunction("void print(const string &in)", AngelScript::asFUNCTION(logString), + AngelScript::asCALL_CDECL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectType("BeamFactoryClass", sizeof(ActorManager), AngelScript::asOBJ_REF); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamFactoryClass", "void setSimulationSpeed(float)", + AngelScript::asMETHOD(ActorManager, SetSimulationSpeed), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectBehaviour("BeamFactoryClass", AngelScript::asBEHAVE_ADDREF, "void f()", + AngelScript::asMETHOD(ActorManager, AddRef), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectBehaviour("BeamFactoryClass", AngelScript::asBEHAVE_RELEASE, "void f()", + AngelScript::asMETHOD(ActorManager, Release), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); // enum aiEvents - result = engine->RegisterEnum("aiEvents"); MYASSERT(result >= 0); - result = engine->RegisterEnumValue("aiEvents", "AI_LIGHTSTOGGLE", AI_LIGHTSTOGGLE); MYASSERT(result >= 0); - result = engine->RegisterEnumValue("aiEvents", "AI_WAIT_SECONDS", AI_WAIT_SECONDS); MYASSERT(result >= 0); - result = engine->RegisterEnumValue("aiEvents", "AI_BEACONSTOGGLE", AI_BEACONSTOGGLE); MYASSERT(result >= 0); + result = engine->RegisterEnum("aiEvents"); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("aiEvents", "AI_LIGHTSTOGGLE", AI_LIGHTSTOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("aiEvents", "AI_WAIT_SECONDS", AI_WAIT_SECONDS); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("aiEvents", "AI_BEACONSTOGGLE", AI_BEACONSTOGGLE); + MYASSERT(result >= 0); // enum aiEvents - result = engine->RegisterEnum("AiValues"); MYASSERT(result >= 0); - result = engine->RegisterEnumValue("AiValues", "AI_SPEED", AI_SPEED); MYASSERT(result >= 0); - result = engine->RegisterEnumValue("AiValues", "AI_POWER", AI_POWER); MYASSERT(result >= 0); - - result = engine->RegisterObjectType("VehicleAIClass", sizeof(VehicleAI), AngelScript::asOBJ_REF); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("VehicleAIClass", "void addWaypoint(string &in, vector3 &in)", AngelScript::asMETHOD(VehicleAI, AddWaypoint), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("VehicleAIClass", "void addWaypoints(dictionary &in)", AngelScript::asMETHOD(VehicleAI, AddWaypoint), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("VehicleAIClass", "void setActive(bool)", AngelScript::asMETHOD(VehicleAI, SetActive), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("VehicleAIClass", "void addEvent(string &in,int &in)", AngelScript::asMETHOD(VehicleAI, AddEvent), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("VehicleAIClass", "void setValueAtWaypoint(string &in, int &in, float &in)", AngelScript::asMETHOD(VehicleAI, SetValueAtWaypoint), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectBehaviour("VehicleAIClass", AngelScript::asBEHAVE_ADDREF, "void f()", AngelScript::asMETHOD(VehicleAI, addRef), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectBehaviour("VehicleAIClass", AngelScript::asBEHAVE_RELEASE, "void f()", AngelScript::asMETHOD(VehicleAI, release), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - - + result = engine->RegisterEnum("AiValues"); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("AiValues", "AI_SPEED", AI_SPEED); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("AiValues", "AI_POWER", AI_POWER); + MYASSERT(result >= 0); + + result = engine->RegisterObjectType("VehicleAIClass", sizeof(VehicleAI), AngelScript::asOBJ_REF); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("VehicleAIClass", "void addWaypoint(string &in, vector3 &in)", + AngelScript::asMETHOD(VehicleAI, AddWaypoint), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("VehicleAIClass", "void addWaypoints(dictionary &in)", + AngelScript::asMETHOD(VehicleAI, AddWaypoint), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("VehicleAIClass", "void setActive(bool)", AngelScript::asMETHOD(VehicleAI, SetActive), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("VehicleAIClass", "void addEvent(string &in,int &in)", + AngelScript::asMETHOD(VehicleAI, AddEvent), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("VehicleAIClass", "void setValueAtWaypoint(string &in, int &in, float &in)", + AngelScript::asMETHOD(VehicleAI, SetValueAtWaypoint), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectBehaviour("VehicleAIClass", AngelScript::asBEHAVE_ADDREF, "void f()", + AngelScript::asMETHOD(VehicleAI, addRef), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectBehaviour("VehicleAIClass", AngelScript::asBEHAVE_RELEASE, "void f()", + AngelScript::asMETHOD(VehicleAI, release), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); // Register everything // class Beam - result = engine->RegisterObjectType("BeamClass", sizeof(Actor), AngelScript::asOBJ_REF); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void scaleTruck(float)", AngelScript::asMETHOD(Actor,ScaleActor), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "string getTruckName()", AngelScript::asMETHOD(Actor,GetActorDesignName), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "string getTruckFileName()", AngelScript::asMETHOD(Actor,GetActorFileName), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "int getTruckType()", AngelScript::asMETHOD(Actor,GetActorType), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void reset(bool)", AngelScript::asFUNCTION(AS_RequestActorReset), AngelScript::asCALL_CDECL_OBJFIRST); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void parkingbrakeToggle()", AngelScript::asMETHOD(Actor,ToggleParkingBrake), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void tractioncontrolToggle()", AngelScript::asMETHOD(Actor,ToggleTractionControl), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void antilockbrakeToggle()", AngelScript::asMETHOD(Actor,ToggleAntiLockBrake), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void beaconsToggle()", AngelScript::asMETHOD(Actor,ToggleBeacons), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void setReplayMode(bool)", AngelScript::asMETHOD(Actor,setReplayMode), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void ToggleCustomParticles()", AngelScript::asMETHOD(Actor,ToggleCustomParticles), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "int getNodeCount()", AngelScript::asMETHOD(Actor,GetNumNodes), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "float getTotalMass(bool)", AngelScript::asMETHOD(Actor,getTotalMass), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "int getWheelNodeCount()", AngelScript::asMETHOD(Actor,getWheelNodeCount), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void setMass(float)", AngelScript::asMETHOD(Actor,setMass), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "bool getBrakeLightVisible()", AngelScript::asMETHOD(Actor,getBrakeLightVisible), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "bool getCustomLightVisible(int)", AngelScript::asMETHOD(Actor,getCustomLightVisible), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void setCustomLightVisible(int, bool)", AngelScript::asMETHOD(Actor,setCustomLightVisible), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "bool getBeaconMode()", AngelScript::asMETHOD(Actor,getBeaconMode), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "void setBlinkType(int)", AngelScript::asMETHOD(Actor,setBlinkType), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "int getBlinkType()", AngelScript::asMETHOD(Actor,getBlinkType), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "bool getCustomParticleMode()", AngelScript::asMETHOD(Actor,getCustomParticleMode), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "bool getReverseLightVisible()", AngelScript::asMETHOD(Actor,getCustomParticleMode), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "float getHeadingDirectionAngle()", AngelScript::asMETHOD(Actor,getRotation), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "bool isLocked()", AngelScript::asMETHOD(Actor,isLocked), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "float getWheelSpeed()", AngelScript::asMETHOD(Actor,getWheelSpeed), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "float getSpeed()", AngelScript::asMETHOD(Actor,getSpeed), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "vector3 getGForces()", AngelScript::asMETHOD(Actor,GetGForcesCur), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("BeamClass", "float getRotation()", AngelScript::asMETHOD(Actor,getRotation), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "vector3 getVehiclePosition()", AngelScript::asMETHOD(Actor,getPosition), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("BeamClass", "vector3 getNodePosition(int)", AngelScript::asMETHOD(Actor,getNodePosition), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("BeamClass", "VehicleAIClass @getVehicleAI()", AngelScript::asMETHOD(Actor,getVehicleAI), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - + result = engine->RegisterObjectType("BeamClass", sizeof(Actor), AngelScript::asOBJ_REF); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void scaleTruck(float)", AngelScript::asMETHOD(Actor, ScaleActor), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "string getTruckName()", AngelScript::asMETHOD(Actor, GetActorDesignName), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "string getTruckFileName()", + AngelScript::asMETHOD(Actor, GetActorFileName), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "int getTruckType()", AngelScript::asMETHOD(Actor, GetActorType), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void reset(bool)", AngelScript::asFUNCTION(AS_RequestActorReset), + AngelScript::asCALL_CDECL_OBJFIRST); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void parkingbrakeToggle()", + AngelScript::asMETHOD(Actor, ToggleParkingBrake), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void tractioncontrolToggle()", + AngelScript::asMETHOD(Actor, ToggleTractionControl), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void antilockbrakeToggle()", + AngelScript::asMETHOD(Actor, ToggleAntiLockBrake), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void beaconsToggle()", AngelScript::asMETHOD(Actor, ToggleBeacons), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void setReplayMode(bool)", AngelScript::asMETHOD(Actor, setReplayMode), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void ToggleCustomParticles()", + AngelScript::asMETHOD(Actor, ToggleCustomParticles), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "int getNodeCount()", AngelScript::asMETHOD(Actor, GetNumNodes), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "float getTotalMass(bool)", AngelScript::asMETHOD(Actor, getTotalMass), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "int getWheelNodeCount()", AngelScript::asMETHOD(Actor, getWheelNodeCount), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void setMass(float)", AngelScript::asMETHOD(Actor, setMass), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "bool getBrakeLightVisible()", + AngelScript::asMETHOD(Actor, getBrakeLightVisible), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "bool getCustomLightVisible(int)", + AngelScript::asMETHOD(Actor, getCustomLightVisible), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void setCustomLightVisible(int, bool)", + AngelScript::asMETHOD(Actor, setCustomLightVisible), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "bool getBeaconMode()", AngelScript::asMETHOD(Actor, getBeaconMode), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "void setBlinkType(int)", AngelScript::asMETHOD(Actor, setBlinkType), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "int getBlinkType()", AngelScript::asMETHOD(Actor, getBlinkType), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "bool getCustomParticleMode()", + AngelScript::asMETHOD(Actor, getCustomParticleMode), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "bool getReverseLightVisible()", + AngelScript::asMETHOD(Actor, getCustomParticleMode), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "float getHeadingDirectionAngle()", + AngelScript::asMETHOD(Actor, getRotation), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "bool isLocked()", AngelScript::asMETHOD(Actor, isLocked), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "float getWheelSpeed()", AngelScript::asMETHOD(Actor, getWheelSpeed), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "float getSpeed()", AngelScript::asMETHOD(Actor, getSpeed), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "vector3 getGForces()", AngelScript::asMETHOD(Actor, GetGForcesCur), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("BeamClass", "float getRotation()", AngelScript::asMETHOD(Actor, getRotation), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "vector3 getVehiclePosition()", AngelScript::asMETHOD(Actor, getPosition), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "vector3 getNodePosition(int)", + AngelScript::asMETHOD(Actor, getNodePosition), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("BeamClass", "VehicleAIClass @getVehicleAI()", + AngelScript::asMETHOD(Actor, getVehicleAI), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); /* // impossible to use offsetof for derived classes // unusable, read http://www.angelcode.com/angelscript/sdk/docs/manual/doc_adv_class_hierarchy.html */ - result = engine->RegisterObjectBehaviour("BeamClass", AngelScript::asBEHAVE_ADDREF, "void f()", AngelScript::asMETHOD(Actor,addRef), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectBehaviour("BeamClass", AngelScript::asBEHAVE_RELEASE, "void f()", AngelScript::asMETHOD(Actor,release), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); + result = engine->RegisterObjectBehaviour("BeamClass", AngelScript::asBEHAVE_ADDREF, "void f()", + AngelScript::asMETHOD(Actor, addRef), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectBehaviour("BeamClass", AngelScript::asBEHAVE_RELEASE, "void f()", + AngelScript::asMETHOD(Actor, release), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); // TODO: add Vector3 classes and other utility classes! // class GameScript - result = engine->RegisterObjectType("GameScriptClass", sizeof(GameScript), AngelScript::asOBJ_VALUE | AngelScript::asOBJ_POD | AngelScript::asOBJ_APP_CLASS); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void log(const string &in)", AngelScript::asMETHOD(GameScript,log), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "float getTime()", AngelScript::asMETHOD(GameScript,getTime), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "float rangeRandom(float, float)", AngelScript::asMETHOD(GameScript,rangeRandom), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void activateAllVehicles()", AngelScript::asMETHOD(GameScript,activateAllVehicles), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setTrucksForcedActive(bool forceActive)", AngelScript::asMETHOD(GameScript,SetTrucksForcedAwake), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void setBestLapTime(float time)", AngelScript::asMETHOD(GameScript,setBestLapTime), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setTimeDiff(float diff)", AngelScript::asMETHOD(GameScript,setTimeDiff), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void startTimer(int id)", AngelScript::asMETHOD(GameScript,startTimer), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void stopTimer()", AngelScript::asMETHOD(GameScript,stopTimer), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void flashMessage(const string &in, float, float)", AngelScript::asMETHOD(GameScript,flashMessage), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void message(const string &in, const string &in, float, bool)", AngelScript::asMETHOD(GameScript,message), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void UpdateDirectionArrow(const string &in, vector3 &in)", AngelScript::asMETHOD(GameScript,UpdateDirectionArrow), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void hideDirectionArrow()", AngelScript::asMETHOD(GameScript,hideDirectionArrow), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void showChooser(const string &in, const string &in, const string &in)", AngelScript::asMETHOD(GameScript,showChooser), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int getChatFontSize()", AngelScript::asMETHOD(GameScript,getChatFontSize), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setChatFontSize(int)", AngelScript::asMETHOD(GameScript,setChatFontSize), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void loadTerrain(const string &in)", AngelScript::asMETHOD(GameScript,loadTerrain), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int getLoadedTerrain(string &out)", AngelScript::asMETHOD(GameScript,getLoadedTerrain), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "bool getCaelumAvailable()", AngelScript::asMETHOD(GameScript,getCaelumAvailable), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "string getCaelumTime()", AngelScript::asMETHOD(GameScript,getCaelumTime), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setCaelumTime(float)", AngelScript::asMETHOD(GameScript,setCaelumTime), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setWaterHeight(float)", AngelScript::asMETHOD(GameScript,setWaterHeight), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "float getWaterHeight()", AngelScript::asMETHOD(GameScript,getWaterHeight), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "float getGroundHeight(vector3 &in)", AngelScript::asMETHOD(GameScript,getGroundHeight), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "float getGravity()", AngelScript::asMETHOD(GameScript,getGravity), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setGravity(float)", AngelScript::asMETHOD(GameScript,setGravity), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void spawnObject(const string &in, const string &in, vector3 &in, vector3 &in, const string &in, bool)", AngelScript::asMETHOD(GameScript,spawnObject), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void MoveObjectVisuals(const string &in, vector3 &in)", AngelScript::asMETHOD(GameScript,MoveTerrainObjectVisuals), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void destroyObject(const string &in)", AngelScript::asMETHOD(GameScript,destroyObject), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialAmbient(const string &in, float, float, float)", AngelScript::asMETHOD(GameScript,setMaterialAmbient), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialDiffuse(const string &in, float, float, float, float)", AngelScript::asMETHOD(GameScript,setMaterialDiffuse), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialSpecular(const string &in, float, float, float, float)", AngelScript::asMETHOD(GameScript,setMaterialSpecular), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialEmissive(const string &in, float, float, float)", AngelScript::asMETHOD(GameScript,setMaterialEmissive), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialTextureName(const string &in, int, int, int, const string &in)", AngelScript::asMETHOD(GameScript,setMaterialTextureName), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialTextureRotate(const string &in, int, int, int, float)", AngelScript::asMETHOD(GameScript,setMaterialTextureRotate), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialTextureScroll(const string &in, int, int, int, float, float)", AngelScript::asMETHOD(GameScript,setMaterialTextureScroll), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialTextureScale(const string &in, int, int, int, float, float)", AngelScript::asMETHOD(GameScript,setMaterialTextureScale), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void repairVehicle(const string &in, const string &in, bool)", AngelScript::asMETHOD(GameScript,repairVehicle), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void removeVehicle(const string &in, const string &in)", AngelScript::asMETHOD(GameScript,removeVehicle), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int getCurrentTruckNumber()", AngelScript::asMETHOD(GameScript,GetPlayerActorId), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void boostCurrentTruck(float)", AngelScript::asMETHOD(GameScript, boostCurrentTruck), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int getNumTrucks()", AngelScript::asMETHOD(GameScript,getNumTrucks), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "BeamClass @getCurrentTruck()", AngelScript::asMETHOD(GameScript,getCurrentTruck), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "BeamClass @getTruckByNum(int)", AngelScript::asMETHOD(GameScript,getTruckByNum), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int getNumTrucksByFlag(int)", AngelScript::asMETHOD(GameScript,getNumTrucksByFlag), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void setPersonPosition(vector3 &in)", AngelScript::asMETHOD(GameScript,setPersonPosition), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getPersonPosition()", AngelScript::asMETHOD(GameScript,getPersonPosition), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setPersonRotation(radian &in)", AngelScript::asMETHOD(GameScript,setPersonRotation), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "radian getPersonRotation()", AngelScript::asMETHOD(GameScript,getPersonRotation), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraPosition(vector3 &in)", AngelScript::asMETHOD(GameScript,setCameraPosition), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraDirection(vector3 &in)", AngelScript::asMETHOD(GameScript,setCameraDirection), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraYaw(float)", AngelScript::asMETHOD(GameScript,setCameraYaw), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraPitch(float)", AngelScript::asMETHOD(GameScript,setCameraPitch), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraRoll(float)", AngelScript::asMETHOD(GameScript,setCameraRoll), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getCameraPosition()", AngelScript::asMETHOD(GameScript,getCameraPosition), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getCameraDirection()", AngelScript::asMETHOD(GameScript,getCameraDirection), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void cameraLookAt(vector3 &in)", AngelScript::asMETHOD(GameScript,cameraLookAt), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraOrientation(vector3 &in)", AngelScript::asMETHOD(GameScript,setCameraOrientation), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getCameraOrientation()", AngelScript::asMETHOD(GameScript,getCameraOrientation), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "int addScriptFunction(const string &in)", AngelScript::asMETHOD(GameScript,addScriptFunction), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int scriptFunctionExists(const string &in)", AngelScript::asMETHOD(GameScript,scriptFunctionExists), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int deleteScriptFunction(const string &in)", AngelScript::asMETHOD(GameScript,deleteScriptFunction), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int addScriptVariable(const string &in)", AngelScript::asMETHOD(GameScript,addScriptVariable), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int deleteScriptVariable(const string &in)", AngelScript::asMETHOD(GameScript,deleteScriptVariable), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void clearEventCache()", AngelScript::asMETHOD(GameScript,clearEventCache), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "void registerForEvent(int)", AngelScript::asMETHOD(GameScript,registerForEvent), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "int sendGameCmd(const string &in)", AngelScript::asMETHOD(GameScript,sendGameCmd), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - result = engine->RegisterObjectMethod("GameScriptClass", "int useOnlineAPI(const string &in, const dictionary &in, string &out)", AngelScript::asMETHOD(GameScript,useOnlineAPI), AngelScript::asCALL_THISCALL); MYASSERT(result>=0); - - result = engine->RegisterObjectMethod("GameScriptClass", "VehicleAIClass @getCurrentTruckAI()", AngelScript::asMETHOD(GameScript, getCurrentTruckAI), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("GameScriptClass", "VehicleAIClass @getTruckAIByNum(int)", AngelScript::asMETHOD(GameScript, getTruckAIByNum), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void showMessageBox(string &in, string &in, bool button1, string &in, bool AllowClose, bool button2,string &in)", AngelScript::asMETHOD(GameScript, showMessageBox), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("GameScriptClass", "BeamClass @spawnTruck(string &in, vector3 &in, vector3 &in)", AngelScript::asMETHOD(GameScript, spawnTruck), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - - result = engine->RegisterObjectMethod("GameScriptClass", "float getFPS()", AngelScript::asMETHOD(GameScript, getFPS), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - - result = engine->RegisterObjectMethod("GameScriptClass", "void backToMenu()", AngelScript::asMETHOD(GameScript, backToMenu), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - result = engine->RegisterObjectMethod("GameScriptClass", "void quitGame()", AngelScript::asMETHOD(GameScript, quitGame), AngelScript::asCALL_THISCALL); MYASSERT(result >= 0); - - - + result = engine->RegisterObjectType("GameScriptClass", sizeof(GameScript), + AngelScript::asOBJ_VALUE | AngelScript::asOBJ_POD | AngelScript::asOBJ_APP_CLASS); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void log(const string &in)", AngelScript::asMETHOD(GameScript, log), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "float getTime()", AngelScript::asMETHOD(GameScript, getTime), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "float rangeRandom(float, float)", + AngelScript::asMETHOD(GameScript, rangeRandom), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void activateAllVehicles()", + AngelScript::asMETHOD(GameScript, activateAllVehicles), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setTrucksForcedActive(bool forceActive)", + AngelScript::asMETHOD(GameScript, SetTrucksForcedAwake), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void setBestLapTime(float time)", + AngelScript::asMETHOD(GameScript, setBestLapTime), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setTimeDiff(float diff)", + AngelScript::asMETHOD(GameScript, setTimeDiff), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void startTimer(int id)", + AngelScript::asMETHOD(GameScript, startTimer), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void stopTimer()", AngelScript::asMETHOD(GameScript, stopTimer), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void flashMessage(const string &in, float, float)", + AngelScript::asMETHOD(GameScript, flashMessage), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void message(const string &in, const string &in, float, bool)", + AngelScript::asMETHOD(GameScript, message), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void UpdateDirectionArrow(const string &in, vector3 &in)", + AngelScript::asMETHOD(GameScript, UpdateDirectionArrow), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void hideDirectionArrow()", + AngelScript::asMETHOD(GameScript, hideDirectionArrow), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = + engine->RegisterObjectMethod("GameScriptClass", "void showChooser(const string &in, const string &in, const string &in)", + AngelScript::asMETHOD(GameScript, showChooser), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int getChatFontSize()", + AngelScript::asMETHOD(GameScript, getChatFontSize), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setChatFontSize(int)", + AngelScript::asMETHOD(GameScript, setChatFontSize), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void loadTerrain(const string &in)", + AngelScript::asMETHOD(GameScript, loadTerrain), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int getLoadedTerrain(string &out)", + AngelScript::asMETHOD(GameScript, getLoadedTerrain), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "bool getCaelumAvailable()", + AngelScript::asMETHOD(GameScript, getCaelumAvailable), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "string getCaelumTime()", + AngelScript::asMETHOD(GameScript, getCaelumTime), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setCaelumTime(float)", + AngelScript::asMETHOD(GameScript, setCaelumTime), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setWaterHeight(float)", + AngelScript::asMETHOD(GameScript, setWaterHeight), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "float getWaterHeight()", + AngelScript::asMETHOD(GameScript, getWaterHeight), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "float getGroundHeight(vector3 &in)", + AngelScript::asMETHOD(GameScript, getGroundHeight), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "float getGravity()", AngelScript::asMETHOD(GameScript, getGravity), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setGravity(float)", + AngelScript::asMETHOD(GameScript, setGravity), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod( + "GameScriptClass", + "void spawnObject(const string &in, const string &in, vector3 &in, vector3 &in, const string &in, bool)", + AngelScript::asMETHOD(GameScript, spawnObject), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = + engine->RegisterObjectMethod("GameScriptClass", "void MoveObjectVisuals(const string &in, vector3 &in)", + AngelScript::asMETHOD(GameScript, MoveTerrainObjectVisuals), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void destroyObject(const string &in)", + AngelScript::asMETHOD(GameScript, destroyObject), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialAmbient(const string &in, float, float, float)", + AngelScript::asMETHOD(GameScript, setMaterialAmbient), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = + engine->RegisterObjectMethod("GameScriptClass", "int setMaterialDiffuse(const string &in, float, float, float, float)", + AngelScript::asMETHOD(GameScript, setMaterialDiffuse), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = + engine->RegisterObjectMethod("GameScriptClass", "int setMaterialSpecular(const string &in, float, float, float, float)", + AngelScript::asMETHOD(GameScript, setMaterialSpecular), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int setMaterialEmissive(const string &in, float, float, float)", + AngelScript::asMETHOD(GameScript, setMaterialEmissive), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod( + "GameScriptClass", "int setMaterialTextureName(const string &in, int, int, int, const string &in)", + AngelScript::asMETHOD(GameScript, setMaterialTextureName), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = + engine->RegisterObjectMethod("GameScriptClass", "int setMaterialTextureRotate(const string &in, int, int, int, float)", + AngelScript::asMETHOD(GameScript, setMaterialTextureRotate), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod( + "GameScriptClass", "int setMaterialTextureScroll(const string &in, int, int, int, float, float)", + AngelScript::asMETHOD(GameScript, setMaterialTextureScroll), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod( + "GameScriptClass", "int setMaterialTextureScale(const string &in, int, int, int, float, float)", + AngelScript::asMETHOD(GameScript, setMaterialTextureScale), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void repairVehicle(const string &in, const string &in, bool)", + AngelScript::asMETHOD(GameScript, repairVehicle), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void removeVehicle(const string &in, const string &in)", + AngelScript::asMETHOD(GameScript, removeVehicle), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int getCurrentTruckNumber()", + AngelScript::asMETHOD(GameScript, GetPlayerActorId), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void boostCurrentTruck(float)", + AngelScript::asMETHOD(GameScript, boostCurrentTruck), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int getNumTrucks()", + AngelScript::asMETHOD(GameScript, getNumTrucks), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "BeamClass @getCurrentTruck()", + AngelScript::asMETHOD(GameScript, getCurrentTruck), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "BeamClass @getTruckByNum(int)", + AngelScript::asMETHOD(GameScript, getTruckByNum), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int getNumTrucksByFlag(int)", + AngelScript::asMETHOD(GameScript, getNumTrucksByFlag), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void setPersonPosition(vector3 &in)", + AngelScript::asMETHOD(GameScript, setPersonPosition), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getPersonPosition()", + AngelScript::asMETHOD(GameScript, getPersonPosition), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setPersonRotation(radian &in)", + AngelScript::asMETHOD(GameScript, setPersonRotation), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "radian getPersonRotation()", + AngelScript::asMETHOD(GameScript, getPersonRotation), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraPosition(vector3 &in)", + AngelScript::asMETHOD(GameScript, setCameraPosition), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraDirection(vector3 &in)", + AngelScript::asMETHOD(GameScript, setCameraDirection), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraYaw(float)", + AngelScript::asMETHOD(GameScript, setCameraYaw), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraPitch(float)", + AngelScript::asMETHOD(GameScript, setCameraPitch), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraRoll(float)", + AngelScript::asMETHOD(GameScript, setCameraRoll), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getCameraPosition()", + AngelScript::asMETHOD(GameScript, getCameraPosition), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getCameraDirection()", + AngelScript::asMETHOD(GameScript, getCameraDirection), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void cameraLookAt(vector3 &in)", + AngelScript::asMETHOD(GameScript, cameraLookAt), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void setCameraOrientation(vector3 &in)", + AngelScript::asMETHOD(GameScript, setCameraOrientation), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "vector3 getCameraOrientation()", + AngelScript::asMETHOD(GameScript, getCameraOrientation), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "int addScriptFunction(const string &in)", + AngelScript::asMETHOD(GameScript, addScriptFunction), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int scriptFunctionExists(const string &in)", + AngelScript::asMETHOD(GameScript, scriptFunctionExists), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int deleteScriptFunction(const string &in)", + AngelScript::asMETHOD(GameScript, deleteScriptFunction), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int addScriptVariable(const string &in)", + AngelScript::asMETHOD(GameScript, addScriptVariable), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "int deleteScriptVariable(const string &in)", + AngelScript::asMETHOD(GameScript, deleteScriptVariable), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void clearEventCache()", + AngelScript::asMETHOD(GameScript, clearEventCache), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void registerForEvent(int)", + AngelScript::asMETHOD(GameScript, registerForEvent), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "int sendGameCmd(const string &in)", + AngelScript::asMETHOD(GameScript, sendGameCmd), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = + engine->RegisterObjectMethod("GameScriptClass", "int useOnlineAPI(const string &in, const dictionary &in, string &out)", + AngelScript::asMETHOD(GameScript, useOnlineAPI), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "VehicleAIClass @getCurrentTruckAI()", + AngelScript::asMETHOD(GameScript, getCurrentTruckAI), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "VehicleAIClass @getTruckAIByNum(int)", + AngelScript::asMETHOD(GameScript, getTruckAIByNum), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod( + "GameScriptClass", + "void showMessageBox(string &in, string &in, bool button1, string &in, bool AllowClose, bool button2,string &in)", + AngelScript::asMETHOD(GameScript, showMessageBox), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "BeamClass @spawnTruck(string &in, vector3 &in, vector3 &in)", + AngelScript::asMETHOD(GameScript, spawnTruck), AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "float getFPS()", AngelScript::asMETHOD(GameScript, getFPS), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + + result = engine->RegisterObjectMethod("GameScriptClass", "void backToMenu()", AngelScript::asMETHOD(GameScript, backToMenu), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + result = engine->RegisterObjectMethod("GameScriptClass", "void quitGame()", AngelScript::asMETHOD(GameScript, quitGame), + AngelScript::asCALL_THISCALL); + MYASSERT(result >= 0); + // enum scriptEvents - result = engine->RegisterEnum("scriptEvents"); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_COLLISION_BOX_ENTER", SE_COLLISION_BOX_ENTER); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_COLLISION_BOX_LEAVE", SE_COLLISION_BOX_LEAVE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENTER", SE_TRUCK_ENTER); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_EXIT", SE_TRUCK_EXIT); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENGINE_DIED", SE_TRUCK_ENGINE_DIED); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENGINE_FIRE", SE_TRUCK_ENGINE_FIRE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_TOUCHED_WATER", SE_TRUCK_TOUCHED_WATER); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_BEAM_BROKE", SE_TRUCK_BEAM_BROKE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_LOCKED", SE_TRUCK_LOCKED); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_UNLOCKED", SE_TRUCK_UNLOCKED); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_LIGHT_TOGGLE", SE_TRUCK_LIGHT_TOGGLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_SKELETON_TOGGLE", SE_TRUCK_SKELETON_TOGGLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_TIE_TOGGLE", SE_TRUCK_TIE_TOGGLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_PARKINGBREAK_TOGGLE", SE_TRUCK_PARKINGBREAK_TOGGLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_RESET", SE_TRUCK_RESET); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_TELEPORT", SE_TRUCK_TELEPORT); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_BEACONS_TOGGLE", SE_TRUCK_BEACONS_TOGGLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_CPARTICLES_TOGGLE", SE_TRUCK_CPARTICLES_TOGGLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_GROUND_CONTACT_CHANGED", SE_TRUCK_GROUND_CONTACT_CHANGED); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_NEW_TRUCK", SE_GENERIC_NEW_TRUCK); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_DELETED_TRUCK", SE_GENERIC_DELETED_TRUCK); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_INPUT_EVENT", SE_GENERIC_INPUT_EVENT); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_MOUSE_BEAM_INTERACTION", SE_GENERIC_MOUSE_BEAM_INTERACTION); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_ANGELSCRIPT_MANIPULATIONS", SE_ANGELSCRIPT_MANIPULATIONS); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_MESSAGEBOX_CLICK", SE_GENERIC_MESSAGEBOX_CLICK); MYASSERT(result>=0); - result = engine->RegisterEnumValue("scriptEvents", "SE_ALL_EVENTS", SE_ALL_EVENTS); MYASSERT(result>=0); - + result = engine->RegisterEnum("scriptEvents"); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_COLLISION_BOX_ENTER", SE_COLLISION_BOX_ENTER); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_COLLISION_BOX_LEAVE", SE_COLLISION_BOX_LEAVE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENTER", SE_TRUCK_ENTER); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_EXIT", SE_TRUCK_EXIT); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENGINE_DIED", SE_TRUCK_ENGINE_DIED); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENGINE_FIRE", SE_TRUCK_ENGINE_FIRE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_TOUCHED_WATER", SE_TRUCK_TOUCHED_WATER); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_BEAM_BROKE", SE_TRUCK_BEAM_BROKE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_LOCKED", SE_TRUCK_LOCKED); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_UNLOCKED", SE_TRUCK_UNLOCKED); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_LIGHT_TOGGLE", SE_TRUCK_LIGHT_TOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_SKELETON_TOGGLE", SE_TRUCK_SKELETON_TOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_TIE_TOGGLE", SE_TRUCK_TIE_TOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_PARKINGBREAK_TOGGLE", SE_TRUCK_PARKINGBREAK_TOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_RESET", SE_TRUCK_RESET); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_TELEPORT", SE_TRUCK_TELEPORT); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_BEACONS_TOGGLE", SE_TRUCK_BEACONS_TOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_CPARTICLES_TOGGLE", SE_TRUCK_CPARTICLES_TOGGLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_GROUND_CONTACT_CHANGED", SE_TRUCK_GROUND_CONTACT_CHANGED); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_NEW_TRUCK", SE_GENERIC_NEW_TRUCK); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_DELETED_TRUCK", SE_GENERIC_DELETED_TRUCK); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_INPUT_EVENT", SE_GENERIC_INPUT_EVENT); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_MOUSE_BEAM_INTERACTION", SE_GENERIC_MOUSE_BEAM_INTERACTION); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_ANGELSCRIPT_MANIPULATIONS", SE_ANGELSCRIPT_MANIPULATIONS); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_MESSAGEBOX_CLICK", SE_GENERIC_MESSAGEBOX_CLICK); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_ALL_EVENTS", SE_ALL_EVENTS); + MYASSERT(result >= 0); + // enum truckStates - result = engine->RegisterEnum("truckStates"); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckStates", "TS_SIMULATED", static_cast(Actor::SimState::LOCAL_SIMULATED)); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckStates", "TS_SLEEPING", static_cast(Actor::SimState::LOCAL_SLEEPING)); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckStates", "TS_NETWORKED", static_cast(Actor::SimState::NETWORKED_OK)); MYASSERT(result>=0); + result = engine->RegisterEnum("truckStates"); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckStates", "TS_SIMULATED", static_cast(Actor::SimState::LOCAL_SIMULATED)); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckStates", "TS_SLEEPING", static_cast(Actor::SimState::LOCAL_SLEEPING)); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckStates", "TS_NETWORKED", static_cast(Actor::SimState::NETWORKED_OK)); + MYASSERT(result >= 0); // enum truckTypes - result = engine->RegisterEnum("truckTypes"); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckTypes", "TT_NOT_DRIVEABLE", NOT_DRIVEABLE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckTypes", "TT_TRUCK", TRUCK); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckTypes", "TT_AIRPLANE", AIRPLANE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckTypes", "TT_BOAT", BOAT); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckTypes", "TT_MACHINE", MACHINE); MYASSERT(result>=0); - result = engine->RegisterEnumValue("truckTypes", "TT_AI", AI); MYASSERT(result>=0); + result = engine->RegisterEnum("truckTypes"); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckTypes", "TT_NOT_DRIVEABLE", NOT_DRIVEABLE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckTypes", "TT_TRUCK", TRUCK); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckTypes", "TT_AIRPLANE", AIRPLANE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckTypes", "TT_BOAT", BOAT); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckTypes", "TT_MACHINE", MACHINE); + MYASSERT(result >= 0); + result = engine->RegisterEnumValue("truckTypes", "TT_AI", AI); + MYASSERT(result >= 0); // now the global instances GameScript *gamescript = new GameScript(this); - result = engine->RegisterGlobalProperty("GameScriptClass game", gamescript); MYASSERT(result>=0); - //result = engine->RegisterGlobalProperty("CacheSystemClass cache", &CacheSystem::getSingleton()); MYASSERT(result>=0); + result = engine->RegisterGlobalProperty("GameScriptClass game", gamescript); + MYASSERT(result >= 0); + // result = engine->RegisterGlobalProperty("CacheSystemClass cache", &CacheSystem::getSingleton()); MYASSERT(result>=0); SLOG("Type registrations done. If you see no error above everything should be working"); } @@ -391,12 +682,12 @@ void ScriptEngine::init() void ScriptEngine::msgCallback(const AngelScript::asSMessageInfo *msg) { const char *type = "Error"; - if ( msg->type == AngelScript::asMSGTYPE_INFORMATION ) + if (msg->type == AngelScript::asMSGTYPE_INFORMATION) type = "Info"; - else if ( msg->type == AngelScript::asMSGTYPE_WARNING ) + else if (msg->type == AngelScript::asMSGTYPE_WARNING) type = "Warning"; - char tmp[1024]=""; + char tmp[1024] = ""; sprintf(tmp, "%s (%d, %d): %s = %s", msg->section, msg->row, msg->col, type, msg->message); SLOG(tmp); } @@ -407,13 +698,13 @@ int ScriptEngine::framestep(Real dt) std::vector tmpQueue; stringExecutionQueue.pull(tmpQueue); std::vector::iterator it; - for (it=tmpQueue.begin(); it!=tmpQueue.end();it++) + for (it = tmpQueue.begin(); it != tmpQueue.end(); it++) { executeString(*it); } // framestep stuff below - if (frameStepFunctionPtr==nullptr) return 1; + if (frameStepFunctionPtr == nullptr) return 1; if (!engine) return 0; if (!context) context = engine->CreateContext(); context->Prepare(frameStepFunctionPtr); @@ -422,9 +713,9 @@ int ScriptEngine::framestep(Real dt) context->SetArgFloat(0, dt); int r = context->Execute(); - if ( r == AngelScript::asEXECUTION_FINISHED ) + if (r == AngelScript::asEXECUTION_FINISHED) { - // The return value is only valid if the execution finished successfully + // The return value is only valid if the execution finished successfully AngelScript::asDWORD ret = context->GetReturnDWord(); } return 0; @@ -432,39 +723,36 @@ int ScriptEngine::framestep(Real dt) int ScriptEngine::fireEvent(std::string instanceName, float intensity) { - if (!engine) - return 0; + if (!engine) return 0; - AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_CREATE_IF_NOT_EXISTS); - AngelScript::asIScriptFunction* func = mod->GetFunctionByDecl("void fireEvent(string, float)"); // TODO: this shouldn't be hard coded --neorej16 - if (func == nullptr) - return 0; // TODO: This function returns 0 no matter what - WTF? ~ only_a_ptr, 08/2017 + AngelScript::asIScriptModule * mod = engine->GetModule(moduleName, AngelScript::asGM_CREATE_IF_NOT_EXISTS); + AngelScript::asIScriptFunction *func = + mod->GetFunctionByDecl("void fireEvent(string, float)"); // TODO: this shouldn't be hard coded --neorej16 + if (func == nullptr) return 0; // TODO: This function returns 0 no matter what - WTF? ~ only_a_ptr, 08/2017 - if (!context) - context = engine->CreateContext(); + if (!context) context = engine->CreateContext(); context->Prepare(func); // Set the function arguments std::string *instance_name = new std::string(instanceName); context->SetArgObject(0, &instanceName); - context->SetArgFloat (1, intensity); + context->SetArgFloat(1, intensity); int r = context->Execute(); - if ( r == AngelScript::asEXECUTION_FINISHED ) + if (r == AngelScript::asEXECUTION_FINISHED) { - // The return value is only valid if the execution finished successfully + // The return value is only valid if the execution finished successfully AngelScript::asDWORD ret = context->GetReturnDWord(); } - delete(instance_name); + delete (instance_name); return 0; } int ScriptEngine::envokeCallback(int functionId, eventsource_t *source, node_t *node, int type) { - if (!engine) - return 0; // TODO: this function returns 0 no matter what - WTF? ~ only_a_ptr, 08/2017 + if (!engine) return 0; // TODO: this function returns 0 no matter what - WTF? ~ only_a_ptr, 08/2017 if (functionId <= 0 && (defaultEventCallbackFunctionPtr != nullptr)) { @@ -476,30 +764,29 @@ int ScriptEngine::envokeCallback(int functionId, eventsource_t *source, node_t * // no default callback available, discard the event return 0; } - if (!context) - context = engine->CreateContext(); + if (!context) context = engine->CreateContext(); context->Prepare(engine->GetFunctionById(functionId)); // Set the function arguments std::string *instance_name = new std::string(source->instancename); - std::string *boxname = new std::string(source->boxname); - context->SetArgDWord (0, type); + std::string *boxname = new std::string(source->boxname); + context->SetArgDWord(0, type); context->SetArgObject(1, instance_name); context->SetArgObject(2, boxname); if (node) - context->SetArgDWord (3, node->pos); + context->SetArgDWord(3, node->pos); else - context->SetArgDWord (3, -1); // conversion from 'int' to 'AngelScript::asDWORD', signed/unsigned mismatch! + context->SetArgDWord(3, -1); // conversion from 'int' to 'AngelScript::asDWORD', signed/unsigned mismatch! int r = context->Execute(); - if ( r == AngelScript::asEXECUTION_FINISHED ) + if (r == AngelScript::asEXECUTION_FINISHED) { - // The return value is only valid if the execution finished successfully + // The return value is only valid if the execution finished successfully AngelScript::asDWORD ret = context->GetReturnDWord(); } - delete(instance_name); - delete(boxname); + delete (instance_name); + delete (boxname); return 0; } @@ -511,38 +798,32 @@ void ScriptEngine::queueStringForExecution(const String command) int ScriptEngine::executeString(String command) { - if (!engine) - return 1; + if (!engine) return 1; - if (!context) - context = engine->CreateContext(); + if (!context) context = engine->CreateContext(); - AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_CREATE_IF_NOT_EXISTS); - int result = ExecuteString(engine, command.c_str(), mod, context); - if (result < 0) - { - SLOG("error " + TOSTRING(result) + " while executing string: " + command + "."); - } + AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_CREATE_IF_NOT_EXISTS); + int result = ExecuteString(engine, command.c_str(), mod, context); + if (result < 0) { SLOG("error " + TOSTRING(result) + " while executing string: " + command + "."); } return result; } int ScriptEngine::addFunction(const String &arg) { - if (!engine) - return 1; + if (!engine) return 1; - if (!context) - context = engine->CreateContext(); + if (!context) context = engine->CreateContext(); AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_CREATE_IF_NOT_EXISTS); AngelScript::asIScriptFunction *func = 0; - int r = mod->CompileFunction("addfunc", arg.c_str(), 0, AngelScript::asCOMP_ADD_TO_MODULE, &func); - - if ( r < 0 ) + int r = mod->CompileFunction("addfunc", arg.c_str(), 0, AngelScript::asCOMP_ADD_TO_MODULE, &func); + + if (r < 0) { char tmp[512] = ""; - snprintf(tmp, 512, "An error occurred while trying to add a function ('%s') to script module '%s'.", arg.c_str(), moduleName); + snprintf(tmp, 512, "An error occurred while trying to add a function ('%s') to script module '%s'.", arg.c_str(), + moduleName); SLOG(tmp); } else @@ -551,35 +832,31 @@ int ScriptEngine::addFunction(const String &arg) if (func == mod->GetFunctionByDecl("void frameStep(float)")) { - if (frameStepFunctionPtr == nullptr) - frameStepFunctionPtr = func; + if (frameStepFunctionPtr == nullptr) frameStepFunctionPtr = func; } else if (func == mod->GetFunctionByDecl("void eventCallback(int, int)")) { - if (eventCallbackFunctionPtr == nullptr) - eventCallbackFunctionPtr = func; + if (eventCallbackFunctionPtr == nullptr) eventCallbackFunctionPtr = func; } else if (func == mod->GetFunctionByDecl("void defaultEventCallback(int, string, string, int)")) { - if (defaultEventCallbackFunctionPtr == nullptr) - defaultEventCallbackFunctionPtr = func; + if (defaultEventCallbackFunctionPtr == nullptr) defaultEventCallbackFunctionPtr = func; } } // We must release the function object - if ( func ) - func->Release(); + if (func) func->Release(); return r; } int ScriptEngine::functionExists(const String &arg) { - if (!engine) // WTF? If the scripting engine failed to start, how would it invoke this function? - return -1; // ... OK, I guess the author wanted the fn. to be usable both within script and C++, but IMO that's bad design (generally good, but bad for a game.. bad for RoR), really ~ only_a_ptr, 09/2017 + if (!engine) // WTF? If the scripting engine failed to start, how would it invoke this function? + return -1; // ... OK, I guess the author wanted the fn. to be usable both within script and C++, but IMO that's bad design + // (generally good, but bad for a game.. bad for RoR), really ~ only_a_ptr, 09/2017 - if (!context) - context = engine->CreateContext(); // Same as above, I don't think this is a good design ~ only_a_ptr, 09/2017 + if (!context) context = engine->CreateContext(); // Same as above, I don't think this is a good design ~ only_a_ptr, 09/2017 AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_ONLY_IF_EXISTS); @@ -589,7 +866,7 @@ int ScriptEngine::functionExists(const String &arg) } else { - AngelScript::asIScriptFunction* fn = mod->GetFunctionByDecl(arg.c_str()); + AngelScript::asIScriptFunction *fn = mod->GetFunctionByDecl(arg.c_str()); if (fn != nullptr) return fn->GetId(); else @@ -599,23 +876,24 @@ int ScriptEngine::functionExists(const String &arg) int ScriptEngine::deleteFunction(const String &arg) { - if (!engine) - return AngelScript::asERROR; + if (!engine) return AngelScript::asERROR; - if (!context) - context = engine->CreateContext(); + if (!context) context = engine->CreateContext(); AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_ONLY_IF_EXISTS); - if ( mod == 0 || mod->GetFunctionCount() == 0 ) + if (mod == 0 || mod->GetFunctionCount() == 0) { char tmp[512] = ""; - sprintf(tmp, "An error occurred while trying to remove a function ('%s') from script module '%s': No functions have been added (and consequently: the function does not exist).", arg.c_str(), moduleName); + sprintf(tmp, + "An error occurred while trying to remove a function ('%s') from script module '%s': No functions have been " + "added (and consequently: the function does not exist).", + arg.c_str(), moduleName); SLOG(tmp); return AngelScript::asNO_FUNCTION; } - AngelScript::asIScriptFunction* func = mod->GetFunctionByDecl(arg.c_str()); + AngelScript::asIScriptFunction *func = mod->GetFunctionByDecl(arg.c_str()); if (func != nullptr) { // Warning: The function is not destroyed immediately, only when no more references point to it. @@ -627,21 +905,19 @@ int ScriptEngine::deleteFunction(const String &arg) // Check if we removed a "special" function - if ( frameStepFunctionPtr == func ) - frameStepFunctionPtr = nullptr; + if (frameStepFunctionPtr == func) frameStepFunctionPtr = nullptr; - if ( eventCallbackFunctionPtr == func ) - eventCallbackFunctionPtr = nullptr; + if (eventCallbackFunctionPtr == func) eventCallbackFunctionPtr = nullptr; - if ( defaultEventCallbackFunctionPtr == func ) - defaultEventCallbackFunctionPtr = nullptr; + if (defaultEventCallbackFunctionPtr == func) defaultEventCallbackFunctionPtr = nullptr; return func->GetId(); } else { char tmp[512] = ""; - sprintf(tmp, "An error occurred while trying to remove a function ('%s') from script module '%s'.", arg.c_str(), moduleName); + sprintf(tmp, "An error occurred while trying to remove a function ('%s') from script module '%s'.", arg.c_str(), + moduleName); SLOG(tmp); return AngelScript::asERROR; } @@ -654,7 +930,7 @@ int ScriptEngine::addVariable(const String &arg) AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_CREATE_IF_NOT_EXISTS); int r = mod->CompileGlobalVar("addvar", arg.c_str(), 0); - if ( r < 0 ) + if (r < 0) { char tmp[512] = ""; sprintf(tmp, "An error occurred while trying to add a variable ('%s') to script module '%s'.", arg.c_str(), moduleName); @@ -670,23 +946,24 @@ int ScriptEngine::deleteVariable(const String &arg) if (!context) context = engine->CreateContext(); AngelScript::asIScriptModule *mod = engine->GetModule(moduleName, AngelScript::asGM_ONLY_IF_EXISTS); - if ( mod == 0 || mod->GetGlobalVarCount() == 0 ) + if (mod == 0 || mod->GetGlobalVarCount() == 0) { char tmp[512] = ""; - sprintf(tmp, "An error occurred while trying to remove a variable ('%s') from script module '%s': No variables have been added (and consequently: the variable does not exist).", arg.c_str(), moduleName); + sprintf(tmp, + "An error occurred while trying to remove a variable ('%s') from script module '%s': No variables have been " + "added (and consequently: the variable does not exist).", + arg.c_str(), moduleName); SLOG(tmp); return AngelScript::asNO_GLOBAL_VAR; } int index = mod->GetGlobalVarIndexByName(arg.c_str()); - if ( index >= 0 ) - { - index = mod->RemoveGlobalVar(index); - } + if (index >= 0) { index = mod->RemoveGlobalVar(index); } else { char tmp[512] = ""; - sprintf(tmp, "An error occurred while trying to remove a variable ('%s') from script module '%s'.", arg.c_str(), moduleName); + sprintf(tmp, "An error occurred while trying to remove a variable ('%s') from script module '%s'.", arg.c_str(), + moduleName); SLOG(tmp); } @@ -696,7 +973,7 @@ int ScriptEngine::deleteVariable(const String &arg) void ScriptEngine::triggerEvent(int eventnum, int value) { if (!engine) return; - if (eventCallbackFunctionPtr==nullptr) return; + if (eventCallbackFunctionPtr == nullptr) return; if (eventMask & eventnum) { // script registered for that event, so sent it @@ -708,9 +985,9 @@ void ScriptEngine::triggerEvent(int eventnum, int value) context->SetArgDWord(1, value); int r = context->Execute(); - if ( r == AngelScript::asEXECUTION_FINISHED ) + if (r == AngelScript::asEXECUTION_FINISHED) { - // The return value is only valid if the execution finished successfully + // The return value is only valid if the execution finished successfully AngelScript::asDWORD ret = context->GetReturnDWord(); } return; @@ -722,7 +999,7 @@ int ScriptEngine::loadScript(String _scriptName) scriptName = _scriptName; // Load the entire script file into the buffer - int result=0; + int result = 0; // The builder is a helper class that will load the script file, // search for #include directives, and load any included files as @@ -732,7 +1009,7 @@ int ScriptEngine::loadScript(String _scriptName) AngelScript::asIScriptModule *mod = 0; result = builder.StartNewModule(engine, moduleName); - if ( result < 0 ) + if (result < 0) { SLOG("Failed to start new module"); return result; @@ -741,14 +1018,14 @@ int ScriptEngine::loadScript(String _scriptName) mod = engine->GetModule(moduleName, AngelScript::asGM_ONLY_IF_EXISTS); result = builder.AddSectionFromFile(scriptName.c_str()); - if ( result < 0 ) + if (result < 0) { - SLOG("Unkown error while loading script file: "+scriptName); + SLOG("Unkown error while loading script file: " + scriptName); SLOG("Failed to add script file"); return result; } result = builder.BuildModule(); - if ( result < 0 ) + if (result < 0) { SLOG("Failed to build the module"); return result; @@ -765,7 +1042,7 @@ int ScriptEngine::loadScript(String _scriptName) // Find the function that is to be called. auto main_func = mod->GetFunctionByDecl("void main()"); - if ( main_func == nullptr ) + if (main_func == nullptr) { // The function couldn't be found. Instruct the script writer to include the // expected function in the script. @@ -791,20 +1068,19 @@ int ScriptEngine::loadScript(String _scriptName) SLOG("Executing main()"); result = context->Execute(); - if ( result != AngelScript::asEXECUTION_FINISHED ) + if (result != AngelScript::asEXECUTION_FINISHED) { // The execution didn't complete as expected. Determine what happened. - if ( result == AngelScript::asEXECUTION_ABORTED ) - { - SLOG("The script was aborted before it could finish. Probably it timed out."); - } - else if ( result == AngelScript::asEXECUTION_EXCEPTION ) + if (result == AngelScript::asEXECUTION_ABORTED) + { SLOG("The script was aborted before it could finish. Probably it timed out."); } + else if (result == AngelScript::asEXECUTION_EXCEPTION) { // An exception occurred, let the script writer know what happened so it can be corrected. - SLOG("An exception '" + String(context->GetExceptionString()) + "' occurred. Please correct the code in file '" + scriptName + "' and try again."); + SLOG("An exception '" + String(context->GetExceptionString()) + "' occurred. Please correct the code in file '" + + scriptName + "' and try again."); // Write some information about the script exception - AngelScript::asIScriptFunction* func = context->GetExceptionFunction(); + AngelScript::asIScriptFunction *func = context->GetExceptionFunction(); SLOG("func: " + String(func->GetDeclaration())); SLOG("modl: " + String(func->GetModuleName())); SLOG("sect: " + String(func->GetScriptSectionName())); @@ -824,7 +1100,6 @@ int ScriptEngine::loadScript(String _scriptName) return 0; } - StringVector ScriptEngine::getAutoComplete(String command) { StringVector result; @@ -844,16 +1119,11 @@ StringVector ScriptEngine::getAutoComplete(String command) result.push_back(String(desc->GetName())); } - for (unsigned int i = 0; i < engine->GetGlobalPropertyCount(); i++) { const char *name; - if (!engine->GetGlobalPropertyByIndex(i, &name)) - { - result.push_back(String(name)); - } - + if (!engine->GetGlobalPropertyByIndex(i, &name)) { result.push_back(String(name)); } } if (!command.empty()) @@ -862,10 +1132,7 @@ StringVector ScriptEngine::getAutoComplete(String command) // now check if we hit anything for (unsigned int i = 0; i < result.size(); i++) { - if (result[i].substr(0, command.size()) == command) - { - res2.push_back(result[i]); - } + if (result[i].substr(0, command.size()) == command) { res2.push_back(result[i]); } } if (command.find(".") != command.npos) diff --git a/source/main/scripting/ScriptEngine.h b/source/main/scripting/ScriptEngine.h index 8a485ef5b5..7b2cb75a5e 100644 --- a/source/main/scripting/ScriptEngine.h +++ b/source/main/scripting/ScriptEngine.h @@ -27,15 +27,13 @@ #ifdef USE_ANGELSCRIPT -#include + #include "InterThreadStoreVector.h" + #include "RoRPrerequisites.h" + #include "Singleton.h" + #include "scriptbuilder/scriptbuilder.h" + #include "scriptdictionary/scriptdictionary.h" -#include "RoRPrerequisites.h" - -#include "InterThreadStoreVector.h" -#include "Singleton.h" - -#include "scriptdictionary/scriptdictionary.h" -#include "scriptbuilder/scriptbuilder.h" + #include /** * @file ScriptEngine.h @@ -53,9 +51,8 @@ class ScriptEngine : public RoRSingletonNoCreation, public Ogre::L { friend class GameScript; -public: - - ScriptEngine(Collisions* _coll = nullptr); + public: + ScriptEngine(Collisions *_coll = nullptr); ~ScriptEngine(); /** @@ -99,65 +96,80 @@ class ScriptEngine : public RoRSingletonNoCreation, public Ogre::L /** * Adds a global function to the script * @param arg A declaration for the function. - */ - int addFunction(const Ogre::String& arg); + */ + int addFunction(const Ogre::String &arg); /** * Checks if a global function exists * @param arg A declaration for the function. - */ - int functionExists(const Ogre::String& arg); + */ + int functionExists(const Ogre::String &arg); /** * Deletes a global function from the script * @param arg A declaration for the function. - */ - int deleteFunction(const Ogre::String& arg); + */ + int deleteFunction(const Ogre::String &arg); /** * Adds a global variable to the script * @param arg A declaration for the variable. - */ - int addVariable(const Ogre::String& arg); + */ + int addVariable(const Ogre::String &arg); /** * Deletes a global variable from the script * @param arg A declaration for the variable. - */ - int deleteVariable(const Ogre::String& arg); + */ + int deleteVariable(const Ogre::String &arg); Ogre::StringVector getAutoComplete(Ogre::String command); int fireEvent(std::string instanceName, float intensity); - int envokeCallback(int functionId, eventsource_t* source, node_t* node = 0, int type = 0); + int envokeCallback(int functionId, eventsource_t *source, node_t *node = 0, int type = 0); - AngelScript::asIScriptEngine* getEngine() { return engine; }; + AngelScript::asIScriptEngine *getEngine() + { + return engine; + }; - Ogre::String getScriptName() { return scriptName; }; - Ogre::String getScriptHash() { return scriptHash; }; + Ogre::String getScriptName() + { + return scriptName; + }; + Ogre::String getScriptHash() + { + return scriptHash; + }; // method from Ogre::LogListener - void messageLogged(const Ogre::String& message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String& logName, bool& skipThisMessage); - - inline void SLOG(const char* msg) { this->scriptLog->logMessage(msg); } ///< Replacement of macro - inline void SLOG(std::string msg) { this->scriptLog->logMessage(msg); } ///< Replacement of macro - -protected: - - Collisions* coll; - AngelScript::asIScriptEngine* engine; //!< instance of the scripting engine - AngelScript::asIScriptContext* context; //!< context in which all scripting happens - AngelScript::asIScriptFunction* frameStepFunctionPtr; //!< script function pointer to the frameStep function - AngelScript::asIScriptFunction* eventCallbackFunctionPtr; //!< script function pointer to the event callback function - AngelScript::asIScriptFunction* defaultEventCallbackFunctionPtr; //!< script function pointer for spawner events - Ogre::String scriptName; - Ogre::String scriptHash; - Ogre::Log* scriptLog; + void messageLogged(const Ogre::String &message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String &logName, + bool &skipThisMessage); + + inline void SLOG(const char *msg) + { + this->scriptLog->logMessage(msg); + } ///< Replacement of macro + inline void SLOG(std::string msg) + { + this->scriptLog->logMessage(msg); + } ///< Replacement of macro + + protected: + Collisions * coll; + AngelScript::asIScriptEngine * engine; //!< instance of the scripting engine + AngelScript::asIScriptContext * context; //!< context in which all scripting happens + AngelScript::asIScriptFunction *frameStepFunctionPtr; //!< script function pointer to the frameStep function + AngelScript::asIScriptFunction *eventCallbackFunctionPtr; //!< script function pointer to the event callback function + AngelScript::asIScriptFunction *defaultEventCallbackFunctionPtr; //!< script function pointer for spawner events + Ogre::String scriptName; + Ogre::String scriptHash; + Ogre::Log * scriptLog; InterThreadStoreVector stringExecutionQueue; //!< The string execution queue \see queueStringForExecution - static const char* moduleName; + static const char *moduleName; /** * This function initialzies the engine and registeres all types @@ -169,7 +181,7 @@ class ScriptEngine : public RoRSingletonNoCreation, public Ogre::L * When the script crashes, this function will provide you with more detail * @param msg arguments that contain details about the crash */ - void msgCallback(const AngelScript::asSMessageInfo* msg); + void msgCallback(const AngelScript::asSMessageInfo *msg); }; #endif // USE_ANGELSCRIPT diff --git a/source/main/terrain/IHeightFinder.h b/source/main/terrain/IHeightFinder.h index dca68e15e9..8d592ed053 100644 --- a/source/main/terrain/IHeightFinder.h +++ b/source/main/terrain/IHeightFinder.h @@ -2,4 +2,3 @@ // ======= TO BE DELETED ======= // File temporarily kept as placeholder to avoid modifying CMake scripts (and subsequently re-generating MSVC projects) - diff --git a/source/main/terrain/OgreTerrainPSSMMaterialGenerator.cpp b/source/main/terrain/OgreTerrainPSSMMaterialGenerator.cpp index 0585dfb52a..792708f3f1 100644 --- a/source/main/terrain/OgreTerrainPSSMMaterialGenerator.cpp +++ b/source/main/terrain/OgreTerrainPSSMMaterialGenerator.cpp @@ -27,1725 +27,1534 @@ THE SOFTWARE. */ #include "OgreTerrainPSSMMaterialGenerator.h" -#include -#include -#include -#include -#include #include -#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include -namespace Ogre { -//--------------------------------------------------------------------- -TerrainPSSMMaterialGenerator::TerrainPSSMMaterialGenerator() -{ - // define the layers - // We expect terrain textures to have no alpha, so we use the alpha channel - // in the albedo texture to store specular reflection - // similarly we double-up the normal and height (for parallax) - mLayerDecl.samplers.push_back(TerrainLayerSampler("albedo_specular", PF_BYTE_RGBA)); - mLayerDecl.samplers.push_back(TerrainLayerSampler("normal_height", PF_BYTE_RGBA)); - - mLayerDecl.elements.push_back( - TerrainLayerSamplerElement(0, TLSS_ALBEDO, 0, 3)); - mLayerDecl.elements.push_back( - TerrainLayerSamplerElement(0, TLSS_SPECULAR, 3, 1)); - mLayerDecl.elements.push_back( - TerrainLayerSamplerElement(1, TLSS_NORMAL, 0, 3)); - mLayerDecl.elements.push_back( - TerrainLayerSamplerElement(1, TLSS_HEIGHT, 3, 1)); - - mProfiles.push_back(OGRE_NEW SM2Profile(this, "SM2", "Profile for rendering on Shader Model 2 capable cards")); - // TODO - check hardware capabilities & use fallbacks if required (more profiles needed) - setActiveProfile("SM2"); -} - -//--------------------------------------------------------------------- -TerrainPSSMMaterialGenerator::~TerrainPSSMMaterialGenerator() -{ -} - -//--------------------------------------------------------------------- -//--------------------------------------------------------------------- -TerrainPSSMMaterialGenerator::SM2Profile::SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc) - : Profile(parent, name, desc) - , mShaderGen(0) - , mLayerNormalMappingEnabled(true) - , mLayerParallaxMappingEnabled(true) - , mLayerSpecularMappingEnabled(true) - , mGlobalColourMapEnabled(true) - , mLightmapEnabled(true) - , mCompositeMapEnabled(true) - , mReceiveDynamicShadows(true) - , mPSSM(0) - , mDepthShadows(false) - , mLowLodShadows(false) +namespace Ogre { -} + //--------------------------------------------------------------------- + TerrainPSSMMaterialGenerator::TerrainPSSMMaterialGenerator() + { + // define the layers + // We expect terrain textures to have no alpha, so we use the alpha channel + // in the albedo texture to store specular reflection + // similarly we double-up the normal and height (for parallax) + mLayerDecl.samplers.push_back(TerrainLayerSampler("albedo_specular", PF_BYTE_RGBA)); + mLayerDecl.samplers.push_back(TerrainLayerSampler("normal_height", PF_BYTE_RGBA)); -//--------------------------------------------------------------------- -TerrainPSSMMaterialGenerator::SM2Profile::~SM2Profile() -{ - OGRE_DELETE mShaderGen; -} + mLayerDecl.elements.push_back(TerrainLayerSamplerElement(0, TLSS_ALBEDO, 0, 3)); + mLayerDecl.elements.push_back(TerrainLayerSamplerElement(0, TLSS_SPECULAR, 3, 1)); + mLayerDecl.elements.push_back(TerrainLayerSamplerElement(1, TLSS_NORMAL, 0, 3)); + mLayerDecl.elements.push_back(TerrainLayerSamplerElement(1, TLSS_HEIGHT, 3, 1)); -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::requestOptions(Terrain* terrain) -{ - terrain->_setMorphRequired(true); - terrain->_setNormalMapRequired(true); - terrain->_setLightMapRequired(mLightmapEnabled, true); - terrain->_setCompositeMapRequired(mCompositeMapEnabled); -} - -//--------------------------------------------------------------------- -bool TerrainPSSMMaterialGenerator::SM2Profile::isVertexCompressionSupported() const -{ - return true; -} + mProfiles.push_back(OGRE_NEW SM2Profile(this, "SM2", "Profile for rendering on Shader Model 2 capable cards")); + // TODO - check hardware capabilities & use fallbacks if required (more profiles needed) + setActiveProfile("SM2"); + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setLayerNormalMappingEnabled(bool enabled) -{ - if (enabled != mLayerNormalMappingEnabled) + //--------------------------------------------------------------------- + TerrainPSSMMaterialGenerator::~TerrainPSSMMaterialGenerator() { - mLayerNormalMappingEnabled = enabled; - mParent->_markChanged(); } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setLayerParallaxMappingEnabled(bool enabled) -{ - if (enabled != mLayerParallaxMappingEnabled) + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + TerrainPSSMMaterialGenerator::SM2Profile::SM2Profile(TerrainMaterialGenerator *parent, const String &name, const String &desc) + : Profile(parent, name, desc), mShaderGen(0), mLayerNormalMappingEnabled(true), mLayerParallaxMappingEnabled(true), + mLayerSpecularMappingEnabled(true), mGlobalColourMapEnabled(true), mLightmapEnabled(true), mCompositeMapEnabled(true), + mReceiveDynamicShadows(true), mPSSM(0), mDepthShadows(false), mLowLodShadows(false) { - mLayerParallaxMappingEnabled = enabled; - mParent->_markChanged(); } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setLayerSpecularMappingEnabled(bool enabled) -{ - if (enabled != mLayerSpecularMappingEnabled) + //--------------------------------------------------------------------- + TerrainPSSMMaterialGenerator::SM2Profile::~SM2Profile() { - mLayerSpecularMappingEnabled = enabled; - mParent->_markChanged(); + OGRE_DELETE mShaderGen; } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setGlobalColourMapEnabled(bool enabled) -{ - if (enabled != mGlobalColourMapEnabled) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::requestOptions(Terrain *terrain) { - mGlobalColourMapEnabled = enabled; - mParent->_markChanged(); + terrain->_setMorphRequired(true); + terrain->_setNormalMapRequired(true); + terrain->_setLightMapRequired(mLightmapEnabled, true); + terrain->_setCompositeMapRequired(mCompositeMapEnabled); } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setLightmapEnabled(bool enabled) -{ - if (enabled != mLightmapEnabled) + //--------------------------------------------------------------------- + bool TerrainPSSMMaterialGenerator::SM2Profile::isVertexCompressionSupported() const { - mLightmapEnabled = enabled; - mParent->_markChanged(); + return true; } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setCompositeMapEnabled(bool enabled) -{ - if (enabled != mCompositeMapEnabled) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setLayerNormalMappingEnabled(bool enabled) { - mCompositeMapEnabled = enabled; - mParent->_markChanged(); + if (enabled != mLayerNormalMappingEnabled) + { + mLayerNormalMappingEnabled = enabled; + mParent->_markChanged(); + } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsEnabled(bool enabled) -{ - if (enabled != mReceiveDynamicShadows) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setLayerParallaxMappingEnabled(bool enabled) { - mReceiveDynamicShadows = enabled; - mParent->_markChanged(); + if (enabled != mLayerParallaxMappingEnabled) + { + mLayerParallaxMappingEnabled = enabled; + mParent->_markChanged(); + } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings) -{ - if (pssmSettings != mPSSM) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setLayerSpecularMappingEnabled(bool enabled) { - mPSSM = pssmSettings; - mParent->_markChanged(); + if (enabled != mLayerSpecularMappingEnabled) + { + mLayerSpecularMappingEnabled = enabled; + mParent->_markChanged(); + } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsDepth(bool enabled) -{ - if (enabled != mDepthShadows) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setGlobalColourMapEnabled(bool enabled) { - mDepthShadows = enabled; - mParent->_markChanged(); + if (enabled != mGlobalColourMapEnabled) + { + mGlobalColourMapEnabled = enabled; + mParent->_markChanged(); + } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsLowLod(bool enabled) -{ - if (enabled != mLowLodShadows) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setLightmapEnabled(bool enabled) { - mLowLodShadows = enabled; - mParent->_markChanged(); + if (enabled != mLightmapEnabled) + { + mLightmapEnabled = enabled; + mParent->_markChanged(); + } } -} -//--------------------------------------------------------------------- -uint8 TerrainPSSMMaterialGenerator::SM2Profile::getMaxLayers(const Terrain* terrain) const -{ - // count the texture units free - uint8 freeTextureUnits = 16; - // lightmap - --freeTextureUnits; - // normalmap - --freeTextureUnits; - // colourmap - if (terrain->getGlobalColourMapEnabled()) - --freeTextureUnits; - if (isShadowingEnabled(HIGH_LOD, terrain)) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setCompositeMapEnabled(bool enabled) { - uint numShadowTextures = 1; - if (getReceiveDynamicShadowsPSSM()) + if (enabled != mCompositeMapEnabled) { - numShadowTextures = getReceiveDynamicShadowsPSSM()->getSplitCount(); + mCompositeMapEnabled = enabled; + mParent->_markChanged(); } - freeTextureUnits -= numShadowTextures; } - // each layer needs 2.25 units (1xdiffusespec, 1xnormalheight, 0.25xblend) - return static_cast(freeTextureUnits / 2.16f); -} - -//--------------------------------------------------------------------- -MaterialPtr TerrainPSSMMaterialGenerator::SM2Profile::generate(const Terrain* terrain) -{ - // re-use old material if exists - MaterialPtr mat = terrain->_getMaterial(); - if (mat.isNull()) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsEnabled(bool enabled) { - MaterialManager& matMgr = MaterialManager::getSingleton(); - - // it's important that the names are deterministic for a given terrain, so - // use the terrain pointer as an ID - const String& matName = terrain->getMaterialName(); - mat = matMgr.getByName(matName); - if (mat.isNull()) + if (enabled != mReceiveDynamicShadows) { - mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + mReceiveDynamicShadows = enabled; + mParent->_markChanged(); } } - // clear everything - mat->removeAllTechniques(); - - // Automatically disable normal & parallax mapping if card cannot handle it - // We do this rather than having a specific technique for it since it's simpler - GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); - if (!gmgr.isSyntaxSupported("ps_4_0") && !gmgr.isSyntaxSupported("ps_3_0") && !gmgr.isSyntaxSupported("ps_2_x") - && !gmgr.isSyntaxSupported("fp40") && !gmgr.isSyntaxSupported("arbfp1")) + + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup *pssmSettings) { - setLayerNormalMappingEnabled(false); - setLayerParallaxMappingEnabled(false); + if (pssmSettings != mPSSM) + { + mPSSM = pssmSettings; + mParent->_markChanged(); + } } - addTechnique(mat, terrain, HIGH_LOD); + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsDepth(bool enabled) + { + if (enabled != mDepthShadows) + { + mDepthShadows = enabled; + mParent->_markChanged(); + } + } - // LOD - if (mCompositeMapEnabled) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::setReceiveDynamicShadowsLowLod(bool enabled) { - addTechnique(mat, terrain, LOW_LOD); - Material::LodValueList lodValues; - lodValues.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance()); - mat->setLodLevels(lodValues); - Technique* lowLodTechnique = mat->getTechnique(1); - lowLodTechnique->setLodIndex(1); + if (enabled != mLowLodShadows) + { + mLowLodShadows = enabled; + mParent->_markChanged(); + } } - updateParams(mat, terrain); + //--------------------------------------------------------------------- + uint8 TerrainPSSMMaterialGenerator::SM2Profile::getMaxLayers(const Terrain *terrain) const + { + // count the texture units free + uint8 freeTextureUnits = 16; + // lightmap + --freeTextureUnits; + // normalmap + --freeTextureUnits; + // colourmap + if (terrain->getGlobalColourMapEnabled()) --freeTextureUnits; + if (isShadowingEnabled(HIGH_LOD, terrain)) + { + uint numShadowTextures = 1; + if (getReceiveDynamicShadowsPSSM()) { numShadowTextures = getReceiveDynamicShadowsPSSM()->getSplitCount(); } + freeTextureUnits -= numShadowTextures; + } - return mat; -} + // each layer needs 2.25 units (1xdiffusespec, 1xnormalheight, 0.25xblend) + return static_cast(freeTextureUnits / 2.16f); + } -//--------------------------------------------------------------------- -MaterialPtr TerrainPSSMMaterialGenerator::SM2Profile::generateForCompositeMap(const Terrain* terrain) -{ - // re-use old material if exists - MaterialPtr mat = terrain->_getCompositeMapMaterial(); - if (mat.isNull()) + //--------------------------------------------------------------------- + MaterialPtr TerrainPSSMMaterialGenerator::SM2Profile::generate(const Terrain *terrain) { - MaterialManager& matMgr = MaterialManager::getSingleton(); - - // it's important that the names are deterministic for a given terrain, so - // use the terrain pointer as an ID - const String& matName = terrain->getMaterialName() + "/comp"; - mat = matMgr.getByName(matName); + // re-use old material if exists + MaterialPtr mat = terrain->_getMaterial(); if (mat.isNull()) { - mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - } - } - // clear everything - mat->removeAllTechniques(); + MaterialManager &matMgr = MaterialManager::getSingleton(); - addTechnique(mat, terrain, RENDER_COMPOSITE_MAP); + // it's important that the names are deterministic for a given terrain, so + // use the terrain pointer as an ID + const String &matName = terrain->getMaterialName(); + mat = matMgr.getByName(matName); + if (mat.isNull()) { mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } + } + // clear everything + mat->removeAllTechniques(); + + // Automatically disable normal & parallax mapping if card cannot handle it + // We do this rather than having a specific technique for it since it's simpler + GpuProgramManager &gmgr = GpuProgramManager::getSingleton(); + if (!gmgr.isSyntaxSupported("ps_4_0") && !gmgr.isSyntaxSupported("ps_3_0") && !gmgr.isSyntaxSupported("ps_2_x") && + !gmgr.isSyntaxSupported("fp40") && !gmgr.isSyntaxSupported("arbfp1")) + { + setLayerNormalMappingEnabled(false); + setLayerParallaxMappingEnabled(false); + } - updateParamsForCompositeMap(mat, terrain); + addTechnique(mat, terrain, HIGH_LOD); - return mat; -} + // LOD + if (mCompositeMapEnabled) + { + addTechnique(mat, terrain, LOW_LOD); + Material::LodValueList lodValues; + lodValues.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance()); + mat->setLodLevels(lodValues); + Technique *lowLodTechnique = mat->getTechnique(1); + lowLodTechnique->setLodIndex(1); + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::addTechnique( - const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt) -{ - Technique* tech = mat->createTechnique(); + updateParams(mat, terrain); - // Only supporting one pass - Pass* pass = tech->createPass(); + return mat; + } - GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); - HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton(); - if (!mShaderGen) + //--------------------------------------------------------------------- + MaterialPtr TerrainPSSMMaterialGenerator::SM2Profile::generateForCompositeMap(const Terrain *terrain) { - bool check2x = mLayerNormalMappingEnabled || mLayerParallaxMappingEnabled; - if (hmgr.isLanguageSupported("cg")) - mShaderGen = OGRE_NEW ShaderHelperCg(); - else if (hmgr.isLanguageSupported("hlsl") && - ((check2x && gmgr.isSyntaxSupported("ps_4_0")) || - (check2x && gmgr.isSyntaxSupported("ps_2_x")) || - (!check2x && gmgr.isSyntaxSupported("ps_2_0")))) - mShaderGen = OGRE_NEW ShaderHelperHLSL(); - else if (hmgr.isLanguageSupported("glsl")) - mShaderGen = OGRE_NEW ShaderHelperGLSL(); - else if (hmgr.isLanguageSupported("glsles")) - mShaderGen = OGRE_NEW ShaderHelperGLSLES(); - else + // re-use old material if exists + MaterialPtr mat = terrain->_getCompositeMapMaterial(); + if (mat.isNull()) { - // todo + MaterialManager &matMgr = MaterialManager::getSingleton(); + + // it's important that the names are deterministic for a given terrain, so + // use the terrain pointer as an ID + const String &matName = terrain->getMaterialName() + "/comp"; + mat = matMgr.getByName(matName); + if (mat.isNull()) { mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } } + // clear everything + mat->removeAllTechniques(); - // check SM3 features - mSM3Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0"); - mSM4Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"); - } - HighLevelGpuProgramPtr vprog = mShaderGen->generateVertexProgram(this, terrain, tt); - HighLevelGpuProgramPtr fprog = mShaderGen->generateFragmentProgram(this, terrain, tt); + addTechnique(mat, terrain, RENDER_COMPOSITE_MAP); + + updateParamsForCompositeMap(mat, terrain); - pass->setVertexProgram(vprog->getName()); - pass->setFragmentProgram(fprog->getName()); + return mat; + } - if (tt == HIGH_LOD || tt == RENDER_COMPOSITE_MAP) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::addTechnique(const MaterialPtr &mat, const Terrain *terrain, TechniqueType tt) { - // global normal map - TextureUnitState* tu = pass->createTextureUnitState(); - tu->setTextureName(terrain->getTerrainNormalMap()->getName()); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + Technique *tech = mat->createTechnique(); + + // Only supporting one pass + Pass *pass = tech->createPass(); - // global colour map - if (terrain->getGlobalColourMapEnabled() && isGlobalColourMapEnabled()) + GpuProgramManager & gmgr = GpuProgramManager::getSingleton(); + HighLevelGpuProgramManager &hmgr = HighLevelGpuProgramManager::getSingleton(); + if (!mShaderGen) { - tu = pass->createTextureUnitState(terrain->getGlobalColourMap()->getName()); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + bool check2x = mLayerNormalMappingEnabled || mLayerParallaxMappingEnabled; + if (hmgr.isLanguageSupported("cg")) + mShaderGen = OGRE_NEW ShaderHelperCg(); + else if (hmgr.isLanguageSupported("hlsl") && + ((check2x && gmgr.isSyntaxSupported("ps_4_0")) || (check2x && gmgr.isSyntaxSupported("ps_2_x")) || + (!check2x && gmgr.isSyntaxSupported("ps_2_0")))) + mShaderGen = OGRE_NEW ShaderHelperHLSL(); + else if (hmgr.isLanguageSupported("glsl")) + mShaderGen = OGRE_NEW ShaderHelperGLSL(); + else if (hmgr.isLanguageSupported("glsles")) + mShaderGen = OGRE_NEW ShaderHelperGLSLES(); + else + { + // todo + } + + // check SM3 features + mSM3Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0"); + mSM4Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"); } + HighLevelGpuProgramPtr vprog = mShaderGen->generateVertexProgram(this, terrain, tt); + HighLevelGpuProgramPtr fprog = mShaderGen->generateFragmentProgram(this, terrain, tt); + + pass->setVertexProgram(vprog->getName()); + pass->setFragmentProgram(fprog->getName()); - // light map - if (isLightmapEnabled()) + if (tt == HIGH_LOD || tt == RENDER_COMPOSITE_MAP) { - tu = pass->createTextureUnitState(terrain->getLightmap()->getName()); + // global normal map + TextureUnitState *tu = pass->createTextureUnitState(); + tu->setTextureName(terrain->getTerrainNormalMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - } - // blend maps - uint maxLayers = getMaxLayers(terrain); - uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - for (uint i = 0; i < numBlendTextures; ++i) + // global colour map + if (terrain->getGlobalColourMapEnabled() && isGlobalColourMapEnabled()) + { + tu = pass->createTextureUnitState(terrain->getGlobalColourMap()->getName()); + tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + } + + // light map + if (isLightmapEnabled()) + { + tu = pass->createTextureUnitState(terrain->getLightmap()->getName()); + tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + } + + // blend maps + uint maxLayers = getMaxLayers(terrain); + uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + for (uint i = 0; i < numBlendTextures; ++i) + { + tu = pass->createTextureUnitState(terrain->getBlendTextureName(i)); + tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + } + + // layer textures + for (uint i = 0; i < numLayers; ++i) + { + // diffuse / specular + pass->createTextureUnitState(terrain->getLayerTextureName(i, 0)); + // normal / height + pass->createTextureUnitState(terrain->getLayerTextureName(i, 1)); + } + } + else { - tu = pass->createTextureUnitState(terrain->getBlendTextureName(i)); + // LOW_LOD textures + // composite map + TextureUnitState *tu = pass->createTextureUnitState(); + tu->setTextureName(terrain->getCompositeMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + + // That's it! } - // layer textures - for (uint i = 0; i < numLayers; ++i) + // Add shadow textures (always at the end) + if (isShadowingEnabled(tt, terrain)) { - // diffuse / specular - pass->createTextureUnitState(terrain->getLayerTextureName(i, 0)); - // normal / height - pass->createTextureUnitState(terrain->getLayerTextureName(i, 1)); + uint numTextures = 1; + if (getReceiveDynamicShadowsPSSM()) { numTextures = getReceiveDynamicShadowsPSSM()->getSplitCount(); } + for (uint i = 0; i < numTextures; ++i) + { + TextureUnitState *tu = pass->createTextureUnitState(); + tu->setContentType(TextureUnitState::CONTENT_SHADOW); + tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER); + tu->setTextureBorderColour(ColourValue::White); + } } } - else - { - // LOW_LOD textures - // composite map - TextureUnitState* tu = pass->createTextureUnitState(); - tu->setTextureName(terrain->getCompositeMap()->getName()); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - // That's it! + //--------------------------------------------------------------------- + bool TerrainPSSMMaterialGenerator::SM2Profile::isShadowingEnabled(TechniqueType tt, const Terrain *terrain) const + { + return getReceiveDynamicShadowsEnabled() && tt != RENDER_COMPOSITE_MAP && (tt != LOW_LOD || mLowLodShadows) && + terrain->getSceneManager()->isShadowTechniqueTextureBased(); } - // Add shadow textures (always at the end) - if (isShadowingEnabled(tt, terrain)) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::updateParams(const MaterialPtr &mat, const Terrain *terrain) { - uint numTextures = 1; - if (getReceiveDynamicShadowsPSSM()) - { - numTextures = getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - for (uint i = 0; i < numTextures; ++i) - { - TextureUnitState* tu = pass->createTextureUnitState(); - tu->setContentType(TextureUnitState::CONTENT_SHADOW); - tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER); - tu->setTextureBorderColour(ColourValue::White); - } + mShaderGen->updateParams(this, mat, terrain, false); } -} - -//--------------------------------------------------------------------- -bool TerrainPSSMMaterialGenerator::SM2Profile::isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const -{ - return getReceiveDynamicShadowsEnabled() && tt != RENDER_COMPOSITE_MAP && - (tt != LOW_LOD || mLowLodShadows) && - terrain->getSceneManager()->isShadowTechniqueTextureBased(); -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::updateParams(const MaterialPtr& mat, const Terrain* terrain) -{ - mShaderGen->updateParams(this, mat, terrain, false); -} + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::updateParamsForCompositeMap(const MaterialPtr &mat, const Terrain *terrain) + { + mShaderGen->updateParams(this, mat, terrain, true); + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain) -{ - mShaderGen->updateParams(this, mat, terrain, true); -} - -//--------------------------------------------------------------------- -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramPtr ret = createVertexProgram(prof, terrain, tt); + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateVertexProgram(const SM2Profile *prof, + const Terrain *terrain, + TechniqueType tt) + { + HighLevelGpuProgramPtr ret = createVertexProgram(prof, terrain, tt); - StringUtil::StrStreamType sourceStr; - generateVertexProgramSource(prof, terrain, tt, sourceStr); - ret->setSource(sourceStr.str()); - ret->load(); - defaultVpParams(prof, terrain, tt, ret); + StringUtil::StrStreamType sourceStr; + generateVertexProgramSource(prof, terrain, tt, sourceStr); + ret->setSource(sourceStr.str()); + ret->load(); + defaultVpParams(prof, terrain, tt, ret); #if OGRE_DEBUG_MODE - LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Vertex Program: " - << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; + LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Vertex Program: " << ret->getName() << " ***\n" + << ret->getSource() << "\n*** ***"; #endif - return ret; -} + return ret; + } -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramPtr ret = createFragmentProgram(prof, terrain, tt); + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateFragmentProgram(const SM2Profile *prof, + const Terrain *terrain, + TechniqueType tt) + { + HighLevelGpuProgramPtr ret = createFragmentProgram(prof, terrain, tt); - StringUtil::StrStreamType sourceStr; - generateFragmentProgramSource(prof, terrain, tt, sourceStr); - ret->setSource(sourceStr.str()); - ret->load(); - defaultFpParams(prof, terrain, tt, ret); + StringUtil::StrStreamType sourceStr; + generateFragmentProgramSource(prof, terrain, tt, sourceStr); + ret->setSource(sourceStr.str()); + ret->load(); + defaultFpParams(prof, terrain, tt, ret); #if OGRE_DEBUG_MODE - LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Fragment Program: " - << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; + LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Fragment Program: " << ret->getName() << " ***\n" + << ret->getSource() << "\n*** ***"; #endif - return ret; -} - -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateVertexProgramSource( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - generateVpHeader(prof, terrain, tt, outStream); + return ret; + } - if (tt != LOW_LOD) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateVertexProgramSource(const SM2Profile * prof, + const Terrain * terrain, + TechniqueType tt, + StringUtil::StrStreamType &outStream) { - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + generateVpHeader(prof, terrain, tt, outStream); - for (uint i = 0; i < numLayers; ++i) - generateVpLayer(prof, terrain, tt, i, outStream); - } + if (tt != LOW_LOD) + { + uint maxLayers = prof->getMaxLayers(terrain); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - generateVpFooter(prof, terrain, tt, outStream); -} + for (uint i = 0; i < numLayers; ++i) + generateVpLayer(prof, terrain, tt, i, outStream); + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateFragmentProgramSource( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - generateFpHeader(prof, terrain, tt, outStream); + generateVpFooter(prof, terrain, tt, outStream); + } - if (tt != LOW_LOD) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::generateFragmentProgramSource( + const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, StringUtil::StrStreamType &outStream) { - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + generateFpHeader(prof, terrain, tt, outStream); - for (uint i = 0; i < numLayers; ++i) - generateFpLayer(prof, terrain, tt, i, outStream); - } + if (tt != LOW_LOD) + { + uint maxLayers = prof->getMaxLayers(terrain); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + + for (uint i = 0; i < numLayers; ++i) + generateFpLayer(prof, terrain, tt, i, outStream); + } - generateFpFooter(prof, terrain, tt, outStream); -} + generateFpFooter(prof, terrain, tt, outStream); + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::defaultVpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog) -{ - GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); - params->setIgnoreMissingParams(true); - params->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX); - params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX); - params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM, - Terrain::LOD_MORPH_CUSTOM_PARAM); - params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); - - if (prof->isShadowingEnabled(tt, terrain)) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::defaultVpParams(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, + const HighLevelGpuProgramPtr &prog) { - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) + GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); + params->setIgnoreMissingParams(true); + params->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX); + params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX); + params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM, Terrain::LOD_MORPH_CUSTOM_PARAM); + params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); + + if (prof->isShadowingEnabled(tt, terrain)) { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); + uint numTextures = 1; + if (prof->getReceiveDynamicShadowsPSSM()) { numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); } + for (uint i = 0; i < numTextures; ++i) + { + params->setNamedAutoConstant("texViewProjMatrix" + StringConverter::toString(i), + GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i); + /*if (prof->getReceiveDynamicShadowsDepth()) + { + params->setNamedAutoConstant("depthRange" + StringConverter::toString(i), + GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i); + }*/ + } } - for (uint i = 0; i < numTextures; ++i) + + if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP) { - params->setNamedAutoConstant("texViewProjMatrix" + StringConverter::toString(i), - GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i); - /*if (prof->getReceiveDynamicShadowsDepth()) - { - params->setNamedAutoConstant("depthRange" + StringConverter::toString(i), - GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i); - }*/ + Matrix4 posIndexToObjectSpace; + terrain->getPointTransform(&posIndexToObjectSpace); + params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace); } } - if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::defaultFpParams(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, + const HighLevelGpuProgramPtr &prog) { - Matrix4 posIndexToObjectSpace; - terrain->getPointTransform(&posIndexToObjectSpace); - params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace); - } -} - -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::defaultFpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog) -{ - GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); - params->setIgnoreMissingParams(true); + GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); + params->setIgnoreMissingParams(true); - params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); - params->setNamedAutoConstant("lightPosObjSpace", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, 0); - params->setNamedAutoConstant("lightDiffuseColour", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0); - params->setNamedAutoConstant("lightSpecularColour", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0); - params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR); + params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); + params->setNamedAutoConstant("lightPosObjSpace", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, 0); + params->setNamedAutoConstant("lightDiffuseColour", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0); + params->setNamedAutoConstant("lightSpecularColour", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0); + params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); + params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR); - if (prof->isShadowingEnabled(tt, terrain)) - { - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) + if (prof->isShadowingEnabled(tt, terrain)) { - PSSMShadowCameraSetup* pssm = prof->getReceiveDynamicShadowsPSSM(); - numTextures = pssm->getSplitCount(); - Vector4 splitPoints; - const PSSMShadowCameraSetup::SplitPointList& splitPointList = pssm->getSplitPoints(); - // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) - for (uint i = 1; i < numTextures; ++i) + uint numTextures = 1; + if (prof->getReceiveDynamicShadowsPSSM()) { - splitPoints[i - 1] = splitPointList[i]; + PSSMShadowCameraSetup *pssm = prof->getReceiveDynamicShadowsPSSM(); + numTextures = pssm->getSplitCount(); + Vector4 splitPoints; + const PSSMShadowCameraSetup::SplitPointList &splitPointList = pssm->getSplitPoints(); + // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) + for (uint i = 1; i < numTextures; ++i) + { + splitPoints[i - 1] = splitPointList[i]; + } + params->setNamedConstant("pssmSplitPoints", splitPoints); } - params->setNamedConstant("pssmSplitPoints", splitPoints); - } - if (prof->getReceiveDynamicShadowsDepth()) - { - size_t samplerOffset = (tt == HIGH_LOD) ? mShadowSamplerStartHi : mShadowSamplerStartLo; - for (uint i = 0; i < numTextures; ++i) + if (prof->getReceiveDynamicShadowsDepth()) { - params->setNamedAutoConstant("inverseShadowmapSize" + StringConverter::toString(i), - GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i + samplerOffset); + size_t samplerOffset = (tt == HIGH_LOD) ? mShadowSamplerStartHi : mShadowSamplerStartLo; + for (uint i = 0; i < numTextures; ++i) + { + params->setNamedAutoConstant("inverseShadowmapSize" + StringConverter::toString(i), + GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i + samplerOffset); + } } } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::updateParams( - const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap) -{ - Pass* p = mat->getTechnique(0)->getPass(0); - if (compositeMap) - { - updateVpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getVertexProgramParameters()); - updateFpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getFragmentProgramParameters()); - } - else + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::updateParams(const SM2Profile *prof, const MaterialPtr &mat, + const Terrain *terrain, bool compositeMap) { - // high lod - updateVpParams(prof, terrain, HIGH_LOD, p->getVertexProgramParameters()); - updateFpParams(prof, terrain, HIGH_LOD, p->getFragmentProgramParameters()); - - if (prof->isCompositeMapEnabled()) + Pass *p = mat->getTechnique(0)->getPass(0); + if (compositeMap) { - // low lod - p = mat->getTechnique(1)->getPass(0); - updateVpParams(prof, terrain, LOW_LOD, p->getVertexProgramParameters()); - updateFpParams(prof, terrain, LOW_LOD, p->getFragmentProgramParameters()); + updateVpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getVertexProgramParameters()); + updateFpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getFragmentProgramParameters()); } - } -} - -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::updateVpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params) -{ - params->setIgnoreMissingParams(true); - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - uint numUVMul = numLayers / 4; - if (numLayers % 4) - ++numUVMul; - for (uint i = 0; i < numUVMul; ++i) - { - Vector4 uvMul( - terrain->getLayerUVMultiplier(i * 4), - terrain->getLayerUVMultiplier(i * 4 + 1), - terrain->getLayerUVMultiplier(i * 4 + 2), - terrain->getLayerUVMultiplier(i * 4 + 3) - ); - params->setNamedConstant("uvMul_" + StringConverter::toString(i), uvMul); - } + else + { + // high lod + updateVpParams(prof, terrain, HIGH_LOD, p->getVertexProgramParameters()); + updateFpParams(prof, terrain, HIGH_LOD, p->getFragmentProgramParameters()); - if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP) - { - Real baseUVScale = 1.0f / (terrain->getSize() - 1); - params->setNamedConstant("baseUVScale", baseUVScale); + if (prof->isCompositeMapEnabled()) + { + // low lod + p = mat->getTechnique(1)->getPass(0); + updateVpParams(prof, terrain, LOW_LOD, p->getVertexProgramParameters()); + updateFpParams(prof, terrain, LOW_LOD, p->getFragmentProgramParameters()); + } + } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::updateFpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params) -{ - params->setIgnoreMissingParams(true); - // TODO - parameterise this? - Vector4 scaleBiasSpecular(0.03, -0.04, 32, 1); - params->setNamedConstant("scaleBiasSpecular", scaleBiasSpecular); -} - -//--------------------------------------------------------------------- -String TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::getChannel(uint idx) -{ - uint rem = idx % 4; - switch (rem) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::updateVpParams(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, + const GpuProgramParametersSharedPtr ¶ms) { - case 0: - default: - return "r"; - case 1: - return "g"; - case 2: - return "b"; - case 3: - return "a"; - }; -} - -//--------------------------------------------------------------------- -String TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::getVertexProgramName( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - String progName = terrain->getMaterialName() + "/sm2/vp"; + params->setIgnoreMissingParams(true); + uint maxLayers = prof->getMaxLayers(terrain); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + uint numUVMul = numLayers / 4; + if (numLayers % 4) ++numUVMul; + for (uint i = 0; i < numUVMul; ++i) + { + Vector4 uvMul(terrain->getLayerUVMultiplier(i * 4), terrain->getLayerUVMultiplier(i * 4 + 1), + terrain->getLayerUVMultiplier(i * 4 + 2), terrain->getLayerUVMultiplier(i * 4 + 3)); + params->setNamedConstant("uvMul_" + StringConverter::toString(i), uvMul); + } - switch (tt) - { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; + if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP) + { + Real baseUVScale = 1.0f / (terrain->getSize() - 1); + params->setNamedConstant("baseUVScale", baseUVScale); + } } - return progName; -} - -//--------------------------------------------------------------------- -String TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::getFragmentProgramName( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - String progName = terrain->getMaterialName() + "/sm2/fp"; - - switch (tt) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::updateFpParams(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, + const GpuProgramParametersSharedPtr ¶ms) { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; + params->setIgnoreMissingParams(true); + // TODO - parameterise this? + Vector4 scaleBiasSpecular(0.03, -0.04, 32, 1); + params->setNamedConstant("scaleBiasSpecular", scaleBiasSpecular); } - return progName; -} - -//--------------------------------------------------------------------- -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_VERTEX_PROGRAM); - } - else + //--------------------------------------------------------------------- + String TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::getChannel(uint idx) { - ret->unload(); + uint rem = idx % 4; + switch (rem) + { + case 0: + default: return "r"; + case 1: return "g"; + case 2: return "b"; + case 3: return "a"; + }; } - ret->setParameter("profiles", "vs_4_0 vs_3_0 vs_2_0 arbvp1"); - ret->setParameter("entry_point", "main_vp"); - - return ret; -} - -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - } - else + //--------------------------------------------------------------------- + String TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::getVertexProgramName(const SM2Profile *prof, + const Terrain *terrain, TechniqueType tt) { - ret->unload(); - } - - if (prof->isLayerNormalMappingEnabled() || prof->isLayerParallaxMappingEnabled()) - ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_x fp40 arbfp1"); - else - ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_0 fp30 arbfp1"); - ret->setParameter("entry_point", "main_fp"); + String progName = terrain->getMaterialName() + "/sm2/vp"; - return ret; -} + switch (tt) + { + case HIGH_LOD: progName += "/hlod"; break; + case LOW_LOD: progName += "/llod"; break; + case RENDER_COMPOSITE_MAP: progName += "/comp"; break; + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpHeader( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - outStream << - "void main_vp(\n"; - bool compression = terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP; - if (compression) - { - outStream << - "float2 posIndex : POSITION,\n" - "float height : TEXCOORD0,\n"; + return progName; } - else + + //--------------------------------------------------------------------- + String TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelper::getFragmentProgramName(const SM2Profile *prof, + const Terrain * terrain, + TechniqueType tt) { - outStream << - "float4 pos : POSITION,\n" - "float2 uv : TEXCOORD0,\n"; - } - if (tt != RENDER_COMPOSITE_MAP) - outStream << "float2 delta : TEXCOORD1,\n"; // lodDelta, lodThreshold + String progName = terrain->getMaterialName() + "/sm2/fp"; - outStream << - "uniform float4x4 worldMatrix,\n" - "uniform float4x4 viewProjMatrix,\n" - "uniform float2 lodMorph,\n"; // morph amount, morph LOD target + switch (tt) + { + case HIGH_LOD: progName += "/hlod"; break; + case LOW_LOD: progName += "/llod"; break; + case RENDER_COMPOSITE_MAP: progName += "/comp"; break; + } - if (compression) - { - outStream << - "uniform float4x4 posIndexToObjectSpace,\n" - "uniform float baseUVScale,\n"; + return progName; } - // uv multipliers - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - uint numUVMultipliers = (numLayers / 4); - if (numLayers % 4) - ++numUVMultipliers; - for (uint i = 0; i < numUVMultipliers; ++i) - outStream << "uniform float4 uvMul_" << i << ", \n"; - - outStream << - "out float4 oPos : POSITION,\n" - "out float4 oPosObj : TEXCOORD0 \n"; - - uint texCoordSet = 1; - outStream << - ", out float4 oUVMisc : TEXCOORD" << texCoordSet++ << " // xy = uv, z = camDepth\n"; - - // layer UV's premultiplied, packed as xy/zw - uint numUVSets = numLayers / 2; - if (numLayers % 2) - ++numUVSets; - if (tt != LOW_LOD) + + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::createVertexProgram(const SM2Profile *prof, + const Terrain *terrain, + TechniqueType tt) { - for (uint i = 0; i < numUVSets; ++i) + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getVertexProgramName(prof, terrain, tt); + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); } + else { - outStream << - ", out float4 oUV" << i << " : TEXCOORD" << texCoordSet++ << "\n"; + ret->unload(); } - } - if (prof->getParent()->getDebugLevel() && tt != RENDER_COMPOSITE_MAP) - { - outStream << ", out float2 lodInfo : TEXCOORD" << texCoordSet++ << "\n"; - } + ret->setParameter("profiles", "vs_4_0 vs_3_0 vs_2_0 arbvp1"); + ret->setParameter("entry_point", "main_vp"); - bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; - if (fog) - { - outStream << - ", uniform float4 fogParams\n" - ", out float fogVal : COLOR\n"; + return ret; } - if (prof->isShadowingEnabled(tt, terrain)) + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::createFragmentProgram(const SM2Profile *prof, + const Terrain *terrain, + TechniqueType tt) { - texCoordSet = generateVpDynamicShadowsParams(texCoordSet, prof, terrain, tt, outStream); - } + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getFragmentProgramName(prof, terrain, tt); - // check we haven't exceeded texture coordinates - if (texCoordSet > 8) - { - OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, - "Requested options require too many texture coordinate sets! Try reducing the number of layers.", - __FUNCTION__); - } + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); } + else + { + ret->unload(); + } - outStream << - ")\n" - "{\n"; - if (compression) - { - outStream << - " float4 pos;\n" - " pos = mul(posIndexToObjectSpace, float4(posIndex, height, 1));\n" - " float2 uv = float2(posIndex.x * baseUVScale, 1.0 - (posIndex.y * baseUVScale));\n"; - } - outStream << - " float4 worldPos = mul(worldMatrix, pos);\n" - " oPosObj = pos;\n"; + if (prof->isLayerNormalMappingEnabled() || prof->isLayerParallaxMappingEnabled()) + ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_x fp40 arbfp1"); + else + ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_0 fp30 arbfp1"); + ret->setParameter("entry_point", "main_fp"); - if (tt != RENDER_COMPOSITE_MAP) - { - // determine whether to apply the LOD morph to this vertex - // we store the deltas against all vertices so we only want to apply - // the morph to the ones which would disappear. The target LOD which is - // being morphed to is stored in lodMorph.y, and the LOD at which - // the vertex should be morphed is stored in uv.w. If we subtract - // the former from the latter, and arrange to only morph if the - // result is negative (it will only be -1 in fact, since after that - // the vertex will never be indexed), we will achieve our aim. - // sign(vertexLOD - targetLOD) == -1 is to morph - outStream << - " float toMorph = -min(0, sign(delta.y - lodMorph.y));\n"; - // this will either be 1 (morph) or 0 (don't morph) - if (prof->getParent()->getDebugLevel()) - { - // x == LOD level (-1 since value is target level, we want to display actual) - outStream << "lodInfo.x = (lodMorph.y - 1) / " << terrain->getNumLodLevels() << ";\n"; - // y == LOD morph - outStream << "lodInfo.y = toMorph * lodMorph.x;\n"; - } - - // morph - switch (terrain->getAlignment()) - { - case Terrain::ALIGN_X_Y: - outStream << " worldPos.z += delta.x * toMorph * lodMorph.x;\n"; - break; - case Terrain::ALIGN_X_Z: - outStream << " worldPos.y += delta.x * toMorph * lodMorph.x;\n"; - break; - case Terrain::ALIGN_Y_Z: - outStream << " worldPos.x += delta.x * toMorph * lodMorph.x;\n"; - break; - }; + return ret; } - // generate UVs - if (tt != LOW_LOD) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpHeader(const SM2Profile *prof, + const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) { - for (uint i = 0; i < numUVSets; ++i) + outStream << "void main_vp(\n"; + bool compression = terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP; + if (compression) { - uint layer = i * 2; - uint uvMulIdx = layer / 4; - - outStream << - " oUV" << i << ".xy = " << " uv.xy * uvMul_" << uvMulIdx << "." << getChannel(layer) << ";\n"; - outStream << - " oUV" << i << ".zw = " << " uv.xy * uvMul_" << uvMulIdx << "." << getChannel(layer + 1) << ";\n"; + outStream << "float2 posIndex : POSITION,\n" + "float height : TEXCOORD0,\n"; } - } -} - -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpHeader( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - // Main header - outStream << - // helpers - "float4 expand(float4 v)\n" - "{ \n" - " return v * 2 - 1;\n" - "}\n\n\n"; - - if (prof->isShadowingEnabled(tt, terrain)) - generateFpDynamicShadowsHelpers(prof, terrain, tt, outStream); - - outStream << - "float4 main_fp(\n" - "float4 vertexPos : POSITION,\n" - "float4 position : TEXCOORD0,\n"; - - uint texCoordSet = 1; - outStream << - "float4 uvMisc : TEXCOORD" << texCoordSet++ << ",\n"; - - // UV's premultiplied, packed as xy/zw - uint maxLayers = prof->getMaxLayers(terrain); - uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - uint numUVSets = numLayers / 2; - if (numLayers % 2) - ++numUVSets; - if (tt != LOW_LOD) - { - for (uint i = 0; i < numUVSets; ++i) + else { - outStream << - "float4 layerUV" << i << " : TEXCOORD" << texCoordSet++ << ", \n"; + outStream << "float4 pos : POSITION,\n" + "float2 uv : TEXCOORD0,\n"; } - } - if (prof->getParent()->getDebugLevel() && tt != RENDER_COMPOSITE_MAP) - { - outStream << "float2 lodInfo : TEXCOORD" << texCoordSet++ << ", \n"; - } + if (tt != RENDER_COMPOSITE_MAP) outStream << "float2 delta : TEXCOORD1,\n"; // lodDelta, lodThreshold - bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; - if (fog) - { - outStream << - "uniform float3 fogColour, \n" - "float fogVal : COLOR,\n"; - } + outStream << "uniform float4x4 worldMatrix,\n" + "uniform float4x4 viewProjMatrix,\n" + "uniform float2 lodMorph,\n"; // morph amount, morph LOD target - uint currentSamplerIdx = 0; + if (compression) + { + outStream << "uniform float4x4 posIndexToObjectSpace,\n" + "uniform float baseUVScale,\n"; + } + // uv multipliers + uint maxLayers = prof->getMaxLayers(terrain); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + uint numUVMultipliers = (numLayers / 4); + if (numLayers % 4) ++numUVMultipliers; + for (uint i = 0; i < numUVMultipliers; ++i) + outStream << "uniform float4 uvMul_" << i << ", \n"; + + outStream << "out float4 oPos : POSITION,\n" + "out float4 oPosObj : TEXCOORD0 \n"; + + uint texCoordSet = 1; + outStream << ", out float4 oUVMisc : TEXCOORD" << texCoordSet++ << " // xy = uv, z = camDepth\n"; + + // layer UV's premultiplied, packed as xy/zw + uint numUVSets = numLayers / 2; + if (numLayers % 2) ++numUVSets; + if (tt != LOW_LOD) + { + for (uint i = 0; i < numUVSets; ++i) + { + outStream << ", out float4 oUV" << i << " : TEXCOORD" << texCoordSet++ << "\n"; + } + } - outStream << - // Only 1 light supported in this version - // deferred shading profile / generator later, ok? :) - "uniform float3 ambient,\n" - "uniform float4 lightPosObjSpace,\n" - "uniform float3 lightDiffuseColour,\n" - "uniform float3 lightSpecularColour,\n" - "uniform float3 eyePosObjSpace,\n" - // pack scale, bias and specular - "uniform float4 scaleBiasSpecular,\n"; + if (prof->getParent()->getDebugLevel() && tt != RENDER_COMPOSITE_MAP) + { outStream << ", out float2 lodInfo : TEXCOORD" << texCoordSet++ << "\n"; } - if (tt == LOW_LOD) - { - // single composite map covers all the others below - outStream << - "uniform sampler2D compositeMap : register(s" << currentSamplerIdx++ << ")\n"; - } - else - { - outStream << - "uniform sampler2D globalNormal : register(s" << currentSamplerIdx++ << ")\n"; + bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; + if (fog) + { + outStream << ", uniform float4 fogParams\n" + ", out float fogVal : COLOR\n"; + } - if (terrain->getGlobalColourMapEnabled() && prof->isGlobalColourMapEnabled()) + if (prof->isShadowingEnabled(tt, terrain)) + { texCoordSet = generateVpDynamicShadowsParams(texCoordSet, prof, terrain, tt, outStream); } + + // check we haven't exceeded texture coordinates + if (texCoordSet > 8) { - outStream << ", uniform sampler2D globalColourMap : register(s" - << currentSamplerIdx++ << ")\n"; + OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, + "Requested options require too many texture coordinate sets! Try reducing the number of layers.", + __FUNCTION__); } - if (prof->isLightmapEnabled()) + + outStream << ")\n" + "{\n"; + if (compression) { - outStream << ", uniform sampler2D lightMap : register(s" - << currentSamplerIdx++ << ")\n"; + outStream << " float4 pos;\n" + " pos = mul(posIndexToObjectSpace, float4(posIndex, height, 1));\n" + " float2 uv = float2(posIndex.x * baseUVScale, 1.0 - (posIndex.y * baseUVScale));\n"; } - // Blend textures - sampler definitions - for (uint i = 0; i < numBlendTextures; ++i) + outStream << " float4 worldPos = mul(worldMatrix, pos);\n" + " oPosObj = pos;\n"; + + if (tt != RENDER_COMPOSITE_MAP) { - outStream << ", uniform sampler2D blendTex" << i - << " : register(s" << currentSamplerIdx++ << ")\n"; + // determine whether to apply the LOD morph to this vertex + // we store the deltas against all vertices so we only want to apply + // the morph to the ones which would disappear. The target LOD which is + // being morphed to is stored in lodMorph.y, and the LOD at which + // the vertex should be morphed is stored in uv.w. If we subtract + // the former from the latter, and arrange to only morph if the + // result is negative (it will only be -1 in fact, since after that + // the vertex will never be indexed), we will achieve our aim. + // sign(vertexLOD - targetLOD) == -1 is to morph + outStream << " float toMorph = -min(0, sign(delta.y - lodMorph.y));\n"; + // this will either be 1 (morph) or 0 (don't morph) + if (prof->getParent()->getDebugLevel()) + { + // x == LOD level (-1 since value is target level, we want to display actual) + outStream << "lodInfo.x = (lodMorph.y - 1) / " << terrain->getNumLodLevels() << ";\n"; + // y == LOD morph + outStream << "lodInfo.y = toMorph * lodMorph.x;\n"; + } + + // morph + switch (terrain->getAlignment()) + { + case Terrain::ALIGN_X_Y: outStream << " worldPos.z += delta.x * toMorph * lodMorph.x;\n"; break; + case Terrain::ALIGN_X_Z: outStream << " worldPos.y += delta.x * toMorph * lodMorph.x;\n"; break; + case Terrain::ALIGN_Y_Z: outStream << " worldPos.x += delta.x * toMorph * lodMorph.x;\n"; break; + }; } - // Layer textures - sampler definitions & UV multipliers - for (uint i = 0; i < numLayers; ++i) + // generate UVs + if (tt != LOW_LOD) { - outStream << ", uniform sampler2D difftex" << i - << " : register(s" << currentSamplerIdx++ << ")\n"; - outStream << ", uniform sampler2D normtex" << i - << " : register(s" << currentSamplerIdx++ << ")\n"; + for (uint i = 0; i < numUVSets; ++i) + { + uint layer = i * 2; + uint uvMulIdx = layer / 4; + + outStream << " oUV" << i << ".xy = " + << " uv.xy * uvMul_" << uvMulIdx << "." << getChannel(layer) << ";\n"; + outStream << " oUV" << i << ".zw = " + << " uv.xy * uvMul_" << uvMulIdx << "." << getChannel(layer + 1) << ";\n"; + } } } - if (prof->isShadowingEnabled(tt, terrain)) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpHeader(const SM2Profile *prof, + const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) { - generateFpDynamicShadowsParams(&texCoordSet, ¤tSamplerIdx, prof, terrain, tt, outStream); - } + // Main header + outStream << + // helpers + "float4 expand(float4 v)\n" + "{ \n" + " return v * 2 - 1;\n" + "}\n\n\n"; - // check we haven't exceeded samplers - if (currentSamplerIdx > 16) - { - OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, - "Requested options require too many texture samplers! Try reducing the number of layers.", - __FUNCTION__); - } + if (prof->isShadowingEnabled(tt, terrain)) generateFpDynamicShadowsHelpers(prof, terrain, tt, outStream); - outStream << - ") : COLOR\n" - "{\n" - " float4 outputCol;\n" - " float shadow = 1.0;\n" - " float2 uv = uvMisc.xy;\n" - // base colour - " outputCol = float4(0,0,0,1);\n"; + outStream << "float4 main_fp(\n" + "float4 vertexPos : POSITION,\n" + "float4 position : TEXCOORD0,\n"; - if (tt != LOW_LOD) - { - outStream << - // global normal - " float3 normal = expand(tex2D(globalNormal, uv)).rgb;\n"; - } + uint texCoordSet = 1; + outStream << "float4 uvMisc : TEXCOORD" << texCoordSet++ << ",\n"; - outStream << - " float3 lightDir = \n" - " lightPosObjSpace.xyz - (position.xyz * lightPosObjSpace.w);\n" - " float3 eyeDir = eyePosObjSpace - position.xyz;\n" + // UV's premultiplied, packed as xy/zw + uint maxLayers = prof->getMaxLayers(terrain); + uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + uint numUVSets = numLayers / 2; + if (numLayers % 2) ++numUVSets; + if (tt != LOW_LOD) + { + for (uint i = 0; i < numUVSets; ++i) + { + outStream << "float4 layerUV" << i << " : TEXCOORD" << texCoordSet++ << ", \n"; + } + } + if (prof->getParent()->getDebugLevel() && tt != RENDER_COMPOSITE_MAP) + { outStream << "float2 lodInfo : TEXCOORD" << texCoordSet++ << ", \n"; } + + bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; + if (fog) + { + outStream << "uniform float3 fogColour, \n" + "float fogVal : COLOR,\n"; + } - // set up accumulation areas - " float3 diffuse = float3(0,0,0);\n" - " float specular = 0;\n"; + uint currentSamplerIdx = 0; - if (tt == LOW_LOD) - { - // we just do a single calculation from composite map outStream << - " float4 composite = tex2D(compositeMap, uv);\n" - " diffuse = composite.rgb;\n"; - // TODO - specular; we'll need normals for this! - } - else - { - // set up the blend values - for (uint i = 0; i < numBlendTextures; ++i) + // Only 1 light supported in this version + // deferred shading profile / generator later, ok? :) + "uniform float3 ambient,\n" + "uniform float4 lightPosObjSpace,\n" + "uniform float3 lightDiffuseColour,\n" + "uniform float3 lightSpecularColour,\n" + "uniform float3 eyePosObjSpace,\n" + // pack scale, bias and specular + "uniform float4 scaleBiasSpecular,\n"; + + if (tt == LOW_LOD) { - outStream << " float4 blendTexVal" << i << " = tex2D(blendTex" << i << ", uv);\n"; + // single composite map covers all the others below + outStream << "uniform sampler2D compositeMap : register(s" << currentSamplerIdx++ << ")\n"; } - - if (prof->isLayerNormalMappingEnabled()) + else { - // derive the tangent space basis - // we do this in the pixel shader because we don't have per-vertex normals - // because of the LOD, we use a normal map - // tangent is always +x or -z in object space depending on alignment - switch (terrain->getAlignment()) + outStream << "uniform sampler2D globalNormal : register(s" << currentSamplerIdx++ << ")\n"; + + if (terrain->getGlobalColourMapEnabled() && prof->isGlobalColourMapEnabled()) + { outStream << ", uniform sampler2D globalColourMap : register(s" << currentSamplerIdx++ << ")\n"; } + if (prof->isLightmapEnabled()) + { outStream << ", uniform sampler2D lightMap : register(s" << currentSamplerIdx++ << ")\n"; } + // Blend textures - sampler definitions + for (uint i = 0; i < numBlendTextures; ++i) { - case Terrain::ALIGN_X_Y: - case Terrain::ALIGN_X_Z: - outStream << " float3 tangent = float3(1, 0, 0);\n"; - break; - case Terrain::ALIGN_Y_Z: - outStream << " float3 tangent = float3(0, 0, -1);\n"; - break; - }; + outStream << ", uniform sampler2D blendTex" << i << " : register(s" << currentSamplerIdx++ << ")\n"; + } - outStream << " float3 binormal = normalize(cross(tangent, normal));\n"; - // note, now we need to re-cross to derive tangent again because it wasn't orthonormal - outStream << " tangent = normalize(cross(normal, binormal));\n"; - // derive final matrix - outStream << " float3x3 TBN = float3x3(tangent, binormal, normal);\n"; - - // set up lighting result placeholders for interpolation - outStream << " float4 litRes, litResLayer;\n"; - outStream << " float3 TSlightDir, TSeyeDir, TShalfAngle, TSnormal;\n"; - if (prof->isLayerParallaxMappingEnabled()) - outStream << " float displacement;\n"; - // move - outStream << " TSlightDir = normalize(mul(TBN, lightDir));\n"; - outStream << " TSeyeDir = normalize(mul(TBN, eyeDir));\n"; + // Layer textures - sampler definitions & UV multipliers + for (uint i = 0; i < numLayers; ++i) + { + outStream << ", uniform sampler2D difftex" << i << " : register(s" << currentSamplerIdx++ << ")\n"; + outStream << ", uniform sampler2D normtex" << i << " : register(s" << currentSamplerIdx++ << ")\n"; + } } - else + + if (prof->isShadowingEnabled(tt, terrain)) + { generateFpDynamicShadowsParams(&texCoordSet, ¤tSamplerIdx, prof, terrain, tt, outStream); } + + // check we haven't exceeded samplers + if (currentSamplerIdx > 16) { - // simple per-pixel lighting with no normal mapping - outStream << " lightDir = normalize(lightDir);\n"; - outStream << " eyeDir = normalize(eyeDir);\n"; - outStream << " float3 halfAngle = normalize(lightDir + eyeDir);\n"; - outStream << " float4 litRes = lit(dot(lightDir, normal), dot(halfAngle, normal), scaleBiasSpecular.z);\n"; + OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, + "Requested options require too many texture samplers! Try reducing the number of layers.", __FUNCTION__); } - } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpLayer( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) -{ - // nothing to do -} + outStream << ") : COLOR\n" + "{\n" + " float4 outputCol;\n" + " float shadow = 1.0;\n" + " float2 uv = uvMisc.xy;\n" + // base colour + " outputCol = float4(0,0,0,1);\n"; -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpLayer( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) -{ - uint uvIdx = layer / 2; - String uvChannels = (layer % 2) ? ".zw" : ".xy"; - uint blendIdx = (layer - 1) / 4; - String blendChannel = getChannel(layer - 1); - String blendWeightStr = String("blendTexVal") + StringConverter::toString(blendIdx) + - "." + blendChannel; - - // generate early-out conditional - /* Disable - causing some issues even when trying to force the use of texldd - if (layer && prof->_isSM3Available()) - outStream << " if (" << blendWeightStr << " > 0.0003)\n { \n"; - */ - - // generate UV - outStream << " float2 uv" << layer << " = layerUV" << uvIdx << uvChannels << ";\n"; - - // calculate lighting here if normal mapping - if (prof->isLayerNormalMappingEnabled()) - { - if (prof->isLayerParallaxMappingEnabled() && tt != RENDER_COMPOSITE_MAP) + if (tt != LOW_LOD) { - // modify UV - note we have to sample an extra time - outStream << " displacement = tex2D(normtex" << layer << ", uv" << layer << ").a\n" - " * scaleBiasSpecular.x + scaleBiasSpecular.y;\n"; - outStream << " uv" << layer << " += TSeyeDir.xy * displacement;\n"; + outStream << + // global normal + " float3 normal = expand(tex2D(globalNormal, uv)).rgb;\n"; } - // access TS normal map - outStream << " TSnormal = expand(tex2D(normtex" << layer << ", uv" << layer << ")).rgb;\n"; - outStream << " TShalfAngle = normalize(TSlightDir + TSeyeDir);\n"; - outStream << " litResLayer = lit(dot(TSlightDir, TSnormal), dot(TShalfAngle, TSnormal), scaleBiasSpecular.z);\n"; - if (!layer) - outStream << " litRes = litResLayer;\n"; + outStream << " float3 lightDir = \n" + " lightPosObjSpace.xyz - (position.xyz * lightPosObjSpace.w);\n" + " float3 eyeDir = eyePosObjSpace - position.xyz;\n" + + // set up accumulation areas + " float3 diffuse = float3(0,0,0);\n" + " float specular = 0;\n"; + + if (tt == LOW_LOD) + { + // we just do a single calculation from composite map + outStream << " float4 composite = tex2D(compositeMap, uv);\n" + " diffuse = composite.rgb;\n"; + // TODO - specular; we'll need normals for this! + } else - outStream << " litRes = lerp(litRes, litResLayer, " << blendWeightStr << ");\n"; - } + { + // set up the blend values + for (uint i = 0; i < numBlendTextures; ++i) + { + outStream << " float4 blendTexVal" << i << " = tex2D(blendTex" << i << ", uv);\n"; + } - // sample diffuse texture - outStream << " float4 diffuseSpecTex" << layer - << " = tex2D(difftex" << layer << ", uv" << layer << ");\n"; + if (prof->isLayerNormalMappingEnabled()) + { + // derive the tangent space basis + // we do this in the pixel shader because we don't have per-vertex normals + // because of the LOD, we use a normal map + // tangent is always +x or -z in object space depending on alignment + switch (terrain->getAlignment()) + { + case Terrain::ALIGN_X_Y: + case Terrain::ALIGN_X_Z: outStream << " float3 tangent = float3(1, 0, 0);\n"; break; + case Terrain::ALIGN_Y_Z: outStream << " float3 tangent = float3(0, 0, -1);\n"; break; + }; + + outStream << " float3 binormal = normalize(cross(tangent, normal));\n"; + // note, now we need to re-cross to derive tangent again because it wasn't orthonormal + outStream << " tangent = normalize(cross(normal, binormal));\n"; + // derive final matrix + outStream << " float3x3 TBN = float3x3(tangent, binormal, normal);\n"; + + // set up lighting result placeholders for interpolation + outStream << " float4 litRes, litResLayer;\n"; + outStream << " float3 TSlightDir, TSeyeDir, TShalfAngle, TSnormal;\n"; + if (prof->isLayerParallaxMappingEnabled()) outStream << " float displacement;\n"; + // move + outStream << " TSlightDir = normalize(mul(TBN, lightDir));\n"; + outStream << " TSeyeDir = normalize(mul(TBN, eyeDir));\n"; + } + else + { + // simple per-pixel lighting with no normal mapping + outStream << " lightDir = normalize(lightDir);\n"; + outStream << " eyeDir = normalize(eyeDir);\n"; + outStream << " float3 halfAngle = normalize(lightDir + eyeDir);\n"; + outStream << " float4 litRes = lit(dot(lightDir, normal), dot(halfAngle, normal), scaleBiasSpecular.z);\n"; + } + } + } - // apply to common - if (!layer) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpLayer(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) { - outStream << " diffuse = diffuseSpecTex0.rgb;\n"; - if (prof->isLayerSpecularMappingEnabled()) - outStream << " specular = diffuseSpecTex0.a;\n"; + // nothing to do } - else + + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpLayer(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) { - outStream << " diffuse = lerp(diffuse, diffuseSpecTex" << layer - << ".rgb, " << blendWeightStr << ");\n"; - if (prof->isLayerSpecularMappingEnabled()) - outStream << " specular = lerp(specular, diffuseSpecTex" << layer - << ".a, " << blendWeightStr << ");\n"; - } + uint uvIdx = layer / 2; + String uvChannels = (layer % 2) ? ".zw" : ".xy"; + uint blendIdx = (layer - 1) / 4; + String blendChannel = getChannel(layer - 1); + String blendWeightStr = String("blendTexVal") + StringConverter::toString(blendIdx) + "." + blendChannel; - // End early-out - /* Disable - causing some issues even when trying to force the use of texldd - if (layer && prof->_isSM3Available()) - outStream << " } // early-out blend value\n"; - */ -} + // generate early-out conditional + /* Disable - causing some issues even when trying to force the use of texldd + if (layer && prof->_isSM3Available()) + outStream << " if (" << blendWeightStr << " > 0.0003)\n { \n"; + */ -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpFooter( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - outStream << - " oPos = mul(viewProjMatrix, worldPos);\n" - " oUVMisc.xy = uv.xy;\n"; + // generate UV + outStream << " float2 uv" << layer << " = layerUV" << uvIdx << uvChannels << ";\n"; - bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; - if (fog) - { - if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR) - { - outStream << - " fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n"; - } - else + // calculate lighting here if normal mapping + if (prof->isLayerNormalMappingEnabled()) { - outStream << - " fogVal = 1 - saturate(1 / (exp(oPos.z * fogParams.x)));\n"; - } - } + if (prof->isLayerParallaxMappingEnabled() && tt != RENDER_COMPOSITE_MAP) + { + // modify UV - note we have to sample an extra time + outStream << " displacement = tex2D(normtex" << layer << ", uv" << layer + << ").a\n" + " * scaleBiasSpecular.x + scaleBiasSpecular.y;\n"; + outStream << " uv" << layer << " += TSeyeDir.xy * displacement;\n"; + } - if (prof->isShadowingEnabled(tt, terrain)) - generateVpDynamicShadows(prof, terrain, tt, outStream); + // access TS normal map + outStream << " TSnormal = expand(tex2D(normtex" << layer << ", uv" << layer << ")).rgb;\n"; + outStream << " TShalfAngle = normalize(TSlightDir + TSeyeDir);\n"; + outStream << " litResLayer = lit(dot(TSlightDir, TSnormal), dot(TShalfAngle, TSnormal), scaleBiasSpecular.z);\n"; + if (!layer) + outStream << " litRes = litResLayer;\n"; + else + outStream << " litRes = lerp(litRes, litResLayer, " << blendWeightStr << ");\n"; + } - outStream << - "}\n"; -} + // sample diffuse texture + outStream << " float4 diffuseSpecTex" << layer << " = tex2D(difftex" << layer << ", uv" << layer << ");\n"; -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpFooter( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - if (tt == LOW_LOD) - { - if (prof->isShadowingEnabled(tt, terrain)) + // apply to common + if (!layer) { - generateFpDynamicShadows(prof, terrain, tt, outStream); - outStream << - " outputCol.rgb = diffuse * rtshadow;\n"; + outStream << " diffuse = diffuseSpecTex0.rgb;\n"; + if (prof->isLayerSpecularMappingEnabled()) outStream << " specular = diffuseSpecTex0.a;\n"; } else { - outStream << - " outputCol.rgb = diffuse;\n"; + outStream << " diffuse = lerp(diffuse, diffuseSpecTex" << layer << ".rgb, " << blendWeightStr << ");\n"; + if (prof->isLayerSpecularMappingEnabled()) + outStream << " specular = lerp(specular, diffuseSpecTex" << layer << ".a, " << blendWeightStr << ");\n"; } + + // End early-out + /* Disable - causing some issues even when trying to force the use of texldd + if (layer && prof->_isSM3Available()) + outStream << " } // early-out blend value\n"; + */ } - else + + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpFooter(const SM2Profile *prof, + const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) { - if (terrain->getGlobalColourMapEnabled() && prof->isGlobalColourMapEnabled()) - { - // sample colour map and apply to diffuse - outStream << " diffuse *= tex2D(globalColourMap, uv).rgb;\n"; - } - if (prof->isLightmapEnabled()) - { - // sample lightmap - outStream << " shadow = tex2D(lightMap, uv).r;\n"; - } + outStream << " oPos = mul(viewProjMatrix, worldPos);\n" + " oUVMisc.xy = uv.xy;\n"; - if (prof->isShadowingEnabled(tt, terrain)) + bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; + if (fog) { - generateFpDynamicShadows(prof, terrain, tt, outStream); + if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR) + { outStream << " fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n"; } + else + { + outStream << " fogVal = 1 - saturate(1 / (exp(oPos.z * fogParams.x)));\n"; + } } - // diffuse lighting - outStream << " outputCol.rgb += ambient * diffuse + litRes.y * lightDiffuseColour * diffuse * shadow;\n"; + if (prof->isShadowingEnabled(tt, terrain)) generateVpDynamicShadows(prof, terrain, tt, outStream); - // specular default - if (!prof->isLayerSpecularMappingEnabled()) - outStream << " specular = 1.0;\n"; + outStream << "}\n"; + } - if (tt == RENDER_COMPOSITE_MAP) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpFooter(const SM2Profile *prof, + const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + if (tt == LOW_LOD) { - // Lighting embedded in alpha - outStream << - " outputCol.a = shadow;\n"; + if (prof->isShadowingEnabled(tt, terrain)) + { + generateFpDynamicShadows(prof, terrain, tt, outStream); + outStream << " outputCol.rgb = diffuse * rtshadow;\n"; + } + else + { + outStream << " outputCol.rgb = diffuse;\n"; + } } else { - // Apply specular - outStream << " outputCol.rgb += litRes.z * lightSpecularColour * specular * shadow;\n"; - - if (prof->getParent()->getDebugLevel()) + if (terrain->getGlobalColourMapEnabled() && prof->isGlobalColourMapEnabled()) { - outStream << " outputCol.rg += lodInfo.xy;\n"; + // sample colour map and apply to diffuse + outStream << " diffuse *= tex2D(globalColourMap, uv).rgb;\n"; + } + if (prof->isLightmapEnabled()) + { + // sample lightmap + outStream << " shadow = tex2D(lightMap, uv).r;\n"; } - } - } - bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; - if (fog) - { - outStream << " outputCol.rgb = lerp(outputCol.rgb, fogColour, fogVal);\n"; - } + if (prof->isShadowingEnabled(tt, terrain)) { generateFpDynamicShadows(prof, terrain, tt, outStream); } - // Final return - outStream << " return outputCol;\n" - << "}\n"; -} + // diffuse lighting + outStream << " outputCol.rgb += ambient * diffuse + litRes.y * lightDiffuseColour * diffuse * shadow;\n"; -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsHelpers( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - // TODO make filtering configurable - outStream << - "// Simple PCF \n" - "// Number of samples in one dimension (square for total samples) \n" - "#define NUM_SHADOW_SAMPLES_1D 2.0 \n" - "#define SHADOW_FILTER_SCALE 1 \n" + // specular default + if (!prof->isLayerSpecularMappingEnabled()) outStream << " specular = 1.0;\n"; + + if (tt == RENDER_COMPOSITE_MAP) + { + // Lighting embedded in alpha + outStream << " outputCol.a = shadow;\n"; + } + else + { + // Apply specular + outStream << " outputCol.rgb += litRes.z * lightSpecularColour * specular * shadow;\n"; - "#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n" + if (prof->getParent()->getDebugLevel()) { outStream << " outputCol.rg += lodInfo.xy;\n"; } + } + } - "float4 offsetSample(float4 uv, float2 offset, float invMapSize) \n" - "{ \n" - " return float4(uv.xy + offset * invMapSize * uv.w, uv.z, uv.w); \n" - "} \n"; + bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; + if (fog) { outStream << " outputCol.rgb = lerp(outputCol.rgb, fogColour, fogVal);\n"; } - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - "float calcDepthShadow(sampler2D shadowMap, float4 uv, float invShadowMapSize) \n" - "{ \n" - " // 4-sample PCF \n" - - " float shadow = 0.0; \n" - " float offset = (NUM_SHADOW_SAMPLES_1D/2 - 0.5) * SHADOW_FILTER_SCALE; \n" - " for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE) \n" - " for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE) \n" - " { \n" - " float4 newUV = offsetSample(uv, float2(x, y), invShadowMapSize);\n" - " // manually project and assign derivatives \n" - " // to avoid gradient issues inside loops \n" - " newUV = newUV / newUV.w; \n" - " float depth = tex2D(shadowMap, newUV.xy, 1, 1).x; \n" - " if (depth >= 1 || depth >= uv.z)\n" - " shadow += 1.0;\n" - " } \n" - - " shadow /= SHADOW_SAMPLES; \n" - - " return shadow; \n" - "} \n"; - } - else - { - outStream << - "float calcSimpleShadow(sampler2D shadowMap, float4 shadowMapPos) \n" - "{ \n" - " return tex2Dproj(shadowMap, shadowMapPos).x; \n" - "} \n"; + // Final return + outStream << " return outputCol;\n" + << "}\n"; } - if (prof->getReceiveDynamicShadowsPSSM()) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsHelpers( + const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, StringUtil::StrStreamType &outStream) { - uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); + // TODO make filtering configurable + outStream << "// Simple PCF \n" + "// Number of samples in one dimension (square for total samples) \n" + "#define NUM_SHADOW_SAMPLES_1D 2.0 \n" + "#define SHADOW_FILTER_SCALE 1 \n" + + "#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n" + + "float4 offsetSample(float4 uv, float2 offset, float invMapSize) \n" + "{ \n" + " return float4(uv.xy + offset * invMapSize * uv.w, uv.z, uv.w); \n" + "} \n"; if (prof->getReceiveDynamicShadowsDepth()) { - outStream << - "float calcPSSMDepthShadow("; + outStream << "float calcDepthShadow(sampler2D shadowMap, float4 uv, float invShadowMapSize) \n" + "{ \n" + " // 4-sample PCF \n" + + " float shadow = 0.0; \n" + " float offset = (NUM_SHADOW_SAMPLES_1D/2 - 0.5) * SHADOW_FILTER_SCALE; \n" + " for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE) \n" + " for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE) \n" + " { \n" + " float4 newUV = offsetSample(uv, float2(x, y), invShadowMapSize);\n" + " // manually project and assign derivatives \n" + " // to avoid gradient issues inside loops \n" + " newUV = newUV / newUV.w; \n" + " float depth = tex2D(shadowMap, newUV.xy, 1, 1).x; \n" + " if (depth >= 1 || depth >= uv.z)\n" + " shadow += 1.0;\n" + " } \n" + + " shadow /= SHADOW_SAMPLES; \n" + + " return shadow; \n" + "} \n"; } else { - outStream << - "float calcPSSMSimpleShadow("; + outStream << "float calcSimpleShadow(sampler2D shadowMap, float4 shadowMapPos) \n" + "{ \n" + " return tex2Dproj(shadowMap, shadowMapPos).x; \n" + "} \n"; } - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "sampler2D shadowMap" << i << ", "; - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "float4 lsPos" << i << ", "; - if (prof->getReceiveDynamicShadowsDepth()) + if (prof->getReceiveDynamicShadowsPSSM()) { - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "float invShadowmapSize" << i << ", "; - } - outStream << "\n" - " float4 pssmSplitPoints, float camDepth) \n" - "{ \n" - " float shadow; \n" - " // calculate shadow \n"; + uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - for (uint i = 0; i < numTextures; ++i) - { - if (!i) - outStream << " if (camDepth <= pssmSplitPoints." << ShaderHelper::getChannel(i) << ") \n"; - else if (i < numTextures - 1) - outStream << " else if (camDepth <= pssmSplitPoints." << ShaderHelper::getChannel(i) << ") \n"; + if (prof->getReceiveDynamicShadowsDepth()) { outStream << "float calcPSSMDepthShadow("; } else - outStream << " else \n"; + { + outStream << "float calcPSSMSimpleShadow("; + } - outStream << - " { \n"; + outStream << "\n "; + for (uint i = 0; i < numTextures; ++i) + outStream << "sampler2D shadowMap" << i << ", "; + outStream << "\n "; + for (uint i = 0; i < numTextures; ++i) + outStream << "float4 lsPos" << i << ", "; if (prof->getReceiveDynamicShadowsDepth()) { - outStream << - " shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << "); \n"; + outStream << "\n "; + for (uint i = 0; i < numTextures; ++i) + outStream << "float invShadowmapSize" << i << ", "; } - else + outStream << "\n" + " float4 pssmSplitPoints, float camDepth) \n" + "{ \n" + " float shadow; \n" + " // calculate shadow \n"; + + for (uint i = 0; i < numTextures; ++i) { - outStream << - " shadow = calcSimpleShadow(shadowMap" << i << ", lsPos" << i << "); \n"; + if (!i) + outStream << " if (camDepth <= pssmSplitPoints." << ShaderHelper::getChannel(i) << ") \n"; + else if (i < numTextures - 1) + outStream << " else if (camDepth <= pssmSplitPoints." << ShaderHelper::getChannel(i) << ") \n"; + else + outStream << " else \n"; + + outStream << " { \n"; + if (prof->getReceiveDynamicShadowsDepth()) + { + outStream << " shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i + << "); \n"; + } + else + { + outStream << " shadow = calcSimpleShadow(shadowMap" << i << ", lsPos" << i << "); \n"; + } + outStream << " } \n"; } - outStream << - " } \n"; - } - outStream << - " return shadow; \n" - "} \n\n\n"; + outStream << " return shadow; \n" + "} \n\n\n"; + } } -} -//--------------------------------------------------------------------- -uint TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpDynamicShadowsParams( - uint texCoord, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - // out semantics & params - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) + //--------------------------------------------------------------------- + uint TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpDynamicShadowsParams( + uint texCoord, const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, StringUtil::StrStreamType &outStream) { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - for (uint i = 0; i < numTextures; ++i) - { - outStream << - ", out float4 oLightSpacePos" << i << " : TEXCOORD" << texCoord++ << " \n" << - ", uniform float4x4 texViewProjMatrix" << i << " \n"; - - /*if (prof->getReceiveDynamicShadowsDepth()) + // out semantics & params + uint numTextures = 1; + if (prof->getReceiveDynamicShadowsPSSM()) { numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); } + for (uint i = 0; i < numTextures; ++i) { - outStream << - ", uniform float4 depthRange" << i << " // x = min, y = max, z = range, w = 1/range \n"; - }*/ - } + outStream << ", out float4 oLightSpacePos" << i << " : TEXCOORD" << texCoord++ << " \n" + << ", uniform float4x4 texViewProjMatrix" << i << " \n"; - return texCoord; -} + /*if (prof->getReceiveDynamicShadowsDepth()) + { + outStream << + ", uniform float4 depthRange" << i << " // x = min, y = max, z = range, w = 1/range \n"; + }*/ + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpDynamicShadows( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) - { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); + return texCoord; } - // Calculate the position of vertex in light space - for (uint i = 0; i < numTextures; ++i) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateVpDynamicShadows(const SM2Profile * prof, + const Terrain * terrain, + TechniqueType tt, + StringUtil::StrStreamType &outStream) { - outStream << - " oLightSpacePos" << i << " = mul(texViewProjMatrix" << i << ", worldPos); \n"; - /*if (prof->getReceiveDynamicShadowsDepth()) - { - // make linear - outStream << - "oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n"; + uint numTextures = 1; + if (prof->getReceiveDynamicShadowsPSSM()) { numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); } - }*/ - } + // Calculate the position of vertex in light space + for (uint i = 0; i < numTextures; ++i) + { + outStream << " oLightSpacePos" << i << " = mul(texViewProjMatrix" << i << ", worldPos); \n"; + /*if (prof->getReceiveDynamicShadowsDepth()) + { + // make linear + outStream << + "oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n"; - if (prof->getReceiveDynamicShadowsPSSM()) - { - outStream << - " // pass cam depth\n" - " oUVMisc.z = oPos.z;\n"; - } -} + }*/ + } -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams( - uint* texCoord, uint* sampler, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - if (tt == HIGH_LOD) - mShadowSamplerStartHi = *sampler; - else if (tt == LOW_LOD) - mShadowSamplerStartLo = *sampler; - - // in semantics & params - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) - { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - outStream << - ", uniform float4 pssmSplitPoints \n"; - } - for (uint i = 0; i < numTextures; ++i) - { - outStream << - ", float4 lightSpacePos" << i << " : TEXCOORD" << *texCoord << " \n" << - ", uniform sampler2D shadowMap" << i << " : register(s" << *sampler << ") \n"; - *sampler = *sampler + 1; - *texCoord = *texCoord + 1; - if (prof->getReceiveDynamicShadowsDepth()) + if (prof->getReceiveDynamicShadowsPSSM()) { - outStream << - ", uniform float inverseShadowmapSize" << i << " \n"; + outStream << " // pass cam depth\n" + " oUVMisc.z = oPos.z;\n"; } } -} -//--------------------------------------------------------------------- -void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpDynamicShadows( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) -{ - if (prof->getReceiveDynamicShadowsPSSM()) + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams( + uint *texCoord, uint *sampler, const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) { - uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - outStream << - " float camDepth = uvMisc.z;\n"; + if (tt == HIGH_LOD) + mShadowSamplerStartHi = *sampler; + else if (tt == LOW_LOD) + mShadowSamplerStartLo = *sampler; - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - " float rtshadow = calcPSSMDepthShadow("; - } - else + // in semantics & params + uint numTextures = 1; + if (prof->getReceiveDynamicShadowsPSSM()) { - outStream << - " float rtshadow = calcPSSMSimpleShadow("; + numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); + outStream << ", uniform float4 pssmSplitPoints \n"; } for (uint i = 0; i < numTextures; ++i) - outStream << "shadowMap" << i << ", "; - outStream << "\n "; - - for (uint i = 0; i < numTextures; ++i) - outStream << "lightSpacePos" << i << ", "; - if (prof->getReceiveDynamicShadowsDepth()) { - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "inverseShadowmapSize" << i << ", "; + outStream << ", float4 lightSpacePos" << i << " : TEXCOORD" << *texCoord << " \n" + << ", uniform sampler2D shadowMap" << i << " : register(s" << *sampler << ") \n"; + *sampler = *sampler + 1; + *texCoord = *texCoord + 1; + if (prof->getReceiveDynamicShadowsDepth()) { outStream << ", uniform float inverseShadowmapSize" << i << " \n"; } } - outStream << "\n" << - " pssmSplitPoints, camDepth);\n"; } - else + + //--------------------------------------------------------------------- + void TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperCg::generateFpDynamicShadows(const SM2Profile * prof, + const Terrain * terrain, + TechniqueType tt, + StringUtil::StrStreamType &outStream) { - if (prof->getReceiveDynamicShadowsDepth()) + if (prof->getReceiveDynamicShadowsPSSM()) { - outStream << - " float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0);"; + uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); + outStream << " float camDepth = uvMisc.z;\n"; + + if (prof->getReceiveDynamicShadowsDepth()) { outStream << " float rtshadow = calcPSSMDepthShadow("; } + else + { + outStream << " float rtshadow = calcPSSMSimpleShadow("; + } + for (uint i = 0; i < numTextures; ++i) + outStream << "shadowMap" << i << ", "; + outStream << "\n "; + + for (uint i = 0; i < numTextures; ++i) + outStream << "lightSpacePos" << i << ", "; + if (prof->getReceiveDynamicShadowsDepth()) + { + outStream << "\n "; + for (uint i = 0; i < numTextures; ++i) + outStream << "inverseShadowmapSize" << i << ", "; + } + outStream << "\n" + << " pssmSplitPoints, camDepth);\n"; } else { - outStream << - " float rtshadow = calcSimpleShadow(shadowMap0, lightSpacePos0);"; + if (prof->getReceiveDynamicShadowsDepth()) + { outStream << " float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0);"; } + else + { + outStream << " float rtshadow = calcSimpleShadow(shadowMap0, lightSpacePos0);"; + } } - } - outStream << - " shadow = min(shadow, rtshadow);\n"; -} - -//--------------------------------------------------------------------- -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperHLSL::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", GPT_VERTEX_PROGRAM); + outStream << " shadow = min(shadow, rtshadow);\n"; } - else - { - ret->unload(); - } - - if (prof->_isSM4Available()) - ret->setParameter("target", "vs_4_0"); - else if (prof->_isSM3Available()) - ret->setParameter("target", "vs_3_0"); - else - ret->setParameter("target", "vs_2_0"); - ret->setParameter("entry_point", "main_vp"); - - return ret; -} - -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperHLSL::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", GPT_FRAGMENT_PROGRAM); - } - else + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperHLSL::createVertexProgram(const SM2Profile *prof, + const Terrain *terrain, + TechniqueType tt) { - ret->unload(); - } + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getVertexProgramName(prof, terrain, tt); - if (prof->_isSM4Available()) - ret->setParameter("target", "ps_4_0"); - else if (prof->_isSM3Available()) - ret->setParameter("target", "ps_3_0"); - else - ret->setParameter("target", "ps_2_x"); - ret->setParameter("entry_point", "main_fp"); - - return ret; -} - -//--------------------------------------------------------------------- -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSL::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", GPT_VERTEX_PROGRAM); } + else + { + ret->unload(); + } - switch (tt) - { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; - } + if (prof->_isSM4Available()) + ret->setParameter("target", "vs_4_0"); + else if (prof->_isSM3Available()) + ret->setParameter("target", "vs_3_0"); + else + ret->setParameter("target", "vs_2_0"); + ret->setParameter("entry_point", "main_vp"); - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsl", GPT_VERTEX_PROGRAM); + return ret; } - else + + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperHLSL::createFragmentProgram( + const SM2Profile *prof, const Terrain *terrain, TechniqueType tt) { - ret->unload(); - } + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getFragmentProgramName(prof, terrain, tt); - return ret; -} + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", GPT_FRAGMENT_PROGRAM); } + else + { + ret->unload(); + } -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSL::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); + if (prof->_isSM4Available()) + ret->setParameter("target", "ps_4_0"); + else if (prof->_isSM3Available()) + ret->setParameter("target", "ps_3_0"); + else + ret->setParameter("target", "ps_2_x"); + ret->setParameter("entry_point", "main_fp"); - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsl", GPT_FRAGMENT_PROGRAM); + return ret; } - else + + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSL::createVertexProgram(const SM2Profile *prof, + const Terrain *terrain, + TechniqueType tt) { - ret->unload(); - } + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getVertexProgramName(prof, terrain, tt); - return ret; -} + switch (tt) + { + case HIGH_LOD: progName += "/hlod"; break; + case LOW_LOD: progName += "/llod"; break; + case RENDER_COMPOSITE_MAP: progName += "/comp"; break; + } -//--------------------------------------------------------------------- -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSLES::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", GPT_VERTEX_PROGRAM); } + else + { + ret->unload(); + } - switch (tt) - { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; + return ret; } - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSL::createFragmentProgram( + const SM2Profile *prof, const Terrain *terrain, TechniqueType tt) { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsles", GPT_VERTEX_PROGRAM); + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getFragmentProgramName(prof, terrain, tt); + + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", GPT_FRAGMENT_PROGRAM); } + else + { + ret->unload(); + } + + return ret; } - else + + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSLES::createVertexProgram( + const SM2Profile *prof, const Terrain *terrain, TechniqueType tt) { - ret->unload(); - } + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getVertexProgramName(prof, terrain, tt); - return ret; -} + switch (tt) + { + case HIGH_LOD: progName += "/hlod"; break; + case LOW_LOD: progName += "/llod"; break; + case RENDER_COMPOSITE_MAP: progName += "/comp"; break; + } -//--------------------------------------------------------------------- -HighLevelGpuProgramPtr -TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSLES::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsles", GPT_VERTEX_PROGRAM); } + else + { + ret->unload(); + } - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsles", GPT_FRAGMENT_PROGRAM); + return ret; } - else + + //--------------------------------------------------------------------- + HighLevelGpuProgramPtr TerrainPSSMMaterialGenerator::SM2Profile::ShaderHelperGLSLES::createFragmentProgram( + const SM2Profile *prof, const Terrain *terrain, TechniqueType tt) { - ret->unload(); - } + HighLevelGpuProgramManager &mgr = HighLevelGpuProgramManager::getSingleton(); + String progName = getFragmentProgramName(prof, terrain, tt); - return ret; -} + HighLevelGpuProgramPtr ret = mgr.getByName(progName); + if (ret.isNull()) + { + ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsles", GPT_FRAGMENT_PROGRAM); + } + else + { + ret->unload(); + } + + return ret; + } -} +} // namespace Ogre diff --git a/source/main/terrain/OgreTerrainPSSMMaterialGenerator.h b/source/main/terrain/OgreTerrainPSSMMaterialGenerator.h index 5991dffa59..4a9dd9a168 100644 --- a/source/main/terrain/OgreTerrainPSSMMaterialGenerator.h +++ b/source/main/terrain/OgreTerrainPSSMMaterialGenerator.h @@ -28,266 +28,366 @@ THE SOFTWARE. #pragma once -#include -#include #include +#include +#include -namespace Ogre { -class PSSMShadowCameraSetup; - -/** \addtogroup Optional Components -* @{ -*/ -/** \addtogroup Terrain -* Some details on the terrain component -* @{ -*/ - -/** A TerrainMaterialGenerator which can cope with normal mapped, specular mapped -terrain. -@note Requires the Cg plugin to render correctly -*/ -class TerrainPSSMMaterialGenerator : public TerrainMaterialGenerator +namespace Ogre { -public: - TerrainPSSMMaterialGenerator(); - ~TerrainPSSMMaterialGenerator(); - - /** Shader model 2 profile target. + class PSSMShadowCameraSetup; + + /** \addtogroup Optional Components + * @{ + */ + /** \addtogroup Terrain + * Some details on the terrain component + * @{ + */ + + /** A TerrainMaterialGenerator which can cope with normal mapped, specular mapped + terrain. + @note Requires the Cg plugin to render correctly */ - class SM2Profile : public TerrainMaterialGenerator::Profile + class TerrainPSSMMaterialGenerator : public TerrainMaterialGenerator { - public: - SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc); - ~SM2Profile(); - MaterialPtr generate(const Terrain* terrain); - MaterialPtr generateForCompositeMap(const Terrain* terrain); - uint8 getMaxLayers(const Terrain* terrain) const; - void updateParams(const MaterialPtr& mat, const Terrain* terrain); - void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain); - void requestOptions(Terrain* terrain); - bool isVertexCompressionSupported() const; - - /** Whether to support normal mapping per layer in the shader (default true). - */ - bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; } - /** Whether to support normal mapping per layer in the shader (default true). - */ - void setLayerNormalMappingEnabled(bool enabled); - - /** Whether to support parallax mapping per layer in the shader (default true). - */ - bool isLayerParallaxMappingEnabled() const { return mLayerParallaxMappingEnabled; } - /** Whether to support parallax mapping per layer in the shader (default true). - */ - void setLayerParallaxMappingEnabled(bool enabled); - - /** Whether to support specular mapping per layer in the shader (default true). - */ - bool isLayerSpecularMappingEnabled() const { return mLayerSpecularMappingEnabled; } - /** Whether to support specular mapping per layer in the shader (default true). - */ - void setLayerSpecularMappingEnabled(bool enabled); - - /** Whether to support a global colour map over the terrain in the shader, - if it's present (default true). - */ - bool isGlobalColourMapEnabled() const { return mGlobalColourMapEnabled; } - /** Whether to support a global colour map over the terrain in the shader, - if it's present (default true). - */ - void setGlobalColourMapEnabled(bool enabled); - - /** Whether to support a light map over the terrain in the shader, - if it's present (default true). - */ - bool isLightmapEnabled() const { return mLightmapEnabled; } - /** Whether to support a light map over the terrain in the shader, - if it's present (default true). - */ - void setLightmapEnabled(bool enabled); - - /** Whether to use the composite map to provide a lower LOD technique - in the distance (default true). - */ - bool isCompositeMapEnabled() const { return mCompositeMapEnabled; } - /** Whether to use the composite map to provide a lower LOD technique - in the distance (default true). - */ - void setCompositeMapEnabled(bool enabled); - - /** Whether to support dynamic texture shadows received from other - objects, on the terrain (default true). - */ - bool getReceiveDynamicShadowsEnabled() const { return mReceiveDynamicShadows; } - /** Whether to support dynamic texture shadows received from other - objects, on the terrain (default true). - */ - void setReceiveDynamicShadowsEnabled(bool enabled); - - /** Whether to use PSSM support dynamic texture shadows, and if so the - settings to use (default 0). - */ - void setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings); - - /** Whether to use PSSM support dynamic texture shadows, and if so the - settings to use (default 0). - */ - PSSMShadowCameraSetup* getReceiveDynamicShadowsPSSM() const { return mPSSM; } - /** Whether to use depth shadows (default false). - */ - void setReceiveDynamicShadowsDepth(bool enabled); - - /** Whether to use depth shadows (default false). - */ - bool getReceiveDynamicShadowsDepth() const { return mDepthShadows; } - /** Whether to use shadows on low LOD material rendering (when using composite map) (default false). - */ - void setReceiveDynamicShadowsLowLod(bool enabled); - - /** Whether to use shadows on low LOD material rendering (when using composite map) (default false). - */ - bool getReceiveDynamicShadowsLowLod() const { return mLowLodShadows; } - - /// Internal - bool _isSM3Available() const { return mSM3Available; } - bool _isSM4Available() const { return mSM4Available; } - - protected: - - enum TechniqueType - { - HIGH_LOD, - LOW_LOD, - RENDER_COMPOSITE_MAP - }; + public: + TerrainPSSMMaterialGenerator(); + ~TerrainPSSMMaterialGenerator(); - void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt); - - /// Interface definition for helper class to generate shaders - class ShaderHelper : public TerrainAlloc + /** Shader model 2 profile target. + */ + class SM2Profile : public TerrainMaterialGenerator::Profile { - public: - ShaderHelper() + public: + SM2Profile(TerrainMaterialGenerator *parent, const String &name, const String &desc); + ~SM2Profile(); + MaterialPtr generate(const Terrain *terrain); + MaterialPtr generateForCompositeMap(const Terrain *terrain); + uint8 getMaxLayers(const Terrain *terrain) const; + void updateParams(const MaterialPtr &mat, const Terrain *terrain); + void updateParamsForCompositeMap(const MaterialPtr &mat, const Terrain *terrain); + void requestOptions(Terrain *terrain); + bool isVertexCompressionSupported() const; + + /** Whether to support normal mapping per layer in the shader (default true). + */ + bool isLayerNormalMappingEnabled() const { + return mLayerNormalMappingEnabled; } + /** Whether to support normal mapping per layer in the shader (default true). + */ + void setLayerNormalMappingEnabled(bool enabled); - virtual ~ShaderHelper() + /** Whether to support parallax mapping per layer in the shader (default true). + */ + bool isLayerParallaxMappingEnabled() const { + return mLayerParallaxMappingEnabled; } + /** Whether to support parallax mapping per layer in the shader (default true). + */ + void setLayerParallaxMappingEnabled(bool enabled); - virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual void updateParams(const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap); - protected: - virtual String getVertexProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual String getFragmentProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0; - virtual HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0; - virtual void generateVertexProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - virtual void generateFragmentProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - virtual void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0; - virtual void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0; - virtual void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void defaultVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog); - virtual void defaultFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog); - virtual void updateVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params); - virtual void updateFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params); - static String getChannel(uint idx); - - size_t mShadowSamplerStartHi; - size_t mShadowSamplerStartLo; - }; - - /// Utility class to help with generating shaders for Cg / HLSL. - class ShaderHelperCg : public ShaderHelper - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream); - void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream); - void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - uint generateVpDynamicShadowsParams(uint texCoordStart, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateVpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpDynamicShadowsHelpers(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpDynamicShadowsParams(uint* texCoord, uint* sampler, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - }; - - class ShaderHelperHLSL : public ShaderHelperCg - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - }; - - /// Utility class to help with generating shaders for GLSL. - class ShaderHelperGLSL : public ShaderHelper - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - - void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - - void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - - void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {} - - void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {} - - void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - - void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - }; + /** Whether to support specular mapping per layer in the shader (default true). + */ + bool isLayerSpecularMappingEnabled() const + { + return mLayerSpecularMappingEnabled; + } + /** Whether to support specular mapping per layer in the shader (default true). + */ + void setLayerSpecularMappingEnabled(bool enabled); + + /** Whether to support a global colour map over the terrain in the shader, + if it's present (default true). + */ + bool isGlobalColourMapEnabled() const + { + return mGlobalColourMapEnabled; + } + /** Whether to support a global colour map over the terrain in the shader, + if it's present (default true). + */ + void setGlobalColourMapEnabled(bool enabled); + + /** Whether to support a light map over the terrain in the shader, + if it's present (default true). + */ + bool isLightmapEnabled() const + { + return mLightmapEnabled; + } + /** Whether to support a light map over the terrain in the shader, + if it's present (default true). + */ + void setLightmapEnabled(bool enabled); + + /** Whether to use the composite map to provide a lower LOD technique + in the distance (default true). + */ + bool isCompositeMapEnabled() const + { + return mCompositeMapEnabled; + } + /** Whether to use the composite map to provide a lower LOD technique + in the distance (default true). + */ + void setCompositeMapEnabled(bool enabled); + + /** Whether to support dynamic texture shadows received from other + objects, on the terrain (default true). + */ + bool getReceiveDynamicShadowsEnabled() const + { + return mReceiveDynamicShadows; + } + /** Whether to support dynamic texture shadows received from other + objects, on the terrain (default true). + */ + void setReceiveDynamicShadowsEnabled(bool enabled); + + /** Whether to use PSSM support dynamic texture shadows, and if so the + settings to use (default 0). + */ + void setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup *pssmSettings); + + /** Whether to use PSSM support dynamic texture shadows, and if so the + settings to use (default 0). + */ + PSSMShadowCameraSetup *getReceiveDynamicShadowsPSSM() const + { + return mPSSM; + } + /** Whether to use depth shadows (default false). + */ + void setReceiveDynamicShadowsDepth(bool enabled); - /// Utility class to help with generating shaders for GLSL ES. - class ShaderHelperGLSLES : public ShaderHelper - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); + /** Whether to use depth shadows (default false). + */ + bool getReceiveDynamicShadowsDepth() const + { + return mDepthShadows; + } + /** Whether to use shadows on low LOD material rendering (when using composite map) (default false). + */ + void setReceiveDynamicShadowsLowLod(bool enabled); - void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} + /** Whether to use shadows on low LOD material rendering (when using composite map) (default false). + */ + bool getReceiveDynamicShadowsLowLod() const + { + return mLowLodShadows; + } - void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} + /// Internal + bool _isSM3Available() const + { + return mSM3Available; + } + bool _isSM4Available() const + { + return mSM4Available; + } - void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {} + protected: + enum TechniqueType + { + HIGH_LOD, + LOW_LOD, + RENDER_COMPOSITE_MAP + }; - void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {} + void addTechnique(const MaterialPtr &mat, const Terrain *terrain, TechniqueType tt); - void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} + /// Interface definition for helper class to generate shaders + class ShaderHelper : public TerrainAlloc + { + public: + ShaderHelper() + { + } + + virtual ~ShaderHelper() + { + } + + virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt); + virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt); + virtual void updateParams(const SM2Profile *prof, const MaterialPtr &mat, const Terrain *terrain, + bool compositeMap); + + protected: + virtual String getVertexProgramName(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + virtual String getFragmentProgramName(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + virtual HighLevelGpuProgramPtr createVertexProgram(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt) = 0; + virtual HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt) = 0; + virtual void generateVertexProgramSource(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + virtual void generateFragmentProgramSource(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + virtual void generateVpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) = 0; + virtual void generateFpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) = 0; + virtual void generateVpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) = 0; + virtual void generateFpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) = 0; + virtual void generateVpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) = 0; + virtual void generateFpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) = 0; + virtual void defaultVpParams(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + const HighLevelGpuProgramPtr &prog); + virtual void defaultFpParams(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + const HighLevelGpuProgramPtr &prog); + virtual void updateVpParams(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + const GpuProgramParametersSharedPtr ¶ms); + virtual void updateFpParams(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + const GpuProgramParametersSharedPtr ¶ms); + static String getChannel(uint idx); + + size_t mShadowSamplerStartHi; + size_t mShadowSamplerStartLo; + }; + + /// Utility class to help with generating shaders for Cg / HLSL. + class ShaderHelperCg : public ShaderHelper + { + protected: + HighLevelGpuProgramPtr createVertexProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + void generateVpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + void generateFpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + void generateVpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream); + void generateFpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream); + void generateVpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + void generateFpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + uint generateVpDynamicShadowsParams(uint texCoordStart, const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, StringUtil::StrStreamType &outStream); + void generateVpDynamicShadows(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + void generateFpDynamicShadowsHelpers(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + void generateFpDynamicShadowsParams(uint *texCoord, uint *sampler, const SM2Profile *prof, const Terrain *terrain, + TechniqueType tt, StringUtil::StrStreamType &outStream); + void generateFpDynamicShadows(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream); + }; + + class ShaderHelperHLSL : public ShaderHelperCg + { + protected: + HighLevelGpuProgramPtr createVertexProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + }; - void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} + /// Utility class to help with generating shaders for GLSL. + class ShaderHelperGLSL : public ShaderHelper + { + protected: + HighLevelGpuProgramPtr createVertexProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + + void generateVpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + + void generateFpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + + void generateVpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) + { + } + + void generateFpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) + { + } + + void generateVpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + + void generateFpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + }; + + /// Utility class to help with generating shaders for GLSL ES. + class ShaderHelperGLSLES : public ShaderHelper + { + protected: + HighLevelGpuProgramPtr createVertexProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt); + + void generateVpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + + void generateFpHeader(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + + void generateVpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) + { + } + + void generateFpLayer(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, uint layer, + StringUtil::StrStreamType &outStream) + { + } + + void generateVpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + + void generateFpFooter(const SM2Profile *prof, const Terrain *terrain, TechniqueType tt, + StringUtil::StrStreamType &outStream) + { + } + }; + + ShaderHelper * mShaderGen; + bool mLayerNormalMappingEnabled; + bool mLayerParallaxMappingEnabled; + bool mLayerSpecularMappingEnabled; + bool mGlobalColourMapEnabled; + bool mLightmapEnabled; + bool mCompositeMapEnabled; + bool mReceiveDynamicShadows; + PSSMShadowCameraSetup *mPSSM; + bool mDepthShadows; + bool mLowLodShadows; + bool mSM3Available; + bool mSM4Available; + + bool isShadowingEnabled(TechniqueType tt, const Terrain *terrain) const; }; - - ShaderHelper* mShaderGen; - bool mLayerNormalMappingEnabled; - bool mLayerParallaxMappingEnabled; - bool mLayerSpecularMappingEnabled; - bool mGlobalColourMapEnabled; - bool mLightmapEnabled; - bool mCompositeMapEnabled; - bool mReceiveDynamicShadows; - PSSMShadowCameraSetup* mPSSM; - bool mDepthShadows; - bool mLowLodShadows; - bool mSM3Available; - bool mSM4Available; - - bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const; }; -}; - -/** @} */ -/** @} */ -} + /** @} */ + /** @} */ +} // namespace Ogre diff --git a/source/main/terrain/TerrainGeometryManager.cpp b/source/main/terrain/TerrainGeometryManager.cpp index 39109a9ae4..e3fc67b129 100644 --- a/source/main/terrain/TerrainGeometryManager.cpp +++ b/source/main/terrain/TerrainGeometryManager.cpp @@ -23,13 +23,13 @@ #include "Application.h" #include "ContentManager.h" -#include "Language.h" #include "GUIManager.h" #include "GUI_LoadingWindow.h" -#include "TerrainManager.h" -#include "ShadowManager.h" -#include "OgreTerrainPSSMMaterialGenerator.h" +#include "Language.h" #include "OTCFileformat.h" +#include "OgreTerrainPSSMMaterialGenerator.h" +#include "ShadowManager.h" +#include "TerrainManager.h" #include #include @@ -42,10 +42,9 @@ using namespace RoR; /// @author: http://www.ogre3d.org/forums/viewtopic.php?f=5&t=72455 class Terrn2CustomMaterial : public Ogre::TerrainMaterialGenerator { -public: - - Terrn2CustomMaterial(Ogre::String materialName, bool addNormalmap, bool cloneMaterial) - : m_material_name(materialName), m_add_normal_map(addNormalmap), m_clone_material(cloneMaterial) + public: + Terrn2CustomMaterial(Ogre::String materialName, bool addNormalmap, bool cloneMaterial) + : m_material_name(materialName), m_add_normal_map(addNormalmap), m_clone_material(cloneMaterial) { mProfiles.push_back(OGRE_NEW Profile(this, CUSTOM_MAT_PROFILE_NAME, "Renders RoR terrn2 with custom material")); this->setActiveProfile(CUSTOM_MAT_PROFILE_NAME); @@ -59,26 +58,32 @@ class Terrn2CustomMaterial : public Ogre::TerrainMaterialGenerator class Profile : public Ogre::TerrainMaterialGenerator::Profile { - public: - Profile(Ogre::TerrainMaterialGenerator* parent, const Ogre::String& name, const Ogre::String& desc) - : Ogre::TerrainMaterialGenerator::Profile(parent, name, desc) + public: + Profile(Ogre::TerrainMaterialGenerator *parent, const Ogre::String &name, const Ogre::String &desc) + : Ogre::TerrainMaterialGenerator::Profile(parent, name, desc){}; + ~Profile() override{}; + + bool isVertexCompressionSupported() const + { + return false; + } + void setLightmapEnabled(bool set) /*override*/ + { + } // OGRE 1.8 doesn't have this method + Ogre::MaterialPtr generate(const Ogre::Terrain *terrain) override; + Ogre::uint8 getMaxLayers(const Ogre::Terrain *terrain) const override { + return 0; }; - ~Profile() override {}; + void updateParams(const Ogre::MaterialPtr &mat, const Ogre::Terrain *terrain) override{}; + void updateParamsForCompositeMap(const Ogre::MaterialPtr &mat, const Ogre::Terrain *terrain) override{}; - bool isVertexCompressionSupported () const { return false; } - void setLightmapEnabled (bool set) /*override*/ {} // OGRE 1.8 doesn't have this method - Ogre::MaterialPtr generate (const Ogre::Terrain* terrain) override; - Ogre::uint8 getMaxLayers (const Ogre::Terrain* terrain) const override { return 0; }; - void updateParams (const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) override {}; - void updateParamsForCompositeMap (const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) override {}; - - Ogre::MaterialPtr generateForCompositeMap(const Ogre::Terrain* terrain) override + Ogre::MaterialPtr generateForCompositeMap(const Ogre::Terrain *terrain) override { return terrain->_getCompositeMapMaterial(); }; - void requestOptions(Ogre::Terrain* terrain) override + void requestOptions(Ogre::Terrain *terrain) override { terrain->_setMorphRequired(false); terrain->_setNormalMapRequired(true); // enable global normal map @@ -87,40 +92,39 @@ class Terrn2CustomMaterial : public Ogre::TerrainMaterialGenerator }; }; -protected: + protected: Ogre::String m_material_name; - bool m_clone_material; - bool m_add_normal_map; + bool m_clone_material; + bool m_add_normal_map; }; -Ogre::MaterialPtr Terrn2CustomMaterial::Profile::generate(const Ogre::Terrain* terrain) +Ogre::MaterialPtr Terrn2CustomMaterial::Profile::generate(const Ogre::Terrain *terrain) { - const Ogre::String& matName = terrain->getMaterialName(); + const Ogre::String &matName = terrain->getMaterialName(); Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(matName); - if (!mat.isNull()) - Ogre::MaterialManager::getSingleton().remove(matName); + if (!mat.isNull()) Ogre::MaterialManager::getSingleton().remove(matName); - Terrn2CustomMaterial* parent = static_cast(this->getParent()); + Terrn2CustomMaterial *parent = static_cast(this->getParent()); - // Set Ogre material + // Set Ogre material mat = Ogre::MaterialManager::getSingleton().getByName(parent->m_material_name); // Clone material - if(parent->m_clone_material) + if (parent->m_clone_material) { - mat = mat->clone(matName); + mat = mat->clone(matName); parent->m_material_name = matName; } // Add normalmap - if(parent->m_add_normal_map) + if (parent->m_add_normal_map) { // Get default pass Ogre::Pass *p = mat->getTechnique(0)->getPass(0); // Add terrain's global normalmap to renderpass so the fragment program can find it. - Ogre::TextureUnitState *tu = p->createTextureUnitState(matName+"/nm"); + Ogre::TextureUnitState *tu = p->createTextureUnitState(matName + "/nm"); Ogre::TexturePtr nmtx = terrain->getTerrainNormalMap(); tu->_setTexturePtr(nmtx); @@ -129,46 +133,39 @@ Ogre::MaterialPtr Terrn2CustomMaterial::Profile::generate(const Ogre::Terrain* t return mat; }; -// ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- -#define XZSTR(X,Z) String("[") + TOSTRING(X) + String(",") + TOSTRING(Z) + String("]") +#define XZSTR(X, Z) String("[") + TOSTRING(X) + String(",") + TOSTRING(Z) + String("]") -TerrainGeometryManager::TerrainGeometryManager(TerrainManager* terrainManager) - : mHeightData(nullptr) - , mIsFlat(false) - , mMinHeight(0.0f) - , mMaxHeight(std::numeric_limits::min()) - , m_was_new_geometry_generated(false) - , terrainManager(terrainManager) +TerrainGeometryManager::TerrainGeometryManager(TerrainManager *terrainManager) + : mHeightData(nullptr), mIsFlat(false), mMinHeight(0.0f), mMaxHeight(std::numeric_limits::min()), + m_was_new_geometry_generated(false), terrainManager(terrainManager) { } TerrainGeometryManager::~TerrainGeometryManager() { - if (m_ogre_terrain_group != nullptr) - { - m_ogre_terrain_group->removeAllTerrains(); - } + if (m_ogre_terrain_group != nullptr) { m_ogre_terrain_group->removeAllTerrains(); } } /// @author Ported from OGRE engine, www.ogre3d.org, file OgreTerrain.cpp float TerrainGeometryManager::getHeightAtTerrainPosition(Real x, Real y) { // get left / bottom points (rounded down) - Real factor = (Real)mSize - 1.0f; + Real factor = (Real)mSize - 1.0f; Real invFactor = 1.0f / factor; long startX = static_cast(x * factor); long startY = static_cast(y * factor); - long endX = startX + 1; - long endY = startY + 1; + long endX = startX + 1; + long endY = startY + 1; // now get points in terrain space (effectively rounding them to boundaries) // note that we do not clamp! We need a valid plane Real startXTS = startX * invFactor; Real startYTS = startY * invFactor; - Real endXTS = endX * invFactor; - Real endYTS = endY * invFactor; + Real endXTS = endX * invFactor; + Real endYTS = endY * invFactor; // get parametric from start coord to next point Real xParam = (x * factor - startX); @@ -183,13 +180,13 @@ float TerrainGeometryManager::getHeightAtTerrainPosition(Real x, Real y) // Build all 4 positions in terrain space, using point-sampled height Vector3 v0(startXTS, startYTS, mHeightData[startY * mSize + startX]); - Vector3 v1(endXTS , startYTS, mHeightData[startY * mSize + endX]); - Vector3 v2(endXTS , endYTS , mHeightData[endY * mSize + endX]); - Vector3 v3(startXTS, endYTS , mHeightData[endY * mSize + startX]); + Vector3 v1(endXTS, startYTS, mHeightData[startY * mSize + endX]); + Vector3 v2(endXTS, endYTS, mHeightData[endY * mSize + endX]); + Vector3 v3(startXTS, endYTS, mHeightData[endY * mSize + startX]); // define this plane in terrain space Vector3 normal; - Real d; + Real d; if (startY % 2) { // odd row @@ -197,12 +194,12 @@ float TerrainGeometryManager::getHeightAtTerrainPosition(Real x, Real y) if (secondTri) { normal = (v1 - v0).crossProduct(v3 - v0); - d = -normal.dotProduct(v0); + d = -normal.dotProduct(v0); } else { normal = (v2 - v1).crossProduct(v3 - v1); - d = -normal.dotProduct(v1); + d = -normal.dotProduct(v1); } } else @@ -212,12 +209,12 @@ float TerrainGeometryManager::getHeightAtTerrainPosition(Real x, Real y) if (secondTri) { normal = (v2 - v0).crossProduct(v3 - v0); - d = -normal.dotProduct(v0); + d = -normal.dotProduct(v0); } else { normal = (v1 - v0).crossProduct(v2 - v0); - d = -normal.dotProduct(v0); + d = -normal.dotProduct(v0); } } @@ -227,10 +224,9 @@ float TerrainGeometryManager::getHeightAtTerrainPosition(Real x, Real y) float TerrainGeometryManager::getHeightAt(float x, float z) { - if (m_spec->is_flat) - return 0.0f; + if (m_spec->is_flat) return 0.0f; - float tx = (x - mBase - mPos.x) / ((mSize - 1) * mScale); + float tx = (x - mBase - mPos.x) / ((mSize - 1) * mScale); float ty = (z + mBase - mPos.z) / ((mSize - 1) * -mScale); if (tx <= 0.0f || ty <= 0.0f || tx >= 1.0f || ty >= 1.0f) @@ -244,7 +240,7 @@ float TerrainGeometryManager::getHeightAt(float x, float z) Ogre::Vector3 TerrainGeometryManager::getNormalAt(float x, float y, float z) { const float precision = 0.1f; - Vector3 normal(getHeightAt(x - precision, z) - y, precision, y - getHeightAt(x, z + precision)); + Vector3 normal(getHeightAt(x - precision, z) - y, precision, y - getHeightAt(x, z + precision)); normal.normalise(); return normal; } @@ -271,11 +267,11 @@ bool TerrainGeometryManager::InitTerrain(std::string otc_filename) { terrainManager->HandleException("Error reading main *.otc file"); // If we stop parsing we might break some legacy maps - //return false; + // return false; } // Load *.otc files for pages - for (OTCPage& page : otc_parser.GetDefinition()->pages) + for (OTCPage &page : otc_parser.GetDefinition()->pages) { if (page.pageconf_filename.empty()) { @@ -316,7 +312,7 @@ bool TerrainGeometryManager::InitTerrain(std::string otc_filename) configureTerrainDefaults(); - for (OTCPage& page : m_spec->pages) + for (OTCPage &page : m_spec->pages) { this->SetupGeometry(page, m_spec->is_flat); } @@ -325,24 +321,23 @@ bool TerrainGeometryManager::InitTerrain(std::string otc_filename) App::GetGuiManager()->GetLoadingWindow()->setProgress(44, _L("Loading terrain pages ...")); m_ogre_terrain_group->loadAllTerrains(true); - Terrain* terrain = m_ogre_terrain_group->getTerrain(0, 0); + Terrain *terrain = m_ogre_terrain_group->getTerrain(0, 0); - if (terrain == nullptr) - return true; + if (terrain == nullptr) return true; - mHeightData = terrain->getHeightData(); - mSize = terrain->getSize(); + mHeightData = terrain->getHeightData(); + mSize = terrain->getSize(); const float world_size = terrain->getWorldSize(); - mBase = -world_size * 0.5f; - mScale = world_size / (Real)(mSize - 1); - mPos = terrain->getPosition(); + mBase = -world_size * 0.5f; + mScale = world_size / (Real)(mSize - 1); + mPos = terrain->getPosition(); // terrain->getMinHeight() / terrain->getMaxHeight() seem to be unreliable ~ ulteq 12/18 for (int x = 0; x < mSize; x++) { for (int y = 0; y < mSize; y++) { - float h = mHeightData[y * mSize + x]; + float h = mHeightData[y * mSize + x]; mMinHeight = std::min(h, mMinHeight); mMaxHeight = std::max(mMaxHeight, h); } @@ -354,9 +349,9 @@ bool TerrainGeometryManager::InitTerrain(std::string otc_filename) // update the blend maps if (terrainManager->GetDef().custom_material_name.empty()) { - for (OTCPage& page : m_spec->pages) + for (OTCPage &page : m_spec->pages) { - Ogre::Terrain* terrain = m_ogre_terrain_group->getTerrain(page.pos_x, page.pos_z); + Ogre::Terrain *terrain = m_ogre_terrain_group->getTerrain(page.pos_x, page.pos_z); if (terrain != nullptr) { @@ -388,9 +383,8 @@ void TerrainGeometryManager::updateLightMap() while (ti.hasMoreElements()) { - Terrain* terrain = ti.getNext()->instance; - if (!terrain) - continue; + Terrain *terrain = ti.getNext()->instance; + if (!terrain) continue; if (!terrain->isDerivedDataUpdateInProgress()) { @@ -402,8 +396,8 @@ void TerrainGeometryManager::updateLightMap() void TerrainGeometryManager::UpdateMainLightPosition() { - Light* light = terrainManager->getMainLight(); - TerrainGlobalOptions* terrainOptions = TerrainGlobalOptions::getSingletonPtr(); + Light * light = terrainManager->getMainLight(); + TerrainGlobalOptions *terrainOptions = TerrainGlobalOptions::getSingletonPtr(); if (light) { terrainOptions->setLightMapDirection(light->getDerivedDirection()); @@ -416,13 +410,10 @@ void TerrainGeometryManager::UpdateMainLightPosition() void TerrainGeometryManager::configureTerrainDefaults() { - if (!TerrainGlobalOptions::getSingletonPtr()) - { - OGRE_NEW TerrainGlobalOptions(); - } + if (!TerrainGlobalOptions::getSingletonPtr()) { OGRE_NEW TerrainGlobalOptions(); } - TerrainGlobalOptions* terrainOptions = TerrainGlobalOptions::getSingletonPtr(); - std::string const & custom_mat = terrainManager->GetDef().custom_material_name; + TerrainGlobalOptions *terrainOptions = TerrainGlobalOptions::getSingletonPtr(); + std::string const & custom_mat = terrainManager->GetDef().custom_material_name; if (!custom_mat.empty()) { terrainOptions->setDefaultMaterialGenerator( @@ -430,37 +421,34 @@ void TerrainGeometryManager::configureTerrainDefaults() } else { - terrainOptions->setDefaultMaterialGenerator( - Ogre::TerrainMaterialGeneratorPtr(new Ogre::TerrainPSSMMaterialGenerator())); + terrainOptions->setDefaultMaterialGenerator(Ogre::TerrainMaterialGeneratorPtr(new Ogre::TerrainPSSMMaterialGenerator())); } // Configure global terrainOptions->setMaxPixelError(m_spec->max_pixel_error); // Important to set these so that the terrain knows what to use for derived (non-realtime) data - Light* light = terrainManager->getMainLight(); + Light *light = terrainManager->getMainLight(); if (light) { terrainOptions->setLightMapDirection(light->getDerivedDirection()); - if (custom_mat.empty()) - { - terrainOptions->setCompositeMapDiffuse(light->getDiffuseColour()); - } + if (custom_mat.empty()) { terrainOptions->setCompositeMapDiffuse(light->getDiffuseColour()); } } terrainOptions->setCompositeMapAmbient(gEnv->sceneManager->getAmbientLight()); // Configure default import settings for if we use imported image - Ogre::Terrain::ImportData& defaultimp = m_ogre_terrain_group->getDefaultImportSettings(); - defaultimp.terrainSize = m_spec->page_size; // the heightmap size - defaultimp.worldSize = m_spec->world_size; // this is the scaled up size, like 12km - defaultimp.inputScale = m_spec->world_size_y; - defaultimp.minBatchSize = m_spec->batch_size_min; - defaultimp.maxBatchSize = m_spec->batch_size_max; + Ogre::Terrain::ImportData &defaultimp = m_ogre_terrain_group->getDefaultImportSettings(); + defaultimp.terrainSize = m_spec->page_size; // the heightmap size + defaultimp.worldSize = m_spec->world_size; // this is the scaled up size, like 12km + defaultimp.inputScale = m_spec->world_size_y; + defaultimp.minBatchSize = m_spec->batch_size_min; + defaultimp.maxBatchSize = m_spec->batch_size_max; // optimizations - TerrainPSSMMaterialGenerator::SM2Profile* matProfile = nullptr; + TerrainPSSMMaterialGenerator::SM2Profile *matProfile = nullptr; if (custom_mat.empty()) { - matProfile = static_cast(terrainOptions->getDefaultMaterialGenerator()->getActiveProfile()); + matProfile = static_cast( + terrainOptions->getDefaultMaterialGenerator()->getActiveProfile()); if (matProfile) { matProfile->setLightmapEnabled(m_spec->lightmap_enabled); @@ -483,47 +471,39 @@ void TerrainGeometryManager::configureTerrainDefaults() } } - terrainOptions->setLayerBlendMapSize (m_spec->layer_blendmap_size); - terrainOptions->setCompositeMapSize (m_spec->composite_map_size); + terrainOptions->setLayerBlendMapSize(m_spec->layer_blendmap_size); + terrainOptions->setCompositeMapSize(m_spec->composite_map_size); terrainOptions->setCompositeMapDistance(m_spec->composite_map_distance); - terrainOptions->setSkirtSize (m_spec->skirt_size); - terrainOptions->setLightMapSize (m_spec->lightmap_size); + terrainOptions->setSkirtSize(m_spec->skirt_size); + terrainOptions->setLightMapSize(m_spec->lightmap_size); if (custom_mat.empty()) { - if (matProfile->getReceiveDynamicShadowsPSSM()) - { - terrainOptions->setCastsDynamicShadows(true); - } + if (matProfile->getReceiveDynamicShadowsPSSM()) { terrainOptions->setCastsDynamicShadows(true); } } terrainOptions->setUseRayBoxDistanceCalculation(false); - //TODO: Make this only when hydrax is enabled. + // TODO: Make this only when hydrax is enabled. terrainOptions->setUseVertexCompressionWhenAvailable(false); // HACK: Load the single page config now // This is how it "worked before" ~ only_a_ptr, 04/2017 - if (!m_spec->pages.empty()) - { - this->SetupLayers(*m_spec->pages.begin(), nullptr); - } + if (!m_spec->pages.empty()) { this->SetupLayers(*m_spec->pages.begin(), nullptr); } } // if terrain is set, we operate on the already loaded terrain -void TerrainGeometryManager::SetupLayers(RoR::OTCPage& page, Ogre::Terrain *terrain) +void TerrainGeometryManager::SetupLayers(RoR::OTCPage &page, Ogre::Terrain *terrain) { - if (page.num_layers == 0) - return; + if (page.num_layers == 0) return; - Ogre::Terrain::ImportData& defaultimp = m_ogre_terrain_group->getDefaultImportSettings(); + Ogre::Terrain::ImportData &defaultimp = m_ogre_terrain_group->getDefaultImportSettings(); - if (!terrain) - defaultimp.layerList.resize(page.num_layers); + if (!terrain) defaultimp.layerList.resize(page.num_layers); int layer_idx = 0; - for (OTCLayer& layer : page.layers) + for (OTCLayer &layer : page.layers) { if (!terrain) { @@ -543,42 +523,40 @@ void TerrainGeometryManager::SetupLayers(RoR::OTCPage& page, Ogre::Terrain *terr LOG("done loading page: loaded " + TOSTRING(layer_idx) + " layers"); } -void TerrainGeometryManager::SetupBlendMaps(OTCPage& page, Ogre::Terrain* terrain ) +void TerrainGeometryManager::SetupBlendMaps(OTCPage &page, Ogre::Terrain *terrain) { - const int layerCount = terrain->getLayerCount(); - auto layer_def_itor = page.layers.begin(); + const int layerCount = terrain->getLayerCount(); + auto layer_def_itor = page.layers.begin(); ++layer_def_itor; for (int i = 1; i < layerCount; i++) { - if (layer_def_itor->blendmap_filename.empty()) - continue; + if (layer_def_itor->blendmap_filename.empty()) continue; Ogre::Image img; try { img.load(layer_def_itor->blendmap_filename, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); } - catch (Exception& e) + catch (Exception &e) { LOG("Error loading blendmap: " + layer_def_itor->blendmap_filename + " : " + e.getFullDescription()); continue; } - TerrainLayerBlendMap* blendmap = terrain->getLayerBlendMap(i); + TerrainLayerBlendMap *blendmap = terrain->getLayerBlendMap(i); // resize that blending map so it will fit const Ogre::uint32 blendmapSize = terrain->getLayerBlendMapSize(); - if (img.getWidth() != blendmapSize) - img.resize(blendmapSize, blendmapSize); + if (img.getWidth() != blendmapSize) img.resize(blendmapSize, blendmapSize); // now to the ugly part - float* ptr = blendmap->getBlendPointer(); + float *ptr = blendmap->getBlendPointer(); for (Ogre::uint32 z = 0; z != blendmapSize; z++) { for (Ogre::uint32 x = 0; x != blendmapSize; x++) { - Ogre::ColourValue c = img.getColourAt(x, z, 0); - const float alpha = layer_def_itor->alpha; + Ogre::ColourValue c = img.getColourAt(x, z, 0); + const float alpha = layer_def_itor->alpha; if (layer_def_itor->blend_mode == 'R') *ptr++ = c.r * alpha; else if (layer_def_itor->blend_mode == 'G') @@ -598,15 +576,15 @@ void TerrainGeometryManager::SetupBlendMaps(OTCPage& page, Ogre::Terrain* terrai { for (int i = 1; i < layerCount; i++) { - Ogre::TerrainLayerBlendMap* blendMap = terrain->getLayerBlendMap(i); - Ogre::uint32 blendmapSize = terrain->getLayerBlendMapSize(); - Ogre::Image img; - unsigned short* idata = OGRE_ALLOC_T(unsigned short, blendmapSize * blendmapSize, Ogre::MEMCATEGORY_RESOURCE); - float scale = 65535.0f; + Ogre::TerrainLayerBlendMap *blendMap = terrain->getLayerBlendMap(i); + Ogre::uint32 blendmapSize = terrain->getLayerBlendMapSize(); + Ogre::Image img; + unsigned short *idata = OGRE_ALLOC_T(unsigned short, blendmapSize *blendmapSize, Ogre::MEMCATEGORY_RESOURCE); + float scale = 65535.0f; for (unsigned int x = 0; x < blendmapSize; x++) for (unsigned int z = 0; z < blendmapSize; z++) idata[x + z * blendmapSize] = (unsigned short)(blendMap->getBlendValue(x, blendmapSize - z) * scale); - img.loadDynamicImage((Ogre::uchar*)(idata), blendmapSize, blendmapSize, Ogre::PF_L16); + img.loadDynamicImage((Ogre::uchar *)(idata), blendmapSize, blendmapSize, Ogre::PF_L16); std::string fileName = "blendmap_layer_" + Ogre::StringConverter::toString(i) + ".png"; img.save(fileName); OGRE_FREE(idata, Ogre::MEMCATEGORY_RESOURCE); @@ -615,7 +593,7 @@ void TerrainGeometryManager::SetupBlendMaps(OTCPage& page, Ogre::Terrain* terrai } // Internal helper -bool LoadHeightmap(OTCPage& page, Image& img) +bool LoadHeightmap(OTCPage &page, Image &img) { if (page.heightmap_filename.empty()) { @@ -627,7 +605,8 @@ bool LoadHeightmap(OTCPage& page, Image& img) { // load raw data DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource(page.heightmap_filename); - LOG("[RoR|Terrain] loading RAW image: " + TOSTRING(stream->size()) + " / " + TOSTRING(page.raw_size*page.raw_size*page.raw_bpp)); + LOG("[RoR|Terrain] loading RAW image: " + TOSTRING(stream->size()) + " / " + + TOSTRING(page.raw_size * page.raw_size * page.raw_bpp)); PixelFormat pix_format = (page.raw_bpp == 2) ? PF_L16 : PF_L8; img.loadRawData(stream, page.raw_size, page.raw_size, 1, pix_format); } @@ -636,15 +615,13 @@ bool LoadHeightmap(OTCPage& page, Image& img) img.load(page.heightmap_filename, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } - if (page.raw_flip_x) - img.flipAroundX(); - if (page.raw_flip_y) - img.flipAroundY(); + if (page.raw_flip_x) img.flipAroundX(); + if (page.raw_flip_y) img.flipAroundY(); return true; } -void TerrainGeometryManager::SetupGeometry(RoR::OTCPage& page, bool flat) +void TerrainGeometryManager::SetupGeometry(RoR::OTCPage &page, bool flat) { if (flat) { @@ -654,7 +631,7 @@ void TerrainGeometryManager::SetupGeometry(RoR::OTCPage& page, bool flat) } const std::string page_cache_filename = m_ogre_terrain_group->generateFilename(page.pos_x, page.pos_z); - const std::string res_group = m_ogre_terrain_group->getResourceGroup(); + const std::string res_group = m_ogre_terrain_group->getResourceGroup(); if (!m_spec->disable_cache && ResourceGroupManager::getSingleton().resourceExists(res_group, page_cache_filename)) { // load from cache @@ -680,4 +657,3 @@ Ogre::Vector3 TerrainGeometryManager::getMaxTerrainSize() { return Vector3(m_spec->world_size_x, mMaxHeight, m_spec->world_size_z); } - diff --git a/source/main/terrain/TerrainGeometryManager.h b/source/main/terrain/TerrainGeometryManager.h index 4e96266fd0..3f5bbebb7e 100644 --- a/source/main/terrain/TerrainGeometryManager.h +++ b/source/main/terrain/TerrainGeometryManager.h @@ -21,9 +21,9 @@ #pragma once -#include "RoRPrerequisites.h" #include "ConfigFile.h" #include "OTCFileformat.h" +#include "RoRPrerequisites.h" #include #include @@ -31,13 +31,16 @@ /// this class handles all interactions with the Ogre Terrain system class TerrainGeometryManager : public ZeroedMemoryAllocator { -public: - TerrainGeometryManager(TerrainManager* terrainManager); + public: + TerrainGeometryManager(TerrainManager *terrainManager); ~TerrainGeometryManager(); bool InitTerrain(std::string otc_filename); - Ogre::TerrainGroup* getTerrainGroup() { return m_ogre_terrain_group; }; + Ogre::TerrainGroup *getTerrainGroup() + { + return m_ogre_terrain_group; + }; float getHeightAt(float x, float z); @@ -45,38 +48,39 @@ class TerrainGeometryManager : public ZeroedMemoryAllocator Ogre::Vector3 getMaxTerrainSize(); - bool isFlat() { return mIsFlat; }; + bool isFlat() + { + return mIsFlat; + }; void UpdateMainLightPosition(); void updateLightMap(); -private: - + private: float getHeightAtTerrainPosition(float x, float z); - bool getTerrainImage(int x, int y, Ogre::Image& img); - bool loadTerrainConfig(Ogre::String filename); - void configureTerrainDefaults(); - void SetupGeometry(RoR::OTCPage& page, bool flat=false); - void SetupBlendMaps(RoR::OTCPage& page, Ogre::Terrain* t); - void initTerrain(); - void SetupLayers(RoR::OTCPage& page, Ogre::Terrain *terrain); + bool getTerrainImage(int x, int y, Ogre::Image &img); + bool loadTerrainConfig(Ogre::String filename); + void configureTerrainDefaults(); + void SetupGeometry(RoR::OTCPage &page, bool flat = false); + void SetupBlendMaps(RoR::OTCPage &page, Ogre::Terrain *t); + void initTerrain(); + void SetupLayers(RoR::OTCPage &page, Ogre::Terrain *terrain); Ogre::DataStreamPtr getPageConfig(int x, int z); std::shared_ptr m_spec; - TerrainManager* terrainManager; - Ogre::TerrainGroup* m_ogre_terrain_group; - bool m_was_new_geometry_generated; + TerrainManager * terrainManager; + Ogre::TerrainGroup * m_ogre_terrain_group; + bool m_was_new_geometry_generated; // Terrn position lookup - ported from OGRE engine. Ogre::Vector3 mPos; - Ogre::Real mBase; - Ogre::Real mScale; - Ogre::uint16 mSize; - float* mHeightData; + Ogre::Real mBase; + Ogre::Real mScale; + Ogre::uint16 mSize; + float * mHeightData; bool mIsFlat; float mMinHeight; float mMaxHeight; }; - diff --git a/source/main/terrain/TerrainManager.cpp b/source/main/terrain/TerrainManager.cpp index 4883a84191..b167933587 100644 --- a/source/main/terrain/TerrainManager.cpp +++ b/source/main/terrain/TerrainManager.cpp @@ -23,11 +23,11 @@ #include "BeamFactory.h" #include "Collisions.h" -#include "Renderdash.h" #include "GUIManager.h" #include "GUI_LoadingWindow.h" #include "HydraxWater.h" #include "Language.h" +#include "Renderdash.h" #include "RoRFrameListener.h" #include "Scripting.h" #include "ShadowManager.h" @@ -37,25 +37,16 @@ #include "TerrainObjectManager.h" #include "Water.h" -#include #include +#include using namespace RoR; using namespace Ogre; TerrainManager::TerrainManager() - : m_collisions(0) - , m_geometry_manager(0) - , m_hdr_listener(0) - , m_object_manager(0) - , m_shadow_manager(0) - , m_sky_manager(0) - , SkyX_manager(0) - , m_sight_range(1000) - , m_main_light(0) - , m_paged_detail_factor(0.0f) - , m_cur_gravity(DEFAULT_GRAVITY) - , m_hydrax_water(nullptr) + : m_collisions(0), m_geometry_manager(0), m_hdr_listener(0), m_object_manager(0), m_shadow_manager(0), m_sky_manager(0), + SkyX_manager(0), m_sight_range(1000), m_main_light(0), m_paged_detail_factor(0.0f), m_cur_gravity(DEFAULT_GRAVITY), + m_hydrax_water(nullptr) { } @@ -67,20 +58,20 @@ TerrainManager::~TerrainManager() return; } - //I think that the order is important + // I think that the order is important #ifdef USE_CAELUM if (m_sky_manager != nullptr) { - delete(m_sky_manager); + delete (m_sky_manager); m_sky_manager = nullptr; } #endif // USE_CAELUM if (SkyX_manager != nullptr) { - delete(SkyX_manager); - gEnv->SkyX = nullptr; + delete (SkyX_manager); + gEnv->SkyX = nullptr; SkyX_manager = nullptr; } @@ -97,31 +88,35 @@ TerrainManager::~TerrainManager() if (m_object_manager != nullptr) { - delete(m_object_manager); + delete (m_object_manager); m_object_manager = nullptr; } if (m_geometry_manager != nullptr) { - delete(m_geometry_manager); + delete (m_geometry_manager); m_geometry_manager = nullptr; } if (m_shadow_manager != nullptr) { - delete(m_shadow_manager); + delete (m_shadow_manager); m_shadow_manager = nullptr; } if (gEnv->collisions != nullptr) { - delete(gEnv->collisions); + delete (gEnv->collisions); gEnv->collisions = nullptr; } } // some shortcut to remove ugly code -# define PROGRESS_WINDOW(x, y) { LOG(Ogre::String(" ## ") + y); RoR::App::GetGuiManager()->GetLoadingWindow()->setProgress(x, y); } +#define PROGRESS_WINDOW(x, y) \ + { \ + LOG(Ogre::String(" ## ") + y); \ + RoR::App::GetGuiManager()->GetLoadingWindow()->setProgress(x, y); \ + } bool TerrainManager::LoadAndPrepareTerrain(std::string filename) { @@ -130,7 +125,7 @@ bool TerrainManager::LoadAndPrepareTerrain(std::string filename) Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(filename); LOG(" ===== LOADING TERRAIN " + filename); Terrn2Parser parser; - if (! parser.LoadTerrn2(m_def, stream)) + if (!parser.LoadTerrn2(m_def, stream)) { LOG("[RoR|Terrain] Failed to parse: " + filename); for (std::string msg : parser.GetMessages()) @@ -171,7 +166,7 @@ bool TerrainManager::LoadAndPrepareTerrain(std::string filename) PROGRESS_WINDOW(27, _L("Initializing Light Subsystem")); initLight(); - if (App::gfx_sky_mode.GetActive() != GfxSkyMode::CAELUM) //Caelum has its own fog management + if (App::gfx_sky_mode.GetActive() != GfxSkyMode::CAELUM) // Caelum has its own fog management { PROGRESS_WINDOW(29, _L("Initializing Fog Subsystem")); initFog(); @@ -181,8 +176,8 @@ bool TerrainManager::LoadAndPrepareTerrain(std::string filename) initVegetation(); // water must be done later on - //PROGRESS_WINDOW(33, _L("Initializing Water Subsystem")); - //initWater(); + // PROGRESS_WINDOW(33, _L("Initializing Water Subsystem")); + // initWater(); fixCompositorClearColor(); @@ -194,7 +189,7 @@ bool TerrainManager::LoadAndPrepareTerrain(std::string filename) } PROGRESS_WINDOW(60, _L("Initializing Collision Subsystem")); - m_collisions = new Collisions(); + m_collisions = new Collisions(); gEnv->collisions = m_collisions; PROGRESS_WINDOW(75, _L("Initializing Script Subsystem")); @@ -207,7 +202,7 @@ bool TerrainManager::LoadAndPrepareTerrain(std::string filename) loadTerrainObjects(); // bake the decals - //finishTerrainDecal(); + // finishTerrainDecal(); // init things after loading the terrain initTerrainCollisions(); @@ -236,24 +231,22 @@ void TerrainManager::initCamera() if (App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX) { - m_sight_range = 5000; //Force unlimited for SkyX, lower settings are glitchy - } + m_sight_range = 5000; // Force unlimited for SkyX, lower settings are glitchy + } else { m_sight_range = App::gfx_sight_range.GetActive(); - } + } if (m_sight_range < UNLIMITED_SIGHTRANGE && App::gfx_sky_mode.GetActive() != GfxSkyMode::SKYX) - { - gEnv->mainCamera->setFarClipDistance(m_sight_range); - } + { gEnv->mainCamera->setFarClipDistance(m_sight_range); } else { // disabled in global config if (App::gfx_water_mode.GetActive() != GfxWaterMode::HYDRAX) - gEnv->mainCamera->setFarClipDistance(0); //Unlimited + gEnv->mainCamera->setFarClipDistance(0); // Unlimited else - gEnv->mainCamera->setFarClipDistance(9999 * 6); //Unlimited for hydrax and stuff + gEnv->mainCamera->setFarClipDistance(9999 * 6); // Unlimited for hydrax and stuff } } @@ -278,17 +271,17 @@ void TerrainManager::initSkySubSystem() } } else -#endif //USE_CAELUM - // SkyX skies - if (App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX) +#endif // USE_CAELUM + // SkyX skies + if (App::gfx_sky_mode.GetActive() == GfxSkyMode::SKYX) { - // try to load SkyX config - if (!m_def.skyx_config.empty() && ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(m_def.skyx_config)) + // try to load SkyX config + if (!m_def.skyx_config.empty() && ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(m_def.skyx_config)) SkyX_manager = new SkyXManager(m_def.skyx_config); - else + else SkyX_manager = new SkyXManager("SkyXDefault.skx"); - gEnv->SkyX = SkyX_manager; + gEnv->SkyX = SkyX_manager; } else { @@ -324,7 +317,7 @@ void TerrainManager::initLight() // Create a light m_main_light = gEnv->sceneManager->createLight("MainLight"); - //directional light for shadow + // directional light for shadow m_main_light->setType(Light::LT_DIRECTIONAL); m_main_light->setDirection(Ogre::Vector3(0.785, -0.423, 0.453).normalisedCopy()); @@ -341,25 +334,17 @@ void TerrainManager::initFog() if (m_sight_range >= UNLIMITED_SIGHTRANGE) gEnv->sceneManager->setFog(FOG_NONE); else - gEnv->sceneManager->setFog(FOG_LINEAR, m_def.ambient_color, 0.000f, m_sight_range * 0.65f, m_sight_range*0.9); + gEnv->sceneManager->setFog(FOG_LINEAR, m_def.ambient_color, 0.000f, m_sight_range * 0.65f, m_sight_range * 0.9); } void TerrainManager::initVegetation() { switch (App::gfx_vegetation_mode.GetActive()) { - case GfxVegetation::x20PERC: - m_paged_detail_factor = 0.2f; - break; - case GfxVegetation::x50PERC: - m_paged_detail_factor = 0.5f; - break; - case GfxVegetation::FULL: - m_paged_detail_factor = 1.0f; - break; - default: - m_paged_detail_factor = 0.0f; - break; + case GfxVegetation::x20PERC: m_paged_detail_factor = 0.2f; break; + case GfxVegetation::x50PERC: m_paged_detail_factor = 0.5f; break; + case GfxVegetation::FULL: m_paged_detail_factor = 1.0f; break; + default: m_paged_detail_factor = 0.0f; break; } } @@ -369,20 +354,18 @@ void TerrainManager::fixCompositorClearColor() // now with extensive error checking if (CompositorManager::getSingleton().hasCompositorChain(gEnv->mainCamera->getViewport())) { - CompositorInstance* co = CompositorManager::getSingleton().getCompositorChain(gEnv->mainCamera->getViewport())->_getOriginalSceneCompositor(); + CompositorInstance *co = + CompositorManager::getSingleton().getCompositorChain(gEnv->mainCamera->getViewport())->_getOriginalSceneCompositor(); if (co) { - CompositionTechnique* ct = co->getTechnique(); + CompositionTechnique *ct = co->getTechnique(); if (ct) { - CompositionTargetPass* ctp = ct->getOutputTargetPass(); + CompositionTargetPass *ctp = ct->getOutputTargetPass(); if (ctp) { - CompositionPass* p = ctp->getPass(0); - if (p) - { - p->setClearColour(Ogre::ColourValue::Black); - } + CompositionPass *p = ctp->getPass(0); + if (p) { p->setClearColour(Ogre::ColourValue::Black); } } } } @@ -392,22 +375,17 @@ void TerrainManager::fixCompositorClearColor() void TerrainManager::initWater() { // disabled in global config - if (App::gfx_water_mode.GetActive() == GfxWaterMode::NONE) - return; + if (App::gfx_water_mode.GetActive() == GfxWaterMode::NONE) return; // disabled in map config - if (!m_def.has_water) - { - return; - } + if (!m_def.has_water) { return; } if (App::gfx_water_mode.GetActive() == GfxWaterMode::HYDRAX) { // try to load hydrax config - if (!m_def.hydrax_conf_file.empty() && ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(m_def.hydrax_conf_file)) - { - m_hydrax_water = new HydraxWater(m_def.water_height, m_def.hydrax_conf_file); - } + if (!m_def.hydrax_conf_file.empty() && + ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(m_def.hydrax_conf_file)) + { m_hydrax_water = new HydraxWater(m_def.water_height, m_def.hydrax_conf_file); } else { // no config provided, fall back to the default one @@ -416,11 +394,11 @@ void TerrainManager::initWater() m_water = std::unique_ptr(m_hydrax_water); - //Apply depth technique to the terrain + // Apply depth technique to the terrain TerrainGroup::TerrainIterator ti = m_geometry_manager->getTerrainGroup()->getTerrainIterator(); while (ti.hasMoreElements()) { - Terrain* t = ti.getNext()->instance; + Terrain * t = ti.getNext()->instance; MaterialPtr ptr = t->getMaterial(); m_hydrax_water->GetHydrax()->getMaterialManager()->addDepthTechnique(ptr->createTechnique()); } @@ -451,10 +429,7 @@ void TerrainManager::loadTerrainObjects() void TerrainManager::initTerrainCollisions() { - if (!m_def.traction_map_file.empty()) - { - m_collisions->setupLandUse(m_def.traction_map_file.c_str()); - } + if (!m_def.traction_map_file.empty()) { m_collisions->setupLandUse(m_def.traction_map_file.c_str()); } } void TerrainManager::initScripting() @@ -464,8 +439,7 @@ void TerrainManager::initScripting() for (std::string as_filename : m_def.as_files) { - if (ScriptEngine::getSingleton().loadScript(as_filename) == 0) - loaded = true; + if (ScriptEngine::getSingleton().loadScript(as_filename) == 0) loaded = true; } if (!loaded) @@ -475,7 +449,7 @@ void TerrainManager::initScripting() } // finally activate AS logging, so we dont spam the users screen with initialization messages ScriptEngine::getSingleton().activateLogging(); -#endif //USE_ANGELSCRIPT +#endif // USE_ANGELSCRIPT } void TerrainManager::setGravity(float value) @@ -495,8 +469,7 @@ Ogre::AxisAlignedBox TerrainManager::getTerrainCollisionAAB() Ogre::Vector3 TerrainManager::getMaxTerrainSize() { - if (!m_geometry_manager) - return Vector3::ZERO; + if (!m_geometry_manager) return Vector3::ZERO; return m_geometry_manager->getMaxTerrainSize(); } @@ -510,7 +483,7 @@ Ogre::Vector3 TerrainManager::GetNormalAt(float x, float y, float z) return m_geometry_manager->getNormalAt(x, y, z); } -SkyManager* TerrainManager::getSkyManager() +SkyManager *TerrainManager::getSkyManager() { return m_sky_manager; } @@ -522,34 +495,31 @@ bool TerrainManager::isFlat() void TerrainManager::LoadTelepoints() { - if (m_object_manager) - m_object_manager->LoadTelepoints(); + if (m_object_manager) m_object_manager->LoadTelepoints(); } void TerrainManager::LoadPredefinedActors() { - if (m_object_manager) - m_object_manager->LoadPredefinedActors(); + if (m_object_manager) m_object_manager->LoadPredefinedActors(); } bool TerrainManager::HasPredefinedActors() { - if (m_object_manager) - return m_object_manager->HasPredefinedActors(); + if (m_object_manager) return m_object_manager->HasPredefinedActors(); return false; } -void TerrainManager::HandleException(const char* summary) +void TerrainManager::HandleException(const char *summary) { try { throw; // rethrow } - catch (Ogre::Exception& oex) + catch (Ogre::Exception &oex) { RoR::LogFormat("[RoR|Terrain] %s, message: '%s', type: .", summary, oex.getFullDescription().c_str()); } - catch (std::exception& stex) + catch (std::exception &stex) { RoR::LogFormat("[RoR|Terrain] %s, message: '%s', type: .", summary, stex.what()); } @@ -558,4 +528,3 @@ void TerrainManager::HandleException(const char* summary) RoR::LogFormat("[RoR|Terrain] %s, unknown error occurred.", summary); } } - diff --git a/source/main/terrain/TerrainManager.h b/source/main/terrain/TerrainManager.h index fbba4f88a0..1fbfa3b88a 100644 --- a/source/main/terrain/TerrainManager.h +++ b/source/main/terrain/TerrainManager.h @@ -29,47 +29,99 @@ class TerrainManager : public ZeroedMemoryAllocator { -public: - + public: TerrainManager(); ~TerrainManager(); - void setGravity(float value); - std::vector& GetAuthors(); - TerrainGeometryManager* getGeometryManager() { return m_geometry_manager; }; - TerrainObjectManager* getObjectManager() { return m_object_manager; }; + void setGravity(float value); + std::vector &GetAuthors(); + TerrainGeometryManager * getGeometryManager() + { + return m_geometry_manager; + }; + TerrainObjectManager *getObjectManager() + { + return m_object_manager; + }; Ogre::AxisAlignedBox getTerrainCollisionAAB(); - float getGravity() const { return m_cur_gravity; }; - std::string getTerrainName() const { return m_def.name; }; - std::string getGUID() const { return m_def.guid; }; - int getCategoryID() const { return m_def.category_id; }; - int getVersion() const { return m_def.version; }; - int getFarClip() const { return m_sight_range; } - float getPagedDetailFactor() const { return m_paged_detail_factor; }; - float getWaterHeight() const { return m_def.water_height; }; - Ogre::Vector3 getMaxTerrainSize(); - Collisions* getCollisions() { return m_collisions; }; - IWater* getWater() { return m_water.get(); }; - Ogre::Light* getMainLight() { return m_main_light; }; - Ogre::Vector3 getSpawnPos() { return m_def.start_position; }; - RoR::Terrn2Def& GetDef() { return m_def; } - HydraxWater* getHydraxManager() { return m_hydrax_water; } - SkyManager* getSkyManager(); - SkyXManager* getSkyXManager() { return SkyX_manager; }; - ShadowManager* getShadowManager() { return m_shadow_manager; }; - bool isFlat(); - void LoadTelepoints(); - void LoadPredefinedActors(); - bool HasPredefinedActors(); - bool LoadAndPrepareTerrain(std::string terrn2_filename); - void HandleException(const char* summary); - float GetHeightAt(float x, float z); - Ogre::Vector3 GetNormalAt(float x, float y, float z); + float getGravity() const + { + return m_cur_gravity; + }; + std::string getTerrainName() const + { + return m_def.name; + }; + std::string getGUID() const + { + return m_def.guid; + }; + int getCategoryID() const + { + return m_def.category_id; + }; + int getVersion() const + { + return m_def.version; + }; + int getFarClip() const + { + return m_sight_range; + } + float getPagedDetailFactor() const + { + return m_paged_detail_factor; + }; + float getWaterHeight() const + { + return m_def.water_height; + }; + Ogre::Vector3 getMaxTerrainSize(); + Collisions * getCollisions() + { + return m_collisions; + }; + IWater *getWater() + { + return m_water.get(); + }; + Ogre::Light *getMainLight() + { + return m_main_light; + }; + Ogre::Vector3 getSpawnPos() + { + return m_def.start_position; + }; + RoR::Terrn2Def &GetDef() + { + return m_def; + } + HydraxWater *getHydraxManager() + { + return m_hydrax_water; + } + SkyManager * getSkyManager(); + SkyXManager *getSkyXManager() + { + return SkyX_manager; + }; + ShadowManager *getShadowManager() + { + return m_shadow_manager; + }; + bool isFlat(); + void LoadTelepoints(); + void LoadPredefinedActors(); + bool HasPredefinedActors(); + bool LoadAndPrepareTerrain(std::string terrn2_filename); + void HandleException(const char *summary); + float GetHeightAt(float x, float z); + Ogre::Vector3 GetNormalAt(float x, float y, float z); static const int UNLIMITED_SIGHTRANGE = 4999; -private: - + private: SkyXManager *SkyX_manager; // internal methods void initCamera(); @@ -88,17 +140,17 @@ class TerrainManager : public ZeroedMemoryAllocator void fixCompositorClearColor(); void loadTerrainObjects(); - TerrainObjectManager* m_object_manager; - TerrainGeometryManager* m_geometry_manager; + TerrainObjectManager * m_object_manager; + TerrainGeometryManager *m_geometry_manager; std::unique_ptr m_water; - Collisions* m_collisions; - HDRListener* m_hdr_listener; - ShadowManager* m_shadow_manager; - SkyManager* m_sky_manager; - HydraxWater* m_hydrax_water; - Ogre::Light* m_main_light; - RoR::Terrn2Def m_def; - float m_cur_gravity; - float m_paged_detail_factor; - int m_sight_range; + Collisions * m_collisions; + HDRListener * m_hdr_listener; + ShadowManager * m_shadow_manager; + SkyManager * m_sky_manager; + HydraxWater * m_hydrax_water; + Ogre::Light * m_main_light; + RoR::Terrn2Def m_def; + float m_cur_gravity; + float m_paged_detail_factor; + int m_sight_range; }; diff --git a/source/main/terrain/TerrainObjectManager.cpp b/source/main/terrain/TerrainObjectManager.cpp index cc1ad8c72a..ef5ac1b9ac 100644 --- a/source/main/terrain/TerrainObjectManager.cpp +++ b/source/main/terrain/TerrainObjectManager.cpp @@ -26,14 +26,14 @@ #include "CacheSystem.h" #include "Collisions.h" #include "ErrorUtils.h" -#include "Language.h" #include "GUIManager.h" #include "GUI_LoadingWindow.h" +#include "Language.h" #include "MeshObject.h" #include "PlatformUtils.h" #include "ProceduralManager.h" -#include "Road2.h" #include "RoRFrameListener.h" +#include "Road2.h" #include "SoundScriptManager.h" #include "SurveyMapManager.h" #include "TerrainGeometryManager.h" @@ -41,36 +41,34 @@ #include "Utils.h" #include "WriteTextToTexture.h" -#include #include +#include #ifdef USE_ANGELSCRIPT -# include "ExtinguishableFireAffector.h" + #include "ExtinguishableFireAffector.h" #endif // USE_ANGELSCRIPT using namespace Ogre; using namespace RoR; using namespace Forests; -//workaround for pagedgeometry -inline float getTerrainHeight(Real x, Real z, void* unused = 0) +// workaround for pagedgeometry +inline float getTerrainHeight(Real x, Real z, void *unused = 0) { return App::GetSimTerrain()->GetHeightAt(x, z); } -TerrainObjectManager::TerrainObjectManager(TerrainManager* terrainManager) : - terrainManager(terrainManager) +TerrainObjectManager::TerrainObjectManager(TerrainManager *terrainManager) : terrainManager(terrainManager) { - //prepare for baking + // prepare for baking m_staticgeometry_bake_node = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); } TerrainObjectManager::~TerrainObjectManager() { - for (MeshObject* mo : m_mesh_objects) + for (MeshObject *mo : m_mesh_objects) { - if (mo) - delete mo; + if (mo) delete mo; } for (auto geom : m_paged_geometry) { @@ -82,31 +80,26 @@ TerrainObjectManager::~TerrainObjectManager() gEnv->sceneManager->destroyStaticGeometry("bakeSG"); m_staticgeometry = nullptr; } - if (m_procedural_mgr != nullptr) - { - delete m_procedural_mgr; - } + if (m_procedural_mgr != nullptr) { delete m_procedural_mgr; } gEnv->sceneManager->destroyAllEntities(); } void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) { - if (m_procedural_mgr == nullptr) - { - m_procedural_mgr = new ProceduralManager(); - } + if (m_procedural_mgr == nullptr) { m_procedural_mgr = new ProceduralManager(); } localizers.clear(); ProceduralObject po; - po.loadingState = -1; - int r2oldmode = 0; - int lastprogress = 0; - bool proroad = false; + po.loadingState = -1; + int r2oldmode = 0; + int lastprogress = 0; + bool proroad = false; DataStreamPtr ds; try { - ds = ResourceGroupManager::getSingleton().openResource(odefname, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); + ds = ResourceGroupManager::getSingleton().openResource(odefname, + Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); } catch (...) { @@ -115,12 +108,12 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) } int m_terrain_size_x = terrainManager->getGeometryManager()->getMaxTerrainSize().x; - int m_map_size_z = terrainManager->getGeometryManager()->getMaxTerrainSize().z; + int m_map_size_z = terrainManager->getGeometryManager()->getMaxTerrainSize().z; - Vector3 r2lastpos = Vector3::ZERO; + Vector3 r2lastpos = Vector3::ZERO; Quaternion r2lastrot = Quaternion::IDENTITY; - //long line = 0; + // long line = 0; char line[4096] = ""; while (!ds->eof()) @@ -132,35 +125,33 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) lastprogress = progress; } - char oname[1024] = {}; - char type[256] = {}; - char name[256] = {}; + char oname[1024] = {}; + char type[256] = {}; + char name[256] = {}; Vector3 pos(Vector3::ZERO); Vector3 rot(Vector3::ZERO); size_t ll = ds->readLine(line, 1023); - if (line[0] == '/' || line[0] == ';' || ll == 0) - continue; //comments - if (!strcmp("end", line)) - break; + if (line[0] == '/' || line[0] == ';' || ll == 0) continue; // comments + if (!strcmp("end", line)) break; if (!strncmp(line, "grid", 4)) { sscanf(line, "grid %f, %f, %f", &pos.x, &pos.y, &pos.z); - Ogre::ColourValue BackgroundColour = Ogre::ColourValue::White;//Ogre::ColourValue(0.1337f, 0.1337f, 0.1337f, 1.0f); - Ogre::ColourValue GridColour = Ogre::ColourValue(0.2f, 0.2f, 0.2f, 1.0f); + Ogre::ColourValue BackgroundColour = Ogre::ColourValue::White; // Ogre::ColourValue(0.1337f, 0.1337f, 0.1337f, 1.0f); + Ogre::ColourValue GridColour = Ogre::ColourValue(0.2f, 0.2f, 0.2f, 1.0f); - Ogre::ManualObject* mReferenceObject = new Ogre::ManualObject("ReferenceGrid"); + Ogre::ManualObject *mReferenceObject = new Ogre::ManualObject("ReferenceGrid"); mReferenceObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST); - Ogre::Real step = 1.0f; - unsigned int count = 50; - unsigned int halfCount = count / 2; - Ogre::Real full = (step * count); - Ogre::Real half = full / 2; - Ogre::Real y = 0; + Ogre::Real step = 1.0f; + unsigned int count = 50; + unsigned int halfCount = count / 2; + Ogre::Real full = (step * count); + Ogre::Real half = full / 2; + Ogre::Real y = 0; Ogre::ColourValue c; for (unsigned i = 0; i < count + 1; i++) { @@ -196,26 +187,26 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) mReferenceObject->end(); mReferenceObject->setCastShadows(false); - SceneNode* n = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + SceneNode *n = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); n->setPosition(pos); n->attachObject(mReferenceObject); n->setVisible(true); } - //ugly stuff to parse trees :) + // ugly stuff to parse trees :) if (!strncmp("trees", line, 5)) { - if (terrainManager->getPagedDetailFactor() == 0.0f) - continue; - char ColorMap[256] = {}; - char DensityMap[256] = {}; - char treemesh[256] = {}; - char treeCollmesh[256] = {}; - float gridspacing = 0.0f; + if (terrainManager->getPagedDetailFactor() == 0.0f) continue; + char ColorMap[256] = {}; + char DensityMap[256] = {}; + char treemesh[256] = {}; + char treeCollmesh[256] = {}; + float gridspacing = 0.0f; float yawfrom = 0.0f, yawto = 0.0f; float scalefrom = 0.0f, scaleto = 0.0f; float highdens = 1.0f; - int minDist = 90, maxDist = 700; - sscanf(line, "trees %f, %f, %f, %f, %f, %d, %d, %s %s %s %f %s", &yawfrom, &yawto, &scalefrom, &scaleto, &highdens, &minDist, &maxDist, treemesh, ColorMap, DensityMap, &gridspacing, treeCollmesh); + int minDist = 90, maxDist = 700; + sscanf(line, "trees %f, %f, %f, %f, %f, %d, %d, %s %s %s %f %s", &yawfrom, &yawto, &scalefrom, &scaleto, &highdens, + &minDist, &maxDist, treemesh, ColorMap, DensityMap, &gridspacing, treeCollmesh); if (strnlen(ColorMap, 3) == 0) { LOG("tree ColorMap map zero!"); @@ -226,10 +217,10 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) LOG("tree DensityMap zero!"); continue; } - Forests::DensityMap* densityMap = Forests::DensityMap::load(DensityMap, Forests::CHANNEL_COLOR); + Forests::DensityMap *densityMap = Forests::DensityMap::load(DensityMap, Forests::CHANNEL_COLOR); if (!densityMap) { - LOG("could not load densityMap: "+String(DensityMap)); + LOG("could not load densityMap: " + String(DensityMap)); continue; } densityMap->setFilter(Forests::MAPFILTER_BILINEAR); @@ -240,20 +231,18 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) geom->setBounds(bounds); // Set up LODs - float batchRange = std::max(50.0f, minDist * terrainManager->getPagedDetailFactor()); + float batchRange = std::max(50.0f, minDist * terrainManager->getPagedDetailFactor()); float imposterRange = std::max(1.5f * minDist, maxDist * terrainManager->getPagedDetailFactor()); geom->addDetailLevel(batchRange, batchRange / 2.0f); geom->addDetailLevel(imposterRange, imposterRange / 10.0f); - TreeLoader2D* tree_loader = new TreeLoader2D(geom, TBounds(0, 0, m_terrain_size_x, m_map_size_z)); + TreeLoader2D *tree_loader = new TreeLoader2D(geom, TBounds(0, 0, m_terrain_size_x, m_map_size_z)); geom->setPageLoader(tree_loader); tree_loader->setHeightFunction(&getTerrainHeight); - if (String(ColorMap) != "none") - { - tree_loader->setColorMap(ColorMap); - } + if (String(ColorMap) != "none") { tree_loader->setColorMap(ColorMap); } - Entity* curTree = gEnv->sceneManager->createEntity(String("paged_") + treemesh + TOSTRING(m_paged_geometry.size()), treemesh); + Entity *curTree = + gEnv->sceneManager->createEntity(String("paged_") + treemesh + TOSTRING(m_paged_geometry.size()), treemesh); if (gridspacing > 0) { @@ -263,19 +252,20 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) for (float z = 0; z < m_map_size_z; z += gridspacing) { float density = densityMap->_getDensityAt_Unfiltered(x, z, bounds); - if (density < 0.8f) - continue; - float nx = x + gridspacing * 0.5f; - float nz = z + gridspacing * 0.5f; - float yaw = Math::RangeRandom(yawfrom, yawto); - float scale = Math::RangeRandom(scalefrom, scaleto); - Vector3 pos = Vector3(nx, 0, nz); + if (density < 0.8f) continue; + float nx = x + gridspacing * 0.5f; + float nz = z + gridspacing * 0.5f; + float yaw = Math::RangeRandom(yawfrom, yawto); + float scale = Math::RangeRandom(scalefrom, scaleto); + Vector3 pos = Vector3(nx, 0, nz); tree_loader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale); if (strlen(treeCollmesh)) { pos.y = App::GetSimTerrain()->GetHeightAt(pos.x, pos.z); scale *= 0.1f; - gEnv->collisions->addCollisionMesh(String(treeCollmesh), pos, Quaternion(Degree(yaw), Vector3::UNIT_Y), Vector3(scale, scale, scale)); + gEnv->collisions->addCollisionMesh(String(treeCollmesh), pos, + Quaternion(Degree(yaw), Vector3::UNIT_Y), + Vector3(scale, scale, scale)); } } } @@ -283,39 +273,35 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) else { float gridsize = 10; - if (gridspacing < 0 && gridspacing != 0) - { - gridsize = -gridspacing; - } + if (gridspacing < 0 && gridspacing != 0) { gridsize = -gridspacing; } float hd = highdens; // normal style, random for (float x = 0; x < m_terrain_size_x; x += gridsize) { for (float z = 0; z < m_map_size_z; z += gridsize) { - if (highdens < 0) - hd = Math::RangeRandom(0, -highdens); + if (highdens < 0) hd = Math::RangeRandom(0, -highdens); float numTreesToPlace = hd * densityMap->_getDensityAt_Unfiltered(x, z, bounds); if (numTreesToPlace >= 1.0f) { numTreesToPlace *= terrainManager->getPagedDetailFactor(); if (numTreesToPlace > 1.0f || Math::RangeRandom(0, 1.0f) > numTreesToPlace) - { - numTreesToPlace = Math::Floor(numTreesToPlace); - } + { numTreesToPlace = Math::Floor(numTreesToPlace); } float nx = 0, nz = 0; while (numTreesToPlace-- > 0) { - nx = Math::RangeRandom(x, x + gridsize); - nz = Math::RangeRandom(z, z + gridsize); - float yaw = Math::RangeRandom(yawfrom, yawto); - float scale = Math::RangeRandom(scalefrom, scaleto); - Vector3 pos = Vector3(nx, 0, nz); + nx = Math::RangeRandom(x, x + gridsize); + nz = Math::RangeRandom(z, z + gridsize); + float yaw = Math::RangeRandom(yawfrom, yawto); + float scale = Math::RangeRandom(scalefrom, scaleto); + Vector3 pos = Vector3(nx, 0, nz); tree_loader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale); if (strlen(treeCollmesh)) { pos.y = App::GetSimTerrain()->GetHeightAt(pos.x, pos.z); - gEnv->collisions->addCollisionMesh(String(treeCollmesh), pos, Quaternion(Degree(yaw), Vector3::UNIT_Y), Vector3(scale, scale, scale)); + gEnv->collisions->addCollisionMesh(String(treeCollmesh), pos, + Quaternion(Degree(yaw), Vector3::UNIT_Y), + Vector3(scale, scale, scale)); } } } @@ -325,41 +311,45 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) m_paged_geometry.push_back(geom); } - //ugly stuff to parse grass :) + // ugly stuff to parse grass :) if (!strncmp("grass", line, 5) || !strncmp("grass2", line, 6)) { // is paged geometry disabled by configuration? - if (terrainManager->getPagedDetailFactor() == 0.0f) - continue; - int range = 80; - float SwaySpeed = 0.5, SwayLength = 0.05, SwayDistribution = 10.0, minx = 0.2, miny = 0.2, maxx = 1, maxy = 0.6, Density = 0.6, minH = -9999, maxH = 9999; - char grassmat[256] = ""; - char colorMapFilename[256] = ""; + if (terrainManager->getPagedDetailFactor() == 0.0f) continue; + int range = 80; + float SwaySpeed = 0.5, SwayLength = 0.05, SwayDistribution = 10.0, minx = 0.2, miny = 0.2, maxx = 1, maxy = 0.6, + Density = 0.6, minH = -9999, maxH = 9999; + char grassmat[256] = ""; + char colorMapFilename[256] = ""; char densityMapFilename[256] = ""; - int growtechnique = 0; - int techn = GRASSTECH_CROSSQUADS; + int growtechnique = 0; + int techn = GRASSTECH_CROSSQUADS; if (!strncmp("grass2", line, 6)) - sscanf(line, "grass2 %d, %f, %f, %f, %f, %f, %f, %f, %f, %d, %f, %f, %d, %s %s %s", &range, &SwaySpeed, &SwayLength, &SwayDistribution, &Density, &minx, &miny, &maxx, &maxy, &growtechnique, &minH, &maxH, &techn, grassmat, colorMapFilename, densityMapFilename); + sscanf(line, "grass2 %d, %f, %f, %f, %f, %f, %f, %f, %f, %d, %f, %f, %d, %s %s %s", &range, &SwaySpeed, + &SwayLength, &SwayDistribution, &Density, &minx, &miny, &maxx, &maxy, &growtechnique, &minH, &maxH, &techn, + grassmat, colorMapFilename, densityMapFilename); else if (!strncmp("grass", line, 5)) - sscanf(line, "grass %d, %f, %f, %f, %f, %f, %f, %f, %f, %d, %f, %f, %s %s %s", &range, &SwaySpeed, &SwayLength, &SwayDistribution, &Density, &minx, &miny, &maxx, &maxy, &growtechnique, &minH, &maxH, grassmat, colorMapFilename, densityMapFilename); + sscanf(line, "grass %d, %f, %f, %f, %f, %f, %f, %f, %f, %d, %f, %f, %s %s %s", &range, &SwaySpeed, &SwayLength, + &SwayDistribution, &Density, &minx, &miny, &maxx, &maxy, &growtechnique, &minH, &maxH, grassmat, + colorMapFilename, densityMapFilename); - //Initialize the PagedGeometry engine + // Initialize the PagedGeometry engine try { - PagedGeometry* grass = new PagedGeometry(gEnv->mainCamera, 30); - //Set up LODs + PagedGeometry *grass = new PagedGeometry(gEnv->mainCamera, 30); + // Set up LODs grass->addDetailLevel(range * terrainManager->getPagedDetailFactor()); // original value: 80 - //Set up a GrassLoader for easy use - GrassLoader* grassLoader = new GrassLoader(grass); + // Set up a GrassLoader for easy use + GrassLoader *grassLoader = new GrassLoader(grass); grass->setPageLoader(grassLoader); grassLoader->setHeightFunction(&getTerrainHeight); // render grass at first grassLoader->setRenderQueueGroup(RENDER_QUEUE_MAIN - 1); - GrassLayer* grassLayer = grassLoader->addLayer(grassmat); + GrassLayer *grassLayer = grassLoader->addLayer(grassmat); grassLayer->setHeightRange(minH, maxH); grassLayer->setLightingEnabled(true); @@ -368,7 +358,7 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) grassLayer->setSwayLength(SwayLength); grassLayer->setSwayDistribution(SwayDistribution); - //String grassdensityTextureFilename = String(DensityMap); + // String grassdensityTextureFilename = String(DensityMap); grassLayer->setDensity(Density * terrainManager->getPagedDetailFactor()); if (techn > 10) @@ -390,8 +380,8 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) grassLayer->setDensityMapFilter(MAPFILTER_BILINEAR); } - //grassLayer->setMinimumSize(0.5,0.5); - //grassLayer->setMaximumSize(1.0, 1.0); + // grassLayer->setMinimumSize(0.5,0.5); + // grassLayer->setMaximumSize(1.0, 1.0); grassLayer->setMinimumSize(minx, miny); grassLayer->setMaximumSize(maxx, maxy); @@ -416,18 +406,17 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) { // ugly stuff to parse procedural roads if (!strncmp("begin_procedural_roads", line, 22)) { - po = ProceduralObject(); + po = ProceduralObject(); po.loadingState = 1; - r2oldmode = 1; - proroad = true; + r2oldmode = 1; + proroad = true; continue; } if (!strncmp("end_procedural_roads", line, 20)) { if (r2oldmode) { - if (m_procedural_mgr) - m_procedural_mgr->addObject(po); + if (m_procedural_mgr) m_procedural_mgr->addObject(po); po = ProceduralObject(); } proroad = false; @@ -436,65 +425,64 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) if (proroad) { float rwidth, bwidth, bheight; - //position x,y,z rotation rx,ry,rz, width, border width, border height, type - int r = sscanf(line, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %s", &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z, &rwidth, &bwidth, &bheight, oname); - Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); - int roadtype = Road2::ROAD_AUTOMATIC; + // position x,y,z rotation rx,ry,rz, width, border width, border height, type + int r = sscanf(line, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %s", &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z, + &rwidth, &bwidth, &bheight, oname); + Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z); + int roadtype = Road2::ROAD_AUTOMATIC; int pillartype = 0; - if (!strcmp(oname, "flat")) - roadtype = Road2::ROAD_FLAT; - if (!strcmp(oname, "left")) - roadtype = Road2::ROAD_LEFT; - if (!strcmp(oname, "right")) - roadtype = Road2::ROAD_RIGHT; - if (!strcmp(oname, "both")) - roadtype = Road2::ROAD_BOTH; + if (!strcmp(oname, "flat")) roadtype = Road2::ROAD_FLAT; + if (!strcmp(oname, "left")) roadtype = Road2::ROAD_LEFT; + if (!strcmp(oname, "right")) roadtype = Road2::ROAD_RIGHT; + if (!strcmp(oname, "both")) roadtype = Road2::ROAD_BOTH; if (!strcmp(oname, "bridge")) { - roadtype = Road2::ROAD_BRIDGE; + roadtype = Road2::ROAD_BRIDGE; pillartype = 1; } if (!strcmp(oname, "monorail")) { - roadtype = Road2::ROAD_MONORAIL; + roadtype = Road2::ROAD_MONORAIL; pillartype = 2; } if (!strcmp(oname, "monorail2")) { - roadtype = Road2::ROAD_MONORAIL; + roadtype = Road2::ROAD_MONORAIL; pillartype = 0; } if (!strcmp(oname, "bridge_no_pillars")) { - roadtype = Road2::ROAD_BRIDGE; + roadtype = Road2::ROAD_BRIDGE; pillartype = 0; } if (r2oldmode) { - //fill object + // fill object ProceduralPoint pp; - pp.bheight = bheight; - pp.bwidth = bwidth; + pp.bheight = bheight; + pp.bwidth = bwidth; pp.pillartype = pillartype; - pp.position = pos; - pp.rotation = rotation; - pp.type = roadtype; - pp.width = rwidth; + pp.position = pos; + pp.rotation = rotation; + pp.type = roadtype; + pp.width = rwidth; po.points.push_back(pp); } continue; } - } //end of the ugly (somewhat) + } // end of the ugly (somewhat) memset(oname, 0, 1023); memset(type, 0, 255); memset(name, 0, 255); - int r = sscanf(line, "%f, %f, %f, %f, %f, %f, %s %s %s", &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z, oname, type, name); - if (r < 6) - continue; - if ((!strcmp(oname, "truck")) || (!strcmp(oname, "load") || (!strcmp(oname, "machine")) || (!strcmp(oname, "boat")) || (!strcmp(oname, "truck2")))) + int r = + sscanf(line, "%f, %f, %f, %f, %f, %f, %s %s %s", &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z, oname, type, name); + if (r < 6) continue; + if ((!strcmp(oname, "truck")) || + (!strcmp(oname, "load") || (!strcmp(oname, "machine")) || (!strcmp(oname, "boat")) || (!strcmp(oname, "truck2")))) { if (!strcmp(oname, "boat") && !terrainManager->getWater()) { @@ -510,32 +498,29 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) } PredefinedActor predef; - //this is a truck or load declaration - predef.px = pos.x; - predef.py = pos.y; - predef.pz = pos.z; + // this is a truck or load declaration + predef.px = pos.x; + predef.py = pos.y; + predef.pz = pos.z; predef.freePosition = (!strcmp(oname, "truck2")); - predef.ismachine = (!strcmp(oname, "machine")); - predef.rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); + predef.ismachine = (!strcmp(oname, "machine")); + predef.rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z); predef.name = actor_filename; m_predefined_actors.push_back(predef); continue; } - if (!strcmp(oname, "road") - || !strcmp(oname, "roadborderleft") - || !strcmp(oname, "roadborderright") - || !strcmp(oname, "roadborderboth") - || !strcmp(oname, "roadbridgenopillar") - || !strcmp(oname, "roadbridge")) + if (!strcmp(oname, "road") || !strcmp(oname, "roadborderleft") || !strcmp(oname, "roadborderright") || + !strcmp(oname, "roadborderboth") || !strcmp(oname, "roadbridgenopillar") || !strcmp(oname, "roadbridge")) { int pillartype = !(strcmp(oname, "roadbridgenopillar") == 0); // okay, this is a job for roads2 int roadtype = Road2::ROAD_AUTOMATIC; - if (!strcmp(oname, "road")) - roadtype = Road2::ROAD_FLAT; + if (!strcmp(oname, "road")) roadtype = Road2::ROAD_FLAT; Quaternion rotation; - rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); + rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z); if (pos.distance(r2lastpos) > 20.0f) { // break the road @@ -543,44 +528,43 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) { // fill object ProceduralPoint pp; - pp.bheight = 0.2; - pp.bwidth = 1.4; + pp.bheight = 0.2; + pp.bwidth = 1.4; pp.pillartype = pillartype; - pp.position = r2lastpos + r2lastrot * Vector3(10.0f, 0.0f, 0.9f); - pp.rotation = r2lastrot; - pp.type = roadtype; - pp.width = 8; + pp.position = r2lastpos + r2lastrot * Vector3(10.0f, 0.0f, 0.9f); + pp.rotation = r2lastrot; + pp.type = roadtype; + pp.width = 8; po.points.push_back(pp); // finish it and start new object - if (m_procedural_mgr) - m_procedural_mgr->addObject(po); - po = ProceduralObject(); + if (m_procedural_mgr) m_procedural_mgr->addObject(po); + po = ProceduralObject(); r2oldmode = 1; } r2oldmode = 1; // beginning of new ProceduralPoint pp; - pp.bheight = 0.2; - pp.bwidth = 1.4; + pp.bheight = 0.2; + pp.bwidth = 1.4; pp.pillartype = pillartype; - pp.position = pos; - pp.rotation = rotation; - pp.type = roadtype; - pp.width = 8; + pp.position = pos; + pp.rotation = rotation; + pp.type = roadtype; + pp.width = 8; po.points.push_back(pp); } else { // fill object ProceduralPoint pp; - pp.bheight = 0.2; - pp.bwidth = 1.4; + pp.bheight = 0.2; + pp.bwidth = 1.4; pp.pillartype = pillartype; - pp.position = pos; - pp.rotation = rotation; - pp.type = roadtype; - pp.width = 8; + pp.position = pos; + pp.rotation = rotation; + pp.type = roadtype; + pp.width = 8; po.points.push_back(pp); } r2lastpos = pos; @@ -598,18 +582,17 @@ void TerrainObjectManager::LoadTObjFile(Ogre::String odefname) { // fill object ProceduralPoint pp; - pp.bheight = 0.2; - pp.bwidth = 1.4; + pp.bheight = 0.2; + pp.bwidth = 1.4; pp.pillartype = 1; - pp.position = r2lastpos + r2lastrot * Vector3(10.0, 0, 0); - pp.rotation = r2lastrot; - pp.type = Road2::ROAD_AUTOMATIC; - pp.width = 8; + pp.position = r2lastpos + r2lastrot * Vector3(10.0, 0, 0); + pp.rotation = r2lastrot; + pp.type = Road2::ROAD_AUTOMATIC; + pp.width = 8; po.points.push_back(pp); // finish it and start new object - if (m_procedural_mgr) - m_procedural_mgr->addObject(po); + if (m_procedural_mgr) m_procedural_mgr->addObject(po); } } @@ -619,14 +602,15 @@ void TerrainObjectManager::PostLoadTerrain() m_staticgeometry = gEnv->sceneManager->createStaticGeometry("bakeSG"); m_staticgeometry->setCastShadows(true); m_staticgeometry->addSceneNode(m_staticgeometry_bake_node); - m_staticgeometry->setRegionDimensions(Vector3(terrainManager->getFarClip() / 2.0f, 10000.0, terrainManager->getFarClip() / 2.0f)); + m_staticgeometry->setRegionDimensions( + Vector3(terrainManager->getFarClip() / 2.0f, 10000.0, terrainManager->getFarClip() / 2.0f)); m_staticgeometry->setRenderingDistance(terrainManager->getFarClip()); try { m_staticgeometry->build(); m_staticgeometry_bake_node->detachAllObjects(); // crash under linux: - //m_staticgeometry_bake_node->removeAndDestroyAllChildren(); + // m_staticgeometry_bake_node->removeAndDestroyAllChildren(); } catch (...) { @@ -634,23 +618,22 @@ void TerrainObjectManager::PostLoadTerrain() } } -void TerrainObjectManager::MoveObjectVisuals(const String& instancename, const Ogre::Vector3& pos) +void TerrainObjectManager::MoveObjectVisuals(const String &instancename, const Ogre::Vector3 &pos) { if (m_static_objects.find(instancename) == m_static_objects.end()) { - LOG(instancename+ " not found!"); + LOG(instancename + " not found!"); return; } StaticObject obj = m_static_objects[instancename]; - if (!obj.enabled) - return; + if (!obj.enabled) return; obj.sceneNode->setPosition(pos); } -void TerrainObjectManager::unloadObject(const String& instancename) +void TerrainObjectManager::unloadObject(const String &instancename) { if (m_static_objects.find(instancename) == m_static_objects.end()) { @@ -660,8 +643,7 @@ void TerrainObjectManager::unloadObject(const String& instancename) StaticObject obj = m_static_objects[instancename]; - if (!obj.enabled) - return; + if (!obj.enabled) return; for (auto tri : obj.collTris) { @@ -677,10 +659,14 @@ void TerrainObjectManager::unloadObject(const String& instancename) obj.enabled = false; m_editor_objects.erase(std::remove_if(m_editor_objects.begin(), m_editor_objects.end(), - [instancename](EditorObject& e) { return e.instance_name == instancename; }), m_editor_objects.end()); + [instancename](EditorObject &e) { return e.instance_name == instancename; }), + m_editor_objects.end()); } -void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogre::Vector3& pos, const Ogre::Vector3& rot, Ogre::SceneNode* m_staticgeometry_bake_node, const Ogre::String& instancename, const Ogre::String& type, bool enable_collisions /* = true */, int scripthandler /* = -1 */, bool uniquifyMaterial /* = false */) +void TerrainObjectManager::LoadTerrainObject(const Ogre::String &name, const Ogre::Vector3 &pos, const Ogre::Vector3 &rot, + Ogre::SceneNode *m_staticgeometry_bake_node, const Ogre::String &instancename, + const Ogre::String &type, bool enable_collisions /* = true */, + int scripthandler /* = -1 */, bool uniquifyMaterial /* = false */) { if (type == "grid") { @@ -690,33 +676,34 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr for (int z = 0; z < 500; z += 50) { const String notype = ""; - LoadTerrainObject(name, pos + Vector3(x, 0.0f, z), rot, m_staticgeometry_bake_node, name, notype, enable_collisions, scripthandler, uniquifyMaterial); + LoadTerrainObject(name, pos + Vector3(x, 0.0f, z), rot, m_staticgeometry_bake_node, name, notype, + enable_collisions, scripthandler, uniquifyMaterial); } } return; } - if (name.empty()) - return; + if (name.empty()) return; - char mesh[1024] = {}; - char line[1024] = {}; - char collmesh[1024] = {}; + char mesh[1024] = {}; + char line[1024] = {}; + char collmesh[1024] = {}; Vector3 l(Vector3::ZERO); Vector3 h(Vector3::ZERO); Vector3 dr(Vector3::ZERO); Vector3 fc(Vector3::ZERO); Vector3 sc(Vector3::ZERO); Vector3 sr(Vector3::ZERO); - bool forcecam = false; - bool ismovable = false; + bool forcecam = false; + bool ismovable = false; int event_filter = EVENT_ALL; - Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); + Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * + Quaternion(Degree(rot.z), Vector3::UNIT_Z); String odefgroup = ""; - String odefname = name + ".odef"; + String odefname = name + ".odef"; if (!RoR::App::GetCacheSystem()->CheckResourceLoaded(odefname, odefgroup)) { LOG("Error while loading Terrain: could not find required .odef file: " + odefname + ". Ignoring entry."); @@ -732,17 +719,17 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr ds->readLine(mesh, 1023); } - //scale + // scale ds->readLine(line, 1023); sscanf(line, "%f, %f, %f", &sc.x, &sc.y, &sc.z); - static int objcounter = 0; - String entity_name = "object" + TOSTRING(objcounter) + "(" + name + ")"; + static int objcounter = 0; + String entity_name = "object" + TOSTRING(objcounter) + "(" + name + ")"; RoR::Utils::SanitizeUtf8String(entity_name); objcounter++; - SceneNode* tenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); + SceneNode *tenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); - MeshObject* mo = nullptr; + MeshObject *mo = nullptr; if (String(mesh) != "none") { mo = new MeshObject(mesh, Ogre::RGN_AUTODETECT, entity_name, tenode); @@ -756,41 +743,41 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr tenode->setVisible(true); // register in map - StaticObject* obj = &m_static_objects[instancename]; + StaticObject *obj = &m_static_objects[instancename]; obj->instanceName = instancename; - obj->enabled = true; - obj->sceneNode = tenode; + obj->enabled = true; + obj->sceneNode = tenode; obj->collTris.clear(); EditorObject object; - object.name = name; - object.instance_name = instancename; - object.position = pos; - object.rotation = rot; + object.name = name; + object.instance_name = instancename; + object.position = pos; + object.rotation = rot; object.initial_position = pos; object.initial_rotation = rot; - object.node = tenode; + object.node = tenode; m_editor_objects.push_back(object); if (mo && uniquifyMaterial && !instancename.empty()) { for (unsigned int i = 0; i < mo->getEntity()->getNumSubEntities(); i++) { - SubEntity* se = mo->getEntity()->getSubEntity(i); - String matname = se->getMaterialName(); - String newmatname = matname + "/" + instancename; + SubEntity *se = mo->getEntity()->getSubEntity(i); + String matname = se->getMaterialName(); + String newmatname = matname + "/" + instancename; se->getMaterial()->clone(newmatname); se->setMaterialName(newmatname); } } - //collision box(es) - bool virt = false; - bool rotating = false; + // collision box(es) + bool virt = false; + bool rotating = false; bool classic_ref = true; // everything is of concrete by default - ground_model_t* gm = gEnv->collisions->getGroundModelByString("concrete"); - char eventname[256] = {}; + ground_model_t *gm = gEnv->collisions->getGroundModelByString("concrete"); + char eventname[256] = {}; while (!ds->eof()) { size_t ll = ds->readLine(line, 1023); @@ -800,12 +787,10 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr Ogre::StringUtil::trim(line_str); RoR::Utils::SanitizeUtf8String(line_str); - const char* ptline = line_str.c_str(); - if (ll == 0 || line[0] == '/' || line[0] == ';') - continue; + const char *ptline = line_str.c_str(); + if (ll == 0 || line[0] == '/' || line[0] == ';') continue; - if (!strcmp("end", ptline)) - break; + if (!strcmp("end", ptline)) break; if (!strcmp("movable", ptline)) { ismovable = true; @@ -816,7 +801,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr localizer_t loc; loc.position = Vector3(pos.x, pos.y, pos.z); loc.rotation = rotation; - loc.type = Autopilot::LOCALIZER_HORIZONTAL; + loc.type = Autopilot::LOCALIZER_HORIZONTAL; localizers.push_back(loc); continue; } @@ -825,7 +810,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr localizer_t loc; loc.position = Vector3(pos.x, pos.y, pos.z); loc.rotation = rotation; - loc.type = Autopilot::LOCALIZER_VERTICAL; + loc.type = Autopilot::LOCALIZER_VERTICAL; localizers.push_back(loc); continue; } @@ -834,7 +819,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr localizer_t loc; loc.position = Vector3(pos.x, pos.y, pos.z); loc.rotation = rotation; - loc.type = Autopilot::LOCALIZER_NDB; + loc.type = Autopilot::LOCALIZER_NDB; localizers.push_back(loc); continue; } @@ -843,7 +828,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr localizer_t loc; loc.position = Vector3(pos.x, pos.y, pos.z); loc.rotation = rotation; - loc.type = Autopilot::LOCALIZER_VOR; + loc.type = Autopilot::LOCALIZER_VOR; localizers.push_back(loc); continue; } @@ -860,23 +845,23 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr { char tmp[255] = ""; sscanf(ptline, "sound %s", tmp); - SoundScriptInstance* sound = SoundScriptManager::getSingleton().createInstance(tmp, MAX_ACTORS + 1, tenode); + SoundScriptInstance *sound = SoundScriptManager::getSingleton().createInstance(tmp, MAX_ACTORS + 1, tenode); sound->setPosition(tenode->getPosition(), Vector3::ZERO); sound->start(); } -#endif //USE_OPENAL +#endif // USE_OPENAL continue; } if (!strcmp("beginbox", ptline) || !strcmp("beginmesh", ptline)) { - dr = Vector3::ZERO; - rotating = false; - virt = false; - forcecam = false; + dr = Vector3::ZERO; + rotating = false; + virt = false; + forcecam = false; event_filter = EVENT_NONE; eventname[0] = 0; - collmesh[0] = 0; - gm = gEnv->collisions->getGroundModelByString("concrete"); + collmesh[0] = 0; + gm = gEnv->collisions->getGroundModelByString("concrete"); continue; }; if (!strncmp("boxcoords", ptline, 9)) @@ -915,7 +900,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr if ((!strncmp("stdfriction", ptline, 11) || !strncmp("usefriction", ptline, 11)) && strlen(ptline) > 12) { String modelName = String(ptline + 12); - gm = gEnv->collisions->getGroundModelByString(modelName); + gm = gEnv->collisions->getGroundModelByString(modelName); continue; } if (!strcmp("virtual", ptline)) @@ -940,12 +925,10 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr event_filter = EVENT_DELETE; // fallback - if (strlen(ts) == 0) - event_filter = EVENT_ALL; + if (strlen(ts) == 0) event_filter = EVENT_ALL; // hack to avoid fps drops near spawnzones - if (!strncmp(eventname, "spawnzone", 9)) - event_filter = EVENT_AVATAR; + if (!strncmp(eventname, "spawnzone", 9)) event_filter = EVENT_AVATAR; continue; } @@ -955,37 +938,33 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr if (!box_is_valid) { RoR::LogFormat("[ODEF] Invalid collision box (file: '%s', event: '%s', instance: '%s')," - " at least one axis has negative size. Ignoring the box.", - name.c_str(), eventname, instancename.c_str()); + " at least one axis has negative size. Ignoring the box.", + name.c_str(), eventname, instancename.c_str()); continue; } bool race_event = !instancename.compare(0, 10, "checkpoint") || !instancename.compare(0, 4, "race"); if (enable_collisions && (App::sim_races_enabled.GetActive() || !race_event)) { - int boxnum = gEnv->collisions->addCollisionBox(tenode, rotating, virt, pos, rot, l, h, sr, eventname, instancename, forcecam, fc, sc, dr, event_filter, scripthandler); + int boxnum = gEnv->collisions->addCollisionBox(tenode, rotating, virt, pos, rot, l, h, sr, eventname, + instancename, forcecam, fc, sc, dr, event_filter, scripthandler); obj->collBoxes.push_back((boxnum)); if (race_event) { String type = "checkpoint"; - auto res = StringUtil::split(instancename, "|"); - if ((res.size() == 4 && res[2] == "0") || !instancename.compare(0, 4, "race")) - { - type = "racestart"; - } - int race_id = res.size() > 1 ? StringConverter::parseInt(res[1], -1) : -1; - auto ent = App::GetSimController()->GetGfxScene().GetSurveyMap()->createMapEntity(type); + auto res = StringUtil::split(instancename, "|"); + if ((res.size() == 4 && res[2] == "0") || !instancename.compare(0, 4, "race")) { type = "racestart"; } + int race_id = res.size() > 1 ? StringConverter::parseInt(res[1], -1) : -1; + auto ent = App::GetSimController()->GetGfxScene().GetSurveyMap()->createMapEntity(type); m_map_entities.push_back({ent, type, "", pos, rot.y, race_id}); } else if (!type.empty()) { String caption = ""; - if (type == "station" || type == "hotel" || type == "village" || - type == "observatory" || type == "farm" || type == "ship") - { - caption = instancename + " " + type; - } + if (type == "station" || type == "hotel" || type == "village" || type == "observatory" || type == "farm" || + type == "ship") + { caption = instancename + " " + type; } auto ent = App::GetSimController()->GetGfxScene().GetSurveyMap()->createMapEntity(type); m_map_entities.push_back({ent, type, caption, pos, rot.y, -1}); } @@ -994,17 +973,17 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr } if (!strcmp("endmesh", ptline)) { - gEnv->collisions->addCollisionMesh(collmesh, Vector3(pos.x, pos.y, pos.z), tenode->getOrientation(), sc, gm, &(obj->collTris)); + gEnv->collisions->addCollisionMesh(collmesh, Vector3(pos.x, pos.y, pos.z), tenode->getOrientation(), sc, gm, + &(obj->collTris)); continue; } if (!strncmp("particleSystem", ptline, 14) && tenode) { float x = 0, y = 0, z = 0, scale = 0; - char pname[255] = "", sname[255] = ""; - int res = sscanf(ptline, "particleSystem %f, %f, %f, %f, %s %s", &scale, &x, &y, &z, pname, sname); - if (res != 6) - continue; + char pname[255] = "", sname[255] = ""; + int res = sscanf(ptline, "particleSystem %f, %f, %f, %f, %s %s", &scale, &x, &y, &z, pname, sname); + if (res != 6) continue; // hacky: prevent duplicates String paname = String(pname); @@ -1012,25 +991,23 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr paname += "_"; // create particle system - ParticleSystem* pParticleSys = gEnv->sceneManager->createParticleSystem(paname, String(sname)); + ParticleSystem *pParticleSys = gEnv->sceneManager->createParticleSystem(paname, String(sname)); pParticleSys->setCastShadows(false); pParticleSys->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap // Some affectors may need its instance name (e.g. for script feedback purposes) #ifdef USE_ANGELSCRIPT - unsigned short affCount = pParticleSys->getNumAffectors(); - ParticleAffector* pAff; + unsigned short affCount = pParticleSys->getNumAffectors(); + ParticleAffector *pAff; for (unsigned short i = 0; i < affCount; ++i) { pAff = pParticleSys->getAffector(i); if (pAff->getType() == "ExtinguishableFire") - { - ((ExtinguishableFireAffector*)pAff)->setInstanceName(obj->instanceName); - } + { ((ExtinguishableFireAffector *)pAff)->setInstanceName(obj->instanceName); } } #endif // USE_ANGELSCRIPT - SceneNode* sn = tenode->createChildSceneNode(); + SceneNode *sn = tenode->createChildSceneNode(); sn->attachObject(pParticleSys); sn->pitch(Degree(90)); continue; @@ -1044,7 +1021,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr { mo->getEntity()->setMaterialName(String(mat)); // load it - //MaterialManager::getSingleton().load(String(mat), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + // MaterialManager::getSingleton().load(String(mat), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } continue; } @@ -1054,32 +1031,34 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr sscanf(ptline, "generateMaterialShaders %s", matn); if (RoR::App::gfx_enable_rtshaders.GetActive()) { - MaterialPtr mat = MaterialManager::getSingleton().create(matn,"generatedMaterialShaders"); - Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(*mat, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME); - Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, matn); + MaterialPtr mat = MaterialManager::getSingleton().create(matn, "generatedMaterialShaders"); + Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique( + *mat, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME); + Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, + matn); } continue; } if (!strncmp("playanimation", ptline, 13) && mo) { - char animname[256] = ""; + char animname[256] = ""; float speedfactorMin = 0, speedfactorMax = 0; sscanf(ptline, "playanimation %f, %f, %s", &speedfactorMin, &speedfactorMax, animname); if (tenode && mo->getEntity() && strnlen(animname, 250) > 0) { - AnimationStateSet* s = mo->getEntity()->getAllAnimationStates(); + AnimationStateSet *s = mo->getEntity()->getAllAnimationStates(); if (!s->hasAnimationState(String(animname))) { - LOG("[ODEF] animation '" + String(animname) + "' for mesh: '" + String(mesh) + "' in odef file '" + name + ".odef' not found!"); + LOG("[ODEF] animation '" + String(animname) + "' for mesh: '" + String(mesh) + "' in odef file '" + name + + ".odef' not found!"); continue; } AnimatedObject ao; - ao.node = tenode; - ao.ent = mo->getEntity(); + ao.node = tenode; + ao.ent = mo->getEntity(); ao.speedfactor = speedfactorMin; - if (speedfactorMin != speedfactorMax) - ao.speedfactor = Math::RangeRandom(speedfactorMin, speedfactorMax); + if (speedfactorMin != speedfactorMax) ao.speedfactor = Math::RangeRandom(speedfactorMin, speedfactorMax); ao.anim = 0; try { @@ -1091,7 +1070,8 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr } if (!ao.anim) { - LOG("[ODEF] animation '" + String(animname) + "' for mesh: '" + String(mesh) + "' in odef file '" + name + ".odef' not found!"); + LOG("[ODEF] animation '" + String(animname) + "' for mesh: '" + String(mesh) + "' in odef file '" + name + + ".odef' not found!"); continue; } ao.anim->setEnabled(true); @@ -1101,20 +1081,21 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr } if (!strncmp("drawTextOnMeshTexture", ptline, 21) && mo) { - if (!mo->getEntity()) - continue; - String matName = mo->getEntity()->getSubEntity(0)->getMaterialName(); - MaterialPtr m = MaterialManager::getSingleton().getByName(matName); + if (!mo->getEntity()) continue; + String matName = mo->getEntity()->getSubEntity(0)->getMaterialName(); + MaterialPtr m = MaterialManager::getSingleton().getByName(matName); if (m.getPointer() == 0) { - LOG("[ODEF] problem with drawTextOnMeshTexture command: mesh material not found: "+odefname+" : "+String(ptline)); + LOG("[ODEF] problem with drawTextOnMeshTexture command: mesh material not found: " + odefname + " : " + + String(ptline)); continue; } - String texName = m->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName(); - Texture* background = (Texture *)TextureManager::getSingleton().getByName(texName).getPointer(); + String texName = m->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName(); + Texture *background = (Texture *)TextureManager::getSingleton().getByName(texName).getPointer(); if (!background) { - LOG("[ODEF] problem with drawTextOnMeshTexture command: mesh texture not found: "+odefname+" : "+String(ptline)); + LOG("[ODEF] problem with drawTextOnMeshTexture command: mesh texture not found: " + odefname + " : " + + String(ptline)); continue; } @@ -1122,48 +1103,52 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr textureNumber++; char tmpTextName[256] = "", tmpMatName[256] = ""; sprintf(tmpTextName, "TextOnTexture_%d_Texture", textureNumber); - sprintf(tmpMatName, "TextOnTexture_%d_Material", textureNumber); // Make sure the texture is not WRITE_ONLY, we need to read the buffer to do the blending with the font (get the alpha for example) - TexturePtr texture = TextureManager::getSingleton().createManual(tmpTextName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (Ogre::uint)background->getWidth(), (Ogre::uint)background->getHeight(), MIP_UNLIMITED, PF_X8R8G8B8, Ogre::TU_STATIC | Ogre::TU_AUTOMIPMAP); + sprintf(tmpMatName, "TextOnTexture_%d_Material", + textureNumber); // Make sure the texture is not WRITE_ONLY, we need to read the buffer to do the + // blending with the font (get the alpha for example) + TexturePtr texture = TextureManager::getSingleton().createManual( + tmpTextName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (Ogre::uint)background->getWidth(), + (Ogre::uint)background->getHeight(), MIP_UNLIMITED, PF_X8R8G8B8, Ogre::TU_STATIC | Ogre::TU_AUTOMIPMAP); if (texture.getPointer() == 0) { - LOG("[ODEF] problem with drawTextOnMeshTexture command: could not create texture: "+odefname+" : "+String(ptline)); + LOG("[ODEF] problem with drawTextOnMeshTexture command: could not create texture: " + odefname + " : " + + String(ptline)); continue; } float x = 0, y = 0, w = 0, h = 0; float a = 0, r = 0, g = 0, b = 0; - int fs = 40, fdpi = 144; - char fontname[256] = ""; - char text[256] = ""; - char option = 'l'; - int res = sscanf(ptline, "drawTextOnMeshTexture %f, %f, %f, %f, %f, %f, %f, %f, %c, %i, %i, %s %s", &x, &y, &w, &h, &r, &g, &b, &a, &option, &fs, &fdpi, fontname, text); + int fs = 40, fdpi = 144; + char fontname[256] = ""; + char text[256] = ""; + char option = 'l'; + int res = sscanf(ptline, "drawTextOnMeshTexture %f, %f, %f, %f, %f, %f, %f, %f, %c, %i, %i, %s %s", &x, &y, &w, &h, + &r, &g, &b, &a, &option, &fs, &fdpi, fontname, text); if (res < 13) { - LOG("[ODEF] problem with drawTextOnMeshTexture command: "+odefname+" : "+String(ptline)); + LOG("[ODEF] problem with drawTextOnMeshTexture command: " + odefname + " : " + String(ptline)); continue; } // check if we got a template argument - if (!strncmp(text, "{{argument1}}", 13)) - strncpy(text, instancename.c_str(), 250); + if (!strncmp(text, "{{argument1}}", 13)) strncpy(text, instancename.c_str(), 250); // replace '_' with ' ' - char* text_pointer = text; + char *text_pointer = text; while (*text_pointer != 0) { - if (*text_pointer == '_') - *text_pointer = ' '; + if (*text_pointer == '_') *text_pointer = ' '; text_pointer++; }; - Ogre::Font* font = (Ogre::Font *)FontManager::getSingleton().getByName(String(fontname)).getPointer(); + Ogre::Font *font = (Ogre::Font *)FontManager::getSingleton().getByName(String(fontname)).getPointer(); if (!font) { - LOG("[ODEF] problem with drawTextOnMeshTexture command: font not found: "+odefname+" : "+String(ptline)); + LOG("[ODEF] problem with drawTextOnMeshTexture command: font not found: " + odefname + " : " + String(ptline)); continue; } - //Draw the background to the new texture + // Draw the background to the new texture texture->getBuffer()->blit(background->getBuffer()); x = background->getWidth() * x; @@ -1175,7 +1160,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr WriteToTexture(String(text), texture, box, font, ColourValue(r, g, b, a), fs, fdpi, option); // we can save it to disc for debug purposes: - //SaveImage(texture, "test.png"); + // SaveImage(texture, "test.png"); m->clone(tmpMatName); MaterialPtr mNew = MaterialManager::getSingleton().getByName(tmpMatName); @@ -1187,12 +1172,12 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr if (!strncmp("spotlight", ptline, 9)) { - Vector3 lpos, ldir; - float lrange = 10, innerAngle = 45, outerAngle = 45; + Vector3 lpos, ldir; + float lrange = 10, innerAngle = 45, outerAngle = 45; ColourValue lcol; - int res = sscanf(ptline, "spotlight %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", - &lpos.x, &lpos.y, &lpos.z, &ldir.x, &ldir.y, &ldir.z, &lcol.r, &lcol.g, &lcol.b, &lrange, &innerAngle, &outerAngle); + int res = sscanf(ptline, "spotlight %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", &lpos.x, &lpos.y, &lpos.z, + &ldir.x, &ldir.y, &ldir.z, &lcol.r, &lcol.g, &lcol.b, &lrange, &innerAngle, &outerAngle); if (res < 12) { LOG("ODEF: problem with light command: " + odefname + " : " + String(ptline)); @@ -1200,10 +1185,10 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr } static unsigned int counter = 0; - char name[50]; + char name[50]; snprintf(name, 50, "terrn2/spotlight-%u", counter); ++counter; - Light* spotLight = gEnv->sceneManager->createLight(name); + Light *spotLight = gEnv->sceneManager->createLight(name); spotLight->setType(Light::LT_SPOTLIGHT); spotLight->setPosition(lpos); @@ -1213,7 +1198,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr spotLight->setSpecularColour(lcol); spotLight->setSpotlightRange(Degree(innerAngle), Degree(outerAngle)); - BillboardSet* lflare = gEnv->sceneManager->createBillboardSet(1); + BillboardSet *lflare = gEnv->sceneManager->createBillboardSet(1); lflare->createBillboard(lpos, lcol); lflare->setMaterialName("tracks/flare"); lflare->setVisibilityFlags(DEPTHMAP_DISABLED); @@ -1221,7 +1206,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr float fsize = Math::Clamp(lrange / 10, 0.2f, 2.0f); lflare->setDefaultDimensions(fsize, fsize); - SceneNode* sn = tenode->createChildSceneNode(); + SceneNode *sn = tenode->createChildSceneNode(); sn->attachObject(spotLight); sn->attachObject(lflare); continue; @@ -1229,12 +1214,12 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr if (!strncmp("pointlight", ptline, 10)) { - Vector3 lpos, ldir; - float lrange = 10; + Vector3 lpos, ldir; + float lrange = 10; ColourValue lcol; - int res = sscanf(ptline, "pointlight %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", - &lpos.x, &lpos.y, &lpos.z, &ldir.x, &ldir.y, &ldir.z, &lcol.r, &lcol.g, &lcol.b, &lrange); + int res = sscanf(ptline, "pointlight %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", &lpos.x, &lpos.y, &lpos.z, &ldir.x, + &ldir.y, &ldir.z, &lcol.r, &lcol.g, &lcol.b, &lrange); if (res < 10) { LOG("ODEF: problem with light command: " + odefname + " : " + String(ptline)); @@ -1242,10 +1227,10 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr } static unsigned int counter = 0; - char name[50]; + char name[50]; snprintf(name, 50, "terrn2/pointlight-%x", counter); ++counter; - Light* pointlight = gEnv->sceneManager->createLight(name); + Light *pointlight = gEnv->sceneManager->createLight(name); pointlight->setType(Light::LT_POINT); pointlight->setPosition(lpos); @@ -1254,7 +1239,7 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr pointlight->setDiffuseColour(lcol); pointlight->setSpecularColour(lcol); - BillboardSet* lflare = gEnv->sceneManager->createBillboardSet(1); + BillboardSet *lflare = gEnv->sceneManager->createBillboardSet(1); lflare->createBillboard(lpos, lcol); lflare->setMaterialName("tracks/flare"); lflare->setVisibilityFlags(DEPTHMAP_DISABLED); @@ -1262,20 +1247,19 @@ void TerrainObjectManager::LoadTerrainObject(const Ogre::String& name, const Ogr float fsize = Math::Clamp(lrange / 10, 0.2f, 2.0f); lflare->setDefaultDimensions(fsize, fsize); - SceneNode* sn = tenode->createChildSceneNode(); + SceneNode *sn = tenode->createChildSceneNode(); sn->attachObject(pointlight); sn->attachObject(lflare); continue; } - LOG("ODEF: unknown command in "+odefname+" : "+String(ptline)); + LOG("ODEF: unknown command in " + odefname + " : " + String(ptline)); } } bool TerrainObjectManager::UpdateAnimatedObjects(float dt) { - if (m_animated_objects.size() == 0) - return true; + if (m_animated_objects.size() == 0) return true; std::vector::iterator it; @@ -1292,7 +1276,7 @@ bool TerrainObjectManager::UpdateAnimatedObjects(float dt) void TerrainObjectManager::LoadTelepoints() { - for (Terrn2Telepoint& telepoint: terrainManager->GetDef().telepoints) + for (Terrn2Telepoint &telepoint : terrainManager->GetDef().telepoints) { auto ent = App::GetSimController()->GetGfxScene().GetSurveyMap()->createMapEntity("telepoint"); m_map_entities.push_back({ent, "telepoint", telepoint.name, telepoint.position, 0}); @@ -1302,10 +1286,7 @@ void TerrainObjectManager::LoadTelepoints() void TerrainObjectManager::LoadPredefinedActors() { // in netmode, don't load other actors! - if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) - { - return; - } + if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { return; } for (unsigned int i = 0; i < m_predefined_actors.size(); i++) { @@ -1331,7 +1312,7 @@ bool TerrainObjectManager::UpdateTerrainObjects(float dt) for (auto e : m_map_entities) { - int id = App::GetSimController()->GetRaceId(); + int id = App::GetSimController()->GetRaceId(); bool visible = !((e.type == "checkpoint" && e.id != id) || (e.type == "racestart" && id != -1 && e.id != id)); App::GetSimController()->GetGfxScene().GetSurveyMap()->UpdateMapEntity(e.ent, e.name, e.pos, e.rot, -1, visible); } diff --git a/source/main/terrain/TerrainObjectManager.h b/source/main/terrain/TerrainObjectManager.h index e8c5461e30..077bd2b9b2 100644 --- a/source/main/terrain/TerrainObjectManager.h +++ b/source/main/terrain/TerrainObjectManager.h @@ -18,111 +18,118 @@ along with Rigs of Rods. If not, see . */ - #pragma once -#include "RoRPrerequisites.h" - #include "BatchPage.h" #include "GrassLoader.h" #include "ImpostorPage.h" #include "PagedGeometry.h" +#include "RoRPrerequisites.h" #include "TreeLoader2D.h" #include "TreeLoader3D.h" - class TerrainObjectManager : public ZeroedMemoryAllocator { -public: - + public: struct EditorObject { - Ogre::String name; - Ogre::String instance_name; - Ogre::Vector3 position; - Ogre::Vector3 rotation; - Ogre::Vector3 initial_position; - Ogre::Vector3 initial_rotation; - Ogre::SceneNode* node; + Ogre::String name; + Ogre::String instance_name; + Ogre::Vector3 position; + Ogre::Vector3 rotation; + Ogre::Vector3 initial_position; + Ogre::Vector3 initial_rotation; + Ogre::SceneNode *node; }; - TerrainObjectManager(TerrainManager* terrainManager); + TerrainObjectManager(TerrainManager *terrainManager); ~TerrainObjectManager(); - std::vector& GetEditorObjects() { return m_editor_objects; } - void LoadTObjFile(Ogre::String filename); - void LoadTerrainObject(const Ogre::String& name, const Ogre::Vector3& pos, const Ogre::Vector3& rot, Ogre::SceneNode* m_staticgeometry_bake_node, const Ogre::String& instancename, const Ogre::String& type, bool enable_collisions = true, int scripthandler = -1, bool uniquifyMaterial = false); - void MoveObjectVisuals(const Ogre::String& instancename, const Ogre::Vector3& pos); - void unloadObject(const Ogre::String& instancename); - void LoadTelepoints(); - void LoadPredefinedActors(); - bool HasPredefinedActors() { return !m_predefined_actors.empty(); }; - void PostLoadTerrain(); - bool UpdateTerrainObjects(float dt); + std::vector &GetEditorObjects() + { + return m_editor_objects; + } + void LoadTObjFile(Ogre::String filename); + void LoadTerrainObject(const Ogre::String &name, const Ogre::Vector3 &pos, const Ogre::Vector3 &rot, + Ogre::SceneNode *m_staticgeometry_bake_node, const Ogre::String &instancename, + const Ogre::String &type, bool enable_collisions = true, int scripthandler = -1, + bool uniquifyMaterial = false); + void MoveObjectVisuals(const Ogre::String &instancename, const Ogre::Vector3 &pos); + void unloadObject(const Ogre::String &instancename); + void LoadTelepoints(); + void LoadPredefinedActors(); + bool HasPredefinedActors() + { + return !m_predefined_actors.empty(); + }; + void PostLoadTerrain(); + bool UpdateTerrainObjects(float dt); typedef struct localizer_t { - int type; - Ogre::Vector3 position; + int type; + Ogre::Vector3 position; Ogre::Quaternion rotation; } localizer_t; - std::vector GetLocalizers() { return localizers; } -private: + std::vector GetLocalizers() + { + return localizers; + } + private: struct MapEntity { - SurveyMapEntity* ent; - Ogre::String type; - Ogre::String name; - Ogre::Vector3 pos; - float rot; - int id; + SurveyMapEntity *ent; + Ogre::String type; + Ogre::String name; + Ogre::Vector3 pos; + float rot; + int id; }; struct AnimatedObject { - Ogre::Entity* ent; - Ogre::SceneNode* node; - Ogre::AnimationState* anim; - float speedfactor; + Ogre::Entity * ent; + Ogre::SceneNode * node; + Ogre::AnimationState *anim; + float speedfactor; }; struct PredefinedActor { - float px; - float py; - float pz; + float px; + float py; + float pz; Ogre::Quaternion rotation; - std::string name; - bool ismachine; - bool freePosition; + std::string name; + bool ismachine; + bool freePosition; }; struct StaticObject { - Ogre::SceneNode* sceneNode; - Ogre::String instanceName; - bool enabled; + Ogre::SceneNode *sceneNode; + Ogre::String instanceName; + bool enabled; std::vector collBoxes; std::vector collTris; }; - bool UpdateAnimatedObjects(float dt); + bool UpdateAnimatedObjects(float dt); std::vector localizers; - std::map m_static_objects; - std::vector m_editor_objects; - std::vector m_predefined_actors; - std::vector m_animated_objects; - std::vector m_mesh_objects; - std::vector m_map_entities; - TerrainManager* terrainManager; - Ogre::StaticGeometry* m_staticgeometry; - ProceduralManager* m_procedural_mgr; - Road* m_road; - Ogre::SceneNode* m_staticgeometry_bake_node; - - std::vector m_paged_geometry; + std::map m_static_objects; + std::vector m_editor_objects; + std::vector m_predefined_actors; + std::vector m_animated_objects; + std::vector m_mesh_objects; + std::vector m_map_entities; + TerrainManager * terrainManager; + Ogre::StaticGeometry * m_staticgeometry; + ProceduralManager * m_procedural_mgr; + Road * m_road; + Ogre::SceneNode * m_staticgeometry_bake_node; + + std::vector m_paged_geometry; }; - diff --git a/source/main/terrain/map/SurveyMapEntity.cpp b/source/main/terrain/map/SurveyMapEntity.cpp index dc8295c55d..545301e428 100644 --- a/source/main/terrain/map/SurveyMapEntity.cpp +++ b/source/main/terrain/map/SurveyMapEntity.cpp @@ -25,11 +25,8 @@ using namespace Ogre; -SurveyMapEntity::SurveyMapEntity(String type, MyGUI::StaticImagePtr parent) : - mFileName("icon_" + type + ".dds") - , mParent(parent) - , mRotation(0) - , mType(type) +SurveyMapEntity::SurveyMapEntity(String type, MyGUI::StaticImagePtr parent) + : mFileName("icon_" + type + ".dds"), mParent(parent), mRotation(0), mType(type) { initialiseByAttributes(this, parent); @@ -42,16 +39,10 @@ SurveyMapEntity::SurveyMapEntity(String type, MyGUI::StaticImagePtr parent) : void SurveyMapEntity::setPosition(float x, float z) { - mMainWidget->setPosition( - x * mParent->getWidth() - mMainWidget->getWidth() / 2, - z * mParent->getHeight() - mMainWidget->getHeight() / 2 - ); - mIcon->setCoord( - mMainWidget->getWidth() / 2 - mIconSize.width / 2, - mMainWidget->getHeight() / 2 - mIconSize.height / 2, - mIconSize.width, - mIconSize.height - ); + mMainWidget->setPosition(x * mParent->getWidth() - mMainWidget->getWidth() / 2, + z * mParent->getHeight() - mMainWidget->getHeight() / 2); + mIcon->setCoord(mMainWidget->getWidth() / 2 - mIconSize.width / 2, mMainWidget->getHeight() / 2 - mIconSize.height / 2, + mIconSize.width, mIconSize.height); } void SurveyMapEntity::setRotation(float r) @@ -73,8 +64,7 @@ void SurveyMapEntity::setVisibility(bool v) void SurveyMapEntity::setState(int truckstate) { - if (mFileName == "icon_missing.dds") - return; + if (mFileName == "icon_missing.dds") return; String fileName = mFileName; @@ -106,12 +96,12 @@ void SurveyMapEntity::updateIcon() if (texture.isNull()) { mFileName = "icon_missing.dds"; - texture = TextureManager::getSingleton().getByName(mFileName); + texture = TextureManager::getSingleton().getByName(mFileName); } if (!texture.isNull()) { - mIconSize.width = (int)texture->getWidth(); + mIconSize.width = (int)texture->getWidth(); mIconSize.height = (int)texture->getHeight(); mIcon->setSize(mIconSize); } diff --git a/source/main/terrain/map/SurveyMapEntity.h b/source/main/terrain/map/SurveyMapEntity.h index ff0c4c568c..bb4abdd803 100644 --- a/source/main/terrain/map/SurveyMapEntity.h +++ b/source/main/terrain/map/SurveyMapEntity.h @@ -22,15 +22,13 @@ #pragma once #include "RoRPrerequisites.h" - #include "mygui/BaseLayout.h" ATTRIBUTE_CLASS_LAYOUT(SurveyMapEntity, "MapEntity.layout"); class SurveyMapEntity : public wraps::BaseLayout, public ZeroedMemoryAllocator { -public: - + public: SurveyMapEntity(Ogre::String type, MyGUI::StaticImagePtr parent); void setCaption(Ogre::String s); @@ -39,27 +37,27 @@ class SurveyMapEntity : public wraps::BaseLayout, public ZeroedMemoryAllocator void setState(int state); void setVisibility(bool value); - bool isPlayable() { return mType == "person" || mType == "truck" || mType == "airplane" || mType == "boat"; }; - -private: + bool isPlayable() + { + return mType == "person" || mType == "truck" || mType == "airplane" || mType == "boat"; + }; + private: MyGUI::StaticImagePtr mParent; ATTRIBUTE_FIELD_WIDGET_NAME(SurveyMapEntity, mCaption, "mCaption"); - MyGUI::StaticText* mCaption; + MyGUI::StaticText *mCaption; ATTRIBUTE_FIELD_WIDGET_NAME(SurveyMapEntity, mIcon, "mIcon"); - MyGUI::StaticImage* mIcon; - MyGUI::RotatingSkin* mIconRotating; + MyGUI::StaticImage * mIcon; + MyGUI::RotatingSkin *mIconRotating; MyGUI::IntSize mIconSize; - Ogre::Real mRotation; - Ogre::String mFileName; - Ogre::String mType; + Ogre::Real mRotation; + Ogre::String mFileName; + Ogre::String mType; void updateIcon(); }; - - diff --git a/source/main/terrain/map/SurveyMapManager.cpp b/source/main/terrain/map/SurveyMapManager.cpp index 6b24dbce56..14724e98fb 100644 --- a/source/main/terrain/map/SurveyMapManager.cpp +++ b/source/main/terrain/map/SurveyMapManager.cpp @@ -18,8 +18,6 @@ along with Rigs of Rods. If not, see . */ - - #include "SurveyMapManager.h" #include "Application.h" @@ -37,19 +35,10 @@ using namespace RoR; using namespace Ogre; -SurveyMapManager::SurveyMapManager() : - mMapCenter(Vector2::ZERO) - , mMapCenterOffset(Vector2::ZERO) - , mMapLastMode(SurveyMapMode::SMALL) - , mMapMode(SurveyMapMode::NONE) - , mMapSize(Vector2::ZERO) - , mMapTextureCreatorStatic() - , mMapTextureCreatorDynamic() - , mMapZoom(0.0f) - , mMapLastZoom(0.0f) - , mHidden(false) - , mPlayerPosition(Vector2::ZERO) - , mTerrainSize(Vector2::ZERO) +SurveyMapManager::SurveyMapManager() + : mMapCenter(Vector2::ZERO), mMapCenterOffset(Vector2::ZERO), mMapLastMode(SurveyMapMode::SMALL), + mMapMode(SurveyMapMode::NONE), mMapSize(Vector2::ZERO), mMapTextureCreatorStatic(), mMapTextureCreatorDynamic(), + mMapZoom(0.0f), mMapLastZoom(0.0f), mHidden(false), mPlayerPosition(Vector2::ZERO), mTerrainSize(Vector2::ZERO) { initialiseByAttributes(this); mMainWidget->setVisible(false); @@ -59,36 +48,33 @@ SurveyMapManager::~SurveyMapManager() { for (auto entity : mMapEntities) { - if (entity) - { - delete entity; - } + if (entity) { delete entity; } } } void SurveyMapManager::init() { - AxisAlignedBox aab = App::GetSimTerrain()->getTerrainCollisionAAB(); - Vector3 terrain_size = App::GetSimTerrain()->getMaxTerrainSize(); - bool use_aab = App::GetSimTerrain()->isFlat() && std::min(aab.getSize().x, aab.getSize().z) > 50.0f; + AxisAlignedBox aab = App::GetSimTerrain()->getTerrainCollisionAAB(); + Vector3 terrain_size = App::GetSimTerrain()->getMaxTerrainSize(); + bool use_aab = App::GetSimTerrain()->isFlat() && std::min(aab.getSize().x, aab.getSize().z) > 50.0f; if (terrain_size.isZeroLength() || use_aab && (aab.getSize().length() < terrain_size.length())) { - terrain_size = aab.getSize(); - terrain_size.y = aab.getMaximum().y; - Vector3 offset = aab.getCenter() - terrain_size / 2; + terrain_size = aab.getSize(); + terrain_size.y = aab.getMaximum().y; + Vector3 offset = aab.getCenter() - terrain_size / 2; mMapCenterOffset = Vector2(offset.x, offset.z); } - mTerrainSize = Vector2(terrain_size.x, terrain_size.z); + mTerrainSize = Vector2(terrain_size.x, terrain_size.z); mPlayerPosition = mTerrainSize / 2; - mMapCenter = mTerrainSize / 2; - mMapSize = mTerrainSize; + mMapCenter = mTerrainSize / 2; + mMapSize = mTerrainSize; - ConfigOptionMap ropts = App::GetOgreSubsystem()->GetOgreRoot()->getRenderSystem()->getConfigOptions(); - int resolution = StringConverter::parseInt(StringUtil::split(ropts["Video Mode"].currentValue, " x ")[0], 1024); - int fsaa = StringConverter::parseInt(ropts["FSAA"].currentValue, 0); - int res = std::pow(2, std::floor(std::log2(resolution))); + ConfigOptionMap ropts = App::GetOgreSubsystem()->GetOgreRoot()->getRenderSystem()->getConfigOptions(); + int resolution = StringConverter::parseInt(StringUtil::split(ropts["Video Mode"].currentValue, " x ")[0], 1024); + int fsaa = StringConverter::parseInt(ropts["FSAA"].currentValue, 0); + int res = std::pow(2, std::floor(std::log2(resolution))); mMapTextureCreatorStatic = std::unique_ptr(new SurveyMapTextureCreator(terrain_size.y)); mMapTextureCreatorStatic->init(res, fsaa); @@ -99,9 +85,9 @@ void SurveyMapManager::init() mMapTextureCreatorDynamic->init(res / 4, fsaa); mMapTextureCreatorDynamic->update(mMapCenter + mMapCenterOffset, mMapSize); - mMapTexture->eventMouseSetFocus += MyGUI::newDelegate(this, &SurveyMapManager::setFocus); - mMapTexture->eventMouseLostFocus += MyGUI::newDelegate(this, &SurveyMapManager::lostFocus); - mMapTexture->eventMouseMove += MyGUI::newDelegate(this, &SurveyMapManager::mouseMove); + mMapTexture->eventMouseSetFocus += MyGUI::newDelegate(this, &SurveyMapManager::setFocus); + mMapTexture->eventMouseLostFocus += MyGUI::newDelegate(this, &SurveyMapManager::lostFocus); + mMapTexture->eventMouseMove += MyGUI::newDelegate(this, &SurveyMapManager::mouseMove); mMapTexture->eventMouseButtonPressed += MyGUI::newDelegate(this, &SurveyMapManager::mousePressed); mCursorEntity = createMapEntity("other"); @@ -109,14 +95,14 @@ void SurveyMapManager::init() mCursorEntity->setCaption(_L("Teleport")); } -SurveyMapEntity* SurveyMapManager::createMapEntity(String type) +SurveyMapEntity *SurveyMapManager::createMapEntity(String type) { auto entity = new SurveyMapEntity(type, mMapTexture); mMapEntities.insert(entity); return entity; } -void SurveyMapManager::deleteMapEntity(SurveyMapEntity* entity) +void SurveyMapManager::deleteMapEntity(SurveyMapEntity *entity) { if (entity) { @@ -130,7 +116,7 @@ void SurveyMapManager::updateWindow() switch (mMapMode) { case SurveyMapMode::SMALL: setWindowPosition(1, -1, 0.30f); break; - case SurveyMapMode::BIG: setWindowPosition(0, 0, 0.98f); break; + case SurveyMapMode::BIG: setWindowPosition(0, 0, 0.98f); break; default:; } } @@ -144,8 +130,7 @@ void SurveyMapManager::setMapZoom(Real zoom) { zoom = Math::Clamp(zoom, 0.0f, std::max(0.0f, (mTerrainSize.x - 50.0f) / mTerrainSize.x)); - if (mMapZoom == zoom) - return; + if (mMapZoom == zoom) return; mMapZoom = zoom; updateMap(); @@ -163,16 +148,12 @@ void SurveyMapManager::updateMap() mMapCenter.x = Math::Clamp(mPlayerPosition.x - mMapCenterOffset.x, mMapSize.x / 2, mTerrainSize.x - mMapSize.x / 2); mMapCenter.y = Math::Clamp(mPlayerPosition.y - mMapCenterOffset.y, mMapSize.y / 2, mTerrainSize.y - mMapSize.y / 2); - if (mMapMode == SurveyMapMode::SMALL) - { - mMapTextureCreatorDynamic->update(mMapCenter + mMapCenterOffset, mMapSize); - } + if (mMapMode == SurveyMapMode::SMALL) { mMapTextureCreatorDynamic->update(mMapCenter + mMapCenterOffset, mMapSize); } } void SurveyMapManager::setPlayerPosition(Ogre::Vector2 position) { - if ((mPlayerPosition - position).isZeroLength()) - return; + if ((mPlayerPosition - position).isZeroLength()) return; mPlayerPosition = position; updateMap(); @@ -180,7 +161,7 @@ void SurveyMapManager::setPlayerPosition(Ogre::Vector2 position) void SurveyMapManager::setWindowPosition(int x, int y, float size) { - int rWinLeft, rWinTop; + int rWinLeft, rWinTop; unsigned int rWinWidth, rWinHeight, rWinDepth; App::GetOgreSubsystem()->GetRenderWindow()->getMetrics(rWinWidth, rWinHeight, rWinDepth, rWinLeft, rWinTop); @@ -189,10 +170,7 @@ void SurveyMapManager::setWindowPosition(int x, int y, float size) int realw = size * std::min(rWinWidth, rWinHeight) * mMapSize.x / std::max(mMapSize.x, mMapSize.y); int realh = size * std::min(rWinWidth, rWinHeight) * mMapSize.y / std::max(mMapSize.x, mMapSize.y); - if (x == -1) - { - realx = 0; - } + if (x == -1) { realx = 0; } else if (x == 0) { realx = (rWinWidth - realw) / 2; @@ -202,10 +180,7 @@ void SurveyMapManager::setWindowPosition(int x, int y, float size) realx = rWinWidth - realw; } - if (y == -1) - { - realy = 0; - } + if (y == -1) { realy = 0; } else if (y == 0) { realy = (rWinHeight - realh) / 2; @@ -222,22 +197,16 @@ Ogre::String SurveyMapManager::getTypeByDriveable(int driveable) { switch (driveable) { - case NOT_DRIVEABLE: - return "load"; - case TRUCK: - return "truck"; - case AIRPLANE: - return "airplane"; - case BOAT: - return "boat"; - case MACHINE: - return "machine"; - default: - return "unknown"; + case NOT_DRIVEABLE: return "load"; + case TRUCK: return "truck"; + case AIRPLANE: return "airplane"; + case BOAT: return "boat"; + case MACHINE: return "machine"; + default: return "unknown"; } } -void SurveyMapManager::Update(Ogre::Real dt, Actor* curr_truck) +void SurveyMapManager::Update(Ogre::Real dt, Actor *curr_truck) { if (App::GetInputEngine()->getEventBoolValueBounce(EV_SURVEY_MAP_CYCLE)) { @@ -253,8 +222,7 @@ void SurveyMapManager::Update(Ogre::Real dt, Actor* curr_truck) mMainWidget->setVisible(!mHidden && mMapMode != SurveyMapMode::NONE); - if (mHidden || mMapMode == SurveyMapMode::NONE) - return; + if (mHidden || mMapMode == SurveyMapMode::NONE) return; if (App::GetInputEngine()->getEventBoolValueBounce(EV_SURVEY_MAP_TOGGLE_ICONS)) App::gfx_surveymap_icons.SetActive(!App::gfx_surveymap_icons.GetActive()); @@ -267,25 +235,19 @@ void SurveyMapManager::Update(Ogre::Real dt, Actor* curr_truck) setMapZoom(mMapLastZoom); mMapLastZoom = 0.0f; } - if (App::GetInputEngine()->getEventBoolValue(EV_SURVEY_MAP_ZOOM_IN)) - { - setMapZoomRelative(+dt); - } - if (App::GetInputEngine()->getEventBoolValue(EV_SURVEY_MAP_ZOOM_OUT)) - { - setMapZoomRelative(-dt); - } + if (App::GetInputEngine()->getEventBoolValue(EV_SURVEY_MAP_ZOOM_IN)) { setMapZoomRelative(+dt); } + if (App::GetInputEngine()->getEventBoolValue(EV_SURVEY_MAP_ZOOM_OUT)) { setMapZoomRelative(-dt); } if (mMapZoom > 0.0f) { mMapTexture->setImageTexture(mMapTextureCreatorDynamic->getTextureName()); if (curr_truck) { - auto& simbuf = curr_truck->GetGfxActor()->GetSimDataBuffer(); + auto &simbuf = curr_truck->GetGfxActor()->GetSimDataBuffer(); setPlayerPosition(Vector2(simbuf.simbuf_pos.x, simbuf.simbuf_pos.z)); } else { - auto& simbuf = App::GetSimController()->GetGfxScene().GetSimDataBuffer(); + auto &simbuf = App::GetSimController()->GetGfxScene().GetSimDataBuffer(); setPlayerPosition(Vector2(simbuf.simbuf_character_pos.x, simbuf.simbuf_character_pos.z)); } mMapLastZoom = mMapZoom; @@ -311,8 +273,7 @@ void SurveyMapManager::Update(Ogre::Real dt, Actor* curr_truck) } break; - default: - break; + default: break; } } @@ -320,9 +281,9 @@ void SurveyMapManager::cycleMode() { switch (mMapMode) { - case SurveyMapMode::NONE: mMapLastMode = mMapMode = SurveyMapMode::SMALL; break; - case SurveyMapMode::SMALL: mMapLastMode = mMapMode = SurveyMapMode::BIG; break; - case SurveyMapMode::BIG: mMapMode = SurveyMapMode::NONE; break; + case SurveyMapMode::NONE: mMapLastMode = mMapMode = SurveyMapMode::SMALL; break; + case SurveyMapMode::SMALL: mMapLastMode = mMapMode = SurveyMapMode::BIG; break; + case SurveyMapMode::BIG: mMapMode = SurveyMapMode::NONE; break; default:; } updateWindow(); @@ -334,14 +295,14 @@ void SurveyMapManager::toggleMode() updateWindow(); } -void SurveyMapManager::UpdateMapEntity(SurveyMapEntity* e, String caption, Vector3 pos, float rot, int state, bool visible) +void SurveyMapManager::UpdateMapEntity(SurveyMapEntity *e, String caption, Vector3 pos, float rot, int state, bool visible) { if (e) { - Vector2 origin = mMapCenter + mMapCenterOffset - mMapSize / 2; - Vector2 relPos = Vector2(pos.x, pos.z) - origin; - bool culled = !(Vector2(0) < relPos && relPos < mMapSize); - bool declutter = App::gfx_declutter_map.GetActive() && mMapMode == SurveyMapMode::SMALL && !e->isPlayable(); + Vector2 origin = mMapCenter + mMapCenterOffset - mMapSize / 2; + Vector2 relPos = Vector2(pos.x, pos.z) - origin; + bool culled = !(Vector2(0) < relPos && relPos < mMapSize); + bool declutter = App::gfx_declutter_map.GetActive() && mMapMode == SurveyMapMode::SMALL && !e->isPlayable(); e->setState(state); e->setRotation(rot); e->setCaption(declutter ? "" : caption); @@ -350,36 +311,34 @@ void SurveyMapManager::UpdateMapEntity(SurveyMapEntity* e, String caption, Vecto } } -void SurveyMapManager::setFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) +void SurveyMapManager::setFocus(MyGUI::Widget *_sender, MyGUI::Widget *_new) { mCursorEntity->setVisibility(true); } -void SurveyMapManager::lostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _old) +void SurveyMapManager::lostFocus(MyGUI::Widget *_sender, MyGUI::Widget *_old) { mCursorEntity->setVisibility(false); } -void SurveyMapManager::mouseMove(MyGUI::Widget* _sender, int _left, int _top) +void SurveyMapManager::mouseMove(MyGUI::Widget *_sender, int _left, int _top) { float left = (float)(_left - mMapTexture->getAbsoluteLeft()) / (float)mMapTexture->getWidth(); - float top = (float)(_top - mMapTexture->getAbsoluteTop()) / (float)mMapTexture->getHeight(); + float top = (float)(_top - mMapTexture->getAbsoluteTop()) / (float)mMapTexture->getHeight(); mCursorEntity->setPosition(left, top); if (App::sim_state.GetActive() == SimState::RUNNING) - { - RoR::App::GetGuiManager()->SetMouseCursorVisibility(RoR::GUIManager::MouseCursorVisibility::HIDDEN); - } + { RoR::App::GetGuiManager()->SetMouseCursorVisibility(RoR::GUIManager::MouseCursorVisibility::HIDDEN); } } -void SurveyMapManager::mousePressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) +void SurveyMapManager::mousePressed(MyGUI::Widget *_sender, int _left, int _top, MyGUI::MouseButton _id) { float left = (float)(_left - mMapTexture->getAbsoluteLeft()) / (float)mMapTexture->getWidth(); - float top = (float)(_top - mMapTexture->getAbsoluteTop()) / (float)mMapTexture->getHeight(); - + float top = (float)(_top - mMapTexture->getAbsoluteTop()) / (float)mMapTexture->getHeight(); + Vector2 origin = mMapCenter + mMapCenterOffset - mMapSize / 2; - Vector2 pos = origin + Vector2(left, top) * mMapSize; + Vector2 pos = origin + Vector2(left, top) * mMapSize; App::GetSimController()->TeleportPlayerXZ(pos.x, pos.y); } diff --git a/source/main/terrain/map/SurveyMapManager.h b/source/main/terrain/map/SurveyMapManager.h index f5782e113c..c3e97a76fe 100644 --- a/source/main/terrain/map/SurveyMapManager.h +++ b/source/main/terrain/map/SurveyMapManager.h @@ -22,7 +22,6 @@ #pragma once #include "RoRPrerequisites.h" - #include "mygui/BaseLayout.h" class SurveyMapTextureCreator; @@ -31,27 +30,28 @@ ATTRIBUTE_CLASS_LAYOUT(SurveyMapManager, "MapControl.layout"); class SurveyMapManager : public wraps::BaseLayout { -public: - + public: SurveyMapManager(); ~SurveyMapManager(); void init(); - SurveyMapEntity* createMapEntity(Ogre::String type); - void deleteMapEntity(SurveyMapEntity* entity); + SurveyMapEntity *createMapEntity(Ogre::String type); + void deleteMapEntity(SurveyMapEntity *entity); - void hideGUI(bool hidden) { mHidden = hidden; }; + void hideGUI(bool hidden) + { + mHidden = hidden; + }; void windowResized(); - void Update(Ogre::Real dt, Actor* curr_truck); - void UpdateMapEntity(SurveyMapEntity* e, Ogre::String caption, Ogre::Vector3 pos, float rot, int state, bool visible); + void Update(Ogre::Real dt, Actor *curr_truck); + void UpdateMapEntity(SurveyMapEntity *e, Ogre::String caption, Ogre::Vector3 pos, float rot, int state, bool visible); static Ogre::String getTypeByDriveable(int driveable); -protected: - + protected: enum class SurveyMapMode { NONE, @@ -64,28 +64,28 @@ class SurveyMapManager : public wraps::BaseLayout Ogre::Vector2 mTerrainSize; Ogre::Vector2 mPlayerPosition; - Ogre::Real mMapZoom; - Ogre::Real mMapLastZoom; + Ogre::Real mMapZoom; + Ogre::Real mMapLastZoom; Ogre::Vector2 mMapSize; Ogre::Vector2 mMapCenter; Ogre::Vector2 mMapCenterOffset; ATTRIBUTE_FIELD_WIDGET_NAME(SurveyMapManager, mMapTexture, "mMapTexture"); - MyGUI::StaticImage* mMapTexture; + MyGUI::StaticImage *mMapTexture; std::unique_ptr mMapTextureCreatorStatic; std::unique_ptr mMapTextureCreatorDynamic; - std::set mMapEntities; - SurveyMapMode mMapLastMode; - SurveyMapMode mMapMode; + std::set mMapEntities; + SurveyMapMode mMapLastMode; + SurveyMapMode mMapMode; - SurveyMapEntity* mCursorEntity; - void setFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); - void lostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _old); - void mouseMove(MyGUI::Widget* _sender, int _left, int _top); - void mousePressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); + SurveyMapEntity *mCursorEntity; + void setFocus(MyGUI::Widget *_sender, MyGUI::Widget *_new); + void lostFocus(MyGUI::Widget *_sender, MyGUI::Widget *_old); + void mouseMove(MyGUI::Widget *_sender, int _left, int _top); + void mousePressed(MyGUI::Widget *_sender, int _left, int _top, MyGUI::MouseButton _id); void cycleMode(); void toggleMode(); @@ -98,4 +98,3 @@ class SurveyMapManager : public wraps::BaseLayout void setPlayerPosition(Ogre::Vector2 position); void setWindowPosition(int x, int y, float size); }; - diff --git a/source/main/terrain/map/SurveyMapTextureCreator.cpp b/source/main/terrain/map/SurveyMapTextureCreator.cpp index 2cf29a93a5..0164e1aa6f 100644 --- a/source/main/terrain/map/SurveyMapTextureCreator.cpp +++ b/source/main/terrain/map/SurveyMapTextureCreator.cpp @@ -29,10 +29,8 @@ using namespace RoR; static int counter = 0; -SurveyMapTextureCreator::SurveyMapTextureCreator(Ogre::Real terrain_height) : - mCamera(nullptr), - mRttTex(nullptr), - mTerrainHeight(Math::Clamp(terrain_height + 100.0f, 150.0f, 420.0f)) +SurveyMapTextureCreator::SurveyMapTextureCreator(Ogre::Real terrain_height) + : mCamera(nullptr), mRttTex(nullptr), mTerrainHeight(Math::Clamp(terrain_height + 100.0f, 150.0f, 420.0f)) { counter++; mTextureName = "MapRttTex-" + TOSTRING(counter); @@ -40,25 +38,22 @@ SurveyMapTextureCreator::SurveyMapTextureCreator(Ogre::Real terrain_height) : SurveyMapTextureCreator::~SurveyMapTextureCreator() { - if (mCamera) - gEnv->sceneManager->destroyCamera(mCamera); - if (mTexture) - Ogre::TextureManager::getSingleton().remove(mTexture); + if (mCamera) gEnv->sceneManager->destroyCamera(mCamera); + if (mTexture) Ogre::TextureManager::getSingleton().remove(mTexture); } bool SurveyMapTextureCreator::init(int res, int fsaa) { - mTexture = Ogre::TextureManager::getSingleton().createManual(mTextureName, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res, res, - Ogre::TU_RENDERTARGET, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); + mTexture = Ogre::TextureManager::getSingleton().createManual( + mTextureName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res, res, Ogre::TU_RENDERTARGET, + Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, false, fsaa); - if (mTexture.isNull()) - return false;; + if (mTexture.isNull()) return false; + ; mRttTex = mTexture->getBuffer()->getRenderTarget(); - if (!mRttTex) - return false; + if (!mRttTex) return false; mRttTex->addListener(this); mRttTex->setAutoUpdated(false); @@ -81,9 +76,8 @@ bool SurveyMapTextureCreator::init(int res, int fsaa) void SurveyMapTextureCreator::update(Vector2 center, Vector2 size) { - if (!mRttTex) - return; - + if (!mRttTex) return; + mCamera->setOrthoWindow(size.x, size.y); mCamera->setPosition(Vector3(center.x, mTerrainHeight, center.y)); diff --git a/source/main/terrain/map/SurveyMapTextureCreator.h b/source/main/terrain/map/SurveyMapTextureCreator.h index 516ff180db..87b8ed0aef 100644 --- a/source/main/terrain/map/SurveyMapTextureCreator.h +++ b/source/main/terrain/map/SurveyMapTextureCreator.h @@ -24,8 +24,7 @@ class SurveyMapTextureCreator : public Ogre::RenderTargetListener, public ZeroedMemoryAllocator { -public: - + public: SurveyMapTextureCreator(Ogre::Real terrain_height); ~SurveyMapTextureCreator(); @@ -34,15 +33,14 @@ class SurveyMapTextureCreator : public Ogre::RenderTargetListener, public Zeroed Ogre::String getTextureName(); -protected: - + protected: void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt); - Ogre::Real mTerrainHeight; + Ogre::Real mTerrainHeight; Ogre::String mTextureName; - Ogre::Camera* mCamera; - Ogre::TexturePtr mTexture; - Ogre::RenderTarget* mRttTex; + Ogre::Camera * mCamera; + Ogre::TexturePtr mTexture; + Ogre::RenderTarget *mRttTex; }; diff --git a/source/main/threadpool/ThreadPool.h b/source/main/threadpool/ThreadPool.h index aa66a49de8..53bfc149b8 100644 --- a/source/main/threadpool/ThreadPool.h +++ b/source/main/threadpool/ThreadPool.h @@ -25,11 +25,10 @@ along with Rigs of Rods. If not, see . #include #include #include -#include #include +#include #include - /** /brief Handle for a task executed by ThreadPool * * Returned by ThreadPool instance when submitting a new task to run. @@ -41,7 +40,8 @@ along with Rigs of Rods. If not, see . class Task { friend class ThreadPool; - public: + + public: /// Block the current thread and wait for the associated task to finish. void join() const { @@ -60,26 +60,29 @@ class Task // - locks task_mutex // - is_finished will be true std::unique_lock lock(m_task_mutex); - m_finish_cv.wait(lock, [this]{ return m_is_finished; }); + m_finish_cv.wait(lock, [this] { return m_is_finished; }); } - private: + private: // Only constructable by friend class ThreadPool - Task(std::function task_func) : m_task_func(task_func) {} - Task(Task &) = delete; - Task & operator=(Task &) = delete; - - bool m_is_finished = false; ///< Indicates whether the task execution has finished. - mutable std::condition_variable m_finish_cv; ///< Used to signal the current thread when the task has finished. - mutable std::mutex m_task_mutex; ///< Mutex which is locked while the task is running. - const std::function m_task_func; ///< Callable object which implements the task to execute. + Task(std::function task_func) : m_task_func(task_func) + { + } + Task(Task &) = delete; + Task &operator=(Task &) = delete; + + bool m_is_finished = false; ///< Indicates whether the task execution has finished. + mutable std::condition_variable m_finish_cv; ///< Used to signal the current thread when the task has finished. + mutable std::mutex m_task_mutex; ///< Mutex which is locked while the task is running. + const std::function m_task_func; ///< Callable object which implements the task to execute. }; /** \brief Facilitates execution of (small) tasks on separate threads. * - * Implements a "rent-a-thread" model where each submitted task is assigned to one of several worker threads managed by the thread pool instance. - * This is especially useful for short running tasks as it avoids the runtime cost of creating and launching a new thread. Notice, there - * still is a certain overhead present due to the synchronization of threads required in the internal implementation. + * Implements a "rent-a-thread" model where each submitted task is assigned to one of several worker threads managed by the thread + * pool instance. This is especially useful for short running tasks as it avoids the runtime cost of creating and launching a new + * thread. Notice, there still is a certain overhead present due to the synchronization of threads required in the internal + * implementation. * * Usage example 1: * \code @@ -99,8 +102,9 @@ class Task * * \see Task */ -class ThreadPool { -public: +class ThreadPool +{ + public: /** \brief Construct thread pool and launch worker threads. * * @param num_threads Number of worker threads to use @@ -113,15 +117,17 @@ class ThreadPool { // are executed. It implements an endless loop (only returning when the ThreadPool // instance itself is destructed) which constantly checks the task queue, grabbing // and executing the frontmost task while the queue is not empty. - auto thread_body = [this]{ - while (true) { + auto thread_body = [this] { + while (true) + { // Get next task from queue (synchronized access via taskqueue_mutex). // If the queue is empty wait until either // - being signaled about an available task. // - the terminate flag is true (i.e. the ThreadPool instance is being destructed). // In this case return from the running thread. std::unique_lock queue_lock(m_taskqueue_mutex); - while (m_taskqueue.empty()) { + while (m_taskqueue.empty()) + { if (m_terminate.load()) { return; } m_task_available_cv.wait(queue_lock); } @@ -140,21 +146,27 @@ class ThreadPool { }; // Launch the specified number of threads - for (int i = 0; i < num_threads; ++i) { + for (int i = 0; i < num_threads; ++i) + { m_threads.emplace_back(thread_body); } } - ~ThreadPool() { + ~ThreadPool() + { // Indicate termination and signal potential waiting threads to wake up. // Then wait for all threads to finish their work and return properly. m_terminate = true; m_task_available_cv.notify_all(); - for (auto &t : m_threads) { t.join(); } + for (auto &t : m_threads) + { + t.join(); + } } /// Submit new asynchronous task to thread pool and return Task handle to allow for synchronization. - std::shared_ptr RunTask(const std::function &task_func) { + std::shared_ptr RunTask(const std::function &task_func) + { // Wrap provided task callable object in task handle. Then append it to the task queue and // notify a waiting worker thread (if any) about the newly available task auto task = std::shared_ptr(new Task(task_func)); @@ -174,11 +186,11 @@ class ThreadPool { if (task_funcs.empty()) return; // Launch all provided tasks (except for the first) in parallel and store the associated handles - auto it = begin(task_funcs); - const auto first_task = it++; + auto it = begin(task_funcs); + const auto first_task = it++; std::vector> handles; - for(; it != end(task_funcs); ++it) - { + for (; it != end(task_funcs); ++it) + { handles.push_back(RunTask(*it)); } @@ -186,12 +198,15 @@ class ThreadPool { (*first_task)(); // Synchronize, i.e. wait for all parallelized tasks to complete - for(const auto &h : handles) { h->join(); } + for (const auto &h : handles) + { + h->join(); + } } - std::atomic_bool m_terminate{false}; ///< Indicates destruction of ThreadPool instance to worker threads - std::vector m_threads; ///< Collection of worker threads to run tasks - std::queue> m_taskqueue; ///< Queue of submitted tasks pending for execution - std::mutex m_taskqueue_mutex; ///< Protects task queue from concurrent access. - std::condition_variable m_task_available_cv; ///< Used to signal threads that a new task was submitted and is ready to run. + std::atomic_bool m_terminate{false}; ///< Indicates destruction of ThreadPool instance to worker threads + std::vector m_threads; ///< Collection of worker threads to run tasks + std::queue> m_taskqueue; ///< Queue of submitted tasks pending for execution + std::mutex m_taskqueue_mutex; ///< Protects task queue from concurrent access. + std::condition_variable m_task_available_cv; ///< Used to signal threads that a new task was submitted and is ready to run. }; diff --git a/source/main/utils/BitFlags.h b/source/main/utils/BitFlags.h index 0fb8c2c1d1..667c01bac6 100644 --- a/source/main/utils/BitFlags.h +++ b/source/main/utils/BitFlags.h @@ -6,59 +6,71 @@ // BITMASK(1) = 0x00000001 = 0b00....0001 // BITMASK(2) = 0x00000002 = 0b00....0010 -#define BITMASK( OFFSET ) (1 << ( (OFFSET) - 1)) +#define BITMASK(OFFSET) (1 << ((OFFSET)-1)) -#define BITMASK_SET_0( VAR, FLAGS ) ( (VAR) &= ~ (FLAGS) ) +#define BITMASK_SET_0(VAR, FLAGS) ((VAR) &= ~(FLAGS)) -#define BITMASK_SET_1( VAR, FLAGS ) ( (VAR) |= (FLAGS) ) +#define BITMASK_SET_1(VAR, FLAGS) ((VAR) |= (FLAGS)) -template void Bitmask_SetBool(bool val, var_T & _in_out_var, flags_T flags) +template void Bitmask_SetBool(bool val, var_T &_in_out_var, flags_T flags) { - // This code is supposed to compile only as conditional assignments, not as branches. + // This code is supposed to compile only as conditional assignments, not as branches. - var_T var_true = _in_out_var; - BITMASK_SET_1(var_true, flags); + var_T var_true = _in_out_var; + BITMASK_SET_1(var_true, flags); - var_T var_false = _in_out_var; - BITMASK_SET_0(var_false, flags); + var_T var_false = _in_out_var; + BITMASK_SET_0(var_false, flags); - _in_out_var = (val) ? var_true : var_false; + _in_out_var = (val) ? var_true : var_false; } -#define BITMASK_IS_0( VAR, FLAGS ) ( ((VAR) & (FLAGS)) == 0 ) +#define BITMASK_IS_0(VAR, FLAGS) (((VAR) & (FLAGS)) == 0) -#define BITMASK_IS_1( VAR, FLAGS ) ( ((VAR) & (FLAGS)) == (FLAGS) ) +#define BITMASK_IS_1(VAR, FLAGS) (((VAR) & (FLAGS)) == (FLAGS)) -#define BITMASK_FILL_1_EXCEPT( FLAGS_0 ) (( 0xFFFFFFFF & ~((FLAGS_0)) )) +#define BITMASK_FILL_1_EXCEPT(FLAGS_0) ((0xFFFFFFFF & ~((FLAGS_0)))) -/// Defines a bitmask constant with given bit index (1-indexed) and a getter function. -#define BITMASK_PROPERTY_GET(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME) \ - static const unsigned int FLAG_NAME = BITMASK((BIT_INDEX)); \ - inline bool GETTER_NAME() const { return BITMASK_IS_1((VAR), FLAG_NAME); } +/// Defines a bitmask constant with given bit index (1-indexed) and a getter function. +#define BITMASK_PROPERTY_GET(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME) \ + static const unsigned int FLAG_NAME = BITMASK((BIT_INDEX)); \ + inline bool GETTER_NAME() const \ + { \ + return BITMASK_IS_1((VAR), FLAG_NAME); \ + } /// Defines a bitmask constant with given bit index (1-indexed) and a getter/setter functions. -#define BITMASK_PROPERTY(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME, SETTER_NAME) \ - BITMASK_PROPERTY_GET((VAR), (BIT_INDEX), FLAG_NAME, GETTER_NAME) \ - inline void SETTER_NAME(bool value) { Bitmask_SetBool(value, (VAR), FLAG_NAME); } +#define BITMASK_PROPERTY(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME, SETTER_NAME) \ + BITMASK_PROPERTY_GET((VAR), (BIT_INDEX), FLAG_NAME, GETTER_NAME) \ + inline void SETTER_NAME(bool value) \ + { \ + Bitmask_SetBool(value, (VAR), FLAG_NAME); \ + } // -------------------------------------------------------------------------------- -#define BITMASK_64( OFFSET ) ( uint64_t(1) << ((OFFSET) - 1) ) +#define BITMASK_64(OFFSET) (uint64_t(1) << ((OFFSET)-1)) -#define BITMASK_64_SET_0 BITMASK_SET_0 +#define BITMASK_64_SET_0 BITMASK_SET_0 -#define BITMASK_64_SET_1 BITMASK_SET_1 +#define BITMASK_64_SET_1 BITMASK_SET_1 -#define BITMASK_64_IS_0( VAR, FLAGS ) ( ((VAR) & (FLAGS)) == uint64_t(0) ) +#define BITMASK_64_IS_0(VAR, FLAGS) (((VAR) & (FLAGS)) == uint64_t(0)) -#define BITMASK_64_IS_1 BITMASK_IS_1 +#define BITMASK_64_IS_1 BITMASK_IS_1 -/// Defines a 64bit bitmask constant with given bit index (1-indexed) and a getter function. -#define BITMASK_64_PROPERTY_GET(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME) \ - static const unsigned int FLAG_NAME = BITMASK_64((BIT_INDEX)); \ - inline bool GETTER_NAME() const { return BITMASK_64_IS_1((VAR), FLAG_NAME); } +/// Defines a 64bit bitmask constant with given bit index (1-indexed) and a getter function. +#define BITMASK_64_PROPERTY_GET(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME) \ + static const unsigned int FLAG_NAME = BITMASK_64((BIT_INDEX)); \ + inline bool GETTER_NAME() const \ + { \ + return BITMASK_64_IS_1((VAR), FLAG_NAME); \ + } /// Defines a 64bit bitmask constant with given bit index (1-indexed) and a getter/setter functions. -#define BITMASK_64_PROPERTY(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME, SETTER_NAME) \ - BITMASK_PROPERTY_GET((VAR), (BIT_INDEX), FLAG_NAME, GETTER_NAME) \ - inline void SETTER_NAME(bool value) { Bitmask_SetBool(value, (VAR), FLAG_NAME); } +#define BITMASK_64_PROPERTY(VAR, BIT_INDEX, FLAG_NAME, GETTER_NAME, SETTER_NAME) \ + BITMASK_PROPERTY_GET((VAR), (BIT_INDEX), FLAG_NAME, GETTER_NAME) \ + inline void SETTER_NAME(bool value) \ + { \ + Bitmask_SetBool(value, (VAR), FLAG_NAME); \ + } diff --git a/source/main/utils/CollisionTools.cpp b/source/main/utils/CollisionTools.cpp index ee69ab084e..17f90b77b8 100644 --- a/source/main/utils/CollisionTools.cpp +++ b/source/main/utils/CollisionTools.cpp @@ -47,507 +47,477 @@ THE SOFTWARE. #include -namespace MOC { +namespace MOC +{ #ifdef ETM_TERRAIN -CollisionTools::CollisionTools(Ogre::SceneManager *sceneMgr, const ET::TerrainInfo* terrainInfo) -{ - mRaySceneQuery = sceneMgr->createRayQuery(Ogre::Ray()); - if (NULL == mRaySceneQuery) + CollisionTools::CollisionTools(Ogre::SceneManager *sceneMgr, const ET::TerrainInfo *terrainInfo) { -// LOG_ERROR << "Failed to create Ogre::RaySceneQuery instance" << ENDLOG; - return; - } - mRaySceneQuery->setSortByDistance(true); + mRaySceneQuery = sceneMgr->createRayQuery(Ogre::Ray()); + if (NULL == mRaySceneQuery) + { + // LOG_ERROR << "Failed to create Ogre::RaySceneQuery instance" << ENDLOG; + return; + } + mRaySceneQuery->setSortByDistance(true); - mTSMRaySceneQuery = NULL; + mTSMRaySceneQuery = NULL; - mTerrainInfo = terrainInfo; + mTerrainInfo = terrainInfo; - _heightAdjust = 0.0f; -} + _heightAdjust = 0.0f; + } #endif -CollisionTools::CollisionTools(Ogre::SceneManager* sceneMgr) -{ - mSceneMgr = sceneMgr; - - mRaySceneQuery = mSceneMgr->createRayQuery(Ogre::Ray()); - if (NULL == mRaySceneQuery) + CollisionTools::CollisionTools(Ogre::SceneManager *sceneMgr) { - // LOG_ERROR << "Failed to create Ogre::RaySceneQuery instance" << ENDLOG; - return; - } - mRaySceneQuery->setSortByDistance(true); - - mTSMRaySceneQuery = mSceneMgr->createRayQuery(Ogre::Ray()); + mSceneMgr = sceneMgr; - _heightAdjust = 0.0f; -} + mRaySceneQuery = mSceneMgr->createRayQuery(Ogre::Ray()); + if (NULL == mRaySceneQuery) + { + // LOG_ERROR << "Failed to create Ogre::RaySceneQuery instance" << ENDLOG; + return; + } + mRaySceneQuery->setSortByDistance(true); -CollisionTools::~CollisionTools() -{ - if (mRaySceneQuery != NULL) - delete mRaySceneQuery; + mTSMRaySceneQuery = mSceneMgr->createRayQuery(Ogre::Ray()); - if (mTSMRaySceneQuery != NULL) - delete mTSMRaySceneQuery; -} + _heightAdjust = 0.0f; + } -bool CollisionTools::raycastFromCamera(Ogre::RenderWindow* rw, Ogre::Camera* camera, const Ogre::Vector2& mousecoords, Ogre::Vector3& result, Ogre::Entity* & target, float& closest_distance, const Ogre::uint32 queryMask) -{ - return raycastFromCamera(rw, camera, mousecoords, result, (Ogre::MovableObject*&) target, closest_distance, queryMask); -} + CollisionTools::~CollisionTools() + { + if (mRaySceneQuery != NULL) delete mRaySceneQuery; -bool CollisionTools::raycastFromCamera(Ogre::RenderWindow* rw, Ogre::Camera* camera, const Ogre::Vector2& mousecoords, Ogre::Vector3& result, Ogre::MovableObject* & target, float& closest_distance, const Ogre::uint32 queryMask) -{ - // Create the ray to test - Ogre::Real tx = mousecoords.x / (Ogre::Real) rw->getWidth(); - Ogre::Real ty = mousecoords.y / (Ogre::Real) rw->getHeight(); - Ogre::Ray ray = camera->getCameraToViewportRay(tx, ty); + if (mTSMRaySceneQuery != NULL) delete mTSMRaySceneQuery; + } - return raycast(ray, result, target, closest_distance, queryMask); -} + bool CollisionTools::raycastFromCamera(Ogre::RenderWindow *rw, Ogre::Camera *camera, const Ogre::Vector2 &mousecoords, + Ogre::Vector3 &result, Ogre::Entity *&target, float &closest_distance, + const Ogre::uint32 queryMask) + { + return raycastFromCamera(rw, camera, mousecoords, result, (Ogre::MovableObject *&)target, closest_distance, queryMask); + } -bool CollisionTools::collidesWithEntity(const Ogre::Vector3& fromPoint, const Ogre::Vector3& toPoint, const float collisionRadius, const float rayHeightLevel, const Ogre::uint32 queryMask) -{ - Ogre::Vector3 fromPointAdj(fromPoint.x, fromPoint.y + rayHeightLevel, fromPoint.z); - Ogre::Vector3 toPointAdj(toPoint.x, toPoint.y + rayHeightLevel, toPoint.z); - Ogre::Vector3 normal = toPointAdj - fromPointAdj; - float distToDest = normal.normalise(); - if (distToDest > 10) - return false; - - Ogre::Vector3 myResult(0, 0, 0); - Ogre::MovableObject* myObject = NULL; - float distToColl = 0.0f; - - if (raycastFromPoint(fromPointAdj, normal, myResult, myObject, distToColl, queryMask)) + bool CollisionTools::raycastFromCamera(Ogre::RenderWindow *rw, Ogre::Camera *camera, const Ogre::Vector2 &mousecoords, + Ogre::Vector3 &result, Ogre::MovableObject *&target, float &closest_distance, + const Ogre::uint32 queryMask) { - distToColl -= collisionRadius; - return (distToColl <= distToDest); + // Create the ray to test + Ogre::Real tx = mousecoords.x / (Ogre::Real)rw->getWidth(); + Ogre::Real ty = mousecoords.y / (Ogre::Real)rw->getHeight(); + Ogre::Ray ray = camera->getCameraToViewportRay(tx, ty); + + return raycast(ray, result, target, closest_distance, queryMask); } - else + + bool CollisionTools::collidesWithEntity(const Ogre::Vector3 &fromPoint, const Ogre::Vector3 &toPoint, + const float collisionRadius, const float rayHeightLevel, const Ogre::uint32 queryMask) { - return false; + Ogre::Vector3 fromPointAdj(fromPoint.x, fromPoint.y + rayHeightLevel, fromPoint.z); + Ogre::Vector3 toPointAdj(toPoint.x, toPoint.y + rayHeightLevel, toPoint.z); + Ogre::Vector3 normal = toPointAdj - fromPointAdj; + float distToDest = normal.normalise(); + if (distToDest > 10) return false; + + Ogre::Vector3 myResult(0, 0, 0); + Ogre::MovableObject *myObject = NULL; + float distToColl = 0.0f; + + if (raycastFromPoint(fromPointAdj, normal, myResult, myObject, distToColl, queryMask)) + { + distToColl -= collisionRadius; + return (distToColl <= distToDest); + } + else + { + return false; + } } -} -float CollisionTools::getTSMHeightAt(const float x, const float z) -{ - float y = 0.0f; + float CollisionTools::getTSMHeightAt(const float x, const float z) + { + float y = 0.0f; - static Ogre::Ray updateRay; + static Ogre::Ray updateRay; - updateRay.setOrigin(Ogre::Vector3(x, 9999, z)); - updateRay.setDirection(Ogre::Vector3::NEGATIVE_UNIT_Y); + updateRay.setOrigin(Ogre::Vector3(x, 9999, z)); + updateRay.setDirection(Ogre::Vector3::NEGATIVE_UNIT_Y); - mTSMRaySceneQuery->setRay(updateRay); - Ogre::RaySceneQueryResult& qryResult = mTSMRaySceneQuery->execute(); + mTSMRaySceneQuery->setRay(updateRay); + Ogre::RaySceneQueryResult &qryResult = mTSMRaySceneQuery->execute(); - Ogre::RaySceneQueryResult::iterator i = qryResult.begin(); - if (i != qryResult.end() && i->worldFragment) - { - y = i->worldFragment->singleIntersection.y; + Ogre::RaySceneQueryResult::iterator i = qryResult.begin(); + if (i != qryResult.end() && i->worldFragment) { y = i->worldFragment->singleIntersection.y; } + return y; } - return y; -} -void CollisionTools::calculateY(Ogre::SceneNode* n, const bool doTerrainCheck, const bool doGridCheck, const float gridWidth, const Ogre::uint32 queryMask) -{ - Ogre::Vector3 pos = n->getPosition(); + void CollisionTools::calculateY(Ogre::SceneNode *n, const bool doTerrainCheck, const bool doGridCheck, const float gridWidth, + const Ogre::uint32 queryMask) + { + Ogre::Vector3 pos = n->getPosition(); - float x = pos.x; - float z = pos.z; - float y = pos.y; + float x = pos.x; + float z = pos.z; + float y = pos.y; - Ogre::Vector3 myResult(0, 0, 0); - Ogre::MovableObject* myObject = NULL; - float distToColl = 0.0f; + Ogre::Vector3 myResult(0, 0, 0); + Ogre::MovableObject *myObject = NULL; + float distToColl = 0.0f; - float terrY = 0, colY = 0, colY2 = 0; + float terrY = 0, colY = 0, colY2 = 0; - if (raycastFromPoint(Ogre::Vector3(x, y, z), Ogre::Vector3::NEGATIVE_UNIT_Y, myResult, myObject, distToColl, queryMask)) - { - if (myObject != NULL) + if (raycastFromPoint(Ogre::Vector3(x, y, z), Ogre::Vector3::NEGATIVE_UNIT_Y, myResult, myObject, distToColl, queryMask)) { - colY = myResult.y; - } - else - { - colY = -99999; + if (myObject != NULL) { colY = myResult.y; } + else + { + colY = -99999; + } } - } - //if doGridCheck is on, repeat not to fall through small holes for example when crossing a hangbridge - if (doGridCheck) - { - if (raycastFromPoint(Ogre::Vector3(x, y, z) + (n->getOrientation() * Ogre::Vector3(0, 0, gridWidth)), Ogre::Vector3::NEGATIVE_UNIT_Y, myResult, myObject, distToColl, queryMask)) + // if doGridCheck is on, repeat not to fall through small holes for example when crossing a hangbridge + if (doGridCheck) { - if (myObject != NULL) - { - colY = myResult.y; - } - else + if (raycastFromPoint(Ogre::Vector3(x, y, z) + (n->getOrientation() * Ogre::Vector3(0, 0, gridWidth)), + Ogre::Vector3::NEGATIVE_UNIT_Y, myResult, myObject, distToColl, queryMask)) { - colY = -99999; + if (myObject != NULL) { colY = myResult.y; } + else + { + colY = -99999; + } } + if (colY < colY2) colY = colY2; } - if (colY < colY2) - colY = colY2; - } - // set the parameter to false if you are not using ETM or TSM - if (doTerrainCheck) - { + // set the parameter to false if you are not using ETM or TSM + if (doTerrainCheck) + { #ifdef ETM_TERRAIN - // ETM height value - terrY = mTerrainInfo->getHeightAt(x,z); + // ETM height value + terrY = mTerrainInfo->getHeightAt(x, z); #else - // TSM height value - terrY = getTSMHeightAt(x, z); + // TSM height value + terrY = getTSMHeightAt(x, z); #endif - if (terrY < colY) - { - n->setPosition(x, colY + _heightAdjust, z); + if (terrY < colY) { n->setPosition(x, colY + _heightAdjust, z); } + else + { + n->setPosition(x, terrY + _heightAdjust, z); + } } else { - n->setPosition(x, terrY + _heightAdjust, z); + if (!doTerrainCheck && colY == -99999) colY = y; + n->setPosition(x, colY + _heightAdjust, z); } } - else + + // raycast from a point in to the scene. + // returns success or failure. + // on success the point is returned in the result. + bool CollisionTools::raycastFromPoint(const Ogre::Vector3 &point, const Ogre::Vector3 &normal, Ogre::Vector3 &result, + Ogre::Entity *&target, float &closest_distance, const Ogre::uint32 queryMask) { - if (!doTerrainCheck && colY == -99999) - colY = y; - n->setPosition(x, colY + _heightAdjust, z); + return raycastFromPoint(point, normal, result, (Ogre::MovableObject *&)target, closest_distance, queryMask); } -} - -// raycast from a point in to the scene. -// returns success or failure. -// on success the point is returned in the result. -bool CollisionTools::raycastFromPoint(const Ogre::Vector3& point, - const Ogre::Vector3& normal, - Ogre::Vector3& result, Ogre::Entity* & target, - float& closest_distance, - const Ogre::uint32 queryMask) -{ - return raycastFromPoint(point, normal, result, (Ogre::MovableObject*&) target, closest_distance, queryMask); -} - -bool CollisionTools::raycastFromPoint(const Ogre::Vector3& point, - const Ogre::Vector3& normal, - Ogre::Vector3& result, Ogre::MovableObject* & target, - float& closest_distance, - const Ogre::uint32 queryMask) -{ - // create the ray to test - static Ogre::Ray ray; - ray.setOrigin(point); - ray.setDirection(normal); - return raycast(ray, result, target, closest_distance, queryMask); -} + bool CollisionTools::raycastFromPoint(const Ogre::Vector3 &point, const Ogre::Vector3 &normal, Ogre::Vector3 &result, + Ogre::MovableObject *&target, float &closest_distance, const Ogre::uint32 queryMask) + { + // create the ray to test + static Ogre::Ray ray; + ray.setOrigin(point); + ray.setDirection(normal); -bool CollisionTools::raycast(const Ogre::Ray& ray, Ogre::Vector3& result, Ogre::Entity* & target, float& closest_distance, const Ogre::uint32 queryMask) -{ - return raycast(ray, result, (Ogre::MovableObject*&)target, closest_distance, queryMask); -} + return raycast(ray, result, target, closest_distance, queryMask); + } -bool CollisionTools::raycast(const Ogre::Ray& ray, Ogre::Vector3& result, Ogre::MovableObject* & target, float& closest_distance, const Ogre::uint32 queryMask) -{ - target = NULL; + bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result, Ogre::Entity *&target, float &closest_distance, + const Ogre::uint32 queryMask) + { + return raycast(ray, result, (Ogre::MovableObject *&)target, closest_distance, queryMask); + } - // check we are initialised - if (mRaySceneQuery != NULL) + bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result, Ogre::MovableObject *&target, + float &closest_distance, const Ogre::uint32 queryMask) { - // create a query object - mRaySceneQuery->setRay(ray); - mRaySceneQuery->setSortByDistance(true); - mRaySceneQuery->setQueryMask(queryMask); - // execute the query, returns a vector of hits - if (mRaySceneQuery->execute().size() <= 0) + target = NULL; + + // check we are initialised + if (mRaySceneQuery != NULL) + { + // create a query object + mRaySceneQuery->setRay(ray); + mRaySceneQuery->setSortByDistance(true); + mRaySceneQuery->setQueryMask(queryMask); + // execute the query, returns a vector of hits + if (mRaySceneQuery->execute().size() <= 0) + { + // raycast did not hit an objects bounding box + return (false); + } + } + else { - // raycast did not hit an objects bounding box + // LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG; return (false); } - } - else - { - //LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG; - return (false); - } - // at this point we have raycast to a series of different objects bounding boxes. - // we need to test these different objects to see which is the first polygon hit. - // there are some minor optimizations (distance based) that mean we wont have to - // check all of the objects most of the time, but the worst case scenario is that - // we need to test every triangle of every object. - //Ogre::Ogre::Real closest_distance = -1.0f; - closest_distance = -1.0f; - Ogre::Vector3 closest_result = Ogre::Vector3::ZERO; - Ogre::RaySceneQueryResult& query_result = mRaySceneQuery->getLastResults(); - for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) - { - // stop checking if we have found a raycast hit that is closer - // than all remaining entities - if ((closest_distance >= 0.0f) && - (closest_distance < query_result[qr_idx].distance)) + // at this point we have raycast to a series of different objects bounding boxes. + // we need to test these different objects to see which is the first polygon hit. + // there are some minor optimizations (distance based) that mean we wont have to + // check all of the objects most of the time, but the worst case scenario is that + // we need to test every triangle of every object. + // Ogre::Ogre::Real closest_distance = -1.0f; + closest_distance = -1.0f; + Ogre::Vector3 closest_result = Ogre::Vector3::ZERO; + Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults(); + for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) { - break; - } + // stop checking if we have found a raycast hit that is closer + // than all remaining entities + if ((closest_distance >= 0.0f) && (closest_distance < query_result[qr_idx].distance)) { break; } #if 0 if (query_result[qr_idx].movable != NULL) LOG(TOSTRING(qr_idx) + ": " + query_result[qr_idx].movable->getMovableType() + " : " + query_result[qr_idx].movable->getName()); #endif - // mesh data to retrieve - bool valid = false; - mesh_info_t meshInfo; + // mesh data to retrieve + bool valid = false; + mesh_info_t meshInfo; - if ((query_result[qr_idx].movable != NULL) && !query_result[qr_idx].movable->getMovableType().compare("Entity")) - { - // movables - // get the entity to check - Ogre::MovableObject* pentity = static_cast(query_result[qr_idx].movable); - // get the mesh information - GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), meshInfo.vertex_count, meshInfo.vertices, meshInfo.index_count, meshInfo.indices, - pentity->getParentNode()->_getDerivedPosition(), - pentity->getParentNode()->_getDerivedOrientation(), - pentity->getParentNode()->_getDerivedScale()); - meshInfo.store = false; - valid = true; - } - else if ((query_result[qr_idx].movable != NULL) && !query_result[qr_idx].movable->getMovableType().compare("StaticGeometry")) - { - // static geometry - Ogre::StaticGeometry::Region* rg = static_cast(query_result[qr_idx].movable); - - // this is a quick hack to prevent that we allocate unlimited amount of memory - // it clears the memory if we have more than 4 regions saved - if (meshInfoStorage.size() > 4) + if ((query_result[qr_idx].movable != NULL) && !query_result[qr_idx].movable->getMovableType().compare("Entity")) { - // free everything - for (std::map::iterator it = meshInfoStorage.begin(); it != meshInfoStorage.end(); it++) - { - // free memory before clearing map - free(it->second.indices); - free(it->second.vertices); - } - // clear map - meshInfoStorage.clear(); + // movables + // get the entity to check + Ogre::MovableObject *pentity = static_cast(query_result[qr_idx].movable); + // get the mesh information + GetMeshInformation(((Ogre::Entity *)pentity)->getMesh(), meshInfo.vertex_count, meshInfo.vertices, + meshInfo.index_count, meshInfo.indices, pentity->getParentNode()->_getDerivedPosition(), + pentity->getParentNode()->_getDerivedOrientation(), + pentity->getParentNode()->_getDerivedScale()); + meshInfo.store = false; + valid = true; } - - if (meshInfoStorage.find(rg->getName()) == meshInfoStorage.end()) + else if ((query_result[qr_idx].movable != NULL) && + !query_result[qr_idx].movable->getMovableType().compare("StaticGeometry")) { - // get mesh and store it - getStaticGeometry(rg->getParent(), rg, meshInfo.vertex_count, meshInfo.vertices, meshInfo.index_count, meshInfo.indices, - rg->getParentNode()->_getDerivedPosition(), - rg->getParentNode()->_getDerivedOrientation(), - rg->getParentNode()->getScale()); - meshInfo.store = true; - meshInfoStorage[rg->getName()] = meshInfo; - } - else - // existing, get it - meshInfo = meshInfoStorage[rg->getName()]; - valid = true; - } + // static geometry + Ogre::StaticGeometry::Region *rg = static_cast(query_result[qr_idx].movable); - if (valid) - { - // test for hitting individual triangles on the mesh - bool new_closest_found = false; - for (size_t i = 0; i < meshInfo.index_count; i += 3) - { - // check for a hit against this triangle - std::pair hit = Ogre::Math::intersects(ray, meshInfo.vertices[meshInfo.indices[i]], - meshInfo.vertices[meshInfo.indices[i + 1]], meshInfo.vertices[meshInfo.indices[i + 2]], true, false); - - // if it was a hit check if its the closest - if (hit.first) + // this is a quick hack to prevent that we allocate unlimited amount of memory + // it clears the memory if we have more than 4 regions saved + if (meshInfoStorage.size() > 4) { - if ((closest_distance < 0.0f) || - (hit.second < closest_distance)) + // free everything + for (std::map::iterator it = meshInfoStorage.begin(); it != meshInfoStorage.end(); + it++) { - // this is the closest so far, save it off - closest_distance = hit.second; - new_closest_found = true; + // free memory before clearing map + free(it->second.indices); + free(it->second.vertices); } + // clear map + meshInfoStorage.clear(); } - } - // free the verticies and indicies memory if we are not storing the data - if (!meshInfo.store) - { - delete[] meshInfo.vertices; - delete[] meshInfo.indices; + if (meshInfoStorage.find(rg->getName()) == meshInfoStorage.end()) + { + // get mesh and store it + getStaticGeometry(rg->getParent(), rg, meshInfo.vertex_count, meshInfo.vertices, meshInfo.index_count, + meshInfo.indices, rg->getParentNode()->_getDerivedPosition(), + rg->getParentNode()->_getDerivedOrientation(), rg->getParentNode()->getScale()); + meshInfo.store = true; + meshInfoStorage[rg->getName()] = meshInfo; + } + else + // existing, get it + meshInfo = meshInfoStorage[rg->getName()]; + valid = true; } - // if we found a new closest raycast for this object, update the - // closest_result before moving on to the next object. - if (new_closest_found) + if (valid) { - //target = pentity; - closest_result = ray.getPoint(closest_distance); - } - } - } + // test for hitting individual triangles on the mesh + bool new_closest_found = false; + for (size_t i = 0; i < meshInfo.index_count; i += 3) + { + // check for a hit against this triangle + std::pair hit = Ogre::Math::intersects( + ray, meshInfo.vertices[meshInfo.indices[i]], meshInfo.vertices[meshInfo.indices[i + 1]], + meshInfo.vertices[meshInfo.indices[i + 2]], true, false); - // return the result - if (closest_distance >= 0.0f) - { - // raycast success - result = closest_result; - return (true); - } - else - { - // raycast failed - return (false); - } -} - -// Get the mesh information for the given mesh. -// Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData -void CollisionTools::GetMeshInformation(const Ogre::MeshPtr mesh, - size_t& vertex_count, - Ogre::Vector3* & vertices, - size_t& index_count, - Ogre::uint32* & indices, - const Ogre::Vector3& position, - const Ogre::Quaternion& orient, - const Ogre::Vector3& scale) -{ - bool added_shared = false; - size_t current_offset = 0; - size_t shared_offset = 0; - size_t next_offset = 0; - size_t index_offset = 0; + // if it was a hit check if its the closest + if (hit.first) + { + if ((closest_distance < 0.0f) || (hit.second < closest_distance)) + { + // this is the closest so far, save it off + closest_distance = hit.second; + new_closest_found = true; + } + } + } - vertex_count = index_count = 0; + // free the verticies and indicies memory if we are not storing the data + if (!meshInfo.store) + { + delete[] meshInfo.vertices; + delete[] meshInfo.indices; + } - // Calculate how many vertices and indices we're going to need - for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) - { - Ogre::SubMesh* submesh = mesh->getSubMesh(i); + // if we found a new closest raycast for this object, update the + // closest_result before moving on to the next object. + if (new_closest_found) + { + // target = pentity; + closest_result = ray.getPoint(closest_distance); + } + } + } - // We only need to add the shared vertices once - if (submesh->useSharedVertices) + // return the result + if (closest_distance >= 0.0f) { - if (!added_shared) - { - vertex_count += mesh->sharedVertexData->vertexCount; - added_shared = true; - } + // raycast success + result = closest_result; + return (true); } else { - vertex_count += submesh->vertexData->vertexCount; + // raycast failed + return (false); } - - // Add the indices - index_count += submesh->indexData->indexCount; } - // Allocate space for the vertices and indices - vertices = new Ogre::Vector3[vertex_count]; - indices = new Ogre::uint32[index_count]; - - added_shared = false; - - // Run through the submeshes again, adding the data into the arrays - for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) + // Get the mesh information for the given mesh. + // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData + void CollisionTools::GetMeshInformation(const Ogre::MeshPtr mesh, size_t &vertex_count, Ogre::Vector3 *&vertices, + size_t &index_count, Ogre::uint32 *&indices, const Ogre::Vector3 &position, + const Ogre::Quaternion &orient, const Ogre::Vector3 &scale) { - Ogre::SubMesh* submesh = mesh->getSubMesh(i); + bool added_shared = false; + size_t current_offset = 0; + size_t shared_offset = 0; + size_t next_offset = 0; + size_t index_offset = 0; - Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; + vertex_count = index_count = 0; - if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared)) + // Calculate how many vertices and indices we're going to need + for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { + Ogre::SubMesh *submesh = mesh->getSubMesh(i); + + // We only need to add the shared vertices once if (submesh->useSharedVertices) { - added_shared = true; - shared_offset = current_offset; + if (!added_shared) + { + vertex_count += mesh->sharedVertexData->vertexCount; + added_shared = true; + } + } + else + { + vertex_count += submesh->vertexData->vertexCount; } - const Ogre::VertexElement* posElem = - vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + // Add the indices + index_count += submesh->indexData->indexCount; + } - Ogre::HardwareVertexBufferSharedPtr vbuf = - vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); + // Allocate space for the vertices and indices + vertices = new Ogre::Vector3[vertex_count]; + indices = new Ogre::uint32[index_count]; - unsigned char* vertex = - static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + added_shared = false; - // There is _no_ baseVertexPointerToElement() which takes an Ogre::Ogre::Real or a double - // as second argument. So make it float, to avoid trouble when Ogre::Ogre::Real will - // be comiled/typedefed as double: - // Ogre::Ogre::Real* pOgre::Real; - float* pReal; + // Run through the submeshes again, adding the data into the arrays + for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) + { + Ogre::SubMesh *submesh = mesh->getSubMesh(i); + + Ogre::VertexData *vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; - for (size_t j = 0; j < vertex_data->vertexCount; ++j , vertex += vbuf->getVertexSize()) + if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared)) { - posElem->baseVertexPointerToElement(vertex, &pReal); + if (submesh->useSharedVertices) + { + added_shared = true; + shared_offset = current_offset; + } - Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); + const Ogre::VertexElement *posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); - vertices[current_offset + j] = (orient * (pt * scale)) + position; - } + Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); - vbuf->unlock(); - next_offset += vertex_data->vertexCount; - } + unsigned char *vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); - Ogre::IndexData* index_data = submesh->indexData; - size_t numTris = index_data->indexCount / 3; - Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; + // There is _no_ baseVertexPointerToElement() which takes an Ogre::Ogre::Real or a double + // as second argument. So make it float, to avoid trouble when Ogre::Ogre::Real will + // be comiled/typedefed as double: + // Ogre::Ogre::Real* pOgre::Real; + float *pReal; - bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); + for (size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) + { + posElem->baseVertexPointerToElement(vertex, &pReal); - Ogre::uint32* pLong = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); - unsigned short* pShort = reinterpret_cast(pLong); + Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); - size_t offset = (submesh->useSharedVertices) ? shared_offset : current_offset; + vertices[current_offset + j] = (orient * (pt * scale)) + position; + } - if (use32bitindexes) - { - for (size_t k = 0; k < numTris * 3; ++k) + vbuf->unlock(); + next_offset += vertex_data->vertexCount; + } + + Ogre::IndexData * index_data = submesh->indexData; + size_t numTris = index_data->indexCount / 3; + Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; + + bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); + + Ogre::uint32 * pLong = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + unsigned short *pShort = reinterpret_cast(pLong); + + size_t offset = (submesh->useSharedVertices) ? shared_offset : current_offset; + + if (use32bitindexes) { - indices[index_offset++] = pLong[k] + static_cast(offset); + for (size_t k = 0; k < numTris * 3; ++k) + { + indices[index_offset++] = pLong[k] + static_cast(offset); + } } - } - else - { - for (size_t k = 0; k < numTris * 3; ++k) + else { - indices[index_offset++] = static_cast(pShort[k]) + - static_cast(offset); + for (size_t k = 0; k < numTris * 3; ++k) + { + indices[index_offset++] = static_cast(pShort[k]) + static_cast(offset); + } } - } - ibuf->unlock(); - current_offset = next_offset; + ibuf->unlock(); + current_offset = next_offset; + } } -} - -//retrieved from http://svn.rtti.de/filedetails.php?repname=CoA%20Jump%20n%20Run&path=/tags/run01_2008-01-29/src/SceneryTest.cpp&rev=254&sc=1 -void CollisionTools::getStaticGeometry( - Ogre::StaticGeometry* mesh, - Ogre::StaticGeometry::Region* rg, - size_t& overtex_count, - Ogre::Vector3* & overtices, - size_t& oindex_count, - Ogre::uint32* & oindices, - const Ogre::Vector3& position, - const Ogre::Quaternion& orient, - const Ogre::Vector3& scale) -{ - // iterate regions - std::vector vertices; - std::vector indices; - //size_t next_offset = 0; + + // retrieved from + // http://svn.rtti.de/filedetails.php?repname=CoA%20Jump%20n%20Run&path=/tags/run01_2008-01-29/src/SceneryTest.cpp&rev=254&sc=1 + void CollisionTools::getStaticGeometry(Ogre::StaticGeometry *mesh, Ogre::StaticGeometry::Region *rg, size_t &overtex_count, + Ogre::Vector3 *&overtices, size_t &oindex_count, Ogre::uint32 *&oindices, + const Ogre::Vector3 &position, const Ogre::Quaternion &orient, + const Ogre::Vector3 &scale) + { + // iterate regions + std::vector vertices; + std::vector indices; + // size_t next_offset = 0; #if 0 Ogre::Vector3 center = rg->getCentre(); @@ -613,32 +583,32 @@ void CollisionTools::getStaticGeometry( next_offset += vertex_data->vertexCount; } } -#endif //0 +#endif // 0 - overtex_count = vertices.size(); - overtices = 0; - if (overtex_count > 0) - { - overtices = new Ogre::Vector3[overtex_count]; - memcpy(overtices, &vertices[0], sizeof(*overtices) * overtex_count); + overtex_count = vertices.size(); + overtices = 0; + if (overtex_count > 0) + { + overtices = new Ogre::Vector3[overtex_count]; + memcpy(overtices, &vertices[0], sizeof(*overtices) * overtex_count); + } + oindex_count = indices.size(); + oindices = 0; + if (oindex_count > 0) + { + oindices = new Ogre::uint32[oindex_count]; + memcpy(oindices, &indices[0], sizeof(*oindices) * oindex_count); + } } - oindex_count = indices.size(); - oindices = 0; - if (oindex_count > 0) + + void CollisionTools::setHeightAdjust(const float heightadjust) { - oindices = new Ogre::uint32[oindex_count]; - memcpy(oindices, &indices[0], sizeof(*oindices) * oindex_count); + _heightAdjust = heightadjust; } -} -void CollisionTools::setHeightAdjust(const float heightadjust) -{ - _heightAdjust = heightadjust; -} - -float CollisionTools::getHeightAdjust(void) -{ - return _heightAdjust; -} + float CollisionTools::getHeightAdjust(void) + { + return _heightAdjust; + } -}; +}; // namespace MOC diff --git a/source/main/utils/CollisionTools.h b/source/main/utils/CollisionTools.h index a3c47b807f..b9c1162ed3 100644 --- a/source/main/utils/CollisionTools.h +++ b/source/main/utils/CollisionTools.h @@ -48,87 +48,87 @@ #pragma once #include "RoRPrerequisites.h" + #include // uncomment if you want to use ETM as terrainmanager //#define ETM_TERRAIN #ifdef ETM_TERRAIN -#include "ETTerrainInfo.h" + #include "ETTerrainInfo.h" #endif -namespace MOC { - -typedef struct mesh_info_ -{ - size_t vertex_count; - size_t index_count; - Ogre::Vector3* vertices; - Ogre::uint32* indices; - bool store; -} mesh_info_t; - -class CollisionTools : public ZeroedMemoryAllocator +namespace MOC { -public: - Ogre::RaySceneQuery* mRaySceneQuery; - Ogre::RaySceneQuery* mTSMRaySceneQuery; - Ogre::SceneManager* mSceneMgr; + typedef struct mesh_info_ + { + size_t vertex_count; + size_t index_count; + Ogre::Vector3 *vertices; + Ogre::uint32 * indices; + bool store; + } mesh_info_t; + + class CollisionTools : public ZeroedMemoryAllocator + { + public: + Ogre::RaySceneQuery *mRaySceneQuery; + Ogre::RaySceneQuery *mTSMRaySceneQuery; + + Ogre::SceneManager *mSceneMgr; #ifdef ETM_TERRAIN - const ET::TerrainInfo* mTerrainInfo; - CollisionTools(Ogre::SceneManager *sceneMgr, const ET::TerrainInfo* terrainInfo); + const ET::TerrainInfo *mTerrainInfo; + CollisionTools(Ogre::SceneManager *sceneMgr, const ET::TerrainInfo *terrainInfo); #endif - CollisionTools(Ogre::SceneManager* sceneMgr); - ~CollisionTools(); - - bool raycastFromCamera(Ogre::RenderWindow* rw, Ogre::Camera* camera, const Ogre::Vector2& mousecoords, Ogre::Vector3& result, Ogre::MovableObject* & target, float& closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); - // convenience wrapper with Ogre::Entity to it: - bool raycastFromCamera(Ogre::RenderWindow* rw, Ogre::Camera* camera, const Ogre::Vector2& mousecoords, Ogre::Vector3& result, Ogre::Entity* & target, float& closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); + CollisionTools(Ogre::SceneManager *sceneMgr); + ~CollisionTools(); - bool collidesWithEntity(const Ogre::Vector3& fromPoint, const Ogre::Vector3& toPoint, const float collisionRadius = 2.5f, const float rayHeightLevel = 0.0f, const Ogre::uint32 queryMask = 0xFFFFFFFF); + bool raycastFromCamera(Ogre::RenderWindow *rw, Ogre::Camera *camera, const Ogre::Vector2 &mousecoords, + Ogre::Vector3 &result, Ogre::MovableObject *&target, float &closest_distance, + const Ogre::uint32 queryMask = 0xFFFFFFFF); + // convenience wrapper with Ogre::Entity to it: + bool raycastFromCamera(Ogre::RenderWindow *rw, Ogre::Camera *camera, const Ogre::Vector2 &mousecoords, + Ogre::Vector3 &result, Ogre::Entity *&target, float &closest_distance, + const Ogre::uint32 queryMask = 0xFFFFFFFF); - void calculateY(Ogre::SceneNode* n, const bool doTerrainCheck = true, const bool doGridCheck = true, const float gridWidth = 1.0f, const Ogre::uint32 queryMask = 0xFFFFFFFF); + bool collidesWithEntity(const Ogre::Vector3 &fromPoint, const Ogre::Vector3 &toPoint, const float collisionRadius = 2.5f, + const float rayHeightLevel = 0.0f, const Ogre::uint32 queryMask = 0xFFFFFFFF); - float getTSMHeightAt(const float x, const float z); + void calculateY(Ogre::SceneNode *n, const bool doTerrainCheck = true, const bool doGridCheck = true, + const float gridWidth = 1.0f, const Ogre::uint32 queryMask = 0xFFFFFFFF); - bool raycastFromPoint(const Ogre::Vector3& point, const Ogre::Vector3& normal, Ogre::Vector3& result, Ogre::MovableObject* & target, float& closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); - // convenience wrapper with Ogre::Entity to it: - bool raycastFromPoint(const Ogre::Vector3& point, const Ogre::Vector3& normal, Ogre::Vector3& result, Ogre::Entity* & target, float& closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); + float getTSMHeightAt(const float x, const float z); - bool raycast(const Ogre::Ray& ray, Ogre::Vector3& result, Ogre::MovableObject* & target, float& closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); - // convenience wrapper with Ogre::Entity to it: - bool raycast(const Ogre::Ray& ray, Ogre::Vector3& result, Ogre::Entity* & target, float& closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); + bool raycastFromPoint(const Ogre::Vector3 &point, const Ogre::Vector3 &normal, Ogre::Vector3 &result, + Ogre::MovableObject *&target, float &closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); + // convenience wrapper with Ogre::Entity to it: + bool raycastFromPoint(const Ogre::Vector3 &point, const Ogre::Vector3 &normal, Ogre::Vector3 &result, + Ogre::Entity *&target, float &closest_distance, const Ogre::uint32 queryMask = 0xFFFFFFFF); - void setHeightAdjust(const float heightadjust); - float getHeightAdjust(void); + bool raycast(const Ogre::Ray &ray, Ogre::Vector3 &result, Ogre::MovableObject *&target, float &closest_distance, + const Ogre::uint32 queryMask = 0xFFFFFFFF); + // convenience wrapper with Ogre::Entity to it: + bool raycast(const Ogre::Ray &ray, Ogre::Vector3 &result, Ogre::Entity *&target, float &closest_distance, + const Ogre::uint32 queryMask = 0xFFFFFFFF); -private: + void setHeightAdjust(const float heightadjust); + float getHeightAdjust(void); - float _heightAdjust; + private: + float _heightAdjust; - void GetMeshInformation(const Ogre::MeshPtr mesh, - size_t& vertex_count, - Ogre::Vector3* & vertices, - size_t& index_count, - Ogre::uint32* & indices, - const Ogre::Vector3& position, - const Ogre::Quaternion& orient, - const Ogre::Vector3& scale); + void GetMeshInformation(const Ogre::MeshPtr mesh, size_t &vertex_count, Ogre::Vector3 *&vertices, size_t &index_count, + Ogre::uint32 *&indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient, + const Ogre::Vector3 &scale); - void getStaticGeometry(Ogre::StaticGeometry* mesh, - Ogre::StaticGeometry::Region* rg, - size_t& overtex_count, - Ogre::Vector3* & overtices, - size_t& oindex_count, - Ogre::uint32* & oindices, - const Ogre::Vector3& position, - const Ogre::Quaternion& orient, - const Ogre::Vector3& scale); + void getStaticGeometry(Ogre::StaticGeometry *mesh, Ogre::StaticGeometry::Region *rg, size_t &overtex_count, + Ogre::Vector3 *&overtices, size_t &oindex_count, Ogre::uint32 *&oindices, + const Ogre::Vector3 &position, const Ogre::Quaternion &orient, const Ogre::Vector3 &scale); - std::map meshInfoStorage; -}; + std::map meshInfoStorage; + }; -}; +}; // namespace MOC diff --git a/source/main/utils/ConfigFile.cpp b/source/main/utils/ConfigFile.cpp index 2c31e7c32d..b7ceea4783 100644 --- a/source/main/utils/ConfigFile.cpp +++ b/source/main/utils/ConfigFile.cpp @@ -19,13 +19,14 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file ConfigFile.cpp @date 06/2014 @author Petr Ohlidal */ #include "ConfigFile.h" + #include "Utils.h" #include @@ -34,43 +35,41 @@ using namespace RoR; -float ConfigFile::GetFloat(Ogre::String const& key, Ogre::String const& section, float defaultValue) +float ConfigFile::GetFloat(Ogre::String const &key, Ogre::String const §ion, float defaultValue) { return Ogre::StringConverter::parseReal(Ogre::ConfigFile::getSetting(key, section), defaultValue); } -Ogre::ColourValue ConfigFile::GetColourValue(Ogre::String const& key, Ogre::String const& section, Ogre::ColourValue const& defaultValue) +Ogre::ColourValue ConfigFile::GetColourValue(Ogre::String const &key, Ogre::String const §ion, + Ogre::ColourValue const &defaultValue) { return Ogre::StringConverter::parseColourValue(Ogre::ConfigFile::getSetting(key, section), defaultValue); } -int ConfigFile::GetInt(Ogre::String const& key, Ogre::String const& section, int defaultValue) +int ConfigFile::GetInt(Ogre::String const &key, Ogre::String const §ion, int defaultValue) { return Ogre::StringConverter::parseInt(Ogre::ConfigFile::getSetting(key, section), defaultValue); } -bool ConfigFile::GetBool(Ogre::String const& key, Ogre::String const& section, bool defaultValue) +bool ConfigFile::GetBool(Ogre::String const &key, Ogre::String const §ion, bool defaultValue) { return Ogre::StringConverter::parseBool(Ogre::ConfigFile::getSetting(key, section), defaultValue); } -Ogre::String ConfigFile::GetStringEx(Ogre::String const& key, Ogre::String const& section, Ogre::String const& defaultValue) +Ogre::String ConfigFile::GetStringEx(Ogre::String const &key, Ogre::String const §ion, Ogre::String const &defaultValue) { auto setting = Ogre::ConfigFile::getSetting(key, section); - if (setting.empty()) - { - return defaultValue; - } + if (setting.empty()) { return defaultValue; } return RoR::Utils::SanitizeUtf8String(setting); } void ConfigFile::SetString(Ogre::String key, Ogre::String value, Ogre::String section /* = Ogre::StringUtil::BLANK */) { - SettingsMultiMap* set = mSettingsPtr[section]; + SettingsMultiMap *set = mSettingsPtr[section]; if (!set) { // new section - set = new SettingsMultiMap(); + set = new SettingsMultiMap(); mSettingsPtr[section] = set; } if (set->count(key)) @@ -82,7 +81,7 @@ void ConfigFile::SetString(Ogre::String key, Ogre::String value, Ogre::String se set->insert(std::multimap::value_type(key, value)); } -bool ConfigFile::HasSection(std::string const & name) +bool ConfigFile::HasSection(std::string const &name) { // This is the only way to check existence of section // without either an OGRE exception being logged or using deprecated API. diff --git a/source/main/utils/ConfigFile.h b/source/main/utils/ConfigFile.h index 1d2ca6efbe..a77116af2d 100644 --- a/source/main/utils/ConfigFile.h +++ b/source/main/utils/ConfigFile.h @@ -19,7 +19,7 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file ConfigFile.h @date 06/2014 @author Petr Ohlidal @@ -27,60 +27,61 @@ #pragma once -#include #include +#include #include -namespace RoR { - -/// Adds direct parsing of custom types. -class ConfigFile: public Ogre::ConfigFile +namespace RoR { -public: - Ogre::ColourValue GetColourValue(Ogre::String const& key, Ogre::ColourValue const& defaultValue = Ogre::ColourValue()) + /// Adds direct parsing of custom types. + class ConfigFile : public Ogre::ConfigFile { - return this->GetColourValue(key, Ogre::StringUtil::BLANK, defaultValue); - } + public: + Ogre::ColourValue GetColourValue(Ogre::String const &key, Ogre::ColourValue const &defaultValue = Ogre::ColourValue()) + { + return this->GetColourValue(key, Ogre::StringUtil::BLANK, defaultValue); + } - Ogre::ColourValue GetColourValue(Ogre::String const& key, Ogre::String const& section, Ogre::ColourValue const& defaultValue = Ogre::ColourValue()); + Ogre::ColourValue GetColourValue(Ogre::String const &key, Ogre::String const §ion, + Ogre::ColourValue const &defaultValue = Ogre::ColourValue()); - float GetFloat(Ogre::String const& key, float defaultValue = 0.f) - { - return this->GetFloat(key, Ogre::StringUtil::BLANK, defaultValue); - } + float GetFloat(Ogre::String const &key, float defaultValue = 0.f) + { + return this->GetFloat(key, Ogre::StringUtil::BLANK, defaultValue); + } - float GetFloat(Ogre::String const& key, Ogre::String const& section, float defaultValue = 0.f); + float GetFloat(Ogre::String const &key, Ogre::String const §ion, float defaultValue = 0.f); - bool GetBool(Ogre::String const& key, bool defaultValue = false) - { - return this->GetBool(key, Ogre::StringUtil::BLANK, defaultValue); - } + bool GetBool(Ogre::String const &key, bool defaultValue = false) + { + return this->GetBool(key, Ogre::StringUtil::BLANK, defaultValue); + } - bool GetBool(Ogre::String const& key, Ogre::String const& section, bool defaultValue = false); + bool GetBool(Ogre::String const &key, Ogre::String const §ion, bool defaultValue = false); - int GetInt(Ogre::String const& key, int defaultValue = 0) - { - return this->GetInt(key, Ogre::StringUtil::BLANK, defaultValue); - } + int GetInt(Ogre::String const &key, int defaultValue = 0) + { + return this->GetInt(key, Ogre::StringUtil::BLANK, defaultValue); + } - int GetInt(Ogre::String const& key, Ogre::String const& section, int defaultValue = 0); + int GetInt(Ogre::String const &key, Ogre::String const §ion, int defaultValue = 0); - Ogre::String GetString(Ogre::String const& key, Ogre::String const& defaultValue = "") - { - return this->GetStringEx(key, Ogre::StringUtil::BLANK, defaultValue); - } + Ogre::String GetString(Ogre::String const &key, Ogre::String const &defaultValue = "") + { + return this->GetStringEx(key, Ogre::StringUtil::BLANK, defaultValue); + } - Ogre::String GetStringEx(Ogre::String const& key, Ogre::String const& section, Ogre::String const& defaultValue = ""); + Ogre::String GetStringEx(Ogre::String const &key, Ogre::String const §ion, Ogre::String const &defaultValue = ""); - void SetString(Ogre::String key, Ogre::String value, Ogre::String section = Ogre::StringUtil::BLANK); + void SetString(Ogre::String key, Ogre::String value, Ogre::String section = Ogre::StringUtil::BLANK); - bool HasSection(std::string const & name); + bool HasSection(std::string const &name); -private: - //Block access to Ogre::ConfigFile::getSetting() - not UTF8 safe! - Ogre::String getSetting(Ogre::String, Ogre::String); - Ogre::String getSetting(Ogre::String, Ogre::String, Ogre::String); -}; + private: + // Block access to Ogre::ConfigFile::getSetting() - not UTF8 safe! + Ogre::String getSetting(Ogre::String, Ogre::String); + Ogre::String getSetting(Ogre::String, Ogre::String, Ogre::String); + }; } // namespace RoR diff --git a/source/main/utils/ErrorUtils.cpp b/source/main/utils/ErrorUtils.cpp index a8bd0398bc..a66efde88a 100644 --- a/source/main/utils/ErrorUtils.cpp +++ b/source/main/utils/ErrorUtils.cpp @@ -19,7 +19,7 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file ErrorUtils.cpp @author Thomas Fischer @date 3rd October 2009 @@ -28,12 +28,12 @@ #include "ErrorUtils.h" #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 -#include -#include -#include // for ShellExecuteW -#define _L + #include // for ShellExecuteW + #include + #include + #define _L #elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX -#include "Language.h" + #include "Language.h" #endif using namespace Ogre; @@ -52,18 +52,18 @@ int ErrorUtils::ShowInfo(Ogre::UTFString title, Ogre::UTFString err) int ErrorUtils::ShowMsgBox(Ogre::UTFString title, Ogre::UTFString err, int type) { // we might call the ErrorUtils::ShowMsgBox without having ogre created yet! - //LOG("message box: " + title + ": " + err); + // LOG("message box: " + title + ": " + err); #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 int mtype = MB_ICONERROR; - if (type == 1) - mtype = MB_ICONINFORMATION; + if (type == 1) mtype = MB_ICONINFORMATION; MessageBoxW(NULL, err.asWStr_c_str(), title.asWStr_c_str(), MB_OK | mtype | MB_TOPMOST); #elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX - printf("\n\n%s: %s\n\n", title.asUTF8_c_str(), err.asUTF8_c_str()); + printf("\n\n%s: %s\n\n", title.asUTF8_c_str(), err.asUTF8_c_str()); #elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE - printf("\n\n%s: %s\n\n", title.asUTF8_c_str(), err.asUTF8_c_str()); - //CFOptionFlags flgs; - //CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, T("A network error occured"), T("Bad server port."), NULL, NULL, NULL, &flgs); + printf("\n\n%s: %s\n\n", title.asUTF8_c_str(), err.asUTF8_c_str()); + // CFOptionFlags flgs; + // CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, T("A network error occured"), T("Bad + // server port."), NULL, NULL, NULL, &flgs); #endif return 0; } diff --git a/source/main/utils/ErrorUtils.h b/source/main/utils/ErrorUtils.h index cefc418178..6c3f766a71 100644 --- a/source/main/utils/ErrorUtils.h +++ b/source/main/utils/ErrorUtils.h @@ -19,7 +19,7 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file ErrorUtils.h @author Thomas Fischer @date 3rd October 2009 diff --git a/source/main/utils/FileSystemInfo.h b/source/main/utils/FileSystemInfo.h index d20a860471..5464fbf8c6 100644 --- a/source/main/utils/FileSystemInfo.h +++ b/source/main/utils/FileSystemInfo.h @@ -36,166 +36,157 @@ #include #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 -#include -#include + #include + #include #else -#include -#include + #include + #include #endif #include #include -namespace RoR { - -namespace FileSystem { - -struct FileInfo +namespace RoR { - FileInfo(const std::wstring& _name, bool _folder) : name(_name), folder(_folder) + + namespace FileSystem { - } - std::wstring name; - bool folder; -}; + struct FileInfo + { + FileInfo(const std::wstring &_name, bool _folder) : name(_name), folder(_folder) + { + } -typedef std::vector VectorFileInfo; + std::wstring name; + bool folder; + }; -inline bool isAbsolutePath(const wchar_t* path) -{ + typedef std::vector VectorFileInfo; + + inline bool isAbsolutePath(const wchar_t *path) + { #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 - if (IsCharAlphaW(path[0]) && path[1] == ':') - return true; + if (IsCharAlphaW(path[0]) && path[1] == ':') return true; #endif - return path[0] == '/' || path[0] == '\\'; -} + return path[0] == '/' || path[0] == '\\'; + } -inline std::wstring concatenatePath(const std::wstring& _base, const std::wstring& _name) -{ - if (_base.empty() || isAbsolutePath(_name.c_str())) - return _name; - else + inline std::wstring concatenatePath(const std::wstring &_base, const std::wstring &_name) + { + if (_base.empty() || isAbsolutePath(_name.c_str())) + return _name; + else #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 - return _base + L'\\' + _name; + return _base + L'\\' + _name; #else - return _base + L'/' + _name; + return _base + L'/' + _name; #endif -} - -inline bool isReservedDir(const wchar_t* _fn) -{ - // if "." - return (_fn[0] == '.' && _fn[1] == 0); -} - -inline bool isParentDir(const wchar_t* _fn) -{ - // if ".." - return (_fn[0] == '.' && _fn[1] == '.' && _fn[2] == 0); -} - -inline void getSystemFileList(VectorFileInfo& _result, const std::wstring& _folder, const std::wstring& _mask) -{ -#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 - //FIXME add optional parameter? - bool ms_IgnoreHidden = true; - - long lHandle, res; - struct _wfinddata_t tagData; - - // pattern can contain a directory name, separate it from mask - size_t pos = _mask.find_last_of(L"/\\"); - std::wstring directory; - if (pos != _mask.npos) - directory = _mask.substr(0, pos); - - std::wstring full_mask = concatenatePath(_folder, _mask); - - lHandle = _wfindfirst(full_mask.c_str(), &tagData); - res = 0; - while (lHandle != -1 && res != -1) - { - if ((!ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0) && - (!isReservedDir(tagData.name))) - { - _result.push_back(FileInfo(concatenatePath(directory, tagData.name), (tagData.attrib & _A_SUBDIR) != 0)); } - res = _wfindnext(lHandle, &tagData); - } - // Close if we found any files - if (lHandle != -1) - _findclose(lHandle); -#else - DIR* dir = opendir(MyGUI::UString(_folder).asUTF8_c_str()); - struct dirent* dp; - if (dir == NULL) + inline bool isReservedDir(const wchar_t *_fn) { - /* opendir() failed */ + // if "." + return (_fn[0] == '.' && _fn[1] == 0); } - rewinddir (dir); - - while ((dp = readdir (dir)) != NULL) + inline bool isParentDir(const wchar_t *_fn) { - if (!isReservedDir (MyGUI::UString(dp->d_name).asWStr_c_str())) - _result.push_back(FileInfo(MyGUI::UString(dp->d_name).asWStr(), (dp->d_type == DT_DIR))); + // if ".." + return (_fn[0] == '.' && _fn[1] == '.' && _fn[2] == 0); } - closedir(dir); -#endif -} - -inline std::wstring getSystemCurrentFolder() -{ + inline void getSystemFileList(VectorFileInfo &_result, const std::wstring &_folder, const std::wstring &_mask) + { #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 - wchar_t buff[MAX_PATH + 1]; - ::GetCurrentDirectoryW(MAX_PATH, buff); - return buff; + // FIXME add optional parameter? + bool ms_IgnoreHidden = true; + + long lHandle, res; + struct _wfinddata_t tagData; + + // pattern can contain a directory name, separate it from mask + size_t pos = _mask.find_last_of(L"/\\"); + std::wstring directory; + if (pos != _mask.npos) directory = _mask.substr(0, pos); + + std::wstring full_mask = concatenatePath(_folder, _mask); + + lHandle = _wfindfirst(full_mask.c_str(), &tagData); + res = 0; + while (lHandle != -1 && res != -1) + { + if ((!ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0) && (!isReservedDir(tagData.name))) + { _result.push_back(FileInfo(concatenatePath(directory, tagData.name), (tagData.attrib & _A_SUBDIR) != 0)); } + res = _wfindnext(lHandle, &tagData); + } + // Close if we found any files + if (lHandle != -1) _findclose(lHandle); #else - char buff[PATH_MAX+1]; - return getcwd(buff, PATH_MAX) ? MyGUI::UString(buff).asWStr() : std::wstring(); -#endif -} + DIR *dir = opendir(MyGUI::UString(_folder).asUTF8_c_str()); + struct dirent *dp; -typedef std::vector VectorWString; + if (dir == NULL) + { /* opendir() failed */ + } -inline void scanFolder(VectorWString& _result, const std::wstring& _folder, bool _recursive, const std::wstring& _mask, bool _fullpath) -{ - std::wstring folder = _folder; - if (!folder.empty()) - folder += L"/"; + rewinddir(dir); - VectorFileInfo result; - getSystemFileList(result, folder, _mask); + while ((dp = readdir(dir)) != NULL) + { + if (!isReservedDir(MyGUI::UString(dp->d_name).asWStr_c_str())) + _result.push_back(FileInfo(MyGUI::UString(dp->d_name).asWStr(), (dp->d_type == DT_DIR))); + } - for (VectorFileInfo::const_iterator item = result.begin(); item != result.end(); ++item) - { - if (item->folder) - continue; + closedir(dir); +#endif + } - if (_fullpath) - _result.push_back(folder + item->name); - else - _result.push_back(item->name); - } + inline std::wstring getSystemCurrentFolder() + { +#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 + wchar_t buff[MAX_PATH + 1]; + ::GetCurrentDirectoryW(MAX_PATH, buff); + return buff; +#else + char buff[PATH_MAX + 1]; + return getcwd(buff, PATH_MAX) ? MyGUI::UString(buff).asWStr() : std::wstring(); +#endif + } - if (_recursive) - { - getSystemFileList(result, folder, L"*"); + typedef std::vector VectorWString; - for (VectorFileInfo::const_iterator item = result.begin(); item != result.end(); ++item) + inline void scanFolder(VectorWString &_result, const std::wstring &_folder, bool _recursive, const std::wstring &_mask, + bool _fullpath) { - if (!item->folder - || item->name == L".." - || item->name == L".") - continue; - scanFolder(_result, folder + item->name, _recursive, _mask, _fullpath); + std::wstring folder = _folder; + if (!folder.empty()) folder += L"/"; + + VectorFileInfo result; + getSystemFileList(result, folder, _mask); + + for (VectorFileInfo::const_iterator item = result.begin(); item != result.end(); ++item) + { + if (item->folder) continue; + + if (_fullpath) + _result.push_back(folder + item->name); + else + _result.push_back(item->name); + } + + if (_recursive) + { + getSystemFileList(result, folder, L"*"); + + for (VectorFileInfo::const_iterator item = result.begin(); item != result.end(); ++item) + { + if (!item->folder || item->name == L".." || item->name == L".") continue; + scanFolder(_result, folder + item->name, _recursive, _mask, _fullpath); + } + } } - } -} -} // namespace FileSystem + } // namespace FileSystem } // namespace RoR diff --git a/source/main/utils/ForceFeedback.cpp b/source/main/utils/ForceFeedback.cpp index 1adad7e969..53edc3ece7 100644 --- a/source/main/utils/ForceFeedback.cpp +++ b/source/main/utils/ForceFeedback.cpp @@ -28,83 +28,82 @@ #include #include -namespace RoR { - -void ForceFeedback::Setup() +namespace RoR { - using namespace Ogre; - m_device = App::GetInputEngine()->getForceFeedbackDevice(); - LOG(String("ForceFeedback: ")+TOSTRING(m_device->getFFAxesNumber())+" axe(s)"); - const OIS::ForceFeedback::SupportedEffectList& supEffects = m_device->getSupportedEffects(); - if (supEffects.size() > 0) + + void ForceFeedback::Setup() { - LOG("ForceFeedback: supported effects:"); - OIS::ForceFeedback::SupportedEffectList::const_iterator efit; + using namespace Ogre; + m_device = App::GetInputEngine()->getForceFeedbackDevice(); + LOG(String("ForceFeedback: ") + TOSTRING(m_device->getFFAxesNumber()) + " axe(s)"); + const OIS::ForceFeedback::SupportedEffectList &supEffects = m_device->getSupportedEffects(); + if (supEffects.size() > 0) + { + LOG("ForceFeedback: supported effects:"); + OIS::ForceFeedback::SupportedEffectList::const_iterator efit; #ifdef OISHEAD - for (efit=supEffects.begin(); efit!=supEffects.end(); ++efit) - LOG(String("ForceFeedback: ")+OIS::Effect::getEffectTypeName(efit->second)); -#endif //OISHEAD + for (efit = supEffects.begin(); efit != supEffects.end(); ++efit) + LOG(String("ForceFeedback: ") + OIS::Effect::getEffectTypeName(efit->second)); +#endif // OISHEAD + } + else + LOG("ForceFeedback: no supported effect found!"); + m_device->setAutoCenterMode(false); + m_device->setMasterGain(0.0); + + // do not load effect now, its too early } - else - LOG("ForceFeedback: no supported effect found!"); - m_device->setAutoCenterMode(false); - m_device->setMasterGain(0.0); - //do not load effect now, its too early -} + void ForceFeedback::SetForces(float roll, float pitch, float wspeed, float dircommand, float stress) + { + if (!m_device) { return; } -void ForceFeedback::SetForces(float roll, float pitch, float wspeed, float dircommand, float stress) -{ - if (!m_device) { return; } + // LOG(String("ForceFeedback: R=")+TOSTRING(roll)+" D="+TOSTRING(dir)+" S="+TOSTRING(wspeed)+" H="+TOSTRING(stress)); + if (!m_hydro_effect) + { + // we create effect at the last moment, because it does not works otherwise + m_hydro_effect = new OIS::Effect(OIS::Effect::ConstantForce, OIS::Effect::Constant); + m_hydro_effect->direction = OIS::Effect::North; + m_hydro_effect->trigger_button = 0; + m_hydro_effect->trigger_interval = 0; + m_hydro_effect->replay_length = OIS::Effect::OIS_INFINITE; // Linux/Win32: Same behaviour as 0. + m_hydro_effect->replay_delay = 0; + m_hydro_effect->setNumAxes(1); + OIS::ConstantEffect *hydroConstForce = dynamic_cast(m_hydro_effect->getForceEffect()); + if (hydroConstForce != nullptr) + { + hydroConstForce->level = 0; //-10K to +10k + hydroConstForce->envelope.attackLength = 0; + hydroConstForce->envelope.attackLevel = (unsigned short)hydroConstForce->level; + hydroConstForce->envelope.fadeLength = 0; + hydroConstForce->envelope.fadeLevel = (unsigned short)hydroConstForce->level; + } + m_device->upload(m_hydro_effect); + } - //LOG(String("ForceFeedback: R=")+TOSTRING(roll)+" D="+TOSTRING(dir)+" S="+TOSTRING(wspeed)+" H="+TOSTRING(stress)); - if (!m_hydro_effect) - { - //we create effect at the last moment, because it does not works otherwise - m_hydro_effect = new OIS::Effect(OIS::Effect::ConstantForce, OIS::Effect::Constant); - m_hydro_effect->direction = OIS::Effect::North; - m_hydro_effect->trigger_button = 0; - m_hydro_effect->trigger_interval = 0; - m_hydro_effect->replay_length = OIS::Effect::OIS_INFINITE; // Linux/Win32: Same behaviour as 0. - m_hydro_effect->replay_delay = 0; - m_hydro_effect->setNumAxes(1); - OIS::ConstantEffect* hydroConstForce = dynamic_cast(m_hydro_effect->getForceEffect()); + OIS::ConstantEffect *hydroConstForce = dynamic_cast(m_hydro_effect->getForceEffect()); if (hydroConstForce != nullptr) { - hydroConstForce->level = 0; //-10K to +10k - hydroConstForce->envelope.attackLength = 0; - hydroConstForce->envelope.attackLevel = (unsigned short)hydroConstForce->level; - hydroConstForce->envelope.fadeLength = 0; - hydroConstForce->envelope.fadeLevel = (unsigned short)hydroConstForce->level; + float stress_gain = App::io_ffb_stress_gain.GetActive(); + float centering_gain = App::io_ffb_center_gain.GetActive(); + float ff = -stress * stress_gain + dircommand * 100.0 * centering_gain * wspeed * wspeed; + if (ff > 10000) ff = 10000; + if (ff < -10000) ff = -10000; + hydroConstForce->level = ff; //-10K to +10k } - m_device->upload(m_hydro_effect); + m_device->modify(m_hydro_effect); } - OIS::ConstantEffect* hydroConstForce = dynamic_cast(m_hydro_effect->getForceEffect()); - if (hydroConstForce != nullptr) + void ForceFeedback::SetEnabled(bool b) { - float stress_gain = App::io_ffb_stress_gain.GetActive(); - float centering_gain = App::io_ffb_center_gain.GetActive(); - float ff = -stress * stress_gain + dircommand * 100.0 * centering_gain * wspeed * wspeed; - if (ff > 10000) - ff = 10000; - if (ff < -10000) - ff = -10000; - hydroConstForce->level = ff; //-10K to +10k - } - m_device->modify(m_hydro_effect); -} - -void ForceFeedback::SetEnabled(bool b) -{ - if (!m_device) { return; } + if (!m_device) { return; } - if (b != m_enabled) - { - float gain = (b) ? App::io_ffb_master_gain.GetActive() : 0.f; - m_device->setMasterGain(gain); + if (b != m_enabled) + { + float gain = (b) ? App::io_ffb_master_gain.GetActive() : 0.f; + m_device->setMasterGain(gain); + } + m_enabled = b; } - m_enabled = b; -} } // namespace RoR diff --git a/source/main/utils/ForceFeedback.h b/source/main/utils/ForceFeedback.h index bfdd428584..468990299b 100644 --- a/source/main/utils/ForceFeedback.h +++ b/source/main/utils/ForceFeedback.h @@ -22,31 +22,35 @@ #pragma once // Forward decl. -namespace OIS { class ForceFeedback; class Effect; } - -namespace RoR { +namespace OIS +{ + class ForceFeedback; + class Effect; +} // namespace OIS -class ForceFeedback +namespace RoR { -public: - ForceFeedback(): m_device(nullptr), m_hydro_effect(nullptr), m_enabled(false) + class ForceFeedback { - } - - void Setup(); - void SetEnabled(bool v); - - ///we take here : - /// -roll and pitch inertial forces at the camera: this is not used currently, but it can be used for 2 axes force feedback devices, like FF joysticks, to render shocks - /// -wheel speed and direction command, for the artificial auto-centering (which is wheel speed dependant) - /// -hydro beam stress, the ideal data source for FF wheels - void SetForces(float roll, float pitch, float wspeed, float dircommand, float stress); - -private: - OIS::ForceFeedback* m_device; - OIS::Effect* m_hydro_effect; - bool m_enabled; /// Disables FF when not in vehicle -}; + public: + ForceFeedback() : m_device(nullptr), m_hydro_effect(nullptr), m_enabled(false) + { + } + + void Setup(); + void SetEnabled(bool v); + + /// we take here : + /// -roll and pitch inertial forces at the camera: this is not used currently, but it can be used for 2 axes force + /// feedback devices, like FF joysticks, to render shocks -wheel speed and direction command, for the artificial + /// auto-centering (which is wheel speed dependant) -hydro beam stress, the ideal data source for FF wheels + void SetForces(float roll, float pitch, float wspeed, float dircommand, float stress); + + private: + OIS::ForceFeedback *m_device; + OIS::Effect * m_hydro_effect; + bool m_enabled; /// Disables FF when not in vehicle + }; } // namespace RoR diff --git a/source/main/utils/ImprovedConfigFile.h b/source/main/utils/ImprovedConfigFile.h index 43a477bcbe..f35abed6d7 100644 --- a/source/main/utils/ImprovedConfigFile.h +++ b/source/main/utils/ImprovedConfigFile.h @@ -21,8 +21,8 @@ #pragma once -#include "RoRPrerequisites.h" #include "ConfigFile.h" +#include "RoRPrerequisites.h" #include #include @@ -31,7 +31,7 @@ class ImprovedConfigFile : public RoR::ConfigFile { -public: + public: ImprovedConfigFile() : separators("="), filename() { ConfigFile(); @@ -42,31 +42,33 @@ class ImprovedConfigFile : public RoR::ConfigFile } // note: saving is only supported for direct loaded files atm! - void load(const Ogre::String& filename, const Ogre::String& separators = "=", bool trimWhitespace = true) + void load(const Ogre::String &filename, const Ogre::String &separators = "=", bool trimWhitespace = true) { this->separators = separators; - this->filename = filename; + this->filename = filename; ConfigFile::load(filename, separators, trimWhitespace); } - void load(const Ogre::DataStreamPtr& ptr, const Ogre::String& separators, bool trimWhitespace) + void load(const Ogre::DataStreamPtr &ptr, const Ogre::String &separators, bool trimWhitespace) { this->separators = separators; - this->filename = ""; + this->filename = ""; ConfigFile::load(ptr, separators, trimWhitespace); } - void loadFromString(const Ogre::String str, const Ogre::String& separators, bool trimWhitespace) + void loadFromString(const Ogre::String str, const Ogre::String &separators, bool trimWhitespace) { - Ogre::DataStreamPtr ds(Ogre::DataStreamPtr(OGRE_NEW Ogre::MemoryDataStream((void*)str.c_str(), str.size(), false, true))); + Ogre::DataStreamPtr ds( + Ogre::DataStreamPtr(OGRE_NEW Ogre::MemoryDataStream((void *)str.c_str(), str.size(), false, true))); this->separators = separators; - this->filename = ""; + this->filename = ""; ConfigFile::load(ds, separators, trimWhitespace); } bool hasSetting(Ogre::String key, Ogre::String section = "") { - return (mSettingsPtr.find(section) != mSettingsPtr.end() && mSettingsPtr[section]->find(key) != mSettingsPtr[section]->end()); + return (mSettingsPtr.find(section) != mSettingsPtr.end() && + mSettingsPtr[section]->find(key) != mSettingsPtr[section]->end()); } bool save() @@ -79,23 +81,23 @@ class ImprovedConfigFile : public RoR::ConfigFile if (!fn.length()) { OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, - "Saving of the configuration File is only allowed" - "when the configuration was not loaded using the resource system!", - "ImprovedConfigFile::save"); + "Saving of the configuration File is only allowed" + "when the configuration was not loaded using the resource system!", + "ImprovedConfigFile::save"); return false; } - FILE* f = fopen(fn.c_str(), "w"); + FILE *f = fopen(fn.c_str(), "w"); if (!f) { - OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND, "Cannot open File '"+fn+"' for writing.", "ImprovedConfigFile::save"); + OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND, "Cannot open File '" + fn + "' for writing.", + "ImprovedConfigFile::save"); return false; } SettingsBySection::iterator secIt; for (secIt = mSettingsPtr.begin(); secIt != mSettingsPtr.end(); secIt++) { - if (secIt->first.size() > 0) - fprintf(f, "[%s]\n", secIt->first.c_str()); + if (secIt->first.size() > 0) fprintf(f, "[%s]\n", secIt->first.c_str()); SettingsMultiMap::iterator setIt; for (setIt = secIt->second->begin(); setIt != secIt->second->end(); setIt++) { @@ -108,15 +110,15 @@ class ImprovedConfigFile : public RoR::ConfigFile void setSetting(Ogre::String key, Ogre::String value, Ogre::String section = Ogre::StringUtil::BLANK) { - SettingsMultiMap* set = mSettingsPtr[section]; + SettingsMultiMap *set = mSettingsPtr[section]; if (!set) { // new section - set = new SettingsMultiMap(); + set = new SettingsMultiMap(); mSettingsPtr[section] = set; } if (set->count(key)) - // known key, delete old first + // known key, delete old first set->erase(key); // add key set->insert(std::multimap::value_type(key, value)); @@ -253,7 +255,7 @@ class ImprovedConfigFile : public RoR::ConfigFile setSetting(key, TOSTRING(value), section); } -protected: + protected: Ogre::String separators; Ogre::String filename; }; diff --git a/source/main/utils/InputEngine.cpp b/source/main/utils/InputEngine.cpp index 8db11aafb6..785d21a960 100644 --- a/source/main/utils/InputEngine.cpp +++ b/source/main/utils/InputEngine.cpp @@ -26,1754 +26,320 @@ #include "Language.h" #include "OgreSubsystem.h" -const char* mOISDeviceType[6] = {"Unknown Device", "Keyboard", "Mouse", "JoyStick", "Tablet", "Other Device"}; +const char *mOISDeviceType[6] = {"Unknown Device", "Keyboard", "Mouse", "JoyStick", "Tablet", "Other Device"}; // LOOOONG list of possible events. see the struct type for the structure ;) eventInfo_t eventInfo[] = { - { - "AIRPLANE_STEER_RIGHT", - EV_AIRPLANE_STEER_RIGHT, - "Keyboard RIGHT", - _L("steer right") - }, - { - "AIRPLANE_BRAKE", - EV_AIRPLANE_BRAKE, - "Keyboard B", - _L("normal brake for an aircraft") - }, - { - "AIRPLANE_ELEVATOR_DOWN", - EV_AIRPLANE_ELEVATOR_DOWN, - "Keyboard DOWN", - _L("pull the elevator down in an aircraft.") - }, - { - "AIRPLANE_ELEVATOR_UP", - EV_AIRPLANE_ELEVATOR_UP, - "Keyboard UP", - _L("pull the elevator up in an aircraft.") - }, - { - "AIRPLANE_FLAPS_FULL", - EV_AIRPLANE_FLAPS_FULL, - "Keyboard CTRL+2", - _L("full flaps in an aircraft.") - }, - { - "AIRPLANE_FLAPS_LESS", - EV_AIRPLANE_FLAPS_LESS, - "Keyboard EXPL+1", - _L("one step less flaps.") - }, - { - "AIRPLANE_FLAPS_MORE", - EV_AIRPLANE_FLAPS_MORE, - "Keyboard EXPL+2", - _L("one step more flaps.") - }, - { - "AIRPLANE_FLAPS_NONE", - EV_AIRPLANE_FLAPS_NONE, - "Keyboard CTRL+1", - _L("no flaps.") - }, - { - "AIRPLANE_PARKING_BRAKE", - EV_AIRPLANE_PARKING_BRAKE, - "Keyboard P", - _L("airplane parking brake.") - - }, - { - "AIRPLANE_REVERSE", - EV_AIRPLANE_REVERSE, - "Keyboard R", - _L("reverse the turboprops") - }, - { - "AIRPLANE_RUDDER_LEFT", - EV_AIRPLANE_RUDDER_LEFT, - "Keyboard Z", - _L("rudder left") - }, - { - "AIRPLANE_RUDDER_RIGHT", - EV_AIRPLANE_RUDDER_RIGHT, - "Keyboard X", - _L("rudder right") - }, - { - "AIRPLANE_STEER_LEFT", - EV_AIRPLANE_STEER_LEFT, - "Keyboard LEFT", - _L("steer left") - }, - { - "AIRPLANE_STEER_RIGHT", - EV_AIRPLANE_STEER_RIGHT, - "Keyboard RIGHT", - _L("steer right") - }, - { - "AIRPLANE_THROTTLE_AXIS", - EV_AIRPLANE_THROTTLE_AXIS, - "None", - _L("throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)") - }, - { - "AIRPLANE_THROTTLE_DOWN", - EV_AIRPLANE_THROTTLE_DOWN, - "Keyboard EXPL+PGDOWN", - _L("decreases the airplane thrust") - }, - { - "AIRPLANE_THROTTLE_FULL", - EV_AIRPLANE_THROTTLE_FULL, - "Keyboard CTRL+PGUP", - _L("full thrust") - }, - { - "AIRPLANE_THROTTLE_NO", - EV_AIRPLANE_THROTTLE_NO, - "Keyboard CTRL+PGDOWN", - _L("no thrust") - }, - { - "AIRPLANE_THROTTLE_UP", - EV_AIRPLANE_THROTTLE_UP, - "Keyboard EXPL+PGUP", - _L("increase the airplane thrust") - }, - { - "AIRPLANE_TOGGLE_ENGINES", - EV_AIRPLANE_TOGGLE_ENGINES, - "Keyboard CTRL+HOME", - _L("switch all engines on / off") - }, - { - "BOAT_CENTER_RUDDER", - EV_BOAT_CENTER_RUDDER, - "Keyboard PGDOWN", - _L("center the rudder") - }, - { - "BOAT_REVERSE", - EV_BOAT_REVERSE, - "Keyboard PGUP", - _L("no thrust") - }, - { - "BOAT_STEER_LEFT", - EV_BOAT_STEER_LEFT, - "Keyboard LEFT", - _L("steer left a step") - }, - { - "BOAT_STEER_LEFT_AXIS", - EV_BOAT_STEER_LEFT_AXIS, - "None", - _L("steer left (analog value!)") - }, - { - "BOAT_STEER_RIGHT", - EV_BOAT_STEER_RIGHT, - "Keyboard RIGHT", - _L("steer right a step") - }, - { - "BOAT_STEER_RIGHT_AXIS", - EV_BOAT_STEER_RIGHT_AXIS, - "None", - _L("steer right (analog value!)") - }, - { - "BOAT_THROTTLE_AXIS", - EV_BOAT_THROTTLE_AXIS, - "None", - _L("throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)") - }, - { - "BOAT_THROTTLE_DOWN", - EV_BOAT_THROTTLE_DOWN, - "Keyboard DOWN", - _L("decrease throttle") - }, - { - "BOAT_THROTTLE_UP", - EV_BOAT_THROTTLE_UP, - "Keyboard UP", - _L("increase throttle") - }, - { - "SKY_DECREASE_TIME", - EV_SKY_DECREASE_TIME, - "Keyboard EXPL+SUBTRACT", - _L("decrease day-time") - }, - { - "SKY_DECREASE_TIME_FAST", - EV_SKY_DECREASE_TIME_FAST, - "Keyboard SHIFT+SUBTRACT", - _L("decrease day-time a lot faster") - }, - { - "SKY_INCREASE_TIME", - EV_SKY_INCREASE_TIME, - "Keyboard EXPL+ADD", - _L("increase day-time") - }, - { - "SKY_INCREASE_TIME_FAST", - EV_SKY_INCREASE_TIME_FAST, - "Keyboard SHIFT+ADD", - _L("increase day-time a lot faster") - }, - { - "CAMERA_CHANGE", - EV_CAMERA_CHANGE, - "Keyboard EXPL+C", - _L("change camera mode") - }, - { - "CAMERA_LOOKBACK", - EV_CAMERA_LOOKBACK, - "Keyboard NUMPAD1", - _L("look back (toggles between normal and lookback)") - }, - { - "CAMERA_RESET", - EV_CAMERA_RESET, - "Keyboard NUMPAD5", - _L("reset the camera position") - }, - { - "CAMERA_ROTATE_DOWN", - EV_CAMERA_ROTATE_DOWN, - "Keyboard NUMPAD2", - _L("rotate camera down") - }, - { - "CAMERA_ROTATE_LEFT", - EV_CAMERA_ROTATE_LEFT, - "Keyboard NUMPAD4", - _L("rotate camera left") - }, - { - "CAMERA_ROTATE_RIGHT", - EV_CAMERA_ROTATE_RIGHT, - "Keyboard NUMPAD6", - _L("rotate camera right") - }, - { - "CAMERA_ROTATE_UP", - EV_CAMERA_ROTATE_UP, - "Keyboard NUMPAD8", - _L("rotate camera up") - }, - { - "CAMERA_ZOOM_IN", - EV_CAMERA_ZOOM_IN, - "Keyboard EXPL+NUMPAD9", - _L("zoom camera in") - }, - { - "CAMERA_ZOOM_IN_FAST", - EV_CAMERA_ZOOM_IN_FAST, - "Keyboard SHIFT+NUMPAD9", - _L("zoom camera in faster") - }, - { - "CAMERA_ZOOM_OUT", - EV_CAMERA_ZOOM_OUT, - "Keyboard EXPL+NUMPAD3", - _L("zoom camera out") - }, - { - "CAMERA_ZOOM_OUT_FAST", - EV_CAMERA_ZOOM_OUT_FAST, - "Keyboard SHIFT+NUMPAD3", - _L("zoom camera out faster") - }, - { - "CHARACTER_BACKWARDS", - EV_CHARACTER_BACKWARDS, - "Keyboard S", - _L("step backwards with the character") - }, - { - "CHARACTER_FORWARD", - EV_CHARACTER_FORWARD, - "Keyboard W", - _L("step forward with the character") - }, - { - "CHARACTER_JUMP", - EV_CHARACTER_JUMP, - "Keyboard SPACE", - _L("let the character jump") - }, - { - "CHARACTER_LEFT", - EV_CHARACTER_LEFT, - "Keyboard LEFT", - _L("rotate character left") - }, - { - "CHARACTER_RIGHT", - EV_CHARACTER_RIGHT, - "Keyboard RIGHT", - _L("rotate character right") - }, - { - "CHARACTER_RUN", - EV_CHARACTER_RUN, - "Keyboard SHIFT+W", - _L("let the character run") - }, - { - "CHARACTER_SIDESTEP_LEFT", - EV_CHARACTER_SIDESTEP_LEFT, - "Keyboard A", - _L("sidestep to the left") - }, - { - "CHARACTER_SIDESTEP_RIGHT", - EV_CHARACTER_SIDESTEP_RIGHT, - "Keyboard D", - _L("sidestep to the right") - }, - { - "COMMANDS_01", - EV_COMMANDS_01, - "Keyboard EXPL+F1", - _L("Command 1") - }, - { - "COMMANDS_02", - EV_COMMANDS_02, - "Keyboard EXPL+F2", - _L("Command 2") - }, - { - "COMMANDS_03", - EV_COMMANDS_03, - "Keyboard EXPL+F3", - _L("Command 3") - }, - { - "COMMANDS_04", - EV_COMMANDS_04, - "Keyboard EXPL+F4", - _L("Command 4") - }, - { - "COMMANDS_05", - EV_COMMANDS_05, - "Keyboard EXPL+F5", - _L("Command 5") - }, - { - "COMMANDS_06", - EV_COMMANDS_06, - "Keyboard EXPL+F6", - _L("Command 6") - }, - { - "COMMANDS_07", - EV_COMMANDS_07, - "Keyboard EXPL+F7", - _L("Command 7") - }, - { - "COMMANDS_08", - EV_COMMANDS_08, - "Keyboard EXPL+F8", - _L("Command 8") - }, - { - "COMMANDS_09", - EV_COMMANDS_09, - "Keyboard EXPL+F9", - _L("Command 9") - }, - { - "COMMANDS_10", - EV_COMMANDS_10, - "Keyboard EXPL+F10", - _L("Command 10") - }, - { - "COMMANDS_11", - EV_COMMANDS_11, - "Keyboard EXPL+F11", - _L("Command 11") - }, - { - "COMMANDS_12", - EV_COMMANDS_12, - "Keyboard EXPL+F12", - _L("Command 12") - }, - { - "COMMANDS_13", - EV_COMMANDS_13, - "Keyboard EXPL+CTRL+F1", - _L("Command 13") - }, - { - "COMMANDS_14", - EV_COMMANDS_14, - "Keyboard EXPL+CTRL+F2", - _L("Command 14") - }, - { - "COMMANDS_15", - EV_COMMANDS_15, - "Keyboard EXPL+CTRL+F3", - _L("Command 15") - }, - { - "COMMANDS_16", - EV_COMMANDS_16, - "Keyboard EXPL+CTRL+F4", - _L("Command 16") - }, - { - "COMMANDS_17", - EV_COMMANDS_17, - "Keyboard EXPL+CTRL+F5", - _L("Command 17") - }, - { - "COMMANDS_18", - EV_COMMANDS_18, - "Keyboard EXPL+CTRL+F6", - _L("Command 18") - }, - { - "COMMANDS_19", - EV_COMMANDS_19, - "Keyboard EXPL+CTRL+F7", - _L("Command 19") - }, - { - "COMMANDS_20", - EV_COMMANDS_20, - "Keyboard EXPL+CTRL+F8", - _L("Command 20") - }, - { - "COMMANDS_21", - EV_COMMANDS_21, - "Keyboard EXPL+CTRL+F9", - _L("Command 21") - }, - { - "COMMANDS_22", - EV_COMMANDS_22, - "Keyboard EXPL+CTRL+F10", - _L("Command 22") - }, - { - "COMMANDS_23", - EV_COMMANDS_23, - "Keyboard EXPL+CTRL+F11", - _L("Command 23") - }, - { - "COMMANDS_24", - EV_COMMANDS_24, - "Keyboard EXPL+CTRL+F12", - _L("Command 24") - }, - { - "COMMANDS_25", - EV_COMMANDS_25, - "Keyboard EXPL+SHIFT+F1", - _L("Command 25") - }, - { - "COMMANDS_26", - EV_COMMANDS_26, - "Keyboard EXPL+SHIFT+F2", - _L("Command 26") - }, - { - "COMMANDS_27", - EV_COMMANDS_27, - "Keyboard EXPL+SHIFT+F3", - _L("Command 27") - }, - { - "COMMANDS_28", - EV_COMMANDS_28, - "Keyboard EXPL+SHIFT+F4", - _L("Command 28") - }, - { - "COMMANDS_29", - EV_COMMANDS_29, - "Keyboard EXPL+SHIFT+F5", - _L("Command 29") - }, - { - "COMMANDS_30", - EV_COMMANDS_30, - "Keyboard EXPL+SHIFT+F6", - _L("Command 30") - }, - { - "COMMANDS_31", - EV_COMMANDS_31, - "Keyboard EXPL+SHIFT+F7", - _L("Command 31") - }, - { - "COMMANDS_32", - EV_COMMANDS_32, - "Keyboard EXPL+SHIFT+F8", - _L("Command 32") - }, - { - "COMMANDS_33", - EV_COMMANDS_33, - "Keyboard EXPL+SHIFT+F9", - _L("Command 33") - }, - { - "COMMANDS_34", - EV_COMMANDS_34, - "Keyboard EXPL+SHIFT+F10", - _L("Command 34") - }, - { - "COMMANDS_35", - EV_COMMANDS_35, - "Keyboard EXPL+SHIFT+F11", - _L("Command 35") - }, - { - "COMMANDS_36", - EV_COMMANDS_36, - "Keyboard EXPL+SHIFT+F12", - _L("Command 36") - }, - { - "COMMANDS_37", - EV_COMMANDS_37, - "Keyboard EXPL+ALT+F1", - _L("Command 37") - }, - { - "COMMANDS_38", - EV_COMMANDS_38, - "Keyboard EXPL+ALT+F2", - _L("Command 38") - }, - { - "COMMANDS_39", - EV_COMMANDS_39, - "Keyboard EXPL+ALT+F3", - _L("Command 39") - }, - { - "COMMANDS_40", - EV_COMMANDS_40, - "Keyboard EXPL+ALT+F4", - _L("Command 40") - }, - { - "COMMANDS_41", - EV_COMMANDS_41, - "Keyboard EXPL+ALT+F5", - _L("Command 41") - }, - { - "COMMANDS_42", - EV_COMMANDS_42, - "Keyboard EXPL+ALT+F6", - _L("Command 42") - }, - { - "COMMANDS_43", - EV_COMMANDS_43, - "Keyboard EXPL+ALT+F7", - _L("Command 43") - }, - { - "COMMANDS_44", - EV_COMMANDS_44, - "Keyboard EXPL+ALT+F8", - _L("Command 44") - }, - { - "COMMANDS_45", - EV_COMMANDS_45, - "Keyboard EXPL+ALT+F9", - _L("Command 45") - }, - { - "COMMANDS_46", - EV_COMMANDS_46, - "Keyboard EXPL+ALT+F10", - _L("Command 46") - }, - { - "COMMANDS_47", - EV_COMMANDS_47, - "Keyboard EXPL+ALT+F11", - _L("Command 47") - }, - { - "COMMANDS_48", - EV_COMMANDS_48, - "Keyboard EXPL+ALT+F12", - _L("Command 48") - }, - { - "COMMANDS_49", - EV_COMMANDS_49, - "Keyboard EXPL+CTRL+SHIFT+F1", - _L("Command 49") - }, - { - "COMMANDS_50", - EV_COMMANDS_50, - "Keyboard EXPL+CTRL+SHIFT+F2", - _L("Command 50") - }, - { - "COMMANDS_51", - EV_COMMANDS_51, - "Keyboard EXPL+CTRL+SHIFT+F3", - _L("Command 51") - }, - { - "COMMANDS_52", - EV_COMMANDS_52, - "Keyboard EXPL+CTRL+SHIFT+F4", - _L("Command 52") - }, - { - "COMMANDS_53", - EV_COMMANDS_53, - "Keyboard EXPL+CTRL+SHIFT+F5", - _L("Command 53") - }, - { - "COMMANDS_54", - EV_COMMANDS_54, - "Keyboard EXPL+CTRL+SHIFT+F6", - _L("Command 54") - }, - { - "COMMANDS_55", - EV_COMMANDS_55, - "Keyboard EXPL+CTRL+SHIFT+F7", - _L("Command 55") - }, - { - "COMMANDS_56", - EV_COMMANDS_56, - "Keyboard EXPL+CTRL+SHIFT+F8", - _L("Command 56") - }, - { - "COMMANDS_57", - EV_COMMANDS_57, - "Keyboard EXPL+CTRL+SHIFT+F9", - _L("Command 57") - }, - { - "COMMANDS_58", - EV_COMMANDS_58, - "Keyboard EXPL+CTRL+SHIFT+F10", - _L("Command 58") - }, - { - "COMMANDS_59", - EV_COMMANDS_59, - "Keyboard EXPL+CTRL+SHIFT+F11", - _L("Command 59") - }, - { - "COMMANDS_60", - EV_COMMANDS_60, - "Keyboard EXPL+CTRL+SHIFT+F12", - _L("Command 60") - }, - { - "COMMANDS_61", - EV_COMMANDS_61, - "Keyboard EXPL+CTRL+ALT+F1", - _L("Command 61") - }, - { - "COMMANDS_62", - EV_COMMANDS_62, - "Keyboard EXPL+CTRL+ALT+F2", - _L("Command 62") - }, - { - "COMMANDS_63", - EV_COMMANDS_63, - "Keyboard EXPL+CTRL+ALT+F3", - _L("Command 63") - }, - { - "COMMANDS_64", - EV_COMMANDS_64, - "Keyboard EXPL+CTRL+ALT+F4", - _L("Command 64") - }, - { - "COMMANDS_65", - EV_COMMANDS_65, - "Keyboard EXPL+CTRL+ALT+F5", - _L("Command 65") - }, - { - "COMMANDS_66", - EV_COMMANDS_66, - "Keyboard EXPL+CTRL+ALT+F6", - _L("Command 66") - }, - { - "COMMANDS_67", - EV_COMMANDS_67, - "Keyboard EXPL+CTRL+ALT+F7", - _L("Command 67") - }, - { - "COMMANDS_68", - EV_COMMANDS_68, - "Keyboard EXPL+CTRL+ALT+F8", - _L("Command 68") - }, - { - "COMMANDS_69", - EV_COMMANDS_69, - "Keyboard EXPL+CTRL+ALT+F9", - _L("Command 69") - }, - { - "COMMANDS_70", - EV_COMMANDS_70, - "Keyboard EXPL+CTRL+ALT+F10", - _L("Command 70") - }, - { - "COMMANDS_71", - EV_COMMANDS_71, - "Keyboard EXPL+CTRL+ALT+F11", - _L("Command 71") - }, - { - "COMMANDS_72", - EV_COMMANDS_72, - "Keyboard EXPL+CTRL+ALT+F12", - _L("Command 72") - }, - { - "COMMANDS_73", - EV_COMMANDS_73, - "Keyboard EXPL+CTRL+SHIFT+ALT+F1", - _L("Command 73") - }, - { - "COMMANDS_74", - EV_COMMANDS_74, - "Keyboard EXPL+CTRL+SHIFT+ALT+F2", - _L("Command 74") - }, - { - "COMMANDS_75", - EV_COMMANDS_75, - "Keyboard EXPL+CTRL+SHIFT+ALT+F3", - _L("Command 75") - }, - { - "COMMANDS_76", - EV_COMMANDS_76, - "Keyboard EXPL+CTRL+SHIFT+ALT+F4", - _L("Command 76") - }, - { - "COMMANDS_77", - EV_COMMANDS_77, - "Keyboard EXPL+CTRL+SHIFT+ALT+F5", - _L("Command 77") - }, - { - "COMMANDS_78", - EV_COMMANDS_78, - "Keyboard EXPL+CTRL+SHIFT+ALT+F6", - _L("Command 78") - }, - { - "COMMANDS_79", - EV_COMMANDS_79, - "Keyboard EXPL+CTRL+SHIFT+ALT+F7", - _L("Command 79") - }, - { - "COMMANDS_80", - EV_COMMANDS_80, - "Keyboard EXPL+CTRL+SHIFT+ALT+F8", - _L("Command 80") - }, - { - "COMMANDS_81", - EV_COMMANDS_81, - "Keyboard EXPL+CTRL+SHIFT+ALT+F9", - _L("Command 81") - }, - { - "COMMANDS_82", - EV_COMMANDS_82, - "Keyboard EXPL+CTRL+SHIFT+ALT+F10", - _L("Command 82") - }, - { - "COMMANDS_83", - EV_COMMANDS_83, - "Keyboard EXPL+CTRL+SHIFT+ALT+F11", - _L("Command 83") - }, - { - "COMMANDS_84", - EV_COMMANDS_84, - "Keyboard EXPL+CTRL+SHIFT+ALT+F12", - _L("Command 84") - }, - { - "COMMON_ACCELERATE_SIMULATION", - EV_COMMON_ACCELERATE_SIMULATION, - "Keyboard CTRL+EQUALS", - _L("accelerate the simulation") - }, - { - "COMMON_DECELERATE_SIMULATION", - EV_COMMON_DECELERATE_SIMULATION, - "Keyboard SHIFT+EQUALS", - _L("decelerate the simulation") - }, - { - "COMMON_RESET_SIMULATION_PACE", - EV_COMMON_RESET_SIMULATION_PACE, - "Keyboard BACKSLASH", - _L("reset the simulation pace") - }, - { - "COMMON_CONSOLE_TOGGLE", - EV_COMMON_CONSOLE_TOGGLE, - "Keyboard EXPL+GRAVE", - _L("show / hide the console") - }, - { - "COMMON_ENTER_CHATMODE", - EV_COMMON_ENTER_CHATMODE, - "Keyboard Y", - _L("enter the chat") - }, - { - "COMMON_SEND_CHAT", - EV_COMMON_SEND_CHAT, - "Keyboard RETURN", - _L("sends the entered text") - }, - { - "COMMON_ENTER_OR_EXIT_TRUCK", - EV_COMMON_ENTER_OR_EXIT_TRUCK, - "Keyboard RETURN", - _L("enter or exit a truck") - }, - { - "COMMON_ENTER_NEXT_TRUCK", - EV_COMMON_ENTER_NEXT_TRUCK, - "Keyboard EXPL+CTRL+RBRACKET", - _L("enter next truck") - }, - { - "COMMON_ENTER_PREVIOUS_TRUCK", - EV_COMMON_ENTER_PREVIOUS_TRUCK, - "Keyboard EXPL+CTRL+LBRACKET", - _L("enter previous truck") - }, - { - "COMMON_REMOVE_CURRENT_TRUCK", - EV_COMMON_REMOVE_CURRENT_TRUCK, - "Keyboard EXPL+CTRL+DELETE", - _L("remove current truck") - }, - { - "COMMON_RESPAWN_LAST_TRUCK", - EV_COMMON_RESPAWN_LAST_TRUCK, - "Keyboard EXPL+CTRL+PERIOD", - _L("respawn last truck") - }, - { - "COMMON_HIDE_GUI", - EV_COMMON_HIDE_GUI, - "Keyboard EXPL+U", - _L("hide all GUI elements") - }, - { - "COMMON_TOGGLE_DASHBOARD", - EV_COMMON_TOGGLE_DASHBOARD, - "Keyboard EXPL+CTRL+U", - _L("display or hide the dashboard overlay") - }, - { - "COMMON_LOCK", - EV_COMMON_LOCK, - "Keyboard EXPL+L", - _L("connect hook node to a node in close proximity") - }, - { - "COMMON_AUTOLOCK", - EV_COMMON_AUTOLOCK, - "Keyboard EXPL+ALT+L", - _L("unlock autolock hook node") - }, - { - "COMMON_ROPELOCK", - EV_COMMON_ROPELOCK, - "Keyboard EXPL+CTRL+L", - _L("connect a rope to a node in close proximity") - }, - { - "COMMON_OUTPUT_POSITION", - EV_COMMON_OUTPUT_POSITION, - "Keyboard H", - _L("write current position to log (you can open the logfile and reuse the position)") - }, - { - "COMMON_GET_NEW_VEHICLE", - EV_COMMON_GET_NEW_VEHICLE, - "Keyboard EXPL+CTRL+G", - _L("get new vehicle") - }, - { - "COMMON_PRESSURE_LESS", - EV_COMMON_PRESSURE_LESS, - "Keyboard LBRACKET", - _L("decrease tire pressure (note: only very few trucks support this)") - }, - { - "COMMON_PRESSURE_MORE", - EV_COMMON_PRESSURE_MORE, - "Keyboard RBRACKET", - _L("increase tire pressure (note: only very few trucks support this)") - }, - { - "COMMON_QUIT_GAME", - EV_COMMON_QUIT_GAME, - "Keyboard EXPL+ESCAPE", - _L("exit the game") - }, - { - "COMMON_QUICKLOAD", - EV_COMMON_QUICKLOAD, - "Keyboard MULTIPLY", - _L("quickload scene") - }, - { - "COMMON_QUICKSAVE", - EV_COMMON_QUICKSAVE, - "Keyboard DIVIDE", - _L("quicksave scene") - }, - { - "COMMON_REPAIR_TRUCK", - EV_COMMON_REPAIR_TRUCK, - "Keyboard BACK", - _L("repair truck") - }, - { - "COMMON_RESCUE_TRUCK", - EV_COMMON_RESCUE_TRUCK, - "Keyboard EXPL+R", - _L("teleport to rescue truck") - }, - { - "COMMON_RESET_TRUCK", - EV_COMMON_RESET_TRUCK, - "Keyboard I", - _L("reset truck to original starting position") - }, - { - "COMMON_TOGGLE_RESET_MODE", - EV_COMMON_TOGGLE_RESET_MODE, - "Keyboard EXPL+APOSTROPHE", - _L("toggle reset mode") - }, - { - "COMMON_SCREENSHOT", - EV_COMMON_SCREENSHOT, - "Keyboard EXPL+SYSRQ", - _L("take a screenshot") - }, - { - "COMMON_SCREENSHOT_BIG", - EV_COMMON_SCREENSHOT_BIG, - "Keyboard EXPL+CTRL+SYSRQ", - _L("take a big screenshot (3 times the screen size)") - }, - { - "COMMON_SAVE_TERRAIN", - EV_COMMON_SAVE_TERRAIN, - "Keyboard EXPL+ALT+SHIF+CTRL+M", - _L("save the currently loaded terrain to a mesh file") - }, - { - "COMMON_SECURE_LOAD", - EV_COMMON_SECURE_LOAD, - "Keyboard O", - _L("tie a load to the truck") - }, - { - "COMMON_TOGGLE_DEBUG_VIEW", - EV_COMMON_TOGGLE_DEBUG_VIEW, - "Keyboard EXPL+K", - _L("toggle debug view") - }, - { - "COMMON_CYCLE_DEBUG_VIEWS", - EV_COMMON_CYCLE_DEBUG_VIEWS, - "Keyboard EXPL+CTRL+K", - _L("cycle debug views") - }, - { - "COMMON_TOGGLE_TERRAIN_EDITOR", - EV_COMMON_TOGGLE_TERRAIN_EDITOR, - "Keyboard EXPL+SHIFT+Y", - _L("toggle terrain editor") - }, - { - "COMMON_TOGGLE_CUSTOM_PARTICLES", - EV_COMMON_TOGGLE_CUSTOM_PARTICLES, - "Keyboard G", - _L("toggle particle cannon") - }, - { - "COMMON_TOGGLE_MAT_DEBUG", - EV_COMMON_TOGGLE_MAT_DEBUG, - "", - _L("debug purpose - dont use") - }, - { - "COMMON_TOGGLE_RENDER_MODE", - EV_COMMON_TOGGLE_RENDER_MODE, - "Keyboard E", - _L("toggle render mode (solid, wireframe and points)") - }, - { - "COMMON_TOGGLE_REPLAY_MODE", - EV_COMMON_TOGGLE_REPLAY_MODE, - "Keyboard EXPL+CTRL+J", - _L("enable or disable replay mode") - }, - { - "COMMON_TOGGLE_PHYSICS", - EV_COMMON_TOGGLE_PHYSICS, - "Keyboard EXPL+J", - _L("enable or disable physics") - }, - { - "COMMON_TOGGLE_STATS", - EV_COMMON_TOGGLE_STATS, - "Keyboard EXPL+F", - _L("toggle Ogre statistics (FPS etc.)") - }, - { - "COMMON_TOGGLE_TRUCK_BEACONS", - EV_COMMON_TOGGLE_TRUCK_BEACONS, - "Keyboard M", - _L("toggle truck beacons") - }, - { - "COMMON_TOGGLE_TRUCK_LIGHTS", - EV_COMMON_TOGGLE_TRUCK_LIGHTS, - "Keyboard N", - _L("toggle truck front lights") - }, - { - "COMMON_TRUCK_INFO", - EV_COMMON_TRUCK_INFO, - "Keyboard EXPL+T", - _L("toggle truck HUD") - }, - { - "COMMON_TRUCK_DESCRIPTION", - EV_COMMON_TRUCK_DESCRIPTION, - "Keyboard EXPL+CTRL+T", - _L("toggle truck description") - }, - { - "COMMON_FOV_LESS", - EV_COMMON_FOV_LESS, - "Keyboard EXPL+NUMPAD7", - _L("decreases the current FOV value") - }, - { - "COMMON_FOV_MORE", - EV_COMMON_FOV_MORE, - "Keyboard EXPL+CTRL+NUMPAD7", - _L("increase the current FOV value") - }, - { - "COMMON_FOV_RESET", - EV_COMMON_FOV_RESET, - "Keyboard EXPL+SHIFT+NUMPAD7", - _L("reset the FOV value") - }, - { - "GRASS_LESS", - EV_GRASS_LESS, - "", - _L("EXPERIMENTAL: remove some grass") - }, - { - "GRASS_MORE", - EV_GRASS_MORE, - "", - _L("EXPERIMENTAL: add some grass") - }, - { - "GRASS_MOST", - EV_GRASS_MOST, - "", - _L("EXPERIMENTAL: set maximum amount of grass") - }, - { - "GRASS_NONE", - EV_GRASS_NONE, - "", - _L("EXPERIMENTAL: remove grass completely") - }, - { - "GRASS_SAVE", - EV_GRASS_SAVE, - "", - _L("EXPERIMENTAL: save changes to the grass density image") - }, - { - "MENU_DOWN", - EV_MENU_DOWN, - "Keyboard DOWN", - _L("select next element in current category") - }, - { - "MENU_LEFT", - EV_MENU_LEFT, - "Keyboard LEFT", - _L("select previous category") - }, - { - "MENU_RIGHT", - EV_MENU_RIGHT, - "Keyboard RIGHT", - _L("select next category") - }, - { - "MENU_SELECT", - EV_MENU_SELECT, - "Keyboard EXPL+RETURN", - _L("select focussed item and close menu") - }, - { - "MENU_UP", - EV_MENU_UP, - "Keyboard UP", - _L("select previous element in current category") - }, - { - "SURVEY_MAP_TOGGLE_ICONS", - EV_SURVEY_MAP_TOGGLE_ICONS, - "Keyboard EXPL+CTRL+SHIFT+ALT+TAB", - _L("toggle map icons") - }, - { - "SURVEY_MAP_TOGGLE", - EV_SURVEY_MAP_TOGGLE, - "Keyboard EXPL+CTRL+SHIFT+TAB", - _L("toggle map") - }, - { - "SURVEY_MAP_CYCLE", - EV_SURVEY_MAP_CYCLE, - "Keyboard EXPL+TAB", - _L("cycle map modes") - }, - { - "SURVEY_MAP_ZOOM_IN", - EV_SURVEY_MAP_ZOOM_IN, - "Keyboard EXPL+CTRL+TAB", - _L("zoom in") - }, - { - "SURVEY_MAP_ZOOM_OUT", - EV_SURVEY_MAP_ZOOM_OUT, - "Keyboard EXPL+SHIFT+TAB", - _L("zoom out") - }, - { - "TRUCK_ACCELERATE", - EV_TRUCK_ACCELERATE, - "Keyboard UP", - _L("accelerate the truck") - }, - { - "TRUCK_ACCELERATE_MODIFIER_25", - EV_TRUCK_ACCELERATE_MODIFIER_25, - "Keyboard ALT+UP", - _L("accelerate with 25 percent pedal input") - }, - { - "TRUCK_ACCELERATE_MODIFIER_50", - EV_TRUCK_ACCELERATE_MODIFIER_50, - "Keyboard CTRL+UP", - _L("accelerate with 50 percent pedal input") - }, - { - "TRUCK_AUTOSHIFT_DOWN", - EV_TRUCK_AUTOSHIFT_DOWN, - "Keyboard PGDOWN", - _L("shift automatic transmission one gear down") - }, - { - "TRUCK_AUTOSHIFT_UP", - EV_TRUCK_AUTOSHIFT_UP, - "Keyboard PGUP", - _L("shift automatic transmission one gear up") - }, - { - "TRUCK_BLINK_LEFT", - EV_TRUCK_BLINK_LEFT, - "Keyboard COMMA", - _L("toggle left direction indicator (blinker)") - }, - { - "TRUCK_BLINK_RIGHT", - EV_TRUCK_BLINK_RIGHT, - "Keyboard PERIOD", - _L("toggle right direction indicator (blinker)") - }, - { - "TRUCK_BLINK_WARN", - EV_TRUCK_BLINK_WARN, - "Keyboard MINUS", - _L("toggle all direction indicators") - }, - { - "TRUCK_BRAKE", - EV_TRUCK_BRAKE, - "Keyboard DOWN", - _L("brake") - }, - { - "TRUCK_BRAKE_MODIFIER_25", - EV_TRUCK_BRAKE_MODIFIER_25, - "Keyboard ALT+DOWN", - _L("brake with 25 percent pedal input") - }, - { - "TRUCK_BRAKE_MODIFIER_50", - EV_TRUCK_BRAKE_MODIFIER_50, - "Keyboard CTRL+DOWN", - _L("brake with 50 percent pedal input") - }, - { - "TRUCK_HORN", - EV_TRUCK_HORN, - "Keyboard H", - _L("truck horn") - }, - { - "TRUCK_LIGHTTOGGLE1", - EV_TRUCK_LIGHTTOGGLE01, - "Keyboard EXPL+CTRL+1", - _L("toggle custom light 1") - }, - { - "TRUCK_LIGHTTOGGLE2", - EV_TRUCK_LIGHTTOGGLE02, - "Keyboard EXPL+CTRL+2", - _L("toggle custom light 2") - }, - { - "TRUCK_LIGHTTOGGLE3", - EV_TRUCK_LIGHTTOGGLE03, - "Keyboard EXPL+CTRL+3", - _L("toggle custom light 3") - }, - { - "TRUCK_LIGHTTOGGLE4", - EV_TRUCK_LIGHTTOGGLE04, - "Keyboard EXPL+CTRL+4", - _L("toggle custom light 4") - }, - { - "TRUCK_LIGHTTOGGLE5", - EV_TRUCK_LIGHTTOGGLE05, - "Keyboard EXPL+CTRL+5", - _L("toggle custom light 5") - }, - { - "TRUCK_LIGHTTOGGLE6", - EV_TRUCK_LIGHTTOGGLE06, - "Keyboard EXPL+CTRL+6", - _L("toggle custom light 6") - }, - { - "TRUCK_LIGHTTOGGLE7", - EV_TRUCK_LIGHTTOGGLE07, - "Keyboard EXPL+CTRL+7", - _L("toggle custom light 7") - }, - { - "TRUCK_LIGHTTOGGLE8", - EV_TRUCK_LIGHTTOGGLE08, - "Keyboard EXPL+CTRL+8", - _L("toggle custom light 8") - }, - { - "TRUCK_LIGHTTOGGLE9", - EV_TRUCK_LIGHTTOGGLE09, - "Keyboard EXPL+CTRL+9", - _L("toggle custom light 9") - }, - { - "TRUCK_LIGHTTOGGLE10", - EV_TRUCK_LIGHTTOGGLE10, - "Keyboard EXPL+CTRL+0", - _L("toggle custom light 10") - }, - { - "TRUCK_MANUAL_CLUTCH", - EV_TRUCK_MANUAL_CLUTCH, - "Keyboard LSHIFT", - _L("manual clutch (for manual transmission)") - }, - { - "TRUCK_PARKING_BRAKE", - EV_TRUCK_PARKING_BRAKE, - "Keyboard P", - _L("toggle parking brake") - }, - { - "TRUCK_TRAILER_PARKING_BRAKE", - EV_TRUCK_TRAILER_PARKING_BRAKE, - "Keyboard EXPL+CTRL+P", - _L("toggle trailer parking brake") - }, - { - "TRUCK_ANTILOCK_BRAKE", - EV_TRUCK_ANTILOCK_BRAKE, - "Keyboard EXPL+SHIFT+B", - _L("toggle antilock brake") - }, - { - "TRUCK_TOGGLE_VIDEOCAMERA", - EV_TRUCK_TOGGLE_VIDEOCAMERA, - "Keyboard EXPL+CTRL+V", - _L("toggle videocamera") - }, - { - "TRUCK_TRACTION_CONTROL", - EV_TRUCK_TRACTION_CONTROL, - "Keyboard EXPL+SHIFT+T", - _L("toggle traction control") - }, - { - "TRUCK_CRUISE_CONTROL", - EV_TRUCK_CRUISE_CONTROL, - "Keyboard EXPL+SPACE", - _L("toggle cruise control") - }, - { - "TRUCK_CRUISE_CONTROL_READJUST", - EV_TRUCK_CRUISE_CONTROL_READJUST, - "Keyboard EXPL+CTRL+SPACE", - _L("match target speed / rpm with current truck speed / rpm") - }, - { - "TRUCK_CRUISE_CONTROL_ACCL", - EV_TRUCK_CRUISE_CONTROL_ACCL, - "Keyboard EXPL+CTRL+R", - _L("increase target speed / rpm") - }, - { - "TRUCK_CRUISE_CONTROL_DECL", - EV_TRUCK_CRUISE_CONTROL_DECL, - "Keyboard EXPL+CTRL+F", - _L("decrease target speed / rpm") - }, - { - "TRUCK_SHIFT_DOWN", - EV_TRUCK_SHIFT_DOWN, - "Keyboard Z", - _L("shift one gear down in manual transmission mode") - }, - { - "TRUCK_SHIFT_NEUTRAL", - EV_TRUCK_SHIFT_NEUTRAL, - "Keyboard D", - _L("shift to neutral gear in manual transmission mode") - }, - { - "TRUCK_SHIFT_UP", - EV_TRUCK_SHIFT_UP, - "Keyboard A", - _L("shift one gear up in manual transmission mode") - }, - { - "TRUCK_SHIFT_GEAR_REVERSE", - EV_TRUCK_SHIFT_GEAR_REVERSE, - "", - _L("shift directly to reverse gear") - }, - { - "TRUCK_SHIFT_GEAR1", - EV_TRUCK_SHIFT_GEAR01, - "", - _L("shift directly to first gear") - }, - { - "TRUCK_SHIFT_GEAR2", - EV_TRUCK_SHIFT_GEAR02, - "", - _L("shift directly to second gear") - }, - { - "TRUCK_SHIFT_GEAR3", - EV_TRUCK_SHIFT_GEAR03, - "", - _L("shift directly to third gear") - }, - { - "TRUCK_SHIFT_GEAR4", - EV_TRUCK_SHIFT_GEAR04, - "", - _L("shift directly to fourth gear") - }, - { - "TRUCK_SHIFT_GEAR5", - EV_TRUCK_SHIFT_GEAR05, - "", - _L("shift directly to 5th gear") - }, - { - "TRUCK_SHIFT_GEAR6", - EV_TRUCK_SHIFT_GEAR06, - "", - _L("shift directly to 6th gear") - }, - { - "TRUCK_SHIFT_GEAR7", - EV_TRUCK_SHIFT_GEAR07, - "", - _L("shift directly to 7th gear") - }, - { - "TRUCK_SHIFT_GEAR8", - EV_TRUCK_SHIFT_GEAR08, - "", - _L("shift directly to 8th gear") - }, - { - "TRUCK_SHIFT_GEAR9", - EV_TRUCK_SHIFT_GEAR09, - "", - _L("shift directly to 9th gear") - }, - { - "TRUCK_SHIFT_GEAR10", - EV_TRUCK_SHIFT_GEAR10, - "", - _L("shift directly to 10th gear") - }, - { - "TRUCK_SHIFT_GEAR11", - EV_TRUCK_SHIFT_GEAR11, - "", - _L("shift directly to 11th gear") - }, - { - "TRUCK_SHIFT_GEAR12", - EV_TRUCK_SHIFT_GEAR12, - "", - _L("shift directly to 12th gear") - }, - - { - "TRUCK_SHIFT_GEAR13", - EV_TRUCK_SHIFT_GEAR13, - "", - _L("shift directly to 13th gear") - }, - { - "TRUCK_SHIFT_GEAR14", - EV_TRUCK_SHIFT_GEAR14, - "", - _L("shift directly to 14th gear") - }, - { - "TRUCK_SHIFT_GEAR15", - EV_TRUCK_SHIFT_GEAR15, - "", - _L("shift directly to 15th gear") - }, - { - "TRUCK_SHIFT_GEAR16", - EV_TRUCK_SHIFT_GEAR16, - "", - _L("shift directly to 16th gear") - }, - { - "TRUCK_SHIFT_GEAR17", - EV_TRUCK_SHIFT_GEAR17, - "", - _L("shift directly to 17th gear") - }, - { - "TRUCK_SHIFT_GEAR18", - EV_TRUCK_SHIFT_GEAR18, - "", - _L("shift directly to 18th gear") - }, - { - "TRUCK_SHIFT_LOWRANGE", - EV_TRUCK_SHIFT_LOWRANGE, - "", - _L("sets low range (1-6) for H-shaft") - }, - { - "TRUCK_SHIFT_MIDRANGE", - EV_TRUCK_SHIFT_MIDRANGE, - "", - _L("sets middle range (7-12) for H-shaft") - }, - { - "TRUCK_SHIFT_HIGHRANGE", - EV_TRUCK_SHIFT_HIGHRANGE, - "", - _L("sets high range (13-18) for H-shaft") - }, - { - "TRUCK_STARTER", - EV_TRUCK_STARTER, - "Keyboard S", - _L("hold to start the engine") - }, - { - "TRUCK_STEER_LEFT", - EV_TRUCK_STEER_LEFT, - "Keyboard LEFT", - _L("steer left") - }, - { - "TRUCK_STEER_RIGHT", - EV_TRUCK_STEER_RIGHT, - "Keyboard RIGHT", - _L("steer right") - }, - { - "TRUCK_SWITCH_SHIFT_MODES", - EV_TRUCK_SWITCH_SHIFT_MODES, - "Keyboard Q", - _L("toggle between transmission modes") - }, - { - "TRUCK_TOGGLE_INTER_AXLE_DIFF", - EV_TRUCK_TOGGLE_INTER_AXLE_DIFF, - "Keyboard EXPL+ALT+W", - _L("cycle between available inter axle differential modes") - }, - { - "TRUCK_TOGGLE_INTER_WHEEL_DIFF", - EV_TRUCK_TOGGLE_INTER_WHEEL_DIFF, - "Keyboard EXPL+W", - _L("cycle between available inter wheel differential modes") - }, - { - "TRUCK_TOGGLE_PHYSICS", - EV_TRUCK_TOGGLE_PHYSICS, - "Keyboard END", - _L("toggle physics") - }, - { - "TRUCK_TOGGLE_TCASE_4WD_MODE", - EV_TRUCK_TOGGLE_TCASE_4WD_MODE, - "Keyboard EXPL+CTRL+W", - _L("toggle transfer case mode") - }, - { - "TRUCK_TOGGLE_TCASE_GEAR_RATIO", - EV_TRUCK_TOGGLE_TCASE_GEAR_RATIO, - "Keyboard EXPL+SHIFT+W", - _L("toggle transfer case gear ratio") - }, - { - "TRUCK_TOGGLE_CONTACT", - EV_TRUCK_TOGGLE_CONTACT, - "Keyboard X", - _L("toggle ignition") - }, - { - "TRUCK_TOGGLE_FORWARDCOMMANDS", - EV_TRUCK_TOGGLE_FORWARDCOMMANDS, - "Keyboard EXPL+CTRL+SHIFT+F", - _L("toggle forwardcommands") - }, - { - "TRUCK_TOGGLE_IMPORTCOMMANDS", - EV_TRUCK_TOGGLE_IMPORTCOMMANDS, - "Keyboard EXPL+CTRL+SHIFT+I", - _L("toggle importcommands") - }, + {"AIRPLANE_STEER_RIGHT", EV_AIRPLANE_STEER_RIGHT, "Keyboard RIGHT", _L("steer right")}, + {"AIRPLANE_BRAKE", EV_AIRPLANE_BRAKE, "Keyboard B", _L("normal brake for an aircraft")}, + {"AIRPLANE_ELEVATOR_DOWN", EV_AIRPLANE_ELEVATOR_DOWN, "Keyboard DOWN", _L("pull the elevator down in an aircraft.")}, + {"AIRPLANE_ELEVATOR_UP", EV_AIRPLANE_ELEVATOR_UP, "Keyboard UP", _L("pull the elevator up in an aircraft.")}, + {"AIRPLANE_FLAPS_FULL", EV_AIRPLANE_FLAPS_FULL, "Keyboard CTRL+2", _L("full flaps in an aircraft.")}, + {"AIRPLANE_FLAPS_LESS", EV_AIRPLANE_FLAPS_LESS, "Keyboard EXPL+1", _L("one step less flaps.")}, + {"AIRPLANE_FLAPS_MORE", EV_AIRPLANE_FLAPS_MORE, "Keyboard EXPL+2", _L("one step more flaps.")}, + {"AIRPLANE_FLAPS_NONE", EV_AIRPLANE_FLAPS_NONE, "Keyboard CTRL+1", _L("no flaps.")}, + {"AIRPLANE_PARKING_BRAKE", EV_AIRPLANE_PARKING_BRAKE, "Keyboard P", _L("airplane parking brake.") + + }, + {"AIRPLANE_REVERSE", EV_AIRPLANE_REVERSE, "Keyboard R", _L("reverse the turboprops")}, + {"AIRPLANE_RUDDER_LEFT", EV_AIRPLANE_RUDDER_LEFT, "Keyboard Z", _L("rudder left")}, + {"AIRPLANE_RUDDER_RIGHT", EV_AIRPLANE_RUDDER_RIGHT, "Keyboard X", _L("rudder right")}, + {"AIRPLANE_STEER_LEFT", EV_AIRPLANE_STEER_LEFT, "Keyboard LEFT", _L("steer left")}, + {"AIRPLANE_STEER_RIGHT", EV_AIRPLANE_STEER_RIGHT, "Keyboard RIGHT", _L("steer right")}, + {"AIRPLANE_THROTTLE_AXIS", EV_AIRPLANE_THROTTLE_AXIS, "None", + _L("throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)")}, + {"AIRPLANE_THROTTLE_DOWN", EV_AIRPLANE_THROTTLE_DOWN, "Keyboard EXPL+PGDOWN", _L("decreases the airplane thrust")}, + {"AIRPLANE_THROTTLE_FULL", EV_AIRPLANE_THROTTLE_FULL, "Keyboard CTRL+PGUP", _L("full thrust")}, + {"AIRPLANE_THROTTLE_NO", EV_AIRPLANE_THROTTLE_NO, "Keyboard CTRL+PGDOWN", _L("no thrust")}, + {"AIRPLANE_THROTTLE_UP", EV_AIRPLANE_THROTTLE_UP, "Keyboard EXPL+PGUP", _L("increase the airplane thrust")}, + {"AIRPLANE_TOGGLE_ENGINES", EV_AIRPLANE_TOGGLE_ENGINES, "Keyboard CTRL+HOME", _L("switch all engines on / off")}, + {"BOAT_CENTER_RUDDER", EV_BOAT_CENTER_RUDDER, "Keyboard PGDOWN", _L("center the rudder")}, + {"BOAT_REVERSE", EV_BOAT_REVERSE, "Keyboard PGUP", _L("no thrust")}, + {"BOAT_STEER_LEFT", EV_BOAT_STEER_LEFT, "Keyboard LEFT", _L("steer left a step")}, + {"BOAT_STEER_LEFT_AXIS", EV_BOAT_STEER_LEFT_AXIS, "None", _L("steer left (analog value!)")}, + {"BOAT_STEER_RIGHT", EV_BOAT_STEER_RIGHT, "Keyboard RIGHT", _L("steer right a step")}, + {"BOAT_STEER_RIGHT_AXIS", EV_BOAT_STEER_RIGHT_AXIS, "None", _L("steer right (analog value!)")}, + {"BOAT_THROTTLE_AXIS", EV_BOAT_THROTTLE_AXIS, "None", + _L("throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)")}, + {"BOAT_THROTTLE_DOWN", EV_BOAT_THROTTLE_DOWN, "Keyboard DOWN", _L("decrease throttle")}, + {"BOAT_THROTTLE_UP", EV_BOAT_THROTTLE_UP, "Keyboard UP", _L("increase throttle")}, + {"SKY_DECREASE_TIME", EV_SKY_DECREASE_TIME, "Keyboard EXPL+SUBTRACT", _L("decrease day-time")}, + {"SKY_DECREASE_TIME_FAST", EV_SKY_DECREASE_TIME_FAST, "Keyboard SHIFT+SUBTRACT", _L("decrease day-time a lot faster")}, + {"SKY_INCREASE_TIME", EV_SKY_INCREASE_TIME, "Keyboard EXPL+ADD", _L("increase day-time")}, + {"SKY_INCREASE_TIME_FAST", EV_SKY_INCREASE_TIME_FAST, "Keyboard SHIFT+ADD", _L("increase day-time a lot faster")}, + {"CAMERA_CHANGE", EV_CAMERA_CHANGE, "Keyboard EXPL+C", _L("change camera mode")}, + {"CAMERA_LOOKBACK", EV_CAMERA_LOOKBACK, "Keyboard NUMPAD1", _L("look back (toggles between normal and lookback)")}, + {"CAMERA_RESET", EV_CAMERA_RESET, "Keyboard NUMPAD5", _L("reset the camera position")}, + {"CAMERA_ROTATE_DOWN", EV_CAMERA_ROTATE_DOWN, "Keyboard NUMPAD2", _L("rotate camera down")}, + {"CAMERA_ROTATE_LEFT", EV_CAMERA_ROTATE_LEFT, "Keyboard NUMPAD4", _L("rotate camera left")}, + {"CAMERA_ROTATE_RIGHT", EV_CAMERA_ROTATE_RIGHT, "Keyboard NUMPAD6", _L("rotate camera right")}, + {"CAMERA_ROTATE_UP", EV_CAMERA_ROTATE_UP, "Keyboard NUMPAD8", _L("rotate camera up")}, + {"CAMERA_ZOOM_IN", EV_CAMERA_ZOOM_IN, "Keyboard EXPL+NUMPAD9", _L("zoom camera in")}, + {"CAMERA_ZOOM_IN_FAST", EV_CAMERA_ZOOM_IN_FAST, "Keyboard SHIFT+NUMPAD9", _L("zoom camera in faster")}, + {"CAMERA_ZOOM_OUT", EV_CAMERA_ZOOM_OUT, "Keyboard EXPL+NUMPAD3", _L("zoom camera out")}, + {"CAMERA_ZOOM_OUT_FAST", EV_CAMERA_ZOOM_OUT_FAST, "Keyboard SHIFT+NUMPAD3", _L("zoom camera out faster")}, + {"CHARACTER_BACKWARDS", EV_CHARACTER_BACKWARDS, "Keyboard S", _L("step backwards with the character")}, + {"CHARACTER_FORWARD", EV_CHARACTER_FORWARD, "Keyboard W", _L("step forward with the character")}, + {"CHARACTER_JUMP", EV_CHARACTER_JUMP, "Keyboard SPACE", _L("let the character jump")}, + {"CHARACTER_LEFT", EV_CHARACTER_LEFT, "Keyboard LEFT", _L("rotate character left")}, + {"CHARACTER_RIGHT", EV_CHARACTER_RIGHT, "Keyboard RIGHT", _L("rotate character right")}, + {"CHARACTER_RUN", EV_CHARACTER_RUN, "Keyboard SHIFT+W", _L("let the character run")}, + {"CHARACTER_SIDESTEP_LEFT", EV_CHARACTER_SIDESTEP_LEFT, "Keyboard A", _L("sidestep to the left")}, + {"CHARACTER_SIDESTEP_RIGHT", EV_CHARACTER_SIDESTEP_RIGHT, "Keyboard D", _L("sidestep to the right")}, + {"COMMANDS_01", EV_COMMANDS_01, "Keyboard EXPL+F1", _L("Command 1")}, + {"COMMANDS_02", EV_COMMANDS_02, "Keyboard EXPL+F2", _L("Command 2")}, + {"COMMANDS_03", EV_COMMANDS_03, "Keyboard EXPL+F3", _L("Command 3")}, + {"COMMANDS_04", EV_COMMANDS_04, "Keyboard EXPL+F4", _L("Command 4")}, + {"COMMANDS_05", EV_COMMANDS_05, "Keyboard EXPL+F5", _L("Command 5")}, + {"COMMANDS_06", EV_COMMANDS_06, "Keyboard EXPL+F6", _L("Command 6")}, + {"COMMANDS_07", EV_COMMANDS_07, "Keyboard EXPL+F7", _L("Command 7")}, + {"COMMANDS_08", EV_COMMANDS_08, "Keyboard EXPL+F8", _L("Command 8")}, + {"COMMANDS_09", EV_COMMANDS_09, "Keyboard EXPL+F9", _L("Command 9")}, + {"COMMANDS_10", EV_COMMANDS_10, "Keyboard EXPL+F10", _L("Command 10")}, + {"COMMANDS_11", EV_COMMANDS_11, "Keyboard EXPL+F11", _L("Command 11")}, + {"COMMANDS_12", EV_COMMANDS_12, "Keyboard EXPL+F12", _L("Command 12")}, + {"COMMANDS_13", EV_COMMANDS_13, "Keyboard EXPL+CTRL+F1", _L("Command 13")}, + {"COMMANDS_14", EV_COMMANDS_14, "Keyboard EXPL+CTRL+F2", _L("Command 14")}, + {"COMMANDS_15", EV_COMMANDS_15, "Keyboard EXPL+CTRL+F3", _L("Command 15")}, + {"COMMANDS_16", EV_COMMANDS_16, "Keyboard EXPL+CTRL+F4", _L("Command 16")}, + {"COMMANDS_17", EV_COMMANDS_17, "Keyboard EXPL+CTRL+F5", _L("Command 17")}, + {"COMMANDS_18", EV_COMMANDS_18, "Keyboard EXPL+CTRL+F6", _L("Command 18")}, + {"COMMANDS_19", EV_COMMANDS_19, "Keyboard EXPL+CTRL+F7", _L("Command 19")}, + {"COMMANDS_20", EV_COMMANDS_20, "Keyboard EXPL+CTRL+F8", _L("Command 20")}, + {"COMMANDS_21", EV_COMMANDS_21, "Keyboard EXPL+CTRL+F9", _L("Command 21")}, + {"COMMANDS_22", EV_COMMANDS_22, "Keyboard EXPL+CTRL+F10", _L("Command 22")}, + {"COMMANDS_23", EV_COMMANDS_23, "Keyboard EXPL+CTRL+F11", _L("Command 23")}, + {"COMMANDS_24", EV_COMMANDS_24, "Keyboard EXPL+CTRL+F12", _L("Command 24")}, + {"COMMANDS_25", EV_COMMANDS_25, "Keyboard EXPL+SHIFT+F1", _L("Command 25")}, + {"COMMANDS_26", EV_COMMANDS_26, "Keyboard EXPL+SHIFT+F2", _L("Command 26")}, + {"COMMANDS_27", EV_COMMANDS_27, "Keyboard EXPL+SHIFT+F3", _L("Command 27")}, + {"COMMANDS_28", EV_COMMANDS_28, "Keyboard EXPL+SHIFT+F4", _L("Command 28")}, + {"COMMANDS_29", EV_COMMANDS_29, "Keyboard EXPL+SHIFT+F5", _L("Command 29")}, + {"COMMANDS_30", EV_COMMANDS_30, "Keyboard EXPL+SHIFT+F6", _L("Command 30")}, + {"COMMANDS_31", EV_COMMANDS_31, "Keyboard EXPL+SHIFT+F7", _L("Command 31")}, + {"COMMANDS_32", EV_COMMANDS_32, "Keyboard EXPL+SHIFT+F8", _L("Command 32")}, + {"COMMANDS_33", EV_COMMANDS_33, "Keyboard EXPL+SHIFT+F9", _L("Command 33")}, + {"COMMANDS_34", EV_COMMANDS_34, "Keyboard EXPL+SHIFT+F10", _L("Command 34")}, + {"COMMANDS_35", EV_COMMANDS_35, "Keyboard EXPL+SHIFT+F11", _L("Command 35")}, + {"COMMANDS_36", EV_COMMANDS_36, "Keyboard EXPL+SHIFT+F12", _L("Command 36")}, + {"COMMANDS_37", EV_COMMANDS_37, "Keyboard EXPL+ALT+F1", _L("Command 37")}, + {"COMMANDS_38", EV_COMMANDS_38, "Keyboard EXPL+ALT+F2", _L("Command 38")}, + {"COMMANDS_39", EV_COMMANDS_39, "Keyboard EXPL+ALT+F3", _L("Command 39")}, + {"COMMANDS_40", EV_COMMANDS_40, "Keyboard EXPL+ALT+F4", _L("Command 40")}, + {"COMMANDS_41", EV_COMMANDS_41, "Keyboard EXPL+ALT+F5", _L("Command 41")}, + {"COMMANDS_42", EV_COMMANDS_42, "Keyboard EXPL+ALT+F6", _L("Command 42")}, + {"COMMANDS_43", EV_COMMANDS_43, "Keyboard EXPL+ALT+F7", _L("Command 43")}, + {"COMMANDS_44", EV_COMMANDS_44, "Keyboard EXPL+ALT+F8", _L("Command 44")}, + {"COMMANDS_45", EV_COMMANDS_45, "Keyboard EXPL+ALT+F9", _L("Command 45")}, + {"COMMANDS_46", EV_COMMANDS_46, "Keyboard EXPL+ALT+F10", _L("Command 46")}, + {"COMMANDS_47", EV_COMMANDS_47, "Keyboard EXPL+ALT+F11", _L("Command 47")}, + {"COMMANDS_48", EV_COMMANDS_48, "Keyboard EXPL+ALT+F12", _L("Command 48")}, + {"COMMANDS_49", EV_COMMANDS_49, "Keyboard EXPL+CTRL+SHIFT+F1", _L("Command 49")}, + {"COMMANDS_50", EV_COMMANDS_50, "Keyboard EXPL+CTRL+SHIFT+F2", _L("Command 50")}, + {"COMMANDS_51", EV_COMMANDS_51, "Keyboard EXPL+CTRL+SHIFT+F3", _L("Command 51")}, + {"COMMANDS_52", EV_COMMANDS_52, "Keyboard EXPL+CTRL+SHIFT+F4", _L("Command 52")}, + {"COMMANDS_53", EV_COMMANDS_53, "Keyboard EXPL+CTRL+SHIFT+F5", _L("Command 53")}, + {"COMMANDS_54", EV_COMMANDS_54, "Keyboard EXPL+CTRL+SHIFT+F6", _L("Command 54")}, + {"COMMANDS_55", EV_COMMANDS_55, "Keyboard EXPL+CTRL+SHIFT+F7", _L("Command 55")}, + {"COMMANDS_56", EV_COMMANDS_56, "Keyboard EXPL+CTRL+SHIFT+F8", _L("Command 56")}, + {"COMMANDS_57", EV_COMMANDS_57, "Keyboard EXPL+CTRL+SHIFT+F9", _L("Command 57")}, + {"COMMANDS_58", EV_COMMANDS_58, "Keyboard EXPL+CTRL+SHIFT+F10", _L("Command 58")}, + {"COMMANDS_59", EV_COMMANDS_59, "Keyboard EXPL+CTRL+SHIFT+F11", _L("Command 59")}, + {"COMMANDS_60", EV_COMMANDS_60, "Keyboard EXPL+CTRL+SHIFT+F12", _L("Command 60")}, + {"COMMANDS_61", EV_COMMANDS_61, "Keyboard EXPL+CTRL+ALT+F1", _L("Command 61")}, + {"COMMANDS_62", EV_COMMANDS_62, "Keyboard EXPL+CTRL+ALT+F2", _L("Command 62")}, + {"COMMANDS_63", EV_COMMANDS_63, "Keyboard EXPL+CTRL+ALT+F3", _L("Command 63")}, + {"COMMANDS_64", EV_COMMANDS_64, "Keyboard EXPL+CTRL+ALT+F4", _L("Command 64")}, + {"COMMANDS_65", EV_COMMANDS_65, "Keyboard EXPL+CTRL+ALT+F5", _L("Command 65")}, + {"COMMANDS_66", EV_COMMANDS_66, "Keyboard EXPL+CTRL+ALT+F6", _L("Command 66")}, + {"COMMANDS_67", EV_COMMANDS_67, "Keyboard EXPL+CTRL+ALT+F7", _L("Command 67")}, + {"COMMANDS_68", EV_COMMANDS_68, "Keyboard EXPL+CTRL+ALT+F8", _L("Command 68")}, + {"COMMANDS_69", EV_COMMANDS_69, "Keyboard EXPL+CTRL+ALT+F9", _L("Command 69")}, + {"COMMANDS_70", EV_COMMANDS_70, "Keyboard EXPL+CTRL+ALT+F10", _L("Command 70")}, + {"COMMANDS_71", EV_COMMANDS_71, "Keyboard EXPL+CTRL+ALT+F11", _L("Command 71")}, + {"COMMANDS_72", EV_COMMANDS_72, "Keyboard EXPL+CTRL+ALT+F12", _L("Command 72")}, + {"COMMANDS_73", EV_COMMANDS_73, "Keyboard EXPL+CTRL+SHIFT+ALT+F1", _L("Command 73")}, + {"COMMANDS_74", EV_COMMANDS_74, "Keyboard EXPL+CTRL+SHIFT+ALT+F2", _L("Command 74")}, + {"COMMANDS_75", EV_COMMANDS_75, "Keyboard EXPL+CTRL+SHIFT+ALT+F3", _L("Command 75")}, + {"COMMANDS_76", EV_COMMANDS_76, "Keyboard EXPL+CTRL+SHIFT+ALT+F4", _L("Command 76")}, + {"COMMANDS_77", EV_COMMANDS_77, "Keyboard EXPL+CTRL+SHIFT+ALT+F5", _L("Command 77")}, + {"COMMANDS_78", EV_COMMANDS_78, "Keyboard EXPL+CTRL+SHIFT+ALT+F6", _L("Command 78")}, + {"COMMANDS_79", EV_COMMANDS_79, "Keyboard EXPL+CTRL+SHIFT+ALT+F7", _L("Command 79")}, + {"COMMANDS_80", EV_COMMANDS_80, "Keyboard EXPL+CTRL+SHIFT+ALT+F8", _L("Command 80")}, + {"COMMANDS_81", EV_COMMANDS_81, "Keyboard EXPL+CTRL+SHIFT+ALT+F9", _L("Command 81")}, + {"COMMANDS_82", EV_COMMANDS_82, "Keyboard EXPL+CTRL+SHIFT+ALT+F10", _L("Command 82")}, + {"COMMANDS_83", EV_COMMANDS_83, "Keyboard EXPL+CTRL+SHIFT+ALT+F11", _L("Command 83")}, + {"COMMANDS_84", EV_COMMANDS_84, "Keyboard EXPL+CTRL+SHIFT+ALT+F12", _L("Command 84")}, + {"COMMON_ACCELERATE_SIMULATION", EV_COMMON_ACCELERATE_SIMULATION, "Keyboard CTRL+EQUALS", _L("accelerate the simulation")}, + {"COMMON_DECELERATE_SIMULATION", EV_COMMON_DECELERATE_SIMULATION, "Keyboard SHIFT+EQUALS", _L("decelerate the simulation")}, + {"COMMON_RESET_SIMULATION_PACE", EV_COMMON_RESET_SIMULATION_PACE, "Keyboard BACKSLASH", _L("reset the simulation pace")}, + {"COMMON_CONSOLE_TOGGLE", EV_COMMON_CONSOLE_TOGGLE, "Keyboard EXPL+GRAVE", _L("show / hide the console")}, + {"COMMON_ENTER_CHATMODE", EV_COMMON_ENTER_CHATMODE, "Keyboard Y", _L("enter the chat")}, + {"COMMON_SEND_CHAT", EV_COMMON_SEND_CHAT, "Keyboard RETURN", _L("sends the entered text")}, + {"COMMON_ENTER_OR_EXIT_TRUCK", EV_COMMON_ENTER_OR_EXIT_TRUCK, "Keyboard RETURN", _L("enter or exit a truck")}, + {"COMMON_ENTER_NEXT_TRUCK", EV_COMMON_ENTER_NEXT_TRUCK, "Keyboard EXPL+CTRL+RBRACKET", _L("enter next truck")}, + {"COMMON_ENTER_PREVIOUS_TRUCK", EV_COMMON_ENTER_PREVIOUS_TRUCK, "Keyboard EXPL+CTRL+LBRACKET", _L("enter previous truck")}, + {"COMMON_REMOVE_CURRENT_TRUCK", EV_COMMON_REMOVE_CURRENT_TRUCK, "Keyboard EXPL+CTRL+DELETE", _L("remove current truck")}, + {"COMMON_RESPAWN_LAST_TRUCK", EV_COMMON_RESPAWN_LAST_TRUCK, "Keyboard EXPL+CTRL+PERIOD", _L("respawn last truck")}, + {"COMMON_HIDE_GUI", EV_COMMON_HIDE_GUI, "Keyboard EXPL+U", _L("hide all GUI elements")}, + {"COMMON_TOGGLE_DASHBOARD", EV_COMMON_TOGGLE_DASHBOARD, "Keyboard EXPL+CTRL+U", _L("display or hide the dashboard overlay")}, + {"COMMON_LOCK", EV_COMMON_LOCK, "Keyboard EXPL+L", _L("connect hook node to a node in close proximity")}, + {"COMMON_AUTOLOCK", EV_COMMON_AUTOLOCK, "Keyboard EXPL+ALT+L", _L("unlock autolock hook node")}, + {"COMMON_ROPELOCK", EV_COMMON_ROPELOCK, "Keyboard EXPL+CTRL+L", _L("connect a rope to a node in close proximity")}, + {"COMMON_OUTPUT_POSITION", EV_COMMON_OUTPUT_POSITION, "Keyboard H", + _L("write current position to log (you can open the logfile and reuse the position)")}, + {"COMMON_GET_NEW_VEHICLE", EV_COMMON_GET_NEW_VEHICLE, "Keyboard EXPL+CTRL+G", _L("get new vehicle")}, + {"COMMON_PRESSURE_LESS", EV_COMMON_PRESSURE_LESS, "Keyboard LBRACKET", + _L("decrease tire pressure (note: only very few trucks support this)")}, + {"COMMON_PRESSURE_MORE", EV_COMMON_PRESSURE_MORE, "Keyboard RBRACKET", + _L("increase tire pressure (note: only very few trucks support this)")}, + {"COMMON_QUIT_GAME", EV_COMMON_QUIT_GAME, "Keyboard EXPL+ESCAPE", _L("exit the game")}, + {"COMMON_QUICKLOAD", EV_COMMON_QUICKLOAD, "Keyboard MULTIPLY", _L("quickload scene")}, + {"COMMON_QUICKSAVE", EV_COMMON_QUICKSAVE, "Keyboard DIVIDE", _L("quicksave scene")}, + {"COMMON_REPAIR_TRUCK", EV_COMMON_REPAIR_TRUCK, "Keyboard BACK", _L("repair truck")}, + {"COMMON_RESCUE_TRUCK", EV_COMMON_RESCUE_TRUCK, "Keyboard EXPL+R", _L("teleport to rescue truck")}, + {"COMMON_RESET_TRUCK", EV_COMMON_RESET_TRUCK, "Keyboard I", _L("reset truck to original starting position")}, + {"COMMON_TOGGLE_RESET_MODE", EV_COMMON_TOGGLE_RESET_MODE, "Keyboard EXPL+APOSTROPHE", _L("toggle reset mode")}, + {"COMMON_SCREENSHOT", EV_COMMON_SCREENSHOT, "Keyboard EXPL+SYSRQ", _L("take a screenshot")}, + {"COMMON_SCREENSHOT_BIG", EV_COMMON_SCREENSHOT_BIG, "Keyboard EXPL+CTRL+SYSRQ", + _L("take a big screenshot (3 times the screen size)")}, + {"COMMON_SAVE_TERRAIN", EV_COMMON_SAVE_TERRAIN, "Keyboard EXPL+ALT+SHIF+CTRL+M", + _L("save the currently loaded terrain to a mesh file")}, + {"COMMON_SECURE_LOAD", EV_COMMON_SECURE_LOAD, "Keyboard O", _L("tie a load to the truck")}, + {"COMMON_TOGGLE_DEBUG_VIEW", EV_COMMON_TOGGLE_DEBUG_VIEW, "Keyboard EXPL+K", _L("toggle debug view")}, + {"COMMON_CYCLE_DEBUG_VIEWS", EV_COMMON_CYCLE_DEBUG_VIEWS, "Keyboard EXPL+CTRL+K", _L("cycle debug views")}, + {"COMMON_TOGGLE_TERRAIN_EDITOR", EV_COMMON_TOGGLE_TERRAIN_EDITOR, "Keyboard EXPL+SHIFT+Y", _L("toggle terrain editor")}, + {"COMMON_TOGGLE_CUSTOM_PARTICLES", EV_COMMON_TOGGLE_CUSTOM_PARTICLES, "Keyboard G", _L("toggle particle cannon")}, + {"COMMON_TOGGLE_MAT_DEBUG", EV_COMMON_TOGGLE_MAT_DEBUG, "", _L("debug purpose - dont use")}, + {"COMMON_TOGGLE_RENDER_MODE", EV_COMMON_TOGGLE_RENDER_MODE, "Keyboard E", + _L("toggle render mode (solid, wireframe and points)")}, + {"COMMON_TOGGLE_REPLAY_MODE", EV_COMMON_TOGGLE_REPLAY_MODE, "Keyboard EXPL+CTRL+J", _L("enable or disable replay mode")}, + {"COMMON_TOGGLE_PHYSICS", EV_COMMON_TOGGLE_PHYSICS, "Keyboard EXPL+J", _L("enable or disable physics")}, + {"COMMON_TOGGLE_STATS", EV_COMMON_TOGGLE_STATS, "Keyboard EXPL+F", _L("toggle Ogre statistics (FPS etc.)")}, + {"COMMON_TOGGLE_TRUCK_BEACONS", EV_COMMON_TOGGLE_TRUCK_BEACONS, "Keyboard M", _L("toggle truck beacons")}, + {"COMMON_TOGGLE_TRUCK_LIGHTS", EV_COMMON_TOGGLE_TRUCK_LIGHTS, "Keyboard N", _L("toggle truck front lights")}, + {"COMMON_TRUCK_INFO", EV_COMMON_TRUCK_INFO, "Keyboard EXPL+T", _L("toggle truck HUD")}, + {"COMMON_TRUCK_DESCRIPTION", EV_COMMON_TRUCK_DESCRIPTION, "Keyboard EXPL+CTRL+T", _L("toggle truck description")}, + {"COMMON_FOV_LESS", EV_COMMON_FOV_LESS, "Keyboard EXPL+NUMPAD7", _L("decreases the current FOV value")}, + {"COMMON_FOV_MORE", EV_COMMON_FOV_MORE, "Keyboard EXPL+CTRL+NUMPAD7", _L("increase the current FOV value")}, + {"COMMON_FOV_RESET", EV_COMMON_FOV_RESET, "Keyboard EXPL+SHIFT+NUMPAD7", _L("reset the FOV value")}, + {"GRASS_LESS", EV_GRASS_LESS, "", _L("EXPERIMENTAL: remove some grass")}, + {"GRASS_MORE", EV_GRASS_MORE, "", _L("EXPERIMENTAL: add some grass")}, + {"GRASS_MOST", EV_GRASS_MOST, "", _L("EXPERIMENTAL: set maximum amount of grass")}, + {"GRASS_NONE", EV_GRASS_NONE, "", _L("EXPERIMENTAL: remove grass completely")}, + {"GRASS_SAVE", EV_GRASS_SAVE, "", _L("EXPERIMENTAL: save changes to the grass density image")}, + {"MENU_DOWN", EV_MENU_DOWN, "Keyboard DOWN", _L("select next element in current category")}, + {"MENU_LEFT", EV_MENU_LEFT, "Keyboard LEFT", _L("select previous category")}, + {"MENU_RIGHT", EV_MENU_RIGHT, "Keyboard RIGHT", _L("select next category")}, + {"MENU_SELECT", EV_MENU_SELECT, "Keyboard EXPL+RETURN", _L("select focussed item and close menu")}, + {"MENU_UP", EV_MENU_UP, "Keyboard UP", _L("select previous element in current category")}, + {"SURVEY_MAP_TOGGLE_ICONS", EV_SURVEY_MAP_TOGGLE_ICONS, "Keyboard EXPL+CTRL+SHIFT+ALT+TAB", _L("toggle map icons")}, + {"SURVEY_MAP_TOGGLE", EV_SURVEY_MAP_TOGGLE, "Keyboard EXPL+CTRL+SHIFT+TAB", _L("toggle map")}, + {"SURVEY_MAP_CYCLE", EV_SURVEY_MAP_CYCLE, "Keyboard EXPL+TAB", _L("cycle map modes")}, + {"SURVEY_MAP_ZOOM_IN", EV_SURVEY_MAP_ZOOM_IN, "Keyboard EXPL+CTRL+TAB", _L("zoom in")}, + {"SURVEY_MAP_ZOOM_OUT", EV_SURVEY_MAP_ZOOM_OUT, "Keyboard EXPL+SHIFT+TAB", _L("zoom out")}, + {"TRUCK_ACCELERATE", EV_TRUCK_ACCELERATE, "Keyboard UP", _L("accelerate the truck")}, + {"TRUCK_ACCELERATE_MODIFIER_25", EV_TRUCK_ACCELERATE_MODIFIER_25, "Keyboard ALT+UP", + _L("accelerate with 25 percent pedal input")}, + {"TRUCK_ACCELERATE_MODIFIER_50", EV_TRUCK_ACCELERATE_MODIFIER_50, "Keyboard CTRL+UP", + _L("accelerate with 50 percent pedal input")}, + {"TRUCK_AUTOSHIFT_DOWN", EV_TRUCK_AUTOSHIFT_DOWN, "Keyboard PGDOWN", _L("shift automatic transmission one gear down")}, + {"TRUCK_AUTOSHIFT_UP", EV_TRUCK_AUTOSHIFT_UP, "Keyboard PGUP", _L("shift automatic transmission one gear up")}, + {"TRUCK_BLINK_LEFT", EV_TRUCK_BLINK_LEFT, "Keyboard COMMA", _L("toggle left direction indicator (blinker)")}, + {"TRUCK_BLINK_RIGHT", EV_TRUCK_BLINK_RIGHT, "Keyboard PERIOD", _L("toggle right direction indicator (blinker)")}, + {"TRUCK_BLINK_WARN", EV_TRUCK_BLINK_WARN, "Keyboard MINUS", _L("toggle all direction indicators")}, + {"TRUCK_BRAKE", EV_TRUCK_BRAKE, "Keyboard DOWN", _L("brake")}, + {"TRUCK_BRAKE_MODIFIER_25", EV_TRUCK_BRAKE_MODIFIER_25, "Keyboard ALT+DOWN", _L("brake with 25 percent pedal input")}, + {"TRUCK_BRAKE_MODIFIER_50", EV_TRUCK_BRAKE_MODIFIER_50, "Keyboard CTRL+DOWN", _L("brake with 50 percent pedal input")}, + {"TRUCK_HORN", EV_TRUCK_HORN, "Keyboard H", _L("truck horn")}, + {"TRUCK_LIGHTTOGGLE1", EV_TRUCK_LIGHTTOGGLE01, "Keyboard EXPL+CTRL+1", _L("toggle custom light 1")}, + {"TRUCK_LIGHTTOGGLE2", EV_TRUCK_LIGHTTOGGLE02, "Keyboard EXPL+CTRL+2", _L("toggle custom light 2")}, + {"TRUCK_LIGHTTOGGLE3", EV_TRUCK_LIGHTTOGGLE03, "Keyboard EXPL+CTRL+3", _L("toggle custom light 3")}, + {"TRUCK_LIGHTTOGGLE4", EV_TRUCK_LIGHTTOGGLE04, "Keyboard EXPL+CTRL+4", _L("toggle custom light 4")}, + {"TRUCK_LIGHTTOGGLE5", EV_TRUCK_LIGHTTOGGLE05, "Keyboard EXPL+CTRL+5", _L("toggle custom light 5")}, + {"TRUCK_LIGHTTOGGLE6", EV_TRUCK_LIGHTTOGGLE06, "Keyboard EXPL+CTRL+6", _L("toggle custom light 6")}, + {"TRUCK_LIGHTTOGGLE7", EV_TRUCK_LIGHTTOGGLE07, "Keyboard EXPL+CTRL+7", _L("toggle custom light 7")}, + {"TRUCK_LIGHTTOGGLE8", EV_TRUCK_LIGHTTOGGLE08, "Keyboard EXPL+CTRL+8", _L("toggle custom light 8")}, + {"TRUCK_LIGHTTOGGLE9", EV_TRUCK_LIGHTTOGGLE09, "Keyboard EXPL+CTRL+9", _L("toggle custom light 9")}, + {"TRUCK_LIGHTTOGGLE10", EV_TRUCK_LIGHTTOGGLE10, "Keyboard EXPL+CTRL+0", _L("toggle custom light 10")}, + {"TRUCK_MANUAL_CLUTCH", EV_TRUCK_MANUAL_CLUTCH, "Keyboard LSHIFT", _L("manual clutch (for manual transmission)")}, + {"TRUCK_PARKING_BRAKE", EV_TRUCK_PARKING_BRAKE, "Keyboard P", _L("toggle parking brake")}, + {"TRUCK_TRAILER_PARKING_BRAKE", EV_TRUCK_TRAILER_PARKING_BRAKE, "Keyboard EXPL+CTRL+P", _L("toggle trailer parking brake")}, + {"TRUCK_ANTILOCK_BRAKE", EV_TRUCK_ANTILOCK_BRAKE, "Keyboard EXPL+SHIFT+B", _L("toggle antilock brake")}, + {"TRUCK_TOGGLE_VIDEOCAMERA", EV_TRUCK_TOGGLE_VIDEOCAMERA, "Keyboard EXPL+CTRL+V", _L("toggle videocamera")}, + {"TRUCK_TRACTION_CONTROL", EV_TRUCK_TRACTION_CONTROL, "Keyboard EXPL+SHIFT+T", _L("toggle traction control")}, + {"TRUCK_CRUISE_CONTROL", EV_TRUCK_CRUISE_CONTROL, "Keyboard EXPL+SPACE", _L("toggle cruise control")}, + {"TRUCK_CRUISE_CONTROL_READJUST", EV_TRUCK_CRUISE_CONTROL_READJUST, "Keyboard EXPL+CTRL+SPACE", + _L("match target speed / rpm with current truck speed / rpm")}, + {"TRUCK_CRUISE_CONTROL_ACCL", EV_TRUCK_CRUISE_CONTROL_ACCL, "Keyboard EXPL+CTRL+R", _L("increase target speed / rpm")}, + {"TRUCK_CRUISE_CONTROL_DECL", EV_TRUCK_CRUISE_CONTROL_DECL, "Keyboard EXPL+CTRL+F", _L("decrease target speed / rpm")}, + {"TRUCK_SHIFT_DOWN", EV_TRUCK_SHIFT_DOWN, "Keyboard Z", _L("shift one gear down in manual transmission mode")}, + {"TRUCK_SHIFT_NEUTRAL", EV_TRUCK_SHIFT_NEUTRAL, "Keyboard D", _L("shift to neutral gear in manual transmission mode")}, + {"TRUCK_SHIFT_UP", EV_TRUCK_SHIFT_UP, "Keyboard A", _L("shift one gear up in manual transmission mode")}, + {"TRUCK_SHIFT_GEAR_REVERSE", EV_TRUCK_SHIFT_GEAR_REVERSE, "", _L("shift directly to reverse gear")}, + {"TRUCK_SHIFT_GEAR1", EV_TRUCK_SHIFT_GEAR01, "", _L("shift directly to first gear")}, + {"TRUCK_SHIFT_GEAR2", EV_TRUCK_SHIFT_GEAR02, "", _L("shift directly to second gear")}, + {"TRUCK_SHIFT_GEAR3", EV_TRUCK_SHIFT_GEAR03, "", _L("shift directly to third gear")}, + {"TRUCK_SHIFT_GEAR4", EV_TRUCK_SHIFT_GEAR04, "", _L("shift directly to fourth gear")}, + {"TRUCK_SHIFT_GEAR5", EV_TRUCK_SHIFT_GEAR05, "", _L("shift directly to 5th gear")}, + {"TRUCK_SHIFT_GEAR6", EV_TRUCK_SHIFT_GEAR06, "", _L("shift directly to 6th gear")}, + {"TRUCK_SHIFT_GEAR7", EV_TRUCK_SHIFT_GEAR07, "", _L("shift directly to 7th gear")}, + {"TRUCK_SHIFT_GEAR8", EV_TRUCK_SHIFT_GEAR08, "", _L("shift directly to 8th gear")}, + {"TRUCK_SHIFT_GEAR9", EV_TRUCK_SHIFT_GEAR09, "", _L("shift directly to 9th gear")}, + {"TRUCK_SHIFT_GEAR10", EV_TRUCK_SHIFT_GEAR10, "", _L("shift directly to 10th gear")}, + {"TRUCK_SHIFT_GEAR11", EV_TRUCK_SHIFT_GEAR11, "", _L("shift directly to 11th gear")}, + {"TRUCK_SHIFT_GEAR12", EV_TRUCK_SHIFT_GEAR12, "", _L("shift directly to 12th gear")}, + + {"TRUCK_SHIFT_GEAR13", EV_TRUCK_SHIFT_GEAR13, "", _L("shift directly to 13th gear")}, + {"TRUCK_SHIFT_GEAR14", EV_TRUCK_SHIFT_GEAR14, "", _L("shift directly to 14th gear")}, + {"TRUCK_SHIFT_GEAR15", EV_TRUCK_SHIFT_GEAR15, "", _L("shift directly to 15th gear")}, + {"TRUCK_SHIFT_GEAR16", EV_TRUCK_SHIFT_GEAR16, "", _L("shift directly to 16th gear")}, + {"TRUCK_SHIFT_GEAR17", EV_TRUCK_SHIFT_GEAR17, "", _L("shift directly to 17th gear")}, + {"TRUCK_SHIFT_GEAR18", EV_TRUCK_SHIFT_GEAR18, "", _L("shift directly to 18th gear")}, + {"TRUCK_SHIFT_LOWRANGE", EV_TRUCK_SHIFT_LOWRANGE, "", _L("sets low range (1-6) for H-shaft")}, + {"TRUCK_SHIFT_MIDRANGE", EV_TRUCK_SHIFT_MIDRANGE, "", _L("sets middle range (7-12) for H-shaft")}, + {"TRUCK_SHIFT_HIGHRANGE", EV_TRUCK_SHIFT_HIGHRANGE, "", _L("sets high range (13-18) for H-shaft")}, + {"TRUCK_STARTER", EV_TRUCK_STARTER, "Keyboard S", _L("hold to start the engine")}, + {"TRUCK_STEER_LEFT", EV_TRUCK_STEER_LEFT, "Keyboard LEFT", _L("steer left")}, + {"TRUCK_STEER_RIGHT", EV_TRUCK_STEER_RIGHT, "Keyboard RIGHT", _L("steer right")}, + {"TRUCK_SWITCH_SHIFT_MODES", EV_TRUCK_SWITCH_SHIFT_MODES, "Keyboard Q", _L("toggle between transmission modes")}, + {"TRUCK_TOGGLE_INTER_AXLE_DIFF", EV_TRUCK_TOGGLE_INTER_AXLE_DIFF, "Keyboard EXPL+ALT+W", + _L("cycle between available inter axle differential modes")}, + {"TRUCK_TOGGLE_INTER_WHEEL_DIFF", EV_TRUCK_TOGGLE_INTER_WHEEL_DIFF, "Keyboard EXPL+W", + _L("cycle between available inter wheel differential modes")}, + {"TRUCK_TOGGLE_PHYSICS", EV_TRUCK_TOGGLE_PHYSICS, "Keyboard END", _L("toggle physics")}, + {"TRUCK_TOGGLE_TCASE_4WD_MODE", EV_TRUCK_TOGGLE_TCASE_4WD_MODE, "Keyboard EXPL+CTRL+W", _L("toggle transfer case mode")}, + {"TRUCK_TOGGLE_TCASE_GEAR_RATIO", EV_TRUCK_TOGGLE_TCASE_GEAR_RATIO, "Keyboard EXPL+SHIFT+W", + _L("toggle transfer case gear ratio")}, + {"TRUCK_TOGGLE_CONTACT", EV_TRUCK_TOGGLE_CONTACT, "Keyboard X", _L("toggle ignition")}, + {"TRUCK_TOGGLE_FORWARDCOMMANDS", EV_TRUCK_TOGGLE_FORWARDCOMMANDS, "Keyboard EXPL+CTRL+SHIFT+F", _L("toggle forwardcommands")}, + {"TRUCK_TOGGLE_IMPORTCOMMANDS", EV_TRUCK_TOGGLE_IMPORTCOMMANDS, "Keyboard EXPL+CTRL+SHIFT+I", _L("toggle importcommands")}, // "new" commands - { - "COMMON_FULLSCREEN_TOGGLE", - EV_COMMON_FULLSCREEN_TOGGLE, - "Keyboard EXPL+ALT+RETURN", - _L("toggle between windowed and fullscreen mode") - }, - { - "CAMERA_FREE_MODE_FIX", - EV_CAMERA_FREE_MODE_FIX, - "Keyboard EXPL+ALT+C", - _L("fix the camera to a position") - }, - { - "CAMERA_FREE_MODE", - EV_CAMERA_FREE_MODE, - "Keyboard EXPL+SHIFT+C", - _L("enable / disable free camera mode") - }, - { - "TRUCK_LEFT_MIRROR_LEFT", - EV_TRUCK_LEFT_MIRROR_LEFT, - "Keyboard EXPL+SEMICOLON", - _L("move left mirror to the left") - }, - { - "TRUCK_LEFT_MIRROR_RIGHT", - EV_TRUCK_LEFT_MIRROR_RIGHT, - "Keyboard EXPL+CTRL+SEMICOLON", - _L("move left mirror to the right") - }, - { - "TRUCK_RIGHT_MIRROR_LEFT", - EV_TRUCK_RIGHT_MIRROR_LEFT, - "Keyboard EXPL+COLON", - _L("more right mirror to the left") - }, - { - "TRUCK_RIGHT_MIRROR_RIGHT", - EV_TRUCK_RIGHT_MIRROR_RIGHT, - "Keyboard EXPL+CTRL+COLON", - _L("move right mirror to the right") - }, - { - "COMMON_REPLAY_FORWARD", - EV_COMMON_REPLAY_FORWARD, - "Keyboard EXPL+RIGHT", - _L("more replay forward") - }, - { - "COMMON_REPLAY_BACKWARD", - EV_COMMON_REPLAY_BACKWARD, - "Keyboard EXPL+LEFT", - _L("more replay backward") - }, - { - "COMMON_REPLAY_FAST_FORWARD", - EV_COMMON_REPLAY_FAST_FORWARD, - "Keyboard EXPL+SHIFT+RIGHT", - _L("move replay fast forward") - }, - { - "COMMON_REPLAY_FAST_BACKWARD", - EV_COMMON_REPLAY_FAST_BACKWARD, - "Keyboard EXPL+SHIFT+LEFT", - _L("move replay fast backward") - }, - { - "AIRPLANE_AIRBRAKES_NONE", - EV_AIRPLANE_AIRBRAKES_NONE, - "Keyboard CTRL+3", - _L("no airbrakes") - }, - { - "AIRPLANE_AIRBRAKES_FULL", - EV_AIRPLANE_AIRBRAKES_FULL, - "Keyboard CTRL+4", - _L("full airbrakes") - }, - { - "AIRPLANE_AIRBRAKES_LESS", - EV_AIRPLANE_AIRBRAKES_LESS, - "Keyboard EXPL+3", - _L("less airbrakes") - }, - { - "AIRPLANE_AIRBRAKES_MORE", - EV_AIRPLANE_AIRBRAKES_MORE, - "Keyboard EXPL+4", - _L("more airbrakes") - }, - { - "AIRPLANE_THROTTLE", - EV_AIRPLANE_THROTTLE, - "", - _L("airplane throttle") - }, - { - "COMMON_TRUCK_REMOVE", - EV_COMMON_TRUCK_REMOVE, - "Keyboard EXPL+CTRL+SHIFT+DELETE", - _L("delete current truck") - }, - { - "COMMON_NETCHATDISPLAY", - EV_COMMON_NETCHATDISPLAY, - "Keyboard EXPL+SHIFT+U", - _L("display or hide net chat") - }, - { - "COMMON_NETCHATMODE", - EV_COMMON_NETCHATMODE, - "Keyboard EXPL+CTRL+U", - _L("toggle between net chat display modes") - }, - { - "CHARACTER_ROT_UP", - EV_CHARACTER_ROT_UP, - "Keyboard UP", - _L("rotate view up") - }, - { - "CHARACTER_ROT_DOWN", - EV_CHARACTER_ROT_DOWN, - "Keyboard DOWN", - _L("rotate view down") - }, - { - "CAMERA_UP", - EV_CAMERA_UP, - "Keyboard Q", - _L("move camera up") - }, - { - "CAMERA_DOWN", - EV_CAMERA_DOWN, - "Keyboard Z", - _L("move camera down") - }, + {"COMMON_FULLSCREEN_TOGGLE", EV_COMMON_FULLSCREEN_TOGGLE, "Keyboard EXPL+ALT+RETURN", + _L("toggle between windowed and fullscreen mode")}, + {"CAMERA_FREE_MODE_FIX", EV_CAMERA_FREE_MODE_FIX, "Keyboard EXPL+ALT+C", _L("fix the camera to a position")}, + {"CAMERA_FREE_MODE", EV_CAMERA_FREE_MODE, "Keyboard EXPL+SHIFT+C", _L("enable / disable free camera mode")}, + {"TRUCK_LEFT_MIRROR_LEFT", EV_TRUCK_LEFT_MIRROR_LEFT, "Keyboard EXPL+SEMICOLON", _L("move left mirror to the left")}, + {"TRUCK_LEFT_MIRROR_RIGHT", EV_TRUCK_LEFT_MIRROR_RIGHT, "Keyboard EXPL+CTRL+SEMICOLON", _L("move left mirror to the right")}, + {"TRUCK_RIGHT_MIRROR_LEFT", EV_TRUCK_RIGHT_MIRROR_LEFT, "Keyboard EXPL+COLON", _L("more right mirror to the left")}, + {"TRUCK_RIGHT_MIRROR_RIGHT", EV_TRUCK_RIGHT_MIRROR_RIGHT, "Keyboard EXPL+CTRL+COLON", _L("move right mirror to the right")}, + {"COMMON_REPLAY_FORWARD", EV_COMMON_REPLAY_FORWARD, "Keyboard EXPL+RIGHT", _L("more replay forward")}, + {"COMMON_REPLAY_BACKWARD", EV_COMMON_REPLAY_BACKWARD, "Keyboard EXPL+LEFT", _L("more replay backward")}, + {"COMMON_REPLAY_FAST_FORWARD", EV_COMMON_REPLAY_FAST_FORWARD, "Keyboard EXPL+SHIFT+RIGHT", _L("move replay fast forward")}, + {"COMMON_REPLAY_FAST_BACKWARD", EV_COMMON_REPLAY_FAST_BACKWARD, "Keyboard EXPL+SHIFT+LEFT", _L("move replay fast backward")}, + {"AIRPLANE_AIRBRAKES_NONE", EV_AIRPLANE_AIRBRAKES_NONE, "Keyboard CTRL+3", _L("no airbrakes")}, + {"AIRPLANE_AIRBRAKES_FULL", EV_AIRPLANE_AIRBRAKES_FULL, "Keyboard CTRL+4", _L("full airbrakes")}, + {"AIRPLANE_AIRBRAKES_LESS", EV_AIRPLANE_AIRBRAKES_LESS, "Keyboard EXPL+3", _L("less airbrakes")}, + {"AIRPLANE_AIRBRAKES_MORE", EV_AIRPLANE_AIRBRAKES_MORE, "Keyboard EXPL+4", _L("more airbrakes")}, + {"AIRPLANE_THROTTLE", EV_AIRPLANE_THROTTLE, "", _L("airplane throttle")}, + {"COMMON_TRUCK_REMOVE", EV_COMMON_TRUCK_REMOVE, "Keyboard EXPL+CTRL+SHIFT+DELETE", _L("delete current truck")}, + {"COMMON_NETCHATDISPLAY", EV_COMMON_NETCHATDISPLAY, "Keyboard EXPL+SHIFT+U", _L("display or hide net chat")}, + {"COMMON_NETCHATMODE", EV_COMMON_NETCHATMODE, "Keyboard EXPL+CTRL+U", _L("toggle between net chat display modes")}, + {"CHARACTER_ROT_UP", EV_CHARACTER_ROT_UP, "Keyboard UP", _L("rotate view up")}, + {"CHARACTER_ROT_DOWN", EV_CHARACTER_ROT_DOWN, "Keyboard DOWN", _L("rotate view down")}, + {"CAMERA_UP", EV_CAMERA_UP, "Keyboard Q", _L("move camera up")}, + {"CAMERA_DOWN", EV_CAMERA_DOWN, "Keyboard Z", _L("move camera down")}, // now position storage {"COMMON_QUICKSAVE_01", EV_COMMON_QUICKSAVE_01, "Keyboard EXPL+ALT+CTRL+1", _L("save scene in slot 01")}, @@ -1805,16 +371,16 @@ eventInfo_t eventInfo[] = { }; #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE -#define strnlen(str,len) strlen(str) + #define strnlen(str, len) strlen(str) #endif -//Use this define to signify OIS will be used as a DLL +// Use this define to signify OIS will be used as a DLL //(so that dll import/export macros are in effect) #define OIS_DYNAMIC_LIB #include #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX -#include + #include //#include #endif @@ -1827,16 +393,9 @@ using namespace Ogre; using namespace OIS; // Constructor takes a RenderWindow because it uses that to determine input context -InputEngine::InputEngine() : - captureMode(false) - , free_joysticks(0) - , inputsChanged(true) - , mForceFeedback(0) - , mInputManager(0) - , mKeyboard(0) - , mMouse(0) - , mappingLoaded(false) - , uniqueCounter(0) +InputEngine::InputEngine() + : captureMode(false), free_joysticks(0), inputsChanged(true), mForceFeedback(0), mInputManager(0), mKeyboard(0), mMouse(0), + mappingLoaded(false), uniqueCounter(0) { for (int i = 0; i < MAX_JOYSTICKS; i++) mJoy[i] = 0; @@ -1875,8 +434,7 @@ void InputEngine::destroy() { for (int i = 0; i < MAX_JOYSTICKS; i++) { - if (!mJoy[i]) - continue; + if (!mJoy[i]) continue; mInputManager->destroyInputObject(mJoy[i]); mJoy[i] = 0; } @@ -1892,17 +450,17 @@ bool InputEngine::setup(String hwnd, bool capture, bool capturemouse, bool captu #ifndef NOOGRE LOG("*** Initializing OIS ***"); #endif - //try to delete old ones first (linux can only handle one at a time) + // try to delete old ones first (linux can only handle one at a time) destroy(); captureMode = capture; if (captureMode) { - //size_t hWnd = 0; - //win->getCustomAttribute("WINDOW", &hWnd); + // size_t hWnd = 0; + // win->getCustomAttribute("WINDOW", &hWnd); ParamList pl; -#if 0 //OGRE_PLATFORM == OGRE_PLATFORM_LINUX - // we get the ogre way of defining the handle, extract the window HWND only +#if 0 // OGRE_PLATFORM == OGRE_PLATFORM_LINUX + // we get the ogre way of defining the handle, extract the window HWND only int screen=0,app=0,windowhandle=0; sscanf(hwnd.c_str(), "%d:%d:%d", &screen, &app, &windowhandle); hwnd = TOSTRING(windowhandle); @@ -1926,37 +484,38 @@ bool InputEngine::setup(String hwnd, bool capture, bool capturemouse, bool captu } #ifndef NOOGRE - LOG("*** OIS WINDOW: "+hwnd); -#endif //NOOGRE + LOG("*** OIS WINDOW: " + hwnd); +#endif // NOOGRE mInputManager = OIS::InputManager::createInputSystem(pl); #ifndef NOOGRE - //Print debugging information + // Print debugging information unsigned int v = mInputManager->getVersionNumber(); - LOG("OIS Version: " + TOSTRING(v>>16) + String(".") + TOSTRING((v>>8) & 0x000000FF) + String(".") + TOSTRING(v & 0x000000FF)); + LOG("OIS Version: " + TOSTRING(v >> 16) + String(".") + TOSTRING((v >> 8) & 0x000000FF) + String(".") + + TOSTRING(v & 0x000000FF)); LOG("+ Release Name: " + mInputManager->getVersionName()); LOG("+ Manager: " + mInputManager->inputSystemName()); LOG("+ Total Keyboards: " + TOSTRING(mInputManager->getNumberOfDevices(OISKeyboard))); LOG("+ Total Mice: " + TOSTRING(mInputManager->getNumberOfDevices(OISMouse))); LOG("+ Total JoySticks: " + TOSTRING(mInputManager->getNumberOfDevices(OISJoyStick))); - //List all devices + // List all devices OIS::DeviceList deviceList = mInputManager->listFreeDevices(); for (OIS::DeviceList::iterator i = deviceList.begin(); i != deviceList.end(); ++i) - LOG("* Device: " + String(mOISDeviceType[i->first]) + String(" Vendor: ") + i->second); -#endif //NOOGRE + LOG("* Device: " + String(mOISDeviceType[i->first]) + String(" Vendor: ") + i->second); +#endif // NOOGRE - //Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse) + // Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse) mKeyboard = 0; if (captureKbd) { try { - mKeyboard = static_cast(mInputManager->createInputObject(OISKeyboard, true)); + mKeyboard = static_cast(mInputManager->createInputObject(OISKeyboard, true)); mKeyboard->setTextTranslation(OIS::Keyboard::Unicode); } - catch (OIS::Exception& ex) + catch (OIS::Exception &ex) { LOG(String("Exception raised on keyboard creation: ") + String(ex.eText)); } @@ -1964,18 +523,18 @@ bool InputEngine::setup(String hwnd, bool capture, bool capturemouse, bool captu try { - //This demo uses at most 10 joysticks - use old way to create (i.e. disregard vendor) - int numSticks = std::min(mInputManager->getNumberOfDevices(OISJoyStick), 10); + // This demo uses at most 10 joysticks - use old way to create (i.e. disregard vendor) + int numSticks = std::min(mInputManager->getNumberOfDevices(OISJoyStick), 10); free_joysticks = 0; for (int i = 0; i < numSticks; ++i) { - mJoy[i] = (JoyStick*)mInputManager->createInputObject(OISJoyStick, true); + mJoy[i] = (JoyStick *)mInputManager->createInputObject(OISJoyStick, true); mJoy[i]->setEventCallback(this); free_joysticks++; - //create force feedback too - //here, we take the first device we can get, but we could take a device index + // create force feedback too + // here, we take the first device we can get, but we could take a device index if (!mForceFeedback) - mForceFeedback = (OIS::ForceFeedback*)mJoy[i]->queryInterface(OIS::Interface::ForceFeedback); + mForceFeedback = (OIS::ForceFeedback *)mJoy[i]->queryInterface(OIS::Interface::ForceFeedback); #ifndef NOOGRE LOG("Creating Joystick " + TOSTRING(i + 1) + " (" + mJoy[i]->vendor() + ")"); @@ -1984,38 +543,37 @@ bool InputEngine::setup(String hwnd, bool capture, bool capturemouse, bool captu LOG("* POV/HATs: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_POV))); LOG("* Buttons: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_Button))); LOG("* Vector3: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_Vector3))); -#endif //NOOGRE +#endif // NOOGRE } } #ifndef NOOGRE - catch (OIS::Exception& ex) + catch (OIS::Exception &ex) { LOG(String("Exception raised on joystick creation: ") + String(ex.eText)); } -#else //NOOGRE +#else // NOOGRE catch (...) { } -#endif //NOOGRE +#endif // NOOGRE if (capturemouse) { try { - mMouse = static_cast(mInputManager->createInputObject(OISMouse, true)); + mMouse = static_cast(mInputManager->createInputObject(OISMouse, true)); } - catch (OIS::Exception& ex) + catch (OIS::Exception &ex) { LOG(String("Exception raised on mouse creation: ") + String(ex.eText)); } } - //Set initial mouse clipping size - //windowResized(win); + // Set initial mouse clipping size + // windowResized(win); // set Callbacks - if (mKeyboard) - mKeyboard->setEventCallback(this); + if (mKeyboard) mKeyboard->setEventCallback(this); if (capturemouse && mMouse) { mMouse->setEventCallback(this); @@ -2034,22 +592,22 @@ bool InputEngine::setup(String hwnd, bool capture, bool capturemouse, bool captu // under linux, this will not work and the cursor will never reach (0,0) if (mMouse && RoR::App::GetOgreSubsystem()->GetRenderWindow()) { - OIS::MouseState& mutableMouseState = const_cast(mMouse->getMouseState()); - mutableMouseState.X.abs = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getWidth() * 0.5f; - mutableMouseState.Y.abs = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getHeight() * 0.5f; + OIS::MouseState &mutableMouseState = const_cast(mMouse->getMouseState()); + mutableMouseState.X.abs = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getWidth() * 0.5f; + mutableMouseState.Y.abs = RoR::App::GetOgreSubsystem()->GetRenderWindow()->getHeight() * 0.5f; } #endif // _WIN32 } - //this becomes more and more convoluted! + // this becomes more and more convoluted! #ifdef NOOGRE // we will load the mapping manually -#else //NOOGRE +#else // NOOGRE if (!mappingLoaded) { // load default one loadMapping(CONFIGFILENAME); -#ifndef NOOGRE + #ifndef NOOGRE // then load device specific ones for (int i = 0; i < free_joysticks; ++i) { @@ -2065,111 +623,92 @@ bool InputEngine::setup(String hwnd, bool capture, bool capturemouse, bool captu loadMapping(deviceStr, true, i); } -#endif //NOOGRE + #endif // NOOGRE mappingLoaded = true; completeMissingEvents(); return false; } -#endif //NOOGRE +#endif // NOOGRE return true; } void InputEngine::grabMouse(bool enable) { static int lastmode = -1; - if (!mMouse) - return; + if (!mMouse) return; #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX if ((enable && lastmode == 0) || (!enable && lastmode == 1) || (lastmode == -1)) { LOG("*** mouse grab: " + TOSTRING(enable)); - //((LinuxMouse *)mMouse)->grab(enable); - lastmode = enable?1:0; + //((LinuxMouse *)mMouse)->grab(enable); + lastmode = enable ? 1 : 0; } #endif } void InputEngine::setMousePosition(int x, int y, bool padding) { - if (!mMouse) - return; + if (!mMouse) return; #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX - // padding ensures that the mouse has a safety area at the window's borders - // ((LinuxMouse *)mMouse)->setMousePosition(x, y, padding); + // padding ensures that the mouse has a safety area at the window's borders + // ((LinuxMouse *)mMouse)->setMousePosition(x, y, padding); #endif } OIS::MouseState InputEngine::getMouseState() { OIS::MouseState m; - if (mMouse) - { - m = mMouse->getMouseState(); - } + if (mMouse) { m = mMouse->getMouseState(); } return m; } String InputEngine::getKeyNameForKeyCode(OIS::KeyCode keycode) { - if (keycode == KC_LSHIFT || keycode == KC_RSHIFT) - return "SHIFT"; - if (keycode == KC_LCONTROL || keycode == KC_RCONTROL) - return "CTRL"; - if (keycode == KC_LMENU || keycode == KC_RMENU) - return "ALT"; + if (keycode == KC_LSHIFT || keycode == KC_RSHIFT) return "SHIFT"; + if (keycode == KC_LCONTROL || keycode == KC_RCONTROL) return "CTRL"; + if (keycode == KC_LMENU || keycode == KC_RMENU) return "ALT"; for (allit = allkeys.begin(); allit != allkeys.end(); allit++) { - if (allit->second == keycode) - return allit->first; + if (allit->second == keycode) return allit->first; } return "unknown"; } void InputEngine::Capture() { - if (mKeyboard) - { - mKeyboard->capture(); - } + if (mKeyboard) { mKeyboard->capture(); } - if (mMouse) - { - mMouse->capture(); - } + if (mMouse) { mMouse->capture(); } for (int i = 0; i < free_joysticks; i++) { - if (mJoy[i]) - { - mJoy[i]->capture(); - } + if (mJoy[i]) { mJoy[i]->capture(); } } } -void InputEngine::windowResized(Ogre::RenderWindow* rw) +void InputEngine::windowResized(Ogre::RenderWindow *rw) { - if (!mMouse) - return; - //update mouse area + if (!mMouse) return; + // update mouse area unsigned int width, height, depth; - int left, top; + int left, top; rw->getMetrics(width, height, depth, left, top); - const OIS::MouseState& ms = mMouse->getMouseState(); - ms.width = width; - ms.height = height; + const OIS::MouseState &ms = mMouse->getMouseState(); + ms.width = width; + ms.height = height; RoR::App::GetGuiManager()->windowResized(rw); } -void InputEngine::SetKeyboardListener(OIS::KeyListener* keyboard_listener) +void InputEngine::SetKeyboardListener(OIS::KeyListener *keyboard_listener) { - assert (mKeyboard != nullptr); + assert(mKeyboard != nullptr); mKeyboard->setEventCallback(keyboard_listener); } -OIS::MouseState InputEngine::SetMouseListener(OIS::MouseListener* mouse_listener) +OIS::MouseState InputEngine::SetMouseListener(OIS::MouseListener *mouse_listener) { - assert (mMouse != nullptr); + assert(mMouse != nullptr); mMouse->setEventCallback(mouse_listener); return mMouse->getMouseState(); } @@ -2191,114 +730,102 @@ void InputEngine::RestoreKeyboardListener() } /* --- Joystik Events ------------------------------------------ */ -bool InputEngine::buttonPressed(const OIS::JoyStickEvent& arg, int button) +bool InputEngine::buttonPressed(const OIS::JoyStickEvent &arg, int button) { inputsChanged = true; - //LOG("*** buttonPressed " + TOSTRING(button)); + // LOG("*** buttonPressed " + TOSTRING(button)); int i = arg.device->getID(); - if (i < 0 || i >= MAX_JOYSTICKS) - i = 0; + if (i < 0 || i >= MAX_JOYSTICKS) i = 0; joyState[i] = arg.state; return true; } -bool InputEngine::buttonReleased(const OIS::JoyStickEvent& arg, int button) +bool InputEngine::buttonReleased(const OIS::JoyStickEvent &arg, int button) { inputsChanged = true; - //LOG("*** buttonReleased " + TOSTRING(button)); + // LOG("*** buttonReleased " + TOSTRING(button)); int i = arg.device->getID(); - if (i < 0 || i >= MAX_JOYSTICKS) - i = 0; + if (i < 0 || i >= MAX_JOYSTICKS) i = 0; joyState[i] = arg.state; return true; } -bool InputEngine::axisMoved(const OIS::JoyStickEvent& arg, int axis) +bool InputEngine::axisMoved(const OIS::JoyStickEvent &arg, int axis) { inputsChanged = true; - //LOG("*** axisMoved " + TOSTRING(axis) + " / " + TOSTRING((int)(arg.state.mAxes[axis].abs / (float)(mJoy->MAX_AXIS/100)))); + // LOG("*** axisMoved " + TOSTRING(axis) + " / " + TOSTRING((int)(arg.state.mAxes[axis].abs / (float)(mJoy->MAX_AXIS/100)))); int i = arg.device->getID(); - if (i < 0 || i >= MAX_JOYSTICKS) - i = 0; + if (i < 0 || i >= MAX_JOYSTICKS) i = 0; joyState[i] = arg.state; return true; } -bool InputEngine::sliderMoved(const OIS::JoyStickEvent& arg, int) +bool InputEngine::sliderMoved(const OIS::JoyStickEvent &arg, int) { inputsChanged = true; - //LOG("*** sliderMoved"); + // LOG("*** sliderMoved"); int i = arg.device->getID(); - if (i < 0 || i >= MAX_JOYSTICKS) - i = 0; + if (i < 0 || i >= MAX_JOYSTICKS) i = 0; joyState[i] = arg.state; return true; } -bool InputEngine::povMoved(const OIS::JoyStickEvent& arg, int) +bool InputEngine::povMoved(const OIS::JoyStickEvent &arg, int) { inputsChanged = true; - //LOG("*** povMoved"); + // LOG("*** povMoved"); int i = arg.device->getID(); - if (i < 0 || i >= MAX_JOYSTICKS) - i = 0; + if (i < 0 || i >= MAX_JOYSTICKS) i = 0; joyState[i] = arg.state; return true; } /* --- Key Events ------------------------------------------ */ -bool InputEngine::keyPressed(const OIS::KeyEvent& arg) +bool InputEngine::keyPressed(const OIS::KeyEvent &arg) { - if (RoR::App::GetGuiManager()->keyPressed(arg)) - return true; + if (RoR::App::GetGuiManager()->keyPressed(arg)) return true; - //LOG("*** keyPressed"); - if (keyState[arg.key] != 1) - inputsChanged = true; + // LOG("*** keyPressed"); + if (keyState[arg.key] != 1) inputsChanged = true; keyState[arg.key] = 1; return true; } -bool InputEngine::keyReleased(const OIS::KeyEvent& arg) +bool InputEngine::keyReleased(const OIS::KeyEvent &arg) { - if (RoR::App::GetGuiManager()->keyReleased(arg)) - return true; - //LOG("*** keyReleased"); - if (keyState[arg.key] != 0) - inputsChanged = true; + if (RoR::App::GetGuiManager()->keyReleased(arg)) return true; + // LOG("*** keyReleased"); + if (keyState[arg.key] != 0) inputsChanged = true; keyState[arg.key] = 0; return true; } /* --- Mouse Events ------------------------------------------ */ -bool InputEngine::mouseMoved(const OIS::MouseEvent& arg) +bool InputEngine::mouseMoved(const OIS::MouseEvent &arg) { - if (RoR::App::GetGuiManager()->mouseMoved(arg)) - return true; - //LOG("*** mouseMoved"); + if (RoR::App::GetGuiManager()->mouseMoved(arg)) return true; + // LOG("*** mouseMoved"); inputsChanged = true; - mouseState = arg.state; + mouseState = arg.state; return true; } -bool InputEngine::mousePressed(const OIS::MouseEvent& arg, OIS::MouseButtonID id) +bool InputEngine::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) { - if (RoR::App::GetGuiManager()->mousePressed(arg, id)) - return true; - //LOG("*** mousePressed"); + if (RoR::App::GetGuiManager()->mousePressed(arg, id)) return true; + // LOG("*** mousePressed"); inputsChanged = true; - mouseState = arg.state; + mouseState = arg.state; return true; } -bool InputEngine::mouseReleased(const OIS::MouseEvent& arg, OIS::MouseButtonID id) +bool InputEngine::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id) { - if (RoR::App::GetGuiManager()->mouseReleased(arg, id)) - return true; - //LOG("*** mouseReleased"); + if (RoR::App::GetGuiManager()->mouseReleased(arg, id)) return true; + // LOG("*** mouseReleased"); inputsChanged = true; - mouseState = arg.state; + mouseState = arg.state; return true; } @@ -2331,8 +858,7 @@ bool InputEngine::getEventBoolValueBounce(int eventID, float time) else { bool res = getEventBoolValue(eventID); - if (res) - event_times[eventID] = time; + if (res) event_times[eventID] = time; return res; } } @@ -2346,9 +872,8 @@ void InputEngine::updateKeyBounces(float dt) { for (std::map::iterator it = event_times.begin(); it != event_times.end(); it++) { - if (it->second > 0) - it->second -= dt; - //else + if (it->second > 0) it->second -= dt; + // else // erase element? } } @@ -2356,15 +881,14 @@ void InputEngine::updateKeyBounces(float dt) float InputEngine::deadZone(float axisValue, float dz) { // no deadzone? - if (dz < 0.0001f) - return axisValue; + if (dz < 0.0001f) return axisValue; // check for deadzone if (fabs(axisValue) < dz) - // dead zone case + // dead zone case return 0.0f; else - // non-deadzone, remap the remaining part + // non-deadzone, remap the remaining part return (axisValue - dz) * (1.0f / (1.0f - dz)); } @@ -2375,25 +899,20 @@ float InputEngine::axisLinearity(float axisValue, float linearity) float InputEngine::logval(float val) { - if (val > 0) - return log10(1.0 / (1.1 - val)) / 1.0; - if (val == 0) - return 0; + if (val > 0) return log10(1.0 / (1.1 - val)) / 1.0; + if (val == 0) return 0; return -log10(1.0 / (1.1 + val)) / 1.0; } -void InputEngine::smoothValue(float& ref, float value, float rate) +void InputEngine::smoothValue(float &ref, float value, float rate) { - if (value < -1) - value = -1; - if (value > 1) - value = 1; + if (value < -1) value = -1; + if (value > 1) value = 1; // smooth! if (ref > value) { ref -= rate; - if (ref < value) - ref = value; + if (ref < value) ref = value; } else if (ref < value) ref += rate; @@ -2402,21 +921,19 @@ void InputEngine::smoothValue(float& ref, float value, float rate) String InputEngine::getEventCommand(int eventID) { std::vector t_vec = events[eventID]; - if (t_vec.size() > 0) - return String(t_vec[0].configline); + if (t_vec.size() > 0) return String(t_vec[0].configline); return ""; } -event_trigger_t* InputEngine::getEventBySUID(int suid) +event_trigger_t *InputEngine::getEventBySUID(int suid) { std::map>::iterator a; - std::vector::iterator b; + std::vector::iterator b; for (a = events.begin(); a != events.end(); a++) { for (b = a->second.begin(); b != a->second.end(); b++) { - if (b->suid == suid) - return &(*b); + if (b->suid == suid) return &(*b); } } return 0; @@ -2425,7 +942,7 @@ event_trigger_t* InputEngine::getEventBySUID(int suid) bool InputEngine::deleteEventBySUID(int suid) { std::map>::iterator a; - std::vector::iterator b; + std::vector::iterator b; for (a = events.begin(); a != events.end(); a++) { for (b = a->second.begin(); b != a->second.end(); b++) @@ -2445,8 +962,7 @@ bool InputEngine::isEventDefined(int eventID) std::vector t_vec = events[eventID]; if (t_vec.size() > 0) { - if (t_vec[0].eventtype != ET_NONE) - return true; + if (t_vec[0].eventtype != ET_NONE) return true; } return false; } @@ -2457,8 +973,7 @@ int InputEngine::getKeboardKeyForCommand(int eventID) for (std::vector::iterator i = t_vec.begin(); i != t_vec.end(); i++) { event_trigger_t t = *i; - if (t.eventtype == ET_Keyboard) - return t.keyCode; + if (t.eventtype == ET_Keyboard) return t.keyCode; } return -1; } @@ -2468,23 +983,18 @@ bool InputEngine::isEventAnalog(int eventID) std::vector t_vec = events[eventID]; if (t_vec.size() > 0) { - //loop through all eventtypes, because we want to find a analog device wether it is the first device or not - //this means a analog device is always preferred over a digital one + // loop through all eventtypes, because we want to find a analog device wether it is the first device or not + // this means a analog device is always preferred over a digital one for (unsigned int i = 0; i < t_vec.size(); i++) { - if ((t_vec[i].eventtype == ET_MouseAxisX - || t_vec[i].eventtype == ET_MouseAxisY - || t_vec[i].eventtype == ET_MouseAxisZ - || t_vec[i].eventtype == ET_JoystickAxisAbs - || t_vec[i].eventtype == ET_JoystickAxisRel - || t_vec[i].eventtype == ET_JoystickSliderX - || t_vec[i].eventtype == ET_JoystickSliderY) - //check if value comes from analog device - //this way, only valid events (e.g. joystick mapped, but unplugged) are recognized as analog events + if ((t_vec[i].eventtype == ET_MouseAxisX || t_vec[i].eventtype == ET_MouseAxisY || + t_vec[i].eventtype == ET_MouseAxisZ || t_vec[i].eventtype == ET_JoystickAxisAbs || + t_vec[i].eventtype == ET_JoystickAxisRel || t_vec[i].eventtype == ET_JoystickSliderX || + t_vec[i].eventtype == ET_JoystickSliderY) + // check if value comes from analog device + // this way, only valid events (e.g. joystick mapped, but unplugged) are recognized as analog events && getEventValue(eventID, true, 2) != 0.0) - { - return true; - } + { return true; } } } return false; @@ -2505,14 +1015,14 @@ bool InputEngine::isEventAnalog(int eventID) return true; } return false; -#endif //0 +#endif // 0 } float InputEngine::getEventValue(int eventID, bool pure, int valueSource) { - float returnValue = 0; - std::vector t_vec = events[eventID]; - float value = 0; + float returnValue = 0; + std::vector t_vec = events[eventID]; + float value = 0; for (std::vector::iterator i = t_vec.begin(); i != t_vec.end(); i++) { event_trigger_t t = *i; @@ -2521,202 +1031,183 @@ float InputEngine::getEventValue(int eventID, bool pure, int valueSource) { switch (t.eventtype) { - case ET_NONE: - break; + case ET_NONE: break; case ET_Keyboard: - if (!keyState[t.keyCode]) - break; + if (!keyState[t.keyCode]) break; // only use explicite mapping, if two keys with different modifiers exist, i.e. F1 and SHIFT+F1. // check for modificators if (t.explicite) { - if (t.ctrl != (keyState[KC_LCONTROL] || keyState[KC_RCONTROL])) - break; - if (t.shift != (keyState[KC_LSHIFT] || keyState[KC_RSHIFT])) - break; - if (t.alt != (keyState[KC_LMENU] || keyState[KC_RMENU])) - break; + if (t.ctrl != (keyState[KC_LCONTROL] || keyState[KC_RCONTROL])) break; + if (t.shift != (keyState[KC_LSHIFT] || keyState[KC_RSHIFT])) break; + if (t.alt != (keyState[KC_LMENU] || keyState[KC_RMENU])) break; } else { - if (t.ctrl && !(keyState[KC_LCONTROL] || keyState[KC_RCONTROL])) - break; - if (t.shift && !(keyState[KC_LSHIFT] || keyState[KC_RSHIFT])) - break; - if (t.alt && !(keyState[KC_LMENU] || keyState[KC_RMENU])) - break; + if (t.ctrl && !(keyState[KC_LCONTROL] || keyState[KC_RCONTROL])) break; + if (t.shift && !(keyState[KC_LSHIFT] || keyState[KC_RSHIFT])) break; + if (t.alt && !(keyState[KC_LMENU] || keyState[KC_RMENU])) break; } value = 1; break; case ET_MouseButton: - //if (t.mouseButtonNumber == 0) + // if (t.mouseButtonNumber == 0) // TODO: FIXME value = mouseState.buttonDown(MB_Left); break; case ET_JoystickButton: + { + if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) + { + value = 0; + continue; + } + if (t.joystickButtonNumber >= (int)mJoy[t.joystickNumber]->getNumberOfComponents(OIS_Button)) { - if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) - { - value = 0; - continue; - } - if (t.joystickButtonNumber >= (int)mJoy[t.joystickNumber]->getNumberOfComponents(OIS_Button)) - { #ifndef NOOGRE - LOG("*** Joystick has not enough buttons for mapping: need button "+TOSTRING(t.joystickButtonNumber) + ", availabe buttons: "+TOSTRING(mJoy[t.joystickNumber]->getNumberOfComponents(OIS_Button))); + LOG("*** Joystick has not enough buttons for mapping: need button " + TOSTRING(t.joystickButtonNumber) + + ", availabe buttons: " + TOSTRING(mJoy[t.joystickNumber]->getNumberOfComponents(OIS_Button))); #endif - value = 0; - continue; - } - value = joyState[t.joystickNumber].mButtons[t.joystickButtonNumber]; + value = 0; + continue; } - break; + value = joyState[t.joystickNumber].mButtons[t.joystickButtonNumber]; + } + break; case ET_JoystickPov: + { + if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) + { + value = 0; + continue; + } + if (t.joystickPovNumber >= (int)mJoy[t.joystickNumber]->getNumberOfComponents(OIS_POV)) { - if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) - { - value = 0; - continue; - } - if (t.joystickPovNumber >= (int)mJoy[t.joystickNumber]->getNumberOfComponents(OIS_POV)) - { #ifndef NOOGRE - LOG("*** Joystick has not enough POVs for mapping: need POV "+TOSTRING(t.joystickPovNumber) + ", availabe POVs: "+TOSTRING(mJoy[t.joystickNumber]->getNumberOfComponents(OIS_POV))); + LOG("*** Joystick has not enough POVs for mapping: need POV " + TOSTRING(t.joystickPovNumber) + + ", availabe POVs: " + TOSTRING(mJoy[t.joystickNumber]->getNumberOfComponents(OIS_POV))); #endif - value = 0; - continue; - } - if (joyState[t.joystickNumber].mPOV[t.joystickPovNumber].direction & t.joystickPovDirection) - value = 1; - else - value = 0; + value = 0; + continue; } - break; + if (joyState[t.joystickNumber].mPOV[t.joystickPovNumber].direction & t.joystickPovDirection) + value = 1; + else + value = 0; + } + break; } } if (valueSource == 0 || valueSource == 2) { switch (t.eventtype) { - case ET_MouseAxisX: - value = mouseState.X.abs / 32767; - break; - case ET_MouseAxisY: - value = mouseState.Y.abs / 32767; - break; - case ET_MouseAxisZ: - value = mouseState.Z.abs / 32767; - break; + case ET_MouseAxisX: value = mouseState.X.abs / 32767; break; + case ET_MouseAxisY: value = mouseState.Y.abs / 32767; break; + case ET_MouseAxisZ: value = mouseState.Z.abs / 32767; break; case ET_JoystickAxisRel: case ET_JoystickAxisAbs: + { + if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) + { + value = 0; + continue; + } + if (t.joystickAxisNumber >= (int)joyState[t.joystickNumber].mAxes.size()) { - if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) - { - value = 0; - continue; - } - if (t.joystickAxisNumber >= (int)joyState[t.joystickNumber].mAxes.size()) - { #ifndef NOOGRE - LOG("*** Joystick has not enough axis for mapping: need axe "+TOSTRING(t.joystickAxisNumber) + ", availabe axis: "+TOSTRING(joyState[t.joystickNumber].mAxes.size())); + LOG("*** Joystick has not enough axis for mapping: need axe " + TOSTRING(t.joystickAxisNumber) + + ", availabe axis: " + TOSTRING(joyState[t.joystickNumber].mAxes.size())); #endif - value = 0; - continue; + value = 0; + continue; + } + Axis axe = joyState[t.joystickNumber].mAxes[t.joystickAxisNumber]; + + if (t.eventtype == ET_JoystickAxisRel) { value = (float)axe.rel / (float)mJoy[t.joystickNumber]->MAX_AXIS; } + else + { + value = (float)axe.abs / (float)mJoy[t.joystickNumber]->MAX_AXIS; + switch (t.joystickAxisRegion) + { + case 0: + // normal case, full axis used + value = (value + 1) / 2; + break; + case -1: + // lower range used + if (value > 0) + value = 0; + else + value = -value; + break; + case 1: + // upper range used + if (value < 0) value = 0; + break; } - Axis axe = joyState[t.joystickNumber].mAxes[t.joystickAxisNumber]; - if (t.eventtype == ET_JoystickAxisRel) + if (t.joystickAxisHalf) { - value = (float)axe.rel / (float)mJoy[t.joystickNumber]->MAX_AXIS; + // XXX: TODO: write this + // float a = (double)((value+1.0)/2.0); + // float b = (double)(1.0-(value+1.0)/2.0); + // LOG("half: "+TOSTRING(value)+" / "+TOSTRING(a)+" / "+TOSTRING(b)); + // no dead zone in half axis + value = (1.0 + value) / 2.0; + if (t.joystickAxisReverse) value = 1.0 - value; + if (!pure) value = axisLinearity(value, t.joystickAxisLinearity); } else { - value = (float)axe.abs / (float)mJoy[t.joystickNumber]->MAX_AXIS; - switch (t.joystickAxisRegion) - { - case 0: - // normal case, full axis used - value = (value + 1) / 2; - break; - case -1: - // lower range used - if (value > 0) - value = 0; - else - value = -value; - break; - case 1: - // upper range used - if (value < 0) - value = 0; - break; - } - - if (t.joystickAxisHalf) - { - // XXX: TODO: write this - //float a = (double)((value+1.0)/2.0); - //float b = (double)(1.0-(value+1.0)/2.0); - //LOG("half: "+TOSTRING(value)+" / "+TOSTRING(a)+" / "+TOSTRING(b)); - //no dead zone in half axis - value = (1.0 + value) / 2.0; - if (t.joystickAxisReverse) - value = 1.0 - value; - if (!pure) - value = axisLinearity(value, t.joystickAxisLinearity); - } - else - { - //LOG("not half: "+TOSTRING(value)+" / "+TOSTRING(deadZone(value, t.joystickAxisDeadzone)) +" / "+TOSTRING(t.joystickAxisDeadzone) ); - if (t.joystickAxisReverse) - value = 1 - value; - if (!pure) + // LOG("not half: "+TOSTRING(value)+" / "+TOSTRING(deadZone(value, t.joystickAxisDeadzone)) +" / + // "+TOSTRING(t.joystickAxisDeadzone) ); + if (t.joystickAxisReverse) value = 1 - value; + if (!pure) // no deadzone when using oure value - value = deadZone(value, t.joystickAxisDeadzone); - if (!pure) - value = axisLinearity(value, t.joystickAxisLinearity); - } - // digital mapping of analog axis - if (t.joystickAxisUseDigital) - if (value >= 0.5) - value = 1; - else - value = 0; + value = deadZone(value, t.joystickAxisDeadzone); + if (!pure) value = axisLinearity(value, t.joystickAxisLinearity); } + // digital mapping of analog axis + if (t.joystickAxisUseDigital) + if (value >= 0.5) + value = 1; + else + value = 0; } - break; + } + break; case ET_JoystickSliderX: case ET_JoystickSliderY: + { + if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) { - if (t.joystickNumber > free_joysticks || !mJoy[t.joystickNumber]) - { - value = 0; - continue; - } - if (t.eventtype == ET_JoystickSliderX) - value = (float)joyState[t.joystickNumber].mSliders[t.joystickSliderNumber].abX / (float)mJoy[t.joystickNumber]->MAX_AXIS; - else if (t.eventtype == ET_JoystickSliderY) - value = (float)joyState[t.joystickNumber].mSliders[t.joystickSliderNumber].abY / (float)mJoy[t.joystickNumber]->MAX_AXIS; - value = (value + 1) / 2; // full axis - if (t.joystickSliderReverse) - value = 1.0 - value; // reversed + value = 0; + continue; } - break; + if (t.eventtype == ET_JoystickSliderX) + value = (float)joyState[t.joystickNumber].mSliders[t.joystickSliderNumber].abX / + (float)mJoy[t.joystickNumber]->MAX_AXIS; + else if (t.eventtype == ET_JoystickSliderY) + value = (float)joyState[t.joystickNumber].mSliders[t.joystickSliderNumber].abY / + (float)mJoy[t.joystickNumber]->MAX_AXIS; + value = (value + 1) / 2; // full axis + if (t.joystickSliderReverse) value = 1.0 - value; // reversed + } + break; } } // only return if grater zero, otherwise check all other bombinations - if (value > returnValue) - returnValue = value; + if (value > returnValue) returnValue = value; } return returnValue; } bool InputEngine::isKeyDown(OIS::KeyCode key) { - if (!mKeyboard) - return false; + if (!mKeyboard) return false; return this->mKeyboard->isKeyDown(key); } @@ -2727,8 +1218,7 @@ bool InputEngine::isKeyDownValueBounce(OIS::KeyCode mod, float time) else { bool res = isKeyDown(mod); - if (res) - event_times[-mod] = time; + if (res) event_times[-mod] = time; return res; } } @@ -2737,22 +1227,18 @@ String InputEngine::getDeviceName(event_trigger_t evt) { switch (evt.eventtype) { - case ET_NONE: - return "None"; - case ET_Keyboard: - return "Keyboard"; + case ET_NONE: return "None"; + case ET_Keyboard: return "Keyboard"; case ET_MouseButton: case ET_MouseAxisX: case ET_MouseAxisY: - case ET_MouseAxisZ: - return "Mouse"; + case ET_MouseAxisZ: return "Mouse"; case ET_JoystickButton: case ET_JoystickAxisAbs: case ET_JoystickAxisRel: case ET_JoystickPov: case ET_JoystickSliderX: - case ET_JoystickSliderY: - return "Joystick: " + getJoyVendor(evt.joystickNumber); + case ET_JoystickSliderY: return "Joystick: " + getJoyVendor(evt.joystickNumber); } return "unknown"; } @@ -2777,13 +1263,13 @@ String InputEngine::getEventTypeName(int type) return "unknown"; } -void InputEngine::addEvent(int eventID, event_trigger_t& t) +void InputEngine::addEvent(int eventID, event_trigger_t &t) { uniqueCounter++; t.suid = uniqueCounter; if (eventID == -1) - //unknown event, discard + // unknown event, discard return; if (events.find(eventID) == events.end()) { @@ -2793,10 +1279,10 @@ void InputEngine::addEvent(int eventID, event_trigger_t& t) events[eventID].push_back(t); } -void InputEngine::updateEvent(int eventID, const event_trigger_t& t) +void InputEngine::updateEvent(int eventID, const event_trigger_t &t) { if (eventID == -1) - //unknown event, discard + // unknown event, discard return; if (events.find(eventID) == events.end()) { @@ -2806,26 +1292,26 @@ void InputEngine::updateEvent(int eventID, const event_trigger_t& t) events[eventID].push_back(t); } -bool InputEngine::processLine(char* line, int deviceID) +bool InputEngine::processLine(char *line, int deviceID) { static String cur_comment = ""; - char eventName[256] = "", evtype[256] = ""; - const char delimiters[] = "+"; - size_t linelen = strnlen(line, 1024); - enum eventtypes eventtype = ET_NONE; + char eventName[256] = "", evtype[256] = ""; + const char delimiters[] = "+"; + size_t linelen = strnlen(line, 1024); + enum eventtypes eventtype = ET_NONE; - int joyNo = 0; - float defaultDeadzone = 0.1f; + int joyNo = 0; + float defaultDeadzone = 0.1f; float defaultLinearity = 1.0f; if (line[0] == ';' || linelen < 5) { - cur_comment += line;; + cur_comment += line; + ; return false; } sscanf(line, "%s %s", eventName, evtype); - if (strnlen(eventName, 255) == 0 || strnlen(evtype, 255) == 0) - return false; + if (strnlen(eventName, 255) == 0 || strnlen(evtype, 255) == 0) return false; if (!strncmp(evtype, "Keyboard", 8)) eventtype = ET_Keyboard; @@ -2841,7 +1327,7 @@ bool InputEngine::processLine(char* line, int deviceID) eventtype = ET_JoystickButton; else if (!strncmp(evtype, "JoystickAxis", 12)) eventtype = ET_JoystickAxisAbs; - //else if (!strncmp(evtype, "JoystickAxis", 250)) eventtype = ET_JoystickAxisRel; + // else if (!strncmp(evtype, "JoystickAxis", 250)) eventtype = ET_JoystickAxisRel; else if (!strncmp(evtype, "JoystickPov", 11)) eventtype = ET_JoystickPov; else if (!strncmp(evtype, "JoystickSlider", 14)) @@ -2856,201 +1342,194 @@ bool InputEngine::processLine(char* line, int deviceID) switch (eventtype) { case ET_Keyboard: - { - bool alt = false; - bool shift = false; - bool ctrl = false; - bool expl = false; + { + bool alt = false; + bool shift = false; + bool ctrl = false; + bool expl = false; - char* keycode = 0; - char keycodes[256] = {}; - char keycodes_work[256] = {}; + char *keycode = 0; + char keycodes[256] = {}; + char keycodes_work[256] = {}; - OIS::KeyCode key = KC_UNASSIGNED; + OIS::KeyCode key = KC_UNASSIGNED; - sscanf(line, "%s %s %s", eventName, evtype, keycodes); - // separate all keys and construct the key combination - //LOG("try to add key: " + String(eventName)+","+ String(evtype)+","+String(keycodes)); - strncpy(keycodes_work, keycodes, 255); - keycodes_work[255] = '\0'; - char* token = strtok(keycodes_work, delimiters); + sscanf(line, "%s %s %s", eventName, evtype, keycodes); + // separate all keys and construct the key combination + // LOG("try to add key: " + String(eventName)+","+ String(evtype)+","+String(keycodes)); + strncpy(keycodes_work, keycodes, 255); + keycodes_work[255] = '\0'; + char *token = strtok(keycodes_work, delimiters); - while (token != NULL) - { - if (strncmp(token, "SHIFT", 5) == 0) - shift = true; - else if (strncmp(token, "CTRL", 4) == 0) - ctrl = true; - else if (strncmp(token, "ALT", 3) == 0) - alt = true; - else if (strncmp(token, "EXPL", 4) == 0) - expl = true; - keycode = token; - token = strtok(NULL, delimiters); - } + while (token != NULL) + { + if (strncmp(token, "SHIFT", 5) == 0) + shift = true; + else if (strncmp(token, "CTRL", 4) == 0) + ctrl = true; + else if (strncmp(token, "ALT", 3) == 0) + alt = true; + else if (strncmp(token, "EXPL", 4) == 0) + expl = true; + keycode = token; + token = strtok(NULL, delimiters); + } - allit = allkeys.find(keycode); - if (allit == allkeys.end()) - { + allit = allkeys.find(keycode); + if (allit == allkeys.end()) + { #ifndef NOOGRE - LOG("unknown key: " + string(keycodes)); + LOG("unknown key: " + string(keycodes)); #endif - key = KC_UNASSIGNED; - } - else - { - //LOG("found key: " + string(keycode) + " = " + TOSTRING((int)key)); - key = allit->second; - } - int eventID = resolveEventName(String(eventName)); - if (eventID == -1) - { - LOG("Error while processing input config: Unknown Event: "+String(eventName)); - return false; - } - event_trigger_t t_key = newEvent(); - //memset(&t_key, 0, sizeof(event_trigger_t)); - t_key.eventtype = ET_Keyboard; - t_key.shift = shift; - t_key.ctrl = ctrl; - t_key.alt = alt; - t_key.keyCode = key; - t_key.explicite = expl; - - strncpy(t_key.configline, keycodes, 128); - strncpy(t_key.group, getEventGroup(eventName).c_str(), 128); - strncpy(t_key.tmp_eventname, eventName, 128); - - strncpy(t_key.comments, cur_comment.c_str(), 1024); - addEvent(eventID, t_key); - - return true; + key = KC_UNASSIGNED; + } + else + { + // LOG("found key: " + string(keycode) + " = " + TOSTRING((int)key)); + key = allit->second; + } + int eventID = resolveEventName(String(eventName)); + if (eventID == -1) + { + LOG("Error while processing input config: Unknown Event: " + String(eventName)); + return false; } + event_trigger_t t_key = newEvent(); + // memset(&t_key, 0, sizeof(event_trigger_t)); + t_key.eventtype = ET_Keyboard; + t_key.shift = shift; + t_key.ctrl = ctrl; + t_key.alt = alt; + t_key.keyCode = key; + t_key.explicite = expl; + + strncpy(t_key.configline, keycodes, 128); + strncpy(t_key.group, getEventGroup(eventName).c_str(), 128); + strncpy(t_key.tmp_eventname, eventName, 128); + + strncpy(t_key.comments, cur_comment.c_str(), 1024); + addEvent(eventID, t_key); + + return true; + } case ET_JoystickButton: + { + int buttonNo = 0; + char tmp2[256] = {}; + sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &buttonNo, tmp2); + event_trigger_t t_joy = newEvent(); + // memset(&t_joy, 0, sizeof(event_trigger_t)); + int eventID = resolveEventName(String(eventName)); + if (eventID == -1) return false; + t_joy.eventtype = ET_JoystickButton; + t_joy.joystickNumber = (deviceID == -1 ? joyNo : deviceID); + t_joy.joystickButtonNumber = buttonNo; + if (!strcmp(tmp2, "!NEW!")) { strncpy(t_joy.configline, tmp2, 128); } + else { - int buttonNo = 0; - char tmp2[256] = {}; - sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &buttonNo, tmp2); - event_trigger_t t_joy = newEvent(); - //memset(&t_joy, 0, sizeof(event_trigger_t)); - int eventID = resolveEventName(String(eventName)); - if (eventID == -1) - return false; - t_joy.eventtype = ET_JoystickButton; - t_joy.joystickNumber = (deviceID == -1 ? joyNo : deviceID); - t_joy.joystickButtonNumber = buttonNo; - if (!strcmp(tmp2, "!NEW!")) - { - strncpy(t_joy.configline, tmp2, 128); - } - else - { - char tmp[256] = {}; - sprintf(tmp, "%d", buttonNo); - strncpy(t_joy.configline, tmp, 128); - } - strncpy(t_joy.group, getEventGroup(eventName).c_str(), 128); - strncpy(t_joy.tmp_eventname, eventName, 128); - strncpy(t_joy.comments, cur_comment.c_str(), 1024); - cur_comment = ""; - addEvent(eventID, t_joy); - return true; + char tmp[256] = {}; + sprintf(tmp, "%d", buttonNo); + strncpy(t_joy.configline, tmp, 128); } + strncpy(t_joy.group, getEventGroup(eventName).c_str(), 128); + strncpy(t_joy.tmp_eventname, eventName, 128); + strncpy(t_joy.comments, cur_comment.c_str(), 1024); + cur_comment = ""; + addEvent(eventID, t_joy); + return true; + } case ET_JoystickAxisRel: case ET_JoystickAxisAbs: + { + int axisNo = 0; + char options[256] = {}; + sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &axisNo, options); + int eventID = resolveEventName(String(eventName)); + if (eventID == -1) return false; + + bool half = false; + bool reverse = false; + bool linear = false; + bool relative = false; + bool usedigital = false; + float deadzone = defaultDeadzone; + float linearity = defaultLinearity; + int jAxisRegion = 0; + // 0 = all + // -1 = lower + // 1 = upper + char tmp[256] = {}; + strcpy(tmp, options); + tmp[255] = '\0'; + char *token = strtok(tmp, delimiters); + while (token != NULL) { - int axisNo = 0; - char options[256] = {}; - sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &axisNo, options); - int eventID = resolveEventName(String(eventName)); - if (eventID == -1) - return false; - - bool half = false; - bool reverse = false; - bool linear = false; - bool relative = false; - bool usedigital = false; - float deadzone = defaultDeadzone; - float linearity = defaultLinearity; - int jAxisRegion = 0; - // 0 = all - // -1 = lower - // 1 = upper - char tmp[256] = {}; - strcpy(tmp, options); - tmp[255] = '\0'; - char* token = strtok(tmp, delimiters); - while (token != NULL) + if (strncmp(token, "HALF", 4) == 0) + half = true; + else if (strncmp(token, "REVERSE", 7) == 0) + reverse = true; + else if (strncmp(token, "LINEAR", 6) == 0) + linear = true; + else if (strncmp(token, "UPPER", 5) == 0) + jAxisRegion = 1; + else if (strncmp(token, "LOWER", 5) == 0) + jAxisRegion = -1; + else if (strncmp(token, "RELATIVE", 8) == 0) + relative = true; + else if (strncmp(token, "DIGITAL", 7) == 0) + usedigital = true; + else if (strncmp(token, "DEADZONE", 8) == 0 && strnlen(token, 250) > 9) { - if (strncmp(token, "HALF", 4) == 0) - half = true; - else if (strncmp(token, "REVERSE", 7) == 0) - reverse = true; - else if (strncmp(token, "LINEAR", 6) == 0) - linear = true; - else if (strncmp(token, "UPPER", 5) == 0) - jAxisRegion = 1; - else if (strncmp(token, "LOWER", 5) == 0) - jAxisRegion = -1; - else if (strncmp(token, "RELATIVE", 8) == 0) - relative = true; - else if (strncmp(token, "DIGITAL", 7) == 0) - usedigital = true; - else if (strncmp(token, "DEADZONE", 8) == 0 && strnlen(token, 250) > 9) - { - char tmp2[256] = {}; - strcpy(tmp2, token + 9); - deadzone = atof(tmp2); - //LOG("got deadzone: " + TOSTRING(deadzone)+", "+String(tmp2)); - } - else if (strncmp(token, "LINEARITY", 9) == 0 && strnlen(token, 250) > 10) - { - char tmp2[256] = {}; - strcpy(tmp2, token + 10); - linearity = atof(tmp2); - } - token = strtok(NULL, delimiters); + char tmp2[256] = {}; + strcpy(tmp2, token + 9); + deadzone = atof(tmp2); + // LOG("got deadzone: " + TOSTRING(deadzone)+", "+String(tmp2)); } - - if (relative) - eventtype = ET_JoystickAxisRel; - - event_trigger_t t_joy = newEvent(); - //memset(&t_joy, 0, sizeof(event_trigger_t)); - t_joy.eventtype = eventtype; - t_joy.joystickAxisRegion = jAxisRegion; - t_joy.joystickAxisUseDigital = usedigital; - t_joy.joystickAxisDeadzone = deadzone; - t_joy.joystickAxisHalf = half; - t_joy.joystickAxisLinearity = linearity; - t_joy.joystickAxisReverse = reverse; - t_joy.joystickAxisNumber = axisNo; - t_joy.joystickNumber = (deviceID == -1 ? joyNo : deviceID); - strncpy(t_joy.configline, options, 128); - strncpy(t_joy.group, getEventGroup(eventName).c_str(), 128); - strncpy(t_joy.tmp_eventname, eventName, 128); - strncpy(t_joy.comments, cur_comment.c_str(), 1024); - cur_comment = ""; - addEvent(eventID, t_joy); - //LOG("added axis: " + TOSTRING(axisNo)); - return true; + else if (strncmp(token, "LINEARITY", 9) == 0 && strnlen(token, 250) > 10) + { + char tmp2[256] = {}; + strcpy(tmp2, token + 10); + linearity = atof(tmp2); + } + token = strtok(NULL, delimiters); } + + if (relative) eventtype = ET_JoystickAxisRel; + + event_trigger_t t_joy = newEvent(); + // memset(&t_joy, 0, sizeof(event_trigger_t)); + t_joy.eventtype = eventtype; + t_joy.joystickAxisRegion = jAxisRegion; + t_joy.joystickAxisUseDigital = usedigital; + t_joy.joystickAxisDeadzone = deadzone; + t_joy.joystickAxisHalf = half; + t_joy.joystickAxisLinearity = linearity; + t_joy.joystickAxisReverse = reverse; + t_joy.joystickAxisNumber = axisNo; + t_joy.joystickNumber = (deviceID == -1 ? joyNo : deviceID); + strncpy(t_joy.configline, options, 128); + strncpy(t_joy.group, getEventGroup(eventName).c_str(), 128); + strncpy(t_joy.tmp_eventname, eventName, 128); + strncpy(t_joy.comments, cur_comment.c_str(), 1024); + cur_comment = ""; + addEvent(eventID, t_joy); + // LOG("added axis: " + TOSTRING(axisNo)); + return true; + } case ET_NONE: - { - int eventID = resolveEventName(String(eventName)); - if (eventID == -1) - return false; - event_trigger_t t_none = newEvent(); - t_none.eventtype = eventtype; - //t_none.configline = ""; - strncpy(t_none.group, getEventGroup(eventName).c_str(), 128); - strncpy(t_none.tmp_eventname, eventName, 128); - strncpy(t_none.comments, cur_comment.c_str(), 1024); - cur_comment = ""; - addEvent(eventID, t_none); - return true; - } + { + int eventID = resolveEventName(String(eventName)); + if (eventID == -1) return false; + event_trigger_t t_none = newEvent(); + t_none.eventtype = eventtype; + // t_none.configline = ""; + strncpy(t_none.group, getEventGroup(eventName).c_str(), 128); + strncpy(t_none.tmp_eventname, eventName, 128); + strncpy(t_none.comments, cur_comment.c_str(), 1024); + cur_comment = ""; + addEvent(eventID, t_none); + return true; + } case ET_MouseButton: case ET_MouseAxisX: case ET_MouseAxisY: @@ -3058,98 +1537,86 @@ bool InputEngine::processLine(char* line, int deviceID) // no mouse support D: return false; case ET_JoystickPov: - { - int povNumber = 0; - char dir[256] = {}; - sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &povNumber, dir); - int eventID = resolveEventName(String(eventName)); - if (eventID == -1) - return false; - - int direction = OIS::Pov::Centered; - if (!strcmp(dir, "North")) - direction = OIS::Pov::North; - if (!strcmp(dir, "South")) - direction = OIS::Pov::South; - if (!strcmp(dir, "East")) - direction = OIS::Pov::East; - if (!strcmp(dir, "West")) - direction = OIS::Pov::West; - if (!strcmp(dir, "NorthEast")) - direction = OIS::Pov::NorthEast; - if (!strcmp(dir, "SouthEast")) - direction = OIS::Pov::SouthEast; - if (!strcmp(dir, "NorthWest")) - direction = OIS::Pov::NorthWest; - if (!strcmp(dir, "SouthWest")) - direction = OIS::Pov::SouthWest; - - event_trigger_t t_pov = newEvent(); - t_pov.eventtype = eventtype; - t_pov.joystickNumber = (deviceID == -1 ? joyNo : deviceID); - t_pov.joystickPovNumber = povNumber; - t_pov.joystickPovDirection = direction; - - strncpy(t_pov.group, getEventGroup(eventName).c_str(), 128); - strncpy(t_pov.tmp_eventname, eventName, 128); - strncpy(t_pov.comments, cur_comment.c_str(), 1024); - cur_comment = ""; - addEvent(eventID, t_pov); - //LOG("added axis: " + TOSTRING(axisNo)); - return true; - } + { + int povNumber = 0; + char dir[256] = {}; + sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &povNumber, dir); + int eventID = resolveEventName(String(eventName)); + if (eventID == -1) return false; + + int direction = OIS::Pov::Centered; + if (!strcmp(dir, "North")) direction = OIS::Pov::North; + if (!strcmp(dir, "South")) direction = OIS::Pov::South; + if (!strcmp(dir, "East")) direction = OIS::Pov::East; + if (!strcmp(dir, "West")) direction = OIS::Pov::West; + if (!strcmp(dir, "NorthEast")) direction = OIS::Pov::NorthEast; + if (!strcmp(dir, "SouthEast")) direction = OIS::Pov::SouthEast; + if (!strcmp(dir, "NorthWest")) direction = OIS::Pov::NorthWest; + if (!strcmp(dir, "SouthWest")) direction = OIS::Pov::SouthWest; + + event_trigger_t t_pov = newEvent(); + t_pov.eventtype = eventtype; + t_pov.joystickNumber = (deviceID == -1 ? joyNo : deviceID); + t_pov.joystickPovNumber = povNumber; + t_pov.joystickPovDirection = direction; + + strncpy(t_pov.group, getEventGroup(eventName).c_str(), 128); + strncpy(t_pov.tmp_eventname, eventName, 128); + strncpy(t_pov.comments, cur_comment.c_str(), 1024); + cur_comment = ""; + addEvent(eventID, t_pov); + // LOG("added axis: " + TOSTRING(axisNo)); + return true; + } case ET_JoystickSliderX: case ET_JoystickSliderY: - { - int sliderNumber = 0; - char options[256] = {}; - char type; - sscanf(line, "%s %s %d %c %d %s", eventName, evtype, &joyNo, &type, &sliderNumber, options); - int eventID = resolveEventName(String(eventName)); - if (eventID == -1) - return false; - - bool reverse = false; - char tmp[256] = {}; - strncpy(tmp, options, 255); - tmp[255] = '\0'; - char* token = strtok(tmp, delimiters); - while (token != NULL) - { - if (strncmp(token, "REVERSE", 7) == 0) - reverse = true; + { + int sliderNumber = 0; + char options[256] = {}; + char type; + sscanf(line, "%s %s %d %c %d %s", eventName, evtype, &joyNo, &type, &sliderNumber, options); + int eventID = resolveEventName(String(eventName)); + if (eventID == -1) return false; - token = strtok(NULL, delimiters); - } + bool reverse = false; + char tmp[256] = {}; + strncpy(tmp, options, 255); + tmp[255] = '\0'; + char *token = strtok(tmp, delimiters); + while (token != NULL) + { + if (strncmp(token, "REVERSE", 7) == 0) reverse = true; - event_trigger_t t_slider = newEvent(); - - if (type == 'Y' || type == 'y') - eventtype = ET_JoystickSliderY; - else if (type == 'X' || type == 'x') - eventtype = ET_JoystickSliderX; - - t_slider.eventtype = eventtype; - t_slider.joystickNumber = (deviceID == -1 ? joyNo : deviceID); - t_slider.joystickSliderNumber = sliderNumber; - t_slider.joystickSliderReverse = reverse; - // TODO: add region support to sliders! - t_slider.joystickSliderRegion = 0; - strncpy(t_slider.configline, options, 128); - strncpy(t_slider.group, getEventGroup(eventName).c_str(), 128); - strncpy(t_slider.tmp_eventname, eventName, 128); - strncpy(t_slider.comments, cur_comment.c_str(), 1024); - cur_comment = ""; - addEvent(eventID, t_slider); - //LOG("added axis: " + TOSTRING(axisNo)); - return true; + token = strtok(NULL, delimiters); } - default: - return false; + + event_trigger_t t_slider = newEvent(); + + if (type == 'Y' || type == 'y') + eventtype = ET_JoystickSliderY; + else if (type == 'X' || type == 'x') + eventtype = ET_JoystickSliderX; + + t_slider.eventtype = eventtype; + t_slider.joystickNumber = (deviceID == -1 ? joyNo : deviceID); + t_slider.joystickSliderNumber = sliderNumber; + t_slider.joystickSliderReverse = reverse; + // TODO: add region support to sliders! + t_slider.joystickSliderRegion = 0; + strncpy(t_slider.configline, options, 128); + strncpy(t_slider.group, getEventGroup(eventName).c_str(), 128); + strncpy(t_slider.tmp_eventname, eventName, 128); + strncpy(t_slider.comments, cur_comment.c_str(), 1024); + cur_comment = ""; + addEvent(eventID, t_slider); + // LOG("added axis: " + TOSTRING(axisNo)); + return true; + } + default: return false; } } -int InputEngine::getCurrentJoyButton(int& joystickNumber, int& button) +int InputEngine::getCurrentJoyButton(int &joystickNumber, int &button) { for (int j = 0; j < free_joysticks; j++) { @@ -3158,7 +1625,7 @@ int InputEngine::getCurrentJoyButton(int& joystickNumber, int& button) if (joyState[j].mButtons[i]) { joystickNumber = j; - button = i; + button = i; return 1; } } @@ -3166,7 +1633,7 @@ int InputEngine::getCurrentJoyButton(int& joystickNumber, int& button) return 0; } -int InputEngine::getCurrentPovValue(int& joystickNumber, int& pov, int& povdir) +int InputEngine::getCurrentPovValue(int &joystickNumber, int &pov, int &povdir) { for (int j = 0; j < free_joysticks; j++) { @@ -3175,8 +1642,8 @@ int InputEngine::getCurrentPovValue(int& joystickNumber, int& pov, int& povdir) if (joyState[j].mPOV[i].direction != Pov::Centered) { joystickNumber = j; - pov = i; - povdir = joyState[j].mPOV[i].direction; + pov = i; + povdir = joyState[j].mPOV[i].direction; return 1; } } @@ -3193,37 +1660,35 @@ event_trigger_t InputEngine::newEvent() int InputEngine::getJoyComponentCount(OIS::ComponentType type, int joystickNumber) { - if (joystickNumber > free_joysticks || !mJoy[joystickNumber]) - return 0; + if (joystickNumber > free_joysticks || !mJoy[joystickNumber]) return 0; return mJoy[joystickNumber]->getNumberOfComponents(type); } std::string InputEngine::getJoyVendor(int joystickNumber) { - if (joystickNumber > free_joysticks || !mJoy[joystickNumber]) - return "unknown"; + if (joystickNumber > free_joysticks || !mJoy[joystickNumber]) return "unknown"; return mJoy[joystickNumber]->vendor(); } -JoyStickState* InputEngine::getCurrentJoyState(int joystickNumber) +JoyStickState *InputEngine::getCurrentJoyState(int joystickNumber) { - if (joystickNumber > free_joysticks) - return 0; + if (joystickNumber > free_joysticks) return 0; return &joyState[joystickNumber]; } -int InputEngine::getCurrentKeyCombo(String* combo) +int InputEngine::getCurrentKeyCombo(String *combo) { std::map::iterator i; - int keyCounter = 0; - int modCounter = 0; + int keyCounter = 0; + int modCounter = 0; // list all modificators first for (i = keyState.begin(); i != keyState.end(); i++) { if (i->second) { - if (i->first != KC_LSHIFT && i->first != KC_RSHIFT && i->first != KC_LCONTROL && i->first != KC_RCONTROL && i->first != KC_LMENU && i->first != KC_RMENU) + if (i->first != KC_LSHIFT && i->first != KC_RSHIFT && i->first != KC_LCONTROL && i->first != KC_RCONTROL && + i->first != KC_LMENU && i->first != KC_RMENU) continue; modCounter++; String keyName = getKeyNameForKeyCode((OIS::KeyCode)i->first); @@ -3239,7 +1704,8 @@ int InputEngine::getCurrentKeyCombo(String* combo) { if (i->second) { - if (i->first == KC_LSHIFT || i->first == KC_RSHIFT || i->first == KC_LCONTROL || i->first == KC_RCONTROL || i->first == KC_LMENU || i->first == KC_RMENU) + if (i->first == KC_LSHIFT || i->first == KC_RSHIFT || i->first == KC_LCONTROL || i->first == KC_RCONTROL || + i->first == KC_LMENU || i->first == KC_RMENU) continue; String keyName = getKeyNameForKeyCode((OIS::KeyCode)i->first); if (*combo == "") @@ -3251,10 +1717,7 @@ int InputEngine::getCurrentKeyCombo(String* combo) } // - if (modCounter > 0 && keyCounter == 0) - { - return -modCounter; - } + if (modCounter > 0 && keyCounter == 0) { return -modCounter; } else if (keyCounter == 0 && modCounter == 0) { *combo = "(Please press a key)"; @@ -3266,10 +1729,10 @@ int InputEngine::getCurrentKeyCombo(String* combo) String InputEngine::getEventGroup(String eventName) { const char delimiters[] = "_"; - char tmp[256] = {}; + char tmp[256] = {}; strncpy(tmp, eventName.c_str(), 255); - tmp[255] = '\0'; - char* token = strtok(tmp, delimiters); + tmp[255] = '\0'; + char *token = strtok(tmp, delimiters); while (token != NULL) { return String(token); @@ -3279,9 +1742,8 @@ String InputEngine::getEventGroup(String eventName) bool InputEngine::appendLineToConfig(std::string line, std::string outfile) { - FILE* f = fopen(const_cast(outfile.c_str()), "a"); - if (!f) - return false; + FILE *f = fopen(const_cast(outfile.c_str()), "a"); + if (!f) return false; fprintf(f, "%s\n", line.c_str()); fclose(f); return true; @@ -3294,7 +1756,7 @@ bool InputEngine::reloadConfig(std::string outfile) return true; } -bool InputEngine::updateConfigline(event_trigger_t* t) +bool InputEngine::updateConfigline(event_trigger_t *t) { if (t->eventtype != ET_JoystickAxisAbs && t->eventtype != ET_JoystickSliderX && t->eventtype != ET_JoystickSliderY) return false; @@ -3368,9 +1830,8 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) // -2 = keyboard // -3 = mouse // >0 joystick - FILE* f = fopen(const_cast(outfile.c_str()), "w"); - if (!f) - return false; + FILE *f = fopen(const_cast(outfile.c_str()), "w"); + if (!f) return false; bool created = false; @@ -3381,23 +1842,26 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) created = true; } - int counter = 0; - char curGroup[128] = ""; - std::map> controls = getEvents(); + int counter = 0; + char curGroup[128] = ""; + std::map> controls = getEvents(); std::map>::iterator mapIt; - std::vector::iterator vecIt; + std::vector::iterator vecIt; for (mapIt = controls.begin(); mapIt != controls.end(); mapIt++) { std::vector vec = mapIt->second; - for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++ , counter++) + for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++, counter++) { // filters - if (vecIt->eventtype == ET_Keyboard && joyNum != -10 && joyNum != -2) + if (vecIt->eventtype == ET_Keyboard && joyNum != -10 && joyNum != -2) continue; + if ((vecIt->eventtype == ET_MouseAxisX || vecIt->eventtype == ET_MouseAxisY || vecIt->eventtype == ET_MouseAxisZ) && + joyNum != -10 && joyNum != -3) continue; - if ((vecIt->eventtype == ET_MouseAxisX || vecIt->eventtype == ET_MouseAxisY || vecIt->eventtype == ET_MouseAxisZ) && joyNum != -10 && joyNum != -3) - continue; - if ((vecIt->eventtype == ET_JoystickAxisAbs || vecIt->eventtype == ET_JoystickAxisRel || vecIt->eventtype == ET_JoystickButton || vecIt->eventtype == ET_JoystickPov || vecIt->eventtype == ET_JoystickSliderX || vecIt->eventtype == ET_JoystickSliderY) && joyNum >= 0 && vecIt->joystickNumber != joyNum) + if ((vecIt->eventtype == ET_JoystickAxisAbs || vecIt->eventtype == ET_JoystickAxisRel || + vecIt->eventtype == ET_JoystickButton || vecIt->eventtype == ET_JoystickPov || + vecIt->eventtype == ET_JoystickSliderX || vecIt->eventtype == ET_JoystickSliderY) && + joyNum >= 0 && vecIt->joystickNumber != joyNum) continue; if (strcmp(vecIt->group, curGroup)) @@ -3408,7 +1872,7 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) } // no user comments for now! - //if (vecIt->comments!="") + // if (vecIt->comments!="") // fprintf(f, "%s", vecIt->comments.c_str()); // print event name @@ -3416,10 +1880,7 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) // print event type fprintf(f, "%-20s ", getEventTypeName(vecIt->eventtype).c_str()); - if (vecIt->eventtype == ET_Keyboard) - { - fprintf(f, "%s ", vecIt->configline); - } + if (vecIt->eventtype == ET_Keyboard) { fprintf(f, "%s ", vecIt->configline); } else if (vecIt->eventtype == ET_JoystickAxisAbs || vecIt->eventtype == ET_JoystickAxisRel) { fprintf(f, "%d ", vecIt->joystickNumber); @@ -3430,8 +1891,7 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) { fprintf(f, "%d ", vecIt->joystickNumber); char type = 'X'; - if (vecIt->eventtype == ET_JoystickSliderY) - type = 'Y'; + if (vecIt->eventtype == ET_JoystickSliderY) type = 'Y'; fprintf(f, "%c ", type); fprintf(f, "%d ", vecIt->joystickSliderNumber); fprintf(f, "%s ", vecIt->configline); @@ -3443,23 +1903,15 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) } else if (vecIt->eventtype == ET_JoystickPov) { - const char* dirStr = "North"; - if (vecIt->joystickPovDirection == OIS::Pov::North) - dirStr = "North"; - if (vecIt->joystickPovDirection == OIS::Pov::South) - dirStr = "South"; - if (vecIt->joystickPovDirection == OIS::Pov::East) - dirStr = "East"; - if (vecIt->joystickPovDirection == OIS::Pov::West) - dirStr = "West"; - if (vecIt->joystickPovDirection == OIS::Pov::NorthEast) - dirStr = "NorthEast"; - if (vecIt->joystickPovDirection == OIS::Pov::SouthEast) - dirStr = "SouthEast"; - if (vecIt->joystickPovDirection == OIS::Pov::NorthWest) - dirStr = "NorthWest"; - if (vecIt->joystickPovDirection == OIS::Pov::SouthWest) - dirStr = "SouthWest"; + const char *dirStr = "North"; + if (vecIt->joystickPovDirection == OIS::Pov::North) dirStr = "North"; + if (vecIt->joystickPovDirection == OIS::Pov::South) dirStr = "South"; + if (vecIt->joystickPovDirection == OIS::Pov::East) dirStr = "East"; + if (vecIt->joystickPovDirection == OIS::Pov::West) dirStr = "West"; + if (vecIt->joystickPovDirection == OIS::Pov::NorthEast) dirStr = "NorthEast"; + if (vecIt->joystickPovDirection == OIS::Pov::SouthEast) dirStr = "SouthEast"; + if (vecIt->joystickPovDirection == OIS::Pov::NorthWest) dirStr = "NorthWest"; + if (vecIt->joystickPovDirection == OIS::Pov::SouthWest) dirStr = "SouthWest"; fprintf(f, "%d %d %s", vecIt->joystickNumber, vecIt->joystickPovNumber, dirStr); } @@ -3473,23 +1925,20 @@ bool InputEngine::saveMapping(String outfile, String hwnd, int joyNum) void InputEngine::completeMissingEvents() { - if (!mappingLoaded) - return; + if (!mappingLoaded) return; for (int i = 0; i < EV_MODE_LAST; i++) { if (events.find(eventInfo[i].eventID) == events.end()) { - if (eventInfo[i].defaultKey.empty()) - continue; - if (eventInfo[i].defaultKey == "None") - continue; + if (eventInfo[i].defaultKey.empty()) continue; + if (eventInfo[i].defaultKey == "None") continue; // not existing, insert default char tmp[256] = ""; sprintf(tmp, "%s %s", eventInfo[i].name.c_str(), eventInfo[i].defaultKey.c_str()); #ifndef NOOGRE - //LOG("event mapping not existing, using default: '" + String(tmp) + "'"); + // LOG("event mapping not existing, using default: '" + String(tmp) + "'"); #endif processLine(tmp); } @@ -3499,7 +1948,7 @@ void InputEngine::completeMissingEvents() bool InputEngine::loadMapping(String outfile, bool append, int deviceID) { char line[1025] = ""; - int oldState = uniqueCounter; + int oldState = uniqueCounter; if (!append) { @@ -3523,23 +1972,18 @@ bool InputEngine::loadMapping(String outfile, bool append, int deviceID) while (!ds->eof()) { size_t size = 1024; - if (ds->tell() + size >= ds->size()) - size = ds->size() - ds->tell(); - if (ds->tell() >= ds->size()) - break; + if (ds->tell() + size >= ds->size()) size = ds->size() - ds->tell(); + if (ds->tell() >= ds->size()) break; size_t readnum = ds->readLine(line, size); - if (readnum > 5) - processLine(line, deviceID); + if (readnum > 5) processLine(line, deviceID); } } #else FILE *f = fopen(outfile.c_str(), "r"); - if (!f) - return false; - while(fgets(line, 1024, f)!=NULL) + if (!f) return false; + while (fgets(line, 1024, f) != NULL) { - if (strnlen(line, 1024) > 5) - processLine(line); + if (strnlen(line, 1024) > 5) processLine(line); } fclose(f); @@ -3557,8 +2001,7 @@ int InputEngine::resolveEventName(String eventName) int i = 0; while (i != EV_MODE_LAST) { - if (eventInfo[i].name == eventName) - return eventInfo[i].eventID; + if (eventInfo[i].name == eventName) return eventInfo[i].eventID; i++; } #ifndef NOOGRE @@ -3572,8 +2015,7 @@ String InputEngine::eventIDToName(int eventID) int i = 0; while (i != EV_MODE_LAST) { - if (eventInfo[i].eventID == eventID) - return eventInfo[i].name; + if (eventInfo[i].eventID == eventID) return eventInfo[i].name; i++; } return "unknown"; @@ -3581,151 +2023,151 @@ String InputEngine::eventIDToName(int eventID) void InputEngine::initAllKeys() { - allkeys["0"] = KC_0; - allkeys["1"] = KC_1; - allkeys["2"] = KC_2; - allkeys["3"] = KC_3; - allkeys["4"] = KC_4; - allkeys["5"] = KC_5; - allkeys["6"] = KC_6; - allkeys["7"] = KC_7; - allkeys["8"] = KC_8; - allkeys["9"] = KC_9; - allkeys["A"] = KC_A; - allkeys["ABNT_C1"] = KC_ABNT_C1; - allkeys["ABNT_C2"] = KC_ABNT_C2; - allkeys["ADD"] = KC_ADD; - allkeys["APOSTROPHE"] = KC_APOSTROPHE; - allkeys["APPS"] = KC_APPS; - allkeys["AT"] = KC_AT; - allkeys["AX"] = KC_AX; - allkeys["B"] = KC_B; - allkeys["BACK"] = KC_BACK; - allkeys["BACKSLASH"] = KC_BACKSLASH; - allkeys["C"] = KC_C; - allkeys["CALCULATOR"] = KC_CALCULATOR; - allkeys["CAPITAL"] = KC_CAPITAL; - allkeys["COLON"] = KC_COLON; - allkeys["COMMA"] = KC_COMMA; - allkeys["CONVERT"] = KC_CONVERT; - allkeys["D"] = KC_D; - allkeys["DECIMAL"] = KC_DECIMAL; - allkeys["DELETE"] = KC_DELETE; - allkeys["DIVIDE"] = KC_DIVIDE; - allkeys["DOWN"] = KC_DOWN; - allkeys["E"] = KC_E; - allkeys["END"] = KC_END; - allkeys["EQUALS"] = KC_EQUALS; - allkeys["ESCAPE"] = KC_ESCAPE; - allkeys["F"] = KC_F; - allkeys["F1"] = KC_F1; - allkeys["F10"] = KC_F10; - allkeys["F11"] = KC_F11; - allkeys["F12"] = KC_F12; - allkeys["F13"] = KC_F13; - allkeys["F14"] = KC_F14; - allkeys["F15"] = KC_F15; - allkeys["F2"] = KC_F2; - allkeys["F3"] = KC_F3; - allkeys["F4"] = KC_F4; - allkeys["F5"] = KC_F5; - allkeys["F6"] = KC_F6; - allkeys["F7"] = KC_F7; - allkeys["F8"] = KC_F8; - allkeys["F9"] = KC_F9; - allkeys["G"] = KC_G; - allkeys["GRAVE"] = KC_GRAVE; - allkeys["H"] = KC_H; - allkeys["HOME"] = KC_HOME; - allkeys["I"] = KC_I; - allkeys["INSERT"] = KC_INSERT; - allkeys["J"] = KC_J; - allkeys["K"] = KC_K; - allkeys["KANA"] = KC_KANA; - allkeys["KANJI"] = KC_KANJI; - allkeys["L"] = KC_L; - allkeys["LBRACKET"] = KC_LBRACKET; - allkeys["LCONTROL"] = KC_LCONTROL; - allkeys["LEFT"] = KC_LEFT; - allkeys["LMENU"] = KC_LMENU; - allkeys["LSHIFT"] = KC_LSHIFT; - allkeys["LWIN"] = KC_LWIN; - allkeys["M"] = KC_M; - allkeys["MAIL"] = KC_MAIL; - allkeys["MEDIASELECT"] = KC_MEDIASELECT; - allkeys["MEDIASTOP"] = KC_MEDIASTOP; - allkeys["MINUS"] = KC_MINUS; - allkeys["MULTIPLY"] = KC_MULTIPLY; - allkeys["MUTE"] = KC_MUTE; - allkeys["MYCOMPUTER"] = KC_MYCOMPUTER; - allkeys["N"] = KC_N; - allkeys["NEXTTRACK"] = KC_NEXTTRACK; - allkeys["NOCONVERT"] = KC_NOCONVERT; - allkeys["NUMLOCK"] = KC_NUMLOCK; - allkeys["NUMPAD0"] = KC_NUMPAD0; - allkeys["NUMPAD1"] = KC_NUMPAD1; - allkeys["NUMPAD2"] = KC_NUMPAD2; - allkeys["NUMPAD3"] = KC_NUMPAD3; - allkeys["NUMPAD4"] = KC_NUMPAD4; - allkeys["NUMPAD5"] = KC_NUMPAD5; - allkeys["NUMPAD6"] = KC_NUMPAD6; - allkeys["NUMPAD7"] = KC_NUMPAD7; - allkeys["NUMPAD8"] = KC_NUMPAD8; - allkeys["NUMPAD9"] = KC_NUMPAD9; - allkeys["NUMPADCOMMA"] = KC_NUMPADCOMMA; - allkeys["NUMPADENTER"] = KC_NUMPADENTER; + allkeys["0"] = KC_0; + allkeys["1"] = KC_1; + allkeys["2"] = KC_2; + allkeys["3"] = KC_3; + allkeys["4"] = KC_4; + allkeys["5"] = KC_5; + allkeys["6"] = KC_6; + allkeys["7"] = KC_7; + allkeys["8"] = KC_8; + allkeys["9"] = KC_9; + allkeys["A"] = KC_A; + allkeys["ABNT_C1"] = KC_ABNT_C1; + allkeys["ABNT_C2"] = KC_ABNT_C2; + allkeys["ADD"] = KC_ADD; + allkeys["APOSTROPHE"] = KC_APOSTROPHE; + allkeys["APPS"] = KC_APPS; + allkeys["AT"] = KC_AT; + allkeys["AX"] = KC_AX; + allkeys["B"] = KC_B; + allkeys["BACK"] = KC_BACK; + allkeys["BACKSLASH"] = KC_BACKSLASH; + allkeys["C"] = KC_C; + allkeys["CALCULATOR"] = KC_CALCULATOR; + allkeys["CAPITAL"] = KC_CAPITAL; + allkeys["COLON"] = KC_COLON; + allkeys["COMMA"] = KC_COMMA; + allkeys["CONVERT"] = KC_CONVERT; + allkeys["D"] = KC_D; + allkeys["DECIMAL"] = KC_DECIMAL; + allkeys["DELETE"] = KC_DELETE; + allkeys["DIVIDE"] = KC_DIVIDE; + allkeys["DOWN"] = KC_DOWN; + allkeys["E"] = KC_E; + allkeys["END"] = KC_END; + allkeys["EQUALS"] = KC_EQUALS; + allkeys["ESCAPE"] = KC_ESCAPE; + allkeys["F"] = KC_F; + allkeys["F1"] = KC_F1; + allkeys["F10"] = KC_F10; + allkeys["F11"] = KC_F11; + allkeys["F12"] = KC_F12; + allkeys["F13"] = KC_F13; + allkeys["F14"] = KC_F14; + allkeys["F15"] = KC_F15; + allkeys["F2"] = KC_F2; + allkeys["F3"] = KC_F3; + allkeys["F4"] = KC_F4; + allkeys["F5"] = KC_F5; + allkeys["F6"] = KC_F6; + allkeys["F7"] = KC_F7; + allkeys["F8"] = KC_F8; + allkeys["F9"] = KC_F9; + allkeys["G"] = KC_G; + allkeys["GRAVE"] = KC_GRAVE; + allkeys["H"] = KC_H; + allkeys["HOME"] = KC_HOME; + allkeys["I"] = KC_I; + allkeys["INSERT"] = KC_INSERT; + allkeys["J"] = KC_J; + allkeys["K"] = KC_K; + allkeys["KANA"] = KC_KANA; + allkeys["KANJI"] = KC_KANJI; + allkeys["L"] = KC_L; + allkeys["LBRACKET"] = KC_LBRACKET; + allkeys["LCONTROL"] = KC_LCONTROL; + allkeys["LEFT"] = KC_LEFT; + allkeys["LMENU"] = KC_LMENU; + allkeys["LSHIFT"] = KC_LSHIFT; + allkeys["LWIN"] = KC_LWIN; + allkeys["M"] = KC_M; + allkeys["MAIL"] = KC_MAIL; + allkeys["MEDIASELECT"] = KC_MEDIASELECT; + allkeys["MEDIASTOP"] = KC_MEDIASTOP; + allkeys["MINUS"] = KC_MINUS; + allkeys["MULTIPLY"] = KC_MULTIPLY; + allkeys["MUTE"] = KC_MUTE; + allkeys["MYCOMPUTER"] = KC_MYCOMPUTER; + allkeys["N"] = KC_N; + allkeys["NEXTTRACK"] = KC_NEXTTRACK; + allkeys["NOCONVERT"] = KC_NOCONVERT; + allkeys["NUMLOCK"] = KC_NUMLOCK; + allkeys["NUMPAD0"] = KC_NUMPAD0; + allkeys["NUMPAD1"] = KC_NUMPAD1; + allkeys["NUMPAD2"] = KC_NUMPAD2; + allkeys["NUMPAD3"] = KC_NUMPAD3; + allkeys["NUMPAD4"] = KC_NUMPAD4; + allkeys["NUMPAD5"] = KC_NUMPAD5; + allkeys["NUMPAD6"] = KC_NUMPAD6; + allkeys["NUMPAD7"] = KC_NUMPAD7; + allkeys["NUMPAD8"] = KC_NUMPAD8; + allkeys["NUMPAD9"] = KC_NUMPAD9; + allkeys["NUMPADCOMMA"] = KC_NUMPADCOMMA; + allkeys["NUMPADENTER"] = KC_NUMPADENTER; allkeys["NUMPADEQUALS"] = KC_NUMPADEQUALS; - allkeys["O"] = KC_O; - allkeys["OEM_102"] = KC_OEM_102; - allkeys["P"] = KC_P; - allkeys["PAUSE"] = KC_PAUSE; - allkeys["PERIOD"] = KC_PERIOD; - allkeys["PGDOWN"] = KC_PGDOWN; - allkeys["PGUP"] = KC_PGUP; - allkeys["PLAYPAUSE"] = KC_PLAYPAUSE; - allkeys["POWER"] = KC_POWER; - allkeys["PREVTRACK"] = KC_PREVTRACK; - allkeys["Q"] = KC_Q; - allkeys["R"] = KC_R; - allkeys["RBRACKET"] = KC_RBRACKET; - allkeys["RCONTROL"] = KC_RCONTROL; - allkeys["RETURN"] = KC_RETURN; - allkeys["RIGHT"] = KC_RIGHT; - allkeys["RMENU"] = KC_RMENU; - allkeys["RSHIFT"] = KC_RSHIFT; - allkeys["RWIN"] = KC_RWIN; - allkeys["S"] = KC_S; - allkeys["SCROLL"] = KC_SCROLL; - allkeys["SEMICOLON"] = KC_SEMICOLON; - allkeys["SLASH"] = KC_SLASH; - allkeys["SLEEP"] = KC_SLEEP; - allkeys["SPACE"] = KC_SPACE; - allkeys["STOP"] = KC_STOP; - allkeys["SUBTRACT"] = KC_SUBTRACT; - allkeys["SYSRQ"] = KC_SYSRQ; - allkeys["T"] = KC_T; - allkeys["TAB"] = KC_TAB; - allkeys["U"] = KC_U; - //allkeys["UNASSIGNED"] = KC_UNASSIGNED; - allkeys["UNDERLINE"] = KC_UNDERLINE; - allkeys["UNLABELED"] = KC_UNLABELED; - allkeys["UP"] = KC_UP; - allkeys["V"] = KC_V; - allkeys["VOLUMEDOWN"] = KC_VOLUMEDOWN; - allkeys["VOLUMEUP"] = KC_VOLUMEUP; - allkeys["W"] = KC_W; - allkeys["WAKE"] = KC_WAKE; - allkeys["WEBBACK"] = KC_WEBBACK; + allkeys["O"] = KC_O; + allkeys["OEM_102"] = KC_OEM_102; + allkeys["P"] = KC_P; + allkeys["PAUSE"] = KC_PAUSE; + allkeys["PERIOD"] = KC_PERIOD; + allkeys["PGDOWN"] = KC_PGDOWN; + allkeys["PGUP"] = KC_PGUP; + allkeys["PLAYPAUSE"] = KC_PLAYPAUSE; + allkeys["POWER"] = KC_POWER; + allkeys["PREVTRACK"] = KC_PREVTRACK; + allkeys["Q"] = KC_Q; + allkeys["R"] = KC_R; + allkeys["RBRACKET"] = KC_RBRACKET; + allkeys["RCONTROL"] = KC_RCONTROL; + allkeys["RETURN"] = KC_RETURN; + allkeys["RIGHT"] = KC_RIGHT; + allkeys["RMENU"] = KC_RMENU; + allkeys["RSHIFT"] = KC_RSHIFT; + allkeys["RWIN"] = KC_RWIN; + allkeys["S"] = KC_S; + allkeys["SCROLL"] = KC_SCROLL; + allkeys["SEMICOLON"] = KC_SEMICOLON; + allkeys["SLASH"] = KC_SLASH; + allkeys["SLEEP"] = KC_SLEEP; + allkeys["SPACE"] = KC_SPACE; + allkeys["STOP"] = KC_STOP; + allkeys["SUBTRACT"] = KC_SUBTRACT; + allkeys["SYSRQ"] = KC_SYSRQ; + allkeys["T"] = KC_T; + allkeys["TAB"] = KC_TAB; + allkeys["U"] = KC_U; + // allkeys["UNASSIGNED"] = KC_UNASSIGNED; + allkeys["UNDERLINE"] = KC_UNDERLINE; + allkeys["UNLABELED"] = KC_UNLABELED; + allkeys["UP"] = KC_UP; + allkeys["V"] = KC_V; + allkeys["VOLUMEDOWN"] = KC_VOLUMEDOWN; + allkeys["VOLUMEUP"] = KC_VOLUMEUP; + allkeys["W"] = KC_W; + allkeys["WAKE"] = KC_WAKE; + allkeys["WEBBACK"] = KC_WEBBACK; allkeys["WEBFAVORITES"] = KC_WEBFAVORITES; - allkeys["WEBFORWARD"] = KC_WEBFORWARD; - allkeys["WEBHOME"] = KC_WEBHOME; - allkeys["WEBREFRESH"] = KC_WEBREFRESH; - allkeys["WEBSEARCH"] = KC_WEBSEARCH; - allkeys["WEBSTOP"] = KC_WEBSTOP; - allkeys["X"] = KC_X; - allkeys["Y"] = KC_Y; - allkeys["YEN"] = KC_YEN; - allkeys["Z"] = KC_Z; + allkeys["WEBFORWARD"] = KC_WEBFORWARD; + allkeys["WEBHOME"] = KC_WEBHOME; + allkeys["WEBREFRESH"] = KC_WEBREFRESH; + allkeys["WEBSEARCH"] = KC_WEBSEARCH; + allkeys["WEBSTOP"] = KC_WEBSTOP; + allkeys["X"] = KC_X; + allkeys["Y"] = KC_Y; + allkeys["YEN"] = KC_YEN; + allkeys["Z"] = KC_Z; } void InputEngine::setupDefault(Ogre::String inputhwnd /* = "" */) @@ -3741,10 +2183,8 @@ String InputEngine::getKeyForCommand(int eventID) { std::map>::iterator it = events.find(eventID); - if (it == events.end()) - return String(); - if (it->second.empty()) - return String(); + if (it == events.end()) return String(); + if (it->second.empty()) return String(); std::vector::iterator it2 = it->second.begin(); return getKeyNameForKeyCode((OIS::KeyCode)it2->keyCode); diff --git a/source/main/utils/InputEngine.h b/source/main/utils/InputEngine.h index 7c3c324c90..c6a38c8789 100644 --- a/source/main/utils/InputEngine.h +++ b/source/main/utils/InputEngine.h @@ -19,22 +19,22 @@ along with Rigs of Rods. If not, see . */ -/** +/** @file InputEngine.h @brief Input logic. */ #pragma once -#include "RoRPrerequisites.h" - -#include #include "OISEvents.h" #include "OISForceFeedback.h" #include "OISInputManager.h" #include "OISJoyStick.h" #include "OISKeyboard.h" #include "OISMouse.h" +#include "RoRPrerequisites.h" + +#include // config filename #define CONFIGFILENAME "input.map" @@ -45,7 +45,7 @@ enum eventtypes { - ET_NONE=0, + ET_NONE = 0, ET_Keyboard, ET_MouseButton, ET_MouseAxisX, @@ -62,296 +62,296 @@ enum eventtypes enum events { // has to start at zero, since we iterate over it at times - EV_AIRPLANE_AIRBRAKES_FULL=0, + EV_AIRPLANE_AIRBRAKES_FULL = 0, EV_AIRPLANE_AIRBRAKES_LESS, EV_AIRPLANE_AIRBRAKES_MORE, EV_AIRPLANE_AIRBRAKES_NONE, - EV_AIRPLANE_BRAKE, //!< normal brake for an aircraft. + EV_AIRPLANE_BRAKE, //!< normal brake for an aircraft. EV_AIRPLANE_ELEVATOR_DOWN, //!< pull the elevator down in an aircraft. - EV_AIRPLANE_ELEVATOR_UP, //!< pull the elevator up in an aircraft. - EV_AIRPLANE_FLAPS_FULL, //!< full flaps in an aircraft. - EV_AIRPLANE_FLAPS_LESS, //!< one step less flaps. - EV_AIRPLANE_FLAPS_MORE, //!< one step more flaps. - EV_AIRPLANE_FLAPS_NONE, //!< no flaps. + EV_AIRPLANE_ELEVATOR_UP, //!< pull the elevator up in an aircraft. + EV_AIRPLANE_FLAPS_FULL, //!< full flaps in an aircraft. + EV_AIRPLANE_FLAPS_LESS, //!< one step less flaps. + EV_AIRPLANE_FLAPS_MORE, //!< one step more flaps. + EV_AIRPLANE_FLAPS_NONE, //!< no flaps. EV_AIRPLANE_PARKING_BRAKE, //!< airplane parking brake. - EV_AIRPLANE_REVERSE, //!< reverse the turboprops - EV_AIRPLANE_RUDDER_LEFT, //!< rudder left - EV_AIRPLANE_RUDDER_RIGHT, //!< rudder right - EV_AIRPLANE_STEER_LEFT, //!< steer left - EV_AIRPLANE_STEER_RIGHT, //!< steer right + EV_AIRPLANE_REVERSE, //!< reverse the turboprops + EV_AIRPLANE_RUDDER_LEFT, //!< rudder left + EV_AIRPLANE_RUDDER_RIGHT, //!< rudder right + EV_AIRPLANE_STEER_LEFT, //!< steer left + EV_AIRPLANE_STEER_RIGHT, //!< steer right EV_AIRPLANE_THROTTLE, - EV_AIRPLANE_THROTTLE_AXIS, //!< throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider) - EV_AIRPLANE_THROTTLE_DOWN, //!< decreases the airplane thrust - EV_AIRPLANE_THROTTLE_FULL, //!< full thrust - EV_AIRPLANE_THROTTLE_NO, //!< no thrust - EV_AIRPLANE_THROTTLE_UP, //!< increase the airplane thrust + EV_AIRPLANE_THROTTLE_AXIS, //!< throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider) + EV_AIRPLANE_THROTTLE_DOWN, //!< decreases the airplane thrust + EV_AIRPLANE_THROTTLE_FULL, //!< full thrust + EV_AIRPLANE_THROTTLE_NO, //!< no thrust + EV_AIRPLANE_THROTTLE_UP, //!< increase the airplane thrust EV_AIRPLANE_TOGGLE_ENGINES, //!< switch all engines on / off - EV_BOAT_CENTER_RUDDER, //!< center the rudder - EV_BOAT_REVERSE, //!< no thrust - EV_BOAT_STEER_LEFT, //!< steer left a step - EV_BOAT_STEER_LEFT_AXIS, //!< steer left (analog value!) - EV_BOAT_STEER_RIGHT, //!< steer right a step - EV_BOAT_STEER_RIGHT_AXIS, //!< steer right (analog value!) - EV_BOAT_THROTTLE_AXIS, //!< throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider) - EV_BOAT_THROTTLE_DOWN, //!< decrease throttle - EV_BOAT_THROTTLE_UP, //!< increase throttle - EV_SKY_DECREASE_TIME, //!< decrease day-time - EV_SKY_DECREASE_TIME_FAST, //!< decrease day-time a lot faster - EV_SKY_INCREASE_TIME, //!< increase day-time - EV_SKY_INCREASE_TIME_FAST, //!< increase day-time a lot faster - EV_CAMERA_CHANGE, //!< change camera mode + EV_BOAT_CENTER_RUDDER, //!< center the rudder + EV_BOAT_REVERSE, //!< no thrust + EV_BOAT_STEER_LEFT, //!< steer left a step + EV_BOAT_STEER_LEFT_AXIS, //!< steer left (analog value!) + EV_BOAT_STEER_RIGHT, //!< steer right a step + EV_BOAT_STEER_RIGHT_AXIS, //!< steer right (analog value!) + EV_BOAT_THROTTLE_AXIS, //!< throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider) + EV_BOAT_THROTTLE_DOWN, //!< decrease throttle + EV_BOAT_THROTTLE_UP, //!< increase throttle + EV_SKY_DECREASE_TIME, //!< decrease day-time + EV_SKY_DECREASE_TIME_FAST, //!< decrease day-time a lot faster + EV_SKY_INCREASE_TIME, //!< increase day-time + EV_SKY_INCREASE_TIME_FAST, //!< increase day-time a lot faster + EV_CAMERA_CHANGE, //!< change camera mode EV_CAMERA_DOWN, EV_CAMERA_FREE_MODE, EV_CAMERA_FREE_MODE_FIX, - EV_CAMERA_LOOKBACK, //!< look back (toggles between normal and lookback) - EV_CAMERA_RESET, //!< reset the camera position - EV_CAMERA_ROTATE_DOWN, //!< rotate camera down - EV_CAMERA_ROTATE_LEFT, //!< rotate camera left + EV_CAMERA_LOOKBACK, //!< look back (toggles between normal and lookback) + EV_CAMERA_RESET, //!< reset the camera position + EV_CAMERA_ROTATE_DOWN, //!< rotate camera down + EV_CAMERA_ROTATE_LEFT, //!< rotate camera left EV_CAMERA_ROTATE_RIGHT, //!< rotate camera right - EV_CAMERA_ROTATE_UP, //!< rotate camera up + EV_CAMERA_ROTATE_UP, //!< rotate camera up EV_CAMERA_UP, - EV_CAMERA_ZOOM_IN, //!< zoom camera in - EV_CAMERA_ZOOM_IN_FAST, //!< zoom camera in faster - EV_CAMERA_ZOOM_OUT, //!< zoom camera out + EV_CAMERA_ZOOM_IN, //!< zoom camera in + EV_CAMERA_ZOOM_IN_FAST, //!< zoom camera in faster + EV_CAMERA_ZOOM_OUT, //!< zoom camera out EV_CAMERA_ZOOM_OUT_FAST, //!< zoom camera out faster - EV_CHARACTER_BACKWARDS, //!< step backwards with the character - EV_CHARACTER_FORWARD, //!< step forward with the character - EV_CHARACTER_JUMP, //!< let the character jump - EV_CHARACTER_LEFT, //!< rotate character left - EV_CHARACTER_RIGHT, //!< rotate character right + EV_CHARACTER_BACKWARDS, //!< step backwards with the character + EV_CHARACTER_FORWARD, //!< step forward with the character + EV_CHARACTER_JUMP, //!< let the character jump + EV_CHARACTER_LEFT, //!< rotate character left + EV_CHARACTER_RIGHT, //!< rotate character right EV_CHARACTER_ROT_DOWN, EV_CHARACTER_ROT_UP, - EV_CHARACTER_RUN, //!< let the character run - EV_CHARACTER_SIDESTEP_LEFT, //!< sidestep to the left - EV_CHARACTER_SIDESTEP_RIGHT, //!< sidestep to the right - EV_COMMANDS_01, //!< Command 1 - EV_COMMANDS_02, //!< Command 2 - EV_COMMANDS_03, //!< Command 3 - EV_COMMANDS_04, //!< Command 4 - EV_COMMANDS_05, //!< Command 5 - EV_COMMANDS_06, //!< Command 6 - EV_COMMANDS_07, //!< Command 7 - EV_COMMANDS_08, //!< Command 8 - EV_COMMANDS_09, //!< Command 9 - EV_COMMANDS_10, //!< Command 10 - EV_COMMANDS_11, //!< Command 11 - EV_COMMANDS_12, //!< Command 12 - EV_COMMANDS_13, //!< Command 13 - EV_COMMANDS_14, //!< Command 14 - EV_COMMANDS_15, //!< Command 15 - EV_COMMANDS_16, //!< Command 16 - EV_COMMANDS_17, //!< Command 17 - EV_COMMANDS_18, //!< Command 18 - EV_COMMANDS_19, //!< Command 19 - EV_COMMANDS_20, //!< Command 20 - EV_COMMANDS_21, //!< Command 21 - EV_COMMANDS_22, //!< Command 22 - EV_COMMANDS_23, //!< Command 23 - EV_COMMANDS_24, //!< Command 24 - EV_COMMANDS_25, //!< Command 25 - EV_COMMANDS_26, //!< Command 26 - EV_COMMANDS_27, //!< Command 27 - EV_COMMANDS_28, //!< Command 28 - EV_COMMANDS_29, //!< Command 29 - EV_COMMANDS_30, //!< Command 30 - EV_COMMANDS_31, //!< Command 31 - EV_COMMANDS_32, //!< Command 32 - EV_COMMANDS_33, //!< Command 33 - EV_COMMANDS_34, //!< Command 34 - EV_COMMANDS_35, //!< Command 35 - EV_COMMANDS_36, //!< Command 36 - EV_COMMANDS_37, //!< Command 37 - EV_COMMANDS_38, //!< Command 38 - EV_COMMANDS_39, //!< Command 39 - EV_COMMANDS_40, //!< Command 40 - EV_COMMANDS_41, //!< Command 41 - EV_COMMANDS_42, //!< Command 42 - EV_COMMANDS_43, //!< Command 43 - EV_COMMANDS_44, //!< Command 44 - EV_COMMANDS_45, //!< Command 45 - EV_COMMANDS_46, //!< Command 46 - EV_COMMANDS_47, //!< Command 47 - EV_COMMANDS_48, //!< Command 48 - EV_COMMANDS_49, //!< Command 49 - EV_COMMANDS_50, //!< Command 50 - EV_COMMANDS_51, //!< Command 51 - EV_COMMANDS_52, //!< Command 52 - EV_COMMANDS_53, //!< Command 53 - EV_COMMANDS_54, //!< Command 54 - EV_COMMANDS_55, //!< Command 55 - EV_COMMANDS_56, //!< Command 56 - EV_COMMANDS_57, //!< Command 57 - EV_COMMANDS_58, //!< Command 58 - EV_COMMANDS_59, //!< Command 59 - EV_COMMANDS_60, //!< Command 50 - EV_COMMANDS_61, //!< Command 61 - EV_COMMANDS_62, //!< Command 62 - EV_COMMANDS_63, //!< Command 63 - EV_COMMANDS_64, //!< Command 64 - EV_COMMANDS_65, //!< Command 65 - EV_COMMANDS_66, //!< Command 66 - EV_COMMANDS_67, //!< Command 67 - EV_COMMANDS_68, //!< Command 68 - EV_COMMANDS_69, //!< Command 69 - EV_COMMANDS_70, //!< Command 70 - EV_COMMANDS_71, //!< Command 71 - EV_COMMANDS_72, //!< Command 72 - EV_COMMANDS_73, //!< Command 73 - EV_COMMANDS_74, //!< Command 74 - EV_COMMANDS_75, //!< Command 75 - EV_COMMANDS_76, //!< Command 76 - EV_COMMANDS_77, //!< Command 77 - EV_COMMANDS_78, //!< Command 78 - EV_COMMANDS_79, //!< Command 79 - EV_COMMANDS_80, //!< Command 80 - EV_COMMANDS_81, //!< Command 81 - EV_COMMANDS_82, //!< Command 82 - EV_COMMANDS_83, //!< Command 83 - EV_COMMANDS_84, //!< Command 84 + EV_CHARACTER_RUN, //!< let the character run + EV_CHARACTER_SIDESTEP_LEFT, //!< sidestep to the left + EV_CHARACTER_SIDESTEP_RIGHT, //!< sidestep to the right + EV_COMMANDS_01, //!< Command 1 + EV_COMMANDS_02, //!< Command 2 + EV_COMMANDS_03, //!< Command 3 + EV_COMMANDS_04, //!< Command 4 + EV_COMMANDS_05, //!< Command 5 + EV_COMMANDS_06, //!< Command 6 + EV_COMMANDS_07, //!< Command 7 + EV_COMMANDS_08, //!< Command 8 + EV_COMMANDS_09, //!< Command 9 + EV_COMMANDS_10, //!< Command 10 + EV_COMMANDS_11, //!< Command 11 + EV_COMMANDS_12, //!< Command 12 + EV_COMMANDS_13, //!< Command 13 + EV_COMMANDS_14, //!< Command 14 + EV_COMMANDS_15, //!< Command 15 + EV_COMMANDS_16, //!< Command 16 + EV_COMMANDS_17, //!< Command 17 + EV_COMMANDS_18, //!< Command 18 + EV_COMMANDS_19, //!< Command 19 + EV_COMMANDS_20, //!< Command 20 + EV_COMMANDS_21, //!< Command 21 + EV_COMMANDS_22, //!< Command 22 + EV_COMMANDS_23, //!< Command 23 + EV_COMMANDS_24, //!< Command 24 + EV_COMMANDS_25, //!< Command 25 + EV_COMMANDS_26, //!< Command 26 + EV_COMMANDS_27, //!< Command 27 + EV_COMMANDS_28, //!< Command 28 + EV_COMMANDS_29, //!< Command 29 + EV_COMMANDS_30, //!< Command 30 + EV_COMMANDS_31, //!< Command 31 + EV_COMMANDS_32, //!< Command 32 + EV_COMMANDS_33, //!< Command 33 + EV_COMMANDS_34, //!< Command 34 + EV_COMMANDS_35, //!< Command 35 + EV_COMMANDS_36, //!< Command 36 + EV_COMMANDS_37, //!< Command 37 + EV_COMMANDS_38, //!< Command 38 + EV_COMMANDS_39, //!< Command 39 + EV_COMMANDS_40, //!< Command 40 + EV_COMMANDS_41, //!< Command 41 + EV_COMMANDS_42, //!< Command 42 + EV_COMMANDS_43, //!< Command 43 + EV_COMMANDS_44, //!< Command 44 + EV_COMMANDS_45, //!< Command 45 + EV_COMMANDS_46, //!< Command 46 + EV_COMMANDS_47, //!< Command 47 + EV_COMMANDS_48, //!< Command 48 + EV_COMMANDS_49, //!< Command 49 + EV_COMMANDS_50, //!< Command 50 + EV_COMMANDS_51, //!< Command 51 + EV_COMMANDS_52, //!< Command 52 + EV_COMMANDS_53, //!< Command 53 + EV_COMMANDS_54, //!< Command 54 + EV_COMMANDS_55, //!< Command 55 + EV_COMMANDS_56, //!< Command 56 + EV_COMMANDS_57, //!< Command 57 + EV_COMMANDS_58, //!< Command 58 + EV_COMMANDS_59, //!< Command 59 + EV_COMMANDS_60, //!< Command 50 + EV_COMMANDS_61, //!< Command 61 + EV_COMMANDS_62, //!< Command 62 + EV_COMMANDS_63, //!< Command 63 + EV_COMMANDS_64, //!< Command 64 + EV_COMMANDS_65, //!< Command 65 + EV_COMMANDS_66, //!< Command 66 + EV_COMMANDS_67, //!< Command 67 + EV_COMMANDS_68, //!< Command 68 + EV_COMMANDS_69, //!< Command 69 + EV_COMMANDS_70, //!< Command 70 + EV_COMMANDS_71, //!< Command 71 + EV_COMMANDS_72, //!< Command 72 + EV_COMMANDS_73, //!< Command 73 + EV_COMMANDS_74, //!< Command 74 + EV_COMMANDS_75, //!< Command 75 + EV_COMMANDS_76, //!< Command 76 + EV_COMMANDS_77, //!< Command 77 + EV_COMMANDS_78, //!< Command 78 + EV_COMMANDS_79, //!< Command 79 + EV_COMMANDS_80, //!< Command 80 + EV_COMMANDS_81, //!< Command 81 + EV_COMMANDS_82, //!< Command 82 + EV_COMMANDS_83, //!< Command 83 + EV_COMMANDS_84, //!< Command 84 EV_COMMON_ACCELERATE_SIMULATION, //!< accelerate the simulation speed EV_COMMON_DECELERATE_SIMULATION, //!< decelerate the simulation speed EV_COMMON_RESET_SIMULATION_PACE, //!< reset the simulation speed - EV_COMMON_AUTOLOCK, //!< unlock autolock hook node - EV_COMMON_CONSOLE_TOGGLE, //!< show / hide the console - EV_COMMON_ENTER_CHATMODE, //!< enter the chat mode - EV_COMMON_ENTER_OR_EXIT_TRUCK, //!< enter or exit a truck - EV_COMMON_ENTER_NEXT_TRUCK, //!< enter next truck - EV_COMMON_ENTER_PREVIOUS_TRUCK, //!< enter previous truck - EV_COMMON_REMOVE_CURRENT_TRUCK, //!< remove current truck - EV_COMMON_RESPAWN_LAST_TRUCK, //!< respawn last truck - EV_COMMON_FOV_LESS, //!>& getEvents() { return events; }; + std::map> &getEvents() + { + return events; + }; Ogre::String getDeviceName(event_trigger_t evt); - std::string getEventTypeName(int type); - - int getCurrentKeyCombo(std::string* combo); - int getCurrentJoyButton(int& joystickNumber, int& button); - int getCurrentPovValue(int& joystickNumber, int& pov, int& povdir); - std::string getKeyNameForKeyCode(OIS::KeyCode keycode); - void resetKeys(); - OIS::JoyStickState* getCurrentJoyState(int joystickNumber); - int getJoyComponentCount(OIS::ComponentType type, int joystickNumber); - std::string getJoyVendor(int joystickNumber); - void smoothValue(float& ref, float value, float rate); - bool saveMapping(std::string outfile = CONFIGFILENAME, Ogre::String hwnd = 0, int joyNum = -10); - bool appendLineToConfig(std::string line, std::string outfile = CONFIGFILENAME); - bool loadMapping(std::string outfile = CONFIGFILENAME, bool append = false, int deviceID = -1); + std::string getEventTypeName(int type); + + int getCurrentKeyCombo(std::string *combo); + int getCurrentJoyButton(int &joystickNumber, int &button); + int getCurrentPovValue(int &joystickNumber, int &pov, int &povdir); + std::string getKeyNameForKeyCode(OIS::KeyCode keycode); + void resetKeys(); + OIS::JoyStickState *getCurrentJoyState(int joystickNumber); + int getJoyComponentCount(OIS::ComponentType type, int joystickNumber); + std::string getJoyVendor(int joystickNumber); + void smoothValue(float &ref, float value, float rate); + bool saveMapping(std::string outfile = CONFIGFILENAME, Ogre::String hwnd = 0, int joyNum = -10); + bool appendLineToConfig(std::string line, std::string outfile = CONFIGFILENAME); + bool loadMapping(std::string outfile = CONFIGFILENAME, bool append = false, int deviceID = -1); void destroy(); - Ogre::String getEventCommand(int eventID); - static int resolveEventName(Ogre::String eventName); + Ogre::String getEventCommand(int eventID); + static int resolveEventName(Ogre::String eventName); static Ogre::String eventIDToName(int eventID); - event_trigger_t* getEventBySUID(int suid); + event_trigger_t * getEventBySUID(int suid); void setupDefault(Ogre::String inputhwnd = ""); bool isEventDefined(int eventID); - void addEvent(int eventID, event_trigger_t& t); - void updateEvent(int eventID, const event_trigger_t& t); + void addEvent(int eventID, event_trigger_t &t); + void updateEvent(int eventID, const event_trigger_t &t); bool deleteEventBySUID(int suid); - bool getInputsChanged() { return inputsChanged; }; - void prepareShutdown(); + bool getInputsChanged() + { + return inputsChanged; + }; + void prepareShutdown(); OIS::MouseState getMouseState(); // some custom methods - void windowResized(Ogre::RenderWindow* rw); + void windowResized(Ogre::RenderWindow *rw); bool reloadConfig(std::string outfile = CONFIGFILENAME); - bool updateConfigline(event_trigger_t* t); + bool updateConfigline(event_trigger_t *t); void grabMouse(bool enable); void setMousePosition(int x, int y, bool padding = true); @@ -514,76 +515,87 @@ class InputEngine : void updateKeyBounces(float dt); void completeMissingEvents(); - int getNumJoysticks() { return free_joysticks; }; - OIS::ForceFeedback* getForceFeedbackDevice() { return mForceFeedback; }; + int getNumJoysticks() + { + return free_joysticks; + }; + OIS::ForceFeedback *getForceFeedbackDevice() + { + return mForceFeedback; + }; - void SetKeyboardListener(OIS::KeyListener* keyboard_listener); + void SetKeyboardListener(OIS::KeyListener *keyboard_listener); - OIS::MouseState SetMouseListener(OIS::MouseListener* mouse_listener); + OIS::MouseState SetMouseListener(OIS::MouseListener *mouse_listener); void RestoreMouseListener(); void RestoreKeyboardListener(); - inline OIS::Keyboard* GetOisKeyboard() { return mKeyboard; } - inline OIS::Mouse* GetOisMouse() { return mMouse; } + inline OIS::Keyboard *GetOisKeyboard() + { + return mKeyboard; + } + inline OIS::Mouse *GetOisMouse() + { + return mMouse; + } std::map GetKeyMap() { return allkeys; } -protected: - - InputEngine& operator=(const InputEngine&); + protected: + InputEngine &operator=(const InputEngine &); - //OIS Input devices - OIS::InputManager* mInputManager; - OIS::Mouse* mMouse; - OIS::Keyboard* mKeyboard; - OIS::JoyStick* mJoy[MAX_JOYSTICKS]; - int free_joysticks; - OIS::ForceFeedback* mForceFeedback; - int uniqueCounter; + // OIS Input devices + OIS::InputManager * mInputManager; + OIS::Mouse * mMouse; + OIS::Keyboard * mKeyboard; + OIS::JoyStick * mJoy[MAX_JOYSTICKS]; + int free_joysticks; + OIS::ForceFeedback *mForceFeedback; + int uniqueCounter; // JoyStickListener - bool buttonPressed(const OIS::JoyStickEvent& arg, int button); - bool buttonReleased(const OIS::JoyStickEvent& arg, int button); - bool axisMoved(const OIS::JoyStickEvent& arg, int axis); - bool sliderMoved(const OIS::JoyStickEvent&, int); - bool povMoved(const OIS::JoyStickEvent&, int); + bool buttonPressed(const OIS::JoyStickEvent &arg, int button); + bool buttonReleased(const OIS::JoyStickEvent &arg, int button); + bool axisMoved(const OIS::JoyStickEvent &arg, int axis); + bool sliderMoved(const OIS::JoyStickEvent &, int); + bool povMoved(const OIS::JoyStickEvent &, int); // KeyListener - bool keyPressed(const OIS::KeyEvent& arg); - bool keyReleased(const OIS::KeyEvent& arg); + bool keyPressed(const OIS::KeyEvent &arg); + bool keyReleased(const OIS::KeyEvent &arg); // MouseListener - bool mouseMoved(const OIS::MouseEvent& arg); - bool mousePressed(const OIS::MouseEvent& arg, OIS::MouseButtonID id); - bool mouseReleased(const OIS::MouseEvent& arg, OIS::MouseButtonID id); + bool mouseMoved(const OIS::MouseEvent &arg); + bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id); + bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id); // this stores the key/button/axis values std::map keyState; - OIS::JoyStickState joyState[MAX_JOYSTICKS]; - OIS::MouseState mouseState; + OIS::JoyStickState joyState[MAX_JOYSTICKS]; + OIS::MouseState mouseState; // define event aliases std::map> events; - std::map event_times; + std::map event_times; - bool processLine(char* line, int deviceID = -1); + bool processLine(char *line, int deviceID = -1); bool captureMode; - void initAllKeys(); - std::map allkeys; + void initAllKeys(); + std::map allkeys; std::map::iterator allit; float deadZone(float axis, float dz); float axisLinearity(float axisValue, float linearity); - float logval(float val); + float logval(float val); std::string getEventGroup(Ogre::String eventName); - bool mappingLoaded; + bool mappingLoaded; bool inputsChanged; diff --git a/source/main/utils/InterThreadStoreVector.h b/source/main/utils/InterThreadStoreVector.h index ac5adbd3e9..6b1930fb92 100644 --- a/source/main/utils/InterThreadStoreVector.h +++ b/source/main/utils/InterThreadStoreVector.h @@ -25,26 +25,23 @@ #include /// this class is a helper to exchange data in a class between different threads, it can be pushed and pulled in various threads -template -class InterThreadStoreVector +template class InterThreadStoreVector { -public: - + public: void push(T v) { std::lock_guard lock(m_vector_mutex); store.push_back(v); } - void pull(std::vector& res) + void pull(std::vector &res) { std::lock_guard lock(m_vector_mutex); res = store; store.clear(); } -protected: - - std::mutex m_vector_mutex; + protected: + std::mutex m_vector_mutex; std::vector store; }; diff --git a/source/main/utils/Language.cpp b/source/main/utils/Language.cpp index d65add241f..ece7240685 100644 --- a/source/main/utils/Language.cpp +++ b/source/main/utils/Language.cpp @@ -24,10 +24,10 @@ #ifndef NOLANG -#include "Language.h" + #include "Language.h" -#include "Application.h" -#include "PlatformUtils.h" + #include "Application.h" + #include "PlatformUtils.h" using namespace Ogre; using namespace RoR; @@ -51,8 +51,8 @@ void LanguageEngine::setup() { // load language, must happen after initializing Settings class and Ogre Root! - languages = { {"English", "en"} }; - auto& moFileReader = moFileLib::moFileReaderSingleton::GetInstance(); + languages = {{"English", "en"}}; + auto &moFileReader = moFileLib::moFileReaderSingleton::GetInstance(); String base_path = PathCombine(App::sys_process_dir.GetActive(), "languages"); ResourceGroupManager::getSingleton().addResourceLocation(base_path, "FileSystem", "LngRG"); @@ -62,8 +62,8 @@ void LanguageEngine::setup() for (auto file : *fl) { String locale_path = PathCombine(base_path, file.filename); - String lang_path = PathCombine(locale_path, "LC_MESSAGES"); - String mo_path = PathCombine(lang_path, "ror.mo"); + String lang_path = PathCombine(locale_path, "LC_MESSAGES"); + String mo_path = PathCombine(lang_path, "ror.mo"); if (moFileReader.ReadFile(mo_path.c_str()) == moFileLib::moFileReader::EC_SUCCESS) { String info = moFileLib::moFileReaderSingleton::GetInstance().Lookup(""); @@ -76,9 +76,9 @@ void LanguageEngine::setup() ResourceGroupManager::getSingleton().destroyResourceGroup("LngRG"); String language_short = App::app_language.GetActive(); - String locale_path = PathCombine(base_path, language_short.substr(0, 2)); - String lang_path = PathCombine(locale_path, "LC_MESSAGES"); - String mo_path = PathCombine(lang_path, "ror.mo"); + String locale_path = PathCombine(base_path, language_short.substr(0, 2)); + String lang_path = PathCombine(locale_path, "LC_MESSAGES"); + String mo_path = PathCombine(lang_path, "ror.mo"); if (moFileReader.ReadFile(mo_path.c_str()) == moFileLib::moFileReader::EC_SUCCESS) { @@ -94,4 +94,4 @@ void LanguageEngine::setup() RoR::Log("[RoR|App] Language successfully loaded"); } -#endif //NOLANG +#endif // NOLANG diff --git a/source/main/utils/Language.h b/source/main/utils/Language.h index 2fb0660f0a..b66198c8c7 100644 --- a/source/main/utils/Language.h +++ b/source/main/utils/Language.h @@ -34,31 +34,34 @@ // #define NOLANG = no language translations at all, removes any special parsing tags // #define USE_MOFILEREADER = windows gettext replacement -# define U(str) Ogre::UTFString(L##str) +#define U(str) Ogre::UTFString(L##str) #ifdef NOLANG -// no language mode -# define _L -# define _LC + // no language mode + #define _L + #define _LC #else // NOLANG -// using mofilereader as gettext replacement -#include + // using mofilereader as gettext replacement + #include -#define _L(str) moFileLib::moFileReaderSingleton::GetInstance().Lookup(str).c_str() -#define _LC(ctx,str) moFileLib::moFileReaderSingleton::GetInstance().LookupWithContext(ctx,str).c_str() + #define _L(str) moFileLib::moFileReaderSingleton::GetInstance().Lookup(str).c_str() + #define _LC(ctx, str) moFileLib::moFileReaderSingleton::GetInstance().LookupWithContext(ctx, str).c_str() class LanguageEngine : public RoRSingleton, public ZeroedMemoryAllocator { friend class RoRSingleton; -public: + public: void setup(); - std::vector> getLanguages() { return languages; }; + std::vector> getLanguages() + { + return languages; + }; -private: + private: std::vector> languages; }; diff --git a/source/main/utils/MeshObject.cpp b/source/main/utils/MeshObject.cpp index 6ed4ba6203..ca76196c59 100644 --- a/source/main/utils/MeshObject.cpp +++ b/source/main/utils/MeshObject.cpp @@ -29,41 +29,31 @@ using namespace Ogre; -MeshObject::MeshObject(Ogre::String meshName, Ogre::String meshRG, Ogre::String entityName, Ogre::SceneNode* sceneNode) - : sceneNode(sceneNode) - , ent(nullptr) - , castshadows(true) +MeshObject::MeshObject(Ogre::String meshName, Ogre::String meshRG, Ogre::String entityName, Ogre::SceneNode *sceneNode) + : sceneNode(sceneNode), ent(nullptr), castshadows(true) { this->createEntity(meshName, meshRG, entityName); } void MeshObject::setMaterialName(Ogre::String m) { - if (ent) - { - ent->setMaterialName(m); - } + if (ent) { ent->setMaterialName(m); } } void MeshObject::setCastShadows(bool b) { castshadows = b; - if (sceneNode && sceneNode->numAttachedObjects()) - { - sceneNode->getAttachedObject(0)->setCastShadows(b); - } + if (sceneNode && sceneNode->numAttachedObjects()) { sceneNode->getAttachedObject(0)->setCastShadows(b); } } void MeshObject::setVisible(bool b) { - if (sceneNode) - sceneNode->setVisible(b); + if (sceneNode) sceneNode->setVisible(b); } void MeshObject::createEntity(Ogre::String meshName, Ogre::String meshRG, Ogre::String entityName) { - if (!sceneNode) - return; + if (!sceneNode) return; try { @@ -81,11 +71,10 @@ void MeshObject::createEntity(Ogre::String meshName, Ogre::String meshRG, Ogre:: for (FileInfoList::iterator iterFiles = files->begin(); iterFiles != files->end(); ++iterFiles) { String format = basename + "_lod%d.mesh"; - int i = -1; - int r = sscanf(iterFiles->filename.c_str(), format.c_str(), &i); + int i = -1; + int r = sscanf(iterFiles->filename.c_str(), format.c_str(), &i); - if (r <= 0 || i < 0) - continue; + if (r <= 0 || i < 0) continue; Ogre::MeshManager::getSingleton().load(iterFiles->filename, mesh->getGroup()); } @@ -96,10 +85,9 @@ void MeshObject::createEntity(Ogre::String meshName, Ogre::String meshRG, Ogre:: { // and custom LODs String format = basename + "_clod_%d.mesh"; - int i = -1; - int r = sscanf(iterFiles->filename.c_str(), format.c_str(), &i); - if (r <= 0 || i < 0) - continue; + int i = -1; + int r = sscanf(iterFiles->filename.c_str(), format.c_str(), &i); + if (r <= 0 || i < 0) continue; Ogre::MeshManager::getSingleton().load(iterFiles->filename, mesh->getGroup()); } @@ -112,10 +100,10 @@ void MeshObject::createEntity(Ogre::String meshName, Ogre::String meshRG, Ogre:: sceneNode->attachObject(ent); sceneNode->setVisible(true); } - catch (Ogre::Exception& e) + catch (Ogre::Exception &e) { - RoR::LogFormat("[RoR] Error creating entity of mesh '%s' (group: '%s'), message: %s", - meshName.c_str(), meshRG.c_str(), e.getFullDescription().c_str()); + RoR::LogFormat("[RoR] Error creating entity of mesh '%s' (group: '%s'), message: %s", meshName.c_str(), meshRG.c_str(), + e.getFullDescription().c_str()); return; } } diff --git a/source/main/utils/MeshObject.h b/source/main/utils/MeshObject.h index 47a4ba2565..b28c184ac5 100644 --- a/source/main/utils/MeshObject.h +++ b/source/main/utils/MeshObject.h @@ -25,25 +25,31 @@ #pragma once -#include - #include "RoRPrerequisites.h" +#include + class MeshObject : public Ogre::Resource::Listener, public ZeroedMemoryAllocator { -public: - MeshObject(Ogre::String meshName, Ogre::String meshRG, Ogre::String entityName, Ogre::SceneNode* sceneNode); - - void setMaterialName(Ogre::String m); - void setCastShadows(bool b); - void setVisible(bool b); - inline Ogre::Entity* getEntity() { return ent; }; - inline Ogre::SceneNode* GetSceneNode() { return sceneNode; } - -protected: - Ogre::SceneNode* sceneNode; - Ogre::Entity* ent; - Ogre::MeshPtr mesh; + public: + MeshObject(Ogre::String meshName, Ogre::String meshRG, Ogre::String entityName, Ogre::SceneNode *sceneNode); + + void setMaterialName(Ogre::String m); + void setCastShadows(bool b); + void setVisible(bool b); + inline Ogre::Entity *getEntity() + { + return ent; + }; + inline Ogre::SceneNode *GetSceneNode() + { + return sceneNode; + } + + protected: + Ogre::SceneNode *sceneNode; + Ogre::Entity * ent; + Ogre::MeshPtr mesh; bool castshadows; diff --git a/source/main/utils/PlatformUtils.cpp b/source/main/utils/PlatformUtils.cpp index e060d97c9f..96bfb6a0ec 100644 --- a/source/main/utils/PlatformUtils.cpp +++ b/source/main/utils/PlatformUtils.cpp @@ -23,212 +23,220 @@ /// @author Petr Ohlidal /// @date 05/2014 - #include "PlatformUtils.h" + #include "Application.h" #ifdef _MSC_VER #include #include // SHGetFolderPathW() #else - #include #include + #include #include // readlink() #endif -#include #include +#include #include -namespace RoR { +namespace RoR +{ #ifdef _MSC_VER -// -------------------------- File/path utils for MS Windows -------------------------- -// Based on research in https://github.com/only-a-ptr/filepaths4rigs + // -------------------------- File/path utils for MS Windows -------------------------- + // Based on research in https://github.com/only-a-ptr/filepaths4rigs -char PATH_SLASH = '\\'; + char PATH_SLASH = '\\'; -std::wstring MSW_Utf8ToWchar(const char* path) -{ - if( path == nullptr || path[0] == 0 ) + std::wstring MSW_Utf8ToWchar(const char *path) { - RoR::Log("[RoR] Internal error: MSW_Utf8ToWchar() received empty input"); - return std::wstring(); + if (path == nullptr || path[0] == 0) + { + RoR::Log("[RoR] Internal error: MSW_Utf8ToWchar() received empty input"); + return std::wstring(); + } + + int size_needed = + MultiByteToWideChar(CP_UTF8, 0, &path[0], -1, NULL, + 0); // Doc: https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx + std::wstring out_wstr(size_needed, 0); + int raw_result = MultiByteToWideChar(CP_UTF8, 0, &path[0], -1, &out_wstr[0], size_needed); + if (raw_result <= 0) + { + RoR::LogFormat( + "[RoR] Internal error: MSW_Utf8ToWchar() could not convert UTF-8 to UTF-16; MultiByteToWideChar() returned %d", + raw_result); + return std::wstring(); + } + return out_wstr; } - int size_needed = MultiByteToWideChar(CP_UTF8, 0, &path[0], -1, NULL, 0); // Doc: https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx - std::wstring out_wstr( size_needed, 0 ); - int raw_result = MultiByteToWideChar(CP_UTF8, 0, &path[0], -1, &out_wstr[0], size_needed); - if (raw_result <= 0) + DWORD MSW_GetFileAttrs(const char *path) { - RoR::LogFormat("[RoR] Internal error: MSW_Utf8ToWchar() could not convert UTF-8 to UTF-16; MultiByteToWideChar() returned %d", raw_result); - return std::wstring(); + if (path == nullptr || path[0] == 0) { return INVALID_FILE_ATTRIBUTES; } + + std::wstring wpath = MSW_Utf8ToWchar(path); + // Function reference: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364944(v=vs.85).aspx + // File attribute constants: https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx + return GetFileAttributesW(wpath.c_str()); } - return out_wstr; -} -DWORD MSW_GetFileAttrs(const char* path) -{ - if (path == nullptr || path[0] == 0) + std::string MSW_WcharToUtf8(const wchar_t *wstr) // wstr _must_ be NUL-terminated! { - return INVALID_FILE_ATTRIBUTES; + if (wstr == nullptr || wstr[0] == 0) + { + RoR::Log("[RoR] Internal error: MSW_WcharToUtf8() received empty input"); + return std::string(); + } + + const int dst_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], -1, nullptr, 0, nullptr, nullptr); + std::string dst(dst_size, 0); // Construct by length and initial value + int raw_result = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], -1, &dst[0], dst_size, nullptr, nullptr); + if (raw_result <= 0) + { + RoR::LogFormat( + "[RoR] Internal error: MSW_WcharToUtf8() could not convert UTF-16 to UTF-8; WideCharToMultiByte() returned %d", + raw_result); + return std::string(); + } + return dst; } - std::wstring wpath = MSW_Utf8ToWchar(path); - // Function reference: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364944(v=vs.85).aspx - // File attribute constants: https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx - return GetFileAttributesW(wpath.c_str()); -} - -std::string MSW_WcharToUtf8(const wchar_t* wstr) // wstr _must_ be NUL-terminated! -{ - if( wstr == nullptr || wstr[0] == 0 ) + bool FileExists(const char *path) { - RoR::Log("[RoR] Internal error: MSW_WcharToUtf8() received empty input"); - return std::string(); + DWORD file_attrs = MSW_GetFileAttrs(path); + return (file_attrs != INVALID_FILE_ATTRIBUTES && !(file_attrs & FILE_ATTRIBUTE_DIRECTORY)); } - const int dst_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], -1, nullptr, 0, nullptr, nullptr); - std::string dst(dst_size, 0); // Construct by length and initial value - int raw_result = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], -1, &dst[0], dst_size, nullptr, nullptr); - if (raw_result <= 0) + bool FolderExists(const char *path) { - RoR::LogFormat("[RoR] Internal error: MSW_WcharToUtf8() could not convert UTF-16 to UTF-8; WideCharToMultiByte() returned %d", raw_result); - return std::string(); + DWORD file_attrs = MSW_GetFileAttrs(path); + return (file_attrs != INVALID_FILE_ATTRIBUTES && (file_attrs & FILE_ATTRIBUTE_DIRECTORY)); } - return dst; -} - -bool FileExists(const char *path) -{ - DWORD file_attrs = MSW_GetFileAttrs(path); - return (file_attrs != INVALID_FILE_ATTRIBUTES && ! (file_attrs & FILE_ATTRIBUTE_DIRECTORY)); -} - -bool FolderExists(const char* path) -{ - DWORD file_attrs = MSW_GetFileAttrs(path); - return (file_attrs != INVALID_FILE_ATTRIBUTES && (file_attrs & FILE_ATTRIBUTE_DIRECTORY)); -} -void CreateFolder(const char* path) -{ - if (!FolderExists(path)) + void CreateFolder(const char *path) { - std::wstring wpath = MSW_Utf8ToWchar(path); - CreateDirectoryW(wpath.c_str(), nullptr); + if (!FolderExists(path)) + { + std::wstring wpath = MSW_Utf8ToWchar(path); + CreateDirectoryW(wpath.c_str(), nullptr); + } } -} -std::string GetUserHomeDirectory() -{ - std::wstring out_wstr(MAX_PATH, 0); // Length limit imposed by the function, see https://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx - HRESULT hres = SHGetFolderPathW(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_CURRENT, &out_wstr[0]); - if (hres != S_OK) + std::string GetUserHomeDirectory() { - RoR::LogFormat("[RoR] Internal error: GetUserHomeDirectory() failed; SHGetFolderPathW() returned %ld", static_cast(hres)); - return std::string(); + std::wstring out_wstr(MAX_PATH, 0); // Length limit imposed by the function, see + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx + HRESULT hres = SHGetFolderPathW(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_CURRENT, &out_wstr[0]); + if (hres != S_OK) + { + RoR::LogFormat("[RoR] Internal error: GetUserHomeDirectory() failed; SHGetFolderPathW() returned %ld", + static_cast(hres)); + return std::string(); + } + + return MSW_WcharToUtf8(out_wstr.c_str()); } - return MSW_WcharToUtf8(out_wstr.c_str()); -} - -std::string GetExecutablePath() -{ - const int BUF_SIZE = 500; - std::wstring out_wstr(BUF_SIZE, 0); - DWORD res = GetModuleFileNameW(nullptr, &out_wstr[0], BUF_SIZE); - if (res <= 0) + std::string GetExecutablePath() { - RoR::LogFormat("[RoR] Internal error: GetExecutablePath() failed; GetModuleFileNameW() returned %d", static_cast(res)); - return std::string(); + const int BUF_SIZE = 500; + std::wstring out_wstr(BUF_SIZE, 0); + DWORD res = GetModuleFileNameW(nullptr, &out_wstr[0], BUF_SIZE); + if (res <= 0) + { + RoR::LogFormat("[RoR] Internal error: GetExecutablePath() failed; GetModuleFileNameW() returned %d", + static_cast(res)); + return std::string(); + } + + return MSW_WcharToUtf8(out_wstr.c_str()); } - return MSW_WcharToUtf8(out_wstr.c_str()); -} - #else -// -------------------------- File/path utils for Linux/*nix -------------------------- - -char PATH_SLASH = '/'; + // -------------------------- File/path utils for Linux/*nix -------------------------- -bool FileExists(const char *path) -{ - struct stat st; - return (stat(path, &st) == 0); -} + char PATH_SLASH = '/'; -bool FolderExists(const char* path) -{ - struct stat st; - return (stat(path, &st) == 0); -} + bool FileExists(const char *path) + { + struct stat st; + return (stat(path, &st) == 0); + } -void CreateFolder(const char* path) -{ - mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); -} + bool FolderExists(const char *path) + { + struct stat st; + return (stat(path, &st) == 0); + } -std::string GetUserHomeDirectory() -{ - return getenv("HOME"); -} + void CreateFolder(const char *path) + { + mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + } -std::string GetExecutablePath() -{ - const int BUF_SIZE = 500; - std::string buf_str(BUF_SIZE, 0); - // Linux or POSIX assumed; http://stackoverflow.com/a/625523 - if (readlink("/proc/self/exe", &buf_str[0], BUF_SIZE-1) == -1) + std::string GetUserHomeDirectory() { - RoR::LogFormat("[RoR] Internal error: GetExecutablePath() failed; readlink() sets errno to %d", static_cast(errno)); - return std::string(); + return getenv("HOME"); } - return std::move(buf_str); -} + std::string GetExecutablePath() + { + const int BUF_SIZE = 500; + std::string buf_str(BUF_SIZE, 0); + // Linux or POSIX assumed; http://stackoverflow.com/a/625523 + if (readlink("/proc/self/exe", &buf_str[0], BUF_SIZE - 1) == -1) + { + RoR::LogFormat("[RoR] Internal error: GetExecutablePath() failed; readlink() sets errno to %d", + static_cast(errno)); + return std::string(); + } + + return std::move(buf_str); + } #endif // _MSC_VER -// -------------------------- File/path common utils -------------------------- + // -------------------------- File/path common utils -------------------------- -std::string GetParentDirectory(const char* src_buff) -{ - const char* start = src_buff; - size_t count = strlen(src_buff); - // Trim trailing separator(s) - for (;;) + std::string GetParentDirectory(const char *src_buff) { - if (count == 0) { return std::string(); } - if (start[count - 1] != PATH_SLASH) { break; } - --count; + const char *start = src_buff; + size_t count = strlen(src_buff); + // Trim trailing separator(s) + for (;;) + { + if (count == 0) { return std::string(); } + if (start[count - 1] != PATH_SLASH) { break; } + --count; + } + // Remove last path entry + for (;;) + { + if (count == 0) { return std::string(); } + if (start[count - 1] == PATH_SLASH) { break; } + --count; + } + // Trim rear separator(s) + for (;;) + { + if (count == 0) { return std::string(); } + if (start[count - 1] != PATH_SLASH) { break; } + --count; + } + + return std::string(start, count); } - // Remove last path entry - for (;;) - { - if (count == 0) { return std::string(); } - if (start[count - 1] == PATH_SLASH) {break; } - --count; - } - // Trim rear separator(s) - for (;;) + + std::time_t GetFileLastModifiedTime(std::string const &path) { - if (count == 0) { return std::string(); } - if (start[count - 1] != PATH_SLASH) { break; } - --count; + Ogre::FileSystemArchiveFactory factory; + Ogre::Archive * fs_archive = factory.createInstance(path, /*readOnly*/ true); + std::time_t time = fs_archive->getModifiedTime(path); + factory.destroyInstance(fs_archive); + return time; } - - return std::string(start, count); -} - -std::time_t GetFileLastModifiedTime(std::string const & path) -{ - Ogre::FileSystemArchiveFactory factory; - Ogre::Archive* fs_archive = factory.createInstance(path, /*readOnly*/true); - std::time_t time = fs_archive->getModifiedTime(path); - factory.destroyInstance(fs_archive); - return time; -} } // namespace RoR diff --git a/source/main/utils/PlatformUtils.h b/source/main/utils/PlatformUtils.h index 4a997c2615..335f53c08f 100644 --- a/source/main/utils/PlatformUtils.h +++ b/source/main/utils/PlatformUtils.h @@ -32,24 +32,37 @@ #include -namespace RoR { +namespace RoR +{ -extern char PATH_SLASH; + extern char PATH_SLASH; -bool FileExists(const char* path); //!< Path must be UTF-8 encoded. -bool FolderExists(const char* path); //!< Path must be UTF-8 encoded. -void CreateFolder(const char* path); //!< Path must be UTF-8 encoded. + bool FileExists(const char *path); //!< Path must be UTF-8 encoded. + bool FolderExists(const char *path); //!< Path must be UTF-8 encoded. + void CreateFolder(const char *path); //!< Path must be UTF-8 encoded. -inline bool FileExists(std::string const& path) { return FileExists(path.c_str()); } -inline bool FolderExists(std::string const& path) { return FolderExists(path.c_str()); } -inline void CreateFolder(std::string const& path) { CreateFolder(path.c_str()); } + inline bool FileExists(std::string const &path) + { + return FileExists(path.c_str()); + } + inline bool FolderExists(std::string const &path) + { + return FolderExists(path.c_str()); + } + inline void CreateFolder(std::string const &path) + { + CreateFolder(path.c_str()); + } -inline std::string PathCombine(std::string a, std::string b) { return a + PATH_SLASH + b; }; + inline std::string PathCombine(std::string a, std::string b) + { + return a + PATH_SLASH + b; + }; -std::string GetUserHomeDirectory(); //!< Returns UTF-8 path or empty string on error -std::string GetExecutablePath(); //!< Returns UTF-8 path or empty string on error -std::string GetParentDirectory(const char* path); //!< Returns UTF-8 path without trailing slash. + std::string GetUserHomeDirectory(); //!< Returns UTF-8 path or empty string on error + std::string GetExecutablePath(); //!< Returns UTF-8 path or empty string on error + std::string GetParentDirectory(const char *path); //!< Returns UTF-8 path without trailing slash. -std::time_t GetFileLastModifiedTime(std::string const & path); + std::time_t GetFileLastModifiedTime(std::string const &path); } // namespace RoR diff --git a/source/main/utils/SHA1.cpp b/source/main/utils/SHA1.cpp index f38e8f0686..af48a78110 100644 --- a/source/main/utils/SHA1.cpp +++ b/source/main/utils/SHA1.cpp @@ -37,34 +37,54 @@ using namespace RoR; #ifdef SHA1_UTILITY_FUNCTIONS -#define SHA1_MAX_FILE_BUFFER 8000 + #define SHA1_MAX_FILE_BUFFER 8000 #endif // Rotate x bits to the left #ifndef ROL32 -#ifdef _MSC_VER -#define ROL32(_val32, _nBits) _rotl(_val32, _nBits) -#else -#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits)))) -#endif + #ifdef _MSC_VER + #define ROL32(_val32, _nBits) _rotl(_val32, _nBits) + #else + #define ROL32(_val32, _nBits) (((_val32) << (_nBits)) | ((_val32) >> (32 - (_nBits)))) + #endif #endif #ifdef SHA1_LITTLE_ENDIAN -#define SHABLK0(i) (m_block->l[i] = \ - (ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF)) + #define SHABLK0(i) (m_block->l[i] = (ROL32(m_block->l[i], 24) & 0xFF00FF00) | (ROL32(m_block->l[i], 8) & 0x00FF00FF)) #else -#define SHABLK0(i) (m_block->l[i]) + #define SHABLK0(i) (m_block->l[i]) #endif -#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \ - ^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1)) +#define SHABLK(i) \ + (m_block->l[i & 15] = \ + ROL32(m_block->l[(i + 13) & 15] ^ m_block->l[(i + 8) & 15] ^ m_block->l[(i + 2) & 15] ^ m_block->l[i & 15], 1)) // SHA-1 rounds -#define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } -#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } -#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); } -#define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); } -#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); } +#define _R0(v, w, x, y, z, i) \ + { \ + z += ((w & (x ^ y)) ^ y) + SHABLK0(i) + 0x5A827999 + ROL32(v, 5); \ + w = ROL32(w, 30); \ + } +#define _R1(v, w, x, y, z, i) \ + { \ + z += ((w & (x ^ y)) ^ y) + SHABLK(i) + 0x5A827999 + ROL32(v, 5); \ + w = ROL32(w, 30); \ + } +#define _R2(v, w, x, y, z, i) \ + { \ + z += (w ^ x ^ y) + SHABLK(i) + 0x6ED9EBA1 + ROL32(v, 5); \ + w = ROL32(w, 30); \ + } +#define _R3(v, w, x, y, z, i) \ + { \ + z += (((w | x) & y) | (w & x)) + SHABLK(i) + 0x8F1BBCDC + ROL32(v, 5); \ + w = ROL32(w, 30); \ + } +#define _R4(v, w, x, y, z, i) \ + { \ + z += (w ^ x ^ y) + SHABLK(i) + 0xCA62C1D6 + ROL32(v, 5); \ + w = ROL32(w, 30); \ + } CSHA1::CSHA1() { @@ -99,26 +119,86 @@ void CSHA1::Transform(uint32_t *state, uint8_t *buffer) memcpy(m_block, buffer, 64); // 4 rounds of 20 operations each. Loop unrolled. - _R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3); - _R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7); - _R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11); - _R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15); - _R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19); - _R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23); - _R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27); - _R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31); - _R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35); - _R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39); - _R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43); - _R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47); - _R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51); - _R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55); - _R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59); - _R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63); - _R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67); - _R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71); - _R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75); - _R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79); + _R0(a, b, c, d, e, 0); + _R0(e, a, b, c, d, 1); + _R0(d, e, a, b, c, 2); + _R0(c, d, e, a, b, 3); + _R0(b, c, d, e, a, 4); + _R0(a, b, c, d, e, 5); + _R0(e, a, b, c, d, 6); + _R0(d, e, a, b, c, 7); + _R0(c, d, e, a, b, 8); + _R0(b, c, d, e, a, 9); + _R0(a, b, c, d, e, 10); + _R0(e, a, b, c, d, 11); + _R0(d, e, a, b, c, 12); + _R0(c, d, e, a, b, 13); + _R0(b, c, d, e, a, 14); + _R0(a, b, c, d, e, 15); + _R1(e, a, b, c, d, 16); + _R1(d, e, a, b, c, 17); + _R1(c, d, e, a, b, 18); + _R1(b, c, d, e, a, 19); + _R2(a, b, c, d, e, 20); + _R2(e, a, b, c, d, 21); + _R2(d, e, a, b, c, 22); + _R2(c, d, e, a, b, 23); + _R2(b, c, d, e, a, 24); + _R2(a, b, c, d, e, 25); + _R2(e, a, b, c, d, 26); + _R2(d, e, a, b, c, 27); + _R2(c, d, e, a, b, 28); + _R2(b, c, d, e, a, 29); + _R2(a, b, c, d, e, 30); + _R2(e, a, b, c, d, 31); + _R2(d, e, a, b, c, 32); + _R2(c, d, e, a, b, 33); + _R2(b, c, d, e, a, 34); + _R2(a, b, c, d, e, 35); + _R2(e, a, b, c, d, 36); + _R2(d, e, a, b, c, 37); + _R2(c, d, e, a, b, 38); + _R2(b, c, d, e, a, 39); + _R3(a, b, c, d, e, 40); + _R3(e, a, b, c, d, 41); + _R3(d, e, a, b, c, 42); + _R3(c, d, e, a, b, 43); + _R3(b, c, d, e, a, 44); + _R3(a, b, c, d, e, 45); + _R3(e, a, b, c, d, 46); + _R3(d, e, a, b, c, 47); + _R3(c, d, e, a, b, 48); + _R3(b, c, d, e, a, 49); + _R3(a, b, c, d, e, 50); + _R3(e, a, b, c, d, 51); + _R3(d, e, a, b, c, 52); + _R3(c, d, e, a, b, 53); + _R3(b, c, d, e, a, 54); + _R3(a, b, c, d, e, 55); + _R3(e, a, b, c, d, 56); + _R3(d, e, a, b, c, 57); + _R3(c, d, e, a, b, 58); + _R3(b, c, d, e, a, 59); + _R4(a, b, c, d, e, 60); + _R4(e, a, b, c, d, 61); + _R4(d, e, a, b, c, 62); + _R4(c, d, e, a, b, 63); + _R4(b, c, d, e, a, 64); + _R4(a, b, c, d, e, 65); + _R4(e, a, b, c, d, 66); + _R4(d, e, a, b, c, 67); + _R4(c, d, e, a, b, 68); + _R4(b, c, d, e, a, 69); + _R4(a, b, c, d, e, 70); + _R4(e, a, b, c, d, 71); + _R4(d, e, a, b, c, 72); + _R4(c, d, e, a, b, 73); + _R4(b, c, d, e, a, 74); + _R4(a, b, c, d, e, 75); + _R4(e, a, b, c, d, 76); + _R4(d, e, a, b, c, 77); + _R4(c, d, e, a, b, 78); + _R4(b, c, d, e, a, 79); // Add the working vars back into state state[0] += a; @@ -150,11 +230,13 @@ void CSHA1::UpdateHash(uint8_t *data, uint32_t len) memcpy(&m_buffer[j], data, i); Transform(m_state, m_buffer); - for ( ; i + 63 < len; i += 64) Transform(m_state, &data[i]); + for (; i + 63 < len; i += 64) + Transform(m_state, &data[i]); j = 0; } - else i = 0; + else + i = 0; memcpy(&m_buffer[j], &data[i], len - i); } @@ -165,8 +247,8 @@ bool CSHA1::HashFile(char *szFileName) { unsigned long ulFileSize, ulRest, ulBlocks; unsigned long i; - uint8_t uData[SHA1_MAX_FILE_BUFFER]; - FILE *fIn; + uint8_t uData[SHA1_MAX_FILE_BUFFER]; + FILE * fIn; if (szFileName == NULL) return false; @@ -180,12 +262,12 @@ bool CSHA1::HashFile(char *szFileName) if (ulFileSize != 0) { ulBlocks = ulFileSize / SHA1_MAX_FILE_BUFFER; - ulRest = ulFileSize % SHA1_MAX_FILE_BUFFER; + ulRest = ulFileSize % SHA1_MAX_FILE_BUFFER; } else { ulBlocks = 0; - ulRest = 0; + ulRest = 0; } for (i = 0; i < ulBlocks; i++) @@ -200,7 +282,8 @@ bool CSHA1::HashFile(char *szFileName) UpdateHash((uint8_t *)uData, ulRest); } - fclose(fIn); fIn = NULL; + fclose(fIn); + fIn = NULL; return true; } #endif @@ -208,11 +291,10 @@ bool CSHA1::HashFile(char *szFileName) void CSHA1::Final() { uint32_t i; - uint8_t finalcount[8]; + uint8_t finalcount[8]; for (i = 0; i < 8; i++) - finalcount[i] = (uint8_t)((m_count[((i >= 4) ? 0 : 1)] - >> ((3 - (i & 3)) * 8) ) & 255); // Endian independent + finalcount[i] = (uint8_t)((m_count[((i >= 4) ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); // Endian independent UpdateHash((uint8_t *)"\200", 1); @@ -223,7 +305,7 @@ void CSHA1::Final() for (i = 0; i < 20; i++) { - m_digest[i] = (uint8_t)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255); + m_digest[i] = (uint8_t)((m_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } // Wipe variables for security reasons @@ -242,8 +324,8 @@ void CSHA1::Final() std::string CSHA1::ReportHash() { unsigned char i; - char szTemp[16] = {}; - char szReport[41] = {}; // 40 characters of hash + terminator NULL-character + char szTemp[16] = {}; + char szReport[41] = {}; // 40 characters of hash + terminator NULL-character for (i = 0; i < 20; i++) { diff --git a/source/main/utils/SHA1.h b/source/main/utils/SHA1.h index 937f967d98..d794e61e2f 100644 --- a/source/main/utils/SHA1.h +++ b/source/main/utils/SHA1.h @@ -39,18 +39,18 @@ #include //"pstdint.h" // Needed for uint32_t, uint8_t #if !defined(SHA1_UTILITY_FUNCTIONS) && !defined(SHA1_NO_UTILITY_FUNCTIONS) -#define SHA1_UTILITY_FUNCTIONS + #define SHA1_UTILITY_FUNCTIONS #endif #include // Needed for memset and memcpy #ifdef SHA1_UTILITY_FUNCTIONS -#include // Needed for file access and sprintf -#include // Needed for strcat and strcpy + #include // Needed for file access and sprintf + #include // Needed for strcat and strcpy #endif #ifdef _MSC_VER -#include + #include #endif // You can define the endian mode in your files, without modifying the SHA1 @@ -59,7 +59,7 @@ // define anything, the class defaults to little endian. #if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN) -#define SHA1_LITTLE_ENDIAN + #define SHA1_LITTLE_ENDIAN #endif // Same here. If you want variable wiping, #define SHA1_WIPE_VARIABLES, if @@ -67,60 +67,58 @@ // defaults to wiping. #if !defined(SHA1_WIPE_VARIABLES) && !defined(SHA1_NO_WIPE_VARIABLES) -#define SHA1_WIPE_VARIABLES + #define SHA1_WIPE_VARIABLES #endif ///////////////////////////////////////////////////////////////////////////// // Declare SHA1 workspace -typedef union -{ - uint8_t c[64]; +typedef union { + uint8_t c[64]; uint32_t l[16]; } SHA1_WORKSPACE_BLOCK; -namespace RoR { - -class CSHA1 : public ZeroedMemoryAllocator +namespace RoR { -public: - // Constructor and Destructor - CSHA1(); - ~CSHA1(); + class CSHA1 : public ZeroedMemoryAllocator + { + public: + // Constructor and Destructor + CSHA1(); + ~CSHA1(); - uint32_t m_state[5]; - uint32_t m_count[2]; - uint32_t __reserved1[1]; - uint8_t m_buffer[64]; - uint8_t m_digest[20]; - uint32_t __reserved2[3]; + uint32_t m_state[5]; + uint32_t m_count[2]; + uint32_t __reserved1[1]; + uint8_t m_buffer[64]; + uint8_t m_digest[20]; + uint32_t __reserved2[3]; - void Reset(); + void Reset(); - // Update the hash value - void UpdateHash(uint8_t* data, uint32_t len); + // Update the hash value + void UpdateHash(uint8_t *data, uint32_t len); #ifdef SHA1_UTILITY_FUNCTIONS - bool HashFile(char* szFileName); + bool HashFile(char *szFileName); #endif - // Finalize hash and report - void Final(); + // Finalize hash and report + void Final(); - // Report functions: as pre-formatted and raw data + // Report functions: as pre-formatted and raw data #ifdef SHA1_UTILITY_FUNCTIONS - std::string ReportHash(); + std::string ReportHash(); #endif - void GetHash(uint8_t* puDest); - -private: - // Private SHA-1 transformation - void Transform(uint32_t* state, uint8_t* buffer); + void GetHash(uint8_t *puDest); - // Member variables - uint8_t m_workspace[64]; - SHA1_WORKSPACE_BLOCK* m_block; // SHA1 pointer to the byte array above -}; + private: + // Private SHA-1 transformation + void Transform(uint32_t *state, uint8_t *buffer); -}; //namespace RoR + // Member variables + uint8_t m_workspace[64]; + SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above + }; +}; // namespace RoR diff --git a/source/main/utils/Settings.cpp b/source/main/utils/Settings.cpp index 516574d933..37606d678a 100644 --- a/source/main/utils/Settings.cpp +++ b/source/main/utils/Settings.cpp @@ -19,37 +19,37 @@ along with Rigs of Rods. If not, see . */ - /// @file /// @date 4th of January 2009 /// @author Thomas Fischer #include "Settings.h" + #include "Utils.h" #include #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 -#include // for _chdir -#include + #include + #include // for _chdir #endif #include "Application.h" #include "ErrorUtils.h" #include "Language.h" #include "PlatformUtils.h" - #include "Utils.h" // simpleopt by http://code.jellycan.com/simpleopt/ // license: MIT #ifdef _UNICODE -# undef _UNICODE // We want narrow-string args. + #undef _UNICODE // We want narrow-string args. #endif #include "SimpleOpt.h" // option identifiers -enum { +enum +{ OPT_HELP, OPT_MAP, OPT_POS, @@ -65,52 +65,60 @@ enum { }; // option array -CSimpleOpt::SOption cmdline_options[] = { - { OPT_MAP, ("-map"), SO_REQ_SEP }, - { OPT_MAP, ("-terrain"), SO_REQ_SEP }, - { OPT_POS, ("-pos"), SO_REQ_SEP }, - { OPT_ROT, ("-rot"), SO_REQ_SEP }, - { OPT_TRUCK, ("-truck"), SO_REQ_SEP }, - { OPT_TRUCKCONFIG, ("-truckconfig"), SO_REQ_SEP }, - { OPT_ENTERTRUCK, ("-enter"), SO_NONE }, - { OPT_WDIR, ("-wd"), SO_REQ_SEP }, - { OPT_HELP, ("--help"), SO_NONE }, - { OPT_HELP, ("-help"), SO_NONE }, - { OPT_RESUME, ("-resume"), SO_NONE }, - { OPT_CHECKCACHE, ("-checkcache"), SO_NONE }, - { OPT_VER, ("-version"), SO_NONE }, - { OPT_JOINMPSERVER, ("-joinserver"), SO_REQ_CMB }, - SO_END_OF_OPTIONS -}; - -namespace RoR { - -void ShowCommandLineUsage() +CSimpleOpt::SOption cmdline_options[] = {{OPT_MAP, ("-map"), SO_REQ_SEP}, + {OPT_MAP, ("-terrain"), SO_REQ_SEP}, + {OPT_POS, ("-pos"), SO_REQ_SEP}, + {OPT_ROT, ("-rot"), SO_REQ_SEP}, + {OPT_TRUCK, ("-truck"), SO_REQ_SEP}, + {OPT_TRUCKCONFIG, ("-truckconfig"), SO_REQ_SEP}, + {OPT_ENTERTRUCK, ("-enter"), SO_NONE}, + {OPT_WDIR, ("-wd"), SO_REQ_SEP}, + {OPT_HELP, ("--help"), SO_NONE}, + {OPT_HELP, ("-help"), SO_NONE}, + {OPT_RESUME, ("-resume"), SO_NONE}, + {OPT_CHECKCACHE, ("-checkcache"), SO_NONE}, + {OPT_VER, ("-version"), SO_NONE}, + {OPT_JOINMPSERVER, ("-joinserver"), SO_REQ_CMB}, + SO_END_OF_OPTIONS}; + +namespace RoR { - ErrorUtils::ShowInfo( - _L("Command Line Arguments"), - _L("--help (this)" "\n" - "-map (loads map on startup)" "\n" - "-pos (overrides spawn position)" "\n" - "-rot (overrides spawn rotation)" "\n" - "-truck (loads truck on startup)" "\n" - "-truckconfig
" "\n" - "-enter (player enters the selected truck)" "\n" - "-resume loads previous autosave" "\n" - "-checkcache forces cache update" "\n" - "-version shows the version information" "\n" - "For example: RoR.exe -map simple2 -pos '518 0 518' -rot 45 -truck semi.truck -enter")); -} -void ShowVersion() -{ - ErrorUtils::ShowInfo(_L("Version Information"), getVersionString()); + void ShowCommandLineUsage() + { + ErrorUtils::ShowInfo(_L("Command Line Arguments"), + _L("--help (this)" + "\n" + "-map (loads map on startup)" + "\n" + "-pos (overrides spawn position)" + "\n" + "-rot (overrides spawn rotation)" + "\n" + "-truck (loads truck on startup)" + "\n" + "-truckconfig
" + "\n" + "-enter (player enters the selected truck)" + "\n" + "-resume loads previous autosave" + "\n" + "-checkcache forces cache update" + "\n" + "-version shows the version information" + "\n" + "For example: RoR.exe -map simple2 -pos '518 0 518' -rot 45 -truck semi.truck -enter")); + } + + void ShowVersion() + { + ErrorUtils::ShowInfo(_L("Version Information"), getVersionString()); #ifdef __GNUC__ - printf(" * built with gcc %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); + printf(" * built with gcc %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); #endif //__GNUC__ -} + } -} +} // namespace RoR using namespace Ogre; using namespace RoR; @@ -181,7 +189,7 @@ void Settings::ProcessCommandLine(int argc, char *argv[]) else if (args.OptionId() == OPT_JOINMPSERVER) { std::string server_args = args.OptionArg(); - const int colon = static_cast(server_args.rfind(":")); + const int colon = static_cast(server_args.rfind(":")); if (colon != std::string::npos) { App::mp_join_on_startup.SetActive(true); @@ -205,169 +213,298 @@ void Settings::ProcessCommandLine(int argc, char *argv[]) } } -const char* CONF_GFX_SHADOW_PSSM = "Parallel-split Shadow Maps"; -const char* CONF_GFX_SHADOW_NONE = "No shadows (fastest)"; - -const char* CONF_EXTCAM_PITCHING = "Pitching"; -const char* CONF_EXTCAM_STATIC = "Static"; -const char* CONF_EXTCAM_NONE = "None"; - -const char* CONF_TEXFILTER_NONE = "None (fastest)"; -const char* CONF_TEXFILTER_BILI = "Bilinear"; -const char* CONF_TEXFILTER_TRILI = "Trilinear"; -const char* CONF_TEXFILTER_ANISO = "Anisotropic (best looking)"; - -const char* CONF_VEGET_NONE = "None (fastest)"; -const char* CONF_VEGET_20PERC = "20%"; -const char* CONF_VEGET_50PERC = "50%"; -const char* CONF_VEGET_FULL = "Full (best looking, slower)"; - -const char* CONF_GEARBOX_AUTO = "Automatic shift"; -const char* CONF_GEARBOX_SEMIAUTO = "Manual shift - Auto clutch"; -const char* CONF_GEARBOX_MANUAL = "Fully Manual: sequential shift"; -const char* CONF_GEARBOX_MAN_STICK = "Fully manual: stick shift"; -const char* CONF_GEARBOX_MAN_RANGES = "Fully Manual: stick shift with ranges"; - -const char* CONF_FLARES_NONE = "None (fastest)"; -const char* CONF_FLARES_NO_LIGHT = "No light sources"; -const char* CONF_FLARES_CURR_HEAD = "Only current vehicle, main lights"; -const char* CONF_FLARES_ALL_HEADS = "All vehicles, main lights"; -const char* CONF_FLARES_ALL_LIGHTS = "All vehicles, all lights"; - -const char* CONF_WATER_NONE = "None"; -const char* CONF_WATER_BASIC = "Basic (fastest)"; -const char* CONF_WATER_REFLECT = "Reflection"; -const char* CONF_WATER_FULL_FAST = "Reflection + refraction (speed optimized)"; -const char* CONF_WATER_FULL_HQ = "Reflection + refraction (quality optimized)"; -const char* CONF_WATER_HYDRAX = "Hydrax"; - -const char* CONF_SKY_CAELUM = "Caelum (best looking, slower)"; -const char* CONF_SKY_SKYX = "SkyX (best looking, slower)"; -const char* CONF_SKY_SANDSTORM = "Sandstorm (fastest)"; - -const char* CONF_INPUT_GRAB_DYNAMIC = "Dynamically"; -const char* CONF_INPUT_GRAB_NONE = "None"; -const char* CONF_INPUT_GRAB_ALL = "All"; +const char *CONF_GFX_SHADOW_PSSM = "Parallel-split Shadow Maps"; +const char *CONF_GFX_SHADOW_NONE = "No shadows (fastest)"; + +const char *CONF_EXTCAM_PITCHING = "Pitching"; +const char *CONF_EXTCAM_STATIC = "Static"; +const char *CONF_EXTCAM_NONE = "None"; + +const char *CONF_TEXFILTER_NONE = "None (fastest)"; +const char *CONF_TEXFILTER_BILI = "Bilinear"; +const char *CONF_TEXFILTER_TRILI = "Trilinear"; +const char *CONF_TEXFILTER_ANISO = "Anisotropic (best looking)"; + +const char *CONF_VEGET_NONE = "None (fastest)"; +const char *CONF_VEGET_20PERC = "20%"; +const char *CONF_VEGET_50PERC = "50%"; +const char *CONF_VEGET_FULL = "Full (best looking, slower)"; + +const char *CONF_GEARBOX_AUTO = "Automatic shift"; +const char *CONF_GEARBOX_SEMIAUTO = "Manual shift - Auto clutch"; +const char *CONF_GEARBOX_MANUAL = "Fully Manual: sequential shift"; +const char *CONF_GEARBOX_MAN_STICK = "Fully manual: stick shift"; +const char *CONF_GEARBOX_MAN_RANGES = "Fully Manual: stick shift with ranges"; + +const char *CONF_FLARES_NONE = "None (fastest)"; +const char *CONF_FLARES_NO_LIGHT = "No light sources"; +const char *CONF_FLARES_CURR_HEAD = "Only current vehicle, main lights"; +const char *CONF_FLARES_ALL_HEADS = "All vehicles, main lights"; +const char *CONF_FLARES_ALL_LIGHTS = "All vehicles, all lights"; + +const char *CONF_WATER_NONE = "None"; +const char *CONF_WATER_BASIC = "Basic (fastest)"; +const char *CONF_WATER_REFLECT = "Reflection"; +const char *CONF_WATER_FULL_FAST = "Reflection + refraction (speed optimized)"; +const char *CONF_WATER_FULL_HQ = "Reflection + refraction (quality optimized)"; +const char *CONF_WATER_HYDRAX = "Hydrax"; + +const char *CONF_SKY_CAELUM = "Caelum (best looking, slower)"; +const char *CONF_SKY_SKYX = "SkyX (best looking, slower)"; +const char *CONF_SKY_SANDSTORM = "Sandstorm (fastest)"; + +const char *CONF_INPUT_GRAB_DYNAMIC = "Dynamically"; +const char *CONF_INPUT_GRAB_NONE = "None"; +const char *CONF_INPUT_GRAB_ALL = "All"; // ---------------------------- READING CONFIG FILE ------------------------------- // -inline bool CheckIoInputGrabMode(std::string const & key, std::string const & s) +inline bool CheckIoInputGrabMode(std::string const &key, std::string const &s) { - if (key != App::io_input_grab_mode.conf_name) - return false; + if (key != App::io_input_grab_mode.conf_name) return false; - if (s == CONF_INPUT_GRAB_DYNAMIC) { App::io_input_grab_mode.SetActive(RoR::IoInputGrabMode::DYNAMIC); return true; } - if (s == CONF_INPUT_GRAB_NONE ) { App::io_input_grab_mode.SetActive(RoR::IoInputGrabMode::NONE); return true; } - else { App::io_input_grab_mode.SetActive(RoR::IoInputGrabMode::ALL); return true; } + if (s == CONF_INPUT_GRAB_DYNAMIC) + { + App::io_input_grab_mode.SetActive(RoR::IoInputGrabMode::DYNAMIC); + return true; + } + if (s == CONF_INPUT_GRAB_NONE) + { + App::io_input_grab_mode.SetActive(RoR::IoInputGrabMode::NONE); + return true; + } + else + { + App::io_input_grab_mode.SetActive(RoR::IoInputGrabMode::ALL); + return true; + } } -inline bool CheckShadowTech(std::string const & key, std::string const & s) +inline bool CheckShadowTech(std::string const &key, std::string const &s) { - if (key != App::gfx_shadow_type.conf_name) - return false; + if (key != App::gfx_shadow_type.conf_name) return false; - if (s == CONF_GFX_SHADOW_PSSM) { App::gfx_shadow_type.SetActive(GfxShadowType::PSSM ); return true; } - else { App::gfx_shadow_type.SetActive(GfxShadowType::NONE ); return true; } + if (s == CONF_GFX_SHADOW_PSSM) + { + App::gfx_shadow_type.SetActive(GfxShadowType::PSSM); + return true; + } + else + { + App::gfx_shadow_type.SetActive(GfxShadowType::NONE); + return true; + } } -inline bool CheckExtcamMode(std::string const & key, std::string const & s) +inline bool CheckExtcamMode(std::string const &key, std::string const &s) { - if (key != App::gfx_extcam_mode.conf_name) - return false; + if (key != App::gfx_extcam_mode.conf_name) return false; - if (s == CONF_EXTCAM_PITCHING) { App::gfx_extcam_mode.SetActive(GfxExtCamMode::PITCHING); return true; } - if (s == CONF_EXTCAM_STATIC) { App::gfx_extcam_mode.SetActive(GfxExtCamMode::STATIC ); return true; } - else { App::gfx_extcam_mode.SetActive(GfxExtCamMode::NONE ); return true; } + if (s == CONF_EXTCAM_PITCHING) + { + App::gfx_extcam_mode.SetActive(GfxExtCamMode::PITCHING); + return true; + } + if (s == CONF_EXTCAM_STATIC) + { + App::gfx_extcam_mode.SetActive(GfxExtCamMode::STATIC); + return true; + } + else + { + App::gfx_extcam_mode.SetActive(GfxExtCamMode::NONE); + return true; + } } -inline bool CheckTexFiltering(std::string const & key, std::string const & s) +inline bool CheckTexFiltering(std::string const &key, std::string const &s) { - if (key != App::gfx_texture_filter.conf_name) - return false; + if (key != App::gfx_texture_filter.conf_name) return false; - if (s == CONF_TEXFILTER_NONE) { App::gfx_texture_filter.SetActive(GfxTexFilter::NONE); return true; } - if (s == CONF_TEXFILTER_BILI) { App::gfx_texture_filter.SetActive(GfxTexFilter::BILINEAR); return true; } - if (s == CONF_TEXFILTER_TRILI) { App::gfx_texture_filter.SetActive(GfxTexFilter::TRILINEAR); return true; } - if (s == CONF_TEXFILTER_ANISO) { App::gfx_texture_filter.SetActive(GfxTexFilter::ANISOTROPIC); return true; } + if (s == CONF_TEXFILTER_NONE) + { + App::gfx_texture_filter.SetActive(GfxTexFilter::NONE); + return true; + } + if (s == CONF_TEXFILTER_BILI) + { + App::gfx_texture_filter.SetActive(GfxTexFilter::BILINEAR); + return true; + } + if (s == CONF_TEXFILTER_TRILI) + { + App::gfx_texture_filter.SetActive(GfxTexFilter::TRILINEAR); + return true; + } + if (s == CONF_TEXFILTER_ANISO) + { + App::gfx_texture_filter.SetActive(GfxTexFilter::ANISOTROPIC); + return true; + } return true; } -inline bool CheckVegetationMode(std::string const & key, std::string const & s) +inline bool CheckVegetationMode(std::string const &key, std::string const &s) { - if (key != App::gfx_vegetation_mode.conf_name) - return false; + if (key != App::gfx_vegetation_mode.conf_name) return false; - if (s == CONF_VEGET_NONE ) { App::gfx_vegetation_mode.SetActive(GfxVegetation::NONE); return true; } - if (s == CONF_VEGET_20PERC) { App::gfx_vegetation_mode.SetActive(GfxVegetation::x20PERC); return true; } - if (s == CONF_VEGET_50PERC) { App::gfx_vegetation_mode.SetActive(GfxVegetation::x50PERC); return true; } - if (s == CONF_VEGET_FULL ) { App::gfx_vegetation_mode.SetActive(GfxVegetation::FULL); return true; } + if (s == CONF_VEGET_NONE) + { + App::gfx_vegetation_mode.SetActive(GfxVegetation::NONE); + return true; + } + if (s == CONF_VEGET_20PERC) + { + App::gfx_vegetation_mode.SetActive(GfxVegetation::x20PERC); + return true; + } + if (s == CONF_VEGET_50PERC) + { + App::gfx_vegetation_mode.SetActive(GfxVegetation::x50PERC); + return true; + } + if (s == CONF_VEGET_FULL) + { + App::gfx_vegetation_mode.SetActive(GfxVegetation::FULL); + return true; + } return true; } -inline bool CheckSimGearboxMode(std::string const & key, std::string const & s) +inline bool CheckSimGearboxMode(std::string const &key, std::string const &s) { - if (key != App::sim_gearbox_mode.conf_name) - return false; + if (key != App::sim_gearbox_mode.conf_name) return false; - if (s == CONF_GEARBOX_AUTO ) { App::sim_gearbox_mode.SetActive(SimGearboxMode::AUTO ); return true; } - if (s == CONF_GEARBOX_SEMIAUTO ) { App::sim_gearbox_mode.SetActive(SimGearboxMode::SEMI_AUTO ); return true; } - if (s == CONF_GEARBOX_MANUAL ) { App::sim_gearbox_mode.SetActive(SimGearboxMode::MANUAL ); return true; } - if (s == CONF_GEARBOX_MAN_STICK ) { App::sim_gearbox_mode.SetActive(SimGearboxMode::MANUAL_STICK ); return true; } - if (s == CONF_GEARBOX_MAN_RANGES) { App::sim_gearbox_mode.SetActive(SimGearboxMode::MANUAL_RANGES); return true; } + if (s == CONF_GEARBOX_AUTO) + { + App::sim_gearbox_mode.SetActive(SimGearboxMode::AUTO); + return true; + } + if (s == CONF_GEARBOX_SEMIAUTO) + { + App::sim_gearbox_mode.SetActive(SimGearboxMode::SEMI_AUTO); + return true; + } + if (s == CONF_GEARBOX_MANUAL) + { + App::sim_gearbox_mode.SetActive(SimGearboxMode::MANUAL); + return true; + } + if (s == CONF_GEARBOX_MAN_STICK) + { + App::sim_gearbox_mode.SetActive(SimGearboxMode::MANUAL_STICK); + return true; + } + if (s == CONF_GEARBOX_MAN_RANGES) + { + App::sim_gearbox_mode.SetActive(SimGearboxMode::MANUAL_RANGES); + return true; + } return true; } -inline bool CheckGfxFlaresMode(std::string const & key, std::string const & s) +inline bool CheckGfxFlaresMode(std::string const &key, std::string const &s) { - if (key != App::gfx_flares_mode.conf_name) - return false; + if (key != App::gfx_flares_mode.conf_name) return false; - if (s == CONF_FLARES_NONE ) { App::gfx_flares_mode.SetActive(GfxFlaresMode::NONE); return true; } - if (s == CONF_FLARES_NO_LIGHT ) { App::gfx_flares_mode.SetActive(GfxFlaresMode::NO_LIGHTSOURCES); return true; } - if (s == CONF_FLARES_CURR_HEAD ) { App::gfx_flares_mode.SetActive(GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY); return true; } - if (s == CONF_FLARES_ALL_HEADS ) { App::gfx_flares_mode.SetActive(GfxFlaresMode::ALL_VEHICLES_HEAD_ONLY); return true; } - if (s == CONF_FLARES_ALL_LIGHTS) { App::gfx_flares_mode.SetActive(GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS); return true; } + if (s == CONF_FLARES_NONE) + { + App::gfx_flares_mode.SetActive(GfxFlaresMode::NONE); + return true; + } + if (s == CONF_FLARES_NO_LIGHT) + { + App::gfx_flares_mode.SetActive(GfxFlaresMode::NO_LIGHTSOURCES); + return true; + } + if (s == CONF_FLARES_CURR_HEAD) + { + App::gfx_flares_mode.SetActive(GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY); + return true; + } + if (s == CONF_FLARES_ALL_HEADS) + { + App::gfx_flares_mode.SetActive(GfxFlaresMode::ALL_VEHICLES_HEAD_ONLY); + return true; + } + if (s == CONF_FLARES_ALL_LIGHTS) + { + App::gfx_flares_mode.SetActive(GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS); + return true; + } return true; } -inline bool CheckGfxWaterMode(std::string const & key, std::string const & s) +inline bool CheckGfxWaterMode(std::string const &key, std::string const &s) { - if (key != App::gfx_water_mode.conf_name) - return false; + if (key != App::gfx_water_mode.conf_name) return false; - if (s == CONF_WATER_NONE ) { App::gfx_water_mode.SetActive(GfxWaterMode::NONE ); return true; } - if (s == CONF_WATER_BASIC ) { App::gfx_water_mode.SetActive(GfxWaterMode::BASIC ); return true; } - if (s == CONF_WATER_REFLECT ) { App::gfx_water_mode.SetActive(GfxWaterMode::REFLECT ); return true; } - if (s == CONF_WATER_FULL_FAST) { App::gfx_water_mode.SetActive(GfxWaterMode::FULL_FAST); return true; } - if (s == CONF_WATER_FULL_HQ ) { App::gfx_water_mode.SetActive(GfxWaterMode::FULL_HQ ); return true; } - if (s == CONF_WATER_HYDRAX ) { App::gfx_water_mode.SetActive(GfxWaterMode::HYDRAX ); return true; } + if (s == CONF_WATER_NONE) + { + App::gfx_water_mode.SetActive(GfxWaterMode::NONE); + return true; + } + if (s == CONF_WATER_BASIC) + { + App::gfx_water_mode.SetActive(GfxWaterMode::BASIC); + return true; + } + if (s == CONF_WATER_REFLECT) + { + App::gfx_water_mode.SetActive(GfxWaterMode::REFLECT); + return true; + } + if (s == CONF_WATER_FULL_FAST) + { + App::gfx_water_mode.SetActive(GfxWaterMode::FULL_FAST); + return true; + } + if (s == CONF_WATER_FULL_HQ) + { + App::gfx_water_mode.SetActive(GfxWaterMode::FULL_HQ); + return true; + } + if (s == CONF_WATER_HYDRAX) + { + App::gfx_water_mode.SetActive(GfxWaterMode::HYDRAX); + return true; + } return true; } -inline bool CheckGfxSkyMode(std::string const & key, std::string const & s) +inline bool CheckGfxSkyMode(std::string const &key, std::string const &s) { - if (key != App::gfx_sky_mode.conf_name) - return false; + if (key != App::gfx_sky_mode.conf_name) return false; - if (s == CONF_SKY_SANDSTORM) { App::gfx_sky_mode.SetActive(GfxSkyMode::SANDSTORM); return true; } - if (s == CONF_SKY_CAELUM ) { App::gfx_sky_mode.SetActive(GfxSkyMode::CAELUM); return true; } - if (s == CONF_SKY_SKYX ) { App::gfx_sky_mode.SetActive(GfxSkyMode::SKYX); return true; } + if (s == CONF_SKY_SANDSTORM) + { + App::gfx_sky_mode.SetActive(GfxSkyMode::SANDSTORM); + return true; + } + if (s == CONF_SKY_CAELUM) + { + App::gfx_sky_mode.SetActive(GfxSkyMode::CAELUM); + return true; + } + if (s == CONF_SKY_SKYX) + { + App::gfx_sky_mode.SetActive(GfxSkyMode::SKYX); + return true; + } return true; } -inline bool CheckScreenshotFormat(std::string const & key, std::string const & s) +inline bool CheckScreenshotFormat(std::string const &key, std::string const &s) { - if (key != App::app_screenshot_format.conf_name) - return false; + if (key != App::app_screenshot_format.conf_name) return false; if (s.size() >= 3) { App::app_screenshot_format.SetActive(s.substr(0, 3).c_str()); } return true; } -inline bool CheckEnvmapRate(std::string const & key, std::string const & s) +inline bool CheckEnvmapRate(std::string const &key, std::string const &s) { - if (key != App::gfx_envmap_rate.conf_name) - return false; + if (key != App::gfx_envmap_rate.conf_name) return false; int rate = Ogre::StringConverter::parseInt(s); if (rate < 0) { rate = 0; } @@ -376,10 +513,9 @@ inline bool CheckEnvmapRate(std::string const & key, std::string const & s) return true; } -inline bool CheckShadowQuality(std::string const & key, std::string const & s) +inline bool CheckShadowQuality(std::string const &key, std::string const &s) { - if (key != App::gfx_shadow_quality.conf_name) - return false; + if (key != App::gfx_shadow_quality.conf_name) return false; int quality = Ogre::StringConverter::parseInt(s); if (quality < 0) { quality = 0; } @@ -388,8 +524,7 @@ inline bool CheckShadowQuality(std::string const & key, std::string const & s) return true; } -template -inline bool CheckStr(GVarStr_T& gvar, std::string const & key, std::string const & value) +template inline bool CheckStr(GVarStr_T &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -399,8 +534,7 @@ inline bool CheckStr(GVarStr_T& gvar, std::string const & key, std::string const return false; } -template -inline bool CheckStrAS(GVarStr_T& gvar, std::string const & key, std::string const & value) +template inline bool CheckStrAS(GVarStr_T &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -411,7 +545,7 @@ inline bool CheckStrAS(GVarStr_T& gvar, std::string const & key, std::string con return false; } -inline bool CheckInt(GVarPod_A& gvar, std::string const & key, std::string const & value) +inline bool CheckInt(GVarPod_A &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -421,7 +555,7 @@ inline bool CheckInt(GVarPod_A& gvar, std::string const & key, std::string return false; } -inline bool CheckInt(GVarPod_APS& gvar, std::string const & key, std::string const & value) +inline bool CheckInt(GVarPod_APS &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -433,7 +567,7 @@ inline bool CheckInt(GVarPod_APS& gvar, std::string const & key, std::strin return false; } -inline bool CheckBool(GVarPod_A& gvar, std::string const & key, std::string const & value) +inline bool CheckBool(GVarPod_A &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -443,7 +577,7 @@ inline bool CheckBool(GVarPod_A& gvar, std::string const & key, std::strin return false; } -inline bool CheckBool(GVarPod_APS& gvar, std::string const & key, std::string const & value) +inline bool CheckBool(GVarPod_APS &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -455,7 +589,7 @@ inline bool CheckBool(GVarPod_APS& gvar, std::string const & key, std::str return false; } -inline bool CheckB2I(GVarPod_A& gvar, std::string const & key, std::string const & value) // bool to int +inline bool CheckB2I(GVarPod_A &gvar, std::string const &key, std::string const &value) // bool to int { if (key == gvar.conf_name) { @@ -465,7 +599,7 @@ inline bool CheckB2I(GVarPod_A& gvar, std::string const & key, std::string return false; } -inline bool CheckFloat(GVarPod_A& gvar, std::string const & key, std::string const & value) +inline bool CheckFloat(GVarPod_A &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -475,7 +609,7 @@ inline bool CheckFloat(GVarPod_A& gvar, std::string const & key, std::str return false; } -inline bool CheckFloat(GVarPod_APS& gvar, std::string const & key, std::string const & value) +inline bool CheckFloat(GVarPod_APS &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -487,7 +621,7 @@ inline bool CheckFloat(GVarPod_APS& gvar, std::string const & key, std::s return false; } -inline bool CheckSpeedoImperial(std::string const & key, std::string const & value) +inline bool CheckSpeedoImperial(std::string const &key, std::string const &value) { if (key == "SpeedUnit") // String ["Metric"/"Imperial"], decommissioned 10/2017 { @@ -496,7 +630,7 @@ inline bool CheckSpeedoImperial(std::string const & key, std::string const & val } return CheckBool(App::gfx_speedo_imperial, key, value); } -inline bool CheckFOV(GVarPod_APS& gvar, std::string const & key, std::string const & value) +inline bool CheckFOV(GVarPod_APS &gvar, std::string const &key, std::string const &value) { if (key == gvar.conf_name) { @@ -505,126 +639,126 @@ inline bool CheckFOV(GVarPod_APS& gvar, std::string const & key, std::strin // FOV shouldn't be below 10 if (val < 10) return false; - gvar.SetActive (val); - gvar.SetStored (val); + gvar.SetActive(val); + gvar.SetStored(val); return true; } return false; } -bool Settings::ParseGlobalVarSetting(std::string const & k, std::string const & v) +bool Settings::ParseGlobalVarSetting(std::string const &k, std::string const &v) { // Process and erase settings which propagate to global vars. // Multiplayer - if (CheckBool (App::mp_join_on_startup, k, v)) { return true; } - if (CheckBool (App::mp_chat_auto_hide, k, v)) { return true; } - if (CheckBool (App::mp_hide_net_labels, k, v)) { return true; } - if (CheckBool (App::mp_hide_own_net_label, k, v)) { return true; } - if (CheckBool (App::mp_pseudo_collisions, k, v)) { return true; } - if (CheckStr (App::mp_player_name, k, v)) { return true; } - if (CheckStr (App::mp_server_host, k, v)) { return true; } - if (CheckInt (App::mp_server_port, k, v)) { return true; } - if (CheckStrAS(App::mp_server_password, k, v)) { return true; } - if (CheckStr (App::mp_api_url, k, v)) { return true; } - if (CheckStr (App::mp_player_token, k, v)) { return true; } + if (CheckBool(App::mp_join_on_startup, k, v)) { return true; } + if (CheckBool(App::mp_chat_auto_hide, k, v)) { return true; } + if (CheckBool(App::mp_hide_net_labels, k, v)) { return true; } + if (CheckBool(App::mp_hide_own_net_label, k, v)) { return true; } + if (CheckBool(App::mp_pseudo_collisions, k, v)) { return true; } + if (CheckStr(App::mp_player_name, k, v)) { return true; } + if (CheckStr(App::mp_server_host, k, v)) { return true; } + if (CheckInt(App::mp_server_port, k, v)) { return true; } + if (CheckStrAS(App::mp_server_password, k, v)) { return true; } + if (CheckStr(App::mp_api_url, k, v)) { return true; } + if (CheckStr(App::mp_player_token, k, v)) { return true; } // App - if (CheckScreenshotFormat (k, v)) { return true; } - if (CheckStr (App::app_language, k, v)) { return true; } - if (CheckStr (App::app_country, k, v)) { return true; } - if (CheckStr (App::app_rendersys_override, k, v)) { return true; } - if (CheckBool (App::app_skip_main_menu, k, v)) { return true; } - if (CheckBool (App::app_async_physics, k, v)) { return true; } - if (CheckInt (App::app_num_workers, k, v)) { return true; } - if (CheckStr (App::app_extra_mod_path, k, v)) { return true; } - if (CheckBool (App::app_disable_online_api, k, v)) { return true; } + if (CheckScreenshotFormat(k, v)) { return true; } + if (CheckStr(App::app_language, k, v)) { return true; } + if (CheckStr(App::app_country, k, v)) { return true; } + if (CheckStr(App::app_rendersys_override, k, v)) { return true; } + if (CheckBool(App::app_skip_main_menu, k, v)) { return true; } + if (CheckBool(App::app_async_physics, k, v)) { return true; } + if (CheckInt(App::app_num_workers, k, v)) { return true; } + if (CheckStr(App::app_extra_mod_path, k, v)) { return true; } + if (CheckBool(App::app_disable_online_api, k, v)) { return true; } // Input&Output - if (CheckFloat(App::io_analog_smoothing, k, v)) { return true; } - if (CheckFloat(App::io_analog_sensitivity, k, v)) { return true; } - if (CheckBool (App::io_ffb_enabled, k, v)) { return true; } - if (CheckFloat(App::io_ffb_camera_gain, k, v)) { return true; } - if (CheckFloat(App::io_ffb_center_gain, k, v)) { return true; } - if (CheckFloat(App::io_ffb_master_gain, k, v)) { return true; } - if (CheckFloat(App::io_ffb_stress_gain, k, v)) { return true; } - if (CheckBool (App::io_arcade_controls, k, v)) { return true; } - if (CheckInt (App::io_outgauge_mode, k, v)) { return true; } - if (CheckStr (App::io_outgauge_ip, k, v)) { return true; } - if (CheckInt (App::io_outgauge_port, k, v)) { return true; } - if (CheckFloat(App::io_outgauge_delay, k, v)) { return true; } - if (CheckInt (App::io_outgauge_id, k, v)) { return true; } - if (CheckIoInputGrabMode (k, v)) { return true; } - if (CheckBool (App::io_discord_rpc, k, v)) { return true; } + if (CheckFloat(App::io_analog_smoothing, k, v)) { return true; } + if (CheckFloat(App::io_analog_sensitivity, k, v)) { return true; } + if (CheckBool(App::io_ffb_enabled, k, v)) { return true; } + if (CheckFloat(App::io_ffb_camera_gain, k, v)) { return true; } + if (CheckFloat(App::io_ffb_center_gain, k, v)) { return true; } + if (CheckFloat(App::io_ffb_master_gain, k, v)) { return true; } + if (CheckFloat(App::io_ffb_stress_gain, k, v)) { return true; } + if (CheckBool(App::io_arcade_controls, k, v)) { return true; } + if (CheckInt(App::io_outgauge_mode, k, v)) { return true; } + if (CheckStr(App::io_outgauge_ip, k, v)) { return true; } + if (CheckInt(App::io_outgauge_port, k, v)) { return true; } + if (CheckFloat(App::io_outgauge_delay, k, v)) { return true; } + if (CheckInt(App::io_outgauge_id, k, v)) { return true; } + if (CheckIoInputGrabMode(k, v)) { return true; } + if (CheckBool(App::io_discord_rpc, k, v)) { return true; } // Gfx - if (CheckEnvmapRate (k, v)) { return true; } - if (CheckShadowQuality (k, v)) { return true; } - if (CheckShadowTech (k, v)) { return true; } - if (CheckExtcamMode (k, v)) { return true; } - if (CheckTexFiltering (k, v)) { return true; } - if (CheckVegetationMode (k, v)) { return true; } - if (CheckGfxFlaresMode (k, v)) { return true; } - if (CheckGfxWaterMode (k, v)) { return true; } - if (CheckGfxSkyMode (k, v)) { return true; } - if (CheckSpeedoImperial (k, v)) { return true; } - if (CheckInt (App::gfx_anisotropy, k, v)) { return true; } - if (CheckBool (App::gfx_water_waves, k, v)) { return true; } - if (CheckB2I (App::gfx_particles_mode, k, v)) { return true; } - if (CheckBool (App::gfx_enable_videocams, k, v)) { return true; } - if (CheckBool (App::gfx_window_videocams, k, v)) { return true; } - if (CheckBool (App::gfx_surveymap_icons, k, v)) { return true; } - if (CheckBool (App::gfx_declutter_map, k, v)) { return true; } - if (CheckB2I (App::gfx_skidmarks_mode, k, v)) { return true; } - if (CheckBool (App::gfx_envmap_enabled, k, v)) { return true; } - if (CheckInt (App::gfx_sight_range, k, v)) { return true; } - if (CheckInt (App::gfx_camera_height, k, v)) { return true; } - if (CheckFOV (App::gfx_fov_external, k, v)) { return true; } - if (CheckFOV (App::gfx_fov_internal, k, v)) { return true; } - if (CheckInt (App::gfx_fps_limit, k, v)) { return true; } - if (CheckBool (App::gfx_speedo_digital, k, v)) { return true; } - if (CheckBool (App::gfx_flexbody_lods, k, v)) { return true; } - if (CheckBool (App::gfx_flexbody_cache, k, v)) { return true; } - if (CheckBool (App::gfx_reduce_shadows, k, v)) { return true; } - if (CheckBool (App::gfx_enable_rtshaders, k, v)) { return true; } + if (CheckEnvmapRate(k, v)) { return true; } + if (CheckShadowQuality(k, v)) { return true; } + if (CheckShadowTech(k, v)) { return true; } + if (CheckExtcamMode(k, v)) { return true; } + if (CheckTexFiltering(k, v)) { return true; } + if (CheckVegetationMode(k, v)) { return true; } + if (CheckGfxFlaresMode(k, v)) { return true; } + if (CheckGfxWaterMode(k, v)) { return true; } + if (CheckGfxSkyMode(k, v)) { return true; } + if (CheckSpeedoImperial(k, v)) { return true; } + if (CheckInt(App::gfx_anisotropy, k, v)) { return true; } + if (CheckBool(App::gfx_water_waves, k, v)) { return true; } + if (CheckB2I(App::gfx_particles_mode, k, v)) { return true; } + if (CheckBool(App::gfx_enable_videocams, k, v)) { return true; } + if (CheckBool(App::gfx_window_videocams, k, v)) { return true; } + if (CheckBool(App::gfx_surveymap_icons, k, v)) { return true; } + if (CheckBool(App::gfx_declutter_map, k, v)) { return true; } + if (CheckB2I(App::gfx_skidmarks_mode, k, v)) { return true; } + if (CheckBool(App::gfx_envmap_enabled, k, v)) { return true; } + if (CheckInt(App::gfx_sight_range, k, v)) { return true; } + if (CheckInt(App::gfx_camera_height, k, v)) { return true; } + if (CheckFOV(App::gfx_fov_external, k, v)) { return true; } + if (CheckFOV(App::gfx_fov_internal, k, v)) { return true; } + if (CheckInt(App::gfx_fps_limit, k, v)) { return true; } + if (CheckBool(App::gfx_speedo_digital, k, v)) { return true; } + if (CheckBool(App::gfx_flexbody_lods, k, v)) { return true; } + if (CheckBool(App::gfx_flexbody_cache, k, v)) { return true; } + if (CheckBool(App::gfx_reduce_shadows, k, v)) { return true; } + if (CheckBool(App::gfx_enable_rtshaders, k, v)) { return true; } // Audio - if (CheckFloat(App::audio_master_volume, k, v)) { return true; } - if (CheckBool (App::audio_enable_creak, k, v)) { return true; } - if (CheckBool (App::audio_menu_music, k, v)) { return true; } - if (CheckStr (App::audio_device_name, k, v)) { return true; } + if (CheckFloat(App::audio_master_volume, k, v)) { return true; } + if (CheckBool(App::audio_enable_creak, k, v)) { return true; } + if (CheckBool(App::audio_menu_music, k, v)) { return true; } + if (CheckStr(App::audio_device_name, k, v)) { return true; } // Diag - if (CheckBool (App::diag_auto_spawner_report, k, v)) { return true; } - if (CheckBool (App::diag_camera, k, v)) { return true; } - if (CheckBool (App::diag_rig_log_node_import, k, v)) { return true; } - if (CheckBool (App::diag_rig_log_node_stats, k, v)) { return true; } - if (CheckBool (App::diag_rig_log_messages, k, v)) { return true; } - if (CheckBool (App::diag_collisions, k, v)) { return true; } - if (CheckBool (App::diag_truck_mass, k, v)) { return true; } - if (CheckBool (App::diag_envmap, k, v)) { return true; } - if (CheckBool (App::diag_videocameras, k, v)) { return true; } - if (CheckBool (App::diag_log_console_echo, k, v)) { return true; } - if (CheckBool (App::diag_log_beam_break, k, v)) { return true; } - if (CheckBool (App::diag_log_beam_deform, k, v)) { return true; } - if (CheckBool (App::diag_log_beam_trigger, k, v)) { return true; } - if (CheckStrAS(App::diag_preset_terrain, k, v)) { return true; } - if (CheckStrAS(App::diag_preset_vehicle, k, v)) { return true; } - if (CheckStr (App::diag_preset_veh_config, k, v)) { return true; } - if (CheckBool (App::diag_preset_veh_enter, k, v)) { return true; } - if (CheckBool (App::diag_simple_materials, k, v)) { return true; } - if (CheckBool (App::diag_warning_texture, k, v)) { return true; } - if (CheckBool (App::diag_hide_broken_beams, k, v)) { return true; } - if (CheckBool (App::diag_hide_beam_stress, k, v)) { return true; } - if (CheckBool (App::diag_hide_wheel_info, k, v)) { return true; } - if (CheckBool (App::diag_hide_wheels, k, v)) { return true; } - if (CheckBool (App::diag_hide_nodes, k, v)) { return true; } - if (CheckFloat(App::diag_physics_dt, k, v)) { return true; } + if (CheckBool(App::diag_auto_spawner_report, k, v)) { return true; } + if (CheckBool(App::diag_camera, k, v)) { return true; } + if (CheckBool(App::diag_rig_log_node_import, k, v)) { return true; } + if (CheckBool(App::diag_rig_log_node_stats, k, v)) { return true; } + if (CheckBool(App::diag_rig_log_messages, k, v)) { return true; } + if (CheckBool(App::diag_collisions, k, v)) { return true; } + if (CheckBool(App::diag_truck_mass, k, v)) { return true; } + if (CheckBool(App::diag_envmap, k, v)) { return true; } + if (CheckBool(App::diag_videocameras, k, v)) { return true; } + if (CheckBool(App::diag_log_console_echo, k, v)) { return true; } + if (CheckBool(App::diag_log_beam_break, k, v)) { return true; } + if (CheckBool(App::diag_log_beam_deform, k, v)) { return true; } + if (CheckBool(App::diag_log_beam_trigger, k, v)) { return true; } + if (CheckStrAS(App::diag_preset_terrain, k, v)) { return true; } + if (CheckStrAS(App::diag_preset_vehicle, k, v)) { return true; } + if (CheckStr(App::diag_preset_veh_config, k, v)) { return true; } + if (CheckBool(App::diag_preset_veh_enter, k, v)) { return true; } + if (CheckBool(App::diag_simple_materials, k, v)) { return true; } + if (CheckBool(App::diag_warning_texture, k, v)) { return true; } + if (CheckBool(App::diag_hide_broken_beams, k, v)) { return true; } + if (CheckBool(App::diag_hide_beam_stress, k, v)) { return true; } + if (CheckBool(App::diag_hide_wheel_info, k, v)) { return true; } + if (CheckBool(App::diag_hide_wheels, k, v)) { return true; } + if (CheckBool(App::diag_hide_nodes, k, v)) { return true; } + if (CheckFloat(App::diag_physics_dt, k, v)) { return true; } // Sim - if (CheckSimGearboxMode (k, v)) { return true; } - if (CheckBool (App::sim_spawn_running, k, v)) { return true; } - if (CheckBool (App::sim_replay_enabled, k, v)) { return true; } - if (CheckInt (App::sim_replay_length, k, v)) { return true; } - if (CheckInt (App::sim_replay_stepping, k, v)) { return true; } - if (CheckBool (App::sim_realistic_commands, k, v)) { return true; } - if (CheckBool (App::sim_races_enabled, k, v)) { return true; } - if (CheckBool (App::sim_no_collisions, k, v)) { return true; } - if (CheckBool (App::sim_no_self_collisions, k, v)) { return true; } + if (CheckSimGearboxMode(k, v)) { return true; } + if (CheckBool(App::sim_spawn_running, k, v)) { return true; } + if (CheckBool(App::sim_replay_enabled, k, v)) { return true; } + if (CheckInt(App::sim_replay_length, k, v)) { return true; } + if (CheckInt(App::sim_replay_stepping, k, v)) { return true; } + if (CheckBool(App::sim_realistic_commands, k, v)) { return true; } + if (CheckBool(App::sim_races_enabled, k, v)) { return true; } + if (CheckBool(App::sim_no_collisions, k, v)) { return true; } + if (CheckBool(App::sim_no_self_collisions, k, v)) { return true; } return false; } @@ -639,7 +773,7 @@ void Settings::LoadRoRCfg() // load all settings into a map! Ogre::ConfigFile::SettingsIterator i = cfg.getSettingsIterator(); - String s_value, s_name; + String s_value, s_name; while (i.hasMoreElements()) { s_name = RoR::Utils::SanitizeUtf8String(i.peekNextKey()); @@ -652,143 +786,143 @@ void Settings::LoadRoRCfg() this->ParseGlobalVarSetting(s_name, s_value); } } - catch (Ogre::FileNotFoundException&) {} // Just continue with defaults... + catch (Ogre::FileNotFoundException &) + { + } // Just continue with defaults... } // --------------------------- WRITING CONFIG FILE ------------------------------- // -inline const char* IoInputGrabToStr(IoInputGrabMode v) +inline const char *IoInputGrabToStr(IoInputGrabMode v) { switch (v) { case IoInputGrabMode::DYNAMIC: return CONF_INPUT_GRAB_DYNAMIC; - case IoInputGrabMode::NONE : return CONF_INPUT_GRAB_NONE; - case IoInputGrabMode::ALL : return CONF_INPUT_GRAB_ALL; - default : return ""; + case IoInputGrabMode::NONE: return CONF_INPUT_GRAB_NONE; + case IoInputGrabMode::ALL: return CONF_INPUT_GRAB_ALL; + default: return ""; } } -inline const char* GfxShadowTechToStr(GfxShadowType v) +inline const char *GfxShadowTechToStr(GfxShadowType v) { switch (v) { - case GfxShadowType::PSSM : return CONF_GFX_SHADOW_PSSM; - case GfxShadowType::NONE : return CONF_GFX_SHADOW_NONE; - default : return ""; + case GfxShadowType::PSSM: return CONF_GFX_SHADOW_PSSM; + case GfxShadowType::NONE: return CONF_GFX_SHADOW_NONE; + default: return ""; } } -inline const char* GfxExtcamModeToStr(GfxExtCamMode v) +inline const char *GfxExtcamModeToStr(GfxExtCamMode v) { switch (v) { case GfxExtCamMode::PITCHING: return CONF_EXTCAM_PITCHING; - case GfxExtCamMode::STATIC : return CONF_EXTCAM_STATIC; - case GfxExtCamMode::NONE : return CONF_EXTCAM_NONE; - default : return ""; + case GfxExtCamMode::STATIC: return CONF_EXTCAM_STATIC; + case GfxExtCamMode::NONE: return CONF_EXTCAM_NONE; + default: return ""; } } -inline const char* GfxTexFilterToStr(GfxTexFilter v) +inline const char *GfxTexFilterToStr(GfxTexFilter v) { switch (v) { - case GfxTexFilter::NONE : return CONF_TEXFILTER_NONE; - case GfxTexFilter::BILINEAR : return CONF_TEXFILTER_BILI; - case GfxTexFilter::TRILINEAR : return CONF_TEXFILTER_TRILI; + case GfxTexFilter::NONE: return CONF_TEXFILTER_NONE; + case GfxTexFilter::BILINEAR: return CONF_TEXFILTER_BILI; + case GfxTexFilter::TRILINEAR: return CONF_TEXFILTER_TRILI; case GfxTexFilter::ANISOTROPIC: return CONF_TEXFILTER_ANISO; - default : return ""; + default: return ""; } } -inline const char* GfxVegetationToStr(GfxVegetation v) +inline const char *GfxVegetationToStr(GfxVegetation v) { switch (v) { - case GfxVegetation::NONE : return CONF_VEGET_NONE; + case GfxVegetation::NONE: return CONF_VEGET_NONE; case GfxVegetation::x20PERC: return CONF_VEGET_20PERC; case GfxVegetation::x50PERC: return CONF_VEGET_50PERC; - case GfxVegetation::FULL : return CONF_VEGET_FULL; - default : return ""; + case GfxVegetation::FULL: return CONF_VEGET_FULL; + default: return ""; } } -inline const char* SimGearboxToStr(SimGearboxMode v) +inline const char *SimGearboxToStr(SimGearboxMode v) { switch (v) { - case SimGearboxMode::AUTO : return CONF_GEARBOX_AUTO; - case SimGearboxMode::SEMI_AUTO : return CONF_GEARBOX_SEMIAUTO; - case SimGearboxMode::MANUAL : return CONF_GEARBOX_MANUAL; - case SimGearboxMode::MANUAL_STICK : return CONF_GEARBOX_MAN_STICK; + case SimGearboxMode::AUTO: return CONF_GEARBOX_AUTO; + case SimGearboxMode::SEMI_AUTO: return CONF_GEARBOX_SEMIAUTO; + case SimGearboxMode::MANUAL: return CONF_GEARBOX_MANUAL; + case SimGearboxMode::MANUAL_STICK: return CONF_GEARBOX_MAN_STICK; case SimGearboxMode::MANUAL_RANGES: return CONF_GEARBOX_MAN_RANGES; - default : return ""; + default: return ""; } } -inline const char* GfxFlaresToStr(GfxFlaresMode v) +inline const char *GfxFlaresToStr(GfxFlaresMode v) { - switch(v) + switch (v) { - case GfxFlaresMode::NONE : return CONF_FLARES_NONE; - case GfxFlaresMode::NO_LIGHTSOURCES : return CONF_FLARES_NO_LIGHT; - case GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY : return CONF_FLARES_CURR_HEAD; - case GfxFlaresMode::ALL_VEHICLES_HEAD_ONLY : return CONF_FLARES_ALL_HEADS; + case GfxFlaresMode::NONE: return CONF_FLARES_NONE; + case GfxFlaresMode::NO_LIGHTSOURCES: return CONF_FLARES_NO_LIGHT; + case GfxFlaresMode::CURR_VEHICLE_HEAD_ONLY: return CONF_FLARES_CURR_HEAD; + case GfxFlaresMode::ALL_VEHICLES_HEAD_ONLY: return CONF_FLARES_ALL_HEADS; case GfxFlaresMode::ALL_VEHICLES_ALL_LIGHTS: return CONF_FLARES_ALL_LIGHTS; - default : return ""; + default: return ""; } } -inline const char* GfxWaterToStr(GfxWaterMode v) +inline const char *GfxWaterToStr(GfxWaterMode v) { - switch(v) + switch (v) { - case GfxWaterMode::BASIC : return CONF_WATER_BASIC; - case GfxWaterMode::REFLECT : return CONF_WATER_REFLECT; + case GfxWaterMode::BASIC: return CONF_WATER_BASIC; + case GfxWaterMode::REFLECT: return CONF_WATER_REFLECT; case GfxWaterMode::FULL_FAST: return CONF_WATER_FULL_FAST; - case GfxWaterMode::FULL_HQ : return CONF_WATER_FULL_HQ; - case GfxWaterMode::HYDRAX : return CONF_WATER_HYDRAX; - default : return ""; + case GfxWaterMode::FULL_HQ: return CONF_WATER_FULL_HQ; + case GfxWaterMode::HYDRAX: return CONF_WATER_HYDRAX; + default: return ""; } } -inline const char* GfxSkyToStr(GfxSkyMode v) +inline const char *GfxSkyToStr(GfxSkyMode v) { - switch(v) + switch (v) { - case GfxSkyMode::CAELUM : return CONF_SKY_CAELUM; - case GfxSkyMode::SKYX : return CONF_SKY_SKYX; + case GfxSkyMode::CAELUM: return CONF_SKY_CAELUM; + case GfxSkyMode::SKYX: return CONF_SKY_SKYX; case GfxSkyMode::SANDSTORM: return CONF_SKY_SANDSTORM; - default : return ""; + default: return ""; } } -template -inline void WriteStr(std::ofstream& f, GVarStr_T& gvar) +template inline void WriteStr(std::ofstream &f, GVarStr_T &gvar) { f << gvar.conf_name << "=" << gvar.GetStored() << std::endl; } -template -inline void WritePod(std::ofstream& f, GVarPod_T& gvar) +template inline void WritePod(std::ofstream &f, GVarPod_T &gvar) { f << gvar.conf_name << "=" << gvar.GetStored() << std::endl; } template -inline void WriteYN(std::ofstream& f, GVarPod_T& gvar) ///< Writes "Yes/No" - handles `bool` and `int(1/0)` +inline void WriteYN(std::ofstream &f, GVarPod_T &gvar) ///< Writes "Yes/No" - handles `bool` and `int(1/0)` { f << gvar.conf_name << "=" << (static_cast(gvar.GetStored()) == 0 ? "No" : "Yes") << std::endl; } -inline void WriteAny(std::ofstream& f, const char* name, const char* value) +inline void WriteAny(std::ofstream &f, const char *name, const char *value) { f << name << "=" << value << std::endl; } void Settings::SaveSettings() { - std::string rorcfg_path = PathCombine(App::sys_config_dir.GetActive(), "RoR.cfg"); + std::string rorcfg_path = PathCombine(App::sys_config_dir.GetActive(), "RoR.cfg"); std::ofstream f(rorcfg_path); if (!f.is_open()) { @@ -800,120 +934,120 @@ void Settings::SaveSettings() f << "; -------------------------------" << std::endl; f << std::endl << "; Multiplayer" << std::endl; - WriteYN (f, App::mp_join_on_startup); - WriteYN (f, App::mp_chat_auto_hide); - WriteYN (f, App::mp_hide_net_labels); - WriteYN (f, App::mp_hide_own_net_label); - WriteYN (f, App::mp_pseudo_collisions); - WriteStr (f, App::mp_player_name); - WriteStr (f, App::mp_server_host); - WritePod (f, App::mp_server_port); - WriteStr (f, App::mp_server_password); - WriteStr (f, App::mp_api_url); - WriteStr (f, App::mp_player_token); + WriteYN(f, App::mp_join_on_startup); + WriteYN(f, App::mp_chat_auto_hide); + WriteYN(f, App::mp_hide_net_labels); + WriteYN(f, App::mp_hide_own_net_label); + WriteYN(f, App::mp_pseudo_collisions); + WriteStr(f, App::mp_player_name); + WriteStr(f, App::mp_server_host); + WritePod(f, App::mp_server_port); + WriteStr(f, App::mp_server_password); + WriteStr(f, App::mp_api_url); + WriteStr(f, App::mp_player_token); f << std::endl << "; Simulation" << std::endl; - WriteAny (f, App::sim_gearbox_mode.conf_name, SimGearboxToStr(App::sim_gearbox_mode.GetActive())); - WriteYN (f, App::sim_spawn_running ); - WriteYN (f, App::sim_replay_enabled ); - WritePod (f, App::sim_replay_length ); - WritePod (f, App::sim_replay_stepping ); - WriteYN (f, App::sim_realistic_commands); - WriteYN (f, App::sim_races_enabled ); - WriteYN (f, App::sim_no_collisions ); - WriteYN (f, App::sim_no_self_collisions); + WriteAny(f, App::sim_gearbox_mode.conf_name, SimGearboxToStr(App::sim_gearbox_mode.GetActive())); + WriteYN(f, App::sim_spawn_running); + WriteYN(f, App::sim_replay_enabled); + WritePod(f, App::sim_replay_length); + WritePod(f, App::sim_replay_stepping); + WriteYN(f, App::sim_realistic_commands); + WriteYN(f, App::sim_races_enabled); + WriteYN(f, App::sim_no_collisions); + WriteYN(f, App::sim_no_self_collisions); f << std::endl << "; Input/Output" << std::endl; - WriteAny (f, App::io_input_grab_mode.conf_name, IoInputGrabToStr(App::io_input_grab_mode.GetActive())); - WritePod (f, App::io_analog_smoothing); - WritePod (f, App::io_analog_sensitivity); - WriteYN (f, App::io_ffb_enabled); - WritePod (f, App::io_ffb_camera_gain); - WritePod (f, App::io_ffb_center_gain); - WritePod (f, App::io_ffb_master_gain); - WritePod (f, App::io_ffb_stress_gain); - WriteYN (f, App::io_arcade_controls); - WritePod (f, App::io_outgauge_mode); - WriteStr (f, App::io_outgauge_ip); - WritePod (f, App::io_outgauge_port); - WritePod (f, App::io_outgauge_delay); - WritePod (f, App::io_outgauge_id); - WriteYN (f, App::io_discord_rpc); + WriteAny(f, App::io_input_grab_mode.conf_name, IoInputGrabToStr(App::io_input_grab_mode.GetActive())); + WritePod(f, App::io_analog_smoothing); + WritePod(f, App::io_analog_sensitivity); + WriteYN(f, App::io_ffb_enabled); + WritePod(f, App::io_ffb_camera_gain); + WritePod(f, App::io_ffb_center_gain); + WritePod(f, App::io_ffb_master_gain); + WritePod(f, App::io_ffb_stress_gain); + WriteYN(f, App::io_arcade_controls); + WritePod(f, App::io_outgauge_mode); + WriteStr(f, App::io_outgauge_ip); + WritePod(f, App::io_outgauge_port); + WritePod(f, App::io_outgauge_delay); + WritePod(f, App::io_outgauge_id); + WriteYN(f, App::io_discord_rpc); f << std::endl << "; Graphics" << std::endl; - WriteAny (f, App::gfx_shadow_type.conf_name , GfxShadowTechToStr(App::gfx_shadow_type.GetActive ())); - WriteAny (f, App::gfx_extcam_mode.conf_name , GfxExtcamModeToStr(App::gfx_extcam_mode.GetActive ())); - WriteAny (f, App::gfx_texture_filter.conf_name , GfxTexFilterToStr (App::gfx_texture_filter.GetActive ())); - WriteAny (f, App::gfx_vegetation_mode.conf_name, GfxVegetationToStr(App::gfx_vegetation_mode.GetActive ())); - WriteAny (f, App::gfx_flares_mode.conf_name , GfxFlaresToStr (App::gfx_flares_mode.GetActive ())); - WriteAny (f, App::gfx_water_mode.conf_name , GfxWaterToStr (App::gfx_water_mode.GetActive ())); - WriteAny (f, App::gfx_sky_mode.conf_name , GfxSkyToStr (App::gfx_sky_mode.GetActive ())); - WritePod (f, App::gfx_anisotropy ); - WriteYN (f, App::gfx_enable_videocams); - WriteYN (f, App::gfx_window_videocams); - WriteYN (f, App::gfx_surveymap_icons ); - WriteYN (f, App::gfx_declutter_map ); - WriteYN (f, App::gfx_water_waves ); - WriteYN (f, App::gfx_particles_mode ); - WriteYN (f, App::gfx_skidmarks_mode ); - WriteYN (f, App::gfx_speedo_digital ); - WriteYN (f, App::gfx_speedo_imperial ); - WriteYN (f, App::gfx_envmap_enabled ); - WritePod (f, App::gfx_envmap_rate ); - WritePod (f, App::gfx_shadow_quality ); - WritePod (f, App::gfx_sight_range ); - WritePod (f, App::gfx_camera_height ); - WritePod (f, App::gfx_fps_limit ); - WritePod (f, App::gfx_fov_external ); - WritePod (f, App::gfx_fov_internal ); - WriteYN (f, App::gfx_flexbody_lods ); - WriteYN (f, App::gfx_flexbody_cache ); - WriteYN (f, App::gfx_reduce_shadows ); - WriteYN (f, App::gfx_enable_rtshaders); + WriteAny(f, App::gfx_shadow_type.conf_name, GfxShadowTechToStr(App::gfx_shadow_type.GetActive())); + WriteAny(f, App::gfx_extcam_mode.conf_name, GfxExtcamModeToStr(App::gfx_extcam_mode.GetActive())); + WriteAny(f, App::gfx_texture_filter.conf_name, GfxTexFilterToStr(App::gfx_texture_filter.GetActive())); + WriteAny(f, App::gfx_vegetation_mode.conf_name, GfxVegetationToStr(App::gfx_vegetation_mode.GetActive())); + WriteAny(f, App::gfx_flares_mode.conf_name, GfxFlaresToStr(App::gfx_flares_mode.GetActive())); + WriteAny(f, App::gfx_water_mode.conf_name, GfxWaterToStr(App::gfx_water_mode.GetActive())); + WriteAny(f, App::gfx_sky_mode.conf_name, GfxSkyToStr(App::gfx_sky_mode.GetActive())); + WritePod(f, App::gfx_anisotropy); + WriteYN(f, App::gfx_enable_videocams); + WriteYN(f, App::gfx_window_videocams); + WriteYN(f, App::gfx_surveymap_icons); + WriteYN(f, App::gfx_declutter_map); + WriteYN(f, App::gfx_water_waves); + WriteYN(f, App::gfx_particles_mode); + WriteYN(f, App::gfx_skidmarks_mode); + WriteYN(f, App::gfx_speedo_digital); + WriteYN(f, App::gfx_speedo_imperial); + WriteYN(f, App::gfx_envmap_enabled); + WritePod(f, App::gfx_envmap_rate); + WritePod(f, App::gfx_shadow_quality); + WritePod(f, App::gfx_sight_range); + WritePod(f, App::gfx_camera_height); + WritePod(f, App::gfx_fps_limit); + WritePod(f, App::gfx_fov_external); + WritePod(f, App::gfx_fov_internal); + WriteYN(f, App::gfx_flexbody_lods); + WriteYN(f, App::gfx_flexbody_cache); + WriteYN(f, App::gfx_reduce_shadows); + WriteYN(f, App::gfx_enable_rtshaders); f << std::endl << "; Audio" << std::endl; - WritePod (f, App::audio_master_volume); - WriteYN (f, App::audio_enable_creak ); - WriteYN (f, App::audio_menu_music ); - WriteStr (f, App::audio_device_name ); + WritePod(f, App::audio_master_volume); + WriteYN(f, App::audio_enable_creak); + WriteYN(f, App::audio_menu_music); + WriteStr(f, App::audio_device_name); f << std::endl << "; Diagnostics" << std::endl; - WriteYN (f, App::diag_auto_spawner_report); - WriteYN (f, App::diag_camera ); - WriteYN (f, App::diag_rig_log_node_import); - WriteYN (f, App::diag_rig_log_node_stats ); - WriteYN (f, App::diag_rig_log_messages ); - WriteYN (f, App::diag_collisions ); - WriteYN (f, App::diag_truck_mass ); - WriteYN (f, App::diag_envmap ); - WriteYN (f, App::diag_log_console_echo ); - WriteYN (f, App::diag_log_beam_break ); - WriteYN (f, App::diag_log_beam_deform ); - WriteYN (f, App::diag_log_beam_trigger ); - WriteYN (f, App::diag_preset_veh_enter ); - WriteStr (f, App::diag_preset_terrain ); - WriteStr (f, App::diag_preset_vehicle ); - WriteStr (f, App::diag_preset_veh_config ); - WriteYN (f, App::diag_videocameras ); - WriteYN (f, App::diag_simple_materials ); - WriteYN (f, App::diag_warning_texture ); - WriteYN (f, App::diag_hide_broken_beams ); - WriteYN (f, App::diag_hide_beam_stress ); - WriteYN (f, App::diag_hide_wheel_info ); - WriteYN (f, App::diag_hide_wheels ); - WriteYN (f, App::diag_hide_nodes ); - WritePod (f, App::diag_physics_dt ); - - f << std::endl << "; Application"<< std::endl; - WriteStr (f, App::app_screenshot_format ); - WriteStr (f, App::app_language ); - WriteStr (f, App::app_country ); - WriteStr (f, App::app_rendersys_override); - WriteYN (f, App::app_skip_main_menu ); - WriteYN (f, App::app_async_physics ); - WritePod (f, App::app_num_workers ); - WriteStr (f, App::app_extra_mod_path ); - WriteYN (f, App::app_disable_online_api); + WriteYN(f, App::diag_auto_spawner_report); + WriteYN(f, App::diag_camera); + WriteYN(f, App::diag_rig_log_node_import); + WriteYN(f, App::diag_rig_log_node_stats); + WriteYN(f, App::diag_rig_log_messages); + WriteYN(f, App::diag_collisions); + WriteYN(f, App::diag_truck_mass); + WriteYN(f, App::diag_envmap); + WriteYN(f, App::diag_log_console_echo); + WriteYN(f, App::diag_log_beam_break); + WriteYN(f, App::diag_log_beam_deform); + WriteYN(f, App::diag_log_beam_trigger); + WriteYN(f, App::diag_preset_veh_enter); + WriteStr(f, App::diag_preset_terrain); + WriteStr(f, App::diag_preset_vehicle); + WriteStr(f, App::diag_preset_veh_config); + WriteYN(f, App::diag_videocameras); + WriteYN(f, App::diag_simple_materials); + WriteYN(f, App::diag_warning_texture); + WriteYN(f, App::diag_hide_broken_beams); + WriteYN(f, App::diag_hide_beam_stress); + WriteYN(f, App::diag_hide_wheel_info); + WriteYN(f, App::diag_hide_wheels); + WriteYN(f, App::diag_hide_nodes); + WritePod(f, App::diag_physics_dt); + + f << std::endl << "; Application" << std::endl; + WriteStr(f, App::app_screenshot_format); + WriteStr(f, App::app_language); + WriteStr(f, App::app_country); + WriteStr(f, App::app_rendersys_override); + WriteYN(f, App::app_skip_main_menu); + WriteYN(f, App::app_async_physics); + WritePod(f, App::app_num_workers); + WriteStr(f, App::app_extra_mod_path); + WriteYN(f, App::app_disable_online_api); f.close(); } @@ -923,9 +1057,9 @@ bool Settings::SetupAllPaths() using namespace RoR; // User directories - App::sys_config_dir .SetActive(PathCombine(App::sys_user_dir.GetActive(), "config").c_str()); - App::sys_cache_dir .SetActive(PathCombine(App::sys_user_dir.GetActive(), "cache").c_str()); - App::sys_savegames_dir .SetActive(PathCombine(App::sys_user_dir.GetActive(), "savegames").c_str()); + App::sys_config_dir.SetActive(PathCombine(App::sys_user_dir.GetActive(), "config").c_str()); + App::sys_cache_dir.SetActive(PathCombine(App::sys_user_dir.GetActive(), "cache").c_str()); + App::sys_savegames_dir.SetActive(PathCombine(App::sys_user_dir.GetActive(), "savegames").c_str()); App::sys_screenshot_dir.SetActive(PathCombine(App::sys_user_dir.GetActive(), "screenshots").c_str()); // Resources dir diff --git a/source/main/utils/Settings.h b/source/main/utils/Settings.h index 036d0dc9f9..88213218a1 100644 --- a/source/main/utils/Settings.h +++ b/source/main/utils/Settings.h @@ -19,7 +19,6 @@ along with Rigs of Rods. If not, see . */ - /// @file /// @date 4th of January 2009 /// @author Thomas Fischer @@ -29,98 +28,95 @@ /// Entries without corresponding GVar can be read /// by ad-hoc by macros like SSETTING(), BSETTING() etc... - #pragma once #include "RoRPrerequisites.h" - #include "Singleton.h" -namespace RoR { +namespace RoR +{ -void ShowCommandLineUsage(); -void ShowVersion(); + void ShowCommandLineUsage(); + void ShowVersion(); } // namespace RoR // --------------------- // Config value strings -extern const char* CONF_GFX_SHADOW_PSSM; -extern const char* CONF_GFX_SHADOW_NONE; +extern const char *CONF_GFX_SHADOW_PSSM; +extern const char *CONF_GFX_SHADOW_NONE; -extern const char* CONF_EXTCAM_PITCHING; -extern const char* CONF_EXTCAM_STATIC; -extern const char* CONF_EXTCAM_NONE; +extern const char *CONF_EXTCAM_PITCHING; +extern const char *CONF_EXTCAM_STATIC; +extern const char *CONF_EXTCAM_NONE; -extern const char* CONF_TEXFILTER_BILI; -extern const char* CONF_TEXFILTER_TRILI; -extern const char* CONF_TEXFILTER_ANISO; +extern const char *CONF_TEXFILTER_BILI; +extern const char *CONF_TEXFILTER_TRILI; +extern const char *CONF_TEXFILTER_ANISO; -extern const char* CONF_VEGET_NONE; -extern const char* CONF_VEGET_20PERC; -extern const char* CONF_VEGET_50PERC; -extern const char* CONF_VEGET_FULL; +extern const char *CONF_VEGET_NONE; +extern const char *CONF_VEGET_20PERC; +extern const char *CONF_VEGET_50PERC; +extern const char *CONF_VEGET_FULL; -extern const char* CONF_GEARBOX_AUTO; -extern const char* CONF_GEARBOX_SEMIAUTO; -extern const char* CONF_GEARBOX_MANUAL; -extern const char* CONF_GEARBOX_MAN_STICK; -extern const char* CONF_GEARBOX_MAN_RANGES; +extern const char *CONF_GEARBOX_AUTO; +extern const char *CONF_GEARBOX_SEMIAUTO; +extern const char *CONF_GEARBOX_MANUAL; +extern const char *CONF_GEARBOX_MAN_STICK; +extern const char *CONF_GEARBOX_MAN_RANGES; -extern const char* CONF_FLARES_NONE; -extern const char* CONF_FLARES_NO_LIGHT; -extern const char* CONF_FLARES_CURR_HEAD; -extern const char* CONF_FLARES_ALL_HEADS; -extern const char* CONF_FLARES_ALL_LIGHTS; +extern const char *CONF_FLARES_NONE; +extern const char *CONF_FLARES_NO_LIGHT; +extern const char *CONF_FLARES_CURR_HEAD; +extern const char *CONF_FLARES_ALL_HEADS; +extern const char *CONF_FLARES_ALL_LIGHTS; -extern const char* CONF_WATER_BASIC; -extern const char* CONF_WATER_REFLECT; -extern const char* CONF_WATER_FULL_FAST; -extern const char* CONF_WATER_FULL_HQ; -extern const char* CONF_WATER_HYDRAX; +extern const char *CONF_WATER_BASIC; +extern const char *CONF_WATER_REFLECT; +extern const char *CONF_WATER_FULL_FAST; +extern const char *CONF_WATER_FULL_HQ; +extern const char *CONF_WATER_HYDRAX; -extern const char* CONF_SKY_CAELUM; -extern const char* CONF_SKY_SKYX; -extern const char* CONF_SKY_SANDSTORM; +extern const char *CONF_SKY_CAELUM; +extern const char *CONF_SKY_SKYX; +extern const char *CONF_SKY_SANDSTORM; -extern const char* CONF_INPUT_GRAB_DYNAMIC; -extern const char* CONF_INPUT_GRAB_NONE; -extern const char* CONF_INPUT_GRAB_ALL; +extern const char *CONF_INPUT_GRAB_DYNAMIC; +extern const char *CONF_INPUT_GRAB_NONE; +extern const char *CONF_INPUT_GRAB_ALL; // --------------------- // Config string -> GVar -void App__SetIoInputGrabMode(std::string const& s); -void App__SetShadowTech(std::string const& s); -void App__SetExtcamMode(std::string const& s); -void App__SetTexFiltering(std::string const& s); -void App__SetVegetationMode(std::string const& s); -void App__SetSimGearboxMode(std::string const& s); -void App__SetGfxFlaresMode(std::string const& s); -void App__SetGfxWaterMode(std::string const& s); -void App__SetGfxSkyMode(std::string const& s); +void App__SetIoInputGrabMode(std::string const &s); +void App__SetShadowTech(std::string const &s); +void App__SetExtcamMode(std::string const &s); +void App__SetTexFiltering(std::string const &s); +void App__SetVegetationMode(std::string const &s); +void App__SetSimGearboxMode(std::string const &s); +void App__SetGfxFlaresMode(std::string const &s); +void App__SetGfxWaterMode(std::string const &s); +void App__SetGfxSkyMode(std::string const &s); class Settings : public RoRSingleton, public ZeroedMemoryAllocator { friend class RoRSingleton; -public: - + public: void LoadRoRCfg(); // Reads GVars void SaveSettings(); // Writes GVars /// Process command line arguments into settings. - void ProcessCommandLine(int argc, char* argv[]); + void ProcessCommandLine(int argc, char *argv[]); /// Process and erase settings which propagate to global vars. /// @return True if the value was processed, false if it remains in settings. - bool ParseGlobalVarSetting(std::string const& name, std::string const& value); + bool ParseGlobalVarSetting(std::string const &name, std::string const &value); static bool SetupAllPaths(); -protected: - - static Settings* myInstance; + protected: + static Settings *myInstance; }; diff --git a/source/main/utils/SimpleGlob.h b/source/main/utils/SimpleGlob.h index c83c985af0..16244daf1f 100644 --- a/source/main/utils/SimpleGlob.h +++ b/source/main/utils/SimpleGlob.h @@ -3,22 +3,22 @@ @version 3.6 @brief A cross-platform file globbing library providing the ability to - expand wildcards in command-line arguments to a list of all matching - files. It is designed explicitly to be portable to any platform and has - been tested on Windows and Linux. See CSimpleGlobTempl for the class + expand wildcards in command-line arguments to a list of all matching + files. It is designed explicitly to be portable to any platform and has + been tested on Windows and Linux. See CSimpleGlobTempl for the class definition. @section features FEATURES - - MIT Licence allows free use in all software (including GPL and + - MIT Licence allows free use in all software (including GPL and commercial) - multi-platform (Windows 95/98/ME/NT/2K/XP, Linux, Unix) - supports most of the standard linux glob() options - - recognition of a forward paths as equivalent to a backward slash + - recognition of a forward paths as equivalent to a backward slash on Windows. e.g. "c:/path/foo*" is equivalent to "c:\path\foo*". - implemented with only a single C++ header file - char, wchar_t and Windows TCHAR in the same program - complete working examples included - - compiles cleanly at warning level 4 (Windows/VC.NET 2003), + - compiles cleanly at warning level 4 (Windows/VC.NET 2003), warning level 3 (Windows/VC6) and -Wall (Linux/gcc) @section usage USAGE @@ -70,12 +70,12 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ @@ -83,7 +83,7 @@ #ifndef INCLUDED_SimpleGlob #define INCLUDED_SimpleGlob -/*! @brief The operation of SimpleGlob is fine-tuned via the use of a +/*! @brief The operation of SimpleGlob is fine-tuned via the use of a combination of the following flags. The flags may be passed at initialization of the class and used for every @@ -99,15 +99,15 @@ @param SG_GLOB_NOSORT By default, files are returned in sorted into string order. With this - flag, no sorting is done. This is not compatible with + flag, no sorting is done. This is not compatible with SG_GLOB_FULLSORT. @param SG_GLOB_FULLSORT By default, files are sorted in groups belonging to each filespec that - was added. For example if the filespec "b*" was added before the - filespec "a*" then the argv array will contain all b* files sorted in - order, followed by all a* files sorted in order. If this flag is - specified, the entire array will be sorted ignoring the filespec + was added. For example if the filespec "b*" was added before the + filespec "a*" then the argv array will contain all b* files sorted in + order, followed by all a* files sorted in order. If this flag is + specified, the entire array will be sorted ignoring the filespec groups. @param SG_GLOB_NOCHECK @@ -117,7 +117,7 @@ Tilde expansion is carried out (on Unix platforms) @param SG_GLOB_ONLYDIR - Return only directories which match (not compatible with + Return only directories which match (not compatible with SG_GLOB_ONLYFILE) @param SG_GLOB_ONLYFILE @@ -126,24 +126,26 @@ @param SG_GLOB_NODOT Do not return the "." or ".." special directories. */ -enum SG_Flags { - SG_GLOB_ERR = 1 << 0, - SG_GLOB_MARK = 1 << 1, - SG_GLOB_NOSORT = 1 << 2, - SG_GLOB_NOCHECK = 1 << 3, - SG_GLOB_TILDE = 1 << 4, - SG_GLOB_ONLYDIR = 1 << 5, - SG_GLOB_ONLYFILE = 1 << 6, - SG_GLOB_NODOT = 1 << 7, - SG_GLOB_FULLSORT = 1 << 8 +enum SG_Flags +{ + SG_GLOB_ERR = 1 << 0, + SG_GLOB_MARK = 1 << 1, + SG_GLOB_NOSORT = 1 << 2, + SG_GLOB_NOCHECK = 1 << 3, + SG_GLOB_TILDE = 1 << 4, + SG_GLOB_ONLYDIR = 1 << 5, + SG_GLOB_ONLYFILE = 1 << 6, + SG_GLOB_NODOT = 1 << 7, + SG_GLOB_FULLSORT = 1 << 8 }; /*! @brief Error return codes */ -enum SG_Error { - SG_SUCCESS = 0, - SG_ERR_NOMATCH = 1, - SG_ERR_MEMORY = -1, - SG_ERR_FAILURE = -2 +enum SG_Error +{ + SG_SUCCESS = 0, + SG_ERR_NOMATCH = 1, + SG_ERR_MEMORY = -1, + SG_ERR_FAILURE = -2 }; // --------------------------------------------------------------------------- @@ -152,263 +154,293 @@ enum SG_Error { // if we aren't on Windows and we have ICU available, then enable ICU // by default. Define this to 0 to intentially disable it. #ifndef SG_HAVE_ICU -# if !defined(_WIN32) && defined(USTRING_H) -# define SG_HAVE_ICU 1 -# else -# define SG_HAVE_ICU 0 -# endif + #if !defined(_WIN32) && defined(USTRING_H) + #define SG_HAVE_ICU 1 + #else + #define SG_HAVE_ICU 0 + #endif #endif // don't include this in documentation as it isn't relevant #ifndef DOXYGEN -// on Windows we want to use MBCS aware string functions and mimic the -// Unix glob functionality. On Unix we just use glob. -#ifdef _WIN32 -# include -# define sg_strchr ::_mbschr -# define sg_strrchr ::_mbsrchr -# define sg_strlen ::_mbslen -# if __STDC_WANT_SECURE_LIB__ -# define sg_strcpy_s(a,n,b) ::_mbscpy_s(a,n,b) -# else -# define sg_strcpy_s(a,n,b) ::_mbscpy(a,b) -# endif -# define sg_strcmp ::_mbscmp -# define sg_strcasecmp ::_mbsicmp -# define SOCHAR_T unsigned char -#else -# include -# include -# include -# include -# define MAX_PATH PATH_MAX -# define sg_strchr ::strchr -# define sg_strrchr ::strrchr -# define sg_strlen ::strlen -# define sg_strcpy_s(a,n,b) ::strcpy(a,b) -# define sg_strcmp ::strcmp -# define sg_strcasecmp ::strcasecmp -# define SOCHAR_T char -#endif - -#include -#include -#include - -// use assertions to test the input data -#ifdef _DEBUG -# ifdef _MSC_VER -# include -# define SG_ASSERT(b) _ASSERTE(b) -# else -# include -# define SG_ASSERT(b) assert(b) -# endif -#else -# define SG_ASSERT(b) -#endif + // on Windows we want to use MBCS aware string functions and mimic the + // Unix glob functionality. On Unix we just use glob. + #ifdef _WIN32 + #include + #define sg_strchr ::_mbschr + #define sg_strrchr ::_mbsrchr + #define sg_strlen ::_mbslen + #if __STDC_WANT_SECURE_LIB__ + #define sg_strcpy_s(a, n, b) ::_mbscpy_s(a, n, b) + #else + #define sg_strcpy_s(a, n, b) ::_mbscpy(a, b) + #endif + #define sg_strcmp ::_mbscmp + #define sg_strcasecmp ::_mbsicmp + #define SOCHAR_T unsigned char + #else + #include + #include + #include + #include + #define MAX_PATH PATH_MAX + #define sg_strchr ::strchr + #define sg_strrchr ::strrchr + #define sg_strlen ::strlen + #define sg_strcpy_s(a, n, b) ::strcpy(a, b) + #define sg_strcmp ::strcmp + #define sg_strcasecmp ::strcasecmp + #define SOCHAR_T char + #endif + + #include + #include + #include + + // use assertions to test the input data + #ifdef _DEBUG + #ifdef _MSC_VER + #include + #define SG_ASSERT(b) _ASSERTE(b) + #else + #include + #define SG_ASSERT(b) assert(b) + #endif + #else + #define SG_ASSERT(b) + #endif /*! @brief String manipulation functions. */ class SimpleGlobUtil { -public: - static const char * strchr(const char *s, char c) { - return (char *) sg_strchr((const SOCHAR_T *)s, c); + public: + static const char *strchr(const char *s, char c) + { + return (char *)sg_strchr((const SOCHAR_T *)s, c); } - static const wchar_t * strchr(const wchar_t *s, wchar_t c) { + static const wchar_t *strchr(const wchar_t *s, wchar_t c) + { return ::wcschr(s, c); } -#if SG_HAVE_ICU - static const UChar * strchr(const UChar *s, UChar c) { + #if SG_HAVE_ICU + static const UChar *strchr(const UChar *s, UChar c) + { return ::u_strchr(s, c); } -#endif + #endif - static const char * strrchr(const char *s, char c) { - return (char *) sg_strrchr((const SOCHAR_T *)s, c); + static const char *strrchr(const char *s, char c) + { + return (char *)sg_strrchr((const SOCHAR_T *)s, c); } - static const wchar_t * strrchr(const wchar_t *s, wchar_t c) { + static const wchar_t *strrchr(const wchar_t *s, wchar_t c) + { return ::wcsrchr(s, c); } -#if SG_HAVE_ICU - static const UChar * strrchr(const UChar *s, UChar c) { + #if SG_HAVE_ICU + static const UChar *strrchr(const UChar *s, UChar c) + { return ::u_strrchr(s, c); } -#endif + #endif // Note: char strlen returns number of bytes, not characters - static size_t strlen(const char *s) { return ::strlen(s); } - static size_t strlen(const wchar_t *s) { return ::wcslen(s); } -#if SG_HAVE_ICU - static size_t strlen(const UChar *s) { return ::u_strlen(s); } -#endif + static size_t strlen(const char *s) + { + return ::strlen(s); + } + static size_t strlen(const wchar_t *s) + { + return ::wcslen(s); + } + #if SG_HAVE_ICU + static size_t strlen(const UChar *s) + { + return ::u_strlen(s); + } + #endif - static void strcpy_s(char *dst, size_t n, const char *src) { - (void) n; + static void strcpy_s(char *dst, size_t n, const char *src) + { + (void)n; sg_strcpy_s((SOCHAR_T *)dst, n, (const SOCHAR_T *)src); } - static void strcpy_s(wchar_t *dst, size_t n, const wchar_t *src) { -# if __STDC_WANT_SECURE_LIB__ + static void strcpy_s(wchar_t *dst, size_t n, const wchar_t *src) + { + #if __STDC_WANT_SECURE_LIB__ ::wcscpy_s(dst, n, src); -#else - (void) n; + #else + (void)n; ::wcscpy(dst, src); -#endif + #endif } -#if SG_HAVE_ICU - static void strcpy_s(UChar *dst, size_t n, const UChar *src) { + #if SG_HAVE_ICU + static void strcpy_s(UChar *dst, size_t n, const UChar *src) + { ::u_strncpy(dst, src, n); } -#endif + #endif - static int strcmp(const char *s1, const char *s2) { + static int strcmp(const char *s1, const char *s2) + { return sg_strcmp((const SOCHAR_T *)s1, (const SOCHAR_T *)s2); } - static int strcmp(const wchar_t *s1, const wchar_t *s2) { + static int strcmp(const wchar_t *s1, const wchar_t *s2) + { return ::wcscmp(s1, s2); } -#if SG_HAVE_ICU - static int strcmp(const UChar *s1, const UChar *s2) { + #if SG_HAVE_ICU + static int strcmp(const UChar *s1, const UChar *s2) + { return ::u_strcmp(s1, s2); } -#endif + #endif - static int strcasecmp(const char *s1, const char *s2) { + static int strcasecmp(const char *s1, const char *s2) + { return sg_strcasecmp((const SOCHAR_T *)s1, (const SOCHAR_T *)s2); } -#if _WIN32 - static int strcasecmp(const wchar_t *s1, const wchar_t *s2) { + #if _WIN32 + static int strcasecmp(const wchar_t *s1, const wchar_t *s2) + { return ::_wcsicmp(s1, s2); } -#endif // _WIN32 -#if SG_HAVE_ICU - static int strcasecmp(const UChar *s1, const UChar *s2) { + #endif // _WIN32 + #if SG_HAVE_ICU + static int strcasecmp(const UChar *s1, const UChar *s2) + { return u_strcasecmp(s1, s2, 0); } -#endif + #endif }; -enum SG_FileType { +enum SG_FileType +{ SG_FILETYPE_INVALID, SG_FILETYPE_FILE, SG_FILETYPE_DIR }; -#ifdef _WIN32 + #ifdef _WIN32 -#ifndef INVALID_FILE_ATTRIBUTES -# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) -#endif + #ifndef INVALID_FILE_ATTRIBUTES + #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) + #endif -#define SG_PATH_CHAR '\\' + #define SG_PATH_CHAR '\\' /*! @brief Windows glob implementation. */ -template -struct SimpleGlobBase +template struct SimpleGlobBase { - SimpleGlobBase() : m_hFind(INVALID_HANDLE_VALUE) { } + SimpleGlobBase() : m_hFind(INVALID_HANDLE_VALUE) + { + } - int FindFirstFileS(const char * a_pszFileSpec, unsigned int) { + int FindFirstFileS(const char *a_pszFileSpec, unsigned int) + { m_hFind = FindFirstFileA(a_pszFileSpec, &m_oFindDataA); - if (m_hFind != INVALID_HANDLE_VALUE) { - return SG_SUCCESS; - } + if (m_hFind != INVALID_HANDLE_VALUE) { return SG_SUCCESS; } DWORD dwErr = GetLastError(); - if (dwErr == ERROR_FILE_NOT_FOUND) { - return SG_ERR_NOMATCH; - } + if (dwErr == ERROR_FILE_NOT_FOUND) { return SG_ERR_NOMATCH; } return SG_ERR_FAILURE; } - int FindFirstFileS(const wchar_t * a_pszFileSpec, unsigned int) { + int FindFirstFileS(const wchar_t *a_pszFileSpec, unsigned int) + { m_hFind = FindFirstFileW(a_pszFileSpec, &m_oFindDataW); - if (m_hFind != INVALID_HANDLE_VALUE) { - return SG_SUCCESS; - } + if (m_hFind != INVALID_HANDLE_VALUE) { return SG_SUCCESS; } DWORD dwErr = GetLastError(); - if (dwErr == ERROR_FILE_NOT_FOUND) { - return SG_ERR_NOMATCH; - } + if (dwErr == ERROR_FILE_NOT_FOUND) { return SG_ERR_NOMATCH; } return SG_ERR_FAILURE; } - bool FindNextFileS(char) { + bool FindNextFileS(char) + { return FindNextFileA(m_hFind, &m_oFindDataA) != FALSE; } - bool FindNextFileS(wchar_t) { + bool FindNextFileS(wchar_t) + { return FindNextFileW(m_hFind, &m_oFindDataW) != FALSE; } - void FindDone() { + void FindDone() + { FindClose(m_hFind); } - const char * GetFileNameS(char) const { + const char *GetFileNameS(char) const + { return m_oFindDataA.cFileName; } - const wchar_t * GetFileNameS(wchar_t) const { + const wchar_t *GetFileNameS(wchar_t) const + { return m_oFindDataW.cFileName; } - bool IsDirS(char) const { + bool IsDirS(char) const + { return this->GetFileTypeS(m_oFindDataA.dwFileAttributes) == SG_FILETYPE_DIR; } - bool IsDirS(wchar_t) const { + bool IsDirS(wchar_t) const + { return this->GetFileTypeS(m_oFindDataW.dwFileAttributes) == SG_FILETYPE_DIR; } - SG_FileType GetFileTypeS(const char * a_pszPath) { + SG_FileType GetFileTypeS(const char *a_pszPath) + { return this->GetFileTypeS(GetFileAttributesA(a_pszPath)); } - SG_FileType GetFileTypeS(const wchar_t * a_pszPath) { + SG_FileType GetFileTypeS(const wchar_t *a_pszPath) + { return this->GetFileTypeS(GetFileAttributesW(a_pszPath)); } - SG_FileType GetFileTypeS(DWORD a_dwAttribs) const { - if (a_dwAttribs == INVALID_FILE_ATTRIBUTES) { - return SG_FILETYPE_INVALID; - } - if (a_dwAttribs & FILE_ATTRIBUTE_DIRECTORY) { - return SG_FILETYPE_DIR; - } + SG_FileType GetFileTypeS(DWORD a_dwAttribs) const + { + if (a_dwAttribs == INVALID_FILE_ATTRIBUTES) { return SG_FILETYPE_INVALID; } + if (a_dwAttribs & FILE_ATTRIBUTE_DIRECTORY) { return SG_FILETYPE_DIR; } return SG_FILETYPE_FILE; } -private: - HANDLE m_hFind; - WIN32_FIND_DATAA m_oFindDataA; - WIN32_FIND_DATAW m_oFindDataW; + private: + HANDLE m_hFind; + WIN32_FIND_DATAA m_oFindDataA; + WIN32_FIND_DATAW m_oFindDataW; }; -#else // !_WIN32 + #else // !_WIN32 -#define SG_PATH_CHAR '/' + #define SG_PATH_CHAR '/' /*! @brief Unix glob implementation. */ -template -struct SimpleGlobBase +template struct SimpleGlobBase { - SimpleGlobBase() { + SimpleGlobBase() + { memset(&m_glob, 0, sizeof(m_glob)); m_uiCurr = (size_t)-1; } - ~SimpleGlobBase() { + ~SimpleGlobBase() + { globfree(&m_glob); } - void FilePrep() { + void FilePrep() + { m_bIsDir = false; size_t len = strlen(m_glob.gl_pathv[m_uiCurr]); - if (m_glob.gl_pathv[m_uiCurr][len-1] == '/') { + if (m_glob.gl_pathv[m_uiCurr][len - 1] == '/') + { m_bIsDir = true; - m_glob.gl_pathv[m_uiCurr][len-1] = 0; + m_glob.gl_pathv[m_uiCurr][len - 1] = 0; } } - int FindFirstFileS(const char * a_pszFileSpec, unsigned int a_uiFlags) { + int FindFirstFileS(const char *a_pszFileSpec, unsigned int a_uiFlags) + { int nFlags = GLOB_MARK | GLOB_NOSORT; - if (a_uiFlags & SG_GLOB_ERR) nFlags |= GLOB_ERR; - if (a_uiFlags & SG_GLOB_TILDE) nFlags |= GLOB_TILDE; + if (a_uiFlags & SG_GLOB_ERR) nFlags |= GLOB_ERR; + if (a_uiFlags & SG_GLOB_TILDE) nFlags |= GLOB_TILDE; int rc = glob(a_pszFileSpec, nFlags, NULL, &m_glob); if (rc == GLOB_NOSPACE) return SG_ERR_MEMORY; if (rc == GLOB_ABORTED) return SG_ERR_FAILURE; @@ -418,45 +450,49 @@ struct SimpleGlobBase return SG_SUCCESS; } -#if SG_HAVE_ICU - int FindFirstFileS(const UChar * a_pszFileSpec, unsigned int a_uiFlags) { - char buf[PATH_MAX] = { 0 }; + #if SG_HAVE_ICU + int FindFirstFileS(const UChar *a_pszFileSpec, unsigned int a_uiFlags) + { + char buf[PATH_MAX] = {0}; UErrorCode status = U_ZERO_ERROR; u_strToUTF8(buf, sizeof(buf), NULL, a_pszFileSpec, -1, &status); if (U_FAILURE(status)) return SG_ERR_FAILURE; return this->FindFirstFileS(buf, a_uiFlags); } -#endif + #endif - bool FindNextFileS(char) { + bool FindNextFileS(char) + { SG_ASSERT(m_uiCurr != (size_t)-1); - if (++m_uiCurr >= m_glob.gl_pathc) { - return false; - } + if (++m_uiCurr >= m_glob.gl_pathc) { return false; } FilePrep(); return true; } -#if SG_HAVE_ICU - bool FindNextFileS(UChar) { + #if SG_HAVE_ICU + bool FindNextFileS(UChar) + { return this->FindNextFileS((char)0); } -#endif + #endif - void FindDone() { + void FindDone() + { globfree(&m_glob); memset(&m_glob, 0, sizeof(m_glob)); m_uiCurr = (size_t)-1; } - const char * GetFileNameS(char) const { + const char *GetFileNameS(char) const + { SG_ASSERT(m_uiCurr != (size_t)-1); return m_glob.gl_pathv[m_uiCurr]; } -#if SG_HAVE_ICU - const UChar * GetFileNameS(UChar) const { - const char * pszFile = this->GetFileNameS((char)0); + #if SG_HAVE_ICU + const UChar *GetFileNameS(UChar) const + { + const char *pszFile = this->GetFileNameS((char)0); if (!pszFile) return NULL; UErrorCode status = U_ZERO_ERROR; memset(m_szBuf, 0, sizeof(m_szBuf)); @@ -464,53 +500,51 @@ struct SimpleGlobBase if (U_FAILURE(status)) return NULL; return m_szBuf; } -#endif + #endif - bool IsDirS(char) const { + bool IsDirS(char) const + { SG_ASSERT(m_uiCurr != (size_t)-1); return m_bIsDir; } -#if SG_HAVE_ICU - bool IsDirS(UChar) const { + #if SG_HAVE_ICU + bool IsDirS(UChar) const + { return this->IsDirS((char)0); } -#endif + #endif - SG_FileType GetFileTypeS(const char * a_pszPath) const { + SG_FileType GetFileTypeS(const char *a_pszPath) const + { struct stat sb; - if (0 != stat(a_pszPath, &sb)) { - return SG_FILETYPE_INVALID; - } - if (S_ISDIR(sb.st_mode)) { - return SG_FILETYPE_DIR; - } - if (S_ISREG(sb.st_mode)) { - return SG_FILETYPE_FILE; - } + if (0 != stat(a_pszPath, &sb)) { return SG_FILETYPE_INVALID; } + if (S_ISDIR(sb.st_mode)) { return SG_FILETYPE_DIR; } + if (S_ISREG(sb.st_mode)) { return SG_FILETYPE_FILE; } return SG_FILETYPE_INVALID; } -#if SG_HAVE_ICU - SG_FileType GetFileTypeS(const UChar * a_pszPath) const { - char buf[PATH_MAX] = { 0 }; + #if SG_HAVE_ICU + SG_FileType GetFileTypeS(const UChar *a_pszPath) const + { + char buf[PATH_MAX] = {0}; UErrorCode status = U_ZERO_ERROR; u_strToUTF8(buf, sizeof(buf), NULL, a_pszPath, -1, &status); if (U_FAILURE(status)) return SG_FILETYPE_INVALID; return this->GetFileTypeS(buf); } -#endif + #endif -private: - glob_t m_glob; - size_t m_uiCurr; - bool m_bIsDir; -#if SG_HAVE_ICU + private: + glob_t m_glob; + size_t m_uiCurr; + bool m_bIsDir; + #if SG_HAVE_ICU mutable UChar m_szBuf[PATH_MAX]; -#endif + #endif }; -#endif // _WIN32 + #endif // _WIN32 #endif // DOXYGEN @@ -519,10 +553,9 @@ struct SimpleGlobBase // --------------------------------------------------------------------------- /*! @brief Implementation of the SimpleGlob class */ -template -class CSimpleGlobTempl : private SimpleGlobBase +template class CSimpleGlobTempl : private SimpleGlobBase { -public: + public: /*! @brief Initialize the class. @param a_uiFlags Combination of SG_GLOB flags. @@ -558,7 +591,7 @@ class CSimpleGlobTempl : private SimpleGlobBase @param a_pszFileSpec Filespec to add to the glob. @return SG_SUCCESS Matching files were added to the glob. - @return SG_ERR_NOMATCH Nothing matched the pattern. To ignore this + @return SG_ERR_NOMATCH Nothing matched the pattern. To ignore this error compare return value to >= SG_SUCCESS. @return SG_ERR_MEMORY Out of memory failure. @return SG_ERR_FAILURE General failure. @@ -574,39 +607,48 @@ class CSimpleGlobTempl : private SimpleGlobBase @param a_rgpszFileSpec Array of filespec to add to the glob. @return SG_SUCCESS Matching files were added to the glob. - @return SG_ERR_NOMATCH Nothing matched the pattern. To ignore this + @return SG_ERR_NOMATCH Nothing matched the pattern. To ignore this error compare return value to >= SG_SUCCESS. @return SG_ERR_MEMORY Out of memory failure. @return SG_ERR_FAILURE General failure. */ - int Add(int a_nCount, const SOCHAR * const * a_rgpszFileSpec); + int Add(int a_nCount, const SOCHAR *const *a_rgpszFileSpec); /*! @brief Return the number of files in the argv array. */ - inline int FileCount() const { return m_nArgsLen; } + inline int FileCount() const + { + return m_nArgsLen; + } /*! @brief Return the full argv array. */ - inline SOCHAR ** Files() { + inline SOCHAR **Files() + { SetArgvArrayType(POINTERS); return m_rgpArgs; } /*! @brief Return the a single file. */ - inline SOCHAR * File(int n) { + inline SOCHAR *File(int n) + { SG_ASSERT(n >= 0 && n < m_nArgsLen); return Files()[n]; } -private: - CSimpleGlobTempl(const CSimpleGlobTempl &); // disabled - CSimpleGlobTempl & operator=(const CSimpleGlobTempl &); // disabled + private: + CSimpleGlobTempl(const CSimpleGlobTempl &); // disabled + CSimpleGlobTempl &operator=(const CSimpleGlobTempl &); // disabled /*! @brief The argv array has it's members stored as either an offset into - the string buffer, or as pointers to their string in the buffer. The - offsets are used because if the string buffer is dynamically resized, + the string buffer, or as pointers to their string in the buffer. The + offsets are used because if the string buffer is dynamically resized, all pointers into that buffer would become invalid. */ - enum ARG_ARRAY_TYPE { OFFSETS, POINTERS }; + enum ARG_ARRAY_TYPE + { + OFFSETS, + POINTERS + }; /*! @brief Change the type of data stored in the argv array. */ void SetArgvArrayType(ARG_ARRAY_TYPE a_nNewType); @@ -623,62 +665,52 @@ class CSimpleGlobTempl : private SimpleGlobBase /*! @brief Compare two (possible NULL) strings */ static int fileSortCompare(const void *a1, const void *a2); -private: - unsigned int m_uiFlags; - ARG_ARRAY_TYPE m_nArgArrayType; //!< argv is indexes or pointers - SOCHAR ** m_rgpArgs; //!< argv - int m_nReservedSlots; //!< # client slots in argv array - int m_nArgsSize; //!< allocated size of array - int m_nArgsLen; //!< used length - SOCHAR * m_pBuffer; //!< argv string buffer - size_t m_uiBufferSize; //!< allocated size of buffer - size_t m_uiBufferLen; //!< used length of buffer - SOCHAR m_szPathPrefix[MAX_PATH]; //!< wildcard path prefix + private: + unsigned int m_uiFlags; + ARG_ARRAY_TYPE m_nArgArrayType; //!< argv is indexes or pointers + SOCHAR ** m_rgpArgs; //!< argv + int m_nReservedSlots; //!< # client slots in argv array + int m_nArgsSize; //!< allocated size of array + int m_nArgsLen; //!< used length + SOCHAR * m_pBuffer; //!< argv string buffer + size_t m_uiBufferSize; //!< allocated size of buffer + size_t m_uiBufferLen; //!< used length of buffer + SOCHAR m_szPathPrefix[MAX_PATH]; //!< wildcard path prefix }; // --------------------------------------------------------------------------- // IMPLEMENTATION // --------------------------------------------------------------------------- -template -CSimpleGlobTempl::CSimpleGlobTempl( - unsigned int a_uiFlags, - int a_nReservedSlots - ) +template CSimpleGlobTempl::CSimpleGlobTempl(unsigned int a_uiFlags, int a_nReservedSlots) { - m_rgpArgs = NULL; - m_nArgsSize = 0; - m_pBuffer = NULL; - m_uiBufferSize = 0; + m_rgpArgs = NULL; + m_nArgsSize = 0; + m_pBuffer = NULL; + m_uiBufferSize = 0; Init(a_uiFlags, a_nReservedSlots); } -template -CSimpleGlobTempl::~CSimpleGlobTempl() +template CSimpleGlobTempl::~CSimpleGlobTempl() { if (m_rgpArgs) free(m_rgpArgs); if (m_pBuffer) free(m_pBuffer); } -template -int -CSimpleGlobTempl::Init( - unsigned int a_uiFlags, - int a_nReservedSlots - ) +template int CSimpleGlobTempl::Init(unsigned int a_uiFlags, int a_nReservedSlots) { - m_nArgArrayType = POINTERS; - m_uiFlags = a_uiFlags; - m_nArgsLen = a_nReservedSlots; - m_nReservedSlots = a_nReservedSlots; - m_uiBufferLen = 0; - - if (m_nReservedSlots > 0) { - if (!GrowArgvArray(m_nReservedSlots)) { - return SG_ERR_MEMORY; - } - for (int n = 0; n < m_nReservedSlots; ++n) { + m_nArgArrayType = POINTERS; + m_uiFlags = a_uiFlags; + m_nArgsLen = a_nReservedSlots; + m_nReservedSlots = a_nReservedSlots; + m_uiBufferLen = 0; + + if (m_nReservedSlots > 0) + { + if (!GrowArgvArray(m_nReservedSlots)) { return SG_ERR_MEMORY; } + for (int n = 0; n < m_nReservedSlots; ++n) + { m_rgpArgs[n] = NULL; } } @@ -686,48 +718,43 @@ CSimpleGlobTempl::Init( return SG_SUCCESS; } -template -int -CSimpleGlobTempl::Add( - const SOCHAR *a_pszFileSpec - ) +template int CSimpleGlobTempl::Add(const SOCHAR *a_pszFileSpec) { #ifdef _WIN32 - // Windows FindFirst/FindNext recognizes forward slash as the same as - // backward slash and follows the directories. We need to do the same + // Windows FindFirst/FindNext recognizes forward slash as the same as + // backward slash and follows the directories. We need to do the same // when calculating the prefix and when we have no wildcards. SOCHAR szFileSpec[MAX_PATH]; SimpleGlobUtil::strcpy_s(szFileSpec, MAX_PATH, a_pszFileSpec); - const SOCHAR * pszPath = SimpleGlobUtil::strchr(szFileSpec, '/'); - while (pszPath) { + const SOCHAR *pszPath = SimpleGlobUtil::strchr(szFileSpec, '/'); + while (pszPath) + { szFileSpec[pszPath - szFileSpec] = SG_PATH_CHAR; - pszPath = SimpleGlobUtil::strchr(pszPath + 1, '/'); + pszPath = SimpleGlobUtil::strchr(pszPath + 1, '/'); } a_pszFileSpec = szFileSpec; #endif // if this doesn't contain wildcards then we can just add it directly m_szPathPrefix[0] = 0; - if (!SimpleGlobUtil::strchr(a_pszFileSpec, '*') && - !SimpleGlobUtil::strchr(a_pszFileSpec, '?')) + if (!SimpleGlobUtil::strchr(a_pszFileSpec, '*') && !SimpleGlobUtil::strchr(a_pszFileSpec, '?')) { SG_FileType nType = this->GetFileTypeS(a_pszFileSpec); - if (nType == SG_FILETYPE_INVALID) { - if (m_uiFlags & SG_GLOB_NOCHECK) { - return AppendName(a_pszFileSpec, false); - } + if (nType == SG_FILETYPE_INVALID) + { + if (m_uiFlags & SG_GLOB_NOCHECK) { return AppendName(a_pszFileSpec, false); } return SG_ERR_NOMATCH; } return AppendName(a_pszFileSpec, nType == SG_FILETYPE_DIR); } #ifdef _WIN32 - // Windows doesn't return the directory with the filename, so we need to - // extract the path from the search string ourselves and prefix it to the + // Windows doesn't return the directory with the filename, so we need to + // extract the path from the search string ourselves and prefix it to the // filename we get back. - const SOCHAR * pszFilename = - SimpleGlobUtil::strrchr(a_pszFileSpec, SG_PATH_CHAR); - if (pszFilename) { + const SOCHAR *pszFilename = SimpleGlobUtil::strrchr(a_pszFileSpec, SG_PATH_CHAR); + if (pszFilename) + { SimpleGlobUtil::strcpy_s(m_szPathPrefix, MAX_PATH, a_pszFileSpec); m_szPathPrefix[pszFilename - a_pszFileSpec + 1] = 0; } @@ -735,8 +762,10 @@ CSimpleGlobTempl::Add( // search for the first match on the file int rc = this->FindFirstFileS(a_pszFileSpec, m_uiFlags); - if (rc != SG_SUCCESS) { - if (rc == SG_ERR_NOMATCH && (m_uiFlags & SG_GLOB_NOCHECK)) { + if (rc != SG_SUCCESS) + { + if (rc == SG_ERR_NOMATCH && (m_uiFlags & SG_GLOB_NOCHECK)) + { int ok = AppendName(a_pszFileSpec, false); if (ok != SG_SUCCESS) rc = ok; } @@ -744,187 +773,147 @@ CSimpleGlobTempl::Add( } // add it and find all subsequent matches - int nError, nStartLen = m_nArgsLen; + int nError, nStartLen = m_nArgsLen; bool bSuccess; - do { - nError = AppendName(this->GetFileNameS((SOCHAR)0), this->IsDirS((SOCHAR)0)); + do + { + nError = AppendName(this->GetFileNameS((SOCHAR)0), this->IsDirS((SOCHAR)0)); bSuccess = this->FindNextFileS((SOCHAR)0); - } - while (nError == SG_SUCCESS && bSuccess); + } while (nError == SG_SUCCESS && bSuccess); SimpleGlobBase::FindDone(); // sort these files if required - if (m_nArgsLen > nStartLen && !(m_uiFlags & SG_GLOB_NOSORT)) { - if (m_uiFlags & SG_GLOB_FULLSORT) { - nStartLen = m_nReservedSlots; - } + if (m_nArgsLen > nStartLen && !(m_uiFlags & SG_GLOB_NOSORT)) + { + if (m_uiFlags & SG_GLOB_FULLSORT) { nStartLen = m_nReservedSlots; } SetArgvArrayType(POINTERS); - qsort( - m_rgpArgs + nStartLen, - m_nArgsLen - nStartLen, - sizeof(m_rgpArgs[0]), fileSortCompare); + qsort(m_rgpArgs + nStartLen, m_nArgsLen - nStartLen, sizeof(m_rgpArgs[0]), fileSortCompare); } return nError; } -template -int -CSimpleGlobTempl::Add( - int a_nCount, - const SOCHAR * const * a_rgpszFileSpec - ) +template int CSimpleGlobTempl::Add(int a_nCount, const SOCHAR *const *a_rgpszFileSpec) { int nResult; - for (int n = 0; n < a_nCount; ++n) { + for (int n = 0; n < a_nCount; ++n) + { nResult = Add(a_rgpszFileSpec[n]); - if (nResult != SG_SUCCESS) { - return nResult; - } + if (nResult != SG_SUCCESS) { return nResult; } } return SG_SUCCESS; } -template -int -CSimpleGlobTempl::AppendName( - const SOCHAR * a_pszFileName, - bool a_bIsDir - ) +template int CSimpleGlobTempl::AppendName(const SOCHAR *a_pszFileName, bool a_bIsDir) { // we need the argv array as offsets in case we resize it SetArgvArrayType(OFFSETS); // check for special cases which cause us to ignore this entry - if ((m_uiFlags & SG_GLOB_ONLYDIR) && !a_bIsDir) { - return SG_SUCCESS; - } - if ((m_uiFlags & SG_GLOB_ONLYFILE) && a_bIsDir) { - return SG_SUCCESS; - } - if ((m_uiFlags & SG_GLOB_NODOT) && a_bIsDir) { - if (a_pszFileName[0] == '.') { - if (a_pszFileName[1] == '\0') { - return SG_SUCCESS; - } - if (a_pszFileName[1] == '.' && a_pszFileName[2] == '\0') { - return SG_SUCCESS; - } + if ((m_uiFlags & SG_GLOB_ONLYDIR) && !a_bIsDir) { return SG_SUCCESS; } + if ((m_uiFlags & SG_GLOB_ONLYFILE) && a_bIsDir) { return SG_SUCCESS; } + if ((m_uiFlags & SG_GLOB_NODOT) && a_bIsDir) + { + if (a_pszFileName[0] == '.') + { + if (a_pszFileName[1] == '\0') { return SG_SUCCESS; } + if (a_pszFileName[1] == '.' && a_pszFileName[2] == '\0') { return SG_SUCCESS; } } } // ensure that we have enough room in the argv array - if (!GrowArgvArray(m_nArgsLen + 1)) { - return SG_ERR_MEMORY; - } + if (!GrowArgvArray(m_nArgsLen + 1)) { return SG_ERR_MEMORY; } // ensure that we have enough room in the string buffer (+1 for null) size_t uiPrefixLen = SimpleGlobUtil::strlen(m_szPathPrefix); - size_t uiLen = uiPrefixLen + SimpleGlobUtil::strlen(a_pszFileName) + 1; - if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) { - ++uiLen; // need space for the backslash - } - if (!GrowStringBuffer(m_uiBufferLen + uiLen)) { - return SG_ERR_MEMORY; + size_t uiLen = uiPrefixLen + SimpleGlobUtil::strlen(a_pszFileName) + 1; + if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) + { + ++uiLen; // need space for the backslash } + if (!GrowStringBuffer(m_uiBufferLen + uiLen)) { return SG_ERR_MEMORY; } // add this entry. m_uiBufferLen is offset from beginning of buffer. - m_rgpArgs[m_nArgsLen++] = (SOCHAR*)m_uiBufferLen; - SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen, - m_uiBufferSize - m_uiBufferLen, m_szPathPrefix); - SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen + uiPrefixLen, - m_uiBufferSize - m_uiBufferLen - uiPrefixLen, a_pszFileName); + m_rgpArgs[m_nArgsLen++] = (SOCHAR *)m_uiBufferLen; + SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen, m_uiBufferSize - m_uiBufferLen, m_szPathPrefix); + SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen + uiPrefixLen, m_uiBufferSize - m_uiBufferLen - uiPrefixLen, + a_pszFileName); m_uiBufferLen += uiLen; // add the directory slash if desired - if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) { - const static SOCHAR szDirSlash[] = { SG_PATH_CHAR, 0 }; - SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen - 2, - m_uiBufferSize - (m_uiBufferLen - 2), szDirSlash); + if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) + { + const static SOCHAR szDirSlash[] = {SG_PATH_CHAR, 0}; + SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen - 2, m_uiBufferSize - (m_uiBufferLen - 2), szDirSlash); } return SG_SUCCESS; } -template -void -CSimpleGlobTempl::SetArgvArrayType( - ARG_ARRAY_TYPE a_nNewType - ) +template void CSimpleGlobTempl::SetArgvArrayType(ARG_ARRAY_TYPE a_nNewType) { if (m_nArgArrayType == a_nNewType) return; - if (a_nNewType == POINTERS) { + if (a_nNewType == POINTERS) + { SG_ASSERT(m_nArgArrayType == OFFSETS); - for (int n = 0; n < m_nArgsLen; ++n) { - m_rgpArgs[n] = (m_rgpArgs[n] == (SOCHAR*)-1) ? - NULL : m_pBuffer + (size_t) m_rgpArgs[n]; + for (int n = 0; n < m_nArgsLen; ++n) + { + m_rgpArgs[n] = (m_rgpArgs[n] == (SOCHAR *)-1) ? NULL : m_pBuffer + (size_t)m_rgpArgs[n]; } } - else { + else + { SG_ASSERT(a_nNewType == OFFSETS); SG_ASSERT(m_nArgArrayType == POINTERS); - for (int n = 0; n < m_nArgsLen; ++n) { - m_rgpArgs[n] = (m_rgpArgs[n] == NULL) ? - (SOCHAR*) -1 : (SOCHAR*) (m_rgpArgs[n] - m_pBuffer); + for (int n = 0; n < m_nArgsLen; ++n) + { + m_rgpArgs[n] = (m_rgpArgs[n] == NULL) ? (SOCHAR *)-1 : (SOCHAR *)(m_rgpArgs[n] - m_pBuffer); } } m_nArgArrayType = a_nNewType; } -template -bool -CSimpleGlobTempl::GrowArgvArray( - int a_nNewLen - ) +template bool CSimpleGlobTempl::GrowArgvArray(int a_nNewLen) { - if (a_nNewLen >= m_nArgsSize) { + if (a_nNewLen >= m_nArgsSize) + { static const int SG_ARGV_INITIAL_SIZE = 32; - int nNewSize = (m_nArgsSize > 0) ? - m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE; - while (a_nNewLen >= nNewSize) { + int nNewSize = (m_nArgsSize > 0) ? m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE; + while (a_nNewLen >= nNewSize) + { nNewSize *= 2; } - void * pNewBuffer = realloc(m_rgpArgs, nNewSize * sizeof(SOCHAR*)); + void *pNewBuffer = realloc(m_rgpArgs, nNewSize * sizeof(SOCHAR *)); if (!pNewBuffer) return false; m_nArgsSize = nNewSize; - m_rgpArgs = (SOCHAR**) pNewBuffer; + m_rgpArgs = (SOCHAR **)pNewBuffer; } return true; } -template -bool -CSimpleGlobTempl::GrowStringBuffer( - size_t a_uiMinSize - ) +template bool CSimpleGlobTempl::GrowStringBuffer(size_t a_uiMinSize) { - if (a_uiMinSize >= m_uiBufferSize) { + if (a_uiMinSize >= m_uiBufferSize) + { static const int SG_BUFFER_INITIAL_SIZE = 1024; - size_t uiNewSize = (m_uiBufferSize > 0) ? - m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE; - while (a_uiMinSize >= uiNewSize) { + size_t uiNewSize = (m_uiBufferSize > 0) ? m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE; + while (a_uiMinSize >= uiNewSize) + { uiNewSize *= 2; } - void * pNewBuffer = realloc(m_pBuffer, uiNewSize * sizeof(SOCHAR)); + void *pNewBuffer = realloc(m_pBuffer, uiNewSize * sizeof(SOCHAR)); if (!pNewBuffer) return false; m_uiBufferSize = uiNewSize; - m_pBuffer = (SOCHAR*) pNewBuffer; + m_pBuffer = (SOCHAR *)pNewBuffer; } return true; } -template -int -CSimpleGlobTempl::fileSortCompare( - const void *a1, - const void *a2 - ) +template int CSimpleGlobTempl::fileSortCompare(const void *a1, const void *a2) { - const SOCHAR * s1 = *(const SOCHAR **)a1; - const SOCHAR * s2 = *(const SOCHAR **)a2; - if (s1 && s2) { - return SimpleGlobUtil::strcasecmp(s1, s2); - } + const SOCHAR *s1 = *(const SOCHAR **)a1; + const SOCHAR *s2 = *(const SOCHAR **)a2; + if (s1 && s2) { return SimpleGlobUtil::strcasecmp(s1, s2); } // NULL sorts first return s1 == s2 ? 0 : (s1 ? 1 : -1); } @@ -934,26 +923,26 @@ CSimpleGlobTempl::fileSortCompare( // --------------------------------------------------------------------------- /*! @brief ASCII/MBCS version of CSimpleGlob */ -typedef CSimpleGlobTempl CSimpleGlobA; +typedef CSimpleGlobTempl CSimpleGlobA; /*! @brief wchar_t version of CSimpleGlob */ -typedef CSimpleGlobTempl CSimpleGlobW; +typedef CSimpleGlobTempl CSimpleGlobW; #if SG_HAVE_ICU /*! @brief UChar version of CSimpleGlob */ -typedef CSimpleGlobTempl CSimpleGlobU; +typedef CSimpleGlobTempl CSimpleGlobU; #endif #ifdef _UNICODE -/*! @brief TCHAR version dependent on if _UNICODE is defined */ -# if SG_HAVE_ICU -# define CSimpleGlob CSimpleGlobU -# else -# define CSimpleGlob CSimpleGlobW -# endif + /*! @brief TCHAR version dependent on if _UNICODE is defined */ + #if SG_HAVE_ICU + #define CSimpleGlob CSimpleGlobU + #else + #define CSimpleGlob CSimpleGlobW + #endif #else -/*! @brief TCHAR version dependent on if _UNICODE is defined */ -# define CSimpleGlob CSimpleGlobA + /*! @brief TCHAR version dependent on if _UNICODE is defined */ + #define CSimpleGlob CSimpleGlobA #endif #endif // INCLUDED_SimpleGlob diff --git a/source/main/utils/SimpleOpt.h b/source/main/utils/SimpleOpt.h index bd2da41879..76ccf0ab87 100644 --- a/source/main/utils/SimpleOpt.h +++ b/source/main/utils/SimpleOpt.h @@ -3,70 +3,70 @@ @version 3.6 @brief A cross-platform command line library which can parse almost any - of the standard command line formats in use today. It is designed - explicitly to be portable to any platform and has been tested on Windows + of the standard command line formats in use today. It is designed + explicitly to be portable to any platform and has been tested on Windows and Linux. See CSimpleOptTempl for the class definition. @section features FEATURES - - MIT Licence allows free use in all software (including GPL + - MIT Licence allows free use in all software (including GPL and commercial) - multi-platform (Windows 95/98/ME/NT/2K/XP, Linux, Unix) - supports all lengths of option names: -
- +
- switch character only (e.g. use stdin for input) -
-o +
-o short (single character) -
-long +
-long long (multiple character, single switch character) -
--longer +
--longer long (multiple character, multiple switch characters)
- supports all types of arguments for options: -
--option +
--option short/long option flag (no argument) -
--option ARG +
--option ARG short/long option with separate required argument -
--option=ARG +
--option=ARG short/long option with combined required argument -
--option[=ARG] +
--option[=ARG] short/long option with combined optional argument -
-oARG +
-oARG short option with combined required argument -
-o[ARG] +
-o[ARG] short option with combined optional argument
- supports options with multiple or variable numbers of arguments: -
--multi ARG1 ARG2 +
--multi ARG1 ARG2 Multiple arguments -
--multi N ARG-1 ARG-2 ... ARG-N +
--multi N ARG-1 ARG-2 ... ARG-N Variable number of arguments
- - supports case-insensitive option matching on short, long and/or + - supports case-insensitive option matching on short, long and/or word arguments. - - supports options which do not use a switch character. i.e. a special - word which is construed as an option. - e.g. "foo.exe open /directory/file.txt" - - supports clumping of multiple short options (no arguments) in a string + - supports options which do not use a switch character. i.e. a special + word which is construed as an option. + e.g. "foo.exe open /directory/file.txt" + - supports clumping of multiple short options (no arguments) in a string e.g. "foo.exe -abcdef file1" <==> "foo.exe -a -b -c -d -e -f file1" - - automatic recognition of a single slash as equivalent to a single + - automatic recognition of a single slash as equivalent to a single hyphen on Windows, e.g. "/f FILE" is equivalent to "-f FILE". - file arguments can appear anywhere in the argument list: "foo.exe file1.txt -a ARG file2.txt --flag file3.txt file4.txt" - files will be returned to the application in the same order they were + files will be returned to the application in the same order they were supplied on the command line - short-circuit option matching: "--man" will match "--mandate" - invalid options can be handled while continuing to parse the command + invalid options can be handled while continuing to parse the command line valid options list can be changed dynamically during command line - processing, i.e. accept different options depending on an option + processing, i.e. accept different options depending on an option supplied earlier in the command line. - implemented with only a single C++ header file - optionally use no C runtime or OS functions - char, wchar_t and Windows TCHAR in the same program - complete working examples included - - compiles cleanly at warning level 4 (Windows/VC.NET 2003), warning + - compiles cleanly at warning level 4 (Windows/VC.NET 2003), warning level 3 (Windows/VC6) and -Wall (Linux/gcc) @section usage USAGE @@ -89,19 +89,19 @@ Note that all options must start with a hyphen even if the slash will be accepted. This is because the slash character is automatically - converted into a hyphen to test against the list of options. - For example, the following line matches both "-?" and "/?" + converted into a hyphen to test against the list of options. + For example, the following line matches both "-?" and "/?" (on Windows).
     { OPT_HELP, _T("-?"),     SO_NONE    }, // "-?"
 
-
  • Instantiate a CSimpleOpt object supplying argc, argv and the option +
  • Instantiate a CSimpleOpt object supplying argc, argv and the option table
     @link CSimpleOptTempl CSimpleOpt @endlink args(argc, argv, g_rgOptions);
     
    -
  • Process the arguments by calling Next() until it returns false. - On each call, first check for an error by calling LastError(), then +
  • Process the arguments by calling Next() until it returns false. + On each call, first check for an error by calling LastError(), then either handle the error or process the argument.
     while (args.Next()) {
    @@ -142,12 +142,12 @@ ShowFiles(args.FileCount(), args.Files());
         The above copyright notice and this permission notice shall be included
         in all copies or substantial portions of the Software.
     
    -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
    -    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    -    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
    -    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
    -    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
    -    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
    +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    +    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    +    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    +    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    +    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
         SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     
    */ @@ -165,132 +165,133 @@ ShowFiles(args.FileCount(), args.Files()); A cross-platform library providing a simple method to parse almost any of the standard command-line formats in use today. - See the @link SimpleOpt.h SimpleOpt @endlink documentation for full + See the @link SimpleOpt.h SimpleOpt @endlink documentation for full details. @section SimpleGlob SimpleGlob A cross-platform file globbing library providing the ability to - expand wildcards in command-line arguments to a list of all matching + expand wildcards in command-line arguments to a list of all matching files. - See the @link SimpleGlob.h SimpleGlob @endlink documentation for full + See the @link SimpleGlob.h SimpleGlob @endlink documentation for full details. */ #ifndef INCLUDED_SimpleOpt #define INCLUDED_SimpleOpt -// Default the max arguments to a fixed value. If you want to be able to -// handle any number of arguments, then predefine this to 0 and it will +// Default the max arguments to a fixed value. If you want to be able to +// handle any number of arguments, then predefine this to 0 and it will // use an internal dynamically allocated buffer instead. #ifdef SO_MAX_ARGS -# define SO_STATICBUF SO_MAX_ARGS + #define SO_STATICBUF SO_MAX_ARGS #else -# include // malloc, free -# include // memcpy -# define SO_STATICBUF 50 + #include // malloc, free + #include // memcpy + #define SO_STATICBUF 50 #endif //! Error values typedef enum _ESOError { //! No error - SO_SUCCESS = 0, + SO_SUCCESS = 0, - /*! It looks like an option (it starts with a switch character), but + /*! It looks like an option (it starts with a switch character), but it isn't registered in the option table. */ - SO_OPT_INVALID = -1, + SO_OPT_INVALID = -1, - /*! Multiple options matched the supplied option text. + /*! Multiple options matched the supplied option text. Only returned when NOT using SO_O_EXACT. */ - SO_OPT_MULTIPLE = -2, + SO_OPT_MULTIPLE = -2, - /*! Option doesn't take an argument, but a combined argument was + /*! Option doesn't take an argument, but a combined argument was supplied. */ - SO_ARG_INVALID = -3, + SO_ARG_INVALID = -3, /*! SO_REQ_CMB style-argument was supplied to a SO_REQ_SEP option Only returned when using SO_O_PEDANTIC. */ - SO_ARG_INVALID_TYPE = -4, + SO_ARG_INVALID_TYPE = -4, //! Required argument was not supplied - SO_ARG_MISSING = -5, + SO_ARG_MISSING = -5, - /*! Option argument looks like another option. + /*! Option argument looks like another option. Only returned when NOT using SO_O_NOERR. */ - SO_ARG_INVALID_DATA = -6 + SO_ARG_INVALID_DATA = -6 } ESOError; //! Option flags enum _ESOFlags { /*! Disallow partial matching of option names */ - SO_O_EXACT = 0x0001, + SO_O_EXACT = 0x0001, - /*! Disallow use of slash as an option marker on Windows. + /*! Disallow use of slash as an option marker on Windows. Un*x only ever recognizes a hyphen. */ - SO_O_NOSLASH = 0x0002, + SO_O_NOSLASH = 0x0002, - /*! Permit arguments on single letter options with no equals sign. + /*! Permit arguments on single letter options with no equals sign. e.g. -oARG or -o[ARG] */ - SO_O_SHORTARG = 0x0004, + SO_O_SHORTARG = 0x0004, - /*! Permit single character options to be clumped into a single + /*! Permit single character options to be clumped into a single option string. e.g. "-a -b -c" <==> "-abc" */ - SO_O_CLUMP = 0x0008, + SO_O_CLUMP = 0x0008, - /*! Process the entire argv array for options, including the + /*! Process the entire argv array for options, including the argv[0] entry. */ - SO_O_USEALL = 0x0010, + SO_O_USEALL = 0x0010, - /*! Do not generate an error for invalid options. errors for missing - arguments will still be generated. invalid options will be - treated as files. invalid options in clumps will be silently + /*! Do not generate an error for invalid options. errors for missing + arguments will still be generated. invalid options will be + treated as files. invalid options in clumps will be silently ignored. */ - SO_O_NOERR = 0x0020, + SO_O_NOERR = 0x0020, - /*! Validate argument type pedantically. Return an error when a - separated argument "-opt arg" is supplied by the user as a - combined argument "-opt=arg". By default this is not considered + /*! Validate argument type pedantically. Return an error when a + separated argument "-opt arg" is supplied by the user as a + combined argument "-opt=arg". By default this is not considered an error. */ - SO_O_PEDANTIC = 0x0040, + SO_O_PEDANTIC = 0x0040, /*! Case-insensitive comparisons for short arguments */ - SO_O_ICASE_SHORT = 0x0100, + SO_O_ICASE_SHORT = 0x0100, /*! Case-insensitive comparisons for long arguments */ - SO_O_ICASE_LONG = 0x0200, + SO_O_ICASE_LONG = 0x0200, - /*! Case-insensitive comparisons for word arguments + /*! Case-insensitive comparisons for word arguments i.e. arguments without any hyphens at the start. */ - SO_O_ICASE_WORD = 0x0400, + SO_O_ICASE_WORD = 0x0400, /*! Case-insensitive comparisons for all arg types */ - SO_O_ICASE = 0x0700 + SO_O_ICASE = 0x0700 }; /*! Types of arguments that options may have. Note that some of the _ESOFlags are not compatible with all argument types. SO_O_SHORTARG requires that - relevant options use either SO_REQ_CMB or SO_OPT. SO_O_CLUMP requires + relevant options use either SO_REQ_CMB or SO_OPT. SO_O_CLUMP requires that relevant options use only SO_NONE. */ -typedef enum _ESOArgType { +typedef enum _ESOArgType +{ /*! No argument. Just the option flags. e.g. -o --opt */ - SO_NONE, + SO_NONE, - /*! Required separate argument. + /*! Required separate argument. e.g. -o ARG --opt ARG */ - SO_REQ_SEP, + SO_REQ_SEP, - /*! Required combined argument. + /*! Required combined argument. e.g. -oARG -o=ARG --opt=ARG */ - SO_REQ_CMB, + SO_REQ_CMB, - /*! Optional combined argument. + /*! Optional combined argument. e.g. -o[ARG] -o[=ARG] --opt[=ARG] */ - SO_OPT, + SO_OPT, /*! Multiple separate arguments. The actual number of arguments is determined programatically at the time the argument is processed. @@ -299,18 +300,21 @@ typedef enum _ESOArgType { } ESOArgType; //! this option definition must be the last entry in the table -#define SO_END_OF_OPTIONS { -1, NULL, SO_NONE } +#define SO_END_OF_OPTIONS \ + { \ + -1, NULL, SO_NONE \ + } #ifdef _DEBUG -# ifdef _MSC_VER -# include -# define SO_ASSERT(b) _ASSERTE(b) -# else -# include -# define SO_ASSERT(b) assert(b) -# endif + #ifdef _MSC_VER + #include + #define SO_ASSERT(b) _ASSERTE(b) + #else + #include + #define SO_ASSERT(b) assert(b) + #endif #else -# define SO_ASSERT(b) //!< assertion used to test input data + #define SO_ASSERT(b) //!< assertion used to test input data #endif // --------------------------------------------------------------------------- @@ -318,46 +322,42 @@ typedef enum _ESOArgType { // --------------------------------------------------------------------------- /*! @brief Implementation of the SimpleOpt class */ -template -class CSimpleOptTempl +template class CSimpleOptTempl { -public: + public: /*! @brief Structure used to define all known options. */ - struct SOption { + struct SOption + { /*! ID to return for this flag. Optional but must be >= 0 */ - int nId; + int nId; - /*! arg string to search for, e.g. "open", "-", "-f", "--file" + /*! arg string to search for, e.g. "open", "-", "-f", "--file" Note that on Windows the slash option marker will be converted to a hyphen so that "-f" will also match "/f". */ - const SOCHAR * pszArg; + const SOCHAR *pszArg; /*! type of argument accepted by this option */ - ESOArgType nArgType; + ESOArgType nArgType; }; /*! @brief Initialize the class. Init() must be called later. */ - CSimpleOptTempl() - : m_rgShuffleBuf(NULL) - { - Init(0, NULL, NULL, 0); + CSimpleOptTempl() : m_rgShuffleBuf(NULL) + { + Init(0, NULL, NULL, 0); } /*! @brief Initialize the class in preparation for use. */ - CSimpleOptTempl( - int argc, - SOCHAR * argv[], - const SOption * a_rgOptions, - int a_nFlags = 0 - ) - : m_rgShuffleBuf(NULL) - { - Init(argc, argv, a_rgOptions, a_nFlags); + CSimpleOptTempl(int argc, SOCHAR *argv[], const SOption *a_rgOptions, int a_nFlags = 0) : m_rgShuffleBuf(NULL) + { + Init(argc, argv, a_rgOptions, a_nFlags); } #ifndef SO_MAX_ARGS /*! @brief Deallocate any allocated memory. */ - ~CSimpleOptTempl() { if (m_rgShuffleBuf) free(m_rgShuffleBuf); } + ~CSimpleOptTempl() + { + if (m_rgShuffleBuf) free(m_rgShuffleBuf); + } #endif /*! @brief Initialize the class in preparation for calling Next. @@ -374,26 +374,22 @@ class CSimpleOptTempl @param a_argc Argument array size @param a_argv Argument array @param a_rgOptions Valid option array - @param a_nFlags Optional flags to modify the processing of + @param a_nFlags Optional flags to modify the processing of the arguments - @return true Successful + @return true Successful @return false if SO_MAX_ARGC > 0: Too many arguments if SO_MAX_ARGC == 0: Memory allocation failure */ - bool Init( - int a_argc, - SOCHAR * a_argv[], - const SOption * a_rgOptions, - int a_nFlags = 0 - ); + bool Init(int a_argc, SOCHAR *a_argv[], const SOption *a_rgOptions, int a_nFlags = 0); /*! @brief Change the current options table during option parsing. @param a_rgOptions Valid option array */ - inline void SetOptions(const SOption * a_rgOptions) { - m_rgOptions = a_rgOptions; + inline void SetOptions(const SOption *a_rgOptions) + { + m_rgOptions = a_rgOptions; } /*! @brief Change the current flags during option parsing. @@ -403,19 +399,23 @@ class CSimpleOptTempl @param a_nFlags Flags to modify the processing of the arguments */ - inline void SetFlags(int a_nFlags) { m_nFlags = a_nFlags; } + inline void SetFlags(int a_nFlags) + { + m_nFlags = a_nFlags; + } /*! @brief Query if a particular flag is set */ - inline bool HasFlag(int a_nFlag) const { - return (m_nFlags & a_nFlag) == a_nFlag; + inline bool HasFlag(int a_nFlag) const + { + return (m_nFlags & a_nFlag) == a_nFlag; } /*! @brief Advance to the next option if available. When all options have been processed it will return false. When true has been returned, you must check for an invalid or unrecognized - option using the LastError() method. This will be return an error - value other than SO_SUCCESS on an error. All standard data + option using the LastError() method. This will be return an error + value other than SO_SUCCESS on an error. All standard data (e.g. OptionText(), OptionArg(), OptionId(), etc) will be available depending on the error. @@ -435,31 +435,43 @@ class CSimpleOptTempl /*! @brief Return the last error that occurred. - This function must always be called before processing the current + This function must always be called before processing the current option. This function is available only when Next() has returned true. */ - inline ESOError LastError() const { return m_nLastError; } + inline ESOError LastError() const + { + return m_nLastError; + } /*! @brief Return the nId value from the options array for the current option. This function is available only when Next() has returned true. */ - inline int OptionId() const { return m_nOptionId; } + inline int OptionId() const + { + return m_nOptionId; + } - /*! @brief Return the pszArg from the options array for the current + /*! @brief Return the pszArg from the options array for the current option. This function is available only when Next() has returned true. */ - inline const SOCHAR * OptionText() const { return m_pszOptionText; } + inline const SOCHAR *OptionText() const + { + return m_pszOptionText; + } /*! @brief Return the argument for the current option where one exists. If there is no argument for the option, this will return NULL. This function is available only when Next() has returned true. */ - inline SOCHAR * OptionArg() const { return m_pszOptionArg; } + inline SOCHAR *OptionArg() const + { + return m_pszOptionArg; + } /*! @brief Validate and return the desired number of arguments. @@ -473,143 +485,144 @@ class CSimpleOptTempl @param n Number of arguments to return. */ - SOCHAR ** MultiArg(int n); + SOCHAR **MultiArg(int n); /*! @brief Returned the number of entries in the Files() array. After Next() has returned false, this will be the list of files (or otherwise unprocessed arguments). */ - inline int FileCount() const { return m_argc - m_nLastArg; } + inline int FileCount() const + { + return m_argc - m_nLastArg; + } /*! @brief Return the specified file argument. @param n Index of the file to return. This must be between 0 and FileCount() - 1; */ - inline SOCHAR * File(int n) const { + inline SOCHAR *File(int n) const + { SO_ASSERT(n >= 0 && n < FileCount()); return m_argv[m_nLastArg + n]; } /*! @brief Return the array of files. */ - inline SOCHAR ** Files() const { return &m_argv[m_nLastArg]; } + inline SOCHAR **Files() const + { + return &m_argv[m_nLastArg]; + } -private: - CSimpleOptTempl(const CSimpleOptTempl &); // disabled - CSimpleOptTempl & operator=(const CSimpleOptTempl &); // disabled + private: + CSimpleOptTempl(const CSimpleOptTempl &); // disabled + CSimpleOptTempl &operator=(const CSimpleOptTempl &); // disabled - SOCHAR PrepareArg(SOCHAR * a_pszString) const; - bool NextClumped(); - void ShuffleArg(int a_nStartIdx, int a_nCount); - int LookupOption(const SOCHAR * a_pszOption) const; - int CalcMatch(const SOCHAR *a_pszSource, const SOCHAR *a_pszTest) const; + SOCHAR PrepareArg(SOCHAR *a_pszString) const; + bool NextClumped(); + void ShuffleArg(int a_nStartIdx, int a_nCount); + int LookupOption(const SOCHAR *a_pszOption) const; + int CalcMatch(const SOCHAR *a_pszSource, const SOCHAR *a_pszTest) const; // Find the '=' character within a string. - inline SOCHAR * FindEquals(SOCHAR *s) const { - while (*s && *s != (SOCHAR)'=') ++s; + inline SOCHAR *FindEquals(SOCHAR *s) const + { + while (*s && *s != (SOCHAR)'=') + ++s; return *s ? s : NULL; } bool IsEqual(SOCHAR a_cLeft, SOCHAR a_cRight, int a_nArgType) const; - inline void Copy(SOCHAR ** ppDst, SOCHAR ** ppSrc, int nCount) const { + inline void Copy(SOCHAR **ppDst, SOCHAR **ppSrc, int nCount) const + { #ifdef SO_MAX_ARGS // keep our promise of no CLIB usage - while (nCount-- > 0) *ppDst++ = *ppSrc++; + while (nCount-- > 0) + *ppDst++ = *ppSrc++; #else - memcpy(ppDst, ppSrc, nCount * sizeof(SOCHAR*)); + memcpy(ppDst, ppSrc, nCount * sizeof(SOCHAR *)); #endif } -private: - const SOption * m_rgOptions; //!< pointer to options table - int m_nFlags; //!< flags - int m_nOptionIdx; //!< current argv option index - int m_nOptionId; //!< id of current option (-1 = invalid) - int m_nNextOption; //!< index of next option - int m_nLastArg; //!< last argument, after this are files - int m_argc; //!< argc to process - SOCHAR ** m_argv; //!< argv - const SOCHAR * m_pszOptionText; //!< curr option text, e.g. "-f" - SOCHAR * m_pszOptionArg; //!< curr option arg, e.g. "c:\file.txt" - SOCHAR * m_pszClump; //!< clumped single character options - SOCHAR m_szShort[3]; //!< temp for clump and combined args - ESOError m_nLastError; //!< error status from the last call - SOCHAR ** m_rgShuffleBuf; //!< shuffle buffer for large argc + private: + const SOption *m_rgOptions; //!< pointer to options table + int m_nFlags; //!< flags + int m_nOptionIdx; //!< current argv option index + int m_nOptionId; //!< id of current option (-1 = invalid) + int m_nNextOption; //!< index of next option + int m_nLastArg; //!< last argument, after this are files + int m_argc; //!< argc to process + SOCHAR ** m_argv; //!< argv + const SOCHAR * m_pszOptionText; //!< curr option text, e.g. "-f" + SOCHAR * m_pszOptionArg; //!< curr option arg, e.g. "c:\file.txt" + SOCHAR * m_pszClump; //!< clumped single character options + SOCHAR m_szShort[3]; //!< temp for clump and combined args + ESOError m_nLastError; //!< error status from the last call + SOCHAR ** m_rgShuffleBuf; //!< shuffle buffer for large argc }; // --------------------------------------------------------------------------- // IMPLEMENTATION // --------------------------------------------------------------------------- -template -bool -CSimpleOptTempl::Init( - int a_argc, - SOCHAR * a_argv[], - const SOption * a_rgOptions, - int a_nFlags - ) +template bool CSimpleOptTempl::Init(int a_argc, SOCHAR *a_argv[], const SOption *a_rgOptions, int a_nFlags) { - m_argc = a_argc; - m_nLastArg = a_argc; - m_argv = a_argv; - m_rgOptions = a_rgOptions; - m_nLastError = SO_SUCCESS; - m_nOptionIdx = 0; - m_nOptionId = -1; - m_pszOptionText = NULL; - m_pszOptionArg = NULL; - m_nNextOption = (a_nFlags & SO_O_USEALL) ? 0 : 1; - m_szShort[0] = (SOCHAR)'-'; - m_szShort[2] = (SOCHAR)'\0'; - m_nFlags = a_nFlags; - m_pszClump = NULL; + m_argc = a_argc; + m_nLastArg = a_argc; + m_argv = a_argv; + m_rgOptions = a_rgOptions; + m_nLastError = SO_SUCCESS; + m_nOptionIdx = 0; + m_nOptionId = -1; + m_pszOptionText = NULL; + m_pszOptionArg = NULL; + m_nNextOption = (a_nFlags & SO_O_USEALL) ? 0 : 1; + m_szShort[0] = (SOCHAR)'-'; + m_szShort[2] = (SOCHAR)'\0'; + m_nFlags = a_nFlags; + m_pszClump = NULL; #ifdef SO_MAX_ARGS - if (m_argc > SO_MAX_ARGS) { + if (m_argc > SO_MAX_ARGS) + { m_nLastError = SO_ARG_INVALID_DATA; - m_nLastArg = 0; - return false; - } -#else - if (m_rgShuffleBuf) { - free(m_rgShuffleBuf); + m_nLastArg = 0; + return false; } - if (m_argc > SO_STATICBUF) { - m_rgShuffleBuf = (SOCHAR**) malloc(sizeof(SOCHAR*) * m_argc); - if (!m_rgShuffleBuf) { - return false; - } +#else + if (m_rgShuffleBuf) { free(m_rgShuffleBuf); } + if (m_argc > SO_STATICBUF) + { + m_rgShuffleBuf = (SOCHAR **)malloc(sizeof(SOCHAR *) * m_argc); + if (!m_rgShuffleBuf) { return false; } } #endif return true; } -template -bool -CSimpleOptTempl::Next() +template bool CSimpleOptTempl::Next() { #ifdef SO_MAX_ARGS - if (m_argc > SO_MAX_ARGS) { + if (m_argc > SO_MAX_ARGS) + { SO_ASSERT(!"Too many args! Check the return value of Init()!"); return false; } #endif // process a clumped option string if appropriate - if (m_pszClump && *m_pszClump) { + if (m_pszClump && *m_pszClump) + { // silently discard invalid clumped option bool bIsValid = NextClumped(); - while (*m_pszClump && !bIsValid && HasFlag(SO_O_NOERR)) { + while (*m_pszClump && !bIsValid && HasFlag(SO_O_NOERR)) + { bIsValid = NextClumped(); } // return this option if valid or we are returning errors - if (bIsValid || !HasFlag(SO_O_NOERR)) { - return true; - } + if (bIsValid || !HasFlag(SO_O_NOERR)) { return true; } } SO_ASSERT(!m_pszClump || !*m_pszClump); m_pszClump = NULL; @@ -623,39 +636,33 @@ CSimpleOptTempl::Next() // find the next option SOCHAR cFirst; - int nTableIdx = -1; - int nOptIdx = m_nOptionIdx; - while (nTableIdx < 0 && nOptIdx < m_nLastArg) { - SOCHAR * pszArg = m_argv[nOptIdx]; - m_pszOptionArg = NULL; + int nTableIdx = -1; + int nOptIdx = m_nOptionIdx; + while (nTableIdx < 0 && nOptIdx < m_nLastArg) + { + SOCHAR *pszArg = m_argv[nOptIdx]; + m_pszOptionArg = NULL; // find this option in the options table cFirst = PrepareArg(pszArg); - if (pszArg[0] == (SOCHAR)'-') { + if (pszArg[0] == (SOCHAR)'-') + { // find any combined argument string and remove equals sign m_pszOptionArg = FindEquals(pszArg); - if (m_pszOptionArg) { - *m_pszOptionArg++ = (SOCHAR)'\0'; - } + if (m_pszOptionArg) { *m_pszOptionArg++ = (SOCHAR)'\0'; } } nTableIdx = LookupOption(pszArg); // if we didn't find this option but if it is a short form // option then we try the alternative forms - if (nTableIdx < 0 - && !m_pszOptionArg - && pszArg[0] == (SOCHAR)'-' - && pszArg[1] - && pszArg[1] != (SOCHAR)'-' - && pszArg[2]) + if (nTableIdx < 0 && !m_pszOptionArg && pszArg[0] == (SOCHAR)'-' && pszArg[1] && pszArg[1] != (SOCHAR)'-' && pszArg[2]) { // test for a short-form with argument if appropriate - if (HasFlag(SO_O_SHORTARG)) { + if (HasFlag(SO_O_SHORTARG)) + { m_szShort[1] = pszArg[1]; - int nIdx = LookupOption(m_szShort); - if (nIdx >= 0 - && (m_rgOptions[nIdx].nArgType == SO_REQ_CMB - || m_rgOptions[nIdx].nArgType == SO_OPT)) + int nIdx = LookupOption(m_szShort); + if (nIdx >= 0 && (m_rgOptions[nIdx].nArgType == SO_REQ_CMB || m_rgOptions[nIdx].nArgType == SO_OPT)) { m_pszOptionArg = &pszArg[2]; pszArg = m_szShort; @@ -665,12 +672,11 @@ CSimpleOptTempl::Next() // test for a clumped short-form option string and we didn't // match on the short-form argument above - if (nTableIdx < 0 && HasFlag(SO_O_CLUMP)) { + if (nTableIdx < 0 && HasFlag(SO_O_CLUMP)) + { m_pszClump = &pszArg[1]; ++m_nNextOption; - if (nOptIdx > m_nOptionIdx) { - ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx); - } + if (nOptIdx > m_nOptionIdx) { ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx); } return Next(); } } @@ -678,62 +684,59 @@ CSimpleOptTempl::Next() // The option wasn't found. If it starts with a switch character // and we are not suppressing errors for invalid options then it // is reported as an error, otherwise it is data. - if (nTableIdx < 0) { - if (!HasFlag(SO_O_NOERR) && pszArg[0] == (SOCHAR)'-') { + if (nTableIdx < 0) + { + if (!HasFlag(SO_O_NOERR) && pszArg[0] == (SOCHAR)'-') + { m_pszOptionText = pszArg; break; } - + pszArg[0] = cFirst; ++nOptIdx; - if (m_pszOptionArg) { - *(--m_pszOptionArg) = (SOCHAR)'='; - } + if (m_pszOptionArg) { *(--m_pszOptionArg) = (SOCHAR)'='; } } } // end of options - if (nOptIdx >= m_nLastArg) { - if (nOptIdx > m_nOptionIdx) { - ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx); - } + if (nOptIdx >= m_nLastArg) + { + if (nOptIdx > m_nOptionIdx) { ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx); } return false; } ++m_nNextOption; // get the option id ESOArgType nArgType = SO_NONE; - if (nTableIdx < 0) { - m_nLastError = (ESOError) nTableIdx; // error code + if (nTableIdx < 0) + { + m_nLastError = (ESOError)nTableIdx; // error code } - else { + else + { m_nOptionId = m_rgOptions[nTableIdx].nId; m_pszOptionText = m_rgOptions[nTableIdx].pszArg; // ensure that the arg type is valid nArgType = m_rgOptions[nTableIdx].nArgType; - switch (nArgType) { + switch (nArgType) + { case SO_NONE: - if (m_pszOptionArg) { - m_nLastError = SO_ARG_INVALID; - } + if (m_pszOptionArg) { m_nLastError = SO_ARG_INVALID; } break; case SO_REQ_SEP: - if (m_pszOptionArg) { - // they wanted separate args, but we got a combined one, + if (m_pszOptionArg) + { + // they wanted separate args, but we got a combined one, // unless we are pedantic, just accept it. - if (HasFlag(SO_O_PEDANTIC)) { - m_nLastError = SO_ARG_INVALID_TYPE; - } + if (HasFlag(SO_O_PEDANTIC)) { m_nLastError = SO_ARG_INVALID_TYPE; } } // more processing after we shuffle break; case SO_REQ_CMB: - if (!m_pszOptionArg) { - m_nLastError = SO_ARG_MISSING; - } + if (!m_pszOptionArg) { m_nLastError = SO_ARG_MISSING; } break; case SO_OPT: @@ -748,49 +751,32 @@ CSimpleOptTempl::Next() } // shuffle the files out of the way - if (nOptIdx > m_nOptionIdx) { - ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx); - } + if (nOptIdx > m_nOptionIdx) { ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx); } // we need to return the separate arg if required, just re-use the // multi-arg code because it all does the same thing - if ( nArgType == SO_REQ_SEP - && !m_pszOptionArg - && m_nLastError == SO_SUCCESS) + if (nArgType == SO_REQ_SEP && !m_pszOptionArg && m_nLastError == SO_SUCCESS) { - SOCHAR ** ppArgs = MultiArg(1); - if (ppArgs) { - m_pszOptionArg = *ppArgs; - } + SOCHAR **ppArgs = MultiArg(1); + if (ppArgs) { m_pszOptionArg = *ppArgs; } } return true; } -template -void -CSimpleOptTempl::Stop() +template void CSimpleOptTempl::Stop() { - if (m_nNextOption < m_nLastArg) { - ShuffleArg(m_nNextOption, m_nLastArg - m_nNextOption); - } + if (m_nNextOption < m_nLastArg) { ShuffleArg(m_nNextOption, m_nLastArg - m_nNextOption); } } -template -SOCHAR -CSimpleOptTempl::PrepareArg( - SOCHAR * a_pszString - ) const +template SOCHAR CSimpleOptTempl::PrepareArg(SOCHAR *a_pszString) const { #ifdef _WIN32 // On Windows we can accept the forward slash as a single character // option delimiter, but it cannot replace the '-' option used to // denote stdin. On Un*x paths may start with slash so it may not // be used to start an option. - if (!HasFlag(SO_O_NOSLASH) - && a_pszString[0] == (SOCHAR)'/' - && a_pszString[1] - && a_pszString[1] != (SOCHAR)'-') + if (!HasFlag(SO_O_NOSLASH) && a_pszString[0] == (SOCHAR)'/' && a_pszString[1] && a_pszString[1] != (SOCHAR)'-') { a_pszString[0] = (SOCHAR)'-'; return (SOCHAR)'/'; @@ -799,9 +785,7 @@ CSimpleOptTempl::PrepareArg( return a_pszString[0]; } -template -bool -CSimpleOptTempl::NextClumped() +template bool CSimpleOptTempl::NextClumped() { // prepare for the next clumped option m_szShort[1] = *m_pszClump++; @@ -812,29 +796,33 @@ CSimpleOptTempl::NextClumped() // lookup this option, ensure that we are using exact matching int nSavedFlags = m_nFlags; - m_nFlags = SO_O_EXACT; - int nTableIdx = LookupOption(m_szShort); - m_nFlags = nSavedFlags; + m_nFlags = SO_O_EXACT; + int nTableIdx = LookupOption(m_szShort); + m_nFlags = nSavedFlags; // unknown option - if (nTableIdx < 0) { - m_pszOptionText = m_szShort; // invalid option - m_nLastError = (ESOError) nTableIdx; // error code + if (nTableIdx < 0) + { + m_pszOptionText = m_szShort; // invalid option + m_nLastError = (ESOError)nTableIdx; // error code return false; } // valid option - m_pszOptionText = m_rgOptions[nTableIdx].pszArg; + m_pszOptionText = m_rgOptions[nTableIdx].pszArg; ESOArgType nArgType = m_rgOptions[nTableIdx].nArgType; - if (nArgType == SO_NONE) { + if (nArgType == SO_NONE) + { m_nOptionId = m_rgOptions[nTableIdx].nId; return true; } - if (nArgType == SO_REQ_CMB && *m_pszClump) { - m_nOptionId = m_rgOptions[nTableIdx].nId; + if (nArgType == SO_REQ_CMB && *m_pszClump) + { + m_nOptionId = m_rgOptions[nTableIdx].nId; m_pszOptionArg = m_pszClump; - while (*m_pszClump) ++m_pszClump; // must point to an empty string + while (*m_pszClump) + ++m_pszClump; // must point to an empty string return true; } @@ -851,16 +839,11 @@ CSimpleOptTempl::NextClumped() // ShuffleArg(1, 1) = { "0", "2", "3", "4", "5", "6", "7", "8", "1" }; // ShuffleArg(5, 2) = { "0", "1", "2", "3", "4", "7", "8", "5", "6" }; // ShuffleArg(2, 4) = { "0", "1", "6", "7", "8", "2", "3", "4", "5" }; -template -void -CSimpleOptTempl::ShuffleArg( - int a_nStartIdx, - int a_nCount - ) +template void CSimpleOptTempl::ShuffleArg(int a_nStartIdx, int a_nCount) { SOCHAR * staticBuf[SO_STATICBUF]; - SOCHAR ** buf = m_rgShuffleBuf ? m_rgShuffleBuf : staticBuf; - int nTail = m_argc - a_nStartIdx - a_nCount; + SOCHAR **buf = m_rgShuffleBuf ? m_rgShuffleBuf : staticBuf; + int nTail = m_argc - a_nStartIdx - a_nCount; // make a copy of the elements to be moved Copy(buf, m_argv + a_nStartIdx, a_nCount); @@ -877,85 +860,70 @@ CSimpleOptTempl::ShuffleArg( // match on the long format strings. partial matches will be // accepted only if that feature is enabled. -template -int -CSimpleOptTempl::LookupOption( - const SOCHAR * a_pszOption - ) const +template int CSimpleOptTempl::LookupOption(const SOCHAR *a_pszOption) const { - int nBestMatch = -1; // index of best match so far + int nBestMatch = -1; // index of best match so far int nBestMatchLen = 0; // matching characters of best match int nLastMatchLen = 0; // matching characters of last best match - for (int n = 0; m_rgOptions[n].nId >= 0; ++n) { + for (int n = 0; m_rgOptions[n].nId >= 0; ++n) + { // the option table must use hyphens as the option character, // the slash character is converted to a hyphen for testing. SO_ASSERT(m_rgOptions[n].pszArg[0] != (SOCHAR)'/'); int nMatchLen = CalcMatch(m_rgOptions[n].pszArg, a_pszOption); - if (nMatchLen == -1) { - return n; - } - if (nMatchLen > 0 && nMatchLen >= nBestMatchLen) { + if (nMatchLen == -1) { return n; } + if (nMatchLen > 0 && nMatchLen >= nBestMatchLen) + { nLastMatchLen = nBestMatchLen; nBestMatchLen = nMatchLen; - nBestMatch = n; + nBestMatch = n; } } // only partial matches or no match gets to here, ensure that we // don't return a partial match unless it is a clear winner - if (HasFlag(SO_O_EXACT) || nBestMatch == -1) { - return SO_OPT_INVALID; - } + if (HasFlag(SO_O_EXACT) || nBestMatch == -1) { return SO_OPT_INVALID; } return (nBestMatchLen > nLastMatchLen) ? nBestMatch : SO_OPT_MULTIPLE; } // calculate the number of characters that match (case-sensitive) // 0 = no match, > 0 == number of characters, -1 == perfect match -template -int -CSimpleOptTempl::CalcMatch( - const SOCHAR * a_pszSource, - const SOCHAR * a_pszTest - ) const +template int CSimpleOptTempl::CalcMatch(const SOCHAR *a_pszSource, const SOCHAR *a_pszTest) const { - if (!a_pszSource || !a_pszTest) { - return 0; - } + if (!a_pszSource || !a_pszTest) { return 0; } // determine the argument type int nArgType = SO_O_ICASE_LONG; - if (a_pszSource[0] != '-') { - nArgType = SO_O_ICASE_WORD; - } - else if (a_pszSource[1] != '-' && !a_pszSource[2]) { + if (a_pszSource[0] != '-') { nArgType = SO_O_ICASE_WORD; } + else if (a_pszSource[1] != '-' && !a_pszSource[2]) + { nArgType = SO_O_ICASE_SHORT; } // match and skip leading hyphens - while (*a_pszSource == (SOCHAR)'-' && *a_pszSource == *a_pszTest) { - ++a_pszSource; + while (*a_pszSource == (SOCHAR)'-' && *a_pszSource == *a_pszTest) + { + ++a_pszSource; ++a_pszTest; } - if (*a_pszSource == (SOCHAR)'-' || *a_pszTest == (SOCHAR)'-') { - return 0; - } + if (*a_pszSource == (SOCHAR)'-' || *a_pszTest == (SOCHAR)'-') { return 0; } // find matching number of characters in the strings int nLen = 0; - while (*a_pszSource && IsEqual(*a_pszSource, *a_pszTest, nArgType)) { - ++a_pszSource; - ++a_pszTest; + while (*a_pszSource && IsEqual(*a_pszSource, *a_pszTest, nArgType)) + { + ++a_pszSource; + ++a_pszTest; ++nLen; } // if we have exhausted the source... - if (!*a_pszSource) { + if (!*a_pszSource) + { // and the test strings, then it's a perfect match - if (!*a_pszTest) { - return -1; - } + if (!*a_pszTest) { return -1; } // otherwise the match failed as the test is longer than // the source. i.e. "--mant" will not match the option "--man". @@ -964,25 +932,18 @@ CSimpleOptTempl::CalcMatch( // if we haven't exhausted the test string then it is not a match // i.e. "--mantle" will not best-fit match to "--mandate" at all. - if (*a_pszTest) { - return 0; - } + if (*a_pszTest) { return 0; } // partial match to the current length of the test string return nLen; } -template -bool -CSimpleOptTempl::IsEqual( - SOCHAR a_cLeft, - SOCHAR a_cRight, - int a_nArgType - ) const +template bool CSimpleOptTempl::IsEqual(SOCHAR a_cLeft, SOCHAR a_cRight, int a_nArgType) const { // if this matches then we are doing case-insensitive matching - if (m_nFlags & a_nArgType) { - if (a_cLeft >= 'A' && a_cLeft <= 'Z') a_cLeft += 'a' - 'A'; + if (m_nFlags & a_nArgType) + { + if (a_cLeft >= 'A' && a_cLeft <= 'Z') a_cLeft += 'a' - 'A'; if (a_cRight >= 'A' && a_cRight <= 'Z') a_cRight += 'a' - 'A'; } return a_cLeft == a_cRight; @@ -990,29 +951,29 @@ CSimpleOptTempl::IsEqual( // calculate the number of characters that match (case-sensitive) // 0 = no match, > 0 == number of characters, -1 == perfect match -template -SOCHAR ** -CSimpleOptTempl::MultiArg( - int a_nCount - ) +template SOCHAR **CSimpleOptTempl::MultiArg(int a_nCount) { // ensure we have enough arguments - if (m_nNextOption + a_nCount > m_nLastArg) { + if (m_nNextOption + a_nCount > m_nLastArg) + { m_nLastError = SO_ARG_MISSING; return NULL; } // our argument array - SOCHAR ** rgpszArg = &m_argv[m_nNextOption]; + SOCHAR **rgpszArg = &m_argv[m_nNextOption]; // Ensure that each of the following don't start with an switch character. // Only make this check if we are returning errors for unknown arguments. - if (!HasFlag(SO_O_NOERR)) { - for (int n = 0; n < a_nCount; ++n) { + if (!HasFlag(SO_O_NOERR)) + { + for (int n = 0; n < a_nCount; ++n) + { SOCHAR ch = PrepareArg(rgpszArg[n]); - if (rgpszArg[n][0] == (SOCHAR)'-') { + if (rgpszArg[n][0] == (SOCHAR)'-') + { rgpszArg[n][0] = ch; - m_nLastError = SO_ARG_INVALID_DATA; + m_nLastError = SO_ARG_INVALID_DATA; return NULL; } rgpszArg[n][0] = ch; @@ -1024,23 +985,22 @@ CSimpleOptTempl::MultiArg( return rgpszArg; } - // --------------------------------------------------------------------------- // TYPE DEFINITIONS // --------------------------------------------------------------------------- /*! @brief ASCII/MBCS version of CSimpleOpt */ -typedef CSimpleOptTempl CSimpleOptA; +typedef CSimpleOptTempl CSimpleOptA; /*! @brief wchar_t version of CSimpleOpt */ -typedef CSimpleOptTempl CSimpleOptW; +typedef CSimpleOptTempl CSimpleOptW; #if defined(_UNICODE) -/*! @brief TCHAR version dependent on if _UNICODE is defined */ -# define CSimpleOpt CSimpleOptW + /*! @brief TCHAR version dependent on if _UNICODE is defined */ + #define CSimpleOpt CSimpleOptW #else -/*! @brief TCHAR version dependent on if _UNICODE is defined */ -# define CSimpleOpt CSimpleOptA + /*! @brief TCHAR version dependent on if _UNICODE is defined */ + #define CSimpleOpt CSimpleOptA #endif #endif // INCLUDED_SimpleOpt diff --git a/source/main/utils/Singleton.h b/source/main/utils/Singleton.h index 33df8c6e9f..4480088deb 100644 --- a/source/main/utils/Singleton.h +++ b/source/main/utils/Singleton.h @@ -27,83 +27,106 @@ // friend class RoRSingleton; ////////////////////////////////////////////////////////////////////////// -template -class RoRSingleton +template class RoRSingleton { - static T* _instance; -protected: + static T *_instance; + + protected: RoRSingleton() { } - virtual ~RoRSingleton() { _instance = 0; } - void _free() { delete this; } - RoRSingleton(const RoRSingleton&); // not implemented - const RoRSingleton& operator=(const RoRSingleton&); // not implemented -public: - inline static T& getSingleton() + virtual ~RoRSingleton() + { + _instance = 0; + } + void _free() { - if (!_instance) - _instance = new T; + delete this; + } + RoRSingleton(const RoRSingleton &); // not implemented + const RoRSingleton &operator=(const RoRSingleton &); // not implemented + public: + inline static T &getSingleton() + { + if (!_instance) _instance = new T; return *_instance; } - inline static T* getSingletonPtr() + inline static T *getSingletonPtr() { - if (!_instance) - _instance = new T; + if (!_instance) _instance = new T; return _instance; } - inline static T* getSingletonPtrNoCreation() + inline static T *getSingletonPtrNoCreation() { return _instance; } - static bool singletonExists(void) { return (_instance != 0); } - static void freeSingleton() { getSingletonPtr()->_free(); } + static bool singletonExists(void) + { + return (_instance != 0); + } + static void freeSingleton() + { + getSingletonPtr()->_free(); + } }; -template -T* RoRSingleton::_instance = 0; +template T *RoRSingleton::_instance = 0; ////////////////////////////////////////////////////////////////////////// -template -class RoRSingletonNoCreation +template class RoRSingletonNoCreation { - static T* _instance; -protected: + static T *_instance; + + protected: RoRSingletonNoCreation() { } - virtual ~RoRSingletonNoCreation() { _instance = 0; } - void _free() { delete this; } - RoRSingletonNoCreation(const RoRSingletonNoCreation&); // not implemented - const RoRSingletonNoCreation& operator=(const RoRSingletonNoCreation&); // not implemented - void setSingleton(T* i) { _instance = i; } -public: - inline static T& getSingleton() + virtual ~RoRSingletonNoCreation() + { + _instance = 0; + } + void _free() + { + delete this; + } + RoRSingletonNoCreation(const RoRSingletonNoCreation &); // not implemented + const RoRSingletonNoCreation &operator=(const RoRSingletonNoCreation &); // not implemented + void setSingleton(T *i) + { + _instance = i; + } + + public: + inline static T &getSingleton() { MYASSERT(_instance); return *_instance; } - inline static T* getSingletonPtr() + inline static T *getSingletonPtr() { MYASSERT(_instance); return _instance; } - inline static T* getSingletonPtrNoCreation() + inline static T *getSingletonPtrNoCreation() { return _instance; } - static bool singletonExists(void) { return (_instance != 0); } - static void freeSingleton() { getSingletonPtr()->_free(); } + static bool singletonExists(void) + { + return (_instance != 0); + } + static void freeSingleton() + { + getSingletonPtr()->_free(); + } }; -template -T* RoRSingletonNoCreation::_instance = 0; - +template T *RoRSingletonNoCreation::_instance = 0; diff --git a/source/main/utils/Utils.cpp b/source/main/utils/Utils.cpp index 96a87bf68d..32293af0f0 100644 --- a/source/main/utils/Utils.cpp +++ b/source/main/utils/Utils.cpp @@ -21,23 +21,23 @@ #include "Utils.h" -#include "RoRnet.h" +#include "Application.h" #include "RoRVersion.h" +#include "RoRnet.h" #include "SHA1.h" -#include "Application.h" #include #ifdef USE_DISCORD_RPC -#include + #include #endif #ifndef _WIN32 -# include + #include #endif #ifdef _WIN32 -# include // Sleep() + #include // Sleep() #endif using namespace Ogre; @@ -57,14 +57,15 @@ void DiscordReadyCallback(const DiscordUser *user) void InitDiscord() { #ifdef USE_DISCORD_RPC - if(RoR::App::io_discord_rpc.GetActive()) + if (RoR::App::io_discord_rpc.GetActive()) { DiscordEventHandlers handlers; memset(&handlers, 0, sizeof(handlers)); - handlers.ready = DiscordReadyCallback; + handlers.ready = DiscordReadyCallback; handlers.errored = DiscordErrorCallback; - // Discord_Initialize(const char* applicationId, DiscordEventHandlers* handlers, int autoRegister, const char* optionalSteamId) + // Discord_Initialize(const char* applicationId, DiscordEventHandlers* handlers, int autoRegister, const char* + // optionalSteamId) Discord_Initialize("492484203435393035", &handlers, 1, "1234"); } #endif @@ -73,18 +74,16 @@ void InitDiscord() void UpdatePresence() { #ifdef USE_DISCORD_RPC - if(RoR::App::io_discord_rpc.GetActive()) + if (RoR::App::io_discord_rpc.GetActive()) { - char buffer[256]; + char buffer[256]; DiscordRichPresence discordPresence; memset(&discordPresence, 0, sizeof(discordPresence)); if (RoR::App::mp_state.GetActive() == RoR::MpState::CONNECTED) { discordPresence.state = "Playing online"; - sprintf(buffer, "On server: %s:%d on terrain: %s", - RoR::App::mp_server_host.GetActive(), - RoR::App::mp_server_port.GetActive(), - RoR::App::sim_terrain_gui_name.GetActive()); + sprintf(buffer, "On server: %s:%d on terrain: %s", RoR::App::mp_server_host.GetActive(), + RoR::App::mp_server_port.GetActive(), RoR::App::sim_terrain_gui_name.GetActive()); } else { @@ -121,7 +120,7 @@ String HashData(const char *key, int len) String HashFile(const char *szFileName) { - unsigned long ulFileSize, ulRest, ulBlocks; + unsigned long ulFileSize, ulRest, ulBlocks; std::vector uData(2097152); if (szFileName == NULL) return ""; @@ -136,35 +135,36 @@ String HashFile(const char *szFileName) if (ulFileSize != 0) { ulBlocks = ulFileSize / static_cast(uData.size()); - ulRest = ulFileSize % uData.size(); + ulRest = ulFileSize % uData.size(); } else { ulBlocks = 0; - ulRest = 0; + ulRest = 0; } uint32_t hash = 0; for (unsigned long i = 0; i < ulBlocks; i++) { size_t result = fread(uData.data(), 1, uData.size(), fIn); - hash = FastHash(uData.data(), uData.size(), hash); + hash = FastHash(uData.data(), uData.size(), hash); } if (ulRest != 0) { size_t result = fread(uData.data(), 1, ulRest, fIn); - hash = FastHash(uData.data(), ulRest, hash); + hash = FastHash(uData.data(), ulRest, hash); } - fclose(fIn); fIn = NULL; + fclose(fIn); + fIn = NULL; std::stringstream result; result << std::hex << hash; return result.str(); } -UTFString tryConvertUTF(const char* buffer) +UTFString tryConvertUTF(const char *buffer) { std::string str_in(buffer); return UTFString(RoR::Utils::SanitizeUtf8String(str_in)); @@ -172,17 +172,17 @@ UTFString tryConvertUTF(const char* buffer) UTFString formatBytes(double bytes) { - wchar_t tmp[128] = L""; - const wchar_t* si_prefix[] = {L"B", L"KB", L"MB", L"GB", L"TB", L"EB", L"ZB", L"YB"}; - int base = 1024; - int c = bytes > 0 ? std::min((int)(log(bytes) / log((float)base)), (int)sizeof(si_prefix) - 1) : 0; + wchar_t tmp[128] = L""; + const wchar_t *si_prefix[] = {L"B", L"KB", L"MB", L"GB", L"TB", L"EB", L"ZB", L"YB"}; + int base = 1024; + int c = bytes > 0 ? std::min((int)(log(bytes) / log((float)base)), (int)sizeof(si_prefix) - 1) : 0; swprintf(tmp, 128, L"%1.2f %ls", bytes / pow((float)base, c), si_prefix[c]); return UTFString(tmp); } std::time_t getTimeStamp() { - return time(NULL); //this will overflow in 2038 + return time(NULL); // this will overflow in 2038 } String getVersionString(bool multiline) @@ -190,21 +190,23 @@ String getVersionString(bool multiline) char tmp[1024] = ""; if (multiline) { - sprintf(tmp, "Rigs of Rods\n" - " version: %s\n" - " protocol version: %s\n" - " build time: %s, %s\n" - , ROR_VERSION_STRING, RORNET_VERSION, ROR_BUILD_DATE, ROR_BUILD_TIME); + sprintf(tmp, + "Rigs of Rods\n" + " version: %s\n" + " protocol version: %s\n" + " build time: %s, %s\n", + ROR_VERSION_STRING, RORNET_VERSION, ROR_BUILD_DATE, ROR_BUILD_TIME); } else { - sprintf(tmp, "Rigs of Rods version %s, protocol version: %s, build time: %s, %s", ROR_VERSION_STRING, RORNET_VERSION, ROR_BUILD_DATE, ROR_BUILD_TIME); + sprintf(tmp, "Rigs of Rods version %s, protocol version: %s, build time: %s, %s", ROR_VERSION_STRING, RORNET_VERSION, + ROR_BUILD_DATE, ROR_BUILD_TIME); } return String(tmp); } -void fixRenderWindowIcon(RenderWindow* rw) +void fixRenderWindowIcon(RenderWindow *rw) { #ifdef _WIN32 size_t hWnd = 0; @@ -214,7 +216,7 @@ void fixRenderWindowIcon(RenderWindow* rw) ::GetModuleFileNameA(0, (LPCH)&buf, MAX_PATH); HINSTANCE instance = ::GetModuleHandleA(buf); - HICON hIcon = ::LoadIconA(instance, MAKEINTRESOURCEA(101)); + HICON hIcon = ::LoadIconA(instance, MAKEINTRESOURCEA(101)); if (hIcon) { ::SendMessageA((HWND)hWnd, WM_SETICON, 1, (LPARAM)hIcon); @@ -233,13 +235,11 @@ std::wstring ANSI_TO_WCHAR(const String source) return ANSI_TO_UTF(source).asWStr(); } -void trimUTFString(UTFString& str, bool left, bool right) +void trimUTFString(UTFString &str, bool left, bool right) { static const String delims = " \t\r"; - if (right) - str.erase(str.find_last_not_of(delims) + 1); // trim right - if (left) - str.erase(0, str.find_first_not_of(delims)); // trim left + if (right) str.erase(str.find_last_not_of(delims) + 1); // trim right + if (left) str.erase(0, str.find_first_not_of(delims)); // trim left } Real Round(Real value, unsigned short ndigits /* = 0 */) @@ -280,37 +280,36 @@ Real Round(Real value, int valueN, unsigned short ndigits /* = 0 */) return value; } -namespace RoR { -namespace Utils { - -std::string SanitizeUtf8String(std::string const& str_in) -{ - // Cloned from UTFCPP tutorial: http://utfcpp.sourceforge.net/#fixinvalid - std::string str_out; - utf8::replace_invalid(str_in.begin(), str_in.end(), std::back_inserter(str_out)); - return str_out; -} - -std::string SanitizeUtf8CString(const char* start, const char* end /* = nullptr */) +namespace RoR { - if (end == nullptr) + namespace Utils { - end = (start + strlen(start)); - } - // Cloned from UTFCPP tutorial: http://utfcpp.sourceforge.net/#fixinvalid - std::string str_out; - utf8::replace_invalid(start, end, std::back_inserter(str_out)); - return str_out; -} + std::string SanitizeUtf8String(std::string const &str_in) + { + // Cloned from UTFCPP tutorial: http://utfcpp.sourceforge.net/#fixinvalid + std::string str_out; + utf8::replace_invalid(str_in.begin(), str_in.end(), std::back_inserter(str_out)); + return str_out; + } -std::string Sha1Hash(std::string const & input) -{ - RoR::CSHA1 sha1; - sha1.UpdateHash((uint8_t *)input.c_str(), input.length()); - sha1.Final(); - return sha1.ReportHash(); -} + std::string SanitizeUtf8CString(const char *start, const char *end /* = nullptr */) + { + if (end == nullptr) { end = (start + strlen(start)); } + + // Cloned from UTFCPP tutorial: http://utfcpp.sourceforge.net/#fixinvalid + std::string str_out; + utf8::replace_invalid(start, end, std::back_inserter(str_out)); + return str_out; + } + + std::string Sha1Hash(std::string const &input) + { + RoR::CSHA1 sha1; + sha1.UpdateHash((uint8_t *)input.c_str(), input.length()); + sha1.Final(); + return sha1.ReportHash(); + } -} // namespace Utils + } // namespace Utils } // namespace RoR diff --git a/source/main/utils/Utils.h b/source/main/utils/Utils.h index c940161a89..e8927445aa 100644 --- a/source/main/utils/Utils.h +++ b/source/main/utils/Utils.h @@ -28,7 +28,6 @@ #pragma once #include "RoRPrerequisites.h" - #include "utf8/checked.h" #include "utf8/unchecked.h" @@ -44,9 +43,9 @@ Ogre::String sha1sum(const char *key, int len); Ogre::String HashData(const char *key, int len); -Ogre::String HashFile(const char* szFileName); +Ogre::String HashFile(const char *szFileName); -Ogre::UTFString tryConvertUTF(const char* buffer); +Ogre::UTFString tryConvertUTF(const char *buffer); Ogre::UTFString formatBytes(double bytes); @@ -54,19 +53,19 @@ std::time_t getTimeStamp(); Ogre::String getVersionString(bool multiline = true); -void fixRenderWindowIcon(Ogre::RenderWindow* rw); +void fixRenderWindowIcon(Ogre::RenderWindow *rw); -std::wstring ANSI_TO_WCHAR(const Ogre::String source); +std::wstring ANSI_TO_WCHAR(const Ogre::String source); Ogre::UTFString ANSI_TO_UTF(const Ogre::String source); -void trimUTFString(Ogre::UTFString& str, bool left = true, bool right = true); +void trimUTFString(Ogre::UTFString &str, bool left = true, bool right = true); -inline MyGUI::UString convertToMyGUIString(char* charstr) +inline MyGUI::UString convertToMyGUIString(char *charstr) { return MyGUI::UString(ANSI_TO_WCHAR(charstr)); } -inline MyGUI::UString convertToMyGUIString(wchar_t* charstr, int len) +inline MyGUI::UString convertToMyGUIString(wchar_t *charstr, int len) { return MyGUI::UString(charstr, len); } @@ -86,7 +85,7 @@ inline Ogre::UTFString convertFromMyGUIString(MyGUI::UString str) return Ogre::UTFString(str.asWStr()); } -inline void replaceString(std::string& str, std::string searchString, std::string replaceString) +inline void replaceString(std::string &str, std::string searchString, std::string replaceString) { std::string::size_type pos = 0; while ((pos = str.find(searchString, pos)) != std::string::npos) @@ -98,46 +97,54 @@ inline void replaceString(std::string& str, std::string searchString, std::strin Ogre::Real Round(Ogre::Real value, unsigned short ndigits = 0); -namespace RoR { -namespace Utils { -std::string SanitizeUtf8String(std::string const& str_in); -std::string SanitizeUtf8CString(const char* start, const char* end = nullptr); - - inline std::string& TrimStr(std::string& s) { Ogre::StringUtil::trim(s); return s; } - std::string Sha1Hash(std::string const & data); -} - -namespace Color { -const Ogre::UTFString CommandColour = Ogre::UTFString("#00FF00"); -const Ogre::UTFString WarningColour = Ogre::UTFString("#FF0000"); -const Ogre::UTFString NormalColour = Ogre::UTFString("#FFFFFF"); -const Ogre::UTFString WhisperColour = Ogre::UTFString("#FFCC00"); -const Ogre::UTFString ScriptCommandColour = Ogre::UTFString("#0099FF"); -} - -/// @author http://www.ogre3d.org/forums/viewtopic.php?p=463232#p463232 -/// @author http://www.ogre3d.org/tikiwiki/tiki-index.php?page=GetScreenspaceCoords&structure=Cookbook -class World2ScreenConverter ///< Keeps data close for faster access. +namespace RoR { -public: - World2ScreenConverter(Ogre::Matrix4 view_mtx, Ogre::Matrix4 proj_mtx, Ogre::Vector2 screen_size): - m_view_matrix(view_mtx), m_projection_matrix(proj_mtx), m_screen_size(screen_size) - {} - - /// @return X,Y=screen pos, Z=view space pos ('Z<0' means 'in front of the camera') - Ogre::Vector3 Convert(Ogre::Vector3 world_pos) + namespace Utils { - Ogre::Vector3 view_space_pos = m_view_matrix * world_pos; - Ogre::Vector3 clip_space_pos = m_projection_matrix * view_space_pos; // Clip space pos is [-1.f, 1.f] - float screen_x = ((clip_space_pos.x / 2.f) + 0.5f) * m_screen_size.x; - float screen_y = (1.f - ((clip_space_pos.y / 2.f) + 0.5f)) * m_screen_size.y; - return Ogre::Vector3(screen_x, screen_y, view_space_pos.z); - } - -private: - Ogre::Matrix4 m_view_matrix; - Ogre::Matrix4 m_projection_matrix; - Ogre::Vector2 m_screen_size; -}; + std::string SanitizeUtf8String(std::string const &str_in); + std::string SanitizeUtf8CString(const char *start, const char *end = nullptr); + + inline std::string &TrimStr(std::string &s) + { + Ogre::StringUtil::trim(s); + return s; + } + std::string Sha1Hash(std::string const &data); + } // namespace Utils + + namespace Color + { + const Ogre::UTFString CommandColour = Ogre::UTFString("#00FF00"); + const Ogre::UTFString WarningColour = Ogre::UTFString("#FF0000"); + const Ogre::UTFString NormalColour = Ogre::UTFString("#FFFFFF"); + const Ogre::UTFString WhisperColour = Ogre::UTFString("#FFCC00"); + const Ogre::UTFString ScriptCommandColour = Ogre::UTFString("#0099FF"); + } // namespace Color + + /// @author http://www.ogre3d.org/forums/viewtopic.php?p=463232#p463232 + /// @author http://www.ogre3d.org/tikiwiki/tiki-index.php?page=GetScreenspaceCoords&structure=Cookbook + class World2ScreenConverter ///< Keeps data close for faster access. + { + public: + World2ScreenConverter(Ogre::Matrix4 view_mtx, Ogre::Matrix4 proj_mtx, Ogre::Vector2 screen_size) + : m_view_matrix(view_mtx), m_projection_matrix(proj_mtx), m_screen_size(screen_size) + { + } + + /// @return X,Y=screen pos, Z=view space pos ('Z<0' means 'in front of the camera') + Ogre::Vector3 Convert(Ogre::Vector3 world_pos) + { + Ogre::Vector3 view_space_pos = m_view_matrix * world_pos; + Ogre::Vector3 clip_space_pos = m_projection_matrix * view_space_pos; // Clip space pos is [-1.f, 1.f] + float screen_x = ((clip_space_pos.x / 2.f) + 0.5f) * m_screen_size.x; + float screen_y = (1.f - ((clip_space_pos.y / 2.f) + 0.5f)) * m_screen_size.y; + return Ogre::Vector3(screen_x, screen_y, view_space_pos.z); + } + + private: + Ogre::Matrix4 m_view_matrix; + Ogre::Matrix4 m_projection_matrix; + Ogre::Vector2 m_screen_size; + }; } // namespace RoR diff --git a/source/main/utils/WriteTextToTexture.cpp b/source/main/utils/WriteTextToTexture.cpp index a66447d44f..5d36613b34 100644 --- a/source/main/utils/WriteTextToTexture.cpp +++ b/source/main/utils/WriteTextToTexture.cpp @@ -22,12 +22,12 @@ #include "Application.h" -#include #include #include #include #include #include +#include #include // source: ogre wiki: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=HowTo%3A+Write+text+on+texture @@ -38,29 +38,27 @@ void SaveImage(TexturePtr TextureToSave, String filename) HardwarePixelBufferSharedPtr readbuffer; readbuffer = TextureToSave->getBuffer(0, 0); readbuffer->lock(HardwareBuffer::HBL_NORMAL); - const PixelBox& readrefpb = readbuffer->getCurrentLock(); - uchar* readrefdata = static_cast(readrefpb.data); + const PixelBox &readrefpb = readbuffer->getCurrentLock(); + uchar * readrefdata = static_cast(readrefpb.data); Image img; - img = img.loadDynamicImage(readrefdata, TextureToSave->getWidth(), - TextureToSave->getHeight(), TextureToSave->getFormat()); + img = img.loadDynamicImage(readrefdata, TextureToSave->getWidth(), TextureToSave->getHeight(), TextureToSave->getFormat()); img.save(filename); readbuffer->unlock(); } -void WriteToTexture(const String& str, TexturePtr destTexture, Ogre::Box destRectangle, Ogre::Font* Reffont, const ColourValue& color, int fontSize, int fontDPI, char justify, bool wordwrap) +void WriteToTexture(const String &str, TexturePtr destTexture, Ogre::Box destRectangle, Ogre::Font *Reffont, + const ColourValue &color, int fontSize, int fontDPI, char justify, bool wordwrap) { using namespace Ogre; - if (destTexture->getHeight() < destRectangle.bottom) - destRectangle.bottom = destTexture->getHeight(); - if (destTexture->getWidth() < destRectangle.right) - destRectangle.right = destTexture->getWidth(); + if (destTexture->getHeight() < destRectangle.bottom) destRectangle.bottom = destTexture->getHeight(); + if (destTexture->getWidth() < destRectangle.right) destRectangle.right = destTexture->getWidth(); // Find our scaled up (or down) font. std::string fontname = "WTTFont_" + TOSTRING(fontSize + fontDPI) + "_" + Reffont->getSource(); - FontPtr font = FontManager::getSingleton().getByName(fontname); + FontPtr font = FontManager::getSingleton().getByName(fontname); // Font not found, let's created it :) if (font.isNull()) @@ -75,25 +73,27 @@ void WriteToTexture(const String& str, TexturePtr destTexture, Ogre::Box destRec LOG("[WriteToTexture] Created font: " + fontname); } - TexturePtr fontTexture = (TexturePtr)TextureManager::getSingleton().getByName(font->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName()); + TexturePtr fontTexture = (TexturePtr)TextureManager::getSingleton().getByName( + font->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName()); HardwarePixelBufferSharedPtr fontBuffer = fontTexture->getBuffer(); HardwarePixelBufferSharedPtr destBuffer = destTexture->getBuffer(); PixelBox destPb = destBuffer->lock(destRectangle, HardwareBuffer::HBL_NORMAL); - // The font texture buffer was created write only...so we cannot read it back :o). One solution is to copy the buffer instead of locking it. (Maybe there is a way to create a font texture which is not write_only ?) + // The font texture buffer was created write only...so we cannot read it back :o). One solution is to copy the buffer instead + // of locking it. (Maybe there is a way to create a font texture which is not write_only ?) // create a buffer size_t nBuffSize = fontBuffer->getSizeInBytes(); - uint8* buffer = (uint8*)calloc(nBuffSize, sizeof(uint8)); + uint8 *buffer = (uint8 *)calloc(nBuffSize, sizeof(uint8)); // create pixel box using the copy of the buffer PixelBox fontPb(fontBuffer->getWidth(), fontBuffer->getHeight(), fontBuffer->getDepth(), fontBuffer->getFormat(), buffer); fontBuffer->blitToMemory(fontPb); - uint8* fontData = static_cast(fontPb.data); - uint8* destData = static_cast(destPb.data); + uint8 *fontData = static_cast(fontPb.data); + uint8 *destData = static_cast(destPb.data); const size_t fontPixelSize = PixelUtil::getNumElemBytes(fontPb.format); const size_t destPixelSize = PixelUtil::getNumElemBytes(destPb.format); @@ -101,136 +101,138 @@ void WriteToTexture(const String& str, TexturePtr destTexture, Ogre::Box destRec const size_t fontRowPitchBytes = fontPb.rowPitch * fontPixelSize; const size_t destRowPitchBytes = destPb.rowPitch * destPixelSize; - Box* GlyphTexCoords; + Box *GlyphTexCoords; GlyphTexCoords = new Box[str.size()]; Ogre::Font::UVRect glypheTexRect; - size_t charheight = 0; - size_t charwidth = 0; + size_t charheight = 0; + size_t charwidth = 0; for (unsigned int i = 0; i < str.size(); i++) { if ((str[i] != '\t') && (str[i] != '\n') && (str[i] != ' ')) { - glypheTexRect = font->getGlyphTexCoords(str[i]); - GlyphTexCoords[i].left = glypheTexRect.left * fontTexture->getSrcWidth(); - GlyphTexCoords[i].top = glypheTexRect.top * fontTexture->getSrcHeight(); - GlyphTexCoords[i].right = glypheTexRect.right * fontTexture->getSrcWidth(); + glypheTexRect = font->getGlyphTexCoords(str[i]); + GlyphTexCoords[i].left = glypheTexRect.left * fontTexture->getSrcWidth(); + GlyphTexCoords[i].top = glypheTexRect.top * fontTexture->getSrcHeight(); + GlyphTexCoords[i].right = glypheTexRect.right * fontTexture->getSrcWidth(); GlyphTexCoords[i].bottom = glypheTexRect.bottom * fontTexture->getSrcHeight(); - if (GlyphTexCoords[i].getHeight() > charheight) - charheight = GlyphTexCoords[i].getHeight(); - if (GlyphTexCoords[i].getWidth() > charwidth) - charwidth = GlyphTexCoords[i].getWidth(); + if (GlyphTexCoords[i].getHeight() > charheight) charheight = GlyphTexCoords[i].getHeight(); + if (GlyphTexCoords[i].getWidth() > charwidth) charwidth = GlyphTexCoords[i].getWidth(); } } - size_t cursorX = 0; - size_t cursorY = 0; - size_t lineend = destRectangle.getWidth(); - bool carriagreturn = true; + size_t cursorX = 0; + size_t cursorY = 0; + size_t lineend = destRectangle.getWidth(); + bool carriagreturn = true; for (unsigned int strindex = 0; strindex < str.size(); strindex++) { switch (str[strindex]) { - case ' ': cursorX += charwidth; - break; - case '\t': cursorX += charwidth * 3; - break; - case '\n': cursorY += charheight; + case ' ': cursorX += charwidth; break; + case '\t': cursorX += charwidth * 3; break; + case '\n': + cursorY += charheight; carriagreturn = true; break; default: + { + // wrapping + if ((cursorX + GlyphTexCoords[strindex].getWidth() > lineend) && !carriagreturn) { - //wrapping - if ((cursorX + GlyphTexCoords[strindex].getWidth() > lineend) && !carriagreturn) - { - cursorY += charheight; - carriagreturn = true; - } + cursorY += charheight; + carriagreturn = true; + } + + // justify + if (carriagreturn) + { + size_t l = strindex; + size_t textwidth = 0; + size_t wordwidth = 0; - //justify - if (carriagreturn) + while (l < str.size() && str[l] != '\n') { - size_t l = strindex; - size_t textwidth = 0; - size_t wordwidth = 0; + wordwidth = 0; - while (l < str.size() && str[l] != '\n') + switch (str[l]) { - wordwidth = 0; - - switch (str[l]) - { - case ' ': wordwidth = charwidth; - ++l; - break; - case '\t': wordwidth = charwidth * 3; - ++l; - break; - case '\n': l = str.size(); - } + case ' ': + wordwidth = charwidth; + ++l; + break; + case '\t': + wordwidth = charwidth * 3; + ++l; + break; + case '\n': l = str.size(); + } - if (wordwrap) - while (l < str.size() && str[l] != ' ' && str[l] != '\t' && str[l] != '\n') - { - wordwidth += GlyphTexCoords[l].getWidth(); - ++l; - } - else + if (wordwrap) + while (l < str.size() && str[l] != ' ' && str[l] != '\t' && str[l] != '\n') { wordwidth += GlyphTexCoords[l].getWidth(); - l++; + ++l; } - - if ((textwidth + wordwidth) <= destRectangle.getWidth()) - textwidth += (wordwidth); - else - break; - } - - if ((textwidth == 0) && (wordwidth > destRectangle.getWidth())) - textwidth = destRectangle.getWidth(); - - switch (justify) + else { - case 'c': cursorX = (destRectangle.getWidth() - textwidth) / 2; - lineend = destRectangle.getWidth() - cursorX; - break; + wordwidth += GlyphTexCoords[l].getWidth(); + l++; + } - case 'r': cursorX = (destRectangle.getWidth() - textwidth); - lineend = destRectangle.getWidth(); + if ((textwidth + wordwidth) <= destRectangle.getWidth()) + textwidth += (wordwidth); + else break; + } - default: cursorX = 0; - lineend = textwidth; - break; - } + if ((textwidth == 0) && (wordwidth > destRectangle.getWidth())) textwidth = destRectangle.getWidth(); - carriagreturn = false; + switch (justify) + { + case 'c': + cursorX = (destRectangle.getWidth() - textwidth) / 2; + lineend = destRectangle.getWidth() - cursorX; + break; + + case 'r': + cursorX = (destRectangle.getWidth() - textwidth); + lineend = destRectangle.getWidth(); + break; + + default: + cursorX = 0; + lineend = textwidth; + break; } - //abort - net enough space to draw - if ((cursorY + charheight) > destRectangle.getHeight()) - goto stop; + carriagreturn = false; + } - //draw pixel by pixel - for (size_t i = 0; i < GlyphTexCoords[strindex].getHeight(); i++) - for (size_t j = 0; j < GlyphTexCoords[strindex].getWidth(); j++) - { - float alpha = color.a * (fontData[(i + GlyphTexCoords[strindex].top) * fontRowPitchBytes + (j + GlyphTexCoords[strindex].left) * fontPixelSize + 1] / 255.0); - float invalpha = 1.0 - alpha; - size_t offset = (i + cursorY) * destRowPitchBytes + (j + cursorX) * destPixelSize; - ColourValue pix; - PixelUtil::unpackColour(&pix, destPb.format, &destData[offset]); - pix = (pix * invalpha) + (color * alpha); - PixelUtil::packColour(pix, destPb.format, &destData[offset]); - } + // abort - net enough space to draw + if ((cursorY + charheight) > destRectangle.getHeight()) goto stop; + + // draw pixel by pixel + for (size_t i = 0; i < GlyphTexCoords[strindex].getHeight(); i++) + for (size_t j = 0; j < GlyphTexCoords[strindex].getWidth(); j++) + { + float alpha = color.a * (fontData[(i + GlyphTexCoords[strindex].top) * fontRowPitchBytes + + (j + GlyphTexCoords[strindex].left) * fontPixelSize + 1] / + 255.0); + float invalpha = 1.0 - alpha; + size_t offset = (i + cursorY) * destRowPitchBytes + (j + cursorX) * destPixelSize; + ColourValue pix; + PixelUtil::unpackColour(&pix, destPb.format, &destData[offset]); + pix = (pix * invalpha) + (color * alpha); + PixelUtil::packColour(pix, destPb.format, &destData[offset]); + } - cursorX += GlyphTexCoords[strindex].getWidth(); - }//default - }//switch - }//for + cursorX += GlyphTexCoords[strindex].getWidth(); + } // default + } // switch + } // for stop: delete[] GlyphTexCoords; diff --git a/source/main/utils/WriteTextToTexture.h b/source/main/utils/WriteTextToTexture.h index a5e1afafc8..92eb1ab965 100644 --- a/source/main/utils/WriteTextToTexture.h +++ b/source/main/utils/WriteTextToTexture.h @@ -27,7 +27,7 @@ /** * @brief Saves a texture to the disk. - * + * * @param TextureToSave The texture to save. * @param filename The file-name. */ @@ -35,7 +35,7 @@ void SaveImage(Ogre::TexturePtr TextureToSave, Ogre::String filename); /** * @brief Writes a string onto a texture. - * + * * @param str The string to write onto the texture. * @param destTexture The texture to write the string on. * @param destRectangle The Area to write in. @@ -46,4 +46,6 @@ void SaveImage(Ogre::TexturePtr TextureToSave, Ogre::String filename); * @param justify 'l' = left aligned, 'c' = centered, 'r' = right aligned. * @param wordwrap if true the line will only be wrapped after a word. */ -void WriteToTexture(const Ogre::String& str, Ogre::TexturePtr destTexture, Ogre::Box destRectangle, Ogre::Font* font, const Ogre::ColourValue& color, int fontSize = 15, int fontDPI = 400, char justify = 'l', bool wordwrap = true); +void WriteToTexture(const Ogre::String &str, Ogre::TexturePtr destTexture, Ogre::Box destRectangle, Ogre::Font *font, + const Ogre::ColourValue &color, int fontSize = 15, int fontDPI = 400, char justify = 'l', + bool wordwrap = true); diff --git a/source/main/utils/ZeroedMemoryAllocator.h b/source/main/utils/ZeroedMemoryAllocator.h index 4e4271783e..89d176fa5c 100644 --- a/source/main/utils/ZeroedMemoryAllocator.h +++ b/source/main/utils/ZeroedMemoryAllocator.h @@ -29,7 +29,7 @@ */ class ZeroedMemoryAllocator { -public: + public: ZeroedMemoryAllocator() { } @@ -43,7 +43,7 @@ class ZeroedMemoryAllocator * @param size the amount of bytes to allocate. * @return the given amounts of bytes zeroed. */ - inline void* operator new(size_t size) + inline void *operator new(size_t size) { return calloc(size, sizeof(unsigned char)); } @@ -53,7 +53,7 @@ class ZeroedMemoryAllocator * @param size the amount of bytes to allocate. * @return the given amounts of bytes zeroed. */ - inline void* operator new[](size_t size) + inline void *operator new[](size_t size) { return calloc(size, sizeof(unsigned char)); } @@ -62,7 +62,7 @@ class ZeroedMemoryAllocator * Memory release for a single class instance. * @param ptr the memory to free. */ - inline void operator delete(void* ptr) + inline void operator delete(void *ptr) { free(ptr); } @@ -71,9 +71,8 @@ class ZeroedMemoryAllocator * Memory release for an array of class instances. * @param ptr the memory to free. */ - inline void operator delete[](void* ptr) + inline void operator delete[](void *ptr) { free(ptr); } }; - diff --git a/source/main/utils/utf8/checked.h b/source/main/utils/utf8/checked.h index b0013377fe..7e2a3572e3 100644 --- a/source/main/utils/utf8/checked.h +++ b/source/main/utils/utf8/checked.h @@ -24,73 +24,109 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #include "core.h" + #include namespace utf8 { // Base for the exceptions that may be thrown from the library - class exception : public ::std::exception { + class exception : public ::std::exception + { }; // Exceptions that may be thrown from the library functions. - class invalid_code_point : public exception { + class invalid_code_point : public exception + { uint32_t cp; - public: - invalid_code_point(uint32_t cp) : cp(cp) {} - virtual const char* what() const throw() { return "Invalid code point"; } - uint32_t code_point() const {return cp;} + + public: + invalid_code_point(uint32_t cp) : cp(cp) + { + } + virtual const char *what() const throw() + { + return "Invalid code point"; + } + uint32_t code_point() const + { + return cp; + } }; - class invalid_utf8 : public exception { + class invalid_utf8 : public exception + { uint8_t u8; - public: - invalid_utf8 (uint8_t u) : u8(u) {} - virtual const char* what() const throw() { return "Invalid UTF-8"; } - uint8_t utf8_octet() const {return u8;} + + public: + invalid_utf8(uint8_t u) : u8(u) + { + } + virtual const char *what() const throw() + { + return "Invalid UTF-8"; + } + uint8_t utf8_octet() const + { + return u8; + } }; - class invalid_utf16 : public exception { + class invalid_utf16 : public exception + { uint16_t u16; - public: - invalid_utf16 (uint16_t u) : u16(u) {} - virtual const char* what() const throw() { return "Invalid UTF-16"; } - uint16_t utf16_word() const {return u16;} + + public: + invalid_utf16(uint16_t u) : u16(u) + { + } + virtual const char *what() const throw() + { + return "Invalid UTF-16"; + } + uint16_t utf16_word() const + { + return u16; + } }; - class not_enough_room : public exception { - public: - virtual const char* what() const throw() { return "Not enough space"; } + class not_enough_room : public exception + { + public: + virtual const char *what() const throw() + { + return "Not enough space"; + } }; /// The library API - functions intended to be called by the users - template - octet_iterator append(uint32_t cp, octet_iterator result) + template octet_iterator append(uint32_t cp, octet_iterator result) { - if (!utf8::internal::is_code_point_valid(cp)) - throw invalid_code_point(cp); + if (!utf8::internal::is_code_point_valid(cp)) throw invalid_code_point(cp); - if (cp < 0x80) // one octet + if (cp < 0x80) // one octet *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); + else if (cp < 0x800) + { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); + else if (cp < 0x10000) + { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); + else + { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); } return result; } @@ -98,31 +134,33 @@ namespace utf8 template output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) { - while (start != end) { - octet_iterator sequence_start = start; - internal::utf_error err_code = utf8::internal::validate_next(start, end); - switch (err_code) { - case internal::UTF8_OK : - for (octet_iterator it = sequence_start; it != start; ++it) - *out++ = *it; - break; - case internal::NOT_ENOUGH_ROOM: - // RoR patch // not_enough_room means 'incomplete Unicode character at the end of string'. - // RoR patch // just append replacement character and return early. - return utf8::append (replacement, out); - case internal::INVALID_LEAD: - out = utf8::append (replacement, out); - ++start; - break; - case internal::INCOMPLETE_SEQUENCE: - case internal::OVERLONG_SEQUENCE: - case internal::INVALID_CODE_POINT: - out = utf8::append (replacement, out); + while (start != end) + { + octet_iterator sequence_start = start; + internal::utf_error err_code = utf8::internal::validate_next(start, end); + switch (err_code) + { + case internal::UTF8_OK: + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + // RoR patch // not_enough_room means 'incomplete Unicode character at the end of string'. + // RoR patch // just append replacement character and return early. + return utf8::append(replacement, out); + case internal::INVALID_LEAD: + out = utf8::append(replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + out = utf8::append(replacement, out); + ++start; + // just one replacement mark for the sequence + while (start != end && utf8::internal::is_trail(*start)) ++start; - // just one replacement mark for the sequence - while (start != end && utf8::internal::is_trail(*start)) - ++start; - break; + break; } } return out; @@ -135,69 +173,58 @@ namespace utf8 return utf8::replace_invalid(start, end, out, replacement_marker); } - template - uint32_t next(octet_iterator& it, octet_iterator end) + template uint32_t next(octet_iterator &it, octet_iterator end) { - uint32_t cp = 0; + uint32_t cp = 0; internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); - switch (err_code) { - case internal::UTF8_OK : - break; - case internal::NOT_ENOUGH_ROOM : - throw not_enough_room(); - case internal::INVALID_LEAD : - case internal::INCOMPLETE_SEQUENCE : - case internal::OVERLONG_SEQUENCE : - throw invalid_utf8(*it); - case internal::INVALID_CODE_POINT : - throw invalid_code_point(cp); + switch (err_code) + { + case internal::UTF8_OK: break; + case internal::NOT_ENOUGH_ROOM: throw not_enough_room(); + case internal::INVALID_LEAD: + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT: throw invalid_code_point(cp); } return cp; } - template - uint32_t peek_next(octet_iterator it, octet_iterator end) + template uint32_t peek_next(octet_iterator it, octet_iterator end) { return utf8::next(it, end); } - template - uint32_t prior(octet_iterator& it, octet_iterator start) + template uint32_t prior(octet_iterator &it, octet_iterator start) { // can't do much if it == start - if (it == start) - throw not_enough_room(); + if (it == start) throw not_enough_room(); octet_iterator end = it; // Go back until we hit either a lead octet or start while (utf8::internal::is_trail(*(--it))) - if (it == start) - throw invalid_utf8(*it); // error - no lead byte in the sequence + if (it == start) throw invalid_utf8(*it); // error - no lead byte in the sequence return utf8::peek_next(it, end); } /// Deprecated in versions that include "prior" - template - uint32_t previous(octet_iterator& it, octet_iterator pass_start) + template uint32_t previous(octet_iterator &it, octet_iterator pass_start) { octet_iterator end = it; while (utf8::internal::is_trail(*(--it))) - if (it == pass_start) - throw invalid_utf8(*it); // error - no lead byte in the sequence + if (it == pass_start) throw invalid_utf8(*it); // error - no lead byte in the sequence octet_iterator temp = it; return utf8::next(temp, end); } template - void advance (octet_iterator& it, distance_type n, octet_iterator end) + void advance(octet_iterator &it, distance_type n, octet_iterator end) { for (distance_type i = 0; i < n; ++i) utf8::next(it, end); } template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) + typename std::iterator_traits::difference_type distance(octet_iterator first, octet_iterator last) { typename std::iterator_traits::difference_type dist; for (dist = 0; first < last; ++dist) @@ -206,13 +233,16 @@ namespace utf8 } template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result) { - while (start != end) { + while (start != end) + { uint32_t cp = utf8::internal::mask16(*start++); // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - if (start != end) { + if (utf8::internal::is_lead_surrogate(cp)) + { + if (start != end) + { uint32_t trail_surrogate = utf8::internal::mask16(*start++); if (utf8::internal::is_trail_surrogate(trail_surrogate)) cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; @@ -221,7 +251,6 @@ namespace utf8 } else throw invalid_utf16(static_cast(cp)); - } // Lone trail surrogate else if (utf8::internal::is_trail_surrogate(cp)) @@ -233,12 +262,14 @@ namespace utf8 } template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result) { - while (start != end) { + while (start != end) + { uint32_t cp = utf8::next(start, end); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + if (cp > 0xffff) + { // make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); } else @@ -248,7 +279,7 @@ namespace utf8 } template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + octet_iterator utf32to8(u32bit_iterator start, u32bit_iterator end, octet_iterator result) { while (start != end) result = utf8::append(*(start++), result); @@ -257,7 +288,7 @@ namespace utf8 } template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + u32bit_iterator utf8to32(octet_iterator start, octet_iterator end, u32bit_iterator result) { while (start != end) (*result++) = utf8::next(start, end); @@ -266,64 +297,65 @@ namespace utf8 } // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - octet_iterator range_start; - octet_iterator range_end; + template class iterator : public std::iterator + { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: - iterator () {} - explicit iterator (const octet_iterator& octet_it, - const octet_iterator& range_start, - const octet_iterator& range_end) : - it(octet_it), range_start(range_start), range_end(range_end) - { - if (it < range_start || it > range_end) - throw std::out_of_range("Invalid utf-8 iterator position"); - } - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::next(temp, range_end); - } - bool operator == (const iterator& rhs) const - { - if (range_start != rhs.range_start || range_end != rhs.range_end) - throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - utf8::next(it, range_end); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - utf8::next(it, range_end); - return temp; - } - iterator& operator -- () - { - utf8::prior(it, range_start); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::prior(it, range_start); - return temp; - } + iterator() + { + } + explicit iterator(const octet_iterator &octet_it, const octet_iterator &range_start, const octet_iterator &range_end) + : it(octet_it), range_start(range_start), range_end(range_end) + { + if (it < range_start || it > range_end) throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base() const + { + return it; + } + uint32_t operator*() const + { + octet_iterator temp = it; + return utf8::next(temp, range_end); + } + bool operator==(const iterator &rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator!=(const iterator &rhs) const + { + return !(operator==(rhs)); + } + iterator &operator++() + { + utf8::next(it, range_end); + return *this; + } + iterator operator++(int) + { + iterator temp = *this; + utf8::next(it, range_end); + return temp; + } + iterator &operator--() + { + utf8::prior(it, range_start); + return *this; + } + iterator operator--(int) + { + iterator temp = *this; + utf8::prior(it, range_start); + return temp; + } }; // class iterator } // namespace utf8 -#endif //header guard - - +#endif // header guard diff --git a/source/main/utils/utf8/core.h b/source/main/utils/utf8/core.h index 693d388c07..463a5912b7 100644 --- a/source/main/utils/utf8/core.h +++ b/source/main/utils/utf8/core.h @@ -24,7 +24,6 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 @@ -35,295 +34,270 @@ namespace utf8 // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers // You may need to change them to match your system. // These typedefs have the same names as ones from cstdint, or boost/cstdint - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; -// Helper code - not intended to be directly called by the library users. May be changed at any time -namespace internal -{ - // Unicode constants - // Leading (high) surrogates: 0xd800 - 0xdbff - // Trailing (low) surrogates: 0xdc00 - 0xdfff - const uint16_t LEAD_SURROGATE_MIN = 0xd800u; - const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; - const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; - const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; - const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); - const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; - - // Maximum valid value for a Unicode code point - const uint32_t CODE_POINT_MAX = 0x0010ffffu; - - template - inline uint8_t mask8(octet_type oc) - { - return static_cast(0xff & oc); - } - template - inline uint16_t mask16(u16_type oc) + // Helper code - not intended to be directly called by the library users. May be changed at any time + namespace internal { - return static_cast(0xffff & oc); - } - template - inline bool is_trail(octet_type oc) - { - return ((utf8::internal::mask8(oc) >> 6) == 0x2); - } - - template - inline bool is_lead_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); - } - - template - inline bool is_trail_surrogate(u16 cp) - { - return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template inline uint8_t mask8(octet_type oc) + { + return static_cast(0xff & oc); + } + template inline uint16_t mask16(u16_type oc) + { + return static_cast(0xffff & oc); + } + template inline bool is_trail(octet_type oc) + { + return ((utf8::internal::mask8(oc) >> 6) == 0x2); + } - template - inline bool is_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } + template inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } - template - inline bool is_code_point_valid(u32 cp) - { - return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); - } + template inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } - template - inline typename std::iterator_traits::difference_type - sequence_length(octet_iterator lead_it) - { - uint8_t lead = utf8::internal::mask8(*lead_it); - if (lead < 0x80) - return 1; - else if ((lead >> 5) == 0x6) - return 2; - else if ((lead >> 4) == 0xe) - return 3; - else if ((lead >> 3) == 0x1e) - return 4; - else - return 0; - } + template inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } - template - inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) - { - if (cp < 0x80) { - if (length != 1) - return true; + template inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); } - else if (cp < 0x800) { - if (length != 2) - return true; + + template + inline typename std::iterator_traits::difference_type sequence_length(octet_iterator lead_it) + { + uint8_t lead = utf8::internal::mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; } - else if (cp < 0x10000) { - if (length != 3) - return true; + + template inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) + { + if (cp < 0x80) + { + if (length != 1) return true; + } + else if (cp < 0x800) + { + if (length != 2) return true; + } + else if (cp < 0x10000) + { + if (length != 3) return true; + } + + return false; } - return false; - } + enum utf_error + { + UTF8_OK, + NOT_ENOUGH_ROOM, + INVALID_LEAD, + INCOMPLETE_SEQUENCE, + OVERLONG_SEQUENCE, + INVALID_CODE_POINT + }; - enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + /// Helper for get_sequence_x + template utf_error increase_safely(octet_iterator &it, octet_iterator end) + { + if (++it == end) return NOT_ENOUGH_ROOM; - /// Helper for get_sequence_x - template - utf_error increase_safely(octet_iterator& it, octet_iterator end) - { - if (++it == end) - return NOT_ENOUGH_ROOM; + if (!utf8::internal::is_trail(*it)) return INCOMPLETE_SEQUENCE; - if (!utf8::internal::is_trail(*it)) - return INCOMPLETE_SEQUENCE; - - return UTF8_OK; + return UTF8_OK; + } + +#define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) \ + { \ + utf_error ret = increase_safely(IT, END); \ + if (ret != UTF8_OK) return ret; \ } - #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} + /// get_sequence_x functions decode utf-8 sequences of the length x + template utf_error get_sequence_1(octet_iterator &it, octet_iterator end, uint32_t &code_point) + { + if (it == end) return NOT_ENOUGH_ROOM; - /// get_sequence_x functions decode utf-8 sequences of the length x - template - utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; + code_point = utf8::internal::mask8(*it); - code_point = utf8::internal::mask8(*it); + return UTF8_OK; + } - return UTF8_OK; - } + template utf_error get_sequence_2(octet_iterator &it, octet_iterator end, uint32_t &code_point) + { + if (it == end) return NOT_ENOUGH_ROOM; - template - utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); + code_point = utf8::internal::mask8(*it); - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); + code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); - return UTF8_OK; - } + return UTF8_OK; + } - template - utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); + template utf_error get_sequence_3(octet_iterator &it, octet_iterator end, uint32_t &code_point) + { + if (it == end) return NOT_ENOUGH_ROOM; - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + code_point = utf8::internal::mask8(*it); - code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - code_point += (*it) & 0x3f; + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - return UTF8_OK; - } + code_point += (*it) & 0x3f; - template - utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); + return UTF8_OK; + } - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + template utf_error get_sequence_4(octet_iterator &it, octet_iterator end, uint32_t &code_point) + { + if (it == end) return NOT_ENOUGH_ROOM; - code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + code_point = utf8::internal::mask8(*it); - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; + code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - code_point += (*it) & 0x3f; + code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; - return UTF8_OK; - } + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + code_point += (*it) & 0x3f; - template - utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - // Save the original value of it so we can go back in case of failure - // Of course, it does not make much sense with i.e. stream iterators - octet_iterator original_it = it; - - uint32_t cp = 0; - // Determine the sequence length based on the lead octet - typedef typename std::iterator_traits::difference_type octet_difference_type; - const octet_difference_type length = utf8::internal::sequence_length(it); - - // Get trail octets and calculate the code point - utf_error err = UTF8_OK; - switch (length) { - case 0: - return INVALID_LEAD; - case 1: - err = utf8::internal::get_sequence_1(it, end, cp); - break; - case 2: - err = utf8::internal::get_sequence_2(it, end, cp); - break; - case 3: - err = utf8::internal::get_sequence_3(it, end, cp); - break; - case 4: - err = utf8::internal::get_sequence_4(it, end, cp); - break; + return UTF8_OK; } - if (err == UTF8_OK) { - // Decoding succeeded. Now, security checks... - if (utf8::internal::is_code_point_valid(cp)) { - if (!utf8::internal::is_overlong_sequence(cp, length)){ - // Passed! Return here. - code_point = cp; - ++it; - return UTF8_OK; +#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + + template utf_error validate_next(octet_iterator &it, octet_iterator end, uint32_t &code_point) + { + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits::difference_type octet_difference_type; + const octet_difference_type length = utf8::internal::sequence_length(it); + + // Get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) + { + case 0: return INVALID_LEAD; + case 1: err = utf8::internal::get_sequence_1(it, end, cp); break; + case 2: err = utf8::internal::get_sequence_2(it, end, cp); break; + case 3: err = utf8::internal::get_sequence_3(it, end, cp); break; + case 4: err = utf8::internal::get_sequence_4(it, end, cp); break; + } + + if (err == UTF8_OK) + { + // Decoding succeeded. Now, security checks... + if (utf8::internal::is_code_point_valid(cp)) + { + if (!utf8::internal::is_overlong_sequence(cp, length)) + { + // Passed! Return here. + code_point = cp; + ++it; + return UTF8_OK; + } + else + err = OVERLONG_SEQUENCE; } else - err = OVERLONG_SEQUENCE; + err = INVALID_CODE_POINT; } - else - err = INVALID_CODE_POINT; - } - // Failure branch - restore the original value of the iterator - it = original_it; - return err; - } + // Failure branch - restore the original value of the iterator + it = original_it; + return err; + } - template - inline utf_error validate_next(octet_iterator& it, octet_iterator end) { - uint32_t ignored; - return utf8::internal::validate_next(it, end, ignored); - } + template inline utf_error validate_next(octet_iterator &it, octet_iterator end) + { + uint32_t ignored; + return utf8::internal::validate_next(it, end, ignored); + } -} // namespace internal + } // namespace internal /// The library API - functions intended to be called by the users // Byte order mark const uint8_t bom[] = {0xef, 0xbb, 0xbf}; - template - octet_iterator find_invalid(octet_iterator start, octet_iterator end) + template octet_iterator find_invalid(octet_iterator start, octet_iterator end) { octet_iterator result = start; - while (result != end) { + while (result != end) + { utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); - if (err_code != internal::UTF8_OK) - return result; + if (err_code != internal::UTF8_OK) return result; } return result; } - template - inline bool is_valid(octet_iterator start, octet_iterator end) + template inline bool is_valid(octet_iterator start, octet_iterator end) { return (utf8::find_invalid(start, end) == end); } - template - inline bool starts_with_bom (octet_iterator it, octet_iterator end) + template inline bool starts_with_bom(octet_iterator it, octet_iterator end) { - return ( - ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && - ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && - ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) - ); + return (((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && + ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && + ((it != end) && (utf8::internal::mask8(*it)) == bom[2])); } - - //Deprecated in release 2.3 - template - inline bool is_bom (octet_iterator it) + + // Deprecated in release 2.3 + template inline bool is_bom(octet_iterator it) { - return ( - (utf8::internal::mask8(*it++)) == bom[0] && - (utf8::internal::mask8(*it++)) == bom[1] && - (utf8::internal::mask8(*it)) == bom[2] - ); + return ((utf8::internal::mask8(*it++)) == bom[0] && (utf8::internal::mask8(*it++)) == bom[1] && + (utf8::internal::mask8(*it)) == bom[2]); } } // namespace utf8 #endif // header guard - - diff --git a/source/main/utils/utf8/unchecked.h b/source/main/utils/utf8/unchecked.h index cb2427166b..30bffcaa14 100644 --- a/source/main/utils/utf8/unchecked.h +++ b/source/main/utils/utf8/unchecked.h @@ -24,7 +24,6 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 @@ -32,122 +31,123 @@ DEALINGS IN THE SOFTWARE. namespace utf8 { - namespace unchecked + namespace unchecked { - template - octet_iterator append(uint32_t cp, octet_iterator result) + template octet_iterator append(uint32_t cp, octet_iterator result) { - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) + { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) + { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); + else + { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); } return result; } - template - uint32_t next(octet_iterator& it) + template uint32_t next(octet_iterator &it) { - uint32_t cp = utf8::internal::mask8(*it); + uint32_t cp = utf8::internal::mask8(*it); typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); - switch (length) { - case 1: - break; - case 2: - it++; - cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); - break; - case 3: - ++it; - cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - ++it; - cp += (*it) & 0x3f; - break; - case 4: - ++it; - cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - ++it; - cp += (utf8::internal::mask8(*it) << 6) & 0xfff; - ++it; - cp += (*it) & 0x3f; - break; + switch (length) + { + case 1: break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (utf8::internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; } ++it; - return cp; + return cp; } - template - uint32_t peek_next(octet_iterator it) + template uint32_t peek_next(octet_iterator it) { - return utf8::unchecked::next(it); + return utf8::unchecked::next(it); } - template - uint32_t prior(octet_iterator& it) + template uint32_t prior(octet_iterator &it) { - while (utf8::internal::is_trail(*(--it))) ; + while (utf8::internal::is_trail(*(--it))) + ; octet_iterator temp = it; return utf8::unchecked::next(temp); } // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) - template - inline uint32_t previous(octet_iterator& it) + template inline uint32_t previous(octet_iterator &it) { return utf8::unchecked::prior(it); } - template - void advance (octet_iterator& it, distance_type n) + template void advance(octet_iterator &it, distance_type n) { for (distance_type i = 0; i < n; ++i) utf8::unchecked::next(it); } template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) + typename std::iterator_traits::difference_type distance(octet_iterator first, octet_iterator last) { typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) + for (dist = 0; first < last; ++dist) utf8::unchecked::next(first); return dist; } template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { + octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) + { uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) + { uint32_t trail_surrogate = utf8::internal::mask16(*start++); - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; } result = utf8::unchecked::append(cp, result); } - return result; + return result; } template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result) { - while (start < end) { + while (start < end) + { uint32_t cp = utf8::unchecked::next(start); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + if (cp > 0xffff) + { // make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); } else @@ -157,7 +157,7 @@ namespace utf8 } template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + octet_iterator utf32to8(u32bit_iterator start, u32bit_iterator end, octet_iterator result) { while (start != end) result = utf8::unchecked::append(*(start++), result); @@ -166,7 +166,7 @@ namespace utf8 } template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + u32bit_iterator utf8to32(octet_iterator start, octet_iterator end, u32bit_iterator result) { while (start < end) (*result++) = utf8::unchecked::next(start); @@ -175,54 +175,60 @@ namespace utf8 } // The iterator class - template - class iterator : public std::iterator { + template class iterator : public std::iterator + { octet_iterator it; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + + public: + iterator() + { + } + explicit iterator(const octet_iterator &octet_it) : it(octet_it) + { + } // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const + octet_iterator base() const + { + return it; + } + uint32_t operator*() const { octet_iterator temp = it; return utf8::unchecked::next(temp); } - bool operator == (const iterator& rhs) const - { + bool operator==(const iterator &rhs) const + { return (it == rhs.it); } - bool operator != (const iterator& rhs) const + bool operator!=(const iterator &rhs) const { - return !(operator == (rhs)); + return !(operator==(rhs)); } - iterator& operator ++ () + iterator &operator++() { ::std::advance(it, utf8::internal::sequence_length(it)); return *this; } - iterator operator ++ (int) + iterator operator++(int) { iterator temp = *this; ::std::advance(it, utf8::internal::sequence_length(it)); return temp; - } - iterator& operator -- () + } + iterator &operator--() { utf8::unchecked::prior(it); return *this; } - iterator operator -- (int) + iterator operator--(int) { iterator temp = *this; utf8::unchecked::prior(it); return temp; } - }; // class iterator - - } // namespace utf8::unchecked -} // namespace utf8 + }; // class iterator + } // namespace unchecked +} // namespace utf8 #endif // header guard - diff --git a/tools/format-files.sh b/tools/format-files.sh new file mode 100644 index 0000000000..cf5833ac11 --- /dev/null +++ b/tools/format-files.sh @@ -0,0 +1,9 @@ + +#!/usr/bin/env bash + +if ! [ -x "$(command -v clang-format)" ]; then + printf "\e[31mError: the command clang-format was not found\e[0m" + exit +fi + +find .. -regex '.*\.\(h\|cpp\)' -not -path '*/plugins/*' -exec clang-format -style=file -i {} \; \ No newline at end of file