1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Platform/BsCursor.h"
4#include "Platform/BsPlatform.h"
5#include "Error/BsException.h"
6#include "Resources/BsBuiltinResources.h"
7#include "Debug/BsDebug.h"
8
9namespace bs
10{
11 Cursor::Cursor()
12 {
13 for(UINT32 i = 0; i < (UINT32)CursorType::Count; i++)
14 restoreCursorIcon((CursorType)i);
15 }
16
17 void Cursor::setScreenPosition(const Vector2I& screenPos)
18 {
19 Platform::setCursorPosition(screenPos);
20 }
21
22 Vector2I Cursor::getScreenPosition()
23 {
24 return Platform::getCursorPosition();
25 }
26
27 void Cursor::hide()
28 {
29 Platform::hideCursor();
30 }
31
32 void Cursor::show()
33 {
34 Platform::showCursor();
35 }
36
37 void Cursor::clipToWindow(const RenderWindow& window)
38 {
39 Platform::clipCursorToWindow(window);
40 }
41
42 void Cursor::clipToRect(const Rect2I& screenRect)
43 {
44 Platform::clipCursorToRect(screenRect);
45 }
46
47 void Cursor::clipDisable()
48 {
49 Platform::clipCursorDisable();
50 }
51
52 void Cursor::setCursor(CursorType type)
53 {
54 UINT32 id = (UINT32)type;
55 if((UINT32)mActiveCursorId != id)
56 {
57 mActiveCursorId = id;
58 updateCursorImage();
59 }
60 }
61
62 void Cursor::setCursor(const String& name)
63 {
64 auto iterFind = mCustomIconNameToId.find(name);
65 if(iterFind == mCustomIconNameToId.end())
66 {
67 LOGWRN("Cannot find cursor icon with name: " + name);
68 return;
69 }
70
71 UINT32 id = iterFind->second;
72 if((UINT32)mActiveCursorId != id)
73 {
74 mActiveCursorId = id;
75 updateCursorImage();
76 }
77 }
78
79 void Cursor::setCursorIcon(const String& name, const PixelData& pixelData, const Vector2I& hotSpot)
80 {
81 auto iterFind = mCustomIconNameToId.find(name);
82 if(iterFind != mCustomIconNameToId.end())
83 {
84 UINT32 id = iterFind->second;
85 mCustomIcons[id] = CustomIcon(pixelData, hotSpot);
86
87 if((UINT32)mActiveCursorId == id)
88 updateCursorImage(); // Refresh active
89 }
90 else
91 {
92 UINT32 id = mNextUniqueId++;
93 mCustomIconNameToId[name] = id;
94 mCustomIcons[id] = CustomIcon(pixelData, hotSpot);
95 }
96 }
97
98 void Cursor::setCursorIcon(CursorType type, const PixelData& pixelData, const Vector2I& hotSpot)
99 {
100 UINT32 id = (UINT32)type;
101
102 mCustomIcons[id].pixelData = pixelData;
103 mCustomIcons[id].hotSpot = hotSpot;
104
105 if((UINT32)mActiveCursorId == id)
106 updateCursorImage(); // Refresh active
107 }
108
109 void Cursor::clearCursorIcon(const String& name)
110 {
111 auto iterFind = mCustomIconNameToId.find(name);
112 if(iterFind == mCustomIconNameToId.end())
113 return;
114
115 mCustomIcons.erase(iterFind->second);
116 mCustomIconNameToId.erase(iterFind);
117 }
118
119 void Cursor::clearCursorIcon(CursorType type)
120 {
121 restoreCursorIcon(type);
122
123 if(mActiveCursorId == (INT32)type)
124 updateCursorImage(); // Refresh active
125 }
126
127 void Cursor::restoreCursorIcon(CursorType type)
128 {
129 UINT32 id = (UINT32)type;
130 mCustomIcons[id] = CustomIcon();
131
132 switch (type)
133 {
134 case CursorType::Arrow:
135 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorArrow(mCustomIcons[id].hotSpot);
136 return;
137 case CursorType::Wait:
138 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorWait(mCustomIcons[id].hotSpot);
139 return;
140 case CursorType::IBeam:
141 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorIBeam(mCustomIcons[id].hotSpot);
142 return;
143 case CursorType::ArrowDrag:
144 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorArrowDrag(mCustomIcons[id].hotSpot);
145 return;
146 case CursorType::SizeNESW:
147 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorSizeNESW(mCustomIcons[id].hotSpot);
148 return;
149 case CursorType::SizeNS:
150 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorSizeNS(mCustomIcons[id].hotSpot);
151 return;
152 case CursorType::SizeNWSE:
153 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorSizeNWSE(mCustomIcons[id].hotSpot);
154 return;
155 case CursorType::SizeWE:
156 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorSizeWE(mCustomIcons[id].hotSpot);
157 return;
158 case CursorType::Deny:
159 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorDeny(mCustomIcons[id].hotSpot);
160 return;
161 case CursorType::ArrowLeftRight:
162 mCustomIcons[id].pixelData = BuiltinResources::instance().getCursorMoveLeftRight(mCustomIcons[id].hotSpot);
163 return;
164 default:
165 break;
166 }
167
168 BS_EXCEPT(InvalidParametersException, "Invalid cursor type: " + toString((UINT32)type));
169 }
170
171 void Cursor::updateCursorImage()
172 {
173 if (mActiveCursorId < 0)
174 return;
175
176 CustomIcon& customIcon = mCustomIcons[mActiveCursorId];
177 Platform::setCursor(customIcon.pixelData, customIcon.hotSpot);
178 }
179
180 Cursor& gCursor()
181 {
182 return static_cast<Cursor&>(Cursor::instance());
183 }
184}