diff options
28 files changed, 893 insertions, 210 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 0c07abb002..a8895f7bfc 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -466,8 +466,10 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - glVertexAttrib4f(1, rect->rect.position.x, rect->rect.position.y, rect->rect.size.x, rect->rect.size.y); - glVertexAttrib4f(2, src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y); + state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(rect->rect.position.x, rect->rect.position.y, rect->rect.size.x, rect->rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, (rect->flags & CANVAS_RECT_CLIP_UV) ? true : false); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); if (untile) { @@ -477,8 +479,9 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } else { - glVertexAttrib4f(1, rect->rect.position.x, rect->rect.position.y, rect->rect.size.x, rect->rect.size.y); - glVertexAttrib4f(2, 0, 0, 1, 1); + state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(rect->rect.position.x, rect->rect.position.y, rect->rect.size.x, rect->rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } @@ -507,9 +510,10 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); -#define DSTRECT(m_x, m_y, m_w, m_h) glVertexAttrib4f(1, m_x, m_y, m_w, m_h) -#define SRCRECT(m_x, m_y, m_w, m_h) glVertexAttrib4f(2, (m_x)*texpixel_size.x, (m_y)*texpixel_size.y, (m_w)*texpixel_size.x, (m_h)*texpixel_size.y) +#define DSTRECT(m_x, m_y, m_w, m_h) state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(m_x, m_y, m_w, m_h)) +#define SRCRECT(m_x, m_y, m_w, m_h) state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color((m_x)*texpixel_size.x, (m_y)*texpixel_size.y, (m_w)*texpixel_size.x, (m_h)*texpixel_size.y)) //top left DSTRECT(np->rect.position.x, np->rect.position.y, np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); @@ -1312,8 +1316,10 @@ void RasterizerCanvasGLES3::reset_canvas() { void RasterizerCanvasGLES3::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) { - glVertexAttrib4f(1, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y); - glVertexAttrib4f(2, p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y); + state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index b0ce38cb68..7be6ee857a 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -6,8 +6,8 @@ layout(location=3) in vec4 color_attrib; #ifdef USE_TEXTURE_RECT -layout(location=1) in highp vec4 dst_rect; -layout(location=2) in highp vec4 src_rect; +uniform vec4 dst_rect; +uniform vec4 src_rect; #else @@ -65,6 +65,7 @@ const bool at_light_pass = false; #endif + VERTEX_SHADER_GLOBALS #if defined(USE_MATERIAL) @@ -228,22 +229,39 @@ LIGHT_SHADER_CODE } +#ifdef USE_TEXTURE_RECT + +uniform vec4 dst_rect; +uniform vec4 src_rect; +uniform bool clip_rect_uv; + +#endif + uniform bool use_default_normal; void main() { vec4 color = color_interp; + vec2 uv = uv_interp; +#ifdef USE_TEXTURE_RECT + if (clip_rect_uv) { + + vec2 half_texpixel = color_texpixel_size * 0.5; + uv = clamp(uv,src_rect.xy+half_texpixel,src_rect.xy+abs(src_rect.zw)-color_texpixel_size); + } + +#endif #if !defined(COLOR_USED) //default behavior, texture by color #ifdef USE_DISTANCE_FIELD const float smoothing = 1.0/32.0; - float distance = textureLod(color_texture, uv_interp,0.0).a; + float distance = textureLod(color_texture, uv,0.0).a; color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance) * color.a; #else - color *= texture( color_texture, uv_interp ); + color *= texture( color_texture, uv ); #endif @@ -259,7 +277,7 @@ void main() { #endif if (use_default_normal) { - normal.xy = textureLod(normal_texture, uv_interp,0.0).xy * 2.0 - 1.0; + normal.xy = textureLod(normal_texture, uv,0.0).xy * 2.0 - 1.0; normal.z = sqrt(1.0-dot(normal.xy,normal.xy)); normal_used=true; } else { diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 7f8b98e1d3..11d804422a 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -427,13 +427,14 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) { Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"); Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"); + img->lock(); + for (int i = 0; i < thumbnail_size; i++) { for (int j = 0; j < thumbnail_size; j++) { img->put_pixel(i, j, bg_color); } } - img->lock(); bool prev_is_text = false; bool in_keyword = false; for (int i = 0; i < code.length(); i++) { 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/2d/area_2d.cpp b/scene/2d/area_2d.cpp index aca7a8c736..db22a38cec 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "area_2d.h" #include "scene/scene_string_names.h" +#include "servers/audio_server.h" #include "servers/physics_2d_server.h" + void Area2D::set_space_override_mode(SpaceOverride p_mode) { space_override = p_mode; @@ -542,6 +544,47 @@ bool Area2D::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } +void Area2D::set_audio_bus_override(bool p_override) { + + audio_bus_override = p_override; +} + +bool Area2D::is_overriding_audio_bus() const { + + return audio_bus_override; +} + +void Area2D::set_audio_bus(const StringName &p_audio_bus) { + + audio_bus = p_audio_bus; +} + +StringName Area2D::get_audio_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) { + return audio_bus; + } + } + return "Master"; +} + +void Area2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "audio_bus_name") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_enter_tree", "id"), &Area2D::_body_enter_tree); @@ -598,6 +641,12 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area2D::overlaps_body); ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area2D::overlaps_area); + ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area2D::set_audio_bus); + ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area2D::get_audio_bus); + + ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override); + ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus); + ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout); @@ -624,6 +673,10 @@ void Area2D::_bind_methods() { ADD_GROUP("Collision", "collision_"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_GROUP("Audio Bus", "audio_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); } Area2D::Area2D() @@ -642,6 +695,7 @@ Area2D::Area2D() monitorable = false; collision_mask = 1; collision_layer = 1; + audio_bus_override = false; set_monitoring(true); set_monitorable(true); } diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index f0eb1e9240..12d71f3911 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -126,9 +126,13 @@ private: Map<ObjectID, AreaState> area_map; void _clear_monitoring(); + bool audio_bus_override; + StringName audio_bus; + protected: void _notification(int p_what); static void _bind_methods(); + void _validate_property(PropertyInfo &property) const; public: void set_space_override_mode(SpaceOverride p_mode); @@ -179,6 +183,12 @@ public: bool overlaps_area(Node *p_area) const; bool overlaps_body(Node *p_body) const; + void set_audio_bus_override(bool p_override); + bool is_overriding_audio_bus() const; + + void set_audio_bus(const StringName &p_audio_bus); + StringName get_audio_bus() const; + Area2D(); ~Area2D(); }; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp new file mode 100644 index 0000000000..3d9e64ae79 --- /dev/null +++ b/scene/2d/audio_stream_player_2d.cpp @@ -0,0 +1,463 @@ + +#include "audio_stream_player_2d.h" +#include "scene/2d/area_2d.h" +#include "scene/main/viewport.h" +void AudioStreamPlayer2D::_mix_audio() { + + if (!stream_playback.is_valid()) { + return; + } + + if (!active) { + return; + } + + if (setseek >= 0.0) { + stream_playback->start(setseek); + setseek = -1.0; //reset seek + } + + //get data + AudioFrame *buffer = mix_buffer.ptr(); + int buffer_size = mix_buffer.size(); + + //mix + stream_playback->mix(buffer, 1.0, buffer_size); + + //write all outputs + for (int i = 0; i < output_count; i++) { + + Output current = outputs[i]; + + //see if current output exists, to keep volume ramp + bool found = false; + for (int j = i; j < prev_output_count; j++) { + if (prev_outputs[j].viewport == current.viewport) { + if (j != i) { + SWAP(prev_outputs[j], prev_outputs[i]); + } + found = true; + break; + } + } + + if (!found) { + //create new if was not used before + if (prev_output_count < MAX_OUTPUTS) { + prev_outputs[prev_output_count] = prev_outputs[i]; //may be owned by another viewport + prev_output_count++; + } + prev_outputs[i] = current; + } + + //mix! + AudioFrame vol_inc = (current.vol - prev_outputs[i].vol) / float(buffer_size); + AudioFrame vol = current.vol; + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 0); + + for (int j = 0; j < buffer_size; j++) { + + target[j] = buffer[j] * vol; + vol += vol_inc; + } + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + + AudioFrame *targets[2] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 2), + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] = frame; + targets[1][j] = frame; + vol += vol_inc; + } + + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + AudioFrame *targets[3] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 2), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 3) + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] = frame; + targets[1][j] = frame; + targets[2][j] = frame; + vol += vol_inc; + } + + } break; + } + + prev_outputs[i] = current; + } + + prev_output_count = output_count; + + //stream is no longer active, disable this. + if (!stream_playback->is_playing()) { + active = false; + } + + output_ready = false; +} + +void AudioStreamPlayer2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + + AudioServer::get_singleton()->add_callback(_mix_audios, this); + if (autoplay && !get_tree()->is_editor_hint()) { + play(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + + AudioServer::get_singleton()->remove_callback(_mix_audios, this); + } + + if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) { + + //update anything related to position first, if possible of course + + if (!output_ready) { + List<Viewport *> viewports; + Ref<World2D> world_2d = get_world_2d(); + ERR_FAIL_COND(world_2d.is_null()); + + int new_output_count = 0; + + Vector2 global_pos = get_global_position(); + + int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); + + //check if any area is diverting sound into a bus + + Physics2DDirectSpaceState *space_state = Physics2DServer::get_singleton()->space_get_direct_state(world_2d->get_space()); + + Physics2DDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; + + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, Physics2DDirectSpaceState::TYPE_MASK_AREA); + + for (int i = 0; i < areas; i++) { + if (!sr[i].collider) + continue; + + Area2D *area2d = sr[i].collider->cast_to<Area2D>(); + if (!area2d) + continue; + + if (!area2d->is_overriding_audio_bus()) + continue; + + StringName bus_name = area2d->get_audio_bus(); + bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name); + break; + } + + world_2d->get_viewport_list(&viewports); + for (List<Viewport *>::Element *E = viewports.front(); E; E = E->next()) { + + Viewport *vp = E->get(); + if (vp->is_audio_listener_2d()) { + + //compute matrix to convert to screen + Transform2D to_screen = vp->get_global_canvas_transform() * vp->get_canvas_transform(); + Vector2 screen_size = vp->get_visible_rect().size; + + //screen in global is used for attenuation + Vector2 screen_in_global = to_screen.affine_inverse().xform(screen_size * 0.5); + + float dist = global_pos.distance_to(screen_in_global); //distance to screen center + + if (dist > max_distance) + continue; //cant hear this sound in this viewport + + float multiplier = Math::pow(1.0f - dist / max_distance, attenuation); + multiplier *= Math::db2linear(volume_db); //also apply player volume! + + //point in screen is used for panning + Vector2 point_in_screen = to_screen.xform(global_pos); + + float pan = CLAMP(point_in_screen.x / screen_size.width, 0.0, 1.0); + + float l = 1.0 - pan; + float r = pan; + + outputs[new_output_count].vol = AudioFrame(l, r) * multiplier; + outputs[new_output_count].bus_index = bus_index; + outputs[new_output_count].viewport = vp; //keep pointer only for reference + new_output_count++; + if (new_output_count == MAX_OUTPUTS) + break; + } + } + + output_count = new_output_count; + output_ready = true; + } + + //start playing if requested + if (setplay >= 0.0) { + setseek = setplay; + active = true; + setplay = -1; + _change_notify("playing"); //update property in editor + } + + //stop playing if no longer active + if (!active) { + set_fixed_process_internal(false); + _change_notify("playing"); //update property in editor + } + } +} + +void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) { + + ERR_FAIL_COND(!p_stream.is_valid()); + AudioServer::get_singleton()->lock(); + + mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); + + if (stream_playback.is_valid()) { + stream_playback.unref(); + stream.unref(); + active = false; + setseek = -1; + } + + stream = p_stream; + stream_playback = p_stream->instance_playback(); + + if (stream_playback.is_null()) { + stream.unref(); + ERR_FAIL_COND(stream_playback.is_null()); + } + + AudioServer::get_singleton()->unlock(); +} + +Ref<AudioStream> AudioStreamPlayer2D::get_stream() const { + + return stream; +} + +void AudioStreamPlayer2D::set_volume_db(float p_volume) { + + volume_db = p_volume; +} +float AudioStreamPlayer2D::get_volume_db() const { + + return volume_db; +} + +void AudioStreamPlayer2D::play(float p_from_pos) { + + if (stream_playback.is_valid()) { + setplay = p_from_pos; + output_ready = false; + set_fixed_process_internal(true); + } +} + +void AudioStreamPlayer2D::seek(float p_seconds) { + + if (stream_playback.is_valid()) { + setseek = p_seconds; + } +} + +void AudioStreamPlayer2D::stop() { + + if (stream_playback.is_valid()) { + active = false; + set_fixed_process_internal(false); + setplay = -1; + } +} + +bool AudioStreamPlayer2D::is_playing() const { + + if (stream_playback.is_valid()) { + return active; // && stream_playback->is_playing(); + } + + return false; +} + +float AudioStreamPlayer2D::get_pos() { + + if (stream_playback.is_valid()) { + return stream_playback->get_pos(); + } + + return 0; +} + +void AudioStreamPlayer2D::set_bus(const StringName &p_bus) { + + //if audio is active, must lock this + AudioServer::get_singleton()->lock(); + bus = p_bus; + AudioServer::get_singleton()->unlock(); +} +StringName AudioStreamPlayer2D::get_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == bus) { + return bus; + } + } + return "Master"; +} + +void AudioStreamPlayer2D::set_autoplay(bool p_enable) { + + autoplay = p_enable; +} +bool AudioStreamPlayer2D::is_autoplay_enabled() { + + return autoplay; +} + +void AudioStreamPlayer2D::_set_playing(bool p_enable) { + + if (p_enable) + play(); + else + stop(); +} +bool AudioStreamPlayer2D::_is_active() const { + + return active; +} + +void AudioStreamPlayer2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "bus") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + +void AudioStreamPlayer2D::_bus_layout_changed() { + + _change_notify(); +} + +void AudioStreamPlayer2D::set_max_distance(float p_pixels) { + + ERR_FAIL_COND(p_pixels <= 0.0); + max_distance = p_pixels; +} + +float AudioStreamPlayer2D::get_max_distance() const { + + return max_distance; +} + +void AudioStreamPlayer2D::set_attenuation(float p_curve) { + + attenuation = p_curve; +} +float AudioStreamPlayer2D::get_attenuation() const { + + return attenuation; +} + +void AudioStreamPlayer2D::set_area_mask(uint32_t p_mask) { + + area_mask = p_mask; +} + +uint32_t AudioStreamPlayer2D::get_area_mask() const { + + return area_mask; +} + +void AudioStreamPlayer2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioStreamPlayer2D::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer2D::get_stream); + + ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer2D::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer2D::get_volume_db); + + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer2D::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer2D::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer2D::stop); + + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer2D::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer2D::get_pos); + + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer2D::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer2D::get_bus); + + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer2D::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer2D::is_autoplay_enabled); + + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer2D::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer2D::_is_active); + + ClassDB::bind_method(D_METHOD("set_max_distance", "pixels"), &AudioStreamPlayer2D::set_max_distance); + ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer2D::get_max_distance); + + ClassDB::bind_method(D_METHOD("set_attenuation", "curve"), &AudioStreamPlayer2D::set_attenuation); + ClassDB::bind_method(D_METHOD("get_attenuation"), &AudioStreamPlayer2D::get_attenuation); + + ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer2D::set_area_mask); + ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer2D::get_area_mask); + + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer2D::_bus_layout_changed); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "_is_active"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "1,65536,1"), "set_max_distance", "get_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation", PROPERTY_HINT_EXP_EASING), "set_attenuation", "get_attenuation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask"); +} + +AudioStreamPlayer2D::AudioStreamPlayer2D() { + + volume_db = 0; + autoplay = false; + setseek = -1; + active = false; + output_count = 0; + prev_output_count = 0; + max_distance = 2000; + attenuation = 1; + setplay = -1; + output_ready = false; + area_mask = 1; + AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); +} + +AudioStreamPlayer2D::~AudioStreamPlayer2D() { +} diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h new file mode 100644 index 0000000000..25eff61b76 --- /dev/null +++ b/scene/2d/audio_stream_player_2d.h @@ -0,0 +1,96 @@ +#ifndef AUDIO_STREAM_PLAYER_2D_H +#define AUDIO_STREAM_PLAYER_2D_H + +#include "scene/2d/node_2d.h" +#include "servers/audio/audio_stream.h" +#include "servers/audio_server.h" + +class AudioStreamPlayer2D : public Node2D { + + GDCLASS(AudioStreamPlayer2D, Node2D) + +private: + enum { + MAX_OUTPUTS = 8, + MAX_INTERSECT_AREAS = 32 + + }; + + struct Output { + + AudioFrame vol; + int bus_index; + Viewport *viewport; //pointer only used for reference to previous mix + }; + + Output outputs[MAX_OUTPUTS]; + volatile int output_count; + volatile bool output_ready; + + //these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks) + Output prev_outputs[MAX_OUTPUTS]; + int prev_output_count; + + Ref<AudioStreamPlayback> stream_playback; + Ref<AudioStream> stream; + Vector<AudioFrame> mix_buffer; + + volatile float setseek; + volatile bool active; + volatile float setplay; + + float volume_db; + bool autoplay; + StringName bus; + + void _mix_audio(); + static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer2D *>(self)->_mix_audio(); } + + void _set_playing(bool p_enable); + bool _is_active() const; + + void _bus_layout_changed(); + + uint32_t area_mask; + + float max_distance; + float attenuation; + +protected: + void _validate_property(PropertyInfo &property) const; + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_stream(Ref<AudioStream> p_stream); + Ref<AudioStream> get_stream() const; + + void set_volume_db(float p_volume); + float get_volume_db() const; + + void play(float p_from_pos = 0.0); + void seek(float p_seconds); + void stop(); + bool is_playing() const; + float get_pos(); + + void set_bus(const StringName &p_bus); + StringName get_bus() const; + + void set_autoplay(bool p_enable); + bool is_autoplay_enabled(); + + void set_max_distance(float p_pixels); + float get_max_distance() const; + + void set_attenuation(float p_curve); + float get_attenuation() const; + + void set_area_mask(uint32_t p_mask); + uint32_t get_area_mask() const; + + AudioStreamPlayer2D(); + ~AudioStreamPlayer2D(); +}; + +#endif diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 4f3a20d61f..471f529713 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -459,14 +459,14 @@ void CanvasItem::draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p ERR_FAIL_COND(p_texture.is_null()); p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose, p_normal_map); } -void CanvasItem::draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) { +void CanvasItem::draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL(); } ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_normal_map); + p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_normal_map, p_clip_uv); } void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) { @@ -758,7 +758,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_circle", "pos", "radius", "color"), &CanvasItem::draw_circle); ClassDB::bind_method(D_METHOD("draw_texture", "texture:Texture", "pos", "modulate", "normal_map:Texture"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture:Texture", "rect", "tile", "modulate", "transpose", "normal_map:Texture"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture:Texture", "rect", "src_rect", "modulate", "transpose", "normal_map:Texture"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture:Texture", "rect", "src_rect", "modulate", "transpose", "normal_map:Texture", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_style_box", "style_box:StyleBox", "rect"), &CanvasItem::draw_style_box); ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture:Texture", "width", "normal_map:Texture"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture:Texture", "normal_map:Texture"), &CanvasItem::draw_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant())); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index b47dbd00fa..595dd03057 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -160,7 +160,7 @@ public: void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color); void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>()); void draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()); - void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()); + void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture = Ref<Texture>(), float p_width = 1, const Ref<Texture> &p_normal_map = Ref<Texture>()); void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>()); diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index dedec2dd49..ff574a6bd6 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -65,11 +65,13 @@ void Sprite::_notification(int p_what) { Size2 s; Rect2 src_rect; + bool filter_clip = false; if (region) { s = region_rect.size; src_rect = region_rect; + filter_clip = region_filter_clip; } else { s = Size2(texture->get_size()); s = s / Size2(hframes, vframes); @@ -93,7 +95,7 @@ void Sprite::_notification(int p_what) { if (vflip) dst_rect.size.y = -dst_rect.size.y; - texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map); + texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, filter_clip); } break; } @@ -214,6 +216,15 @@ Rect2 Sprite::get_region_rect() const { return region_rect; } +void Sprite::set_region_filter_clip(bool p_enable) { + region_filter_clip = p_enable; + update(); +} + +bool Sprite::is_region_filter_clip_enabled() const { + return region_filter_clip; +} + void Sprite::set_frame(int p_frame) { ERR_FAIL_INDEX(p_frame, vframes * hframes); @@ -323,6 +334,9 @@ void Sprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite::set_region_rect); ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect); + ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite::set_region_filter_clip); + ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite::is_region_filter_clip_enabled); + ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite::set_frame); ClassDB::bind_method(D_METHOD("get_frame"), &Sprite::get_frame); @@ -344,8 +358,11 @@ void Sprite::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region"), "set_region", "is_region"); + + ADD_GROUP("Region", "region_"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled"); } Sprite::Sprite() { @@ -354,6 +371,7 @@ Sprite::Sprite() { hflip = false; vflip = false; region = false; + region_filter_clip = false; frame = 0; diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index 3b5d031e92..d3f9a5f032 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -47,6 +47,7 @@ class Sprite : public Node2D { bool vflip; bool region; Rect2 region_rect; + bool region_filter_clip; int frame; @@ -86,6 +87,9 @@ public: void set_region(bool p_region); bool is_region() const; + void set_region_filter_clip(bool p_enable); + bool is_region_filter_clip_enabled() const; + void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index ad72a512d8..bcca834642 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "audio_player.h" -void AudioPlayer::_mix_audio() { +void AudioStreamPlayer::_mix_audio() { if (!stream_playback.is_valid()) { return; @@ -95,7 +95,7 @@ void AudioPlayer::_mix_audio() { } } -void AudioPlayer::_notification(int p_what) { +void AudioStreamPlayer::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -111,7 +111,7 @@ void AudioPlayer::_notification(int p_what) { } } -void AudioPlayer::set_stream(Ref<AudioStream> p_stream) { +void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { ERR_FAIL_COND(!p_stream.is_valid()); AudioServer::get_singleton()->lock(); @@ -136,21 +136,21 @@ void AudioPlayer::set_stream(Ref<AudioStream> p_stream) { AudioServer::get_singleton()->unlock(); } -Ref<AudioStream> AudioPlayer::get_stream() const { +Ref<AudioStream> AudioStreamPlayer::get_stream() const { return stream; } -void AudioPlayer::set_volume_db(float p_volume) { +void AudioStreamPlayer::set_volume_db(float p_volume) { volume_db = p_volume; } -float AudioPlayer::get_volume_db() const { +float AudioStreamPlayer::get_volume_db() const { return volume_db; } -void AudioPlayer::play(float p_from_pos) { +void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { mix_volume_db = volume_db; //reset volume ramp @@ -159,21 +159,21 @@ void AudioPlayer::play(float p_from_pos) { } } -void AudioPlayer::seek(float p_seconds) { +void AudioStreamPlayer::seek(float p_seconds) { if (stream_playback.is_valid()) { setseek = p_seconds; } } -void AudioPlayer::stop() { +void AudioStreamPlayer::stop() { if (stream_playback.is_valid()) { active = false; } } -bool AudioPlayer::is_playing() const { +bool AudioStreamPlayer::is_playing() const { if (stream_playback.is_valid()) { return active && stream_playback->is_playing(); @@ -182,7 +182,7 @@ bool AudioPlayer::is_playing() const { return false; } -float AudioPlayer::get_pos() { +float AudioStreamPlayer::get_pos() { if (stream_playback.is_valid()) { return stream_playback->get_pos(); @@ -191,14 +191,14 @@ float AudioPlayer::get_pos() { return 0; } -void AudioPlayer::set_bus(const StringName &p_bus) { +void AudioStreamPlayer::set_bus(const StringName &p_bus) { //if audio is active, must lock this AudioServer::get_singleton()->lock(); bus = p_bus; AudioServer::get_singleton()->unlock(); } -StringName AudioPlayer::get_bus() const { +StringName AudioStreamPlayer::get_bus() const { for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { if (AudioServer::get_singleton()->get_bus_name(i) == bus) { @@ -208,38 +208,38 @@ StringName AudioPlayer::get_bus() const { return "Master"; } -void AudioPlayer::set_autoplay(bool p_enable) { +void AudioStreamPlayer::set_autoplay(bool p_enable) { autoplay = p_enable; } -bool AudioPlayer::is_autoplay_enabled() { +bool AudioStreamPlayer::is_autoplay_enabled() { return autoplay; } -void AudioPlayer::set_mix_target(MixTarget p_target) { +void AudioStreamPlayer::set_mix_target(MixTarget p_target) { mix_target = p_target; } -AudioPlayer::MixTarget AudioPlayer::get_mix_target() const { +AudioStreamPlayer::MixTarget AudioStreamPlayer::get_mix_target() const { return mix_target; } -void AudioPlayer::_set_playing(bool p_enable) { +void AudioStreamPlayer::_set_playing(bool p_enable) { if (p_enable) play(); else stop(); } -bool AudioPlayer::_is_active() const { +bool AudioStreamPlayer::_is_active() const { return active; } -void AudioPlayer::_validate_property(PropertyInfo &property) const { +void AudioStreamPlayer::_validate_property(PropertyInfo &property) const { if (property.name == "bus") { @@ -255,39 +255,39 @@ void AudioPlayer::_validate_property(PropertyInfo &property) const { } } -void AudioPlayer::_bus_layout_changed() { +void AudioStreamPlayer::_bus_layout_changed() { _change_notify(); } -void AudioPlayer::_bind_methods() { +void AudioStreamPlayer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioPlayer::set_stream); - ClassDB::bind_method(D_METHOD("get_stream"), &AudioPlayer::get_stream); + ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioStreamPlayer::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer::get_stream); - ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioPlayer::set_volume_db); - ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioPlayer::get_volume_db); + ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db); - ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioPlayer::play, DEFVAL(0.0)); - ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioPlayer::seek); - ClassDB::bind_method(D_METHOD("stop"), &AudioPlayer::stop); + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer::stop); - ClassDB::bind_method(D_METHOD("is_playing"), &AudioPlayer::is_playing); - ClassDB::bind_method(D_METHOD("get_pos"), &AudioPlayer::get_pos); + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer::get_pos); - ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioPlayer::set_bus); - ClassDB::bind_method(D_METHOD("get_bus"), &AudioPlayer::get_bus); + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer::get_bus); - ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioPlayer::set_autoplay); - ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioPlayer::is_autoplay_enabled); + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer::is_autoplay_enabled); - ClassDB::bind_method(D_METHOD("set_mix_target", "mix_target"), &AudioPlayer::set_mix_target); - ClassDB::bind_method(D_METHOD("get_mix_target"), &AudioPlayer::get_mix_target); + ClassDB::bind_method(D_METHOD("set_mix_target", "mix_target"), &AudioStreamPlayer::set_mix_target); + ClassDB::bind_method(D_METHOD("get_mix_target"), &AudioStreamPlayer::get_mix_target); - ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioPlayer::_set_playing); - ClassDB::bind_method(D_METHOD("_is_active"), &AudioPlayer::_is_active); + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer::_is_active); - ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioPlayer::_bus_layout_changed); + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer::_bus_layout_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); @@ -297,7 +297,7 @@ void AudioPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); } -AudioPlayer::AudioPlayer() { +AudioStreamPlayer::AudioStreamPlayer() { mix_volume_db = 0; volume_db = 0; @@ -309,5 +309,5 @@ AudioPlayer::AudioPlayer() { AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); } -AudioPlayer::~AudioPlayer() { +AudioStreamPlayer::~AudioStreamPlayer() { } diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 5a8a8494e1..8bd6844dec 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -33,9 +33,9 @@ #include "scene/main/node.h" #include "servers/audio/audio_stream.h" -class AudioPlayer : public Node { +class AudioStreamPlayer : public Node { - GDCLASS(AudioPlayer, Node) + GDCLASS(AudioStreamPlayer, Node) public: enum MixTarget { @@ -60,7 +60,7 @@ private: MixTarget mix_target; void _mix_audio(); - static void _mix_audios(void *self) { reinterpret_cast<AudioPlayer *>(self)->_mix_audio(); } + static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer *>(self)->_mix_audio(); } void _set_playing(bool p_enable); bool _is_active() const; @@ -94,9 +94,9 @@ public: void set_mix_target(MixTarget p_target); MixTarget get_mix_target() const; - AudioPlayer(); - ~AudioPlayer(); + AudioStreamPlayer(); + ~AudioStreamPlayer(); }; -VARIANT_ENUM_CAST(AudioPlayer::MixTarget) +VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget) #endif // AUDIOPLAYER_H 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; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index df3729c50b..b2737353fb 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -111,6 +111,7 @@ #include "scene/2d/ray_cast_2d.h" //#include "scene/2d/sound_player_2d.h" //#include "scene/2d/sample_player_2d.h" +#include "scene/2d/audio_stream_player_2d.h" #include "scene/2d/canvas_modulate.h" #include "scene/2d/navigation2d.h" #include "scene/2d/remote_transform_2d.h" @@ -591,7 +592,8 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<AudioPlayer>(); + ClassDB::register_class<AudioStreamPlayer>(); + ClassDB::register_class<AudioStreamPlayer2D>(); ClassDB::register_virtual_class<VideoStream>(); ClassDB::register_class<AudioStreamSample>(); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 1682971f9c..2120b37497 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -46,10 +46,10 @@ void Texture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, con RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid); } -void Texture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void Texture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); } bool Texture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -70,7 +70,7 @@ void Texture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_flags"), &Texture::get_flags); ClassDB::bind_method(D_METHOD("draw", "canvas_item", "pos", "modulate", "transpose", "normal_map:Texture"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map:Texture"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map:Texture"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map:Texture", "clip_uv"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true)); BIND_CONSTANT(FLAG_MIPMAPS); BIND_CONSTANT(FLAG_REPEAT); @@ -282,12 +282,12 @@ void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid); } -void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); } void ImageTexture::set_size_override(const Size2 &p_size) { @@ -685,12 +685,12 @@ void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_til RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid); } -void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); } bool StreamTexture::has_alpha() const { @@ -912,7 +912,7 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid); } -void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { //this might not necessarily work well if using a rect, needs to be fixed properly Rect2 rc = region; @@ -941,7 +941,7 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons Rect2 dr(p_rect.position + ofs * scale, src_c.size * scale); RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, p_clip_uv); } bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -1130,7 +1130,7 @@ void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.position, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose, p_normal_map); } } -void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { //tiling not supported for this if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0) @@ -1150,7 +1150,7 @@ void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons target.size *= scale; target.position = p_rect.position + (p_src_rect.position + rect.position) * scale; local.position -= rect.position; - pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose, p_normal_map); + pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose, p_normal_map, false); } } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 78693b07ac..2b82dbd21f 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -70,7 +70,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; virtual Ref<Image> get_data() const { return Ref<Image>(); } @@ -133,7 +133,7 @@ public: bool has_alpha() const; virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; void set_storage(Storage p_storage); Storage get_storage() const; @@ -205,7 +205,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; virtual bool has_alpha() const; virtual void set_flags(uint32_t p_flags); @@ -259,7 +259,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; AtlasTexture(); @@ -307,7 +307,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; LargeTexture(); }; diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index ec9ec96e50..36d2a38b3d 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -360,16 +360,17 @@ RID World2D::get_space() { return space; } -RID World2D::get_sound_space() { +void World2D::get_viewport_list(List<Viewport *> *r_viewports) { - return sound_space; + for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) { + r_viewports->push_back(E->key()); + } } void World2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas); ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space); - ClassDB::bind_method(D_METHOD("get_sound_space"), &World2D::get_sound_space); ClassDB::bind_method(D_METHOD("get_direct_space_state:Physics2DDirectSpaceState"), &World2D::get_direct_space_state); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index 2b6e7e7383..35c8ce390f 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -44,7 +44,6 @@ class World2D : public Resource { RID canvas; RID space; - RID sound_space; SpatialIndexer2D *indexer; @@ -66,10 +65,11 @@ protected: public: RID get_canvas(); RID get_space(); - RID get_sound_space(); Physics2DDirectSpaceState *get_direct_space_state(); + void get_viewport_list(List<Viewport *> *r_viewports); + World2D(); ~World2D(); }; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index a56cdcdc50..07d6542b62 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -525,7 +525,8 @@ public: CANVAS_RECT_TILE = 2, CANVAS_RECT_FLIP_H = 4, CANVAS_RECT_FLIP_V = 8, - CANVAS_RECT_TRANSPOSE = 16 + CANVAS_RECT_TRANSPOSE = 16, + CANVAS_RECT_CLIP_UV = 32 }; struct Light : public RID_Data { diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 0ae86cd389..2ef1fd417b 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -461,7 +461,7 @@ void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p canvas_item->commands.push_back(rect); } -void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, RID p_normal_map) { +void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, RID p_normal_map, bool p_clip_uv) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -490,6 +490,10 @@ void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const R SWAP(rect->rect.size.x, rect->rect.size.y); } + if (p_clip_uv) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_CLIP_UV; + } + canvas_item->rect_dirty = true; canvas_item->commands.push_back(rect); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index 0808bf72ad..2c86b14c70 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -166,7 +166,7 @@ public: void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()); - void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()); + void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = true); void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, VS::NinePatchAxisMode p_x_axis_mode = VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode = VS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID()); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID()); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 504d836913..c48bee7fa4 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1042,7 +1042,7 @@ public: BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) BIND7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) - BIND7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID) + BIND8(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, bool) BIND11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID) BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) BIND6(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID) diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index e60a478bd9..94cbfc815e 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -469,7 +469,7 @@ public: FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) FUNC7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) - FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID) + FUNC8(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, bool) FUNC11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID) FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) FUNC6(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID) diff --git a/servers/visual_server.h b/servers/visual_server.h index 22f91f6a73..a27b32f54f 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -786,7 +786,7 @@ public: virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()) = 0; - virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()) = 0; + virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = true) = 0; virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID()) = 0; |