summaryrefslogtreecommitdiff
path: root/servers/visual
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual')
-rw-r--r--servers/visual/rasterizer.h12
-rw-r--r--servers/visual/shader_language.cpp99
-rw-r--r--servers/visual/shader_language.h13
-rw-r--r--servers/visual/shader_types.cpp1
-rw-r--r--servers/visual/visual_server_canvas.cpp76
-rw-r--r--servers/visual/visual_server_canvas.h14
-rw-r--r--servers/visual/visual_server_raster.h8
-rw-r--r--servers/visual/visual_server_scene.cpp91
-rw-r--r--servers/visual/visual_server_scene.h13
-rw-r--r--servers/visual/visual_server_viewport.cpp10
-rw-r--r--servers/visual/visual_server_viewport.h19
-rw-r--r--servers/visual/visual_server_wrap_mt.h8
12 files changed, 278 insertions, 86 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 8c3736a1bf..f78b4aaf5f 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -62,7 +62,7 @@ public:
virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
- virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) = 0;
+ virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;
@@ -73,7 +73,7 @@ public:
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
- virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+ virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
virtual bool is_environment(RID p_env) = 0;
@@ -120,9 +120,7 @@ public:
Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader
virtual void base_removed() = 0;
- virtual void base_changed() = 0;
- virtual void base_material_changed() = 0;
-
+ virtual void base_changed(bool p_aabb, bool p_materials) = 0;
InstanceBase() :
dependency_item(this) {
@@ -520,6 +518,8 @@ public:
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
virtual void particles_restart(RID p_particles) = 0;
+ virtual bool particles_is_inactive(RID p_particles) const = 0;
+
virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0;
virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
@@ -800,8 +800,6 @@ public:
RID particles;
RID texture;
RID normal_map;
- int h_frames;
- int v_frames;
CommandParticles() { type = TYPE_PARTICLES; }
};
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index d52e121a13..1acec7ccaf 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -131,7 +131,6 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"INTERPOLATION_FLAT",
- "INTERPOLATION_NO_PERSPECTIVE",
"INTERPOLATION_SMOOTH",
"PRECISION_LOW",
"PRECISION_MID",
@@ -271,7 +270,6 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_PRECISION_LOW, "lowp" },
{ TK_PRECISION_MID, "mediump" },
@@ -691,6 +689,30 @@ String ShaderLanguage::token_debug(const String &p_code) {
return output;
}
+bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) {
+ return (
+ p_type == TK_TYPE_VOID ||
+ p_type == TK_TYPE_BOOL ||
+ p_type == TK_TYPE_BVEC2 ||
+ p_type == TK_TYPE_BVEC3 ||
+ p_type == TK_TYPE_BVEC4 ||
+ p_type == TK_TYPE_INT ||
+ p_type == TK_TYPE_IVEC2 ||
+ p_type == TK_TYPE_IVEC3 ||
+ p_type == TK_TYPE_IVEC4 ||
+ p_type == TK_TYPE_UINT ||
+ p_type == TK_TYPE_UVEC2 ||
+ p_type == TK_TYPE_UVEC3 ||
+ p_type == TK_TYPE_UVEC4 ||
+ p_type == TK_TYPE_FLOAT ||
+ p_type == TK_TYPE_VEC2 ||
+ p_type == TK_TYPE_VEC3 ||
+ p_type == TK_TYPE_VEC4 ||
+ p_type == TK_TYPE_MAT2 ||
+ p_type == TK_TYPE_MAT3 ||
+ p_type == TK_TYPE_MAT4);
+}
+
bool ShaderLanguage::is_token_datatype(TokenType p_type) {
return (
@@ -735,7 +757,6 @@ bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
return (
p_type == TK_INTERPOLATION_FLAT ||
- p_type == TK_INTERPOLATION_NO_PERSPECTIVE ||
p_type == TK_INTERPOLATION_SMOOTH);
}
@@ -743,8 +764,6 @@ ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenT
if (p_type == TK_INTERPOLATION_FLAT)
return INTERPOLATION_FLAT;
- else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE)
- return INTERPOLATION_NO_PERSPECTIVE;
else
return INTERPOLATION_SMOOTH;
}
@@ -1196,6 +1215,15 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) {
valid = true;
ret_type = TYPE_MAT4;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) {
+ valid = true;
+ ret_type = TYPE_VEC2;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) {
+ valid = true;
+ ret_type = TYPE_VEC3;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) {
+ valid = true;
+ ret_type = TYPE_VEC4;
}
} break;
case OP_ASSIGN_BIT_AND:
@@ -2013,6 +2041,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
};
+const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
+ //constructors
+ { "modf", 1 },
+ { NULL, 0 }
+};
+
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type) {
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, NULL);
@@ -2056,6 +2090,41 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
if (!fail) {
+ //make sure its not an out argument used in the wrong way
+ int outarg_idx = 0;
+ while (builtin_func_out_args[outarg_idx].name) {
+
+ if (String(name) == builtin_func_out_args[outarg_idx].name) {
+ int arg_idx = builtin_func_out_args[outarg_idx].argument;
+
+ if (arg_idx < argcount) {
+
+ if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable");
+ return false;
+ }
+ StringName var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
+
+ const BlockNode *b = p_block;
+ bool valid = false;
+ while (b) {
+ if (b->variables.has(var_name)) {
+ valid = true;
+ break;
+ }
+ b = b->parent_block;
+ }
+
+ if (!valid) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable");
+ return false;
+ }
+ }
+ }
+
+ outarg_idx++;
+ }
+
if (r_ret_type)
*r_ret_type = builtin_func_defs[idx].rettype;
@@ -2288,7 +2357,7 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLERCUBE;
}
-Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type) {
+Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
if (p_value.size() > 0) {
Variant value;
switch (p_type) {
@@ -2332,7 +2401,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
break;
case ShaderLanguage::TYPE_VEC4:
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ } else {
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ }
break;
case ShaderLanguage::TYPE_MAT2:
value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
@@ -2498,7 +2571,7 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT
identifier = StringName();
- TkPos pos;
+ TkPos pos = { 0, 0 };
Token tk = _get_token();
@@ -3563,6 +3636,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
}
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for variable (samplers not allowed)");
+ return ERR_PARSE_ERROR;
+ }
+
DataType type = get_token_datatype(tk.type);
tk = _get_token();
@@ -4218,6 +4296,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for function return (samplers not allowed)");
+ return ERR_PARSE_ERROR;
+ }
+
type = get_token_datatype(tk.type);
_get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name);
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 08c4d06992..2d1851928e 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -80,7 +80,6 @@ public:
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_INTERPOLATION_FLAT,
- TK_INTERPOLATION_NO_PERSPECTIVE,
TK_INTERPOLATION_SMOOTH,
TK_PRECISION_LOW,
TK_PRECISION_MID,
@@ -210,7 +209,6 @@ public:
enum DataInterpolation {
INTERPOLATION_FLAT,
- INTERPOLATION_NO_PERSPECTIVE,
INTERPOLATION_SMOOTH,
};
@@ -333,6 +331,7 @@ public:
virtual DataType get_datatype() const { return datatype_cache; }
VariableNode() {
+
type = TYPE_VARIABLE;
datatype_cache = TYPE_VOID;
}
@@ -534,6 +533,7 @@ public:
static String get_token_text(Token p_token);
static bool is_token_datatype(TokenType p_type);
+ static bool is_token_variable_datatype(TokenType p_type);
static DataType get_token_datatype(TokenType p_type);
static bool is_token_interpolation(TokenType p_type);
static DataInterpolation get_token_interpolation(TokenType p_type);
@@ -548,7 +548,7 @@ public:
static int get_cardinality(DataType p_type);
static bool is_scalar_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
- static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type);
+ static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
@@ -642,6 +642,12 @@ private:
const DataType args[MAX_ARGS];
};
+ struct BuiltinFuncOutArgs { //arguments used as out in built in funcions
+
+ const char *name;
+ int argument;
+ };
+
CompletionType completion_type;
int completion_line;
BlockNode *completion_block;
@@ -652,6 +658,7 @@ private:
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
+ static const BuiltinFuncOutArgs builtin_func_out_args[];
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 69acf52e17..baafe2f8d0 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -199,6 +199,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 3c8088c75c..734c295a72 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -51,6 +51,23 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
}
}
+void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, int &r_index) {
+ int child_item_count = p_canvas_item->child_items.size();
+ VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
+ for (int i = 0; i < child_item_count; i++) {
+ if (r_items) {
+ r_items[r_index] = child_items[i];
+ child_items[i]->ysort_xform = p_transform;
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
+ }
+
+ r_index++;
+
+ if (child_items[i]->sort_y)
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index);
+ }
+}
+
void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
Item *ci = p_canvas_item;
@@ -58,10 +75,10 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (!ci->visible)
return;
- if (p_canvas_item->children_order_dirty) {
+ if (ci->children_order_dirty) {
- p_canvas_item->child_items.sort_custom<ItemIndexSort>();
- p_canvas_item->children_order_dirty = false;
+ ci->child_items.sort_custom<ItemIndexSort>();
+ ci->children_order_dirty = false;
}
Rect2 rect = ci->get_rect();
@@ -82,8 +99,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
return;
int child_item_count = ci->child_items.size();
- Item **child_items = (Item **)alloca(child_item_count * sizeof(Item *));
- copymem(child_items, ci->child_items.ptr(), child_item_count * sizeof(Item *));
+ Item **child_items = ci->child_items.ptrw();
if (ci->clip) {
if (p_canvas_clip != NULL) {
@@ -99,6 +115,17 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (ci->sort_y) {
+ if (ci->ysort_children_count == -1) {
+ ci->ysort_children_count = 0;
+ _collect_ysort_children(ci, Transform2D(), NULL, ci->ysort_children_count);
+ }
+
+ child_item_count = ci->ysort_children_count;
+ child_items = (Item **)alloca(child_item_count * sizeof(Item *));
+
+ int i = 0;
+ _collect_ysort_children(ci, Transform2D(), child_items, i);
+
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
}
@@ -110,9 +137,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
for (int i = 0; i < child_item_count; i++) {
- if (!child_items[i]->behind)
+ if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
- _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ if (ci->sort_y) {
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ } else {
+ _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ }
}
if (ci->copy_back_buffer) {
@@ -148,9 +179,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
for (int i = 0; i < child_item_count; i++) {
- if (child_items[i]->behind)
+ if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
- _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ if (ci->sort_y) {
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ } else {
+ _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ }
}
}
@@ -300,6 +335,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
canvas_item->parent = RID();
@@ -319,6 +360,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
item_owner->child_items.push_back(canvas_item);
item_owner->children_order_dirty = true;
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
+
} else {
ERR_EXPLAIN("Invalid parent");
@@ -776,7 +823,7 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID
canvas_item->commands.push_back(m);
}
-void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames) {
+void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -786,8 +833,6 @@ void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles,
part->particles = p_particles;
part->texture = p_texture;
part->normal_map = p_normal;
- part->h_frames = p_h_frames;
- part->v_frames = p_v_frames;
//take the chance and request processing for them, at least once until they become visible again
VSG::storage->particles_request_process(p_particles);
@@ -828,6 +873,7 @@ void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_e
ERR_FAIL_COND(!canvas_item);
canvas_item->sort_y = p_enable;
+ canvas_item->ysort_children_count = -1;
}
void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
@@ -1304,6 +1350,12 @@ bool VisualServerCanvas::free(RID p_rid) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 966b51d341..4b7422b15a 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -48,6 +48,9 @@ public:
bool use_parent_material;
int index;
bool children_order_dirty;
+ int ysort_children_count;
+ Transform2D ysort_xform;
+ Vector2 ysort_pos;
Vector<Item *> child_items;
@@ -61,6 +64,9 @@ public:
use_parent_material = false;
z_relative = true;
index = 0;
+ ysort_children_count = -1;
+ ysort_xform = Transform2D();
+ ysort_pos = Vector2();
}
};
@@ -76,10 +82,10 @@ public:
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
- if (Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON)
- return p_left->xform.elements[2].x < p_right->xform.elements[2].x;
+ if (Math::abs(p_left->ysort_pos.y - p_right->ysort_pos.y) < CMP_EPSILON)
+ return p_left->ysort_pos.x < p_right->ysort_pos.x;
else
- return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
+ return p_left->ysort_pos.y < p_right->ysort_pos.y;
}
};
@@ -186,7 +192,7 @@ public:
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID());
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
- void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames);
+ void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 62ba2eab69..f3a442be99 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -474,7 +474,7 @@ public:
BIND2(viewport_set_transparent_background, RID, bool)
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- BIND3(viewport_set_canvas_layer, RID, RID, int)
+ BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
BIND2(viewport_set_shadow_atlas_size, RID, int)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
@@ -504,14 +504,14 @@ public:
BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
- BIND10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
+ BIND11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
BIND6(environment_set_adjustment, RID, bool, float, float, float, RID)
BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float)
- BIND6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+ BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
BIND5(environment_set_fog_height, RID, bool, float, float, float)
/* SCENARIO API */
@@ -599,7 +599,7 @@ public:
BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID)
BIND4(canvas_item_add_multimesh, RID, RID, RID, RID)
- BIND6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
+ BIND4(canvas_item_add_particles, RID, RID, RID, RID)
BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
BIND2(canvas_item_add_clip_ignore, RID, bool)
BIND2(canvas_item_set_sort_children_by_y, RID, bool)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 654994b83f..1deca7bc66 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -601,8 +601,9 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
Instance *instance = instance_owner.get(p_instance);
ERR_FAIL_COND(!instance);
- if (instance->update_item.in_list()) {
- _update_dirty_instance(instance);
+ if (instance->base_type == VS::INSTANCE_MESH) {
+ //may not have been updated yet
+ instance->materials.resize(VSG::storage->mesh_get_surface_count(instance->base));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
@@ -611,7 +612,7 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
VSG::storage->material_remove_instance_owner(instance->materials[p_surface], instance);
}
instance->materials.write[p_surface] = p_material;
- instance->base_material_changed();
+ instance->base_changed(false, true);
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_add_instance_owner(instance->materials[p_surface], instance);
@@ -839,7 +840,7 @@ void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instanc
ERR_FAIL_COND(!instance);
instance->cast_shadows = p_shadow_casting_setting;
- instance->base_material_changed(); // to actually compute if shadows are visible or not
+ instance->base_changed(false, true); // to actually compute if shadows are visible or not
}
void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
@@ -850,7 +851,7 @@ void VisualServerScene::instance_geometry_set_material_override(RID p_instance,
VSG::storage->material_remove_instance_owner(instance->material_override, instance);
}
instance->material_override = p_material;
- instance->base_material_changed();
+ instance->base_changed(false, true);
if (instance->material_override.is_valid()) {
VSG::storage->material_add_instance_owner(instance->material_override, instance);
@@ -1263,13 +1264,15 @@ void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance)
}
}
-void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
+bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform light_transform = p_instance->transform;
light_transform.orthonormalize(); //scale does not count on lights
+ bool animated_material_found = false;
+
switch (VSG::storage->light_get_type(p_instance->base)) {
case VS::LIGHT_DIRECTIONAL: {
@@ -1302,6 +1305,10 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
continue;
}
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
+
float max, min;
instance->transformed_aabb.project_range_in_plane(base, min, max);
@@ -1557,6 +1564,10 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
+
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1608,6 +1619,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1644,6 +1658,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1654,6 +1671,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
} break;
}
+
+ return animated_material_found;
}
void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
@@ -1893,9 +1912,14 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (ins->base_type == VS::INSTANCE_PARTICLES) {
//particles visible? process them
- VSG::storage->particles_request_process(ins->base);
- //particles visible? request redraw
- VisualServerRaster::redraw_request();
+ if (VSG::storage->particles_is_inactive(ins->base)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ VSG::storage->particles_request_process(ins->base);
+ //particles visible? request redraw
+ VisualServerRaster::redraw_request();
+ }
}
if (geom->lighting_dirty) {
@@ -2095,7 +2119,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (redraw) {
//must redraw!
- _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
}
}
}
@@ -3243,11 +3267,13 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
bool can_cast_shadows = true;
+ bool is_animated = false;
if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) {
can_cast_shadows = false;
} else if (p_instance->material_override.is_valid()) {
can_cast_shadows = VSG::storage->material_casts_shadows(p_instance->material_override);
+ is_animated = VSG::storage->material_is_animated(p_instance->material_override);
} else {
if (p_instance->base_type == VS::INSTANCE_MESH) {
@@ -3262,12 +3288,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
+ } else {
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
@@ -3289,12 +3318,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ } else {
+
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
@@ -3311,6 +3343,10 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
} else {
can_cast_shadows = false;
}
+
+ if (mat.is_valid() && VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
} else if (p_instance->base_type == VS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@@ -3330,12 +3366,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
+ } else {
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
}
@@ -3355,6 +3394,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
geom->can_cast_shadows = can_cast_shadows;
}
+
+ geom->material_is_animated = is_animated;
}
}
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 0d4737f268..38c5258116 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -192,14 +192,9 @@ public:
singleton->instance_set_base(self, RID());
}
- virtual void base_changed() {
+ virtual void base_changed(bool p_aabb, bool p_materials) {
- singleton->_instance_queue_update(this, true, true);
- }
-
- virtual void base_material_changed() {
-
- singleton->_instance_queue_update(this, false, true);
+ singleton->_instance_queue_update(this, p_aabb, p_materials);
}
Instance() :
@@ -247,6 +242,7 @@ public:
List<Instance *> lighting;
bool lighting_dirty;
bool can_cast_shadows;
+ bool material_is_animated;
List<Instance *> reflection_probes;
bool reflection_dirty;
@@ -261,6 +257,7 @@ public:
lighting_dirty = false;
reflection_dirty = true;
can_cast_shadows = true;
+ material_is_animated = true;
gi_probes_dirty = true;
}
};
@@ -488,7 +485,7 @@ public:
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
- _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe);
void _render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index b286533590..571b71db85 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -137,7 +137,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
}
- canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get();
+ canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
}
if (lights_with_shadow) {
@@ -176,7 +176,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VSG::rasterizer->restore_render_target();
- if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer > scenario_canvas_max_layer) {
+ if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
if (!can_draw_3d) {
@@ -209,7 +209,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect);
i++;
- if (scenario_draw_canvas_bg && E->key().layer >= scenario_canvas_max_layer) {
+ if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
if (!can_draw_3d) {
@@ -496,6 +496,7 @@ void VisualServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas)
canvas->viewports.insert(p_viewport);
viewport->canvas_map[p_canvas] = Viewport::CanvasData();
viewport->canvas_map[p_canvas].layer = 0;
+ viewport->canvas_map[p_canvas].sublayer = 0;
viewport->canvas_map[p_canvas].canvas = canvas;
}
@@ -534,13 +535,14 @@ void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,
viewport->global_transform = p_transform;
}
-void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) {
+void VisualServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
viewport->canvas_map[p_canvas].layer = p_layer;
+ viewport->canvas_map[p_canvas].sublayer = p_sublayer;
}
void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index cb7912d6f4..66baa48458 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -78,17 +78,21 @@ public:
struct CanvasKey {
- int layer;
+ int64_t stacking;
RID canvas;
bool operator<(const CanvasKey &p_canvas) const {
- if (layer == p_canvas.layer) return canvas < p_canvas.canvas;
- return layer < p_canvas.layer;
+ if (stacking == p_canvas.stacking)
+ return canvas < p_canvas.canvas;
+ return stacking < p_canvas.stacking;
+ }
+ CanvasKey() {
+ stacking = 0;
}
- CanvasKey() { layer = 0; }
- CanvasKey(const RID &p_canvas, int p_layer) {
+ CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) {
canvas = p_canvas;
- layer = p_layer;
+ stacking = ((int64_t)p_layer << 32) + p_sublayer;
}
+ int get_layer() const { return stacking >> 32; }
};
struct CanvasData {
@@ -96,6 +100,7 @@ public:
CanvasBase *canvas;
Transform2D transform;
int layer;
+ int sublayer;
};
Transform2D global_transform;
@@ -176,7 +181,7 @@ public:
void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
- void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer);
+ void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index e4d69121f0..37f6323b8f 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -400,7 +400,7 @@ public:
FUNC2(viewport_set_transparent_background, RID, bool)
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- FUNC3(viewport_set_canvas_layer, RID, RID, int)
+ FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
FUNC2(viewport_set_shadow_atlas_size, RID, int)
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
@@ -430,14 +430,14 @@ public:
FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
- FUNC10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
+ FUNC11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID)
FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float)
- FUNC6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+ FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
FUNCRID(scenario)
@@ -516,7 +516,7 @@ public:
FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID)
FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID)
- FUNC6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
+ FUNC4(canvas_item_add_particles, RID, RID, RID, RID)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
FUNC2(canvas_item_add_clip_ignore, RID, bool)
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)