From 0eaf0d6f6596fce0213bb9c7c61814eee2f7312c Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sat, 15 Aug 2015 21:29:08 +0200 Subject: [PATCH] Split Programmable and ProgramStorage --- src/CMakeLists.txt | 1 + src/level/robotmain.cpp | 108 ++++---- src/object/auto/autoegg.cpp | 7 +- src/object/auto/autofactory.cpp | 16 +- .../implementation/program_storage_impl.cpp | 246 ++++++++++++++++++ .../implementation/program_storage_impl.h | 67 +++++ .../implementation/programmable_impl.cpp | 244 ++--------------- src/object/implementation/programmable_impl.h | 27 +- src/object/interface/program_storage_object.h | 74 ++++++ src/object/interface/programmable_object.h | 37 +-- src/object/object_interface_type.h | 1 + src/object/old_object.cpp | 4 + src/object/old_object.h | 2 + src/physics/physics.cpp | 4 +- src/script/scriptfunc.cpp | 8 +- src/ui/object_interface.cpp | 80 +++--- src/ui/object_interface.h | 2 + 17 files changed, 540 insertions(+), 388 deletions(-) create mode 100644 src/object/implementation/program_storage_impl.cpp create mode 100644 src/object/implementation/program_storage_impl.h create mode 100644 src/object/interface/program_storage_object.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9527a688..4a385275 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -162,6 +162,7 @@ set(BASE_SOURCES object/interface/trace_drawing_object.cpp object/implementation/power_container_impl.cpp object/implementation/programmable_impl.cpp + object/implementation/program_storage_impl.cpp object/implementation/task_executor_impl.cpp object/motion/motion.cpp object/motion/motionant.cpp diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 44594da3..026faae0 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -3261,16 +3261,15 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "LevelController" && m_sceneReadPath.empty()) { m_controller = m_objMan->CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, OBJECT_CONTROLLER); - if (m_controller->Implements(ObjectInterfaceType::Programmable)) + assert(m_controller->Implements(ObjectInterfaceType::Programmable)); + assert(m_controller->Implements(ObjectInterfaceType::ProgramStorage)); + + if (line->GetParam("script")->IsDefined()) { - CProgrammableObject* programmable = dynamic_cast(m_controller); - if (line->GetParam("script")->IsDefined()) - { - Program* program = programmable->AddProgram(); - program->filename = "../" + line->GetParam("script")->AsPath("ai"); - program->readOnly = true; - programmable->SetScriptRun(program); - } + Program* program = dynamic_cast(m_controller)->AddProgram(); + program->filename = "../" + line->GetParam("script")->AsPath("ai"); + program->readOnly = true; + dynamic_cast(m_controller)->SetScriptRun(program); } continue; } @@ -3309,11 +3308,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (obj->Implements(ObjectInterfaceType::Old)) dynamic_cast(obj)->SetDefRank(rankObj); // TODO: do we really need this? - if (obj->Implements(ObjectInterfaceType::Programmable)) + std::map loadedPrograms; + if (obj->Implements(ObjectInterfaceType::ProgramStorage)) { - CProgrammableObject* programmable = dynamic_cast(obj); - - std::map loadedPrograms; bool allFilled = true; for (int i = 0; i < 10 || allFilled; i++) { @@ -3322,7 +3319,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) std::string opRunnable = "scriptRunnable" + StrUtils::ToString(i+1); // scriptRunnable1..scriptRunnable10 if (line->GetParam(op)->IsDefined()) { - Program* program = programmable->AddProgram(); + Program* program = dynamic_cast(obj)->AddProgram(); program->filename = "../" + line->GetParam(op)->AsPath("ai"); program->readOnly = line->GetParam(opReadOnly)->AsBool(true); program->runnable = line->GetParam(opRunnable)->AsBool(true); @@ -3333,16 +3330,19 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) allFilled = false; } } + } + if (obj->Implements(ObjectInterfaceType::Programmable)) + { int i = line->GetParam("run")->AsInt(0); if (i != 0) { - programmable->SetScriptRun(loadedPrograms[i-1]); + dynamic_cast(obj)->SetScriptRun(loadedPrograms[i-1]); } } - if (soluce && obj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined()) - dynamic_cast(obj)->SetSoluceName(line->GetParam("soluce")->AsPath("ai")); + if (soluce && obj->Implements(ObjectInterfaceType::ProgramStorage) && line->GetParam("soluce")->IsDefined()) + dynamic_cast(obj)->SetSoluceName(line->GetParam("soluce")->AsPath("ai")); } catch (const CObjectCreateException& e) { @@ -4304,33 +4304,33 @@ void CRobotMain::CompileScript(bool soluce) for (CObject* obj : m_objMan->GetAllObjects()) { - if (! obj->Implements(ObjectInterfaceType::Programmable)) continue; + if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) continue; float objectProgress = static_cast(objCounter) / static_cast(numObjects); m_ui->GetLoadingScreen()->SetProgress(0.75f+objectProgress*0.25f, RT_LOADING_PROGRAMS, "for object "+StrUtils::ToString(objCounter+1)+" / "+StrUtils::ToString(numObjects)); objCounter++; - CProgrammableObject* programmable = dynamic_cast(obj); - for (auto& prog : programmable->GetPrograms()) + CProgramStorageObject* programStorage = dynamic_cast(obj); + for (auto& prog : programStorage->GetPrograms()) { Program* program = prog.get(); if (program->filename.empty()) continue; std::string name = "ai/" + program->filename; - if (! programmable->ReadProgram(program, const_cast(name.c_str()))) + if (! programStorage->ReadProgram(program, const_cast(name.c_str()))) { GetLogger()->Error("Unable to read script from file \"%s\"\n", name.c_str()); } - //? if (!programmable->GetCompile(program)) nbError++; + //? if (!programStorage->GetCompile(program)) nbError++; } if (soluce) { - std::string name = programmable->GetSoluceName(); + std::string name = programStorage->GetSoluceName(); if (!name.empty()) { - programmable->ReadSoluce(name); // load solution + programStorage->ReadSoluce(name); // load solution } } @@ -4354,9 +4354,9 @@ void CRobotMain::CompileScript(bool soluce) //! Load all programs of the robot void CRobotMain::LoadOneScript(CObject *obj) { - if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return; - CProgrammableObject* programmable = dynamic_cast(obj); + CProgramStorageObject* programStorage = dynamic_cast(obj); if (!IsSelectable(obj)) return; @@ -4375,10 +4375,10 @@ void CRobotMain::LoadOneScript(CObject *obj) if (CResourceManager::Exists(filename)) { - Program* program = programmable->GetOrAddProgram(i); - if(programmable->GetCompile(program)) continue; // If already loaded (e.g. from level file), skip - programmable->ReadProgram(program, filename.c_str()); - //? if (!programmable->GetCompile(program)) nbError++; + Program* program = programStorage->GetOrAddProgram(i); + if(programStorage->GetCompile(program)) continue; // If already loaded (e.g. from level file), skip + programStorage->ReadProgram(program, filename.c_str()); + //? if (!programStorage->GetCompile(program)) nbError++; } } } @@ -4388,9 +4388,9 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank) { if (objRank == -1) return; - if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return; - CProgrammableObject* programmable = dynamic_cast(obj); + CProgramStorageObject* programStorage = dynamic_cast(obj); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; @@ -4404,9 +4404,9 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank) sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i); if (CResourceManager::Exists(fn)) { - Program* program = programmable->GetOrAddProgram(i); - programmable->ReadProgram(program, fn); - //? if (!programmable->GetCompile(program)) nbError++; + Program* program = programStorage->GetOrAddProgram(i); + programStorage->ReadProgram(program, fn); + //? if (!programStorage->GetCompile(program)) nbError++; } } } @@ -4424,9 +4424,9 @@ void CRobotMain::SaveAllScript() //! If a program does not exist, the corresponding file is destroyed. void CRobotMain::SaveOneScript(CObject *obj) { - if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return; - CProgrammableObject* programmable = dynamic_cast(obj); + CProgramStorageObject* programStorage = dynamic_cast(obj); if (!IsSelectable(obj)) return; @@ -4437,7 +4437,7 @@ void CRobotMain::SaveOneScript(CObject *obj) if (objRank == -1) return; char categoryChar = GetLevelCategoryDir(m_levelCategory)[0]; - auto& programs = programmable->GetPrograms(); + auto& programs = programStorage->GetPrograms(); // TODO: Find a better way to do that for (unsigned int i = 0; i <= 999; i++) { @@ -4447,7 +4447,7 @@ void CRobotMain::SaveOneScript(CObject *obj) if (i < programs.size()) { - programmable->WriteProgram(programs[i].get(), filename.c_str()); + programStorage->WriteProgram(programs[i].get(), filename.c_str()); } else { @@ -4462,9 +4462,9 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) { if (objRank == -1) return; - if (! obj->Implements(ObjectInterfaceType::Programmable)) return; + if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return; - CProgrammableObject* programmable = dynamic_cast(obj); + CProgramStorageObject* programStorage = dynamic_cast(obj); ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; @@ -4473,14 +4473,14 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) dirname = dirname.substr(0, dirname.find_last_of("/")); char fn[MAX_FNAME]; //TODO: Refactor to std::string - auto& programs = programmable->GetPrograms(); + auto& programs = programStorage->GetPrograms(); // TODO: Find a better way to do that for (unsigned int i = 0; i <= 999; i++) { sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i); if (i < programs.size()) { - programmable->WriteProgram(programs[i].get(), fn); + programStorage->WriteProgram(programs[i].get(), fn); } else { @@ -4634,17 +4634,18 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj) if (obj->GetType() == OBJECT_BASE) line->AddParam("run", MakeUnique(3)); // stops and open (PARAM_FIXSCENE) - if (obj->Implements(ObjectInterfaceType::Programmable)) + if (obj->Implements(ObjectInterfaceType::Programmable) && obj->Implements(ObjectInterfaceType::ProgramStorage)) { - CProgrammableObject* programmable = dynamic_cast(obj); - - int run = programmable->GetProgram(); + int run = dynamic_cast(obj)->GetProgramIndex(dynamic_cast(obj)->GetCurrentProgram()); if (run != -1) { line->AddParam("run", MakeUnique(run+1)); } + } - auto& programs = programmable->GetPrograms(); + if (obj->Implements(ObjectInterfaceType::ProgramStorage)) + { + auto& programs = dynamic_cast(obj)->GetPrograms(); for (unsigned int i = 0; i < programs.size(); i++) { if (programs[i]->readOnly) @@ -4870,19 +4871,20 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename, if (obj->Implements(ObjectInterfaceType::Programmable)) { - CProgrammableObject* programmable = dynamic_cast(obj); - if (run != -1) { - Program* program = programmable->GetOrAddProgram(run-1); - programmable->SetScriptRun(program); // marks the program to be started + Program* program = dynamic_cast(obj)->GetOrAddProgram(run-1); + dynamic_cast(obj)->SetScriptRun(program); // marks the program to be started } + } + if (obj->Implements(ObjectInterfaceType::ProgramStorage)) + { for (unsigned int i = 0; i <= 999; i++) { if (line->GetParam("scriptReadOnly" + boost::lexical_cast(i+1))->AsBool(false)) { - Program* prog = programmable->GetOrAddProgram(i); + Program* prog = dynamic_cast(obj)->GetOrAddProgram(i); prog->readOnly = true; } } diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp index 7eb8e9ac..a170808d 100644 --- a/src/object/auto/autoegg.cpp +++ b/src/object/auto/autoegg.cpp @@ -33,6 +33,7 @@ #include "object/old_object.h" #include "object/interface/programmable_object.h" +#include "object/interface/program_storage_object.h" #include "object/interface/transportable_object.h" @@ -189,11 +190,11 @@ bool CAutoEgg::EventProcess(const Event &event) if (alien->Implements(ObjectInterfaceType::Programmable)) { CProgrammableObject* programmable = dynamic_cast(alien); - programmable->SetActivity(false); - Program* program = programmable->AddProgram(); - programmable->ReadProgram(program, m_alienProgramName.c_str()); + CProgramStorageObject* programStorage = dynamic_cast(alien); + Program* program = programStorage->AddProgram(); + programStorage->ReadProgram(program, m_alienProgramName.c_str()); programmable->RunProgram(program); } Init(); diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp index f2cb76ca..18dc29a1 100644 --- a/src/object/auto/autofactory.cpp +++ b/src/object/auto/autofactory.cpp @@ -34,6 +34,7 @@ #include "object/old_object.h" #include "object/interface/programmable_object.h" +#include "object/interface/program_storage_object.h" #include "object/interface/transportable_object.h" #include "physics/physics.h" @@ -399,10 +400,9 @@ bool CAutoFactory::EventProcess(const Event &event) if ( !m_program.empty() ) { - if (vehicle->Implements(ObjectInterfaceType::Programmable)) + if (vehicle->Implements(ObjectInterfaceType::Programmable) && vehicle->Implements(ObjectInterfaceType::ProgramStorage)) { - CProgrammableObject* programmable = dynamic_cast(vehicle); - Program* program = programmable->AddProgram(); + Program* program = dynamic_cast(vehicle)->AddProgram(); if (boost::regex_search(m_program, boost::regex("^[A-Za-z0-9_]+$"))) // Public function name? { @@ -418,7 +418,7 @@ bool CAutoFactory::EventProcess(const Event &event) program->script->SendScript(m_program.c_str()); } - programmable->RunProgram(program); + dynamic_cast(vehicle)->RunProgram(program); } } } @@ -660,15 +660,15 @@ bool CAutoFactory::CreateVehicle() CPhysics* physics = dynamic_cast(vehicle)->GetPhysics(); physics->SetFreeze(true); // it doesn't move - if (vehicle->Implements(ObjectInterfaceType::Programmable)) + if (vehicle->Implements(ObjectInterfaceType::ProgramStorage)) { - CProgrammableObject* programmable = dynamic_cast(vehicle); + CProgramStorageObject* programStorage = dynamic_cast(vehicle); for ( int i=0 ; ; i++ ) { char* name = m_main->GetNewScriptName(m_type, i); if ( name == nullptr ) break; - Program* prog = programmable->GetOrAddProgram(i); - programmable->ReadProgram(prog, name); + Program* prog = programStorage->GetOrAddProgram(i); + programStorage->ReadProgram(prog, name); prog->readOnly = true; } } diff --git a/src/object/implementation/program_storage_impl.cpp b/src/object/implementation/program_storage_impl.cpp new file mode 100644 index 00000000..7df8d5e0 --- /dev/null +++ b/src/object/implementation/program_storage_impl.cpp @@ -0,0 +1,246 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, 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 + */ + +#include "object/implementation/programmable_impl.h" + +#include "common/global.h" + +#include "level/robotmain.h" + +#include "math/all.h" + +#include "object/object.h" +#include "object/old_object.h" + +#include "object/interface/controllable_object.h" +#include "object/interface/task_executor_object.h" + +#include "object/motion/motion.h" +#include "object/motion/motionvehicle.h" + +#include "physics/physics.h" + +#include "script/script.h" + +#include "ui/controls/edit.h" + +#include +#include + +CProgramStorageObjectImpl::CProgramStorageObjectImpl(ObjectInterfaceTypes& types, CObject* object) + : CProgramStorageObject(types), + m_object(object), + m_program(), + m_activeVirus(false), + m_soluceName("") +{ +} + +CProgramStorageObjectImpl::~CProgramStorageObjectImpl() +{} + +// Introduces a virus into a program. +// Returns true if it was inserted. + +bool CProgramStorageObjectImpl::IntroduceVirus() +{ + if(m_program.size() == 0) return false; + + for ( int i=0 ; i<50 ; i++ ) + { + int programIndex = rand() % m_program.size(); + if ( m_program[programIndex]->script->IntroduceVirus() ) // tries to introduce + { + m_activeVirus = true; // active virus + return true; + } + } + return false; +} + +// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus) +// letters which automatically disappear after a while, +// ActiveVirus does not disappear after you edit the program +// (Even if the virus is not fixed). + +void CProgramStorageObjectImpl::SetActiveVirus(bool bActive) +{ + m_activeVirus = bActive; + + if ( !m_activeVirus ) // virus disabled? + { + m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also + } +} + +bool CProgramStorageObjectImpl::GetActiveVirus() +{ + return m_activeVirus; +} + + +Program* CProgramStorageObjectImpl::AddProgram() +{ + assert(m_object->Implements(ObjectInterfaceType::Old)); //TODO + auto program = MakeUnique(); + program->script = MakeUnique(dynamic_cast(this)); + program->readOnly = false; + program->runnable = true; + + Program* prog = program.get(); + AddProgram(std::move(program)); + return prog; +} + +void CProgramStorageObjectImpl::AddProgram(std::unique_ptr program) +{ + m_program.push_back(std::move(program)); + m_object->UpdateInterface(); +} + +void CProgramStorageObjectImpl::RemoveProgram(Program* program) +{ + m_program.erase( + std::remove_if(m_program.begin(), m_program.end(), + [program](std::unique_ptr& prog) { return prog.get() == program; }), + m_program.end()); + + m_object->UpdateInterface(); +} + +Program* CProgramStorageObjectImpl::CloneProgram(Program* program) +{ + Program* newprog = AddProgram(); + + // TODO: Is there any reason CScript doesn't have a function to get the program code directly? + auto edit = MakeUnique(); + edit->SetMaxChar(Ui::EDITSTUDIOMAX); + program->script->PutScript(edit.get(), ""); + newprog->script->GetScript(edit.get()); + + return newprog; +} + +std::vector>& CProgramStorageObjectImpl::GetPrograms() +{ + return m_program; +} + +int CProgramStorageObjectImpl::GetProgramCount() +{ + return static_cast(m_program.size()); +} + +int CProgramStorageObjectImpl::GetProgramIndex(Program* program) +{ + for(unsigned int i = 0; i < m_program.size(); i++) + { + if(m_program[i].get() == program) + { + return i; + } + } + return -1; +} + +Program* CProgramStorageObjectImpl::GetProgram(int index) +{ + if(index < 0 || index >= static_cast(m_program.size())) + return nullptr; + + return m_program[index].get(); +} + +Program* CProgramStorageObjectImpl::GetOrAddProgram(int index) +{ + if(index < 0) + return nullptr; + + if(index < static_cast(m_program.size())) + return m_program[index].get(); + + for(int i = m_program.size(); i < index; i++) + { + AddProgram(); + } + return AddProgram(); +} + + +void CProgramStorageObjectImpl::SetSoluceName(const std::string& name) +{ + m_soluceName = name; +} + +const std::string& CProgramStorageObjectImpl::GetSoluceName() +{ + return m_soluceName; +} + + +// Load a script solution, in the first free script. +// If there is already an identical script, nothing is loaded. + +bool CProgramStorageObjectImpl::ReadSoluce(const std::string& filename) +{ + Program* prog = AddProgram(); + + if ( !ReadProgram(prog, filename) ) return false; // load solution + prog->readOnly = true; + + for(unsigned int i = 0; i < m_program.size(); i++) + { + if(m_program[i].get() == prog) continue; + + //TODO: This is bad. It's very sensitive to things like \n vs \r\n etc. + if ( m_program[i]->script->Compare(prog->script.get()) ) // the same already? + { + m_program[i]->readOnly = true; // Mark is as read-only + RemoveProgram(prog); + return false; + } + } + + return true; +} + +// Load a script with a text file. + +bool CProgramStorageObjectImpl::ReadProgram(Program* program, const std::string& filename) +{ + if ( program->script->ReadScript(filename.c_str()) ) return true; + + return false; +} + +// Indicates whether a program is compiled correctly. + +bool CProgramStorageObjectImpl::GetCompile(Program* program) +{ + return program->script->GetCompile(); +} + +// Saves a script in a text file. + +bool CProgramStorageObjectImpl::WriteProgram(Program* program, const std::string& filename) +{ + if ( program->script->WriteScript(filename.c_str()) ) return true; + + return false; +} diff --git a/src/object/implementation/program_storage_impl.h b/src/object/implementation/program_storage_impl.h new file mode 100644 index 00000000..a0725a6c --- /dev/null +++ b/src/object/implementation/program_storage_impl.h @@ -0,0 +1,67 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, 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/interface/program_storage_object.h" + +#include "math/vector.h" + +#include + +class CObject; + +class CProgramStorageObjectImpl : public CProgramStorageObject +{ +public: + explicit CProgramStorageObjectImpl(ObjectInterfaceTypes& types, CObject* object); + virtual ~CProgramStorageObjectImpl(); + + bool IntroduceVirus() override; + void SetActiveVirus(bool bActive) override; + bool GetActiveVirus() override; + + void SetSoluceName(const std::string& name) override; + const std::string& GetSoluceName() override; + + bool ReadSoluce(const std::string& filename) override; + bool ReadProgram(Program* program, const std::string& filename) override; + bool GetCompile(Program* program) override; + bool WriteProgram(Program* program, const std::string& filename) override; + + Program* AddProgram() override; + void AddProgram(std::unique_ptr program) override; + void RemoveProgram(Program* program) override; + Program* CloneProgram(Program* program) override; + + std::vector>& GetPrograms() override; + int GetProgramCount() override; + Program* GetProgram(int index) override; + Program* GetOrAddProgram(int index) override; + int GetProgramIndex(Program* program) override; +private: + CObject* m_object; + +private: + std::vector> m_program; + + bool m_activeVirus; + + std::string m_soluceName; +}; diff --git a/src/object/implementation/programmable_impl.cpp b/src/object/implementation/programmable_impl.cpp index 79bc528c..5fbef135 100644 --- a/src/object/implementation/programmable_impl.cpp +++ b/src/object/implementation/programmable_impl.cpp @@ -48,11 +48,8 @@ CProgrammableObjectImpl::CProgrammableObjectImpl(ObjectInterfaceTypes& types, CO m_object(object), m_activity(true), m_cmdLine(), - m_program(), m_currentProgram(nullptr), - m_activeVirus(false), m_scriptRun(nullptr), - m_soluceName(""), m_traceRecord(false), m_traceOper(TO_STOP), m_traceAngle(0.0f), @@ -129,161 +126,17 @@ void CProgrammableObjectImpl::StopProgram() m_object->UpdateInterface(); } +Program* CProgrammableObjectImpl::GetCurrentProgram() +{ + return m_currentProgram; +} + bool CProgrammableObjectImpl::IsProgram() { return m_currentProgram != nullptr; } -// Introduces a virus into a program. -// Returns true if it was inserted. - -bool CProgrammableObjectImpl::IntroduceVirus() -{ - if(m_program.size() == 0) return false; - - for ( int i=0 ; i<50 ; i++ ) - { - int programIndex = rand() % m_program.size(); - if ( m_program[programIndex]->script->IntroduceVirus() ) // tries to introduce - { - m_activeVirus = true; // active virus - return true; - } - } - return false; -} - -// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus) -// letters which automatically disappear after a while, -// ActiveVirus does not disappear after you edit the program -// (Even if the virus is not fixed). - -void CProgrammableObjectImpl::SetActiveVirus(bool bActive) -{ - m_activeVirus = bActive; - - if ( !m_activeVirus ) // virus disabled? - { - m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also - } -} - -bool CProgrammableObjectImpl::GetActiveVirus() -{ - return m_activeVirus; -} - - -Program* CProgrammableObjectImpl::AddProgram() -{ - assert(m_object->Implements(ObjectInterfaceType::Old)); //TODO - auto program = MakeUnique(); - program->script = MakeUnique(dynamic_cast(this)); - program->readOnly = false; - program->runnable = true; - - Program* prog = program.get(); - AddProgram(std::move(program)); - return prog; -} - -void CProgrammableObjectImpl::AddProgram(std::unique_ptr program) -{ - m_program.push_back(std::move(program)); - m_object->UpdateInterface(); -} - -void CProgrammableObjectImpl::RemoveProgram(Program* program) -{ - if(m_currentProgram == program) - { - StopProgram(); - } - - m_program.erase( - std::remove_if(m_program.begin(), m_program.end(), - [program](std::unique_ptr& prog) { return prog.get() == program; }), - m_program.end()); - - m_object->UpdateInterface(); -} - -Program* CProgrammableObjectImpl::CloneProgram(Program* program) -{ - Program* newprog = AddProgram(); - - // TODO: Is there any reason CScript doesn't have a function to get the program code directly? - auto edit = MakeUnique(); - edit->SetMaxChar(Ui::EDITSTUDIOMAX); - program->script->PutScript(edit.get(), ""); - newprog->script->GetScript(edit.get()); - - return newprog; -} - -std::vector>& CProgrammableObjectImpl::GetPrograms() -{ - return m_program; -} - -int CProgrammableObjectImpl::GetProgramCount() -{ - return static_cast(m_program.size()); -} - -int CProgrammableObjectImpl::GetProgramIndex(Program* program) -{ - for(unsigned int i = 0; i < m_program.size(); i++) - { - if(m_program[i].get() == program) - { - return i; - } - } - return -1; -} - -int CProgrammableObjectImpl::GetProgram() -{ - if(m_currentProgram == nullptr) - return -1; - - for(unsigned int i = 0; i < m_program.size(); i++) - { - if(m_program[i].get() == m_currentProgram) - { - return i; - } - } - return -1; -} - -Program* CProgrammableObjectImpl::GetProgram(int index) -{ - if(index < 0 || index >= static_cast(m_program.size())) - return nullptr; - - return m_program[index].get(); -} - -Program* CProgrammableObjectImpl::GetOrAddProgram(int index) -{ - if(index < 0) - return nullptr; - - if(index < static_cast(m_program.size())) - return m_program[index].get(); - - for(int i = m_program.size(); i < index; i++) - { - AddProgram(); - } - return AddProgram(); -} - -// Name management scripts to load. - void CProgrammableObjectImpl::SetScriptRun(Program* program) { m_scriptRun = program; @@ -294,69 +147,6 @@ Program* CProgrammableObjectImpl::GetScriptRun() return m_scriptRun; } -void CProgrammableObjectImpl::SetSoluceName(const std::string& name) -{ - m_soluceName = name; -} - -const std::string& CProgrammableObjectImpl::GetSoluceName() -{ - return m_soluceName; -} - - -// Load a script solution, in the first free script. -// If there is already an identical script, nothing is loaded. - -bool CProgrammableObjectImpl::ReadSoluce(const std::string& filename) -{ - Program* prog = AddProgram(); - - if ( !ReadProgram(prog, filename) ) return false; // load solution - prog->readOnly = true; - - for(unsigned int i = 0; i < m_program.size(); i++) - { - if(m_program[i].get() == prog) continue; - - //TODO: This is bad. It's very sensitive to things like \n vs \r\n etc. - if ( m_program[i]->script->Compare(prog->script.get()) ) // the same already? - { - m_program[i]->readOnly = true; // Mark is as read-only - RemoveProgram(prog); - return false; - } - } - - return true; -} - -// Load a script with a text file. - -bool CProgrammableObjectImpl::ReadProgram(Program* program, const std::string& filename) -{ - if ( program->script->ReadScript(filename.c_str()) ) return true; - - return false; -} - -// Indicates whether a program is compiled correctly. - -bool CProgrammableObjectImpl::GetCompile(Program* program) -{ - return program->script->GetCompile(); -} - -// Saves a script in a text file. - -bool CProgrammableObjectImpl::WriteProgram(Program* program, const std::string& filename) -{ - if ( program->script->WriteScript(filename.c_str()) ) return true; - - return false; -} - - // Load a stack of script implementation from a file. bool CProgrammableObjectImpl::ReadStack(FILE *file) @@ -369,11 +159,16 @@ bool CProgrammableObjectImpl::ReadStack(FILE *file) fRead(&op, sizeof(short), 1, file); // program rank if ( op >= 0 ) { - assert(op < static_cast(m_program.size())); - - //TODO: m_selScript = op; - - if ( !m_program[op]->script->ReadStack(file) ) return false; + if (m_object->Implements(ObjectInterfaceType::ProgramStorage)) + { + assert(op < static_cast(dynamic_cast(m_object)->GetProgramCount())); + m_currentProgram = dynamic_cast(m_object)->GetProgram(op); + if ( !m_currentProgram->script->ReadStack(file) ) return false; + } + else + { + return false; + } } } @@ -392,7 +187,11 @@ bool CProgrammableObjectImpl::WriteStack(FILE *file) op = 1; // run fWrite(&op, sizeof(short), 1, file); - op = GetProgram(); + op = -1; + if (m_object->Implements(ObjectInterfaceType::ProgramStorage)) + { + op = dynamic_cast(m_object)->GetProgramIndex(m_currentProgram); + } fWrite(&op, sizeof(short), 1, file); return m_currentProgram->script->WriteStack(file); @@ -536,7 +335,8 @@ void CProgrammableObjectImpl::TraceRecordStop() buffer << "}\n"; - Program* prog = AddProgram(); + assert(m_object->Implements(ObjectInterfaceType::ProgramStorage)); + Program* prog = dynamic_cast(m_object)->AddProgram(); prog->script->SendScript(buffer.str().c_str()); } diff --git a/src/object/implementation/programmable_impl.h b/src/object/implementation/programmable_impl.h index 33794d5b..4704c646 100644 --- a/src/object/implementation/programmable_impl.h +++ b/src/object/implementation/programmable_impl.h @@ -54,36 +54,15 @@ public: bool IsProgram() override; void RunProgram(Program* program) override; - int GetProgram() override; + Program* GetCurrentProgram() override; void StopProgram() override; - bool IntroduceVirus() override; - void SetActiveVirus(bool bActive) override; - bool GetActiveVirus() override; - void SetScriptRun(Program* rank) override; Program* GetScriptRun() override; - void SetSoluceName(const std::string& name) override; - const std::string& GetSoluceName() override; - bool ReadSoluce(const std::string& filename) override; - bool ReadProgram(Program* program, const std::string& filename) override; - bool GetCompile(Program* program) override; - bool WriteProgram(Program* program, const std::string& filename) override; bool ReadStack(FILE *file) override; bool WriteStack(FILE *file) override; - Program* AddProgram() override; - void AddProgram(std::unique_ptr program) override; - void RemoveProgram(Program* program) override; - Program* CloneProgram(Program* program) override; - - std::vector>& GetPrograms() override; - int GetProgramCount() override; - Program* GetProgram(int index) override; - Program* GetOrAddProgram(int index) override; - int GetProgramIndex(Program* program) override; - void TraceRecordStart() override; void TraceRecordStop() override; bool IsTraceRecord() override; @@ -111,13 +90,9 @@ private: std::vector m_cmdLine; - std::vector> m_program; Program* m_currentProgram; - bool m_activeVirus; - Program* m_scriptRun; - std::string m_soluceName; bool m_traceRecord; TraceOper m_traceOper; diff --git a/src/object/interface/program_storage_object.h b/src/object/interface/program_storage_object.h new file mode 100644 index 00000000..5b16c538 --- /dev/null +++ b/src/object/interface/program_storage_object.h @@ -0,0 +1,74 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, 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" + +#include +#include +#include + +class CScript; + +struct Program +{ + std::unique_ptr script; + std::string filename; + bool readOnly = false; + bool runnable = true; +}; + +/** + * \class CProgramStorageObject + * \brief Interface for objects that store CBOT programs + */ +class CProgramStorageObject +{ +public: + explicit CProgramStorageObject(ObjectInterfaceTypes& types) + { + types[static_cast(ObjectInterfaceType::ProgramStorage)] = true; + } + virtual ~CProgramStorageObject() + {} + + virtual bool IntroduceVirus() = 0; + virtual void SetActiveVirus(bool bActive) = 0; + virtual bool GetActiveVirus() = 0; + + virtual void SetSoluceName(const std::string& name) = 0; + virtual const std::string& GetSoluceName() = 0; + + virtual bool ReadSoluce(const std::string& filename) = 0; + virtual bool ReadProgram(Program* program, const std::string& filename) = 0; + virtual bool GetCompile(Program* program) = 0; + virtual bool WriteProgram(Program* program, const std::string& filename) = 0; + + virtual Program* AddProgram() = 0; + virtual void AddProgram(std::unique_ptr program) = 0; + virtual void RemoveProgram(Program* program) = 0; + virtual Program* CloneProgram(Program* program) = 0; + + virtual std::vector>& GetPrograms() = 0; + virtual int GetProgramCount() = 0; + virtual Program* GetProgram(int index) = 0; + virtual Program* GetOrAddProgram(int index) = 0; + virtual int GetProgramIndex(Program* program) = 0; +}; diff --git a/src/object/interface/programmable_object.h b/src/object/interface/programmable_object.h index f84a6c33..7df7ee45 100644 --- a/src/object/interface/programmable_object.h +++ b/src/object/interface/programmable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2015, 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 @@ -21,20 +21,12 @@ #include "object/object_interface_type.h" +#include "object/interface/program_storage_object.h" + #include #include #include -class CScript; - -struct Program -{ - std::unique_ptr script; - std::string filename; - bool readOnly = false; - bool runnable = true; -}; - /** * \class CProgrammableObject * \brief Interface for programmable objects @@ -53,36 +45,15 @@ public: virtual bool IsProgram() = 0; virtual void RunProgram(Program* program) = 0; - virtual int GetProgram() = 0; + virtual Program* GetCurrentProgram() = 0; virtual void StopProgram() = 0; - virtual bool IntroduceVirus() = 0; - virtual void SetActiveVirus(bool bActive) = 0; - virtual bool GetActiveVirus() = 0; - virtual void SetScriptRun(Program* rank) = 0; virtual Program* GetScriptRun() = 0; - virtual void SetSoluceName(const std::string& name) = 0; - virtual const std::string& GetSoluceName() = 0; - virtual bool ReadSoluce(const std::string& filename) = 0; - virtual bool ReadProgram(Program* program, const std::string& filename) = 0; - virtual bool GetCompile(Program* program) = 0; - virtual bool WriteProgram(Program* program, const std::string& filename) = 0; virtual bool ReadStack(FILE *file) = 0; virtual bool WriteStack(FILE *file) = 0; - virtual Program* AddProgram() = 0; - virtual void AddProgram(std::unique_ptr program) = 0; - virtual void RemoveProgram(Program* program) = 0; - virtual Program* CloneProgram(Program* program) = 0; - - virtual std::vector>& GetPrograms() = 0; - virtual int GetProgramCount() = 0; - virtual Program* GetProgram(int index) = 0; - virtual Program* GetOrAddProgram(int index) = 0; - virtual int GetProgramIndex(Program* program) = 0; - //! Start recording trace virtual void TraceRecordStart() = 0; //! Stop recording trace and generate CBot program diff --git a/src/object/object_interface_type.h b/src/object/object_interface_type.h index a4cdd327..9ecbc7b1 100644 --- a/src/object/object_interface_type.h +++ b/src/object/object_interface_type.h @@ -35,6 +35,7 @@ enum class ObjectInterfaceType { Interactive, //!< interactive objects can process events from event loop Transportable, //!< objects that can be carried by robots or astronaut + ProgramStorage, //!< objects that store CBOT programs Programmable, //!< objects that can be programmed in CBOT TaskExecutor, //!< objects that can execute tasks (CTask classes) Jostleable, //!< object that can be jostled diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 1c5ea202..16283290 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -77,6 +77,7 @@ COldObject::COldObject(int id) CInteractiveObject(m_implementedInterfaces), CTransportableObject(m_implementedInterfaces), CTaskExecutorObjectImpl(m_implementedInterfaces, this), + CProgramStorageObjectImpl(m_implementedInterfaces, this), CProgrammableObjectImpl(m_implementedInterfaces, this), CJostleableObject(m_implementedInterfaces), CCarrierObject(m_implementedInterfaces), @@ -90,6 +91,7 @@ COldObject::COldObject(int id) m_partiSel() { // A bit of a hack since we don't have subclasses yet, set externally in SetProgrammable() + m_implementedInterfaces[static_cast(ObjectInterfaceType::ProgramStorage)] = false; m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; // Another hack, see SetMovable() m_implementedInterfaces[static_cast(ObjectInterfaceType::Movable)] = false; @@ -302,6 +304,7 @@ void COldObject::Simplify() } m_main->SaveOneScript(this); + m_implementedInterfaces[static_cast(ObjectInterfaceType::ProgramStorage)] = false; m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = false; if ( m_physics != nullptr ) @@ -3141,6 +3144,7 @@ CMotion* COldObject::GetMotion() // TODO: Temporary hack until we'll have subclasses for objects void COldObject::SetProgrammable() { + m_implementedInterfaces[static_cast(ObjectInterfaceType::ProgramStorage)] = true; m_implementedInterfaces[static_cast(ObjectInterfaceType::Programmable)] = true; } diff --git a/src/object/old_object.h b/src/object/old_object.h index a1ebd514..f18d1dfe 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -43,6 +43,7 @@ #include "object/interface/transportable_object.h" #include "object/implementation/power_container_impl.h" +#include "object/implementation/program_storage_impl.h" #include "object/implementation/programmable_impl.h" #include "object/implementation/task_executor_impl.h" @@ -77,6 +78,7 @@ class COldObject : public CObject, public CInteractiveObject, public CTransportableObject, public CTaskExecutorObjectImpl, + public CProgramStorageObjectImpl, public CProgrammableObjectImpl, public CJostleableObject, public CCarrierObject, diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 457f0498..8bb7de56 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -3765,9 +3765,9 @@ Error CPhysics::GetError() type == OBJECT_APOLLO2 || type == OBJECT_MOBILEdr ) return ERR_OK; - if (m_object->Implements(ObjectInterfaceType::Programmable)) + if (m_object->Implements(ObjectInterfaceType::ProgramStorage)) { - if ( dynamic_cast(m_object)->GetActiveVirus() ) + if ( dynamic_cast(m_object)->GetActiveVirus() ) { return ERR_VEH_VIRUS; } diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 69e048be..39197399 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -1610,10 +1610,10 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v std::string name2 = InjectLevelPathsForCurrentLevel(name, "ai"); if (object->Implements(ObjectInterfaceType::Programmable)) { - CProgrammableObject* programmable = dynamic_cast(object); - Program* program = programmable->AddProgram(); - programmable->ReadProgram(program, name2.c_str()); - programmable->RunProgram(program); + CProgramStorageObject* programStorage = dynamic_cast(object); + Program* program = programStorage->AddProgram(); + programStorage->ReadProgram(program, name2.c_str()); + dynamic_cast(object)->RunProgram(program); } } diff --git a/src/ui/object_interface.cpp b/src/ui/object_interface.cpp index f45dd2e1..87a4514d 100644 --- a/src/ui/object_interface.cpp +++ b/src/ui/object_interface.cpp @@ -65,6 +65,8 @@ CObjectInterface::CObjectInterface(COldObject* object) m_taskExecutor = dynamic_cast(m_object); assert(object->Implements(ObjectInterfaceType::Programmable)); m_programmable = dynamic_cast(m_object); + assert(object->Implements(ObjectInterfaceType::ProgramStorage)); + m_programStorage = dynamic_cast(m_object); m_physics = m_object->GetPhysics(); m_motion = m_object->GetMotion(); @@ -195,8 +197,8 @@ bool CObjectInterface::EventProcess(const Event &event) index = data->key-KEY(1); else if(data->key == KEY(0)) index = 9; - if(index < 0) index = m_programmable->GetProgramCount()-1; - if(index > static_cast(m_programmable->GetProgramCount())-1) index = 0; + if(index < 0) index = m_programStorage->GetProgramCount()-1; + if(index > static_cast(m_programStorage->GetProgramCount())-1) index = 0; if(GetSelScript() != index) { @@ -229,9 +231,9 @@ bool CObjectInterface::EventProcess(const Event &event) { if ( !m_programmable->IsProgram() ) { - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - m_programmable->RunProgram(m_programmable->GetProgram(m_selScript)); + m_programmable->RunProgram(m_programStorage->GetProgram(m_selScript)); } } else @@ -242,9 +244,9 @@ bool CObjectInterface::EventProcess(const Event &event) if ( action == EVENT_OBJECT_PROGSTART ) { m_main->SaveOneScript(m_object); - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - m_programmable->RunProgram(m_programmable->GetProgram(m_selScript)); + m_programmable->RunProgram(m_programStorage->GetProgram(m_selScript)); } } if ( action == EVENT_OBJECT_PROGSTOP ) @@ -264,8 +266,8 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_STUDIO_CLONE ) { StopEditScript(false); - Program* newProgram = m_programmable->CloneProgram(m_programmable->GetProgram(m_selScript)); - m_selScript = m_programmable->GetProgramIndex(newProgram); + Program* newProgram = m_programStorage->CloneProgram(m_programStorage->GetProgram(m_selScript)); + m_selScript = m_programStorage->GetProgramIndex(newProgram); m_main->SaveOneScript(m_object); UpdateInterface(); @@ -305,9 +307,9 @@ bool CObjectInterface::EventProcess(const Event &event) } if ( action == EVENT_OBJECT_PROGEDIT ) { - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - StartEditScript(m_programmable->GetProgram(m_selScript), m_main->GetScriptName()); + StartEditScript(m_programStorage->GetProgram(m_selScript), m_main->GetScriptName()); } } @@ -318,8 +320,8 @@ bool CObjectInterface::EventProcess(const Event &event) { if( action == EVENT_OBJECT_PROGADD ) { - Program* program = m_programmable->AddProgram(); - m_selScript = m_programmable->GetProgramIndex(program); + Program* program = m_programStorage->AddProgram(); + m_selScript = m_programStorage->GetProgramIndex(program); m_main->SaveOneScript(m_object); UpdateInterface(); @@ -333,11 +335,15 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGREMOVE ) { - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - m_programmable->RemoveProgram(m_programmable->GetProgram(m_selScript)); - if(m_selScript >= m_programmable->GetProgramCount()) - m_selScript = m_programmable->GetProgramCount()-1; + if(m_programmable->GetCurrentProgram() == m_programStorage->GetProgram(m_selScript)) + { + m_programmable->StopProgram(); + } + m_programStorage->RemoveProgram(m_programStorage->GetProgram(m_selScript)); + if(m_selScript >= m_programStorage->GetProgramCount()) + m_selScript = m_programStorage->GetProgramCount()-1; m_main->SaveOneScript(m_object); UpdateInterface(); @@ -352,10 +358,10 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGCLONE ) { - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - m_programmable->CloneProgram(m_programmable->GetProgram(m_selScript)); - m_selScript = m_programmable->GetProgramCount()-1; + m_programStorage->CloneProgram(m_programStorage->GetProgram(m_selScript)); + m_selScript = m_programStorage->GetProgramCount()-1; m_main->SaveOneScript(m_object); UpdateInterface(); @@ -371,7 +377,7 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGMOVEUP ) { - std::iter_swap(m_programmable->GetPrograms().begin() + m_selScript, m_programmable->GetPrograms().begin() + m_selScript - 1); + std::iter_swap(m_programStorage->GetPrograms().begin() + m_selScript, m_programStorage->GetPrograms().begin() + m_selScript - 1); m_selScript--; m_main->SaveOneScript(m_object); @@ -386,7 +392,7 @@ bool CObjectInterface::EventProcess(const Event &event) if( action == EVENT_OBJECT_PROGMOVEDOWN ) { - std::iter_swap(m_programmable->GetPrograms().begin() + m_selScript, m_programmable->GetPrograms().begin() + m_selScript + 1); + std::iter_swap(m_programStorage->GetPrograms().begin() + m_selScript, m_programStorage->GetPrograms().begin() + m_selScript + 1); m_selScript++; m_main->SaveOneScript(m_object); @@ -408,18 +414,18 @@ bool CObjectInterface::EventProcess(const Event &event) if ( action == EVENT_OBJECT_PROGEDIT ) { - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - StartEditScript(m_programmable->GetProgram(m_selScript), m_main->GetScriptName()); + StartEditScript(m_programStorage->GetProgram(m_selScript), m_main->GetScriptName()); } } if ( action == EVENT_OBJECT_PROGRUN ) { m_programmable->StopProgram(); // stops the current program - if(m_selScript < m_programmable->GetProgramCount()) + if(m_selScript < m_programStorage->GetProgramCount()) { - m_programmable->RunProgram(m_programmable->GetProgram(m_selScript)); + m_programmable->RunProgram(m_programStorage->GetProgram(m_selScript)); } UpdateInterface(); } @@ -728,7 +734,7 @@ void CObjectInterface::StopEditScript(bool bCancel) if ( !m_studio->StopEditScript(bCancel) ) return; m_studio.reset(); - if ( !bCancel ) m_programmable->SetActiveVirus(false); + if ( !bCancel ) m_programStorage->SetActiveVirus(false); CreateInterface(true); // puts the control buttons } @@ -1614,13 +1620,13 @@ void CObjectInterface::UpdateInterface() bEnable = ( !m_taskExecutor->IsForegroundTask() && !m_programmable->IsProgram() ) && m_main->CanPlayerInteract(); - EnableInterface(pw, EVENT_OBJECT_PROGEDIT, !m_programmable->IsTraceRecord() && m_selScript < m_programmable->GetProgramCount() && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGEDIT, !m_programmable->IsTraceRecord() && m_selScript < m_programStorage->GetProgramCount() && m_main->CanPlayerInteract()); EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_programmable->IsTraceRecord()); EnableInterface(pw, EVENT_OBJECT_PROGADD, !m_programmable->IsProgram() && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, !m_programmable->IsProgram() && m_selScript < m_programmable->GetProgramCount() && !m_programmable->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_programmable->IsProgram() && m_selScript < m_programmable->GetProgramCount() && m_programmable->GetProgram(m_selScript)->runnable && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, !m_programmable->IsProgram() && m_programmable->GetProgramCount() >= 2 && m_selScript > 0 && m_main->CanPlayerInteract()); - EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,!m_programmable->IsProgram() && m_programmable->GetProgramCount() >= 2 && m_selScript < m_programmable->GetProgramCount()-1 && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, !m_programmable->IsProgram() && m_selScript < m_programStorage->GetProgramCount() && !m_programStorage->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_programmable->IsProgram() && m_selScript < m_programStorage->GetProgramCount() && m_programStorage->GetProgram(m_selScript)->runnable && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, !m_programmable->IsProgram() && m_programStorage->GetProgramCount() >= 2 && m_selScript > 0 && m_main->CanPlayerInteract()); + EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,!m_programmable->IsProgram() && m_programStorage->GetProgramCount() >= 2 && m_selScript < m_programStorage->GetProgramCount()-1 && m_main->CanPlayerInteract()); EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable); EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable); EnableInterface(pw, EVENT_OBJECT_UP, bEnable); @@ -1760,11 +1766,11 @@ void CObjectInterface::UpdateInterface() type == OBJECT_CONTROLLER) // vehicle? { bRun = false; - if ( m_selScript < m_programmable->GetProgramCount() ) + if ( m_selScript < m_programStorage->GetProgramCount() ) { - if(m_programmable->GetProgram(m_selScript)->runnable) + if(m_programStorage->GetProgram(m_selScript)->runnable) { - m_programmable->GetProgram(m_selScript)->script->GetTitle(title); + m_programStorage->GetProgram(m_selScript)->script->GetTitle(title); if ( title[0] != 0 ) { bRun = true; @@ -1920,14 +1926,14 @@ void CObjectInterface::UpdateScript(CWindow *pw) if ( pl == 0 ) return; pl->Flush(); - for ( int i = 0 ; i < m_programmable->GetProgramCount() ; i++ ) + for ( int i = 0 ; i < m_programStorage->GetProgramCount() ; i++ ) { sprintf(name, "%d", i+1); - m_programmable->GetProgram(i)->script->GetTitle(title); + m_programStorage->GetProgram(i)->script->GetTitle(title); if ( title[0] != 0 ) { - if(!m_programmable->GetProgram(i)->readOnly) + if(!m_programStorage->GetProgram(i)->readOnly) { sprintf(name, "%d: %s", i+1, title); } diff --git a/src/ui/object_interface.h b/src/ui/object_interface.h index cb684398..3f81e4a1 100644 --- a/src/ui/object_interface.h +++ b/src/ui/object_interface.h @@ -24,6 +24,7 @@ class COldObject; class CTaskExecutorObject; class CProgrammableObject; +class CProgramStorageObject; class CPhysics; class CMotion; class CRobotMain; @@ -93,6 +94,7 @@ protected: COldObject* m_object; CTaskExecutorObject* m_taskExecutor; CProgrammableObject* m_programmable; + CProgramStorageObject* m_programStorage; CPhysics* m_physics; CMotion* m_motion;