Implement global and per instance shader uniforms.
Adds two keywords to shader language for uniforms: -'global' -'instance' This allows them to reference values outside the material.
This commit is contained in:
parent
30ab5c9baa
commit
0e1c66d9fc
|
@ -66,6 +66,11 @@ Size2 EditorProperty::get_minimum_size() const {
|
||||||
ms.width += key->get_width() + get_theme_constant("hseparator", "Tree");
|
ms.width += key->get_width() + get_theme_constant("hseparator", "Tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deletable) {
|
||||||
|
Ref<Texture2D> key = get_theme_icon("Close", "EditorIcons");
|
||||||
|
ms.width += key->get_width() + get_theme_constant("hseparator", "Tree");
|
||||||
|
}
|
||||||
|
|
||||||
if (checkable) {
|
if (checkable) {
|
||||||
Ref<Texture2D> check = get_theme_icon("checked", "CheckBox");
|
Ref<Texture2D> check = get_theme_icon("checked", "CheckBox");
|
||||||
ms.width += check->get_width() + get_theme_constant("hseparation", "CheckBox") + get_theme_constant("hseparator", "Tree");
|
ms.width += check->get_width() + get_theme_constant("hseparation", "CheckBox") + get_theme_constant("hseparator", "Tree");
|
||||||
|
@ -154,6 +159,18 @@ void EditorProperty::_notification(int p_what) {
|
||||||
text_size -= key->get_width() + 4 * EDSCALE;
|
text_size -= key->get_width() + 4 * EDSCALE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deletable) {
|
||||||
|
Ref<Texture2D> close;
|
||||||
|
|
||||||
|
close = get_theme_icon("Close", "EditorIcons");
|
||||||
|
|
||||||
|
rect.size.x -= close->get_width() + get_theme_constant("hseparator", "Tree");
|
||||||
|
|
||||||
|
if (no_children) {
|
||||||
|
text_size -= close->get_width() + 4 * EDSCALE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//set children
|
//set children
|
||||||
|
@ -278,6 +295,25 @@ void EditorProperty::_notification(int p_what) {
|
||||||
} else {
|
} else {
|
||||||
keying_rect = Rect2();
|
keying_rect = Rect2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deletable) {
|
||||||
|
Ref<Texture2D> close;
|
||||||
|
|
||||||
|
close = get_theme_icon("Close", "EditorIcons");
|
||||||
|
|
||||||
|
ofs = size.width - close->get_width() - get_theme_constant("hseparator", "Tree");
|
||||||
|
|
||||||
|
Color color2(1, 1, 1);
|
||||||
|
if (delete_hover) {
|
||||||
|
color2.r *= 1.2;
|
||||||
|
color2.g *= 1.2;
|
||||||
|
color2.b *= 1.2;
|
||||||
|
}
|
||||||
|
delete_rect = Rect2(ofs, ((size.height - close->get_height()) / 2), close->get_width(), close->get_height());
|
||||||
|
draw_texture(close, delete_rect.position, color2);
|
||||||
|
} else {
|
||||||
|
delete_rect = Rect2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,6 +583,16 @@ void EditorProperty::set_keying(bool p_keying) {
|
||||||
queue_sort();
|
queue_sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorProperty::set_deletable(bool p_deletable) {
|
||||||
|
deletable = p_deletable;
|
||||||
|
update();
|
||||||
|
queue_sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditorProperty::is_deletable() const {
|
||||||
|
return deletable;
|
||||||
|
}
|
||||||
|
|
||||||
bool EditorProperty::is_keying() const {
|
bool EditorProperty::is_keying() const {
|
||||||
return keying;
|
return keying;
|
||||||
}
|
}
|
||||||
|
@ -619,6 +665,12 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool new_delete_hover = delete_rect.has_point(me->get_position()) && !button_left;
|
||||||
|
if (new_delete_hover != delete_hover) {
|
||||||
|
delete_hover = new_delete_hover;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
bool new_revert_hover = revert_rect.has_point(me->get_position()) && !button_left;
|
bool new_revert_hover = revert_rect.has_point(me->get_position()) && !button_left;
|
||||||
if (new_revert_hover != revert_hover) {
|
if (new_revert_hover != revert_hover) {
|
||||||
revert_hover = new_revert_hover;
|
revert_hover = new_revert_hover;
|
||||||
|
@ -662,6 +714,9 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
|
||||||
call_deferred("update_property");
|
call_deferred("update_property");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (delete_rect.has_point(mb->get_position())) {
|
||||||
|
emit_signal("property_deleted", property);
|
||||||
|
}
|
||||||
|
|
||||||
if (revert_rect.has_point(mb->get_position())) {
|
if (revert_rect.has_point(mb->get_position())) {
|
||||||
|
|
||||||
|
@ -821,6 +876,9 @@ void EditorProperty::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_keying", "keying"), &EditorProperty::set_keying);
|
ClassDB::bind_method(D_METHOD("set_keying", "keying"), &EditorProperty::set_keying);
|
||||||
ClassDB::bind_method(D_METHOD("is_keying"), &EditorProperty::is_keying);
|
ClassDB::bind_method(D_METHOD("is_keying"), &EditorProperty::is_keying);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_deletable", "deletable"), &EditorProperty::set_deletable);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_deletable"), &EditorProperty::is_deletable);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_edited_property"), &EditorProperty::get_edited_property);
|
ClassDB::bind_method(D_METHOD("get_edited_property"), &EditorProperty::get_edited_property);
|
||||||
ClassDB::bind_method(D_METHOD("get_edited_object"), &EditorProperty::get_edited_object);
|
ClassDB::bind_method(D_METHOD("get_edited_object"), &EditorProperty::get_edited_object);
|
||||||
|
|
||||||
|
@ -839,9 +897,11 @@ void EditorProperty::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "checked"), "set_checked", "is_checked");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "checked"), "set_checked", "is_checked");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_red"), "set_draw_red", "is_draw_red");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_red"), "set_draw_red", "is_draw_red");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keying"), "set_keying", "is_keying");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keying"), "set_keying", "is_keying");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deletable"), "set_deletable", "is_deletable");
|
||||||
ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
|
ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
|
||||||
ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::PACKED_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value")));
|
ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::PACKED_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value")));
|
||||||
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING_NAME, "property")));
|
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING_NAME, "property")));
|
||||||
|
ADD_SIGNAL(MethodInfo("property_deleted", PropertyInfo(Variant::STRING_NAME, "property")));
|
||||||
ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
|
ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
|
||||||
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::STRING, "bool")));
|
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::STRING, "bool")));
|
||||||
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
|
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
|
||||||
|
@ -865,6 +925,7 @@ EditorProperty::EditorProperty() {
|
||||||
checked = false;
|
checked = false;
|
||||||
draw_red = false;
|
draw_red = false;
|
||||||
keying = false;
|
keying = false;
|
||||||
|
deletable = false;
|
||||||
keying_hover = false;
|
keying_hover = false;
|
||||||
revert_hover = false;
|
revert_hover = false;
|
||||||
check_hover = false;
|
check_hover = false;
|
||||||
|
@ -926,7 +987,7 @@ void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_par
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorInspectorPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
|
bool EditorInspectorPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
|
||||||
|
|
||||||
if (get_script_instance()) {
|
if (get_script_instance()) {
|
||||||
Variant arg[6] = {
|
Variant arg[6] = {
|
||||||
|
@ -1276,11 +1337,11 @@ EditorInspectorSection::~EditorInspectorSection() {
|
||||||
Ref<EditorInspectorPlugin> EditorInspector::inspector_plugins[MAX_PLUGINS];
|
Ref<EditorInspectorPlugin> EditorInspector::inspector_plugins[MAX_PLUGINS];
|
||||||
int EditorInspector::inspector_plugin_count = 0;
|
int EditorInspector::inspector_plugin_count = 0;
|
||||||
|
|
||||||
EditorProperty *EditorInspector::instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
|
EditorProperty *EditorInspector::instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
|
||||||
|
|
||||||
for (int i = inspector_plugin_count - 1; i >= 0; i--) {
|
for (int i = inspector_plugin_count - 1; i >= 0; i--) {
|
||||||
|
|
||||||
inspector_plugins[i]->parse_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage);
|
inspector_plugins[i]->parse_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide);
|
||||||
if (inspector_plugins[i]->added_editors.size()) {
|
if (inspector_plugins[i]->added_editors.size()) {
|
||||||
for (int j = 1; j < inspector_plugins[i]->added_editors.size(); j++) { //only keep first one
|
for (int j = 1; j < inspector_plugins[i]->added_editors.size(); j++) { //only keep first one
|
||||||
memdelete(inspector_plugins[i]->added_editors[j].property_editor);
|
memdelete(inspector_plugins[i]->added_editors[j].property_editor);
|
||||||
|
@ -1362,6 +1423,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
|
||||||
ep->object = object;
|
ep->object = object;
|
||||||
ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed));
|
ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed));
|
||||||
ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed));
|
ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed));
|
||||||
|
ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED);
|
||||||
ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value));
|
ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value));
|
||||||
ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked));
|
ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked));
|
||||||
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
|
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
|
||||||
|
@ -1394,6 +1456,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
|
||||||
ep->set_read_only(read_only);
|
ep->set_read_only(read_only);
|
||||||
ep->update_property();
|
ep->update_property();
|
||||||
ep->update_reload_status();
|
ep->update_reload_status();
|
||||||
|
ep->set_deletable(deletable_properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ped->added_editors.clear();
|
ped->added_editors.clear();
|
||||||
|
@ -1762,7 +1825,7 @@ void EditorInspector::update_tree() {
|
||||||
|
|
||||||
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
||||||
Ref<EditorInspectorPlugin> ped = E->get();
|
Ref<EditorInspectorPlugin> ped = E->get();
|
||||||
bool exclusive = ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage);
|
bool exclusive = ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage, wide_editors);
|
||||||
|
|
||||||
List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector
|
List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector
|
||||||
ped->added_editors.clear();
|
ped->added_editors.clear();
|
||||||
|
@ -1806,6 +1869,7 @@ void EditorInspector::update_tree() {
|
||||||
ep->set_keying(keying);
|
ep->set_keying(keying);
|
||||||
|
|
||||||
ep->set_read_only(read_only);
|
ep->set_read_only(read_only);
|
||||||
|
ep->set_deletable(deletable_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_vbox->add_child(F->get().property_editor);
|
current_vbox->add_child(F->get().property_editor);
|
||||||
|
@ -1817,6 +1881,7 @@ void EditorInspector::update_tree() {
|
||||||
ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed_update_all), varray(), CONNECT_DEFERRED);
|
ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed_update_all), varray(), CONNECT_DEFERRED);
|
||||||
}
|
}
|
||||||
ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed));
|
ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed));
|
||||||
|
ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED);
|
||||||
ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value));
|
ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value));
|
||||||
ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked));
|
ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked));
|
||||||
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
|
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
|
||||||
|
@ -2000,6 +2065,10 @@ int EditorInspector::get_scroll_offset() const {
|
||||||
return get_v_scroll();
|
return get_v_scroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorInspector::set_use_wide_editors(bool p_enable) {
|
||||||
|
wide_editors = p_enable;
|
||||||
|
}
|
||||||
|
|
||||||
void EditorInspector::set_sub_inspector(bool p_enable) {
|
void EditorInspector::set_sub_inspector(bool p_enable) {
|
||||||
|
|
||||||
sub_inspector = p_enable;
|
sub_inspector = p_enable;
|
||||||
|
@ -2013,6 +2082,10 @@ void EditorInspector::set_sub_inspector(bool p_enable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorInspector::set_use_deletable_properties(bool p_enabled) {
|
||||||
|
deletable_properties = p_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
void EditorInspector::_edit_request_change(Object *p_object, const String &p_property) {
|
void EditorInspector::_edit_request_change(Object *p_object, const String &p_property) {
|
||||||
|
|
||||||
if (object != p_object) //may be undoing/redoing for a non edited object, so ignore
|
if (object != p_object) //may be undoing/redoing for a non edited object, so ignore
|
||||||
|
@ -2145,6 +2218,15 @@ void EditorInspector::_property_keyed(const String &p_path, bool p_advance) {
|
||||||
emit_signal("property_keyed", p_path, object->get(p_path), p_advance); //second param is deprecated
|
emit_signal("property_keyed", p_path, object->get(p_path), p_advance); //second param is deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorInspector::_property_deleted(const String &p_path) {
|
||||||
|
|
||||||
|
print_line("deleted pressed?");
|
||||||
|
if (!object)
|
||||||
|
return;
|
||||||
|
|
||||||
|
emit_signal("property_deleted", p_path); //second param is deprecated
|
||||||
|
}
|
||||||
|
|
||||||
void EditorInspector::_property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance) {
|
void EditorInspector::_property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance) {
|
||||||
|
|
||||||
if (!object)
|
if (!object)
|
||||||
|
@ -2348,6 +2430,7 @@ void EditorInspector::_bind_methods() {
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("property_selected", PropertyInfo(Variant::STRING, "property")));
|
ADD_SIGNAL(MethodInfo("property_selected", PropertyInfo(Variant::STRING, "property")));
|
||||||
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property")));
|
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property")));
|
||||||
|
ADD_SIGNAL(MethodInfo("property_deleted", PropertyInfo(Variant::STRING, "property")));
|
||||||
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "res"), PropertyInfo(Variant::STRING, "prop")));
|
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "res"), PropertyInfo(Variant::STRING, "prop")));
|
||||||
ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::INT, "id")));
|
ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::INT, "id")));
|
||||||
ADD_SIGNAL(MethodInfo("property_edited", PropertyInfo(Variant::STRING, "property")));
|
ADD_SIGNAL(MethodInfo("property_edited", PropertyInfo(Variant::STRING, "property")));
|
||||||
|
@ -2365,6 +2448,7 @@ EditorInspector::EditorInspector() {
|
||||||
set_enable_h_scroll(false);
|
set_enable_h_scroll(false);
|
||||||
set_enable_v_scroll(true);
|
set_enable_v_scroll(true);
|
||||||
|
|
||||||
|
wide_editors = false;
|
||||||
show_categories = false;
|
show_categories = false;
|
||||||
hide_script = true;
|
hide_script = true;
|
||||||
use_doc_hints = false;
|
use_doc_hints = false;
|
||||||
|
@ -2383,6 +2467,7 @@ EditorInspector::EditorInspector() {
|
||||||
set_process(true);
|
set_process(true);
|
||||||
property_focusable = -1;
|
property_focusable = -1;
|
||||||
sub_inspector = false;
|
sub_inspector = false;
|
||||||
|
deletable_properties = false;
|
||||||
|
|
||||||
get_v_scrollbar()->connect("value_changed", callable_mp(this, &EditorInspector::_vscroll_changed));
|
get_v_scrollbar()->connect("value_changed", callable_mp(this, &EditorInspector::_vscroll_changed));
|
||||||
update_scroll_request = -1;
|
update_scroll_request = -1;
|
||||||
|
|
|
@ -64,6 +64,7 @@ private:
|
||||||
bool checked;
|
bool checked;
|
||||||
bool draw_red;
|
bool draw_red;
|
||||||
bool keying;
|
bool keying;
|
||||||
|
bool deletable;
|
||||||
|
|
||||||
Rect2 right_child_rect;
|
Rect2 right_child_rect;
|
||||||
Rect2 bottom_child_rect;
|
Rect2 bottom_child_rect;
|
||||||
|
@ -74,6 +75,8 @@ private:
|
||||||
bool revert_hover;
|
bool revert_hover;
|
||||||
Rect2 check_rect;
|
Rect2 check_rect;
|
||||||
bool check_hover;
|
bool check_hover;
|
||||||
|
Rect2 delete_rect;
|
||||||
|
bool delete_hover;
|
||||||
|
|
||||||
bool can_revert;
|
bool can_revert;
|
||||||
|
|
||||||
|
@ -133,6 +136,8 @@ public:
|
||||||
void set_keying(bool p_keying);
|
void set_keying(bool p_keying);
|
||||||
bool is_keying() const;
|
bool is_keying() const;
|
||||||
|
|
||||||
|
void set_deletable(bool p_enable);
|
||||||
|
bool is_deletable() const;
|
||||||
void add_focusable(Control *p_control);
|
void add_focusable(Control *p_control);
|
||||||
void select(int p_focusable = -1);
|
void select(int p_focusable = -1);
|
||||||
void deselect();
|
void deselect();
|
||||||
|
@ -190,7 +195,7 @@ public:
|
||||||
virtual bool can_handle(Object *p_object);
|
virtual bool can_handle(Object *p_object);
|
||||||
virtual void parse_begin(Object *p_object);
|
virtual void parse_begin(Object *p_object);
|
||||||
virtual void parse_category(Object *p_object, const String &p_parse_category);
|
virtual void parse_category(Object *p_object, const String &p_parse_category);
|
||||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
|
||||||
virtual void parse_end();
|
virtual void parse_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,6 +288,8 @@ class EditorInspector : public ScrollContainer {
|
||||||
bool read_only;
|
bool read_only;
|
||||||
bool keying;
|
bool keying;
|
||||||
bool sub_inspector;
|
bool sub_inspector;
|
||||||
|
bool wide_editors;
|
||||||
|
bool deletable_properties;
|
||||||
|
|
||||||
float refresh_countdown;
|
float refresh_countdown;
|
||||||
bool update_tree_pending;
|
bool update_tree_pending;
|
||||||
|
@ -307,6 +314,7 @@ class EditorInspector : public ScrollContainer {
|
||||||
void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
|
void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
|
||||||
void _property_keyed(const String &p_path, bool p_advance);
|
void _property_keyed(const String &p_path, bool p_advance);
|
||||||
void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance);
|
void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance);
|
||||||
|
void _property_deleted(const String &p_path);
|
||||||
|
|
||||||
void _property_checked(const String &p_path, bool p_checked);
|
void _property_checked(const String &p_path, bool p_checked);
|
||||||
|
|
||||||
|
@ -337,7 +345,7 @@ public:
|
||||||
static void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
|
static void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
|
||||||
static void cleanup_plugins();
|
static void cleanup_plugins();
|
||||||
|
|
||||||
static EditorProperty *instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
static EditorProperty *instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
|
||||||
|
|
||||||
void set_undo_redo(UndoRedo *p_undo_redo);
|
void set_undo_redo(UndoRedo *p_undo_redo);
|
||||||
|
|
||||||
|
@ -380,8 +388,11 @@ public:
|
||||||
void set_object_class(const String &p_class);
|
void set_object_class(const String &p_class);
|
||||||
String get_object_class() const;
|
String get_object_class() const;
|
||||||
|
|
||||||
|
void set_use_wide_editors(bool p_enable);
|
||||||
void set_sub_inspector(bool p_enable);
|
void set_sub_inspector(bool p_enable);
|
||||||
|
|
||||||
|
void set_use_deletable_properties(bool p_enabled);
|
||||||
|
|
||||||
EditorInspector();
|
EditorInspector();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -708,6 +708,11 @@ void EditorNode::_sources_changed(bool p_exist) {
|
||||||
if (waiting_for_first_scan) {
|
if (waiting_for_first_scan) {
|
||||||
waiting_for_first_scan = false;
|
waiting_for_first_scan = false;
|
||||||
|
|
||||||
|
// Reload the global shader variables, but this time
|
||||||
|
// loading texures, as they are now properly imported.
|
||||||
|
print_line("done scanning, reload textures");
|
||||||
|
RenderingServer::get_singleton()->global_variables_load_settings(true);
|
||||||
|
|
||||||
// Start preview thread now that it's safe.
|
// Start preview thread now that it's safe.
|
||||||
if (!singleton->cmdline_export_mode) {
|
if (!singleton->cmdline_export_mode) {
|
||||||
EditorResourcePreview::get_singleton()->start();
|
EditorResourcePreview::get_singleton()->start();
|
||||||
|
|
|
@ -1150,12 +1150,15 @@ void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPropertyVector2::EditorPropertyVector2() {
|
EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) {
|
||||||
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector2_editing");
|
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector2_editing");
|
||||||
|
|
||||||
BoxContainer *bc;
|
BoxContainer *bc;
|
||||||
|
|
||||||
if (horizontal) {
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
bc = memnew(HBoxContainer);
|
bc = memnew(HBoxContainer);
|
||||||
add_child(bc);
|
add_child(bc);
|
||||||
set_bottom_editor(bc);
|
set_bottom_editor(bc);
|
||||||
|
@ -1231,13 +1234,16 @@ void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPropertyRect2::EditorPropertyRect2() {
|
EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) {
|
||||||
|
|
||||||
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
bool horizontal = !p_force_wide && bool(EDITOR_GET("interface/inspector/horizontal_vector_types_editing"));
|
||||||
|
|
||||||
BoxContainer *bc;
|
BoxContainer *bc;
|
||||||
|
|
||||||
if (horizontal) {
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
bc = memnew(HBoxContainer);
|
bc = memnew(HBoxContainer);
|
||||||
add_child(bc);
|
add_child(bc);
|
||||||
set_bottom_editor(bc);
|
set_bottom_editor(bc);
|
||||||
|
@ -1311,12 +1317,15 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPropertyVector3::EditorPropertyVector3() {
|
EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) {
|
||||||
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
||||||
|
|
||||||
BoxContainer *bc;
|
BoxContainer *bc;
|
||||||
|
|
||||||
if (horizontal) {
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
bc = memnew(HBoxContainer);
|
bc = memnew(HBoxContainer);
|
||||||
add_child(bc);
|
add_child(bc);
|
||||||
set_bottom_editor(bc);
|
set_bottom_editor(bc);
|
||||||
|
@ -1343,6 +1352,255 @@ EditorPropertyVector3::EditorPropertyVector3() {
|
||||||
}
|
}
|
||||||
setting = false;
|
setting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////// VECTOR2i /////////////////////////
|
||||||
|
|
||||||
|
void EditorPropertyVector2i::_value_changed(double val, const String &p_name) {
|
||||||
|
if (setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector2i v2;
|
||||||
|
v2.x = spin[0]->get_value();
|
||||||
|
v2.y = spin[1]->get_value();
|
||||||
|
emit_changed(get_edited_property(), v2, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyVector2i::update_property() {
|
||||||
|
Vector2i val = get_edited_object()->get(get_edited_property());
|
||||||
|
setting = true;
|
||||||
|
spin[0]->set_value(val.x);
|
||||||
|
spin[1]->set_value(val.y);
|
||||||
|
setting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyVector2i::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||||
|
Color base = get_theme_color("accent_color", "Editor");
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
|
||||||
|
Color c = base;
|
||||||
|
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
|
||||||
|
spin[i]->set_custom_label_color(true, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyVector2i::_bind_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider) {
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
spin[i]->set_min(p_min);
|
||||||
|
spin[i]->set_max(p_max);
|
||||||
|
spin[i]->set_step(1);
|
||||||
|
spin[i]->set_hide_slider(p_no_slider);
|
||||||
|
spin[i]->set_allow_greater(true);
|
||||||
|
spin[i]->set_allow_lesser(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) {
|
||||||
|
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector2_editing");
|
||||||
|
|
||||||
|
BoxContainer *bc;
|
||||||
|
|
||||||
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
set_bottom_editor(bc);
|
||||||
|
} else {
|
||||||
|
bc = memnew(VBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *desc[2] = { "x", "y" };
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
spin[i] = memnew(EditorSpinSlider);
|
||||||
|
spin[i]->set_flat(true);
|
||||||
|
spin[i]->set_label(desc[i]);
|
||||||
|
bc->add_child(spin[i]);
|
||||||
|
add_focusable(spin[i]);
|
||||||
|
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2i::_value_changed), varray(desc[i]));
|
||||||
|
if (horizontal) {
|
||||||
|
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!horizontal) {
|
||||||
|
set_label_reference(spin[0]); //show text and buttons around this
|
||||||
|
}
|
||||||
|
setting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////// RECT2 /////////////////////////
|
||||||
|
|
||||||
|
void EditorPropertyRect2i::_value_changed(double val, const String &p_name) {
|
||||||
|
if (setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Rect2i r2;
|
||||||
|
r2.position.x = spin[0]->get_value();
|
||||||
|
r2.position.y = spin[1]->get_value();
|
||||||
|
r2.size.x = spin[2]->get_value();
|
||||||
|
r2.size.y = spin[3]->get_value();
|
||||||
|
emit_changed(get_edited_property(), r2, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyRect2i::update_property() {
|
||||||
|
Rect2i val = get_edited_object()->get(get_edited_property());
|
||||||
|
setting = true;
|
||||||
|
spin[0]->set_value(val.position.x);
|
||||||
|
spin[1]->set_value(val.position.y);
|
||||||
|
spin[2]->set_value(val.size.x);
|
||||||
|
spin[3]->set_value(val.size.y);
|
||||||
|
setting = false;
|
||||||
|
}
|
||||||
|
void EditorPropertyRect2i::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||||
|
Color base = get_theme_color("accent_color", "Editor");
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
|
||||||
|
Color c = base;
|
||||||
|
c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
|
||||||
|
spin[i]->set_custom_label_color(true, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void EditorPropertyRect2i::_bind_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider) {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
spin[i]->set_min(p_min);
|
||||||
|
spin[i]->set_max(p_max);
|
||||||
|
spin[i]->set_step(1);
|
||||||
|
spin[i]->set_hide_slider(p_no_slider);
|
||||||
|
spin[i]->set_allow_greater(true);
|
||||||
|
spin[i]->set_allow_lesser(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) {
|
||||||
|
|
||||||
|
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
||||||
|
|
||||||
|
BoxContainer *bc;
|
||||||
|
|
||||||
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
set_bottom_editor(bc);
|
||||||
|
} else {
|
||||||
|
bc = memnew(VBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *desc[4] = { "x", "y", "w", "h" };
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
spin[i] = memnew(EditorSpinSlider);
|
||||||
|
spin[i]->set_label(desc[i]);
|
||||||
|
spin[i]->set_flat(true);
|
||||||
|
bc->add_child(spin[i]);
|
||||||
|
add_focusable(spin[i]);
|
||||||
|
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2i::_value_changed), varray(desc[i]));
|
||||||
|
if (horizontal) {
|
||||||
|
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!horizontal) {
|
||||||
|
set_label_reference(spin[0]); //show text and buttons around this
|
||||||
|
}
|
||||||
|
setting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////// VECTOR3 /////////////////////////
|
||||||
|
|
||||||
|
void EditorPropertyVector3i::_value_changed(double val, const String &p_name) {
|
||||||
|
if (setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector3i v3;
|
||||||
|
v3.x = spin[0]->get_value();
|
||||||
|
v3.y = spin[1]->get_value();
|
||||||
|
v3.z = spin[2]->get_value();
|
||||||
|
emit_changed(get_edited_property(), v3, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyVector3i::update_property() {
|
||||||
|
Vector3i val = get_edited_object()->get(get_edited_property());
|
||||||
|
setting = true;
|
||||||
|
spin[0]->set_value(val.x);
|
||||||
|
spin[1]->set_value(val.y);
|
||||||
|
spin[2]->set_value(val.z);
|
||||||
|
setting = false;
|
||||||
|
}
|
||||||
|
void EditorPropertyVector3i::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||||
|
Color base = get_theme_color("accent_color", "Editor");
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
|
||||||
|
Color c = base;
|
||||||
|
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
|
||||||
|
spin[i]->set_custom_label_color(true, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void EditorPropertyVector3i::_bind_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
spin[i]->set_min(p_min);
|
||||||
|
spin[i]->set_max(p_max);
|
||||||
|
spin[i]->set_step(1);
|
||||||
|
spin[i]->set_hide_slider(p_no_slider);
|
||||||
|
spin[i]->set_allow_greater(true);
|
||||||
|
spin[i]->set_allow_lesser(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) {
|
||||||
|
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
||||||
|
|
||||||
|
BoxContainer *bc;
|
||||||
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
set_bottom_editor(bc);
|
||||||
|
} else {
|
||||||
|
bc = memnew(VBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *desc[3] = { "x", "y", "z" };
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
spin[i] = memnew(EditorSpinSlider);
|
||||||
|
spin[i]->set_flat(true);
|
||||||
|
spin[i]->set_label(desc[i]);
|
||||||
|
bc->add_child(spin[i]);
|
||||||
|
add_focusable(spin[i]);
|
||||||
|
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3i::_value_changed), varray(desc[i]));
|
||||||
|
if (horizontal) {
|
||||||
|
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!horizontal) {
|
||||||
|
set_label_reference(spin[0]); //show text and buttons around this
|
||||||
|
}
|
||||||
|
setting = false;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////// PLANE /////////////////////////
|
///////////////////// PLANE /////////////////////////
|
||||||
|
|
||||||
void EditorPropertyPlane::_value_changed(double val, const String &p_name) {
|
void EditorPropertyPlane::_value_changed(double val, const String &p_name) {
|
||||||
|
@ -1391,13 +1649,16 @@ void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPropertyPlane::EditorPropertyPlane() {
|
EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) {
|
||||||
|
|
||||||
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
|
||||||
|
|
||||||
BoxContainer *bc;
|
BoxContainer *bc;
|
||||||
|
|
||||||
if (horizontal) {
|
if (p_force_wide) {
|
||||||
|
bc = memnew(HBoxContainer);
|
||||||
|
add_child(bc);
|
||||||
|
} else if (horizontal) {
|
||||||
bc = memnew(HBoxContainer);
|
bc = memnew(HBoxContainer);
|
||||||
add_child(bc);
|
add_child(bc);
|
||||||
set_bottom_editor(bc);
|
set_bottom_editor(bc);
|
||||||
|
@ -2877,7 +3138,7 @@ void EditorInspectorDefaultPlugin::parse_begin(Object *p_object) {
|
||||||
//do none
|
//do none
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
|
bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
|
||||||
|
|
||||||
float default_float_step = EDITOR_GET("interface/inspector/default_float_step");
|
float default_float_step = EDITOR_GET("interface/inspector/default_float_step");
|
||||||
|
|
||||||
|
@ -3083,7 +3344,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
|
||||||
// math types
|
// math types
|
||||||
|
|
||||||
case Variant::VECTOR2: {
|
case Variant::VECTOR2: {
|
||||||
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2);
|
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2(p_wide));
|
||||||
double min = -65535, max = 65535, step = default_float_step;
|
double min = -65535, max = 65535, step = default_float_step;
|
||||||
bool hide_slider = true;
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
@ -3099,9 +3360,24 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
|
||||||
editor->setup(min, max, step, hide_slider);
|
editor->setup(min, max, step, hide_slider);
|
||||||
add_property_editor(p_path, editor);
|
add_property_editor(p_path, editor);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case Variant::VECTOR2I: {
|
||||||
|
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide));
|
||||||
|
int min = -65535, max = 65535;
|
||||||
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
|
||||||
|
min = p_hint_text.get_slice(",", 0).to_double();
|
||||||
|
max = p_hint_text.get_slice(",", 1).to_double();
|
||||||
|
hide_slider = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor->setup(min, max, hide_slider);
|
||||||
|
add_property_editor(p_path, editor);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::RECT2: {
|
case Variant::RECT2: {
|
||||||
EditorPropertyRect2 *editor = memnew(EditorPropertyRect2);
|
EditorPropertyRect2 *editor = memnew(EditorPropertyRect2(p_wide));
|
||||||
double min = -65535, max = 65535, step = default_float_step;
|
double min = -65535, max = 65535, step = default_float_step;
|
||||||
bool hide_slider = true;
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
@ -3117,8 +3393,22 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
|
||||||
editor->setup(min, max, step, hide_slider);
|
editor->setup(min, max, step, hide_slider);
|
||||||
add_property_editor(p_path, editor);
|
add_property_editor(p_path, editor);
|
||||||
} break;
|
} break;
|
||||||
|
case Variant::RECT2I: {
|
||||||
|
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide));
|
||||||
|
int min = -65535, max = 65535;
|
||||||
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
|
||||||
|
min = p_hint_text.get_slice(",", 0).to_double();
|
||||||
|
max = p_hint_text.get_slice(",", 1).to_double();
|
||||||
|
hide_slider = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor->setup(min, max, hide_slider);
|
||||||
|
add_property_editor(p_path, editor);
|
||||||
|
} break;
|
||||||
case Variant::VECTOR3: {
|
case Variant::VECTOR3: {
|
||||||
EditorPropertyVector3 *editor = memnew(EditorPropertyVector3);
|
EditorPropertyVector3 *editor = memnew(EditorPropertyVector3(p_wide));
|
||||||
double min = -65535, max = 65535, step = default_float_step;
|
double min = -65535, max = 65535, step = default_float_step;
|
||||||
bool hide_slider = true;
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
@ -3134,6 +3424,22 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
|
||||||
editor->setup(min, max, step, hide_slider);
|
editor->setup(min, max, step, hide_slider);
|
||||||
add_property_editor(p_path, editor);
|
add_property_editor(p_path, editor);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case Variant::VECTOR3I: {
|
||||||
|
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide));
|
||||||
|
int min = -65535, max = 65535;
|
||||||
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
|
||||||
|
min = p_hint_text.get_slice(",", 0).to_double();
|
||||||
|
max = p_hint_text.get_slice(",", 1).to_double();
|
||||||
|
|
||||||
|
hide_slider = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor->setup(min, max, hide_slider);
|
||||||
|
add_property_editor(p_path, editor);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::TRANSFORM2D: {
|
case Variant::TRANSFORM2D: {
|
||||||
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
|
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
|
||||||
|
@ -3154,7 +3460,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::PLANE: {
|
case Variant::PLANE: {
|
||||||
EditorPropertyPlane *editor = memnew(EditorPropertyPlane);
|
EditorPropertyPlane *editor = memnew(EditorPropertyPlane(p_wide));
|
||||||
double min = -65535, max = 65535, step = default_float_step;
|
double min = -65535, max = 65535, step = default_float_step;
|
||||||
bool hide_slider = true;
|
bool hide_slider = true;
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual void update_property();
|
virtual void update_property();
|
||||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||||
EditorPropertyVector2();
|
EditorPropertyVector2(bool p_force_wide = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditorPropertyRect2 : public EditorProperty {
|
class EditorPropertyRect2 : public EditorProperty {
|
||||||
|
@ -377,7 +377,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual void update_property();
|
virtual void update_property();
|
||||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||||
EditorPropertyRect2();
|
EditorPropertyRect2(bool p_force_wide = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditorPropertyVector3 : public EditorProperty {
|
class EditorPropertyVector3 : public EditorProperty {
|
||||||
|
@ -393,7 +393,55 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual void update_property();
|
virtual void update_property();
|
||||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||||
EditorPropertyVector3();
|
EditorPropertyVector3(bool p_force_wide = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditorPropertyVector2i : public EditorProperty {
|
||||||
|
GDCLASS(EditorPropertyVector2i, EditorProperty);
|
||||||
|
EditorSpinSlider *spin[2];
|
||||||
|
bool setting;
|
||||||
|
void _value_changed(double p_val, const String &p_name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int p_what);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void update_property();
|
||||||
|
void setup(int p_min, int p_max, bool p_no_slider);
|
||||||
|
EditorPropertyVector2i(bool p_force_wide = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditorPropertyRect2i : public EditorProperty {
|
||||||
|
GDCLASS(EditorPropertyRect2i, EditorProperty);
|
||||||
|
EditorSpinSlider *spin[4];
|
||||||
|
bool setting;
|
||||||
|
void _value_changed(double p_val, const String &p_name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int p_what);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void update_property();
|
||||||
|
void setup(int p_min, int p_max, bool p_no_slider);
|
||||||
|
EditorPropertyRect2i(bool p_force_wide = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditorPropertyVector3i : public EditorProperty {
|
||||||
|
GDCLASS(EditorPropertyVector3i, EditorProperty);
|
||||||
|
EditorSpinSlider *spin[3];
|
||||||
|
bool setting;
|
||||||
|
void _value_changed(double p_val, const String &p_name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int p_what);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void update_property();
|
||||||
|
void setup(int p_min, int p_max, bool p_no_slider);
|
||||||
|
EditorPropertyVector3i(bool p_force_wide = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditorPropertyPlane : public EditorProperty {
|
class EditorPropertyPlane : public EditorProperty {
|
||||||
|
@ -409,7 +457,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual void update_property();
|
virtual void update_property();
|
||||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
|
||||||
EditorPropertyPlane();
|
EditorPropertyPlane(bool p_force_wide = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditorPropertyQuat : public EditorProperty {
|
class EditorPropertyQuat : public EditorProperty {
|
||||||
|
@ -626,7 +674,7 @@ class EditorInspectorDefaultPlugin : public EditorInspectorPlugin {
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(Object *p_object);
|
virtual bool can_handle(Object *p_object);
|
||||||
virtual void parse_begin(Object *p_object);
|
virtual void parse_begin(Object *p_object);
|
||||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
|
||||||
virtual void parse_end();
|
virtual void parse_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -741,6 +741,13 @@ void EditorPropertyDictionary::update_property() {
|
||||||
editor->setup(-100000, 100000, 0.001, true);
|
editor->setup(-100000, 100000, 0.001, true);
|
||||||
prop = editor;
|
prop = editor;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case Variant::VECTOR2I: {
|
||||||
|
|
||||||
|
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i);
|
||||||
|
editor->setup(-100000, 100000, true);
|
||||||
|
prop = editor;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::RECT2: {
|
case Variant::RECT2: {
|
||||||
|
|
||||||
|
@ -748,6 +755,13 @@ void EditorPropertyDictionary::update_property() {
|
||||||
editor->setup(-100000, 100000, 0.001, true);
|
editor->setup(-100000, 100000, 0.001, true);
|
||||||
prop = editor;
|
prop = editor;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case Variant::RECT2I: {
|
||||||
|
|
||||||
|
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i);
|
||||||
|
editor->setup(-100000, 100000, true);
|
||||||
|
prop = editor;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::VECTOR3: {
|
case Variant::VECTOR3: {
|
||||||
|
|
||||||
|
@ -755,6 +769,13 @@ void EditorPropertyDictionary::update_property() {
|
||||||
editor->setup(-100000, 100000, 0.001, true);
|
editor->setup(-100000, 100000, 0.001, true);
|
||||||
prop = editor;
|
prop = editor;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case Variant::VECTOR3I: {
|
||||||
|
|
||||||
|
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i);
|
||||||
|
editor->setup(-100000, 100000, true);
|
||||||
|
prop = editor;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::TRANSFORM2D: {
|
case Variant::TRANSFORM2D: {
|
||||||
|
|
||||||
|
|
|
@ -288,7 +288,7 @@ void EditorInspectorRootMotionPlugin::parse_begin(Object *p_object) {
|
||||||
//do none
|
//do none
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
|
bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
|
||||||
|
|
||||||
if (p_path == "root_motion_track" && p_object->is_class("AnimationTree") && p_type == Variant::NODE_PATH) {
|
if (p_path == "root_motion_track" && p_object->is_class("AnimationTree") && p_type == Variant::NODE_PATH) {
|
||||||
EditorPropertyRootMotion *editor = memnew(EditorPropertyRootMotion);
|
EditorPropertyRootMotion *editor = memnew(EditorPropertyRootMotion);
|
||||||
|
|
|
@ -65,7 +65,7 @@ class EditorInspectorRootMotionPlugin : public EditorInspectorPlugin {
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(Object *p_object);
|
virtual bool can_handle(Object *p_object);
|
||||||
virtual void parse_begin(Object *p_object);
|
virtual void parse_begin(Object *p_object);
|
||||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
|
||||||
virtual void parse_end();
|
virtual void parse_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,12 @@ void ShaderTextEditor::_check_shader_mode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) {
|
||||||
|
|
||||||
|
RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable);
|
||||||
|
return RS::global_variable_type_get_shader_datatype(gvt);
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options) {
|
void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options) {
|
||||||
|
|
||||||
_check_shader_mode();
|
_check_shader_mode();
|
||||||
|
@ -200,7 +206,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo
|
||||||
ShaderLanguage sl;
|
ShaderLanguage sl;
|
||||||
String calltip;
|
String calltip;
|
||||||
|
|
||||||
sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), r_options, calltip);
|
sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip);
|
||||||
|
|
||||||
get_text_edit()->set_code_hint(calltip);
|
get_text_edit()->set_code_hint(calltip);
|
||||||
}
|
}
|
||||||
|
@ -215,7 +221,7 @@ void ShaderTextEditor::_validate_script() {
|
||||||
|
|
||||||
ShaderLanguage sl;
|
ShaderLanguage sl;
|
||||||
|
|
||||||
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types());
|
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
|
String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
|
||||||
|
|
|
@ -45,7 +45,7 @@ void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) {
|
||||||
preview->edit(sb);
|
preview->edit(sb);
|
||||||
add_custom_control(preview);
|
add_custom_control(preview);
|
||||||
}
|
}
|
||||||
bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
|
bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
|
||||||
return false; //do not want
|
return false; //do not want
|
||||||
}
|
}
|
||||||
void EditorInspectorPluginStyleBox::parse_end() {
|
void EditorInspectorPluginStyleBox::parse_end() {
|
||||||
|
|
|
@ -62,7 +62,7 @@ class EditorInspectorPluginStyleBox : public EditorInspectorPlugin {
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(Object *p_object);
|
virtual bool can_handle(Object *p_object);
|
||||||
virtual void parse_begin(Object *p_object);
|
virtual void parse_begin(Object *p_object);
|
||||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
|
||||||
virtual void parse_end();
|
virtual void parse_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2261,6 +2261,12 @@ void VisualShaderEditor::_show_preview_text() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) {
|
||||||
|
|
||||||
|
RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable);
|
||||||
|
return RS::global_variable_type_get_shader_datatype(gvt);
|
||||||
|
}
|
||||||
|
|
||||||
void VisualShaderEditor::_update_preview() {
|
void VisualShaderEditor::_update_preview() {
|
||||||
|
|
||||||
if (!preview_showed) {
|
if (!preview_showed) {
|
||||||
|
@ -2274,7 +2280,7 @@ void VisualShaderEditor::_update_preview() {
|
||||||
|
|
||||||
ShaderLanguage sl;
|
ShaderLanguage sl;
|
||||||
|
|
||||||
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types());
|
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type);
|
||||||
|
|
||||||
for (int i = 0; i < preview_text->get_line_count(); i++) {
|
for (int i = 0; i < preview_text->get_line_count(); i++) {
|
||||||
preview_text->set_line_as_marked(i, false);
|
preview_text->set_line_as_marked(i, false);
|
||||||
|
@ -3291,7 +3297,7 @@ void EditorInspectorShaderModePlugin::parse_begin(Object *p_object) {
|
||||||
//do none
|
//do none
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
|
bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
|
||||||
|
|
||||||
if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
|
if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
|
||||||
|
|
||||||
|
|
|
@ -338,7 +338,7 @@ class EditorInspectorShaderModePlugin : public EditorInspectorPlugin {
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(Object *p_object);
|
virtual bool can_handle(Object *p_object);
|
||||||
virtual void parse_begin(Object *p_object);
|
virtual void parse_begin(Object *p_object);
|
||||||
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
|
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
|
||||||
virtual void parse_end();
|
virtual void parse_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2135,6 +2135,11 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
|
||||||
tab_container->add_child(autoload_settings);
|
tab_container->add_child(autoload_settings);
|
||||||
autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed));
|
autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed));
|
||||||
|
|
||||||
|
shaders_global_variables_editor = memnew(ShaderGlobalsEditor);
|
||||||
|
shaders_global_variables_editor->set_name(TTR("Shader Globals"));
|
||||||
|
tab_container->add_child(shaders_global_variables_editor);
|
||||||
|
shaders_global_variables_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed));
|
||||||
|
|
||||||
plugin_settings = memnew(EditorPluginSettings);
|
plugin_settings = memnew(EditorPluginSettings);
|
||||||
plugin_settings->set_name(TTR("Plugins"));
|
plugin_settings->set_name(TTR("Plugins"));
|
||||||
tab_container->add_child(plugin_settings);
|
tab_container->add_child(plugin_settings);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "editor/editor_data.h"
|
#include "editor/editor_data.h"
|
||||||
#include "editor/editor_plugin_settings.h"
|
#include "editor/editor_plugin_settings.h"
|
||||||
#include "editor/editor_sectioned_inspector.h"
|
#include "editor/editor_sectioned_inspector.h"
|
||||||
|
#include "editor/shader_globals_editor.h"
|
||||||
#include "scene/gui/dialogs.h"
|
#include "scene/gui/dialogs.h"
|
||||||
#include "scene/gui/tab_container.h"
|
#include "scene/gui/tab_container.h"
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ class ProjectSettingsEditor : public AcceptDialog {
|
||||||
OptionButton *device_index;
|
OptionButton *device_index;
|
||||||
Label *device_index_label;
|
Label *device_index_label;
|
||||||
MenuButton *popup_copy_to_feature;
|
MenuButton *popup_copy_to_feature;
|
||||||
|
ShaderGlobalsEditor *shaders_global_variables_editor;
|
||||||
|
|
||||||
LineEdit *action_name;
|
LineEdit *action_name;
|
||||||
Button *action_add;
|
Button *action_add;
|
||||||
|
|
|
@ -0,0 +1,452 @@
|
||||||
|
#include "shader_globals_editor.h"
|
||||||
|
#include "editor_node.h"
|
||||||
|
|
||||||
|
static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
|
||||||
|
"bool",
|
||||||
|
"bvec2",
|
||||||
|
"bvec3",
|
||||||
|
"bvec4",
|
||||||
|
"int",
|
||||||
|
"ivec2",
|
||||||
|
"ivec3",
|
||||||
|
"ivec4",
|
||||||
|
"rect2i",
|
||||||
|
"uint",
|
||||||
|
"uvec2",
|
||||||
|
"uvec3",
|
||||||
|
"uvec4",
|
||||||
|
"float",
|
||||||
|
"vec2",
|
||||||
|
"vec3",
|
||||||
|
"vec4",
|
||||||
|
"color",
|
||||||
|
"rect2",
|
||||||
|
"mat2",
|
||||||
|
"mat3",
|
||||||
|
"mat4",
|
||||||
|
"transform_2d",
|
||||||
|
"transform",
|
||||||
|
"sampler2D",
|
||||||
|
"sampler2DArray",
|
||||||
|
"sampler3D",
|
||||||
|
"samplerCube",
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderGlobalsEditorInterface : public Object {
|
||||||
|
GDCLASS(ShaderGlobalsEditorInterface, Object)
|
||||||
|
|
||||||
|
void _var_changed() {
|
||||||
|
emit_signal("var_changed");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {
|
||||||
|
ClassDB::bind_method("_var_changed", &ShaderGlobalsEditorInterface::_var_changed);
|
||||||
|
ADD_SIGNAL(MethodInfo("var_changed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
Variant existing = RS::get_singleton()->global_variable_get(p_name);
|
||||||
|
|
||||||
|
if (existing.get_type() == Variant::NIL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||||
|
|
||||||
|
undo_redo->create_action("Set Shader Global Variable");
|
||||||
|
undo_redo->add_do_method(RS::get_singleton(), "global_variable_set", p_name, p_value);
|
||||||
|
undo_redo->add_undo_method(RS::get_singleton(), "global_variable_set", p_name, existing);
|
||||||
|
RS::GlobalVariableType type = RS::get_singleton()->global_variable_get_type(p_name);
|
||||||
|
Dictionary gv;
|
||||||
|
gv["type"] = global_var_type_names[type];
|
||||||
|
if (type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
|
||||||
|
RES res = p_value;
|
||||||
|
if (res.is_valid()) {
|
||||||
|
gv["value"] = res->get_path();
|
||||||
|
} else {
|
||||||
|
gv["value"] = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gv["value"] = p_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = "shader_globals/" + String(p_name);
|
||||||
|
undo_redo->add_do_property(ProjectSettings::get_singleton(), path, gv);
|
||||||
|
undo_redo->add_undo_property(ProjectSettings::get_singleton(), path, ProjectSettings::get_singleton()->get(path));
|
||||||
|
undo_redo->add_do_method(this, "_var_changed");
|
||||||
|
undo_redo->add_undo_method(this, "_var_changed");
|
||||||
|
block_update = true;
|
||||||
|
undo_redo->commit_action();
|
||||||
|
block_update = false;
|
||||||
|
|
||||||
|
print_line("all good?");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _get(const StringName &p_name, Variant &r_ret) const {
|
||||||
|
r_ret = RS::get_singleton()->global_variable_get(p_name);
|
||||||
|
return r_ret.get_type() != Variant::NIL;
|
||||||
|
}
|
||||||
|
void _get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
|
Vector<StringName> variables;
|
||||||
|
variables = RS::get_singleton()->global_variable_get_list();
|
||||||
|
for (int i = 0; i < variables.size(); i++) {
|
||||||
|
PropertyInfo pinfo;
|
||||||
|
pinfo.name = variables[i];
|
||||||
|
|
||||||
|
switch (RS::get_singleton()->global_variable_get_type(variables[i])) {
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BOOL: {
|
||||||
|
pinfo.type = Variant::BOOL;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC2: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_FLAGS;
|
||||||
|
pinfo.hint_string = "x,y";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC3: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_FLAGS;
|
||||||
|
pinfo.hint_string = "x,y,z";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC4: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_FLAGS;
|
||||||
|
pinfo.hint_string = "x,y,z,w";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_INT: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC2: {
|
||||||
|
pinfo.type = Variant::VECTOR2I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC3: {
|
||||||
|
pinfo.type = Variant::VECTOR3I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC4: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2I: {
|
||||||
|
pinfo.type = Variant::RECT2I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UINT: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC2: {
|
||||||
|
pinfo.type = Variant::VECTOR2I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC3: {
|
||||||
|
pinfo.type = Variant::VECTOR3I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC4: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_FLOAT: {
|
||||||
|
pinfo.type = Variant::FLOAT;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC2: {
|
||||||
|
pinfo.type = Variant::VECTOR2;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC3: {
|
||||||
|
pinfo.type = Variant::VECTOR3;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC4: {
|
||||||
|
pinfo.type = Variant::PLANE;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2: {
|
||||||
|
pinfo.type = Variant::RECT2;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_COLOR: {
|
||||||
|
pinfo.type = Variant::COLOR;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT2: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT3: {
|
||||||
|
pinfo.type = Variant::BASIS;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
|
||||||
|
pinfo.type = Variant::TRANSFORM2D;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
|
||||||
|
pinfo.type = Variant::TRANSFORM;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT4: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Texture2D";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Texture2DArray";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Texture3D";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Cubemap";
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_list->push_back(pinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool block_update = false;
|
||||||
|
|
||||||
|
ShaderGlobalsEditorInterface() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Variant create_var(RS::GlobalVariableType p_type) {
|
||||||
|
switch (p_type) {
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BOOL: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC2: {
|
||||||
|
return 0; //bits
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC3: {
|
||||||
|
return 0; //bits
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC4: {
|
||||||
|
return 0; //bits
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_INT: {
|
||||||
|
return 0; //bits
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC2: {
|
||||||
|
return Vector2i();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC3: {
|
||||||
|
return Vector3i();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC4: {
|
||||||
|
Vector<int> v4;
|
||||||
|
v4.resize(4);
|
||||||
|
v4.write[0] = 0;
|
||||||
|
v4.write[1] = 0;
|
||||||
|
v4.write[2] = 0;
|
||||||
|
v4.write[3] = 0;
|
||||||
|
return v4;
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2I: {
|
||||||
|
return Rect2i();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UINT: {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC2: {
|
||||||
|
return Vector2i();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC3: {
|
||||||
|
return Vector3i();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC4: {
|
||||||
|
return Rect2i();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_FLOAT: {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC2: {
|
||||||
|
return Vector2();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC3: {
|
||||||
|
return Vector3();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC4: {
|
||||||
|
return Plane();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2: {
|
||||||
|
return Rect2();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_COLOR: {
|
||||||
|
return Color();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT2: {
|
||||||
|
Vector<real_t> xform;
|
||||||
|
xform.resize(4);
|
||||||
|
xform.write[0] = 1;
|
||||||
|
xform.write[1] = 0;
|
||||||
|
xform.write[2] = 0;
|
||||||
|
xform.write[3] = 1;
|
||||||
|
return xform;
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT3: {
|
||||||
|
return Basis();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
|
||||||
|
return Transform2D();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
|
||||||
|
return Transform();
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT4: {
|
||||||
|
Vector<real_t> xform;
|
||||||
|
xform.resize(4);
|
||||||
|
xform.write[0] = 1;
|
||||||
|
xform.write[1] = 0;
|
||||||
|
xform.write[2] = 0;
|
||||||
|
xform.write[3] = 0;
|
||||||
|
|
||||||
|
xform.write[4] = 0;
|
||||||
|
xform.write[5] = 1;
|
||||||
|
xform.write[6] = 0;
|
||||||
|
xform.write[7] = 0;
|
||||||
|
|
||||||
|
xform.write[8] = 0;
|
||||||
|
xform.write[9] = 0;
|
||||||
|
xform.write[10] = 1;
|
||||||
|
xform.write[11] = 0;
|
||||||
|
|
||||||
|
xform.write[12] = 0;
|
||||||
|
xform.write[13] = 0;
|
||||||
|
xform.write[14] = 0;
|
||||||
|
xform.write[15] = 1;
|
||||||
|
|
||||||
|
return xform;
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsEditor::_variable_added() {
|
||||||
|
|
||||||
|
String var = variable_name->get_text().strip_edges();
|
||||||
|
if (var == "" || !var.is_valid_identifier()) {
|
||||||
|
EditorNode::get_singleton()->show_warning(TTR("Please specify a valid variable identifier name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RenderingServer::get_singleton()->global_variable_get(var).get_type() != Variant::NIL) {
|
||||||
|
EditorNode::get_singleton()->show_warning(vformat(TTR("Global variable '%s' already exists'"), var));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> keywords;
|
||||||
|
ShaderLanguage::get_keyword_list(&keywords);
|
||||||
|
|
||||||
|
if (keywords.find(var) != nullptr || var == "script") {
|
||||||
|
EditorNode::get_singleton()->show_warning(vformat(TTR("Name '%s' is a reserved shader language keyword."), var));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||||
|
|
||||||
|
Variant value = create_var(RS::GlobalVariableType(variable_type->get_selected()));
|
||||||
|
|
||||||
|
undo_redo->create_action("Add Shader Global Variable");
|
||||||
|
undo_redo->add_do_method(RS::get_singleton(), "global_variable_add", var, RS::GlobalVariableType(variable_type->get_selected()), value);
|
||||||
|
undo_redo->add_undo_method(RS::get_singleton(), "global_variable_remove", var);
|
||||||
|
Dictionary gv;
|
||||||
|
gv["type"] = global_var_type_names[variable_type->get_selected()];
|
||||||
|
gv["value"] = value;
|
||||||
|
|
||||||
|
undo_redo->add_do_property(ProjectSettings::get_singleton(), "shader_globals/" + var, gv);
|
||||||
|
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "shader_globals/" + var, Variant());
|
||||||
|
undo_redo->add_do_method(this, "_changed");
|
||||||
|
undo_redo->add_undo_method(this, "_changed");
|
||||||
|
undo_redo->commit_action();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
|
||||||
|
|
||||||
|
print_line("deleted " + p_variable);
|
||||||
|
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||||
|
|
||||||
|
undo_redo->create_action("Add Shader Global Variable");
|
||||||
|
undo_redo->add_do_method(RS::get_singleton(), "global_variable_remove", p_variable);
|
||||||
|
undo_redo->add_undo_method(RS::get_singleton(), "global_variable_add", p_variable, RS::get_singleton()->global_variable_get_type(p_variable), RS::get_singleton()->global_variable_get(p_variable));
|
||||||
|
|
||||||
|
undo_redo->add_do_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, Variant());
|
||||||
|
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, ProjectSettings::get_singleton()->get("shader_globals/" + p_variable));
|
||||||
|
undo_redo->add_do_method(this, "_changed");
|
||||||
|
undo_redo->add_undo_method(this, "_changed");
|
||||||
|
undo_redo->commit_action();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsEditor::_changed() {
|
||||||
|
emit_signal("globals_changed");
|
||||||
|
if (!interface->block_update) {
|
||||||
|
interface->_change_notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsEditor::_bind_methods() {
|
||||||
|
ClassDB::bind_method("_changed", &ShaderGlobalsEditor::_changed);
|
||||||
|
ADD_SIGNAL(MethodInfo("globals_changed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsEditor::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||||
|
if (is_visible_in_tree()) {
|
||||||
|
print_line("OK load settings in globalseditor");
|
||||||
|
inspector->edit(interface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderGlobalsEditor::ShaderGlobalsEditor() {
|
||||||
|
|
||||||
|
HBoxContainer *add_menu_hb = memnew(HBoxContainer);
|
||||||
|
add_child(add_menu_hb);
|
||||||
|
|
||||||
|
add_menu_hb->add_child(memnew(Label(TTR("Name:"))));
|
||||||
|
variable_name = memnew(LineEdit);
|
||||||
|
variable_name->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
add_menu_hb->add_child(variable_name);
|
||||||
|
|
||||||
|
add_menu_hb->add_child(memnew(Label(TTR("Type:"))));
|
||||||
|
variable_type = memnew(OptionButton);
|
||||||
|
variable_type->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
add_menu_hb->add_child(variable_type);
|
||||||
|
|
||||||
|
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
|
||||||
|
variable_type->add_item(global_var_type_names[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
variable_add = memnew(Button(TTR("Add")));
|
||||||
|
add_menu_hb->add_child(variable_add);
|
||||||
|
variable_add->connect("pressed", callable_mp(this, &ShaderGlobalsEditor::_variable_added));
|
||||||
|
|
||||||
|
inspector = memnew(EditorInspector);
|
||||||
|
inspector->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
add_child(inspector);
|
||||||
|
inspector->set_use_wide_editors(true);
|
||||||
|
inspector->set_enable_capitalize_paths(false);
|
||||||
|
inspector->set_use_deletable_properties(true);
|
||||||
|
inspector->connect("property_deleted", callable_mp(this, &ShaderGlobalsEditor::_variable_deleted), varray(), CONNECT_DEFERRED);
|
||||||
|
|
||||||
|
interface = memnew(ShaderGlobalsEditorInterface);
|
||||||
|
interface->connect("var_changed", Callable(this, "_changed"));
|
||||||
|
}
|
||||||
|
ShaderGlobalsEditor::~ShaderGlobalsEditor() {
|
||||||
|
inspector->edit(NULL);
|
||||||
|
memdelete(interface);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef SHADER_GLOBALS_EDITOR_H
|
||||||
|
#define SHADER_GLOBALS_EDITOR_H
|
||||||
|
|
||||||
|
#include "core/undo_redo.h"
|
||||||
|
#include "editor/editor_autoload_settings.h"
|
||||||
|
#include "editor/editor_data.h"
|
||||||
|
#include "editor/editor_plugin_settings.h"
|
||||||
|
#include "editor/editor_sectioned_inspector.h"
|
||||||
|
#include "scene/gui/dialogs.h"
|
||||||
|
#include "scene/gui/tab_container.h"
|
||||||
|
|
||||||
|
class ShaderGlobalsEditorInterface;
|
||||||
|
|
||||||
|
class ShaderGlobalsEditor : public VBoxContainer {
|
||||||
|
|
||||||
|
GDCLASS(ShaderGlobalsEditor, VBoxContainer)
|
||||||
|
|
||||||
|
ShaderGlobalsEditorInterface *interface;
|
||||||
|
EditorInspector *inspector;
|
||||||
|
|
||||||
|
LineEdit *variable_name;
|
||||||
|
OptionButton *variable_type;
|
||||||
|
Button *variable_add;
|
||||||
|
|
||||||
|
void _variable_added();
|
||||||
|
void _variable_deleted(const String &p_variable);
|
||||||
|
void _changed();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
void _notification(int p_what);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShaderGlobalsEditor();
|
||||||
|
~ShaderGlobalsEditor();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHADER_GLOBALS_EDITOR_H
|
|
@ -1481,6 +1481,15 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
// We could add more, and make the CLI arg require a comma-separated list of profilers.
|
// We could add more, and make the CLI arg require a comma-separated list of profilers.
|
||||||
EngineDebugger::get_singleton()->profiler_enable("scripts", true);
|
EngineDebugger::get_singleton()->profiler_enable("scripts", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!project_manager) {
|
||||||
|
// If not running the project manager, and now that the engine is
|
||||||
|
// able to load resources, load the global shader variables.
|
||||||
|
// If running on editor, dont load the textures because the editor
|
||||||
|
// may want to import them first. Editor will reload those later.
|
||||||
|
rendering_server->global_variables_load_settings(!editor);
|
||||||
|
}
|
||||||
|
|
||||||
_start_success = true;
|
_start_success = true;
|
||||||
locale = String();
|
locale = String();
|
||||||
|
|
||||||
|
@ -2280,6 +2289,9 @@ void Main::cleanup() {
|
||||||
// Sync pending commands that may have been queued from a different thread during ScriptServer finalization
|
// Sync pending commands that may have been queued from a different thread during ScriptServer finalization
|
||||||
RenderingServer::get_singleton()->sync();
|
RenderingServer::get_singleton()->sync();
|
||||||
|
|
||||||
|
//clear global shader variables before scene and other graphics stuff is deinitialized.
|
||||||
|
rendering_server->global_variables_clear();
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
EditorNode::unregister_editor_types();
|
EditorNode::unregister_editor_types();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -342,7 +342,7 @@ MainLoop *test() {
|
||||||
Set<String> types;
|
Set<String> types;
|
||||||
types.insert("spatial");
|
types.insert("spatial");
|
||||||
|
|
||||||
Error err = sl.compile(code, dt, rm, types);
|
Error err = sl.compile(code, dt, rm, types, NULL);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,62 @@ float GeometryInstance3D::get_lod_max_hysteresis() const {
|
||||||
void GeometryInstance3D::_notification(int p_what) {
|
void GeometryInstance3D::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringName p_name) const {
|
||||||
|
StringName *r = instance_uniform_property_remap.getptr(p_name);
|
||||||
|
if (!r) {
|
||||||
|
String s = p_name;
|
||||||
|
if (s.begins_with("shader_params/")) {
|
||||||
|
StringName name = s.replace("shader_params/", "");
|
||||||
|
instance_uniform_property_remap[p_name] = name;
|
||||||
|
return instance_uniform_property_remap.getptr(p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
const StringName *r = _instance_uniform_get_remap(p_name);
|
||||||
|
if (r) {
|
||||||
|
set_shader_instance_uniform(*r, p_value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
|
const StringName *r = _instance_uniform_get_remap(p_name);
|
||||||
|
if (r) {
|
||||||
|
r_ret = get_shader_instance_uniform(*r);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
|
List<PropertyInfo> pinfo;
|
||||||
|
RS::get_singleton()->instance_geometry_get_shader_parameter_list(get_instance(), &pinfo);
|
||||||
|
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
|
||||||
|
PropertyInfo pi = E->get();
|
||||||
|
bool has_def_value = false;
|
||||||
|
Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), pi.name);
|
||||||
|
if (def_value.get_type() != Variant::NIL) {
|
||||||
|
has_def_value = true;
|
||||||
|
}
|
||||||
|
if (instance_uniforms.has(pi.name)) {
|
||||||
|
pi.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | (has_def_value ? (PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED) : 0);
|
||||||
|
} else {
|
||||||
|
pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : 0); //do not save if not changed
|
||||||
|
}
|
||||||
|
|
||||||
|
pi.name = "shader_params/" + pi.name;
|
||||||
|
p_list->push_back(pi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) {
|
void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) {
|
||||||
|
|
||||||
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
|
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
|
||||||
|
@ -258,6 +314,22 @@ float GeometryInstance3D::get_extra_cull_margin() const {
|
||||||
return extra_cull_margin;
|
return extra_cull_margin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value) {
|
||||||
|
|
||||||
|
if (p_value.get_type() == Variant::NIL) {
|
||||||
|
Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_uniform);
|
||||||
|
RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, def_value);
|
||||||
|
instance_uniforms.erase(p_value);
|
||||||
|
} else {
|
||||||
|
instance_uniforms[p_uniform] = p_value;
|
||||||
|
RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant GeometryInstance3D::get_shader_instance_uniform(const StringName &p_uniform) const {
|
||||||
|
|
||||||
|
return RS::get_singleton()->instance_geometry_get_shader_parameter(get_instance(), p_uniform);
|
||||||
|
}
|
||||||
void GeometryInstance3D::set_custom_aabb(AABB aabb) {
|
void GeometryInstance3D::set_custom_aabb(AABB aabb) {
|
||||||
|
|
||||||
RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb);
|
RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb);
|
||||||
|
@ -280,6 +352,9 @@ void GeometryInstance3D::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance3D::set_lod_max_distance);
|
ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance3D::set_lod_max_distance);
|
||||||
ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance3D::get_lod_max_distance);
|
ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance3D::get_lod_max_distance);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance3D::set_lod_min_hysteresis);
|
ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance3D::set_lod_min_hysteresis);
|
||||||
ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance3D::get_lod_min_hysteresis);
|
ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance3D::get_lod_min_hysteresis);
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,18 @@ private:
|
||||||
float lod_min_hysteresis;
|
float lod_min_hysteresis;
|
||||||
float lod_max_hysteresis;
|
float lod_max_hysteresis;
|
||||||
|
|
||||||
|
mutable HashMap<StringName, Variant> instance_uniforms;
|
||||||
|
mutable HashMap<StringName, StringName> instance_uniform_property_remap;
|
||||||
|
|
||||||
float extra_cull_margin;
|
float extra_cull_margin;
|
||||||
|
|
||||||
|
const StringName *_instance_uniform_get_remap(const StringName p_name) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
|
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||||
|
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
@ -139,6 +148,9 @@ public:
|
||||||
void set_extra_cull_margin(float p_margin);
|
void set_extra_cull_margin(float p_margin);
|
||||||
float get_extra_cull_margin() const;
|
float get_extra_cull_margin() const;
|
||||||
|
|
||||||
|
void set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value);
|
||||||
|
Variant get_shader_instance_uniform(const StringName &p_uniform) const;
|
||||||
|
|
||||||
void set_custom_aabb(AABB aabb);
|
void set_custom_aabb(AABB aabb);
|
||||||
|
|
||||||
GeometryInstance3D();
|
GeometryInstance3D();
|
||||||
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
#include "shader_globals_override.h"
|
||||||
|
|
||||||
|
#include "core/core_string_names.h"
|
||||||
|
#include "scene/main/window.h"
|
||||||
|
#include "scene/scene_string_names.h"
|
||||||
|
|
||||||
|
StringName *ShaderGlobalsOverride::_remap(const StringName &p_name) const {
|
||||||
|
|
||||||
|
StringName *r = param_remaps.getptr(p_name);
|
||||||
|
if (!r) {
|
||||||
|
//not cached, do caching
|
||||||
|
String p = p_name;
|
||||||
|
if (p.begins_with("params/")) {
|
||||||
|
String q = p.replace_first("params/", "");
|
||||||
|
param_remaps[p] = q;
|
||||||
|
r = param_remaps.getptr(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
|
||||||
|
StringName *r = _remap(p_name);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
Override *o = overrides.getptr(*r);
|
||||||
|
if (!o) {
|
||||||
|
Override ov;
|
||||||
|
ov.in_use = false;
|
||||||
|
overrides[*r] = ov;
|
||||||
|
o = overrides.getptr(*r);
|
||||||
|
}
|
||||||
|
if (o) {
|
||||||
|
o->override = p_value;
|
||||||
|
if (active) {
|
||||||
|
RS::get_singleton()->global_variable_set_override(*r, p_value);
|
||||||
|
}
|
||||||
|
o->in_use = p_value.get_type() != Variant::NIL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
|
|
||||||
|
StringName *r = _remap(p_name);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
const Override *o = overrides.getptr(*r);
|
||||||
|
if (o) {
|
||||||
|
r_ret = o->override;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
|
|
||||||
|
Vector<StringName> variables;
|
||||||
|
variables = RS::get_singleton()->global_variable_get_list();
|
||||||
|
for (int i = 0; i < variables.size(); i++) {
|
||||||
|
PropertyInfo pinfo;
|
||||||
|
pinfo.name = "params/" + variables[i];
|
||||||
|
pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
|
||||||
|
|
||||||
|
switch (RS::get_singleton()->global_variable_get_type(variables[i])) {
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BOOL: {
|
||||||
|
pinfo.type = Variant::BOOL;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC2: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_FLAGS;
|
||||||
|
pinfo.hint_string = "x,y";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC3: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_FLAGS;
|
||||||
|
pinfo.hint_string = "x,y,z";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC4: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_FLAGS;
|
||||||
|
pinfo.hint_string = "x,y,z,w";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_INT: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC2: {
|
||||||
|
pinfo.type = Variant::VECTOR2I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC3: {
|
||||||
|
pinfo.type = Variant::VECTOR3I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC4: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2I: {
|
||||||
|
pinfo.type = Variant::RECT2I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UINT: {
|
||||||
|
pinfo.type = Variant::INT;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC2: {
|
||||||
|
pinfo.type = Variant::VECTOR2I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC3: {
|
||||||
|
pinfo.type = Variant::VECTOR3I;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC4: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_FLOAT: {
|
||||||
|
pinfo.type = Variant::FLOAT;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC2: {
|
||||||
|
pinfo.type = Variant::VECTOR2;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC3: {
|
||||||
|
pinfo.type = Variant::VECTOR3;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC4: {
|
||||||
|
pinfo.type = Variant::PLANE;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2: {
|
||||||
|
pinfo.type = Variant::RECT2;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_COLOR: {
|
||||||
|
pinfo.type = Variant::COLOR;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT2: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT3: {
|
||||||
|
pinfo.type = Variant::BASIS;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
|
||||||
|
pinfo.type = Variant::TRANSFORM2D;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
|
||||||
|
pinfo.type = Variant::TRANSFORM;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT4: {
|
||||||
|
pinfo.type = Variant::PACKED_INT32_ARRAY;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Texture2D";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Texture2DArray";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Texture3D";
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
|
||||||
|
pinfo.type = Variant::OBJECT;
|
||||||
|
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||||
|
pinfo.hint_string = "Cubemap";
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!overrides.has(variables[i])) {
|
||||||
|
Override o;
|
||||||
|
o.in_use = false;
|
||||||
|
Callable::CallError ce;
|
||||||
|
o.override = Variant::construct(pinfo.type, NULL, 0, ce);
|
||||||
|
overrides[variables[i]] = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
Override *o = overrides.getptr(variables[i]);
|
||||||
|
if (o->in_use && o->override.get_type() != Variant::NIL) {
|
||||||
|
pinfo.usage |= PROPERTY_USAGE_CHECKED;
|
||||||
|
pinfo.usage |= PROPERTY_USAGE_STORAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_list->push_back(pinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsOverride::_activate() {
|
||||||
|
|
||||||
|
List<Node *> nodes;
|
||||||
|
get_tree()->get_nodes_in_group(SceneStringNames::get_singleton()->shader_overrides_group_active, &nodes);
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
//good we are the only override, enable all
|
||||||
|
active = true;
|
||||||
|
add_to_group(SceneStringNames::get_singleton()->shader_overrides_group_active);
|
||||||
|
|
||||||
|
const StringName *K = nullptr;
|
||||||
|
while ((K = overrides.next(K))) {
|
||||||
|
Override *o = overrides.getptr(*K);
|
||||||
|
if (o->in_use && o->override.get_type() != Variant::NIL) {
|
||||||
|
RS::get_singleton()->global_variable_set_override(*K, o->override);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_configuration_warning(); //may have activated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsOverride::_notification(int p_what) {
|
||||||
|
|
||||||
|
if (p_what == Node3D::NOTIFICATION_ENTER_TREE) {
|
||||||
|
|
||||||
|
add_to_group(SceneStringNames::get_singleton()->shader_overrides_group);
|
||||||
|
_activate();
|
||||||
|
|
||||||
|
} else if (p_what == Node3D::NOTIFICATION_EXIT_TREE) {
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
//remove overrides
|
||||||
|
const StringName *K = nullptr;
|
||||||
|
while ((K = overrides.next(K))) {
|
||||||
|
Override *o = overrides.getptr(*K);
|
||||||
|
if (o->in_use) {
|
||||||
|
RS::get_singleton()->global_variable_set_override(*K, Variant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group_active);
|
||||||
|
remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group);
|
||||||
|
get_tree()->call_group(SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String ShaderGlobalsOverride::get_configuration_warning() const {
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
return TTR("ShaderGlobalsOverride is not active because another node of the same type is in the scene.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderGlobalsOverride::_bind_methods() {
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("_activate"), &ShaderGlobalsOverride::_activate);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderGlobalsOverride::ShaderGlobalsOverride() {
|
||||||
|
active = false;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef SHADER_GLOBALS_OVERRIDE_H
|
||||||
|
#define SHADER_GLOBALS_OVERRIDE_H
|
||||||
|
|
||||||
|
#include "scene/3d/node_3d.h"
|
||||||
|
|
||||||
|
class ShaderGlobalsOverride : public Node {
|
||||||
|
|
||||||
|
GDCLASS(ShaderGlobalsOverride, Node);
|
||||||
|
|
||||||
|
struct Override {
|
||||||
|
bool in_use = false;
|
||||||
|
Variant override;
|
||||||
|
};
|
||||||
|
|
||||||
|
StringName *_remap(const StringName &p_name) const;
|
||||||
|
|
||||||
|
bool active;
|
||||||
|
mutable HashMap<StringName, Override> overrides;
|
||||||
|
mutable HashMap<StringName, StringName> param_remaps;
|
||||||
|
|
||||||
|
void _activate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
|
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||||
|
|
||||||
|
void _notification(int p_what);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
String get_configuration_warning() const;
|
||||||
|
|
||||||
|
ShaderGlobalsOverride();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHADER_GLOBALS_OVERRIDE_H
|
|
@ -177,6 +177,8 @@
|
||||||
#include "scene/3d/node_3d.h"
|
#include "scene/3d/node_3d.h"
|
||||||
#include "scene/3d/skeleton_3d.h"
|
#include "scene/3d/skeleton_3d.h"
|
||||||
|
|
||||||
|
#include "scene/main/shader_globals_override.h"
|
||||||
|
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
#include "scene/3d/area_3d.h"
|
#include "scene/3d/area_3d.h"
|
||||||
#include "scene/3d/audio_stream_player_3d.h"
|
#include "scene/3d/audio_stream_player_3d.h"
|
||||||
|
@ -403,6 +405,8 @@ void register_scene_types() {
|
||||||
ClassDB::register_class<AnimationNodeTimeSeek>();
|
ClassDB::register_class<AnimationNodeTimeSeek>();
|
||||||
ClassDB::register_class<AnimationNodeTransition>();
|
ClassDB::register_class<AnimationNodeTransition>();
|
||||||
|
|
||||||
|
ClassDB::register_class<ShaderGlobalsOverride>(); //can be used in any shader
|
||||||
|
|
||||||
OS::get_singleton()->yield(); //may take time to init
|
OS::get_singleton()->yield(); //may take time to init
|
||||||
|
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
|
|
|
@ -202,4 +202,7 @@ SceneStringNames::SceneStringNames() {
|
||||||
parameters_base_path = "parameters/";
|
parameters_base_path = "parameters/";
|
||||||
|
|
||||||
tracks_changed = "tracks_changed";
|
tracks_changed = "tracks_changed";
|
||||||
|
|
||||||
|
shader_overrides_group = StaticCString::create("_shader_overrides_group_");
|
||||||
|
shader_overrides_group_active = StaticCString::create("_shader_overrides_group_active_");
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,8 @@ public:
|
||||||
StringName window_input;
|
StringName window_input;
|
||||||
|
|
||||||
StringName theme_changed;
|
StringName theme_changed;
|
||||||
|
StringName shader_overrides_group;
|
||||||
|
StringName shader_overrides_group_active;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MAX_MATERIALS = 32
|
MAX_MATERIALS = 32
|
||||||
|
|
|
@ -167,6 +167,17 @@ public:
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
AABB transformed_aabb;
|
AABB transformed_aabb;
|
||||||
|
|
||||||
|
struct InstanceShaderParameter {
|
||||||
|
int32_t index = -1;
|
||||||
|
Variant value;
|
||||||
|
Variant default_value;
|
||||||
|
PropertyInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<StringName, InstanceShaderParameter> instance_shader_parameters;
|
||||||
|
bool instance_allocated_shader_parameters = false;
|
||||||
|
int32_t instance_allocated_shader_parameters_offset = -1;
|
||||||
|
|
||||||
virtual void dependency_deleted(RID p_dependency) = 0;
|
virtual void dependency_deleted(RID p_dependency) = 0;
|
||||||
virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0;
|
virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0;
|
||||||
|
|
||||||
|
@ -357,6 +368,14 @@ public:
|
||||||
virtual bool material_is_animated(RID p_material) = 0;
|
virtual bool material_is_animated(RID p_material) = 0;
|
||||||
virtual bool material_casts_shadows(RID p_material) = 0;
|
virtual bool material_casts_shadows(RID p_material) = 0;
|
||||||
|
|
||||||
|
struct InstanceShaderParam {
|
||||||
|
PropertyInfo info;
|
||||||
|
int index;
|
||||||
|
Variant default_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
|
||||||
|
|
||||||
virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0;
|
virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0;
|
||||||
|
|
||||||
/* MESH API */
|
/* MESH API */
|
||||||
|
@ -635,6 +654,24 @@ public:
|
||||||
virtual int particles_get_draw_passes(RID p_particles) const = 0;
|
virtual int particles_get_draw_passes(RID p_particles) const = 0;
|
||||||
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
|
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES */
|
||||||
|
|
||||||
|
virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
|
||||||
|
virtual void global_variable_remove(const StringName &p_name) = 0;
|
||||||
|
virtual Vector<StringName> global_variable_get_list() const = 0;
|
||||||
|
|
||||||
|
virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
|
||||||
|
virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
|
||||||
|
virtual Variant global_variable_get(const StringName &p_name) const = 0;
|
||||||
|
virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
|
||||||
|
|
||||||
|
virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
|
||||||
|
virtual void global_variables_clear() = 0;
|
||||||
|
|
||||||
|
virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
|
||||||
|
virtual void global_variables_instance_free(RID p_instance) = 0;
|
||||||
|
virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
|
||||||
|
|
||||||
/* RENDER TARGET */
|
/* RENDER TARGET */
|
||||||
|
|
||||||
enum RenderTargetFlags {
|
enum RenderTargetFlags {
|
||||||
|
|
|
@ -618,6 +618,14 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||||
|
u.binding = 7;
|
||||||
|
u.ids.push_back(storage->global_variables_get_storage_buffer());
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
//validate and update lighs if they are being used
|
//validate and update lighs if they are being used
|
||||||
|
|
||||||
if (light_count > 0) {
|
if (light_count > 0) {
|
||||||
|
@ -2012,6 +2020,9 @@ void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_
|
||||||
|
|
||||||
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (E->get().texture_order >= 0) {
|
if (E->get().texture_order >= 0) {
|
||||||
order[E->get().texture_order + 100000] = E->key();
|
order[E->get().texture_order + 100000] = E->key();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2027,6 +2038,23 @@ void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerCanvasRD::ShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const {
|
||||||
|
|
||||||
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterizerStorage::InstanceShaderParam p;
|
||||||
|
p.info = ShaderLanguage::uniform_to_property_info(E->get());
|
||||||
|
p.info.name = E->key(); //supply name
|
||||||
|
p.index = E->get().instance_index;
|
||||||
|
p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
|
||||||
|
p_param_list->push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const {
|
bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const {
|
||||||
if (!uniforms.has(p_param)) {
|
if (!uniforms.has(p_param)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2366,6 +2394,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
|
||||||
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
|
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
|
||||||
actions.base_varying_index = 4;
|
actions.base_varying_index = 4;
|
||||||
|
|
||||||
|
actions.global_buffer_array_variable = "global_variables.data";
|
||||||
|
|
||||||
shader.compiler.initialize(actions);
|
shader.compiler.initialize(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
|
||||||
virtual void set_code(const String &p_Code);
|
virtual void set_code(const String &p_Code);
|
||||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
||||||
|
virtual void get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const;
|
||||||
|
|
||||||
virtual bool is_param_texture(const StringName &p_param) const;
|
virtual bool is_param_texture(const StringName &p_param) const;
|
||||||
virtual bool is_animated() const;
|
virtual bool is_animated() const;
|
||||||
virtual bool casts_shadows() const;
|
virtual bool casts_shadows() const;
|
||||||
|
|
|
@ -378,6 +378,10 @@ void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_
|
||||||
|
|
||||||
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (E->get().texture_order >= 0) {
|
if (E->get().texture_order >= 0) {
|
||||||
order[E->get().texture_order + 100000] = E->key();
|
order[E->get().texture_order + 100000] = E->key();
|
||||||
} else {
|
} else {
|
||||||
|
@ -393,6 +397,23 @@ void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneHighEndRD::ShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const {
|
||||||
|
|
||||||
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterizerStorage::InstanceShaderParam p;
|
||||||
|
p.info = ShaderLanguage::uniform_to_property_info(E->get());
|
||||||
|
p.info.name = E->key(); //supply name
|
||||||
|
p.index = E->get().instance_index;
|
||||||
|
p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
|
||||||
|
p_param_list->push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const {
|
bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const {
|
||||||
if (!uniforms.has(p_param)) {
|
if (!uniforms.has(p_param)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -828,6 +849,7 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements,
|
||||||
store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
|
store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
|
||||||
id.flags = 0;
|
id.flags = 0;
|
||||||
id.mask = e->instance->layer_mask;
|
id.mask = e->instance->layer_mask;
|
||||||
|
id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
|
||||||
|
|
||||||
if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
|
if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
|
||||||
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
|
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
|
||||||
|
@ -2701,6 +2723,14 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||||
|
u.binding = 16;
|
||||||
|
u.ids.push_back(storage->global_variables_get_storage_buffer());
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET);
|
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3077,6 +3107,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
||||||
|
|
||||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||||
|
actions.global_buffer_array_variable = "global_variables.data";
|
||||||
|
actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
|
||||||
|
|
||||||
shader.compiler.initialize(actions);
|
shader.compiler.initialize(actions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||||
virtual void set_code(const String &p_Code);
|
virtual void set_code(const String &p_Code);
|
||||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
||||||
|
void get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const;
|
||||||
|
|
||||||
virtual bool is_param_texture(const StringName &p_param) const;
|
virtual bool is_param_texture(const StringName &p_param) const;
|
||||||
virtual bool is_animated() const;
|
virtual bool is_animated() const;
|
||||||
virtual bool casts_shadows() const;
|
virtual bool casts_shadows() const;
|
||||||
|
@ -361,7 +363,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||||
float transform[16];
|
float transform[16];
|
||||||
float normal_transform[16];
|
float normal_transform[16];
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
|
uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer
|
||||||
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
|
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
};
|
};
|
||||||
|
|
|
@ -926,6 +926,10 @@ void RasterizerSceneRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_para
|
||||||
|
|
||||||
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (E->get().texture_order >= 0) {
|
if (E->get().texture_order >= 0) {
|
||||||
order[E->get().texture_order + 100000] = E->key();
|
order[E->get().texture_order + 100000] = E->key();
|
||||||
} else {
|
} else {
|
||||||
|
@ -941,6 +945,23 @@ void RasterizerSceneRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_para
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneRD::SkyShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const {
|
||||||
|
|
||||||
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterizerStorage::InstanceShaderParam p;
|
||||||
|
p.info = ShaderLanguage::uniform_to_property_info(E->get());
|
||||||
|
p.info.name = E->key(); //supply name
|
||||||
|
p.index = E->get().instance_index;
|
||||||
|
p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
|
||||||
|
p_param_list->push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
|
bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
|
||||||
if (!uniforms.has(p_param)) {
|
if (!uniforms.has(p_param)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -4217,6 +4238,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
|
||||||
|
|
||||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||||
|
actions.global_buffer_array_variable = "global_variables.data";
|
||||||
|
|
||||||
sky_shader.compiler.initialize(actions);
|
sky_shader.compiler.initialize(actions);
|
||||||
}
|
}
|
||||||
|
@ -4254,6 +4276,14 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||||
|
u.binding = 1;
|
||||||
|
u.ids.push_back(storage->global_variables_get_storage_buffer());
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS);
|
sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ private:
|
||||||
virtual void set_code(const String &p_Code);
|
virtual void set_code(const String &p_Code);
|
||||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
||||||
|
virtual void get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const;
|
||||||
virtual bool is_param_texture(const StringName &p_param) const;
|
virtual bool is_param_texture(const StringName &p_param) const;
|
||||||
virtual bool is_animated() const;
|
virtual bool is_animated() const;
|
||||||
virtual bool casts_shadows() const;
|
virtual bool casts_shadows() const;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "rasterizer_storage_rd.h"
|
#include "rasterizer_storage_rd.h"
|
||||||
|
|
||||||
#include "core/engine.h"
|
#include "core/engine.h"
|
||||||
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/project_settings.h"
|
#include "core/project_settings.h"
|
||||||
#include "servers/rendering/shader_language.h"
|
#include "servers/rendering/shader_language.h"
|
||||||
|
|
||||||
|
@ -921,6 +922,7 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
|
||||||
Material *material = E->get();
|
Material *material = E->get();
|
||||||
if (shader->data) {
|
if (shader->data) {
|
||||||
material->data = material_data_request_func[new_type](shader->data);
|
material->data = material_data_request_func[new_type](shader->data);
|
||||||
|
material->data->self = material->self;
|
||||||
material->data->set_next_pass(material->next_pass);
|
material->data->set_next_pass(material->next_pass);
|
||||||
material->data->set_render_priority(material->priority);
|
material->data->set_render_priority(material->priority);
|
||||||
}
|
}
|
||||||
|
@ -1021,8 +1023,8 @@ void RasterizerStorageRD::_material_queue_update(Material *material, bool p_unif
|
||||||
material->update_next = material_update_list;
|
material->update_next = material_update_list;
|
||||||
material_update_list = material;
|
material_update_list = material;
|
||||||
material->update_requested = true;
|
material->update_requested = true;
|
||||||
material->uniform_dirty = p_uniform;
|
material->uniform_dirty = material->uniform_dirty || p_uniform;
|
||||||
material->texture_dirty = p_texture;
|
material->texture_dirty = material->texture_dirty || p_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
|
void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
|
||||||
|
@ -1059,6 +1061,7 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
|
||||||
ERR_FAIL_COND(shader->data == nullptr);
|
ERR_FAIL_COND(shader->data == nullptr);
|
||||||
|
|
||||||
material->data = material_data_request_func[shader->type](shader->data);
|
material->data = material_data_request_func[shader->type](shader->data);
|
||||||
|
material->data->self = p_material;
|
||||||
material->data->set_next_pass(material->next_pass);
|
material->data->set_next_pass(material->next_pass);
|
||||||
material->data->set_render_priority(material->priority);
|
material->data->set_render_priority(material->priority);
|
||||||
//updating happens later
|
//updating happens later
|
||||||
|
@ -1144,6 +1147,19 @@ bool RasterizerStorageRD::material_casts_shadows(RID p_material) {
|
||||||
return true; //by default everything casts shadows
|
return true; //by default everything casts shadows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
|
||||||
|
|
||||||
|
Material *material = material_owner.getornull(p_material);
|
||||||
|
ERR_FAIL_COND(!material);
|
||||||
|
if (material->shader && material->shader->data) {
|
||||||
|
material->shader->data->get_instance_param_list(r_parameters);
|
||||||
|
|
||||||
|
if (material->next_pass.is_valid()) {
|
||||||
|
material_get_instance_shader_parameters(material->next_pass, r_parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) {
|
void RasterizerStorageRD::material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) {
|
||||||
Material *material = material_owner.getornull(p_material);
|
Material *material = material_owner.getornull(p_material);
|
||||||
ERR_FAIL_COND(!material);
|
ERR_FAIL_COND(!material);
|
||||||
|
@ -1631,11 +1647,36 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
|
||||||
|
|
||||||
void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
|
void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
|
||||||
|
|
||||||
|
bool uses_global_buffer = false;
|
||||||
|
|
||||||
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_uniforms.front(); E; E = E->next()) {
|
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_uniforms.front(); E; E = E->next()) {
|
||||||
|
|
||||||
if (E->get().order < 0)
|
if (E->get().order < 0)
|
||||||
continue; // texture, does not go here
|
continue; // texture, does not go here
|
||||||
|
|
||||||
|
if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
continue; //instance uniforms don't appear in the bufferr
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
|
||||||
|
//this is a global variable, get the index to it
|
||||||
|
RasterizerStorageRD *rs = base_singleton;
|
||||||
|
|
||||||
|
GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E->key());
|
||||||
|
uint32_t index = 0;
|
||||||
|
if (gv) {
|
||||||
|
index = gv->buffer_index;
|
||||||
|
} else {
|
||||||
|
WARN_PRINT("Shader uses global uniform '" + E->key() + "', but it was removed at some point. Material will not display correctly.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = p_uniform_offsets[E->get().order];
|
||||||
|
uint32_t *intptr = (uint32_t *)&p_buffer[offset];
|
||||||
|
*intptr = index;
|
||||||
|
uses_global_buffer = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//regular uniform
|
//regular uniform
|
||||||
uint32_t offset = p_uniform_offsets[E->get().order];
|
uint32_t offset = p_uniform_offsets[E->get().order];
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
@ -1664,6 +1705,38 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uses_global_buffer != (global_buffer_E != nullptr)) {
|
||||||
|
RasterizerStorageRD *rs = base_singleton;
|
||||||
|
if (uses_global_buffer) {
|
||||||
|
global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self);
|
||||||
|
} else {
|
||||||
|
rs->global_variables.materials_using_buffer.erase(global_buffer_E);
|
||||||
|
global_buffer_E = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterizerStorageRD::MaterialData::~MaterialData() {
|
||||||
|
if (global_buffer_E) {
|
||||||
|
//unregister global buffers
|
||||||
|
RasterizerStorageRD *rs = base_singleton;
|
||||||
|
rs->global_variables.materials_using_buffer.erase(global_buffer_E);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_texture_E) {
|
||||||
|
//unregister global textures
|
||||||
|
RasterizerStorageRD *rs = base_singleton;
|
||||||
|
|
||||||
|
for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
|
||||||
|
GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
|
||||||
|
if (v) {
|
||||||
|
v->texture_materials.erase(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//unregister material from those using global textures
|
||||||
|
rs->global_variables.materials_using_texture.erase(global_texture_E);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
|
void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
|
||||||
|
@ -1675,22 +1748,57 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
|
||||||
Texture *normal_detect_texture = nullptr;
|
Texture *normal_detect_texture = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool uses_global_textures = false;
|
||||||
|
global_textures_pass++;
|
||||||
|
|
||||||
for (int i = 0; i < p_texture_uniforms.size(); i++) {
|
for (int i = 0; i < p_texture_uniforms.size(); i++) {
|
||||||
|
|
||||||
const StringName &uniform_name = p_texture_uniforms[i].name;
|
const StringName &uniform_name = p_texture_uniforms[i].name;
|
||||||
|
|
||||||
RID texture;
|
RID texture;
|
||||||
|
|
||||||
const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
|
if (p_texture_uniforms[i].global) {
|
||||||
if (V) {
|
|
||||||
texture = V->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!texture.is_valid()) {
|
RasterizerStorageRD *rs = base_singleton;
|
||||||
const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
|
|
||||||
if (W) {
|
|
||||||
|
|
||||||
texture = W->get();
|
uses_global_textures = true;
|
||||||
|
|
||||||
|
GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name);
|
||||||
|
if (v) {
|
||||||
|
if (v->buffer_index >= 0) {
|
||||||
|
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
|
||||||
|
if (!E) {
|
||||||
|
E = used_global_textures.insert(uniform_name, global_textures_pass);
|
||||||
|
v->texture_materials.insert(self);
|
||||||
|
} else {
|
||||||
|
E->get() = global_textures_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = v->override.get_type() != Variant::NIL ? v->override : v->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!texture.is_valid()) {
|
||||||
|
|
||||||
|
const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
|
||||||
|
if (V) {
|
||||||
|
texture = V->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texture.is_valid()) {
|
||||||
|
const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
|
||||||
|
if (W) {
|
||||||
|
|
||||||
|
texture = W->get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1753,6 +1861,36 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
|
||||||
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
|
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
//for textures no longer used, unregister them
|
||||||
|
List<Map<StringName, uint64_t>::Element *> to_delete;
|
||||||
|
RasterizerStorageRD *rs = base_singleton;
|
||||||
|
|
||||||
|
for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
|
||||||
|
if (E->get() != global_textures_pass) {
|
||||||
|
to_delete.push_back(E);
|
||||||
|
|
||||||
|
GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
|
||||||
|
if (v) {
|
||||||
|
v->texture_materials.erase(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (to_delete.front()) {
|
||||||
|
used_global_textures.erase(to_delete.front()->get());
|
||||||
|
to_delete.pop_front();
|
||||||
|
}
|
||||||
|
//handle registering/unregistering global textures
|
||||||
|
if (uses_global_textures != (global_texture_E != nullptr)) {
|
||||||
|
if (uses_global_textures) {
|
||||||
|
global_texture_E = rs->global_variables.materials_using_texture.push_back(self);
|
||||||
|
} else {
|
||||||
|
rs->global_variables.materials_using_texture.erase(global_texture_E);
|
||||||
|
global_texture_E = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
|
void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
|
||||||
|
@ -4627,7 +4765,685 @@ void RasterizerStorageRD::_update_decal_atlas() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t RasterizerStorageRD::_global_variable_allocate(uint32_t p_elements) {
|
||||||
|
|
||||||
|
int32_t idx = 0;
|
||||||
|
while (idx + p_elements <= global_variables.buffer_size) {
|
||||||
|
if (global_variables.buffer_usage[idx].elements == 0) {
|
||||||
|
bool valid = true;
|
||||||
|
for (uint32_t i = 1; i < p_elements; i++) {
|
||||||
|
if (global_variables.buffer_usage[idx + i].elements > 0) {
|
||||||
|
valid = false;
|
||||||
|
idx += i + global_variables.buffer_usage[idx + i].elements;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
continue; //if not valid, idx is in new position
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
} else {
|
||||||
|
idx += global_variables.buffer_usage[idx].elements;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
|
||||||
|
|
||||||
|
switch (p_type) {
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BOOL: {
|
||||||
|
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
bool b = p_value;
|
||||||
|
bv.x = b ? 1.0 : 0.0;
|
||||||
|
bv.y = 0.0;
|
||||||
|
bv.z = 0.0;
|
||||||
|
bv.w = 0.0;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC2: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
uint32_t bvec = p_value;
|
||||||
|
bv.x = (bvec & 1) ? 1.0 : 0.0;
|
||||||
|
bv.y = (bvec & 2) ? 1.0 : 0.0;
|
||||||
|
bv.z = 0.0;
|
||||||
|
bv.w = 0.0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC3: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
uint32_t bvec = p_value;
|
||||||
|
bv.x = (bvec & 1) ? 1.0 : 0.0;
|
||||||
|
bv.y = (bvec & 2) ? 1.0 : 0.0;
|
||||||
|
bv.z = (bvec & 4) ? 1.0 : 0.0;
|
||||||
|
bv.w = 0.0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC4: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
uint32_t bvec = p_value;
|
||||||
|
bv.x = (bvec & 1) ? 1.0 : 0.0;
|
||||||
|
bv.y = (bvec & 2) ? 1.0 : 0.0;
|
||||||
|
bv.z = (bvec & 4) ? 1.0 : 0.0;
|
||||||
|
bv.w = (bvec & 8) ? 1.0 : 0.0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_INT: {
|
||||||
|
GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
|
||||||
|
int32_t v = p_value;
|
||||||
|
bv.x = v;
|
||||||
|
bv.y = 0;
|
||||||
|
bv.z = 0;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC2: {
|
||||||
|
GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Vector2i v = p_value;
|
||||||
|
bv.x = v.x;
|
||||||
|
bv.y = v.y;
|
||||||
|
bv.z = 0;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC3: {
|
||||||
|
GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Vector3i v = p_value;
|
||||||
|
bv.x = v.x;
|
||||||
|
bv.y = v.y;
|
||||||
|
bv.z = v.z;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC4: {
|
||||||
|
GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Vector<int32_t> v = p_value;
|
||||||
|
bv.x = v.size() >= 1 ? v[0] : 0;
|
||||||
|
bv.y = v.size() >= 2 ? v[1] : 0;
|
||||||
|
bv.z = v.size() >= 3 ? v[2] : 0;
|
||||||
|
bv.w = v.size() >= 4 ? v[3] : 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2I: {
|
||||||
|
GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Rect2i v = p_value;
|
||||||
|
bv.x = v.position.x;
|
||||||
|
bv.y = v.position.y;
|
||||||
|
bv.z = v.size.x;
|
||||||
|
bv.w = v.size.y;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UINT: {
|
||||||
|
GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
|
||||||
|
uint32_t v = p_value;
|
||||||
|
bv.x = v;
|
||||||
|
bv.y = 0;
|
||||||
|
bv.z = 0;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC2: {
|
||||||
|
GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Vector2i v = p_value;
|
||||||
|
bv.x = v.x;
|
||||||
|
bv.y = v.y;
|
||||||
|
bv.z = 0;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC3: {
|
||||||
|
GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Vector3i v = p_value;
|
||||||
|
bv.x = v.x;
|
||||||
|
bv.y = v.y;
|
||||||
|
bv.z = v.z;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC4: {
|
||||||
|
GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
|
||||||
|
Vector<int32_t> v = p_value;
|
||||||
|
bv.x = v.size() >= 1 ? v[0] : 0;
|
||||||
|
bv.y = v.size() >= 2 ? v[1] : 0;
|
||||||
|
bv.z = v.size() >= 3 ? v[2] : 0;
|
||||||
|
bv.w = v.size() >= 4 ? v[3] : 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_FLOAT: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
float v = p_value;
|
||||||
|
bv.x = v;
|
||||||
|
bv.y = 0;
|
||||||
|
bv.z = 0;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC2: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
Vector2 v = p_value;
|
||||||
|
bv.x = v.x;
|
||||||
|
bv.y = v.y;
|
||||||
|
bv.z = 0;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC3: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
Vector3 v = p_value;
|
||||||
|
bv.x = v.x;
|
||||||
|
bv.y = v.y;
|
||||||
|
bv.z = v.z;
|
||||||
|
bv.w = 0;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC4: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
Plane v = p_value;
|
||||||
|
bv.x = v.normal.x;
|
||||||
|
bv.y = v.normal.y;
|
||||||
|
bv.z = v.normal.z;
|
||||||
|
bv.w = v.d;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_COLOR: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
Color v = p_value;
|
||||||
|
bv.x = v.r;
|
||||||
|
bv.y = v.g;
|
||||||
|
bv.z = v.b;
|
||||||
|
bv.w = v.a;
|
||||||
|
|
||||||
|
GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
|
||||||
|
v = v.to_linear();
|
||||||
|
bv_linear.x = v.r;
|
||||||
|
bv_linear.y = v.g;
|
||||||
|
bv_linear.z = v.b;
|
||||||
|
bv_linear.w = v.a;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2: {
|
||||||
|
GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
|
||||||
|
Rect2 v = p_value;
|
||||||
|
bv.x = v.position.x;
|
||||||
|
bv.y = v.position.y;
|
||||||
|
bv.z = v.size.x;
|
||||||
|
bv.w = v.size.y;
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT2: {
|
||||||
|
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
|
||||||
|
Vector<float> m2 = p_value;
|
||||||
|
if (m2.size() < 4) {
|
||||||
|
m2.resize(4);
|
||||||
|
}
|
||||||
|
bv[0].x = m2[0];
|
||||||
|
bv[0].y = m2[1];
|
||||||
|
bv[0].z = 0;
|
||||||
|
bv[0].w = 0;
|
||||||
|
|
||||||
|
bv[1].x = m2[2];
|
||||||
|
bv[1].y = m2[3];
|
||||||
|
bv[1].z = 0;
|
||||||
|
bv[1].w = 0;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT3: {
|
||||||
|
|
||||||
|
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
|
||||||
|
Basis v = p_value;
|
||||||
|
bv[0].x = v.elements[0][0];
|
||||||
|
bv[0].y = v.elements[1][0];
|
||||||
|
bv[0].z = v.elements[2][0];
|
||||||
|
bv[0].w = 0;
|
||||||
|
|
||||||
|
bv[1].x = v.elements[0][1];
|
||||||
|
bv[1].y = v.elements[1][1];
|
||||||
|
bv[1].z = v.elements[2][1];
|
||||||
|
bv[1].w = 0;
|
||||||
|
|
||||||
|
bv[2].x = v.elements[0][2];
|
||||||
|
bv[2].y = v.elements[1][2];
|
||||||
|
bv[2].z = v.elements[2][2];
|
||||||
|
bv[2].w = 0;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT4: {
|
||||||
|
|
||||||
|
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
|
||||||
|
|
||||||
|
Vector<float> m2 = p_value;
|
||||||
|
if (m2.size() < 16) {
|
||||||
|
m2.resize(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
bv[0].x = m2[0];
|
||||||
|
bv[0].y = m2[1];
|
||||||
|
bv[0].z = m2[2];
|
||||||
|
bv[0].w = m2[3];
|
||||||
|
|
||||||
|
bv[1].x = m2[4];
|
||||||
|
bv[1].y = m2[5];
|
||||||
|
bv[1].z = m2[6];
|
||||||
|
bv[1].w = m2[7];
|
||||||
|
|
||||||
|
bv[2].x = m2[8];
|
||||||
|
bv[2].y = m2[9];
|
||||||
|
bv[2].z = m2[10];
|
||||||
|
bv[2].w = m2[11];
|
||||||
|
|
||||||
|
bv[3].x = m2[12];
|
||||||
|
bv[3].y = m2[13];
|
||||||
|
bv[3].z = m2[14];
|
||||||
|
bv[3].w = m2[15];
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
|
||||||
|
|
||||||
|
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
|
||||||
|
Transform2D v = p_value;
|
||||||
|
bv[0].x = v.elements[0][0];
|
||||||
|
bv[0].y = v.elements[0][1];
|
||||||
|
bv[0].z = 0;
|
||||||
|
bv[0].w = 0;
|
||||||
|
|
||||||
|
bv[1].x = v.elements[1][0];
|
||||||
|
bv[1].y = v.elements[1][1];
|
||||||
|
bv[1].z = 0;
|
||||||
|
bv[1].w = 0;
|
||||||
|
|
||||||
|
bv[2].x = v.elements[2][0];
|
||||||
|
bv[2].y = v.elements[2][1];
|
||||||
|
bv[2].z = 1;
|
||||||
|
bv[2].w = 0;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
|
||||||
|
|
||||||
|
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
|
||||||
|
Transform v = p_value;
|
||||||
|
bv[0].x = v.basis.elements[0][0];
|
||||||
|
bv[0].y = v.basis.elements[1][0];
|
||||||
|
bv[0].z = v.basis.elements[2][0];
|
||||||
|
bv[0].w = 0;
|
||||||
|
|
||||||
|
bv[1].x = v.basis.elements[0][1];
|
||||||
|
bv[1].y = v.basis.elements[1][1];
|
||||||
|
bv[1].z = v.basis.elements[2][1];
|
||||||
|
bv[1].w = 0;
|
||||||
|
|
||||||
|
bv[2].x = v.basis.elements[0][2];
|
||||||
|
bv[2].y = v.basis.elements[1][2];
|
||||||
|
bv[2].z = v.basis.elements[2][2];
|
||||||
|
bv[2].w = 0;
|
||||||
|
|
||||||
|
bv[2].x = v.origin.x;
|
||||||
|
bv[2].y = v.origin.y;
|
||||||
|
bv[2].z = v.origin.z;
|
||||||
|
bv[2].w = 1;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
ERR_FAIL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
|
||||||
|
|
||||||
|
int32_t prev_chunk = -1;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < p_elements; i++) {
|
||||||
|
int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
|
||||||
|
if (chunk != prev_chunk) {
|
||||||
|
if (!global_variables.buffer_dirty_regions[chunk]) {
|
||||||
|
global_variables.buffer_dirty_regions[chunk] = true;
|
||||||
|
global_variables.buffer_dirty_region_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_chunk = chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
|
||||||
|
|
||||||
|
ERR_FAIL_COND(global_variables.variables.has(p_name));
|
||||||
|
GlobalVariables::Variable gv;
|
||||||
|
gv.type = p_type;
|
||||||
|
gv.value = p_value;
|
||||||
|
gv.buffer_index = -1;
|
||||||
|
|
||||||
|
if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
|
||||||
|
//is texture
|
||||||
|
global_variables.must_update_texture_materials = true; //normally ther are no
|
||||||
|
} else {
|
||||||
|
|
||||||
|
gv.buffer_elements = 1;
|
||||||
|
if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
|
||||||
|
//color needs to elements to store srgb and linear
|
||||||
|
gv.buffer_elements = 2;
|
||||||
|
}
|
||||||
|
if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
|
||||||
|
//color needs to elements to store srgb and linear
|
||||||
|
gv.buffer_elements = 3;
|
||||||
|
}
|
||||||
|
if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
|
||||||
|
//color needs to elements to store srgb and linear
|
||||||
|
gv.buffer_elements = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//is vector, allocate in buffer and update index
|
||||||
|
gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
|
||||||
|
ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
|
||||||
|
global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
|
||||||
|
_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
|
||||||
|
_global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
|
||||||
|
|
||||||
|
global_variables.must_update_buffer_materials = true; //normally ther are no
|
||||||
|
}
|
||||||
|
|
||||||
|
global_variables.variables[p_name] = gv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::global_variable_remove(const StringName &p_name) {
|
||||||
|
if (!global_variables.variables.has(p_name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GlobalVariables::Variable &gv = global_variables.variables[p_name];
|
||||||
|
|
||||||
|
if (gv.buffer_index >= 0) {
|
||||||
|
global_variables.buffer_usage[gv.buffer_index].elements = 0;
|
||||||
|
global_variables.must_update_buffer_materials = true;
|
||||||
|
} else {
|
||||||
|
global_variables.must_update_texture_materials = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_variables.variables.erase(p_name);
|
||||||
|
}
|
||||||
|
Vector<StringName> RasterizerStorageRD::global_variable_get_list() const {
|
||||||
|
|
||||||
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const StringName *K = NULL;
|
||||||
|
Vector<StringName> names;
|
||||||
|
while ((K = global_variables.variables.next(K))) {
|
||||||
|
names.push_back(*K);
|
||||||
|
}
|
||||||
|
names.sort_custom<StringName::AlphCompare>();
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
ERR_FAIL_COND(!global_variables.variables.has(p_name));
|
||||||
|
GlobalVariables::Variable &gv = global_variables.variables[p_name];
|
||||||
|
gv.value = p_value;
|
||||||
|
if (gv.override.get_type() == Variant::NIL) {
|
||||||
|
if (gv.buffer_index >= 0) {
|
||||||
|
//buffer
|
||||||
|
_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
|
||||||
|
_global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
|
||||||
|
} else {
|
||||||
|
//texture
|
||||||
|
for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
|
||||||
|
Material *material = material_owner.getornull(E->get());
|
||||||
|
ERR_CONTINUE(!material);
|
||||||
|
_material_queue_update(material, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void RasterizerStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
|
||||||
|
if (!global_variables.variables.has(p_name)) {
|
||||||
|
return; //variable may not exist
|
||||||
|
}
|
||||||
|
GlobalVariables::Variable &gv = global_variables.variables[p_name];
|
||||||
|
|
||||||
|
gv.override = p_value;
|
||||||
|
|
||||||
|
if (gv.buffer_index >= 0) {
|
||||||
|
//buffer
|
||||||
|
if (gv.override.get_type() == Variant::NIL) {
|
||||||
|
_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
|
||||||
|
} else {
|
||||||
|
_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
|
||||||
|
}
|
||||||
|
|
||||||
|
_global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
|
||||||
|
} else {
|
||||||
|
//texture
|
||||||
|
//texture
|
||||||
|
for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
|
||||||
|
Material *material = material_owner.getornull(E->get());
|
||||||
|
ERR_CONTINUE(!material);
|
||||||
|
_material_queue_update(material, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant RasterizerStorageRD::global_variable_get(const StringName &p_name) const {
|
||||||
|
|
||||||
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global_variables.variables.has(p_name)) {
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_variables.variables[p_name].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type_internal(const StringName &p_name) const {
|
||||||
|
|
||||||
|
if (!global_variables.variables.has(p_name)) {
|
||||||
|
return RS::GLOBAL_VAR_TYPE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_variables.variables[p_name].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type(const StringName &p_name) const {
|
||||||
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_variable_get_type_internal(p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::global_variables_load_settings(bool p_load_textures) {
|
||||||
|
|
||||||
|
List<PropertyInfo> settings;
|
||||||
|
ProjectSettings::get_singleton()->get_property_list(&settings);
|
||||||
|
|
||||||
|
for (List<PropertyInfo>::Element *E = settings.front(); E; E = E->next()) {
|
||||||
|
if (E->get().name.begins_with("shader_globals/")) {
|
||||||
|
StringName name = E->get().name.get_slice("/", 1);
|
||||||
|
Dictionary d = ProjectSettings::get_singleton()->get(E->get().name);
|
||||||
|
|
||||||
|
ERR_CONTINUE(!d.has("type"));
|
||||||
|
ERR_CONTINUE(!d.has("value"));
|
||||||
|
|
||||||
|
String type = d["type"];
|
||||||
|
|
||||||
|
static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
|
||||||
|
"bool",
|
||||||
|
"bvec2",
|
||||||
|
"bvec3",
|
||||||
|
"bvec4",
|
||||||
|
"int",
|
||||||
|
"ivec2",
|
||||||
|
"ivec3",
|
||||||
|
"ivec4",
|
||||||
|
"rect2i",
|
||||||
|
"uint",
|
||||||
|
"uvec2",
|
||||||
|
"uvec3",
|
||||||
|
"uvec4",
|
||||||
|
"float",
|
||||||
|
"vec2",
|
||||||
|
"vec3",
|
||||||
|
"vec4",
|
||||||
|
"color",
|
||||||
|
"rect2",
|
||||||
|
"mat2",
|
||||||
|
"mat3",
|
||||||
|
"mat4",
|
||||||
|
"transform_2d",
|
||||||
|
"transform",
|
||||||
|
"sampler2D",
|
||||||
|
"sampler2DArray",
|
||||||
|
"sampler3D",
|
||||||
|
"samplerCube",
|
||||||
|
};
|
||||||
|
|
||||||
|
RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
|
||||||
|
|
||||||
|
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
|
||||||
|
if (global_var_type_names[i] == type) {
|
||||||
|
gvtype = RS::GlobalVariableType(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
|
||||||
|
|
||||||
|
Variant value = d["value"];
|
||||||
|
|
||||||
|
if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
|
||||||
|
//textire
|
||||||
|
if (!p_load_textures) {
|
||||||
|
value = RID();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = value;
|
||||||
|
RES resource = ResourceLoader::load(path);
|
||||||
|
ERR_CONTINUE(resource.is_null());
|
||||||
|
value = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_variables.variables.has(name)) {
|
||||||
|
//has it, update it
|
||||||
|
global_variable_set(name, value);
|
||||||
|
} else {
|
||||||
|
global_variable_add(name, gvtype, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::global_variables_clear() {
|
||||||
|
global_variables.variables.clear(); //not right but for now enough
|
||||||
|
}
|
||||||
|
|
||||||
|
RID RasterizerStorageRD::global_variables_get_storage_buffer() const {
|
||||||
|
return global_variables.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t RasterizerStorageRD::global_variables_instance_allocate(RID p_instance) {
|
||||||
|
ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
|
||||||
|
int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
|
||||||
|
global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
|
||||||
|
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
|
||||||
|
global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::global_variables_instance_free(RID p_instance) {
|
||||||
|
ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
|
||||||
|
int32_t pos = global_variables.instance_buffer_pos[p_instance];
|
||||||
|
if (pos >= 0) {
|
||||||
|
global_variables.buffer_usage[pos].elements = 0;
|
||||||
|
}
|
||||||
|
global_variables.instance_buffer_pos.erase(p_instance);
|
||||||
|
}
|
||||||
|
void RasterizerStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
|
||||||
|
|
||||||
|
if (!global_variables.instance_buffer_pos.has(p_instance)) {
|
||||||
|
return; //just not allocated, ignore
|
||||||
|
}
|
||||||
|
int32_t pos = global_variables.instance_buffer_pos[p_instance];
|
||||||
|
|
||||||
|
if (pos < 0) {
|
||||||
|
return; //again, not allocated, ignore
|
||||||
|
}
|
||||||
|
ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
|
||||||
|
ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
|
||||||
|
|
||||||
|
ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
|
||||||
|
ShaderLanguage::TYPE_MAX, //nil
|
||||||
|
ShaderLanguage::TYPE_BOOL, //bool
|
||||||
|
ShaderLanguage::TYPE_INT, //int
|
||||||
|
ShaderLanguage::TYPE_FLOAT, //float
|
||||||
|
ShaderLanguage::TYPE_MAX, //string
|
||||||
|
ShaderLanguage::TYPE_VEC2, //vec2
|
||||||
|
ShaderLanguage::TYPE_IVEC2, //vec2i
|
||||||
|
ShaderLanguage::TYPE_VEC4, //rect2
|
||||||
|
ShaderLanguage::TYPE_IVEC4, //rect2i
|
||||||
|
ShaderLanguage::TYPE_VEC3, // vec3
|
||||||
|
ShaderLanguage::TYPE_IVEC3, //vec3i
|
||||||
|
ShaderLanguage::TYPE_MAX, //xform2d not supported here
|
||||||
|
ShaderLanguage::TYPE_VEC4, //plane
|
||||||
|
ShaderLanguage::TYPE_VEC4, //quat
|
||||||
|
ShaderLanguage::TYPE_MAX, //aabb not supported here
|
||||||
|
ShaderLanguage::TYPE_MAX, //basis not supported here
|
||||||
|
ShaderLanguage::TYPE_MAX, //xform not supported here
|
||||||
|
ShaderLanguage::TYPE_VEC4 //color
|
||||||
|
};
|
||||||
|
|
||||||
|
ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
|
||||||
|
|
||||||
|
ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
|
||||||
|
|
||||||
|
pos += p_index;
|
||||||
|
|
||||||
|
_fill_std140_variant_ubo_value(datatype, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
|
||||||
|
_global_variable_mark_buffer_dirty(pos, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::_update_global_variables() {
|
||||||
|
|
||||||
|
if (global_variables.buffer_dirty_region_count > 0) {
|
||||||
|
uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
|
||||||
|
if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
|
||||||
|
// 25% of regions dirty, just update all buffer
|
||||||
|
RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
|
||||||
|
zeromem(global_variables.buffer_dirty_regions, sizeof(bool) * total_regions);
|
||||||
|
} else {
|
||||||
|
uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < total_regions; i++) {
|
||||||
|
if (global_variables.buffer_dirty_regions[i]) {
|
||||||
|
|
||||||
|
RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, global_variables.buffer_values);
|
||||||
|
|
||||||
|
global_variables.buffer_dirty_regions[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_variables.buffer_dirty_region_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_variables.must_update_buffer_materials) {
|
||||||
|
// only happens in the case of a buffer variable added or removed,
|
||||||
|
// so not often.
|
||||||
|
for (List<RID>::Element *E = global_variables.materials_using_buffer.front(); E; E = E->next()) {
|
||||||
|
Material *material = material_owner.getornull(E->get());
|
||||||
|
ERR_CONTINUE(!material); //wtf
|
||||||
|
|
||||||
|
_material_queue_update(material, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
global_variables.must_update_buffer_materials = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_variables.must_update_texture_materials) {
|
||||||
|
// only happens in the case of a buffer variable added or removed,
|
||||||
|
// so not often.
|
||||||
|
for (List<RID>::Element *E = global_variables.materials_using_texture.front(); E; E = E->next()) {
|
||||||
|
Material *material = material_owner.getornull(E->get());
|
||||||
|
ERR_CONTINUE(!material); //wtf
|
||||||
|
|
||||||
|
_material_queue_update(material, false, true);
|
||||||
|
print_line("update material texture?");
|
||||||
|
}
|
||||||
|
|
||||||
|
global_variables.must_update_texture_materials = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::update_dirty_resources() {
|
void RasterizerStorageRD::update_dirty_resources() {
|
||||||
|
_update_global_variables(); //must do before materials, so it can queue them for update
|
||||||
_update_queued_materials();
|
_update_queued_materials();
|
||||||
_update_dirty_multimeshes();
|
_update_dirty_multimeshes();
|
||||||
_update_dirty_skeletons();
|
_update_dirty_skeletons();
|
||||||
|
@ -4806,12 +5622,27 @@ String RasterizerStorageRD::get_captured_timestamp_name(uint32_t p_index) const
|
||||||
return RD::get_singleton()->get_captured_timestamp_name(p_index);
|
return RD::get_singleton()->get_captured_timestamp_name(p_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RasterizerStorageRD *RasterizerStorageRD::base_singleton = nullptr;
|
||||||
|
|
||||||
RasterizerStorageRD::RasterizerStorageRD() {
|
RasterizerStorageRD::RasterizerStorageRD() {
|
||||||
|
|
||||||
|
base_singleton = this;
|
||||||
|
|
||||||
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
|
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
|
||||||
shader_data_request_func[i] = nullptr;
|
shader_data_request_func[i] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assert(sizeof(GlobalVariables::Value) == 16);
|
||||||
|
|
||||||
|
global_variables.buffer_size = GLOBAL_GET("rendering/high_end/global_shader_variables_buffer_size");
|
||||||
|
global_variables.buffer_size = MAX(4096, global_variables.buffer_size);
|
||||||
|
global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
|
||||||
|
zeromem(global_variables.buffer_values, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
|
||||||
|
global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
|
||||||
|
global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
|
||||||
|
zeromem(global_variables.buffer_dirty_regions, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
|
||||||
|
global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
|
||||||
|
|
||||||
material_update_list = nullptr;
|
material_update_list = nullptr;
|
||||||
{ //create default textures
|
{ //create default textures
|
||||||
|
|
||||||
|
@ -5165,6 +5996,11 @@ RasterizerStorageRD::RasterizerStorageRD() {
|
||||||
|
|
||||||
RasterizerStorageRD::~RasterizerStorageRD() {
|
RasterizerStorageRD::~RasterizerStorageRD() {
|
||||||
|
|
||||||
|
memdelete_arr(global_variables.buffer_values);
|
||||||
|
memdelete_arr(global_variables.buffer_usage);
|
||||||
|
memdelete_arr(global_variables.buffer_dirty_regions);
|
||||||
|
RD::get_singleton()->free(global_variables.buffer);
|
||||||
|
|
||||||
//def textures
|
//def textures
|
||||||
for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
|
for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
|
||||||
RD::get_singleton()->free(default_rd_textures[i]);
|
RD::get_singleton()->free(default_rd_textures[i]);
|
||||||
|
|
|
@ -52,6 +52,8 @@ public:
|
||||||
virtual void set_code(const String &p_Code) = 0;
|
virtual void set_code(const String &p_Code) = 0;
|
||||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
|
virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
|
||||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
|
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
|
||||||
|
|
||||||
|
virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
|
||||||
virtual bool is_param_texture(const StringName &p_param) const = 0;
|
virtual bool is_param_texture(const StringName &p_param) const = 0;
|
||||||
virtual bool is_animated() const = 0;
|
virtual bool is_animated() const = 0;
|
||||||
virtual bool casts_shadows() const = 0;
|
virtual bool casts_shadows() const = 0;
|
||||||
|
@ -69,7 +71,15 @@ public:
|
||||||
virtual void set_render_priority(int p_priority) = 0;
|
virtual void set_render_priority(int p_priority) = 0;
|
||||||
virtual void set_next_pass(RID p_pass) = 0;
|
virtual void set_next_pass(RID p_pass) = 0;
|
||||||
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
|
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
|
||||||
virtual ~MaterialData() {}
|
virtual ~MaterialData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class RasterizerStorageRD;
|
||||||
|
RID self;
|
||||||
|
List<RID>::Element *global_buffer_E = nullptr;
|
||||||
|
List<RID>::Element *global_texture_E = nullptr;
|
||||||
|
uint64_t global_textures_pass = 0;
|
||||||
|
Map<StringName, uint64_t> used_global_textures;
|
||||||
};
|
};
|
||||||
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
|
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
|
||||||
|
|
||||||
|
@ -555,6 +565,73 @@ private:
|
||||||
void _update_render_target(RenderTarget *rt);
|
void _update_render_target(RenderTarget *rt);
|
||||||
void _create_render_target_backbuffer(RenderTarget *rt);
|
void _create_render_target_backbuffer(RenderTarget *rt);
|
||||||
|
|
||||||
|
/* GLOBAL SHADER VARIABLES */
|
||||||
|
|
||||||
|
struct GlobalVariables {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BUFFER_DIRTY_REGION_SIZE = 1024
|
||||||
|
};
|
||||||
|
struct Variable {
|
||||||
|
Set<RID> texture_materials; // materials using this
|
||||||
|
|
||||||
|
RS::GlobalVariableType type;
|
||||||
|
Variant value;
|
||||||
|
Variant override;
|
||||||
|
int32_t buffer_index; //for vectors
|
||||||
|
int32_t buffer_elements; //for vectors
|
||||||
|
};
|
||||||
|
|
||||||
|
HashMap<StringName, Variable> variables;
|
||||||
|
|
||||||
|
struct Value {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueInt {
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int32_t z;
|
||||||
|
int32_t w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueUInt {
|
||||||
|
uint32_t x;
|
||||||
|
uint32_t y;
|
||||||
|
uint32_t z;
|
||||||
|
uint32_t w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueUsage {
|
||||||
|
uint32_t elements = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
List<RID> materials_using_buffer;
|
||||||
|
List<RID> materials_using_texture;
|
||||||
|
|
||||||
|
RID buffer;
|
||||||
|
Value *buffer_values;
|
||||||
|
ValueUsage *buffer_usage;
|
||||||
|
bool *buffer_dirty_regions;
|
||||||
|
uint32_t buffer_dirty_region_count = 0;
|
||||||
|
|
||||||
|
uint32_t buffer_size;
|
||||||
|
|
||||||
|
bool must_update_texture_materials = false;
|
||||||
|
bool must_update_buffer_materials = false;
|
||||||
|
|
||||||
|
HashMap<RID, int32_t> instance_buffer_pos;
|
||||||
|
|
||||||
|
} global_variables;
|
||||||
|
|
||||||
|
int32_t _global_variable_allocate(uint32_t p_elements);
|
||||||
|
void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
|
||||||
|
void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
|
||||||
|
|
||||||
|
void _update_global_variables();
|
||||||
/* EFFECTS */
|
/* EFFECTS */
|
||||||
|
|
||||||
RasterizerEffectsRD effects;
|
RasterizerEffectsRD effects;
|
||||||
|
@ -675,6 +752,8 @@ public:
|
||||||
bool material_is_animated(RID p_material);
|
bool material_is_animated(RID p_material);
|
||||||
bool material_casts_shadows(RID p_material);
|
bool material_casts_shadows(RID p_material);
|
||||||
|
|
||||||
|
void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
|
||||||
|
|
||||||
void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance);
|
void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance);
|
||||||
void material_force_update_textures(RID p_material, ShaderType p_shader_type);
|
void material_force_update_textures(RID p_material, ShaderType p_shader_type);
|
||||||
|
|
||||||
|
@ -1246,6 +1325,27 @@ public:
|
||||||
|
|
||||||
virtual bool particles_is_inactive(RID p_particles) const { return false; }
|
virtual bool particles_is_inactive(RID p_particles) const { return false; }
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES API */
|
||||||
|
|
||||||
|
virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
|
||||||
|
virtual void global_variable_remove(const StringName &p_name);
|
||||||
|
virtual Vector<StringName> global_variable_get_list() const;
|
||||||
|
|
||||||
|
virtual void global_variable_set(const StringName &p_name, const Variant &p_value);
|
||||||
|
virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value);
|
||||||
|
virtual Variant global_variable_get(const StringName &p_name) const;
|
||||||
|
virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const;
|
||||||
|
RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
|
||||||
|
|
||||||
|
virtual void global_variables_load_settings(bool p_load_textures = true);
|
||||||
|
virtual void global_variables_clear();
|
||||||
|
|
||||||
|
virtual int32_t global_variables_instance_allocate(RID p_instance);
|
||||||
|
virtual void global_variables_instance_free(RID p_instance);
|
||||||
|
virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value);
|
||||||
|
|
||||||
|
RID global_variables_get_storage_buffer() const;
|
||||||
|
|
||||||
/* RENDER TARGET API */
|
/* RENDER TARGET API */
|
||||||
|
|
||||||
RID render_target_create();
|
RID render_target_create();
|
||||||
|
@ -1295,7 +1395,7 @@ public:
|
||||||
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
|
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
|
||||||
virtual String get_captured_timestamp_name(uint32_t p_index) const;
|
virtual String get_captured_timestamp_name(uint32_t p_index) const;
|
||||||
|
|
||||||
static RasterizerStorage *base_singleton;
|
static RasterizerStorageRD *base_singleton;
|
||||||
|
|
||||||
RasterizerEffectsRD *get_effects();
|
RasterizerEffectsRD *get_effects();
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/project_settings.h"
|
#include "core/project_settings.h"
|
||||||
|
#include "rasterizer_storage_rd.h"
|
||||||
|
#include "servers/rendering_server.h"
|
||||||
|
|
||||||
#define SL ShaderLanguage
|
#define SL ShaderLanguage
|
||||||
|
|
||||||
|
@ -91,6 +93,9 @@ static int _get_datatype_size(SL::DataType p_type) {
|
||||||
case SL::TYPE_USAMPLER3D: return 16;
|
case SL::TYPE_USAMPLER3D: return 16;
|
||||||
case SL::TYPE_SAMPLERCUBE: return 16;
|
case SL::TYPE_SAMPLERCUBE: return 16;
|
||||||
case SL::TYPE_STRUCT: return 0;
|
case SL::TYPE_STRUCT: return 0;
|
||||||
|
case SL::TYPE_MAX: {
|
||||||
|
ERR_FAIL_V(0);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_V(0);
|
ERR_FAIL_V(0);
|
||||||
|
@ -131,6 +136,9 @@ static int _get_datatype_alignment(SL::DataType p_type) {
|
||||||
case SL::TYPE_USAMPLER3D: return 16;
|
case SL::TYPE_USAMPLER3D: return 16;
|
||||||
case SL::TYPE_SAMPLERCUBE: return 16;
|
case SL::TYPE_SAMPLERCUBE: return 16;
|
||||||
case SL::TYPE_STRUCT: return 0;
|
case SL::TYPE_STRUCT: return 0;
|
||||||
|
case SL::TYPE_MAX: {
|
||||||
|
ERR_FAIL_V(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_V(0);
|
ERR_FAIL_V(0);
|
||||||
|
@ -341,6 +349,71 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
|
||||||
|
switch (p_type) {
|
||||||
|
case ShaderLanguage::TYPE_BOOL: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].x != 0.0)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_BVEC2: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].xy != vec2(0.0))";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_BVEC3: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].xyz != vec3(0.0))";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_BVEC4: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].xyzw != vec4(0.0))";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_INT: {
|
||||||
|
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].x)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_IVEC2: {
|
||||||
|
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xy)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_IVEC3: {
|
||||||
|
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyz)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_IVEC4: {
|
||||||
|
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyzw)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_UINT: {
|
||||||
|
return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].x)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_UVEC2: {
|
||||||
|
return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xy)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_UVEC3: {
|
||||||
|
return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xyz)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_UVEC4: {
|
||||||
|
return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xyzw)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_FLOAT: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].x)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_VEC2: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].xy)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_VEC3: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].xyz)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_VEC4: {
|
||||||
|
return "(" + p_buffer + "[" + p_index + "].xyzw)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_MAT2: {
|
||||||
|
return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1].xy)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_MAT3: {
|
||||||
|
return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1].xyz," + p_buffer + "[" + p_index + "+2].xyz)";
|
||||||
|
}
|
||||||
|
case ShaderLanguage::TYPE_MAT4: {
|
||||||
|
return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1].xyzw," + p_buffer + "[" + p_index + "+2].xyzw," + p_buffer + "[" + p_index + "+3].xyzw)";
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
ERR_FAIL_V("void");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) {
|
String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) {
|
||||||
|
|
||||||
String code;
|
String code;
|
||||||
|
@ -408,10 +481,17 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||||
int max_uniforms = 0;
|
int max_uniforms = 0;
|
||||||
|
|
||||||
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
|
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
|
||||||
if (SL::is_sampler_type(E->get().type))
|
|
||||||
|
if (SL::is_sampler_type(E->get().type)) {
|
||||||
max_texture_uniforms++;
|
max_texture_uniforms++;
|
||||||
else
|
} else {
|
||||||
|
|
||||||
|
if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
continue; //instances are indexed directly, dont need index uniforms
|
||||||
|
}
|
||||||
|
|
||||||
max_uniforms++;
|
max_uniforms++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
|
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
|
||||||
|
@ -428,12 +508,25 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||||
|
|
||||||
String ucode;
|
String ucode;
|
||||||
|
|
||||||
|
if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
//insert, but don't generate any code.
|
||||||
|
p_actions.uniforms->insert(E->key(), E->get());
|
||||||
|
continue; //instances are indexed directly, dont need index uniforms
|
||||||
|
}
|
||||||
if (SL::is_sampler_type(E->get().type)) {
|
if (SL::is_sampler_type(E->get().type)) {
|
||||||
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + E->get().texture_order) + ") uniform ";
|
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + E->get().texture_order) + ") uniform ";
|
||||||
}
|
}
|
||||||
|
|
||||||
ucode += _prestr(E->get().precision);
|
bool is_buffer_global = !SL::is_sampler_type(E->get().type) && E->get().scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
|
||||||
ucode += _typestr(E->get().type);
|
|
||||||
|
if (is_buffer_global) {
|
||||||
|
//this is an integer to index the global table
|
||||||
|
ucode += _typestr(ShaderLanguage::TYPE_UINT);
|
||||||
|
} else {
|
||||||
|
ucode += _prestr(E->get().precision);
|
||||||
|
ucode += _typestr(E->get().type);
|
||||||
|
}
|
||||||
|
|
||||||
ucode += " " + _mkid(E->key());
|
ucode += " " + _mkid(E->key());
|
||||||
ucode += ";\n";
|
ucode += ";\n";
|
||||||
if (SL::is_sampler_type(E->get().type)) {
|
if (SL::is_sampler_type(E->get().type)) {
|
||||||
|
@ -446,6 +539,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||||
texture.type = E->get().type;
|
texture.type = E->get().type;
|
||||||
texture.filter = E->get().filter;
|
texture.filter = E->get().filter;
|
||||||
texture.repeat = E->get().repeat;
|
texture.repeat = E->get().repeat;
|
||||||
|
texture.global = E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
|
||||||
|
if (texture.global) {
|
||||||
|
r_gen_code.uses_global_textures = true;
|
||||||
|
}
|
||||||
|
|
||||||
r_gen_code.texture_uniforms.write[E->get().texture_order] = texture;
|
r_gen_code.texture_uniforms.write[E->get().texture_order] = texture;
|
||||||
} else {
|
} else {
|
||||||
|
@ -455,8 +552,14 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||||
uses_uniforms = true;
|
uses_uniforms = true;
|
||||||
}
|
}
|
||||||
uniform_defines.write[E->get().order] = ucode;
|
uniform_defines.write[E->get().order] = ucode;
|
||||||
uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type);
|
if (is_buffer_global) {
|
||||||
uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type);
|
//globals are indices into the global table
|
||||||
|
uniform_sizes.write[E->get().order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
|
||||||
|
uniform_alignments.write[E->get().order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
|
||||||
|
} else {
|
||||||
|
uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type);
|
||||||
|
uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p_actions.uniforms->insert(E->key(), E->get());
|
p_actions.uniforms->insert(E->key(), E->get());
|
||||||
|
@ -690,9 +793,29 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||||
if (p_default_actions.renames.has(vnode->name))
|
if (p_default_actions.renames.has(vnode->name))
|
||||||
code = p_default_actions.renames[vnode->name];
|
code = p_default_actions.renames[vnode->name];
|
||||||
else {
|
else {
|
||||||
code = _mkid(vnode->name);
|
if (shader->uniforms.has(vnode->name)) {
|
||||||
if (actions.base_uniform_string != String() && shader->uniforms.has(vnode->name) && shader->uniforms[vnode->name].texture_order < 0) {
|
//its a uniform!
|
||||||
code = actions.base_uniform_string + code;
|
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
|
||||||
|
if (u.texture_order >= 0) {
|
||||||
|
code = _mkid(vnode->name); //texture, use as is
|
||||||
|
} else {
|
||||||
|
//a scalar or vector
|
||||||
|
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
|
||||||
|
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
|
||||||
|
//global variable, this means the code points to an index to the global table
|
||||||
|
code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
|
||||||
|
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
//instance variable, index it as such
|
||||||
|
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
|
||||||
|
code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
|
||||||
|
} else {
|
||||||
|
//regular uniform, index from UBO
|
||||||
|
code = actions.base_uniform_string + _mkid(vnode->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
code = _mkid(vnode->name); //its something else (local var most likely) use as is
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,9 +1160,14 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderLanguage::DataType ShaderCompilerRD::_get_variable_type(const StringName &p_type) {
|
||||||
|
RS::GlobalVariableType gvt = ((RasterizerStorageRD *)(RasterizerStorage::base_singleton))->global_variable_get_type_internal(p_type);
|
||||||
|
return RS::global_variable_type_get_shader_datatype(gvt);
|
||||||
|
}
|
||||||
|
|
||||||
Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
|
Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
|
||||||
|
|
||||||
Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types());
|
Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types(), _get_variable_type);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
|
|
||||||
|
@ -1060,6 +1188,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
|
||||||
r_gen_code.light = String();
|
r_gen_code.light = String();
|
||||||
r_gen_code.uses_fragment_time = false;
|
r_gen_code.uses_fragment_time = false;
|
||||||
r_gen_code.uses_vertex_time = false;
|
r_gen_code.uses_vertex_time = false;
|
||||||
|
r_gen_code.uses_global_textures = false;
|
||||||
|
|
||||||
used_name_defines.clear();
|
used_name_defines.clear();
|
||||||
used_rmode_defines.clear();
|
used_rmode_defines.clear();
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
ShaderLanguage::ShaderNode::Uniform::Hint hint;
|
ShaderLanguage::ShaderNode::Uniform::Hint hint;
|
||||||
ShaderLanguage::TextureFilter filter;
|
ShaderLanguage::TextureFilter filter;
|
||||||
ShaderLanguage::TextureRepeat repeat;
|
ShaderLanguage::TextureRepeat repeat;
|
||||||
|
bool global;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<Texture> texture_uniforms;
|
Vector<Texture> texture_uniforms;
|
||||||
|
@ -70,6 +71,7 @@ public:
|
||||||
String fragment;
|
String fragment;
|
||||||
String light;
|
String light;
|
||||||
|
|
||||||
|
bool uses_global_textures;
|
||||||
bool uses_fragment_time;
|
bool uses_fragment_time;
|
||||||
bool uses_vertex_time;
|
bool uses_vertex_time;
|
||||||
};
|
};
|
||||||
|
@ -86,6 +88,8 @@ public:
|
||||||
int base_texture_binding_index = 0;
|
int base_texture_binding_index = 0;
|
||||||
int texture_layout_set = 0;
|
int texture_layout_set = 0;
|
||||||
String base_uniform_string;
|
String base_uniform_string;
|
||||||
|
String global_buffer_array_variable;
|
||||||
|
String instance_uniform_index_variable;
|
||||||
uint32_t base_varying_index = 0;
|
uint32_t base_varying_index = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,6 +117,8 @@ private:
|
||||||
|
|
||||||
DefaultIdentifierActions actions;
|
DefaultIdentifierActions actions;
|
||||||
|
|
||||||
|
static ShaderLanguage::DataType _get_variable_type(const StringName &p_type);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
|
Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,11 @@ layout(set = 2, binding = 6) uniform sampler shadow_sampler;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
layout(set = 2, binding = 7, std430) restrict readonly buffer GlobalVariableData {
|
||||||
|
vec4 data[];
|
||||||
|
}
|
||||||
|
global_variables;
|
||||||
|
|
||||||
/* SET3: Render Target Data */
|
/* SET3: Render Target Data */
|
||||||
|
|
||||||
#ifdef SCREEN_TEXTURE_USED
|
#ifdef SCREEN_TEXTURE_USED
|
||||||
|
|
|
@ -134,7 +134,7 @@ struct InstanceData {
|
||||||
mat4 transform;
|
mat4 transform;
|
||||||
mat4 normal_transform;
|
mat4 normal_transform;
|
||||||
uint flags;
|
uint flags;
|
||||||
uint instance_ofs; //instance_offset in instancing/skeleton buffer
|
uint instance_uniforms_ofs; //base offset in global buffer for instance variables
|
||||||
uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
|
uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
|
||||||
uint layer_mask;
|
uint layer_mask;
|
||||||
};
|
};
|
||||||
|
@ -287,6 +287,11 @@ cluster_data;
|
||||||
|
|
||||||
layout(set = 0, binding = 15) uniform texture2D directional_shadow_atlas;
|
layout(set = 0, binding = 15) uniform texture2D directional_shadow_atlas;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 16, std430) restrict readonly buffer GlobalVariableData {
|
||||||
|
vec4 data[];
|
||||||
|
}
|
||||||
|
global_variables;
|
||||||
|
|
||||||
// decal atlas
|
// decal atlas
|
||||||
|
|
||||||
/* Set 1, Radiance */
|
/* Set 1, Radiance */
|
||||||
|
|
|
@ -58,6 +58,11 @@ params;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
|
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
|
||||||
|
|
||||||
|
layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
|
||||||
|
vec4 data[];
|
||||||
|
}
|
||||||
|
global_variables;
|
||||||
|
|
||||||
#ifdef USE_MATERIAL_UNIFORMS
|
#ifdef USE_MATERIAL_UNIFORMS
|
||||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
|
@ -1025,7 +1025,6 @@ public:
|
||||||
virtual uint32_t get_frame_delay() const = 0;
|
virtual uint32_t get_frame_delay() const = 0;
|
||||||
|
|
||||||
static RenderingDevice *get_singleton();
|
static RenderingDevice *get_singleton();
|
||||||
|
|
||||||
RenderingDevice();
|
RenderingDevice();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,8 @@ public:
|
||||||
|
|
||||||
#define BIND0R(m_r, m_name) \
|
#define BIND0R(m_r, m_name) \
|
||||||
m_r m_name() { return BINDBASE->m_name(); }
|
m_r m_name() { return BINDBASE->m_name(); }
|
||||||
|
#define BIND0RC(m_r, m_name) \
|
||||||
|
m_r m_name() const { return BINDBASE->m_name(); }
|
||||||
#define BIND1R(m_r, m_name, m_type1) \
|
#define BIND1R(m_r, m_name, m_type1) \
|
||||||
m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
|
m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
|
||||||
#define BIND1RC(m_r, m_name, m_type1) \
|
#define BIND1RC(m_r, m_name, m_type1) \
|
||||||
|
@ -111,8 +113,12 @@ public:
|
||||||
#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
|
#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
|
||||||
m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
|
m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
|
||||||
|
|
||||||
|
#define BIND0(m_name) \
|
||||||
|
void m_name() { DISPLAY_CHANGED BINDBASE->m_name(); }
|
||||||
#define BIND1(m_name, m_type1) \
|
#define BIND1(m_name, m_type1) \
|
||||||
void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
|
void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
|
||||||
|
#define BIND1C(m_name, m_type1) \
|
||||||
|
void m_name(m_type1 arg1) const { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
|
||||||
#define BIND2(m_name, m_type1, m_type2) \
|
#define BIND2(m_name, m_type1, m_type2) \
|
||||||
void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); }
|
void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); }
|
||||||
#define BIND2C(m_name, m_type1, m_type2) \
|
#define BIND2C(m_name, m_type1, m_type2) \
|
||||||
|
@ -620,6 +626,11 @@ public:
|
||||||
BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||||
BIND2(instance_geometry_set_as_instance_lod, RID, RID)
|
BIND2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||||
|
|
||||||
|
BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
|
||||||
|
BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
|
||||||
|
BIND2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
|
||||||
|
BIND2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
|
||||||
|
|
||||||
#undef BINDBASE
|
#undef BINDBASE
|
||||||
//from now on, calls forwarded to this singleton
|
//from now on, calls forwarded to this singleton
|
||||||
#define BINDBASE RSG::canvas
|
#define BINDBASE RSG::canvas
|
||||||
|
@ -717,6 +728,23 @@ public:
|
||||||
|
|
||||||
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES */
|
||||||
|
|
||||||
|
#undef BINDBASE
|
||||||
|
//from now on, calls forwarded to this singleton
|
||||||
|
#define BINDBASE RSG::storage
|
||||||
|
|
||||||
|
BIND3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
|
||||||
|
BIND1(global_variable_remove, const StringName &)
|
||||||
|
BIND0RC(Vector<StringName>, global_variable_get_list)
|
||||||
|
BIND2(global_variable_set, const StringName &, const Variant &)
|
||||||
|
BIND2(global_variable_set_override, const StringName &, const Variant &)
|
||||||
|
BIND1RC(GlobalVariableType, global_variable_get_type, const StringName &)
|
||||||
|
BIND1RC(Variant, global_variable_get, const StringName &)
|
||||||
|
|
||||||
|
BIND1(global_variables_load_settings, bool)
|
||||||
|
BIND0(global_variables_clear)
|
||||||
|
|
||||||
/* BLACK BARS */
|
/* BLACK BARS */
|
||||||
|
|
||||||
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
|
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
|
||||||
|
|
|
@ -968,6 +968,67 @@ void RenderingServerScene::instance_geometry_set_draw_range(RID p_instance, floa
|
||||||
void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
|
void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingServerScene::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
|
||||||
|
|
||||||
|
Instance *instance = instance_owner.getornull(p_instance);
|
||||||
|
ERR_FAIL_COND(!instance);
|
||||||
|
|
||||||
|
Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
|
||||||
|
|
||||||
|
if (!E) {
|
||||||
|
RasterizerScene::InstanceBase::InstanceShaderParameter isp;
|
||||||
|
isp.index = -1;
|
||||||
|
isp.info = PropertyInfo();
|
||||||
|
isp.value = p_value;
|
||||||
|
instance->instance_shader_parameters[p_parameter] = isp;
|
||||||
|
} else {
|
||||||
|
E->get().value = p_value;
|
||||||
|
if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) {
|
||||||
|
//update directly
|
||||||
|
RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant RenderingServerScene::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
|
||||||
|
|
||||||
|
const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
|
||||||
|
ERR_FAIL_COND_V(!instance, Variant());
|
||||||
|
|
||||||
|
if (instance->instance_shader_parameters.has(p_parameter)) {
|
||||||
|
return instance->instance_shader_parameters[p_parameter].value;
|
||||||
|
}
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant RenderingServerScene::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
|
||||||
|
|
||||||
|
const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
|
||||||
|
ERR_FAIL_COND_V(!instance, Variant());
|
||||||
|
|
||||||
|
if (instance->instance_shader_parameters.has(p_parameter)) {
|
||||||
|
return instance->instance_shader_parameters[p_parameter].default_value;
|
||||||
|
}
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingServerScene::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
|
||||||
|
const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
|
||||||
|
ERR_FAIL_COND(!instance);
|
||||||
|
|
||||||
|
const_cast<RenderingServerScene *>(this)->update_dirty_instances();
|
||||||
|
|
||||||
|
Vector<StringName> names;
|
||||||
|
for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
|
||||||
|
names.push_back(E->key());
|
||||||
|
}
|
||||||
|
names.sort_custom<StringName::AlphCompare>();
|
||||||
|
for (int i = 0; i < names.size(); i++) {
|
||||||
|
PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
|
||||||
|
p_parameters->push_back(pinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingServerScene::_update_instance(Instance *p_instance) {
|
void RenderingServerScene::_update_instance(Instance *p_instance) {
|
||||||
|
|
||||||
p_instance->version++;
|
p_instance->version++;
|
||||||
|
@ -2761,6 +2822,35 @@ void RenderingServerScene::render_probes() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingServerScene::_update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) {
|
||||||
|
|
||||||
|
List<RasterizerStorage::InstanceShaderParam> plist;
|
||||||
|
RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
|
||||||
|
for (List<RasterizerStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
|
||||||
|
StringName name = E->get().info.name;
|
||||||
|
if (isparams.has(name)) {
|
||||||
|
if (isparams[name].info.type != E->get().info.type) {
|
||||||
|
WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly.");
|
||||||
|
}
|
||||||
|
if (isparams[name].index != E->get().index) {
|
||||||
|
WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly.");
|
||||||
|
}
|
||||||
|
continue; //first one found always has priority
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterizerScene::InstanceBase::InstanceShaderParameter isp;
|
||||||
|
isp.index = E->get().index;
|
||||||
|
isp.info = E->get().info;
|
||||||
|
isp.default_value = E->get().default_value;
|
||||||
|
if (existing_isparams.has(name)) {
|
||||||
|
isp.value = existing_isparams[name].value;
|
||||||
|
} else {
|
||||||
|
isp.value = E->get().default_value;
|
||||||
|
}
|
||||||
|
isparams[name] = isp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
|
|
||||||
if (p_instance->update_aabb) {
|
if (p_instance->update_aabb) {
|
||||||
|
@ -2800,12 +2890,18 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
|
|
||||||
bool can_cast_shadows = true;
|
bool can_cast_shadows = true;
|
||||||
bool is_animated = false;
|
bool is_animated = false;
|
||||||
|
Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> isparams;
|
||||||
|
|
||||||
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
|
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
|
||||||
can_cast_shadows = false;
|
can_cast_shadows = false;
|
||||||
} else if (p_instance->material_override.is_valid()) {
|
}
|
||||||
can_cast_shadows = RSG::storage->material_casts_shadows(p_instance->material_override);
|
|
||||||
|
if (p_instance->material_override.is_valid()) {
|
||||||
|
if (!RSG::storage->material_casts_shadows(p_instance->material_override)) {
|
||||||
|
can_cast_shadows = false;
|
||||||
|
}
|
||||||
is_animated = RSG::storage->material_is_animated(p_instance->material_override);
|
is_animated = RSG::storage->material_is_animated(p_instance->material_override);
|
||||||
|
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (p_instance->base_type == RS::INSTANCE_MESH) {
|
if (p_instance->base_type == RS::INSTANCE_MESH) {
|
||||||
|
@ -2830,6 +2926,8 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
is_animated = true;
|
is_animated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
|
||||||
|
|
||||||
RSG::storage->material_update_dependency(mat, p_instance);
|
RSG::storage->material_update_dependency(mat, p_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2862,6 +2960,8 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
is_animated = true;
|
is_animated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
|
||||||
|
|
||||||
RSG::storage->material_update_dependency(mat, p_instance);
|
RSG::storage->material_update_dependency(mat, p_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2876,12 +2976,18 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
|
|
||||||
RID mat = RSG::storage->immediate_get_material(p_instance->base);
|
RID mat = RSG::storage->immediate_get_material(p_instance->base);
|
||||||
|
|
||||||
can_cast_shadows = !mat.is_valid() || RSG::storage->material_casts_shadows(mat);
|
if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) {
|
||||||
|
can_cast_shadows = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
|
if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
|
||||||
is_animated = true;
|
is_animated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mat.is_valid()) {
|
||||||
|
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
|
||||||
|
}
|
||||||
|
|
||||||
if (mat.is_valid()) {
|
if (mat.is_valid()) {
|
||||||
RSG::storage->material_update_dependency(mat, p_instance);
|
RSG::storage->material_update_dependency(mat, p_instance);
|
||||||
}
|
}
|
||||||
|
@ -2915,6 +3021,8 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
is_animated = true;
|
is_animated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
|
||||||
|
|
||||||
RSG::storage->material_update_dependency(mat, p_instance);
|
RSG::storage->material_update_dependency(mat, p_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2937,6 +3045,22 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
geom->material_is_animated = is_animated;
|
geom->material_is_animated = is_animated;
|
||||||
|
p_instance->instance_shader_parameters = isparams;
|
||||||
|
|
||||||
|
if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
|
||||||
|
p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
|
||||||
|
if (p_instance->instance_allocated_shader_parameters) {
|
||||||
|
p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
|
||||||
|
for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
|
||||||
|
if (E->get().value.get_type() != Variant::NIL) {
|
||||||
|
RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RSG::storage->global_variables_instance_free(p_instance->self);
|
||||||
|
p_instance->instance_allocated_shader_parameters_offset = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_instance->skeleton.is_valid()) {
|
if (p_instance->skeleton.is_valid()) {
|
||||||
|
@ -2998,6 +3122,10 @@ bool RenderingServerScene::free(RID p_rid) {
|
||||||
instance_geometry_set_material_override(p_rid, RID());
|
instance_geometry_set_material_override(p_rid, RID());
|
||||||
instance_attach_skeleton(p_rid, RID());
|
instance_attach_skeleton(p_rid, RID());
|
||||||
|
|
||||||
|
if (instance->instance_allocated_shader_parameters) {
|
||||||
|
//free the used shader parameters
|
||||||
|
RSG::storage->global_variables_instance_free(instance->self);
|
||||||
|
}
|
||||||
update_dirty_instances(); //in case something changed this
|
update_dirty_instances(); //in case something changed this
|
||||||
|
|
||||||
instance_owner.free(p_rid);
|
instance_owner.free(p_rid);
|
||||||
|
|
|
@ -435,6 +435,13 @@ public:
|
||||||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
|
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
|
||||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
|
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
|
||||||
|
|
||||||
|
void _update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material);
|
||||||
|
|
||||||
|
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
|
||||||
|
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
|
||||||
|
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const;
|
||||||
|
virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const;
|
||||||
|
|
||||||
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
|
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
|
||||||
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
||||||
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
||||||
|
|
|
@ -532,6 +532,11 @@ public:
|
||||||
FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||||
FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
|
FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||||
|
|
||||||
|
FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
|
||||||
|
FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
|
||||||
|
FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
|
||||||
|
FUNC2SC(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
|
||||||
|
|
||||||
/* CANVAS (2D) */
|
/* CANVAS (2D) */
|
||||||
|
|
||||||
FUNCRID(canvas)
|
FUNCRID(canvas)
|
||||||
|
@ -625,6 +630,18 @@ public:
|
||||||
|
|
||||||
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES */
|
||||||
|
|
||||||
|
FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
|
||||||
|
FUNC1(global_variable_remove, const StringName &)
|
||||||
|
FUNC0RC(Vector<StringName>, global_variable_get_list)
|
||||||
|
FUNC2(global_variable_set, const StringName &, const Variant &)
|
||||||
|
FUNC2(global_variable_set_override, const StringName &, const Variant &)
|
||||||
|
FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
|
||||||
|
FUNC1RC(Variant, global_variable_get, const StringName &)
|
||||||
|
FUNC1(global_variables_load_settings, bool)
|
||||||
|
FUNC0(global_variables_clear)
|
||||||
|
|
||||||
/* BLACK BARS */
|
/* BLACK BARS */
|
||||||
|
|
||||||
FUNC4(black_bars_set_margins, int, int, int, int)
|
FUNC4(black_bars_set_margins, int, int, int, int)
|
||||||
|
|
|
@ -194,6 +194,8 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
|
||||||
"SEMICOLON",
|
"SEMICOLON",
|
||||||
"PERIOD",
|
"PERIOD",
|
||||||
"UNIFORM",
|
"UNIFORM",
|
||||||
|
"INSTANCE",
|
||||||
|
"GLOBAL",
|
||||||
"VARYING",
|
"VARYING",
|
||||||
"IN",
|
"IN",
|
||||||
"OUT",
|
"OUT",
|
||||||
|
@ -207,6 +209,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
|
||||||
"HINT_BLACK_ALBEDO_TEXTURE",
|
"HINT_BLACK_ALBEDO_TEXTURE",
|
||||||
"HINT_COLOR",
|
"HINT_COLOR",
|
||||||
"HINT_RANGE",
|
"HINT_RANGE",
|
||||||
|
"HINT_INSTANCE_INDEX",
|
||||||
"FILTER_NEAREST",
|
"FILTER_NEAREST",
|
||||||
"FILTER_LINEAR",
|
"FILTER_LINEAR",
|
||||||
"FILTER_NEAREST_MIPMAP",
|
"FILTER_NEAREST_MIPMAP",
|
||||||
|
@ -300,6 +303,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
|
||||||
{ TK_CF_RETURN, "return" },
|
{ TK_CF_RETURN, "return" },
|
||||||
{ TK_CF_DISCARD, "discard" },
|
{ TK_CF_DISCARD, "discard" },
|
||||||
{ TK_UNIFORM, "uniform" },
|
{ TK_UNIFORM, "uniform" },
|
||||||
|
{ TK_INSTANCE, "instance" },
|
||||||
|
{ TK_GLOBAL, "global" },
|
||||||
{ TK_VARYING, "varying" },
|
{ TK_VARYING, "varying" },
|
||||||
{ TK_ARG_IN, "in" },
|
{ TK_ARG_IN, "in" },
|
||||||
{ TK_ARG_OUT, "out" },
|
{ TK_ARG_OUT, "out" },
|
||||||
|
@ -319,6 +324,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
|
||||||
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
|
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
|
||||||
{ TK_HINT_COLOR, "hint_color" },
|
{ TK_HINT_COLOR, "hint_color" },
|
||||||
{ TK_HINT_RANGE, "hint_range" },
|
{ TK_HINT_RANGE, "hint_range" },
|
||||||
|
{ TK_HINT_INSTANCE_INDEX, "instance_index" },
|
||||||
{ TK_FILTER_NEAREST, "filter_nearest" },
|
{ TK_FILTER_NEAREST, "filter_nearest" },
|
||||||
{ TK_FILTER_LINEAR, "filter_linear" },
|
{ TK_FILTER_LINEAR, "filter_linear" },
|
||||||
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
|
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
|
||||||
|
@ -864,6 +870,7 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
|
||||||
case TYPE_USAMPLER3D: return "usampler3D";
|
case TYPE_USAMPLER3D: return "usampler3D";
|
||||||
case TYPE_SAMPLERCUBE: return "samplerCube";
|
case TYPE_SAMPLERCUBE: return "samplerCube";
|
||||||
case TYPE_STRUCT: return "struct";
|
case TYPE_STRUCT: return "struct";
|
||||||
|
case TYPE_MAX: return "invalid";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
@ -2678,6 +2685,8 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
|
||||||
break;
|
break;
|
||||||
case ShaderLanguage::TYPE_VOID:
|
case ShaderLanguage::TYPE_VOID:
|
||||||
break;
|
break;
|
||||||
|
case ShaderLanguage::TYPE_MAX:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -2774,6 +2783,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
|
||||||
case ShaderLanguage::TYPE_STRUCT: {
|
case ShaderLanguage::TYPE_STRUCT: {
|
||||||
// FIXME: Implement this.
|
// FIXME: Implement this.
|
||||||
} break;
|
} break;
|
||||||
|
case ShaderLanguage::TYPE_MAX:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
@ -2822,6 +2833,8 @@ uint32_t ShaderLanguage::get_type_size(DataType p_type) {
|
||||||
case TYPE_STRUCT:
|
case TYPE_STRUCT:
|
||||||
// FIXME: Implement.
|
// FIXME: Implement.
|
||||||
return 0;
|
return 0;
|
||||||
|
case ShaderLanguage::TYPE_MAX:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5685,6 +5698,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
|
|
||||||
int texture_uniforms = 0;
|
int texture_uniforms = 0;
|
||||||
int uniforms = 0;
|
int uniforms = 0;
|
||||||
|
int instance_index = 0;
|
||||||
|
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
|
||||||
|
|
||||||
while (tk.type != TK_EOF) {
|
while (tk.type != TK_EOF) {
|
||||||
|
|
||||||
|
@ -5853,6 +5868,27 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
shader->vstructs.push_back(st); // struct's order is important!
|
shader->vstructs.push_back(st); // struct's order is important!
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case TK_GLOBAL: {
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_UNIFORM) {
|
||||||
|
_set_error("Expected 'uniform' after 'global'");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
uniform_scope = ShaderNode::Uniform::SCOPE_GLOBAL;
|
||||||
|
};
|
||||||
|
[[fallthrough]];
|
||||||
|
case TK_INSTANCE: {
|
||||||
|
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_UNIFORM) {
|
||||||
|
_set_error("Expected 'uniform' after 'instance'");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
[[fallthrough]];
|
||||||
case TK_UNIFORM:
|
case TK_UNIFORM:
|
||||||
case TK_VARYING: {
|
case TK_VARYING: {
|
||||||
|
|
||||||
|
@ -5910,25 +5946,50 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
|
|
||||||
if (uniform) {
|
if (uniform) {
|
||||||
|
|
||||||
|
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
|
||||||
|
//validate global uniform
|
||||||
|
DataType gvtype = global_var_get_type_func(name);
|
||||||
|
if (gvtype == TYPE_MAX) {
|
||||||
|
_set_error("Global uniform '" + String(name) + "' does not exist. Create it in Project Settings.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != gvtype) {
|
||||||
|
_set_error("Global uniform '" + String(name) + "' must be of type '" + get_datatype_name(gvtype) + "'.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
ShaderNode::Uniform uniform2;
|
ShaderNode::Uniform uniform2;
|
||||||
|
|
||||||
if (is_sampler_type(type)) {
|
if (is_sampler_type(type)) {
|
||||||
|
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
_set_error("Uniforms with 'instance' qualifiers can't be of sampler type.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
uniform2.texture_order = texture_uniforms++;
|
uniform2.texture_order = texture_uniforms++;
|
||||||
uniform2.order = -1;
|
uniform2.order = -1;
|
||||||
if (_validate_datatype(type) != OK) {
|
if (_validate_datatype(type) != OK) {
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) {
|
||||||
|
_set_error("Uniforms with 'instance' qualifiers can't be of matrix type.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
uniform2.texture_order = -1;
|
uniform2.texture_order = -1;
|
||||||
uniform2.order = uniforms++;
|
uniform2.order = uniforms++;
|
||||||
}
|
}
|
||||||
uniform2.type = type;
|
uniform2.type = type;
|
||||||
|
uniform2.scope = uniform_scope;
|
||||||
uniform2.precision = precision;
|
uniform2.precision = precision;
|
||||||
|
|
||||||
//todo parse default value
|
//todo parse default value
|
||||||
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
|
int custom_instance_index = -1;
|
||||||
|
|
||||||
if (tk.type == TK_COLON) {
|
if (tk.type == TK_COLON) {
|
||||||
//hint
|
//hint
|
||||||
do {
|
do {
|
||||||
|
@ -6039,7 +6100,45 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tk.type != TK_PARENTHESIS_CLOSE) {
|
if (tk.type != TK_PARENTHESIS_CLOSE) {
|
||||||
_set_error("Expected ','");
|
_set_error("Expected ')'");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
} else if (tk.type == TK_HINT_INSTANCE_INDEX) {
|
||||||
|
|
||||||
|
if (custom_instance_index != -1) {
|
||||||
|
_set_error("Can only specify 'instance_index' once.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_PARENTHESIS_OPEN) {
|
||||||
|
_set_error("Expected '(' after 'instance_index'");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
|
||||||
|
if (tk.type == TK_OP_SUB) {
|
||||||
|
_set_error("The instance index can't be negative.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tk.type != TK_INT_CONSTANT) {
|
||||||
|
_set_error("Expected integer constant");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_instance_index = tk.constant;
|
||||||
|
|
||||||
|
if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) {
|
||||||
|
_set_error("Allowed instance uniform indices are 0-" + itos(MAX_INSTANCE_UNIFORM_INDICES - 1));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
|
||||||
|
if (tk.type != TK_PARENTHESIS_CLOSE) {
|
||||||
|
_set_error("Expected ')'");
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
} else if (tk.type == TK_FILTER_LINEAR) {
|
} else if (tk.type == TK_FILTER_LINEAR) {
|
||||||
|
@ -6072,6 +6171,20 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
} while (tk.type == TK_COMMA);
|
} while (tk.type == TK_COMMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||||
|
if (custom_instance_index >= 0) {
|
||||||
|
uniform2.instance_index = custom_instance_index;
|
||||||
|
} else {
|
||||||
|
uniform2.instance_index = instance_index++;
|
||||||
|
if (instance_index > MAX_INSTANCE_UNIFORM_INDICES) {
|
||||||
|
_set_error("Too many 'instance' uniforms in shader, maximum supported is " + itos(MAX_INSTANCE_UNIFORM_INDICES));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//reset scope for next uniform
|
||||||
|
|
||||||
if (tk.type == TK_OP_ASSIGN) {
|
if (tk.type == TK_OP_ASSIGN) {
|
||||||
|
|
||||||
Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>());
|
Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>());
|
||||||
|
@ -6094,6 +6207,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->uniforms[name] = uniform2;
|
shader->uniforms[name] = uniform2;
|
||||||
|
//reset scope for next uniform
|
||||||
|
uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
|
||||||
|
|
||||||
if (tk.type != TK_SEMICOLON) {
|
if (tk.type != TK_SEMICOLON) {
|
||||||
_set_error("Expected ';'");
|
_set_error("Expected ';'");
|
||||||
|
@ -6639,11 +6754,12 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
|
Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
code = p_code;
|
code = p_code;
|
||||||
|
global_var_get_type_func = p_global_variable_type_func;
|
||||||
|
|
||||||
nodes = nullptr;
|
nodes = nullptr;
|
||||||
|
|
||||||
|
@ -6656,13 +6772,14 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
|
Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
code = p_code;
|
code = p_code;
|
||||||
|
|
||||||
nodes = nullptr;
|
nodes = nullptr;
|
||||||
|
global_var_get_type_func = p_global_variable_type_func;
|
||||||
|
|
||||||
shader = alloc_node<ShaderNode>();
|
shader = alloc_node<ShaderNode>();
|
||||||
_parse_shader(p_functions, p_render_modes, p_shader_types);
|
_parse_shader(p_functions, p_render_modes, p_shader_types);
|
||||||
|
|
|
@ -143,6 +143,8 @@ public:
|
||||||
TK_SEMICOLON,
|
TK_SEMICOLON,
|
||||||
TK_PERIOD,
|
TK_PERIOD,
|
||||||
TK_UNIFORM,
|
TK_UNIFORM,
|
||||||
|
TK_INSTANCE,
|
||||||
|
TK_GLOBAL,
|
||||||
TK_VARYING,
|
TK_VARYING,
|
||||||
TK_ARG_IN,
|
TK_ARG_IN,
|
||||||
TK_ARG_OUT,
|
TK_ARG_OUT,
|
||||||
|
@ -162,6 +164,7 @@ public:
|
||||||
TK_HINT_BLACK_ALBEDO_TEXTURE,
|
TK_HINT_BLACK_ALBEDO_TEXTURE,
|
||||||
TK_HINT_COLOR,
|
TK_HINT_COLOR,
|
||||||
TK_HINT_RANGE,
|
TK_HINT_RANGE,
|
||||||
|
TK_HINT_INSTANCE_INDEX,
|
||||||
TK_FILTER_NEAREST,
|
TK_FILTER_NEAREST,
|
||||||
TK_FILTER_LINEAR,
|
TK_FILTER_LINEAR,
|
||||||
TK_FILTER_NEAREST_MIPMAP,
|
TK_FILTER_NEAREST_MIPMAP,
|
||||||
|
@ -216,6 +219,7 @@ public:
|
||||||
TYPE_USAMPLER3D,
|
TYPE_USAMPLER3D,
|
||||||
TYPE_SAMPLERCUBE,
|
TYPE_SAMPLERCUBE,
|
||||||
TYPE_STRUCT,
|
TYPE_STRUCT,
|
||||||
|
TYPE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DataPrecision {
|
enum DataPrecision {
|
||||||
|
@ -317,6 +321,10 @@ public:
|
||||||
REPEAT_DEFAULT,
|
REPEAT_DEFAULT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MAX_INSTANCE_UNIFORM_INDICES = 16
|
||||||
|
};
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
Node *next;
|
Node *next;
|
||||||
|
|
||||||
|
@ -650,15 +658,23 @@ public:
|
||||||
HINT_MAX
|
HINT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Scope {
|
||||||
|
SCOPE_LOCAL,
|
||||||
|
SCOPE_INSTANCE,
|
||||||
|
SCOPE_GLOBAL,
|
||||||
|
};
|
||||||
|
|
||||||
int order;
|
int order;
|
||||||
int texture_order;
|
int texture_order;
|
||||||
DataType type;
|
DataType type;
|
||||||
DataPrecision precision;
|
DataPrecision precision;
|
||||||
Vector<ConstantNode::Value> default_value;
|
Vector<ConstantNode::Value> default_value;
|
||||||
|
Scope scope;
|
||||||
Hint hint;
|
Hint hint;
|
||||||
TextureFilter filter;
|
TextureFilter filter;
|
||||||
TextureRepeat repeat;
|
TextureRepeat repeat;
|
||||||
float hint_range[3];
|
float hint_range[3];
|
||||||
|
int instance_index;
|
||||||
|
|
||||||
Uniform() :
|
Uniform() :
|
||||||
order(0),
|
order(0),
|
||||||
|
@ -667,7 +683,8 @@ public:
|
||||||
precision(PRECISION_DEFAULT),
|
precision(PRECISION_DEFAULT),
|
||||||
hint(HINT_NONE),
|
hint(HINT_NONE),
|
||||||
filter(FILTER_DEFAULT),
|
filter(FILTER_DEFAULT),
|
||||||
repeat(REPEAT_DEFAULT) {
|
repeat(REPEAT_DEFAULT),
|
||||||
|
instance_index(0) {
|
||||||
hint_range[0] = 0.0f;
|
hint_range[0] = 0.0f;
|
||||||
hint_range[1] = 1.0f;
|
hint_range[1] = 1.0f;
|
||||||
hint_range[2] = 0.001f;
|
hint_range[2] = 0.001f;
|
||||||
|
@ -764,6 +781,8 @@ public:
|
||||||
};
|
};
|
||||||
static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
|
static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
|
||||||
|
|
||||||
|
typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct KeyWord {
|
struct KeyWord {
|
||||||
TokenType token;
|
TokenType token;
|
||||||
|
@ -772,6 +791,8 @@ private:
|
||||||
|
|
||||||
static const KeyWord keyword_list[];
|
static const KeyWord keyword_list[];
|
||||||
|
|
||||||
|
GlobalVariableGetTypeFunc global_var_get_type_func;
|
||||||
|
|
||||||
bool error_set;
|
bool error_set;
|
||||||
String error_str;
|
String error_str;
|
||||||
int error_line;
|
int error_line;
|
||||||
|
@ -884,8 +905,8 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
static String get_shader_type(const String &p_code);
|
static String get_shader_type(const String &p_code);
|
||||||
Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
|
Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func);
|
||||||
Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
|
Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
|
||||||
|
|
||||||
String get_error_text();
|
String get_error_text();
|
||||||
int get_error_line();
|
int get_error_line();
|
||||||
|
|
|
@ -1565,6 +1565,42 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ShaderLanguage::DataType RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) {
|
||||||
|
|
||||||
|
switch (p_type) {
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BOOL: return ShaderLanguage::TYPE_BOOL;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC2: return ShaderLanguage::TYPE_BVEC2;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC3: return ShaderLanguage::TYPE_BVEC3;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_BVEC4: return ShaderLanguage::TYPE_BVEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_INT: return ShaderLanguage::TYPE_INT;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC2: return ShaderLanguage::TYPE_IVEC2;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC3: return ShaderLanguage::TYPE_IVEC3;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_IVEC4: return ShaderLanguage::TYPE_IVEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2I: return ShaderLanguage::TYPE_IVEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UINT: return ShaderLanguage::TYPE_UINT;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC2: return ShaderLanguage::TYPE_UVEC2;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC3: return ShaderLanguage::TYPE_UVEC3;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_UVEC4: return ShaderLanguage::TYPE_UVEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_FLOAT: return ShaderLanguage::TYPE_FLOAT;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC2: return ShaderLanguage::TYPE_VEC2;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC3: return ShaderLanguage::TYPE_VEC3;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_VEC4: return ShaderLanguage::TYPE_VEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_COLOR: return ShaderLanguage::TYPE_VEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_RECT2: return ShaderLanguage::TYPE_VEC4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT2: return ShaderLanguage::TYPE_MAT2;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT3: return ShaderLanguage::TYPE_MAT3;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_MAT4: return ShaderLanguage::TYPE_MAT4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: return ShaderLanguage::TYPE_MAT3;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_TRANSFORM: return ShaderLanguage::TYPE_MAT4;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: return ShaderLanguage::TYPE_SAMPLER2D;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: return ShaderLanguage::TYPE_SAMPLER2DARRAY;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: return ShaderLanguage::TYPE_SAMPLER3D;
|
||||||
|
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: return ShaderLanguage::TYPE_SAMPLERCUBE;
|
||||||
|
default: return ShaderLanguage::TYPE_MAX; //invalid or not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingServer::_bind_methods() {
|
void RenderingServer::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("force_sync"), &RenderingServer::sync);
|
ClassDB::bind_method(D_METHOD("force_sync"), &RenderingServer::sync);
|
||||||
|
@ -1921,6 +1957,13 @@ void RenderingServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &RenderingServer::canvas_occluder_polygon_set_shape_as_lines);
|
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &RenderingServer::canvas_occluder_polygon_set_shape_as_lines);
|
||||||
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode);
|
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
|
||||||
|
ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove);
|
||||||
|
ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list);
|
||||||
|
ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set);
|
||||||
|
ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get);
|
||||||
|
ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_margins);
|
ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_margins);
|
||||||
ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_images);
|
ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_images);
|
||||||
|
|
||||||
|
@ -2206,6 +2249,36 @@ void RenderingServer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
|
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
|
||||||
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
|
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC3);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC4);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_INT);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_IVEC2);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_IVEC3);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_IVEC4);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_RECT2I);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_UINT);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_UVEC2);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_UVEC3);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_UVEC4);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_FLOAT);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_VEC2);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_VEC3);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_VEC4);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_COLOR);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_RECT2);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAT2);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAT3);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAT4);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_TRANSFORM_2D);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_TRANSFORM);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLER2D);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLER2DARRAY);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLER3D);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLERCUBE);
|
||||||
|
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAX);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME);
|
BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME);
|
||||||
BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME);
|
BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME);
|
||||||
BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME);
|
BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME);
|
||||||
|
@ -2370,6 +2443,8 @@ RenderingServer::RenderingServer() {
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
|
||||||
GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", 0.01);
|
GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", 0.01);
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
|
||||||
|
|
||||||
|
GLOBAL_DEF("rendering/high_end/global_shader_variables_buffer_size", 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderingServer::~RenderingServer() {
|
RenderingServer::~RenderingServer() {
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "core/rid.h"
|
#include "core/rid.h"
|
||||||
#include "core/variant.h"
|
#include "core/variant.h"
|
||||||
#include "servers/display_server.h"
|
#include "servers/display_server.h"
|
||||||
|
#include "servers/rendering/shader_language.h"
|
||||||
|
|
||||||
class RenderingServer : public Object {
|
class RenderingServer : public Object {
|
||||||
|
|
||||||
|
@ -950,6 +951,11 @@ public:
|
||||||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
|
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
|
||||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
|
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
|
||||||
|
|
||||||
|
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0;
|
||||||
|
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0;
|
||||||
|
virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &) const = 0;
|
||||||
|
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
|
||||||
|
|
||||||
/* CANVAS (2D) */
|
/* CANVAS (2D) */
|
||||||
|
|
||||||
virtual RID canvas_create() = 0;
|
virtual RID canvas_create() = 0;
|
||||||
|
@ -1090,6 +1096,55 @@ public:
|
||||||
};
|
};
|
||||||
virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, CanvasOccluderPolygonCullMode p_mode) = 0;
|
virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, CanvasOccluderPolygonCullMode p_mode) = 0;
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES */
|
||||||
|
|
||||||
|
enum GlobalVariableType {
|
||||||
|
GLOBAL_VAR_TYPE_BOOL,
|
||||||
|
GLOBAL_VAR_TYPE_BVEC2,
|
||||||
|
GLOBAL_VAR_TYPE_BVEC3,
|
||||||
|
GLOBAL_VAR_TYPE_BVEC4,
|
||||||
|
GLOBAL_VAR_TYPE_INT,
|
||||||
|
GLOBAL_VAR_TYPE_IVEC2,
|
||||||
|
GLOBAL_VAR_TYPE_IVEC3,
|
||||||
|
GLOBAL_VAR_TYPE_IVEC4,
|
||||||
|
GLOBAL_VAR_TYPE_RECT2I,
|
||||||
|
GLOBAL_VAR_TYPE_UINT,
|
||||||
|
GLOBAL_VAR_TYPE_UVEC2,
|
||||||
|
GLOBAL_VAR_TYPE_UVEC3,
|
||||||
|
GLOBAL_VAR_TYPE_UVEC4,
|
||||||
|
GLOBAL_VAR_TYPE_FLOAT,
|
||||||
|
GLOBAL_VAR_TYPE_VEC2,
|
||||||
|
GLOBAL_VAR_TYPE_VEC3,
|
||||||
|
GLOBAL_VAR_TYPE_VEC4,
|
||||||
|
GLOBAL_VAR_TYPE_COLOR,
|
||||||
|
GLOBAL_VAR_TYPE_RECT2,
|
||||||
|
GLOBAL_VAR_TYPE_MAT2,
|
||||||
|
GLOBAL_VAR_TYPE_MAT3,
|
||||||
|
GLOBAL_VAR_TYPE_MAT4,
|
||||||
|
GLOBAL_VAR_TYPE_TRANSFORM_2D,
|
||||||
|
GLOBAL_VAR_TYPE_TRANSFORM,
|
||||||
|
GLOBAL_VAR_TYPE_SAMPLER2D,
|
||||||
|
GLOBAL_VAR_TYPE_SAMPLER2DARRAY,
|
||||||
|
GLOBAL_VAR_TYPE_SAMPLER3D,
|
||||||
|
GLOBAL_VAR_TYPE_SAMPLERCUBE,
|
||||||
|
GLOBAL_VAR_TYPE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void global_variable_add(const StringName &p_name, GlobalVariableType p_type, const Variant &p_value) = 0;
|
||||||
|
virtual void global_variable_remove(const StringName &p_name) = 0;
|
||||||
|
virtual Vector<StringName> global_variable_get_list() const = 0;
|
||||||
|
|
||||||
|
virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
|
||||||
|
virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
|
||||||
|
|
||||||
|
virtual Variant global_variable_get(const StringName &p_name) const = 0;
|
||||||
|
virtual GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
|
||||||
|
|
||||||
|
virtual void global_variables_load_settings(bool p_load_textures) = 0;
|
||||||
|
virtual void global_variables_clear() = 0;
|
||||||
|
|
||||||
|
static ShaderLanguage::DataType global_variable_type_get_shader_datatype(GlobalVariableType p_type);
|
||||||
|
|
||||||
/* BLACK BARS */
|
/* BLACK BARS */
|
||||||
|
|
||||||
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0;
|
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0;
|
||||||
|
@ -1217,6 +1272,7 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureRepeat);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode);
|
VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
|
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
|
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
|
||||||
|
VARIANT_ENUM_CAST(RenderingServer::GlobalVariableType);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::RenderInfo);
|
VARIANT_ENUM_CAST(RenderingServer::RenderInfo);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::Features);
|
VARIANT_ENUM_CAST(RenderingServer::Features);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue