summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/SCsub1
-rw-r--r--scene/animation/animation_player.cpp87
-rw-r--r--scene/animation/animation_player.h26
-rw-r--r--scene/gui/file_dialog.cpp87
-rw-r--r--scene/gui/file_dialog.h8
-rw-r--r--scene/gui/item_list.cpp27
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/gui/text_edit.cpp38
-rw-r--r--scene/gui/tree.cpp25
-rw-r--r--scene/gui/tree.h2
-rw-r--r--scene/gui/video_player.cpp1
-rw-r--r--scene/main/scene_tree.cpp10
-rw-r--r--scene/main/scene_tree.h3
-rw-r--r--scene/resources/material.cpp6
14 files changed, 283 insertions, 40 deletions
diff --git a/scene/SCsub b/scene/SCsub
index 513adeffda..bec1b40ed6 100644
--- a/scene/SCsub
+++ b/scene/SCsub
@@ -31,6 +31,7 @@ SConscript('resources/SCsub')
# Build it all as a library
lib = env.Library("scene", env.scene_sources)
+env.NoCache(lib)
env.Prepend(LIBS=[lib])
Export('env')
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 010f5a586f..206f3ccca2 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -33,6 +33,17 @@
#include "message_queue.h"
#include "scene/scene_string_names.h"
+#ifdef TOOLS_ENABLED
+void AnimatedValuesBackup::update_skeletons() {
+
+ for (int i = 0; i < entries.size(); i++) {
+ if (entries[i].bone_idx != -1) {
+ Object::cast_to<Skeleton>(entries[i].object)->notification(Skeleton::NOTIFICATION_UPDATE_SKELETON);
+ }
+ }
+}
+#endif
+
bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
@@ -228,7 +239,11 @@ void AnimationPlayer::_notification(int p_what) {
}
}
-void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
+void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
+
+ // Already cached?
+ if (p_anim->node_cache.size() == p_anim->animation->get_track_count())
+ return;
Node *parent = get_node(root);
@@ -336,11 +351,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete) {
- if (p_anim->node_cache.size() != p_anim->animation->get_track_count()) {
- // animation hasn't been "node-cached"
- _generate_node_caches(p_anim);
- }
-
+ _ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
Animation *a = p_anim->animation.operator->();
@@ -1205,6 +1216,70 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i
Node::get_argument_options(p_function, p_idx, r_options);
}
+#ifdef TOOLS_ENABLED
+AnimatedValuesBackup AnimationPlayer::backup_animated_values() {
+
+ if (!playback.current.from)
+ return AnimatedValuesBackup();
+
+ _ensure_node_caches(playback.current.from);
+
+ AnimatedValuesBackup backup;
+
+ for (int i = 0; i < playback.current.from->node_cache.size(); i++) {
+ TrackNodeCache *nc = playback.current.from->node_cache[i];
+ if (!nc)
+ continue;
+
+ if (nc->skeleton) {
+ if (nc->bone_idx == -1)
+ continue;
+
+ AnimatedValuesBackup::Entry entry;
+ entry.object = nc->skeleton;
+ entry.bone_idx = nc->bone_idx;
+ entry.value = nc->skeleton->get_bone_pose(nc->bone_idx);
+ backup.entries.push_back(entry);
+ } else {
+ if (nc->spatial) {
+ AnimatedValuesBackup::Entry entry;
+ entry.object = nc->spatial;
+ entry.subpath.push_back("transform");
+ entry.value = nc->spatial->get_transform();
+ entry.bone_idx = -1;
+ backup.entries.push_back(entry);
+ } else {
+ for (Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.front(); E; E = E->next()) {
+ AnimatedValuesBackup::Entry entry;
+ entry.object = E->value().object;
+ entry.subpath = E->value().subpath;
+ bool valid;
+ entry.value = E->value().object->get_indexed(E->value().subpath, &valid);
+ entry.bone_idx = -1;
+ if (valid)
+ backup.entries.push_back(entry);
+ }
+ }
+ }
+ }
+
+ return backup;
+}
+
+void AnimationPlayer::restore_animated_values(const AnimatedValuesBackup &p_backup) {
+
+ for (int i = 0; i < p_backup.entries.size(); i++) {
+
+ const AnimatedValuesBackup::Entry *entry = &p_backup.entries[i];
+ if (entry->bone_idx == -1) {
+ entry->object->set_indexed(entry->subpath, entry->value);
+ } else {
+ Object::cast_to<Skeleton>(entry->object)->set_bone_pose(entry->bone_idx, entry->value);
+ }
+ }
+}
+#endif
+
void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("_node_removed"), &AnimationPlayer::_node_removed);
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index e4e021c7fe..e39afcf199 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -38,6 +38,24 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+#ifdef TOOLS_ENABLED
+// To save/restore animated values
+class AnimatedValuesBackup {
+ struct Entry {
+ Object *object;
+ Vector<StringName> subpath; // Unused if bone
+ int bone_idx; // -1 if not a bone
+ Variant value;
+ };
+ Vector<Entry> entries;
+
+ friend class AnimationPlayer;
+
+public:
+ void update_skeletons();
+};
+#endif
+
class AnimationPlayer : public Node {
GDCLASS(AnimationPlayer, Node);
OBJ_CATEGORY("Animation Nodes");
@@ -198,7 +216,7 @@ private:
void _animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete = true);
- void _generate_node_caches(AnimationData *p_anim);
+ void _ensure_node_caches(AnimationData *p_anim);
void _animation_process_data(PlaybackData &cd, float p_delta, float p_blend);
void _animation_process2(float p_delta);
void _animation_update_transforms();
@@ -291,6 +309,12 @@ public:
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
+#ifdef TOOLS_ENABLED
+ // These may be interesting for games, but are too dangerous for general use
+ AnimatedValuesBackup backup_animated_values();
+ void restore_animated_values(const AnimatedValuesBackup &p_backup);
+#endif
+
AnimationPlayer();
~AnimationPlayer();
};
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 6aba535572..9bfb70bf42 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -47,6 +47,7 @@ void FileDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
refresh->set_icon(get_icon("reload"));
+ dir_up->set_icon(get_icon("ArrowUp", "EditorIcons"));
}
if (p_what == NOTIFICATION_DRAW) {
@@ -85,6 +86,10 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
invalidate();
} break;
+ case KEY_BACKSPACE: {
+
+ _dir_entered("..");
+ } break;
default: { handled = false; }
}
@@ -118,6 +123,9 @@ void FileDialog::update_dir() {
if (drives->is_visible()) {
drives->select(dir_access->get_current_drive());
}
+
+ // Deselect any item, to make "Select Current Folder" button text by default.
+ deselect_items();
}
void FileDialog::_dir_entered(String p_dir) {
@@ -152,6 +160,10 @@ void FileDialog::_post_popup() {
tree->grab_focus();
set_process_unhandled_input(true);
+
+ // For open dir mode, deselect all items on file dialog open.
+ if (mode == MODE_OPEN_DIR)
+ deselect_items();
}
void FileDialog::_action_pressed() {
@@ -189,7 +201,7 @@ void FileDialog::_action_pressed() {
TreeItem *item = tree->get_selected();
if (item) {
Dictionary d = item->get_metadata(0);
- if (d["dir"]) {
+ if (d["dir"] && d["name"] != "..") {
path = path.plus_file(d["name"]);
}
}
@@ -272,6 +284,57 @@ void FileDialog::_cancel_pressed() {
hide();
}
+bool FileDialog::_is_open_should_be_disabled() {
+
+ if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE)
+ return false;
+
+ TreeItem *ti = tree->get_selected();
+ // We have something that we can't select?
+ if (!ti)
+ return true;
+
+ Dictionary d = ti->get_metadata(0);
+
+ // Opening a file, but selected a folder? Forbidden.
+ if (((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden.
+ (mode == MODE_OPEN_DIR && !d["dir"]))
+ return true;
+
+ return false;
+}
+
+void FileDialog::_go_up() {
+
+ dir_access->change_dir("..");
+ update_file_list();
+ update_dir();
+}
+
+void FileDialog::deselect_items() {
+
+ // Clear currently selected items in file manager.
+ tree->deselect_all();
+
+ // And change get_ok title.
+ if (!tree->is_anything_selected()) {
+ get_ok()->set_disabled(_is_open_should_be_disabled());
+
+ switch (mode) {
+
+ case MODE_OPEN_FILE:
+ case MODE_OPEN_FILES:
+ get_ok()->set_text(TTR("Open"));
+ get_ok()->set_disabled(false);
+ break;
+
+ case MODE_OPEN_DIR:
+ get_ok()->set_text(TTR("Select Current Folder"));
+ get_ok()->set_disabled(false);
+ break;
+ }
+ }
+}
void FileDialog::_tree_selected() {
TreeItem *ti = tree->get_selected();
@@ -282,7 +345,11 @@ void FileDialog::_tree_selected() {
if (!d["dir"]) {
file->set_text(d["name"]);
+ } else if (mode == MODE_OPEN_DIR) {
+ get_ok()->set_text(TTR("Select this Folder"));
}
+
+ get_ok()->set_disabled(_is_open_should_be_disabled());
}
void FileDialog::_tree_dc_selected() {
@@ -323,7 +390,7 @@ void FileDialog::update_file_list() {
while ((item = dir_access->get_next(&isdir)) != "") {
- if (item == ".")
+ if (item == "." || item == "..")
continue;
ishidden = dir_access->current_is_hidden();
@@ -336,11 +403,6 @@ void FileDialog::update_file_list() {
}
}
- if (dirs.find("..") == NULL) {
- //may happen if lacking permissions
- dirs.push_back("..");
- }
-
dirs.sort_custom<NaturalNoCaseComparator>();
files.sort_custom<NaturalNoCaseComparator>();
@@ -563,7 +625,7 @@ void FileDialog::set_mode(Mode p_mode) {
makedir->hide();
break;
case MODE_OPEN_DIR:
- get_ok()->set_text(RTR("Open"));
+ get_ok()->set_text(RTR("Select Current Folder"));
set_title(RTR("Open a Directory"));
makedir->show();
break;
@@ -716,6 +778,8 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileDialog::_make_dir_confirm);
ClassDB::bind_method(D_METHOD("_update_file_list"), &FileDialog::update_file_list);
ClassDB::bind_method(D_METHOD("_update_dir"), &FileDialog::update_dir);
+ ClassDB::bind_method(D_METHOD("_go_up"), &FileDialog::_go_up);
+ ClassDB::bind_method(D_METHOD("deselect_items"), &FileDialog::deselect_items);
ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate);
@@ -763,6 +827,12 @@ FileDialog::FileDialog() {
set_title(RTR("Save a File"));
HBoxContainer *hbc = memnew(HBoxContainer);
+
+ dir_up = memnew(ToolButton);
+ dir_up->set_tooltip(TTR("Go to parent folder"));
+ hbc->add_child(dir_up);
+ dir_up->connect("pressed", this, "_go_up");
+
hbc->add_child(memnew(Label(RTR("Path:"))));
dir = memnew(LineEdit);
hbc->add_child(dir);
@@ -807,6 +877,7 @@ FileDialog::FileDialog() {
//cancel->connect("pressed", this,"_cancel_pressed");
tree->connect("cell_selected", this, "_tree_selected", varray(), CONNECT_DEFERRED);
tree->connect("item_activated", this, "_tree_db_selected", varray());
+ tree->connect("nothing_selected", this, "deselect_items");
dir->connect("text_entered", this, "_dir_entered");
file->connect("text_entered", this, "_file_entered");
filter->connect("item_selected", this, "_filter_selected");
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 34cecfe4d0..ca3d9f54b2 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -33,7 +33,6 @@
#include "box_container.h"
#include "os/dir_access.h"
#include "scene/gui/dialogs.h"
-#include "scene/gui/dialogs.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
#include "scene/gui/tool_button.h"
@@ -87,6 +86,8 @@ private:
DirAccess *dir_access;
ConfirmationDialog *confirm_save;
+ ToolButton *dir_up;
+
ToolButton *refresh;
Vector<String> filters;
@@ -112,11 +113,14 @@ private:
void _filter_selected(int);
void _make_dir();
void _make_dir_confirm();
+ void _go_up();
void _update_drives();
void _unhandled_input(const Ref<InputEvent> &p_event);
+ bool _is_open_should_be_disabled();
+
virtual void _post_popup();
protected:
@@ -155,6 +159,8 @@ public:
void invalidate();
+ void deselect_items();
+
FileDialog();
~FileDialog();
};
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 51ab49e643..197e474fd6 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -257,6 +257,20 @@ void ItemList::unselect(int p_idx) {
}
update();
}
+
+void ItemList::unselect_all() {
+
+ if (items.size() < 1)
+ return;
+
+ for (int i = 0; i < items.size(); i++) {
+
+ items[i].selected = false;
+ }
+
+ update();
+}
+
bool ItemList::is_selected(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), false);
@@ -530,6 +544,9 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
+
+ // Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting.
+ emit_signal("nothing_selected");
}
if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
@@ -1249,6 +1266,15 @@ Vector<int> ItemList::get_selected_items() {
return selected;
}
+bool ItemList::is_anything_selected() {
+ for (int i = 0; i < items.size(); i++) {
+ if (items[i].selected)
+ return true;
+ }
+
+ return false;
+}
+
void ItemList::_set_items(const Array &p_items) {
ERR_FAIL_COND(p_items.size() % 3);
@@ -1409,6 +1435,7 @@ void ItemList::_bind_methods() {
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected")));
ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index")));
ADD_SIGNAL(MethodInfo("rmb_clicked", PropertyInfo(Variant::VECTOR2, "at_position")));
+ ADD_SIGNAL(MethodInfo("nothing_selected"));
GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000);
}
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index ccdd705325..b1e1e5eeb0 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -156,8 +156,10 @@ public:
void select(int p_idx, bool p_single = true);
void unselect(int p_idx);
+ void unselect_all();
bool is_selected(int p_idx) const;
Vector<int> get_selected_items();
+ bool is_anything_selected();
void set_current(int p_current);
int get_current() const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index b5e809fd03..166b55d6f3 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1712,12 +1712,12 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
rows -= cache.style_normal->get_margin(MARGIN_TOP);
rows /= get_row_height();
int lsp = get_line_scroll_pos(true);
- int row = cursor.line_ofs + (rows + (v_scroll->get_value() - lsp));
+ int row = cursor.line_ofs + (rows + (round(v_scroll->get_value()) - lsp));
if (is_hiding_enabled()) {
// row will be offset by the hidden rows
int f_ofs = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(rows + 1, text.size() - cursor.line_ofs)) - 1;
- row = cursor.line_ofs + (f_ofs + (v_scroll->get_value() - lsp));
+ row = cursor.line_ofs + (f_ofs + (round(v_scroll->get_value()) - lsp));
row = CLAMP(row, 0, text.size() - num_lines_from(text.size() - 1, -1));
}
@@ -3475,11 +3475,13 @@ void TextEdit::adjust_viewport_to_cursor() {
int num_rows = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(visible_rows, text.size() - 1 - cursor.line_ofs));
// make sure the cursor is on the screen
+ // above the caret
if (cursor.line > (cursor.line_ofs + MAX(num_rows, visible_rows))) {
cursor.line_ofs = cursor.line - num_lines_from(cursor.line, -visible_rows) + 1;
}
- if (cursor.line < cursor.line_ofs) {
- cursor.line_ofs = cursor.line;
+ // below the caret
+ if (cursor.line_ofs == cursor.line) {
+ cursor.line_ofs = cursor.line - 2;
}
int line_ofs_max = text.size() - 1;
if (!scroll_past_end_of_file_enabled) {
@@ -3499,17 +3501,17 @@ void TextEdit::adjust_viewport_to_cursor() {
if (cursor_x < cursor.x_ofs)
cursor.x_ofs = cursor_x;
+ updating_scrolls = true;
h_scroll->set_value(cursor.x_ofs);
update_line_scroll_pos();
- v_scroll->set_value(get_line_scroll_pos());
+ double new_v_scroll = get_line_scroll_pos();
+ // keep offset if smooth scroll is enabled
+ if (smooth_scroll_enabled) {
+ new_v_scroll += fmod(v_scroll->get_value(), 1.0);
+ }
+ v_scroll->set_value(new_v_scroll);
+ updating_scrolls = false;
update();
- /*
- get_range()->set_max(text.size());
-
- get_range()->set_page(get_visible_rows());
-
- get_range()->set((int)cursor.line_ofs);
-*/
}
void TextEdit::center_viewport_to_cursor() {
@@ -3540,10 +3542,16 @@ void TextEdit::center_viewport_to_cursor() {
if (cursor_x < cursor.x_ofs)
cursor.x_ofs = cursor_x;
+ updating_scrolls = true;
h_scroll->set_value(cursor.x_ofs);
update_line_scroll_pos();
- v_scroll->set_value(get_line_scroll_pos());
-
+ double new_v_scroll = get_line_scroll_pos();
+ // keep offset if smooth scroll is enabled
+ if (smooth_scroll_enabled) {
+ new_v_scroll += fmod(v_scroll->get_value(), 1.0);
+ }
+ v_scroll->set_value(new_v_scroll);
+ updating_scrolls = false;
update();
}
@@ -3666,7 +3674,7 @@ void TextEdit::_scroll_moved(double p_to_val) {
cursor.x_ofs = h_scroll->get_value();
if (v_scroll->is_visible_in_tree()) {
double val = v_scroll->get_value();
- cursor.line_ofs = num_lines_from(0, (int)floor(val)) - 1;
+ cursor.line_ofs = num_lines_from(0, (int)floor(val));
line_scroll_pos = (int)floor(val);
}
update();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 9213296c55..ab12d123ba 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2599,6 +2599,11 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (drag_touching) {
set_physics_process(true);
}
+
+ if (b->get_button_index() == BUTTON_LEFT) {
+ if (get_item_at_position(b->get_position()) == NULL && !b->get_shift() && !b->get_control() && !b->get_command())
+ emit_signal("nothing_selected");
+ }
}
} break;
@@ -3043,6 +3048,25 @@ void Tree::set_select_mode(SelectMode p_mode) {
select_mode = p_mode;
}
+void Tree::deselect_all() {
+
+ TreeItem *item = get_next_selected(get_root());
+ while (item) {
+ item->deselect(selected_col);
+ item = get_next_selected(get_root());
+ }
+
+ selected_item = NULL;
+ selected_col = -1;
+
+ update();
+}
+
+bool Tree::is_anything_selected() {
+
+ return (selected_item != NULL);
+}
+
void Tree::clear() {
if (blocked > 0) {
@@ -3750,6 +3774,7 @@ void Tree::_bind_methods() {
ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked")));
ADD_SIGNAL(MethodInfo("item_activated"));
ADD_SIGNAL(MethodInfo("column_title_pressed", PropertyInfo(Variant::INT, "column")));
+ ADD_SIGNAL(MethodInfo("nothing_selected"));
BIND_ENUM_CONSTANT(SELECT_SINGLE);
BIND_ENUM_CONSTANT(SELECT_ROW);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 64d6016942..112de3165f 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -546,6 +546,8 @@ public:
int get_selected_column() const;
int get_pressed_button() const;
void set_select_mode(SelectMode p_mode);
+ void deselect_all();
+ bool is_anything_selected();
void set_columns(int p_columns);
int get_columns() const;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index c7157d539d..8f567f9796 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -490,6 +490,7 @@ VideoPlayer::VideoPlayer() {
expand = true;
audio_track = 0;
+ bus_index = 0;
buffering_ms = 500;
server_mix_rate = 44100;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 17abf2425a..f74bf161f0 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -127,7 +127,7 @@ void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) {
group_map.erase(E);
}
-void SceneTree::_flush_transform_notifications() {
+void SceneTree::flush_transform_notifications() {
SelfList<Node> *n = xform_change_list.first();
while (n) {
@@ -448,7 +448,7 @@ bool SceneTree::iteration(float p_time) {
current_frame++;
- _flush_transform_notifications();
+ flush_transform_notifications();
MainLoop::iteration(p_time);
physics_process_time = p_time;
@@ -459,7 +459,7 @@ bool SceneTree::iteration(float p_time) {
_notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
- _flush_transform_notifications();
+ flush_transform_notifications();
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
root_lock--;
@@ -487,7 +487,7 @@ bool SceneTree::idle(float p_time) {
MessageQueue::get_singleton()->flush(); //small little hack
- _flush_transform_notifications();
+ flush_transform_notifications();
_notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
_notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS);
@@ -503,7 +503,7 @@ bool SceneTree::idle(float p_time) {
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
- _flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
+ flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
root_lock--;
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index bc3efdc42f..7898dc065a 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -157,7 +157,6 @@ private:
Map<UGCall, Vector<Variant> > unique_group_calls;
bool ugc_locked;
void _flush_ugc();
- void _flush_transform_notifications();
_FORCE_INLINE_ void _update_group_order(Group &g);
void _update_listener();
@@ -344,6 +343,8 @@ public:
void notify_group(const StringName &p_group, int p_notification);
void set_group(const StringName &p_group, const String &p_name, const Variant &p_value);
+ void flush_transform_notifications();
+
virtual void input_text(const String &p_text);
virtual void input_event(const Ref<InputEvent> &p_event);
virtual void init();
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 286840656b..79f642a09b 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -653,16 +653,16 @@ void SpatialMaterial::_update_shader() {
code += "\t\tvec2 P = view_dir.xy * depth_scale;\n";
code += "\t\tvec2 delta = P / num_layers;\n";
code += "\t\tvec2 ofs = base_uv;\n";
- code += "\t\tfloat depth = texture(texture_depth, ofs).r;\n";
+ code += "\t\tfloat depth = textureLod(texture_depth, ofs,0.0).r;\n";
code += "\t\tfloat current_depth = 0.0;\n";
code += "\t\twhile(current_depth < depth) {\n";
code += "\t\t\tofs -= delta;\n";
- code += "\t\t\tdepth = texture(texture_depth, ofs).r;\n";
+ code += "\t\t\tdepth = textureLod(texture_depth, ofs,0.0).r;\n";
code += "\t\t\tcurrent_depth += layer_depth;\n";
code += "\t\t}\n";
code += "\t\tvec2 prev_ofs = ofs + delta;\n";
code += "\t\tfloat after_depth = depth - current_depth;\n";
- code += "\t\tfloat before_depth = texture(texture_depth, prev_ofs).r - current_depth + layer_depth;\n";
+ code += "\t\tfloat before_depth = textureLod(texture_depth, prev_ofs, 0.0).r - current_depth + layer_depth;\n";
code += "\t\tfloat weight = after_depth / (after_depth - before_depth);\n";
code += "\t\tofs = mix(ofs,prev_ofs,weight);\n";