2020-05-10 18:53:46 +08:00
/*************************************************************************/
/* shader_globals_override.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
2022-01-04 04:27:34 +08:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2020-05-10 18:53:46 +08:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2020-04-17 10:52:00 +08:00
# include "shader_globals_override.h"
2021-08-13 07:05:59 +08:00
# include "scene/3d/node_3d.h"
2020-04-17 10:52:00 +08:00
# 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 ;
}
2020-05-14 20:29:06 +08:00
2020-04-17 10:52:00 +08:00
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 ) {
2021-07-06 09:40:29 +08:00
if ( o - > override . get_type ( ) = = Variant : : OBJECT ) {
RID tex_rid = p_value ;
RS : : get_singleton ( ) - > global_variable_set_override ( * r , tex_rid ) ;
} else {
RS : : get_singleton ( ) - > global_variable_set_override ( * r , p_value ) ;
}
2020-04-17 10:52:00 +08:00
}
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 : {
2022-04-13 01:09:29 +08:00
pinfo . type = Variant : : QUATERNION ;
2020-04-17 10:52:00 +08:00
} 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 : {
2021-04-28 15:36:08 +08:00
pinfo . type = Variant : : TRANSFORM3D ;
2020-04-17 10:52:00 +08:00
} 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 ;
2020-11-09 11:19:09 +08:00
Variant : : construct ( pinfo . type , o . override , nullptr , 0 , ce ) ;
2020-04-17 10:52:00 +08:00
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 ( ) {
2022-02-11 01:22:20 +08:00
ERR_FAIL_NULL ( get_tree ( ) ) ;
2020-04-17 10:52:00 +08:00
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 ) {
2021-07-06 09:40:29 +08:00
if ( o - > override . get_type ( ) = = Variant : : OBJECT ) {
RID tex_rid = o - > override ;
RS : : get_singleton ( ) - > global_variable_set_override ( * K , tex_rid ) ;
} else {
RS : : get_singleton ( ) - > global_variable_set_override ( * K , o - > override ) ;
}
2020-04-17 10:52:00 +08:00
}
}
2020-10-29 18:01:28 +08:00
update_configuration_warnings ( ) ; //may have activated
2020-04-17 10:52:00 +08:00
}
}
void ShaderGlobalsOverride : : _notification ( int p_what ) {
2022-02-16 01:06:48 +08:00
switch ( p_what ) {
case Node3D : : NOTIFICATION_ENTER_TREE : {
add_to_group ( SceneStringNames : : get_singleton ( ) - > shader_overrides_group ) ;
_activate ( ) ;
} break ;
2020-04-17 10:52:00 +08:00
2022-02-16 01:06:48 +08:00
case 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 ( ) ) ;
}
2020-04-17 10:52:00 +08:00
}
}
2022-02-16 01:06:48 +08:00
remove_from_group ( SceneStringNames : : get_singleton ( ) - > shader_overrides_group_active ) ;
remove_from_group ( SceneStringNames : : get_singleton ( ) - > shader_overrides_group ) ;
2021-08-13 05:40:13 +08:00
get_tree ( ) - > call_group_flags ( SceneTree : : GROUP_CALL_DEFERRED , SceneStringNames : : get_singleton ( ) - > shader_overrides_group , " _activate " ) ; //another may want to activate when this is removed
2022-02-16 01:06:48 +08:00
active = false ;
} break ;
2020-04-17 10:52:00 +08:00
}
}
2020-10-29 18:01:28 +08:00
TypedArray < String > ShaderGlobalsOverride : : get_configuration_warnings ( ) const {
TypedArray < String > warnings = Node : : get_configuration_warnings ( ) ;
2020-05-15 04:59:27 +08:00
2020-04-17 10:52:00 +08:00
if ( ! active ) {
2022-03-28 21:24:14 +08:00
warnings . push_back ( RTR ( " ShaderGlobalsOverride is not active because another node of the same type is in the scene. " ) ) ;
2020-04-17 10:52:00 +08:00
}
2020-10-29 18:01:28 +08:00
return warnings ;
2020-04-17 10:52:00 +08:00
}
void ShaderGlobalsOverride : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " _activate " ) , & ShaderGlobalsOverride : : _activate ) ;
}
2021-02-10 01:24:36 +08:00
ShaderGlobalsOverride : : ShaderGlobalsOverride ( ) { }