Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / motion / user_controls.cpp
blob1a9dac6e1c632c382b673ad69ed03e9cdbe177fc
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Robert TIMM (rti) <mail@rtti.de>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "stdpch.h"
27 //////////////
28 // Includes //
29 //////////////
30 // GAME SHARE
31 #include "game_share/bot_chat_types.h"
32 // Client.
33 #include "user_controls.h"
34 #include "../actions_client.h"
35 #include "../user_entity.h"
36 #include "../cursor_functions.h"
37 #include "../time_client.h"
38 #include "../interface_v3/interface_manager.h"
39 #include "../entities.h"
40 #include "../view.h"
41 #include "../input.h"
43 #include "../r2/editor.h"
45 #ifdef DEBUG_NEW
46 #define new DEBUG_NEW
47 #endif
49 ///////////
50 // Using //
51 ///////////
52 using namespace std;
53 using namespace NLMISC;
54 using namespace NL3D;
57 /////////////
58 // Externs //
59 /////////////
60 extern UDriver *Driver;
61 extern UScene *Scene;
62 extern CEventsListener EventsListener; // Inputs Manager
64 /////////////
65 // Globals //
66 /////////////
67 // User Controls (mouse, keyboard, interfaces, ...)
68 CUserControls UserControls;
70 // Hierarchical timer
71 H_AUTO_DECL ( RZ_Client_User_Controls_Update )
74 // ----------------------------------------------------------------------------
75 static bool isSwimming()
77 if (UserEntity != NULL)
78 return (UserEntity->mode() == MBEHAV::SWIM || UserEntity->mode() == MBEHAV::MOUNT_SWIM);
79 else
80 return false;
83 static bool isSit()
85 if (UserEntity)
86 return UserEntity->isSit();
87 else
88 return false;
91 static bool isRiding()
93 if (UserEntity)
94 return UserEntity->isRiding();
95 else
96 return false;
100 ///////////////
101 // Functions //
102 ///////////////
103 //---------------------------------------------------
104 // CUserControls :
105 // Constructor.
106 //---------------------------------------------------
107 CUserControls::CUserControls()
109 init();
110 }// CUserControls //
112 //---------------------------------------------------
113 // init :
114 // Initialize all the components.
115 //---------------------------------------------------
116 void CUserControls::init()
118 // Default Mode is Interface Mode.
119 _LastMode = _Mode = InterfaceMode;
121 _LeftClickStart = 0;
122 _LeftClickEnd = 0;
123 _RightClickStart = 0;
124 _RightClickEnd = 0;
125 _TimeBeforeMouseSlide = 50;
126 _TimeLongClick = 200;
128 _TransSpeed = 1.f;
130 _UpdateView = false;
131 _ZOscil = 0;
132 _Acc = 0;
133 _T0 = 0;
134 _T = 0;
135 _V0 = _TransSpeed;
137 _T0View = 0;
138 _TView = 0;
140 _TurnBack = false;
141 _ClickMove = false;
143 _Start = CVector(0,0,0);
144 _Destination = _Start;
146 _Dist = -1;
148 _DirectionMove = none;
150 _Locked = false; // Move is not locked.
152 _FreeLook = false;
153 _InternalView = true;
155 _LastFrameBackward = false;
156 _LastFrameForward = false;
157 _LastFrameAutowalk = false;
158 _LastFrameStrafeLeft = false;
159 _LastFrameStrafeRight = false;
160 _LastFrameTurnLeft = false;
161 _LastFrameTurnRight = false;
162 _LastFrameLeftButtonDown= false;
163 _LastFrameMousePosX = 0.f;
164 _LastFrameMousePosY = 0.f;
167 _CameraAuto = false;
169 _UserCameraDeltaYaw = 0;
170 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
172 _CurrentFrameFreeLookCalled= false;
174 _RotateUserLRVelocity= 0.f;
175 _RotateUserUDVelocity= 0.f;
176 _RotateCameraLRVelocity= 0.f;
178 _MouseCaptured = false;
180 _NeedReleaseForward = false;
181 _NextForwardCancelMoveTo = false;
183 }// init //
185 void CUserControls::reset()
187 init();
190 //-----------------------------------------------
191 // needReleaseForward :
192 //-----------------------------------------------
193 void CUserControls::needReleaseForward()
195 if( Actions.valide("forward") )
197 _NeedReleaseForward = true;
202 //-----------------------------------------------
203 // autowalkState :
204 //-----------------------------------------------
205 void CUserControls::autowalkState(bool enable)
207 if(enable)
209 _DirectionMove |= autowalk;
210 // If not backward, default is forward.
211 if(!(_DirectionMove & backward))
212 _DirectionMove |= forward;
214 else
215 _DirectionMove &= ~(autowalk|forward|backward);
216 }// autowalkState //
219 //-----------------------------------------------
220 // update :
221 // Main function of the Class -> Call it each frame.
222 //-----------------------------------------------
223 void CUserControls::update()
225 H_AUTO_USE ( RZ_Client_User_Controls_Update );
227 View.update();
229 // Reset the moving direction.
230 _DirectionMove &= ~(left | right);
232 // if not locked, move
233 if(!_Locked)
235 // What is the current _Mode ?
236 switch(_Mode)
238 // Interface Mode.
239 case InterfaceMode:
240 interfaceMode();
241 break;
243 // AI Mode
244 case AIMode:
245 aiMode();
246 break;
248 // Death Mode
249 case DeathMode:
250 deathMode();
251 break;
253 // Mount Mode
254 case MountMode:
255 mountMode();
256 break;
258 // Third Person View Mode
259 case ThirdMode:
260 thirdMode();
261 break;
263 default:
264 break;
267 _LastFrameForward = Actions.valide("forward") && !_NeedReleaseForward;
268 if( UserEntity->mode() != MBEHAV::MOUNT_SWIM )
270 _LastFrameBackward = Actions.valide("backward");
272 _LastFrameAutowalk = Actions.valide("toggle_auto_walk");
273 if( isSit() || UserEntity->isAFK() )
275 if( _LastFrameForward || _LastFrameBackward )
277 UserEntity->sit(false);
278 UserEntity->setAFK(false);
281 if (isSwimming() || isRiding())
283 _LastFrameStrafeLeft = false;
284 _LastFrameStrafeRight = false;
286 else
288 _LastFrameStrafeLeft = Actions.valide("strafe_left");
289 _LastFrameStrafeRight = Actions.valide("strafe_right");
291 _LastFrameTurnLeft = Actions.valide("turn_left");
292 _LastFrameTurnRight = Actions.valide("turn_right");
293 _LastFrameLeftButtonDown= EventsListener.isMouseButtonDown(leftButton);
294 _LastFrameMousePosX = EventsListener.getMousePosX();
295 _LastFrameMousePosY = EventsListener.getMousePosY();
298 // update the refinePos (for landscape refining...)
299 // In fly mode, take the view pos.
300 if(_Mode == AIMode)
301 View.refinePos(View.viewPos());
302 // Else take the entity pos (for less update if 3rd personn)
303 else
304 View.refinePos(UserEntity->pos());
306 // update camera collision once per frame
307 View.updateCameraCollision();
309 NLMISC::CCDBNodeLeaf *node = _UiVarMkMoveDB ? &*_UiVarMkMoveDB
310 : &*(_UiVarMkMoveDB = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MK_MOVE"));
311 node->setValue32(autowalkState());
312 }// update //
315 //-----------------------------------------------
316 // Acceleration helper
317 //-----------------------------------------------
318 void CUserControls::updateVelocity (float deltaTime, float acceleration, float brake, float speedMax, float &speed)
320 speed += acceleration * deltaTime;
321 // No acclereration, brake
322 if (acceleration == 0)
324 brake *= deltaTime;
325 if (speed < 0)
327 if (speed > -brake)
328 speed = 0;
329 else
330 speed += brake;
332 else
334 if (speed < brake)
335 speed = 0;
336 else
337 speed -= brake;
340 // Clamp the speed
341 clamp (speed, -speedMax, speedMax);
342 }// updateVelocity //
344 //-----------------------------------------------
345 // keyboardRotation :
346 // Manage keyboard rotation
347 //-----------------------------------------------
348 void CUserControls::keyboardRotationLR (bool left, bool right)
350 if (left || right)
352 float accel = 0;
353 if (left)
355 accel += ClientCfg.RotAccel;
356 _RotateUserLRVelocity = std::max (_RotateUserLRVelocity, ClientCfg.RotKeySpeedMin);
359 if (right)
361 accel -= ClientCfg.RotAccel;
362 _RotateUserLRVelocity = std::min (_RotateUserLRVelocity, -ClientCfg.RotKeySpeedMin);
364 updateVelocity (DT, accel, ClientCfg.RotAccel, ClientCfg.RotKeySpeedMax, _RotateUserLRVelocity);
366 // Rotate the body.
367 UserEntity->rotate(DT*_RotateUserLRVelocity);
369 else
370 _RotateUserLRVelocity = 0;
371 }// keyboardRotation //
373 //-----------------------------------------------
374 // keyboardRotationUD :
375 //-----------------------------------------------
376 void CUserControls::keyboardRotationUD (bool up, bool down)
378 if (up || down)
380 float accel = 0;
381 if (up)
383 accel += ClientCfg.RotAccel;
384 _RotateUserUDVelocity = std::max (_RotateUserUDVelocity, ClientCfg.RotKeySpeedMin);
387 if (down)
389 accel -= ClientCfg.RotAccel;
390 _RotateUserUDVelocity = std::min (_RotateUserUDVelocity, -ClientCfg.RotKeySpeedMin);
392 updateVelocity (DT, accel, ClientCfg.RotAccel, ClientCfg.RotKeySpeedMax, _RotateUserUDVelocity);
394 UserEntity->rotHeadVertically(DT*_RotateUserUDVelocity);
395 UserEntity->stopForceHeadPitchInFollow();
397 else
398 _RotateUserUDVelocity = 0;
399 }// keyboardRotationUD //
401 //-----------------------------------------------
402 // keyboardRotationCameraLR :
403 //-----------------------------------------------
404 void CUserControls::keyboardRotationCameraLR (bool left, bool right)
406 if (left || right)
408 float accel = 0;
409 if (left)
411 accel += ClientCfg.RotAccel;
412 _RotateCameraLRVelocity = std::max (_RotateCameraLRVelocity, ClientCfg.RotKeySpeedMin);
415 if (right)
417 accel -= ClientCfg.RotAccel;
418 _RotateCameraLRVelocity = std::min (_RotateCameraLRVelocity, -ClientCfg.RotKeySpeedMin);
420 updateVelocity (DT, accel, ClientCfg.RotAccel, ClientCfg.RotKeySpeedMax, _RotateCameraLRVelocity);
422 // Rotate the camera
423 appendCameraDeltaYaw(DT*_RotateCameraLRVelocity);
425 else
426 _RotateCameraLRVelocity = 0;
429 //-----------------------------------------------
430 // getMouseAngleMove
431 //-----------------------------------------------
432 void CUserControls::getMouseAngleMove(float &dx, float &dy)
434 dx = 0.0f;
435 dy = 0.0f;
437 // The mouse may still "StandardMove" ie through a CEventMouseMove
438 // This can happen because of the "Rotation Anti-Lag system" which
439 // start to rotate before the mouse is hid and message mode passed
440 // to updateFreeLookPos
442 // if the mouse position changed
443 if( EventsListener.getMousePosX() != _LastFrameMousePosX ||
444 EventsListener.getMousePosY() != _LastFrameMousePosY )
446 // get the mouse movement delta
447 float dmpx= EventsListener.getMousePosX() - _LastFrameMousePosX;
448 float dmpy= EventsListener.getMousePosY() - _LastFrameMousePosY;
450 // simulate mickeys mode if there is a mouse device
451 dmpx *= (float)Driver->getWindowWidth();
452 dmpy *= (float)Driver->getWindowHeight();
454 // handle inverted mouse, if enabled
455 if (ClientCfg.FreeLookInverted) dmpy = -dmpy;
457 // update free look
458 EventsListener.updateFreeLookPos(dmpx, dmpy);
461 // If the mouse move on the axis X, with a CGDMouseMove
462 if (EventsListener.isMouseAngleX())
463 dx = -EventsListener.getMouseAngleX();
465 // If the mouse move on the axis Y, with a CGDMouseMove
466 if (EventsListener.isMouseAngleY())
467 dy = EventsListener.getMouseAngleY();
471 //-----------------------------------------------
472 // freeLook :
473 // Manage a free look.
474 //-----------------------------------------------
475 void CUserControls::freeLook(bool fullMode)
477 static bool leftButtonDownInFullMode = false;
479 EventsListener.enableMouseSmoothing(true);
480 // **** Mouse rotation => apply to user
481 float dx,dy;
482 getMouseAngleMove(dx,dy);
484 // apply
485 if(dx != 0.f)
487 if( UserEntity->canChangeFront() )
489 UserEntity->rotate(dx);
491 else
493 appendCameraDeltaYaw(dx);
496 if(dy != 0.f)
498 UserEntity->rotHeadVertically(dy);
499 UserEntity->stopForceHeadPitchInFollow();
503 // **** Only in fullMode (longClick for instance)
504 if(fullMode)
506 _CurrentFrameFreeLookCalled= true;
508 CInterfaceManager *IM = CInterfaceManager::getInstance ();
510 // FREE LOOK : Hide the cursor
511 // disable interface mouse handling.
512 CWidgetManager::getInstance()->enableMouseHandling(false);
513 // Get the cursor instance
514 CViewPointer *cursor = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
515 if(cursor)
517 // Hide the Cursor.
518 SetMouseFreeLook();
521 // **** special actions keys while in free look
522 if (isSwimming() || isRiding())
523 keyboardRotationLR (false, false);
524 else
525 keyboardRotationLR (Actions.valide("strafe_left"), Actions.valide("strafe_right"));
526 // Strafe Left
527 if(Actions.valide("turn_left"))
528 _DirectionMove |= left;
529 // Strafe Right
530 if(Actions.valide("turn_right"))
531 _DirectionMove |= right;
533 // **** Left mouse click while in freelook: forward
534 // NB: in commonMove() the case "rightButtonDown+leftButtonDown" is managed.
535 // but still important to test it here, in case of FreeLook mode (no right button down needed)
536 if(EventsListener.isMouseButtonDown (leftButton))
538 // Forward.
539 _DirectionMove |= forward;
540 _DirectionMove &= ~backward;
541 // Quit autowalk if first frame in this mode
542 if( !leftButtonDownInFullMode )
543 _DirectionMove &= ~autowalk;
545 // Moving Break any Follow Mode
546 UserEntity->disableFollow();
547 UserEntity->moveTo(CLFECOMMON::INVALID_SLOT, 0.0, CUserEntity::None);
549 leftButtonDownInFullMode = true;
551 else
553 leftButtonDownInFullMode = false;
556 if( UserEntity->canChangeFront() )
558 // **** reset delta camera
559 applyCameraDeltaYawToUser();
563 }// freeLook //
566 //-----------------------------------------------
567 // cameraLook :
568 // Manage the camera look.
569 //-----------------------------------------------
570 void CUserControls::cameraLook(bool fullMode)
572 EventsListener.enableMouseSmoothing(true);
573 // **** Mouse rotation => apply X to camera, Y to user
574 float dx,dy;
575 getMouseAngleMove(dx,dy);
577 // apply
578 if(dx != 0.f)
579 appendCameraDeltaYaw(dx);
580 // If the mouse move on the axis Y, cahnge the actual user pitch (not the delta camera)
581 if(dy != 0.f)
583 UserEntity->rotHeadVertically(dy);
584 UserEntity->stopForceHeadPitchInFollow();
588 // **** Only in fullMode (longClick for instance)
589 if(fullMode)
591 CInterfaceManager *IM = CInterfaceManager::getInstance ();
593 // CAMERA LOOK : Hide the cursor
594 // disable interface mouse handling.
595 CWidgetManager::getInstance()->enableMouseHandling(false);
596 // Get the cursor instance
597 CViewPointer *cursor = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
598 if(cursor)
600 // Hide the Cursor.
601 SetMouseFreeLook();
606 }// cameraLook //
609 //-----------------------------------------------
610 // commonMove :
611 // Manage some common actions.
612 // \todo GUIGUI : manage control before entities update, but view only after move
613 //-----------------------------------------------
614 void CUserControls::commonMove()
616 CInterfaceManager *IM = CInterfaceManager::getInstance ();
618 /////////////////
619 // RESET USER CAMERA YAW
620 testApplyCameraYawToUser();
622 /////////////////
623 // MOUSE WHEEL //
624 CEventsListener::TWheelState wheelState = EventsListener.getWheelState(); // Done all the time, to reset the state
625 View.changeCameraDist((wheelState == CEventsListener::foreward), (wheelState == CEventsListener::backward));
626 View.changeCameraDist(Actions.valide("camera_foreward"), Actions.valide("camera_backward"));
627 // Camera Up/Down.
628 View.changeCameraHeight(Actions.valide("camera_up"), Actions.valide("camera_down"));
629 //////////////////
630 // LOOK UP/DOWN //
631 keyboardRotationUD(Actions.valide("look_up"), Actions.valide("look_down"));
632 /////////////
633 // FORWARD //
634 // ON
635 if(Actions.valide("forward") && !_NeedReleaseForward)
637 // Forward
638 _DirectionMove |= forward;
639 _DirectionMove &= ~backward;
641 // Start Action
642 if(!_LastFrameForward)
644 // Start autowalk mode.
645 if(Actions.valide("toggle_auto_walk"))
646 _DirectionMove |= autowalk;
647 // Leave autowalk mode.
648 else
649 _DirectionMove &= ~autowalk;
652 if( _NextForwardCancelMoveTo )
654 _NextForwardCancelMoveTo = false;
655 UserEntity->moveTo(CLFECOMMON::INVALID_SLOT, 0.0, CUserEntity::None);
656 applyCameraDeltaYawToUser();
659 // OFF
660 else
662 if(_LastFrameForward)
663 if(!(_DirectionMove & autowalk))
664 _DirectionMove &= ~forward;
666 // since forward is released, forward is now enable again
667 if( !Actions.valide("forward") && _NeedReleaseForward)
669 _NeedReleaseForward = false;
670 _NextForwardCancelMoveTo = true;
673 //////////////
674 // BACKWARD //
675 // ON
676 if(Actions.valide("backward"))
678 if( UserEntity->mode()!=MBEHAV::MOUNT_SWIM )
680 // Backward
681 _DirectionMove |= backward;
682 _DirectionMove &= ~forward;
684 // Start Action
685 if(!_LastFrameBackward)
687 // Start autowalk mode.
688 if(Actions.valide("toggle_auto_walk"))
689 _DirectionMove |= autowalk;
690 // Leave autowalk mode.
691 else
692 _DirectionMove &= ~autowalk;
695 // OFF
696 else
698 if(_LastFrameBackward)
699 if(!(_DirectionMove & autowalk))
700 _DirectionMove &= ~backward;
703 // turn left or right will break the move-to, so forward is enable again here
704 if(Actions.valide("turn_left") || Actions.valide("turn_right"))
706 if( _NeedReleaseForward )
708 _NeedReleaseForward = false;
709 _NextForwardCancelMoveTo = false;
710 // if free cam mode reset the view because move if target turned around camera may be
711 if( !ClientCfg.AutomaticCamera )
713 resetSmoothCameraDeltaYaw();
718 //////////////
719 // AUTOWALK //
720 // Must be after forward and backward to know the autowalk direction
721 // ON
722 if(Actions.valide("toggle_auto_walk"))
724 // Action start
725 if(!_LastFrameAutowalk)
727 // Leave autowalk if forward and backward not pushed and only if autowalk just pushed.
728 if((_DirectionMove & autowalk) && !Actions.valide("forward") && !Actions.valide("backward"))
729 _DirectionMove &= ~(autowalk|forward|backward);
730 else
732 // Start Autowalk
733 _DirectionMove |= autowalk;
734 // If not backward, default is forward.
735 if(!(_DirectionMove & backward))
736 _DirectionMove |= forward;
742 //////////////
743 // MOUSE MANAGEMENT
744 //////////////
746 // Left Click and Dbl Click
747 bool dblClickLeft = false;
748 if(EventsListener.isMouseButtonPushed(leftButton))
750 _LeftClickStart = T1;
752 if( EventsListener.isMouseButtonReleased (leftButton) )
754 if(T1 <= _LeftClickEnd + CWidgetManager::getInstance()->getUserDblClickDelay())
756 dblClickLeft = true;
758 _LeftClickEnd = T1;
761 // Right Click and Dbl Click
762 bool dblClickRight = false;
763 if(EventsListener.isMouseButtonPushed(rightButton))
765 _RightClickStart = T1;
767 if( EventsListener.isMouseButtonReleased (rightButton) )
769 if(T1 <= _RightClickEnd + CWidgetManager::getInstance()->getUserDblClickDelay())
771 dblClickRight = true;
773 _RightClickEnd = T1;
776 _CurrentFrameFreeLookCalled= false;
777 if(_FreeLook)
779 if(EventsListener.isMouseButtonReleased (rightButton))
781 // stop FreeLook (and restore mouse/cursor)
782 stopFreeLook();
784 else
786 // if we are in follow mode, do a cameraLook instead
787 if(UserEntity->follow() || UserEntity->moveTo())
788 cameraLook(true);
789 else
790 freeLook(true);
793 else
795 if (!_MouseCaptured)
797 // if rightbutton release while left MouseButton UP
798 if ( EventsListener.isMouseButtonReleased (rightButton) && EventsListener.isMouseButtonUp (leftButton))
800 // Cursor mode.
801 SetMouseCursor ();
803 // Short Right Click -> Check Action
804 if((T1-_RightClickStart) <= _TimeLongClick)
806 if(ClientCfg.SelectWithRClick || R2::isEditionCurrent())
808 // nb : the ring editor also need that kind of events
809 execActionCursorPos(true,dblClickRight);
812 // Launch Context Menu
813 if (R2::getEditor().getMode() != R2::CEditor::EditionMode)
815 IM->launchContextMenuInGame("ui:interface:game_context_menu");
820 // Give back the mouse handling to the interface.
821 CWidgetManager::getInstance()->enableMouseHandling(true);
822 EventsListener.enableMouseSmoothing(false);
825 // if leftbutton release while right MouseButton UP
826 if ( EventsListener.isMouseButtonReleased (leftButton) && EventsListener.isMouseButtonUp (rightButton))
828 // Cursor mode.
829 SetMouseCursor ();
831 // Short Left Click -> Check Action
832 if((T1-_LeftClickStart) <= _TimeLongClick)
834 execActionCursorPos(false, dblClickLeft);
837 // Give back the mouse handling to the interface.
838 CWidgetManager::getInstance()->enableMouseHandling(true);
839 EventsListener.enableMouseSmoothing(false);
843 // if Right button down
844 if (EventsListener.isMouseButtonDown (rightButton))
846 // NB: start the freeLook sooner than a longclick
847 if((T1-_RightClickStart) > _TimeBeforeMouseSlide)
849 // if we are in follow mode, do a cameraLook on RightSlide, else do a freeLook
850 if(UserEntity->follow() || UserEntity->moveTo() || UserEntity->isSit() || UserEntity->isAFK())
851 // FullMode (hide mouse...) only if longClick
852 cameraLook(T1-_RightClickStart > _TimeLongClick);
853 else
855 // FullMode (hide mouse...) only if longClick
856 freeLook(T1-_RightClickStart > _TimeLongClick);
858 if( _NeedReleaseForward )
860 _NeedReleaseForward = false;
861 _NextForwardCancelMoveTo = false;
862 // if free cam mode reset the view because move if target turned around camera may be
863 if( !ClientCfg.AutomaticCamera )
865 resetSmoothCameraDeltaYaw();
871 // if Right Mouse button is up
872 else
874 // mouse camera look: when the user hold down the left button for a time, while the right button is up
875 if (EventsListener.isMouseButtonDown (leftButton))
877 // NB: start the freeLook sooner than a longclick
878 if((T1 -_LeftClickStart ) > _TimeBeforeMouseSlide)
879 // FullMode (hide mouse...) only if longClick
880 cameraLook(T1-_LeftClickStart > _TimeLongClick);
883 if ( ! (isSwimming() || isRiding()))
885 // Strafe Left
886 if(Actions.valide("strafe_left"))
887 _DirectionMove |= left;
888 // Strafe Right
889 if(Actions.valide("strafe_right"))
890 _DirectionMove |= right;
893 if( !UserEntity->isSit() && !UserEntity->isAFK() )
895 // Test rotation keys
896 if( UserEntity->canChangeFront() )
898 keyboardRotationLR (Actions.valide("turn_left"), Actions.valide("turn_right"));
900 else
902 keyboardRotationCameraLR (Actions.valide("turn_left"), Actions.valide("turn_right"));
909 if (!_MouseCaptured)
911 // If both button are pressed in any case (whatever the _TimeBeforeMouseSlide time), treat as "forward"
912 static bool bothButtonPressed = false;
913 if(EventsListener.isMouseButtonDown (leftButton) && EventsListener.isMouseButtonDown (rightButton))
915 // Forward.
916 _DirectionMove |= forward;
917 _DirectionMove &= ~backward;
918 // quit autowalk if entering both button pressed mode
919 if( !bothButtonPressed )
921 _DirectionMove &= ~autowalk;
924 // Moving Break any Follow Mode
925 UserEntity->disableFollow();
926 UserEntity->moveTo(CLFECOMMON::INVALID_SLOT, 0.0, CUserEntity::None);
928 // if sit, stand up
929 UserEntity->sit(false);
930 // and no more in afk mode
931 UserEntity->setAFK(false);
933 bothButtonPressed = true;
935 else
937 bothButtonPressed = false;
942 // Manage here the Release of Forward in any of third case (keyUP, leftButton in freeLook, and both buttons down)
943 if( (_DirectionMove & forward) && (_DirectionMove & autowalk)==0)
945 // freeLook() called and leftButton down => walk
946 bool walkInFreeLook= _CurrentFrameFreeLookCalled && EventsListener.isMouseButtonDown(leftButton);
947 // both button down => walk too
948 bool walkWithBothButton= (EventsListener.isMouseButtonDown (leftButton) && EventsListener.isMouseButtonDown (rightButton));
949 // if no forward action valid, quit forward
950 if(! (Actions.valide("forward") || walkInFreeLook || walkWithBothButton) )
951 _DirectionMove &= ~forward;
955 ////////////////////
956 // CAMERA DELTA YAW ADDS
957 ////////////////////
958 if (!_MouseCaptured)
960 // reset too if middle button clicked
961 if(EventsListener.isMouseButtonReleased(middleButton))
963 resetSmoothCameraDeltaYaw();
966 // Handle rotations with keys
967 bool cameraLeft,cameraRight;
968 if( UserEntity->isSit() || UserEntity->isAFK() )
970 cameraLeft = Actions.valide("camera_turn_left") || Actions.valide("turn_left");
971 cameraRight = Actions.valide("camera_turn_right") || Actions.valide("turn_right");
973 else
975 cameraLeft = Actions.valide("camera_turn_left");
976 cameraRight = Actions.valide("camera_turn_right");
978 keyboardRotationCameraLR (cameraLeft, cameraRight);
981 // reset over time
982 if(_ResetSmoothCameraDeltaYaw!=ResetCDYOff)
984 // normalize in -Pi/Pi
985 _UserCameraDeltaYaw = float(fmod(_UserCameraDeltaYaw, 2.0f*(float)Pi));
986 if(_UserCameraDeltaYaw>Pi)
987 _UserCameraDeltaYaw-= 2*float(Pi);
988 else if(_UserCameraDeltaYaw<-Pi)
989 _UserCameraDeltaYaw+= 2*float(Pi);
991 // reset over time
992 if(_UserCameraDeltaYaw<0)
994 _UserCameraDeltaYaw+= DT*ClientCfg.CameraResetSpeed;
995 if(_UserCameraDeltaYaw>=0)
997 _UserCameraDeltaYaw= 0;
998 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1001 else
1003 _UserCameraDeltaYaw-= DT*ClientCfg.CameraResetSpeed;
1004 if(_UserCameraDeltaYaw<=0)
1006 _UserCameraDeltaYaw= 0;
1007 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1013 ////////////////////
1014 // APPLY MOTION.
1015 ////////////////////
1016 move();
1017 }// commonMove //
1019 //-----------------------------------------------
1020 // move :
1021 // Move the caracter according to the inputs.
1022 //-----------------------------------------------
1023 void CUserControls::move()
1025 // If the user is sit(), remove any move
1026 if( UserEntity->isSit() || UserEntity->isAFK() )
1027 _DirectionMove= none;
1029 if( _DirectionMove != none )
1031 cancelActionsWhenMoving();
1034 // Forward/backward motion.
1035 float direction = 0;
1036 if(_DirectionMove&forward)
1037 direction += 1;
1038 if( UserEntity->mode() != MBEHAV::MOUNT_SWIM )
1040 if(_DirectionMove&backward)
1041 direction -= 1;
1043 // Changes the front velocity for the user.
1044 UserEntity->frontVelocity(direction);
1046 // Strafe motion.
1047 float directionStrafe = 0;
1048 if( ! (isSwimming() || isRiding()) )
1050 if(_DirectionMove&left)
1051 directionStrafe += 1;
1052 if(_DirectionMove&right)
1053 directionStrafe -= 1;
1055 else if ( isRiding() )
1057 // Check if the mount is able to run, and force walking mode if not, because the player can always switch the mode
1058 UserEntity->checkMountAbleToRun();
1061 // Changes the lateral velocity for the user.
1062 UserEntity->lateralVelocity(directionStrafe);
1064 }// move //
1067 //-----------------------------------------------
1068 // mode :
1069 // Change the current Mode.
1070 //-----------------------------------------------
1071 void CUserControls::mode(const TMoveMode mode)
1073 // Unlock the motion;
1074 _Locked = false;
1076 // If the mode didn't change -> return.
1077 if(_Mode == mode)
1078 return;
1080 // Write that the last Mode end.
1081 switch(_Mode)
1083 case InterfaceMode:
1084 interfaceModeStop();
1085 break;
1087 case AIMode:
1088 aiModeStop();
1089 break;
1091 // Death Mode
1092 case DeathMode:
1093 deathModeStop();
1094 break;
1096 // Mount Mode
1097 case MountMode:
1098 mountModeStop();
1099 break;
1101 // Third Person View Mode
1102 case ThirdMode:
1103 thirdModeStop();
1104 break;
1106 default:
1107 break;
1110 // Backup the last Mode.
1111 _LastMode = _Mode;
1112 // Set the new mode.
1113 _Mode = mode;
1115 // Write that the new Mode Start.
1116 switch(_Mode)
1118 case InterfaceMode:
1119 interfaceModeStart();
1120 break;
1122 // AI Mode
1123 case AIMode:
1124 aiModeStart();
1125 break;
1127 // Death Mode
1128 case DeathMode:
1129 deathModeStart();
1130 break;
1132 // Mount Mode
1133 case MountMode:
1134 mountModeStart();
1135 break;
1137 // Third Person View Mode
1138 case ThirdMode:
1139 thirdModeStart();
1140 break;
1142 default:
1143 break;
1145 }// mode //
1147 //-----------------------------------------------
1148 // modeStr :
1149 // Return the string associated to the motion Mode.
1150 //-----------------------------------------------
1151 string CUserControls::modeStr() const
1153 switch(mode())
1155 // Interface Mode
1156 case CUserControls::InterfaceMode:
1157 return "InterfaceMode";
1159 // Camera Mode
1160 case CUserControls::AIMode:
1161 return "AIMode";
1163 // Death Mode
1164 case CUserControls::DeathMode:
1165 return "DeathMode";
1167 // Mount Mode
1168 case CUserControls::MountMode:
1169 return "MountMode";
1171 // Third Person View Mode
1172 case CUserControls::ThirdMode:
1173 return "Third Person View Mode";
1175 // Unknown Mode
1176 default:
1177 return "Unknown Control Mode";
1179 }// modeStr //
1181 //-----------------------------------------------
1183 //-----------------------------------------------
1184 // execActionCursorPos :
1185 // Execute action depending on the cursor position (left/right click).
1186 //-----------------------------------------------
1187 void CUserControls::execActionCursorPos(bool rightClick, bool dblClick)
1189 // Check there is no interface under the cursor.
1190 if( CWidgetManager::getInstance()->isMouseOverWindow())
1191 return;
1192 // Update the cursor.
1193 ContextCur.check();
1194 // Execute Action.
1195 ContextCur.execute(rightClick,dblClick);
1196 }// execActionCursorPos //
1199 //-----------------------------------------------
1200 // resetCameraDeltaYaw()
1201 //-----------------------------------------------
1202 void CUserControls::resetCameraDeltaYaw()
1204 _UserCameraDeltaYaw= 0.f;
1205 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1209 //-----------------------------------------------
1210 // appendCameraDeltaYaw()
1211 //-----------------------------------------------
1212 void CUserControls::appendCameraDeltaYaw(float dYaw)
1214 _UserCameraDeltaYaw+= dYaw;
1216 // Stop the smooth reset if any
1217 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1221 //-----------------------------------------------
1222 // resetSmoothCameraDeltaYaw()
1223 //-----------------------------------------------
1224 void CUserControls::resetSmoothCameraDeltaYaw()
1226 // Force the reset if the user currently in follow/moveTo
1227 if(UserEntity->follow() || UserEntity->moveTo())
1228 _ResetSmoothCameraDeltaYaw= ResetCDYForced;
1229 else
1230 _ResetSmoothCameraDeltaYaw= ResetCDYOn;
1234 //-----------------------------------------------
1235 // applyCameraDeltaYawToUser();
1236 //-----------------------------------------------
1237 void CUserControls::applyCameraDeltaYawToUser()
1239 // apply delta camera to the UserEntity
1240 UserEntity->rotate(_UserCameraDeltaYaw);
1241 // and reset
1242 _UserCameraDeltaYaw= 0.f;
1243 _ResetSmoothCameraDeltaYaw= ResetCDYOff;
1247 //-----------------------------------------------
1248 // testApplyCameraYawToUser()
1249 //-----------------------------------------------
1250 void CUserControls::testApplyCameraYawToUser()
1252 // only if not in "camera look" mode
1253 if(!EventsListener.isMouseButtonDown(leftButton))
1255 // if any of those actions start
1256 if( ( !_LastFrameForward && Actions.valide("forward") && !_NeedReleaseForward) ||
1257 ( !_LastFrameBackward && Actions.valide("backward") ) ||
1258 ( !_LastFrameAutowalk && Actions.valide("toggle_auto_walk") ) )
1259 /*( !_LastFrameStrafeLeft && Actions.valide("strafe_left") ) ||
1260 ( !_LastFrameStrafeRight && Actions.valide("strafe_right") ) ||
1261 ( !_LastFrameTurnLeft && Actions.valide("turn_left") ) ||
1262 ( !_LastFrameTurnRight && Actions.valide("turn_right") ) )*/
1264 applyCameraDeltaYawToUser();
1268 // if both buttons are pressed, then reset.
1269 // This is for the case where right button is pressed while left button was down for cameraLook()
1270 if( EventsListener.isMouseButtonDown(leftButton) && EventsListener.isMouseButtonDown(rightButton))
1272 applyCameraDeltaYawToUser();
1278 //-----------------------------------------------
1279 //commonSetView()
1280 //-----------------------------------------------
1281 void CUserControls::commonSetView()
1283 // Set the view direction.
1284 CMatrix camMat;
1285 camMat.identity();
1286 camMat.setRot(CVector(0,-1,0), CVector(1,0,0), CVector(0,0,1), true);
1287 camMat.rotateZ(UserEntity->frontYaw() + _UserCameraDeltaYaw);
1288 camMat.rotateX(float(UserEntity->getHeadPitch()));
1289 View.view(camMat.getJ());
1291 // Update the mount direction.
1292 CEntityCL *mount = EntitiesMngr.entity(UserEntity->parent());
1293 if(mount)
1295 mount->front(UserEntity->front());
1299 //-----------------------------------------------
1300 // startFreeLook()
1301 //-----------------------------------------------
1302 void CUserControls::startFreeLook()
1304 _FreeLook= true;
1307 //-----------------------------------------------
1308 // stopFreeLook()
1309 //-----------------------------------------------
1310 void CUserControls::stopFreeLook()
1312 EventsListener.enableMouseSmoothing(false);
1313 _FreeLook= false;
1315 // Cursor mode
1316 SetMouseCursor ();
1317 // Give back the mouse handling to the interface.
1318 CWidgetManager::getInstance()->enableMouseHandling(true);
1322 //-----------------------------------------------
1323 // cancelActionsWhenMoving()
1324 //-----------------------------------------------
1325 void CUserControls::cancelActionsWhenMoving()
1327 if( UserEntity->behaviour() == MBEHAV::EXTRACTING ||
1328 (UserEntity->behaviour() >= MBEHAV::MAGIC_CASTING_BEHAVIOUR_BEGIN && UserEntity->behaviour() <= MBEHAV::MAGIC_CASTING_BEHAVIOUR_END) )
1330 UserEntity->cancelAllPhrases();
1332 if( UserEntity->behaviour() == MBEHAV::RANGE_ATTACK )
1334 //UserEntity->disengage();