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/common/event.h b/src/common/event.h index b4eb79fa..d1b851c9 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -149,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 @@ -380,6 +380,29 @@ 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_CRASHSPHERES = 854, + EVENT_DBG_LIGHTS = 855, + EVENT_DBG_LIGHTS_DUMP = 856, + + 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/engine/engine.cpp b/src/graphics/engine/engine.cpp index afc8a173..4ab66f3d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -392,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 @@ -1753,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)) @@ -1792,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; } } } @@ -1804,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; } } } @@ -1818,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())); @@ -1865,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; } @@ -5078,4 +5079,19 @@ 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; +} + } // namespace Gfx diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index bda5f782..ba1b1718 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -841,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); @@ -1184,6 +1184,10 @@ public: void ClearDisplayCrashSpheres(); void AddDisplayCrashSpheres(const std::vector& crashSpheres); + void SetDebugLights(bool debugLights); + bool GetDebugLights(); + void DebugDumpLights(); + 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 **/ @@ -1250,7 +1254,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. */ 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..69b27e37 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -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/level/robotmain.cpp b/src/level/robotmain.cpp index 1d51b59d..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" @@ -162,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; @@ -650,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) { @@ -763,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 && @@ -830,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: @@ -841,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) @@ -1400,16 +1410,6 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) } return; } - if (cmd == "debugcrashon") - { - m_debugCrashSpheres = true; - return; - } - if (cmd == "debugcrashoff") - { - m_debugCrashSpheres = false; - return; - } } if (cmd == "debugmode") @@ -1993,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()) { @@ -6007,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 079add3e..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 @@ -361,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); @@ -432,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 diff --git a/src/ui/controls/target.cpp b/src/ui/controls/target.cpp index b42116fc..9ba4f4e0 100644 --- a/src/ui/controls/target.cpp +++ b/src/ui/controls/target.cpp @@ -135,7 +135,8 @@ bool CTarget::GetTooltip(Math::Point pos, std::string &name) CObject* CTarget::DetectFriendObject(Math::Point pos) { - int objRank = m_engine->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..2c98371f --- /dev/null +++ b/src/ui/debug_menu.cpp @@ -0,0 +1,400 @@ +/* + * 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_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 -= 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_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_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; +}; + +}