Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
Display.cpp
Go to the documentation of this file.
1#include "Display.hpp"
3
4#include "PlayerSelection.hpp"
5#include "IBar.hpp"
6
7#include <algorithm>
8#include <array>
9#include <cmath>
10#include <cstdlib>
11#include <limits>
12
13namespace monopoly::display
14{
15 namespace
16 {
17 State globalState;
18 boardcamera::Controller boardCameraController;
19 std::uint64_t boardCameraTick{};
20
21
23 {
24 // =================================================
25 // Partie de DISPLAY_UDBOARD_Show() qui valide
26 // desired2DView -> current2DView.
27 //
28 // UDBOARD_SetBackdrop() ne fait PAS ce travail.
29 // =================================================
30
31 if (
32 globalState.current2DView ==
33 globalState.desired2DView)
34 {
35 return;
36 }
37
38
39 globalState.lastBoardActivityTick = boardCameraTick;
40
41 switch (globalState.desired2DView)
42 {
43 case Screen2D::Main:
44 {
45 // DISPLAY_SCREEN_MainA
46 globalState.viewportInUse =
48
49 break;
50 }
51
52
54 {
55 globalState.viewportInUse =
57
58 break;
59 }
60
61
62 case Screen2D::Trade:
63 {
64 globalState.viewportInUse =
66
67 break;
68 }
69
70
72 {
73 // DISPLAY_SCREEN_Pselect
74 //
75 // Original :
76 // currentBackdropID =
77 // DAT_LANG2/BMP_sybkgrnd
78 //
79 // Ce DAT compilé n'est pas dans l'archive,
80 // donc aucun substitut graphique n'est
81 // inventé ici.
82 globalState.viewportInUse =
84
85 break;
86 }
87
88
90 {
91 // DISPLAY_SCREEN_PselectRules
92 //
93 // Original :
94 // DAT_PAT/BMP_rnbacknd
95 globalState.viewportInUse =
97
98 break;
99 }
100
101
102 case Screen2D::Black:
106 default:
107 {
108 globalState.viewportInUse =
110
111 break;
112 }
113 }
114
115
116 // UDBoard.cpp original, fin de
117 // DISPLAY_UDBOARD_Show():
118 //
119 // DISPLAY_state.current2DView =
120 // DISPLAY_state.desired2DView;
121
122 globalState.current2DView =
123 globalState.desired2DView;
124 }
126 {
127 // UDBoard.cpp:913-916 mirrors LE_REND3D_ClearBeforeRender.
128 // When full 3D is disabled, slot 1 must preserve the 2D board
129 // underneath instead of restoring the 3D background surface.
130 globalState.viewportBackgroundFillOn = globalState.game3DOn;
131 const bool shouldBoard3DBeOn = globalState.game3DOn &&
132 isBoardVisible(globalState.desired2DView);
133 const bool boardModeChanged = shouldBoard3DBeOn != globalState.board3DOn;
134 const bool cameraChanged = !globalState.currentBoardCamera ||
135 *globalState.currentBoardCamera != globalState.desiredBoardCamera;
136 const bool revalidate = globalState.desiredCameraInvalidatedLock &&
137 globalState.desiredCameraClearToValidate;
138 const bool manualRequest = globalState.manualCameraRequested;
139 const bool automaticRequest = globalState.optionCameraMovementOn &&
141 const bool initialRequest = !globalState.currentBoardCamera.has_value();
143 {
144 const bool forceInterrupt = !globalState.board3DOn;
145 boardCameraController.requestPreset(
146 globalState.desiredBoardCamera, boardCameraTick, forceInterrupt,
148 globalState.manualCameraRequested = false;
149 globalState.currentBoardCamera = globalState.desiredBoardCamera;
150 if (revalidate)
151 {
152 globalState.desiredCameraInvalidatedLock = false;
153 globalState.desiredCameraClearToValidate = false;
154 }
155 }
156 globalState.board3DOn = shouldBoard3DBeOn;
157 globalState.worldCamera = boardCameraController.current();
158 }
159
160 [[nodiscard]] std::array<float, 3> normalized3(
161 std::array<float, 3> value) noexcept
162 {
163 const float length = std::sqrt(value[0] * value[0] +
164 value[1] * value[1] + value[2] * value[2]);
165 if (length <= 0.00001F) return {};
166 for (float& component : value) component /= length;
167 return value;
168 }
169
170 void startFloatingIdle()
171 {
172 const float cameraY = boardcamera::preset(
173 globalState.desiredBoardCamera).location[1];
174 const float minVariation = cameraY *
175 (globalState.tokenAnimationStackActive ? 0.07F : 0.08F);
176 const float randomVariation = cameraY *
177 (globalState.tokenAnimationStackActive ? 0.05F : 0.08F);
178
179 if (!globalState.floatingCameraActive)
180 {
181 const auto& start = boardCameraController.startCamera().location;
182 const auto& end = boardCameraController.endCamera().location;
183 std::array<float, 3> direction{
184 start[0] - end[0], start[1] - end[1], start[2] - end[2]};
185 direction = normalized3(direction);
186 for (std::size_t axis = 0; axis < 3; ++axis)
187 globalState.lastFloatingVariation[axis] =
188 randomVariation * 0.33F * direction[axis];
189 }
190
191 std::array<float, 3> nextVariation{};
192 do
193 {
194 for (float& component : nextVariation)
196 (static_cast<float>(std::rand() % 100) / 100.0F);
197 }
198 while (nextVariation[0] + nextVariation[1] + nextVariation[2] <
200
201 for (float& component : nextVariation)
202 component -= randomVariation * 0.5F;
203
204 boardCameraController.requestFloatingIdle(boardCameraTick,
205 globalState.lastFloatingVariation, nextVariation);
206 globalState.lastFloatingVariation = nextVariation;
207 globalState.cameraCanFloat = false;
208 globalState.floatingCameraActive = true;
209 }
210
211 void updateDemoMode(std::uint64_t numberOfTicks)
212 {
213 if (numberOfTicks == 0) return;
214 if (!globalState.optionCameraMovementOn)
215 {
216 globalState.lastBoardActivityTick = boardCameraTick;
217 globalState.demoModeDesired = false;
218 globalState.demoWaitTicks = 0;
219 return;
220 }
221
222 constexpr std::uint64_t DemoDelayTicks = 90U * 60U;
223 constexpr float DemoBaseMoveTicks = 85.0F;
224
225 if (globalState.lastBoardActivityTick + DemoDelayTicks <= boardCameraTick &&
226 (!globalState.board3DOn || !globalState.game3DOn))
227 {
228 globalState.lastBoardActivityTick = boardCameraTick;
229 }
230
231 const bool shouldDemo =
232 globalState.lastBoardActivityTick + DemoDelayTicks < boardCameraTick &&
233 globalState.board3DOn;
234
235 if (shouldDemo)
236 {
237 if (!globalState.demoModeDesired)
238 {
239 globalState.cameraCanFloat = false;
240 globalState.floatingCameraActive = false;
241 globalState.demoStartCamera = globalState.desiredBoardCamera;
242 globalState.demoCameraIndex =
243 static_cast<std::uint8_t>(globalState.desiredBoardCamera);
244 globalState.demoCycles = 0;
245 globalState.demoWaitTicks = globalState.demoTicksPerMove;
246 globalState.demoTicksPerMove = static_cast<std::uint32_t>(
248 (static_cast<float>(std::rand() % 800 + 600) / 1000.0F));
249 }
250
251 globalState.demoWaitTicks += static_cast<std::uint32_t>(numberOfTicks);
252 if (globalState.demoWaitTicks >= globalState.demoTicksPerMove)
253 {
254 const auto startIndex =
255 static_cast<std::uint8_t>(globalState.demoStartCamera);
256 if (globalState.demoCameraIndex == startIndex)
257 {
258 ++globalState.demoCycles;
259 if (globalState.demoCycles == 2)
260 globalState.lastBoardActivityTick = boardCameraTick;
261 }
262
263 globalState.demoWaitTicks = 0;
264 globalState.demoCameraIndex = static_cast<std::uint8_t>(
265 (globalState.demoCameraIndex + 1U) % 39U);
266 boardCameraController.requestDemoPreset(
267 static_cast<pieces::BoardCameraView>(globalState.demoCameraIndex),
268 boardCameraTick, globalState.demoTicksPerMove);
269 }
270 globalState.demoModeDesired = true;
271 }
272 else if (globalState.demoModeDesired)
273 {
274 globalState.lastBoardActivityTick = boardCameraTick;
275 globalState.demoModeDesired = false;
276 boardCameraController.requestDemoPreset(globalState.demoStartCamera,
277 boardCameraTick, globalState.demoTicksPerMove);
278 }
279 }
280 }
281
283 {
284 // DISPLAY_initialize() original remet d'abord son état
285 // général en place puis initialise les sous-modules DISPLAY_*.
286
287 globalState = {};
288 globalState.current2DView = Screen2D::Invalid;
289 globalState.desired2DView = Screen2D::PlayerSelect;
290
291 globalState.viewportInUse =
293
294 boardCameraTick = 0;
295 boardCameraController.reset(0);
296 globalState.worldCamera = boardCameraController.current();
297
298 // DISPLAY_UDIBAR_Initialize();
299 if (!ibar::initialize())
300 {
301 return false;
302 }
303
304
305 // DISPLAY_UDPSEL_Initialize();
307 {
309 return false;
310 }
311
312 globalState.initialized = true;
313
314 // Les autres modules historiques viendront dans leur ordre :
315 //
316 // DISPLAY_UDAUCT_Initialize
317 // DISPLAY_UDBOARD_Initialize
318 // DISPLAY_UDIBAR_Initialize
319 // DISPLAY_UDOPTS_Initialize
320 // DISPLAY_UDPIECES_Initialize
321 // DISPLAY_UDPSEL_Initialize <- présent
322 // DISPLAY_UDSOUND_Initialize
323 // DISPLAY_UDSTATS_Initialize
324 // DISPLAY_UDTRADE_Initialize
325
326 return true;
327 }
328
329 void shutdown()
330 {
331 if (globalState.initialized)
332 {
333 // DISPLAY_destroy() original :
334 //
335 // UDBOARD_SetBackdrop(DISPLAY_SCREEN_Black);
336 // DISPLAY_tickActions(1);
337
340 );
341
342
343 tickActions(1);
344 }
345
346
347 // Ordre original relatif :
348 //
349 // DISPLAY_UDIBAR_Destroy()
350 // ...
351 // DISPLAY_UDPSEL_Destroy()
352
354
356
357
358 boardCameraController.reset(0);
359 boardCameraTick = 0;
360 globalState = {};
361 }
362
364 {
365 // ====================================================
366 // UDBOARD_SetBackdrop() ORIGINAL :
367 //
368 // void UDBOARD_SetBackdrop(int backdrop)
369 // {
370 // DISPLAY_state.desired2DView = backdrop;
371 // }
372 //
373 // current2DView est validé plus tard par
374 // DISPLAY_UDBOARD_Show().
375 // ====================================================
376
377 globalState.desired2DView =
378 screen;
379 }
380
382 std::optional<std::uint8_t> randomFourteen)
383 {
384 globalState.diceCameraControlActive = true;
385 globalState.desiredCameraInvalidatedLock = true;
386 globalState.desiredCameraClearToValidate = false;
387 if (randomFourteen && globalState.board3DOn &&
388 globalState.optionCameraMovementOn)
390 }
391
393 {
394 globalState.diceCameraControlActive = false;
395 globalState.desiredCameraClearToValidate = true;
396 }
397
399 {
400 // UDPieces.cpp exits the dice lock early when IBar disappears
401 // without setting desiredCameraClearToValidate.
402 globalState.diceCameraControlActive = false;
403 }
404
406 {
407 if (globalState.desiredCameraInvalidatedLock)
408 globalState.desiredCameraClearToValidate = true;
409 globalState.diceCameraControlActive = false;
410 }
411
413 {
414 globalState.lastBoardActivityTick = boardCameraTick;
415 }
416
417 void applyTokenVoicesOption(bool enabled) noexcept
418 {
419 globalState.optionTokenVoicesOn = enabled;
420 }
421
423 {
424 globalState.optionHostCommentsOn = enabled;
425 }
426
427 void applyMusicOption(bool musicOn) noexcept
428 {
429 globalState.optionMusicOn = musicOn;
430 }
431
432 void applyMusicTune(std::uint8_t tuneIndex) noexcept
433 {
434 globalState.optionMusicTuneIndex = std::min<std::uint8_t>(tuneIndex, 4);
435 }
436
438 bool lightingOn, bool board3DOn) noexcept
439 {
440 globalState.optionTokenAnimationsOn = tokenAnimationsOn;
441 globalState.optionLightingOn = lightingOn;
442
443 if (globalState.optionCameraMovementOn != cameraMovementOn)
444 {
445 globalState.optionCameraMovementOn = cameraMovementOn;
446 globalState.lastBoardActivityTick = boardCameraTick;
447 globalState.cameraCanFloat = false;
448 globalState.floatingCameraActive = false;
449 globalState.demoModeDesired = false;
450 globalState.demoWaitTicks = 0;
452 {
453 globalState.desiredCameraInvalidatedLock = true;
454 globalState.desiredCameraClearToValidate = true;
455 }
456 }
457
458 if (globalState.game3DOn != board3DOn)
459 {
460 globalState.game3DOn = board3DOn;
461 if (!board3DOn)
462 {
463 globalState.manualMouseCamLock = false;
464 boardCameraController.releaseManualMouse();
465 globalState.desiredCameraInvalidatedLock = true;
466 globalState.desiredCameraClearToValidate = true;
467 }
468 }
469 }
470
471 void cycleIBarCamera(std::int32_t currentSquare, bool sequential) noexcept
472 {
473 static std::uint8_t topView = 0;
475
476 const auto current = globalState.desiredBoardCamera;
477 const int currentIndex = static_cast<int>(current);
478 BoardCameraView desired = current;
479
480 if (sequential)
481 {
482 desired = static_cast<BoardCameraView>(
483 (currentIndex + 1) % static_cast<int>(BoardCameraView::Count));
484 }
485 else
486 {
487 int category = 0;
488 if (currentIndex >= static_cast<int>(BoardCameraView::ThreeTiles01)) ++category;
489 if (currentIndex >= static_cast<int>(BoardCameraView::CornerGo)) ++category;
490 if (currentIndex >= static_cast<int>(BoardCameraView::FiveTiles01)) ++category;
491 if (currentIndex >= static_cast<int>(BoardCameraView::FifteenTiles01)) ++category;
492
493 switch ((category + 1) % 5)
494 {
495 case 0:
496 desired = static_cast<BoardCameraView>(topView++ % 3U);
497 break;
498 case 1:
499 desired = pieces::pickCameraFor3Squares(currentSquare);
500 break;
501 default:
503 if (desired == BoardCameraView::CornerJail)
504 desired = static_cast<BoardCameraView>(topView++ % 3U);
505 break;
506 }
507 }
508
509 globalState.desiredBoardCamera = desired;
510 if (!globalState.optionCameraMovementOn || globalState.manualMouseCamLock)
511 globalState.manualCameraRequested = true;
512 }
513
514 void setTokenAnimationStackActive(bool active) noexcept
515 {
516 globalState.tokenAnimationStackActive = active;
517 }
518
519 void requestBssmCamera(std::int32_t square, std::uint8_t action) noexcept
520 {
521 if (square < 0 || square >= 40 || action >= 4) return;
522 if (action >= 2 && globalState.bssmCameraState == 0) return;
523
524 const bool cameraIdle = !boardCameraController.moving() ||
525 boardCameraController.floating();
526 const bool canStart = cameraIdle && globalState.optionCameraMovementOn &&
527 !globalState.demoModeDesired && !globalState.manualMouseCamLock;
528 if (!canStart && globalState.bssmCameraState == 0) return;
529
530 if (globalState.bssmCameraState == 0)
531 globalState.bssmPriorCamera = globalState.desiredBoardCamera;
532 globalState.desiredBoardCamera = pieces::pickCameraFor3Squares(square);
533 globalState.bssmLastRequestedCamera = globalState.desiredBoardCamera;
534 globalState.bssmCameraState = 1;
535 globalState.bssmCameraRequestTick = boardCameraTick;
536 }
537
539 {
540 if (message.type == uimsg::Type::MouseLeftDown ||
542 {
544 }
545 switch (message.type)
546 {
548 globalState.mouseLeftPressed = true;
549 return;
551 globalState.mouseLeftPressed = false;
552 return;
554 globalState.mouseRightPressed = true;
555 return;
557 globalState.mouseRightPressed = false;
558 return;
559 default:
560 break;
561 }
562
563 if (message.type != uimsg::Type::MouseMoved ||
564 !globalState.mouseLeftPressed || !globalState.board3DOn ||
565 globalState.viewportInUse == Viewport3D::Off)
566 return;
567
568 const auto rect = worldViewport(globalState.viewportInUse);
569 if (message.numberA < rect.left || message.numberA > rect.right ||
570 message.numberB < rect.top || message.numberB > rect.bottom)
571 return;
572
573 const auto clampDelta = [](std::int64_t value) noexcept {
574 return static_cast<std::int32_t>(std::clamp<std::int64_t>(value,
575 std::numeric_limits<std::int32_t>::min(),
576 std::numeric_limits<std::int32_t>::max()));
577 };
578 const bool verticalOrbit = globalState.mouseRightPressed ||
579 (message.numberE & uimsg::MouseModifierControl) != 0;
580 if (boardCameraController.requestManualMouseMove(
581 clampDelta(message.numberC), clampDelta(message.numberD),
583 {
584 globalState.manualMouseCamLock = true;
585 globalState.manualMouseCamTime = boardCameraTick;
586 globalState.cameraCanFloat = false;
587 globalState.floatingCameraActive = false;
588 globalState.lastBoardActivityTick = boardCameraTick;
589 globalState.worldCamera = boardCameraController.current();
590 }
591 }
592
593 void showAll2()
594 {
595 // ====================================================
596 // DISPLAY_showAll2() original.
597 //
598 // Modules actuellement portés :
599 //
600 // DISPLAY_UDBOARD_Show
601 // DISPLAY_UDIBAR_Show
602 // DISPLAY_UDPSEL_Show
603 //
604 // On conserve leur ORDRE original.
605 // ====================================================
606
607
608 // DISPLAY_UDBOARD_Show().
611
612
613 // DISPLAY_UDIBAR_Show().
614 ibar::show();
615
616
617 // DISPLAY_UDPSEL_Show().
619 }
620
621 void tickActions(std::uint64_t numberOfTicks)
622 {
623 // ====================================================
624 // DISPLAY_tickActions() original :
625 //
626 // DISPLAY_UDBOARD_TickActions(numberOfTicks);
627 // DISPLAY_UDIBAR_TickActions(numberOfTicks);
628 // DISPLAY_UDPIECES_TickActions(numberOfTicks);
629 // DISPLAY_UDSOUND_tickActions(numberOfTicks);
630 //
631 // DISPLAY_showAll2();
632 // ====================================================
633
634
635 // DISPLAY_UDBOARD_TickActions :
636 // aucune logique temporelle du Board n'est encore
637 // nécessaire dans cette tranche.
638
639
640 boardCameraTick += numberOfTicks;
641 globalState.boardTick = boardCameraTick;
642 updateDemoMode(numberOfTicks);
644 globalState.worldCamera = cameraUpdate.camera;
645 if (globalState.manualMouseCamLock &&
646 !boardCameraController.manualMouseActive())
647 globalState.manualMouseCamLock = false;
648 if (cameraUpdate.startedWaitingMove)
649 {
650 if (globalState.bssmCameraState == 2)
651 globalState.bssmCameraState = 0;
652 else if (globalState.bssmCameraState == 1)
653 globalState.bssmCameraState = 2;
654 globalState.cameraCanFloat = true;
655 globalState.floatingCameraActive = false;
656 }
657 if (globalState.cameraCanFloat && !boardCameraController.moving() &&
658 globalState.optionCameraMovementOn &&
659 !globalState.demoModeDesired && globalState.board3DOn &&
660 globalState.game3DOn &&
662 !globalState.manualMouseCamLock)
663 {
665 }
666 if (globalState.bssmCameraState > 0 &&
667 boardCameraTick > globalState.bssmCameraRequestTick + 60U * 5U)
668 {
669 if (globalState.bssmLastRequestedCamera == globalState.desiredBoardCamera)
670 globalState.desiredBoardCamera = globalState.bssmPriorCamera;
671 globalState.bssmCameraState = 0;
672 }
673
674 if (globalState.manualMouseCamLock &&
675 boardCameraTick > globalState.manualMouseCamTime +
676 60U * 20U)
677 {
678 globalState.manualMouseCamLock = false;
679 boardCameraController.releaseManualMouse();
680 globalState.desiredCameraInvalidatedLock = true;
681 globalState.desiredCameraClearToValidate = true;
682 }
683
684 // DISPLAY_UDIBAR_TickActions().
686 numberOfTicks
687 );
688
689
690 // UDPIECES / UDSOUND seront insérés ici dans leur
691 // emplacement historique lorsqu'ils seront portés.
692
693
694 // IMPORTANT :
695 // DISPLAY_showAll2() vient APRES tous les TickActions.
696 showAll2();
697 }
698
700 {
701 return globalState;
702 }
703
705 {
706 return globalState;
707 }
708}
709
710
711
712
713
bool enabled
Definition Engine.cpp:170
unsigned index
Rect rect
std::uint16_t value
Definition Timers.cpp:16
const engine::World3DCamera & preset(pieces::BoardCameraView view) noexcept
State & state()
Definition Display.cpp:699
void processBoardInput(const uimsg::Message &message)
Definition Display.cpp:538
void applyMusicOption(bool musicOn) noexcept
Definition Display.cpp:427
void applyRuntimeOptions(bool tokenAnimationsOn, bool cameraMovementOn, bool lightingOn, bool board3DOn) noexcept
Definition Display.cpp:437
engine::World3DRect worldViewport(Viewport3D viewport) noexcept
Definition Display.hpp:76
void releaseDiceCameraOverride()
Definition Display.cpp:392
void applyHostCommentsOption(bool enabled) noexcept
Definition Display.cpp:422
constexpr bool isBoardVisible(Screen2D screen) noexcept
Definition Display.hpp:41
void requestBssmCamera(std::int32_t square, std::uint8_t action) noexcept
Definition Display.cpp:519
void noteBoardActivity() noexcept
Definition Display.cpp:412
void endDiceCameraOverrideEarly()
Definition Display.cpp:398
void beginDiceCameraOverride(std::optional< std::uint8_t > randomFourteen)
Definition Display.cpp:381
void setTokenAnimationStackActive(bool active) noexcept
Definition Display.cpp:514
void setBackdrop(Screen2D screen)
Definition Display.cpp:363
const State & stateReadOnly()
Definition Display.cpp:704
void cycleIBarCamera(std::int32_t currentSquare, bool sequential) noexcept
Definition Display.cpp:471
void cancelDiceCameraOverride()
Definition Display.cpp:405
void tickActions(std::uint64_t numberOfTicks)
Definition Display.cpp:621
void applyTokenVoicesOption(bool enabled) noexcept
Definition Display.cpp:417
void applyMusicTune(std::uint8_t tuneIndex) noexcept
Definition Display.cpp:432
bool initialize()
Definition IBar.cpp:745
void shutdown()
Definition IBar.cpp:765
void show()
Definition IBar.cpp:800
void tickActions(std::uint64_t numberOfTicks)
Definition IBar.cpp:773
BoardCameraView pickCameraFor3Squares(std::int32_t square) noexcept
BoardCameraView pickCameraFor15Squares(std::int32_t square) noexcept
constexpr std::int64_t MouseModifierControl