diff options
-rw-r--r-- | core/image.cpp | 130 | ||||
-rw-r--r-- | core/image.h | 3 | ||||
-rw-r--r-- | doc/base/classes.xml | 31 | ||||
-rw-r--r-- | editor/editor_node.cpp | 12 | ||||
-rw-r--r-- | editor/editor_node.h | 5 | ||||
-rw-r--r-- | editor/editor_plugin.cpp | 8 | ||||
-rw-r--r-- | editor/editor_plugin.h | 5 | ||||
-rw-r--r-- | editor/plugins/spatial_editor_plugin.cpp | 13 | ||||
-rw-r--r-- | editor/property_editor.cpp | 3 | ||||
-rw-r--r-- | platform/javascript/os_javascript.cpp | 191 | ||||
-rw-r--r-- | scene/gui/color_picker.cpp | 38 | ||||
-rw-r--r-- | scene/gui/color_picker.h | 1 |
12 files changed, 321 insertions, 119 deletions
diff --git a/core/image.cpp b/core/image.cpp index ad52447935..ec21260b19 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1646,6 +1646,133 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po } } +void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { + + ERR_FAIL_COND(p_src.is_null()); + int dsize = data.size(); + int srcdsize = p_src->data.size(); + ERR_FAIL_COND(dsize == 0); + ERR_FAIL_COND(srcdsize == 0); + ERR_FAIL_COND(format != p_src->format); + + Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); + if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) + return; + + Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size)); + + lock(); + Ref<Image> img = p_src; + img->lock(); + + for (int i = 0; i < dest_rect.size.y; i++) { + + for (int j = 0; j < dest_rect.size.x; j++) { + + int src_x = clipped_src_rect.position.x + j; + int src_y = clipped_src_rect.position.y + i; + + int dst_x = dest_rect.position.x + j; + int dst_y = dest_rect.position.y + i; + + Color sc = img->get_pixel(src_x, src_y); + Color dc = get_pixel(dst_x, dst_y); + dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r); + dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); + dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); + dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); + put_pixel(dst_x, dst_y, dc); + } + } + + img->unlock(); + unlock(); +} + +void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { + + ERR_FAIL_COND(p_src.is_null()); + ERR_FAIL_COND(p_mask.is_null()); + int dsize = data.size(); + int srcdsize = p_src->data.size(); + int maskdsize = p_mask->data.size(); + ERR_FAIL_COND(dsize == 0); + ERR_FAIL_COND(srcdsize == 0); + ERR_FAIL_COND(maskdsize == 0); + ERR_FAIL_COND(p_src->width != p_mask->width); + ERR_FAIL_COND(p_src->height != p_mask->height); + ERR_FAIL_COND(format != p_src->format); + + Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); + if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) + return; + + Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size)); + + lock(); + Ref<Image> img = p_src; + Ref<Image> msk = p_mask; + img->lock(); + msk->lock(); + + for (int i = 0; i < dest_rect.size.y; i++) { + + for (int j = 0; j < dest_rect.size.x; j++) { + + int src_x = clipped_src_rect.position.x + j; + int src_y = clipped_src_rect.position.y + i; + + // If the mask's pixel is transparent then we skip it + //Color c = msk->get_pixel(src_x, src_y); + //if (c.a == 0) continue; + if (msk->get_pixel(src_x, src_y).a != 0) { + + int dst_x = dest_rect.position.x + j; + int dst_y = dest_rect.position.y + i; + + Color sc = img->get_pixel(src_x, src_y); + Color dc = get_pixel(dst_x, dst_y); + dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r); + dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); + dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); + dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); + put_pixel(dst_x, dst_y, dc); + } + } + } + + msk->unlock(); + img->unlock(); + unlock(); +} + +void Image::fill(const Color &c) { + + lock(); + + PoolVector<uint8_t>::Write wp = data.write(); + uint8_t *dst_data_ptr = wp.ptr(); + + int pixel_size = get_format_pixel_size(format); + + // put first pixel with the format-aware API + put_pixel(0, 0, c); + + for (int y = 0; y < height; y++) { + + for (int x = 0; x < width; x++) { + + uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size]; + + for (int k = 0; k < pixel_size; k++) { + dst[k] = dst_data_ptr[k]; + } + } + } + + unlock(); +} + Ref<Image> (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL; Ref<Image> (*Image::_jpg_mem_loader_func)(const uint8_t *, int) = NULL; @@ -2072,6 +2199,9 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("normalmap_to_xy"), &Image::normalmap_to_xy); ClassDB::bind_method(D_METHOD("blit_rect", "src:Image", "src_rect", "dst"), &Image::blit_rect); + ClassDB::bind_method(D_METHOD("blend_rect", "src:Image", "src_rect", "dst"), &Image::blend_rect); + ClassDB::bind_method(D_METHOD("blend_rect_mask", "src:Image", "mask:Image", "src_rect", "dst"), &Image::blend_rect_mask); + ClassDB::bind_method(D_METHOD("fill", "color"), &Image::fill); ClassDB::bind_method(D_METHOD("get_used_rect"), &Image::get_used_rect); ClassDB::bind_method(D_METHOD("get_rect:Image", "rect"), &Image::get_rect); diff --git a/core/image.h b/core/image.h index 838b37352d..3323afdc4b 100644 --- a/core/image.h +++ b/core/image.h @@ -283,6 +283,9 @@ public: void normalmap_to_xy(); void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); + void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); + void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); + void fill(const Color &c); Rect2 get_used_rect() const; Ref<Image> get_rect(const Rect2 &p_area) const; diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 09ddb769b6..2139d1a467 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -18971,6 +18971,30 @@ Native image datatype. Contains image data, which can be converted to a texture, and several functions to interact with it. </description> <methods> + <method name="blend_rect"> + <argument index="0" name="src" type="Image"> + </argument> + <argument index="1" name="src_rect" type="Rect2"> + </argument> + <argument index="2" name="dst" type="Vector2"> + </argument> + <description> + Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] on coordinates "dest". + </description> + </method> + <method name="blend_rect_mask"> + <argument index="0" name="src" type="Image"> + </argument> + <argument index="1" name="mask" type="Image"> + </argument> + <argument index="2" name="src_rect" type="Rect2"> + </argument> + <argument index="3" name="dst" type="Vector2"> + </argument> + <description> + Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] using a "mask" [Image] on coordinates "dest". Alpha channels are required for both "src" and "mask", dest pixels and src pixels will blend if the corresponding mask pixel's alpha value is not 0. "src" [Image] and "mask" [Image] *must* have the same size (width and height) but they can have different formats + </description> + </method> <method name="blit_rect"> <argument index="0" name="src" type="Image"> </argument> @@ -19061,6 +19085,13 @@ <description> </description> </method> + <method name="fill"> + <argument index="0" name="color" type="Color"> + </argument> + <description> + Fills an [Image] with a specified [Color] + </description> + </method> <method name="fix_alpha_edges"> <description> </description> diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 3a0825be9b..56b62cdf6e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6142,6 +6142,7 @@ EditorNode::EditorNode() { editor_plugin_screen = NULL; editor_plugins_over = memnew(EditorPluginList); + editor_plugins_force_input_forwarding = memnew(EditorPluginList); //force_top_viewport(true); _edit_current(); @@ -6290,6 +6291,7 @@ EditorNode::~EditorNode() { memdelete(EditorHelp::get_doc_data()); memdelete(editor_selection); memdelete(editor_plugins_over); + memdelete(editor_plugins_force_input_forwarding); memdelete(file_server); EditorSettings::destroy(); } @@ -6325,10 +6327,14 @@ bool EditorPluginList::forward_gui_input(const Transform2D &p_canvas_xform, cons return discard; } -bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) { +bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled) { bool discard = false; for (int i = 0; i < plugins_list.size(); i++) { + if ((!serve_when_force_input_enabled) && plugins_list[i]->is_input_event_forwarding_always_enabled()) { + continue; + } + if (plugins_list[i]->forward_spatial_gui_input(p_camera, p_event)) { discard = true; } @@ -6344,6 +6350,10 @@ void EditorPluginList::forward_draw_over_canvas(const Transform2D &p_canvas_xfor } } +void EditorPluginList::add_plugin(EditorPlugin *p_plugin) { + plugins_list.push_back(p_plugin); +} + bool EditorPluginList::empty() { return plugins_list.empty(); } diff --git a/editor/editor_node.h b/editor/editor_node.h index 0f4561572a..3870edb7c6 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -398,6 +398,7 @@ private: Vector<EditorPlugin *> editor_plugins; EditorPlugin *editor_plugin_screen; EditorPluginList *editor_plugins_over; + EditorPluginList *editor_plugins_force_input_forwarding; EditorHistory editor_history; EditorData editor_data; @@ -647,6 +648,7 @@ public: EditorPlugin *get_editor_plugin_screen() { return editor_plugin_screen; } EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; } + EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; } PropertyEditor *get_property_editor() { return property_editor; } VBoxContainer *get_property_editor_vb() { return prop_editor_vb; } @@ -823,8 +825,9 @@ public: void make_visible(bool p_visible); void edit(Object *p_object); bool forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event); - bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event); + bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled); void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas); + void add_plugin(EditorPlugin *p_plugin); void clear(); bool empty(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 6fcea98e32..75ab1e8a44 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -147,6 +147,12 @@ void EditorPlugin::remove_tool_menu_item(const String &p_name) { //EditorNode::get_singleton()->remove_tool_menu_item(p_name); } +void EditorPlugin::set_input_event_forwarding_always_enabled() { + input_event_forwarding_always_enabled = true; + EditorPluginList *always_input_forwarding_list = EditorNode::get_singleton()->get_editor_plugins_force_input_forwarding(); + always_input_forwarding_list->add_plugin(this); +} + Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial *p_spatial) { //?? if (get_script_instance() && get_script_instance()->has_method("create_spatial_gizmo")) { @@ -372,6 +378,7 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("edit_resource"), &EditorPlugin::edit_resource); ClassDB::bind_method(D_METHOD("add_import_plugin"), &EditorPlugin::add_import_plugin); ClassDB::bind_method(D_METHOD("remove_import_plugin"), &EditorPlugin::remove_import_plugin); + ClassDB::bind_method(D_METHOD("set_input_event_forwarding_always_enabled"), &EditorPlugin::set_input_event_forwarding_always_enabled); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::TRANSFORM2D, "canvas_xform"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_draw_over_canvas", PropertyInfo(Variant::TRANSFORM2D, "canvas_xform"), PropertyInfo(Variant::OBJECT, "canvas:Control"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); @@ -414,6 +421,7 @@ void EditorPlugin::_bind_methods() { EditorPlugin::EditorPlugin() { undo_redo = NULL; + input_event_forwarding_always_enabled = false; } EditorPlugin::~EditorPlugin() { diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index c607846ec9..57a22a8b2f 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -61,6 +61,8 @@ class EditorPlugin : public Node { UndoRedo *_get_undo_redo() { return undo_redo; } + bool input_event_forwarding_always_enabled; + protected: static void _bind_methods(); UndoRedo &get_undo_redo() { return *undo_redo; } @@ -106,6 +108,9 @@ public: void add_tool_submenu_item(const String &p_name, Object *p_submenu); void remove_tool_menu_item(const String &p_name); + void set_input_event_forwarding_always_enabled(); + bool is_input_event_forwarding_always_enabled() { return input_event_forwarding_always_enabled; } + virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial); virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event); virtual void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 5da242ffaa..2d27e218ec 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -696,12 +696,19 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { return; //do NONE { - + EditorNode *en = editor; + EditorPluginList *force_input_forwarding_list = en->get_editor_plugins_force_input_forwarding(); + if (!force_input_forwarding_list->empty()) { + bool discard = force_input_forwarding_list->forward_spatial_gui_input(camera, p_event, true); + if (discard) + return; + } + } + { EditorNode *en = editor; EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - if (!over_plugin_list->empty()) { - bool discard = over_plugin_list->forward_spatial_gui_input(camera, p_event); + bool discard = over_plugin_list->forward_spatial_gui_input(camera, p_event, false); if (discard) return; } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 3d3fecc8f9..da26c84e45 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -65,6 +65,9 @@ void CustomPropertyEditor::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( 10,10,60, get_size().height-20 ), v ); }*/ } + if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) { + hide(); + } } void CustomPropertyEditor::_menu_option(int p_which) { diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index ae00fb429e..9df26f1471 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -46,14 +46,12 @@ #define DOM_BUTTON_RIGHT 2 template <typename T> -static InputModifierState dom2godot_mod(T emscripten_event_ptr) { +static void dom2godot_mod(T emscripten_event_ptr, Ref<InputEventWithModifiers> godot_event) { - InputModifierState mod; - mod.shift = emscripten_event_ptr->shiftKey; - mod.alt = emscripten_event_ptr->altKey; - mod.control = emscripten_event_ptr->ctrlKey; - mod.meta = emscripten_event_ptr->metaKey; - return mod; + godot_event->set_shift(emscripten_event_ptr->shiftKey); + godot_event->set_alt(emscripten_event_ptr->altKey); + godot_event->set_control(emscripten_event_ptr->ctrlKey); + godot_event->set_metakey(emscripten_event_ptr->metaKey); } int OS_JavaScript::get_video_driver_count() const { @@ -151,26 +149,26 @@ static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_MOUSEDOWN && event_type != EMSCRIPTEN_EVENT_MOUSEUP, false); - Ref<InputEvent> ev; - ev.type = Ref<InputEvent>::MOUSE_BUTTON; - ev->is_pressed() = event_type == EMSCRIPTEN_EVENT_MOUSEDOWN; - ev.mouse_button.global_x = ev->get_pos().x = mouse_event->canvasX; - ev.mouse_button.global_y = ev->get_pos().y = mouse_event->canvasY; - ev.mouse_button.mod = dom2godot_mod(mouse_event); + Ref<InputEventMouseButton> ev; + ev.instance(); + ev->set_pressed(event_type == EMSCRIPTEN_EVENT_MOUSEDOWN); + ev->set_position(Point2(mouse_event->canvasX, mouse_event->canvasY)); + ev->set_global_position(ev->get_position()); + dom2godot_mod(mouse_event, ev); switch (mouse_event->button) { - case DOM_BUTTON_LEFT: ev->get_button_index() = BUTTON_LEFT; break; - case DOM_BUTTON_MIDDLE: ev->get_button_index() = BUTTON_MIDDLE; break; - case DOM_BUTTON_RIGHT: ev->get_button_index() = BUTTON_RIGHT; break; + case DOM_BUTTON_LEFT: ev->set_button_index(BUTTON_LEFT); break; + case DOM_BUTTON_MIDDLE: ev->set_button_index(BUTTON_MIDDLE); break; + case DOM_BUTTON_RIGHT: ev->set_button_index(BUTTON_RIGHT); break; default: return false; } - ev->get_button_mask() = _input->get_mouse_button_mask(); + int mask = _input->get_mouse_button_mask(); if (ev->is_pressed()) - ev->get_button_mask() |= 1 << ev->get_button_index(); + mask |= 1 << ev->get_button_index(); else - ev->get_button_mask() &= ~(1 << ev->get_button_index()); - ev->get_button_mask() >>= 1; + mask &= ~(1 << ev->get_button_index()); + ev->set_button_mask(mask >> 1); _input->parse_input_event(ev); return true; @@ -180,20 +178,17 @@ static EM_BOOL _mousemove_callback(int event_type, const EmscriptenMouseEvent *m ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_MOUSEMOVE, false); - Ref<InputEvent> ev; - ev.type = Ref<InputEvent>::MOUSE_MOTION; - ev.mouse_motion.mod = dom2godot_mod(mouse_event); - ev->get_button_mask() = _input->get_mouse_button_mask() >> 1; + Ref<InputEventMouseMotion> ev; + ev.instance(); + dom2godot_mod(mouse_event, ev); + ev->set_button_mask(_input->get_mouse_button_mask() >> 1); - ev.mouse_motion.global_x = ev.mouse_motion.x = mouse_event->canvasX; - ev.mouse_motion.global_y = ev.mouse_motion.y = mouse_event->canvasY; + ev->set_position(Point2(mouse_event->canvasX, mouse_event->canvasY)); + ev->set_global_position(ev->get_position()); - ev->get_relative().x = _input->get_mouse_position().x - ev.mouse_motion.x; - ev->get_relative().y = _input->get_mouse_position().y - ev.mouse_motion.y; - - _input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y)); - ev.mouse_motion.speed_x = _input->get_last_mouse_speed().x; - ev.mouse_motion.speed_y = _input->get_last_mouse_speed().y; + ev->set_relative(_input->get_mouse_position() - ev->get_position()); + _input->set_mouse_position(ev->get_position()); + ev->set_speed(_input->get_last_mouse_speed()); _input->parse_input_event(ev); return true; @@ -203,31 +198,35 @@ static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_WHEEL, false); - Ref<InputEvent> ev; - ev.type = Ref<InputEvent>::MOUSE_BUTTON; - ev->get_button_mask() = _input->get_mouse_button_mask() >> 1; - ev.mouse_button.global_x = ev->get_pos().x = _input->get_mouse_position().x; - ev.mouse_button.global_y = ev->get_pos().y = _input->get_mouse_position().y; - ev.mouse_button->get_shift() = _input->is_key_pressed(KEY_SHIFT); - ev.mouse_button->get_alt() = _input->is_key_pressed(KEY_ALT); - ev.mouse_button->get_control() = _input->is_key_pressed(KEY_CONTROL); - ev.mouse_button->get_metakey() = _input->is_key_pressed(KEY_META); + Ref<InputEventMouseButton> ev; + ev.instance(); + ev->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev->set_position(_input->get_mouse_position()); + ev->set_global_position(ev->get_position()); + + ev->set_shift(_input->is_key_pressed(KEY_SHIFT)); + ev->set_alt(_input->is_key_pressed(KEY_ALT)); + ev->set_control(_input->is_key_pressed(KEY_CONTROL)); + ev->set_metakey(_input->is_key_pressed(KEY_META)); if (wheel_event->deltaY < 0) - ev->get_button_index() = BUTTON_WHEEL_UP; + ev->set_button_index(BUTTON_WHEEL_UP); else if (wheel_event->deltaY > 0) - ev->get_button_index() = BUTTON_WHEEL_DOWN; + ev->set_button_index(BUTTON_WHEEL_DOWN); else if (wheel_event->deltaX > 0) - ev->get_button_index() = BUTTON_WHEEL_LEFT; + ev->set_button_index(BUTTON_WHEEL_LEFT); else if (wheel_event->deltaX < 0) - ev->get_button_index() = BUTTON_WHEEL_RIGHT; + ev->set_button_index(BUTTON_WHEEL_RIGHT); else return false; - ev->is_pressed() = true; + // Different browsers give wildly different delta values, and we can't + // interpret deltaMode, so use default value for wheel events' factor + + ev->set_pressed(true); _input->parse_input_event(ev); - ev->is_pressed() = false; + ev->set_pressed(false); _input->parse_input_event(ev); return true; @@ -243,8 +242,8 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent * event_type != EMSCRIPTEN_EVENT_TOUCHCANCEL, false); - Ref<InputEvent> ev; - ev.type = Ref<InputEvent>::SCREEN_TOUCH; + Ref<InputEventScreenTouch> ev; + ev.instance(); int lowest_id_index = -1; for (int i = 0; i < touch_event->numTouches; ++i) { @@ -253,25 +252,29 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent * lowest_id_index = i; if (!touch.isChanged) continue; - ev.screen_touch.index = touch.identifier; - _prev_touches[i].x = ev.screen_touch.x = touch.canvasX; - _prev_touches[i].y = ev.screen_touch.y = touch.canvasY; - ev.screen_touch->is_pressed() = event_type == EMSCRIPTEN_EVENT_TOUCHSTART; + ev->set_index(touch.identifier); + ev->set_position(Point2(touch.canvasX, touch.canvasY)); + _prev_touches[i] = ev->get_position(); + ev->set_pressed(event_type == EMSCRIPTEN_EVENT_TOUCHSTART); _input->parse_input_event(ev); } if (touch_event->touches[lowest_id_index].isChanged) { - ev.type = Ref<InputEvent>::MOUSE_BUTTON; - ev.mouse_button.mod = dom2godot_mod(touch_event); - ev->get_button_mask() = _input->get_mouse_button_mask() >> 1; - ev.mouse_button.global_x = ev->get_pos().x = touch_event->touches[lowest_id_index].canvasX; - ev.mouse_button.global_y = ev->get_pos().y = touch_event->touches[lowest_id_index].canvasY; - ev->get_button_index() = BUTTON_LEFT; - ev->is_pressed() = event_type == EMSCRIPTEN_EVENT_TOUCHSTART; + Ref<InputEventMouseButton> ev_mouse; + ev_mouse.instance(); + ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1); + dom2godot_mod(touch_event, ev_mouse); - _input->parse_input_event(ev); + const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index]; + ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY)); + ev_mouse->set_global_position(ev_mouse->get_position()); + + ev_mouse->set_button_index(BUTTON_LEFT); + ev_mouse->set_pressed(event_type == EMSCRIPTEN_EVENT_TOUCHSTART); + + _input->parse_input_event(ev_mouse); } return true; } @@ -280,8 +283,8 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_TOUCHMOVE, false); - Ref<InputEvent> ev; - ev.type = Ref<InputEvent>::SCREEN_DRAG; + Ref<InputEventScreenDrag> ev; + ev.instance(); int lowest_id_index = -1; for (int i = 0; i < touch_event->numTouches; ++i) { @@ -290,44 +293,42 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t lowest_id_index = i; if (!touch.isChanged) continue; - ev.screen_drag.index = touch.identifier; - ev.screen_drag.x = touch.canvasX; - ev.screen_drag.y = touch.canvasY; + ev->set_index(touch.identifier); + ev->set_position(Point2(touch.canvasX, touch.canvasY)); Point2 &prev = _prev_touches[i]; - ev.screen_drag.relative_x = touch.canvasX - prev.x; - ev.screen_drag.relative_y = touch.canvasY - prev.y; - prev.x = ev.screen_drag.x; - prev.y = ev.screen_drag.y; + ev->set_relative(ev->get_position() - prev); + prev = ev->get_position(); _input->parse_input_event(ev); } if (touch_event->touches[lowest_id_index].isChanged) { - ev.type = Ref<InputEvent>::MOUSE_MOTION; - ev.mouse_motion.mod = dom2godot_mod(touch_event); - ev->get_button_mask() = _input->get_mouse_button_mask() >> 1; - ev.mouse_motion.global_x = ev.mouse_motion.x = touch_event->touches[lowest_id_index].canvasX; - ev.mouse_motion.global_y = ev.mouse_motion.y = touch_event->touches[lowest_id_index].canvasY; - ev->get_relative().x = _input->get_mouse_position().x - ev.mouse_motion.x; - ev->get_relative().y = _input->get_mouse_position().y - ev.mouse_motion.y; + Ref<InputEventMouseMotion> ev_mouse; + ev_mouse.instance(); + dom2godot_mod(touch_event, ev_mouse); + ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1); - _input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y)); - ev.mouse_motion.speed_x = _input->get_last_mouse_speed().x; - ev.mouse_motion.speed_y = _input->get_last_mouse_speed().y; + const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index]; + ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY)); + ev_mouse->set_global_position(ev_mouse->get_position()); - _input->parse_input_event(ev); + ev_mouse->set_relative(_input->get_mouse_position() - ev_mouse->get_position()); + _input->set_mouse_position(ev_mouse->get_position()); + ev_mouse->set_speed(_input->get_last_mouse_speed()); + + _input->parse_input_event(ev_mouse); } return true; } -static Ref<InputEvent> _setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) { +static Ref<InputEventKey> _setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) { - Ref<InputEvent> ev; - ev.type = Ref<InputEvent>::KEY; - ev->is_echo() = emscripten_event->repeat; - ev.key.mod = dom2godot_mod(emscripten_event); - ev->get_scancode() = dom2godot_scancode(emscripten_event->keyCode); + Ref<InputEventKey> ev; + ev.instance(); + ev->set_echo(emscripten_event->repeat); + dom2godot_mod(emscripten_event, ev); + ev->set_scancode(dom2godot_scancode(emscripten_event->keyCode)); String unicode = String::utf8(emscripten_event->key); // check if empty or multi-character (e.g. `CapsLock`) @@ -336,21 +337,21 @@ static Ref<InputEvent> _setup_key_event(const EmscriptenKeyboardEvent *emscripte unicode = String::utf8(emscripten_event->charValue); } if (unicode.length() == 1) { - ev.key.unicode = unicode[0]; + ev->set_unicode(unicode[0]); } return ev; } -static Ref<InputEvent> deferred_key_event; +static Ref<InputEventKey> deferred_key_event; static EM_BOOL _keydown_callback(int event_type, const EmscriptenKeyboardEvent *key_event, void *user_data) { ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_KEYDOWN, false); - Ref<InputEvent> ev = _setup_key_event(key_event); - ev->is_pressed() = true; - if (ev.key.unicode == 0 && keycode_has_unicode(ev->get_scancode())) { + Ref<InputEventKey> ev = _setup_key_event(key_event); + ev->set_pressed(true); + if (ev->get_unicode() == 0 && keycode_has_unicode(ev->get_scancode())) { // defer to keypress event for legacy unicode retrieval deferred_key_event = ev; return false; // do not suppress keypress event @@ -363,7 +364,7 @@ static EM_BOOL _keypress_callback(int event_type, const EmscriptenKeyboardEvent ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_KEYPRESS, false); - deferred_key_event.key.unicode = key_event->charCode; + deferred_key_event->set_unicode(key_event->charCode); _input->parse_input_event(deferred_key_event); return true; } @@ -372,8 +373,8 @@ static EM_BOOL _keyup_callback(int event_type, const EmscriptenKeyboardEvent *ke ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_KEYUP, false); - Ref<InputEvent> ev = _setup_key_event(key_event); - ev->is_pressed() = false; + Ref<InputEventKey> ev = _setup_key_event(key_event); + ev->set_pressed(false); _input->parse_input_event(ev); return ev->get_scancode() != KEY_UNKNOWN && ev->get_scancode() != 0; } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index bc1b16bea8..ee6af21dbd 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -48,7 +48,15 @@ void ColorPicker::_notification(int p_what) { btn_pick->set_icon(get_icon("screen_picker", "ColorPicker")); _update_color(); - } + } break; + + case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { + if (screen != NULL) { + if (screen->is_visible()) { + screen->hide(); + } + } + } break; } } @@ -84,9 +92,6 @@ void ColorPicker::set_pick_color(const Color &p_color) { if (!is_inside_tree()) return; - return; //it crashes, so returning - uv_edit->get_child(0)->cast_to<Control>()->update(); - w_edit->get_child(0)->cast_to<Control>()->update(); _update_color(); } @@ -427,19 +432,12 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &ev) { Viewport *r = get_tree()->get_root(); if (!r->get_visible_rect().has_point(Point2(mev->get_global_position().x, mev->get_global_position().y))) return; - Ref<Image> img; //= r->get_screen_capture(); - if (!img.is_null()) { - last_capture = img; - //r->queue_screen_capture(); - } - if (last_capture.is_valid() && !last_capture->empty()) { - int pw = last_capture->get_format() == Image::FORMAT_RGBA8 ? 4 : 3; - int ofs = (mev->get_global_position().y * last_capture->get_width() + mev->get_global_position().x) * pw; - - PoolVector<uint8_t>::Read r = last_capture->get_data().read(); - - Color c(r[ofs + 0] / 255.0, r[ofs + 1] / 255.0, r[ofs + 2] / 255.0); - + Ref<Image> img = r->get_texture()->get_data(); + if (img.is_valid() && !img->empty()) { + img->lock(); + Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position(); + Color c = img->get_pixel(ofs.x, r->get_visible_rect().size.height - ofs.y); + img->unlock(); set_pick_color(c); } } @@ -456,11 +454,11 @@ void ColorPicker::_screen_pick_pressed() { r->add_child(screen); screen->set_as_toplevel(true); screen->set_area_as_parent_rect(); + screen->set_default_cursor_shape(CURSOR_POINTING_HAND); screen->connect("gui_input", this, "_screen_input"); } screen->raise(); screen->show_modal(); - // r->queue_screen_capture(); } void ColorPicker::_bind_methods() { @@ -632,6 +630,10 @@ void ColorPickerButton::_notification(int p_what) { Ref<StyleBox> normal = get_stylebox("normal"); draw_rect(Rect2(normal->get_offset(), get_size() - normal->get_minimum_size()), picker->get_pick_color()); } + + if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) { + popup->hide(); + } } void ColorPickerButton::set_pick_color(const Color &p_color) { diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index ca47c3a5f4..de624fd029 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -47,7 +47,6 @@ class ColorPicker : public BoxContainer { private: Control *screen; - Ref<Image> last_capture; Control *uv_edit; Control *w_edit; TextureRect *sample; |