From 5d30de0d09119b906feec62dee2a7138540fc549 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 10 Jul 2015 20:38:44 +0200 Subject: [PATCH] CProgrammableObject interface --- src/object/auto/autoegg.cpp | 7 +- src/object/auto/autofactory.cpp | 10 ++- src/object/interface/programmable_object.h | 48 +++++++++++ src/object/object_interface_type.h | 1 + src/object/old_object.cpp | 7 ++ src/object/old_object.h | 4 +- src/object/old_object_interface.h | 1 - src/object/robotmain.cpp | 97 ++++++++++++---------- src/object/task/task.cpp | 7 +- src/object/task/taskterraform.cpp | 14 ++-- src/script/scriptfunc.cpp | 4 +- 11 files changed, 137 insertions(+), 63 deletions(-) create mode 100644 src/object/interface/programmable_object.h diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp index 76fe0e74..5b618f63 100644 --- a/src/object/auto/autoegg.cpp +++ b/src/object/auto/autoegg.cpp @@ -26,6 +26,7 @@ #include "object/brain.h" #include "object/object_manager.h" +#include "object/interface/programmable_object.h" #include "object/interface/transportable_object.h" #include "object/level/parserline.h" #include "object/level/parserparam.h" @@ -182,9 +183,11 @@ bool CAutoEgg::EventProcess(const Event &event) CObject* alien = CObjectManager::GetInstancePointer()->CreateObject(pos, angle, m_type); alien->SetActivity(false); - CBrain* brain = alien->GetBrain(); - if(brain != nullptr) + + if (alien->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(alien)->GetBrain(); + Program* program = brain->AddProgram(); brain->ReadProgram(program, m_string); brain->RunProgram(program); diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp index 507ad8c7..d82e43da 100644 --- a/src/object/auto/autofactory.cpp +++ b/src/object/auto/autofactory.cpp @@ -29,6 +29,7 @@ #include "object/robotmain.h" #include "object/level/parserline.h" #include "object/level/parserparam.h" +#include "object/interface/programmable_object.h" #include "object/interface/transportable_object.h" #include "physics/physics.h" @@ -488,9 +489,10 @@ bool CAutoFactory::EventProcess(const Event &event) if ( m_program != nullptr ) { - CBrain* brain = m_vehicle->GetBrain(); - if ( brain != nullptr ) + if (m_vehicle->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(m_vehicle)->GetBrain(); + Program* program = brain->AddProgram(); program->script->SendScript(const_cast(m_program)); brain->RunProgram(program); @@ -649,9 +651,9 @@ bool CAutoFactory::CreateVehicle() physics->SetFreeze(true); // it doesn't move } - CBrain* brain = vehicle->GetBrain(); - if(brain != nullptr) + if (vehicle->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(vehicle)->GetBrain(); for ( int i=0 ; ; i++ ) { char* name = m_main->GetNewScriptName(m_type, i); diff --git a/src/object/interface/programmable_object.h b/src/object/interface/programmable_object.h new file mode 100644 index 00000000..cb399753 --- /dev/null +++ b/src/object/interface/programmable_object.h @@ -0,0 +1,48 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsiteс.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 "object/object_interface_type.h" + +class CBrain; + +/** + * \class CProgrammableObject + * \brief Interface for programmable objects + * + * Programmable objects can be programmed in CBOT + */ +class CProgrammableObject +{ +public: + explicit CProgrammableObject(ObjectInterfaceTypes& types) + { + types[static_cast(ObjectInterfaceType::Programmable)] = true; + } + virtual ~CProgrammableObject() + {} + + //! Returns CBrain + /** If only the object implements ObjectInterfaceType::Programmable, + * returned object will always be non-null*/ + virtual CBrain* GetBrain() = 0; + + // TODO: CBrain interface can actually be moved here +}; diff --git a/src/object/object_interface_type.h b/src/object/object_interface_type.h index e0916fe1..658a017c 100644 --- a/src/object/object_interface_type.h +++ b/src/object/object_interface_type.h @@ -34,6 +34,7 @@ enum class ObjectInterfaceType { Interactive, //!< interactive objects can process events from event loop Transportable, //!< objects that can be carried by robots or astronaut + Programmable, //!< objects that can be programmed in CBOT Max //!< maximum value (for getting number of items in enum) }; diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index a5f5a626..b4acd62b 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -189,7 +189,11 @@ COldObject::COldObject(int id) : CObject(id, OBJECT_NULL) , CInteractiveObject(m_implementedInterfaces) , CTransportableObject(m_implementedInterfaces) + , CProgrammableObject(m_implementedInterfaces) { + // A bit of a hack since CBrain is set externally in SetBrain() + m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; + m_sound = CApplication::GetInstancePointer()->GetSound(); m_engine = Gfx::CEngine::GetInstancePointer(); m_lightMan = m_engine->GetLightManager(); @@ -450,6 +454,8 @@ void COldObject::DeleteObject(bool bAll) void COldObject::Simplify() { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; + if ( m_brain != nullptr ) { m_brain->StopProgram(); @@ -3410,6 +3416,7 @@ CBrain* COldObject::GetBrain() void COldObject::SetBrain(std::unique_ptr brain) { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = true; m_brain = std::move(brain); } diff --git a/src/object/old_object.h b/src/object/old_object.h index a3495094..19ecec30 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -27,6 +27,7 @@ #include "object/object.h" #include "object/interface/interactive_object.h" +#include "object/interface/programmable_object.h" #include "object/interface/transportable_object.h" // The father of all parts must always be the part number zero! @@ -54,7 +55,8 @@ struct ObjectPart class COldObject : public CObject, public CInteractiveObject, - public CTransportableObject + public CTransportableObject, + public CProgrammableObject { friend class CObjectFactory; friend class CObjectManager; diff --git a/src/object/old_object_interface.h b/src/object/old_object_interface.h index 96e52c4b..2f7b1f2e 100644 --- a/src/object/old_object_interface.h +++ b/src/object/old_object_interface.h @@ -273,7 +273,6 @@ public: virtual CScript* GetRunScript() = 0; virtual CBotVar* GetBotVar() = 0; virtual CPhysics* GetPhysics() = 0; - virtual CBrain* GetBrain() = 0; virtual CMotion* GetMotion() = 0; virtual CAuto* GetAuto() = 0; diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index 847b37f0..80b93b0b 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -3467,13 +3467,16 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) m_controller = m_objMan->CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, OBJECT_CONTROLLER, 100.0f); m_controller->SetMagnifyDamage(100.0f); m_controller->SetIgnoreBuildCheck(true); - CBrain* brain = m_controller->GetBrain(); - if (brain != nullptr && line->GetParam("script")->IsDefined()) + if (m_controller->Implements(ObjectInterfaceType::Programmable)) { - Program* program = brain->AddProgram(); - program->filename = "../" + line->GetParam("script")->AsPath("ai"); - program->readOnly = true; - brain->SetScriptRun(program); + CBrain* brain = dynamic_cast(m_controller)->GetBrain(); + if (line->GetParam("script")->IsDefined()) + { + Program* program = brain->AddProgram(); + program->filename = "../" + line->GetParam("script")->AsPath("ai"); + program->readOnly = true; + brain->SetScriptRun(program); + } } continue; } @@ -3600,9 +3603,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) int run = -1; std::map loadedPrograms; - CBrain* brain = obj->GetBrain(); - if (brain != nullptr) + if (obj->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(obj)->GetBrain(); + bool allFilled = true; for (int i = 0; i < 10 || allFilled; i++) { @@ -3651,8 +3655,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) } } - if (soluce && brain != nullptr && line->GetParam("soluce")->IsDefined()) - brain->SetSoluceName(const_cast(line->GetParam("soluce")->AsPath("ai").c_str())); + if (soluce && obj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined()) + dynamic_cast(obj)->GetBrain() + ->SetSoluceName(const_cast(line->GetParam("soluce")->AsPath("ai").c_str())); obj->SetResetPosition(obj->GetPosition(0)); obj->SetResetAngle(obj->GetAngle(0)); @@ -4522,11 +4527,9 @@ void CRobotMain::CompileScript(bool soluce) nbError = 0; for (CObject* obj : m_objMan->GetAllObjects()) { - if (IsObjectBeingTransported(obj)) continue; - - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) continue; + if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; + CBrain* brain = dynamic_cast(obj)->GetBrain(); for (Program* program : brain->GetPrograms()) { //? if (brain->GetCompile(j)) continue; @@ -4550,11 +4553,9 @@ void CRobotMain::CompileScript(bool soluce) { for (CObject* obj : m_objMan->GetAllObjects()) { - if (IsObjectBeingTransported(obj)) continue; - - CBrain* brain = obj->GetBrain(); - if (brain == 0) continue; + if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; + CBrain* brain = dynamic_cast(obj)->GetBrain(); char* name = brain->GetSoluceName(); if (name[0] != 0) { @@ -4566,11 +4567,9 @@ void CRobotMain::CompileScript(bool soluce) // Start all programs according to the command "run". for (CObject* obj : m_objMan->GetAllObjects()) { - if (IsObjectBeingTransported(obj)) continue; - - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) continue; + if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; + CBrain* brain = dynamic_cast(obj)->GetBrain(); Program* program = brain->GetScriptRun(); if (program != nullptr) { @@ -4582,8 +4581,9 @@ void CRobotMain::CompileScript(bool soluce) //! Load all programs of the robot void CRobotMain::LoadOneScript(CObject *obj, int &nbError) { - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) return; + if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); if (!IsSelectable(obj)) return; @@ -4619,8 +4619,9 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank, { if (objRank == -1) return; - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) return; + if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; @@ -4654,8 +4655,9 @@ void CRobotMain::SaveAllScript() //! If a program does not exist, the corresponding file is destroyed. void CRobotMain::SaveOneScript(CObject *obj) { - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) return; + if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); if (!IsSelectable(obj)) return; @@ -4692,8 +4694,9 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) { if (objRank == -1) return; - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) return; + if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; @@ -4723,8 +4726,9 @@ bool CRobotMain::SaveFileStack(CObject *obj, FILE *file, int objRank) { if (objRank == -1) return true; - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) return true; + if (! obj->Implements(ObjectInterfaceType::Programmable)) return true; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return true; @@ -4737,8 +4741,9 @@ bool CRobotMain::ReadFileStack(CObject *obj, FILE *file, int objRank) { if (objRank == -1) return true; - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) return true; + if (! obj->Implements(ObjectInterfaceType::Programmable)) return true; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return true; @@ -4797,11 +4802,10 @@ bool CRobotMain::IsBusy() for (CObject* obj : m_objMan->GetAllObjects()) { - CBrain* brain = obj->GetBrain(); - if (brain != nullptr) - { - if (brain->IsBusy()) return true; - } + if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; + + CBrain* brain = dynamic_cast(obj)->GetBrain(); + if (brain->IsBusy()) return true; } return false; } @@ -4854,9 +4858,10 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj) if (obj->GetType() == OBJECT_BASE) line->AddParam("run", CLevelParserParamUPtr{new CLevelParserParam(3)}); // stops and open (PARAM_FIXSCENE) - CBrain* brain = obj->GetBrain(); - if (brain != nullptr) + if (obj->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(obj)->GetBrain(); + int run = brain->GetProgram(); if (run != -1) { @@ -5056,9 +5061,10 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename, automat->Start(run); // starts the film } - CBrain* brain = obj->GetBrain(); - if (brain != nullptr) + if (obj->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(obj)->GetBrain(); + if (run != -1) { Program* program = brain->GetOrAddProgram(run-1); @@ -5160,11 +5166,10 @@ CObject* CRobotMain::IOReadScene(const char *filename, const char *filecbot) // Starts scripts for (CObject* obj : m_objMan->GetAllObjects()) { - if (IsObjectBeingTransported(obj)) continue; + if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; if (obj->GetDefRank() == -1) continue; - CBrain* brain = obj->GetBrain(); - if (brain == nullptr) continue; + CBrain* brain = dynamic_cast(obj)->GetBrain(); Program* program = brain->GetScriptRun(); if (program != nullptr) diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp index 1459125f..9d70a133 100644 --- a/src/object/task/task.cpp +++ b/src/object/task/task.cpp @@ -24,6 +24,7 @@ #include "object/object.h" #include "object/robotmain.h" +#include "object/interface/programmable_object.h" // Object's constructor. @@ -41,7 +42,11 @@ CTask::CTask(CObject* object) m_object = object; m_physics = m_object->GetPhysics(); - m_brain = m_object->GetBrain(); + m_brain = nullptr; + if (object->Implements(ObjectInterfaceType::Programmable)) + { + m_brain = dynamic_cast(m_object)->GetBrain(); + } m_motion = m_object->GetMotion(); } diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp index 2ce964a2..c3b30ccb 100644 --- a/src/object/task/taskterraform.cpp +++ b/src/object/task/taskterraform.cpp @@ -33,6 +33,7 @@ #include "object/robotmain.h" #include "object/motion/motionant.h" #include "object/motion/motionspider.h" +#include "object/interface/programmable_object.h" #include "physics/physics.h" @@ -339,7 +340,6 @@ bool CTaskTerraform::Abort() bool CTaskTerraform::Terraform() { - CBrain* brain; CMotion* motion; ObjectType type; float dist; @@ -357,7 +357,7 @@ bool CTaskTerraform::Terraform() { // This was used by Ceebot-Teen to destroy objects hit by the Thumper // The old Teen objects are removed, but this code might be reused at some point, e.g. to add destruction of resources like empty batteries - + dist = Math::Distance(m_terraPos, pObj->GetPosition(0)); if ( dist > 20.0f ) continue; @@ -373,15 +373,17 @@ bool CTaskTerraform::Terraform() if ( type == OBJECT_ANT ) { - brain = pObj->GetBrain(); - if ( brain != 0 ) brain->StopTask(); + if (pObj->Implements(ObjectInterfaceType::Programmable)) + dynamic_cast(pObj)->GetBrain()->StopTask(); + motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f); pObj->SetFixed(true); // not moving } if ( type == OBJECT_SPIDER ) { - brain = pObj->GetBrain(); - if ( brain != 0 ) brain->StopTask(); + if (pObj->Implements(ObjectInterfaceType::Programmable)) + dynamic_cast(pObj)->GetBrain()->StopTask(); + motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f); pObj->SetFixed(true); // not moving } diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 9a2e5184..9ee3ddee 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -1765,9 +1765,9 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v if (name[0] != 0) { std::string name2 = CPathManager::InjectLevelDir(name, "ai"); - CBrain* brain = object->GetBrain(); - if (brain != nullptr) + if (object->Implements(ObjectInterfaceType::Programmable)) { + CBrain* brain = dynamic_cast(object)->GetBrain(); Program* program = brain->AddProgram(); brain->ReadProgram(program, name2.c_str()); brain->RunProgram(program);