Add implementation for custom hardware cursor
This commit is contained in:
parent
fa8a1fc420
commit
a392dbdbe3
23 changed files with 318 additions and 41 deletions
|
@ -84,7 +84,7 @@ void Input::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
|
ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
|
||||||
ClassDB::bind_method(D_METHOD("action_press", "action"), &Input::action_press);
|
ClassDB::bind_method(D_METHOD("action_press", "action"), &Input::action_press);
|
||||||
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
|
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
|
||||||
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(Vector2()));
|
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
|
||||||
ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event);
|
ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
|
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
|
||||||
|
@ -92,6 +92,24 @@ void Input::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED);
|
BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED);
|
||||||
BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED);
|
BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_ARROW);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_IBEAM);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_CROSS);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_WAIT);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_BUSY);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_DRAG);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_CAN_DROP);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_FORBIDDEN);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_VSIZE);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_HSIZE);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_BDIAGSIZE);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_FDIAGSIZE);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_MOVE);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_VSPLIT);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_HSPLIT);
|
||||||
|
BIND_ENUM_CONSTANT(CURSOR_HELP);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")));
|
ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,28 @@ public:
|
||||||
MOUSE_MODE_CONFINED
|
MOUSE_MODE_CONFINED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef CursorShape
|
||||||
|
enum CursorShape {
|
||||||
|
CURSOR_ARROW,
|
||||||
|
CURSOR_IBEAM,
|
||||||
|
CURSOR_POINTING_HAND,
|
||||||
|
CURSOR_CROSS,
|
||||||
|
CURSOR_WAIT,
|
||||||
|
CURSOR_BUSY,
|
||||||
|
CURSOR_DRAG,
|
||||||
|
CURSOR_CAN_DROP,
|
||||||
|
CURSOR_FORBIDDEN,
|
||||||
|
CURSOR_VSIZE,
|
||||||
|
CURSOR_HSIZE,
|
||||||
|
CURSOR_BDIAGSIZE,
|
||||||
|
CURSOR_FDIAGSIZE,
|
||||||
|
CURSOR_MOVE,
|
||||||
|
CURSOR_VSPLIT,
|
||||||
|
CURSOR_HSPLIT,
|
||||||
|
CURSOR_HELP,
|
||||||
|
CURSOR_MAX
|
||||||
|
};
|
||||||
|
|
||||||
void set_mouse_mode(MouseMode p_mode);
|
void set_mouse_mode(MouseMode p_mode);
|
||||||
MouseMode get_mouse_mode() const;
|
MouseMode get_mouse_mode() const;
|
||||||
|
|
||||||
|
@ -96,7 +118,7 @@ public:
|
||||||
|
|
||||||
virtual bool is_emulating_touchscreen() const = 0;
|
virtual bool is_emulating_touchscreen() const = 0;
|
||||||
|
|
||||||
virtual void set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot = Vector2()) = 0;
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) = 0;
|
||||||
virtual void set_mouse_in_window(bool p_in_window) = 0;
|
virtual void set_mouse_in_window(bool p_in_window) = 0;
|
||||||
|
|
||||||
virtual String get_joy_button_string(int p_button) = 0;
|
virtual String get_joy_button_string(int p_button) = 0;
|
||||||
|
@ -110,5 +132,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(Input::MouseMode);
|
VARIANT_ENUM_CAST(Input::MouseMode);
|
||||||
|
VARIANT_ENUM_CAST(Input::CursorShape);
|
||||||
|
|
||||||
#endif // INPUT_H
|
#endif // INPUT_H
|
||||||
|
|
|
@ -325,6 +325,7 @@ public:
|
||||||
virtual int get_virtual_keyboard_height() const;
|
virtual int get_virtual_keyboard_height() const;
|
||||||
|
|
||||||
virtual void set_cursor_shape(CursorShape p_shape) = 0;
|
virtual void set_cursor_shape(CursorShape p_shape) = 0;
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) = 0;
|
||||||
|
|
||||||
virtual bool get_swap_ok_cancel() { return false; }
|
virtual bool get_swap_ok_cancel() { return false; }
|
||||||
virtual void dump_memory_to_file(const char *p_file);
|
virtual void dump_memory_to_file(const char *p_file);
|
||||||
|
|
|
@ -275,9 +275,12 @@
|
||||||
</return>
|
</return>
|
||||||
<argument index="0" name="image" type="Resource">
|
<argument index="0" name="image" type="Resource">
|
||||||
</argument>
|
</argument>
|
||||||
<argument index="1" name="hotspot" type="Vector2" default="Vector2( 0, 0 )">
|
<argument index="1" name="cursor_shape" type="int" default="CURSOR_ARROW">
|
||||||
|
</argument>
|
||||||
|
<argument index="2" name="hotspot" type="Vector2" default="Vector2( 0, 0 )">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
|
Set a custom mouse cursor image, which is only visible inside the game window. The hotspot can also be specified. See enum [code]CURSOR_*[/code] for the list of shapes.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_mouse_mode">
|
<method name="set_mouse_mode">
|
||||||
|
|
|
@ -497,26 +497,16 @@ bool InputDefault::is_emulating_touchscreen() const {
|
||||||
return emulate_touch;
|
return emulate_touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot) {
|
void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
/* no longer supported, leaving this for reference to anyone who might want to implement hardware cursors
|
if (Engine::get_singleton()->is_editor_hint())
|
||||||
|
return;
|
||||||
|
|
||||||
if (custom_cursor == p_cursor)
|
if (custom_cursor == p_cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
custom_cursor = p_cursor;
|
custom_cursor = p_cursor;
|
||||||
|
|
||||||
if (p_cursor.is_null()) {
|
OS::get_singleton()->set_custom_mouse_cursor(p_cursor, (OS::CursorShape)p_shape, p_hotspot);
|
||||||
set_mouse_mode(MOUSE_MODE_VISIBLE);
|
|
||||||
//removed, please insist us to implement hardare cursors
|
|
||||||
//VisualServer::get_singleton()->cursor_set_visible(false);
|
|
||||||
} else {
|
|
||||||
Ref<AtlasTexture> atex = custom_cursor;
|
|
||||||
Rect2 region = atex.is_valid() ? atex->get_region() : Rect2();
|
|
||||||
set_mouse_mode(MOUSE_MODE_HIDDEN);
|
|
||||||
VisualServer::get_singleton()->cursor_set_visible(true);
|
|
||||||
VisualServer::get_singleton()->cursor_set_texture(custom_cursor->get_rid(), p_hotspot, 0, region);
|
|
||||||
VisualServer::get_singleton()->cursor_set_pos(get_mouse_position());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDefault::set_mouse_in_window(bool p_in_window) {
|
void InputDefault::set_mouse_in_window(bool p_in_window) {
|
||||||
|
|
|
@ -225,7 +225,7 @@ public:
|
||||||
void set_emulate_touch(bool p_emulate);
|
void set_emulate_touch(bool p_emulate);
|
||||||
virtual bool is_emulating_touchscreen() const;
|
virtual bool is_emulating_touchscreen() const;
|
||||||
|
|
||||||
virtual void set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot = Vector2());
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
|
||||||
virtual void set_mouse_in_window(bool p_in_window);
|
virtual void set_mouse_in_window(bool p_in_window);
|
||||||
|
|
||||||
void parse_mapping(String p_mapping);
|
void parse_mapping(String p_mapping);
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
if (cursor.is_valid()) {
|
if (cursor.is_valid()) {
|
||||||
//print_line("loaded ok");
|
//print_line("loaded ok");
|
||||||
Vector2 hotspot = ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image_hotspot");
|
Vector2 hotspot = ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image_hotspot");
|
||||||
Input::get_singleton()->set_custom_mouse_cursor(cursor, hotspot);
|
Input::get_singleton()->set_custom_mouse_cursor(cursor, Input::CURSOR_ARROW, hotspot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
|
@ -248,6 +248,9 @@ void OS_Android::set_cursor_shape(CursorShape p_shape) {
|
||||||
//android really really really has no mouse.. how amazing..
|
//android really really really has no mouse.. how amazing..
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_Android::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
}
|
||||||
|
|
||||||
void OS_Android::main_loop_begin() {
|
void OS_Android::main_loop_begin() {
|
||||||
|
|
||||||
if (main_loop)
|
if (main_loop)
|
||||||
|
|
|
@ -182,6 +182,7 @@ public:
|
||||||
virtual bool can_draw() const;
|
virtual bool can_draw() const;
|
||||||
|
|
||||||
virtual void set_cursor_shape(CursorShape p_shape);
|
virtual void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
void main_loop_begin();
|
void main_loop_begin();
|
||||||
bool main_loop_iterate();
|
bool main_loop_iterate();
|
||||||
|
|
|
@ -200,6 +200,10 @@ void OS_Haiku::set_cursor_shape(CursorShape p_shape) {
|
||||||
//ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED");
|
//ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_Haiku::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
int OS_Haiku::get_screen_count() const {
|
int OS_Haiku::get_screen_count() const {
|
||||||
// TODO: implement get_screen_count()
|
// TODO: implement get_screen_count()
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -87,6 +87,7 @@ public:
|
||||||
virtual Point2 get_mouse_position() const;
|
virtual Point2 get_mouse_position() const;
|
||||||
virtual int get_mouse_button_state() const;
|
virtual int get_mouse_button_state() const;
|
||||||
virtual void set_cursor_shape(CursorShape p_shape);
|
virtual void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
virtual int get_screen_count() const;
|
virtual int get_screen_count() const;
|
||||||
virtual int get_current_screen() const;
|
virtual int get_current_screen() const;
|
||||||
|
|
|
@ -490,6 +490,8 @@ String OSIPhone::get_user_data_dir() const {
|
||||||
return data_dir;
|
return data_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void OSIPhone::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot){};
|
||||||
|
|
||||||
String OSIPhone::get_name() {
|
String OSIPhone::get_name() {
|
||||||
|
|
||||||
return "iOS";
|
return "iOS";
|
||||||
|
|
|
@ -173,6 +173,7 @@ public:
|
||||||
virtual int get_virtual_keyboard_height() const;
|
virtual int get_virtual_keyboard_height() const;
|
||||||
|
|
||||||
virtual void set_cursor_shape(CursorShape p_shape);
|
virtual void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
virtual Size2 get_window_size() const;
|
virtual Size2 get_window_size() const;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "servers/visual/rasterizer.h"
|
#include "servers/visual/rasterizer.h"
|
||||||
#include "servers/visual/visual_server_wrap_mt.h"
|
#include "servers/visual/visual_server_wrap_mt.h"
|
||||||
#include "servers/visual_server.h"
|
#include "servers/visual_server.h"
|
||||||
|
#include <AppKit/NSCursor.h>
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
#undef CursorShape
|
#undef CursorShape
|
||||||
|
@ -86,6 +87,7 @@ public:
|
||||||
id context;
|
id context;
|
||||||
|
|
||||||
CursorShape cursor_shape;
|
CursorShape cursor_shape;
|
||||||
|
NSCursor *cursors[CURSOR_MAX] = { NULL };
|
||||||
MouseMode mouse_mode;
|
MouseMode mouse_mode;
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
|
@ -137,6 +139,7 @@ public:
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||||
|
|
||||||
virtual void set_cursor_shape(CursorShape p_shape);
|
virtual void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
virtual void set_mouse_show(bool p_show);
|
virtual void set_mouse_show(bool p_show);
|
||||||
virtual void set_mouse_grab(bool p_grab);
|
virtual void set_mouse_grab(bool p_grab);
|
||||||
|
|
|
@ -577,8 +577,11 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
|
||||||
return;
|
return;
|
||||||
if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED)
|
if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED)
|
||||||
OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
|
OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
|
||||||
if (OS_OSX::singleton->input)
|
if (OS_OSX::singleton->input) {
|
||||||
OS_OSX::singleton->input->set_mouse_in_window(true);
|
OS_OSX::singleton->input->set_mouse_in_window(true);
|
||||||
|
OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX;
|
||||||
|
OS_OSX::singleton->set_cursor_shape(OS::CURSOR_ARROW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)magnifyWithEvent:(NSEvent *)event {
|
- (void)magnifyWithEvent:(NSEvent *)event {
|
||||||
|
@ -1240,6 +1243,9 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) {
|
||||||
if (cursor_shape == p_shape)
|
if (cursor_shape == p_shape)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (cursors[p_shape] != NULL) {
|
||||||
|
[cursors[p_shape] set];
|
||||||
|
} else {
|
||||||
switch (p_shape) {
|
switch (p_shape) {
|
||||||
case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break;
|
case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break;
|
||||||
case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break;
|
case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break;
|
||||||
|
@ -1260,10 +1266,61 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) {
|
||||||
case CURSOR_HELP: [[NSCursor arrowCursor] set]; break;
|
case CURSOR_HELP: [[NSCursor arrowCursor] set]; break;
|
||||||
default: {};
|
default: {};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cursor_shape = p_shape;
|
cursor_shape = p_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
if (p_cursor.is_valid()) {
|
||||||
|
Ref<Texture> texture = p_cursor;
|
||||||
|
Ref<Image> image = texture->get_data();
|
||||||
|
|
||||||
|
int image_size = 32 * 32;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
|
||||||
|
|
||||||
|
NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc]
|
||||||
|
initWithBitmapDataPlanes:NULL
|
||||||
|
pixelsWide:image->get_width()
|
||||||
|
pixelsHigh:image->get_height()
|
||||||
|
bitsPerSample:8
|
||||||
|
samplesPerPixel:4
|
||||||
|
hasAlpha:YES
|
||||||
|
isPlanar:NO
|
||||||
|
colorSpaceName:NSDeviceRGBColorSpace
|
||||||
|
bytesPerRow:image->get_width() * 4
|
||||||
|
bitsPerPixel:32] autorelease];
|
||||||
|
|
||||||
|
ERR_FAIL_COND(imgrep == nil);
|
||||||
|
uint8_t *pixels = [imgrep bitmapData];
|
||||||
|
|
||||||
|
int len = image->get_width() * image->get_height();
|
||||||
|
PoolVector<uint8_t> data = image->get_data();
|
||||||
|
PoolVector<uint8_t>::Read r = data.read();
|
||||||
|
|
||||||
|
/* Premultiply the alpha channel */
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
uint8_t alpha = r[i * 4 + 3];
|
||||||
|
pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255);
|
||||||
|
pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255);
|
||||||
|
pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255);
|
||||||
|
pixels[i * 4 + 3] = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSImage *nsimage = [[[NSImage alloc] initWithSize:NSMakeSize(image->get_width(), image->get_height())] autorelease];
|
||||||
|
[nsimage addRepresentation:imgrep];
|
||||||
|
|
||||||
|
NSCursor *cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(p_hotspot.x, p_hotspot.y)];
|
||||||
|
|
||||||
|
cursors[p_shape] = cursor;
|
||||||
|
|
||||||
|
if (p_shape == CURSOR_ARROW) {
|
||||||
|
[cursor set];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OS_OSX::set_mouse_show(bool p_show) {
|
void OS_OSX::set_mouse_show(bool p_show) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,9 @@ void OS_Server::move_window_to_foreground() {
|
||||||
void OS_Server::set_cursor_shape(CursorShape p_shape) {
|
void OS_Server::set_cursor_shape(CursorShape p_shape) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_Server::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
}
|
||||||
|
|
||||||
OS::PowerState OS_Server::get_power_state() {
|
OS::PowerState OS_Server::get_power_state() {
|
||||||
return power_manager->get_power_state();
|
return power_manager->get_power_state();
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
virtual String get_name();
|
virtual String get_name();
|
||||||
|
|
||||||
virtual void set_cursor_shape(CursorShape p_shape);
|
virtual void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
virtual void set_mouse_show(bool p_show);
|
virtual void set_mouse_show(bool p_show);
|
||||||
virtual void set_mouse_grab(bool p_grab);
|
virtual void set_mouse_grab(bool p_grab);
|
||||||
|
|
|
@ -651,6 +651,10 @@ void OSUWP::set_cursor_shape(CursorShape p_shape) {
|
||||||
cursor_shape = p_shape;
|
cursor_shape = p_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OSUWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
|
Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
|
||||||
|
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
|
|
@ -218,6 +218,7 @@ public:
|
||||||
virtual String get_clipboard() const;
|
virtual String get_clipboard() const;
|
||||||
|
|
||||||
void set_cursor_shape(CursorShape p_shape);
|
void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
void set_icon(const Ref<Image> &p_icon);
|
void set_icon(const Ref<Image> &p_icon);
|
||||||
|
|
||||||
virtual String get_executable_path() const;
|
virtual String get_executable_path() const;
|
||||||
|
|
|
@ -1844,10 +1844,125 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) {
|
||||||
IDC_HELP
|
IDC_HELP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (cursors[p_shape] != NULL) {
|
||||||
|
SetCursor(cursors[p_shape]);
|
||||||
|
} else {
|
||||||
SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
|
SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
|
||||||
|
}
|
||||||
cursor_shape = p_shape;
|
cursor_shape = p_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
if (p_cursor.is_valid()) {
|
||||||
|
Ref<Texture> texture = p_cursor;
|
||||||
|
Ref<Image> image = texture->get_data();
|
||||||
|
|
||||||
|
UINT image_size = 32 * 32;
|
||||||
|
UINT size = sizeof(UINT) * image_size;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
|
||||||
|
|
||||||
|
// Create the BITMAP with alpha channel
|
||||||
|
COLORREF *buffer = (COLORREF *)malloc(sizeof(COLORREF) * image_size);
|
||||||
|
|
||||||
|
image->lock();
|
||||||
|
for (UINT index = 0; index < image_size; index++) {
|
||||||
|
int column_index = floor(index / 32);
|
||||||
|
int row_index = index % 32;
|
||||||
|
|
||||||
|
Color pcColor = image->get_pixel(row_index, column_index);
|
||||||
|
*(buffer + index) = image->get_pixel(row_index, column_index).to_argb32();
|
||||||
|
}
|
||||||
|
image->unlock();
|
||||||
|
|
||||||
|
// Using 4 channels, so 4 * 8 bits
|
||||||
|
HBITMAP bitmap = CreateBitmap(32, 32, 1, 4 * 8, buffer);
|
||||||
|
COLORREF clrTransparent = -1;
|
||||||
|
|
||||||
|
// Create the AND and XOR masks for the bitmap
|
||||||
|
HBITMAP hAndMask = NULL;
|
||||||
|
HBITMAP hXorMask = NULL;
|
||||||
|
|
||||||
|
GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask);
|
||||||
|
|
||||||
|
if (NULL == hAndMask || NULL == hXorMask) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, create the icon
|
||||||
|
ICONINFO iconinfo = { 0 };
|
||||||
|
iconinfo.fIcon = FALSE;
|
||||||
|
iconinfo.xHotspot = p_hotspot.x;
|
||||||
|
iconinfo.yHotspot = p_hotspot.y;
|
||||||
|
iconinfo.hbmMask = hAndMask;
|
||||||
|
iconinfo.hbmColor = hXorMask;
|
||||||
|
|
||||||
|
cursors[p_shape] = CreateIconIndirect(&iconinfo);
|
||||||
|
|
||||||
|
if (p_shape == CURSOR_ARROW) {
|
||||||
|
SetCursor(cursors[p_shape]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hAndMask != NULL) {
|
||||||
|
DeleteObject(hAndMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hXorMask != NULL) {
|
||||||
|
DeleteObject(hXorMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) {
|
||||||
|
|
||||||
|
// Get the system display DC
|
||||||
|
HDC hDC = GetDC(NULL);
|
||||||
|
|
||||||
|
// Create helper DC
|
||||||
|
HDC hMainDC = CreateCompatibleDC(hDC);
|
||||||
|
HDC hAndMaskDC = CreateCompatibleDC(hDC);
|
||||||
|
HDC hXorMaskDC = CreateCompatibleDC(hDC);
|
||||||
|
|
||||||
|
// Get the dimensions of the source bitmap
|
||||||
|
BITMAP bm;
|
||||||
|
GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
|
||||||
|
|
||||||
|
// Create the mask bitmaps
|
||||||
|
hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
|
||||||
|
hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
|
||||||
|
|
||||||
|
// Release the system display DC
|
||||||
|
ReleaseDC(NULL, hDC);
|
||||||
|
|
||||||
|
// Select the bitmaps to helper DC
|
||||||
|
HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap);
|
||||||
|
HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
|
||||||
|
HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
|
||||||
|
|
||||||
|
// Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap
|
||||||
|
// with 'clrTransparent' will be white pixels of the monochrome bitmap
|
||||||
|
SetBkColor(hMainDC, clrTransparent);
|
||||||
|
BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY);
|
||||||
|
|
||||||
|
// Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap
|
||||||
|
// with 'clrTransparent' will be black and rest the pixels same as corresponding
|
||||||
|
// pixels of the source bitmap
|
||||||
|
SetBkColor(hXorMaskDC, RGB(0, 0, 0));
|
||||||
|
SetTextColor(hXorMaskDC, RGB(255, 255, 255));
|
||||||
|
BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY);
|
||||||
|
BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND);
|
||||||
|
|
||||||
|
// Deselect bitmaps from the helper DC
|
||||||
|
SelectObject(hMainDC, hOldMainBitmap);
|
||||||
|
SelectObject(hAndMaskDC, hOldAndMaskBitmap);
|
||||||
|
SelectObject(hXorMaskDC, hOldXorMaskBitmap);
|
||||||
|
|
||||||
|
// Delete the helper DC
|
||||||
|
DeleteDC(hXorMaskDC);
|
||||||
|
DeleteDC(hAndMaskDC);
|
||||||
|
DeleteDC(hMainDC);
|
||||||
|
}
|
||||||
|
|
||||||
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
|
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
|
||||||
|
|
||||||
if (p_blocking && r_pipe) {
|
if (p_blocking && r_pipe) {
|
||||||
|
|
|
@ -113,6 +113,7 @@ class OS_Windows : public OS {
|
||||||
bool window_has_focus;
|
bool window_has_focus;
|
||||||
uint32_t last_button_state;
|
uint32_t last_button_state;
|
||||||
|
|
||||||
|
HCURSOR cursors[CURSOR_MAX] = { NULL };
|
||||||
CursorShape cursor_shape;
|
CursorShape cursor_shape;
|
||||||
|
|
||||||
InputDefault *input;
|
InputDefault *input;
|
||||||
|
@ -244,6 +245,8 @@ public:
|
||||||
virtual String get_clipboard() const;
|
virtual String get_clipboard() const;
|
||||||
|
|
||||||
void set_cursor_shape(CursorShape p_shape);
|
void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap);
|
||||||
void set_icon(const Ref<Image> &p_icon);
|
void set_icon(const Ref<Image> &p_icon);
|
||||||
|
|
||||||
virtual String get_executable_path() const;
|
virtual String get_executable_path() const;
|
||||||
|
|
|
@ -2201,6 +2201,48 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) {
|
||||||
current_cursor = p_shape;
|
current_cursor = p_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
|
if (p_cursor.is_valid()) {
|
||||||
|
Ref<Texture> texture = p_cursor;
|
||||||
|
Ref<Image> image = texture->get_data();
|
||||||
|
|
||||||
|
ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
|
||||||
|
|
||||||
|
// Create the cursor structure
|
||||||
|
XcursorImage *cursor_image = XcursorImageCreate(texture->get_width(), texture->get_height());
|
||||||
|
XcursorUInt image_size = 32 * 32;
|
||||||
|
XcursorDim size = sizeof(XcursorPixel) * image_size;
|
||||||
|
|
||||||
|
cursor_image->version = 1;
|
||||||
|
cursor_image->size = size;
|
||||||
|
cursor_image->xhot = p_hotspot.x;
|
||||||
|
cursor_image->yhot = p_hotspot.y;
|
||||||
|
|
||||||
|
// allocate memory to contain the whole file
|
||||||
|
cursor_image->pixels = (XcursorPixel *)malloc(size);
|
||||||
|
|
||||||
|
image->lock();
|
||||||
|
|
||||||
|
for (XcursorPixel index = 0; index < image_size; index++) {
|
||||||
|
int column_index = floor(index / 32);
|
||||||
|
int row_index = index % 32;
|
||||||
|
|
||||||
|
*(cursor_image->pixels + index) = image->get_pixel(row_index, column_index).to_argb32();
|
||||||
|
}
|
||||||
|
|
||||||
|
image->unlock();
|
||||||
|
|
||||||
|
ERR_FAIL_COND(cursor_image->pixels == NULL);
|
||||||
|
|
||||||
|
// Save it for a further usage
|
||||||
|
cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image);
|
||||||
|
|
||||||
|
if (p_shape == CURSOR_ARROW) {
|
||||||
|
XDefineCursor(x11_display, x11_window, cursors[p_shape]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OS_X11::release_rendering_thread() {
|
void OS_X11::release_rendering_thread() {
|
||||||
|
|
||||||
context_gl->release_current();
|
context_gl->release_current();
|
||||||
|
|
|
@ -204,6 +204,7 @@ public:
|
||||||
virtual String get_name();
|
virtual String get_name();
|
||||||
|
|
||||||
virtual void set_cursor_shape(CursorShape p_shape);
|
virtual void set_cursor_shape(CursorShape p_shape);
|
||||||
|
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
void set_mouse_mode(MouseMode p_mode);
|
void set_mouse_mode(MouseMode p_mode);
|
||||||
MouseMode get_mouse_mode() const;
|
MouseMode get_mouse_mode() const;
|
||||||
|
|
Loading…
Reference in a new issue