Browse Source

right click with menu

Bastien Sevajol 3 years ago
parent
commit
b46e282ac1
3 changed files with 172 additions and 16 deletions
  1. BIN
      resources/ui.png
  2. BIN
      resources/ui.xcf
  3. 172 16
      src/main.rs

BIN
resources/ui.png View File


BIN
resources/ui.xcf View File


+ 172 - 16
src/main.rs View File

@@ -11,6 +11,7 @@ use std::collections::HashMap;
11 11
 use std::env;
12 12
 use std::path;
13 13
 
14
+// TODO: create a ScenePosition and a WindowPosition to be more explicit
14 15
 type Point2 = Vec2;
15 16
 type Vector2 = Vec2;
16 17
 
@@ -22,12 +23,15 @@ const SPRITE_EACH: u32 = 10; // change sprite animation tile 30 frames
22 23
 const MAX_FRAME_I: u32 = 4294967295; // max of frame_i used to calculate ticks
23 24
 const DISPLAY_OFFSET_BY: f32 = 3.0; // pixel offset by tick when player move screen display
24 25
 const DISPLAY_OFFSET_BY_SPEED: f32 = 10.0; // pixel offset by tick when player move screen display with speed
25
-const SPRITE_SHEET_WIDTH: f32 = 800.0; // Width of sprite sheet
26
-const SPRITE_SHEET_HEIGHT: f32 = 600.0; // Height of sprite sheet
26
+const SCENE_ITEMS_SPRITE_SHEET_WIDTH: f32 = 800.0; // Width of sprite sheet
27
+const SCENE_ITEMS_SPRITE_SHEET_HEIGHT: f32 = 600.0; // Height of sprite sheet
28
+const UI_SPRITE_SHEET_WIDTH: f32 = 800.0; // Width of sprite sheet
29
+const UI_SPRITE_SHEET_HEIGHT: f32 = 600.0; // Height of sprite sheet
27 30
 const GRID_TILE_WIDTH: f32 = 5.0; // Width of one grid tile
28 31
 const GRID_TILE_HEIGHT: f32 = 5.0; // Height of one grid tile
29 32
 const DEFAULT_SELECTED_SQUARE_SIDE: f32 = 14.0;
30 33
 const DEFAULT_SELECTED_SQUARE_SIDE_HALF: f32 = DEFAULT_SELECTED_SQUARE_SIDE / 2.0;
34
+const SCENE_ITEMS_CHANGE_ERR_MSG: &str = "scene_items content change !";
31 35
 
32 36
 #[derive(Eq, PartialEq, Hash)]
33 37
 pub struct GridPosition {
@@ -54,6 +58,56 @@ fn grid_position_from_position(position: &Point2) -> GridPosition {
54 58
     )
55 59
 }
56 60
 
