Split Programmable and ProgramStorage
parent
d7800e03d1
commit
0eaf0d6f65
|
@ -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
|
||||
|
|
|
@ -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<CProgrammableObject*>(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<CProgramStorageObject*>(m_controller)->AddProgram();
|
||||
program->filename = "../" + line->GetParam("script")->AsPath("ai");
|
||||
program->readOnly = true;
|
||||
dynamic_cast<CProgrammableObject*>(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<COldObject*>(obj)->SetDefRank(rankObj); // TODO: do we really need this?
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
std::map<int, Program*> loadedPrograms;
|
||||
if (obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
|
||||
|
||||
std::map<int, Program*> 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<int>(i+1); // scriptRunnable1..scriptRunnable10
|
||||
if (line->GetParam(op)->IsDefined())
|
||||
{
|
||||
Program* program = programmable->AddProgram();
|
||||
Program* program = dynamic_cast<CProgramStorageObject*>(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<CProgrammableObject*>(obj)->SetScriptRun(loadedPrograms[i-1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (soluce && obj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined())
|
||||
dynamic_cast<CProgrammableObject*>(obj)->SetSoluceName(line->GetParam("soluce")->AsPath("ai"));
|
||||
if (soluce && obj->Implements(ObjectInterfaceType::ProgramStorage) && line->GetParam("soluce")->IsDefined())
|
||||
dynamic_cast<CProgramStorageObject*>(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<float>(objCounter) / static_cast<float>(numObjects);
|
||||
m_ui->GetLoadingScreen()->SetProgress(0.75f+objectProgress*0.25f, RT_LOADING_PROGRAMS, "for object "+StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects));
|
||||
objCounter++;
|
||||
|
||||
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
|
||||
for (auto& prog : programmable->GetPrograms())
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(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<char*>(name.c_str())))
|
||||
if (! programStorage->ReadProgram(program, const_cast<char*>(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<CProgrammableObject*>(obj);
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(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<CProgrammableObject*>(obj);
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(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<CProgrammableObject*>(obj);
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(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<CProgrammableObject*>(obj);
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(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<CLevelParserParam>(3)); // stops and open (PARAM_FIXSCENE)
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable) && obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
|
||||
|
||||
int run = programmable->GetProgram();
|
||||
int run = dynamic_cast<CProgramStorageObject*>(obj)->GetProgramIndex(dynamic_cast<CProgrammableObject*>(obj)->GetCurrentProgram());
|
||||
if (run != -1)
|
||||
{
|
||||
line->AddParam("run", MakeUnique<CLevelParserParam>(run+1));
|
||||
}
|
||||
}
|
||||
|
||||
auto& programs = programmable->GetPrograms();
|
||||
if (obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
auto& programs = dynamic_cast<CProgramStorageObject*>(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<CProgrammableObject*>(obj);
|
||||
|
||||
if (run != -1)
|
||||
{
|
||||
Program* program = programmable->GetOrAddProgram(run-1);
|
||||
programmable->SetScriptRun(program); // marks the program to be started
|
||||
Program* program = dynamic_cast<CProgramStorageObject*>(obj)->GetOrAddProgram(run-1);
|
||||
dynamic_cast<CProgrammableObject*>(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<std::string>(i+1))->AsBool(false))
|
||||
{
|
||||
Program* prog = programmable->GetOrAddProgram(i);
|
||||
Program* prog = dynamic_cast<CProgramStorageObject*>(obj)->GetOrAddProgram(i);
|
||||
prog->readOnly = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<CProgrammableObject*>(alien);
|
||||
|
||||
programmable->SetActivity(false);
|
||||
|
||||
Program* program = programmable->AddProgram();
|
||||
programmable->ReadProgram(program, m_alienProgramName.c_str());
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(alien);
|
||||
Program* program = programStorage->AddProgram();
|
||||
programStorage->ReadProgram(program, m_alienProgramName.c_str());
|
||||
programmable->RunProgram(program);
|
||||
}
|
||||
Init();
|
||||
|
|
|
@ -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<CProgrammableObject*>(vehicle);
|
||||
Program* program = programmable->AddProgram();
|
||||
Program* program = dynamic_cast<CProgramStorageObject*>(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<CProgrammableObject*>(vehicle)->RunProgram(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -660,15 +660,15 @@ bool CAutoFactory::CreateVehicle()
|
|||
CPhysics* physics = dynamic_cast<CMovableObject*>(vehicle)->GetPhysics();
|
||||
physics->SetFreeze(true); // it doesn't move
|
||||
|
||||
if (vehicle->Implements(ObjectInterfaceType::Programmable))
|
||||
if (vehicle->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(vehicle);
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
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>();
|
||||
program->script = MakeUnique<CScript>(dynamic_cast<COldObject*>(this));
|
||||
program->readOnly = false;
|
||||
program->runnable = true;
|
||||
|
||||
Program* prog = program.get();
|
||||
AddProgram(std::move(program));
|
||||
return prog;
|
||||
}
|
||||
|
||||
void CProgramStorageObjectImpl::AddProgram(std::unique_ptr<Program> 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<Program>& 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<Ui::CEdit>();
|
||||
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
|
||||
program->script->PutScript(edit.get(), "");
|
||||
newprog->script->GetScript(edit.get());
|
||||
|
||||
return newprog;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Program>>& CProgramStorageObjectImpl::GetPrograms()
|
||||
{
|
||||
return m_program;
|
||||
}
|
||||
|
||||
int CProgramStorageObjectImpl::GetProgramCount()
|
||||
{
|
||||
return static_cast<int>(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<int>(m_program.size()))
|
||||
return nullptr;
|
||||
|
||||
return m_program[index].get();
|
||||
}
|
||||
|
||||
Program* CProgramStorageObjectImpl::GetOrAddProgram(int index)
|
||||
{
|
||||
if(index < 0)
|
||||
return nullptr;
|
||||
|
||||
if(index < static_cast<int>(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;
|
||||
}
|
|
@ -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 <sstream>
|
||||
|
||||
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> program) override;
|
||||
void RemoveProgram(Program* program) override;
|
||||
Program* CloneProgram(Program* program) override;
|
||||
|
||||
std::vector<std::unique_ptr<Program>>& 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<std::unique_ptr<Program>> m_program;
|
||||
|
||||
bool m_activeVirus;
|
||||
|
||||
std::string m_soluceName;
|
||||
};
|
|
@ -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>();
|
||||
program->script = MakeUnique<CScript>(dynamic_cast<COldObject*>(this));
|
||||
program->readOnly = false;
|
||||
program->runnable = true;
|
||||
|
||||
Program* prog = program.get();
|
||||
AddProgram(std::move(program));
|
||||
return prog;
|
||||
}
|
||||
|
||||
void CProgrammableObjectImpl::AddProgram(std::unique_ptr<Program> 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<Program>& 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<Ui::CEdit>();
|
||||
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
|
||||
program->script->PutScript(edit.get(), "");
|
||||
newprog->script->GetScript(edit.get());
|
||||
|
||||
return newprog;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Program>>& CProgrammableObjectImpl::GetPrograms()
|
||||
{
|
||||
return m_program;
|
||||
}
|
||||
|
||||
int CProgrammableObjectImpl::GetProgramCount()
|
||||
{
|
||||
return static_cast<int>(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<int>(m_program.size()))
|
||||
return nullptr;
|
||||
|
||||
return m_program[index].get();
|
||||
}
|
||||
|
||||
Program* CProgrammableObjectImpl::GetOrAddProgram(int index)
|
||||
{
|
||||
if(index < 0)
|
||||
return nullptr;
|
||||
|
||||
if(index < static_cast<int>(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<int>(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<int>(dynamic_cast<CProgramStorageObject*>(m_object)->GetProgramCount()));
|
||||
m_currentProgram = dynamic_cast<CProgramStorageObject*>(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<CProgramStorageObject*>(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<CProgramStorageObject*>(m_object)->AddProgram();
|
||||
prog->script->SendScript(buffer.str().c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -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> program) override;
|
||||
void RemoveProgram(Program* program) override;
|
||||
Program* CloneProgram(Program* program) override;
|
||||
|
||||
std::vector<std::unique_ptr<Program>>& 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<float> m_cmdLine;
|
||||
|
||||
std::vector<std::unique_ptr<Program>> m_program;
|
||||
Program* m_currentProgram;
|
||||
|
||||
bool m_activeVirus;
|
||||
|
||||
Program* m_scriptRun;
|
||||
std::string m_soluceName;
|
||||
|
||||
bool m_traceRecord;
|
||||
TraceOper m_traceOper;
|
||||
|
|
|
@ -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 <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CScript;
|
||||
|
||||
struct Program
|
||||
{
|
||||
std::unique_ptr<CScript> 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<int>(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> program) = 0;
|
||||
virtual void RemoveProgram(Program* program) = 0;
|
||||
virtual Program* CloneProgram(Program* program) = 0;
|
||||
|
||||
virtual std::vector<std::unique_ptr<Program>>& GetPrograms() = 0;
|
||||
virtual int GetProgramCount() = 0;
|
||||
virtual Program* GetProgram(int index) = 0;
|
||||
virtual Program* GetOrAddProgram(int index) = 0;
|
||||
virtual int GetProgramIndex(Program* program) = 0;
|
||||
};
|
|
@ -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 <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CScript;
|
||||
|
||||
struct Program
|
||||
{
|
||||
std::unique_ptr<CScript> 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> program) = 0;
|
||||
virtual void RemoveProgram(Program* program) = 0;
|
||||
virtual Program* CloneProgram(Program* program) = 0;
|
||||
|
||||
virtual std::vector<std::unique_ptr<Program>>& 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<int>(ObjectInterfaceType::ProgramStorage)] = false;
|
||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false;
|
||||
// Another hack, see SetMovable()
|
||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Movable)] = false;
|
||||
|
@ -302,6 +304,7 @@ void COldObject::Simplify()
|
|||
}
|
||||
m_main->SaveOneScript(this);
|
||||
|
||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::ProgramStorage)] = false;
|
||||
m_implementedInterfaces[static_cast<int>(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<int>(ObjectInterfaceType::ProgramStorage)] = true;
|
||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<CProgrammableObject*>(m_object)->GetActiveVirus() )
|
||||
if ( dynamic_cast<CProgramStorageObject*>(m_object)->GetActiveVirus() )
|
||||
{
|
||||
return ERR_VEH_VIRUS;
|
||||
}
|
||||
|
|
|
@ -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<CProgrammableObject*>(object);
|
||||
Program* program = programmable->AddProgram();
|
||||
programmable->ReadProgram(program, name2.c_str());
|
||||
programmable->RunProgram(program);
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(object);
|
||||
Program* program = programStorage->AddProgram();
|
||||
programStorage->ReadProgram(program, name2.c_str());
|
||||
dynamic_cast<CProgrammableObject*>(object)->RunProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ CObjectInterface::CObjectInterface(COldObject* object)
|
|||
m_taskExecutor = dynamic_cast<CTaskExecutorObject*>(m_object);
|
||||
assert(object->Implements(ObjectInterfaceType::Programmable));
|
||||
m_programmable = dynamic_cast<CProgrammableObject*>(m_object);
|
||||
assert(object->Implements(ObjectInterfaceType::ProgramStorage));
|
||||
m_programStorage = dynamic_cast<CProgramStorageObject*>(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<int>(m_programmable->GetProgramCount())-1) index = 0;
|
||||
if(index < 0) index = m_programStorage->GetProgramCount()-1;
|
||||
if(index > static_cast<int>(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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue