summaryrefslogtreecommitdiff
path: root/scene/main/canvas_item.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main/canvas_item.cpp')
-rw-r--r--scene/main/canvas_item.cpp107
1 files changed, 60 insertions, 47 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 7b0554442c..b36353158b 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -154,17 +154,7 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const {
Transform2D CanvasItem::get_screen_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
- Transform2D xform = get_global_transform_with_canvas();
-
- Window *w = Object::cast_to<Window>(get_viewport());
- if (w && !w->is_embedding_subwindows()) {
- Transform2D s;
- s.set_origin(w->get_position());
-
- xform = s * xform;
- }
-
- return xform;
+ return get_viewport()->get_popup_base_transform() * get_global_transform_with_canvas();
}
Transform2D CanvasItem::get_global_transform() const {
@@ -195,7 +185,7 @@ void CanvasItem::_top_level_raise_self() {
}
void CanvasItem::_enter_canvas() {
- // Resolves to nullptr if the node is toplevel.
+ // Resolves to nullptr if the node is top_level.
CanvasItem *parent_item = get_parent_item();
if (parent_item) {
@@ -410,11 +400,28 @@ void CanvasItem::set_as_top_level(bool p_top_level) {
_exit_canvas();
top_level = p_top_level;
+ _top_level_changed();
_enter_canvas();
_notify_transform();
}
+void CanvasItem::_top_level_changed() {
+ // Inform children that top_level status has changed on a parent.
+ int children = get_child_count();
+ for (int i = 0; i < children; i++) {
+ CanvasItem *child = Object::cast_to<CanvasItem>(get_child(i));
+ if (child) {
+ child->_top_level_changed_on_parent();
+ }
+ }
+}
+
+void CanvasItem::_top_level_changed_on_parent() {
+ // Inform children that top_level status has changed on a parent.
+ _top_level_changed();
+}
+
bool CanvasItem::is_set_as_top_level() const {
return top_level;
}
@@ -484,6 +491,17 @@ int CanvasItem::get_z_index() const {
return z_index;
}
+int CanvasItem::get_effective_z_index() const {
+ int effective_z_index = z_index;
+ if (is_z_relative()) {
+ CanvasItem *p = get_parent_item();
+ if (p) {
+ effective_z_index += p->get_effective_z_index();
+ }
+ }
+ return effective_z_index;
+}
+
void CanvasItem::set_y_sort_enabled(bool p_enabled) {
y_sort_enabled = p_enabled;
RS::get_singleton()->canvas_item_set_sort_children_by_y(canvas_item, y_sort_enabled);
@@ -495,14 +513,16 @@ bool CanvasItem::is_y_sort_enabled() const {
void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_dash <= 0.0);
float length = (p_to - p_from).length();
- if (length < p_dash) {
+ Vector2 step = p_dash * (p_to - p_from).normalized();
+
+ if (length < p_dash || step == Vector2()) {
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
return;
}
- Vector2 step = p_dash * (p_to - p_from).normalized();
int steps = (p_aligned) ? Math::ceil(length / p_dash) : Math::floor(length / p_dash);
if (steps % 2 == 0) {
steps--;
@@ -512,10 +532,18 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
if (p_aligned) {
off += (p_to - p_from).normalized() * (length - steps * p_dash) / 2.0;
}
+
+ Vector<Vector2> points;
+ points.resize(steps + 1);
for (int i = 0; i < steps; i += 2) {
- RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, (i == 0) ? p_from : off, (p_aligned && i == steps - 1) ? p_to : (off + step), p_color, p_width);
+ points.write[i] = (i == 0) ? p_from : off;
+ points.write[i + 1] = (p_aligned && i == steps - 1) ? p_to : (off + step);
off += step * 2;
}
+
+ Vector<Color> colors = { p_color };
+
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width);
}
void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
@@ -581,38 +609,17 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
} else if (p_width >= rect.size.width || p_width >= rect.size.height) {
RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color);
} else {
- // Thick lines are offset depending on their width to avoid partial overlapping.
- // Thin lines are drawn without offset. The result may not be perfect.
- real_t offset = (p_width >= 0) ? 0.5f * p_width : 0.0f;
-
- // Top line.
- RenderingServer::get_singleton()->canvas_item_add_line(
- canvas_item,
- rect.position + Size2(-offset, 0),
- rect.position + Size2(-offset + rect.size.width, 0),
- p_color,
- p_width);
- // Right line.
- RenderingServer::get_singleton()->canvas_item_add_line(
- canvas_item,
- rect.position + Size2(rect.size.width, -offset),
- rect.position + Size2(rect.size.width, -offset + rect.size.height),
- p_color,
- p_width);
- // Bottom line.
- RenderingServer::get_singleton()->canvas_item_add_line(
- canvas_item,
- rect.position + Size2(offset + rect.size.width, rect.size.height),
- rect.position + Size2(offset, rect.size.height),
- p_color,
- p_width);
- // Left line.
- RenderingServer::get_singleton()->canvas_item_add_line(
- canvas_item,
- rect.position + Size2(0, offset + rect.size.height),
- rect.position + Size2(0, offset),
- p_color,
- p_width);
+ Vector<Vector2> points;
+ points.resize(5);
+ points.write[0] = rect.position;
+ points.write[1] = rect.position + Vector2(rect.size.x, 0);
+ points.write[2] = rect.position + rect.size;
+ points.write[3] = rect.position + Vector2(0, rect.size.y);
+ points.write[4] = rect.position;
+
+ Vector<Color> colors = { p_color };
+
+ RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width);
}
}
@@ -927,6 +934,12 @@ void CanvasItem::force_update_transform() {
notification(NOTIFICATION_TRANSFORM_CHANGED);
}
+void CanvasItem::_validate_property(PropertyInfo &p_property) const {
+ if (hide_clip_children && p_property.name == "clip_children") {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+}
+
void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("_top_level_raise_self"), &CanvasItem::_top_level_raise_self);