Skyscraper 2.0
mainscreen.cpp
Go to the documentation of this file.
1/*
2 Skyscraper 2.0 Alpha - Main Screen
3 Copyright (C)2003-2024 Ryan Thoryk
4 https://www.skyscrapersim.net
5 https://sourceforge.net/projects/skyscraper/
6 Contact - ryan@skyscrapersim.net
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21*/
22
23#ifdef USING_WX
24#include "wx/wx.h"
25#include "wx/joystick.h"
26#include <OgreRoot.h>
27#include <OgreRenderWindow.h>
28#include <OgreViewport.h>
29#include <OgreCamera.h>
30#include <OgreRTShaderSystem.h>
31#include "globals.h"
32#include "sbs.h"
33#include "camera.h"
34#include "debugpanel.h"
35#include "skyscraper.h"
36#include "vm.h"
37#include "hal.h"
38#include "sky.h"
39#include "gui.h"
40#include "enginecontext.h"
41#include "loaddialog.h"
42#include "mainscreen.h"
43
44using namespace SBS;
45
46namespace Skyscraper {
47
48BEGIN_EVENT_TABLE(MainScreen, wxFrame)
49 EVT_ICONIZE(MainScreen::OnIconize)
50 EVT_SIZE(MainScreen::OnSize)
51 EVT_CLOSE(MainScreen::OnClose)
52 EVT_IDLE(MainScreen::OnIdle)
53 EVT_PAINT(MainScreen::OnPaint)
54 EVT_ACTIVATE(MainScreen::OnActivate)
55#ifndef __FreeBSD__
56 EVT_JOYSTICK_EVENTS(MainScreen::OnJoystickEvent)
57#endif
58END_EVENT_TABLE()
59
60MainScreen::MainScreen(Skyscraper *parent, int width, int height) : wxFrame(0, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE)
61{
62 frontend = parent;
63 Active = false;
64 InLoop = false;
65 panel = 0;
66 Center();
67 wxString title;
68 title = wxT("Skyscraper " + frontend->GetVM()->version + " " + frontend->GetVM()->version_state);
69 SetTitle(title);
70 SetClientSize(width, height);
71 SetExtraStyle(wxWS_EX_PROCESS_IDLE);
72
73#ifndef __FreeBSD__
74 joystick = new wxJoystick(wxJOYSTICK1);
75 if (joystick->IsOk())
76 {
77 joy_buttons = joystick->GetNumberButtons();
78 joystick->SetCapture(this, 10);
79 }
80 else
81 joy_buttons = -1;
82#endif
83
84 HAL *hal = frontend->GetVM()->GetHAL();
85
86 key_right = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Right", "D")[0];
87 key_left = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Left", "A")[0];
88 key_up = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Up", "W")[0];
89 key_down = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Down", "S")[0];
90 key_strafeleft = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.StrafeLeft", "Q")[0];
91 key_straferight = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.StrafeRight", "E")[0];
92 key_lookup = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.LookUp", "P")[0];
93 key_lookdown = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.LookDown", "L")[0];
94 key_binoculars = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Binoculars", "B")[0];
95 key_crouch = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Crouch", "X")[0];
96 key_floatup = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.FloatUp", "O")[0];
97 key_floatdown = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.FloatDown", "K")[0];
98 key_noclip = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.NoClip", "V")[0];
99 key_pickup = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.PickUp", "C")[0];
100 key_load = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Load", ";")[0];
101 key_enter = hal->GetConfigString(hal->keyconfigfile, "Skyscraper.Frontend.Keyboard.Enter", "E")[0];
102
103#ifndef __FreeBSD__
104 joy_click = hal->GetConfigInt(hal->joyconfigfile, "Skyscraper.Frontend.Joystick.Click", 0);
105 joy_fast = hal->GetConfigInt(hal->joyconfigfile, "Skyscraper.Frontend.Joystick.Fast", 1);
106 joy_strafe = hal->GetConfigInt(hal->joyconfigfile, "Skyscraper.Frontend.Joystick.Strafe", 2);
107 joy_jump = hal->GetConfigInt(hal->joyconfigfile, "Skyscraper.Frontend.Joystick.Jump", 3);
108 joy_turn = hal->GetConfigInt(hal->joyconfigfile, "Skyscraper.Frontend.Joystick.Turn", 0);
109 joy_forward = hal->GetConfigInt(hal->joyconfigfile, "Skyscraper.Frontend.Joystick.Forward", 1);
110#endif
111
112 //create panel, rendering is done on this, along with keyboard and mouse events
113 panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(width, height), wxNO_BORDER);
114 panel->Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(MainScreen::OnKeyDown), NULL, this);
115 panel->Connect(wxID_ANY, wxEVT_KEY_UP, wxKeyEventHandler(MainScreen::OnKeyUp), NULL, this);
116 panel->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
117 panel->Connect(wxID_ANY, wxEVT_LEFT_UP, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
118 panel->Connect(wxID_ANY, wxEVT_LEFT_DCLICK, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
119 panel->Connect(wxID_ANY, wxEVT_MIDDLE_DOWN, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
120 panel->Connect(wxID_ANY, wxEVT_MIDDLE_UP, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
121 panel->Connect(wxID_ANY, wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
122 panel->Connect(wxID_ANY, wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
123 panel->Connect(wxID_ANY, wxEVT_RIGHT_UP, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
124 panel->Connect(wxID_ANY, wxEVT_RIGHT_DCLICK, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
125 panel->Connect(wxID_ANY, wxEVT_MOUSEWHEEL, wxMouseEventHandler(MainScreen::OnMouseButton), NULL, this);
126}
127
128MainScreen::~MainScreen()
129{
130#ifndef __FreeBSD__
131 joystick->ReleaseCapture();
132 delete joystick;
133#endif
134}
135
136void MainScreen::OnIconize(wxIconizeEvent& event)
137{
138 //pause simulator while minimized
139
140 VM *vm = frontend->GetVM();
141 vm->Pause = event.IsIconized();
142
143 if (vm->Pause == true)
144 vm->GetHAL()->Report("Pausing simulator...", "");
145 else
146 vm->GetHAL()->Report("Resuming simulator...", "");
147}
148
149void MainScreen::OnSize(wxSizeEvent& WXUNUSED(event))
150{
151 VM *vm = frontend->GetVM();
152 HAL *hal = vm->GetHAL();
153
154 if (panel)
155 panel->SetSize(this->GetClientSize().GetWidth(), this->GetClientSize().GetHeight());
156
157 if (hal->GetRenderWindow())
158 {
159#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
160 Real scale = this->GetContentScaleFactor();
161 hal->GetRenderWindow()->resize(this->GetClientSize().GetWidth() * scale, this->GetClientSize().GetHeight() * scale);
162#else
163 hal->GetRenderWindow()->windowMovedOrResized();
164#endif
165 }
166 for (size_t i = 0; i < hal->mCameras.size(); i++)
167 {
168 hal->mCameras[i]->setAspectRatio(Real(hal->mViewports[i]->getActualWidth()) / Real(hal->mViewports[i]->getActualHeight()));
169 }
170}
171
172void MainScreen::OnClose(wxCloseEvent& event)
173{
174 if (frontend)
175 {
176 if (frontend->StartupRunning == false)
177 {
178 int result = wxMessageBox(wxT("Are you sure you want to exit?"), wxT("Skyscraper"), wxYES_NO | wxCENTER);
179 if (result == wxNO)
180 return;
181 }
182 }
183
184 wxGetApp().Exit();
185}
186
187void MainScreen::ShowWindow()
188{
189 Show(true);
190}
191
192void MainScreen::OnIdle(wxIdleEvent& event)
193{
194 //prevent simultaneous executions - this fixes an issue with wxYield
195 if (InLoop == false)
196 {
197 InLoop = true;
198
199 if (frontend->GetVM()->Pause == false)
200 {
201 if (this->HasFocus() && !panel->HasFocus())
202 panel->SetFocus();
203
204 try {
205 bool result = frontend->Loop(); //run simulator loop
206 if (!result)
207 frontend->Quit();
208 }
209 catch (Ogre::Exception &e)
210 {
211 frontend->GetVM()->GetHAL()->ReportFatalError("Unhandled OGRE exception:\n\n" + e.getFullDescription() + "\n\nSkyscraper will now exit. Please report this as a bug.", "");
212 frontend->Quit();
213 }
214
215 HandleMouseMovement();
216 event.RequestMore(); //request more idles
217 }
218
219 InLoop = false;
220 }
221}
222
223void MainScreen::OnPaint(wxPaintEvent& event)
224{
225 wxPaintDC dc(this);
226
227 //if (frontend->GetVM()->GetRenderWindow())
228 //frontend->GetVM()->GetRenderWindow()->update(true);
229}
230
231void MainScreen::OnActivate(wxActivateEvent &event)
232{
233 Active = event.GetActive();
234 event.Skip();
235}
236
237void MainScreen::OnKeyDown(wxKeyEvent& event)
238{
239 //this function is run when a key is pressed
240
241 EngineContext *engine = frontend->GetVM()->GetActiveEngine();
242
243 if (!engine)
244 return;
245
246 //get SBS instance
247 ::SBS::SBS *Simcore = engine->GetSystem();
248
249 if (!Simcore)
250 return;
251
252 Camera *camera = Simcore->camera;
253
254 if (!camera)
255 return;
256
257 int key = event.GetKeyCode();
258
259#if OGRE_PLATFORM != OGRE_PLATFORM_APPLE
260 //don't process a key down event if the key is actually up, this fixes a "stuck key" issue on some systems
261 if (wxGetKeyState((wxKeyCode)key) == false)
262 return;
263#endif
264
265 if (key == WXK_ESCAPE)
266 {
267 int result = wxMessageBox(wxT("Exit and return to the main menu?"), wxT("Skyscraper"), wxYES_NO | wxCENTER);
268 if (result == wxYES)
269 frontend->GetVM()->Shutdown = true;
270 return;
271 }
272
273 if (key == WXK_F1)
274 {
275 frontend->GetGUI()->ShowControlReference();
276 }
277
278 if (key == WXK_F2)
279 {
280 Real fps = Simcore->FPS;
281 HAL *hal = frontend->GetVM()->GetHAL();
282 Ogre::RenderSystem *rendersystem = hal->mRoot->getRenderSystem();
283
284 int batches = (int)rendersystem->_getBatchCount();
285 int triangles = (int)rendersystem->_getFaceCount();
286 int vertices = (int)rendersystem->_getVertexCount();
287
288 hal->Report("FPS: " + ToString(Simcore->FPS) + " - Batches: " + ToString(batches) + " - Triangles: " + ToString(triangles) + " - Vertices: " + ToString(vertices), "");
289 }
290
291 //alt modifier
292 if (event.AltDown())
293 {
294 //crash test
295 if (event.ControlDown() && key == (wxKeyCode)'C')
296 throw;
297
298 if (key == WXK_F4)
299 Close();
300 }
301 else
302 {
303 if (key == WXK_SPACE)
304 {
305 //jump (spacebar) action
306 if (camera->IsOnGround() == true)
307 camera->Jump();
308 }
309
310 if (key == (wxKeyCode)key_noclip)
311 {
312 bool status = camera->GetGravityStatus();
313
314 camera->EnableGravity(!status);
315 camera->EnableCollisions(!status);
316
317 if (status == false)
318 frontend->GetVM()->GetHAL()->Report("Gravity and collision detection on", "");
319 else
320 frontend->GetVM()->GetHAL()->Report("Gravity and collision detection off", "");
321 }
322
323 if (event.ControlDown() == true && key == (wxKeyCode)'R')
324 {
325 engine->Reload = true;
326 return;
327 }
328
329 if (key == WXK_F3)
330 {
331 //reset rotation/direction and FOV of camera
332 camera->ResetView();
333 return;
334 }
335
336 if (key == WXK_F6)
337 {
338 //reset camera position and state
339 camera->ResetState();
340 return;
341 }
342
343 if (key == WXK_F7)
344 {
345 //show colliders
346 Simcore->ShowColliders(!frontend->colliders);
347 frontend->colliders = !frontend->colliders;
348 }
349
350 if (key == WXK_F4)
351 {
352 //toggle wireframe mode
353 if (frontend->wireframe == 0)
354 {
355 frontend->GetVM()->GetSkySystem()->EnableSky(false);
356 camera->SetViewMode(1);
357 frontend->wireframe = 1;
358 }
359 else if (frontend->wireframe == 1)
360 {
361 camera->SetViewMode(2);
362 frontend->wireframe = 2;
363 }
364 else if (frontend->wireframe == 2)
365 {
366 frontend->GetVM()->GetSkySystem()->EnableSky(true);
367 camera->SetViewMode(0);
368 frontend->wireframe = 0;
369 }
370 }
371
372 if (key == WXK_F11)
373 {
374 std::string prefix = frontend->GetDataPath();
375 frontend->GetVM()->GetHAL()->GetRenderWindow()->writeContentsToTimestampedFile(prefix + "screenshots/skyscraper-", ".jpg");
376 }
377
378 if (key == WXK_F12)
379 {
380 frontend->GetGUI()->ShowDebugPanel();
381 }
382
383 if (key == WXK_F5)
384 {
385 //toggle freelook mode
386 EnableFreelook(!camera->Freelook);
387 }
388
389 if (key == WXK_F10)
390 {
391 //toggle fullscreen mode
392 frontend->SetFullScreen(!frontend->FullScreen);
393 }
394
395 if (key == WXK_F8)
396 {
397 //show mesh bounding boxes
398 Simcore->ShowBoundingBoxes(!frontend->boxes);
399 frontend->boxes = !frontend->boxes;
400 }
401
402 if (key == WXK_F9)
403 {
404 //toggle statistics bar
405 frontend->GetVM()->GetHAL()->ToggleStats();
406 }
407
408 if (key == WXK_NUMPAD_SUBTRACT || key == (wxKeyCode)'[')
409 {
410 //increase FOV angle
411 Real angle = camera->GetFOVAngle() + camera->cfg_zoomspeed;
412 camera->SetFOVAngle(angle);
413 }
414
415 if (key == WXK_NUMPAD_ADD || key == (wxKeyCode)']')
416 {
417 //decrease FOV angle
418 Real angle = camera->GetFOVAngle() - camera->cfg_zoomspeed;
419 camera->SetFOVAngle(angle);
420 }
421
422 //model pick-up
423 if (key == (wxKeyCode)key_pickup)
424 {
425 if (camera->IsModelAttached() == false)
426 camera->PickUpModel();
427 else
428 camera->DropModel();
429 }
430
431 //load a new additional building
432 if (key == (wxKeyCode)key_load)
433 {
434 frontend->GetGUI()->ShowLoadDialog();
435 return;
436 }
437
438 //engine selection
439 if (key == (wxKeyCode)'1')
440 {
441 frontend->GetVM()->SetActiveEngine(0);
442 }
443 else if (key == (wxKeyCode)'2')
444 {
445 frontend->GetVM()->SetActiveEngine(1);
446 }
447 else if (key == (wxKeyCode)'3')
448 {
449 frontend->GetVM()->SetActiveEngine(2);
450 }
451 else if (key == (wxKeyCode)'4')
452 {
453 frontend->GetVM()->SetActiveEngine(3);
454 }
455 else if (key == (wxKeyCode)'5')
456 {
457 frontend->GetVM()->SetActiveEngine(4);
458 }
459 else if (key == (wxKeyCode)'6')
460 {
461 frontend->GetVM()->SetActiveEngine(5);
462 }
463 else if (key == (wxKeyCode)'7')
464 {
465 frontend->GetVM()->SetActiveEngine(6);
466 }
467 else if (key == (wxKeyCode)'8')
468 {
469 frontend->GetVM()->SetActiveEngine(7);
470 }
471 else if (key == (wxKeyCode)'9')
472 {
473 frontend->GetVM()->SetActiveEngine(8);
474 }
475 else if (key == (wxKeyCode)'0')
476 {
477 frontend->GetVM()->SetActiveEngine(9);
478 }
479
480 //enter and exit a vehicle
481 if (key == (wxKeyCode)key_enter)
482 {
483 //enter or exit a vehicle
484 camera->AttachToVehicle(!camera->inside_vehicle);
485 }
486 }
487
488 GetKeyStates(engine, event, true);
489
490 ProcessMovement(engine, event.ControlDown(), event.ShiftDown());
491}
492
493void MainScreen::OnKeyUp(wxKeyEvent& event)
494{
495 //this function is run when a key is released
496
497 EngineContext *engine = frontend->GetVM()->GetActiveEngine();
498
499 if (!engine)
500 return;
501
502 GetKeyStates(engine, event, false);
503
504 ProcessMovement(engine, event.ControlDown(), event.ShiftDown());
505}
506
507void MainScreen::GetKeyStates(EngineContext *engine, wxKeyEvent& event, bool down)
508{
509 //get SBS camera
510 Camera *camera = engine->GetSystem()->camera;
511
512 if (!camera)
513 return;
514
515 int key = event.GetKeyCode();
516
517 //alt modifier
518 if (event.AltDown())
519 {
520 //strafe movement
521 if (key == WXK_RIGHT || key == (wxKeyCode)key_right)
522 frontend->strafe_right = down;
523
524 else if (key == WXK_LEFT || key == (wxKeyCode)key_left)
525 frontend->strafe_left = down;
526
527 else if (key == WXK_UP || key == (wxKeyCode)key_up)
528 frontend->float_up = down;
529
530 else if (key == WXK_DOWN || key == (wxKeyCode)key_down)
531 frontend->float_down = down;
532
533 else if (key == WXK_PAGEUP || key == (wxKeyCode)key_lookup)
534 frontend->spin_up = down;
535
536 else if (key == WXK_PAGEDOWN || key == (wxKeyCode)key_lookdown)
537 frontend->spin_down = down;
538 }
539 else
540 {
541 if (camera->Freelook == false)
542 {
543 if (key == WXK_RIGHT || key == (wxKeyCode)key_right)
544 frontend->turn_right = down;
545
546 if (key == WXK_LEFT || key == (wxKeyCode)key_left)
547 frontend->turn_left = down;
548
549 if (key == (wxKeyCode)key_straferight)
550 frontend->strafe_right = down;
551
552 if (key == (wxKeyCode)key_strafeleft)
553 frontend->strafe_left = down;
554 }
555 else
556 {
557 if (key == WXK_RIGHT || key == (wxKeyCode)key_right || key == (wxKeyCode)key_straferight)
558 frontend->strafe_right = down;
559
560 if (key == WXK_LEFT || key == (wxKeyCode)key_left || key == (wxKeyCode)key_strafeleft)
561 frontend->strafe_left = down;
562 }
563
564 if (key == WXK_PAGEUP || key == (wxKeyCode)key_lookup)
565 frontend->look_up = down;
566
567 if (key == WXK_PAGEDOWN || key == (wxKeyCode)key_lookdown)
568 frontend->look_down = down;
569
570 if (key == WXK_UP || key == (wxKeyCode)key_up)
571 frontend->step_forward = down;
572
573 if (key == WXK_DOWN || key == (wxKeyCode)key_down)
574 frontend->step_backward = down;
575
576 //binoculars
577 if (key == (wxKeyCode)key_binoculars)
578 {
579 camera->Binoculars(down);
580 }
581
582 //crouch
583 if (key == (wxKeyCode)key_crouch)
584 {
585 camera->Crouch(down);
586 }
587
588 //values from old version
589 if (key == WXK_HOME || key == (wxKeyCode)key_floatup)
590 frontend->float_up = down;
591 if (key == WXK_END || key == (wxKeyCode)key_floatdown)
592 frontend->float_down = down;
593
594 //drive functions, when user is inside a vehicle
595 if (camera->Freelook == true && camera->inside_vehicle == true)
596 {
597 if (key == WXK_LEFT || key == (wxKeyCode)key_left)
598 engine->GetSystem()->camera->Drive(true, false, false, false, down);
599 if (key == WXK_RIGHT || key == (wxKeyCode)key_right)
600 engine->GetSystem()->camera->Drive(false, true, false, false, down);
601 if (key == WXK_DOWN || key == (wxKeyCode)key_down)
602 engine->GetSystem()->camera->Drive(false, false, true, false, down);
603 if (key == WXK_UP || key == (wxKeyCode)key_up)
604 engine->GetSystem()->camera->Drive(false, false, false, true, down);
605 }
606 }
607}
608
609void MainScreen::ProcessMovement(EngineContext *engine, bool control, bool shift, bool angle_only)
610{
611 //process movement
612
613 Real strafe = 0, floatval = 0, spin = 0, turn = 0, look = 0, step = 0;
614
615 //get SBS camera
616 Camera *camera = engine->GetSystem()->camera;
617
618 if (!camera)
619 return;
620
621 Real speed_normal = camera->cfg_speed;
622 Real speed_fast = camera->cfg_speedfast;
623 Real speed_slow = camera->cfg_speedslow;
624
625 if (angle_only == false)
626 {
627 camera->speed = 1;
628
629 if (control == true)
630 camera->speed = speed_slow;
631 else if (shift == true)
632 camera->speed = speed_fast;
633
634 if (frontend->step_forward == true)
635 step += speed_normal;
636 if (frontend->step_backward == true)
637 step -= speed_normal;
638
639 if (frontend->strafe_left == true)
640 strafe -= speed_normal;
641 if (frontend->strafe_right == true)
642 strafe += speed_normal;
643
644 if (frontend->float_up == true)
645 floatval += speed_normal;
646 if (frontend->float_down == true)
647 floatval -= speed_normal;
648
649 //set camera motion values
650 camera->Step(step);
651 camera->Strafe(strafe);
652 camera->Float(floatval);
653 }
654
655 if (frontend->spin_up == true)
656 spin += speed_normal;
657 if (frontend->spin_down == true)
658 spin -= speed_normal;
659
660 if (frontend->turn_left == true)
661 turn -= speed_normal;
662 if (frontend->turn_right == true)
663 turn += speed_normal;
664
665 if (frontend->look_up == true)
666 look += speed_normal;
667 if (frontend->look_down == true)
668 look -= speed_normal;
669
670 //set camera rotation values
671 camera->Spin(spin);
672 camera->Turn(turn);
673 camera->Look(look);
674}
675
676void MainScreen::OnMouseButton(wxMouseEvent& event)
677{
678 //this function is run when a mouse button is pressed
679
680 //enter or exit freelook mode using mouse scroll wheel
681 if (event.GetWheelRotation() > 0)
682 {
683 EnableFreelook(true);
684 return;
685 }
686 else if (event.GetWheelRotation() < 0)
687 {
688 EnableFreelook(false);
689 return;
690 }
691
692 //check if the user clicked on an object, and process it
693 bool left = event.LeftDown();
694 bool left_dclick = event.LeftDClick();
695 bool right = event.RightDown();
696 bool right_dclick = event.RightDClick();
697
698 HAL *hal = frontend->GetVM()->GetHAL();
699
700 if (left == false && right == false && left_dclick == false && right_dclick == false)
701 {
702 hal->UnclickedObject();
703 }
704 else
705 {
706 //apply content scaling factor, fixes issues for example on Retina displays
707 Real scale = frontend->window->GetContentScaleFactor();
708
709#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
710 //set scale to 1.0 on MacOS versions earlier than 10.15
711 if (frontend->GetVM()->macos_major == 10 && frontend->GetVM()->macos_minor < 15)
712 scale = 1.0;
713#endif
714
715 hal->ClickedObject(left, wxGetKeyState(WXK_SHIFT), wxGetKeyState(WXK_CONTROL), wxGetKeyState(WXK_ALT), (right || right_dclick), scale, false);
716 }
717}
718
719void MainScreen::HandleMouseMovement()
720{
721 EngineContext *engine = frontend->GetVM()->GetActiveEngine();
722
723 if (!engine || IsActive() == false)
724 return;
725
726 if (engine->IsRunning() == false)
727 return;
728
729 //get SBS instance
730 ::SBS::SBS *Simcore = engine->GetSystem();
731
732 if (!Simcore)
733 return;
734
735 Camera *camera = Simcore->camera;
736
737 if (!camera)
738 return;
739
740 //get old mouse coordinates
741 int old_mouse_x = camera->mouse_x;
742 int old_mouse_y = camera->mouse_y;
743
744 //get mouse pointer coordinates
745 camera->mouse_x = ScreenToClient(wxGetMousePosition()).x;
746 camera->mouse_y = ScreenToClient(wxGetMousePosition()).y;
747
748 //freelook mode
749 if (camera->Freelook == true)
750 {
751 if (frontend->freelook == false)
752 {
753 //reset values to prevent movement from getting stuck
754 frontend->turn_right = 0;
755 frontend->turn_left = 0;
756
757 EnableFreelook(true);
758 }
759
760 frontend->freelook = true;
761
762 //get window dimensions
763 Real width = GetClientSize().GetWidth();
764 Real height = GetClientSize().GetHeight();
765
766 //if mouse coordinates changed, and we're in freelook mode, rotate camera
767 if (old_mouse_x != camera->mouse_x || old_mouse_y != camera->mouse_y)
768 {
769 WarpPointer(width * 0.5, height * 0.5);
770
771 Vector3 rotational;
772 rotational.x = -(((Real)camera->mouse_y - (height / 2))) / (height * 2);
773 rotational.y = -((width / 2) - (Real)camera->mouse_x) / (width * 2);
774 rotational.z = 0;
775
776 Real fps_adjust = Simcore->FPS / 60;
777 rotational *= fps_adjust;
778
779 //apply freelook rotation
780 camera->FreelookMove(rotational);
781 }
782 else
783 {
784 //reset rotation by reprocessing keyboard-based rotation
785 ProcessMovement(engine, false, false, true);
786 }
787 }
788 else
789 {
790 if (frontend->freelook == true)
791 {
792 //reset values to prevent movement from getting stuck
793 frontend->strafe_right = 0;
794 frontend->strafe_left = 0;
795 if (old_mouse_x != camera->mouse_x || old_mouse_y != camera->mouse_y)
796 camera->FreelookMove(Vector3::ZERO);
797 ProcessMovement(engine, false, false, true);
798 }
799 frontend->freelook = false;
800 }
801}
802
803void MainScreen::EnableFreelook(bool value)
804{
805 //enable or disable freelook mode
806
807 EngineContext *engine = frontend->GetVM()->GetActiveEngine();
808
809 if (!engine)
810 return;
811
812 //get SBS instance
813 ::SBS::SBS *Simcore = engine->GetSystem();
814
815 Camera *camera = Simcore->camera;
816
817 if (!camera)
818 return;
819
820 camera->Freelook = value;
821
822#if defined(__WXMSW__)
823 if (value == true)
824 SetCursor(wxCURSOR_CROSS);
825 else
826 SetCursor(wxNullCursor);
827#else
828
829 //detect for Wayland on Linux
830 bool wayland = false;
831 const char * val = std::getenv("WAYLAND_DISPLAY");
832 if (val != 0)
833 wayland = true;
834
835 if (value == true)
836 {
837 if (wayland == false)
838 wxSetCursor(wxCURSOR_CROSS);
839 else
840 wxSetCursor(wxCURSOR_BLANK); //set to blank for FreeLook to work on Wayland
841 }
842 else
843 wxSetCursor(wxNullCursor);
844#endif
845}
846
847#ifndef __FreeBSD__
848void MainScreen::OnJoystickEvent(wxJoystickEvent &event)
849{
850 if (event.IsZMove())
851 return;
852
853 EngineContext *engine = frontend->GetVM()->GetActiveEngine();
854
855 if (!engine)
856 return;
857
858 //get SBS instance
859 ::SBS::SBS *Simcore = engine->GetSystem();
860
861 Camera *camera = Simcore->camera;
862
863 if (!camera)
864 return;
865
866 Real speed_normal = camera->cfg_speed;
867 Real speed_fast = camera->cfg_speedfast;
868 Real speed_slow = camera->cfg_speedslow;
869
870 Real step = 0, turn = 0, strafe = 0;
871
872 Real speed = speed_normal;
873
874 int MinX = joystick->GetXMin();
875 int MaxX = joystick->GetXMax();
876 int MinY = joystick->GetYMin();
877 int MaxY = joystick->GetYMax();
878
879 int CenterX = (MaxX + MinX) / 2;
880 int CenterY = (MaxY + MinY) / 2;
881 int range = (MaxX - MinX) / 8;
882
883 if (joystick->GetButtonState(joy_fast))
884 speed = speed_fast;
885
886 if (joystick->GetPosition(joy_forward) < (CenterY - range))
887 step += speed;
888 if (joystick->GetPosition(joy_forward) > (CenterY + range))
889 step -= speed;
890
891 if (joystick->GetButtonState(joy_strafe))
892 {
893 if (joystick->GetPosition(joy_turn) > (CenterX + range))
894 strafe += speed;
895 if (joystick->GetPosition(joy_turn) < (CenterX - range))
896 strafe -= speed;
897 }
898 else
899 {
900 if (joystick->GetPosition(joy_turn) > (CenterX + range))
901 turn += speed;
902 if (joystick->GetPosition(joy_turn) < (CenterX - range))
903 turn -= speed;
904 }
905
906 camera->Step(step);
907 camera->Turn(turn);
908 camera->Strafe(strafe);
909
910 if (joystick->GetButtonState(joy_click))
911 engine->GetVM()->GetHAL()->ClickedObject(true, false, false, false, false, 0.0, true);
912
913 if (joystick->GetButtonState(joy_jump) && camera->IsOnGround() == true)
914 camera->Jump();
915}
916#endif
917
918}
919
920#endif
bool PickUpModel()
Definition camera.cpp:1250
int mouse_y
Definition camera.h:98
void Strafe(Real speed=1.0)
Definition camera.cpp:854
Real GetFOVAngle()
Definition camera.cpp:1009
void Binoculars(bool value)
Definition camera.cpp:1193
bool IsOnGround()
Definition camera.cpp:1069
void AttachToVehicle(bool value)
Definition camera.cpp:1552
bool GetGravityStatus()
Definition camera.cpp:984
void ResetView()
Definition camera.cpp:1344
void DropModel()
Definition camera.cpp:1293
void FreelookMove(const Vector3 &rotation)
Definition camera.cpp:904
bool inside_vehicle
Definition camera.h:94
int mouse_x
Definition camera.h:98
bool Freelook
Definition camera.h:87
void Crouch(bool value)
Definition camera.cpp:1536
void SetViewMode(int mode)
Definition camera.cpp:1030
void Turn(Real speed=1.0)
Definition camera.cpp:892
Real cfg_zoomspeed
Definition camera.h:76
Real cfg_speedfast
Definition camera.h:74
void SetFOVAngle(Real angle)
Definition camera.cpp:989
void ResetState()
Definition camera.cpp:1311
void Jump()
Definition camera.cpp:872
void Step(Real speed=1.0)
Definition camera.cpp:860
Real cfg_speed
Definition camera.h:73
bool IsModelAttached()
Definition camera.cpp:1304
Real speed
Definition camera.h:81
void Float(Real speed=1.0)
Definition camera.cpp:866
void Look(Real speed=1.0)
Definition camera.cpp:886
void Spin(Real speed=1.0)
Definition camera.cpp:898
Real cfg_speedslow
Definition camera.h:75
void EnableGravity(bool value)
Definition camera.cpp:966
void EnableCollisions(bool value)
Definition camera.cpp:1051
void ShowBoundingBoxes(bool value)
Definition sbs.cpp:4015
Camera * camera
Definition sbs.h:160
Real FPS
Definition sbs.h:174
void ShowColliders(bool value)
Definition sbs.cpp:3385
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
std::string ToString(int number)
Definition globals.cpp:279