Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
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
36using namespace Ogre;
37using namespace RoR;
38
39#define MOUSE_GRAB_FORCE 30000.0f
40
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)
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;
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
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}
Central state/object manager and communications hub.
Game state manager and message-queue provider.
#define MOUSE_GRAB_FORCE
Mouse interaction with 3D scene.
NodeNum_t ar_custom_camera_node
Sim state; custom tracking node for 3rd-person camera.
Definition Actor.h:497
node_t * ar_nodes
Definition Actor.h:330
GfxActor * GetGfxActor()
Definition Actor.h:309
void mouseMove(NodeNum_t node, Ogre::Vector3 pos, float force)
Definition Actor.cpp:1400
ActorInstanceID_t ar_instance_id
Static attr; session-unique ID.
Definition Actor.h:429
int ar_num_nodes
Definition Actor.h:345
void calculateAveragePosition()
Definition Actor.cpp:1166
std::vector< hook_t > ar_hooks
Definition Actor.h:366
ActorPtrVec & GetActors()
Ogre::Camera * GetCamera()
const ActorPtr & GetPlayerActor()
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
ActorManager * GetActorManager()
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
Ogre::SceneManager * GetSceneManager()
Definition GfxScene.h:83
OIS::MouseState getMouseState()
void InitializeVisuals()
void UpdateSimulation()
void DiscardVisuals()
void releaseMousePick()
Ogre::SceneNode * pickLineNode
Definition SceneMouse.h:55
Ogre::ManualObject * pickLine
Definition SceneMouse.h:54
bool handleMousePressed()
NodeNum_t minnode
Definition SceneMouse.h:58
Ogre::Ray getMouseRay()
Ogre::Vector3 lastgrabpos
Definition SceneMouse.h:61
bool handleMouseMoved()
bool handleMouseReleased()
ActorPtr grab_truck
Definition SceneMouse.h:60
@ EDITOR_MODE
Hacky, but whatever... added by Ulteq, 2016.
@ MSG_SIM_ACTOR_LINKING_REQUESTED
Payload = RoR::ActorLinkingRequest* (owner)
@ MSG_SIM_SEAT_PLAYER_REQUESTED
Payload = RoR::ActorPtr (owner) | nullptr.
@ LOCAL_SIMULATED
simulated (local) actor
CVar * sim_state
InputEngine * GetInputEngine()
CameraManager * GetCameraManager()
GameContext * GetGameContext()
GfxScene * GetGfxScene()
static const NodeNum_t NODENUM_INVALID
RefCountingObjectPtr< Actor > ActorPtr
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Estabilishing a physics linkage between 2 actors modifies a global linkage table and triggers immedia...
Definition SimData.h:909
ActorLinkingRequestType alr_type
Definition SimData.h:911
ActorInstanceID_t alr_actor_instance_id
Definition SimData.h:910
NodeNum_t alr_hook_mousenode
Definition SimData.h:914
Unified game event system - all requests and state changes are reported using a message.
Definition GameContext.h:52
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition SimData.h:267