Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/orxonox/worldentities/ControllableEntity.cc @ 10558

Last change on this file since 10558 was 10558, checked in by landauf, 10 years ago

no need to call get() on Weak or StrongPtr. they are automatically converted to normal pointers.

  • Property svn:eol-style set to native
File size: 24.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
29#include "ControllableEntity.h"
30
31#include <OgreSceneManager.h>
32#include <OgreSceneNode.h>
33
34#include "core/CoreIncludes.h"
35#include "core/config/ConfigValueIncludes.h"
36#include "core/GameMode.h"
37#include "core/XMLPort.h"
38#include "network/NetworkFunctionIncludes.h"
39
40#include "Scene.h"
41#include "infos/PlayerInfo.h"
42#include "controllers/NewHumanController.h"
43#include "graphics/Camera.h"
44#include "worldentities/CameraPosition.h"
45#include "overlays/OverlayGroup.h"
46
47namespace orxonox
48{
49    RegisterClass(ControllableEntity);
50
51    registerMemberNetworkFunction( ControllableEntity, fire );
52    registerMemberNetworkFunction( ControllableEntity, setTargetInternal );
53
54    ControllableEntity::ControllableEntity(Context* context) : MobileEntity(context)
55    {
56        RegisterObject(ControllableEntity);
57
58        this->bHasLocalController_ = false;
59        this->bHasHumanController_ = false;
60
61        this->server_overwrite_ = 0;
62        this->client_overwrite_ = 0;
63        this->player_ = 0;
64        this->formerPlayer_ = NULL;
65        this->playerID_ = OBJECTID_UNKNOWN;
66        this->hud_ = 0;
67        this->camera_ = 0;
68        this->xmlcontroller_ = 0;
69        //this->controller_ = 0;
70        this->reverseCamera_ = 0;
71        this->bDestroyWhenPlayerLeft_ = false;
72        this->cameraPositionRootNode_ = this->node_->createChildSceneNode();
73        this->currentCameraPosition_ = 0;
74        this->bMouseLook_ = false;
75        this->mouseLookSpeed_ = 200;
76
77        this->server_position_         = Vector3::ZERO;
78        this->client_position_         = Vector3::ZERO;
79        this->server_linear_velocity_  = Vector3::ZERO;
80        this->client_linear_velocity_  = Vector3::ZERO;
81        this->server_orientation_      = Quaternion::IDENTITY;
82        this->client_orientation_      = Quaternion::IDENTITY;
83        this->server_angular_velocity_ = Vector3::ZERO;
84        this->client_angular_velocity_ = Vector3::ZERO;
85
86        this->setConfigValues();
87        this->setPriority( Priority::VeryHigh );
88        this->registerVariables();
89        this->team_ = -1;
90    }
91
92    ControllableEntity::~ControllableEntity()
93    {
94        if (this->isInitialized())
95        {
96            this->bDestroyWhenPlayerLeft_ = false;
97
98            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
99                this->getPlayer()->stopControl();
100
101            if (this->xmlcontroller_)
102                this->xmlcontroller_->destroy();
103
104            if (this->hud_)
105                this->hud_->destroy();
106
107            if (this->camera_)
108                this->camera_->destroy();
109
110            for (std::list<StrongPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
111                (*it)->destroy();
112
113            if (this->getScene()->getSceneManager())
114                this->getScene()->getSceneManager()->destroySceneNode(this->cameraPositionRootNode_->getName());
115        }
116    }
117
118    void ControllableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
119    {
120        SUPER(ControllableEntity, XMLPort, xmlelement, mode);
121
122        XMLPortParam(ControllableEntity, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);
123        XMLPortParam(ControllableEntity, "hudtemplate", setHudTemplate, getHudTemplate, xmlelement, mode);
124        XMLPortParam(ControllableEntity, "camerapositiontemplate", setCameraPositionTemplate, getCameraPositionTemplate, xmlelement, mode);
125
126        XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
127        XMLPortObject(ControllableEntity, Controller,     "controller",      setXMLController,  getXMLController,  xmlelement, mode);
128    }
129
130    void ControllableEntity::setConfigValues()
131    {
132        SetConfigValue(mouseLookSpeed_, 3.0f);
133    }
134
135    void ControllableEntity::preDestroy()
136    {
137        // HACK - solve this clean and without preDestroy hook for multiplayer where removePlayer() isn't called
138        if (this->isInitialized() && this->bHasLocalController_ && this->bHasHumanController_)
139            this->stopLocalHumanControl();
140    }
141
142    void ControllableEntity::addCameraPosition(CameraPosition* position)
143    {
144        if (!position->getIsAbsolute())
145        {
146            if (position->getAllowMouseLook())
147                position->attachToNode(this->cameraPositionRootNode_);
148            else
149                this->attach(position);
150        }
151        else
152        {
153            WorldEntity* parent = this->getParent();
154            if (parent)
155                parent->attach(position);
156        }
157
158        if (!position->getRenderCamera())
159            this->cameraPositions_.push_back(position);
160        else
161            this->setReverseCamera(position);
162    }
163
164    CameraPosition* ControllableEntity::getCameraPosition(unsigned int index) const
165    {
166        unsigned int i = 0;
167        for (std::list<StrongPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
168        {
169            if (i == index)
170                return (*it);
171            ++i;
172        }
173        return 0;
174    }
175
176    unsigned int ControllableEntity::getCurrentCameraIndex() const
177    {
178        if (this->cameraPositions_.size() <= 0)
179            return 0;
180
181        unsigned int counter = 0;
182        for (std::list<StrongPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
183        {
184            if ((*it) == this->currentCameraPosition_)
185                break;
186            counter++;
187        }
188        if (counter >= this->cameraPositions_.size())
189            return 0;
190
191        return counter;
192    }
193
194    bool ControllableEntity::setCameraPosition(unsigned int index)
195    {
196        if(this->camera_ != NULL && this->cameraPositions_.size() > 0)
197        {
198            if(index >= this->cameraPositions_.size())
199                index = 0;
200
201            CameraPosition* position = this->getCameraPosition(index);
202            position->attachCamera(this->camera_);
203            this->currentCameraPosition_ = position;
204            return true;
205        }
206
207        return false;
208    }
209
210    void ControllableEntity::switchCamera()
211    {
212        if (this->camera_)
213        {
214            if (this->camera_->getParent() == this && this->cameraPositions_.size() > 0)
215            {
216                this->cameraPositions_.front()->attachCamera(this->camera_);
217                this->currentCameraPosition_ = this->cameraPositions_.front();
218            }
219            else if (this->cameraPositions_.size() > 0)
220            {
221                for (std::list<StrongPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
222                {
223                    if ((*it) == this->camera_->getParent())
224                    {
225                        ++it;
226                        if (it != this->cameraPositions_.end())
227                        {
228                            (*it)->attachCamera(this->camera_);
229                            this->currentCameraPosition_ = *it;
230                        }
231                        else
232                        {
233                            (*this->cameraPositions_.begin())->attachCamera(this->camera_);
234                            this->currentCameraPosition_ = *this->cameraPositions_.begin();
235                        }
236                        break;
237                    }
238                }
239            }
240            else
241            {
242                this->camera_->attachToNode(this->cameraPositionRootNode_);
243                this->currentCameraPosition_ = 0;
244            }
245
246            // disable mouse look if the new camera position doesn't allow it
247            if (this->currentCameraPosition_ && !this->currentCameraPosition_->getAllowMouseLook() && this->bMouseLook_)
248                this->mouseLook();
249
250            // disable drag if in mouse look
251            if (this->bMouseLook_)
252                this->getCamera()->setDrag(false);
253        }
254    }
255
256    void ControllableEntity::mouseLook()
257    {
258        // enable mouse look only if allowed - disabling it works always
259        if (this->currentCameraPosition_ && (this->currentCameraPosition_->getAllowMouseLook() || this->bMouseLook_))
260        {
261            this->bMouseLook_ = !this->bMouseLook_;
262
263            if (!this->bMouseLook_)
264            {
265                this->cameraPositionRootNode_->setOrientation(Quaternion::IDENTITY);
266                this->cameraPositionRootNode_->_update(true, false); // update the camera node because otherwise the camera will drag back in position which looks strange
267
268                NewHumanController* controller = orxonox_cast<NewHumanController*>(this->getController());
269                if (controller)
270                    controller->centerCursor();
271            }
272
273            if (this->getCamera())
274            {
275                if (!this->bMouseLook_ && this->currentCameraPosition_->getDrag())
276                    this->getCamera()->setDrag(true);
277                else
278                    this->getCamera()->setDrag(false);
279            }
280        }
281    }
282
283    void ControllableEntity::rotateYaw(const Vector2& value)
284    {
285        if (this->bMouseLook_)
286            this->cameraPositionRootNode_->yaw(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
287    }
288
289    void ControllableEntity::rotatePitch(const Vector2& value)
290    {
291        if (this->bMouseLook_)
292            this->cameraPositionRootNode_->pitch(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
293    }
294
295    void ControllableEntity::rotateRoll(const Vector2& value)
296    {
297        if (this->bMouseLook_)
298            this->cameraPositionRootNode_->roll(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
299    }
300
301    void ControllableEntity::fire(unsigned int firemode)
302    {
303        if(GameMode::isMaster())
304        {
305            this->fired(firemode);
306        }
307        else
308        {
309            callMemberNetworkFunction(&ControllableEntity::fire, this->getObjectID(), 0, firemode);
310        }
311    }
312
313    void ControllableEntity::setController(Controller* val)
314    {
315        this->controller_ = val;
316    }
317
318    void ControllableEntity::setTarget( WorldEntity* target )
319    {
320        this->target_ = target;
321        if ( !GameMode::isMaster() )
322        {
323            if ( target != 0 )
324            {
325                callMemberNetworkFunction(&ControllableEntity::setTargetInternal, this->getObjectID(), 0, target->getObjectID() );
326            }
327           else
328           {
329                callMemberNetworkFunction(&ControllableEntity::setTargetInternal, this->getObjectID(), 0, OBJECTID_UNKNOWN );
330           }
331        }
332    }
333
334    void ControllableEntity::setTargetInternal( uint32_t targetID )
335    {
336        this->setTarget( orxonox_cast<WorldEntity*>(Synchronisable::getSynchronisable(targetID)) );
337    }
338
339    void ControllableEntity::setPlayer(PlayerInfo* player)
340    {
341        if (!player)
342        {
343            this->removePlayer();
344            return;
345        }
346
347        this->player_ = player;
348        this->formerPlayer_ = player;
349        this->playerID_ = player->getObjectID();
350        this->bHasLocalController_ = player->isLocalPlayer();
351        this->bHasHumanController_ = player->isHumanPlayer();
352        if(controller_ != NULL)
353            this->team_ = controller_->getTeam(); // forward controller team number
354
355        if (this->bHasLocalController_ && this->bHasHumanController_)
356        {
357            this->startLocalHumanControl();
358
359            if (!GameMode::isMaster())
360            {
361                this->client_overwrite_ = this->server_overwrite_;
362                this->setSyncMode(ObjectDirection::Bidirectional);
363            }
364        }
365
366        this->changedPlayer();
367    }
368
369    void ControllableEntity::removePlayer()
370    {
371        if (this->bHasLocalController_ && this->bHasHumanController_)
372            this->stopLocalHumanControl();
373
374        this->player_ = 0;
375        this->playerID_ = OBJECTID_UNKNOWN;
376        this->bHasLocalController_ = false;
377        this->bHasHumanController_ = false;
378        this->setSyncMode(ObjectDirection::ToClient);
379
380        this->changedPlayer();
381
382        if (this->bDestroyWhenPlayerLeft_)
383            this->destroy();
384    }
385
386    void ControllableEntity::networkcallback_changedplayerID()
387    {
388        // just do this in case the entity wasn't yet synchronized when the corresponding PlayerInfo got our objectID
389        if (this->playerID_ != OBJECTID_UNKNOWN)
390        {
391            this->player_ = orxonox_cast<PlayerInfo*>(Synchronisable::getSynchronisable(this->playerID_));
392            if (this->player_ && (this->player_->getControllableEntity() != this))
393                this->player_->startControl(this);
394        }
395    }
396
397    void ControllableEntity::startLocalHumanControl()
398    {
399        if (!this->camera_ && GameMode::showsGraphics())
400        {
401            this->camera_ = new Camera(this->getContext());
402            this->camera_->requestFocus();
403            if (!this->cameraPositionTemplate_.empty())
404                this->addTemplate(this->cameraPositionTemplate_);
405            if (this->cameraPositions_.size() > 0)
406            {
407                this->cameraPositions_.front()->attachCamera(this->camera_);
408                this->currentCameraPosition_ = this->cameraPositions_.front();
409            }
410            else
411            {
412                this->camera_->attachToNode(this->cameraPositionRootNode_);
413                this->currentCameraPosition_ = 0;
414            }
415        }
416
417        this->createHud();
418    }
419
420    // HACK-ish
421    void ControllableEntity::createHud(void)
422    {
423        if (!this->hud_ && GameMode::showsGraphics())
424        {
425            if (!this->hudtemplate_.empty())
426            {
427                this->hud_ = new OverlayGroup(this->getContext());
428                this->hud_->addTemplate(this->hudtemplate_);
429                this->hud_->setOwner(this);
430            }
431        }
432    }
433
434    void ControllableEntity::destroyHud(void)
435    {
436        if (this->hud_ != NULL)
437        {
438            this->hud_->destroy();
439            this->hud_ = NULL;
440        }
441    }
442
443    void ControllableEntity::stopLocalHumanControl()
444    {
445        if (this->camera_)
446        {
447            this->camera_->detachFromParent();
448            this->camera_->destroy();
449            this->camera_ = 0;
450        }
451
452        if (this->hud_)
453        {
454            this->hud_->destroy();
455            this->hud_ = 0;
456        }
457    }
458
459    void ControllableEntity::setXMLController(Controller* controller)
460    {
461        if (!this->xmlcontroller_)
462        {
463            this->xmlcontroller_ = controller;
464            this->bHasLocalController_ = true;
465            this->xmlcontroller_->setControllableEntity(this);
466            this->team_ = this->xmlcontroller_->getTeam(); //forward the team number
467        }
468        else
469            orxout(internal_warning) << "ControllableEntity \"" << this->getName() << "\" already has a Controller." << endl;
470    }
471
472    void ControllableEntity::parentChanged()
473    {
474        WorldEntity::parentChanged();
475
476        WorldEntity* parent = this->getParent();
477        if (parent)
478        {
479            for (std::list<StrongPtr<CameraPosition> >::iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
480                if ((*it)->getIsAbsolute())
481                    parent->attach((*it));
482        }
483    }
484
485    void ControllableEntity::tick(float dt)
486    {
487        MobileEntity::tick(dt);
488
489        if (this->isActive())
490        {
491            // Check whether Bullet doesn't do the physics for us
492            if (!this->isDynamic())
493            {
494                if (GameMode::isMaster())
495                {
496                    this->server_position_ = this->getPosition();
497                    this->server_orientation_ = this->getOrientation();
498                    this->server_linear_velocity_ = this->getVelocity();
499                    this->server_angular_velocity_ = this->getAngularVelocity();
500                }
501                else if (this->bHasLocalController_)
502                {
503                    this->client_position_ = this->getPosition();
504                    this->client_orientation_ = this->getOrientation();
505                    this->client_linear_velocity_ = this->getVelocity();
506                    this->client_angular_velocity_ = this->getAngularVelocity();
507                }
508            }
509        }
510    }
511
512    void ControllableEntity::registerVariables()
513    {
514        registerVariable(this->cameraPositionTemplate_,  VariableDirection::ToClient);
515        registerVariable(this->hudtemplate_,             VariableDirection::ToClient);
516
517        registerVariable(this->server_position_,         VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerPosition));
518        registerVariable(this->server_linear_velocity_,  VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerLinearVelocity));
519        registerVariable(this->server_orientation_,      VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerOrientation));
520        registerVariable(this->server_angular_velocity_, VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerAngularVelocity));
521
522        registerVariable(this->server_overwrite_,        VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processOverwrite));
523        registerVariable(this->client_overwrite_,        VariableDirection::ToServer);
524
525        registerVariable(this->client_position_,         VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientPosition));
526        registerVariable(this->client_linear_velocity_,  VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientLinearVelocity));
527        registerVariable(this->client_orientation_,      VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientOrientation));
528        registerVariable(this->client_angular_velocity_, VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientAngularVelocity));
529
530
531        registerVariable(this->playerID_,                VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::networkcallback_changedplayerID));
532    }
533
534    void ControllableEntity::processServerPosition()
535    {
536        if (!this->bHasLocalController_)
537            MobileEntity::setPosition(this->server_position_);
538    }
539
540    void ControllableEntity::processServerLinearVelocity()
541    {
542        if (!this->bHasLocalController_)
543            MobileEntity::setVelocity(this->server_linear_velocity_);
544    }
545
546    void ControllableEntity::processServerOrientation()
547    {
548        if (!this->bHasLocalController_)
549            MobileEntity::setOrientation(this->server_orientation_);
550    }
551
552    void ControllableEntity::processServerAngularVelocity()
553    {
554        if (!this->bHasLocalController_)
555            MobileEntity::setAngularVelocity(this->server_angular_velocity_);
556    }
557
558    void ControllableEntity::processOverwrite()
559    {
560        if (this->bHasLocalController_)
561        {
562            this->setPosition(this->server_position_);
563            this->setOrientation(this->server_orientation_);
564            this->setVelocity(this->server_linear_velocity_);
565            this->setAngularVelocity(this->server_angular_velocity_);
566
567            this->client_overwrite_ = this->server_overwrite_;
568        }
569    }
570
571    void ControllableEntity::processClientPosition()
572    {
573        if (this->server_overwrite_ == this->client_overwrite_)
574        {
575            MobileEntity::setPosition(this->client_position_);
576            this->server_position_ = this->getPosition();
577        }
578    }
579
580    void ControllableEntity::processClientLinearVelocity()
581    {
582        if (this->server_overwrite_ == this->client_overwrite_)
583        {
584            MobileEntity::setVelocity(this->client_linear_velocity_);
585            this->server_linear_velocity_ = this->getVelocity();
586        }
587    }
588
589    void ControllableEntity::processClientOrientation()
590    {
591        if (this->server_overwrite_ == this->client_overwrite_)
592        {
593            MobileEntity::setOrientation(this->client_orientation_);
594            this->server_orientation_ = this->getOrientation();
595        }
596    }
597
598    void ControllableEntity::processClientAngularVelocity()
599    {
600        if (this->server_overwrite_ == this->client_overwrite_)
601        {
602            MobileEntity::setAngularVelocity(this->client_angular_velocity_);
603            this->server_angular_velocity_ = this->getAngularVelocity();
604        }
605    }
606
607    void ControllableEntity::setPosition(const Vector3& position)
608    {
609        if (GameMode::isMaster())
610        {
611            MobileEntity::setPosition(position);
612            this->server_position_ = this->getPosition();
613            ++this->server_overwrite_;
614        }
615        else if (this->bHasLocalController_)
616        {
617            MobileEntity::setPosition(position);
618            this->client_position_ = this->getPosition();
619        }
620    }
621
622    void ControllableEntity::setOrientation(const Quaternion& orientation)
623    {
624        if (GameMode::isMaster())
625        {
626            MobileEntity::setOrientation(orientation);
627            this->server_orientation_ = this->getOrientation();
628            ++this->server_overwrite_;
629        }
630        else if (this->bHasLocalController_)
631        {
632            MobileEntity::setOrientation(orientation);
633            this->client_orientation_ = this->getOrientation();
634        }
635    }
636
637    void ControllableEntity::setVelocity(const Vector3& velocity)
638    {
639        if (GameMode::isMaster())
640        {
641            MobileEntity::setVelocity(velocity);
642            this->server_linear_velocity_ = this->getVelocity();
643            ++this->server_overwrite_;
644        }
645        else if (this->bHasLocalController_)
646        {
647            MobileEntity::setVelocity(velocity);
648            this->client_linear_velocity_ = this->getVelocity();
649        }
650    }
651
652    void ControllableEntity::setAngularVelocity(const Vector3& velocity)
653    {
654        if (GameMode::isMaster())
655        {
656            MobileEntity::setAngularVelocity(velocity);
657            this->server_angular_velocity_ = this->getAngularVelocity();
658            ++this->server_overwrite_;
659        }
660        else if (this->bHasLocalController_)
661        {
662            MobileEntity::setAngularVelocity(velocity);
663            this->client_angular_velocity_ = this->getAngularVelocity();
664        }
665    }
666
667    void ControllableEntity::setWorldTransform(const btTransform& worldTrans)
668    {
669        MobileEntity::setWorldTransform(worldTrans);
670        if (GameMode::isMaster())
671        {
672            this->server_position_ = this->getPosition();
673            this->server_orientation_ = this->getOrientation();
674            this->server_linear_velocity_ = this->getVelocity();
675            this->server_angular_velocity_ = this->getAngularVelocity();
676        }
677        else if (this->bHasLocalController_)
678        {
679            this->client_position_ = this->getPosition();
680            this->client_orientation_ = this->getOrientation();
681            this->client_linear_velocity_ = this->getVelocity();
682            this->client_angular_velocity_ = this->getAngularVelocity();
683        }
684    }
685}
Note: See TracBrowser for help on using the repository browser.