summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp22
-rw-r--r--drivers/gles3/shaders/canvas.glsl28
-rw-r--r--editor/plugins/editor_preview_plugins.cpp3
-rw-r--r--editor/property_editor.cpp3
-rw-r--r--platform/javascript/os_javascript.cpp191
-rw-r--r--scene/2d/area_2d.cpp54
-rw-r--r--scene/2d/area_2d.h10
-rw-r--r--scene/2d/audio_stream_player_2d.cpp463
-rw-r--r--scene/2d/audio_stream_player_2d.h96
-rw-r--r--scene/2d/canvas_item.cpp6
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/sprite.cpp22
-rw-r--r--scene/2d/sprite.h4
-rw-r--r--scene/audio/audio_player.cpp84
-rw-r--r--scene/audio/audio_player.h12
-rw-r--r--scene/gui/color_picker.cpp38
-rw-r--r--scene/gui/color_picker.h1
-rw-r--r--scene/register_scene_types.cpp4
-rw-r--r--scene/resources/texture.cpp22
-rw-r--r--scene/resources/texture.h10
-rw-r--r--scene/resources/world_2d.cpp7
-rw-r--r--scene/resources/world_2d.h4
-rw-r--r--servers/visual/rasterizer.h3
-rw-r--r--servers/visual/visual_server_canvas.cpp6
-rw-r--r--servers/visual/visual_server_canvas.h2
-rw-r--r--servers/visual/visual_server_raster.h2
-rw-r--r--servers/visual/visual_server_wrap_mt.h2
-rw-r--r--servers/visual_server.h2
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;