diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0012b1f..38d21f0f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -218,6 +218,7 @@ set(BASE_SOURCES script/scriptfunc.cpp sound/sound.cpp sound/sound_type.cpp + ui/debug_menu.cpp ui/displayinfo.cpp ui/displaytext.cpp ui/object_interface.cpp diff --git a/src/app/app.cpp b/src/app/app.cpp index 5547c453..19a48306 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -833,7 +833,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::DeviceConfig &newConfig) m_device->ConfigChanged(m_deviceConfig); - m_engine->ResetAfterVideoConfigChanged(); + m_eventQueue->AddEvent(Event(EVENT_RESOLUTION_CHANGED)); return true; } diff --git a/src/app/input.cpp b/src/app/input.cpp index ca7aff46..ed1fdf93 100644 --- a/src/app/input.cpp +++ b/src/app/input.cpp @@ -332,7 +332,7 @@ InputSlot CInput::FindBinding(unsigned int key) void CInput::SaveKeyBindings() { std::stringstream key; - CConfigFile::GetInstancePointer()->SetStringProperty("Keybindings", "_Version", "SDL2"); + GetConfigFile().SetStringProperty("Keybindings", "_Version", "SDL2"); for (int i = 0; i < INPUT_SLOT_MAX; i++) { InputBinding b = GetInputBinding(static_cast(i)); @@ -341,30 +341,30 @@ void CInput::SaveKeyBindings() key.str(""); key << b.primary << " " << b.secondary; - CConfigFile::GetInstancePointer()->SetStringProperty("Keybindings", m_keyTable[static_cast(i)], key.str()); + GetConfigFile().SetStringProperty("Keybindings", m_keyTable[static_cast(i)], key.str()); } for (int i = 0; i < JOY_AXIS_SLOT_MAX; i++) { JoyAxisBinding b = GetJoyAxisBinding(static_cast(i)); - CConfigFile::GetInstancePointer()->SetIntProperty("Setup", "JoystickAxisBinding"+boost::lexical_cast(i), b.axis); - CConfigFile::GetInstancePointer()->SetIntProperty("Setup", "JoystickAxisInvert"+boost::lexical_cast(i), b.invert); + GetConfigFile().SetIntProperty("Setup", "JoystickAxisBinding"+boost::lexical_cast(i), b.axis); + GetConfigFile().SetIntProperty("Setup", "JoystickAxisInvert"+boost::lexical_cast(i), b.invert); } - CConfigFile::GetInstancePointer()->SetFloatProperty("Setup", "JoystickDeadzone", GetJoystickDeadzone()); + GetConfigFile().SetFloatProperty("Setup", "JoystickDeadzone", GetJoystickDeadzone()); } void CInput::LoadKeyBindings() { std::stringstream skey; std::string keys; - if (CConfigFile::GetInstancePointer()->GetStringProperty("Keybindings", "_Version", keys) && keys == "SDL2") // Keybindings from SDL1.2 are incompatible with SDL2 !! + if (GetConfigFile().GetStringProperty("Keybindings", "_Version", keys) && keys == "SDL2") // Keybindings from SDL1.2 are incompatible with SDL2 !! { for (int i = 0; i < INPUT_SLOT_MAX; i++) { InputBinding b; - if (!CConfigFile::GetInstancePointer()->GetStringProperty("Keybindings", m_keyTable[static_cast(i)], keys)) + if (!GetConfigFile().GetStringProperty("Keybindings", m_keyTable[static_cast(i)], keys)) continue; skey.clear(); skey.str(keys); @@ -380,17 +380,17 @@ void CInput::LoadKeyBindings() { JoyAxisBinding b; - if (!CConfigFile::GetInstancePointer()->GetIntProperty("Setup", "JoystickAxisBinding"+boost::lexical_cast(i), b.axis)) + if (!GetConfigFile().GetIntProperty("Setup", "JoystickAxisBinding"+boost::lexical_cast(i), b.axis)) continue; int x = 0; - CConfigFile::GetInstancePointer()->GetIntProperty("Setup", "JoystickAxisInvert"+boost::lexical_cast(i), x); // If doesn't exist, use default (0) + GetConfigFile().GetIntProperty("Setup", "JoystickAxisInvert"+boost::lexical_cast(i), x); // If doesn't exist, use default (0) b.invert = (x != 0); SetJoyAxisBinding(static_cast(i), b); } float deadzone; - if (CConfigFile::GetInstancePointer()->GetFloatProperty("Setup", "JoystickDeadzone", deadzone)) + if (GetConfigFile().GetFloatProperty("Setup", "JoystickDeadzone", deadzone)) SetJoystickDeadzone(deadzone); } diff --git a/src/common/config_file.h b/src/common/config_file.h index 02a000c8..0ed8e19f 100644 --- a/src/common/config_file.h +++ b/src/common/config_file.h @@ -107,8 +107,8 @@ private: bool m_loaded; }; -//! Global function to get profile instance +//! Global function to get config file instance inline CConfigFile & GetConfigFile() { - return *CConfigFile::GetInstancePointer(); + return CConfigFile::GetInstance(); } diff --git a/src/common/event.cpp b/src/common/event.cpp index ccd7fe8a..49b5218d 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -68,6 +68,8 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_UPDINTERFACE] = "EVENT_UPDINTERFACE"; + EVENT_TYPE_TEXT[EVENT_RESOLUTION_CHANGED]= "EVENT_RESOLUTION_CHANGED"; + EVENT_TYPE_TEXT[EVENT_RELOAD_TEXTURES] = "EVENT_RELOAD_TEXTURES"; EVENT_TYPE_TEXT[EVENT_WIN] = "EVENT_WIN"; EVENT_TYPE_TEXT[EVENT_LOST] = "EVENT_LOST"; diff --git a/src/common/event.h b/src/common/event.h index 50fb0c98..d3f22b0c 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -95,6 +95,10 @@ enum EventType //! Event sent on user quit request EVENT_QUIT = 20, EVENT_UPDINTERFACE = 21, + //! Event sent on resolution change + EVENT_RESOLUTION_CHANGED = 22, + //! Event sent when textures have to be reloaded + EVENT_RELOAD_TEXTURES = 23, EVENT_WIN = 30, EVENT_LOST = 31, @@ -145,7 +149,7 @@ enum EventType EVENT_WINDOW4 = 84, //!< CDisplayInfo EVENT_WINDOW5 = 85, //!< all menu windows EVENT_WINDOW6 = 86, //!< code battle interface - EVENT_WINDOW7 = 87, //!< (unused) + EVENT_WINDOW7 = 87, //!< debug interface EVENT_WINDOW8 = 88, //!< (unused) EVENT_WINDOW9 = 89, //!< CMainDialog and CStudio file selector @@ -376,6 +380,31 @@ enum EventType EVENT_CMD = 800, EVENT_SPEED = 801, + EVENT_DBG_STATS = 850, + EVENT_DBG_SPAWN_OBJ = 851, + EVENT_DBG_TELEPORT = 852, + EVENT_DBG_LIGHTNING = 853, + EVENT_DBG_RESOURCES = 854, + EVENT_DBG_GOTO = 855, + EVENT_DBG_CRASHSPHERES = 856, + EVENT_DBG_LIGHTS = 857, + EVENT_DBG_LIGHTS_DUMP = 858, + + EVENT_SPAWN_CANCEL = 860, + EVENT_SPAWN_ME = 861, + EVENT_SPAWN_WHEELEDGRABBER = 862, + EVENT_SPAWN_WHEELEDSHOOTER = 863, + EVENT_SPAWN_PHAZERSHOOTER = 864, + EVENT_SPAWN_BOTFACTORY = 865, + EVENT_SPAWN_CONVERTER = 866, + EVENT_SPAWN_DERRICK = 867, + EVENT_SPAWN_POWERSTATION= 868, + EVENT_SPAWN_TITANIUM = 869, + EVENT_SPAWN_TITANIUMORE = 870, + EVENT_SPAWN_URANIUMORE = 871, + EVENT_SPAWN_POWERCELL = 872, + EVENT_SPAWN_NUCLEARCELL = 873, + EVENT_HYPER_PREV = 900, EVENT_HYPER_NEXT = 901, EVENT_HYPER_HOME = 902, diff --git a/src/graphics/core/nulldevice.cpp b/src/graphics/core/nulldevice.cpp index 5ab4ec08..ad483ede 100644 --- a/src/graphics/core/nulldevice.cpp +++ b/src/graphics/core/nulldevice.cpp @@ -27,9 +27,6 @@ namespace Gfx CNullDevice::CNullDevice() { - m_matrix = Math::Matrix(); - m_material = Material(); - m_light = Light(); } CNullDevice::~CNullDevice() diff --git a/src/graphics/core/nulldevice.h b/src/graphics/core/nulldevice.h index 68f2effc..3a78ea83 100644 --- a/src/graphics/core/nulldevice.h +++ b/src/graphics/core/nulldevice.h @@ -17,11 +17,6 @@ * along with this program. If not, see http://gnu.org/licenses */ -/** - * \file graphics/core/device.h - * \brief Abstract graphics device - CDevice class and related structs/enums - */ - #pragma once #include "graphics/core/device.h" @@ -38,7 +33,6 @@ namespace Gfx /** * \class CNullDevice * \brief Device implementation that doesn't render anything - * */ class CNullDevice : public CDevice { @@ -160,11 +154,6 @@ public: int GetMaxTextureSize() override; bool IsFramebufferSupported() override; - -private: - Math::Matrix m_matrix; - Material m_material; - Light m_light; }; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index a66f8063..5b2fc6e5 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -359,8 +359,6 @@ void CEngine::ResetAfterVideoConfigChanged() m_size = m_app->GetVideoConfig().size; m_mouseSize = Math::Point(0.04f, 0.04f * (static_cast(m_size.x) / static_cast(m_size.y))); - CRobotMain::GetInstancePointer()->ResetAfterVideoConfigChanged(); //TODO: Remove cross-reference to CRobotMain - // Update the camera projection matrix for new aspect ratio SetFocus(m_focus); @@ -373,13 +371,18 @@ void CEngine::ReloadAllTextures() FlushTextureCache(); m_text->FlushCache(); - CRobotMain::GetInstancePointer()->ReloadAllTextures(); //TODO: Remove cross-reference to CRobotMain + m_app->GetEventQueue()->AddEvent(Event(EVENT_RELOAD_TEXTURES)); UpdateGroundSpotTextures(); LoadAllTextures(); } bool CEngine::ProcessEvent(const Event &event) { + if (event.type == EVENT_RESOLUTION_CHANGED) + { + ResetAfterVideoConfigChanged(); + } + if (event.type == EVENT_KEY_DOWN) { auto data = event.GetData(); @@ -389,18 +392,6 @@ bool CEngine::ProcessEvent(const Event &event) m_showStats = !m_showStats; return false; } - - if (data->key == KEY(F11)) - { - m_debugLights = !m_debugLights; - return false; - } - - if (data->key == KEY(F10)) - { - m_debugDumpLights = true; - return false; - } } // By default, pass on all events @@ -1750,17 +1741,18 @@ bool CEngine::DetectBBox(int objRank, Math::Point mouse) mouse.y <= max.y ); } -int CEngine::DetectObject(Math::Point mouse) +int CEngine::DetectObject(Math::Point mouse, Math::Vector& targetPos, bool terrain) { float min = 1000000.0f; int nearest = -1; + Math::Vector pos; for (int objRank = 0; objRank < static_cast( m_objects.size() ); objRank++) { if (! m_objects[objRank].used) continue; - if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN) + if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN && !terrain) continue; if (! DetectBBox(objRank, mouse)) @@ -1789,10 +1781,11 @@ int CEngine::DetectObject(Math::Point mouse) for (int i = 0; i < static_cast( p3.vertices.size() ); i += 3) { float dist = 0.0f; - if (DetectTriangle(mouse, &p3.vertices[i], objRank, dist) && dist < min) + if (DetectTriangle(mouse, &p3.vertices[i], objRank, dist, pos) && dist < min) { min = dist; nearest = objRank; + targetPos = pos; } } } @@ -1801,10 +1794,11 @@ int CEngine::DetectObject(Math::Point mouse) for (int i = 0; i < static_cast( p3.vertices.size() ) - 2; i += 1) { float dist = 0.0f; - if (DetectTriangle(mouse, &p3.vertices[i], objRank, dist) && dist < min) + if (DetectTriangle(mouse, &p3.vertices[i], objRank, dist, pos) && dist < min) { min = dist; nearest = objRank; + targetPos = pos; } } } @@ -1815,7 +1809,7 @@ int CEngine::DetectObject(Math::Point mouse) return nearest; } -bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRank, float& dist) +bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRank, float& dist, Math::Vector& pos) { assert(objRank >= 0 && objRank < static_cast(m_objects.size())); @@ -1862,6 +1856,16 @@ bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRan if (! Math::IsInsideTriangle(a, b, c, mouse)) return false; + Math::Vector a2 = Math::Transform(m_objects[objRank].transform, triangle[0].coord); + Math::Vector b2 = Math::Transform(m_objects[objRank].transform, triangle[1].coord); + Math::Vector c2 = Math::Transform(m_objects[objRank].transform, triangle[2].coord); + Math::Vector e = Math::Transform(m_matView.Inverse(), Math::Vector(0.0f, 0.0f, -1.0f)); + Math::Vector f = Math::Transform(m_matView.Inverse(), Math::Vector( + (mouse.x*2.0f-1.0f)*m_matProj.Inverse().Get(1,1), + (mouse.y*2.0f-1.0f)*m_matProj.Inverse().Get(2,2), + 0.0f)); + Math::Intersect(a2, b2, c2, e, f, pos); + dist = (p2D[0].z + p2D[1].z + p2D[2].z) / 3.0f; return true; } @@ -3374,6 +3378,21 @@ void CEngine::Draw3DScene() if (m_debugCrashSpheres) DrawCrashSpheres(); + if (m_debugGoto) + { + Math::Matrix worldMatrix; + worldMatrix.LoadIdentity(); + m_device->SetTransform(TRANSFORM_WORLD, worldMatrix); + + SetState(ENG_RSTATE_OPAQUE_COLOR); + + for (const auto& line : m_displayGoto) + { + m_device->DrawPrimitive(PRIMITIVE_LINE_STRIP, line.data(), line.size()); + } + } + m_displayGoto.clear(); + m_app->StartPerformanceCounter(PCNT_RENDER_PARTICLE); m_particle->DrawParticle(SH_WORLD); // draws the particles of the 3D world m_app->StopPerformanceCounter(PCNT_RENDER_PARTICLE); @@ -3967,7 +3986,7 @@ void CEngine::UpdateGroundSpotTextures() set = true; } - if (clear || set) + if (clear || set || m_debugResources || m_displayGotoImage != nullptr) { CImage shadowImg(Math::IntPoint(256, 256)); shadowImg.Fill(Gfx::IntColor(255, 255, 255, 255)); @@ -4127,6 +4146,43 @@ void CEngine::UpdateGroundSpotTextures() } } + if (m_debugResources) + { + for (float x = min.x; x < max.x; x += 1.0f) + { + for (float y = min.y; y < max.y; y += 1.0f) + { + Math::Vector pos( + x / 4.0f / 254.0f * 3200.0f - 1600.0f, + 0.0f, + y / 4.0f / 254.0f * 3200.0f - 1600.0f + ); + TerrainRes res = m_terrain->GetResource(pos); + Math::IntPoint p(x-min.x, y-min.y); + if (res == TR_NULL) + { + shadowImg.SetPixel(p, Gfx::Color(0.5f, 0.5f, 0.5f)); + continue; + } + shadowImg.SetPixelInt(p, ResourceToColor(res)); + } + } + } + + if (m_displayGotoImage != nullptr) + { + Math::IntPoint size = m_displayGotoImage->GetSize(); + for (float x = min.x; x < max.x; x += 1.0f) + { + for (float y = min.y; y < max.y; y += 1.0f) + { + int px = x / 4.0f / 254.0f * size.x; + int py = y / 4.0f / 254.0f * size.y; + shadowImg.SetPixelInt(Math::IntPoint(x-min.x, y-min.y), m_displayGotoImage->GetPixelInt(Math::IntPoint(px, py))); + } + } + } + std::stringstream str; str << "textures/shadow" << std::setfill('0') << std::setw(2) << s << ".png"; std::string texName = str.str(); @@ -5075,4 +5131,57 @@ void CEngine::SetStaticMeshTransparency(int meshHandle, float value) SetObjectTransparency(objRank, value); } +void CEngine::SetDebugLights(bool debugLights) +{ + m_debugLights = debugLights; +} + +bool CEngine::GetDebugLights() +{ + return m_debugLights; +} + +void CEngine::DebugDumpLights() +{ + m_debugDumpLights = true; +} + +void CEngine::SetDebugResources(bool debugResources) +{ + m_debugResources = debugResources; + m_firstGroundSpot = true; // Force a refresh of ground spot textures + UpdateGroundSpotTextures(); +} + +bool CEngine::GetDebugResources() +{ + return m_debugResources; +} + +void CEngine::SetDebugGoto(bool debugGoto) +{ + m_debugGoto = debugGoto; + if (!m_debugGoto) + { + m_displayGotoImage.reset(); + } +} + +bool CEngine::GetDebugGoto() +{ + return m_debugGoto; +} + +void CEngine::AddDebugGotoLine(std::vector line) +{ + m_displayGoto.push_back(line); +} + +void CEngine::SetDebugGotoBitmap(std::unique_ptr debugImage) +{ + m_displayGotoImage = std::move(debugImage); + m_firstGroundSpot = true; // Force ground spot texture reload + UpdateGroundSpotTextures(); +} + } // namespace Gfx diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 5fc65a2c..a64b8c3c 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -655,9 +655,6 @@ public: //! Frees all resources before exit void Destroy(); - //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) - void ResetAfterVideoConfigChanged(); - //! Called once per frame, the call is the entry point for rendering void Render(); @@ -844,7 +841,7 @@ public: //! Detects the target object that is selected with the mouse /** Returns the rank of the object or -1. */ - int DetectObject(Math::Point mouse); + int DetectObject(Math::Point mouse, Math::Vector& targetPos, bool terrain = false); //! Creates a shadow for the given object void CreateShadowSpot(int objRank); @@ -1187,7 +1184,23 @@ public: void ClearDisplayCrashSpheres(); void AddDisplayCrashSpheres(const std::vector& crashSpheres); + void SetDebugLights(bool debugLights); + bool GetDebugLights(); + void DebugDumpLights(); + + void SetDebugResources(bool debugResources); + bool GetDebugResources(); + + void SetDebugGoto(bool debugGoto); + bool GetDebugGoto(); + void AddDebugGotoLine(std::vector line); + void SetDebugGotoBitmap(std::unique_ptr debugImage); + protected: + //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) + /** Instead of calling this directly, send EVENT_RESOLUTION_CHANGED event **/ + void ResetAfterVideoConfigChanged(); + //! Prepares the interface for 3D scene void Draw3DScene(); //! Renders shadow map @@ -1249,7 +1262,7 @@ protected: bool GetBBox2D(int objRank, Math::Point& min, Math::Point& max); //! Detects whether the mouse is in a triangle. - bool DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRank, float& dist); + bool DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRank, float& dist, Math::Vector& pos); //! Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window /** The coordinated p2D.z gives the distance. */ @@ -1281,6 +1294,7 @@ protected: static void WriteScreenShotThread(std::unique_ptr data); //! Reloads all textures + /** This additionally sends EVENT_RELOAD_TEXTURES to reload all textures not maintained by CEngine **/ void ReloadAllTextures(); protected: @@ -1472,12 +1486,16 @@ protected: bool m_debugLights; bool m_debugDumpLights; bool m_debugCrashSpheres = false; + bool m_debugResources = false; + bool m_debugGoto = false; std::string m_timerText; std::unordered_map m_staticMeshBaseObjects; std::vector m_displayCrashSpheres; + std::vector> m_displayGoto; + std::unique_ptr m_displayGotoImage; //! Pause the animation updates bool m_pause = false; diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp index 88b9d33b..18192fe5 100644 --- a/src/graphics/engine/lightning.cpp +++ b/src/graphics/engine/lightning.cpp @@ -82,16 +82,24 @@ bool CLightning::EventProcess(const Event &event) bool CLightning::EventFrame(const Event &event) { + if (m_terrain == nullptr) + m_terrain = CRobotMain::GetInstancePointer()->GetTerrain(); + + if (m_camera == nullptr) + m_camera = CRobotMain::GetInstancePointer()->GetCamera(); + + if (m_sound == nullptr) + m_sound = CApplication::GetInstancePointer()->GetSound(); + if (m_engine->GetPause()) return true; if (CRobotMain::GetInstancePointer()->GetMovieLock()) return true; m_progress += event.rTime*m_speed; - if (m_phase == LightningPhase::Wait) + if (m_phase == LightningPhase::Wait && m_lightningExists) { if (m_progress >= 1.0f) { - m_pos.x = (Math::Rand()-0.5f)*(3200.0f-200.0f); m_pos.z = (Math::Rand()-0.5f)*(3200.0f-200.0f); m_pos.y = 0.0f; @@ -127,21 +135,7 @@ bool CLightning::EventFrame(const Event &event) } } - Math::Vector eye = m_engine->GetEyePt(); - float dist = Math::Distance(m_pos, eye); - float deep = m_engine->GetDeepView(); - - if (dist < deep) - { - Math::Vector pos = eye+((m_pos-eye)*0.2f); // like so close! - m_sound->Play(SOUND_BLITZ, pos); - - m_camera->StartOver(CAM_OVER_EFFECT_LIGHTNING, m_pos, 1.0f); - - m_phase = LightningPhase::Flash; - m_progress = 0.0f; - m_speed = 1.0f; - } + StrikeAtPos(m_pos); } } @@ -193,15 +187,6 @@ bool CLightning::Create(float sleep, float delay, float magnetic) m_progress = 0.0f; m_speed = 1.0f / m_sleep; - if (m_terrain == nullptr) - m_terrain = CRobotMain::GetInstancePointer()->GetTerrain(); - - if (m_camera == nullptr) - m_camera = CRobotMain::GetInstancePointer()->GetCamera(); - - if (m_sound == nullptr) - m_sound = CApplication::GetInstancePointer()->GetSound(); - return false; } @@ -233,7 +218,6 @@ bool CLightning::SetStatus(float sleep, float delay, float magnetic, float progr void CLightning::Draw() { - if (!m_lightningExists) return; if (m_phase != LightningPhase::Flash) return; CDevice* device = m_engine->GetDevice(); @@ -368,4 +352,25 @@ CObject* CLightning::SearchObject(Math::Vector pos) } +void CLightning::StrikeAtPos(Math::Vector pos) +{ + m_pos = pos; + + Math::Vector eye = m_engine->GetEyePt(); + float dist = Math::Distance(m_pos, eye); + float deep = m_engine->GetDeepView(); + + if (dist < deep) + { + Math::Vector pos = eye+((m_pos-eye)*0.2f); // like so close! + m_sound->Play(SOUND_BLITZ, pos); + + m_camera->StartOver(CAM_OVER_EFFECT_LIGHTNING, m_pos, 1.0f); + + m_phase = LightningPhase::Flash; + m_progress = 0.0f; + m_speed = 1.0f; + } +} + } // namespace Gfx diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h index 57cc6f58..505a7cf6 100644 --- a/src/graphics/engine/lightning.h +++ b/src/graphics/engine/lightning.h @@ -75,6 +75,9 @@ public: //! Draws lightning void Draw(); + //! Shoots lightning strike at given position + void StrikeAtPos(Math::Vector pos); + protected: //! Updates lightning bool EventFrame(const Event &event); diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 80e593b3..e9aa0ab4 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -647,13 +647,13 @@ bool CParticle::CheckChannel(int &channel) if (!m_particle[channel].used) { - GetLogger()->Error("CheckChannel used=false !\n"); + GetLogger()->Error("CParticle::CheckChannel used=false !\n"); return false; } if (m_particle[channel].uniqueStamp != uniqueStamp) { - GetLogger()->Error("CheckChannel uniqueStamp !\n"); + GetLogger()->Error("CParticle::CheckChannel uniqueStamp !\n"); return false; } @@ -3724,12 +3724,4 @@ Color CParticle::GetFogColor(Math::Vector pos) return result; } -bool CParticle::WriteWheelTrace(const char *filename, int width, int height, - Math::Vector dl, Math::Vector ur) -{ - // TODO: stub! - GetLogger()->Trace("CParticle::WriteWheelTrace(): stub!\n"); - return true; -} - } // namespace Gfx diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index 676a21b4..5279009a 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -291,9 +291,6 @@ public: //! Draws all the particles void DrawParticle(int sheet); - //! Writes a file containing all the tire tracks - bool WriteWheelTrace(const char *filename, int width, int height, Math::Vector dl, Math::Vector ur); - protected: //! Removes a particle of given rank void DeleteRank(int rank); diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index 8475a8a4..7ff24172 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -192,6 +192,22 @@ void CTerrain::AddMaterial(int id, const std::string& texName, const Math::Point } +// values from original bitmap palette +const std::map RESOURCE_PALETTE = { + {TR_STONE, Gfx::IntColor(255, 0, 0)}, + {TR_URANIUM, Gfx::IntColor(255, 255, 0)}, + {TR_POWER, Gfx::IntColor( 0, 255, 0)}, + {TR_KEY_A, Gfx::IntColor( 0, 204, 0)}, + {TR_KEY_B, Gfx::IntColor( 51, 204, 0)}, + {TR_KEY_C, Gfx::IntColor(102, 204, 0)}, + {TR_KEY_D, Gfx::IntColor(153, 204, 0)} +}; + +Gfx::IntColor ResourceToColor(TerrainRes res) +{ + return RESOURCE_PALETTE.at(res); +} + /** * The image must be 24 bits/pixel and grayscale and dx x dy in size * with dx = dy = (mosaic*brick)+1 */ @@ -224,21 +240,11 @@ bool CTerrain::LoadResources(const std::string& fileName) Gfx::IntColor pixel = img.GetPixelInt(Math::IntPoint(x, size - y - 1)); TerrainRes res = TR_NULL; - // values from original bitmap palette - if (pixel.r == 255 && pixel.g == 0 && pixel.b == 0) - res = TR_STONE; - else if (pixel.r == 255 && pixel.g == 255 && pixel.b == 0) - res = TR_URANIUM; - else if (pixel.r == 0 && pixel.g == 255 && pixel.b == 0) - res = TR_POWER; - else if (pixel.r == 0 && pixel.g == 204 && pixel.b == 0) - res = TR_KEY_A; - else if (pixel.r == 51 && pixel.g == 204 && pixel.b == 0) - res = TR_KEY_B; - else if (pixel.r == 102 && pixel.g == 204 && pixel.b == 0) - res = TR_KEY_C; - else if (pixel.r == 153 && pixel.g == 204 && pixel.b == 0) - res = TR_KEY_D; + for (const auto& it : RESOURCE_PALETTE) + { + if (pixel.r == it.second.r && pixel.g == it.second.g && pixel.b == it.second.b) + res = it.first; + } m_resources[x+size*y] = static_cast(res); } diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index 7f66f726..9a86b584 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -69,6 +69,8 @@ enum TerrainRes TR_KEY_D = 7 //@} }; +//! Converts TerrainRes to color +Gfx::IntColor ResourceToColor(TerrainRes res); /** * \class CTerrain diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 514d2181..c410e31c 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -86,6 +86,7 @@ #include "sound/sound.h" +#include "ui/debug_menu.h" #include "ui/displayinfo.h" #include "ui/displaytext.h" #include "ui/maindialog.h" @@ -116,6 +117,12 @@ const float UNIT = 4.0f; // default for g_unit float g_unit; // conversion factor +// Reference colors used when recoloring textures, see ChangeColor() +const Gfx::Color COLOR_REF_BOT = Gfx::Color( 10.0f/256.0f, 166.0f/256.0f, 254.0f/256.0f); // blue +const Gfx::Color COLOR_REF_ALIEN = Gfx::Color(135.0f/256.0f, 170.0f/256.0f, 13.0f/256.0f); // green +const Gfx::Color COLOR_REF_GREEN = Gfx::Color(135.0f/256.0f, 170.0f/256.0f, 13.0f/256.0f); // green +const Gfx::Color COLOR_REF_WATER = Gfx::Color( 25.0f/256.0f, 255.0f/256.0f, 240.0f/256.0f); // cyan + template<> CRobotMain* CSingleton::m_instance = nullptr; @@ -156,6 +163,8 @@ CRobotMain::CRobotMain() m_modelManager.get(), m_particle); + m_debugMenu = MakeUnique(this, m_engine, m_objMan.get(), m_sound); + m_time = 0.0f; m_gameTime = 0.0f; m_gameTimeAbsolute = 0.0f; @@ -225,8 +234,6 @@ CRobotMain::CRobotMain() m_globalMagnifyDamage = 1.0f; - m_exitAfterMission = false; - m_autosave = true; m_autosaveInterval = 5; m_autosaveSlots = 3; @@ -303,30 +310,6 @@ CPauseManager* CRobotMain::GetPauseManager() return m_pause.get(); } -void CRobotMain::ResetAfterVideoConfigChanged() -{ - // Recreate the interface (needed if the aspect ratio changes) - // TODO: This can sometimes cause unwanted side effects, like hidden windows reappearing. To be fixed during CEGUI refactoring. - m_eventQueue->AddEvent(Event(EVENT_UPDINTERFACE)); - CreateShortcuts(); -} - -void CRobotMain::ReloadAllTextures() -{ - if (m_phase == PHASE_SETUPds || - m_phase == PHASE_SETUPgs || - m_phase == PHASE_SETUPps || - m_phase == PHASE_SETUPcs || - m_phase == PHASE_SETUPss || - m_phase == PHASE_SIMUL || - m_phase == PHASE_WIN || - m_phase == PHASE_LOST) - { - ChangeColor(); - UpdateMap(); - } -} - std::string PhaseToString(Phase phase) { if (phase == PHASE_WELCOME1) return "PHASE_WELCOME1"; @@ -384,6 +367,13 @@ void CRobotMain::ChangePhase(Phase phase) bool resetWorld = false; if ((IsPhaseWithWorld(m_phase) || IsPhaseWithWorld(phase)) && !IsInSimulationConfigPhase(m_phase) && !IsInSimulationConfigPhase(phase)) { + if (IsPhaseWithWorld(m_phase) && !IsPhaseWithWorld(phase) && m_exitAfterMission) + { + GetLogger()->Info("Mission finished in single mission mode, exiting\n"); + m_eventQueue->AddEvent(Event(EVENT_QUIT)); + return; + } + GetLogger()->Info("Reseting world on phase change...\n"); resetWorld = true; } @@ -663,6 +653,12 @@ Phase CRobotMain::GetPhase() bool CRobotMain::ProcessEvent(Event &event) { if (!m_ui->EventProcess(event)) return false; + if (m_phase == PHASE_SIMUL) + { + if (!m_editFull) + m_camera->EventProcess(event); + } + if (!m_debugMenu->EventProcess(event)) return false; if (event.type == EVENT_FRAME) { @@ -693,6 +689,23 @@ bool CRobotMain::ProcessEvent(Event &event) return EventFrame(event); } + if (event.type == EVENT_RELOAD_TEXTURES) + { + if (IsPhaseWithWorld(m_phase)) + { + ChangeColor(); + UpdateMap(); + } + } + + if (event.type == EVENT_RESOLUTION_CHANGED) + { + // Recreate the interface (needed if the aspect ratio changes) + // TODO: This can sometimes cause unwanted side effects, like hidden windows reappearing. To be fixed during CEGUI refactoring. + m_eventQueue->AddEvent(Event(EVENT_UPDINTERFACE)); + CreateShortcuts(); + } + if (event.type == EVENT_FOCUS_LOST) { GetLogger()->Trace("Window unfocused\n"); @@ -759,6 +772,15 @@ bool CRobotMain::ProcessEvent(Event &event) } return false; } + + if (IsPhaseWithWorld(m_phase)) + { + if (data->key == KEY(F11)) + { + m_debugMenu->ToggleInterface(); + return false; + } + } } if (event.type == EVENT_KEY_DOWN && @@ -826,9 +848,6 @@ bool CRobotMain::ProcessEvent(Event &event) // Simulation phase of the game if (m_phase == PHASE_SIMUL) { - if (!m_editFull) - m_camera->EventProcess(event); - switch (event.type) { case EVENT_KEY_DOWN: @@ -837,11 +856,6 @@ bool CRobotMain::ProcessEvent(Event &event) KeyCamera(event.type, data->slot); HiliteClear(); - if (data->key == KEY(F11)) - { - m_particle->WriteWheelTrace("Savegame/t.png", 256, 256, Math::Vector(16.0f, 0.0f, -368.0f), Math::Vector(140.0f, 0.0f, -248.0f)); - return false; - } if (m_editLock) // current edition? { if (data->slot == INPUT_SLOT_HELP) @@ -1163,25 +1177,25 @@ bool CRobotMain::ProcessEvent(Event &event) //! Executes a command -void CRobotMain::ExecuteCmd(char *cmd) +void CRobotMain::ExecuteCmd(const std::string& cmd) { - if (cmd[0] == 0) return; + if (cmd.empty()) return; if (m_phase == PHASE_SIMUL) { - if (strcmp(cmd, "winmission") == 0) + if (cmd == "winmission") m_eventQueue->AddEvent(Event(EVENT_WIN)); - if (strcmp(cmd, "lostmission") == 0) + if (cmd == "lostmission") m_eventQueue->AddEvent(Event(EVENT_LOST)); - if (strcmp(cmd, "trainerpilot") == 0) + if (cmd == "trainerpilot") { m_trainerPilot = !m_trainerPilot; return; } - if (strcmp(cmd, "fly") == 0) + if (cmd == "fly") { m_researchDone[0] |= RESEARCH_FLY; @@ -1189,7 +1203,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "allresearch") == 0) + if (cmd == "allresearch") { m_researchDone[0] = -1; // all research are done @@ -1197,7 +1211,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "allbuildings") == 0) + if (cmd == "allbuildings") { m_build = -1; // all buildings are available @@ -1205,7 +1219,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "all") == 0) + if (cmd == "all") { m_researchDone[0] = -1; // all research are done m_build = -1; // all buildings are available @@ -1214,13 +1228,13 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "nolimit") == 0) + if (cmd == "nolimit") { m_terrain->SetFlyingMaxHeight(280.0f); return; } - if (strcmp(cmd, "controller") == 0) + if (cmd == "controller") { if (m_controller != nullptr) { @@ -1238,7 +1252,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "photo1") == 0) + if (cmd == "photo1") { if (m_freePhotoPause == nullptr) { @@ -1254,7 +1268,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "photo2") == 0) + if (cmd == "photo2") { if (m_freePhotoPause == nullptr) { @@ -1276,26 +1290,26 @@ void CRobotMain::ExecuteCmd(char *cmd) } int camtype; - if (sscanf(cmd, "camtype %d", &camtype) > 0) + if (sscanf(cmd.c_str(), "camtype %d", &camtype) > 0) { m_camera->SetType(static_cast(camtype)); return; } float camspeed; - if (sscanf(cmd, "camspeed %f", &camspeed) > 0) + if (sscanf(cmd.c_str(), "camspeed %f", &camspeed) > 0) { m_camera->SetCameraSpeed(camspeed); return; } - if (strcmp(cmd, "freecam") == 0) + if (cmd == "freecam") { m_camera->SetType(Gfx::CAM_TYPE_FREE); return; } - if (strcmp(cmd, "noclip") == 0) + if (cmd == "noclip") { CObject* object = GetSelect(); if (object != nullptr) @@ -1303,7 +1317,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "clip") == 0) + if (cmd == "clip") { CObject* object = GetSelect(); if (object != nullptr) @@ -1311,7 +1325,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "addhusky") == 0) + if (cmd == "addhusky") { CObject* object = GetSelect(); if (object != nullptr && object->Implements(ObjectInterfaceType::Shielded)) @@ -1319,7 +1333,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "addfreezer") == 0) + if (cmd == "addfreezer") { CObject* object = GetSelect(); if (object != nullptr && object->Implements(ObjectInterfaceType::JetFlying)) @@ -1327,7 +1341,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "\155\157\157") == 0) + if (cmd == "\155\157\157") { // VGhpcyBpcyBlYXN0ZXItZWdnIGFuZCBzbyBpdCBzaG91bGQgYmUgb2JmdXNjYXRlZCEgRG8gbm90 // IGNsZWFuLXVwIHRoaXMgY29kZSEK @@ -1341,7 +1355,7 @@ void CRobotMain::ExecuteCmd(char *cmd) GetLogger()->Info(" \x20\x20 \x7C\x7C\x20\x20\x20\x20 ||\n"); } - if (strcmp(cmd, "fullpower") == 0) + if (cmd == "fullpower") { CObject* object = GetSelect(); if (object != nullptr) @@ -1362,7 +1376,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "fullenergy") == 0) + if (cmd == "fullenergy") { CObject* object = GetSelect(); @@ -1378,7 +1392,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "fullshield") == 0) + if (cmd == "fullshield") { CObject* object = GetSelect(); if (object != nullptr && object->Implements(ObjectInterfaceType::Shielded)) @@ -1386,7 +1400,7 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "fullrange") == 0) + if (cmd == "fullrange") { CObject* object = GetSelect(); if (object != nullptr) @@ -1396,19 +1410,9 @@ void CRobotMain::ExecuteCmd(char *cmd) } return; } - if (strcmp(cmd, "debugcrashon") == 0) - { - m_debugCrashSpheres = true; - return; - } - if (strcmp(cmd, "debugcrashoff") == 0) - { - m_debugCrashSpheres = false; - return; - } } - if (strcmp(cmd, "debugmode") == 0) + if (cmd == "debugmode") { if (m_app->IsDebugModeActive(DEBUG_ALL)) { @@ -1421,46 +1425,46 @@ void CRobotMain::ExecuteCmd(char *cmd) return; } - if (strcmp(cmd, "showstat") == 0) + if (cmd == "showstat") { m_engine->SetShowStats(!m_engine->GetShowStats()); return; } - if (strcmp(cmd, "invui") == 0) + if (cmd == "invui") { m_engine->SetRenderInterface(!m_engine->GetRenderInterface()); return; } - if (strcmp(cmd, "selectinsect") == 0) + if (cmd == "selectinsect") { m_selectInsect = !m_selectInsect; return; } - if (strcmp(cmd, "showsoluce") == 0) + if (cmd == "showsoluce") { m_showSoluce = !m_showSoluce; m_ui->ShowSoluceUpdate(); return; } - if (strcmp(cmd, "allmission") == 0) + if (cmd == "allmission") { m_showAll = !m_showAll; m_ui->AllMissionUpdate(); return; } - if (strcmp(cmd, "invradar") == 0) + if (cmd == "invradar") { m_cheatRadar = !m_cheatRadar; return; } float speed; - if (sscanf(cmd, "speed %f", &speed) > 0) + if (sscanf(cmd.c_str(), "speed %f", &speed) > 0) { SetSpeed(speed); UpdateSpeedLabel(); @@ -1989,7 +1993,8 @@ CObject* CRobotMain::GetSelect() //! Detects the object aimed by the mouse CObject* CRobotMain::DetectObject(Math::Point pos) { - int objRank = m_engine->DetectObject(pos); + Math::Vector p; + int objRank = m_engine->DetectObject(pos, p); for (CObject* obj : m_objMan->GetAllObjects()) { @@ -2830,30 +2835,11 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) m_controller = nullptr; - m_colorRefBot.r = 10.0f/256.0f; - m_colorRefBot.g = 166.0f/256.0f; - m_colorRefBot.b = 254.0f/256.0f; // blue - m_colorRefBot.a = 0.0f; m_colorNewBot.clear(); - m_colorNewBot[0] = m_colorRefBot; - - m_colorRefAlien.r = 135.0f/256.0f; - m_colorRefAlien.g = 170.0f/256.0f; - m_colorRefAlien.b = 13.0f/256.0f; // green - m_colorRefAlien.a = 0.0f; - m_colorNewAlien = m_colorRefAlien; - - m_colorRefGreen.r = 135.0f/256.0f; - m_colorRefGreen.g = 170.0f/256.0f; - m_colorRefGreen.b = 13.0f/256.0f; // green - m_colorRefGreen.a = 0.0f; - m_colorNewGreen = m_colorRefGreen; - - m_colorRefWater.r = 25.0f/256.0f; - m_colorRefWater.g = 255.0f/256.0f; - m_colorRefWater.b = 240.0f/256.0f; // cyan - m_colorRefWater.a = 0.0f; - m_colorNewWater = m_colorRefWater; + m_colorNewBot[0] = COLOR_REF_BOT; + m_colorNewAlien = COLOR_REF_ALIEN; + m_colorNewGreen = COLOR_REF_GREEN; + m_colorNewWater = COLOR_REF_WATER; m_engine->SetAmbientColor(Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f), 0); m_engine->SetAmbientColor(Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f), 1); @@ -3256,7 +3242,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) line->GetParam("level")->AsFloat(100.0f)*g_unit, line->GetParam("glint")->AsFloat(1.0f), pos); - m_colorNewWater = line->GetParam("color")->AsColor(m_colorRefWater); + m_colorNewWater = line->GetParam("color")->AsColor(COLOR_REF_WATER); m_colorShiftWater = line->GetParam("brightness")->AsFloat(0.0f); continue; } @@ -3958,26 +3944,26 @@ void CRobotMain::ChangeColor() // VehicleColor - for(auto it : m_colorNewBot) + for (auto it : m_colorNewBot) { int team = it.first; Gfx::Color newColor = it.second; std::string teamStr = StrUtils::ToString(team); if(team == 0) teamStr = ""; - m_engine->ChangeTextureColor("textures/objects/base1.png"+teamStr, "textures/objects/base1.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/convert.png"+teamStr, "textures/objects/convert.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/derrick.png"+teamStr, "textures/objects/derrick.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/factory.png"+teamStr, "textures/objects/factory.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/lemt.png"+teamStr, "textures/objects/lemt.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/roller.png"+teamStr, "textures/objects/roller.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/search.png"+teamStr, "textures/objects/search.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/base1.png"+teamStr, "textures/objects/base1.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/convert.png"+teamStr, "textures/objects/convert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/derrick.png"+teamStr, "textures/objects/derrick.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/factory.png"+teamStr, "textures/objects/factory.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/lemt.png"+teamStr, "textures/objects/lemt.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/roller.png"+teamStr, "textures/objects/roller.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/search.png"+teamStr, "textures/objects/search.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f); exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils exclu[2] = Math::Point(0.0f, 0.0f); exclu[3] = Math::Point(0.0f, 0.0f); // terminator - m_engine->ChangeTextureColor("textures/objects/drawer.png"+teamStr, "textures/objects/drawer.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); + m_engine->ChangeTextureColor("textures/objects/drawer.png"+teamStr, "textures/objects/drawer.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); exclu[0] = Math::Point(237.0f/256.0f, 176.0f/256.0f); exclu[1] = Math::Point(256.0f/256.0f, 220.0f/256.0f); // blue canister @@ -3985,7 +3971,7 @@ void CRobotMain::ChangeColor() exclu[3] = Math::Point(130.0f/256.0f, 214.0f/256.0f); // safe location exclu[4] = Math::Point(0.0f, 0.0f); exclu[5] = Math::Point(0.0f, 0.0f); // terminator - m_engine->ChangeTextureColor("textures/objects/subm.png"+teamStr, "textures/objects/subm.png", m_colorRefBot, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); + m_engine->ChangeTextureColor("textures/objects/subm.png"+teamStr, "textures/objects/subm.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); } // AlienColor @@ -3994,23 +3980,23 @@ void CRobotMain::ChangeColor() exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom exclu[2] = Math::Point(0.0f, 0.0f); exclu[3] = Math::Point(0.0f, 0.0f); // terminator - m_engine->ChangeTextureColor("textures/objects/ant.png", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu); - m_engine->ChangeTextureColor("textures/objects/mother.png", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); + m_engine->ChangeTextureColor("textures/objects/ant.png", COLOR_REF_ALIEN, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu); + m_engine->ChangeTextureColor("textures/objects/mother.png", COLOR_REF_ALIEN, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); // GreeneryColor - m_engine->ChangeTextureColor("textures/objects/plant.png", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); + m_engine->ChangeTextureColor("textures/objects/plant.png", COLOR_REF_GREEN, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); // water color // PARTIPLOUF0 and PARTIDROP : ts = Math::Point(0.500f, 0.500f); ti = Math::Point(0.875f, 0.750f); - m_engine->ChangeTextureColor("textures/effect00.png", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); + m_engine->ChangeTextureColor("textures/effect00.png", COLOR_REF_WATER, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); // PARTIFLIC : ts = Math::Point(0.00f, 0.75f); ti = Math::Point(0.25f, 1.00f); - m_engine->ChangeTextureColor("textures/effect02.png", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); + m_engine->ChangeTextureColor("textures/effect02.png", COLOR_REF_WATER, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); } //! Calculates the distance to the nearest object @@ -5125,8 +5111,6 @@ Error CRobotMain::CheckEndMission(bool frame) m_missionTimerEnabled = m_missionTimerStarted = false; m_winDelay = m_endTakeWinDelay; // wins in two seconds m_lostDelay = 0.0f; - if (m_exitAfterMission) - m_eventQueue->AddEvent(Event(EVENT_QUIT)); m_displayText->SetEnable(false); } m_missionResult = ERR_OK; @@ -5159,8 +5143,6 @@ Error CRobotMain::CheckEndMission(bool frame) } m_missionTimerEnabled = m_missionTimerStarted = false; m_displayText->SetEnable(false); - if (m_exitAfterMission) - m_eventQueue->AddEvent(Event(EVENT_QUIT)); return INFO_LOSTq; } @@ -5174,8 +5156,6 @@ Error CRobotMain::CheckEndMission(bool frame) } m_missionTimerEnabled = m_missionTimerStarted = false; m_displayText->SetEnable(false); - if (m_exitAfterMission) - m_eventQueue->AddEvent(Event(EVENT_QUIT)); return INFO_LOST; } @@ -5187,8 +5167,6 @@ Error CRobotMain::CheckEndMission(bool frame) m_lostDelay = 0.0f; m_missionTimerEnabled = m_missionTimerStarted = false; m_displayText->SetEnable(false); - if (m_exitAfterMission) - m_eventQueue->AddEvent(Event(EVENT_QUIT)); return ERR_OK; // mission ended } @@ -5214,8 +5192,6 @@ Error CRobotMain::CheckEndMission(bool frame) m_winDelay = m_endTakeWinDelay; // wins in two seconds m_lostDelay = 0.0f; } - if (m_exitAfterMission) - m_eventQueue->AddEvent(Event(EVENT_QUIT)); m_displayText->SetEnable(false); return ERR_OK; // mission ended } @@ -6032,3 +6008,13 @@ void CRobotMain::UpdateDebugCrashSpheres() } } } + +void CRobotMain::SetDebugCrashSpheres(bool draw) +{ + m_debugCrashSpheres = draw; +} + +bool CRobotMain::GetDebugCrashSpheres() +{ + return m_debugCrashSpheres; +} diff --git a/src/level/robotmain.h b/src/level/robotmain.h index 991c97ce..deea9e82 100644 --- a/src/level/robotmain.h +++ b/src/level/robotmain.h @@ -113,6 +113,7 @@ class CMainMap; class CInterface; class CDisplayText; class CDisplayInfo; +class CDebugMenu; } struct NewScriptName @@ -161,9 +162,6 @@ public: Ui::CDisplayText* GetDisplayText(); CPauseManager* GetPauseManager(); - void ResetAfterVideoConfigChanged(); - void ReloadAllTextures(); - void ChangePhase(Phase phase); bool ProcessEvent(Event &event); Phase GetPhase(); @@ -364,6 +362,10 @@ public: bool IsSelectable(CObject* obj); + void SetDebugCrashSpheres(bool draw); + + bool GetDebugCrashSpheres(); + protected: bool EventFrame(const Event &event); bool EventObject(const Event &event); @@ -395,7 +397,7 @@ protected: void StartDisplayVisit(EventType event); void FrameVisit(float rTime); void StopDisplayVisit(); - void ExecuteCmd(char *cmd); + void ExecuteCmd(const std::string& cmd); void UpdateSpeedLabel(); int AutosaveRotate(bool freeOne); @@ -435,6 +437,7 @@ protected: std::unique_ptr m_interface; std::unique_ptr m_displayInfo; std::unique_ptr m_displayText; + std::unique_ptr m_debugMenu; std::unique_ptr m_settings; //! Progress of loaded player @@ -562,13 +565,9 @@ protected: ShowLimit m_showLimit[MAXSHOWLIMIT]; - Gfx::Color m_colorRefBot; std::map m_colorNewBot; - Gfx::Color m_colorRefAlien; Gfx::Color m_colorNewAlien; - Gfx::Color m_colorRefGreen; Gfx::Color m_colorNewGreen; - Gfx::Color m_colorRefWater; Gfx::Color m_colorNewWater; float m_colorShiftWater = 0.0f; diff --git a/src/object/auto/autohouston.cpp b/src/object/auto/autohouston.cpp index a73b2705..9ace4085 100644 --- a/src/object/auto/autohouston.cpp +++ b/src/object/auto/autohouston.cpp @@ -18,6 +18,7 @@ */ +#include #include "object/auto/autohouston.h" #include "object/old_object.h" @@ -30,23 +31,19 @@ CAutoHouston::CAutoHouston(COldObject* object) : CAuto(object) { - Math::Vector pos; - int i; - - for ( i=0 ; iGetPosition(); m_lens[0].type = Gfx::PARTISELR; m_lens[1].type = Gfx::PARTISELR; m_lens[2].type = Gfx::PARTISELR; m_lens[3].type = Gfx::PARTISELR; - m_lens[0].pos = pos+Math::Vector(0.0f+13.0f, 34.0f, 30.0f ); - m_lens[1].pos = pos+Math::Vector(0.0f-13.0f, 34.0f, 30.0f ); - m_lens[2].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f+13.0f); - m_lens[3].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f-13.0f); + m_lens[0].pos = Math::Vector(0.0f+13.0f, 34.0f, 30.0f ); + m_lens[1].pos = Math::Vector(0.0f-13.0f, 34.0f, 30.0f ); + m_lens[2].pos = Math::Vector(0.0f , 34.0f, 30.0f+13.0f); + m_lens[3].pos = Math::Vector(0.0f , 34.0f, 30.0f-13.0f); m_lens[0].dim = 4.0f; m_lens[1].dim = 4.0f; m_lens[2].dim = 4.0f; @@ -60,49 +57,50 @@ CAutoHouston::CAutoHouston(COldObject* object) : CAuto(object) m_lens[2].off = 0.4f; m_lens[3].off = 0.4f; + int i = 4; + // Part under the radar. - i = 4; m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, 40.1f); + m_lens[i].pos = Math::Vector(-7.0f, 9.9f, 40.1f); m_lens[i].dim = 1.8f; m_lens[i].total = 0.4f; m_lens[i].off = 0.2f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f); + m_lens[i].pos = Math::Vector(-7.0f, 7.2f, 34.8f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.7f; m_lens[i].off = 0.3f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f); + m_lens[i].pos = Math::Vector(-7.0f, 6.5f, 34.3f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.7f; m_lens[i].off = 0.3f; i ++; m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f); + m_lens[i].pos = Math::Vector(-7.0f, 6.5f, 33.4f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.0f; m_lens[i].off = 0.0f; i ++; m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f); + m_lens[i].pos = Math::Vector(-7.0f, 6.5f, 33.0f); m_lens[i].dim = 0.4f; m_lens[i].total = 1.0f; m_lens[i].off = 0.5f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, 14.0f); + m_lens[i].pos = Math::Vector(-7.0f, 8.5f, 14.0f); m_lens[i].dim = 1.2f; m_lens[i].total = 0.8f; m_lens[i].off = 0.2f; i ++; m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(4.0f, 6.0f, 8.6f); + m_lens[i].pos = Math::Vector(4.0f, 6.0f, 8.6f); m_lens[i].dim = 1.0f; m_lens[i].total = 0.9f; m_lens[i].off = 0.7f; @@ -110,53 +108,53 @@ CAutoHouston::CAutoHouston(COldObject* object) : CAuto(object) // Part with three windows. m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, -19.9f); + m_lens[i].pos = Math::Vector(-7.0f, 9.9f, -19.9f); m_lens[i].dim = 1.0f; m_lens[i].total = 0.6f; m_lens[i].off = 0.3f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f-60.0f); + m_lens[i].pos = Math::Vector(-7.0f, 7.2f, 34.8f-60.0f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.7f; m_lens[i].off = 0.3f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f-60.0f); + m_lens[i].pos = Math::Vector(-7.0f, 6.5f, 34.3f-60.0f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.0f; m_lens[i].off = 0.0f; i ++; m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f-60.0f); + m_lens[i].pos = Math::Vector(-7.0f, 6.5f, 33.4f-60.0f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.6f; m_lens[i].off = 0.4f; i ++; m_lens[i].type = Gfx::PARTISELR; - m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f-60.0f); + m_lens[i].pos = Math::Vector(-7.0f, 6.5f, 33.0f-60.0f); m_lens[i].dim = 0.4f; m_lens[i].total = 0.8f; m_lens[i].off = 0.2f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-6.5f, 13.5f, -37.0f); + m_lens[i].pos = Math::Vector(-6.5f, 13.5f, -37.0f); m_lens[i].dim = 1.0f; m_lens[i].total = 0.0f; m_lens[i].off = 0.0f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 12.2f, -39.8f); + m_lens[i].pos = Math::Vector(-7.0f, 12.2f, -39.8f); m_lens[i].dim = 1.8f; m_lens[i].total = 1.5f; m_lens[i].off = 0.5f; i ++; m_lens[i].type = Gfx::PARTISELY; - m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, -47.0f); + m_lens[i].pos = Math::Vector(-7.0f, 8.5f, -47.0f); m_lens[i].dim = 0.6f; m_lens[i].total = 0.7f; m_lens[i].off = 0.5f; @@ -204,15 +202,11 @@ void CAutoHouston::Start(int param) bool CAutoHouston::EventProcess(const Event &event) { - Math::Vector speed; - Math::Point dim; - float angle; - int i; - CAuto::EventProcess(event); if ( m_engine->GetPause() ) return true; + float angle; angle = -m_time*1.0f; m_object->SetPartRotationY(1, angle); // rotates the radar angle = sinf(m_time*4.0f)*0.3f; @@ -223,8 +217,7 @@ bool CAutoHouston::EventProcess(const Event &event) m_progress += event.rTime*m_speed; // Flashes the keys. - speed = Math::Vector(0.0f, 0.0f, 0.0f); - for ( i=0 ; iCreateParticle(m_lens[i].pos, speed, dim, m_lens[i].type, 1.0f, 0.0f, 0.0f); + + Math::Vector pos = m_lens[i].pos; + Math::RotatePoint(Math::Vector(0.0f, 0.0f, 0.0f), -m_object->GetRotationY(), 0.0f, pos); + + m_lens[i].parti = m_particle->CreateParticle(m_object->GetPosition()+pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, m_lens[i].type, 1.0f, 0.0f, 0.0f); } } } diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp index d7e36cd7..de37d1a1 100644 --- a/src/object/task/taskgoto.cpp +++ b/src/object/task/taskgoto.cpp @@ -22,6 +22,7 @@ #include "common/event.h" #include "common/global.h" +#include "common/image.h" #include "common/make_unique.h" #include "graphics/engine/terrain.h" @@ -65,6 +66,9 @@ CTaskGoto::CTaskGoto(COldObject* object) : CForegroundTask(object) CTaskGoto::~CTaskGoto() { BitmapClose(); + + if (m_engine->GetDebugGoto() && m_object->GetSelect()) + m_engine->SetDebugGotoBitmap(std::move(nullptr)); } @@ -77,9 +81,63 @@ bool CTaskGoto::EventProcess(const Event &event) float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir; Error ret; - if ( m_engine->GetPause() ) return true; if ( event.type != EVENT_FRAME ) return true; + if (m_engine->GetDebugGoto()) + { + auto AdjustPoint = [&](Math::Vector p) -> Math::Vector + { + m_terrain->AdjustToFloor(p); + p.y += 2.0f; + return p; + }; + + std::vector debugLine; + if (m_bmTotal > 0) + { + Gfx::Color color = Gfx::Color(0.0f, 1.0f, 0.0f); + for (int i = 0; i < m_bmTotal; i++) + { + if (i > m_bmIndex-1) + color = Gfx::Color(1.0f, 0.0f, 0.0f); + debugLine.push_back(Gfx::VertexCol(AdjustPoint(m_bmPoints[i]), color)); + } + m_engine->AddDebugGotoLine(debugLine); + debugLine.clear(); + } + Gfx::Color color = Gfx::Color(0.0f, 0.0f, 1.0f); + debugLine.push_back(Gfx::VertexCol(m_object->GetPosition(), color)); + debugLine.push_back(Gfx::VertexCol(AdjustPoint(m_bmTotal > 0 && m_bmIndex <= m_bmTotal && m_phase != TGP_BEAMSEARCH ? m_bmPoints[m_bmIndex] : m_goal), color)); + m_engine->AddDebugGotoLine(debugLine); + + if (m_object->GetSelect() && m_bmChanged) + { + if (m_bmArray != nullptr) + { + std::unique_ptr debugImage = MakeUnique(Math::IntPoint(m_bmSize, m_bmSize)); + debugImage->Fill(Gfx::IntColor(255, 255, 255, 255)); + for (int x = 0; x < m_bmSize; x++) + { + for (int y = 0; y < m_bmSize; y++) + { + bool a = BitmapTestDot(0, x, y); + bool b = BitmapTestDot(1, x, y); + if (a || b) + { + Gfx::Color c = Gfx::Color(0.0f, 0.0f, 0.0f, 1.0f); + if (b) c = Gfx::Color(0.0f, 0.0f, 1.0f, 1.0f); + debugImage->SetPixel(Math::IntPoint(x, y), c); + } + } + } + m_engine->SetDebugGotoBitmap(std::move(debugImage)); + } + m_bmChanged = false; + } + } + + if ( m_engine->GetPause() ) return true; + // Momentarily stationary object (ant on the back)? CBaseAlien* alien = dynamic_cast(m_object); if ( alien != nullptr && alien->GetFixed() ) @@ -1616,6 +1674,8 @@ Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &cu iLar = 0; if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions + m_bmTotal = i; + if ( m_bmIter[i] == -1 ) { m_bmIter[i] = 0; @@ -1970,6 +2030,7 @@ bool CTaskGoto::BitmapOpen() m_bmSize = static_cast(3200.0f/BM_DIM_STEP); m_bmArray = MakeUniqueArray(m_bmSize*m_bmSize/8*2); + m_bmChanged = true; m_bmOffset = m_bmSize/2; m_bmLine = m_bmSize/8; @@ -1987,6 +2048,7 @@ bool CTaskGoto::BitmapOpen() bool CTaskGoto::BitmapClose() { m_bmArray.reset(); + m_bmChanged = true; return true; } @@ -2043,6 +2105,7 @@ void CTaskGoto::BitmapSetDot(int rank, int x, int y) y < 0 || y >= m_bmSize ) return; m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<= m_bmSize ) return; m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<DetectObject(pos); + Math::Vector p; + int objRank = m_engine->DetectObject(pos, p); for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) { diff --git a/src/ui/debug_menu.cpp b/src/ui/debug_menu.cpp new file mode 100644 index 00000000..88e62c10 --- /dev/null +++ b/src/ui/debug_menu.cpp @@ -0,0 +1,429 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see http://gnu.org/licenses + */ + +#include "ui/debug_menu.h" + +#include "common/event.h" + +#include "graphics/engine/lightning.h" +#include "graphics/engine/terrain.h" + +#include "level/robotmain.h" + +#include "object/object_create_params.h" +#include "object/object_manager.h" +#include "object/object.h" + +#include "ui/controls/interface.h" +#include "ui/controls/window.h" +#include "ui/controls/check.h" +#include "ui/controls/button.h" + +namespace Ui +{ + +CDebugMenu::CDebugMenu(CRobotMain* main, Gfx::CEngine* engine, CObjectManager* objMan, CSoundInterface* sound) +{ + m_main = main; + m_interface = m_main->GetInterface(); + m_engine = engine; + m_objMan = objMan; + m_sound = sound; +} + +CDebugMenu::~CDebugMenu() +{ + +} + +void CDebugMenu::ToggleInterface() +{ + if (m_interface->SearchControl(EVENT_WINDOW7) == nullptr) + CreateInterface(); + else + DestroyInterface(); +} + +const Math::Point dim = Math::Point(33.0f/640.0f, 33.0f/480.0f); +const float ox = 3.0f/640.0f, oy = 3.0f/480.0f; +const float sx = 33.0f/640.0f, sy = 33.0f/480.0f; + +void CDebugMenu::CreateInterface() +{ + CWindow* pw = m_interface->CreateWindows(Math::Point(), Math::Point(), 0, EVENT_WINDOW7); + Math::Point pos, ddim; + CCheck* pc; + CButton* pb; + + ddim.x = 4*dim.x+4*ox; + ddim.y = 222.0f/480.0f; + pos.x = 1.0f-ddim.x; + pos.y = oy+sy*3.0f; + pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW7); + + ddim.x = ddim.x - 4*ox; + ddim.y = dim.y*0.5f; + pos.x += 2*ox; + pos.y = oy+sy*9.0f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_DBG_SPAWN_OBJ); + pb->SetName("Spawn object"); + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_DBG_TELEPORT); + pb->SetName("Teleport"); + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_DBG_LIGHTNING); + pb->SetName("Lightning"); + pos.y -= 0.048f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_DBG_STATS); + pc->SetName("Display stats"); + pos.y -= 0.048f; + pos.y -= 0.048f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_DBG_RESOURCES); + pc->SetName("Underground resources"); + pos.y -= 0.048f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_DBG_GOTO); + pc->SetName("Render goto() path"); + pos.y -= 0.048f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_DBG_CRASHSPHERES); + pc->SetName("Render crash spheres"); + pos.y -= 0.048f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_DBG_LIGHTS); + pc->SetName("Render dynamic lights"); + pos.y -= 0.048f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_DBG_LIGHTS_DUMP); + pb->SetName("Dump lights to log"); + + UpdateInterface(); +} + +void CDebugMenu::CreateSpawnInterface() +{ + CWindow* pw = m_interface->CreateWindows(Math::Point(), Math::Point(), 0, EVENT_WINDOW7); + Math::Point pos, ddim; + CButton* pb; + + ddim.x = 4*dim.x+4*ox; + ddim.y = 222.0f/480.0f; + pos.x = 1.0f-ddim.x; + pos.y = oy+sy*3.0f; + pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW7); + + ddim.x = ddim.x - 4*ox; + ddim.y = dim.y*0.5f; + pos.x += 2*ox; + pos.y = oy+sy*9.0f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_SPAWN_CANCEL); + pb->SetName("Cancel"); + pos.y -= ddim.y; + + pos.y -= dim.y; + pw->CreateButton(pos, dim, 128+8, EVENT_SPAWN_ME); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+9, EVENT_SPAWN_WHEELEDGRABBER); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+15, EVENT_SPAWN_WHEELEDSHOOTER); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+19, EVENT_SPAWN_PHAZERSHOOTER); + pos.x -= 3*dim.x; + pos.y -= dim.y; + pw->CreateButton(pos, dim, 128+32, EVENT_SPAWN_BOTFACTORY); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+34, EVENT_SPAWN_CONVERTER); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+33, EVENT_SPAWN_DERRICK); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+36, EVENT_SPAWN_POWERSTATION); + pos.x -= 3*dim.x; + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_SPAWN_TITANIUM); + pb->SetName("Titanium"); + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_SPAWN_TITANIUMORE); + pb->SetName("TitaniumOre"); + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_SPAWN_URANIUMORE); + pb->SetName("UraniumOre"); + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_SPAWN_POWERCELL); + pb->SetName("PowerCell"); + pos.y -= ddim.y; + pb = pw->CreateButton(pos, ddim, -1, EVENT_SPAWN_NUCLEARCELL); + pb->SetName("NuclearCell"); +} + +const std::map SPAWN_TYPES = { + {EVENT_SPAWN_ME, OBJECT_HUMAN}, + {EVENT_SPAWN_WHEELEDGRABBER, OBJECT_MOBILEwa}, + {EVENT_SPAWN_WHEELEDSHOOTER, OBJECT_MOBILEwc}, + {EVENT_SPAWN_PHAZERSHOOTER, OBJECT_MOBILErc}, + {EVENT_SPAWN_BOTFACTORY, OBJECT_FACTORY}, + {EVENT_SPAWN_CONVERTER, OBJECT_CONVERT}, + {EVENT_SPAWN_DERRICK, OBJECT_DERRICK}, + {EVENT_SPAWN_POWERSTATION, OBJECT_STATION}, + {EVENT_SPAWN_TITANIUM, OBJECT_METAL}, + {EVENT_SPAWN_TITANIUMORE, OBJECT_STONE}, + {EVENT_SPAWN_URANIUMORE, OBJECT_URANIUM}, + {EVENT_SPAWN_POWERCELL, OBJECT_POWER}, + {EVENT_SPAWN_NUCLEARCELL, OBJECT_ATOMIC}, +}; + +void CDebugMenu::UpdateInterface() +{ + CCheck* pc; + CButton* pb; + + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW7)); + if (pw == nullptr) return; + + + pb = static_cast(pw->SearchControl(EVENT_DBG_LIGHTNING)); + if (pb != nullptr) + { + pb->SetName(m_lightningActive ? "Disable lightning" : "Lightning"); + } + + pb = static_cast(pw->SearchControl(EVENT_DBG_TELEPORT)); + if (pb != nullptr) + { + pb->SetName(m_teleportActive ? "Abort teleport" : "Teleport"); + } + + pc = static_cast(pw->SearchControl(EVENT_DBG_STATS)); + if (pc != nullptr) + { + pc->SetState(STATE_CHECK, m_engine->GetShowStats()); + } + + pc = static_cast(pw->SearchControl(EVENT_DBG_RESOURCES)); + if (pc != nullptr) + { + pc->SetState(STATE_CHECK, m_engine->GetDebugResources()); + } + + pc = static_cast(pw->SearchControl(EVENT_DBG_GOTO)); + if (pc != nullptr) + { + pc->SetState(STATE_CHECK, m_engine->GetDebugGoto()); + } + + pc = static_cast(pw->SearchControl(EVENT_DBG_CRASHSPHERES)); + if (pc != nullptr) + { + pc->SetState(STATE_CHECK, m_main->GetDebugCrashSpheres()); + } + + pc = static_cast(pw->SearchControl(EVENT_DBG_LIGHTS)); + if (pc != nullptr) + { + pc->SetState(STATE_CHECK, m_engine->GetDebugLights()); + } + + for (const auto& it : SPAWN_TYPES) + { + pb = static_cast(pw->SearchControl(it.first)); + if (pb != nullptr) + { + pb->SetState(STATE_ENABLE, it.second != m_spawningType); + } + } +} + +void CDebugMenu::DestroyInterface() +{ + m_interface->DeleteControl(EVENT_WINDOW7); + m_spawningType = OBJECT_NULL; +} + +bool CDebugMenu::EventProcess(const Event &event) +{ + switch (event.type) + { + case EVENT_DBG_STATS: + m_engine->SetShowStats(!m_engine->GetShowStats()); + UpdateInterface(); + break; + + case EVENT_DBG_SPAWN_OBJ: + DestroyInterface(); + CreateSpawnInterface(); + break; + + case EVENT_DBG_TELEPORT: + if (!m_teleportActive) + { + if (m_main->GetSelect() != nullptr) + m_teleportActive = true; + else + m_sound->Play(SOUND_CLICK); + } + else + { + m_teleportActive = false; + } + UpdateInterface(); + break; + + case EVENT_DBG_LIGHTNING: + m_lightningActive = !m_lightningActive; + UpdateInterface(); + break; + + case EVENT_DBG_RESOURCES: + m_engine->SetDebugResources(!m_engine->GetDebugResources()); + UpdateInterface(); + break; + + case EVENT_DBG_GOTO: + m_engine->SetDebugGoto(!m_engine->GetDebugGoto()); + UpdateInterface(); + break; + + case EVENT_DBG_CRASHSPHERES: + m_main->SetDebugCrashSpheres(!m_main->GetDebugCrashSpheres()); + UpdateInterface(); + break; + + case EVENT_DBG_LIGHTS: + m_engine->SetDebugLights(!m_engine->GetDebugLights()); + UpdateInterface(); + break; + + case EVENT_DBG_LIGHTS_DUMP: + m_engine->DebugDumpLights(); + break; + + + case EVENT_SPAWN_CANCEL: + DestroyInterface(); + CreateInterface(); + break; + + case EVENT_SPAWN_ME: + case EVENT_SPAWN_WHEELEDGRABBER: + case EVENT_SPAWN_WHEELEDSHOOTER: + case EVENT_SPAWN_PHAZERSHOOTER: + case EVENT_SPAWN_BOTFACTORY: + case EVENT_SPAWN_CONVERTER: + case EVENT_SPAWN_DERRICK: + case EVENT_SPAWN_POWERSTATION: + case EVENT_SPAWN_TITANIUM: + case EVENT_SPAWN_TITANIUMORE: + case EVENT_SPAWN_URANIUMORE: + case EVENT_SPAWN_POWERCELL: + case EVENT_SPAWN_NUCLEARCELL: + m_spawningType = SPAWN_TYPES.at(event.type); + UpdateInterface(); + break; + + case EVENT_MOUSE_BUTTON_DOWN: + if (event.GetData()->button == MOUSE_BUTTON_LEFT) + { + if (m_lightningActive) + { + return !HandleLightning(event.mousePos); + } + + if (m_teleportActive) + { + return !HandleTeleport(event.mousePos); + } + + if (m_spawningType != OBJECT_NULL) + { + return !HandleSpawnObject(m_spawningType, event.mousePos); + } + } + break; + + case EVENT_MOUSE_MOVE: + if (m_spawningType != OBJECT_NULL || m_teleportActive || m_lightningActive) + { + return false; + } + break; + + + default: + break; + } + return true; +} + +bool CDebugMenu::HandleSpawnObject(ObjectType type, Math::Point mousePos) +{ + Math::Vector pos; + if (m_engine->DetectObject(mousePos, pos, true) == -1) + { + m_sound->Play(SOUND_CLICK, 1.0f, 0.5f); + return false; + } + + ObjectCreateParams params; + params.pos = pos; + params.type = type; + params.power = 100.0f; + m_objMan->CreateObject(params); + + // Update shortcuts in the upper-left corner + m_main->CreateShortcuts(); + + m_sound->Play(SOUND_RADAR, 2.0f, 1.5f); + + return true; +} + +bool CDebugMenu::HandleLightning(Math::Point mousePos) +{ + Math::Vector pos; + if (m_engine->DetectObject(mousePos, pos, true) == -1) + { + m_sound->Play(SOUND_CLICK, 1.0f, 0.5f); + return false; + } + + m_engine->GetLightning()->StrikeAtPos(pos); + + return true; +} + +bool CDebugMenu::HandleTeleport(Math::Point mousePos) +{ + CObject* select = m_main->GetSelect(); + + Math::Vector pos; + if (m_engine->DetectObject(mousePos, pos, true) == -1 || !m_engine->GetTerrain()->AdjustToFloor(pos) || select == nullptr) + { + m_sound->Play(SOUND_CLICK, 1.0f, 0.5f); + m_teleportActive = false; + UpdateInterface(); + return false; + } + + select->SetPosition(pos); + + m_sound->Play(SOUND_BUILD, 4.0f, 0.75f); + m_sound->Play(SOUND_BUILD, pos, 4.0f, 0.75f); + + m_teleportActive = false; + UpdateInterface(); + + return true; +} + +} \ No newline at end of file diff --git a/src/ui/debug_menu.h b/src/ui/debug_menu.h new file mode 100644 index 00000000..2fb4b9de --- /dev/null +++ b/src/ui/debug_menu.h @@ -0,0 +1,70 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include +#include +#include "object/object_type.h" + +class CRobotMain; +class CObjectManager; +struct Event; + +namespace Gfx +{ +class CEngine; +} + +namespace Ui +{ +class CInterface; + +class CDebugMenu +{ +public: + CDebugMenu(CRobotMain* main, Gfx::CEngine* engine, CObjectManager* objMan, CSoundInterface* sound); + virtual ~CDebugMenu(); + + void ToggleInterface(); + bool EventProcess(const Event& event); + +protected: + void CreateInterface(); + void CreateSpawnInterface(); + void UpdateInterface(); + void DestroyInterface(); + + bool HandleSpawnObject(ObjectType type, Math::Point mousePos); + bool HandleLightning(Math::Point mousePos); + bool HandleTeleport(Math::Point mousePos); + +protected: + CRobotMain* m_main; + CInterface* m_interface; + Gfx::CEngine* m_engine; + CObjectManager* m_objMan; + CSoundInterface* m_sound; + + ObjectType m_spawningType = OBJECT_NULL; + bool m_lightningActive = false; + bool m_teleportActive = false; +}; + +}