/* * 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/motion/motion.h" #include "object/task/taskmanager.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 = -1; 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; for (int i=0 ; iDeleteInstance(CLASS_BRAIN, this); } // Destroys the object. void CBrain::DeleteObject(bool bAll) { 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 ( !bAll ) { if ( m_beeBullet != 0 ) { m_beeBullet->DeleteObject(); delete m_beeBullet; m_beeBullet = 0; } } 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(char *line) { char name[100]; sprintf(name, " bVirusActive=%d", m_bActiveVirus); strcat(line, name); return true; } // Restores all parameters of the object. bool CBrain::Read(char *line) { m_bActiveVirus = OpInt(line, "bVirusActive", 0); 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.key == m_main->GetInputBinding(INPUT_SLOT_ACTION).primary || event.key.key == m_main->GetInputBinding(INPUT_SLOT_ACTION).secondary ) && !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 ( 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_program == -1 ) { RunProgram(m_selScript); } else { StopProgram(); } } if ( action == EVENT_OBJECT_PROGSTART ) { m_main->SaveOneScript(m_object); RunProgram(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); } return true; } if ( !m_object->GetSelect() && // robot pas sélectionné ? m_program == -1 && 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_program != -1 && 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_program != -1 ) { if ( action == EVENT_OBJECT_PROGRUN ) { StopProgram(); } if ( action == EVENT_OBJECT_PROGEDIT ) { StartEditScript(m_selScript, m_main->GetScriptName()); } if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return true; } 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 ) { StartEditScript(m_selScript, m_main->GetScriptName()); } if ( action == EVENT_OBJECT_PROGRUN ) { StopProgram(); // stops the current program RunProgram(m_selScript); UpdateInterface(); } err = ERR_OK; if ( m_program == -1 ) { 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_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_program != -1 ) // current program? { if ( m_script[m_program]->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_program != -1 && m_script[m_program] != 0 ) { m_script[m_program]->Stop(); } BlinkScript(false); // stops flashing m_program = -1; 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()%BRAINMAXSCRIPT; if ( m_script[j] != 0 ) { if ( m_script[j]->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(int rank, char* name) { CreateInterface(false); // removes the control buttons if ( m_script[rank] == 0 ) { m_script[rank] = new CScript(m_object, &m_secondaryTask); } m_studio = new Ui::CStudio(); m_studio->StartEditScript(m_script[rank], name, rank); } // 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; } // 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*2.0f; // default => 2 pos.x = ox+sx*0.0f; pos.y = oy+sy*0.0f; pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, -1.10f); UpdateScript(pw); 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 ( 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(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_program == -1 ); bEnable = ( m_primaryTask == 0 && m_program == -1 ); EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord)); EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord); 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_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_program == -1 ) { 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_script[m_selScript] != 0 ) { m_script[m_selScript]->GetTitle(title); if ( title[0] != 0 ) { bRun = true; } } if ( !bEnable && m_program == -1 ) 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_program==-1?21:8); // run/stop } //? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT); //? if ( pb != 0 ) //? { //? pb->SetIcon(m_program==-1?22:40); // edit/debug //? } BlinkScript(m_program != -1); // 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]; int i; pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_PROGLIST)); if ( pl == 0 ) return; for ( i=0 ; iGetTitle(title); if ( title[0] != 0 ) { 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(); } // 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_program != -1 ); } // Indicates whether a program exists. bool CBrain::ProgramExist(int rank) { return ( m_script[rank] != 0 ); } // Starts a program. void CBrain::RunProgram(int rank) { if ( rank < 0 ) return; if ( m_script[rank] != 0 && m_script[rank]->Run() ) { m_program = rank; // start new program BlinkScript(true); // blink m_object->CreateSelectParticle(); m_main->UpdateShortcuts(); } } // Returns the first free program. int CBrain::FreeProgram() { int i; for ( i=0 ; iCompare(m_script[rank]) ) // the same already? { delete m_script[rank]; m_script[rank] = 0; return false; } } return true; } // Load a script from text buffer. bool CBrain::SendProgram(int rank, const char* buffer) { if ( m_script[rank] == 0 ) { m_script[rank] = new CScript(m_object, &m_secondaryTask); } if ( m_script[rank]->SendScript(buffer) ) return true; delete m_script[rank]; m_script[rank] = 0; return false; } // Load a script with a text file. bool CBrain::ReadProgram(int rank, const char* filename) { if ( m_script[rank] == 0 ) { m_script[rank] = new CScript(m_object, &m_secondaryTask); } if ( m_script[rank]->ReadScript(filename) ) return true; delete m_script[rank]; m_script[rank] = 0; return false; } // Indicates whether a program is compiled correctly. bool CBrain::GetCompile(int rank) { if ( m_script[rank] == 0 ) return false; return m_script[rank]->GetCompile(); } // Saves a script in a text file. bool CBrain::WriteProgram(int rank, char* filename) { if ( m_script[rank] == 0 ) { m_script[rank] = new CScript(m_object, &m_secondaryTask); } if ( m_script[rank]->WriteScript(filename) ) return true; delete m_script[rank]; m_script[rank] = 0; 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 && op < BRAINMAXSCRIPT ) { m_program = op; // program restarts m_selScript = op; BlinkScript(true); // blink if ( m_script[op] == 0 ) { m_script[op] = new CScript(m_object, &m_secondaryTask); } if ( !m_script[op]->ReadStack(file) ) return false; } } return true; } // ave the script implementation stack of a file. bool CBrain::WriteStack(FILE *file) { short op; if ( m_program != -1 && // current program? m_script[m_program]->IsRunning() ) { op = 1; // run fWrite(&op, sizeof(short), 1, file); op = m_program; fWrite(&op, sizeof(short), 1, file); return m_script[m_program]->WriteStack(file); } op = 0; // stop fWrite(&op, sizeof(short), 1, file); return true; } // 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(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 ; iSendScript(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(param)); //? sprintf(line, "\tturn(%.1f);\n", param); strncat(buffer, line, max-1); } if ( oper == TO_PEN ) { color = static_cast(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; }