1 /** 2 * Mouse 3 */ 4 module d2d.sdl2.Mouse; 5 6 import std.algorithm; 7 import std.datetime; 8 import d2d.sdl2; 9 10 ///A list of all of the button codes 11 immutable allButtonCodes = [ 12 SDL_BUTTON_LEFT, SDL_BUTTON_MIDDLE, SDL_BUTTON_RIGHT, SDL_BUTTON_X1, SDL_BUTTON_X2 13 ]; 14 15 /** 16 * The mouse input source which acculmulates mouse information 17 */ 18 class Mouse : InputSource!uint, EventHandler { 19 20 private Pressable!uint[uint] _allButtons; ///All of the buttons on the mouse 21 private iVector _totalWheelDisplacement; ///Total displacement of the mousewheel since mouse construction 22 private iVector _location; ///The location of the mouse accounting for logical size or viewport 23 24 alias allButtons = allPressables; ///Allows allPressables to be called as allButtons 25 26 /** 27 * Returns all of the mouse buttons 28 */ 29 override @property Pressable!uint[uint] allPressables() { 30 return this._allButtons.dup; 31 } 32 33 /** 34 * Gets the mouse location accounting for logical size or viewport 35 * This should be what is most regularly used 36 */ 37 @property iVector location() { 38 return new iVector(this._location.components); 39 } 40 41 /** 42 * Sets the location of the mouse relative to the window 43 */ 44 @property void windowLocation(iVector location) { 45 SDL_WarpMouseInWindow(null, location.x, location.y); 46 } 47 48 /** 49 * Gets the location of the mouse 50 */ 51 @property iVector windowLocation() { 52 iVector location = new iVector(-1, -1); 53 SDL_GetMouseState(&location.x, &location.y); 54 return location; 55 } 56 57 /** 58 * Sets the location of the mouse globally 59 */ 60 @property void screenLocation(iVector location) { 61 SDL_WarpMouseGlobal(location.x, location.y); 62 } 63 64 /** 65 * Gets the location of the mouse globally 66 */ 67 @property iVector screenLocation() { 68 iVector location = new iVector(-1, -1); 69 SDL_GetGlobalMouseState(&location.x, &location.y); 70 return location; 71 } 72 73 /** 74 * Gets by how much the mouse wheel has been displaced 75 * Records changes in wheel from the start of mouse construction 76 */ 77 @property iVector totalWheelDisplacement() { 78 return new iVector(this._totalWheelDisplacement.components); 79 } 80 81 /** 82 * Sets the cursor of the mouse 83 */ 84 @property void cursor(Cursor newCursor) { 85 SDL_SetCursor(newCursor.handle); 86 } 87 88 /** 89 * Gets the cursor of the mouse 90 * Special precautions must be taken when using this method: 91 * Make sure to store the output of the cursor or make sure the cursor doesn't get GCed 92 * Because the actual cursor is being used in C, D will think this returned cursor won't be being used and destroy it 93 * It is probably better to avoid this method entirely 94 */ 95 @property Cursor cursor() { 96 return new Cursor(ensureSafe(SDL_GetCursor())); 97 } 98 99 /** 100 * Makes a mouse and initializes all of the buttons 101 */ 102 this() { 103 allButtonCodes.each!( 104 buttonCode => this._allButtons[buttonCode] = new Pressable!uint(buttonCode)); 105 this._totalWheelDisplacement = new iVector(0, 0); 106 this._location = new iVector(0, 0); 107 } 108 109 /** 110 * Acculmulates all of the mouse events and updates stored pressables accordingly 111 */ 112 override void handleEvent(SDL_Event event) { 113 switch (event.type) { 114 case SDL_MOUSEMOTION: 115 this._location.x = event.button.x; 116 this._location.y = event.button.y; 117 break; 118 case SDL_MOUSEBUTTONDOWN: 119 this._allButtons[event.button.button].lastPressed = Clock.currTime(); 120 break; 121 case SDL_MOUSEBUTTONUP: 122 this._allButtons[event.button.button].lastReleased = Clock.currTime(); 123 break; 124 case SDL_MOUSEWHEEL: 125 this._totalWheelDisplacement.x += event.wheel.x; 126 this._totalWheelDisplacement.y += event.wheel.y; 127 break; 128 default: 129 break; 130 } 131 } 132 133 } 134 135 /** 136 * A cursor is how the mouse at its location looks 137 * While this class should *technically* be defined in d2d.sdl2, its only use is in Mouse 138 * And since this class is small, instead of giving it its own file, I'll keep it here 139 */ 140 class Cursor { 141 142 private SDL_Cursor* cursor; 143 144 /** 145 * Returns the raw SDL data of this object 146 */ 147 @property handle() { 148 return this.cursor; 149 } 150 151 /** 152 * Creates a cursor from a surface and the hotspot 153 * The hotspot is where on the surface is the actual mouse location 154 */ 155 this(Surface appearance, int hotspotX, int hotspotY) { 156 this.cursor = ensureSafe(SDL_CreateColorCursor(appearance.handle, hotspotX, hotspotY)); 157 } 158 159 /** 160 * Creates a cursor from a predefined system cursor 161 */ 162 this(SDL_SystemCursor id) { 163 this.cursor = ensureSafe(SDL_CreateSystemCursor(id)); 164 } 165 166 /** 167 * Creates a cursor from an already SDL_Cursor 168 */ 169 this(SDL_Cursor* alreadyExisting) { 170 this.cursor = alreadyExisting; 171 } 172 173 /** 174 * Ensures that SDL can properly dispose of the cursor 175 */ 176 ~this() { 177 SDL_FreeCursor(this.cursor); 178 } 179 180 } 181 182 /** 183 * Gets the system's default cursor 184 */ 185 Cursor defaultCursor() { 186 return new Cursor(ensureSafe(SDL_GetDefaultCursor())); 187 }