Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/main/shader_globals_override.cpp
9902 views
1
/**************************************************************************/
2
/* shader_globals_override.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "shader_globals_override.h"
32
33
#include "scene/main/node.h"
34
35
StringName *ShaderGlobalsOverride::_remap(const StringName &p_name) const {
36
StringName *r = param_remaps.getptr(p_name);
37
if (!r) {
38
//not cached, do caching
39
String p = p_name;
40
if (p.begins_with("params/")) {
41
String q = p.replace_first("params/", "");
42
param_remaps[p] = q;
43
r = param_remaps.getptr(p);
44
}
45
}
46
47
return r;
48
}
49
50
bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_value) {
51
StringName *r = _remap(p_name);
52
53
if (r) {
54
Override *o = overrides.getptr(*r);
55
if (!o) {
56
Override ov;
57
ov.in_use = false;
58
overrides[*r] = ov;
59
o = overrides.getptr(*r);
60
}
61
if (o) {
62
o->override = p_value;
63
if (active) {
64
if (o->override.get_type() == Variant::OBJECT) {
65
RID tex_rid = p_value;
66
RS::get_singleton()->global_shader_parameter_set_override(*r, tex_rid);
67
} else {
68
RS::get_singleton()->global_shader_parameter_set_override(*r, p_value);
69
}
70
}
71
o->in_use = p_value.get_type() != Variant::NIL;
72
return true;
73
}
74
}
75
76
return false;
77
}
78
79
bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const {
80
StringName *r = _remap(p_name);
81
82
if (r) {
83
const Override *o = overrides.getptr(*r);
84
if (o) {
85
r_ret = o->override;
86
return true;
87
}
88
}
89
90
return false;
91
}
92
93
void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const {
94
Vector<StringName> variables;
95
variables = RS::get_singleton()->global_shader_parameter_get_list();
96
for (int i = 0; i < variables.size(); i++) {
97
PropertyInfo pinfo;
98
pinfo.name = "params/" + variables[i];
99
pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
100
101
switch (RS::get_singleton()->global_shader_parameter_get_type(variables[i])) {
102
case RS::GLOBAL_VAR_TYPE_BOOL: {
103
pinfo.type = Variant::BOOL;
104
} break;
105
case RS::GLOBAL_VAR_TYPE_BVEC2: {
106
pinfo.type = Variant::INT;
107
pinfo.hint = PROPERTY_HINT_FLAGS;
108
pinfo.hint_string = "x,y";
109
} break;
110
case RS::GLOBAL_VAR_TYPE_BVEC3: {
111
pinfo.type = Variant::INT;
112
pinfo.hint = PROPERTY_HINT_FLAGS;
113
pinfo.hint_string = "x,y,z";
114
} break;
115
case RS::GLOBAL_VAR_TYPE_BVEC4: {
116
pinfo.type = Variant::INT;
117
pinfo.hint = PROPERTY_HINT_FLAGS;
118
pinfo.hint_string = "x,y,z,w";
119
} break;
120
case RS::GLOBAL_VAR_TYPE_INT: {
121
pinfo.type = Variant::INT;
122
} break;
123
case RS::GLOBAL_VAR_TYPE_IVEC2: {
124
pinfo.type = Variant::VECTOR2I;
125
} break;
126
case RS::GLOBAL_VAR_TYPE_IVEC3: {
127
pinfo.type = Variant::VECTOR3I;
128
} break;
129
case RS::GLOBAL_VAR_TYPE_IVEC4: {
130
pinfo.type = Variant::VECTOR4I;
131
} break;
132
case RS::GLOBAL_VAR_TYPE_RECT2I: {
133
pinfo.type = Variant::RECT2I;
134
} break;
135
case RS::GLOBAL_VAR_TYPE_UINT: {
136
pinfo.type = Variant::INT;
137
} break;
138
case RS::GLOBAL_VAR_TYPE_UVEC2: {
139
pinfo.type = Variant::VECTOR2I;
140
} break;
141
case RS::GLOBAL_VAR_TYPE_UVEC3: {
142
pinfo.type = Variant::VECTOR3I;
143
} break;
144
case RS::GLOBAL_VAR_TYPE_UVEC4: {
145
pinfo.type = Variant::VECTOR4I;
146
} break;
147
case RS::GLOBAL_VAR_TYPE_FLOAT: {
148
pinfo.type = Variant::FLOAT;
149
} break;
150
case RS::GLOBAL_VAR_TYPE_VEC2: {
151
pinfo.type = Variant::VECTOR2;
152
} break;
153
case RS::GLOBAL_VAR_TYPE_VEC3: {
154
pinfo.type = Variant::VECTOR3;
155
} break;
156
case RS::GLOBAL_VAR_TYPE_VEC4: {
157
pinfo.type = Variant::VECTOR4;
158
} break;
159
case RS::GLOBAL_VAR_TYPE_RECT2: {
160
pinfo.type = Variant::RECT2;
161
} break;
162
case RS::GLOBAL_VAR_TYPE_COLOR: {
163
pinfo.type = Variant::COLOR;
164
} break;
165
case RS::GLOBAL_VAR_TYPE_MAT2: {
166
pinfo.type = Variant::PACKED_FLOAT32_ARRAY;
167
} break;
168
case RS::GLOBAL_VAR_TYPE_MAT3: {
169
pinfo.type = Variant::BASIS;
170
} break;
171
case RS::GLOBAL_VAR_TYPE_MAT4: {
172
pinfo.type = Variant::PROJECTION;
173
} break;
174
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
175
pinfo.type = Variant::TRANSFORM2D;
176
} break;
177
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
178
pinfo.type = Variant::TRANSFORM3D;
179
} break;
180
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
181
pinfo.type = Variant::OBJECT;
182
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
183
pinfo.hint_string = "Texture2D";
184
} break;
185
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
186
pinfo.type = Variant::OBJECT;
187
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
188
pinfo.hint_string = "Texture2DArray";
189
} break;
190
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
191
pinfo.type = Variant::OBJECT;
192
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
193
pinfo.hint_string = "Texture3D";
194
} break;
195
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
196
pinfo.type = Variant::OBJECT;
197
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
198
pinfo.hint_string = "Cubemap";
199
} break;
200
case RS::GLOBAL_VAR_TYPE_SAMPLEREXT: {
201
pinfo.type = Variant::OBJECT;
202
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
203
pinfo.hint_string = "ExternalTexture";
204
} break;
205
default: {
206
} break;
207
}
208
209
if (!overrides.has(variables[i])) {
210
Override o;
211
o.in_use = false;
212
Callable::CallError ce;
213
Variant::construct(pinfo.type, o.override, nullptr, 0, ce);
214
overrides[variables[i]] = o;
215
}
216
217
Override *o = overrides.getptr(variables[i]);
218
if (o->in_use && o->override.get_type() != Variant::NIL) {
219
pinfo.usage |= PROPERTY_USAGE_CHECKED;
220
pinfo.usage |= PROPERTY_USAGE_STORAGE;
221
}
222
223
p_list->push_back(pinfo);
224
}
225
}
226
227
void ShaderGlobalsOverride::_activate() {
228
ERR_FAIL_NULL(get_tree());
229
List<Node *> nodes;
230
get_tree()->get_nodes_in_group(SceneStringName(shader_overrides_group_active), &nodes);
231
if (nodes.is_empty()) {
232
//good we are the only override, enable all
233
active = true;
234
add_to_group(SceneStringName(shader_overrides_group_active));
235
236
for (const KeyValue<StringName, Override> &E : overrides) {
237
const Override *o = &E.value;
238
if (o->in_use && o->override.get_type() != Variant::NIL) {
239
if (o->override.get_type() == Variant::OBJECT) {
240
RID tex_rid = o->override;
241
RS::get_singleton()->global_shader_parameter_set_override(E.key, tex_rid);
242
} else {
243
RS::get_singleton()->global_shader_parameter_set_override(E.key, o->override);
244
}
245
}
246
247
update_configuration_warnings(); //may have activated
248
}
249
}
250
}
251
252
void ShaderGlobalsOverride::_notification(int p_what) {
253
switch (p_what) {
254
case Node::NOTIFICATION_ENTER_TREE: {
255
add_to_group(SceneStringName(shader_overrides_group));
256
_activate();
257
} break;
258
259
case Node::NOTIFICATION_EXIT_TREE: {
260
if (active) {
261
//remove overrides
262
for (const KeyValue<StringName, Override> &E : overrides) {
263
const Override *o = &E.value;
264
if (o->in_use) {
265
RS::get_singleton()->global_shader_parameter_set_override(E.key, Variant());
266
}
267
}
268
}
269
270
remove_from_group(SceneStringName(shader_overrides_group_active));
271
remove_from_group(SceneStringName(shader_overrides_group));
272
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringName(shader_overrides_group), "_activate"); //another may want to activate when this is removed
273
active = false;
274
} break;
275
}
276
}
277
278
PackedStringArray ShaderGlobalsOverride::get_configuration_warnings() const {
279
PackedStringArray warnings = Node::get_configuration_warnings();
280
281
if (!active) {
282
warnings.push_back(RTR("ShaderGlobalsOverride is not active because another node of the same type is in the scene."));
283
}
284
285
return warnings;
286
}
287
288
void ShaderGlobalsOverride::_bind_methods() {
289
ClassDB::bind_method(D_METHOD("_activate"), &ShaderGlobalsOverride::_activate);
290
}
291
292