12
12
import de .amr .pacmanfx .ui .*;
13
13
import de .amr .pacmanfx .ui ._2d .CrudeCanvasContainer ;
14
14
import de .amr .pacmanfx .ui ._2d .GameScene2D ;
15
- import de .amr .pacmanfx .ui ._2d .PopupLayer ;
15
+ import de .amr .pacmanfx .ui ._2d .HelpLayer ;
16
16
import de .amr .pacmanfx .ui ._3d .PlayScene3D ;
17
17
import de .amr .pacmanfx .ui .dashboard .Dashboard ;
18
18
import de .amr .pacmanfx .ui .dashboard .DashboardID ;
22
22
import javafx .scene .Scene ;
23
23
import javafx .scene .SubScene ;
24
24
import javafx .scene .canvas .Canvas ;
25
- import javafx .scene .canvas .GraphicsContext ;
26
25
import javafx .scene .control .ContextMenu ;
27
26
import javafx .scene .control .MenuItem ;
28
27
import javafx .scene .input .ContextMenuEvent ;
@@ -67,48 +66,46 @@ private static byte identifySceneSwitchType(GameScene sceneBefore, GameScene sce
67
66
};
68
67
}
69
68
70
- private final ActionBindingManager actionBindings ;
71
-
69
+ private final ActionBindingManager actionBindings = new DefaultActionBindingManager ();
72
70
private final GameUI ui ;
73
71
private final Scene parentScene ;
74
-
75
- private BorderPane canvasLayer ;
76
- private PopupLayer popupLayer ; // help, signature
77
- private BorderPane dashboardLayer ;
78
-
79
72
private final Dashboard dashboard ;
80
- private final Canvas commonCanvas = new Canvas ();
81
- private final CrudeCanvasContainer canvasContainer = new CrudeCanvasContainer (commonCanvas );
82
- private final MiniGameView miniGameView ;
73
+ private final Canvas canvas = new Canvas ();
74
+ private final CrudeCanvasContainer canvasContainer = new CrudeCanvasContainer (canvas );
75
+ private final MiniGameView miniView = new MiniGameView () ;
83
76
private final ContextMenu contextMenu = new ContextMenu ();
84
77
78
+ private final BorderPane canvasLayer = new BorderPane ();
79
+ private final BorderPane dashboardAndMiniViewLayer = new BorderPane ();
80
+ private HelpLayer helpLayer ; // help
81
+
85
82
public PlayView (GameUI ui , Scene parentScene ) {
86
83
this .ui = requireNonNull (ui );
87
84
this .parentScene = requireNonNull (parentScene );
88
- this .miniGameView = new MiniGameView ();
89
- this .dashboard = new Dashboard (ui );
90
-
91
- this .actionBindings = new DefaultActionBindingManager ();
92
85
93
- configureMiniGameView ();
86
+ dashboard = new Dashboard (ui );
87
+ dashboard .setVisible (false );
88
+
89
+ configureMiniView ();
94
90
configureCanvasContainer ();
95
91
createLayout ();
96
92
configurePropertyBindings ();
97
93
98
- //TODO what is the cleanest solution to hide the context menu in all needed cases?
99
94
setOnContextMenuRequested (this ::handleContextMenuRequest );
100
- // game scene changes: hide it
101
- GameUI .PROPERTY_CURRENT_GAME_SCENE .addListener (
102
- (obs , oldGameScene , newGameScene ) -> handleGameSceneChange (parentScene , newGameScene ));
103
- // any other mouse button clicked: hide it
95
+ //TODO what is the recommended way to hide the context menu?
104
96
parentScene .addEventFilter (MouseEvent .MOUSE_PRESSED , e -> {
105
- if (e .getButton () == MouseButton .PRIMARY ) {
97
+ if (e .getButton () != MouseButton .SECONDARY ) {
106
98
contextMenu .hide ();
107
99
}
108
100
});
109
101
110
- parentScene .widthProperty () .addListener ((py , ov , width ) -> canvasContainer .resizeTo (width .doubleValue (), parentScene .getHeight ()));
111
- parentScene .heightProperty ().addListener ((py , ov , height ) -> canvasContainer .resizeTo (parentScene .getWidth (), height .doubleValue ()));
102
+ GameUI .PROPERTY_CURRENT_GAME_SCENE .addListener ((py , ov , gameScene ) -> {
103
+ contextMenu .hide ();
104
+ if (gameScene != null ) embedGameScene (parentScene , gameScene );
105
+ });
106
+
107
+ parentScene .widthProperty () .addListener ((py , ov , w ) -> canvasContainer .resizeTo (w .doubleValue (), parentScene .getHeight ()));
108
+ parentScene .heightProperty ().addListener ((py , ov , h ) -> canvasContainer .resizeTo (parentScene .getWidth (), h .doubleValue ()));
112
109
113
110
actionBindings .use (ACTION_BOOT_SHOW_PLAY_VIEW , DEFAULT_ACTION_BINDINGS );
114
111
actionBindings .use (ACTION_ENTER_FULLSCREEN , DEFAULT_ACTION_BINDINGS );
@@ -129,11 +126,6 @@ public PlayView(GameUI ui, Scene parentScene) {
129
126
actionBindings .use (ACTION_TOGGLE_PLAY_SCENE_2D_3D , DEFAULT_ACTION_BINDINGS );
130
127
}
131
128
132
- private void handleGameSceneChange (Scene parentScene , GameScene newScene ) {
133
- if (newScene != null ) embedGameScene (parentScene , newScene );
134
- contextMenu .hide ();
135
- }
136
-
137
129
private void handleContextMenuRequest (ContextMenuEvent contextMenuEvent ) {
138
130
contextMenu .getItems ().clear ();
139
131
ui .currentGameScene ().ifPresent (gameScene -> {
@@ -158,7 +150,7 @@ private void handleContextMenuRequest(ContextMenuEvent contextMenuEvent) {
158
150
}
159
151
160
152
public void showHelp (GameUI ui ) {
161
- popupLayer .showHelp (ui , canvasContainer .scaling ());
153
+ helpLayer .showHelp (ui , canvasContainer .scaling ());
162
154
}
163
155
164
156
// -----------------------------------------------------------------------------------------------------------------
@@ -182,12 +174,12 @@ public void draw() {
182
174
}
183
175
});
184
176
185
- if (miniGameView .isVisible () && ui .isCurrentGameSceneID (SCENE_ID_PLAY_SCENE_3D ) && ui .theGameContext ().optGameLevel ().isPresent ()) {
186
- miniGameView .draw (ui , ui .theGameContext ().theGameLevel ());
177
+ if (miniView .isVisible () && ui .isCurrentGameSceneID (SCENE_ID_PLAY_SCENE_3D ) && ui .theGameContext ().optGameLevel ().isPresent ()) {
178
+ miniView .draw (ui , ui .theGameContext ().theGameLevel ());
187
179
}
188
180
189
181
// Dashboard updates must be called from permanent clock task too!
190
- if (dashboardLayer .isVisible ()) {
182
+ if (dashboardAndMiniViewLayer .isVisible ()) {
191
183
dashboard .infoBoxes ().filter (InfoBox ::isExpanded ).forEach (InfoBox ::update );
192
184
}
193
185
}
@@ -219,14 +211,14 @@ public void onGameEvent(GameEvent gameEvent) {
219
211
ActorAnimationMap ghostAnimationMap = config .createGhostAnimations (ghost );
220
212
ghost .setAnimations (ghostAnimationMap );
221
213
});
222
- miniGameView .onLevelCreated (ui , gameLevel );
214
+ miniView .onLevelCreated (ui , gameLevel );
223
215
224
216
// size of game scene might have changed, so re-embed
225
217
ui .currentGameScene ().ifPresent (gameScene -> embedGameScene (parentScene , gameScene ));
226
218
}
227
219
case GAME_STATE_CHANGED -> {
228
220
if (ui .theGameContext ().theGameState () == GameState .LEVEL_COMPLETE ) {
229
- miniGameView .onLevelCompleted ();
221
+ miniView .onLevelCompleted ();
230
222
}
231
223
}
232
224
}
@@ -293,36 +285,37 @@ private void embedGameScene(Scene parentScene, GameScene gameScene) {
293
285
getChildren ().set (0 , subScene );
294
286
}
295
287
else if (gameScene instanceof GameScene2D gameScene2D ) {
296
- embedGameScene2DDirectly (gameScene2D );
297
- gameScene2D .backgroundColorProperty ().bind (GameUI .PROPERTY_CANVAS_BACKGROUND_COLOR );
298
- gameScene2D .clear ();
288
+ embedGameScene2DWithoutSubScene (gameScene2D );
289
+ getChildren ().set (0 , canvasLayer );
299
290
}
300
291
else {
301
292
Logger .error ("Cannot embed play scene of class {}" , gameScene .getClass ().getName ());
302
293
}
303
294
}
304
295
305
- // Game scenes without camera are drawn into the canvas provided by this play view
306
- private void embedGameScene2DDirectly (GameScene2D gameScene2D ) {
307
- gameScene2D .setCanvas (commonCanvas );
308
- gameScene2D .setGameRenderer (ui .theConfiguration ().createGameRenderer (commonCanvas ));
296
+ // 2D game scenes without sub-scene/camera (Arcade play scene, cut scenes) are drawn into the canvas provided by this play view
297
+ private void embedGameScene2DWithoutSubScene (GameScene2D gameScene2D ) {
298
+ gameScene2D .setCanvas (canvas );
299
+ gameScene2D .setGameRenderer (ui .theConfiguration ().createGameRenderer (canvas ));
300
+ gameScene2D .clear ();
301
+ gameScene2D .backgroundColorProperty ().bind (GameUI .PROPERTY_CANVAS_BACKGROUND_COLOR );
309
302
gameScene2D .scalingProperty ().bind (canvasContainer .scalingProperty ().map (
310
303
scaling -> Math .min (scaling .doubleValue (), ui .theUIPrefs ().getFloat ("scene2d.max_scaling" ))));
311
- Vector2f sizePx = gameScene2D .sizeInPx ();
312
- canvasContainer .setUnscaledCanvasSize (sizePx .x (), sizePx .y ());
304
+
305
+ Vector2f gameSceneSizePx = gameScene2D .sizeInPx ();
306
+ canvasContainer .setUnscaledCanvasSize (gameSceneSizePx .x (), gameSceneSizePx .y ());
313
307
canvasContainer .resizeTo (parentScene .getWidth (), parentScene .getHeight ());
314
308
canvasContainer .backgroundProperty ().bind (GameUI .PROPERTY_CANVAS_BACKGROUND_COLOR .map (Ufx ::colorBackground ));
315
- getChildren ().set (0 , canvasLayer );
316
309
}
317
310
318
311
// -----------------------------------------------------------------------------------------------------------------
319
312
320
- private void configureMiniGameView () {
321
- miniGameView .backgroundColorProperty ().bind (GameUI .PROPERTY_CANVAS_BACKGROUND_COLOR );
322
- miniGameView .debugProperty ().bind (GameUI .PROPERTY_DEBUG_INFO_VISIBLE );
323
- miniGameView .canvasHeightProperty ().bind (GameUI .PROPERTY_MINI_VIEW_HEIGHT );
324
- miniGameView .opacityProperty ().bind (GameUI .PROPERTY_MINI_VIEW_OPACITY_PERCENT .divide (100.0 ));
325
- miniGameView .visibleProperty ().bind (Bindings .createObjectBinding (
313
+ private void configureMiniView () {
314
+ miniView .backgroundColorProperty ().bind (GameUI .PROPERTY_CANVAS_BACKGROUND_COLOR );
315
+ miniView .debugProperty ().bind (GameUI .PROPERTY_DEBUG_INFO_VISIBLE );
316
+ miniView .canvasHeightProperty ().bind (GameUI .PROPERTY_MINI_VIEW_HEIGHT );
317
+ miniView .opacityProperty ().bind (GameUI .PROPERTY_MINI_VIEW_OPACITY_PERCENT .divide (100.0 ));
318
+ miniView .visibleProperty ().bind (Bindings .createObjectBinding (
326
319
() -> GameUI .PROPERTY_MINI_VIEW_ON .get () && ui .isCurrentGameSceneID (SCENE_ID_PLAY_SCENE_3D ),
327
320
GameUI .PROPERTY_MINI_VIEW_ON , GameUI .PROPERTY_CURRENT_GAME_SCENE
328
321
));
@@ -331,42 +324,42 @@ private void configureMiniGameView() {
331
324
private void configureCanvasContainer () {
332
325
canvasContainer .setMinScaling (0.5 );
333
326
// 28*TS x 36*TS = Arcade map size in pixels
334
- canvasContainer .setUnscaledCanvasSize (28 *TS , 36 * TS );
327
+ canvasContainer .setUnscaledCanvasSize (28 * TS , 36 * TS );
335
328
canvasContainer .setBorderColor (Color .rgb (222 , 222 , 255 ));
336
-
337
- //canvasContainer.roundedBorderProperty().addListener((py, ov, nv) -> ui.currentGameScene().ifPresent(this::embedGameScene));
338
329
}
339
330
340
331
private void configurePropertyBindings () {
341
- GraphicsContext ctx = commonCanvas .getGraphicsContext2D ();
342
- GameUI .PROPERTY_CANVAS_FONT_SMOOTHING .addListener ((py , ov , on ) -> ctx .setFontSmoothingType (on ? FontSmoothingType .LCD : FontSmoothingType .GRAY ));
343
- GameUI .PROPERTY_CANVAS_IMAGE_SMOOTHING .addListener ((py , ov , on ) -> ctx .setImageSmoothing (on ));
344
- GameUI .PROPERTY_DEBUG_INFO_VISIBLE .addListener ((py , ov , debug ) -> {
345
- canvasLayer .setBackground (debug ? colorBackground (Color .TEAL ) : null );
346
- canvasLayer .setBorder (debug ? border (Color .LIGHTGREEN , 1 ) : null );
347
- });
332
+ GameUI .PROPERTY_CANVAS_FONT_SMOOTHING .addListener ((py , ov , smooth )
333
+ -> canvas .getGraphicsContext2D ().setFontSmoothingType (smooth ? FontSmoothingType .LCD : FontSmoothingType .GRAY ));
334
+
335
+ GameUI .PROPERTY_CANVAS_IMAGE_SMOOTHING .addListener ((py , ov , smooth )
336
+ -> canvas .getGraphicsContext2D ().setImageSmoothing (smooth ));
337
+
338
+ GameUI .PROPERTY_DEBUG_INFO_VISIBLE .addListener ((py , ov , debug )
339
+ -> {
340
+ canvasLayer .setBackground (debug ? colorBackground (Color .TEAL ) : null );
341
+ canvasLayer .setBorder (debug ? border (Color .LIGHTGREEN , 1 ) : null );
342
+ });
348
343
}
349
344
350
345
private void createLayout () {
351
- canvasLayer = new BorderPane (canvasContainer );
346
+ canvasLayer . setCenter (canvasContainer );
352
347
353
- dashboardLayer = new BorderPane ();
354
- dashboardLayer .visibleProperty ().bind (Bindings .createObjectBinding (
348
+ dashboardAndMiniViewLayer .setLeft (dashboard );
349
+ dashboardAndMiniViewLayer .setRight (miniView );
350
+ dashboardAndMiniViewLayer .visibleProperty ().bind (Bindings .createObjectBinding (
355
351
() -> dashboard .isVisible () || GameUI .PROPERTY_MINI_VIEW_ON .get (),
356
352
dashboard .visibleProperty (), GameUI .PROPERTY_MINI_VIEW_ON
357
353
));
358
- dashboardLayer .setLeft (dashboard );
359
- dashboardLayer .setRight (miniGameView );
360
- dashboard .setVisible (false );
361
354
362
355
//TODO reconsider help functionality
363
- popupLayer = new PopupLayer (canvasContainer );
364
- popupLayer .setMouseTransparent (true );
356
+ helpLayer = new HelpLayer (canvasContainer );
357
+ helpLayer .setMouseTransparent (true );
365
358
366
- getChildren ().addAll (canvasLayer , dashboardLayer , popupLayer );
359
+ getChildren ().addAll (canvasLayer , dashboardAndMiniViewLayer , helpLayer );
367
360
}
368
361
369
- // Dashboard
362
+ // Dashboard access
370
363
371
364
public void configureDashboard (List <DashboardID > dashboardIDs ) {
372
365
dashboard .configure (dashboardIDs );
@@ -383,6 +376,4 @@ public void showDashboard(boolean show) {
383
376
public void toggleDashboard () {
384
377
dashboard .toggleVisibility ();
385
378
}
386
-
387
-
388
379
}
0 commit comments