Rewritten program storage, closes #534
parent
0eaf0d6f65
commit
bc7d0c1c51
|
@ -3266,10 +3266,11 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
|
||||
if (line->GetParam("script")->IsDefined())
|
||||
{
|
||||
Program* program = dynamic_cast<CProgramStorageObject*>(m_controller)->AddProgram();
|
||||
program->filename = "../" + line->GetParam("script")->AsPath("ai");
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(m_controller);
|
||||
Program* program = programStorage->AddProgram();
|
||||
programStorage->ReadProgram(program, "../" + line->GetParam("script")->AsPath("ai"));
|
||||
program->readOnly = true;
|
||||
dynamic_cast<CProgrammableObject*>(m_controller)->SetScriptRun(program);
|
||||
dynamic_cast<CProgrammableObject*>(m_controller)->RunProgram(program);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -3308,41 +3309,22 @@ 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?
|
||||
|
||||
std::map<int, Program*> loadedPrograms;
|
||||
if (obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
bool allFilled = true;
|
||||
for (int i = 0; i < 10 || allFilled; i++)
|
||||
{
|
||||
std::string op = "script" + StrUtils::ToString<int>(i+1); // script1..script10
|
||||
std::string opReadOnly = "scriptReadOnly" + StrUtils::ToString<int>(i+1); // scriptReadOnly1..scriptReadOnly10
|
||||
std::string opRunnable = "scriptRunnable" + StrUtils::ToString<int>(i+1); // scriptRunnable1..scriptRunnable10
|
||||
if (line->GetParam(op)->IsDefined())
|
||||
{
|
||||
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);
|
||||
loadedPrograms[i] = program;
|
||||
}
|
||||
else
|
||||
{
|
||||
allFilled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
{
|
||||
int i = line->GetParam("run")->AsInt(0);
|
||||
if (i != 0)
|
||||
if (obj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject*>(obj)->GetSelectable() && obj->GetType() != OBJECT_HUMAN)
|
||||
{
|
||||
dynamic_cast<CProgrammableObject*>(obj)->SetScriptRun(loadedPrograms[i-1]);
|
||||
programStorage->SetProgramStorageIndex(rankObj);
|
||||
}
|
||||
}
|
||||
|
||||
if (soluce && obj->Implements(ObjectInterfaceType::ProgramStorage) && line->GetParam("soluce")->IsDefined())
|
||||
dynamic_cast<CProgramStorageObject*>(obj)->SetSoluceName(line->GetParam("soluce")->AsPath("ai"));
|
||||
char categoryChar = GetLevelCategoryDir(m_levelCategory)[0];
|
||||
programStorage->LoadAllProgramsForLevel(
|
||||
line.get(),
|
||||
m_playerProfile->GetSaveFile(StrUtils::Format("%c%.3d%.3d", categoryChar, m_levelChap, m_levelRank)),
|
||||
soluce
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (const CObjectCreateException& e)
|
||||
{
|
||||
|
@ -3567,9 +3549,6 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
throw CLevelParserException("Unknown command: '" + line->GetCommand() + "' in " + line->GetLevelFilename() + ":" + boost::lexical_cast<std::string>(line->GetLineNumber()));
|
||||
}
|
||||
|
||||
if (m_sceneReadPath.empty())
|
||||
CompileScript(soluce); // compiles all scripts
|
||||
|
||||
m_ui->GetLoadingScreen()->SetProgress(1.0f, RT_LOADING_FINISHED);
|
||||
if (m_ui->GetLoadingScreen()->IsVisible())
|
||||
{
|
||||
|
@ -4293,124 +4272,6 @@ void CRobotMain::FrameShowLimit(float rTime)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//! Compiles all scripts of robots
|
||||
void CRobotMain::CompileScript(bool soluce)
|
||||
{
|
||||
m_ui->GetLoadingScreen()->SetProgress(0.75f, RT_LOADING_PROGRAMS);
|
||||
|
||||
int numObjects = m_objMan->CountObjectsImplementing(ObjectInterfaceType::Programmable);
|
||||
int objCounter = 0;
|
||||
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
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++;
|
||||
|
||||
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 (! programStorage->ReadProgram(program, const_cast<char*>(name.c_str())))
|
||||
{
|
||||
GetLogger()->Error("Unable to read script from file \"%s\"\n", name.c_str());
|
||||
}
|
||||
//? if (!programStorage->GetCompile(program)) nbError++;
|
||||
}
|
||||
|
||||
if (soluce)
|
||||
{
|
||||
std::string name = programStorage->GetSoluceName();
|
||||
if (!name.empty())
|
||||
{
|
||||
programStorage->ReadSoluce(name); // load solution
|
||||
}
|
||||
}
|
||||
|
||||
LoadOneScript(obj);
|
||||
}
|
||||
|
||||
// Start all programs according to the command "run".
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (! obj->Implements(ObjectInterfaceType::Programmable)) continue;
|
||||
|
||||
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
|
||||
Program* program = programmable->GetScriptRun();
|
||||
if (program != nullptr)
|
||||
{
|
||||
programmable->RunProgram(program); // starts the program
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Load all programs of the robot
|
||||
void CRobotMain::LoadOneScript(CObject *obj)
|
||||
{
|
||||
if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return;
|
||||
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
if (!IsSelectable(obj)) return;
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
if (type == OBJECT_HUMAN) return;
|
||||
|
||||
int objRank = obj->GetDefRank();
|
||||
if (objRank == -1) return;
|
||||
|
||||
char categoryChar = GetLevelCategoryDir(m_levelCategory)[0];
|
||||
for (unsigned int i = 0; i <= 999; i++)
|
||||
{
|
||||
char file[MAX_FNAME];
|
||||
sprintf(file, "%c%.3d%.3d%.3d%.3d.txt", categoryChar, m_levelChap, m_levelRank, objRank, i);
|
||||
std::string filename = m_playerProfile->GetSaveFile(file);
|
||||
|
||||
if (CResourceManager::Exists(filename))
|
||||
{
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Load all programs of the robot
|
||||
void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank)
|
||||
{
|
||||
if (objRank == -1) return;
|
||||
|
||||
if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return;
|
||||
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
if (type == OBJECT_HUMAN) return;
|
||||
|
||||
std::string dirname = filename;
|
||||
dirname = dirname.substr(0, dirname.find_last_of("/"));
|
||||
|
||||
char fn[MAX_FNAME]; //TODO: Refactor to std::string
|
||||
for (unsigned int i = 0; i <= 999; i++)
|
||||
{
|
||||
sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i);
|
||||
if (CResourceManager::Exists(fn))
|
||||
{
|
||||
Program* program = programStorage->GetOrAddProgram(i);
|
||||
programStorage->ReadProgram(program, fn);
|
||||
//? if (!programStorage->GetCompile(program)) nbError++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Saves all programs of all the robots
|
||||
void CRobotMain::SaveAllScript()
|
||||
{
|
||||
|
@ -4428,65 +4289,8 @@ void CRobotMain::SaveOneScript(CObject *obj)
|
|||
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
if (!IsSelectable(obj)) return;
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
if (type == OBJECT_HUMAN) return;
|
||||
|
||||
int objRank = obj->GetDefRank();
|
||||
if (objRank == -1) return;
|
||||
|
||||
char categoryChar = GetLevelCategoryDir(m_levelCategory)[0];
|
||||
auto& programs = programStorage->GetPrograms();
|
||||
// TODO: Find a better way to do that
|
||||
for (unsigned int i = 0; i <= 999; i++)
|
||||
{
|
||||
char file[MAX_FNAME];
|
||||
sprintf(file, "%c%.3d%.3d%.3d%.3d.txt", categoryChar, m_levelChap, m_levelRank, objRank, i);
|
||||
std::string filename = m_playerProfile->GetSaveFile(file);
|
||||
|
||||
if (i < programs.size())
|
||||
{
|
||||
programStorage->WriteProgram(programs[i].get(), filename.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CResourceManager::Remove(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Saves all programs of the robot.
|
||||
//! If a program does not exist, the corresponding file is destroyed.
|
||||
void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank)
|
||||
{
|
||||
if (objRank == -1) return;
|
||||
|
||||
if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return;
|
||||
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
if (type == OBJECT_HUMAN) return;
|
||||
|
||||
std::string dirname = filename;
|
||||
dirname = dirname.substr(0, dirname.find_last_of("/"));
|
||||
|
||||
char fn[MAX_FNAME]; //TODO: Refactor to std::string
|
||||
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())
|
||||
{
|
||||
programStorage->WriteProgram(programs[i].get(), fn);
|
||||
}
|
||||
else
|
||||
{
|
||||
CResourceManager::Remove(fn);
|
||||
}
|
||||
}
|
||||
programStorage->SaveAllUserPrograms(m_playerProfile->GetSaveFile(StrUtils::Format("%c%.3d%.3d", categoryChar, m_levelChap, m_levelRank)));
|
||||
}
|
||||
|
||||
//! Saves the stack of the program in execution of a robot
|
||||
|
@ -4579,7 +4383,7 @@ bool CRobotMain::IOIsBusy()
|
|||
}
|
||||
|
||||
//! Writes an object into the backup file
|
||||
void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj)
|
||||
void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std::string& programDir, int objRank)
|
||||
{
|
||||
if (obj->GetType() == OBJECT_FIX) return;
|
||||
|
||||
|
@ -4634,23 +4438,29 @@ 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) && obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
int run = dynamic_cast<CProgramStorageObject*>(obj)->GetProgramIndex(dynamic_cast<CProgrammableObject*>(obj)->GetCurrentProgram());
|
||||
if (run != -1)
|
||||
{
|
||||
line->AddParam("run", MakeUnique<CLevelParserParam>(run+1));
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
auto& programs = dynamic_cast<CProgramStorageObject*>(obj)->GetPrograms();
|
||||
for (unsigned int i = 0; i < programs.size(); i++)
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
if(programStorage->GetProgramStorageIndex() >= 0)
|
||||
{
|
||||
if (programs[i]->readOnly)
|
||||
programStorage->SaveAllProgramsForSavedScene(line, programDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Probably an object created after the scene started, not loaded from level file
|
||||
// This means it doesn't normally store programs so it doesn't have program storage id assigned
|
||||
programStorage->SetProgramStorageIndex(999-objRank); // Set something that won't collide with normal programs
|
||||
programStorage->SaveAllProgramsForSavedScene(line, programDir);
|
||||
programStorage->SetProgramStorageIndex(-1); // Disable again
|
||||
}
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
{
|
||||
int run = dynamic_cast<CProgramStorageObject*>(obj)->GetProgramIndex(dynamic_cast<CProgrammableObject*>(obj)->GetCurrentProgram());
|
||||
if (run != -1)
|
||||
{
|
||||
line->AddParam("scriptReadOnly" + boost::lexical_cast<std::string>(i+1), MakeUnique<CLevelParserParam>(true));
|
||||
line->AddParam("run", MakeUnique<CLevelParserParam>(run+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4663,6 +4473,8 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s
|
|||
ShowSaveIndicator(true);
|
||||
m_app->Render(); // update
|
||||
|
||||
std::string dirname = filename.substr(0, filename.find_last_of("/"));
|
||||
|
||||
CLevelParser levelParser(filename);
|
||||
CLevelParserLineUPtr line;
|
||||
|
||||
|
@ -4727,7 +4539,7 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s
|
|||
if (cargo != nullptr) // object transported?
|
||||
{
|
||||
line = MakeUnique<CLevelParserLine>("CreateFret");
|
||||
IOWriteObject(line.get(), cargo);
|
||||
IOWriteObject(line.get(), cargo, dirname, objRank++);
|
||||
levelParser.AddLine(std::move(line));
|
||||
}
|
||||
}
|
||||
|
@ -4738,17 +4550,15 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s
|
|||
if (power != nullptr) // battery transported?
|
||||
{
|
||||
line = MakeUnique<CLevelParserLine>("CreatePower");
|
||||
IOWriteObject(line.get(), power);
|
||||
IOWriteObject(line.get(), power, dirname, objRank++);
|
||||
levelParser.AddLine(std::move(line));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
line = MakeUnique<CLevelParserLine>("CreateObject");
|
||||
IOWriteObject(line.get(), obj);
|
||||
IOWriteObject(line.get(), obj, dirname, objRank++);
|
||||
levelParser.AddLine(std::move(line));
|
||||
|
||||
SaveFileScript(obj, filename.c_str(), objRank++);
|
||||
}
|
||||
try
|
||||
{
|
||||
|
@ -4809,7 +4619,7 @@ void CRobotMain::IOWriteSceneFinished()
|
|||
}
|
||||
|
||||
//! Resumes the game
|
||||
CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename, const std::string& objCounterText, float objectProgress, int objRank)
|
||||
CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank)
|
||||
{
|
||||
ObjectCreateParams params = CObject::ReadCreateParams(line);
|
||||
params.power = -1.0f;
|
||||
|
@ -4828,10 +4638,8 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename,
|
|||
{
|
||||
COldObject* oldObj = dynamic_cast<COldObject*>(obj);
|
||||
|
||||
oldObj->SetRotation(line->GetParam("angle")->AsPoint() * Math::DEG_TO_RAD); // Who decided to call this argument differently than in main scene files? :/
|
||||
// TODO: Also, why doesn't CStaticObject implement SetRotation?
|
||||
|
||||
oldObj->SetDefRank(objRank);
|
||||
oldObj->SetPosition(line->GetParam("pos")->AsPoint() * g_unit);
|
||||
oldObj->SetRotation(line->GetParam("angle")->AsPoint() * Math::DEG_TO_RAD);
|
||||
|
||||
for (int i = 1; i < OBJECTMAXPART; i++)
|
||||
{
|
||||
|
@ -4869,25 +4677,12 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename,
|
|||
automat->Start(run); // starts the film
|
||||
}
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
{
|
||||
if (run != -1)
|
||||
{
|
||||
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 = dynamic_cast<CProgramStorageObject*>(obj)->GetOrAddProgram(i);
|
||||
prog->readOnly = true;
|
||||
}
|
||||
}
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
if (!line->GetParam("programStorageIndex")->IsDefined()) // Backwards combatibility
|
||||
programStorage->SetProgramStorageIndex(objRank);
|
||||
programStorage->LoadAllProgramsForSavedScene(line, programDir);
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -4896,6 +4691,8 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename,
|
|||
//! Resumes some part of the game
|
||||
CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
||||
{
|
||||
std::string dirname = filename.substr(0, filename.find_last_of("/"));
|
||||
|
||||
CLevelParser levelParser(filename);
|
||||
levelParser.Load();
|
||||
int numObjects = levelParser.CountLines("CreateObject") + levelParser.CountLines("CreatePower") + levelParser.CountLines("CreateFret");
|
||||
|
@ -4926,19 +4723,19 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
|||
|
||||
if (line->GetCommand() == "CreateFret")
|
||||
{
|
||||
cargo = IOReadObject(line.get(), filename.c_str(), StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), -1);
|
||||
cargo = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects));
|
||||
objCounter++;
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "CreatePower")
|
||||
{
|
||||
power = IOReadObject(line.get(), filename.c_str(), StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), -1);
|
||||
power = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects));
|
||||
objCounter++;
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "CreateObject")
|
||||
{
|
||||
CObject* obj = IOReadObject(line.get(), filename.c_str(), StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), objRank++);
|
||||
CObject* obj = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), objRank++);
|
||||
|
||||
if (line->GetParam("select")->AsBool(false))
|
||||
sel = obj;
|
||||
|
@ -4966,42 +4763,6 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
|||
}
|
||||
}
|
||||
|
||||
// Compiles scripts.
|
||||
m_ui->GetLoadingScreen()->SetProgress(0.75f, RT_LOADING_PROGRAMS);
|
||||
numObjects = m_objMan->CountObjectsImplementing(ObjectInterfaceType::Programmable);
|
||||
objCounter = 0;
|
||||
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (! obj->Implements(ObjectInterfaceType::Programmable)) continue;
|
||||
|
||||
float objectProgress = static_cast<float>(objCounter) / static_cast<float>(numObjects);
|
||||
m_ui->GetLoadingScreen()->SetProgress(0.75f+objectProgress*0.2f, RT_LOADING_PROGRAMS, "for object "+StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects));
|
||||
objCounter++;
|
||||
|
||||
if (IsObjectBeingTransported(obj)) continue; // TODO: WTF, programmable transportable objects?
|
||||
|
||||
objRank = obj->GetDefRank();
|
||||
if (objRank == -1) continue;
|
||||
|
||||
LoadFileScript(obj, filename.c_str(), objRank);
|
||||
}
|
||||
|
||||
// Starts scripts
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (! obj->Implements(ObjectInterfaceType::Programmable)) continue;
|
||||
if (obj->GetDefRank() == -1) continue;
|
||||
|
||||
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
|
||||
|
||||
Program* program = programmable->GetScriptRun();
|
||||
if (program != nullptr)
|
||||
{
|
||||
programmable->RunProgram(program); // starts the program
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->GetLoadingScreen()->SetProgress(0.95f, RT_LOADING_CBOT_SAVE);
|
||||
|
||||
// Reads the file of stacks of execution.
|
||||
|
|
|
@ -273,12 +273,8 @@ public:
|
|||
void StartShowLimit();
|
||||
void FrameShowLimit(float rTime);
|
||||
|
||||
void CompileScript(bool soluce);
|
||||
void LoadOneScript(CObject *pObj);
|
||||
void LoadFileScript(CObject *pObj, const char* filename, int objRank);
|
||||
void SaveAllScript();
|
||||
void SaveOneScript(CObject *pObj);
|
||||
void SaveFileScript(CObject *pObj, const char* filename, int objRank);
|
||||
bool SaveFileStack(CObject *pObj, FILE *file, int objRank);
|
||||
bool ReadFileStack(CObject *pObj, FILE *file, int objRank);
|
||||
|
||||
|
@ -293,8 +289,8 @@ public:
|
|||
bool IOWriteScene(std::string filename, std::string filecbot, std::string filescreenshot, char *info);
|
||||
void IOWriteSceneFinished();
|
||||
CObject* IOReadScene(std::string filename, std::string filecbot);
|
||||
void IOWriteObject(CLevelParserLine *line, CObject* obj);
|
||||
CObject* IOReadObject(CLevelParserLine *line, const char* filename, const std::string& objCounterText, float objectProgress, int objRank);
|
||||
void IOWriteObject(CLevelParserLine *line, CObject* obj, const std::string& programDir, int objRank);
|
||||
CObject* IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank = -1);
|
||||
|
||||
int CreateSpot(Math::Vector pos, Gfx::Color color);
|
||||
|
||||
|
|
|
@ -20,9 +20,15 @@
|
|||
#include "object/implementation/programmable_impl.h"
|
||||
|
||||
#include "common/global.h"
|
||||
#include "common/logger.h"
|
||||
#include "common/stringutils.h"
|
||||
|
||||
#include "common/resources/resourcemanager.h"
|
||||
|
||||
#include "level/robotmain.h"
|
||||
|
||||
#include "level/parser/parserline.h"
|
||||
|
||||
#include "math/all.h"
|
||||
|
||||
#include "object/object.h"
|
||||
|
@ -48,7 +54,9 @@ CProgramStorageObjectImpl::CProgramStorageObjectImpl(ObjectInterfaceTypes& types
|
|||
m_object(object),
|
||||
m_program(),
|
||||
m_activeVirus(false),
|
||||
m_soluceName("")
|
||||
m_soluceName(""),
|
||||
m_programStorageIndex(-1),
|
||||
m_allowProgramSave(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -193,33 +201,6 @@ 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)
|
||||
|
@ -244,3 +225,148 @@ bool CProgramStorageObjectImpl::WriteProgram(Program* program, const std::string
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CProgramStorageObjectImpl::SetProgramStorageIndex(int programStorageIndex)
|
||||
{
|
||||
m_programStorageIndex = programStorageIndex;
|
||||
}
|
||||
|
||||
int CProgramStorageObjectImpl::GetProgramStorageIndex()
|
||||
{
|
||||
return m_programStorageIndex;
|
||||
}
|
||||
|
||||
void CProgramStorageObjectImpl::SaveAllUserPrograms(const std::string& userSource)
|
||||
{
|
||||
if (!m_allowProgramSave) return;
|
||||
if (m_programStorageIndex < 0) return;
|
||||
GetLogger()->Debug("Saving user programs to '%s%.3d___.txt'\n", userSource.c_str(), m_programStorageIndex);
|
||||
|
||||
for (unsigned int i = 0; i <= 999; i++)
|
||||
{
|
||||
std::string filename = userSource + StrUtils::Format("%.3d%.3d.txt", m_programStorageIndex, i);
|
||||
|
||||
if (i < m_program.size() && !m_program[i]->loadedFromLevel)
|
||||
{
|
||||
GetLogger()->Trace("Loading program '%s' into user directory\n", filename.c_str());
|
||||
WriteProgram(m_program[i].get(), filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
CResourceManager::Remove(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CProgramStorageObjectImpl::LoadAllProgramsForLevel(CLevelParserLine* levelSource, const std::string& userSource, bool loadSoluce)
|
||||
{
|
||||
int run = levelSource->GetParam("run")->AsInt(0)-1;
|
||||
bool allFilled = true;
|
||||
for (int i = 0; i < 10 || allFilled; i++)
|
||||
{
|
||||
std::string op = "script" + StrUtils::ToString<int>(i+1); // script1..script10
|
||||
std::string opReadOnly = "scriptReadOnly" + StrUtils::ToString<int>(i+1); // scriptReadOnly1..scriptReadOnly10
|
||||
std::string opRunnable = "scriptRunnable" + StrUtils::ToString<int>(i+1); // scriptRunnable1..scriptRunnable10
|
||||
if (levelSource->GetParam(op)->IsDefined())
|
||||
{
|
||||
std::string filename = levelSource->GetParam(op)->AsPath("ai");
|
||||
GetLogger()->Trace("Loading program '%s' from level file\n", filename.c_str());
|
||||
Program* program = AddProgram();
|
||||
ReadProgram(program, filename);
|
||||
program->readOnly = levelSource->GetParam(opReadOnly)->AsBool(true);
|
||||
program->runnable = levelSource->GetParam(opRunnable)->AsBool(true);
|
||||
program->loadedFromLevel = true;
|
||||
|
||||
if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run)
|
||||
{
|
||||
dynamic_cast<CProgrammableObject*>(m_object)->RunProgram(program);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allFilled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadSoluce && levelSource->GetParam("soluce")->IsDefined())
|
||||
{
|
||||
std::string filename = levelSource->GetParam("soluce")->AsPath("ai");
|
||||
GetLogger()->Trace("Loading program '%s' as soluce file\n", filename.c_str());
|
||||
Program* program = AddProgram();
|
||||
ReadProgram(program, filename);
|
||||
program->readOnly = true;
|
||||
program->runnable = false;
|
||||
program->loadedFromLevel = true;
|
||||
}
|
||||
|
||||
if (m_programStorageIndex >= 0)
|
||||
{
|
||||
GetLogger()->Debug("Loading user programs from '%s%.3d___.txt'\n", userSource.c_str(), m_programStorageIndex);
|
||||
for (unsigned int i = 0; i <= 999; i++)
|
||||
{
|
||||
std::string filename = userSource + StrUtils::Format("%.3d%.3d.txt", m_programStorageIndex, i);
|
||||
if (CResourceManager::Exists(filename))
|
||||
{
|
||||
Program* program = GetOrAddProgram(i);
|
||||
if(GetCompile(program)) continue; // If already loaded from level file, skip
|
||||
GetLogger()->Trace("Loading program '%s' from user directory\n", filename.c_str());
|
||||
ReadProgram(program, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CProgramStorageObjectImpl::SaveAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource)
|
||||
{
|
||||
levelSourceLine->AddParam("programStorageIndex", MakeUnique<CLevelParserParam>(m_programStorageIndex));
|
||||
assert(m_programStorageIndex != -1);
|
||||
|
||||
GetLogger()->Debug("Saving saved scene programs to '%s/prog%.3d___.txt'\n", levelSource.c_str(), m_programStorageIndex);
|
||||
for (int i = 0; i < 999; i++)
|
||||
{
|
||||
std::string filename = levelSource + StrUtils::Format("/prog%.3d%.3d.txt", m_programStorageIndex, i);
|
||||
if (i >= static_cast<int>(m_program.size()))
|
||||
{
|
||||
CResourceManager::Remove(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
levelSourceLine->AddParam("scriptReadOnly" + StrUtils::ToString<int>(i+1), MakeUnique<CLevelParserParam>(m_program[i]->readOnly));
|
||||
levelSourceLine->AddParam("scriptRunnable" + StrUtils::ToString<int>(i+1), MakeUnique<CLevelParserParam>(m_program[i]->runnable));
|
||||
GetLogger()->Trace("Saving program '%s' to saved scene\n", filename.c_str());
|
||||
WriteProgram(m_program[i].get(), filename);
|
||||
}
|
||||
}
|
||||
|
||||
void CProgramStorageObjectImpl::LoadAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource)
|
||||
{
|
||||
m_programStorageIndex = levelSourceLine->GetParam("programStorageIndex")->AsInt(-1);
|
||||
if(m_programStorageIndex == -1) return;
|
||||
|
||||
GetLogger()->Debug("Loading saved scene programs from '%s/prog%.3d___.txt'\n", levelSource.c_str(), m_programStorageIndex);
|
||||
int run = levelSourceLine->GetParam("run")->AsInt(0)-1;
|
||||
for (int i = 0; i <= 999; i++)
|
||||
{
|
||||
std::string opReadOnly = "scriptReadOnly" + StrUtils::ToString<int>(i+1); // scriptReadOnly1..scriptReadOnly10
|
||||
std::string opRunnable = "scriptRunnable" + StrUtils::ToString<int>(i+1); // scriptRunnable1..scriptRunnable10
|
||||
|
||||
std::string filename = levelSource + StrUtils::Format("/prog%.3d%.3d.txt", m_programStorageIndex, i);
|
||||
if (CResourceManager::Exists(filename))
|
||||
{
|
||||
GetLogger()->Trace("Loading program '%s' from saved scene\n", filename.c_str());
|
||||
Program* program = GetOrAddProgram(i);
|
||||
ReadProgram(program, filename);
|
||||
program->readOnly = levelSourceLine->GetParam(opReadOnly)->AsBool(true);
|
||||
program->runnable = levelSourceLine->GetParam(opRunnable)->AsBool(true);
|
||||
|
||||
if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run)
|
||||
{
|
||||
dynamic_cast<CProgrammableObject*>(m_object)->RunProgram(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disable automatic user program storage now!!
|
||||
// This is to prevent overwriting auto-saved user programs with older versions from saved scenes
|
||||
m_allowProgramSave = false;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
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;
|
||||
|
@ -55,6 +54,16 @@ public:
|
|||
Program* GetProgram(int index) override;
|
||||
Program* GetOrAddProgram(int index) override;
|
||||
int GetProgramIndex(Program* program) override;
|
||||
|
||||
void SetProgramStorageIndex(int programStorageIndex) override;
|
||||
int GetProgramStorageIndex() override;
|
||||
|
||||
void SaveAllUserPrograms(const std::string& userSource) override;
|
||||
void LoadAllProgramsForLevel(CLevelParserLine* levelSource, const std::string& userSource, bool loadSoluce) override;
|
||||
|
||||
void SaveAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource) override;
|
||||
void LoadAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource) override;
|
||||
|
||||
private:
|
||||
CObject* m_object;
|
||||
|
||||
|
@ -64,4 +73,7 @@ private:
|
|||
bool m_activeVirus;
|
||||
|
||||
std::string m_soluceName;
|
||||
|
||||
int m_programStorageIndex;
|
||||
bool m_allowProgramSave;
|
||||
};
|
||||
|
|
|
@ -49,7 +49,6 @@ CProgrammableObjectImpl::CProgrammableObjectImpl(ObjectInterfaceTypes& types, CO
|
|||
m_activity(true),
|
||||
m_cmdLine(),
|
||||
m_currentProgram(nullptr),
|
||||
m_scriptRun(nullptr),
|
||||
m_traceRecord(false),
|
||||
m_traceOper(TO_STOP),
|
||||
m_traceAngle(0.0f),
|
||||
|
@ -137,16 +136,6 @@ bool CProgrammableObjectImpl::IsProgram()
|
|||
}
|
||||
|
||||
|
||||
void CProgrammableObjectImpl::SetScriptRun(Program* program)
|
||||
{
|
||||
m_scriptRun = program;
|
||||
}
|
||||
|
||||
Program* CProgrammableObjectImpl::GetScriptRun()
|
||||
{
|
||||
return m_scriptRun;
|
||||
}
|
||||
|
||||
// Load a stack of script implementation from a file.
|
||||
|
||||
bool CProgrammableObjectImpl::ReadStack(FILE *file)
|
||||
|
|
|
@ -57,9 +57,6 @@ public:
|
|||
Program* GetCurrentProgram() override;
|
||||
void StopProgram() override;
|
||||
|
||||
void SetScriptRun(Program* rank) override;
|
||||
Program* GetScriptRun() override;
|
||||
|
||||
bool ReadStack(FILE *file) override;
|
||||
bool WriteStack(FILE *file) override;
|
||||
|
||||
|
@ -92,8 +89,6 @@ private:
|
|||
|
||||
Program* m_currentProgram;
|
||||
|
||||
Program* m_scriptRun;
|
||||
|
||||
bool m_traceRecord;
|
||||
TraceOper m_traceOper;
|
||||
Math::Vector m_tracePos;
|
||||
|
|
|
@ -26,13 +26,14 @@
|
|||
#include <vector>
|
||||
|
||||
class CScript;
|
||||
class CLevelParserLine;
|
||||
|
||||
struct Program
|
||||
{
|
||||
std::unique_ptr<CScript> script;
|
||||
std::string filename;
|
||||
bool readOnly = false;
|
||||
bool runnable = true;
|
||||
bool loadedFromLevel = false;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -56,7 +57,6 @@ public:
|
|||
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;
|
||||
|
@ -71,4 +71,18 @@ public:
|
|||
virtual Program* GetProgram(int index) = 0;
|
||||
virtual Program* GetOrAddProgram(int index) = 0;
|
||||
virtual int GetProgramIndex(Program* program) = 0;
|
||||
|
||||
//! Set index for use in filename for saved programs (-1 to disable)
|
||||
virtual void SetProgramStorageIndex(int programStorageIndex) = 0;
|
||||
virtual int GetProgramStorageIndex() = 0;
|
||||
|
||||
//! Save all user programs
|
||||
virtual void SaveAllUserPrograms(const std::string& userSource) = 0;
|
||||
//! Load all programs when loading the level including previously saved user programs
|
||||
virtual void LoadAllProgramsForLevel(CLevelParserLine* levelSource, const std::string& userSource, bool loadSoluce) = 0;
|
||||
|
||||
//! Save all programs when saving the saved scene
|
||||
virtual void SaveAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource) = 0;
|
||||
//! Load all programs when loading the saved scene
|
||||
virtual void LoadAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource) = 0;
|
||||
};
|
||||
|
|
|
@ -48,9 +48,6 @@ public:
|
|||
virtual Program* GetCurrentProgram() = 0;
|
||||
virtual void StopProgram() = 0;
|
||||
|
||||
virtual void SetScriptRun(Program* rank) = 0;
|
||||
virtual Program* GetScriptRun() = 0;
|
||||
|
||||
virtual bool ReadStack(FILE *file) = 0;
|
||||
virtual bool WriteStack(FILE *file) = 0;
|
||||
|
||||
|
|
|
@ -1623,10 +1623,10 @@ void CObjectInterface::UpdateInterface()
|
|||
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_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_PROGREMOVE, !m_programmable->IsProgram() && m_selScript >= 0 && m_selScript < m_programStorage->GetProgramCount() && !m_programStorage->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract());
|
||||
EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_programmable->IsProgram() && m_selScript >= 0 && 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_PROGMOVEDOWN,!m_programmable->IsProgram() && m_programStorage->GetProgramCount() >= 2 && m_selScript >= 0 && 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);
|
||||
|
|
Loading…
Reference in New Issue