From ebed57aa22b772211387a5561f995eee8f5faed1 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Tue, 26 Jun 2012 22:23:05 +0200 Subject: Whitespace and language change - changed tabs to spaces and DOS line endings to Unix (except in CBot and metafile) - changed language to English - fixed #include in d3dengine.h --- src/object/motion/motiontoto.cpp | 1738 +++++++++++++++++++------------------- 1 file changed, 869 insertions(+), 869 deletions(-) (limited to 'src/object/motion/motiontoto.cpp') diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp index 71e872a..f64570e 100644 --- a/src/object/motion/motiontoto.cpp +++ b/src/object/motion/motiontoto.cpp @@ -1,869 +1,869 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * -// * 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://www.gnu.org/licenses/. - -// motiontoto.cpp - - -#include - -#include "object/motion/motiontoto.h" - -#include "math/geometry.h" -#include "old/terrain.h" -#include "old/water.h" -#include "old/modfile.h" -#include "object/robotmain.h" - - - -const float START_TIME = 1000.0f; // beginning of the relative time - - - -// Object's constructor. - -CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object) - : CMotion(iMan, object) -{ - m_time = 0.0f; - m_bDisplayInfo = false; - m_bQuickPos = false; - m_bStartAction = false; - m_speedAction = 20.0f; - m_soundChannel = -1; - m_clownRadius = 0.0f; - m_clownDelay = 0.0f; - m_clownTime = 0.0f; - m_blinkTime = 0.0f; - m_blinkProgress = -1.0f; - m_lastMotorParticule = 0.0f; - m_type = OBJECT_NULL; - m_mousePos = Math::Point(0.0f, 0.0f); -} - -// Object's destructor. - -CMotionToto::~CMotionToto() -{ -} - - -// Removes an object. - -void CMotionToto::DeleteObject(bool bAll) -{ - if ( m_soundChannel != -1 ) - { - m_sound->Stop(m_soundChannel); - m_soundChannel = -1; - } -} - - -// Creates a vehicle traveling any lands on the ground. - -bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type, - float power) -{ - CModFile* pModFile; - int rank; - - if ( m_engine->RetRestCreate() < 10 ) return false; - - pModFile = new CModFile(m_iMan); - - m_object->SetType(type); - - // Creates the head. - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object - m_object->SetObjectRank(0, rank); - pModFile->ReadModel("objects\\toto1.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(0, pos); - m_object->SetAngleY(0, angle); - - // Creates mouth. - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(1, rank); - m_object->SetObjectParent(1, 0); - pModFile->ReadModel("objects\\toto2.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(1, Math::Vector(1.00f, 0.17f, 0.00f)); - - // Creates the left eye. - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(2, rank); - m_object->SetObjectParent(2, 0); - pModFile->ReadModel("objects\\toto3.mod"); - pModFile->Mirror(); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(2, Math::Vector(0.85f, 1.04f, 0.25f)); - m_object->SetAngleY(2, -20.0f*Math::PI/180.0f); - - // Creates the right eye. - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(3, rank); - m_object->SetObjectParent(3, 0); - pModFile->ReadModel("objects\\toto3.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(3, Math::Vector(0.85f, 1.04f, -0.25f)); - m_object->SetAngleY(3, 20.0f*Math::PI/180.0f); - - // Creates left antenna. - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(4, rank); - m_object->SetObjectParent(4, 0); - pModFile->ReadModel("objects\\toto4.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(4, Math::Vector(0.0f, 1.9f, 0.3f)); - m_object->SetAngleX(4, 30.0f*Math::PI/180.0f); - - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(5, rank); - m_object->SetObjectParent(5, 4); - pModFile->ReadModel("objects\\toto4.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(5, Math::Vector(0.0f, 0.67f, 0.0f)); - m_object->SetAngleX(5, 30.0f*Math::PI/180.0f); - - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(6, rank); - m_object->SetObjectParent(6, 5); - pModFile->ReadModel("objects\\toto5.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(6, Math::Vector(0.0f, 0.70f, 0.0f)); - m_object->SetAngleX(6, 30.0f*Math::PI/180.0f); - - // Creates right antenna. - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(7, rank); - m_object->SetObjectParent(7, 0); - pModFile->ReadModel("objects\\toto4.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(7, Math::Vector(0.0f, 1.9f, -0.3f)); - m_object->SetAngleX(7, -30.0f*Math::PI/180.0f); - - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(8, rank); - m_object->SetObjectParent(8, 7); - pModFile->ReadModel("objects\\toto4.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(8, Math::Vector(0.0f, 0.67f, 0.0f)); - m_object->SetAngleX(8, -30.0f*Math::PI/180.0f); - - rank = m_engine->CreateObject(); - m_engine->SetObjectType(rank, TYPEDESCENDANT); - m_object->SetObjectRank(9, rank); - m_object->SetObjectParent(9, 8); - pModFile->ReadModel("objects\\toto5.mod"); - pModFile->CreateEngineObject(rank); - m_object->SetPosition(9, Math::Vector(0.0f, 0.70f, 0.0f)); - m_object->SetAngleX(9, -30.0f*Math::PI/180.0f); - - m_object->SetZoom(0, 0.5f); // is little - m_object->SetFloorHeight(0.0f); - - pos = m_object->RetPosition(0); - m_object->SetPosition(0, pos); // to display the shadows immediately - - m_engine->LoadAllTexture(); - - delete pModFile; - return true; -} - - -// Beginning of the display of informations, with foo in the left margin. - -void CMotionToto::StartDisplayInfo() -{ -return; -//? - m_bDisplayInfo = true; - - m_actionType = -1; - m_actionTime = 0.0f; - m_progress = 0.0f; - - m_object->SetAngleY(0, 0.0f); - m_mousePos = Math::Point(0.5f, 0.5f); -} - -// End of the display of informations. - -void CMotionToto::StopDisplayInfo() -{ - m_bDisplayInfo = false; - m_bQuickPos = true; -} - -// Gives the position of the mouse. - -void CMotionToto::SetMousePos(Math::Point pos) -{ - m_mousePos = pos; -} - - -// Management of an event. - -bool CMotionToto::EventProcess(const Event &event) -{ - CMotion::EventProcess(event); - - if ( event.event == EVENT_FRAME ) - { - return EventFrame(event); - } - - return true; -} - -// Management of an event. - -bool CMotionToto::EventFrame(const Event &event) -{ - Math::Matrix* mat; - Math::Vector eye, lookat, dir, perp, nPos, aPos, pos, speed; - Math::Vector vibLin, vibCir, dirSpeed, aAntenna; - Math::Point dim; - POINT wDim; - ParticuleType type; - float progress, focus, distance, shift, verti, level, zoom; - float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed; - int sheet, i, r; - bool bHidden; - - if ( m_engine->RetPause() && - !m_main->RetInfoLock() ) return true; - - if ( m_bDisplayInfo ) // "looks" mouse? - { - bHidden = false; - } - else - { - bHidden = false; - - if ( m_main->RetMovieLock() ) // current movie? - { - bHidden = true; - } - if ( !m_engine->RetTotoMode() ) - { - if ( !m_main->RetEditLock() ) // current edition? - { - bHidden = true; - } - } - } - - if ( bHidden ) - { - nPos = m_object->RetPosition(0); - m_terrain->MoveOnFloor(nPos, true); - nPos.y -= 100.0f; // hidden under the ground! - m_object->SetPosition(0, nPos); - return true; - } - - m_time += event.rTime; - m_blinkTime -= event.rTime; - - progress = 0.0f; - if ( m_actionType != -1 ) // current action? - { - if ( m_progress < 0.15f ) - { - progress = m_progress/0.15f; - } - else if ( m_progress < 0.85f ) - { - progress = 1.0f; - } - else - { - progress = (1.0f-m_progress)/0.15f; - } - } - - if ( m_progress >= 1.0f ) - { - m_actionType = -1; // action ended - m_actionTime = 0.0f; - m_progress = 0.0f; - - m_clownTime = 0.0f; - m_clownDelay = 0.0f; - } - - focus = m_engine->RetFocus(); - eye = m_engine->RetEyePt(); - lookat = m_engine->RetLookatPt(); - - vibLin = Math::Vector(0.0f, 0.0f, 0.0f); - vibCir = Math::Vector(0.0f, 0.0f, 0.0f); - aAntenna = Math::Vector(0.0f, 0.0f, 0.0f); - aAntenna.x += 30.0f*Math::PI/180.0f; - - // Calculates the new position. - if ( m_bDisplayInfo ) - { - wDim = m_engine->RetDim(); - nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f); - nPos.y = -0.5f; - nPos.z = 7.0f; // in the left margin - - linSpeed = 0.0f; - } - else - { -#if 0 - distance = 30.0f-progress*24.5f; // remoteness - shift = 18.0f-progress*15.4f; // shift is left - verti = 10.0f-progress* 9.6f; // shift at the top -#else - distance = 30.0f-progress*18.0f; // remoteness - shift = 18.0f-progress*11.0f; // shift is left - verti = 10.0f-progress* 8.0f; // shift at the top -#endif - - if ( m_actionType == -1 && - (m_type == OBJECT_HUMAN || - m_type == OBJECT_TECH || - m_type == OBJECT_MOBILEwa || - m_type == OBJECT_MOBILEta || - m_type == OBJECT_MOBILEfa || - m_type == OBJECT_MOBILEia || - m_type == OBJECT_MOBILEwc || - m_type == OBJECT_MOBILEtc || - m_type == OBJECT_MOBILEfc || - m_type == OBJECT_MOBILEic || - m_type == OBJECT_MOBILEwi || - m_type == OBJECT_MOBILEti || - m_type == OBJECT_MOBILEfi || - m_type == OBJECT_MOBILEii || - m_type == OBJECT_MOBILEws || - m_type == OBJECT_MOBILEts || - m_type == OBJECT_MOBILEfs || - m_type == OBJECT_MOBILEis || - m_type == OBJECT_MOBILErt || - m_type == OBJECT_MOBILErc || - m_type == OBJECT_MOBILErr || - m_type == OBJECT_MOBILErs || - m_type == OBJECT_MOBILEsa || - m_type == OBJECT_MOBILEwt || - m_type == OBJECT_MOBILEtt || - m_type == OBJECT_MOBILEft || - m_type == OBJECT_MOBILEit || - m_type == OBJECT_MOBILEdr ) ) // vehicle? - { - m_clownTime += event.rTime; - if ( m_clownTime >= m_clownDelay ) - { - if ( rand()%10 < 2 ) - { - m_clownRadius = 2.0f+Math::Rand()*10.0f; -//? m_clownDelay = m_clownRadius/(2.0f+Math::Rand()*2.0f); - m_clownDelay = 1.5f+Math::Rand()*1.0f; - } - else - { - m_clownRadius = 0.0f; - m_clownDelay = 2.0f+Math::Rand()*2.0f; - } - pos = m_object->RetPosition(0); - if ( pos.y < m_water->RetLevel() ) // underwater? - { - m_clownRadius /= 1.5f; - m_clownDelay *= 2.0f; - } - m_clownTime = 0.0f; - } - else - { - distance -= m_clownRadius*sinf(m_clownTime*Math::PI*2.0f/m_clownDelay); - shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*Math::PI*2.0f/m_clownDelay); - } - - verti += (18.0f-shift)*0.2f; - } - - distance /= focus; -//? shift *= focus; - verti /= focus; - - dir = Normalize(lookat-eye); - nPos = eye + dir*distance; - - perp.x = -dir.z; - perp.y = dir.y; - perp.z = dir.x; - nPos = nPos + perp*shift; - - nPos.y += verti; - - if ( m_bQuickPos ) // immediately in place? - { - m_bQuickPos = false; - linSpeed = 0.0f; - } - else - { - aPos = m_object->RetPosition(0); - if ( m_actionType == -1 ) - { - level = 4.0f; - } - else - { - if ( m_bStartAction ) - { - m_bStartAction = false; - m_speedAction = Math::Distance(nPos, aPos)/15.0f; - if ( m_speedAction < 20.0f ) m_speedAction = 20.0f; - } - level = m_speedAction; - } - if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime; - nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos - - linSpeed = Math::DistanceProjected(nPos, aPos)/event.rTime; - dirSpeed = (nPos-aPos)/event.rTime; - nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast - } - } - - // Calculate the new angle. - nAngle = Math::NormAngle(Math::RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f); - if ( linSpeed == 0.0f || m_actionType != -1 ) - { - mAngle = nAngle; - } - else - { - mAngle = Math::NormAngle(Math::RotateAngle(dirSpeed.x, -dirSpeed.z)); - } - level = Math::Min(linSpeed*0.1f, 1.0f); - nAngle = nAngle*(1.0f-level) + mAngle*level; - aAngle = Math::NormAngle(m_object->RetAngleY(0)); - - if ( nAngle < aAngle ) - { - if ( nAngle+Math::PI*2.0f-aAngle < aAngle-nAngle ) nAngle += Math::PI*2.0f; - } - else - { - if ( aAngle+Math::PI*2.0f-nAngle < nAngle-aAngle ) aAngle += Math::PI*2.0f; - } - nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f; - - // Leans quotes if running. - cirSpeed = (aAngle-nAngle)/event.rTime; - angle = cirSpeed*0.3f*(1.0f-progress); - if ( angle > 0.7f ) angle = 0.7f; - if ( angle < -0.7f ) angle = -0.7f; - vibCir.x += angle*1.5f; - aAntenna.x += fabs(angle)*0.8f; // deviates - - // Leans forward so quickly advance. - angle = linSpeed*0.10f*(1.0f-progress); - if ( angle > 1.0f ) angle = 1.0f; - vibCir.z -= angle/2.0f; // leans forward - aAntenna.z -= angle; // leans forward - - // Calculates the residual motion. -#if 1 - vibLin.y += (sinf(m_time*2.00f)*0.5f+ - sinf(m_time*2.11f)*0.2f)*(1.0f-progress); - - vibCir.z += sinf(m_time*Math::PI* 2.01f)*(Math::PI/ 75.0f)+ - sinf(m_time*Math::PI* 2.51f)*(Math::PI/100.0f)+ - sinf(m_time*Math::PI*19.01f)*(Math::PI/200.0f); - - vibCir.x += sinf(m_time*Math::PI* 2.03f)*(Math::PI/ 75.0f)+ - sinf(m_time*Math::PI* 2.52f)*(Math::PI/100.0f)+ - sinf(m_time*Math::PI*19.53f)*(Math::PI/200.0f); - - vibCir.y += (sinf(m_time*Math::PI* 1.07f)*(Math::PI/ 10.0f)+ - sinf(m_time*Math::PI* 1.19f)*(Math::PI/ 17.0f)+ - sinf(m_time*Math::PI* 1.57f)*(Math::PI/ 31.0f))*(1.0f-progress); -#endif - - // Calculates the animations in action. - if ( m_actionType == MT_ERROR ) // no-no? - { - vibCir.y += progress*sinf(m_progress*Math::PI*11.0f)*1.0f; - vibCir.z -= progress*0.5f; // leans forward - - aAntenna.x -= progress*0.4f; // narrows - aAntenna.z += progress*1.0f; // leaning back - } - - if ( m_actionType == MT_WARNING ) // warning? - { - vibCir.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; - - aAntenna.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; // deviates - aAntenna.z += progress*cosf(m_progress*Math::PI*17.0f)*0.5f; // turns - } - - if ( m_actionType == MT_INFO ) // yes-yes? - { - vibCir.z += progress*sinf(m_progress*Math::PI*19.0f)*0.7f; - - aAntenna.x -= progress*0.2f; // narrows - aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.9f; // turns - } - - if ( m_actionType == MT_MESSAGE ) // message? - { - vibCir.x += progress*sinf(m_progress*Math::PI*15.0f)*0.3f; - vibCir.z += progress*cosf(m_progress*Math::PI*15.0f)*0.3f; - - aAntenna.x -= progress*0.4f; // narrows - aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.8f; - } - - // Initialize the object. - if ( m_bDisplayInfo ) // "looks" mouse? - { - if ( m_mousePos.x < 0.15f ) - { - progress = 1.0f-m_mousePos.x/0.15f; - vibCir.y += progress*Math::PI/2.0f; - } - else - { - progress = (m_mousePos.x-0.15f)/0.85f; - vibCir.y -= progress*Math::PI/3.0f; - } - - angle = Math::RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f); - if ( angle < Math::PI ) - { - if ( angle > Math::PI*0.5f ) angle = Math::PI-angle; - if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f; - vibCir.z += angle; - } - else - { - angle = Math::PI*2.0f-angle; - if ( angle > Math::PI*0.5f ) angle = Math::PI-angle; - if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f; - vibCir.z -= angle; - } - } - else - { - nPos.y += vibLin.y; - level = m_terrain->RetFloorLevel(nPos); - if ( nPos.y < level+2.0f ) - { - nPos.y = level+2.0f; // just above the ground - } - nPos.y -= vibLin.y; - } - m_object->SetPosition(0, nPos); - m_object->SetAngleY(0, nAngle); - - SetLinVibration(vibLin); - SetCirVibration(vibCir); - - // Calculates the residual movement of the antennas. - pos = aAntenna*0.40f; - pos.x += sinf(m_time*Math::PI*2.07f)*(Math::PI/50.0f)+ - sinf(m_time*Math::PI*2.59f)*(Math::PI/70.0f)+ - sinf(m_time*Math::PI*2.67f)*(Math::PI/90.0f); - - pos.y += sinf(m_time*Math::PI*2.22f)*(Math::PI/50.0f)+ - sinf(m_time*Math::PI*2.36f)*(Math::PI/70.0f)+ - sinf(m_time*Math::PI*3.01f)*(Math::PI/90.0f); - - pos.z += sinf(m_time*Math::PI*2.11f)*(Math::PI/50.0f)+ - sinf(m_time*Math::PI*2.83f)*(Math::PI/70.0f)+ - sinf(m_time*Math::PI*3.09f)*(Math::PI/90.0f); - - m_object->SetAngle(4, pos); // left antenna - m_object->SetAngle(5, pos); // left antenna - m_object->SetAngle(6, pos); // left antenna - - pos = aAntenna*0.40f; - pos.x = -pos.x; - pos.x += sinf(m_time*Math::PI*2.33f)*(Math::PI/50.0f)+ - sinf(m_time*Math::PI*2.19f)*(Math::PI/70.0f)+ - sinf(m_time*Math::PI*2.07f)*(Math::PI/90.0f); - - pos.y += sinf(m_time*Math::PI*2.44f)*(Math::PI/50.0f)+ - sinf(m_time*Math::PI*2.77f)*(Math::PI/70.0f)+ - sinf(m_time*Math::PI*3.22f)*(Math::PI/90.0f); - - pos.z += sinf(m_time*Math::PI*2.05f)*(Math::PI/50.0f)+ - sinf(m_time*Math::PI*2.38f)*(Math::PI/70.0f)+ - sinf(m_time*Math::PI*2.79f)*(Math::PI/90.0f); - - m_object->SetAngle(7, pos); // right antenna - m_object->SetAngle(8, pos); // right antenna - m_object->SetAngle(9, pos); // right antenna - - // Movement of the mouth. - if ( m_actionType == MT_ERROR ) // no-no? - { - m_object->SetAngleX(1, 0.0f); - m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f); - m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f)); - m_object->SetZoomZ(1, 1.0f); - } - else if ( m_actionType == MT_WARNING ) // warning? - { - m_object->SetAngleX(1, 15.0f*Math::PI/180.0f); - m_object->SetAngleZ(1, 0.0f); - m_object->SetZoomY(1, 1.0f); - m_object->SetZoomZ(1, 1.0f); - } - else if ( m_actionType == MT_INFO ) // yes-yes? - { - m_object->SetAngleX(1, 0.0f); - m_object->SetAngleZ(1, 0.0f); - m_object->SetZoomY(1, 1.0f); - m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f); - } - else if ( m_actionType == MT_MESSAGE ) // message? - { - m_object->SetAngleX(1, 0.0f); - m_object->SetAngleZ(1, 0.0f); - m_object->SetZoomY(1, 1.0f); - m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f); - } - else - { - m_object->SetAngleX(1, 0.0f); - m_object->SetAngleZ(1, 0.0f); - m_object->SetZoomY(1, 1.0f); - m_object->SetZoomZ(1, 1.0f); - } - - // Eye blinking management. - if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f ) - { - m_blinkProgress = 0.0f; - } - - if ( m_blinkProgress >= 0.0f ) - { - m_blinkProgress += event.rTime*3.2f; - - if ( m_blinkProgress < 1.0f ) - { - if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f; - else zoom = 2.0f-m_blinkProgress/0.5f; - m_object->SetZoomY(2, 1.0f-zoom*0.9f); - m_object->SetZoomY(3, 1.0f-zoom*0.9f); - } - else - { - m_blinkProgress = -1.0f; - m_blinkTime = 0.1f+Math::Rand()*4.0f; - m_object->SetZoomY(2, 1.0f); - m_object->SetZoomY(3, 1.0f); - } - } - - if ( m_actionType == MT_ERROR ) // no-no? - { - m_object->SetAngleX(2, -30.0f*Math::PI/180.0f); - m_object->SetAngleX(3, 30.0f*Math::PI/180.0f); - } - else if ( m_actionType == MT_WARNING ) // warning? - { - m_object->SetAngleX(2, -15.0f*Math::PI/180.0f); - m_object->SetAngleX(3, 15.0f*Math::PI/180.0f); - } - else if ( m_actionType == MT_INFO ) // yes-yes? - { - m_object->SetAngleX(2, 40.0f*Math::PI/180.0f); - m_object->SetAngleX(3, -40.0f*Math::PI/180.0f); - } - else if ( m_actionType == MT_MESSAGE ) // message? - { - m_object->SetAngleX(2, 20.0f*Math::PI/180.0f); - m_object->SetAngleX(3, -20.0f*Math::PI/180.0f); - } - else - { - m_object->SetAngleX(2, 0.0f); - m_object->SetAngleX(3, 0.0f); - } - - mat = m_object->RetWorldMatrix(0); // must be done every time! - - // Generates particles. - if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) ) - { - m_lastMotorParticule = m_time; - - if ( m_bDisplayInfo ) sheet = SH_FRONT; - else sheet = SH_WORLD; - - pos = m_object->RetPosition(0); - if ( !m_bDisplayInfo && - pos.y < m_water->RetLevel() ) // underwater? - { - float t = Math::Mod(m_time, 3.5f); - if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe? - { - pos = Math::Vector(1.0f, 0.2f, 0.0f); - pos.z += (Math::Rand()-0.5f)*0.5f; - - speed = pos; - speed.y += 5.0f+Math::Rand()*5.0f; - speed.x += Math::Rand()*2.0f; - speed.z += (Math::Rand()-0.5f)*2.0f; - - pos = Transform(*mat, pos); - speed = Transform(*mat, speed)-pos; - - dim.x = 0.12f; - dim.y = dim.x; - m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f); - } - } - else // out of water? - { - pos = Math::Vector(0.0f, -0.5f, 0.0f); - pos.z += (Math::Rand()-0.5f)*0.5f; - - speed = pos; - speed.y -= (1.5f+Math::Rand()*1.5f) + vibLin.y; - speed.x += (Math::Rand()-0.5f)*2.0f; - speed.z += (Math::Rand()-0.5f)*2.0f; - -// mat = m_object->RetWorldMatrix(0); - pos = Transform(*mat, pos); - speed = Transform(*mat, speed)-pos; - - dim.x = (Math::Rand()*0.4f+0.4f)*(1.0f+Math::Min(linSpeed*0.1f, 5.0f)); - dim.y = dim.x; - m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Math::Rand()*1.0f, 0.0f, 1.0f, sheet); - } - - if ( m_actionType != -1 && // current action? - m_progress <= 0.85f ) - { - pos.x = (Math::Rand()-0.5f)*1.0f; - pos.y = (Math::Rand()-0.5f)*1.0f+3.5f; - pos.z = (Math::Rand()-0.5f)*1.0f; - pos = Transform(*mat, pos); - speed = Math::Vector(0.0f, 0.0f, 0.0f); - dim.x = (Math::Rand()*0.3f+0.3f); - dim.y = dim.x; - if ( m_actionType == MT_ERROR ) type = PARTIERROR; - if ( m_actionType == MT_WARNING ) type = PARTIWARNING; - if ( m_actionType == MT_INFO ) type = PARTIINFO; - if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING; - m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet); - - pos.x = 0.50f+(Math::Rand()-0.5f)*0.80f; - pos.y = 0.86f+(Math::Rand()-0.5f)*0.08f; - pos.z = 0.00f; - dim.x = (Math::Rand()*0.04f+0.04f); - dim.y = dim.x/0.75f; - m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE); - } - -//? if ( m_bDisplayInfo && m_main->RetGlint() ) - if ( false ) - { - pos.x = (Math::Rand()-0.5f)*1.4f; - pos.y = (Math::Rand()-0.5f)*1.4f+3.5f; - pos.z = (Math::Rand()-0.5f)*1.4f; - pos = Transform(*mat, pos); - speed = Math::Vector(0.0f, 0.0f, 0.0f); - dim.x = (Math::Rand()*0.5f+0.5f); - dim.y = dim.x; - m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet); - - for ( i=0 ; i<10 ; i++ ) - { - pos.x = 0.60f+(Math::Rand()-0.5f)*0.76f; - pos.y = 0.47f+(Math::Rand()-0.5f)*0.90f; - pos.z = 0.00f; - r = rand()%4; - if ( r == 0 ) pos.x = 0.21f; // the left edge - else if ( r == 1 ) pos.x = 0.98f; // the right edge - else if ( r == 2 ) pos.y = 0.02f; // on the lower edge - else pos.y = 0.92f; // on the upper edge - dim.x = (Math::Rand()*0.02f+0.02f); - dim.y = dim.x/0.75f; - m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE); - } - } - } - - // Move the sound. - if ( m_soundChannel != -1 ) - { - if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) ) - { - m_soundChannel = -1; - } - } - - return true; -} - - -// Starts an action. - -Error CMotionToto::SetAction(int action, float time) -{ - Sound sound; - - CMotion::SetAction(action, time); - - m_bStartAction = true; - - sound = SOUND_CLICK; - if ( action == MT_ERROR ) sound = SOUND_ERROR; - if ( action == MT_WARNING ) sound = SOUND_WARNING; - if ( action == MT_INFO ) sound = SOUND_INFO; - if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE; - - if ( sound != SOUND_CLICK ) - { - m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0)); - } - - return ERR_OK; -} - -// Specifies the type of the object is attached to toto. - -void CMotionToto::SetLinkType(ObjectType type) -{ - m_type = type; -} - - +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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://www.gnu.org/licenses/. + +// motiontoto.cpp + + +#include + +#include "object/motion/motiontoto.h" + +#include "math/geometry.h" +#include "old/terrain.h" +#include "old/water.h" +#include "old/modfile.h" +#include "object/robotmain.h" + + + +const float START_TIME = 1000.0f; // beginning of the relative time + + + +// Object's constructor. + +CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + m_time = 0.0f; + m_bDisplayInfo = false; + m_bQuickPos = false; + m_bStartAction = false; + m_speedAction = 20.0f; + m_soundChannel = -1; + m_clownRadius = 0.0f; + m_clownDelay = 0.0f; + m_clownTime = 0.0f; + m_blinkTime = 0.0f; + m_blinkProgress = -1.0f; + m_lastMotorParticule = 0.0f; + m_type = OBJECT_NULL; + m_mousePos = Math::Point(0.0f, 0.0f); +} + +// Object's destructor. + +CMotionToto::~CMotionToto() +{ +} + + +// Removes an object. + +void CMotionToto::DeleteObject(bool bAll) +{ + if ( m_soundChannel != -1 ) + { + m_sound->Stop(m_soundChannel); + m_soundChannel = -1; + } +} + + +// Creates a vehicle traveling any lands on the ground. + +bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 10 ) return false; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + pModFile->ReadModel("objects\\toto1.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // Creates mouth. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\toto2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, Math::Vector(1.00f, 0.17f, 0.00f)); + + // Creates the left eye. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\toto3.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, Math::Vector(0.85f, 1.04f, 0.25f)); + m_object->SetAngleY(2, -20.0f*Math::PI/180.0f); + + // Creates the right eye. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 0); + pModFile->ReadModel("objects\\toto3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, Math::Vector(0.85f, 1.04f, -0.25f)); + m_object->SetAngleY(3, 20.0f*Math::PI/180.0f); + + // Creates left antenna. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 0); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, Math::Vector(0.0f, 1.9f, 0.3f)); + m_object->SetAngleX(4, 30.0f*Math::PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 4); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, Math::Vector(0.0f, 0.67f, 0.0f)); + m_object->SetAngleX(5, 30.0f*Math::PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 5); + pModFile->ReadModel("objects\\toto5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, Math::Vector(0.0f, 0.70f, 0.0f)); + m_object->SetAngleX(6, 30.0f*Math::PI/180.0f); + + // Creates right antenna. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, Math::Vector(0.0f, 1.9f, -0.3f)); + m_object->SetAngleX(7, -30.0f*Math::PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 7); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, Math::Vector(0.0f, 0.67f, 0.0f)); + m_object->SetAngleX(8, -30.0f*Math::PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 8); + pModFile->ReadModel("objects\\toto5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, Math::Vector(0.0f, 0.70f, 0.0f)); + m_object->SetAngleX(9, -30.0f*Math::PI/180.0f); + + m_object->SetZoom(0, 0.5f); // is little + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return true; +} + + +// Beginning of the display of informations, with foo in the left margin. + +void CMotionToto::StartDisplayInfo() +{ +return; +//? + m_bDisplayInfo = true; + + m_actionType = -1; + m_actionTime = 0.0f; + m_progress = 0.0f; + + m_object->SetAngleY(0, 0.0f); + m_mousePos = Math::Point(0.5f, 0.5f); +} + +// End of the display of informations. + +void CMotionToto::StopDisplayInfo() +{ + m_bDisplayInfo = false; + m_bQuickPos = true; +} + +// Gives the position of the mouse. + +void CMotionToto::SetMousePos(Math::Point pos) +{ + m_mousePos = pos; +} + + +// Management of an event. + +bool CMotionToto::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + return true; +} + +// Management of an event. + +bool CMotionToto::EventFrame(const Event &event) +{ + Math::Matrix* mat; + Math::Vector eye, lookat, dir, perp, nPos, aPos, pos, speed; + Math::Vector vibLin, vibCir, dirSpeed, aAntenna; + Math::Point dim; + POINT wDim; + ParticuleType type; + float progress, focus, distance, shift, verti, level, zoom; + float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed; + int sheet, i, r; + bool bHidden; + + if ( m_engine->RetPause() && + !m_main->RetInfoLock() ) return true; + + if ( m_bDisplayInfo ) // "looks" mouse? + { + bHidden = false; + } + else + { + bHidden = false; + + if ( m_main->RetMovieLock() ) // current movie? + { + bHidden = true; + } + if ( !m_engine->RetTotoMode() ) + { + if ( !m_main->RetEditLock() ) // current edition? + { + bHidden = true; + } + } + } + + if ( bHidden ) + { + nPos = m_object->RetPosition(0); + m_terrain->MoveOnFloor(nPos, true); + nPos.y -= 100.0f; // hidden under the ground! + m_object->SetPosition(0, nPos); + return true; + } + + m_time += event.rTime; + m_blinkTime -= event.rTime; + + progress = 0.0f; + if ( m_actionType != -1 ) // current action? + { + if ( m_progress < 0.15f ) + { + progress = m_progress/0.15f; + } + else if ( m_progress < 0.85f ) + { + progress = 1.0f; + } + else + { + progress = (1.0f-m_progress)/0.15f; + } + } + + if ( m_progress >= 1.0f ) + { + m_actionType = -1; // action ended + m_actionTime = 0.0f; + m_progress = 0.0f; + + m_clownTime = 0.0f; + m_clownDelay = 0.0f; + } + + focus = m_engine->RetFocus(); + eye = m_engine->RetEyePt(); + lookat = m_engine->RetLookatPt(); + + vibLin = Math::Vector(0.0f, 0.0f, 0.0f); + vibCir = Math::Vector(0.0f, 0.0f, 0.0f); + aAntenna = Math::Vector(0.0f, 0.0f, 0.0f); + aAntenna.x += 30.0f*Math::PI/180.0f; + + // Calculates the new position. + if ( m_bDisplayInfo ) + { + wDim = m_engine->RetDim(); + nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f); + nPos.y = -0.5f; + nPos.z = 7.0f; // in the left margin + + linSpeed = 0.0f; + } + else + { +#if 0 + distance = 30.0f-progress*24.5f; // remoteness + shift = 18.0f-progress*15.4f; // shift is left + verti = 10.0f-progress* 9.6f; // shift at the top +#else + distance = 30.0f-progress*18.0f; // remoteness + shift = 18.0f-progress*11.0f; // shift is left + verti = 10.0f-progress* 8.0f; // shift at the top +#endif + + if ( m_actionType == -1 && + (m_type == OBJECT_HUMAN || + m_type == OBJECT_TECH || + m_type == OBJECT_MOBILEwa || + m_type == OBJECT_MOBILEta || + m_type == OBJECT_MOBILEfa || + m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEii || + m_type == OBJECT_MOBILEws || + m_type == OBJECT_MOBILEts || + m_type == OBJECT_MOBILEfs || + m_type == OBJECT_MOBILEis || + m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs || + m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILEdr ) ) // vehicle? + { + m_clownTime += event.rTime; + if ( m_clownTime >= m_clownDelay ) + { + if ( rand()%10 < 2 ) + { + m_clownRadius = 2.0f+Math::Rand()*10.0f; +//? m_clownDelay = m_clownRadius/(2.0f+Math::Rand()*2.0f); + m_clownDelay = 1.5f+Math::Rand()*1.0f; + } + else + { + m_clownRadius = 0.0f; + m_clownDelay = 2.0f+Math::Rand()*2.0f; + } + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) // underwater? + { + m_clownRadius /= 1.5f; + m_clownDelay *= 2.0f; + } + m_clownTime = 0.0f; + } + else + { + distance -= m_clownRadius*sinf(m_clownTime*Math::PI*2.0f/m_clownDelay); + shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*Math::PI*2.0f/m_clownDelay); + } + + verti += (18.0f-shift)*0.2f; + } + + distance /= focus; +//? shift *= focus; + verti /= focus; + + dir = Normalize(lookat-eye); + nPos = eye + dir*distance; + + perp.x = -dir.z; + perp.y = dir.y; + perp.z = dir.x; + nPos = nPos + perp*shift; + + nPos.y += verti; + + if ( m_bQuickPos ) // immediately in place? + { + m_bQuickPos = false; + linSpeed = 0.0f; + } + else + { + aPos = m_object->RetPosition(0); + if ( m_actionType == -1 ) + { + level = 4.0f; + } + else + { + if ( m_bStartAction ) + { + m_bStartAction = false; + m_speedAction = Math::Distance(nPos, aPos)/15.0f; + if ( m_speedAction < 20.0f ) m_speedAction = 20.0f; + } + level = m_speedAction; + } + if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime; + nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos + + linSpeed = Math::DistanceProjected(nPos, aPos)/event.rTime; + dirSpeed = (nPos-aPos)/event.rTime; + nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast + } + } + + // Calculate the new angle. + nAngle = Math::NormAngle(Math::RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f); + if ( linSpeed == 0.0f || m_actionType != -1 ) + { + mAngle = nAngle; + } + else + { + mAngle = Math::NormAngle(Math::RotateAngle(dirSpeed.x, -dirSpeed.z)); + } + level = Math::Min(linSpeed*0.1f, 1.0f); + nAngle = nAngle*(1.0f-level) + mAngle*level; + aAngle = Math::NormAngle(m_object->RetAngleY(0)); + + if ( nAngle < aAngle ) + { + if ( nAngle+Math::PI*2.0f-aAngle < aAngle-nAngle ) nAngle += Math::PI*2.0f; + } + else + { + if ( aAngle+Math::PI*2.0f-nAngle < nAngle-aAngle ) aAngle += Math::PI*2.0f; + } + nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f; + + // Leans quotes if running. + cirSpeed = (aAngle-nAngle)/event.rTime; + angle = cirSpeed*0.3f*(1.0f-progress); + if ( angle > 0.7f ) angle = 0.7f; + if ( angle < -0.7f ) angle = -0.7f; + vibCir.x += angle*1.5f; + aAntenna.x += fabs(angle)*0.8f; // deviates + + // Leans forward so quickly advance. + angle = linSpeed*0.10f*(1.0f-progress); + if ( angle > 1.0f ) angle = 1.0f; + vibCir.z -= angle/2.0f; // leans forward + aAntenna.z -= angle; // leans forward + + // Calculates the residual motion. +#if 1 + vibLin.y += (sinf(m_time*2.00f)*0.5f+ + sinf(m_time*2.11f)*0.2f)*(1.0f-progress); + + vibCir.z += sinf(m_time*Math::PI* 2.01f)*(Math::PI/ 75.0f)+ + sinf(m_time*Math::PI* 2.51f)*(Math::PI/100.0f)+ + sinf(m_time*Math::PI*19.01f)*(Math::PI/200.0f); + + vibCir.x += sinf(m_time*Math::PI* 2.03f)*(Math::PI/ 75.0f)+ + sinf(m_time*Math::PI* 2.52f)*(Math::PI/100.0f)+ + sinf(m_time*Math::PI*19.53f)*(Math::PI/200.0f); + + vibCir.y += (sinf(m_time*Math::PI* 1.07f)*(Math::PI/ 10.0f)+ + sinf(m_time*Math::PI* 1.19f)*(Math::PI/ 17.0f)+ + sinf(m_time*Math::PI* 1.57f)*(Math::PI/ 31.0f))*(1.0f-progress); +#endif + + // Calculates the animations in action. + if ( m_actionType == MT_ERROR ) // no-no? + { + vibCir.y += progress*sinf(m_progress*Math::PI*11.0f)*1.0f; + vibCir.z -= progress*0.5f; // leans forward + + aAntenna.x -= progress*0.4f; // narrows + aAntenna.z += progress*1.0f; // leaning back + } + + if ( m_actionType == MT_WARNING ) // warning? + { + vibCir.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; + + aAntenna.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; // deviates + aAntenna.z += progress*cosf(m_progress*Math::PI*17.0f)*0.5f; // turns + } + + if ( m_actionType == MT_INFO ) // yes-yes? + { + vibCir.z += progress*sinf(m_progress*Math::PI*19.0f)*0.7f; + + aAntenna.x -= progress*0.2f; // narrows + aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.9f; // turns + } + + if ( m_actionType == MT_MESSAGE ) // message? + { + vibCir.x += progress*sinf(m_progress*Math::PI*15.0f)*0.3f; + vibCir.z += progress*cosf(m_progress*Math::PI*15.0f)*0.3f; + + aAntenna.x -= progress*0.4f; // narrows + aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.8f; + } + + // Initialize the object. + if ( m_bDisplayInfo ) // "looks" mouse? + { + if ( m_mousePos.x < 0.15f ) + { + progress = 1.0f-m_mousePos.x/0.15f; + vibCir.y += progress*Math::PI/2.0f; + } + else + { + progress = (m_mousePos.x-0.15f)/0.85f; + vibCir.y -= progress*Math::PI/3.0f; + } + + angle = Math::RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f); + if ( angle < Math::PI ) + { + if ( angle > Math::PI*0.5f ) angle = Math::PI-angle; + if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f; + vibCir.z += angle; + } + else + { + angle = Math::PI*2.0f-angle; + if ( angle > Math::PI*0.5f ) angle = Math::PI-angle; + if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f; + vibCir.z -= angle; + } + } + else + { + nPos.y += vibLin.y; + level = m_terrain->RetFloorLevel(nPos); + if ( nPos.y < level+2.0f ) + { + nPos.y = level+2.0f; // just above the ground + } + nPos.y -= vibLin.y; + } + m_object->SetPosition(0, nPos); + m_object->SetAngleY(0, nAngle); + + SetLinVibration(vibLin); + SetCirVibration(vibCir); + + // Calculates the residual movement of the antennas. + pos = aAntenna*0.40f; + pos.x += sinf(m_time*Math::PI*2.07f)*(Math::PI/50.0f)+ + sinf(m_time*Math::PI*2.59f)*(Math::PI/70.0f)+ + sinf(m_time*Math::PI*2.67f)*(Math::PI/90.0f); + + pos.y += sinf(m_time*Math::PI*2.22f)*(Math::PI/50.0f)+ + sinf(m_time*Math::PI*2.36f)*(Math::PI/70.0f)+ + sinf(m_time*Math::PI*3.01f)*(Math::PI/90.0f); + + pos.z += sinf(m_time*Math::PI*2.11f)*(Math::PI/50.0f)+ + sinf(m_time*Math::PI*2.83f)*(Math::PI/70.0f)+ + sinf(m_time*Math::PI*3.09f)*(Math::PI/90.0f); + + m_object->SetAngle(4, pos); // left antenna + m_object->SetAngle(5, pos); // left antenna + m_object->SetAngle(6, pos); // left antenna + + pos = aAntenna*0.40f; + pos.x = -pos.x; + pos.x += sinf(m_time*Math::PI*2.33f)*(Math::PI/50.0f)+ + sinf(m_time*Math::PI*2.19f)*(Math::PI/70.0f)+ + sinf(m_time*Math::PI*2.07f)*(Math::PI/90.0f); + + pos.y += sinf(m_time*Math::PI*2.44f)*(Math::PI/50.0f)+ + sinf(m_time*Math::PI*2.77f)*(Math::PI/70.0f)+ + sinf(m_time*Math::PI*3.22f)*(Math::PI/90.0f); + + pos.z += sinf(m_time*Math::PI*2.05f)*(Math::PI/50.0f)+ + sinf(m_time*Math::PI*2.38f)*(Math::PI/70.0f)+ + sinf(m_time*Math::PI*2.79f)*(Math::PI/90.0f); + + m_object->SetAngle(7, pos); // right antenna + m_object->SetAngle(8, pos); // right antenna + m_object->SetAngle(9, pos); // right antenna + + // Movement of the mouth. + if ( m_actionType == MT_ERROR ) // no-no? + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f); + m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f)); + m_object->SetZoomZ(1, 1.0f); + } + else if ( m_actionType == MT_WARNING ) // warning? + { + m_object->SetAngleX(1, 15.0f*Math::PI/180.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 1.0f); + } + else if ( m_actionType == MT_INFO ) // yes-yes? + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f); + } + else if ( m_actionType == MT_MESSAGE ) // message? + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f); + } + else + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 1.0f); + } + + // Eye blinking management. + if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f ) + { + m_blinkProgress = 0.0f; + } + + if ( m_blinkProgress >= 0.0f ) + { + m_blinkProgress += event.rTime*3.2f; + + if ( m_blinkProgress < 1.0f ) + { + if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f; + else zoom = 2.0f-m_blinkProgress/0.5f; + m_object->SetZoomY(2, 1.0f-zoom*0.9f); + m_object->SetZoomY(3, 1.0f-zoom*0.9f); + } + else + { + m_blinkProgress = -1.0f; + m_blinkTime = 0.1f+Math::Rand()*4.0f; + m_object->SetZoomY(2, 1.0f); + m_object->SetZoomY(3, 1.0f); + } + } + + if ( m_actionType == MT_ERROR ) // no-no? + { + m_object->SetAngleX(2, -30.0f*Math::PI/180.0f); + m_object->SetAngleX(3, 30.0f*Math::PI/180.0f); + } + else if ( m_actionType == MT_WARNING ) // warning? + { + m_object->SetAngleX(2, -15.0f*Math::PI/180.0f); + m_object->SetAngleX(3, 15.0f*Math::PI/180.0f); + } + else if ( m_actionType == MT_INFO ) // yes-yes? + { + m_object->SetAngleX(2, 40.0f*Math::PI/180.0f); + m_object->SetAngleX(3, -40.0f*Math::PI/180.0f); + } + else if ( m_actionType == MT_MESSAGE ) // message? + { + m_object->SetAngleX(2, 20.0f*Math::PI/180.0f); + m_object->SetAngleX(3, -20.0f*Math::PI/180.0f); + } + else + { + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleX(3, 0.0f); + } + + mat = m_object->RetWorldMatrix(0); // must be done every time! + + // Generates particles. + if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) ) + { + m_lastMotorParticule = m_time; + + if ( m_bDisplayInfo ) sheet = SH_FRONT; + else sheet = SH_WORLD; + + pos = m_object->RetPosition(0); + if ( !m_bDisplayInfo && + pos.y < m_water->RetLevel() ) // underwater? + { + float t = Math::Mod(m_time, 3.5f); + if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe? + { + pos = Math::Vector(1.0f, 0.2f, 0.0f); + pos.z += (Math::Rand()-0.5f)*0.5f; + + speed = pos; + speed.y += 5.0f+Math::Rand()*5.0f; + speed.x += Math::Rand()*2.0f; + speed.z += (Math::Rand()-0.5f)*2.0f; + + pos = Transform(*mat, pos); + speed = Transform(*mat, speed)-pos; + + dim.x = 0.12f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f); + } + } + else // out of water? + { + pos = Math::Vector(0.0f, -0.5f, 0.0f); + pos.z += (Math::Rand()-0.5f)*0.5f; + + speed = pos; + speed.y -= (1.5f+Math::Rand()*1.5f) + vibLin.y; + speed.x += (Math::Rand()-0.5f)*2.0f; + speed.z += (Math::Rand()-0.5f)*2.0f; + +// mat = m_object->RetWorldMatrix(0); + pos = Transform(*mat, pos); + speed = Transform(*mat, speed)-pos; + + dim.x = (Math::Rand()*0.4f+0.4f)*(1.0f+Math::Min(linSpeed*0.1f, 5.0f)); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Math::Rand()*1.0f, 0.0f, 1.0f, sheet); + } + + if ( m_actionType != -1 && // current action? + m_progress <= 0.85f ) + { + pos.x = (Math::Rand()-0.5f)*1.0f; + pos.y = (Math::Rand()-0.5f)*1.0f+3.5f; + pos.z = (Math::Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + speed = Math::Vector(0.0f, 0.0f, 0.0f); + dim.x = (Math::Rand()*0.3f+0.3f); + dim.y = dim.x; + if ( m_actionType == MT_ERROR ) type = PARTIERROR; + if ( m_actionType == MT_WARNING ) type = PARTIWARNING; + if ( m_actionType == MT_INFO ) type = PARTIINFO; + if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING; + m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet); + + pos.x = 0.50f+(Math::Rand()-0.5f)*0.80f; + pos.y = 0.86f+(Math::Rand()-0.5f)*0.08f; + pos.z = 0.00f; + dim.x = (Math::Rand()*0.04f+0.04f); + dim.y = dim.x/0.75f; + m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE); + } + +//? if ( m_bDisplayInfo && m_main->RetGlint() ) + if ( false ) + { + pos.x = (Math::Rand()-0.5f)*1.4f; + pos.y = (Math::Rand()-0.5f)*1.4f+3.5f; + pos.z = (Math::Rand()-0.5f)*1.4f; + pos = Transform(*mat, pos); + speed = Math::Vector(0.0f, 0.0f, 0.0f); + dim.x = (Math::Rand()*0.5f+0.5f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet); + + for ( i=0 ; i<10 ; i++ ) + { + pos.x = 0.60f+(Math::Rand()-0.5f)*0.76f; + pos.y = 0.47f+(Math::Rand()-0.5f)*0.90f; + pos.z = 0.00f; + r = rand()%4; + if ( r == 0 ) pos.x = 0.21f; // the left edge + else if ( r == 1 ) pos.x = 0.98f; // the right edge + else if ( r == 2 ) pos.y = 0.02f; // on the lower edge + else pos.y = 0.92f; // on the upper edge + dim.x = (Math::Rand()*0.02f+0.02f); + dim.y = dim.x/0.75f; + m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE); + } + } + } + + // Move the sound. + if ( m_soundChannel != -1 ) + { + if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) ) + { + m_soundChannel = -1; + } + } + + return true; +} + + +// Starts an action. + +Error CMotionToto::SetAction(int action, float time) +{ + Sound sound; + + CMotion::SetAction(action, time); + + m_bStartAction = true; + + sound = SOUND_CLICK; + if ( action == MT_ERROR ) sound = SOUND_ERROR; + if ( action == MT_WARNING ) sound = SOUND_WARNING; + if ( action == MT_INFO ) sound = SOUND_INFO; + if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE; + + if ( sound != SOUND_CLICK ) + { + m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0)); + } + + return ERR_OK; +} + +// Specifies the type of the object is attached to toto. + +void CMotionToto::SetLinkType(ObjectType type) +{ + m_type = type; +} + + -- cgit v1.2.3-1-g7c22