logo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::collections::HashMap;

use crate::engine::d2::{
    input::{EventSource, MouseButton, MouseCursor, MouseEvent},
    subsystem::MouseSystem,
    util::Signal1,
};

use super::{BasicPointer, MouseCodes};

pub struct BasicMouse {
    pub down: Signal1<MouseEvent>,
    pub move_: Signal1<MouseEvent>,
    pub up: Signal1<MouseEvent>,
    pub scroll: Signal1<f32>,

    // static
    shared_event: MouseEvent, // = MouseEvent::new();

    pointer: BasicPointer,
    source: EventSource,

    x: f32,
    y: f32,
    cursor: MouseCursor,
    button_states: HashMap<u32, bool>,
}

impl BasicMouse {
    pub fn new(pointer: BasicPointer) -> Self {
        let shared_event = MouseEvent::new();
        Self {
            pointer,
            source: EventSource::Mouse {
                event: shared_event.clone(),
            },

            down: Signal1::new(None),
            move_: Signal1::new(None),
            up: Signal1::new(None),
            scroll: Signal1::new(None),
            x: 0.0,
            y: 0.0,
            cursor: MouseCursor::Default,
            button_states: HashMap::new(),
            shared_event,
        }
    }

    pub fn set_cursor(&mut self, cursor: MouseCursor) {
        // See subclasses for implementation
        self.cursor = cursor;
    }

    pub fn submit_down(&mut self, view_x: f32, view_y: f32, button_code: u32) {
        if !self.is_code_down(button_code) {
            self.button_states.insert(button_code, true);

            // Init the MouseEvent, and let the Pointer system handle it before emitting our signal
            self.prepare(view_x, view_y, Some(MouseCodes::to_button(button_code)));
            self.pointer
                .submit_down(view_x, view_y, self.source.clone());
            self.down.emit(self.shared_event.clone());
        }
    }

    pub fn submit_move(&mut self, view_x: f32, view_y: f32) {
        self.prepare(view_x, view_y, None);
        self.pointer
            .submit_move(view_x, view_y, self.source.clone());
        self.move_.emit(self.shared_event.clone());
    }

    pub fn submit_up(&mut self, view_x: f32, view_y: f32, button_code: u32) {
        if self.is_code_down(button_code) {
            self.button_states.remove(&button_code);

            self.prepare(view_x, view_y, Some(MouseCodes::to_button(button_code)));
            self.pointer.submit_up(view_x, view_y, self.source.clone());
            self.up.emit(self.shared_event.clone());
        }
    }

    // Returns true if the scroll signal was handled
    pub fn submit_scroll(&mut self, view_x: f32, view_y: f32, velocity: f32) -> bool {
        self.x = view_x;
        self.y = view_y;
        if !self.scroll.inner.has_listeners() {
            return false;
        }
        self.scroll.emit(velocity);

        true
    }

    #[inline]
    fn is_code_down(&self, button_code: u32) -> bool {
        self.button_states.contains_key(&button_code)
    }

    fn prepare(&mut self, view_x: f32, view_y: f32, button: Option<MouseButton>) {
        self.x = view_x;
        self.y = view_y;
        self.shared_event
            .init(self.shared_event.id + 1, view_x, view_y, button);
    }
}

impl MouseSystem for BasicMouse {
    fn down_signal(&self) -> &Signal1<MouseEvent> {
        &self.down
    }

    fn move_signal(&self) -> &Signal1<MouseEvent> {
        &self.move_
    }

    fn scroll_signal(&self) -> &Signal1<f32> {
        &self.scroll
    }

    fn up_signal(&self) -> &Signal1<MouseEvent> {
        &self.up
    }

    fn is_supported(&self) -> bool {
        true
    }

    fn x(&self) -> f32 {
        self.x
    }

    fn y(&self) -> f32 {
        self.y
    }

    fn cursor(&self) -> MouseCursor {
        self.cursor
    }

    fn is_down(&self, button: MouseButton) -> bool {
        self.is_code_down(MouseCodes::to_button_code(button))
    }
}