RigsofRods
Soft-body Physics Simulation
SceneMouse.cpp
Go to the documentation of this file.
1 /*
2  This source file is part of Rigs of Rods
3  Copyright 2005-2012 Pierre-Michel Ricordel
4  Copyright 2007-2012 Thomas Fischer
5  Copyright 2013-2014 Petr Ohlidal
6 
7  For more information, see http://www.rigsofrods.org/
8 
9  Rigs of Rods is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License version 3, as
11  published by the Free Software Foundation.
12 
13  Rigs of Rods 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 Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
25 
26 #include "SceneMouse.h"
27 
28 #include "Actor.h"
29 #include "Application.h"
30 #include "GameContext.h"
31 #include "GfxScene.h"
32 #include "ScriptEngine.h"
33 
34 #include <Ogre.h>
35 
36 using namespace Ogre;
37 using namespace RoR;
38 
39 #define MOUSE_GRAB_FORCE 30000.0f
40 
41 SceneMouse::SceneMouse() :
42  mouseGrabState(0),
43  grab_truck(nullptr),
44  pickLine(nullptr),
45  pickLineNode(nullptr)
46 {
47  this->reset();
48 }
49 
51 {
52  // load 3d line for mouse picking
53  pickLine = App::GetGfxScene()->GetSceneManager()->createManualObject("PickLineObject");
54  pickLineNode = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode("PickLineNode");
55 
56  MaterialPtr pickLineMaterial = MaterialManager::getSingleton().getByName("PickLineMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
57  if (pickLineMaterial.isNull())
58  {
59  pickLineMaterial = MaterialManager::getSingleton().create("PickLineMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
60  }
61  pickLineMaterial->setReceiveShadows(false);
62  pickLineMaterial->getTechnique(0)->setLightingEnabled(true);
63  pickLineMaterial->getTechnique(0)->getPass(0)->setDiffuse(0, 0, 1, 0);
64  pickLineMaterial->getTechnique(0)->getPass(0)->setAmbient(0, 0, 1);
65  pickLineMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(0, 0, 1);
66 
67  pickLine->begin("PickLineMaterial", RenderOperation::OT_LINE_LIST);
68  pickLine->position(0, 0, 0);
69  pickLine->position(0, 0, 0);
70  pickLine->end();
71  pickLineNode->attachObject(pickLine);
72  pickLineNode->setVisible(false);
73 }
74 
76 {
77  if (pickLineNode != nullptr)
78  {
79  App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->removeAndDestroyChild("PickLineNode");
80  pickLineNode = nullptr;
81  }
82 
83  if (pickLine != nullptr)
84  {
85  App::GetGfxScene()->GetSceneManager()->destroyManualObject("PickLineObject");
86  pickLine = nullptr;
87  }
88 }
89 
91 {
92  if (App::sim_state->getEnum<SimState>() == SimState::PAUSED) { return; } // Do nothing when paused
93 
94  // remove forces
95  if (grab_truck)
96  grab_truck->mouseMove(minnode, Vector3::ZERO, 0);
97 
98  this->reset();
99 }
100 
102 {
104  grab_truck = 0;
105  mindist = 99999;
106  mouseGrabState = 0;
107  lastgrabpos = Vector3::ZERO;
108  lastMouseX = 0;
109  lastMouseY = 0;
110 
111  mouseGrabState = 0;
112 }
113 
115 {
116  // IMPORTANT: get mouse button state from InputEngine, not from OIS directly
117  // - that state may be dirty, see commentary in `InputEngine::getMouseState()`
118  const OIS::MouseState ms = App::GetInputEngine()->getMouseState();
119 
120 
121  if (ms.buttonDown(OIS::MB_Left) && mouseGrabState == 0)
122  {
123  lastMouseY = ms.Y.abs;
124  lastMouseX = ms.X.abs;
125 
126  Ray mouseRay = getMouseRay();
127 
128  // walk all trucks
130  grab_truck = NULL;
131  for (ActorPtr& actor : App::GetGameContext()->GetActorManager()->GetActors())
132  {
133  if (actor->ar_state == ActorState::LOCAL_SIMULATED)
134  {
135  // check if our ray intersects with the bounding box of the truck
136  std::pair<bool, Real> pair = mouseRay.intersects(actor->ar_bounding_box);
137  if (!pair.first)
138  continue;
139 
140  for (int j = 0; j < actor->ar_num_nodes; j++)
141  {
142  if (actor->ar_nodes[j].nd_no_mouse_grab)
143  continue;
144 
145  // check if our ray intersects with the node
146  std::pair<bool, Real> pair = mouseRay.intersects(Sphere(actor->ar_nodes[j].AbsPosition, 0.1f));
147  if (pair.first)
148  {
149  // we hit it, check if its the nearest node
150  if (pair.second < mindist)
151  {
152  mindist = pair.second;
153  minnode = (NodeNum_t)j;
154  grab_truck = actor;
155  }
156  }
157  }
158  }
159  }
160 
161  // check if we hit a node
163  {
164  mouseGrabState = 1;
165 
166  for (std::vector<hook_t>::iterator it = grab_truck->ar_hooks.begin(); it != grab_truck->ar_hooks.end(); it++)
167  {
168  if (it->hk_hook_node->pos == minnode)
169  {
170  //grab_truck->hookToggle(it->hk_group, HOOK_MOUSE_TOGGLE, minnode);
174  rq->alr_hook_group = it->hk_group;
177  }
178  }
179  }
180  }
181  else if (App::GetInputEngine()->getMouseState().buttonDown(OIS::MB_Left) && mouseGrabState == 1)
182  {
183  // force applying and so forth happens in update()
184  lastMouseY = ms.Y.abs;
185  lastMouseX = ms.X.abs;
186  // not fixed
187  return false;
188  }
189  else if (!App::GetInputEngine()->getMouseState().buttonDown(OIS::MB_Left) && mouseGrabState == 1)
190  {
192  // not fixed
193  return false;
194  }
195 
196  return false;
197 }
198 
200 {
201  if (mouseGrabState == 1 && grab_truck)
202  {
203  // get values
204  Ray mouseRay = getMouseRay();
205  lastgrabpos = mouseRay.getPoint(mindist);
206 
207  // add forces
209  }
210 }
211 
213 {
214  if (grab_truck == nullptr)
215  {
216  pickLineNode->setVisible(false); // Hide the line
217  }
218  else
219  {
220  pickLineNode->setVisible(true); // Show the line
221  // update visual line
222  pickLine->beginUpdate(0);
224  pickLine->position(lastgrabpos);
225  pickLine->end();
226  }
227 }
228 
230 {
231  if (App::sim_state->getEnum<SimState>() == SimState::PAUSED) { return true; } // Do nothing when paused
232 
233  // IMPORTANT: get mouse button state from InputEngine, not from OIS directly
234  // - that state may be dirty, see commentary in `InputEngine::getMouseState()`
235  const OIS::MouseState ms = App::GetInputEngine()->getMouseState();
236 
237  if (ms.buttonDown(OIS::MB_Middle))
238  {
239  lastMouseY = ms.Y.abs;
240  lastMouseX = ms.X.abs;
241  Ray mouseRay = getMouseRay();
242 
243  if (App::sim_state->getEnum<SimState>() == SimState::EDITOR_MODE)
244  {
245  return true;
246  }
247 
248  ActorPtr player_actor = App::GetGameContext()->GetPlayerActor();
249 
250  // Reselect the player actor
251  {
252  Real nearest_ray_distance = std::numeric_limits<float>::max();
253 
254  for (ActorPtr& actor : App::GetGameContext()->GetActorManager()->GetActors())
255  {
256  if (actor != player_actor)
257  {
258  Vector3 pos = actor->getPosition();
259  std::pair<bool, Real> pair = mouseRay.intersects(Sphere(pos, actor->getMinCameraRadius()));
260  if (pair.first)
261  {
262  Real ray_distance = mouseRay.getDirection().crossProduct(pos - mouseRay.getOrigin()).length();
263  if (ray_distance < nearest_ray_distance)
264  {
265  nearest_ray_distance = ray_distance;
267  }
268  }
269  }
270  }
271  }
272 
273  // Reselect the vehicle orbit camera center
274  if (player_actor && App::GetCameraManager()->GetCurrentBehavior() == CameraManager::CAMERA_BEHAVIOR_VEHICLE)
275  {
276  Real nearest_camera_distance = std::numeric_limits<float>::max();
277  Real nearest_ray_distance = std::numeric_limits<float>::max();
278  NodeNum_t nearest_node_index = NODENUM_INVALID;
279 
280  for (int i = 0; i < player_actor->ar_num_nodes; i++)
281  {
282  Vector3 pos = player_actor->ar_nodes[i].AbsPosition;
283  std::pair<bool, Real> pair = mouseRay.intersects(Sphere(pos, 0.25f));
284  if (pair.first)
285  {
286  Real ray_distance = mouseRay.getDirection().crossProduct(pos - mouseRay.getOrigin()).length();
287  if (ray_distance < nearest_ray_distance || (ray_distance == nearest_ray_distance && pair.second < nearest_camera_distance))
288  {
289  nearest_camera_distance = pair.second;
290  nearest_ray_distance = ray_distance;
291  nearest_node_index = (NodeNum_t)i;
292  }
293  }
294  }
295  if (player_actor->ar_custom_camera_node != nearest_node_index)
296  {
297  player_actor->ar_custom_camera_node = nearest_node_index;
298  player_actor->calculateAveragePosition();
299  App::GetCameraManager()->NotifyContextChange(); // Reset last 'look at' pos
300  }
301  }
302  }
303 
304  return true;
305 }
306 
308 {
309  if (App::sim_state->getEnum<SimState>() == SimState::PAUSED) { return true; } // Do nothing when paused
310 
311  if (mouseGrabState == 1)
312  {
314  }
315 
316  return true;
317 }
318 
320 {
321  Viewport* vp = App::GetCameraManager()->GetCamera()->getViewport();
322 
323  return App::GetCameraManager()->GetCamera()->getCameraToViewportRay((float)lastMouseX / (float)vp->getActualWidth(), (float)lastMouseY / (float)vp->getActualHeight());
324 }
GameContext.h
Game state manager and message-queue provider.
RoR::ActorLinkingRequest::alr_hook_group
int alr_hook_group
Definition: SimData.h:922
RoR::SceneMouse::lastMouseX
int lastMouseX
Definition: SceneMouse.h:62
RoR::SceneMouse::handleMouseReleased
bool handleMouseReleased()
Definition: SceneMouse.cpp:307
RoR::SceneMouse::reset
void reset()
Definition: SceneMouse.cpp:101
RoR::SceneMouse::DiscardVisuals
void DiscardVisuals()
Definition: SceneMouse.cpp:75
RoR::App::GetCameraManager
CameraManager * GetCameraManager()
Definition: Application.cpp:275
RoR::node_t::AbsPosition
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition: SimData.h:294
RoR::ActorLinkingRequest
Estabilishing a physics linkage between 2 actors modifies a global linkage table and triggers immedia...
Definition: SimData.h:917
RoR::GfxActor::GetSimNodeBuffer
NodeSB * GetSimNodeBuffer()
Definition: GfxActor.h:120
RoR::Actor::ar_instance_id
ActorInstanceID_t ar_instance_id
Static attr; session-unique ID.
Definition: Actor.h:376
RoR::Actor::ar_num_nodes
int ar_num_nodes
Definition: Actor.h:283
RoR::InputEngine::getMouseState
OIS::MouseState getMouseState()
Definition: InputEngine.cpp:603
RoR::NODENUM_INVALID
static const NodeNum_t NODENUM_INVALID
Definition: ForwardDeclarations.h:53
RoR::ActorLinkingRequestType::HOOK_MOUSE_TOGGLE
@ HOOK_MOUSE_TOGGLE
RoR::Actor::mouseMove
void mouseMove(NodeNum_t node, Ogre::Vector3 pos, float force)
Definition: Actor.cpp:1340
RoR::ActorLinkingRequest::alr_type
ActorLinkingRequestType alr_type
Definition: SimData.h:920
RoR::SimState::EDITOR_MODE
@ EDITOR_MODE
Hacky, but whatever... added by Ulteq, 2016.
RoR::SceneMouse::UpdateSimulation
void UpdateSimulation()
Definition: SceneMouse.cpp:199
RoR::SceneMouse::handleMousePressed
bool handleMousePressed()
Definition: SceneMouse.cpp:229
RoR::Actor::ar_hooks
std::vector< hook_t > ar_hooks
Definition: Actor.h:302
RoR::Actor::GetGfxActor
GfxActor * GetGfxActor()
Definition: Actor.h:269
RoR::ActorState::LOCAL_SIMULATED
@ LOCAL_SIMULATED
simulated (local) actor
RoR::App::sim_state
CVar * sim_state
Definition: Application.cpp:96
RefCountingObjectPtr< Actor >
RoR::SceneMouse::lastMouseY
int lastMouseY
Definition: SceneMouse.h:62
Actor.h
RoR::SceneMouse::mouseGrabState
int mouseGrabState
Definition: SceneMouse.h:56
RoR::GfxScene::GetSceneManager
Ogre::SceneManager * GetSceneManager()
Definition: GfxScene.h:64
RoR::CameraManager::NotifyContextChange
void NotifyContextChange()
Definition: CameraManager.cpp:617
RoR::SceneMouse::InitializeVisuals
void InitializeVisuals()
Definition: SceneMouse.cpp:50
RoR::CameraManager::GetCamera
Ogre::Camera * GetCamera()
Definition: CameraManager.h:64
RoR::NodeNum_t
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Definition: ForwardDeclarations.h:52
MOUSE_GRAB_FORCE
#define MOUSE_GRAB_FORCE
Definition: SceneMouse.cpp:39
RoR::MSG_SIM_SEAT_PLAYER_REQUESTED
@ MSG_SIM_SEAT_PLAYER_REQUESTED
Payload = RoR::ActorPtr (owner) | nullptr.
Definition: Application.h:122
ScriptEngine.h
RoR::GameContext::PushMessage
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
Definition: GameContext.cpp:65
RoR::SceneMouse::UpdateVisuals
void UpdateVisuals()
Definition: SceneMouse.cpp:212
GfxScene.h
RoR::CameraManager::CAMERA_BEHAVIOR_VEHICLE
@ CAMERA_BEHAVIOR_VEHICLE
Definition: CameraManager.h:48
RoR::SimState::PAUSED
@ PAUSED
Application.h
Central state/object manager and communications hub.
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:280
RoR::SceneMouse::grab_truck
ActorPtr grab_truck
Definition: SceneMouse.h:60
RoR::SceneMouse::mindist
float mindist
Definition: SceneMouse.h:59
RoR::SceneMouse::getMouseRay
Ogre::Ray getMouseRay()
Definition: SceneMouse.cpp:319
RoR::SceneMouse::pickLine
Ogre::ManualObject * pickLine
Definition: SceneMouse.h:54
RoR::NodeSB::AbsPosition
Ogre::Vector3 AbsPosition
Definition: SimBuffers.h:69
RoR::Actor::ar_nodes
node_t * ar_nodes
Definition: Actor.h:279
RoR::SceneMouse::lastgrabpos
Ogre::Vector3 lastgrabpos
Definition: SceneMouse.h:61
RoR::MSG_SIM_ACTOR_LINKING_REQUESTED
@ MSG_SIM_ACTOR_LINKING_REQUESTED
Payload = RoR::ActorLinkingRequest* (owner)
Definition: Application.h:128
RoR::Message
Unified game event system - all requests and state changes are reported using a message.
Definition: GameContext.h:51
RoR::Actor::ar_custom_camera_node
NodeNum_t ar_custom_camera_node
Sim state; custom tracking node for 3rd-person camera.
Definition: Actor.h:424
RoR::SceneMouse::pickLineNode
Ogre::SceneNode * pickLineNode
Definition: SceneMouse.h:55
RoR::App::GetInputEngine
InputEngine * GetInputEngine()
Definition: Application.cpp:271
RoR::ActorPtr
RefCountingObjectPtr< Actor > ActorPtr
Definition: ForwardDeclarations.h:194
RoR::ActorLinkingRequest::alr_actor_instance_id
ActorInstanceID_t alr_actor_instance_id
Definition: SimData.h:919
RoR::ActorLinkingRequest::alr_hook_mousenode
NodeNum_t alr_hook_mousenode
Definition: SimData.h:923
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::Actor::calculateAveragePosition
void calculateAveragePosition()
Definition: Actor.cpp:1130
RoR::SceneMouse::handleMouseMoved
bool handleMouseMoved()
Definition: SceneMouse.cpp:114
RoR::SceneMouse::releaseMousePick
void releaseMousePick()
Definition: SceneMouse.cpp:90
SceneMouse.h
Mouse interaction with 3D scene.
RoR::SceneMouse::minnode
NodeNum_t minnode
Definition: SceneMouse.h:58
RoR::GameContext::GetPlayerActor
const ActorPtr & GetPlayerActor()
Definition: GameContext.h:134
RoR
Definition: AppContext.h:36
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:276