Split Programmable and ProgramStorage

master
krzys-h 2015-08-15 21:29:08 +02:00
parent d7800e03d1
commit 0eaf0d6f65
17 changed files with 540 additions and 388 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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());
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;