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