colobot/src/object/brain.cpp

3231 lines
89 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#include "object/brain.h"
#include "app/app.h"
#include "common/iman.h"
#include "common/misc.h"
#include "graphics/core/color.h"
#include "graphics/engine/terrain.h"
#include "object/object_manager.h"
#include "object/motion/motion.h"
#include "object/task/taskmanager.h"
#include "object/level/parserline.h"
#include "object/level/parserparam.h"
#include "physics/physics.h"
#include "script/cmdtoken.h"
#include "script/script.h"
#include "sound/sound.h"
#include "ui/interface.h"
#include "ui/slider.h"
#include "ui/studio.h"
#include "ui/window.h"
const int MAXTRACERECORD = 1000;
// Object's constructor.
CBrain::CBrain(CObject* object)
{
CInstanceManager::GetInstancePointer()->AddInstance(CLASS_BRAIN, this, 100);
m_object = object;
m_engine = Gfx::CEngine::GetInstancePointer();
m_water = m_engine->GetWater();
m_particle = m_engine->GetParticle();
m_main = CRobotMain::GetInstancePointer();
m_terrain = m_main->GetTerrain();
m_camera = m_main->GetCamera();
m_interface = m_main->GetInterface();
m_sound = CApplication::GetInstancePointer()->GetSound();
m_physics = nullptr;
m_motion = nullptr;
m_primaryTask = nullptr;
m_secondaryTask = nullptr;
m_studio = nullptr;
m_program.clear();
m_currentProgram = nullptr;
m_bActivity = true;
m_bBurn = false;
m_bActiveVirus = false;
m_time = 0.0f;
m_burnTime = 0.0f;
m_lastUpdateTime = 0.0f;
m_lastHumanTime = 0.0f;
m_lastWormTime = 0.0f;
m_antTarget = 0;
m_beeBullet = 0;
m_lastAlarmTime = 0.0f;
m_soundChannelAlarm = -1;
m_flagColor = 0;
m_buttonAxe = EVENT_NULL;
m_defaultEnter = EVENT_NULL;
m_manipStyle = EVENT_OBJECT_MFRONT;
m_scriptRun = nullptr;
m_soluceName[0] = 0;
m_selScript = 0;
m_bTraceRecord = false;
m_traceRecordBuffer = nullptr;
}
// Object's destructor.
CBrain::~CBrain()
{
for(auto x : m_program)
{
delete x->script;
x->script = nullptr;
delete x;
}
m_program.clear();
delete m_primaryTask;
m_primaryTask = nullptr;
delete m_secondaryTask;
m_secondaryTask = nullptr;
delete m_studio;
m_studio = nullptr;
delete[] m_traceRecordBuffer;
m_traceRecordBuffer = nullptr;
CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_BRAIN, this);
}
// Destroys the object.
void CBrain::DeleteObject(bool all)
{
if ( m_soundChannelAlarm != -1 )
{
m_sound->FlushEnvelope(m_soundChannelAlarm);
m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.5f, 0.5f, SOPER_STOP);
m_soundChannelAlarm = -1;
}
if ( !all )
{
if ( m_beeBullet != nullptr )
{
CObjectManager::GetInstancePointer()->DeleteObject(m_beeBullet);
m_beeBullet = nullptr;
}
}
if ( m_studio != 0 ) // current edition?
{
StopEditScript(true);
}
}
void CBrain::SetPhysics(CPhysics* physics)
{
m_physics = physics;
}
void CBrain::SetMotion(CMotion* motion)
{
m_motion = motion;
}
// Saves all parameters of the object.
bool CBrain::Write(CLevelParserLine* line)
{
line->AddParam("bVirusActive", CLevelParserParamUPtr{new CLevelParserParam(m_bActiveVirus)});
if ( m_object->GetType() == OBJECT_MOBILErs )
{
line->AddParam("bShieldActive", CLevelParserParamUPtr{new CLevelParserParam(m_secondaryTask != nullptr)});
}
return true;
}
// Restores all parameters of the object.
bool CBrain::Read(CLevelParserLine* line)
{
m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false);
if ( m_object->GetType() == OBJECT_MOBILErs )
{
if( line->GetParam("bShieldActive")->AsBool(false) )
{
StartTaskShield(TSM_START);
}
}
return true;
}
// Management of an event.
bool CBrain::EventProcess(const Event &event)
{
Ui::CWindow* pw;
Ui::CControl* pc;
Ui::CSlider* ps;
EventType action;
ObjectType type;
Error err;
float axeX, axeY, axeZ, factor;
type = m_object->GetType();
if ( m_primaryTask != 0 ) // current task?
{
m_primaryTask->EventProcess(event);
}
if ( m_secondaryTask != 0 ) // current task?
{
m_secondaryTask->EventProcess(event);
}
action = EVENT_NULL;
if ( event.type == EVENT_KEY_DOWN &&
event.key.slot == INPUT_SLOT_ACTION &&
!m_main->GetEditLock() )
{
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
pc = pw->SearchControl(m_defaultEnter);
if ( pc != 0 )
{
if ( pc->TestState(Ui::STATE_ENABLE) )
{
action = m_defaultEnter;
}
}
}
}
else
{
action = event.type;
}
if(event.type == EVENT_KEY_DOWN && m_object->GetSelect())
{
bool bControl = (event.kmodState & KEY_MOD(CTRL)) != 0;
bool bAlt = (event.kmodState & KEY_MOD(ALT)) != 0;
CEventQueue* queue = CApplication::GetInstancePointer()->GetEventQueue();
if(event.key.slot == INPUT_SLOT_ACTION && bControl)
{
Event newEvent = event;
newEvent.type = (m_studio == nullptr ? EVENT_OBJECT_PROGEDIT : EVENT_STUDIO_OK);
queue->AddEvent(newEvent);
return false;
}
if(event.key.slot == INPUT_SLOT_ACTION && bAlt)
{
Event newEvent = event;
newEvent.type = EVENT_OBJECT_PROGRUN;
queue->AddEvent(newEvent);
return false;
}
if(bAlt)
{
int index = GetSelScript();
if(event.key.slot == INPUT_SLOT_UP)
index--;
else if(event.key.slot == INPUT_SLOT_DOWN)
index++;
else if(event.key.key >= KEY(1) && event.key.key <= KEY(9))
index = event.key.key-KEY(1);
else if(event.key.key == KEY(0))
index = 9;
if(index < 0) index = m_program.size()-1;
if(index > static_cast<int>(m_program.size())-1) index = 0;
if(GetSelScript() != index)
{
SetSelScript(index);
Event newEvent = event;
newEvent.type = EVENT_OBJECT_PROGLIST;
queue->AddEvent(newEvent);
return false;
}
}
}
if ( action == EVENT_NULL ) return true;
if ( action == EVENT_UPDINTERFACE )
{
if ( m_object->GetSelect() ) CreateInterface(true);
}
if ( action == EVENT_FRAME )
{
EventFrame(event);
}
if ( m_object->GetSelect() && // robot selected?
m_studio != 0 ) // current issue?
{
m_studio->EventProcess(event);
if ( action == EVENT_OBJECT_PROGRUN )
{
if ( m_currentProgram == nullptr )
{
if(m_selScript < m_program.size())
{
RunProgram(m_program[m_selScript]);
}
}
else
{
StopProgram();
}
}
if ( action == EVENT_OBJECT_PROGSTART )
{
m_main->SaveOneScript(m_object);
if(m_selScript < m_program.size())
{
RunProgram(m_program[m_selScript]);
}
}
if ( action == EVENT_OBJECT_PROGSTOP )
{
StopProgram();
}
if ( action == EVENT_STUDIO_OK )
{
StopEditScript(false);
m_main->SaveOneScript(m_object);
}
if ( action == EVENT_STUDIO_CANCEL )
{
StopEditScript(true);
m_main->SaveOneScript(m_object);
}
if( action == EVENT_STUDIO_CLONE )
{
StopEditScript(false);
Program* newProgram = CloneProgram(m_program[m_selScript]);
m_selScript = m_program.size()-1;
m_main->SaveOneScript(m_object);
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
SetSelScript(m_selScript);
char text[] = "";
StartEditScript(newProgram, text);
std::string res;
GetResource(RES_TEXT, RT_STUDIO_CLONED, res);
m_studio->SetInfoText(res, false);
}
return true;
}
if ( !m_object->GetSelect() && // robot pas sélectionné ?
m_currentProgram == nullptr &&
m_primaryTask == 0 )
{
axeX = 0.0f;
axeY = 0.0f;
axeZ = 0.0f;
if ( m_object->GetBurn() ) // Gifted?
{
if ( !m_bBurn ) // beginning?
{
m_bBurn = true;
m_burnTime = 0.0f;
}
axeZ = -1.0f; // tomb
if ( !m_object->GetFixed() &&
(type == OBJECT_ANT ||
type == OBJECT_SPIDER ||
type == OBJECT_WORM ) )
{
axeY = 2.0f; // zigzag disorganized fast
if ( type == OBJECT_WORM ) axeY = 5.0f;
axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
sinf(m_time* 6.0f)*2.0f+
sinf(m_time*21.0f)*0.2f;
factor = 1.0f-m_burnTime/15.0f; // slow motion
if ( factor < 0.0f ) factor = 0.0f;
axeY *= factor;
axeX *= factor;
}
}
m_physics->SetMotorSpeedX(axeY); // move forward/move back
m_physics->SetMotorSpeedY(axeZ); // up / down
m_physics->SetMotorSpeedZ(axeX); // rotate
return true;
}
if ( m_currentProgram != nullptr &&
m_object->GetRuin() )
{
StopProgram();
return true;
}
if ( !m_object->GetSelect() ) // robot not selected?
{
return true;
}
if ( m_secondaryTask != 0 ) // current task?
{
if ( action == EVENT_OBJECT_ENDSHIELD )
{
m_secondaryTask->StartTaskShield(TSM_DOWN, 0.0f);
}
}
if ( m_primaryTask != 0 || // current task?
m_currentProgram != nullptr )
{
if ( action == EVENT_OBJECT_PROGRUN )
{
StopProgram();
}
if ( action == EVENT_OBJECT_PROGEDIT )
{
if(m_selScript < m_program.size())
{
StartEditScript(m_program[m_selScript], m_main->GetScriptName());
}
}
if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return true;
}
if ( m_currentProgram == nullptr )
{
if( action == EVENT_OBJECT_PROGADD )
{
AddProgram();
m_selScript = m_program.size()-1;
m_main->SaveOneScript(m_object);
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
SetSelScript(m_selScript);
}
if( action == EVENT_OBJECT_PROGREMOVE )
{
if(m_selScript < m_program.size())
{
RemoveProgram(m_program[m_selScript]);
if(m_selScript >= m_program.size())
m_selScript = m_program.size()-1;
m_main->SaveOneScript(m_object);
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
SetSelScript(m_selScript);
}
}
if( action == EVENT_OBJECT_PROGCLONE )
{
if(m_selScript < m_program.size())
{
CloneProgram(m_program[m_selScript]);
m_selScript = m_program.size()-1;
m_main->SaveOneScript(m_object);
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
SetSelScript(m_selScript);
}
}
if( action == EVENT_OBJECT_PROGMOVEUP )
{
std::iter_swap(m_program.begin() + m_selScript, m_program.begin() + m_selScript - 1);
m_selScript--;
m_main->SaveOneScript(m_object);
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
SetSelScript(m_selScript);
}
if( action == EVENT_OBJECT_PROGMOVEDOWN )
{
std::iter_swap(m_program.begin() + m_selScript, m_program.begin() + m_selScript + 1);
m_selScript++;
m_main->SaveOneScript(m_object);
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
SetSelScript(m_selScript);
}
}
if ( action == EVENT_OBJECT_LEFT ||
action == EVENT_OBJECT_RIGHT ||
action == EVENT_OBJECT_UP ||
action == EVENT_OBJECT_DOWN ||
action == EVENT_OBJECT_GASUP ||
action == EVENT_OBJECT_GASDOWN )
{
m_buttonAxe = action;
}
if ( action == EVENT_MOUSE_BUTTON_UP )
{
m_buttonAxe = EVENT_NULL;
}
axeX = event.motionInput.x;
axeY = event.motionInput.y;
axeZ = event.motionInput.z;
if ( !m_main->GetTrainerPilot() &&
m_object->GetTrainer() ) // drive vehicle?
{
axeX = 0.0f;
axeY = 0.0f;
axeZ = 0.0f; // Remote control impossible!
}
if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
if ( m_object->GetManual() ) // scribbler in manual mode?
{
if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
axeX *= 0.5f;
axeY *= 0.5f;
}
if ( (g_researchDone&RESEARCH_FLY) == 0 )
{
axeZ = -1.0f; // tomb
}
axeX += m_camera->GetMotorTurn(); // additional power according to camera
if ( axeX > 1.0f ) axeX = 1.0f;
if ( axeX < -1.0f ) axeX = -1.0f;
m_physics->SetMotorSpeedX(axeY); // move forward/move back
m_physics->SetMotorSpeedY(axeZ); // up/down
m_physics->SetMotorSpeedZ(axeX); // rotate
if ( action == EVENT_OBJECT_PROGLIST )
{
m_selScript = GetSelScript();
UpdateInterface();
}
if ( action == EVENT_OBJECT_PROGEDIT )
{
if(m_selScript < m_program.size())
{
StartEditScript(m_program[m_selScript], m_main->GetScriptName());
}
}
if ( action == EVENT_OBJECT_PROGRUN )
{
StopProgram(); // stops the current program
if(m_selScript < m_program.size())
{
RunProgram(m_program[m_selScript]);
}
UpdateInterface();
}
err = ERR_OK;
if ( m_currentProgram == nullptr )
{
if ( action == EVENT_OBJECT_HTAKE )
{
err = StartTaskTake();
}
if ( action == EVENT_OBJECT_MFRONT ||
action == EVENT_OBJECT_MBACK ||
action == EVENT_OBJECT_MPOWER )
{
m_manipStyle = action;
UpdateInterface();
}
if ( action == EVENT_OBJECT_MTAKE )
{
if ( m_manipStyle == EVENT_OBJECT_MFRONT )
{
err = StartTaskManip(TMO_AUTO, TMA_FFRONT);
}
if ( m_manipStyle == EVENT_OBJECT_MBACK )
{
err = StartTaskManip(TMO_AUTO, TMA_FBACK);
if ( err == ERR_OK )
{
m_manipStyle = EVENT_OBJECT_MFRONT;
UpdateInterface();
}
}
if ( m_manipStyle == EVENT_OBJECT_MPOWER )
{
err = StartTaskManip(TMO_AUTO, TMA_POWER);
if ( err == ERR_OK )
{
m_manipStyle = EVENT_OBJECT_MFRONT;
UpdateInterface();
}
}
}
if ( action == EVENT_OBJECT_BDERRICK )
{
err = StartTaskBuild(OBJECT_DERRICK);
}
if ( action == EVENT_OBJECT_BSTATION )
{
err = StartTaskBuild(OBJECT_STATION);
}
if ( action == EVENT_OBJECT_BFACTORY )
{
err = StartTaskBuild(OBJECT_FACTORY);
}
if ( action == EVENT_OBJECT_BREPAIR )
{
err = StartTaskBuild(OBJECT_REPAIR);
}
if ( action == EVENT_OBJECT_BCONVERT )
{
err = StartTaskBuild(OBJECT_CONVERT);
}
if ( action == EVENT_OBJECT_BTOWER )
{
err = StartTaskBuild(OBJECT_TOWER);
}
if ( action == EVENT_OBJECT_BRESEARCH )
{
err = StartTaskBuild(OBJECT_RESEARCH);
}
if ( action == EVENT_OBJECT_BRADAR )
{
err = StartTaskBuild(OBJECT_RADAR);
}
if ( action == EVENT_OBJECT_BENERGY )
{
err = StartTaskBuild(OBJECT_ENERGY);
}
if ( action == EVENT_OBJECT_BLABO )
{
err = StartTaskBuild(OBJECT_LABO);
}
if ( action == EVENT_OBJECT_BNUCLEAR )
{
err = StartTaskBuild(OBJECT_NUCLEAR);
}
if ( action == EVENT_OBJECT_BPARA )
{
err = StartTaskBuild(OBJECT_PARA);
}
if ( action == EVENT_OBJECT_BINFO )
{
err = StartTaskBuild(OBJECT_INFO);
}
if ( action == EVENT_OBJECT_BDESTROYER )
{
err = StartTaskBuild(OBJECT_DESTROYER);
}
if ( action == EVENT_OBJECT_GFLAT )
{
GroundFlat();
}
if ( action == EVENT_OBJECT_FCREATE )
{
err = StartTaskFlag(TFL_CREATE, m_flagColor);
}
if ( action == EVENT_OBJECT_FDELETE )
{
err = StartTaskFlag(TFL_DELETE, m_flagColor);
}
if ( action == EVENT_OBJECT_FCOLORb ||
action == EVENT_OBJECT_FCOLORr ||
action == EVENT_OBJECT_FCOLORg ||
action == EVENT_OBJECT_FCOLORy ||
action == EVENT_OBJECT_FCOLORv )
{
ColorFlag(action - EVENT_OBJECT_FCOLORb);
}
if ( action == EVENT_OBJECT_SEARCH )
{
err = StartTaskSearch();
}
if ( action == EVENT_OBJECT_DELSEARCH )
{
err = StartTaskDeleteMark();
}
if ( action == EVENT_OBJECT_TERRAFORM )
{
err = StartTaskTerraform();
}
if ( action == EVENT_OBJECT_RECOVER )
{
err = StartTaskRecover();
}
if ( action == EVENT_OBJECT_BEGSHIELD )
{
err = StartTaskShield(TSM_UP);
}
if ( action == EVENT_OBJECT_DIMSHIELD )
{
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
ps = static_cast< Ui::CSlider* >(pw->SearchControl(EVENT_OBJECT_DIMSHIELD));
if ( ps != 0 )
{
m_object->SetParam((ps->GetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
}
}
}
if ( action == EVENT_OBJECT_FIRE && m_primaryTask == 0 && !m_object->GetTrainer())
{
if ( m_camera->GetType() != Gfx::CAM_TYPE_ONBOARD )
{
m_camera->SetType(Gfx::CAM_TYPE_ONBOARD);
}
err = StartTaskFire(0.0f);
}
if ( action == EVENT_OBJECT_TARGET && !m_object->GetTrainer() )
{
err = StartTaskGunGoal((event.mousePos.y-0.50f)*1.3f, (event.mousePos.x-0.50f)*2.0f);
}
if ( action == EVENT_OBJECT_FIREANT )
{
//? err = StartTaskFireAnt();
}
if ( action == EVENT_OBJECT_SPIDEREXPLO && m_primaryTask == 0 )
{
err = StartTaskSpiderExplo();
}
if ( action == EVENT_OBJECT_PEN0 ) // up
{
err = StartTaskPen(false, m_object->GetTraceColor());
m_object->SetTraceDown(false);
}
if ( action == EVENT_OBJECT_PEN1 ) // black
{
err = StartTaskPen(true, 1);
m_object->SetTraceDown(true);
m_object->SetTraceColor(1);
}
if ( action == EVENT_OBJECT_PEN2 ) // yellow
{
err = StartTaskPen(true, 8);
m_object->SetTraceDown(true);
m_object->SetTraceColor(8);
}
if ( action == EVENT_OBJECT_PEN3 ) // orange
{
err = StartTaskPen(true, 7);
m_object->SetTraceDown(true);
m_object->SetTraceColor(7);
}
if ( action == EVENT_OBJECT_PEN4 ) // red
{
err = StartTaskPen(true, 4);
m_object->SetTraceDown(true);
m_object->SetTraceColor(4);
}
if ( action == EVENT_OBJECT_PEN5 ) // violet
{
err = StartTaskPen(true, 6);
m_object->SetTraceDown(true);
m_object->SetTraceColor(6);
}
if ( action == EVENT_OBJECT_PEN6 ) // blue
{
err = StartTaskPen(true, 14);
m_object->SetTraceDown(true);
m_object->SetTraceColor(14);
}
if ( action == EVENT_OBJECT_PEN7 ) // green
{
err = StartTaskPen(true, 12);
m_object->SetTraceDown(true);
m_object->SetTraceColor(12);
}
if ( action == EVENT_OBJECT_PEN8 ) // brown
{
err = StartTaskPen(true, 10);
m_object->SetTraceDown(true);
m_object->SetTraceColor(10);
}
if ( action == EVENT_OBJECT_REC ) // registered?
{
if ( m_bTraceRecord )
{
m_bTraceRecord = false;
TraceRecordStop();
}
else
{
m_bTraceRecord = true;
TraceRecordStart();
}
UpdateInterface();
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
}
if ( action == EVENT_OBJECT_STOP ) // stops?
{
if ( m_bTraceRecord )
{
m_bTraceRecord = false;
TraceRecordStop();
}
UpdateInterface();
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
}
if ( action == EVENT_OBJECT_RESET )
{
m_main->ResetObject(); // reset all objects
UpdateInterface();
}
#if 0
if ( event.param == 'T' )
{
Math::Vector p1, p2;
float h;
p1 = m_object->GetPosition(0);
h = m_terrain->GetFloorLevel(p1);
p2 = p1;
p1.x -= 20.0f;
p1.z -= 20.0f;
p2.x += 20.0f;
p2.z += 20.0f;
m_terrain->Terraform(p1, p2, h+1.0f);
}
if ( event.param == 'R' )
{
Math::Vector p1, p2;
float h;
p1 = m_object->GetPosition(0);
h = m_terrain->GetFloorLevel(p1);
p2 = p1;
p1.x -= 20.0f;
p1.z -= 20.0f;
p2.x += 20.0f;
p2.z += 20.0f;
m_terrain->Terraform(p1, p2, h-1.0f);
}
#endif
}
if ( err != ERR_OK )
{
m_main->DisplayError(err, m_object);
}
return true;
}
// The brain is changing by time.
bool CBrain::EventFrame(const Event &event)
{
m_time += event.rTime;
if ( m_bBurn ) m_burnTime += event.rTime;
if ( m_soundChannelAlarm != -1 )
{
m_sound->Position(m_soundChannelAlarm, m_object->GetPosition(0));
}
if ( m_studio != 0 ) // current edition?
{
m_studio->EventProcess(event);
}
UpdateInterface(event.rTime);
if ( m_engine->GetPause() ) return true;
if ( !m_bActivity ) return true; // expected if idle
if ( EndedTask() == ERR_CONTINUE ) return true; // expected if not finished ...
if ( m_currentProgram != nullptr ) // current program?
{
if ( m_currentProgram->script->Continue(event) )
{
StopProgram();
}
}
if ( m_bTraceRecord ) // registration of the design in progress?
{
TraceRecordFrame();
}
return true;
}
// Stops the running program.
void CBrain::StopProgram()
{
StopTask();
if ( m_object->GetType() == OBJECT_HUMAN ||
m_object->GetType() == OBJECT_TECH ) return;
if ( m_currentProgram != nullptr )
{
m_currentProgram->script->Stop();
}
BlinkScript(false); // stops flashing
m_currentProgram = nullptr;
m_physics->SetMotorSpeedX(0.0f);
m_physics->SetMotorSpeedY(0.0f);
m_physics->SetMotorSpeedZ(0.0f);
m_motion->SetAction(-1);
UpdateInterface();
m_main->UpdateShortcuts();
m_object->CreateSelectParticle();
}
// Stops the current task.
void CBrain::StopTask()
{
if (m_primaryTask != nullptr)
{
m_primaryTask->Abort();
delete m_primaryTask; // stops the current task
m_primaryTask = nullptr;
}
}
// Stops the current secondary task.
void CBrain::StopSecondaryTask()
{
if (m_secondaryTask != nullptr)
{
m_secondaryTask->Abort();
delete m_secondaryTask; // stops the current secondary task
m_secondaryTask = nullptr;
}
}
// Introduces a virus into a program.
// Returns true if it was inserted.
bool CBrain::IntroduceVirus()
{
int i, j;
for ( i=0 ; i<50 ; i++ )
{
j = rand()%m_program.size();
if ( m_program[j]->script->IntroduceVirus() ) // tries to introduce
{
m_bActiveVirus = 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 CBrain::SetActiveVirus(bool bActive)
{
m_bActiveVirus = bActive;
if ( !m_bActiveVirus ) // virus disabled?
{
m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
}
}
bool CBrain::GetActiveVirus()
{
return m_bActiveVirus;
}
// Start editing a program.
void CBrain::StartEditScript(Program* program, char* name)
{
CreateInterface(false); // removes the control buttons
m_studio = new Ui::CStudio();
m_studio->StartEditScript(program->script, name, program);
}
// End of editing a program.
void CBrain::StopEditScript(bool bCancel)
{
if ( !bCancel ) SetActiveVirus(false);
if ( !m_studio->StopEditScript(bCancel) ) return;
delete m_studio;
m_studio = 0;
CreateInterface(true); // puts the control buttons
}
// Move the manipulator arm.
Error CBrain::StartTaskTake()
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskTake();
UpdateInterface();
return err;
}
// Move the manipulator arm.
Error CBrain::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskManip(order, arm);
UpdateInterface();
return err;
}
// Puts or removes a flag.
Error CBrain::StartTaskFlag(TaskFlagOrder order, int rank)
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskFlag(order, rank);
UpdateInterface();
return err;
}
// Built a building.
Error CBrain::StartTaskBuild(ObjectType type)
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskBuild(type);
UpdateInterface();
return err;
}
// Probe the ground.
Error CBrain::StartTaskSearch()
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskSearch();
UpdateInterface();
return err;
}
// Delete mark on ground
Error CBrain::StartTaskDeleteMark()
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskDeleteMark();
UpdateInterface();
return err;
}
// Terraformed the ground.
Error CBrain::StartTaskTerraform()
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskTerraform();
UpdateInterface();
return err;
}
// Change pencil.
Error CBrain::StartTaskPen(bool down, int color)
{
m_physics->SetMotorSpeedX(0.0f);
m_physics->SetMotorSpeedY(0.0f);
m_physics->SetMotorSpeedZ(0.0f);
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskPen(down, color);
UpdateInterface();
return err;
}
// Recovers a ruin.
Error CBrain::StartTaskRecover()
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskRecover();
UpdateInterface();
return err;
}
// Deploys the shield.
Error CBrain::StartTaskShield(TaskShieldMode mode)
{
StopSecondaryTask();
m_secondaryTask = new CTaskManager(m_object);
Error err = m_secondaryTask->StartTaskShield(mode, 1000.0f);
UpdateInterface();
return err;
}
// Shoots.
Error CBrain::StartTaskFire(float delay)
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskFire(delay);
UpdateInterface();
return err;
}
// Explodes spider.
Error CBrain::StartTaskSpiderExplo()
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskSpiderExplo();
UpdateInterface();
return err;
}
// Shoots to the ant.
Error CBrain::StartTaskFireAnt(Math::Vector impact)
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskFireAnt(impact);
UpdateInterface();
return err;
}
// Adjusts upward.
Error CBrain::StartTaskGunGoal(float dirV, float dirH)
{
StopSecondaryTask();
m_secondaryTask = new CTaskManager(m_object);
Error err = m_secondaryTask->StartTaskGunGoal(dirV, dirH);
UpdateInterface();
return err;
}
// Reset.
Error CBrain::StartTaskReset(Math::Vector goal, Math::Vector angle)
{
StopTask();
m_primaryTask = new CTaskManager(m_object);
Error err = m_primaryTask->StartTaskReset(goal, angle);
UpdateInterface();
return err;
}
// Completes the task when the time came.
Error CBrain::EndedTask()
{
if (m_secondaryTask != nullptr) // current task?
{
Error err = m_secondaryTask->IsEnded();
if ( err != ERR_CONTINUE ) // job ended?
{
delete m_secondaryTask;
m_secondaryTask = nullptr;
UpdateInterface();
}
}
if (m_primaryTask != nullptr) // current task?
{
Error err = m_primaryTask->IsEnded();
if ( err != ERR_CONTINUE ) // job ended?
{
delete m_primaryTask;
m_primaryTask = nullptr;
UpdateInterface();
}
return err;
}
return ERR_STOP;
}
// Shows flat areas in the field.
void CBrain::GroundFlat()
{
Math::Vector pos, speed;
Math::Point dim;
Error err;
float level;
if ( !m_physics->GetLand() )
{
err = ERR_FLAG_FLY;
pos = m_object->GetPosition(0);
if ( pos.y < m_water->GetLevel() ) err = ERR_FLAG_WATER;
m_main->DisplayError(err, m_object);
return;
}
pos = m_object->GetPosition(0);
m_terrain->ShowFlatGround(pos);
m_sound->Play(SOUND_GFLAT, pos);
level = m_terrain->GetFloorLevel(pos)+2.0f;
if ( pos.y < level ) pos.y = level; // not below the soil
speed = Math::Vector(0.0f, 0.0f, 0.0f);
dim.x = 40.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGFLAT, 1.0f);
}
// Not below the soil.
void CBrain::ColorFlag(int color)
{
m_flagColor = color;
UpdateInterface();
}
// Creates all the interface when the object is selected.
bool CBrain::CreateInterface(bool bSelect)
{
ObjectType type;
Ui::CWindow* pw;
Ui::CButton* pb;
Ui::CSlider* ps;
Ui::CColor* pc;
Ui::CTarget* pt;
Ui::CLabel* pl;
Math::Point pos, dim, ddim;
float ox, oy, sx, sy;
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
pw->Flush(); // destroys the window buttons
m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
}
m_defaultEnter = EVENT_NULL;
if ( !bSelect ) return true;
pos.x = 0.0f;
pos.y = 0.0f;
dim.x = 540.0f/640.0f;
if ( !m_main->GetShowMap() ) dim.x = 640.0f/640.0f;
dim.y = 86.0f/480.0f;
m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return false;
std::string tooltipLabel;
m_object->GetTooltipName(tooltipLabel);
pos.x = 0.0f;
pos.y = 64.0f/480.0f;
ddim.x = 540.0f/640.0f;
if ( !m_main->GetShowMap() ) ddim.x = 640.0f/640.0f;
ddim.y = 16.0f/480.0f;
pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, tooltipLabel);
dim.x = 33.0f/640.0f;
dim.y = 33.0f/480.0f;
ox = 3.0f/640.0f;
oy = 3.0f/480.0f;
sx = 33.0f/640.0f;
sy = 33.0f/480.0f;
type = m_object->GetType();
if ( type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEta ||
type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia ||
type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEtc ||
type == OBJECT_MOBILEwc ||
type == OBJECT_MOBILEic ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEti ||
type == OBJECT_MOBILEwi ||
type == OBJECT_MOBILEii ||
type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEts ||
type == OBJECT_MOBILEws ||
type == OBJECT_MOBILEis ||
type == OBJECT_MOBILErt ||
type == OBJECT_MOBILErc ||
type == OBJECT_MOBILErr ||
type == OBJECT_MOBILErs ||
type == OBJECT_MOBILEsa ||
type == OBJECT_MOBILEtg ||
type == OBJECT_MOBILEft ||
type == OBJECT_MOBILEtt ||
type == OBJECT_MOBILEwt ||
type == OBJECT_MOBILEit ||
type == OBJECT_MOBILEdr ||
type == OBJECT_MOTHER ||
type == OBJECT_ANT ||
type == OBJECT_SPIDER ||
type == OBJECT_BEE ||
type == OBJECT_WORM ||
type == OBJECT_CONTROLLER) // vehicle?
{
if (!(m_main->GetRetroMode()))
{
ddim.x = dim.x*5.1f;
ddim.y = dim.y*1.5f;
pos.x = ox+sx*0.0f;
pos.y = oy+sy*0.5f;
pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, -1.10f);
UpdateScript(pw);
ddim.y = dim.y*0.5f;
pos.y = oy+sy*0.0f;
ddim.x = dim.x*1.1f;
pos.x = ox+sx*0.0f;
pw->CreateButton(pos, ddim, 24, EVENT_OBJECT_PROGADD);
ddim.x = dim.x*1.0f;
pos.x = ox+sx*1.1f;
pw->CreateButton(pos, ddim, 25, EVENT_OBJECT_PROGREMOVE);
pos.x = ox+sx*2.1f;
pw->CreateButton(pos, ddim, 61, EVENT_OBJECT_PROGCLONE);
pos.x = ox+sx*3.1f;
pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_PROGMOVEUP);
pos.x = ox+sx*4.1f;
pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_PROGMOVEDOWN);
pos.x = ox+sx*5.2f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, dim, 8, EVENT_OBJECT_PROGRUN);
pos.y = oy+sy*0.0f;
pw->CreateButton(pos, dim, 22, EVENT_OBJECT_PROGEDIT);
}
}
if ( type == OBJECT_HUMAN ||
type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEft ||
type == OBJECT_BEE ||
type == OBJECT_CONTROLLER) // driving?
{
pos.x = ox+sx*6.4f;
pos.y = oy+sy*0;
pb = pw->CreateButton(pos, dim, 29, EVENT_OBJECT_GASDOWN);
pb->SetImmediat(true);
pos.x = ox+sx*6.4f;
pos.y = oy+sy*1;
pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP);
pb->SetImmediat(true);
if ( (type != OBJECT_HUMAN &&
type != OBJECT_CONTROLLER) ||
m_object->GetOption() != 2 )
{
pos.x = ox+sx*15.3f;
pos.y = oy+sy*0;
ddim.x = 14.0f/640.0f;
ddim.y = 66.0f/480.0f;
pw->CreateGauge(pos, ddim, 2, EVENT_OBJECT_GRANGE);
}
}
if ( type == OBJECT_HUMAN ||
type == OBJECT_TECH )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 31, EVENT_OBJECT_HTAKE);
DefaultEnter(pw, EVENT_OBJECT_HTAKE);
}
if ( (type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEta ||
type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia ) && // arm?
!m_object->GetTrainer() )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
DefaultEnter(pw, EVENT_OBJECT_MTAKE);
pos.x = ox+sx*8.9f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 34, EVENT_OBJECT_MBACK);
pos.x = ox+sx*9.9f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 35, EVENT_OBJECT_MPOWER);
pos.x = ox+sx*10.9f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 33, EVENT_OBJECT_MFRONT);
}
if ( ( type == OBJECT_MOBILEsa && // underwater?
!m_object->GetTrainer() ) ||
type == OBJECT_BEE )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
DefaultEnter(pw, EVENT_OBJECT_MTAKE);
}
if ( type == OBJECT_HUMAN ) // builder?
{
pos.x = 1.0f/640.0f;
pos.y = 4.0f/480.0f;
ddim.x = 212.0f/640.0f;
ddim.y = 64.0f/480.0f;
pw->CreateGroup(pos, ddim, 27, EVENT_NULL);
ddim.x = dim.x*0.9f;
ddim.y = dim.y*0.9f;
pos.x = ox+sx*0.0f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH);
DeadInterface(pw, EVENT_OBJECT_BRESEARCH, g_build&BUILD_RESEARCH);
pos.x = ox+sx*0.9f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY);
DeadInterface(pw, EVENT_OBJECT_BFACTORY, g_build&BUILD_FACTORY);
pos.x = ox+sx*1.8f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT);
DeadInterface(pw, EVENT_OBJECT_BCONVERT, g_build&BUILD_CONVERT);
pos.x = ox+sx*2.7f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION);
DeadInterface(pw, EVENT_OBJECT_BSTATION, g_build&BUILD_STATION);
pos.x = ox+sx*3.6f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR);
DeadInterface(pw, EVENT_OBJECT_BRADAR, g_build&BUILD_RADAR);
pos.x = ox+sx*4.5f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR);
DeadInterface(pw, EVENT_OBJECT_BREPAIR, g_build&BUILD_REPAIR);
pos.x = ox+sx*5.4f;
pos.y = oy+sy*1.0f;
pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO);
DeadInterface(pw, EVENT_OBJECT_BINFO, g_build&BUILD_INFO);
pos.x = ox+sx*0.0f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER);
DeadInterface(pw, EVENT_OBJECT_BTOWER,
(g_build&BUILD_TOWER) &&
(g_researchDone & RESEARCH_TOWER));
pos.x = ox+sx*0.9f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY);
DeadInterface(pw, EVENT_OBJECT_BENERGY, g_build&BUILD_ENERGY);
pos.x = ox+sx*1.8f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK);
DeadInterface(pw, EVENT_OBJECT_BDERRICK, g_build&BUILD_DERRICK);
pos.x = ox+sx*2.7f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR);
DeadInterface(pw, EVENT_OBJECT_BNUCLEAR,
(g_build&BUILD_NUCLEAR) &&
(g_researchDone & RESEARCH_ATOMIC));
pos.x = ox+sx*3.6f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO);
DeadInterface(pw, EVENT_OBJECT_BLABO, g_build&BUILD_LABO);
pos.x = ox+sx*4.5f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA);
DeadInterface(pw, EVENT_OBJECT_BPARA, g_build&BUILD_PARA);
pos.x = ox+sx*5.4f;
pos.y = oy+sy*0.1f;
pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BDESTROYER);
DeadInterface(pw, EVENT_OBJECT_BDESTROYER, g_build&BUILD_DESTROYER);
if ( g_build&BUILD_GFLAT )
{
pos.x = ox+sx*9.0f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT);
}
if ( g_build&BUILD_FLAG )
{
pos.x = ox+sx*10.1f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE);
pos.x = ox+sx*11.1f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE);
ddim.x = dim.x*0.4f;
ddim.y = dim.y*0.4f;
pos.x = ox+sx*10.1f;
pos.y = oy+sy*2.0f-ddim.y;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb);
pc->SetColor(Gfx::Color(0.28f, 0.56f, 1.0f, 0.0f));
pos.x += ddim.x;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr);
pc->SetColor(Gfx::Color(1.0f, 0.0f, 0.0f, 0.0f));
pos.x += ddim.x;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg);
pc->SetColor(Gfx::Color(0.0f, 0.8f, 0.0f, 0.0f));
pos.x += ddim.x;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy);
pc->SetColor(Gfx::Color(1.0f, 0.93f, 0.0f, 0.0f)); //0x00ffec00
pos.x += ddim.x;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv);
pc->SetColor(Gfx::Color(0.82f, 0.004f, 0.99f, 0.0f)); //0x00d101fe
}
}
if ( (type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEts ||
type == OBJECT_MOBILEws ||
type == OBJECT_MOBILEis ) && // Investigator?
!m_object->GetTrainer() )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH);
DefaultEnter(pw, EVENT_OBJECT_SEARCH);
if ( g_build&BUILD_GFLAT )
{
pos.x = ox+sx*9.0f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 111, EVENT_OBJECT_GFLAT);
}
pos.x = ox+sx*10.1f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 11, EVENT_OBJECT_DELSEARCH);
}
if ( type == OBJECT_MOBILErt && // Terraformer?
!m_object->GetTrainer() )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_TERRAFORM);
DefaultEnter(pw, EVENT_OBJECT_TERRAFORM);
pos.x = ox+sx*10.2f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
}
if ( type == OBJECT_MOBILErr && // recoverer?
!m_object->GetTrainer() )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_RECOVER);
DefaultEnter(pw, EVENT_OBJECT_RECOVER);
}
if ( type == OBJECT_MOBILErs && // shield?
!m_object->GetTrainer() )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 39, EVENT_OBJECT_BEGSHIELD);
DefaultEnter(pw, EVENT_OBJECT_BEGSHIELD);
pos.x = ox+sx*9.0f;
pos.y = oy+sy*0.5f;
pw->CreateButton(pos, dim, 47, EVENT_OBJECT_ENDSHIELD);
//? pos.x = ox+sx*10.2f;
//? pos.y = oy+sy*0.5f;
//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
pos.x = ox+sx*10.5f;
pos.y = oy+sy*0.0f;
ddim.x = dim.x*0.5f;
ddim.y = dim.y*2.0f;
ps = pw->CreateSlider(pos, ddim, 0, EVENT_OBJECT_DIMSHIELD);
ps->SetState(Ui::STATE_VALUE);
ps->SetLimit((RADIUS_SHIELD_MIN/g_unit), (RADIUS_SHIELD_MAX/g_unit));
ps->SetArrowStep(1.0f);
}
if ( (type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEtc ||
type == OBJECT_MOBILEwc ||
type == OBJECT_MOBILEic ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEti ||
type == OBJECT_MOBILEwi ||
type == OBJECT_MOBILEii ||
type == OBJECT_MOBILErc ) && // cannon?
!m_object->GetTrainer() )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_FIRE);
pb->SetImmediat(true);
DefaultEnter(pw, EVENT_OBJECT_FIRE);
//? pos.x = ox+sx*10.2f;
//? pos.y = oy+sy*0.5f;
//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
}
if ( type == OBJECT_SPIDER )
{
pos.x = ox+sx*7.7f;
pos.y = oy+sy*0.5f;
pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_SPIDEREXPLO);
pb->SetImmediat(true);
DefaultEnter(pw, EVENT_OBJECT_SPIDEREXPLO);
}
if ( type == OBJECT_MOBILEdr &&
m_object->GetManual() ) // scribbler in manual mode?
{
pos.x = ox+sx*6.9f;
pos.y = oy+sy*0.0f;
ddim.x = dim.x*2.2f;
ddim.y = dim.y*2.0f;
pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
pos.x = ox+sx*9.3f;
pos.y = oy+sy*0.0f;
ddim.x = dim.x*2.2f;
ddim.y = dim.y*2.0f;
pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
pos.x = ox+sx*9.90f;
pos.y = oy+sy*0.50f;
pw->CreateButton(pos, dim, 43, EVENT_OBJECT_PEN0);
ddim.x = dim.x*0.5f;
ddim.y = dim.y*0.5f;
pos.x = ox+sx*10.15f;
pos.y = oy+sy*1.50f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN1); // black
pc->SetColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f));
pos.x = ox+sx*10.65f;
pos.y = oy+sy*1.25f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN2); // yellow
pc->SetColor(Gfx::Color(1.0f, 1.0f, 0.0f, 0.0f ));
pos.x = ox+sx*10.90f;
pos.y = oy+sy*0.75f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN3); // orange
pc->SetColor(Gfx::Color(1.0f, 0.53f, 0x00, 0x00));
pos.x = ox+sx*10.65f;
pos.y = oy+sy*0.25f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN4); // red
pc->SetColor(Gfx::Color(1.0f, 0.0f, 0.0f, 0.0f));
pos.x = ox+sx*10.15f;
pos.y = oy+sy*0.00f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN5); // violet
pc->SetColor(Gfx::Color(1.0f, 0.0f, 1.0f, 0.0f));
pos.x = ox+sx*9.65f;
pos.y = oy+sy*0.25f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN6); // blue
pc->SetColor(Gfx::Color(0.0f, 0.4f, 1.0f, 0.0f));//0x000066ff));
pos.x = ox+sx*9.40f;
pos.y = oy+sy*0.75f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN7); // green
pc->SetColor(Gfx::Color(0.0f, 0.0f, 0.8f, 0.0f));//0x0000cc00));
pos.x = ox+sx*9.65f;
pos.y = oy+sy*1.25f;
pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN8); // brown
pc->SetColor(Gfx::Color(0.53f, 0.27f, 0.0f, 0.0f));//0x00884400));
pos.x = ox+sx*6.9f;
pos.y = oy+sy*1.2f;
ddim.x = dim.x*2.2f;
ddim.y = dim.y*0.4f;
std::string recordLabel;
GetResource(RES_TEXT, RT_INTERFACE_REC, recordLabel);
pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, recordLabel);
pl->SetFontSize(9.0f);
pos.x = ox+sx*7.0f;
pos.y = oy+sy*0.3f;
pw->CreateButton(pos, dim, 44, EVENT_OBJECT_REC);
pos.x = ox+sx*8.0f;
pos.y = oy+sy*0.3f;
pw->CreateButton(pos, dim, 45, EVENT_OBJECT_STOP);
}
if ( m_object->GetToy() )
{
pos.x = ox+sx*12.1f;
pos.y = oy+sy*-0.1f;
ddim.x = dim.x*1.2f;
ddim.y = dim.y*2.1f;
pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
pos.x = ox+sx*12.2f;
pos.y = oy+sy*1;
pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
pos.x = ox+sx*12.2f;
pos.y = oy+sy*0.0f;
pw->CreateButton(pos, dim, 128+57, EVENT_OBJECT_BHELP);
}
else
{
pos.x = ox+sx*12.3f;
pos.y = oy+sy*-0.1f;
ddim.x = dim.x*1.0f;
ddim.y = dim.y*2.1f;
pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
pos.x = ox+sx*12.3f;
pos.y = oy+sy*1;
pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
pos.x = ox+sx*12.4f;
pos.y = oy+sy*0.5f;
ddim.x = dim.x*0.8f;
ddim.y = dim.y*0.5f;
pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
pos.y = oy+sy*0.0f;
pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
}
if ( type != OBJECT_HUMAN &&
type != OBJECT_TECH &&
!m_object->GetCameraLock() )
{
//? if ( m_main->GetShowMap() )
if ( true )
{
pos.x = ox+sx*13.4f;
pos.y = oy+sy*1;
pw->CreateButton(pos, dim, 13, EVENT_OBJECT_CAMERA);
}
else
{
ddim.x = dim.x*0.66f;
ddim.y = dim.y*0.66f;
pos.x = ox+sx*(17.0f+0.66f);
pos.y = oy+sy*0.66f;
pw->CreateButton(pos, ddim, 13, EVENT_OBJECT_CAMERA);
}
}
if ( m_object->GetToy() && !m_object->GetManual() )
{
#if 0
ddim.x = dim.x*0.66f;
ddim.y = dim.y*0.66f;
pos.x = ox+sx*10.0f;
pos.y = oy+sy*0.66f;
pb = pw->CreateButton(pos, ddim, 55, EVENT_OBJECT_CAMERAleft);
pb->SetImmediat(true);
pos.x = ox+sx*(10.0f+0.66f*2.0f);
pos.y = oy+sy*0.66f;
pb = pw->CreateButton(pos, ddim, 48, EVENT_OBJECT_CAMERAright);
pb->SetImmediat(true);
pos.x = ox+sx*(10.0f+0.66f);
pos.y = oy+sy*(0.66f*2.0f);
pb = pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_CAMERAnear);
pb->SetImmediat(true);
pos.x = ox+sx*(10.0f+0.66f);
pos.y = oy+sy*0.0f;
pb = pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_CAMERAaway);
pb->SetImmediat(true);
#else
pos.x = ox+sx*9.0f;
pos.y = oy+sy*0;
pb = pw->CreateButton(pos, dim, 55, EVENT_OBJECT_CAMERAleft);
pb->SetImmediat(true);
pos.x = ox+sx*11.0f;
pos.y = oy+sy*0;
pb = pw->CreateButton(pos, dim, 48, EVENT_OBJECT_CAMERAright);
pb->SetImmediat(true);
pos.x = ox+sx*10.0f;
pos.y = oy+sy*1;
pb = pw->CreateButton(pos, dim, 49, EVENT_OBJECT_CAMERAnear);
pb->SetImmediat(true);
pos.x = ox+sx*10.0f;
pos.y = oy+sy*0;
pb = pw->CreateButton(pos, dim, 50, EVENT_OBJECT_CAMERAaway);
pb->SetImmediat(true);
#endif
}
pos.x = ox+sx*13.4f;
pos.y = oy+sy*0;
if ( m_object->GetTrainer() ) // Training?
{
pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
}
else
{
pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
}
if ( type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEta ||
type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia ||
type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEtc ||
type == OBJECT_MOBILEwc ||
type == OBJECT_MOBILEic ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEti ||
type == OBJECT_MOBILEwi ||
type == OBJECT_MOBILEii ||
type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEts ||
type == OBJECT_MOBILEws ||
type == OBJECT_MOBILEis ||
type == OBJECT_MOBILErt ||
type == OBJECT_MOBILErc ||
type == OBJECT_MOBILErr ||
type == OBJECT_MOBILErs ||
type == OBJECT_MOBILEsa ||
type == OBJECT_MOBILEft ||
type == OBJECT_MOBILEtt ||
type == OBJECT_MOBILEwt ||
type == OBJECT_MOBILEit ) // vehicle?
{
pos.x = ox+sx*14.5f;
pos.y = oy+sy*0;
ddim.x = 14.0f/640.0f;
ddim.y = 66.0f/480.0f;
pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
}
if ( type == OBJECT_HUMAN ||
type == OBJECT_TECH ||
type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEta ||
type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia ||
type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEtc ||
type == OBJECT_MOBILEwc ||
type == OBJECT_MOBILEic ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEti ||
type == OBJECT_MOBILEwi ||
type == OBJECT_MOBILEii ||
type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEts ||
type == OBJECT_MOBILEws ||
type == OBJECT_MOBILEis ||
type == OBJECT_MOBILErt ||
type == OBJECT_MOBILErc ||
type == OBJECT_MOBILErr ||
type == OBJECT_MOBILErs ||
type == OBJECT_MOBILEsa ||
type == OBJECT_MOBILEtg ||
type == OBJECT_MOBILEft ||
type == OBJECT_MOBILEtt ||
type == OBJECT_MOBILEwt ||
type == OBJECT_MOBILEit ) // vehicle?
{
pos.x = ox+sx*14.9f;
pos.y = oy+sy*0;
ddim.x = 14.0f/640.0f;
ddim.y = 66.0f/480.0f;
pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
}
#if 0
if ( false )
{
pos.x = 505.0f/640.0f;
pos.y = 3.0f/480.0f;
ddim.x = 33.0f/640.0f;
ddim.y = 33.0f/480.0f;
pw->CreateCompass(pos, ddim, 0, EVENT_OBJECT_COMPASS);
pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
if ( pc != 0 )
{
pc->SetState(Ui::STATE_VISIBLE, m_main->GetShowMap());
}
}
#endif
if ( type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEtc ||
type == OBJECT_MOBILEwc ||
type == OBJECT_MOBILEic ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEti ||
type == OBJECT_MOBILEwi ||
type == OBJECT_MOBILEii ||
type == OBJECT_MOBILErc ) // cannon?
{
ddim.x = 64.0f/640.0f;
ddim.y = 64.0f/480.0f;
pos.x = 0.5f-ddim.x/2.0f;
pos.y = 0.5f-ddim.y/2.0f;
pw->CreateGroup(pos, ddim, 12, EVENT_OBJECT_CROSSHAIR);
pos.x = 20.0f/640.0f;
pos.y = 100.0f/480.0f;
ddim.x = 600.0f/640.0f;
ddim.y = 340.0f/480.0f;
pt = pw->CreateTarget(pos, ddim, 0, EVENT_OBJECT_TARGET);
pt->ClearState(Ui::STATE_GLINT);
}
ddim.x = 64.0f/640.0f;
ddim.y = 64.0f/480.0f;
pos.x = 30.0f/640.0f;
pos.y = 430.0f/480.0f-ddim.y;
pw->CreateGroup(pos, ddim, 13, EVENT_OBJECT_CORNERul);
ddim.x = 64.0f/640.0f;
ddim.y = 64.0f/480.0f;
pos.x = 610.0f/640.0f-ddim.x;
pos.y = 430.0f/480.0f-ddim.y;
pw->CreateGroup(pos, ddim, 14, EVENT_OBJECT_CORNERur);
ddim.x = 64.0f/640.0f;
ddim.y = 64.0f/480.0f;
pos.x = 30.0f/640.0f;
pos.y = 110.0f/480.0f;
pw->CreateGroup(pos, ddim, 15, EVENT_OBJECT_CORNERdl);
ddim.x = 64.0f/640.0f;
ddim.y = 64.0f/480.0f;
pos.x = 610.0f/640.0f-ddim.x;
pos.y = 110.0f/480.0f;
pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr);
UpdateInterface();
m_lastUpdateTime = 0.0f;
UpdateInterface(0.0f);
return true;
}
// Updates the state of all buttons on the interface,
// following the time that elapses ...
void CBrain::UpdateInterface(float rTime)
{
Ui::CWindow* pw;
Ui::CButton* pb;
Ui::CGauge* pg;
Ui::CCompass* pc;
Ui::CGroup* pgr;
Ui::CTarget* ptg;
CObject* power;
Math::Vector pos, hPos;
Math::Point ppos;
float energy, limit, angle, range;
int icon;
bool bOnBoard;
m_lastAlarmTime += rTime;
if ( m_time < m_lastUpdateTime+0.1f ) return;
m_lastUpdateTime = m_time;
if ( !m_object->GetSelect() )
{
if ( m_soundChannelAlarm != -1 )
{
m_sound->FlushEnvelope(m_soundChannelAlarm);
m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 1.0f, 0.1f, SOPER_STOP);
m_soundChannelAlarm = -1;
}
return;
}
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return;
pg = static_cast< Ui::CGauge* >(pw->SearchControl(EVENT_OBJECT_GENERGY));
if ( pg != 0 )
{
power = m_object->GetPower();
if ( power == 0 )
{
energy = 0.0f;
limit = 0.0f;
}
else
{
energy = power->GetEnergy();
limit = energy*power->GetCapacity();
}
icon = 0; // red/green
if ( limit < 0.2f && energy != 0.0f ) // low but not zero?
{
if ( m_lastAlarmTime >= 0.8f ) // blinks?
{
energy = 1.0f;
icon = 1; // brun
}
if ( m_lastAlarmTime >= 1.0f )
{
m_sound->Play(SOUND_ALARM, 0.5f); // bip-bip-bip
m_lastAlarmTime = 0.0f;
}
}
pg->SetLevel(energy);
pg->SetIcon(icon);
}
pg = static_cast< Ui::CGauge* >(pw->SearchControl(EVENT_OBJECT_GSHIELD));
if ( pg != 0 )
{
pg->SetLevel(m_object->GetShield());
}
pg = static_cast< Ui::CGauge* >(pw->SearchControl(EVENT_OBJECT_GRANGE));
if ( pg != 0 )
{
icon = 2; // blue/red
range = m_physics->GetReactorRange();
if ( range < 0.2f && range != 0.0f && !m_physics->GetLand() )
{
if ( Math::Mod(m_time, 0.5f) >= 0.2f ) // blinks?
{
range = 1.0f;
icon = 1; // yellow
}
if ( m_soundChannelAlarm == -1 )
{
m_soundChannelAlarm = m_sound->Play(SOUND_ALARMt, m_object->GetPosition(0), 0.0f, 0.1f, true);
m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_CONTINUE);
m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
}
}
else
{
if ( m_soundChannelAlarm != -1 )
{
m_sound->FlushEnvelope(m_soundChannelAlarm);
m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.1f, 1.0f, SOPER_STOP);
m_soundChannelAlarm = -1;
}
}
pg->SetLevel(1.0f-range);
pg->SetIcon(icon);
}
pc = static_cast< Ui::CCompass* >(pw->SearchControl(EVENT_OBJECT_COMPASS));
if ( pc != 0 )
{
angle = -(m_object->GetAngleY(0)+Math::PI/2.0f);
pc->SetDirection(angle);
pc->SetState(Ui::STATE_VISIBLE, m_main->GetShowMap());
}
pb = static_cast<Ui::CButton*>(pw->SearchControl(EVENT_OBJECT_REC));
if ( pb != 0 )
{
if ( m_bTraceRecord && Math::Mod(m_time, 0.4f) >= 0.2f )
{
pb->SetState(Ui::STATE_CHECK);
}
else
{
pb->ClearState(Ui::STATE_CHECK);
}
}
bOnBoard = m_camera->GetType() == Gfx::CAM_TYPE_ONBOARD;
pgr = static_cast< Ui::CGroup* >(pw->SearchControl(EVENT_OBJECT_CROSSHAIR));
if ( pgr != 0 )
{
if ( bOnBoard )
{
#if 0
angle = m_object->GetGunGoalV();
if ( m_object->GetType() != OBJECT_MOBILErc )
{
angle += 10.0f*Math::PI/360.0f;
}
ppos.x = 0.5f-(64.0f/640.0f)/2.0f;
ppos.y = 0.5f-(64.0f/480.0f)/2.0f;
ppos.y += sinf(angle)*0.6f;
pgr->SetPos(ppos);
#else
ppos.x = 0.50f-(64.0f/640.0f)/2.0f;
ppos.y = 0.50f-(64.0f/480.0f)/2.0f;
ppos.x += m_object->GetGunGoalH()/2.0f;
ppos.y += m_object->GetGunGoalV()/1.3f;
pgr->SetPos(ppos);
#endif
pgr->SetState(Ui::STATE_VISIBLE, !m_main->GetFriendAim());
}
else
{
pgr->ClearState(Ui::STATE_VISIBLE);
}
}
ptg = static_cast< Ui::CTarget* >(pw->SearchControl(EVENT_OBJECT_TARGET));
if ( ptg != 0 )
{
if ( bOnBoard )
{
ptg->SetState(Ui::STATE_VISIBLE);
}
else
{
ptg->ClearState(Ui::STATE_VISIBLE);
}
}
pgr = static_cast< Ui::CGroup* >(pw->SearchControl(EVENT_OBJECT_CORNERul));
if ( pgr != 0 )
{
pgr->SetState(Ui::STATE_VISIBLE, bOnBoard);
}
pgr = static_cast< Ui::CGroup* >(pw->SearchControl(EVENT_OBJECT_CORNERur));
if ( pgr != 0 )
{
pgr->SetState(Ui::STATE_VISIBLE, bOnBoard);
}
pgr = static_cast< Ui::CGroup* >(pw->SearchControl(EVENT_OBJECT_CORNERdl));
if ( pgr != 0 )
{
pgr->SetState(Ui::STATE_VISIBLE, bOnBoard);
}
pgr = static_cast< Ui::CGroup* >(pw->SearchControl(EVENT_OBJECT_CORNERdr));
if ( pgr != 0 )
{
pgr->SetState(Ui::STATE_VISIBLE, bOnBoard);
}
}
// Updates the status of all interface buttons.
void CBrain::UpdateInterface()
{
ObjectType type;
Ui::CWindow* pw;
Ui::CButton* pb;
Ui::CSlider* ps;
Ui::CColor* pc;
int color;
bool bEnable, bFly, bRun;
char title[100];
if ( !m_object->GetSelect() ) return;
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return;
type = m_object->GetType();
bEnable = ( m_secondaryTask == 0 && m_currentProgram == nullptr );
bEnable = ( m_primaryTask == 0 && m_currentProgram == nullptr );
EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord) && m_selScript < m_program.size());
EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord);
EnableInterface(pw, EVENT_OBJECT_PROGADD, m_currentProgram == nullptr);
EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, m_currentProgram == nullptr && m_selScript < m_program.size() && !m_program[m_selScript]->readOnly);
EnableInterface(pw, EVENT_OBJECT_PROGCLONE, m_currentProgram == nullptr && m_selScript < m_program.size() && m_program[m_selScript]->runnable);
EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, m_currentProgram == nullptr && m_program.size() >= 2 && m_selScript > 0);
EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,m_currentProgram == nullptr && m_program.size() >= 2 && m_selScript < m_program.size()-1);
EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable);
EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable);
EnableInterface(pw, EVENT_OBJECT_UP, bEnable);
EnableInterface(pw, EVENT_OBJECT_DOWN, bEnable);
EnableInterface(pw, EVENT_OBJECT_HTAKE, bEnable);
EnableInterface(pw, EVENT_OBJECT_MTAKE, bEnable);
EnableInterface(pw, EVENT_OBJECT_MBACK, bEnable);
EnableInterface(pw, EVENT_OBJECT_MPOWER, bEnable);
EnableInterface(pw, EVENT_OBJECT_MFRONT, bEnable);
EnableInterface(pw, EVENT_OBJECT_GFLAT, bEnable);
EnableInterface(pw, EVENT_OBJECT_FCREATE, bEnable);
EnableInterface(pw, EVENT_OBJECT_FDELETE, bEnable);
EnableInterface(pw, EVENT_OBJECT_SEARCH, bEnable);
EnableInterface(pw, EVENT_OBJECT_DELSEARCH, bEnable);
EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable);
EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable);
EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable);
EnableInterface(pw, EVENT_OBJECT_SPIDEREXPLO, bEnable);
EnableInterface(pw, EVENT_OBJECT_RESET, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN1, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN2, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN3, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN4, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN5, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN6, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN7, bEnable);
EnableInterface(pw, EVENT_OBJECT_PEN8, bEnable);
EnableInterface(pw, EVENT_OBJECT_REC, bEnable);
EnableInterface(pw, EVENT_OBJECT_STOP, bEnable);
if ( type == OBJECT_HUMAN ) // builder?
{
EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable);
EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable);
EnableInterface(pw, EVENT_OBJECT_BCONVERT, bEnable);
EnableInterface(pw, EVENT_OBJECT_BSTATION, bEnable);
EnableInterface(pw, EVENT_OBJECT_BREPAIR, bEnable);
EnableInterface(pw, EVENT_OBJECT_BTOWER, bEnable);
EnableInterface(pw, EVENT_OBJECT_BRESEARCH, bEnable);
EnableInterface(pw, EVENT_OBJECT_BRADAR, bEnable);
EnableInterface(pw, EVENT_OBJECT_BENERGY, bEnable);
EnableInterface(pw, EVENT_OBJECT_BLABO, bEnable);
EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable);
EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable);
EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable);
EnableInterface(pw, EVENT_OBJECT_BDESTROYER,bEnable);
}
pb = static_cast< Ui::CButton* >(pw->SearchControl(EVENT_OBJECT_GFLAT));
if ( pb != 0 )
{
pb->SetState(Ui::STATE_VISIBLE, m_engine->GetGroundSpot());
}
if ( type == OBJECT_HUMAN || // builder?
type == OBJECT_TECH )
{
CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0);
CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1);
CheckInterface(pw, EVENT_OBJECT_FCOLORg, m_flagColor==2);
CheckInterface(pw, EVENT_OBJECT_FCOLORy, m_flagColor==3);
CheckInterface(pw, EVENT_OBJECT_FCOLORv, m_flagColor==4);
}
if ( type == OBJECT_MOBILErs ) // shield?
{
if ( (m_secondaryTask == 0 || !m_secondaryTask->IsBusy()) && m_currentProgram == nullptr )
{
EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
}
else
{
EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, false);
EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, false);
DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, false);
DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, false);
}
ps = static_cast< Ui::CSlider* >(pw->SearchControl(EVENT_OBJECT_DIMSHIELD));
if ( ps != 0 )
{
ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+m_object->GetParam()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
}
}
bFly = bEnable;
if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) )
{
if ( m_object->GetFret() != 0 ) bFly = false; // if holder -> not fly
}
EnableInterface(pw, EVENT_OBJECT_GASUP, bFly);
EnableInterface(pw, EVENT_OBJECT_GASDOWN, bFly);
if ( m_object->GetTrainer() ) // Training?
{
DeadInterface(pw, EVENT_OBJECT_GASUP, false);
DeadInterface(pw, EVENT_OBJECT_GASDOWN, false);
}
else
{
DeadInterface(pw, EVENT_OBJECT_GASUP, g_researchDone&RESEARCH_FLY);
DeadInterface(pw, EVENT_OBJECT_GASDOWN, g_researchDone&RESEARCH_FLY);
}
if ( type == OBJECT_HUMAN ||
type == OBJECT_TECH ||
type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEta ||
type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia ||
type == OBJECT_MOBILEfc ||
type == OBJECT_MOBILEtc ||
type == OBJECT_MOBILEwc ||
type == OBJECT_MOBILEic ||
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEti ||
type == OBJECT_MOBILEwi ||
type == OBJECT_MOBILEii ||
type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEts ||
type == OBJECT_MOBILEws ||
type == OBJECT_MOBILEis ||
type == OBJECT_MOBILErt ||
type == OBJECT_MOBILErc ||
type == OBJECT_MOBILErr ||
type == OBJECT_MOBILErs ||
type == OBJECT_MOBILEsa ||
type == OBJECT_MOBILEtg ||
type == OBJECT_MOBILEft ||
type == OBJECT_MOBILEtt ||
type == OBJECT_MOBILEwt ||
type == OBJECT_MOBILEit ||
type == OBJECT_MOBILEdr ||
type == OBJECT_MOTHER ||
type == OBJECT_ANT ||
type == OBJECT_SPIDER ||
type == OBJECT_BEE ||
type == OBJECT_WORM ||
type == OBJECT_CONTROLLER) // vehicle?
{
bRun = false;
if ( m_selScript < m_program.size() )
{
if(m_program[m_selScript]->runnable)
{
m_program[m_selScript]->script->GetTitle(title);
if ( title[0] != 0 )
{
bRun = true;
}
}
else
{
bRun = false;
}
}
if ( !bEnable && m_currentProgram == nullptr ) bRun = false;
if ( m_bTraceRecord ) bRun = false;
EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun);
pb = static_cast< Ui::CButton* >(pw->SearchControl(EVENT_OBJECT_PROGRUN));
if ( pb != 0 )
{
pb->SetIcon(m_currentProgram==nullptr?21:8); // run/stop
}
//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT);
//? if ( pb != 0 )
//? {
//? pb->SetIcon(m_currentProgram==nullptr?22:40); // edit/debug
//? }
BlinkScript(m_currentProgram != nullptr); // blinks if script execution
}
if ( type == OBJECT_MOBILEfa ||
type == OBJECT_MOBILEta ||
type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia ) // arm?
{
CheckInterface(pw, EVENT_OBJECT_MPOWER, m_manipStyle==EVENT_OBJECT_MPOWER);
CheckInterface(pw, EVENT_OBJECT_MBACK, m_manipStyle==EVENT_OBJECT_MBACK);
CheckInterface(pw, EVENT_OBJECT_MFRONT, m_manipStyle==EVENT_OBJECT_MFRONT);
}
if ( m_object->GetTraceDown() )
{
pb = static_cast< Ui::CButton* >(pw->SearchControl(EVENT_OBJECT_PEN0));
if ( pb != 0 )
{
pb->ClearState(Ui::STATE_CHECK);
}
color = m_object->GetTraceColor();
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN1));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==1);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN2));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==8);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN3));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==7);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN4));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==4);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN5));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==6);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN6));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==14);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN7));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==12);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN8));
if ( pc != 0 )
{
pc->SetState(Ui::STATE_CHECK, color==10);
}
}
else
{
pb = static_cast< Ui::CButton* >(pw->SearchControl(EVENT_OBJECT_PEN0));
if ( pb != 0 )
{
pb->SetState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN1));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN2));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN3));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN4));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN5));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN6));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN7));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
pc = static_cast< Ui::CColor* >(pw->SearchControl(EVENT_OBJECT_PEN8));
if ( pc != 0 )
{
pc->ClearState(Ui::STATE_CHECK);
}
}
}
// Updates the list of programs.
void CBrain::UpdateScript(Ui::CWindow *pw)
{
Ui::CList* pl;
char name[100];
char title[100];
pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_PROGLIST));
if ( pl == 0 ) return;
pl->Flush();
for ( unsigned int i = 0 ; i < m_program.size() ; i++ )
{
sprintf(name, "%d", i+1);
m_program[i]->script->GetTitle(title);
if ( title[0] != 0 )
{
if(!m_program[i]->readOnly)
{
sprintf(name, "%d: %s", i+1, title);
}
else
{
sprintf(name, "*%d: %s", i+1, title);
}
}
pl->SetItemName(i, name);
}
pl->SetSelect(m_selScript);
pl->ShowSelect(true);
}
// Returns the rank of selected script.
int CBrain::GetSelScript()
{
Ui::CWindow* pw;
Ui::CList* pl;
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return -1;
pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_PROGLIST));
if ( pl == 0 ) return -1;
return pl->GetSelect();
}
// Changes selected script
void CBrain::SetSelScript(int index)
{
Ui::CWindow* pw;
Ui::CList* pl;
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return;
pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_PROGLIST));
if ( pl == 0 ) return;
pl->SetSelect(index);
pl->ShowSelect(true);
}
// Blinks the running program.
void CBrain::BlinkScript(bool bEnable)
{
Ui::CWindow* pw;
Ui::CList* pl;
if ( !m_object->GetSelect() ) return; // robot not selected?
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return;
pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_PROGLIST));
if ( pl == 0 ) return;
pl->SetBlink(bEnable);
}
// Check the status of a button interface.
void CBrain::CheckInterface(Ui::CWindow *pw, EventType event, bool bState)
{
Ui::CControl* control;
control = pw->SearchControl(event);
if ( control == 0 ) return;
control->SetState(Ui::STATE_CHECK, bState);
}
// Changes the state of a button interface.
void CBrain::EnableInterface(Ui::CWindow *pw, EventType event, bool bState)
{
Ui::CControl* control;
control = pw->SearchControl(event);
if ( control == 0 ) return;
control->SetState(Ui::STATE_ENABLE, bState);
}
// Changes the state of a button on the interface.
void CBrain::DeadInterface(Ui::CWindow *pw, EventType event, bool bState)
{
Ui::CControl* control;
control = pw->SearchControl(event);
if ( control == 0 ) return;
control->SetState(Ui::STATE_DEAD, !bState);
}
// Change the default input state of a button interface.
void CBrain::DefaultEnter(Ui::CWindow *pw, EventType event, bool bState)
{
Ui::CControl* control;
control = pw->SearchControl(event);
if ( control == 0 ) return;
if ( bState )
{
control->SetState(Ui::STATE_DEFAULT);
m_defaultEnter = event;
}
else
{
control->ClearState(Ui::STATE_DEFAULT);
}
}
// Indicates whether the object is busy with a task.
bool CBrain::IsBusy()
{
return (m_primaryTask != 0);
}
// Management of the activity of an object.
void CBrain::SetActivity(bool bMode)
{
m_bActivity = bMode;
}
bool CBrain::GetActivity()
{
return m_bActivity;
}
// Indicates whether a program is running.
bool CBrain::IsProgram()
{
return m_currentProgram != nullptr;
}
// Starts a program.
void CBrain::RunProgram(Program* program)
{
if ( program->script->Run() )
{
m_currentProgram = program; // start new program
BlinkScript(true); // blink
m_object->CreateSelectParticle();
m_main->UpdateShortcuts();
if(m_object->GetTrainer())
m_main->StartMissionTimer();
}
}
// Returns the current program.
int CBrain::GetProgram()
{
if(m_currentProgram == nullptr)
return -1;
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i] == m_currentProgram)
{
return i;
}
}
return -1;
}
// Name management scripts to load.
void CBrain::SetScriptRun(Program* program)
{
m_scriptRun = program;
}
Program* CBrain::GetScriptRun()
{
return m_scriptRun;
}
void CBrain::SetSoluceName(char *name)
{
strcpy(m_soluceName, name);
}
char* CBrain::GetSoluceName()
{
return m_soluceName;
}
// Load a script solution, in the first free script.
// If there is already an identical script, nothing is loaded.
bool CBrain::ReadSoluce(char* 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] == 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) ) // 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 CBrain::ReadProgram(Program* program, const char* filename)
{
if ( program->script->ReadScript(filename) ) return true;
return false;
}
// Indicates whether a program is compiled correctly.
bool CBrain::GetCompile(Program* program)
{
return program->script->GetCompile();
}
// Saves a script in a text file.
bool CBrain::WriteProgram(Program* program, char* filename)
{
if ( program->script->WriteScript(filename) ) return true;
return false;
}
// Load a stack of script implementation from a file.
bool CBrain::ReadStack(FILE *file)
{
short op;
fRead(&op, sizeof(short), 1, file);
if ( op == 1 ) // run ?
{
fRead(&op, sizeof(short), 1, file); // program rank
if ( op >= 0 )
{
assert(op < static_cast<int>(m_program.size())); //TODO: is it good?
m_selScript = op;
BlinkScript(true); // blink
if ( !m_program[op]->script->ReadStack(file) ) return false;
}
}
return true;
}
// Save the script implementation stack of a file.
bool CBrain::WriteStack(FILE *file)
{
short op;
if ( m_currentProgram != nullptr && // current program?
m_currentProgram->script->IsRunning() )
{
op = 1; // run
fWrite(&op, sizeof(short), 1, file);
op = GetProgram();
fWrite(&op, sizeof(short), 1, file);
return m_currentProgram->script->WriteStack(file);
}
op = 0; // stop
fWrite(&op, sizeof(short), 1, file);
return true;
}
const std::vector<Program*>& CBrain::GetPrograms()
{
return m_program;
}
// Start of registration of the design.
void CBrain::TraceRecordStart()
{
m_traceOper = TO_STOP;
m_tracePos = m_object->GetPosition(0);
m_traceAngle = m_object->GetAngleY(0);
if ( m_object->GetTraceDown() ) // pencil down?
{
m_traceColor = m_object->GetTraceColor();
}
else // pen up?
{
m_traceColor = -1;
}
delete[] m_traceRecordBuffer;
m_traceRecordBuffer = new TraceRecord[MAXTRACERECORD];
m_traceRecordIndex = 0;
}
// Saving the current drawing.
void CBrain::TraceRecordFrame()
{
TraceOper oper = TO_STOP;
Math::Vector pos;
float angle, len, speed;
int color;
speed = m_physics->GetLinMotionX(MO_REASPEED);
if ( speed > 0.0f ) oper = TO_ADVANCE;
if ( speed < 0.0f ) oper = TO_RECEDE;
speed = m_physics->GetCirMotionY(MO_REASPEED);
if ( speed != 0.0f ) oper = TO_TURN;
if ( m_object->GetTraceDown() ) // pencil down?
{
color = m_object->GetTraceColor();
}
else // pen up?
{
color = -1;
}
if ( oper != m_traceOper ||
color != m_traceColor )
{
if ( m_traceOper == TO_ADVANCE ||
m_traceOper == TO_RECEDE )
{
pos = m_object->GetPosition(0);
len = Math::DistanceProjected(pos, m_tracePos);
TraceRecordOper(m_traceOper, len);
}
if ( m_traceOper == TO_TURN )
{
angle = m_object->GetAngleY(0)-m_traceAngle;
TraceRecordOper(m_traceOper, angle);
}
if ( color != m_traceColor )
{
TraceRecordOper(TO_PEN, static_cast<float>(color));
}
m_traceOper = oper;
m_tracePos = m_object->GetPosition(0);
m_traceAngle = m_object->GetAngleY(0);
m_traceColor = color;
}
}
// End of the registration of the design. Program generates the CBOT.
void CBrain::TraceRecordStop()
{
TraceOper lastOper, curOper;
float lastParam, curParam;
int max, i;
char* buffer;
if ( m_traceRecordBuffer == nullptr ) return;
max = 10000;
buffer = new char[max];
*buffer = 0;
strncat(buffer, "extern void object::AutoDraw()\n{\n", max-1);
lastOper = TO_STOP;
lastParam = 0.0f;
for ( i=0 ; i<m_traceRecordIndex ; i++ )
{
curOper = m_traceRecordBuffer[i].oper;
curParam = m_traceRecordBuffer[i].param;
if ( curOper == lastOper )
{
if ( curOper == TO_PEN )
{
lastParam = curParam;
}
else
{
lastParam += curParam;
}
}
else
{
TraceRecordPut(buffer, max, lastOper, lastParam);
lastOper = curOper;
lastParam = curParam;
}
}
TraceRecordPut(buffer, max, lastOper, lastParam);
delete[] m_traceRecordBuffer;
m_traceRecordBuffer = nullptr;
strncat(buffer, "}\n", max-1);
buffer[max-1] = 0;
Program* prog = AddProgram();
prog->script->SendScript(buffer);
delete[] buffer;
}
// Saves an instruction CBOT.
bool CBrain::TraceRecordOper(TraceOper oper, float param)
{
int i;
i = m_traceRecordIndex;
if ( i >= MAXTRACERECORD ) return false;
m_traceRecordBuffer[i].oper = oper;
m_traceRecordBuffer[i].param = param;
m_traceRecordIndex = i+1;
return true;
}
// Generates an instruction CBOT.
bool CBrain::TraceRecordPut(char *buffer, int max, TraceOper oper, float param)
{
char line[100];
int color;
if ( oper == TO_ADVANCE )
{
param /= g_unit;
sprintf(line, "\tmove(%.1f);\n", param);
strncat(buffer, line, max-1);
}
if ( oper == TO_RECEDE )
{
param /= g_unit;
sprintf(line, "\tmove(-%.1f);\n", param);
strncat(buffer, line, max-1);
}
if ( oper == TO_TURN )
{
param = -param*180.0f/Math::PI;
sprintf(line, "\tturn(%d);\n", static_cast<int>(param));
//? sprintf(line, "\tturn(%.1f);\n", param);
strncat(buffer, line, max-1);
}
if ( oper == TO_PEN )
{
color = static_cast<int>(param);
if ( color == -1 ) strncat(buffer, "\tpenup();\n", max-1);
if ( color == 1 ) strncat(buffer, "\tpendown(Black);\n", max-1);
if ( color == 8 ) strncat(buffer, "\tpendown(Yellow);\n", max-1);
if ( color == 7 ) strncat(buffer, "\tpendown(Orange);\n", max-1);
if ( color == 4 ) strncat(buffer, "\tpendown(Red);\n", max-1);
if ( color == 6 ) strncat(buffer, "\tpendown(Purple);\n", max-1);
if ( color == 14 ) strncat(buffer, "\tpendown(Blue);\n", max-1);
if ( color == 12 ) strncat(buffer, "\tpendown(Green);\n", max-1);
if ( color == 10 ) strncat(buffer, "\tpendown(Brown);\n", max-1);
}
return true;
}
Program* CBrain::AddProgram()
{
Program* program = new Program();
program->script = new CScript(m_object, &m_secondaryTask);
program->readOnly = false;
program->runnable = true;
AddProgram(program);
return program;
}
bool CBrain::AddProgram(Program* program)
{
if(std::find(m_program.begin(), m_program.end(), program) != m_program.end())
return false;
m_program.push_back(program);
if(m_object->GetSelect())
{
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
}
return true;
}
void CBrain::RemoveProgram(Program* program)
{
if(m_currentProgram == program)
{
StopProgram();
}
m_program.erase(std::remove(m_program.begin(), m_program.end(), program), m_program.end());
delete program->script;
program->script = nullptr;
delete program;
if(m_object->GetSelect())
{
UpdateInterface();
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw != 0 )
{
UpdateScript(pw);
}
}
}
Program* CBrain::CloneProgram(Program* program)
{
Program* newprog = AddProgram();
// TODO: Is there any reason CScript doesn't have a function to get the program code directly?
Ui::CEdit* edit = new Ui::CEdit();
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
program->script->PutScript(edit, "");
newprog->script->GetScript(edit);
delete edit;
return newprog;
}
int CBrain::GetProgramIndex(Program* program)
{
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i] == program)
{
return i;
}
}
return -1;
}
Program* CBrain::GetProgram(int index)
{
if(index < 0 || index >= static_cast<int>(m_program.size()))
return nullptr;
return m_program[index];
}
Program* CBrain::GetOrAddProgram(int index)
{
if(index < 0)
return nullptr;
if(index < static_cast<int>(m_program.size()))
return m_program[index];
for(int i = m_program.size(); i < index; i++)
{
AddProgram();
}
return AddProgram();
}