2017-03-05 15:47:28 +01:00
/*************************************************************************/
/* visual_script.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2017-03-05 15:47:28 +01:00
/*************************************************************************/
2022-01-13 09:45:09 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2017-03-05 15:47:28 +01: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. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2016-08-03 00:11:05 +02:00
# include "visual_script.h"
2017-03-05 15:47:28 +01:00
2019-04-10 07:07:40 +02:00
# include "core/core_string_names.h"
2018-09-11 18:13:45 +02:00
# include "core/os/os.h"
# include "core/project_settings.h"
2017-03-05 16:44:50 +01:00
# include "scene/main/node.h"
# include "visual_script_nodes.h"
2016-08-07 00:00:54 +02:00
//used by editor, this is not really saved
void VisualScriptNode : : set_breakpoint ( bool p_breakpoint ) {
2017-03-05 16:44:50 +01:00
breakpoint = p_breakpoint ;
2016-08-07 00:00:54 +02:00
}
bool VisualScriptNode : : is_breakpoint ( ) const {
return breakpoint ;
}
2018-09-29 21:50:04 +02:00
void VisualScriptNode : : ports_changed_notify ( ) {
2016-08-04 03:06:39 +02:00
emit_signal ( " ports_changed " ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptNode : : set_default_input_value ( int p_port , const Variant & p_value ) {
ERR_FAIL_INDEX ( p_port , default_input_values . size ( ) ) ;
2016-08-04 03:06:39 +02:00
2017-03-05 16:44:50 +01:00
default_input_values [ p_port ] = p_value ;
2016-08-31 17:49:45 +02:00
# ifdef TOOLS_ENABLED
2017-03-05 16:44:50 +01:00
for ( Set < VisualScript * > : : Element * E = scripts_used . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-31 17:49:45 +02:00
E - > get ( ) - > set_edited ( true ) ;
}
# endif
2016-08-04 03:06:39 +02:00
}
Variant VisualScriptNode : : get_default_input_value ( int p_port ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_port , default_input_values . size ( ) , Variant ( ) ) ;
2016-08-04 03:06:39 +02:00
return default_input_values [ p_port ] ;
}
void VisualScriptNode : : _set_default_input_values ( Array p_values ) {
2017-03-05 16:44:50 +01:00
default_input_values = p_values ;
2016-08-04 03:06:39 +02:00
}
2016-08-25 22:45:20 +02:00
void VisualScriptNode : : validate_input_default_values ( ) {
2019-03-04 19:41:50 +01:00
default_input_values . resize ( MAX ( default_input_values . size ( ) , get_input_value_port_count ( ) ) ) ; //let it grow as big as possible, we don't want to lose values on resize
2016-08-04 03:06:39 +02:00
//actually validate on save
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < get_input_value_port_count ( ) ; i + + ) {
2016-08-04 03:06:39 +02:00
Variant : : Type expected = get_input_value_port_info ( i ) . type ;
2017-03-05 16:44:50 +01:00
if ( expected = = Variant : : NIL | | expected = = default_input_values [ i ] . get_type ( ) ) {
2016-08-25 22:45:20 +02:00
continue ;
2017-03-05 16:44:50 +01:00
} else {
2016-08-25 22:45:20 +02:00
//not the same, reconvert
2016-08-04 03:06:39 +02:00
Variant : : CallError ce ;
2016-08-25 22:45:20 +02:00
Variant existing = default_input_values [ i ] ;
2017-03-05 16:44:50 +01:00
const Variant * existingp = & existing ;
default_input_values [ i ] = Variant : : construct ( expected , & existingp , 1 , ce , false ) ;
if ( ce . error ! = Variant : : CallError : : CALL_OK ) {
2016-08-25 22:45:20 +02:00
//could not convert? force..
2021-05-04 16:00:45 +02:00
default_input_values [ i ] = Variant : : construct ( expected , nullptr , 0 , ce , false ) ;
2016-08-04 03:06:39 +02:00
}
}
}
2016-08-25 22:45:20 +02:00
}
Array VisualScriptNode : : _get_default_input_values ( ) const {
//validate on save, since on load there is little info about this
2019-03-04 19:41:50 +01:00
Array values = default_input_values ;
values . resize ( get_input_value_port_count ( ) ) ;
2016-08-25 22:45:20 +02:00
2019-03-04 19:41:50 +01:00
return values ;
2016-08-04 03:06:39 +02:00
}
2018-04-30 01:28:31 +02:00
String VisualScriptNode : : get_text ( ) const {
return " " ;
}
2016-08-03 00:11:05 +02:00
void VisualScriptNode : : _bind_methods ( ) {
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_visual_script " ) , & VisualScriptNode : : get_visual_script ) ;
ClassDB : : bind_method ( D_METHOD ( " set_default_input_value " , " port_idx " , " value " ) , & VisualScriptNode : : set_default_input_value ) ;
ClassDB : : bind_method ( D_METHOD ( " get_default_input_value " , " port_idx " ) , & VisualScriptNode : : get_default_input_value ) ;
2017-09-28 12:07:20 +02:00
ClassDB : : bind_method ( D_METHOD ( " ports_changed_notify " ) , & VisualScriptNode : : ports_changed_notify ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _set_default_input_values " , " values " ) , & VisualScriptNode : : _set_default_input_values ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_default_input_values " ) , & VisualScriptNode : : _get_default_input_values ) ;
2016-08-04 03:06:39 +02:00
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : ARRAY , " _default_input_values " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL ) , " _set_default_input_values " , " _get_default_input_values " ) ;
2016-08-03 00:11:05 +02:00
ADD_SIGNAL ( MethodInfo ( " ports_changed " ) ) ;
}
2017-03-05 16:44:50 +01:00
VisualScriptNode : : TypeGuess VisualScriptNode : : guess_output_type ( TypeGuess * p_inputs , int p_output ) const {
2016-08-31 04:44:14 +02:00
PropertyInfo pinfo = get_output_value_port_info ( p_output ) ;
TypeGuess tg ;
2017-03-05 16:44:50 +01:00
tg . type = pinfo . type ;
if ( pinfo . hint = = PROPERTY_HINT_RESOURCE_TYPE ) {
2017-07-01 02:30:17 +02:00
tg . gdclass = pinfo . hint_string ;
2016-08-31 04:44:14 +02:00
}
return tg ;
}
2016-08-03 00:11:05 +02:00
Ref < VisualScript > VisualScriptNode : : get_visual_script ( ) const {
2021-05-05 12:44:11 +02:00
if ( scripts_used . size ( ) ) {
2016-08-03 00:11:05 +02:00
return Ref < VisualScript > ( scripts_used . front ( ) - > get ( ) ) ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
return Ref < VisualScript > ( ) ;
}
2016-08-07 00:00:54 +02:00
VisualScriptNode : : VisualScriptNode ( ) {
2017-03-05 16:44:50 +01:00
breakpoint = false ;
2016-08-07 00:00:54 +02:00
}
2016-08-03 00:11:05 +02:00
////////////////
/////////////////////
2016-08-06 03:46:45 +02:00
VisualScriptNodeInstance : : VisualScriptNodeInstance ( ) {
2021-05-04 16:00:45 +02:00
sequence_outputs = nullptr ;
input_ports = nullptr ;
2016-08-06 03:46:45 +02:00
}
2016-08-03 00:11:05 +02:00
VisualScriptNodeInstance : : ~ VisualScriptNodeInstance ( ) {
2016-08-06 03:46:45 +02:00
if ( sequence_outputs ) {
2016-08-31 04:44:14 +02:00
memdelete_arr ( sequence_outputs ) ;
2016-08-06 03:46:45 +02:00
}
if ( input_ports ) {
2016-08-31 04:44:14 +02:00
memdelete_arr ( input_ports ) ;
2016-08-06 03:46:45 +02:00
}
if ( output_ports ) {
2016-08-31 04:44:14 +02:00
memdelete_arr ( output_ports ) ;
2016-08-06 03:46:45 +02:00
}
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : add_function ( const StringName & p_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! String ( p_name ) . is_valid_identifier ( ) ) ;
ERR_FAIL_COND ( functions . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
functions [ p_name ] = Function ( ) ;
functions [ p_name ] . scroll = Vector2 ( - 50 , - 100 ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_function ( const StringName & p_name ) const {
2016-08-03 00:11:05 +02:00
return functions . has ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : remove_function ( const StringName & p_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
for ( Map < int , Function : : NodeData > : : Element * E = functions [ p_name ] . nodes . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) . node - > disconnect ( " ports_changed " , this , " _node_ports_changed " ) ;
2016-08-03 00:11:05 +02:00
E - > get ( ) . node - > scripts_used . erase ( this ) ;
}
functions . erase ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : rename_function ( const StringName & p_name , const StringName & p_new_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_name ) ) ;
2021-05-05 12:44:11 +02:00
if ( p_new_name = = p_name ) {
2016-08-03 00:11:05 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! String ( p_new_name ) . is_valid_identifier ( ) ) ;
ERR_FAIL_COND ( functions . has ( p_new_name ) ) ;
ERR_FAIL_COND ( variables . has ( p_new_name ) ) ;
ERR_FAIL_COND ( custom_signals . has ( p_new_name ) ) ;
2017-03-05 16:44:50 +01:00
functions [ p_new_name ] = functions [ p_name ] ;
2016-08-03 00:11:05 +02:00
functions . erase ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : set_function_scroll ( const StringName & p_name , const Vector2 & p_scroll ) {
2016-08-07 00:00:54 +02:00
ERR_FAIL_COND ( ! functions . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
functions [ p_name ] . scroll = p_scroll ;
2016-08-07 00:00:54 +02:00
}
2017-03-05 16:44:50 +01:00
Vector2 VisualScript : : get_function_scroll ( const StringName & p_name ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_name ) , Vector2 ( ) ) ;
2016-08-07 00:00:54 +02:00
return functions [ p_name ] . scroll ;
}
2016-08-03 00:11:05 +02:00
void VisualScript : : get_function_list ( List < StringName > * r_functions ) const {
2017-03-05 16:44:50 +01:00
for ( const Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_functions - > push_back ( E - > key ( ) ) ;
}
r_functions - > sort_custom < StringName : : AlphCompare > ( ) ;
}
2017-03-05 16:44:50 +01:00
int VisualScript : : get_function_node_id ( const StringName & p_name ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_name ) , - 1 ) ;
2016-08-03 00:11:05 +02:00
return functions [ p_name ] . function_id ;
}
void VisualScript : : _node_ports_changed ( int p_id ) {
StringName function ;
2017-03-05 16:44:50 +01:00
for ( Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
if ( E - > get ( ) . nodes . has ( p_id ) ) {
2017-03-05 16:44:50 +01:00
function = E - > key ( ) ;
2016-08-03 00:11:05 +02:00
break ;
}
}
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( function = = StringName ( ) ) ;
2016-08-03 00:11:05 +02:00
Function & func = functions [ function ] ;
Ref < VisualScriptNode > vsn = func . nodes [ p_id ] . node ;
2019-05-02 14:29:07 +02:00
vsn - > validate_input_default_values ( ) ;
2016-08-25 22:45:20 +02:00
2016-08-03 00:11:05 +02:00
//must revalidate all the functions
{
List < SequenceConnection > to_remove ;
2017-03-05 16:44:50 +01:00
for ( Set < SequenceConnection > : : Element * E = func . sequence_connections . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . from_node = = p_id & & E - > get ( ) . from_output > = vsn - > get_output_sequence_port_count ( ) ) {
2016-08-03 00:11:05 +02:00
to_remove . push_back ( E - > get ( ) ) ;
}
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . to_node = = p_id & & ! vsn - > has_input_sequence_port ( ) ) {
2016-08-03 00:11:05 +02:00
to_remove . push_back ( E - > get ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
while ( to_remove . size ( ) ) {
2016-08-03 00:11:05 +02:00
func . sequence_connections . erase ( to_remove . front ( ) - > get ( ) ) ;
to_remove . pop_front ( ) ;
}
}
{
List < DataConnection > to_remove ;
2017-03-05 16:44:50 +01:00
for ( Set < DataConnection > : : Element * E = func . data_connections . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . from_node = = p_id & & E - > get ( ) . from_port > = vsn - > get_output_value_port_count ( ) ) {
2016-08-03 00:11:05 +02:00
to_remove . push_back ( E - > get ( ) ) ;
}
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . to_node = = p_id & & E - > get ( ) . to_port > = vsn - > get_input_value_port_count ( ) ) {
2016-08-03 00:11:05 +02:00
to_remove . push_back ( E - > get ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
while ( to_remove . size ( ) ) {
2016-08-03 00:11:05 +02:00
func . data_connections . erase ( to_remove . front ( ) - > get ( ) ) ;
to_remove . pop_front ( ) ;
}
}
2016-08-15 09:54:02 +02:00
# ifdef TOOLS_ENABLED
2016-08-08 00:22:33 +02:00
set_edited ( true ) ; //something changed, let's set as edited
2017-03-05 16:44:50 +01:00
emit_signal ( " node_ports_changed " , function , p_id ) ;
2016-08-15 09:54:02 +02:00
# endif
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : add_node ( const StringName & p_func , int p_id , const Ref < VisualScriptNode > & p_node , const Point2 & p_pos ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
2021-08-02 17:36:13 +02:00
ERR_FAIL_COND ( p_node . is_null ( ) ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
for ( Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( E - > get ( ) . nodes . has ( p_id ) ) ; //id can exist only one in script, even for different functions
}
Function & func = functions [ p_func ] ;
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < VisualScriptFunction > ( * p_node ) ) {
2016-08-03 00:11:05 +02:00
//the function indeed
2019-08-11 10:49:53 +02:00
ERR_FAIL_COND_MSG ( func . function_id > = 0 , " A function node has already been set here. " ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
func . function_id = p_id ;
2016-08-03 00:11:05 +02:00
}
Function : : NodeData nd ;
2017-03-05 16:44:50 +01:00
nd . node = p_node ;
nd . pos = p_pos ;
2016-08-03 00:11:05 +02:00
Ref < VisualScriptNode > vsn = p_node ;
2017-03-05 16:44:50 +01:00
vsn - > connect ( " ports_changed " , this , " _node_ports_changed " , varray ( p_id ) ) ;
2016-08-03 00:11:05 +02:00
vsn - > scripts_used . insert ( this ) ;
2019-05-02 14:29:07 +02:00
vsn - > validate_input_default_values ( ) ; // Validate when fully loaded
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
func . nodes [ p_id ] = nd ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : remove_node ( const StringName & p_func , int p_id ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
Function & func = functions [ p_func ] ;
ERR_FAIL_COND ( ! func . nodes . has ( p_id ) ) ;
{
List < SequenceConnection > to_remove ;
2017-03-05 16:44:50 +01:00
for ( Set < SequenceConnection > : : Element * E = func . sequence_connections . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . from_node = = p_id | | E - > get ( ) . to_node = = p_id ) {
2016-08-03 00:11:05 +02:00
to_remove . push_back ( E - > get ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
while ( to_remove . size ( ) ) {
2016-08-03 00:11:05 +02:00
func . sequence_connections . erase ( to_remove . front ( ) - > get ( ) ) ;
to_remove . pop_front ( ) ;
}
}
{
List < DataConnection > to_remove ;
2017-03-05 16:44:50 +01:00
for ( Set < DataConnection > : : Element * E = func . data_connections . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . from_node = = p_id | | E - > get ( ) . to_node = = p_id ) {
2016-08-03 00:11:05 +02:00
to_remove . push_back ( E - > get ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
while ( to_remove . size ( ) ) {
2016-08-03 00:11:05 +02:00
func . data_connections . erase ( to_remove . front ( ) - > get ( ) ) ;
to_remove . pop_front ( ) ;
}
}
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < VisualScriptFunction > ( func . nodes [ p_id ] . node . ptr ( ) ) ) {
2017-03-05 16:44:50 +01:00
func . function_id = - 1 ; //revert to invalid
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
func . nodes [ p_id ] . node - > disconnect ( " ports_changed " , this , " _node_ports_changed " ) ;
2016-08-03 00:11:05 +02:00
func . nodes [ p_id ] . node - > scripts_used . erase ( this ) ;
func . nodes . erase ( p_id ) ;
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_node ( const StringName & p_func , int p_id ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , false ) ;
2016-08-07 00:00:54 +02:00
const Function & func = functions [ p_func ] ;
return func . nodes . has ( p_id ) ;
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
Ref < VisualScriptNode > VisualScript : : get_node ( const StringName & p_func , int p_id ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , Ref < VisualScriptNode > ( ) ) ;
2016-08-03 00:11:05 +02:00
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! func . nodes . has ( p_id ) , Ref < VisualScriptNode > ( ) ) ;
2016-08-03 00:11:05 +02:00
return func . nodes [ p_id ] . node ;
}
2017-09-10 15:37:49 +02:00
void VisualScript : : set_node_position ( const StringName & p_func , int p_id , const Point2 & p_pos ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
Function & func = functions [ p_func ] ;
ERR_FAIL_COND ( ! func . nodes . has ( p_id ) ) ;
2017-03-05 16:44:50 +01:00
func . nodes [ p_id ] . pos = p_pos ;
2016-08-03 00:11:05 +02:00
}
2017-09-10 15:37:49 +02:00
Point2 VisualScript : : get_node_position ( const StringName & p_func , int p_id ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , Point2 ( ) ) ;
2016-08-03 00:11:05 +02:00
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! func . nodes . has ( p_id ) , Point2 ( ) ) ;
2016-08-03 00:11:05 +02:00
return func . nodes [ p_id ] . pos ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : get_node_list ( const StringName & p_func , List < int > * r_nodes ) const {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
for ( const Map < int , Function : : NodeData > : : Element * E = func . nodes . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_nodes - > push_back ( E - > key ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
void VisualScript : : sequence_connect ( const StringName & p_func , int p_from_node , int p_from_output , int p_to_node ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
Function & func = functions [ p_func ] ;
SequenceConnection sc ;
2017-03-05 16:44:50 +01:00
sc . from_node = p_from_node ;
sc . from_output = p_from_output ;
sc . to_node = p_to_node ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( func . sequence_connections . has ( sc ) ) ;
func . sequence_connections . insert ( sc ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : sequence_disconnect ( const StringName & p_func , int p_from_node , int p_from_output , int p_to_node ) {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
Function & func = functions [ p_func ] ;
SequenceConnection sc ;
2017-03-05 16:44:50 +01:00
sc . from_node = p_from_node ;
sc . from_output = p_from_output ;
sc . to_node = p_to_node ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! func . sequence_connections . has ( sc ) ) ;
func . sequence_connections . erase ( sc ) ;
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_sequence_connection ( const StringName & p_func , int p_from_node , int p_from_output , int p_to_node ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , false ) ;
2016-08-03 00:11:05 +02:00
const Function & func = functions [ p_func ] ;
SequenceConnection sc ;
2017-03-05 16:44:50 +01:00
sc . from_node = p_from_node ;
sc . from_output = p_from_output ;
sc . to_node = p_to_node ;
2016-08-03 00:11:05 +02:00
return func . sequence_connections . has ( sc ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : get_sequence_connection_list ( const StringName & p_func , List < SequenceConnection > * r_connection ) const {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
for ( const Set < SequenceConnection > : : Element * E = func . sequence_connections . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_connection - > push_back ( E - > get ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
void VisualScript : : data_connect ( const StringName & p_func , int p_from_node , int p_from_port , int p_to_node , int p_to_port ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
Function & func = functions [ p_func ] ;
DataConnection dc ;
2017-03-05 16:44:50 +01:00
dc . from_node = p_from_node ;
dc . from_port = p_from_port ;
dc . to_node = p_to_node ;
dc . to_port = p_to_port ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( func . data_connections . has ( dc ) ) ;
2016-08-03 00:11:05 +02:00
func . data_connections . insert ( dc ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : data_disconnect ( const StringName & p_func , int p_from_node , int p_from_port , int p_to_node , int p_to_port ) {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
Function & func = functions [ p_func ] ;
DataConnection dc ;
2017-03-05 16:44:50 +01:00
dc . from_node = p_from_node ;
dc . from_port = p_from_port ;
dc . to_node = p_to_node ;
dc . to_port = p_to_port ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! func . data_connections . has ( dc ) ) ;
2016-08-03 00:11:05 +02:00
func . data_connections . erase ( dc ) ;
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_data_connection ( const StringName & p_func , int p_from_node , int p_from_port , int p_to_node , int p_to_port ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , false ) ;
2016-08-03 00:11:05 +02:00
const Function & func = functions [ p_func ] ;
DataConnection dc ;
2017-03-05 16:44:50 +01:00
dc . from_node = p_from_node ;
dc . from_port = p_from_port ;
dc . to_node = p_to_node ;
dc . to_port = p_to_port ;
2016-08-03 00:11:05 +02:00
return func . data_connections . has ( dc ) ;
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : is_input_value_port_connected ( const StringName & p_func , int p_node , int p_port ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , false ) ;
2016-08-04 03:06:39 +02:00
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
for ( const Set < DataConnection > : : Element * E = func . data_connections . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( E - > get ( ) . to_node = = p_node & & E - > get ( ) . to_port = = p_port ) {
2016-08-04 03:06:39 +02:00
return true ;
2021-05-05 12:44:11 +02:00
}
2016-08-04 03:06:39 +02:00
}
return false ;
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : get_input_value_port_connection_source ( const StringName & p_func , int p_node , int p_port , int * r_node , int * r_port ) const {
ERR_FAIL_COND_V ( ! functions . has ( p_func ) , false ) ;
2016-09-03 19:58:23 +02:00
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
for ( const Set < DataConnection > : : Element * E = func . data_connections . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . to_node = = p_node & & E - > get ( ) . to_port = = p_port ) {
* r_node = E - > get ( ) . from_node ;
* r_port = E - > get ( ) . from_port ;
2016-09-03 19:58:23 +02:00
return true ;
}
}
return false ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : get_data_connection_list ( const StringName & p_func , List < DataConnection > * r_connection ) const {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! functions . has ( p_func ) ) ;
const Function & func = functions [ p_func ] ;
2017-03-05 16:44:50 +01:00
for ( const Set < DataConnection > : : Element * E = func . data_connections . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_connection - > push_back ( E - > get ( ) ) ;
}
}
2019-07-26 22:00:23 +02:00
void VisualScript : : set_tool_enabled ( bool p_enabled ) {
is_tool_script = p_enabled ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : add_variable ( const StringName & p_name , const Variant & p_default_value , bool p_export ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! String ( p_name ) . is_valid_identifier ( ) ) ;
ERR_FAIL_COND ( variables . has ( p_name ) ) ;
Variable v ;
2017-03-05 16:44:50 +01:00
v . default_value = p_default_value ;
v . info . type = p_default_value . get_type ( ) ;
v . info . name = p_name ;
v . info . hint = PROPERTY_HINT_NONE ;
v . _export = p_export ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
variables [ p_name ] = v ;
2016-08-06 03:46:45 +02:00
# ifdef TOOLS_ENABLED
_update_placeholders ( ) ;
# endif
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_variable ( const StringName & p_name ) const {
2016-08-03 00:11:05 +02:00
return variables . has ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : remove_variable ( const StringName & p_name ) {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! variables . has ( p_name ) ) ;
variables . erase ( p_name ) ;
2016-08-06 03:46:45 +02:00
# ifdef TOOLS_ENABLED
_update_placeholders ( ) ;
# endif
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : set_variable_default_value ( const StringName & p_name , const Variant & p_value ) {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! variables . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
variables [ p_name ] . default_value = p_value ;
2016-08-03 00:11:05 +02:00
2016-08-06 03:46:45 +02:00
# ifdef TOOLS_ENABLED
_update_placeholders ( ) ;
# endif
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Variant VisualScript : : get_variable_default_value ( const StringName & p_name ) const {
ERR_FAIL_COND_V ( ! variables . has ( p_name ) , Variant ( ) ) ;
2016-08-03 00:11:05 +02:00
return variables [ p_name ] . default_value ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : set_variable_info ( const StringName & p_name , const PropertyInfo & p_info ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! variables . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
variables [ p_name ] . info = p_info ;
variables [ p_name ] . info . name = p_name ;
2016-08-03 00:11:05 +02:00
2016-08-06 03:46:45 +02:00
# ifdef TOOLS_ENABLED
_update_placeholders ( ) ;
# endif
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
PropertyInfo VisualScript : : get_variable_info ( const StringName & p_name ) const {
ERR_FAIL_COND_V ( ! variables . has ( p_name ) , PropertyInfo ( ) ) ;
2016-08-03 00:11:05 +02:00
return variables [ p_name ] . info ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : set_variable_export ( const StringName & p_name , bool p_export ) {
2016-08-31 04:44:14 +02:00
ERR_FAIL_COND ( ! variables . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
variables [ p_name ] . _export = p_export ;
2017-07-01 02:30:17 +02:00
# ifdef TOOLS_ENABLED
_update_placeholders ( ) ;
# endif
2016-08-31 04:44:14 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : get_variable_export ( const StringName & p_name ) const {
ERR_FAIL_COND_V ( ! variables . has ( p_name ) , false ) ;
2016-08-31 04:44:14 +02:00
return variables [ p_name ] . _export ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : _set_variable_info ( const StringName & p_name , const Dictionary & p_info ) {
2016-08-03 00:11:05 +02:00
PropertyInfo pinfo ;
2021-05-05 12:44:11 +02:00
if ( p_info . has ( " type " ) ) {
2017-03-05 16:44:50 +01:00
pinfo . type = Variant : : Type ( int ( p_info [ " type " ] ) ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_info . has ( " name " ) ) {
2017-03-05 16:44:50 +01:00
pinfo . name = p_info [ " name " ] ;
2021-05-05 12:44:11 +02:00
}
if ( p_info . has ( " hint " ) ) {
2017-03-05 16:44:50 +01:00
pinfo . hint = PropertyHint ( int ( p_info [ " hint " ] ) ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_info . has ( " hint_string " ) ) {
2017-03-05 16:44:50 +01:00
pinfo . hint_string = p_info [ " hint_string " ] ;
2021-05-05 12:44:11 +02:00
}
if ( p_info . has ( " usage " ) ) {
2017-03-05 16:44:50 +01:00
pinfo . usage = p_info [ " usage " ] ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
set_variable_info ( p_name , pinfo ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Dictionary VisualScript : : _get_variable_info ( const StringName & p_name ) const {
PropertyInfo pinfo = get_variable_info ( p_name ) ;
2016-08-03 00:11:05 +02:00
Dictionary d ;
2017-03-05 16:44:50 +01:00
d [ " type " ] = pinfo . type ;
d [ " name " ] = pinfo . name ;
d [ " hint " ] = pinfo . hint ;
d [ " hint_string " ] = pinfo . hint_string ;
d [ " usage " ] = pinfo . usage ;
2016-08-03 00:11:05 +02:00
return d ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : get_variable_list ( List < StringName > * r_variables ) const {
for ( Map < StringName , Variable > : : Element * E = variables . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_variables - > push_back ( E - > key ( ) ) ;
}
r_variables - > sort_custom < StringName : : AlphCompare > ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : set_instance_base_type ( const StringName & p_type ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
base_type = p_type ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : rename_variable ( const StringName & p_name , const StringName & p_new_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! variables . has ( p_name ) ) ;
2021-05-05 12:44:11 +02:00
if ( p_new_name = = p_name ) {
2016-08-03 00:11:05 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! String ( p_new_name ) . is_valid_identifier ( ) ) ;
ERR_FAIL_COND ( functions . has ( p_new_name ) ) ;
ERR_FAIL_COND ( variables . has ( p_new_name ) ) ;
ERR_FAIL_COND ( custom_signals . has ( p_new_name ) ) ;
2017-03-05 16:44:50 +01:00
variables [ p_new_name ] = variables [ p_name ] ;
2016-08-03 00:11:05 +02:00
variables . erase ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : add_custom_signal ( const StringName & p_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! String ( p_name ) . is_valid_identifier ( ) ) ;
ERR_FAIL_COND ( custom_signals . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
custom_signals [ p_name ] = Vector < Argument > ( ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_custom_signal ( const StringName & p_name ) const {
2016-08-03 00:11:05 +02:00
return custom_signals . has ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : custom_signal_add_argument ( const StringName & p_func , Variant : : Type p_type , const String & p_name , int p_index ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_func ) ) ;
Argument arg ;
2017-03-05 16:44:50 +01:00
arg . type = p_type ;
arg . name = p_name ;
2021-05-05 12:44:11 +02:00
if ( p_index < 0 ) {
2016-08-03 00:11:05 +02:00
custom_signals [ p_func ] . push_back ( arg ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
custom_signals [ p_func ] . insert ( 0 , arg ) ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : custom_signal_set_argument_type ( const StringName & p_func , int p_argidx , Variant : : Type p_type ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_func ) ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_argidx , custom_signals [ p_func ] . size ( ) ) ;
2018-07-25 03:11:03 +02:00
custom_signals [ p_func ] . write [ p_argidx ] . type = p_type ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Variant : : Type VisualScript : : custom_signal_get_argument_type ( const StringName & p_func , int p_argidx ) const {
ERR_FAIL_COND_V ( ! custom_signals . has ( p_func ) , Variant : : NIL ) ;
ERR_FAIL_INDEX_V ( p_argidx , custom_signals [ p_func ] . size ( ) , Variant : : NIL ) ;
2016-08-03 00:11:05 +02:00
return custom_signals [ p_func ] [ p_argidx ] . type ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : custom_signal_set_argument_name ( const StringName & p_func , int p_argidx , const String & p_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_func ) ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_argidx , custom_signals [ p_func ] . size ( ) ) ;
2018-07-25 03:11:03 +02:00
custom_signals [ p_func ] . write [ p_argidx ] . name = p_name ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
String VisualScript : : custom_signal_get_argument_name ( const StringName & p_func , int p_argidx ) const {
ERR_FAIL_COND_V ( ! custom_signals . has ( p_func ) , String ( ) ) ;
ERR_FAIL_INDEX_V ( p_argidx , custom_signals [ p_func ] . size ( ) , String ( ) ) ;
2016-08-03 00:11:05 +02:00
return custom_signals [ p_func ] [ p_argidx ] . name ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : custom_signal_remove_argument ( const StringName & p_func , int p_argidx ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_func ) ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_argidx , custom_signals [ p_func ] . size ( ) ) ;
2016-08-03 00:11:05 +02:00
custom_signals [ p_func ] . remove ( p_argidx ) ;
}
2017-03-05 16:44:50 +01:00
int VisualScript : : custom_signal_get_argument_count ( const StringName & p_func ) const {
ERR_FAIL_COND_V ( ! custom_signals . has ( p_func ) , 0 ) ;
2016-08-03 00:11:05 +02:00
return custom_signals [ p_func ] . size ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : custom_signal_swap_argument ( const StringName & p_func , int p_argidx , int p_with_argidx ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_func ) ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_argidx , custom_signals [ p_func ] . size ( ) ) ;
ERR_FAIL_INDEX ( p_with_argidx , custom_signals [ p_func ] . size ( ) ) ;
2016-08-03 00:11:05 +02:00
2018-07-25 03:11:03 +02:00
SWAP ( custom_signals [ p_func ] . write [ p_argidx ] , custom_signals [ p_func ] . write [ p_with_argidx ] ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScript : : remove_custom_signal ( const StringName & p_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_name ) ) ;
custom_signals . erase ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : rename_custom_signal ( const StringName & p_name , const StringName & p_new_name ) {
ERR_FAIL_COND ( instances . size ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! custom_signals . has ( p_name ) ) ;
2021-05-05 12:44:11 +02:00
if ( p_new_name = = p_name ) {
2016-08-03 00:11:05 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! String ( p_new_name ) . is_valid_identifier ( ) ) ;
ERR_FAIL_COND ( functions . has ( p_new_name ) ) ;
ERR_FAIL_COND ( variables . has ( p_new_name ) ) ;
ERR_FAIL_COND ( custom_signals . has ( p_new_name ) ) ;
2017-03-05 16:44:50 +01:00
custom_signals [ p_new_name ] = custom_signals [ p_name ] ;
2016-08-03 00:11:05 +02:00
custom_signals . erase ( p_name ) ;
}
void VisualScript : : get_custom_signal_list ( List < StringName > * r_custom_signals ) const {
2021-05-04 14:20:36 +02:00
for ( const Map < StringName , Vector < Argument > > : : Element * E = custom_signals . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_custom_signals - > push_back ( E - > key ( ) ) ;
}
r_custom_signals - > sort_custom < StringName : : AlphCompare > ( ) ;
}
int VisualScript : : get_available_id ( ) const {
2017-03-05 16:44:50 +01:00
int max_id = 0 ;
for ( Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( E - > get ( ) . nodes . empty ( ) ) {
2016-08-03 00:11:05 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
int last_id = E - > get ( ) . nodes . back ( ) - > key ( ) ;
2017-03-05 16:44:50 +01:00
max_id = MAX ( max_id , last_id + 1 ) ;
2016-08-03 00:11:05 +02:00
}
return max_id ;
}
/////////////////////////////////
bool VisualScript : : can_instance ( ) const {
2017-03-05 16:44:50 +01:00
return true ; //ScriptServer::is_scripting_enabled();
2016-08-03 00:11:05 +02:00
}
StringName VisualScript : : get_instance_base_type ( ) const {
return base_type ;
}
2016-08-25 22:45:20 +02:00
Ref < Script > VisualScript : : get_base_script ( ) const {
return Ref < Script > ( ) ; // no inheritance in visual script
}
2016-08-06 03:46:45 +02:00
# ifdef TOOLS_ENABLED
void VisualScript : : _placeholder_erased ( PlaceHolderScriptInstance * p_placeholder ) {
placeholders . erase ( p_placeholder ) ;
}
void VisualScript : : _update_placeholders ( ) {
2021-05-05 12:44:11 +02:00
if ( placeholders . size ( ) = = 0 ) {
2016-08-06 03:46:45 +02:00
return ; //no bother if no placeholders
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
List < PropertyInfo > pinfo ;
2017-03-05 16:44:50 +01:00
Map < StringName , Variant > values ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
for ( Map < StringName , Variable > : : Element * E = variables . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( ! E - > get ( ) . _export ) {
2016-08-31 22:58:51 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2016-08-31 22:58:51 +02:00
2016-08-06 03:46:45 +02:00
PropertyInfo p = E - > get ( ) . info ;
2017-03-05 16:44:50 +01:00
p . name = String ( E - > key ( ) ) ;
2016-08-06 03:46:45 +02:00
pinfo . push_back ( p ) ;
2017-03-05 16:44:50 +01:00
values [ p . name ] = E - > get ( ) . default_value ;
2016-08-06 03:46:45 +02:00
}
2017-03-05 16:44:50 +01:00
for ( Set < PlaceHolderScriptInstance * > : : Element * E = placeholders . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) - > update ( pinfo , values ) ;
2016-08-06 03:46:45 +02:00
}
}
# endif
2017-03-05 16:44:50 +01:00
ScriptInstance * VisualScript : : instance_create ( Object * p_this ) {
2016-08-06 03:46:45 +02:00
# ifdef TOOLS_ENABLED
2019-07-26 22:00:23 +02:00
if ( ! ScriptServer : : is_scripting_enabled ( ) & & ! is_tool_script ) {
2017-03-05 16:44:50 +01:00
PlaceHolderScriptInstance * sins = memnew ( PlaceHolderScriptInstance ( VisualScriptLanguage : : singleton , Ref < Script > ( ( Script * ) this ) , p_this ) ) ;
2016-08-06 03:46:45 +02:00
placeholders . insert ( sins ) ;
List < PropertyInfo > pinfo ;
2017-03-05 16:44:50 +01:00
Map < StringName , Variant > values ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
for ( Map < StringName , Variable > : : Element * E = variables . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( ! E - > get ( ) . _export ) {
2016-08-31 22:58:51 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2016-08-31 22:58:51 +02:00
2016-08-06 03:46:45 +02:00
PropertyInfo p = E - > get ( ) . info ;
2017-03-05 16:44:50 +01:00
p . name = String ( E - > key ( ) ) ;
2016-08-06 03:46:45 +02:00
pinfo . push_back ( p ) ;
2017-03-05 16:44:50 +01:00
values [ p . name ] = E - > get ( ) . default_value ;
2016-08-06 03:46:45 +02:00
}
2017-03-05 16:44:50 +01:00
sins - > update ( pinfo , values ) ;
2016-08-06 03:46:45 +02:00
return sins ;
}
# endif
2017-03-05 16:44:50 +01:00
VisualScriptInstance * instance = memnew ( VisualScriptInstance ) ;
instance - > create ( Ref < VisualScript > ( this ) , p_this ) ;
2016-08-06 03:46:45 +02:00
2021-01-27 10:43:02 +01:00
VisualScriptLanguage : : singleton - > lock . lock ( ) ;
2017-03-05 16:44:50 +01:00
instances [ p_this ] = instance ;
2021-01-27 10:43:02 +01:00
VisualScriptLanguage : : singleton - > lock . unlock ( ) ;
2016-08-06 03:46:45 +02:00
return instance ;
2016-08-03 00:11:05 +02:00
}
bool VisualScript : : instance_has ( const Object * p_this ) const {
2017-03-05 16:44:50 +01:00
return instances . has ( ( Object * ) p_this ) ;
2016-08-03 00:11:05 +02:00
}
bool VisualScript : : has_source_code ( ) const {
return false ;
}
String VisualScript : : get_source_code ( ) const {
return String ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScript : : set_source_code ( const String & p_code ) {
2016-08-03 00:11:05 +02:00
}
Error VisualScript : : reload ( bool p_keep_state ) {
return OK ;
}
bool VisualScript : : is_tool ( ) const {
2019-07-26 22:00:23 +02:00
return is_tool_script ;
2016-08-03 00:11:05 +02:00
}
2018-11-27 23:55:37 +01:00
bool VisualScript : : is_valid ( ) const {
return true ; //always valid
}
2016-08-03 00:11:05 +02:00
ScriptLanguage * VisualScript : : get_language ( ) const {
return VisualScriptLanguage : : singleton ;
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_script_signal ( const StringName & p_signal ) const {
2016-08-06 03:46:45 +02:00
return custom_signals . has ( p_signal ) ;
2016-08-03 00:11:05 +02:00
}
void VisualScript : : get_script_signal_list ( List < MethodInfo > * r_signals ) const {
2021-05-04 14:20:36 +02:00
for ( const Map < StringName , Vector < Argument > > : : Element * E = custom_signals . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-06 03:46:45 +02:00
MethodInfo mi ;
2017-03-05 16:44:50 +01:00
mi . name = E - > key ( ) ;
for ( int i = 0 ; i < E - > get ( ) . size ( ) ; i + + ) {
2016-08-06 03:46:45 +02:00
PropertyInfo arg ;
2017-03-05 16:44:50 +01:00
arg . type = E - > get ( ) [ i ] . type ;
arg . name = E - > get ( ) [ i ] . name ;
2016-08-06 03:46:45 +02:00
mi . arguments . push_back ( arg ) ;
}
r_signals - > push_back ( mi ) ;
}
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : get_property_default_value ( const StringName & p_property , Variant & r_value ) const {
2021-05-05 12:44:11 +02:00
if ( ! variables . has ( p_property ) ) {
2016-08-06 03:46:45 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
r_value = variables [ p_property ] . default_value ;
2016-08-06 03:46:45 +02:00
return true ;
2016-08-03 00:11:05 +02:00
}
2016-08-19 21:48:08 +02:00
void VisualScript : : get_script_method_list ( List < MethodInfo > * p_list ) const {
2017-03-05 16:44:50 +01:00
for ( Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
MethodInfo mi ;
2017-03-05 16:44:50 +01:00
mi . name = E - > key ( ) ;
if ( E - > get ( ) . function_id > = 0 ) {
Ref < VisualScriptFunction > func = E - > get ( ) . nodes [ E - > get ( ) . function_id ] . node ;
2016-08-03 00:11:05 +02:00
if ( func . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < func - > get_argument_count ( ) ; i + + ) {
2016-08-03 00:11:05 +02:00
PropertyInfo arg ;
2017-03-05 16:44:50 +01:00
arg . name = func - > get_argument_name ( i ) ;
arg . type = func - > get_argument_type ( i ) ;
2016-08-03 00:11:05 +02:00
mi . arguments . push_back ( arg ) ;
}
2019-09-13 21:14:12 +02:00
p_list - > push_back ( mi ) ;
2016-08-03 00:11:05 +02:00
}
}
}
}
2017-03-05 16:44:50 +01:00
bool VisualScript : : has_method ( const StringName & p_method ) const {
2016-08-08 06:21:22 +02:00
return functions . has ( p_method ) ;
}
2017-03-05 16:44:50 +01:00
MethodInfo VisualScript : : get_method_info ( const StringName & p_method ) const {
const Map < StringName , Function > : : Element * E = functions . find ( p_method ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2016-08-08 06:21:22 +02:00
return MethodInfo ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-08-08 06:21:22 +02:00
MethodInfo mi ;
2017-03-05 16:44:50 +01:00
mi . name = E - > key ( ) ;
if ( E - > get ( ) . function_id > = 0 ) {
Ref < VisualScriptFunction > func = E - > get ( ) . nodes [ E - > get ( ) . function_id ] . node ;
2016-08-08 06:21:22 +02:00
if ( func . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < func - > get_argument_count ( ) ; i + + ) {
2016-08-08 06:21:22 +02:00
PropertyInfo arg ;
2017-03-05 16:44:50 +01:00
arg . name = func - > get_argument_name ( i ) ;
arg . type = func - > get_argument_type ( i ) ;
2016-08-08 06:21:22 +02:00
mi . arguments . push_back ( arg ) ;
}
2017-08-08 18:14:36 +02:00
if ( ! func - > is_sequenced ( ) ) {
mi . flags | = METHOD_FLAG_CONST ;
}
2016-08-08 06:21:22 +02:00
}
}
return mi ;
}
2016-08-24 00:29:07 +02:00
void VisualScript : : get_script_property_list ( List < PropertyInfo > * p_list ) const {
List < StringName > vars ;
get_variable_list ( & vars ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * E = vars . front ( ) ; E ; E = E - > next ( ) ) {
2017-07-01 02:30:17 +02:00
//if (!variables[E->get()]._export)
// continue;
PropertyInfo pi = variables [ E - > get ( ) ] . info ;
pi . usage | = PROPERTY_USAGE_SCRIPT_VARIABLE ;
p_list - > push_back ( pi ) ;
2016-08-24 00:29:07 +02:00
}
}
2017-04-15 19:48:10 +02:00
int VisualScript : : get_member_line ( const StringName & p_member ) const {
# ifdef TOOLS_ENABLED
if ( has_function ( p_member ) ) {
for ( Map < int , Function : : NodeData > : : Element * E = functions [ p_member ] . nodes . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( Object : : cast_to < VisualScriptFunction > ( E - > get ( ) . node . ptr ( ) ) ) {
2017-04-15 19:48:10 +02:00
return E - > key ( ) ;
2021-05-05 12:44:11 +02:00
}
2017-04-15 19:48:10 +02:00
}
}
# endif
return - 1 ;
}
2016-09-05 23:50:30 +02:00
# ifdef TOOLS_ENABLED
2016-08-31 22:58:51 +02:00
bool VisualScript : : are_subnodes_edited ( ) const {
2017-03-05 16:44:50 +01:00
for ( const Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
for ( const Map < int , Function : : NodeData > : : Element * F = E - > get ( ) . nodes . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-31 22:58:51 +02:00
if ( F - > get ( ) . node - > is_edited ( ) ) {
return true ;
}
}
}
return false ;
}
2016-09-05 23:50:30 +02:00
# endif
2016-08-08 06:21:22 +02:00
2017-03-05 16:44:50 +01:00
void VisualScript : : _set_data ( const Dictionary & p_data ) {
2016-08-03 00:11:05 +02:00
Dictionary d = p_data ;
2021-05-05 12:44:11 +02:00
if ( d . has ( " base_type " ) ) {
2017-03-05 16:44:50 +01:00
base_type = d [ " base_type " ] ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
variables . clear ( ) ;
2017-03-05 16:44:50 +01:00
Array vars = d [ " variables " ] ;
for ( int i = 0 ; i < vars . size ( ) ; i + + ) {
Dictionary v = vars [ i ] ;
2016-08-06 03:46:45 +02:00
StringName name = v [ " name " ] ;
add_variable ( name ) ;
2017-03-05 16:44:50 +01:00
_set_variable_info ( name , v ) ;
set_variable_default_value ( name , v [ " default_value " ] ) ;
set_variable_export ( name , v . has ( " export " ) & & bool ( v [ " export " ] ) ) ;
2016-08-03 00:11:05 +02:00
}
custom_signals . clear ( ) ;
2017-03-05 16:44:50 +01:00
Array sigs = d [ " signals " ] ;
for ( int i = 0 ; i < sigs . size ( ) ; i + + ) {
Dictionary cs = sigs [ i ] ;
2016-08-03 00:11:05 +02:00
add_custom_signal ( cs [ " name " ] ) ;
2017-03-05 16:44:50 +01:00
Array args = cs [ " arguments " ] ;
for ( int j = 0 ; j < args . size ( ) ; j + = 2 ) {
custom_signal_add_argument ( cs [ " name " ] , Variant : : Type ( int ( args [ j + 1 ] ) ) , args [ j ] ) ;
2016-08-03 00:11:05 +02:00
}
}
2017-03-05 16:44:50 +01:00
Array funcs = d [ " functions " ] ;
2016-08-03 00:11:05 +02:00
functions . clear ( ) ;
2019-09-13 21:14:12 +02:00
Vector2 last_pos = Vector2 ( - 100 * funcs . size ( ) , - 100 * funcs . size ( ) ) ; // this is the center of the last fn box
Vector2 last_size = Vector2 ( 0.0 , 0.0 ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < funcs . size ( ) ; i + + ) {
Dictionary func = funcs [ i ] ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
StringName name = func [ " name " ] ;
2016-08-03 00:11:05 +02:00
//int id=func["function_id"];
add_function ( name ) ;
2017-03-05 16:44:50 +01:00
set_function_scroll ( name , func [ " scroll " ] ) ;
2016-08-07 00:00:54 +02:00
2016-08-03 00:11:05 +02:00
Array nodes = func [ " nodes " ] ;
2019-09-13 21:14:12 +02:00
if ( ! d . has ( " vs_unify " ) & & nodes . size ( ) > 0 ) {
Vector2 top_left = nodes [ 1 ] ;
Vector2 bottom_right = nodes [ 1 ] ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
for ( int j = 0 ; j < nodes . size ( ) ; j + = 3 ) {
Point2 pos = nodes [ j + 1 ] ;
if ( pos . y > top_left . y ) {
top_left . y = pos . y ;
}
if ( pos . y < bottom_right . y ) {
bottom_right . y = pos . y ;
}
if ( pos . x > bottom_right . x ) {
bottom_right . x = pos . x ;
}
if ( pos . x < top_left . x ) {
top_left . x = pos . x ;
}
}
Vector2 size = Vector2 ( bottom_right . x - top_left . x , top_left . y - bottom_right . y ) ;
Vector2 offset = last_pos + ( last_size / 2.0 ) + ( size / 2.0 ) ; // dunno I might just keep it in one axis but diagonal feels better....
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
last_pos = offset ;
last_size = size ;
for ( int j = 0 ; j < nodes . size ( ) ; j + = 3 ) {
add_node ( name , nodes [ j ] , nodes [ j + 2 ] , offset + nodes [ j + 1 ] ) ; // also add an additional buffer if you want to
}
} else {
for ( int j = 0 ; j < nodes . size ( ) ; j + = 3 ) {
add_node ( name , nodes [ j ] , nodes [ j + 2 ] , nodes [ j + 1 ] ) ;
}
}
2017-03-05 16:44:50 +01:00
Array sequence_connections = func [ " sequence_connections " ] ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < sequence_connections . size ( ) ; j + = 3 ) {
sequence_connect ( name , sequence_connections [ j + 0 ] , sequence_connections [ j + 1 ] , sequence_connections [ j + 2 ] ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Array data_connections = func [ " data_connections " ] ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < data_connections . size ( ) ; j + = 4 ) {
data_connect ( name , data_connections [ j + 0 ] , data_connections [ j + 1 ] , data_connections [ j + 2 ] , data_connections [ j + 3 ] ) ;
2016-08-03 00:11:05 +02:00
}
}
2019-07-26 22:00:23 +02:00
2021-05-05 12:44:11 +02:00
if ( d . has ( " is_tool_script " ) ) {
2019-07-26 22:00:23 +02:00
is_tool_script = d [ " is_tool_script " ] ;
2021-05-05 12:44:11 +02:00
} else {
2019-07-26 22:00:23 +02:00
is_tool_script = false ;
2021-05-05 12:44:11 +02:00
}
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Dictionary VisualScript : : _get_data ( ) const {
2016-08-03 00:11:05 +02:00
Dictionary d ;
2017-03-05 16:44:50 +01:00
d [ " base_type " ] = base_type ;
2016-08-03 00:11:05 +02:00
Array vars ;
2017-03-05 16:44:50 +01:00
for ( const Map < StringName , Variable > : : Element * E = variables . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
Dictionary var = _get_variable_info ( E - > key ( ) ) ;
2017-03-05 16:44:50 +01:00
var [ " name " ] = E - > key ( ) ; //make sure it's the right one
var [ " default_value " ] = E - > get ( ) . default_value ;
var [ " export " ] = E - > get ( ) . _export ;
2016-08-03 00:11:05 +02:00
vars . push_back ( var ) ;
}
2017-03-05 16:44:50 +01:00
d [ " variables " ] = vars ;
2016-08-03 00:11:05 +02:00
Array sigs ;
2021-05-04 14:20:36 +02:00
for ( const Map < StringName , Vector < Argument > > : : Element * E = custom_signals . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
Dictionary cs ;
2017-03-05 16:44:50 +01:00
cs [ " name " ] = E - > key ( ) ;
2016-08-03 00:11:05 +02:00
Array args ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < E - > get ( ) . size ( ) ; i + + ) {
2016-08-03 00:11:05 +02:00
args . push_back ( E - > get ( ) [ i ] . name ) ;
args . push_back ( E - > get ( ) [ i ] . type ) ;
}
2017-03-05 16:44:50 +01:00
cs [ " arguments " ] = args ;
2016-08-03 00:11:05 +02:00
sigs . push_back ( cs ) ;
}
2017-03-05 16:44:50 +01:00
d [ " signals " ] = sigs ;
2016-08-03 00:11:05 +02:00
Array funcs ;
2017-03-05 16:44:50 +01:00
for ( const Map < StringName , Function > : : Element * E = functions . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
Dictionary func ;
2017-03-05 16:44:50 +01:00
func [ " name " ] = E - > key ( ) ;
func [ " function_id " ] = E - > get ( ) . function_id ;
func [ " scroll " ] = E - > get ( ) . scroll ;
2016-08-03 00:11:05 +02:00
Array nodes ;
2017-03-05 16:44:50 +01:00
for ( const Map < int , Function : : NodeData > : : Element * F = E - > get ( ) . nodes . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-03 00:11:05 +02:00
nodes . push_back ( F - > key ( ) ) ;
nodes . push_back ( F - > get ( ) . pos ) ;
nodes . push_back ( F - > get ( ) . node ) ;
}
2017-03-05 16:44:50 +01:00
func [ " nodes " ] = nodes ;
2016-08-03 00:11:05 +02:00
Array sequence_connections ;
2017-03-05 16:44:50 +01:00
for ( const Set < SequenceConnection > : : Element * F = E - > get ( ) . sequence_connections . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-03 00:11:05 +02:00
sequence_connections . push_back ( F - > get ( ) . from_node ) ;
sequence_connections . push_back ( F - > get ( ) . from_output ) ;
sequence_connections . push_back ( F - > get ( ) . to_node ) ;
}
2017-03-05 16:44:50 +01:00
func [ " sequence_connections " ] = sequence_connections ;
2016-08-03 00:11:05 +02:00
Array data_connections ;
2017-03-05 16:44:50 +01:00
for ( const Set < DataConnection > : : Element * F = E - > get ( ) . data_connections . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-03 00:11:05 +02:00
data_connections . push_back ( F - > get ( ) . from_node ) ;
data_connections . push_back ( F - > get ( ) . from_port ) ;
data_connections . push_back ( F - > get ( ) . to_node ) ;
data_connections . push_back ( F - > get ( ) . to_port ) ;
}
2017-03-05 16:44:50 +01:00
func [ " data_connections " ] = data_connections ;
2016-08-03 00:11:05 +02:00
funcs . push_back ( func ) ;
}
2017-03-05 16:44:50 +01:00
d [ " functions " ] = funcs ;
2019-07-26 22:00:23 +02:00
d [ " is_tool_script " ] = is_tool_script ;
2019-09-13 21:14:12 +02:00
d [ " vs_unify " ] = true ;
2019-07-26 22:00:23 +02:00
2016-08-03 00:11:05 +02:00
return d ;
}
void VisualScript : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _node_ports_changed " ) , & VisualScript : : _node_ports_changed ) ;
ClassDB : : bind_method ( D_METHOD ( " add_function " , " name " ) , & VisualScript : : add_function ) ;
ClassDB : : bind_method ( D_METHOD ( " has_function " , " name " ) , & VisualScript : : has_function ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_function " , " name " ) , & VisualScript : : remove_function ) ;
ClassDB : : bind_method ( D_METHOD ( " rename_function " , " name " , " new_name " ) , & VisualScript : : rename_function ) ;
2017-07-22 12:11:42 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_function_scroll " , " name " , " ofs " ) , & VisualScript : : set_function_scroll ) ;
ClassDB : : bind_method ( D_METHOD ( " get_function_scroll " , " name " ) , & VisualScript : : get_function_scroll ) ;
2017-03-05 16:44:50 +01:00
2017-09-10 15:37:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_node " , " func " , " id " , " node " , " position " ) , & VisualScript : : add_node , DEFVAL ( Point2 ( ) ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " remove_node " , " func " , " id " ) , & VisualScript : : remove_node ) ;
ClassDB : : bind_method ( D_METHOD ( " get_function_node_id " , " name " ) , & VisualScript : : get_function_node_id ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_node " , " func " , " id " ) , & VisualScript : : get_node ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " has_node " , " func " , " id " ) , & VisualScript : : has_node ) ;
2017-09-10 15:37:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_node_position " , " func " , " id " , " position " ) , & VisualScript : : set_node_position ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_position " , " func " , " id " ) , & VisualScript : : get_node_position ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " sequence_connect " , " func " , " from_node " , " from_output " , " to_node " ) , & VisualScript : : sequence_connect ) ;
ClassDB : : bind_method ( D_METHOD ( " sequence_disconnect " , " func " , " from_node " , " from_output " , " to_node " ) , & VisualScript : : sequence_disconnect ) ;
ClassDB : : bind_method ( D_METHOD ( " has_sequence_connection " , " func " , " from_node " , " from_output " , " to_node " ) , & VisualScript : : has_sequence_connection ) ;
ClassDB : : bind_method ( D_METHOD ( " data_connect " , " func " , " from_node " , " from_port " , " to_node " , " to_port " ) , & VisualScript : : data_connect ) ;
ClassDB : : bind_method ( D_METHOD ( " data_disconnect " , " func " , " from_node " , " from_port " , " to_node " , " to_port " ) , & VisualScript : : data_disconnect ) ;
ClassDB : : bind_method ( D_METHOD ( " has_data_connection " , " func " , " from_node " , " from_port " , " to_node " , " to_port " ) , & VisualScript : : has_data_connection ) ;
ClassDB : : bind_method ( D_METHOD ( " add_variable " , " name " , " default_value " , " export " ) , & VisualScript : : add_variable , DEFVAL ( Variant ( ) ) , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " has_variable " , " name " ) , & VisualScript : : has_variable ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_variable " , " name " ) , & VisualScript : : remove_variable ) ;
ClassDB : : bind_method ( D_METHOD ( " set_variable_default_value " , " name " , " value " ) , & VisualScript : : set_variable_default_value ) ;
ClassDB : : bind_method ( D_METHOD ( " get_variable_default_value " , " name " ) , & VisualScript : : get_variable_default_value ) ;
ClassDB : : bind_method ( D_METHOD ( " set_variable_info " , " name " , " value " ) , & VisualScript : : _set_variable_info ) ;
ClassDB : : bind_method ( D_METHOD ( " get_variable_info " , " name " ) , & VisualScript : : _get_variable_info ) ;
ClassDB : : bind_method ( D_METHOD ( " set_variable_export " , " name " , " enable " ) , & VisualScript : : set_variable_export ) ;
ClassDB : : bind_method ( D_METHOD ( " get_variable_export " , " name " ) , & VisualScript : : get_variable_export ) ;
ClassDB : : bind_method ( D_METHOD ( " rename_variable " , " name " , " new_name " ) , & VisualScript : : rename_variable ) ;
ClassDB : : bind_method ( D_METHOD ( " add_custom_signal " , " name " ) , & VisualScript : : add_custom_signal ) ;
ClassDB : : bind_method ( D_METHOD ( " has_custom_signal " , " name " ) , & VisualScript : : has_custom_signal ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_signal_add_argument " , " name " , " type " , " argname " , " index " ) , & VisualScript : : custom_signal_add_argument , DEFVAL ( - 1 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_signal_set_argument_type " , " name " , " argidx " , " type " ) , & VisualScript : : custom_signal_set_argument_type ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_signal_get_argument_type " , " name " , " argidx " ) , & VisualScript : : custom_signal_get_argument_type ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_signal_set_argument_name " , " name " , " argidx " , " argname " ) , & VisualScript : : custom_signal_set_argument_name ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_signal_get_argument_name " , " name " , " argidx " ) , & VisualScript : : custom_signal_get_argument_name ) ;
2017-07-22 12:11:42 +02:00
ClassDB : : bind_method ( D_METHOD ( " custom_signal_remove_argument " , " name " , " argidx " ) , & VisualScript : : custom_signal_remove_argument ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " custom_signal_get_argument_count " , " name " ) , & VisualScript : : custom_signal_get_argument_count ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_signal_swap_argument " , " name " , " argidx " , " withidx " ) , & VisualScript : : custom_signal_swap_argument ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_custom_signal " , " name " ) , & VisualScript : : remove_custom_signal ) ;
ClassDB : : bind_method ( D_METHOD ( " rename_custom_signal " , " name " , " new_name " ) , & VisualScript : : rename_custom_signal ) ;
2017-02-13 12:47:24 +01:00
//ClassDB::bind_method(D_METHOD("set_variable_info","name","info"),&VScript::set_variable_info);
//ClassDB::bind_method(D_METHOD("get_variable_info","name"),&VScript::set_variable_info);
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_instance_base_type " , " type " ) , & VisualScript : : set_instance_base_type ) ;
2017-02-13 12:47:24 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _set_data " , " data " ) , & VisualScript : : _set_data ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_data " ) , & VisualScript : : _get_data ) ;
2016-08-03 00:11:05 +02:00
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : DICTIONARY , " data " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL ) , " _set_data " , " _get_data " ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " node_ports_changed " , PropertyInfo ( Variant : : STRING , " function " ) , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
2016-08-03 00:11:05 +02:00
}
VisualScript : : VisualScript ( ) {
2017-03-05 16:44:50 +01:00
base_type = " Object " ;
2019-11-01 16:16:31 +01:00
is_tool_script = false ;
2016-08-03 00:11:05 +02:00
}
2021-08-02 04:48:17 +02:00
bool VisualScript : : inherits_script ( const Ref < Script > & p_script ) const {
return this = = p_script . ptr ( ) ; //there is no inheritance in visual scripts, so this is enough
}
2019-09-13 21:14:12 +02:00
StringName VisualScript : : get_default_func ( ) const {
return StringName ( " f_312843592 " ) ;
}
2018-05-13 05:34:35 +02:00
Set < int > VisualScript : : get_output_sequence_ports_connected ( const String & edited_func , int from_node ) {
List < VisualScript : : SequenceConnection > * sc = memnew ( List < VisualScript : : SequenceConnection > ) ;
get_sequence_connection_list ( edited_func , sc ) ;
Set < int > connected ;
for ( List < VisualScript : : SequenceConnection > : : Element * E = sc - > front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . from_node = = from_node ) {
connected . insert ( E - > get ( ) . from_output ) ;
}
}
memdelete ( sc ) ;
return connected ;
}
2016-08-03 00:11:05 +02:00
VisualScript : : ~ VisualScript ( ) {
2017-03-05 16:44:50 +01:00
while ( ! functions . empty ( ) ) {
2016-08-03 00:11:05 +02:00
remove_function ( functions . front ( ) - > key ( ) ) ;
}
}
////////////////////////////////////////////
2017-03-05 16:44:50 +01:00
bool VisualScriptInstance : : set ( const StringName & p_name , const Variant & p_value ) {
Map < StringName , Variant > : : Element * E = variables . find ( p_name ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2016-09-04 15:38:41 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
E - > get ( ) = p_value ;
2016-08-06 03:46:45 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
bool VisualScriptInstance : : get ( const StringName & p_name , Variant & r_ret ) const {
const Map < StringName , Variant > : : Element * E = variables . find ( p_name ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2016-08-06 03:46:45 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
r_ret = E - > get ( ) ;
2016-09-07 00:12:28 +02:00
return true ;
2016-08-06 03:46:45 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptInstance : : get_property_list ( List < PropertyInfo > * p_properties ) const {
for ( const Map < StringName , VisualScript : : Variable > : : Element * E = script - > variables . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( ! E - > get ( ) . _export ) {
2016-08-31 04:44:14 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
PropertyInfo p = E - > get ( ) . info ;
2017-03-05 16:44:50 +01:00
p . name = String ( E - > key ( ) ) ;
2017-07-01 02:30:17 +02:00
p . usage | = PROPERTY_USAGE_SCRIPT_VARIABLE ;
2016-08-06 03:46:45 +02:00
p_properties - > push_back ( p ) ;
}
}
2017-03-05 16:44:50 +01:00
Variant : : Type VisualScriptInstance : : get_property_type ( const StringName & p_name , bool * r_is_valid ) const {
const Map < StringName , VisualScript : : Variable > : : Element * E = script - > variables . find ( p_name ) ;
2016-08-06 03:46:45 +02:00
if ( ! E ) {
2021-05-05 12:44:11 +02:00
if ( r_is_valid ) {
2017-03-05 16:44:50 +01:00
* r_is_valid = false ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
ERR_FAIL_V ( Variant : : NIL ) ;
}
2021-05-05 12:44:11 +02:00
if ( r_is_valid ) {
2017-03-05 16:44:50 +01:00
* r_is_valid = true ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
return E - > get ( ) . info . type ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptInstance : : get_method_list ( List < MethodInfo > * p_list ) const {
for ( const Map < StringName , VisualScript : : Function > : : Element * E = script - > functions . front ( ) ; E ; E = E - > next ( ) ) {
2019-09-13 21:14:12 +02:00
if ( E - > key ( ) = = script - > get_default_func ( ) ) {
continue ;
}
2016-08-06 03:46:45 +02:00
MethodInfo mi ;
2017-03-05 16:44:50 +01:00
mi . name = E - > key ( ) ;
if ( E - > get ( ) . function_id > = 0 & & E - > get ( ) . nodes . has ( E - > get ( ) . function_id ) ) {
2016-08-06 03:46:45 +02:00
Ref < VisualScriptFunction > vsf = E - > get ( ) . nodes [ E - > get ( ) . function_id ] . node ;
if ( vsf . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < vsf - > get_argument_count ( ) ; i + + ) {
2016-08-06 03:46:45 +02:00
PropertyInfo arg ;
2017-03-05 16:44:50 +01:00
arg . name = vsf - > get_argument_name ( i ) ;
arg . type = vsf - > get_argument_type ( i ) ;
2016-08-06 03:46:45 +02:00
mi . arguments . push_back ( arg ) ;
}
2017-08-08 18:14:36 +02:00
if ( ! vsf - > is_sequenced ( ) ) { //assumed constant if not sequenced
mi . flags | = METHOD_FLAG_CONST ;
}
2016-08-06 03:46:45 +02:00
}
}
p_list - > push_back ( mi ) ;
}
}
2017-03-05 16:44:50 +01:00
bool VisualScriptInstance : : has_method ( const StringName & p_method ) const {
2021-05-05 12:44:11 +02:00
if ( p_method = = script - > get_default_func ( ) ) {
2019-09-13 21:14:12 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2019-09-13 21:14:12 +02:00
2016-08-06 03:46:45 +02:00
return script - > functions . has ( p_method ) ;
}
2016-08-07 01:13:27 +02:00
//#define VSDEBUG(m_text) print_line(m_text)
# define VSDEBUG(m_text)
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
void VisualScriptInstance : : _dependency_step ( VisualScriptNodeInstance * node , int p_pass , int * pass_stack , const Variant * * input_args , Variant * * output_args , Variant * variant_stack , Variant : : CallError & r_error , String & error_str , VisualScriptNodeInstance * * r_error_node ) {
ERR_FAIL_COND ( node - > pass_idx = = - 1 ) ;
2016-08-31 04:44:14 +02:00
2021-05-05 12:44:11 +02:00
if ( pass_stack [ node - > pass_idx ] = = p_pass ) {
2016-08-31 04:44:14 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-31 04:44:14 +02:00
2017-03-05 16:44:50 +01:00
pass_stack [ node - > pass_idx ] = p_pass ;
2016-08-31 04:44:14 +02:00
if ( ! node - > dependencies . empty ( ) ) {
int dc = node - > dependencies . size ( ) ;
2017-11-25 04:07:54 +01:00
VisualScriptNodeInstance * * deps = node - > dependencies . ptrw ( ) ;
2016-08-31 04:44:14 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < dc ; i + + ) {
_dependency_step ( deps [ i ] , p_pass , pass_stack , input_args , output_args , variant_stack , r_error , error_str , r_error_node ) ;
2021-05-05 12:44:11 +02:00
if ( r_error . error ! = Variant : : CallError : : CALL_OK ) {
2016-08-31 04:44:14 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-31 04:44:14 +02:00
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > input_port_count ; i + + ) {
2016-08-31 04:44:14 +02:00
int index = node - > input_ports [ i ] & VisualScriptNodeInstance : : INPUT_MASK ;
if ( node - > input_ports [ i ] & VisualScriptNodeInstance : : INPUT_DEFAULT_VALUE_BIT ) {
//is a default value (unassigned input port)
2017-03-05 16:44:50 +01:00
input_args [ i ] = & default_values [ index ] ;
2016-08-31 04:44:14 +02:00
} else {
//regular temporary in stack
2017-03-05 16:44:50 +01:00
input_args [ i ] = & variant_stack [ index ] ;
2016-08-31 04:44:14 +02:00
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > output_port_count ; i + + ) {
output_args [ i ] = & variant_stack [ node - > output_ports [ i ] ] ;
2016-08-31 04:44:14 +02:00
}
2021-05-04 16:00:45 +02:00
Variant * working_mem = node - > working_mem_idx > = 0 ? & variant_stack [ node - > working_mem_idx ] : ( Variant * ) nullptr ;
2016-08-31 04:44:14 +02:00
2017-03-05 16:44:50 +01:00
node - > step ( input_args , output_args , VisualScriptNodeInstance : : START_MODE_BEGIN_SEQUENCE , working_mem , r_error , error_str ) ;
2016-08-31 04:44:14 +02:00
//ignore return
2017-03-05 16:44:50 +01:00
if ( r_error . error ! = Variant : : CallError : : CALL_OK ) {
* r_error_node = node ;
2016-08-31 04:44:14 +02:00
}
}
2017-03-05 16:44:50 +01:00
Variant VisualScriptInstance : : _call_internal ( const StringName & p_method , void * p_stack , int p_stack_size , VisualScriptNodeInstance * p_node , int p_flow_stack_pos , int p_pass , bool p_resuming_yield , Variant : : CallError & r_error ) {
Map < StringName , Function > : : Element * F = functions . find ( p_method ) ;
ERR_FAIL_COND_V ( ! F , Variant ( ) ) ;
Function * f = & F - > get ( ) ;
2016-08-06 03:46:45 +02:00
2016-08-08 00:22:33 +02:00
//this call goes separate, so it can e yielded and suspended
2017-03-05 16:44:50 +01:00
Variant * variant_stack = ( Variant * ) p_stack ;
bool * sequence_bits = ( bool * ) ( variant_stack + f - > max_stack ) ;
const Variant * * input_args = ( const Variant * * ) ( sequence_bits + f - > node_count ) ;
Variant * * output_args = ( Variant * * ) ( input_args + max_input_args ) ;
2016-08-06 03:46:45 +02:00
int flow_max = f - > flow_stack_size ;
2021-05-04 16:00:45 +02:00
int * flow_stack = flow_max ? ( int * ) ( output_args + max_output_args ) : ( int * ) nullptr ;
int * pass_stack = flow_stack ? ( int * ) ( flow_stack + flow_max ) : ( int * ) nullptr ;
2016-08-06 03:46:45 +02:00
String error_str ;
2017-03-05 16:44:50 +01:00
VisualScriptNodeInstance * node = p_node ;
bool error = false ;
int current_node_id = f - > node ;
2016-08-06 03:46:45 +02:00
Variant return_value ;
2021-05-04 16:00:45 +02:00
Variant * working_mem = nullptr ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
int flow_stack_pos = p_flow_stack_pos ;
2016-08-08 00:22:33 +02:00
2016-08-07 00:00:54 +02:00
# ifdef DEBUG_ENABLED
if ( ScriptDebugger : : get_singleton ( ) ) {
2017-03-05 16:44:50 +01:00
VisualScriptLanguage : : singleton - > enter_function ( this , & p_method , variant_stack , & working_mem , & current_node_id ) ;
2016-08-07 00:00:54 +02:00
}
# endif
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
while ( true ) {
2016-08-31 04:44:14 +02:00
p_pass + + ; //increment pass
2017-03-05 16:44:50 +01:00
current_node_id = node - > get_id ( ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
VSDEBUG ( " ==========AT NODE: " + itos ( current_node_id ) + " base: " + node - > get_base_node ( ) - > get_class_name ( ) ) ;
VSDEBUG ( " AT STACK POS: " + itos ( flow_stack_pos ) ) ;
2016-08-06 03:46:45 +02:00
//setup working mem
2021-05-04 16:00:45 +02:00
working_mem = node - > working_mem_idx > = 0 ? & variant_stack [ node - > working_mem_idx ] : ( Variant * ) nullptr ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
VSDEBUG ( " WORKING MEM: " + itos ( node - > working_mem_idx ) ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( current_node_id = = f - > node ) {
2017-03-24 21:45:31 +01:00
//if function node, set up function arguments from beginning of stack
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < f - > argument_count ; i + + ) {
input_args [ i ] = & variant_stack [ i ] ;
2016-08-06 03:46:45 +02:00
}
} else {
2016-08-31 04:44:14 +02:00
//run dependencies first
2016-08-06 03:46:45 +02:00
2016-08-31 04:44:14 +02:00
if ( ! node - > dependencies . empty ( ) ) {
int dc = node - > dependencies . size ( ) ;
2017-11-25 04:07:54 +01:00
VisualScriptNodeInstance * * deps = node - > dependencies . ptrw ( ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < dc ; i + + ) {
_dependency_step ( deps [ i ] , p_pass , pass_stack , input_args , output_args , variant_stack , r_error , error_str , & node ) ;
if ( r_error . error ! = Variant : : CallError : : CALL_OK ) {
error = true ;
current_node_id = node - > id ;
2016-08-06 03:46:45 +02:00
break ;
}
2016-08-31 04:44:14 +02:00
}
}
2016-08-06 03:46:45 +02:00
2016-08-31 04:44:14 +02:00
if ( ! error ) {
//setup input pointers normally
2017-03-05 16:44:50 +01:00
VSDEBUG ( " INPUT PORTS: " + itos ( node - > input_port_count ) ) ;
2016-08-31 04:44:14 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > input_port_count ; i + + ) {
2016-08-31 04:44:14 +02:00
int index = node - > input_ports [ i ] & VisualScriptNodeInstance : : INPUT_MASK ;
if ( node - > input_ports [ i ] & VisualScriptNodeInstance : : INPUT_DEFAULT_VALUE_BIT ) {
//is a default value (unassigned input port)
2017-03-05 16:44:50 +01:00
input_args [ i ] = & default_values [ index ] ;
VSDEBUG ( " \t PORT " + itos ( i ) + " DEFAULT VAL " ) ;
2016-08-31 04:44:14 +02:00
} else {
//regular temporary in stack
2017-03-05 16:44:50 +01:00
input_args [ i ] = & variant_stack [ index ] ;
VSDEBUG ( " PORT " + itos ( i ) + " AT STACK " + itos ( index ) ) ;
2016-08-31 04:44:14 +02:00
}
2016-08-06 03:46:45 +02:00
}
}
}
2021-05-05 12:44:11 +02:00
if ( error ) {
2016-08-06 03:46:45 +02:00
break ;
2021-05-05 12:44:11 +02:00
}
2016-08-06 03:46:45 +02:00
//setup output pointers
2017-03-05 16:44:50 +01:00
VSDEBUG ( " OUTPUT PORTS: " + itos ( node - > output_port_count ) ) ;
for ( int i = 0 ; i < node - > output_port_count ; i + + ) {
output_args [ i ] = & variant_stack [ node - > output_ports [ i ] ] ;
VSDEBUG ( " PORT " + itos ( i ) + " AT STACK " + itos ( node - > output_ports [ i ] ) ) ;
2016-08-06 03:46:45 +02:00
}
//do step
2016-08-08 00:22:33 +02:00
VisualScriptNodeInstance : : StartMode start_mode ;
{
2017-08-19 16:54:32 +02:00
if ( p_resuming_yield ) {
2017-03-05 16:44:50 +01:00
start_mode = VisualScriptNodeInstance : : START_MODE_RESUME_YIELD ;
2017-08-19 16:54:32 +02:00
p_resuming_yield = false ; // should resume only the first time
} else if ( flow_stack & & ( flow_stack [ flow_stack_pos ] & VisualScriptNodeInstance : : FLOW_STACK_PUSHED_BIT ) ) {
//if there is a push bit, it means we are continuing a sequence
2017-03-05 16:44:50 +01:00
start_mode = VisualScriptNodeInstance : : START_MODE_CONTINUE_SEQUENCE ;
2017-08-19 16:54:32 +02:00
} else {
start_mode = VisualScriptNodeInstance : : START_MODE_BEGIN_SEQUENCE ;
}
2016-08-08 00:22:33 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
VSDEBUG ( " STEP - STARTSEQ: " + itos ( start_mode ) ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
int ret = node - > step ( input_args , output_args , start_mode , working_mem , r_error , error_str ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( r_error . error ! = Variant : : CallError : : CALL_OK ) {
2016-08-06 03:46:45 +02:00
//use error from step
2017-03-05 16:44:50 +01:00
error = true ;
2016-08-06 03:46:45 +02:00
break ;
}
2017-03-05 16:44:50 +01:00
if ( ret & VisualScriptNodeInstance : : STEP_YIELD_BIT ) {
2016-08-08 00:22:33 +02:00
//yielded!
2017-03-05 16:44:50 +01:00
if ( node - > get_working_memory_size ( ) = = 0 ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
error_str = RTR ( " A node yielded without working memory, please read the docs on how to yield properly! " ) ;
error = true ;
2016-08-08 00:22:33 +02:00
break ;
} else {
Ref < VisualScriptFunctionState > state = * working_mem ;
if ( ! state . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
error_str = RTR ( " Node yielded, but did not return a function state in the first working memory. " ) ;
error = true ;
2016-08-08 00:22:33 +02:00
break ;
}
//step 1, capture all state
2017-08-07 12:17:31 +02:00
state - > instance_id = get_owner_ptr ( ) - > get_instance_id ( ) ;
state - > script_id = get_script ( ) - > get_instance_id ( ) ;
2017-03-05 16:44:50 +01:00
state - > instance = this ;
state - > function = p_method ;
state - > working_mem_index = node - > working_mem_idx ;
state - > variant_stack_size = f - > max_stack ;
state - > node = node ;
state - > flow_stack_pos = flow_stack_pos ;
2016-08-08 00:22:33 +02:00
state - > stack . resize ( p_stack_size ) ;
2017-03-05 16:44:50 +01:00
state - > pass = p_pass ;
2021-04-29 12:34:11 +02:00
memcpy ( state - > stack . ptrw ( ) , p_stack , p_stack_size ) ;
2016-08-08 00:22:33 +02:00
//step 2, run away, return directly
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_OK ;
2016-08-08 00:22:33 +02:00
# ifdef DEBUG_ENABLED
//will re-enter later, so exiting
if ( ScriptDebugger : : get_singleton ( ) ) {
VisualScriptLanguage : : singleton - > exit_function ( ) ;
}
# endif
return state ;
}
}
2016-08-07 00:00:54 +02:00
# ifdef DEBUG_ENABLED
if ( ScriptDebugger : : get_singleton ( ) ) {
// line
2017-03-05 16:44:50 +01:00
bool do_break = false ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
if ( ScriptDebugger : : get_singleton ( ) - > get_lines_left ( ) > 0 ) {
2021-05-05 12:44:11 +02:00
if ( ScriptDebugger : : get_singleton ( ) - > get_depth ( ) < = 0 ) {
2017-03-05 16:44:50 +01:00
ScriptDebugger : : get_singleton ( ) - > set_lines_left ( ScriptDebugger : : get_singleton ( ) - > get_lines_left ( ) - 1 ) ;
2021-05-05 12:44:11 +02:00
}
if ( ScriptDebugger : : get_singleton ( ) - > get_lines_left ( ) < = 0 ) {
2017-03-05 16:44:50 +01:00
do_break = true ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
}
2021-05-05 12:44:11 +02:00
if ( ScriptDebugger : : get_singleton ( ) - > is_breakpoint ( current_node_id , source ) ) {
2017-03-05 16:44:50 +01:00
do_break = true ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
if ( do_break ) {
2017-03-05 16:44:50 +01:00
VisualScriptLanguage : : singleton - > debug_break ( " Breakpoint " , true ) ;
2016-08-07 00:00:54 +02:00
}
ScriptDebugger : : get_singleton ( ) - > line_poll ( ) ;
}
# endif
2016-08-06 03:46:45 +02:00
int output = ret & VisualScriptNodeInstance : : STEP_MASK ;
2017-03-05 16:44:50 +01:00
VSDEBUG ( " STEP RETURN: " + itos ( ret ) ) ;
2016-08-06 03:46:45 +02:00
if ( ret & VisualScriptNodeInstance : : STEP_EXIT_FUNCTION_BIT ) {
2017-03-05 16:44:50 +01:00
if ( node - > get_working_memory_size ( ) = = 0 ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
error_str = RTR ( " Return value must be assigned to first element of node working memory! Fix your node please. " ) ;
error = true ;
2016-08-06 03:46:45 +02:00
} else {
//assign from working memory, first element
2017-03-05 16:44:50 +01:00
return_value = * working_mem ;
2016-08-06 03:46:45 +02:00
}
2017-03-05 16:44:50 +01:00
VSDEBUG ( " EXITING FUNCTION - VALUE " + String ( return_value ) ) ;
2016-08-06 03:46:45 +02:00
break ; //exit function requested, bye
}
2021-05-04 16:00:45 +02:00
VisualScriptNodeInstance * next = nullptr ; //next node
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( ( ret = = output | | ret & VisualScriptNodeInstance : : STEP_FLAG_PUSH_STACK_BIT ) & & node - > sequence_output_count ) {
2016-08-06 03:46:45 +02:00
//if no exit bit was set, and has sequence outputs, guess next node
2019-06-20 16:59:48 +02:00
if ( output > = node - > sequence_output_count ) {
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
error_str = RTR ( " Node returned an invalid sequence output: " ) + itos ( output ) ;
error = true ;
2016-08-06 03:46:45 +02:00
break ;
}
next = node - > sequence_outputs [ output ] ;
2016-08-08 00:22:33 +02:00
if ( next ) {
2017-03-05 16:44:50 +01:00
VSDEBUG ( " GOT NEXT NODE - " + itos ( next - > get_id ( ) ) ) ;
2016-08-08 00:22:33 +02:00
} else {
2016-08-06 03:46:45 +02:00
VSDEBUG ( " GOT NEXT NODE - NULL " ) ;
2016-08-08 00:22:33 +02:00
}
2016-08-06 03:46:45 +02:00
}
if ( flow_stack ) {
//update flow stack pos (may have changed)
flow_stack [ flow_stack_pos ] = current_node_id ;
//add stack push bit if requested
if ( ret & VisualScriptNodeInstance : : STEP_FLAG_PUSH_STACK_BIT ) {
flow_stack [ flow_stack_pos ] | = VisualScriptNodeInstance : : FLOW_STACK_PUSHED_BIT ;
2017-03-05 16:44:50 +01:00
sequence_bits [ node - > sequence_index ] = true ; //remember sequence bit
2016-08-06 03:46:45 +02:00
VSDEBUG ( " NEXT SEQ - FLAG BIT " ) ;
} else {
2017-03-05 16:44:50 +01:00
sequence_bits [ node - > sequence_index ] = false ; //forget sequence bit
2016-08-06 03:46:45 +02:00
VSDEBUG ( " NEXT SEQ - NORMAL " ) ;
}
if ( ret & VisualScriptNodeInstance : : STEP_FLAG_GO_BACK_BIT ) {
//go back request
2017-03-05 16:44:50 +01:00
if ( flow_stack_pos > 0 ) {
2016-08-06 03:46:45 +02:00
flow_stack_pos - - ;
2017-03-05 16:44:50 +01:00
node = instances [ flow_stack [ flow_stack_pos ] & VisualScriptNodeInstance : : FLOW_STACK_MASK ] ;
2016-08-06 03:46:45 +02:00
VSDEBUG ( " NEXT IS GO BACK " ) ;
} else {
VSDEBUG ( " NEXT IS GO BACK, BUT NO NEXT SO EXIT " ) ;
break ; //simply exit without value or error
}
} else if ( next ) {
if ( sequence_bits [ next - > sequence_index ] ) {
// what happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front
// because each node has a working memory, we can't really do a sub-sequence
// as a result, the sequence will be restarted and the stack will roll back to find where this node
// started the sequence
bool found = false ;
2017-03-05 16:44:50 +01:00
for ( int i = flow_stack_pos ; i > = 0 ; i - - ) {
if ( ( flow_stack [ i ] & VisualScriptNodeInstance : : FLOW_STACK_MASK ) = = next - > get_id ( ) ) {
flow_stack_pos = i ; //roll back and remove bit
flow_stack [ i ] = next - > get_id ( ) ;
sequence_bits [ next - > sequence_index ] = false ;
found = true ;
2016-08-06 03:46:45 +02:00
}
}
if ( ! found ) {
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
error_str = RTR ( " Found sequence bit but not the node in the stack, report bug! " ) ;
error = true ;
2016-08-06 03:46:45 +02:00
break ;
}
2017-03-05 16:44:50 +01:00
node = next ;
VSDEBUG ( " RE-ENTERED A LOOP, RETURNED STACK POS TO - " + itos ( flow_stack_pos ) ) ;
2016-08-06 03:46:45 +02:00
} else {
// check for stack overflow
2017-03-05 16:44:50 +01:00
if ( flow_stack_pos + 1 > = flow_max ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
error_str = RTR ( " Stack overflow with stack depth: " ) + itos ( output ) ;
error = true ;
2016-08-06 03:46:45 +02:00
break ;
}
node = next ;
flow_stack_pos + + ;
2017-03-05 16:44:50 +01:00
flow_stack [ flow_stack_pos ] = node - > get_id ( ) ;
2016-08-06 03:46:45 +02:00
VSDEBUG ( " INCREASE FLOW STACK " ) ;
}
} else {
//no next node, try to go back in stack to pushed bit
bool found = false ;
2017-03-05 16:44:50 +01:00
for ( int i = flow_stack_pos ; i > = 0 ; i - - ) {
VSDEBUG ( " FS " + itos ( i ) + " - " + itos ( flow_stack [ i ] ) ) ;
2016-08-06 03:46:45 +02:00
if ( flow_stack [ i ] & VisualScriptNodeInstance : : FLOW_STACK_PUSHED_BIT ) {
2017-03-05 16:44:50 +01:00
node = instances [ flow_stack [ i ] & VisualScriptNodeInstance : : FLOW_STACK_MASK ] ;
flow_stack_pos = i ;
found = true ;
2016-08-29 01:57:27 +02:00
break ;
2016-08-06 03:46:45 +02:00
}
}
if ( ! found ) {
VSDEBUG ( " NO NEXT NODE, NO GO BACK, EXITING " ) ;
break ; //done, couldn't find a push stack bit
}
2017-03-05 16:44:50 +01:00
VSDEBUG ( " NO NEXT NODE, GO BACK TO: " + itos ( flow_stack_pos ) ) ;
2016-08-06 03:46:45 +02:00
}
} else {
2017-03-05 16:44:50 +01:00
node = next ; //stackless mode, simply assign next node
2016-08-06 03:46:45 +02:00
}
}
if ( error ) {
//error
// function, file, line, error, explanation
String err_file = script - > get_path ( ) ;
String err_func = p_method ;
2017-03-05 16:44:50 +01:00
int err_line = current_node_id ; //not a line but it works as one
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( node & & ( r_error . error ! = Variant : : CallError : : CALL_ERROR_INVALID_METHOD | | error_str = = String ( ) ) ) {
if ( error_str ! = String ( ) ) {
error_str + = " " ;
2016-09-04 15:34:40 +02:00
}
2017-03-05 16:44:50 +01:00
if ( r_error . error = = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ) {
int errorarg = r_error . argument ;
error_str + = " Cannot convert argument " + itos ( errorarg + 1 ) + " to " + Variant : : get_type_name ( r_error . expected ) + " . " ;
} else if ( r_error . error = = Variant : : CallError : : CALL_ERROR_TOO_MANY_ARGUMENTS ) {
error_str + = " Expected " + itos ( r_error . argument ) + " arguments. " ;
} else if ( r_error . error = = Variant : : CallError : : CALL_ERROR_TOO_FEW_ARGUMENTS ) {
error_str + = " Expected " + itos ( r_error . argument ) + " arguments. " ;
} else if ( r_error . error = = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ) {
error_str + = " Invalid Call. " ;
} else if ( r_error . error = = Variant : : CallError : : CALL_ERROR_INSTANCE_IS_NULL ) {
error_str + = " Base Instance is null " ;
2016-08-29 01:57:27 +02:00
}
}
2016-08-06 03:46:45 +02:00
//if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {
2017-03-05 16:44:50 +01:00
// debugger break did not happen
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( ! VisualScriptLanguage : : singleton - > debug_break ( error_str , false ) ) {
_err_print_error ( err_func . utf8 ( ) . get_data ( ) , err_file . utf8 ( ) . get_data ( ) , err_line , error_str . utf8 ( ) . get_data ( ) , ERR_HANDLER_SCRIPT ) ;
2016-08-07 00:00:54 +02:00
}
2016-08-06 03:46:45 +02:00
//}
} else {
//return_value=
}
2016-08-07 00:00:54 +02:00
# ifdef DEBUG_ENABLED
if ( ScriptDebugger : : get_singleton ( ) ) {
VisualScriptLanguage : : singleton - > exit_function ( ) ;
}
# endif
2016-08-06 03:46:45 +02:00
//clean up variant stack
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < f - > max_stack ; i + + ) {
2016-08-06 03:46:45 +02:00
variant_stack [ i ] . ~ Variant ( ) ;
}
return return_value ;
}
2017-03-05 16:44:50 +01:00
Variant VisualScriptInstance : : call ( const StringName & p_method , const Variant * * p_args , int p_argcount , Variant : : CallError & r_error ) {
r_error . error = Variant : : CallError : : CALL_OK ; //ok by default
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
Map < StringName , Function > : : Element * F = functions . find ( p_method ) ;
2016-08-08 00:22:33 +02:00
if ( ! F ) {
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
2016-08-08 00:22:33 +02:00
return Variant ( ) ;
}
2017-03-05 16:44:50 +01:00
VSDEBUG ( " CALLING: " + String ( p_method ) ) ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
Function * f = & F - > get ( ) ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
int total_stack_size = 0 ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
total_stack_size + = f - > max_stack * sizeof ( Variant ) ; //variants
total_stack_size + = f - > node_count * sizeof ( bool ) ;
total_stack_size + = ( max_input_args + max_output_args ) * sizeof ( Variant * ) ; //arguments
total_stack_size + = f - > flow_stack_size * sizeof ( int ) ; //flow
total_stack_size + = f - > pass_stack_size * sizeof ( int ) ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
VSDEBUG ( " STACK SIZE: " + itos ( total_stack_size ) ) ;
VSDEBUG ( " STACK VARIANTS: : " + itos ( f - > max_stack ) ) ;
VSDEBUG ( " SEQBITS: : " + itos ( f - > node_count ) ) ;
VSDEBUG ( " MAX INPUT: " + itos ( max_input_args ) ) ;
VSDEBUG ( " MAX OUTPUT: " + itos ( max_output_args ) ) ;
VSDEBUG ( " FLOW STACK SIZE: " + itos ( f - > flow_stack_size ) ) ;
VSDEBUG ( " PASS STACK SIZE: " + itos ( f - > pass_stack_size ) ) ;
2016-08-08 00:22:33 +02:00
void * stack = alloca ( total_stack_size ) ;
2017-03-05 16:44:50 +01:00
Variant * variant_stack = ( Variant * ) stack ;
bool * sequence_bits = ( bool * ) ( variant_stack + f - > max_stack ) ;
const Variant * * input_args = ( const Variant * * ) ( sequence_bits + f - > node_count ) ;
Variant * * output_args = ( Variant * * ) ( input_args + max_input_args ) ;
2016-08-08 00:22:33 +02:00
int flow_max = f - > flow_stack_size ;
2021-05-04 16:00:45 +02:00
int * flow_stack = flow_max ? ( int * ) ( output_args + max_output_args ) : ( int * ) nullptr ;
int * pass_stack = flow_stack ? ( int * ) ( flow_stack + flow_max ) : ( int * ) nullptr ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < f - > node_count ; i + + ) {
sequence_bits [ i ] = false ; //all starts as false
2016-08-08 00:22:33 +02:00
}
2021-04-29 12:34:11 +02:00
memset ( pass_stack , 0 , f - > pass_stack_size * sizeof ( int ) ) ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
Map < int , VisualScriptNodeInstance * > : : Element * E = instances . find ( f - > node ) ;
2016-08-08 00:22:33 +02:00
if ( ! E ) {
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
2016-08-08 00:22:33 +02:00
2019-08-11 10:49:53 +02:00
ERR_FAIL_V_MSG ( Variant ( ) , " No VisualScriptFunction node in function. " ) ;
2016-08-08 00:22:33 +02:00
}
VisualScriptNodeInstance * node = E - > get ( ) ;
2017-03-05 16:44:50 +01:00
if ( flow_stack ) {
flow_stack [ 0 ] = node - > get_id ( ) ;
2016-08-08 00:22:33 +02:00
}
2017-03-05 16:44:50 +01:00
VSDEBUG ( " ARGUMENTS: " + itos ( f - > argument_count ) = " RECEIVED: " + itos ( p_argcount ) ) ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
if ( p_argcount < f - > argument_count ) {
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_FEW_ARGUMENTS ;
r_error . argument = node - > get_input_port_count ( ) ;
2016-08-08 00:22:33 +02:00
return Variant ( ) ;
}
2017-03-05 16:44:50 +01:00
if ( p_argcount > f - > argument_count ) {
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_MANY_ARGUMENTS ;
r_error . argument = node - > get_input_port_count ( ) ;
2016-08-08 00:22:33 +02:00
return Variant ( ) ;
}
//allocate variant stack
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < f - > max_stack ; i + + ) {
memnew_placement ( & variant_stack [ i ] , Variant ) ;
2016-08-08 00:22:33 +02:00
}
//allocate function arguments (must be copied for yield to work properly)
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_argcount ; i + + ) {
variant_stack [ i ] = * p_args [ i ] ;
2016-08-08 00:22:33 +02:00
}
2017-03-05 16:44:50 +01:00
return _call_internal ( p_method , stack , total_stack_size , node , 0 , 0 , false , r_error ) ;
2016-08-08 00:22:33 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptInstance : : notification ( int p_notification ) {
2016-08-06 03:46:45 +02:00
//do nothing as this is called using virtual
2017-03-05 16:44:50 +01:00
Variant what = p_notification ;
const Variant * whatp = & what ;
2016-08-06 03:46:45 +02:00
Variant : : CallError ce ;
2017-03-05 16:44:50 +01:00
call ( VisualScriptLanguage : : singleton - > notification , & whatp , 1 , ce ) ; //do as call
2016-08-06 03:46:45 +02:00
}
2019-04-10 07:07:40 +02:00
String VisualScriptInstance : : to_string ( bool * r_valid ) {
if ( has_method ( CoreStringNames : : get_singleton ( ) - > _to_string ) ) {
Variant : : CallError ce ;
2021-05-04 16:00:45 +02:00
Variant ret = call ( CoreStringNames : : get_singleton ( ) - > _to_string , nullptr , 0 , ce ) ;
2019-04-10 07:07:40 +02:00
if ( ce . error = = Variant : : CallError : : CALL_OK ) {
if ( ret . get_type ( ) ! = Variant : : STRING ) {
2021-05-05 12:44:11 +02:00
if ( r_valid ) {
2019-04-10 07:07:40 +02:00
* r_valid = false ;
2021-05-05 12:44:11 +02:00
}
2019-08-11 10:49:53 +02:00
ERR_FAIL_V_MSG ( String ( ) , " Wrong type for " + CoreStringNames : : get_singleton ( ) - > _to_string + " , must be a String. " ) ;
2019-04-10 07:07:40 +02:00
}
2021-05-05 12:44:11 +02:00
if ( r_valid ) {
2019-04-10 07:07:40 +02:00
* r_valid = true ;
2021-05-05 12:44:11 +02:00
}
2019-04-10 07:07:40 +02:00
return ret . operator String ( ) ;
}
}
2021-05-05 12:44:11 +02:00
if ( r_valid ) {
2019-04-10 07:07:40 +02:00
* r_valid = false ;
2021-05-05 12:44:11 +02:00
}
2019-04-10 07:07:40 +02:00
return String ( ) ;
}
2017-03-05 16:44:50 +01:00
Ref < Script > VisualScriptInstance : : get_script ( ) const {
2016-08-06 03:46:45 +02:00
return script ;
}
2018-05-13 07:07:56 +02:00
MultiplayerAPI : : RPCMode VisualScriptInstance : : get_rpc_mode ( const StringName & p_method ) const {
2021-05-05 12:44:11 +02:00
if ( p_method = = script - > get_default_func ( ) ) {
2019-09-13 21:14:12 +02:00
return MultiplayerAPI : : RPC_MODE_DISABLED ;
2021-05-05 12:44:11 +02:00
}
2019-09-13 21:14:12 +02:00
2017-03-05 16:44:50 +01:00
const Map < StringName , VisualScript : : Function > : : Element * E = script - > functions . find ( p_method ) ;
2016-08-25 22:45:20 +02:00
if ( ! E ) {
2018-05-13 07:07:56 +02:00
return MultiplayerAPI : : RPC_MODE_DISABLED ;
2016-08-25 22:45:20 +02:00
}
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . function_id > = 0 & & E - > get ( ) . nodes . has ( E - > get ( ) . function_id ) ) {
2016-08-25 22:45:20 +02:00
Ref < VisualScriptFunction > vsf = E - > get ( ) . nodes [ E - > get ( ) . function_id ] . node ;
if ( vsf . is_valid ( ) ) {
return vsf - > get_rpc_mode ( ) ;
}
}
2018-05-13 07:07:56 +02:00
return MultiplayerAPI : : RPC_MODE_DISABLED ;
2016-08-19 21:48:08 +02:00
}
2016-08-25 22:45:20 +02:00
2018-05-13 07:07:56 +02:00
MultiplayerAPI : : RPCMode VisualScriptInstance : : get_rset_mode ( const StringName & p_variable ) const {
return MultiplayerAPI : : RPC_MODE_DISABLED ;
2016-08-19 21:48:08 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptInstance : : create ( const Ref < VisualScript > & p_script , Object * p_owner ) {
script = p_script ;
owner = p_owner ;
source = p_script - > get_path ( ) ;
2016-08-06 03:46:45 +02:00
max_input_args = 0 ;
max_output_args = 0 ;
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < Node > ( p_owner ) ) {
2016-08-08 01:08:15 +02:00
//turn on these if they exist and base is a node
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( p_owner ) ;
2021-05-05 12:44:11 +02:00
if ( p_script - > functions . has ( " _process " ) ) {
2016-08-08 01:08:15 +02:00
node - > set_process ( true ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_script - > functions . has ( " _physics_process " ) ) {
2017-09-30 16:19:07 +02:00
node - > set_physics_process ( true ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_script - > functions . has ( " _input " ) ) {
2016-08-08 01:08:15 +02:00
node - > set_process_input ( true ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_script - > functions . has ( " _unhandled_input " ) ) {
2016-08-08 01:08:15 +02:00
node - > set_process_unhandled_input ( true ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_script - > functions . has ( " _unhandled_key_input " ) ) {
2016-08-08 01:08:15 +02:00
node - > set_process_unhandled_key_input ( true ) ;
2021-05-05 12:44:11 +02:00
}
2016-08-08 01:08:15 +02:00
}
2017-03-05 16:44:50 +01:00
for ( const Map < StringName , VisualScript : : Variable > : : Element * E = script - > variables . front ( ) ; E ; E = E - > next ( ) ) {
variables [ E - > key ( ) ] = E - > get ( ) . default_value ;
2016-08-06 03:46:45 +02:00
}
2017-03-05 16:44:50 +01:00
for ( const Map < StringName , VisualScript : : Function > : : Element * E = script - > functions . front ( ) ; E ; E = E - > next ( ) ) {
2019-09-13 21:14:12 +02:00
if ( E - > key ( ) = = script - > get_default_func ( ) ) {
continue ;
}
2016-08-06 03:46:45 +02:00
Function function ;
2017-03-05 16:44:50 +01:00
function . node = E - > get ( ) . function_id ;
function . max_stack = 0 ;
function . flow_stack_size = 0 ;
function . pass_stack_size = 0 ;
function . node_count = 0 ;
2018-04-19 13:04:41 +02:00
2017-03-05 16:44:50 +01:00
Map < StringName , int > local_var_indices ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( function . node < 0 ) {
VisualScriptLanguage : : singleton - > debug_break_parse ( get_script ( ) - > get_path ( ) , 0 , " No start node in function: " + String ( E - > key ( ) ) ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( function . node < 0 ) ;
2016-08-06 03:46:45 +02:00
}
{
2017-03-05 16:44:50 +01:00
Ref < VisualScriptFunction > func_node = script - > get_node ( E - > key ( ) , E - > get ( ) . function_id ) ;
2016-08-06 03:46:45 +02:00
2016-08-07 00:00:54 +02:00
if ( func_node . is_null ( ) ) {
2017-03-05 16:44:50 +01:00
VisualScriptLanguage : : singleton - > debug_break_parse ( get_script ( ) - > get_path ( ) , 0 , " No VisualScriptFunction typed start node in function: " + String ( E - > key ( ) ) ) ;
2016-08-07 00:00:54 +02:00
}
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( ! func_node . is_valid ( ) ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
function . argument_count = func_node - > get_argument_count ( ) ;
function . max_stack + = function . argument_count ;
function . flow_stack_size = func_node - > is_stack_less ( ) ? 0 : func_node - > get_stack_size ( ) ;
2017-12-07 02:19:56 +01:00
max_input_args = MAX ( max_input_args , function . argument_count ) ;
2016-08-06 03:46:45 +02:00
}
//multiple passes are required to set up this complex thing..
//first create the nodes
2017-03-05 16:44:50 +01:00
for ( const Map < int , VisualScript : : Function : : NodeData > : : Element * F = E - > get ( ) . nodes . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-06 03:46:45 +02:00
Ref < VisualScriptNode > node = F - > get ( ) . node ;
2019-09-13 21:14:12 +02:00
2016-08-06 03:46:45 +02:00
VisualScriptNodeInstance * instance = node - > instance ( this ) ; //create instance
ERR_FAIL_COND ( ! instance ) ;
2017-03-05 16:44:50 +01:00
instance - > base = node . ptr ( ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
instance - > id = F - > key ( ) ;
2016-08-06 03:46:45 +02:00
instance - > input_port_count = node - > get_input_value_port_count ( ) ;
2021-05-04 16:00:45 +02:00
instance - > input_ports = nullptr ;
2016-08-06 03:46:45 +02:00
instance - > output_port_count = node - > get_output_value_port_count ( ) ;
2021-05-04 16:00:45 +02:00
instance - > output_ports = nullptr ;
2016-08-06 03:46:45 +02:00
instance - > sequence_output_count = node - > get_output_sequence_port_count ( ) ;
2017-03-05 16:44:50 +01:00
instance - > sequence_index = function . node_count + + ;
2021-05-04 16:00:45 +02:00
instance - > sequence_outputs = nullptr ;
2017-03-05 16:44:50 +01:00
instance - > pass_idx = - 1 ;
2016-08-06 03:46:45 +02:00
if ( instance - > input_port_count ) {
2017-03-05 16:44:50 +01:00
instance - > input_ports = memnew_arr ( int , instance - > input_port_count ) ;
for ( int i = 0 ; i < instance - > input_port_count ; i + + ) {
instance - > input_ports [ i ] = - 1 ; //if not assigned, will become default value
}
2016-08-06 03:46:45 +02:00
}
if ( instance - > output_port_count ) {
2017-03-05 16:44:50 +01:00
instance - > output_ports = memnew_arr ( int , instance - > output_port_count ) ;
for ( int i = 0 ; i < instance - > output_port_count ; i + + ) {
instance - > output_ports [ i ] = - 1 ; //if not assigned, will output to trash
2016-08-06 03:46:45 +02:00
}
}
if ( instance - > sequence_output_count ) {
2017-03-05 16:44:50 +01:00
instance - > sequence_outputs = memnew_arr ( VisualScriptNodeInstance * , instance - > sequence_output_count ) ;
for ( int i = 0 ; i < instance - > sequence_output_count ; i + + ) {
2021-05-04 16:00:45 +02:00
instance - > sequence_outputs [ i ] = nullptr ; //if it remains null, flow ends here
2016-08-06 03:46:45 +02:00
}
}
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < VisualScriptLocalVar > ( node . ptr ( ) ) | | Object : : cast_to < VisualScriptLocalVarSet > ( * node ) ) {
2016-08-29 01:57:27 +02:00
//working memory is shared only for this node, for the same variables
Ref < VisualScriptLocalVar > vslv = node ;
2016-08-31 04:44:14 +02:00
StringName var_name ;
2021-05-05 12:44:11 +02:00
if ( Object : : cast_to < VisualScriptLocalVar > ( * node ) ) {
2017-08-24 22:58:51 +02:00
var_name = String ( Object : : cast_to < VisualScriptLocalVar > ( * node ) - > get_var_name ( ) ) . strip_edges ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-08-24 22:58:51 +02:00
var_name = String ( Object : : cast_to < VisualScriptLocalVarSet > ( * node ) - > get_var_name ( ) ) . strip_edges ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-08-29 01:57:27 +02:00
if ( ! local_var_indices . has ( var_name ) ) {
2017-03-05 16:44:50 +01:00
local_var_indices [ var_name ] = function . max_stack ;
2016-08-29 01:57:27 +02:00
function . max_stack + + ;
}
2017-03-05 16:44:50 +01:00
instance - > working_mem_idx = local_var_indices [ var_name ] ;
2016-08-29 01:57:27 +02:00
} else if ( instance - > get_working_memory_size ( ) ) {
2016-08-06 03:46:45 +02:00
instance - > working_mem_idx = function . max_stack ;
2017-03-05 16:44:50 +01:00
function . max_stack + = instance - > get_working_memory_size ( ) ;
2016-08-06 03:46:45 +02:00
} else {
2017-03-05 16:44:50 +01:00
instance - > working_mem_idx = - 1 ; //no working mem
2016-08-06 03:46:45 +02:00
}
2017-03-05 16:44:50 +01:00
max_input_args = MAX ( max_input_args , instance - > input_port_count ) ;
max_output_args = MAX ( max_output_args , instance - > output_port_count ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
instances [ F - > key ( ) ] = instance ;
2016-08-06 03:46:45 +02:00
}
function . trash_pos = function . max_stack + + ; //create pos for trash
//second pass, do data connections
2017-03-05 16:44:50 +01:00
for ( const Set < VisualScript : : DataConnection > : : Element * F = E - > get ( ) . data_connections . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-06 03:46:45 +02:00
VisualScript : : DataConnection dc = F - > get ( ) ;
ERR_CONTINUE ( ! instances . has ( dc . from_node ) ) ;
VisualScriptNodeInstance * from = instances [ dc . from_node ] ;
ERR_CONTINUE ( ! instances . has ( dc . to_node ) ) ;
VisualScriptNodeInstance * to = instances [ dc . to_node ] ;
ERR_CONTINUE ( dc . from_port > = from - > output_port_count ) ;
ERR_CONTINUE ( dc . to_port > = to - > input_port_count ) ;
2017-03-05 16:44:50 +01:00
if ( from - > output_ports [ dc . from_port ] = = - 1 ) {
2016-08-06 03:46:45 +02:00
int stack_pos = function . max_stack + + ;
from - > output_ports [ dc . from_port ] = stack_pos ;
}
2017-03-05 16:44:50 +01:00
if ( from - > get_sequence_output_count ( ) = = 0 & & to - > dependencies . find ( from ) = = - 1 ) {
2016-08-31 04:44:14 +02:00
//if the node we are reading from has no output sequence, we must call step() before reading from it.
2017-03-05 16:44:50 +01:00
if ( from - > pass_idx = = - 1 ) {
from - > pass_idx = function . pass_stack_size ;
2016-08-31 04:44:14 +02:00
function . pass_stack_size + + ;
}
to - > dependencies . push_back ( from ) ;
2016-08-06 03:46:45 +02:00
}
2016-08-31 04:44:14 +02:00
to - > input_ports [ dc . to_port ] = from - > output_ports [ dc . from_port ] ; //read from wherever the stack is
2016-08-06 03:46:45 +02:00
}
//third pass, do sequence connections
2017-03-05 16:44:50 +01:00
for ( const Set < VisualScript : : SequenceConnection > : : Element * F = E - > get ( ) . sequence_connections . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-06 03:46:45 +02:00
VisualScript : : SequenceConnection sc = F - > get ( ) ;
ERR_CONTINUE ( ! instances . has ( sc . from_node ) ) ;
VisualScriptNodeInstance * from = instances [ sc . from_node ] ;
ERR_CONTINUE ( ! instances . has ( sc . to_node ) ) ;
VisualScriptNodeInstance * to = instances [ sc . to_node ] ;
ERR_CONTINUE ( sc . from_output > = from - > sequence_output_count ) ;
2017-03-05 16:44:50 +01:00
from - > sequence_outputs [ sc . from_output ] = to ;
2016-08-06 03:46:45 +02:00
}
//fourth pass:
// 1) unassigned input ports to default values
// 2) connect unassigned output ports to trash
2017-03-05 16:44:50 +01:00
for ( const Map < int , VisualScript : : Function : : NodeData > : : Element * F = E - > get ( ) . nodes . front ( ) ; F ; F = F - > next ( ) ) {
2016-08-06 03:46:45 +02:00
ERR_CONTINUE ( ! instances . has ( F - > key ( ) ) ) ;
Ref < VisualScriptNode > node = F - > get ( ) . node ;
VisualScriptNodeInstance * instance = instances [ F - > key ( ) ] ;
2018-02-21 17:30:55 +01:00
// connect to default values
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < instance - > input_port_count ; i + + ) {
if ( instance - > input_ports [ i ] = = - 1 ) {
2016-08-06 03:46:45 +02:00
//unassigned, connect to default val
instance - > input_ports [ i ] = default_values . size ( ) | VisualScriptNodeInstance : : INPUT_DEFAULT_VALUE_BIT ;
2017-03-05 16:44:50 +01:00
default_values . push_back ( node - > get_default_input_value ( i ) ) ;
2016-08-06 03:46:45 +02:00
}
}
2018-02-21 17:30:55 +01:00
// connect to trash
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < instance - > output_port_count ; i + + ) {
if ( instance - > output_ports [ i ] = = - 1 ) {
2016-08-06 03:46:45 +02:00
instance - > output_ports [ i ] = function . trash_pos ; //trash is same for all
}
}
}
2017-03-05 16:44:50 +01:00
functions [ E - > key ( ) ] = function ;
2016-08-06 03:46:45 +02:00
}
}
2017-03-05 16:44:50 +01:00
ScriptLanguage * VisualScriptInstance : : get_language ( ) {
2016-08-06 03:46:45 +02:00
return VisualScriptLanguage : : singleton ;
}
VisualScriptInstance : : VisualScriptInstance ( ) {
}
VisualScriptInstance : : ~ VisualScriptInstance ( ) {
2021-01-27 10:43:02 +01:00
VisualScriptLanguage : : singleton - > lock . lock ( ) ;
2016-08-06 03:46:45 +02:00
script - > instances . erase ( owner ) ;
2021-01-27 10:43:02 +01:00
VisualScriptLanguage : : singleton - > lock . unlock ( ) ;
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
for ( Map < int , VisualScriptNodeInstance * > : : Element * E = instances . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-06 03:46:45 +02:00
memdelete ( E - > get ( ) ) ;
}
}
2016-08-08 00:22:33 +02:00
/////////////////////////////////////////////
/////////////////////
2017-03-05 16:44:50 +01:00
Variant VisualScriptFunctionState : : _signal_callback ( const Variant * * p_args , int p_argcount , Variant : : CallError & r_error ) {
ERR_FAIL_COND_V ( function = = StringName ( ) , Variant ( ) ) ;
2016-08-08 00:22:33 +02:00
# ifdef DEBUG_ENABLED
2019-08-11 10:49:53 +02:00
ERR_FAIL_COND_V_MSG ( instance_id & & ! ObjectDB : : get_instance ( instance_id ) , Variant ( ) , " Resumed after yield, but class instance is gone. " ) ;
ERR_FAIL_COND_V_MSG ( script_id & & ! ObjectDB : : get_instance ( script_id ) , Variant ( ) , " Resumed after yield, but script is gone. " ) ;
2016-08-08 00:22:33 +02:00
# endif
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_OK ;
2016-08-08 00:22:33 +02:00
Array args ;
2017-03-05 16:44:50 +01:00
if ( p_argcount = = 0 ) {
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_FEW_ARGUMENTS ;
r_error . argument = 1 ;
2016-08-08 00:22:33 +02:00
return Variant ( ) ;
2017-03-05 16:44:50 +01:00
} else if ( p_argcount = = 1 ) {
2016-08-08 00:22:33 +02:00
//noooneee, reserved for me, me and only me.
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_argcount - 1 ; i + + ) {
2016-08-08 00:22:33 +02:00
args . push_back ( * p_args [ i ] ) ;
}
}
2017-03-05 16:44:50 +01:00
Ref < VisualScriptFunctionState > self = * p_args [ p_argcount - 1 ] ; //hi, I'm myself, needed this to remain alive.
2016-08-08 00:22:33 +02:00
if ( self . is_null ( ) ) {
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = p_argcount - 1 ;
r_error . expected = Variant : : OBJECT ;
2016-08-08 00:22:33 +02:00
return Variant ( ) ;
}
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_OK ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
Variant * working_mem = ( ( Variant * ) stack . ptr ( ) ) + working_mem_index ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
* working_mem = args ; //arguments go to working mem.
2016-08-08 00:22:33 +02:00
2017-11-25 04:07:54 +01:00
Variant ret = instance - > _call_internal ( function , stack . ptrw ( ) , stack . size ( ) , node , flow_stack_pos , pass , true , r_error ) ;
2017-03-05 16:44:50 +01:00
function = StringName ( ) ; //invalidate
2016-08-08 00:22:33 +02:00
return ret ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptFunctionState : : connect_to_signal ( Object * p_obj , const String & p_signal , Array p_binds ) {
2021-10-13 13:19:29 +02:00
ERR_FAIL_NULL ( p_obj ) ;
2016-08-08 00:22:33 +02:00
Vector < Variant > binds ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_binds . size ( ) ; i + + ) {
2016-08-08 00:22:33 +02:00
binds . push_back ( p_binds [ i ] ) ;
}
binds . push_back ( Ref < VisualScriptFunctionState > ( this ) ) ; //add myself on the back to avoid dying from unreferencing
2017-12-01 04:35:44 +01:00
p_obj - > connect ( p_signal , this , " _signal_callback " , binds , CONNECT_ONESHOT ) ;
2016-08-08 00:22:33 +02:00
}
bool VisualScriptFunctionState : : is_valid ( ) const {
2017-03-05 16:44:50 +01:00
return function ! = StringName ( ) ;
2016-08-08 00:22:33 +02:00
}
Variant VisualScriptFunctionState : : resume ( Array p_args ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( function = = StringName ( ) , Variant ( ) ) ;
2016-08-08 00:22:33 +02:00
# ifdef DEBUG_ENABLED
2019-08-11 10:49:53 +02:00
ERR_FAIL_COND_V_MSG ( instance_id & & ! ObjectDB : : get_instance ( instance_id ) , Variant ( ) , " Resumed after yield, but class instance is gone. " ) ;
ERR_FAIL_COND_V_MSG ( script_id & & ! ObjectDB : : get_instance ( script_id ) , Variant ( ) , " Resumed after yield, but script is gone. " ) ;
2016-08-08 00:22:33 +02:00
# endif
Variant : : CallError r_error ;
2017-03-05 16:44:50 +01:00
r_error . error = Variant : : CallError : : CALL_OK ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
Variant * working_mem = ( ( Variant * ) stack . ptr ( ) ) + working_mem_index ;
2016-08-08 00:22:33 +02:00
2017-03-05 16:44:50 +01:00
* working_mem = p_args ; //arguments go to working mem.
2016-08-08 00:22:33 +02:00
2017-11-25 04:07:54 +01:00
Variant ret = instance - > _call_internal ( function , stack . ptrw ( ) , stack . size ( ) , node , flow_stack_pos , pass , true , r_error ) ;
2017-03-05 16:44:50 +01:00
function = StringName ( ) ; //invalidate
2016-08-08 00:22:33 +02:00
return ret ;
}
void VisualScriptFunctionState : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " connect_to_signal " , " obj " , " signals " , " args " ) , & VisualScriptFunctionState : : connect_to_signal ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " resume " , " args " ) , & VisualScriptFunctionState : : resume , DEFVAL ( Variant ( ) ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_valid " ) , & VisualScriptFunctionState : : is_valid ) ;
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " _signal_callback " , & VisualScriptFunctionState : : _signal_callback , MethodInfo ( " _signal_callback " ) ) ;
2016-08-08 00:22:33 +02:00
}
VisualScriptFunctionState : : VisualScriptFunctionState ( ) {
}
VisualScriptFunctionState : : ~ VisualScriptFunctionState ( ) {
2017-03-05 16:44:50 +01:00
if ( function ! = StringName ( ) ) {
Variant * s = ( ( Variant * ) stack . ptr ( ) ) ;
for ( int i = 0 ; i < variant_stack_size ; i + + ) {
2016-08-08 00:22:33 +02:00
s [ i ] . ~ Variant ( ) ;
}
}
}
2016-08-06 03:46:45 +02:00
///////////////////////////////////////////////
2016-08-03 00:11:05 +02:00
String VisualScriptLanguage : : get_name ( ) const {
return " VisualScript " ;
}
/* LANGUAGE FUNCTIONS */
void VisualScriptLanguage : : init ( ) {
}
String VisualScriptLanguage : : get_type ( ) const {
return " VisualScript " ;
}
String VisualScriptLanguage : : get_extension ( ) const {
return " vs " ;
}
2017-03-05 16:44:50 +01:00
Error VisualScriptLanguage : : execute_file ( const String & p_path ) {
2016-08-03 00:11:05 +02:00
return OK ;
}
void VisualScriptLanguage : : finish ( ) {
}
/* EDITOR FUNCTIONS */
void VisualScriptLanguage : : get_reserved_words ( List < String > * p_words ) const {
}
2019-11-12 17:08:07 +01:00
bool VisualScriptLanguage : : is_control_flow_keyword ( String p_keyword ) const {
return false ;
}
2016-08-03 00:11:05 +02:00
void VisualScriptLanguage : : get_comment_delimiters ( List < String > * p_delimiters ) const {
}
void VisualScriptLanguage : : get_string_delimiters ( List < String > * p_delimiters ) const {
}
2017-03-05 16:44:50 +01:00
Ref < Script > VisualScriptLanguage : : get_template ( const String & p_class_name , const String & p_base_class_name ) const {
2016-08-06 03:46:45 +02:00
Ref < VisualScript > script ;
script . instance ( ) ;
script - > set_instance_base_type ( p_base_class_name ) ;
return script ;
2016-08-03 00:11:05 +02:00
}
2017-06-13 22:03:08 +02:00
bool VisualScriptLanguage : : is_using_templates ( ) {
return true ;
}
void VisualScriptLanguage : : make_template ( const String & p_class_name , const String & p_base_class_name , Ref < Script > & p_script ) {
Ref < VisualScript > script = p_script ;
script - > set_instance_base_type ( p_base_class_name ) ;
}
2018-07-01 18:17:40 +02:00
bool VisualScriptLanguage : : validate ( const String & p_script , int & r_line_error , int & r_col_error , String & r_test_error , const String & p_path , List < String > * r_functions , List < ScriptLanguage : : Warning > * r_warnings , Set < int > * r_safe_lines ) const {
2016-08-03 00:11:05 +02:00
return false ;
}
Script * VisualScriptLanguage : : create_script ( ) const {
2017-03-05 16:44:50 +01:00
return memnew ( VisualScript ) ;
2016-08-03 00:11:05 +02:00
}
bool VisualScriptLanguage : : has_named_classes ( ) const {
return false ;
}
2017-10-24 01:54:47 +02:00
bool VisualScriptLanguage : : supports_builtin_mode ( ) const {
return true ;
}
2017-03-05 16:44:50 +01:00
int VisualScriptLanguage : : find_function ( const String & p_function , const String & p_code ) const {
2016-08-03 00:11:05 +02:00
return - 1 ;
}
2017-03-05 16:44:50 +01:00
String VisualScriptLanguage : : make_function ( const String & p_class , const String & p_name , const PoolStringArray & p_args ) const {
2016-08-03 00:11:05 +02:00
return String ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : auto_indent_code ( String & p_code , int p_from_line , int p_to_line ) const {
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : add_global_constant ( const StringName & p_variable , const Variant & p_value ) {
2016-08-03 00:11:05 +02:00
}
/* DEBUGGER FUNCTIONS */
2017-03-05 16:44:50 +01:00
bool VisualScriptLanguage : : debug_break_parse ( const String & p_file , int p_node , const String & p_error ) {
2016-08-07 00:00:54 +02:00
//break because of parse error
2017-08-07 12:17:31 +02:00
if ( ScriptDebugger : : get_singleton ( ) & & Thread : : get_caller_id ( ) = = Thread : : get_main_id ( ) ) {
2017-03-05 16:44:50 +01:00
_debug_parse_err_node = p_node ;
_debug_parse_err_file = p_file ;
_debug_error = p_error ;
2019-07-29 20:09:22 +02:00
ScriptDebugger : : get_singleton ( ) - > debug ( this , false , true ) ;
2017-03-05 16:44:50 +01:00
return true ;
} else {
return false ;
}
2016-08-07 00:00:54 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScriptLanguage : : debug_break ( const String & p_error , bool p_allow_continue ) {
2017-08-07 12:17:31 +02:00
if ( ScriptDebugger : : get_singleton ( ) & & Thread : : get_caller_id ( ) = = Thread : : get_main_id ( ) ) {
2017-03-05 16:44:50 +01:00
_debug_parse_err_node = - 1 ;
_debug_parse_err_file = " " ;
_debug_error = p_error ;
2019-07-29 20:09:22 +02:00
ScriptDebugger : : get_singleton ( ) - > debug ( this , p_allow_continue , true ) ;
2017-03-05 16:44:50 +01:00
return true ;
} else {
return false ;
}
2016-08-07 00:00:54 +02:00
}
2016-08-03 00:11:05 +02:00
String VisualScriptLanguage : : debug_get_error ( ) const {
2017-03-05 16:44:50 +01:00
return _debug_error ;
2016-08-03 00:11:05 +02:00
}
2016-08-07 00:00:54 +02:00
2016-08-03 00:11:05 +02:00
int VisualScriptLanguage : : debug_get_stack_level_count ( ) const {
2021-05-05 12:44:11 +02:00
if ( _debug_parse_err_node > = 0 ) {
2016-08-07 00:00:54 +02:00
return 1 ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
return _debug_call_stack_pos ;
2016-08-03 00:11:05 +02:00
}
int VisualScriptLanguage : : debug_get_stack_level_line ( int p_level ) const {
2021-05-05 12:44:11 +02:00
if ( _debug_parse_err_node > = 0 ) {
2016-08-07 00:00:54 +02:00
return _debug_parse_err_node ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_level , _debug_call_stack_pos , - 1 ) ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
int l = _debug_call_stack_pos - p_level - 1 ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
return * ( _call_stack [ l ] . current_id ) ;
2016-08-03 00:11:05 +02:00
}
String VisualScriptLanguage : : debug_get_stack_level_function ( int p_level ) const {
2021-05-05 12:44:11 +02:00
if ( _debug_parse_err_node > = 0 ) {
2016-08-07 00:00:54 +02:00
return " " ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_level , _debug_call_stack_pos , " " ) ;
int l = _debug_call_stack_pos - p_level - 1 ;
return * _call_stack [ l ] . function ;
2016-08-03 00:11:05 +02:00
}
String VisualScriptLanguage : : debug_get_stack_level_source ( int p_level ) const {
2021-05-05 12:44:11 +02:00
if ( _debug_parse_err_node > = 0 ) {
2016-08-07 00:00:54 +02:00
return _debug_parse_err_file ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_level , _debug_call_stack_pos , " " ) ;
int l = _debug_call_stack_pos - p_level - 1 ;
return _call_stack [ l ] . instance - > get_script_ptr ( ) - > get_path ( ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : debug_get_stack_level_locals ( int p_level , List < String > * p_locals , List < Variant > * p_values , int p_max_subitems , int p_max_depth ) {
2021-05-05 12:44:11 +02:00
if ( _debug_parse_err_node > = 0 ) {
2016-08-07 00:00:54 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_level , _debug_call_stack_pos ) ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
int l = _debug_call_stack_pos - p_level - 1 ;
2016-08-07 00:00:54 +02:00
const StringName * f = _call_stack [ l ] . function ;
ERR_FAIL_COND ( ! _call_stack [ l ] . instance - > functions . has ( * f ) ) ;
2017-03-05 16:44:50 +01:00
VisualScriptNodeInstance * node = _call_stack [ l ] . instance - > instances [ * _call_stack [ l ] . current_id ] ;
2016-08-07 00:00:54 +02:00
ERR_FAIL_COND ( ! node ) ;
p_locals - > push_back ( " node_name " ) ;
p_values - > push_back ( node - > get_base_node ( ) - > get_text ( ) ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > input_port_count ; i + + ) {
2016-08-07 00:00:54 +02:00
String name = node - > get_base_node ( ) - > get_input_value_port_info ( i ) . name ;
2017-03-05 16:44:50 +01:00
if ( name = = String ( ) ) {
name = " in_ " + itos ( i ) ;
2016-08-07 00:00:54 +02:00
}
2017-03-05 16:44:50 +01:00
p_locals - > push_back ( " input/ " + name ) ;
2016-08-07 00:00:54 +02:00
//value is trickier
int in_from = node - > input_ports [ i ] ;
2017-03-05 16:44:50 +01:00
int in_value = in_from & VisualScriptNodeInstance : : INPUT_MASK ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
if ( in_from & VisualScriptNodeInstance : : INPUT_DEFAULT_VALUE_BIT ) {
2016-08-07 00:00:54 +02:00
p_values - > push_back ( _call_stack [ l ] . instance - > default_values [ in_value ] ) ;
} else {
2017-03-05 16:44:50 +01:00
p_values - > push_back ( _call_stack [ l ] . stack [ in_value ] ) ;
2016-08-07 00:00:54 +02:00
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > output_port_count ; i + + ) {
2016-08-07 00:00:54 +02:00
String name = node - > get_base_node ( ) - > get_output_value_port_info ( i ) . name ;
2017-03-05 16:44:50 +01:00
if ( name = = String ( ) ) {
name = " out_ " + itos ( i ) ;
2016-08-07 00:00:54 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
p_locals - > push_back ( " output/ " + name ) ;
2016-08-07 00:00:54 +02:00
//value is trickier
int in_from = node - > output_ports [ i ] ;
2017-03-05 16:44:50 +01:00
p_values - > push_back ( _call_stack [ l ] . stack [ in_from ] ) ;
2016-08-07 00:00:54 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > get_working_memory_size ( ) ; i + + ) {
p_locals - > push_back ( " working_mem/mem_ " + itos ( i ) ) ;
p_values - > push_back ( ( * _call_stack [ l ] . work_mem ) [ i ] ) ;
2016-08-07 00:00:54 +02:00
}
2016-08-03 00:11:05 +02:00
}
2021-10-28 14:15:02 +02:00
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : debug_get_stack_level_members ( int p_level , List < String > * p_members , List < Variant > * p_values , int p_max_subitems , int p_max_depth ) {
2021-05-05 12:44:11 +02:00
if ( _debug_parse_err_node > = 0 ) {
2016-08-07 00:00:54 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_level , _debug_call_stack_pos ) ;
int l = _debug_call_stack_pos - p_level - 1 ;
2016-08-07 00:00:54 +02:00
Ref < VisualScript > vs = _call_stack [ l ] . instance - > get_script ( ) ;
2021-05-05 12:44:11 +02:00
if ( vs . is_null ( ) ) {
2016-08-07 00:00:54 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-08-07 00:00:54 +02:00
List < StringName > vars ;
vs - > get_variable_list ( & vars ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * E = vars . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-07 00:00:54 +02:00
Variant v ;
2017-03-05 16:44:50 +01:00
if ( _call_stack [ l ] . instance - > get_variable ( E - > get ( ) , & v ) ) {
p_members - > push_back ( " variables/ " + E - > get ( ) ) ;
2016-08-07 00:00:54 +02:00
p_values - > push_back ( v ) ;
}
}
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : debug_get_globals ( List < String > * p_locals , List < Variant > * p_values , int p_max_subitems , int p_max_depth ) {
//no globals are really reachable in gdscript
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
String VisualScriptLanguage : : debug_parse_stack_level_expression ( int p_level , const String & p_expression , int p_max_subitems , int p_max_depth ) {
2016-08-07 00:00:54 +02:00
return " " ;
2016-08-03 00:11:05 +02:00
}
void VisualScriptLanguage : : reload_all_scripts ( ) {
}
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : reload_tool_script ( const Ref < Script > & p_script , bool p_soft_reload ) {
2016-08-03 00:11:05 +02:00
}
/* LOADER FUNCTIONS */
void VisualScriptLanguage : : get_recognized_extensions ( List < String > * p_extensions ) const {
p_extensions - > push_back ( " vs " ) ;
}
void VisualScriptLanguage : : get_public_functions ( List < MethodInfo > * p_functions ) const {
}
2021-05-04 14:20:36 +02:00
void VisualScriptLanguage : : get_public_constants ( List < Pair < String , Variant > > * p_constants ) const {
2016-08-03 00:11:05 +02:00
}
void VisualScriptLanguage : : profiling_start ( ) {
}
void VisualScriptLanguage : : profiling_stop ( ) {
}
2017-03-05 16:44:50 +01:00
int VisualScriptLanguage : : profiling_get_accumulated_data ( ProfilingInfo * p_info_arr , int p_info_max ) {
2016-08-03 00:11:05 +02:00
return 0 ;
}
2017-03-05 16:44:50 +01:00
int VisualScriptLanguage : : profiling_get_frame_data ( ProfilingInfo * p_info_arr , int p_info_max ) {
2016-08-03 00:11:05 +02:00
return 0 ;
}
2021-05-04 16:00:45 +02:00
VisualScriptLanguage * VisualScriptLanguage : : singleton = nullptr ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
void VisualScriptLanguage : : add_register_func ( const String & p_name , VisualScriptNodeRegisterFunc p_func ) {
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( register_funcs . has ( p_name ) ) ;
2017-03-05 16:44:50 +01:00
register_funcs [ p_name ] = p_func ;
2016-08-03 00:11:05 +02:00
}
2017-11-15 16:57:24 +01:00
void VisualScriptLanguage : : remove_register_func ( const String & p_name ) {
ERR_FAIL_COND ( ! register_funcs . has ( p_name ) ) ;
register_funcs . erase ( p_name ) ;
}
2017-03-05 16:44:50 +01:00
Ref < VisualScriptNode > VisualScriptLanguage : : create_node_from_name ( const String & p_name ) {
ERR_FAIL_COND_V ( ! register_funcs . has ( p_name ) , Ref < VisualScriptNode > ( ) ) ;
2016-08-03 00:11:05 +02:00
return register_funcs [ p_name ] ( p_name ) ;
}
void VisualScriptLanguage : : get_registered_node_names ( List < String > * r_names ) {
2017-03-05 16:44:50 +01:00
for ( Map < String , VisualScriptNodeRegisterFunc > : : Element * E = register_funcs . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-03 00:11:05 +02:00
r_names - > push_back ( E - > key ( ) ) ;
}
}
VisualScriptLanguage : : VisualScriptLanguage ( ) {
2017-03-05 16:44:50 +01:00
notification = " _notification " ;
_step = " _step " ;
_subcall = " _subcall " ;
singleton = this ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
_debug_parse_err_node = - 1 ;
_debug_parse_err_file = " " ;
_debug_call_stack_pos = 0 ;
2017-07-18 02:05:38 +02:00
int dmcs = GLOBAL_DEF ( " debug/settings/visual_script/max_call_stack " , 1024 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " debug/settings/visual_script/max_call_stack " , PropertyInfo ( Variant : : INT , " debug/settings/visual_script/max_call_stack " , PROPERTY_HINT_RANGE , " 1024,4096,1,or_greater " ) ) ; //minimum is 1024
2016-08-07 00:00:54 +02:00
if ( ScriptDebugger : : get_singleton ( ) ) {
//debugging enabled!
_debug_max_call_stack = dmcs ;
2017-03-05 16:44:50 +01:00
_call_stack = memnew_arr ( CallLevel , _debug_max_call_stack + 1 ) ;
2016-08-07 00:00:54 +02:00
} else {
2017-03-05 16:44:50 +01:00
_debug_max_call_stack = 0 ;
2021-05-04 16:00:45 +02:00
_call_stack = nullptr ;
2016-08-07 00:00:54 +02:00
}
2016-08-06 03:46:45 +02:00
}
VisualScriptLanguage : : ~ VisualScriptLanguage ( ) {
2017-03-05 16:44:50 +01:00
if ( _call_stack ) {
2016-08-07 00:00:54 +02:00
memdelete_arr ( _call_stack ) ;
}
2021-05-04 16:00:45 +02:00
singleton = nullptr ;
2016-08-03 00:11:05 +02:00
}