61
+enum UiItem {
62
+    SceneItemMenu,
63
+}
64
+
65
+enum SceneItemMenuItem {
66
+    Move,
67
+}
68
+
69
+struct UiSpriteInfo {
70
+    relative_start_x: f32,
71
+    relative_start_y: f32,
72
+    relative_width: f32,
73
+    relative_height: f32,
74
+    width: f32,
75
+    height: f32,
76
+}
77
+
78
+impl UiSpriteInfo {
79
+    pub fn from_type(type_: UiItem) -> Self {
80
+        match type_ {
81
+            UiItem::SceneItemMenu => Self {
82
+                relative_start_x: 0.0,
83
+                relative_start_y: 0.0,
84
+                relative_width: 71.0 / UI_SPRITE_SHEET_WIDTH,
85
+                relative_height: 68.0 / UI_SPRITE_SHEET_HEIGHT,
86
+                width: 71.0,
87
+                height: 68.0,
88
+            },
89
+        }
90
+    }
91
+
92
+    pub fn as_draw_param(&self) -> graphics::DrawParam {
93
+        graphics::DrawParam::new().src(graphics::Rect::new(
94
+            self.relative_start_x,
95
+            self.relative_start_y,
96
+            self.relative_width,
97
+            self.relative_height,
98
+        ))
99
+    }
100
+
101
+    pub fn which_item_clicked(
102
+        &self,
103
+        menu_position: Point2,
104
+        click_position: Point2,
105
+        scene_item: &SceneItem,
106
+    ) -> Option<SceneItemMenuItem> {
107
+        Some(SceneItemMenuItem::Move)
108
+    }
109
+}
110
+
57 111
 struct SpriteInfo {
58 112
     relative_start_y: f32,
59 113
     relative_tile_width: f32,
@@ -75,9 +129,9 @@ impl SpriteInfo {
75 129
         };
76 130
 
77 131
         Self {
78
-            relative_start_y: start_y / SPRITE_SHEET_HEIGHT,
79
-            relative_tile_width: tile_width / SPRITE_SHEET_WIDTH,
80
-            relative_tile_height: tile_height / SPRITE_SHEET_HEIGHT,
132
+            relative_start_y: start_y / SCENE_ITEMS_SPRITE_SHEET_HEIGHT,
133
+            relative_tile_width: tile_width / SCENE_ITEMS_SPRITE_SHEET_WIDTH,
134
+            relative_tile_height: tile_height / SCENE_ITEMS_SPRITE_SHEET_HEIGHT,
81 135
             tile_count,
82 136
             tile_width,
83 137
             tile_height,
@@ -116,6 +170,7 @@ impl ItemState {
116 170
 struct SceneItem {
117 171
     type_: SceneItemType,
118 172
     position: Point2,
173
+    grid_position: GridPosition,
119 174
     state: ItemState,
120 175
     meta_events: Vec<MetaEvent>,
121 176
     current_frame: u16,
@@ -125,7 +180,8 @@ impl SceneItem {
125 180
     pub fn new(type_: SceneItemType, position: Point2, state: ItemState) -> Self {
126 181
         Self {
127 182
             type_,
128
-            position,
183
+            position: position.clone(),
184
+            grid_position: grid_position_from_position(&position.clone()),
129 185
             state,
130 186
             meta_events: vec![],
131 187
             current_frame: 0,
@@ -181,9 +237,14 @@ enum MetaEvent {
181 237
 #[derive(Debug)]
182 238
 enum UserEvent {
183 239
     Click(Point2),                 // Window coordinates
240
+    RightClick(Point2),            // Window coordinates
184 241
     AreaSelection(Point2, Point2), // Window coordinates
185 242
 }
186 243
 
244
+enum SceneItemPrepareOrder {
245
+    Move(usize), // scene_item usize
246
+}
247
+
187 248
 struct MainState {
188 249
     // time
189 250
     frame_i: u32,
@@ -192,6 +253,7 @@ struct MainState {
192 253
     display_offset: Point2,
193 254
     sprite_sheet_batch: graphics::spritebatch::SpriteBatch,
194 255
     map_batch: graphics::spritebatch::SpriteBatch,
256
+    ui_batch: graphics::spritebatch::SpriteBatch,
195 257
 
196 258
     // scene items
197 259
     scene_items: Vec<SceneItem>,
@@ -202,9 +264,12 @@ struct MainState {
202 264
 
203 265
     // user interactions
204 266
     left_click_down: Option<Point2>,
267
+    right_click_down: Option<Point2>,
205 268
     current_cursor_position: Point2,
206 269
     user_events: Vec<UserEvent>,
207
-    selected_scene_items: Vec<usize>,
270
+    selected_scene_items: Vec<usize>,         // scene_item usize
271
+    scene_item_menu: Option<(usize, Point2)>, // scene_item usize, display_at
272
+    scene_item_prepare_order: Option<SceneItemPrepareOrder>,
208 273
 }
209 274
 
210 275
 impl MainState {
@@ -213,6 +278,8 @@ impl MainState {
213 278
         let sprite_sheet_batch = graphics::spritebatch::SpriteBatch::new(sprite_sheet);
214 279
         let map = graphics::Image::new(ctx, "/map1bg.png").unwrap();
215 280
         let map_batch = graphics::spritebatch::SpriteBatch::new(map);
281
+        let ui = graphics::Image::new(ctx, "/ui.png").unwrap();
282
+        let ui_batch = graphics::spritebatch::SpriteBatch::new(ui);
216 283
 
217 284
         let mut scene_items = vec![];
218 285
         for x in 0..1 {
@@ -236,13 +303,17 @@ impl MainState {
236 303
             display_offset: Point2::new(0.0, 0.0),
237 304
             sprite_sheet_batch,
238 305
             map_batch,
306
+            ui_batch,
239 307
             scene_items,
240 308
             scene_items_by_grid_position: HashMap::new(),
241 309
             physics_events: vec![],
242 310
             left_click_down: None,
311
+            right_click_down: None,
243 312
             current_cursor_position: Point2::new(0.0, 0.0),
244 313
             user_events: vec![],
245 314
             selected_scene_items: vec![],
315
+            scene_item_menu: None,
316
+            scene_item_prepare_order: None,
246 317
         };
247 318
 
248 319
         for (i, scene_item) in main_state.scene_items.iter().enumerate() {
@@ -280,10 +351,10 @@ impl MainState {
280 351
 
281 352
         while let Some(user_event) = self.user_events.pop() {
282 353
             match user_event {
283
-                UserEvent::Click(position) => {
354
+                UserEvent::Click(click_position) => {
284 355
                     let scene_position = Point2::new(
285
-                        position.x - self.display_offset.x,
286
-                        position.y - self.display_offset.y,
356
+                        click_position.x - self.display_offset.x,
357
+                        click_position.y - self.display_offset.y,
287 358
                     );
288 359
                     self.selected_scene_items.drain(..);
289 360
                     if let Some(scene_item_usize) =
@@ -291,6 +362,41 @@ impl MainState {
291 362
                     {
292 363
                         self.selected_scene_items.push(scene_item_usize);
293 364
                     }
365
+
366
+                    if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
367
+                        // TODO: Add order to scene_item
368
+                        self.scene_item_prepare_order = None;
369
+                    }
370
+
371
+                    // FIXME BS NOW: interpreter sur quel element du menu on a click ...
372
+                    if let Some((scene_item_usize, menu_position)) = self.scene_item_menu {
373
+                        let menu_sprite_info = UiSpriteInfo::from_type(UiItem::SceneItemMenu);
374
+                        let scene_item = self
375
+                            .scene_items
376
+                            .get(scene_item_usize)
377
+                            .expect(SCENE_ITEMS_CHANGE_ERR_MSG);
378
+                        if click_position.x >= menu_position.x
379
+                            && click_position.x <= menu_position.x + menu_sprite_info.width
380
+                            && click_position.y >= menu_position.y
381
+                            && click_position.y <= menu_position.y + menu_sprite_info.height
382
+                        {
383
+                            if let Some(menu_item) = menu_sprite_info.which_item_clicked(
384
+                                menu_position,
385
+                                click_position,
386
+                                scene_item,
387
+                            ) {
388
+                                match menu_item {
389
+                                    SceneItemMenuItem::Move => {
390
+                                        self.scene_item_prepare_order =
391
+                                            Some(SceneItemPrepareOrder::Move(scene_item_usize));
392
+                                        self.scene_item_menu = None;
393
+                                    }
394
+                                }
395
+                            }
396
+                        } else {
397
+                            self.scene_item_menu = None;
398
+                        }
399
+                    };
294 400
                 }
295 401
                 UserEvent::AreaSelection(from, to) => {
296 402
                     let scene_from = Point2::new(
@@ -303,6 +409,20 @@ impl MainState {
303 409
                     self.selected_scene_items
304 410
                         .extend(self.get_scene_items_for_area(&scene_from, &scene_to));
305 411
                 }
412
+                UserEvent::RightClick(position) => {
413
+                    if let Some(scene_item_usize) =
414
+                        self.get_first_scene_item_for_position(&position)
415
+                    {
416
+                        if self.selected_scene_items.contains(&scene_item_usize) {
417
+                            let scene_item = self
418
+                                .scene_items
419
+                                .get(scene_item_usize)
420
+                                .expect(SCENE_ITEMS_CHANGE_ERR_MSG);
421
+                            self.scene_item_menu =
422
+                                Some((scene_item_usize, scene_item.position.clone()))
423
+                        }
424
+                    }
425
+                }
306 426
             }
307 427
         }
308 428
     }
@@ -315,6 +435,7 @@ impl MainState {
315 435
                 ItemBehavior::Walking(vector) => {
316 436
                     // TODO ici il faut calculer le déplacement réél (en fonction des ticks, etc ...)
317 437
                     scene_item.position.x += 1.0;
438
+                    scene_item.grid_position = grid_position_from_position(&scene_item.position);
318 439
                 }
319 440
                 _ => {}
320 441
             }
@@ -481,10 +602,7 @@ impl event::EventHandler for MainState {
481 602
         }
482 603
 
483 604
         for i in &self.selected_scene_items {
484
-            let selected_scene_item = self
485
-                .scene_items
486
-                .get(*i)
487
-                .expect("scene_items content change !");
605
+            let selected_scene_item = self.scene_items.get(*i).expect(SCENE_ITEMS_CHANGE_ERR_MSG);
488 606
             scene_mesh_builder.rectangle(
489 607
                 DrawMode::Stroke(StrokeOptions::default()),
490 608
                 graphics::Rect::new(
@@ -520,6 +638,30 @@ impl event::EventHandler for MainState {
520 638
             )?;
521 639
         }
522 640
 
641
+        if let Some((_, position)) = self.scene_item_menu {
642
+            self.ui_batch.add(
643
+                UiSpriteInfo::from_type(UiItem::SceneItemMenu)
644
+                    .as_draw_param()
645
+                    .dest(position),
646
+            );
647
+        }
648
+
649
+        if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
650
+            match scene_item_prepare_order {
651
+                SceneItemPrepareOrder::Move(scene_item_usize) => {
652
+                    let scene_item = self
653
+                        .scene_items
654
+                        .get(*scene_item_usize)
655
+                        .expect(SCENE_ITEMS_CHANGE_ERR_MSG);
656
+                    scene_mesh_builder.line(
657
+                        &vec![scene_item.position.clone(), self.current_cursor_position],
658
+                        2.0,
659
+                        graphics::WHITE,
660
+                    )?;
661
+                }
662
+            }
663
+        }
664
+
523 665
         self.map_batch.add(
524 666
             graphics::DrawParam::new()
525 667
                 .src(graphics::Rect::new(0.0, 0.0, 1.0, 1.0))
@@ -545,9 +687,16 @@ impl event::EventHandler for MainState {
545 687
             graphics::DrawParam::new()
546 688
                 .dest(self.position_with_display_offset(&Point2::new(0.0, 0.0))),
547 689
         )?;
690
+        graphics::draw(
691
+            ctx,
692
+            &self.ui_batch,
693
+            graphics::DrawParam::new()
694
+                .dest(self.position_with_display_offset(&Point2::new(0.0, 0.0))),
695
+        )?;
548 696
 
549 697
         self.sprite_sheet_batch.clear();
550 698
         self.map_batch.clear();
699
+        self.ui_batch.clear();
551 700
         graphics::present(ctx)?;
552 701
 
553 702
         println!("FPS: {}", ggez::timer::fps(ctx));
@@ -559,7 +708,9 @@ impl event::EventHandler for MainState {
559 708
             MouseButton::Left => {
560 709
                 self.left_click_down = Some(Point2::new(x, y));
561 710
             }
562
-            MouseButton::Right => {}
711
+            MouseButton::Right => {
712
+                self.right_click_down = Some(Point2::new(x, y));
713
+            }
563 714
             MouseButton::Middle => {}
564 715
             MouseButton::Other(_) => {}
565 716
         }
@@ -585,7 +736,12 @@ impl event::EventHandler for MainState {
585 736
                 }
586 737
                 self.left_click_down = None;
587 738
             }
588
-            MouseButton::Right => {}
739
+            MouseButton::Right => {
740
+                if let Some(right_click_down) = self.right_click_down {
741
+                    self.user_events
742
+                        .push(UserEvent::RightClick(right_click_down));
743
+                }
744
+            }
589 745
             MouseButton::Middle => {}
590 746
             MouseButton::Other(_) => {}
591 747
         }