Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/main/shader_globals_override.cpp
21371 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
#include "servers/rendering/rendering_server.h"
35
36
StringName *ShaderGlobalsOverride::_remap(const StringName &p_name) const {
37
StringName *r = param_remaps.getptr(p_name);
38
if (!r) {
39
//not cached, do caching
40
String p = p_name;
41
if (p.begins_with("params/")) {
42
String q = p.replace_first("params/", "");
43
param_remaps[p] = q;
44
r = param_remaps.getptr(p);
45
}
46
}
47
48
return r;
49
}
50
51
bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_value) {
52
StringName *r = _remap(p_name);
53
54
if (r) {
55
Override *o = overrides.getptr(*r);
56
if (!o) {
57
Override ov;
58
ov.in_use = false;
59
overrides[*r] = ov;
60
o = overrides.getptr(*r);
61
}
62
if (o) {
63
o->override = p_value;
64
if (active) {
65
if (o->override.get_type() == Variant::OBJECT) {
66
RID tex_rid = p_value;
67
RS::get_singleton()->global_shader_parameter_set_override(*r, tex_rid);
68
} else {
69
RS::get_singleton()->global_shader_parameter_set_override(*r, p_value);
70
}
71
}
72
o->in_use = p_value.get_type() != Variant::NIL;
73
return true;
74
}
75
}
76
77
return false;
78
}
79
80
bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const {
81
StringName *r = _remap(p_name);
82
83
if (r) {
84
const Override *o = overrides.getptr(*r);
85
if (o) {
86
r_ret = o->override;
87
return true;
88
}
89
}
90
91
return false;
92
}
93
94
void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const {
95
Vector<StringName> variables;
96
variables = RS::get_singleton()->global_shader_parameter_get_list();
97
for (int i = 0; i < variables.size(); i++) {
98
PropertyInfo pinfo;
99
pinfo.name = "params/" + variables[i];
100
pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
101
102
switch (RS::get_singleton()->global_shader_parameter_get_type(variables[i])) {
103
case RS::GLOBAL_VAR_TYPE_BOOL: {
104
pinfo.type = Variant::BOOL;
105
} break;
106
case RS::GLOBAL_VAR_TYPE_BVEC2: {
107
pinfo.type = Variant::INT;
108
pinfo.hint = PROPERTY_HINT_FLAGS;
109
pinfo.hint_string = "x,y";
110
} break;
111
case RS::GLOBAL_VAR_TYPE_BVEC3: {
112
pinfo.type = Variant::INT;
113
pinfo.hint = PROPERTY_HINT_FLAGS;
114
pinfo.hint_string = "x,y,z";
115
} break;
116
case RS::GLOBAL_VAR_TYPE_BVEC4: {
117
pinfo.type = Variant::INT;
118
pinfo.hint = PROPERTY_HINT_FLAGS;
119
pinfo.hint_string = "x,y,z,w";
120
} break;
121
case RS::GLOBAL_VAR_TYPE_INT: {
122
pinfo.type = Variant::INT;
123
} break;
124
case RS::GLOBAL_VAR_TYPE_IVEC2: {
125
pinfo.type = Variant::VECTOR2I;
126
} break;
127
case RS::GLOBAL_VAR_TYPE_IVEC3: {
128
pinfo.type = Variant::VECTOR3I;
129
} break;
130
case RS::GLOBAL_VAR_TYPE_IVEC4: {
131
pinfo.type = Variant::VECTOR4I;
132
} break;
133
case RS::GLOBAL_VAR_TYPE_RECT2I: {
134
pinfo.type = Variant::RECT2I;
135
} break;
136
case RS::GLOBAL_VAR_TYPE_UINT: {
137
pinfo.type = Variant::INT;
138
} break;
139
case RS::GLOBAL_VAR_TYPE_UVEC2: {
140
pinfo.type = Variant::VECTOR2I;
141
} break;
142
case RS::GLOBAL_VAR_TYPE_UVEC3: {
143
pinfo.type = Variant::VECTOR3I;
144
} break;
145
case RS::GLOBAL_VAR_TYPE_UVEC4: {
146
pinfo.type = Variant::VECTOR4I;
147
} break;
148
case RS::GLOBAL_VAR_TYPE_FLOAT: {
149
pinfo.type = Variant::FLOAT;
150
} break;
151
case RS::GLOBAL_VAR_TYPE_VEC2: {
152
pinfo.type = Variant::VECTOR2;
153
} break;
154
case RS::GLOBAL_VAR_TYPE_VEC3: {
155
pinfo.type = Variant::VECTOR3;
156
} break;
157
case RS::GLOBAL_VAR_TYPE_VEC4: {
158
pinfo.type = Variant::VECTOR4;
159
} break;
160
case RS::GLOBAL_VAR_TYPE_RECT2: {
161
pinfo.type = Variant::RECT2;
162
} break;
163
case RS::GLOBAL_VAR_TYPE_COLOR: {
164
pinfo.type = Variant::COLOR;
165
} break;
166
case RS::GLOBAL_VAR_TYPE_MAT2: {
167
pinfo.type = Variant::PACKED_FLOAT32_ARRAY;
168
} break;
169
case RS::GLOBAL_VAR_TYPE_MAT3: {
170
pinfo.type = Variant::BASIS;
171
} break;
172
case RS::GLOBAL_VAR_TYPE_MAT4: {
173
pinfo.type = Variant::PROJECTION;
174
} break;
175
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
176
pinfo.type = Variant::TRANSFORM2D;
177
} break;
178
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
179
pinfo.type = Variant::TRANSFORM3D;
180
} break;
181
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
182
pinfo.type = Variant::OBJECT;
183
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
184
pinfo.hint_string = "Texture2D";
185
} break;
186
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
187
pinfo.type = Variant::OBJECT;
188
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
189
pinfo.hint_string = "Texture2DArray";
190
} break;
191
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
192
pinfo.type = Variant::OBJECT;
193
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
194
pinfo.hint_string = "Texture3D";
195
} break;
196
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
197
pinfo.type = Variant::OBJECT;
198
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
199
pinfo.hint_string = "Cubemap";
200
} break;
201
case RS::GLOBAL_VAR_TYPE_SAMPLEREXT: {
202
pinfo.type = Variant::OBJECT;
203
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
204
pinfo.hint_string = "ExternalTexture";
205
} break;
206
default: {
207
} break;
208
}
209
210
if (!overrides.has(variables[i])) {
211
Override o;
212
o.in_use = false;
213
Callable::CallError ce;
214
Variant::construct(pinfo.type, o.override, nullptr, 0, ce);
215
overrides[variables[i]] = o;
216
}
217
218
Override *o = overrides.getptr(variables[i]);
219
if (o->in_use && o->override.get_type() != Variant::NIL) {
220
pinfo.usage |= PROPERTY_USAGE_CHECKED;
221
pinfo.usage |= PROPERTY_USAGE_STORAGE;
222
}
223
224
p_list->push_back(pinfo);
225
}
226
}
227
228
void ShaderGlobalsOverride::_activate() {
229
ERR_FAIL_NULL(get_tree());
230
Vector<Node *> nodes = get_tree()->get_nodes_in_group(SceneStringName(shader_overrides_group_active));
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