summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/camera_2d.cpp9
-rw-r--r--scene/3d/skeleton_ik_3d.cpp15
-rw-r--r--scene/3d/skeleton_ik_3d.h4
-rw-r--r--scene/gui/color_picker.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp41
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/tree.cpp99
-rw-r--r--scene/gui/tree.h8
-rw-r--r--scene/resources/default_theme/default_theme.cpp6
-rw-r--r--scene/resources/sky_material.cpp2
-rw-r--r--scene/resources/visual_shader.cpp147
-rw-r--r--scene/resources/visual_shader.h8
-rw-r--r--scene/resources/visual_shader_nodes.cpp28
-rw-r--r--scene/resources/visual_shader_nodes.h4
14 files changed, 310 insertions, 65 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 01045502d5..ca4b8d72a1 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -270,11 +270,10 @@ void Camera2D::_notification(int p_what) {
}
if (screen_drawing_enabled) {
- Color area_axis_color(0.5, 0.42, 0.87, 0.63);
+ Color area_axis_color(1, 0.4, 1, 0.63);
real_t area_axis_width = 1;
if (is_current()) {
area_axis_width = 3;
- area_axis_color.a = 0.83;
}
Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
@@ -295,10 +294,9 @@ void Camera2D::_notification(int p_what) {
}
if (limit_drawing_enabled) {
- Color limit_drawing_color(1, 1, 0, 0.63);
+ Color limit_drawing_color(1, 1, 0.25, 0.63);
real_t limit_drawing_width = 1;
if (is_current()) {
- limit_drawing_color.a = 0.83;
limit_drawing_width = 3;
}
@@ -317,11 +315,10 @@ void Camera2D::_notification(int p_what) {
}
if (margin_drawing_enabled) {
- Color margin_drawing_color(0, 1, 1, 0.63);
+ Color margin_drawing_color(0.25, 1, 1, 0.63);
real_t margin_drawing_width = 1;
if (is_current()) {
margin_drawing_width = 3;
- margin_drawing_color.a = 0.83;
}
Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index bd1c202205..294e313300 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -129,7 +129,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
return true;
}
-void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
+void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet, Vector3 p_origin_pos) {
real_t distance_to_goal(1e4);
real_t previous_distance_to_goal(0);
int can_solve(p_task->max_iterations);
@@ -138,7 +138,7 @@ void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
--can_solve;
solve_simple_backwards(p_task->chain, p_solve_magnet);
- solve_simple_forwards(p_task->chain, p_solve_magnet);
+ solve_simple_forwards(p_task->chain, p_solve_magnet, p_origin_pos);
distance_to_goal = (p_task->chain.tips[0].chain_item->current_pos - p_task->chain.tips[0].end_effector->goal_transform.origin).length();
}
@@ -176,13 +176,13 @@ void FabrikInverseKinematic::solve_simple_backwards(Chain &r_chain, bool p_solve
}
}
-void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_magnet) {
+void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_magnet, Vector3 p_origin_pos) {
if (p_solve_magnet && !r_chain.middle_chain_item) {
return;
}
ChainItem *sub_chain_root(&r_chain.chain_root);
- Vector3 origin(r_chain.chain_root.initial_transform.origin);
+ Vector3 origin = p_origin_pos;
while (sub_chain_root) { // Reach the tip
sub_chain_root->current_pos = origin;
@@ -273,13 +273,16 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
// Update the initial root transform so its synced with any animation changes
_update_chain(p_task->skeleton, &p_task->chain.chain_root);
+ p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform(), 0.0, false);
+ Vector3 origin_pos = p_task->skeleton->get_bone_global_pose(p_task->chain.chain_root.bone).origin;
+
make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta);
if (p_use_magnet && p_task->chain.middle_chain_item) {
p_task->chain.magnet_position = p_task->chain.middle_chain_item->initial_transform.origin.lerp(p_magnet_position, blending_delta);
- solve_simple(p_task, true);
+ solve_simple(p_task, true, origin_pos);
}
- solve_simple(p_task, false);
+ solve_simple(p_task, false, origin_pos);
// Assign new bone position.
ChainItem *ci(&p_task->chain.chain_root);
diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h
index 9255e18b72..9b5ae240f6 100644
--- a/scene/3d/skeleton_ik_3d.h
+++ b/scene/3d/skeleton_ik_3d.h
@@ -106,10 +106,10 @@ private:
/// Init a chain that starts from the root to tip
static bool build_chain(Task *p_task, bool p_force_simple_chain = true);
- static void solve_simple(Task *p_task, bool p_solve_magnet);
+ static void solve_simple(Task *p_task, bool p_solve_magnet, Vector3 p_origin_pos);
/// Special solvers that solve only chains with one end effector
static void solve_simple_backwards(Chain &r_chain, bool p_solve_magnet);
- static void solve_simple_forwards(Chain &r_chain, bool p_solve_magnet);
+ static void solve_simple_forwards(Chain &r_chain, bool p_solve_magnet, Vector3 p_origin_pos);
public:
static Task *create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform);
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 9ccb2886e1..c0b4563615 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -91,7 +91,6 @@ void ColorPicker::init_shaders() {
wheel_shader.instance();
wheel_shader->set_code(
"shader_type canvas_item;"
- "const float TAU = 6.28318530718;"
"void fragment() {"
" float x = UV.x - 0.5;"
" float y = UV.y - 0.5;"
@@ -111,7 +110,6 @@ void ColorPicker::init_shaders() {
circle_shader.instance();
circle_shader->set_code(
"shader_type canvas_item;"
- "const float TAU = 6.28318530718;"
"uniform float v = 1.0;"
"void fragment() {"
" float x = UV.x - 0.5;"
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 9ed4c937f4..a2c3b4ed8a 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2232,18 +2232,22 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
int size = p_item->subitems.size();
if (size == 0) {
p_item->parent->subitems.erase(p_item);
+ // If a newline was erased, all lines AFTER the newline need to be decremented.
if (p_item->type == ITEM_NEWLINE) {
current_frame->lines.remove(p_line);
- for (int i = p_subitem_line; i < current->subitems.size(); i++) {
- if (current->subitems[i]->line > 0) {
+ for (int i = 0; i < current->subitems.size(); i++) {
+ if (current->subitems[i]->line > p_subitem_line) {
current->subitems[i]->line--;
}
}
}
} else {
+ // First, remove all child items for the provided item.
for (int i = 0; i < size; i++) {
_remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line);
}
+ // Then remove the provided item itself.
+ p_item->parent->subitems.erase(p_item);
}
}
@@ -2303,21 +2307,23 @@ bool RichTextLabel::remove_line(const int p_line) {
return false;
}
- int i = 0;
- while (i < current->subitems.size() && current->subitems[i]->line < p_line) {
- i++;
+ // Remove all subitems with the same line as that provided.
+ Vector<int> subitem_indices_to_remove;
+ for (int i = 0; i < current->subitems.size(); i++) {
+ if (current->subitems[i]->line == p_line) {
+ subitem_indices_to_remove.push_back(i);
+ }
}
- bool was_newline = false;
- while (i < current->subitems.size()) {
- was_newline = current->subitems[i]->type == ITEM_NEWLINE;
- _remove_item(current->subitems[i], current->subitems[i]->line, p_line);
- if (was_newline) {
- break;
- }
+ bool had_newline = false;
+ // Reverse for loop to remove items from the end first.
+ for (int i = subitem_indices_to_remove.size() - 1; i >= 0; i--) {
+ int subitem_idx = subitem_indices_to_remove[i];
+ had_newline = had_newline || current->subitems[subitem_idx]->type == ITEM_NEWLINE;
+ _remove_item(current->subitems[subitem_idx], current->subitems[subitem_idx]->line, p_line);
}
- if (!was_newline) {
+ if (!had_newline) {
current_frame->lines.remove(p_line);
if (current_frame->lines.size() == 0) {
current_frame->lines.resize(1);
@@ -2329,6 +2335,7 @@ bool RichTextLabel::remove_line(const int p_line) {
}
main->first_invalid_line = 0; // p_line ???
+ update();
return true;
}
@@ -2613,14 +2620,6 @@ void RichTextLabel::pop() {
current = current->parent;
}
-// Creates a new line without adding an ItemNewline to the previous line.
-// Useful when wanting to calling remove_line and add a new line immediately after.
-void RichTextLabel::increment_line_count() {
- _validate_line_caches(main);
- current_frame->lines.resize(current_frame->lines.size() + 1);
- _invalidate_current_line(current_frame);
-}
-
void RichTextLabel::clear() {
main->_clear_children();
current = main;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index afc88e070a..e3e457d1f2 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -483,8 +483,6 @@ public:
void push_cell();
void pop();
- void increment_line_count();
-
void clear();
void set_offset(int p_pixel);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 927dce7988..d2b98eb0fa 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1184,15 +1184,23 @@ void Tree::update_cache() {
cache.font_color = get_theme_color("font_color");
cache.font_selected_color = get_theme_color("font_selected_color");
- cache.guide_color = get_theme_color("guide_color");
cache.drop_position_color = get_theme_color("drop_position_color");
cache.hseparation = get_theme_constant("hseparation");
cache.vseparation = get_theme_constant("vseparation");
cache.item_margin = get_theme_constant("item_margin");
cache.button_margin = get_theme_constant("button_margin");
+
cache.draw_guides = get_theme_constant("draw_guides");
+ cache.guide_color = get_theme_color("guide_color");
cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
+ cache.relationship_line_width = get_theme_constant("relationship_line_width");
+ cache.parent_hl_line_width = get_theme_constant("parent_hl_line_width");
+ cache.children_hl_line_width = get_theme_constant("children_hl_line_width");
+ cache.parent_hl_line_margin = get_theme_constant("parent_hl_line_margin");
cache.relationship_line_color = get_theme_color("relationship_line_color");
+ cache.parent_hl_line_color = get_theme_color("parent_hl_line_color");
+ cache.children_hl_line_color = get_theme_color("children_hl_line_color");
+
cache.scroll_border = get_theme_constant("scroll_border");
cache.scroll_speed = get_theme_constant("scroll_speed");
@@ -1813,38 +1821,79 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
TreeItem *c = p_item->first_child;
- int prev_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+ int base_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+ int prev_ofs = base_ofs;
+ int prev_hl_ofs = base_ofs;
while (c) {
if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) {
int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
- int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
+ int parent_ofs = p_pos.x + cache.item_margin;
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
if (c->get_first_child() != nullptr) {
root_pos -= Point2i(cache.arrow->get_width(), 0);
}
- float line_width = 1.0;
+ float line_width = cache.relationship_line_width;
+ float parent_line_width = cache.parent_hl_line_width;
+ float children_line_width = cache.children_hl_line_width;
+
#ifdef TOOLS_ENABLED
line_width *= Math::round(EDSCALE);
+ parent_line_width *= Math::round(EDSCALE);
+ children_line_width *= Math::round(EDSCALE);
#endif
Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
+ int more_prev_ofs = 0;
+
if (root_pos.y + line_width >= 0) {
if (rtl) {
root_pos.x = get_size().width - root_pos.x;
parent_pos.x = get_size().width - parent_pos.x;
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width);
+
+ // Order of parts on this bend: the horizontal line first, then the vertical line.
+ if (_is_branch_selected(c)) {
+ // If this item or one of its children is selected, we draw the line using parent highlight style.
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ more_prev_ofs = cache.parent_hl_line_margin;
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else if (p_item->is_selected(0)) {
+ // If parent item is selected (but this item is not), we draw the line using children highlight style.
+ // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
+ if (_is_sibling_branch_selected(c)) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), cache.children_hl_line_color, children_line_width);
+ }
+ } else {
+ // If nothing of the above is true, we draw the line using normal style.
+ // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
+ if (_is_sibling_branch_selected(c)) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + cache.parent_hl_line_margin, root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), cache.relationship_line_color, line_width);
+ }
+ }
}
if (htotal < 0) {
return -1;
}
- prev_ofs = root_pos.y;
+ prev_ofs = root_pos.y + more_prev_ofs;
}
if (htotal >= 0) {
@@ -1853,10 +1902,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (child_h < 0) {
if (cache.draw_relationship_lines == 0) {
return -1; // break, stop drawing, no need to anymore
- } else {
- htotal = -1;
- children_pos.y = cache.offset.y + p_draw_size.height;
}
+
+ htotal = -1;
+ children_pos.y = cache.offset.y + p_draw_size.height;
} else {
htotal += child_h;
children_pos.y += child_h;
@@ -1889,6 +1938,36 @@ int Tree::_count_selected_items(TreeItem *p_from) const {
return count;
}
+bool Tree::_is_branch_selected(TreeItem *p_from) const {
+ for (int i = 0; i < columns.size(); i++) {
+ if (p_from->is_selected(i)) {
+ return true;
+ }
+ }
+
+ TreeItem *child_item = p_from->get_first_child();
+ while (child_item) {
+ if (_is_branch_selected(child_item)) {
+ return true;
+ }
+ child_item = child_item->get_next();
+ }
+
+ return false;
+}
+
+bool Tree::_is_sibling_branch_selected(TreeItem *p_from) const {
+ TreeItem *sibling_item = p_from->get_next();
+ while (sibling_item) {
+ if (_is_branch_selected(sibling_item)) {
+ return true;
+ }
+ sibling_item = sibling_item->get_next();
+ }
+
+ return false;
+}
+
void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) {
TreeItem::Cell &selected_cell = p_selected->cells.write[p_col];
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 9dbfd93082..c0948f1b80 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -494,6 +494,8 @@ private:
Color guide_color;
Color drop_position_color;
Color relationship_line_color;
+ Color parent_hl_line_color;
+ Color children_hl_line_color;
Color custom_button_font_highlight;
int hseparation = 0;
@@ -502,6 +504,10 @@ private:
int button_margin = 0;
Point2 offset;
int draw_relationship_lines = 0;
+ int relationship_line_width = 0;
+ int parent_hl_line_width = 0;
+ int children_hl_line_width = 0;
+ int parent_hl_line_margin = 0;
int draw_guides = 0;
int scroll_border = 0;
int scroll_speed = 0;
@@ -574,6 +580,8 @@ private:
bool hide_folding = false;
int _count_selected_items(TreeItem *p_from) const;
+ bool _is_branch_selected(TreeItem *p_from) const;
+ bool _is_sibling_branch_selected(TreeItem *p_from) const;
void _go_left();
void _go_right();
void _go_down();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 6e67daf15f..3a5b3534c6 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -719,6 +719,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1));
theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2));
theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27));
+ theme->set_color("parent_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
+ theme->set_color("children_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("custom_button_font_highlight", "Tree", control_font_hover_color);
theme->set_constant("hseparation", "Tree", 4 * scale);
@@ -726,6 +728,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("item_margin", "Tree", 12 * scale);
theme->set_constant("button_margin", "Tree", 4 * scale);
theme->set_constant("draw_relationship_lines", "Tree", 0);
+ theme->set_constant("relationship_line_width", "Tree", 1);
+ theme->set_constant("parent_hl_line_width", "Tree", 1);
+ theme->set_constant("children_hl_line_width", "Tree", 1);
+ theme->set_constant("parent_hl_line_margin", "Tree", 0);
theme->set_constant("draw_guides", "Tree", 1);
theme->set_constant("scroll_border", "Tree", 4);
theme->set_constant("scroll_speed", "Tree", 12);
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index f50ee9c4c8..9d79c22159 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -193,7 +193,6 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
code += "uniform float ground_energy = 1.0;\n\n";
code += "uniform float sun_angle_max = 1.74;\n";
code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n";
- code += "const float PI = 3.1415926535897932384626433833;\n\n";
code += "void sky() {\n";
code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n";
code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n";
@@ -499,7 +498,6 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
code += "uniform sampler2D night_sky : hint_black;";
- code += "const float PI = 3.141592653589793238462643383279502884197169;\n";
code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n";
code += "// Sun constants\n";
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index da29f2ebd8..5ac1ad935e 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -94,6 +94,52 @@ bool VisualShaderNode::is_generate_input_var(int p_port) const {
return true;
}
+bool VisualShaderNode::is_output_port_expandable(int p_port) const {
+ return false;
+}
+
+void VisualShaderNode::_set_output_ports_expanded(const Array &p_values) {
+ for (int i = 0; i < p_values.size(); i++) {
+ expanded_output_ports[p_values[i]] = true;
+ }
+ emit_changed();
+}
+
+Array VisualShaderNode::_get_output_ports_expanded() const {
+ Array arr;
+ for (int i = 0; i < get_output_port_count(); i++) {
+ if (_is_output_port_expanded(i)) {
+ arr.push_back(i);
+ }
+ }
+ return arr;
+}
+
+void VisualShaderNode::_set_output_port_expanded(int p_port, bool p_expanded) {
+ expanded_output_ports[p_port] = p_expanded;
+ emit_changed();
+}
+
+bool VisualShaderNode::_is_output_port_expanded(int p_port) const {
+ if (expanded_output_ports.has(p_port)) {
+ return expanded_output_ports[p_port];
+ }
+ return false;
+}
+
+int VisualShaderNode::get_expanded_output_port_count() const {
+ int count = get_output_port_count();
+ int count2 = count;
+ for (int i = 0; i < count; i++) {
+ if (is_output_port_expandable(i) && _is_output_port_expanded(i)) {
+ if (get_output_port_type(i) == PORT_TYPE_VECTOR) {
+ count2 += 3;
+ }
+ }
+ }
+ return count2;
+}
+
bool VisualShaderNode::is_code_generated() const {
return true;
}
@@ -157,6 +203,12 @@ void VisualShaderNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_output_port_for_preview", "port"), &VisualShaderNode::set_output_port_for_preview);
ClassDB::bind_method(D_METHOD("get_output_port_for_preview"), &VisualShaderNode::get_output_port_for_preview);
+ ClassDB::bind_method(D_METHOD("_set_output_port_expanded", "port"), &VisualShaderNode::_set_output_port_expanded);
+ ClassDB::bind_method(D_METHOD("_is_output_port_expanded"), &VisualShaderNode::_is_output_port_expanded);
+
+ ClassDB::bind_method(D_METHOD("_set_output_ports_expanded", "values"), &VisualShaderNode::_set_output_ports_expanded);
+ ClassDB::bind_method(D_METHOD("_get_output_ports_expanded"), &VisualShaderNode::_get_output_ports_expanded);
+
ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value);
ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value);
@@ -165,6 +217,7 @@ void VisualShaderNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded");
ADD_SIGNAL(MethodInfo("editor_refresh_request"));
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
@@ -576,7 +629,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
return false;
}
- if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_output_port_count()) {
+ if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_expanded_output_port_count()) {
return false;
}
@@ -617,7 +670,7 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from
Graph *g = &graph[p_type];
ERR_FAIL_COND(!g->nodes.has(p_from_node));
- ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_output_port_count());
+ ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count());
ERR_FAIL_COND(!g->nodes.has(p_to_node));
ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count());
@@ -639,7 +692,7 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
Graph *g = &graph[p_type];
ERR_FAIL_COND_V(!g->nodes.has(p_from_node), ERR_INVALID_PARAMETER);
- ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_output_port_count(), ERR_INVALID_PARAMETER);
+ ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!g->nodes.has(p_to_node), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_to_port, g->nodes[p_to_node].node->get_input_port_count(), ERR_INVALID_PARAMETER);
@@ -790,7 +843,7 @@ bool VisualShader::is_text_shader() const {
String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &default_tex_params) const {
Ref<VisualShaderNode> node = get_node(p_type, p_node);
ERR_FAIL_COND_V(!node.is_valid(), String());
- ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_output_port_count(), String());
+ ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_expanded_output_port_count(), String());
ERR_FAIL_COND_V(node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_TRANSFORM, String());
StringBuilder global_code;
@@ -1362,13 +1415,30 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
}
int output_count = vsnode->get_output_port_count();
+ int initial_output_count = output_count;
+
+ Map<int, bool> expanded_output_ports;
+
+ for (int i = 0; i < initial_output_count; i++) {
+ bool expanded = false;
+
+ if (vsnode->is_output_port_expandable(i) && vsnode->_is_output_port_expanded(i)) {
+ expanded = true;
+
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ output_count += 3;
+ }
+ }
+ expanded_output_ports.insert(i, expanded);
+ }
+
Vector<String> output_vars;
- output_vars.resize(vsnode->get_output_port_count());
+ output_vars.resize(output_count);
String *outputs = output_vars.ptrw();
if (vsnode->is_simple_decl()) { // less code to generate for some simple_decl nodes
- for (int i = 0; i < output_count; i++) {
- String var_name = "n_out" + itos(node) + "p" + itos(i);
+ for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
+ String var_name = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
outputs[i] = "float " + var_name;
@@ -1388,35 +1458,84 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
default: {
}
}
+ if (expanded_output_ports[i]) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ j += 3;
+ }
+ }
}
} else {
- for (int i = 0; i < output_count; i++) {
- outputs[i] = "n_out" + itos(node) + "p" + itos(i);
+ for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
+ outputs[i] = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
- code += String() + "\tfloat " + outputs[i] + ";\n";
+ code += "\tfloat " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
- code += String() + "\tint " + outputs[i] + ";\n";
+ code += "\tint " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_VECTOR:
- code += String() + "\tvec3 " + outputs[i] + ";\n";
+ code += "\tvec3 " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
- code += String() + "\tbool " + outputs[i] + ";\n";
+ code += "\tbool " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_TRANSFORM:
- code += String() + "\tmat4 " + outputs[i] + ";\n";
+ code += "\tmat4 " + outputs[i] + ";\n";
break;
default: {
}
}
+ if (expanded_output_ports[i]) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ j += 3;
+ }
+ }
}
}
code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
+ for (int i = 0; i < output_count; i++) {
+ bool new_line_inserted = false;
+ if (expanded_output_ports[i]) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String r = "n_out" + itos(node) + "p" + itos(i + 1);
+ code += "\tfloat " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
+ outputs[i + 1] = r;
+ }
+
+ if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String g = "n_out" + itos(node) + "p" + itos(i + 2);
+ code += "\tfloat " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
+ outputs[i + 2] = g;
+ }
+
+ if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String b = "n_out" + itos(node) + "p" + itos(i + 3);
+ code += "\tfloat " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
+ outputs[i + 3] = b;
+ }
+
+ i += 3;
+ }
+ }
+ }
+
code += "\n"; //
processed.insert(node);
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 841672294e..cc9a867e64 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -199,6 +199,7 @@ class VisualShaderNode : public Resource {
Map<int, Variant> default_input_values;
Map<int, bool> connected_input_ports;
Map<int, int> connected_output_ports;
+ Map<int, bool> expanded_output_ports;
protected:
bool simple_decl = true;
@@ -245,6 +246,13 @@ public:
void set_input_port_connected(int p_port, bool p_connected);
virtual bool is_generate_input_var(int p_port) const;
+ virtual bool is_output_port_expandable(int p_port) const;
+ void _set_output_ports_expanded(const Array &p_data);
+ Array _get_output_ports_expanded() const;
+ void _set_output_port_expanded(int p_port, bool p_expanded);
+ bool _is_output_port_expanded(int p_port) const;
+ int get_expanded_output_port_count() const;
+
virtual bool is_code_generated() const;
virtual bool is_show_prop_names() const;
virtual bool is_use_prop_slots() const;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index c2a6ad72d7..314333158c 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -242,6 +242,13 @@ String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const {
return p_port == 0 ? "" : "alpha"; //no output port means the editor will be used as port
}
+bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
String VisualShaderNodeColorConstant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String code;
code += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n";
@@ -455,6 +462,13 @@ String VisualShaderNodeTexture::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
+bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "default";
@@ -917,6 +931,13 @@ String VisualShaderNodeSample3D::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
+bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "default";
@@ -1168,6 +1189,13 @@ String VisualShaderNodeCubemap::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
+bool VisualShaderNodeCubemap::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubemap::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
VisualShader::DefaultTextureParam dtp;
dtp.name = make_unique_id(p_type, p_id, "cube");
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index d3397fad6f..50329d122d 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -163,6 +163,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@@ -275,6 +276,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual String get_input_port_default_hint(int p_port) const override;
@@ -359,6 +361,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@@ -452,6 +455,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;