2017-03-05 15:47:28 +01:00
/*************************************************************************/
2017-09-01 16:07:55 +02:00
/* visual_script_editor.cpp */
2017-03-05 15:47:28 +01:00
/*************************************************************************/
/* 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-03 21:27:34 +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_editor.h"
2017-03-05 15:47:28 +01:00
2021-11-12 06:48:34 +01:00
# include "../visual_script_expression.h"
# include "../visual_script_flow_control.h"
# include "../visual_script_func_nodes.h"
# include "../visual_script_nodes.h"
2020-04-28 15:19:37 +02:00
# include "core/input/input.h"
2020-11-07 23:33:38 +01:00
# include "core/object/class_db.h"
# include "core/object/script_language.h"
2018-09-11 18:13:45 +02:00
# include "core/os/keyboard.h"
2020-11-07 23:33:38 +01:00
# include "core/variant/variant.h"
2017-03-05 14:21:25 +01:00
# include "editor/editor_node.h"
# include "editor/editor_resource_preview.h"
2019-12-24 08:17:23 +01:00
# include "editor/editor_scale.h"
2022-08-01 20:01:48 +02:00
# include "editor/editor_settings.h"
# include "scene/gui/check_button.h"
# include "scene/gui/graph_edit.h"
# include "scene/gui/separator.h"
2022-01-19 19:59:12 +01:00
# include "scene/gui/view_panner.h"
2020-03-04 02:51:12 +01:00
# include "scene/main/window.h"
2016-08-03 00:11:05 +02:00
2016-08-15 09:54:02 +02:00
# ifdef TOOLS_ENABLED
2022-08-01 20:01:48 +02:00
void VisualScriptEditedProperty : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " set_edited_property " , " value " ) , & VisualScriptEditedProperty : : set_edited_property ) ;
ClassDB : : bind_method ( D_METHOD ( " get_edited_property " ) , & VisualScriptEditedProperty : : get_edited_property ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : NIL , " edited_property " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NIL_IS_VARIANT ) , " set_edited_property " , " get_edited_property " ) ;
}
void VisualScriptEditedProperty : : set_edited_property ( Variant p_variant ) {
edited_property = p_variant ;
}
Variant VisualScriptEditedProperty : : get_edited_property ( ) const {
return edited_property ;
}
/////////////////
2016-08-03 00:11:05 +02:00
class VisualScriptEditorSignalEdit : public Object {
2019-03-19 19:35:57 +01:00
GDCLASS ( VisualScriptEditorSignalEdit , Object ) ;
2016-08-03 00:11:05 +02:00
StringName sig ;
2017-03-05 16:44:50 +01:00
2016-08-03 00:11:05 +02:00
public :
UndoRedo * undo_redo ;
Ref < VisualScript > script ;
protected :
static void _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _sig_changed " , & VisualScriptEditorSignalEdit : : _sig_changed ) ;
2017-07-01 02:30:17 +02:00
ADD_SIGNAL ( MethodInfo ( " changed " ) ) ;
2016-08-03 00:11:05 +02:00
}
void _sig_changed ( ) {
2021-02-10 21:18:45 +01:00
notify_property_list_changed ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " changed " ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool _set ( const StringName & p_name , const Variant & p_value ) {
2020-05-14 16:41:43 +02:00
if ( sig = = StringName ( ) ) {
2016-08-03 00:11:05 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( p_name = = " argument_count " ) {
int new_argc = p_value ;
2016-08-03 00:11:05 +02:00
int argc = script - > custom_signal_get_argument_count ( sig ) ;
2020-05-14 16:41:43 +02:00
if ( argc = = new_argc ) {
2016-08-03 00:11:05 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Change Signal Arguments " ) ) ;
2016-08-03 00:11:05 +02:00
if ( new_argc < argc ) {
2017-03-05 16:44:50 +01:00
for ( int i = new_argc ; i < argc ; i + + ) {
undo_redo - > add_do_method ( script . ptr ( ) , " custom_signal_remove_argument " , sig , new_argc ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " custom_signal_add_argument " , sig , script - > custom_signal_get_argument_name ( sig , i ) , script - > custom_signal_get_argument_type ( sig , i ) , - 1 ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
} else if ( new_argc > argc ) {
for ( int i = argc ; i < new_argc ; i + + ) {
undo_redo - > add_do_method ( script . ptr ( ) , " custom_signal_add_argument " , sig , Variant : : NIL , " arg " + itos ( i + 1 ) , - 1 ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " custom_signal_remove_argument " , sig , argc ) ;
2016-08-03 00:11:05 +02:00
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _sig_changed " ) ;
undo_redo - > add_undo_method ( this , " _sig_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
if ( String ( p_name ) . begins_with ( " argument/ " ) ) {
2017-03-05 16:44:50 +01:00
int idx = String ( p_name ) . get_slice ( " / " , 1 ) . to_int ( ) - 1 ;
ERR_FAIL_INDEX_V ( idx , script - > custom_signal_get_argument_count ( sig ) , false ) ;
String what = String ( p_name ) . get_slice ( " / " , 2 ) ;
if ( what = = " type " ) {
int old_type = script - > custom_signal_get_argument_type ( sig , idx ) ;
int new_type = p_value ;
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Change Argument Type " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " custom_signal_set_argument_type " , sig , idx , new_type ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " custom_signal_set_argument_type " , sig , idx , old_type ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
2017-03-05 16:44:50 +01:00
if ( what = = " name " ) {
String old_name = script - > custom_signal_get_argument_name ( sig , idx ) ;
String new_name = p_value ;
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Change Argument name " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " custom_signal_set_argument_name " , sig , idx , new_name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " custom_signal_set_argument_name " , sig , idx , old_name ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
}
return false ;
}
2017-03-05 16:44:50 +01:00
bool _get ( const StringName & p_name , Variant & r_ret ) const {
2020-05-14 16:41:43 +02:00
if ( sig = = StringName ( ) ) {
2016-08-03 00:11:05 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( p_name = = " argument_count " ) {
2016-08-03 00:11:05 +02:00
r_ret = script - > custom_signal_get_argument_count ( sig ) ;
return true ;
}
if ( String ( p_name ) . begins_with ( " argument/ " ) ) {
2017-03-05 16:44:50 +01:00
int idx = String ( p_name ) . get_slice ( " / " , 1 ) . to_int ( ) - 1 ;
ERR_FAIL_INDEX_V ( idx , script - > custom_signal_get_argument_count ( sig ) , false ) ;
String what = String ( p_name ) . get_slice ( " / " , 2 ) ;
if ( what = = " type " ) {
r_ret = script - > custom_signal_get_argument_type ( sig , idx ) ;
2016-08-03 00:11:05 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
if ( what = = " name " ) {
r_ret = script - > custom_signal_get_argument_name ( sig , idx ) ;
2016-08-03 00:11:05 +02:00
return true ;
}
}
return false ;
}
2017-03-05 16:44:50 +01:00
void _get_property_list ( List < PropertyInfo > * p_list ) const {
2020-05-14 16:41:43 +02:00
if ( sig = = StringName ( ) ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " argument_count " , PROPERTY_HINT_RANGE , " 0,256 " ) ) ;
String argt = " Variant " ;
for ( int i = 1 ; i < Variant : : VARIANT_MAX ; i + + ) {
argt + = " , " + Variant : : get_type_name ( Variant : : Type ( i ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < script - > custom_signal_get_argument_count ( sig ) ; i + + ) {
p_list - > push_back ( PropertyInfo ( Variant : : INT , " argument/ " + itos ( i + 1 ) + " /type " , PROPERTY_HINT_ENUM , argt ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : STRING , " argument/ " + itos ( i + 1 ) + " /name " ) ) ;
2016-08-03 00:11:05 +02:00
}
}
public :
2017-03-05 16:44:50 +01:00
void edit ( const StringName & p_sig ) {
sig = p_sig ;
2021-02-10 21:18:45 +01:00
notify_property_list_changed ( ) ;
2016-08-03 00:11:05 +02:00
}
2020-04-02 01:20:12 +02:00
VisualScriptEditorSignalEdit ( ) { undo_redo = nullptr ; }
2016-08-03 00:11:05 +02:00
} ;
class VisualScriptEditorVariableEdit : public Object {
2019-03-19 19:35:57 +01:00
GDCLASS ( VisualScriptEditorVariableEdit , Object ) ;
2016-08-03 00:11:05 +02:00
StringName var ;
2017-03-05 16:44:50 +01:00
2016-08-03 00:11:05 +02:00
public :
UndoRedo * undo_redo ;
Ref < VisualScript > script ;
protected :
static void _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _var_changed " , & VisualScriptEditorVariableEdit : : _var_changed ) ;
ClassDB : : bind_method ( " _var_value_changed " , & VisualScriptEditorVariableEdit : : _var_value_changed ) ;
2017-07-01 02:30:17 +02:00
ADD_SIGNAL ( MethodInfo ( " changed " ) ) ;
2016-08-03 00:11:05 +02:00
}
void _var_changed ( ) {
2021-02-10 21:18:45 +01:00
notify_property_list_changed ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " changed " ) ) ;
2016-08-03 00:11:05 +02:00
}
void _var_value_changed ( ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " changed " ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool _set ( const StringName & p_name , const Variant & p_value ) {
2020-05-14 16:41:43 +02:00
if ( var = = StringName ( ) ) {
2016-08-03 00:11:05 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " value " ) {
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Set Variable Default Value " ) ) ;
2017-03-05 16:44:50 +01:00
Variant current = script - > get_variable_default_value ( var ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " set_variable_default_value " , var , p_value ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_variable_default_value " , var , current ) ;
undo_redo - > add_do_method ( this , " _var_value_changed " ) ;
undo_redo - > add_undo_method ( this , " _var_value_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
2017-03-05 16:44:50 +01:00
Dictionary d = script - > call ( " get_variable_info " , var ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " type " ) {
2017-12-17 23:07:15 +01:00
Dictionary dc = d . duplicate ( ) ;
2017-03-05 16:44:50 +01:00
dc [ " type " ] = p_value ;
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Set Variable Type " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " set_variable_info " , var , dc ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_variable_info " , var , d ) ;
2021-01-04 19:10:04 +01:00
// Setting the default value.
Variant : : Type type = ( Variant : : Type ) ( int ) p_value ;
if ( type ! = Variant : : NIL ) {
Variant default_value ;
Callable : : CallError ce ;
Variant : : construct ( type , default_value , nullptr , 0 , ce ) ;
if ( ce . error = = Callable : : CallError : : CALL_OK ) {
undo_redo - > add_do_method ( script . ptr ( ) , " set_variable_default_value " , var , default_value ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_variable_default_value " , var , dc [ " value " ] ) ;
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _var_changed " ) ;
undo_redo - > add_undo_method ( this , " _var_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " hint " ) {
2017-12-17 23:07:15 +01:00
Dictionary dc = d . duplicate ( ) ;
2017-03-05 16:44:50 +01:00
dc [ " hint " ] = p_value ;
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Set Variable Type " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " set_variable_info " , var , dc ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_variable_info " , var , d ) ;
undo_redo - > add_do_method ( this , " _var_changed " ) ;
undo_redo - > add_undo_method ( this , " _var_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " hint_string " ) {
2017-12-17 23:07:15 +01:00
Dictionary dc = d . duplicate ( ) ;
2017-03-05 16:44:50 +01:00
dc [ " hint_string " ] = p_value ;
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Set Variable Type " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " set_variable_info " , var , dc ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_variable_info " , var , d ) ;
undo_redo - > add_do_method ( this , " _var_changed " ) ;
undo_redo - > add_undo_method ( this , " _var_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
return true ;
}
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " export " ) {
script - > set_variable_export ( var , p_value ) ;
2021-11-17 21:08:55 +01:00
InspectorDock : : get_inspector_singleton ( ) - > update_tree ( ) ;
2016-08-31 04:44:14 +02:00
return true ;
}
2016-08-03 00:11:05 +02:00
return false ;
}
2017-03-05 16:44:50 +01:00
bool _get ( const StringName & p_name , Variant & r_ret ) const {
2020-05-14 16:41:43 +02:00
if ( var = = StringName ( ) ) {
2016-08-03 00:11:05 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " value " ) {
r_ret = script - > get_variable_default_value ( var ) ;
2016-08-03 00:11:05 +02:00
return true ;
}
PropertyInfo pinfo = script - > get_variable_info ( var ) ;
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " type " ) {
r_ret = pinfo . type ;
2016-08-03 00:11:05 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " hint " ) {
r_ret = pinfo . hint ;
2016-08-03 00:11:05 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " hint_string " ) {
r_ret = pinfo . hint_string ;
2016-08-03 00:11:05 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
if ( String ( p_name ) = = " export " ) {
r_ret = script - > get_variable_export ( var ) ;
2016-08-31 04:44:14 +02:00
return true ;
}
2016-08-03 00:11:05 +02:00
return false ;
}
2017-03-05 16:44:50 +01:00
void _get_property_list ( List < PropertyInfo > * p_list ) const {
2020-05-14 16:41:43 +02:00
if ( var = = StringName ( ) ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
String argt = " Variant " ;
for ( int i = 1 ; i < Variant : : VARIANT_MAX ; i + + ) {
argt + = " , " + Variant : : get_type_name ( Variant : : Type ( i ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " type " , PROPERTY_HINT_ENUM , argt ) ) ;
p_list - > push_back ( PropertyInfo ( script - > get_variable_info ( var ) . type , " value " , script - > get_variable_info ( var ) . hint , script - > get_variable_info ( var ) . hint_string , PROPERTY_USAGE_DEFAULT ) ) ;
2020-06-17 17:39:25 +02:00
// Update this when PropertyHint changes.
2018-09-08 11:51:23 +02:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " hint " , PROPERTY_HINT_ENUM , " None,Range,ExpRange,Enum,ExpEasing,Length,SpriteFrame,KeyAccel,Flags,Layers2dRender,Layers2dPhysics,Layer3dRender,Layer3dPhysics,File,Dir,GlobalFile,GlobalDir,ResourceType,MultilineText,PlaceholderText,ColorNoAlpha,ImageCompressLossy,ImageCompressLossLess,ObjectId,String,NodePathToEditedNode,MethodOfVariantType,MethodOfBaseType,MethodOfInstance,MethodOfScript,PropertyOfVariantType,PropertyOfBaseType,PropertyOfInstance,PropertyOfScript,ObjectTooBig,NodePathValidTypes " ) ) ;
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : STRING , " hint_string " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " export " ) ) ;
2016-08-03 00:11:05 +02:00
}
public :
2017-03-05 16:44:50 +01:00
void edit ( const StringName & p_var ) {
var = p_var ;
2021-02-10 21:18:45 +01:00
notify_property_list_changed ( ) ;
2016-08-03 00:11:05 +02:00
}
2020-04-02 01:20:12 +02:00
VisualScriptEditorVariableEdit ( ) { undo_redo = nullptr ; }
2016-08-03 00:11:05 +02:00
} ;
2017-10-03 04:31:32 +02:00
static Color _color_from_type ( Variant : : Type p_type , bool dark_theme = true ) {
2016-08-03 00:11:05 +02:00
Color color ;
2020-05-14 16:41:43 +02:00
if ( dark_theme ) {
2017-10-03 04:31:32 +02:00
switch ( p_type ) {
2020-05-10 13:00:47 +02:00
case Variant : : NIL :
color = Color ( 0.41 , 0.93 , 0.74 ) ;
break ;
case Variant : : BOOL :
color = Color ( 0.55 , 0.65 , 0.94 ) ;
break ;
case Variant : : INT :
color = Color ( 0.49 , 0.78 , 0.94 ) ;
break ;
case Variant : : FLOAT :
color = Color ( 0.38 , 0.85 , 0.96 ) ;
break ;
case Variant : : STRING :
color = Color ( 0.42 , 0.65 , 0.93 ) ;
break ;
case Variant : : VECTOR2 :
color = Color ( 0.74 , 0.57 , 0.95 ) ;
break ;
case Variant : : VECTOR2I :
color = Color ( 0.74 , 0.57 , 0.95 ) ;
break ;
case Variant : : RECT2 :
color = Color ( 0.95 , 0.57 , 0.65 ) ;
break ;
case Variant : : RECT2I :
color = Color ( 0.95 , 0.57 , 0.65 ) ;
break ;
case Variant : : VECTOR3 :
color = Color ( 0.84 , 0.49 , 0.93 ) ;
break ;
case Variant : : VECTOR3I :
color = Color ( 0.84 , 0.49 , 0.93 ) ;
break ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
case Variant : : VECTOR4 :
color = Color ( 0.84 , 0.49 , 0.94 ) ;
break ;
case Variant : : VECTOR4I :
color = Color ( 0.84 , 0.49 , 0.94 ) ;
break ;
2020-05-10 13:00:47 +02:00
case Variant : : TRANSFORM2D :
color = Color ( 0.77 , 0.93 , 0.41 ) ;
break ;
case Variant : : PLANE :
color = Color ( 0.97 , 0.44 , 0.44 ) ;
break ;
2021-01-20 08:02:02 +01:00
case Variant : : QUATERNION :
2020-05-10 13:00:47 +02:00
color = Color ( 0.93 , 0.41 , 0.64 ) ;
break ;
case Variant : : AABB :
color = Color ( 0.93 , 0.47 , 0.57 ) ;
break ;
case Variant : : BASIS :
color = Color ( 0.89 , 0.93 , 0.41 ) ;
break ;
2021-04-28 09:36:08 +02:00
case Variant : : TRANSFORM3D :
2020-05-10 13:00:47 +02:00
color = Color ( 0.96 , 0.66 , 0.43 ) ;
break ;
case Variant : : COLOR :
color = Color ( 0.62 , 1.0 , 0.44 ) ;
break ;
case Variant : : NODE_PATH :
color = Color ( 0.41 , 0.58 , 0.93 ) ;
break ;
2020-11-09 14:53:05 +01:00
case Variant : : RID :
2020-05-10 13:00:47 +02:00
color = Color ( 0.41 , 0.93 , 0.6 ) ;
break ;
case Variant : : OBJECT :
color = Color ( 0.47 , 0.95 , 0.91 ) ;
break ;
case Variant : : DICTIONARY :
color = Color ( 0.47 , 0.93 , 0.69 ) ;
break ;
case Variant : : ARRAY :
color = Color ( 0.88 , 0.88 , 0.88 ) ;
break ;
case Variant : : PACKED_BYTE_ARRAY :
color = Color ( 0.67 , 0.96 , 0.78 ) ;
break ;
case Variant : : PACKED_INT32_ARRAY :
color = Color ( 0.69 , 0.86 , 0.96 ) ;
break ;
case Variant : : PACKED_FLOAT32_ARRAY :
color = Color ( 0.59 , 0.91 , 0.97 ) ;
break ;
case Variant : : PACKED_INT64_ARRAY :
color = Color ( 0.69 , 0.86 , 0.96 ) ;
break ;
case Variant : : PACKED_FLOAT64_ARRAY :
color = Color ( 0.59 , 0.91 , 0.97 ) ;
break ;
case Variant : : PACKED_STRING_ARRAY :
color = Color ( 0.62 , 0.77 , 0.95 ) ;
break ;
case Variant : : PACKED_VECTOR2_ARRAY :
color = Color ( 0.82 , 0.7 , 0.96 ) ;
break ;
case Variant : : PACKED_VECTOR3_ARRAY :
color = Color ( 0.87 , 0.61 , 0.95 ) ;
break ;
case Variant : : PACKED_COLOR_ARRAY :
color = Color ( 0.91 , 1.0 , 0.59 ) ;
break ;
2017-10-03 04:31:32 +02:00
default :
color . set_hsv ( p_type / float ( Variant : : VARIANT_MAX ) , 0.7 , 0.7 ) ;
}
2020-05-14 16:41:43 +02:00
} else {
2017-10-03 04:31:32 +02:00
switch ( p_type ) {
2020-05-10 13:00:47 +02:00
case Variant : : NIL :
color = Color ( 0.15 , 0.89 , 0.63 ) ;
break ;
case Variant : : BOOL :
color = Color ( 0.43 , 0.56 , 0.92 ) ;
break ;
case Variant : : INT :
color = Color ( 0.31 , 0.7 , 0.91 ) ;
break ;
case Variant : : FLOAT :
color = Color ( 0.15 , 0.8 , 0.94 ) ;
break ;
case Variant : : STRING :
color = Color ( 0.27 , 0.56 , 0.91 ) ;
break ;
case Variant : : VECTOR2 :
color = Color ( 0.68 , 0.46 , 0.93 ) ;
break ;
case Variant : : VECTOR2I :
color = Color ( 0.68 , 0.46 , 0.93 ) ;
break ;
case Variant : : RECT2 :
color = Color ( 0.93 , 0.46 , 0.56 ) ;
break ;
case Variant : : RECT2I :
color = Color ( 0.93 , 0.46 , 0.56 ) ;
break ;
case Variant : : VECTOR3 :
color = Color ( 0.86 , 0.42 , 0.93 ) ;
break ;
case Variant : : VECTOR3I :
color = Color ( 0.86 , 0.42 , 0.93 ) ;
break ;
case Variant : : TRANSFORM2D :
color = Color ( 0.59 , 0.81 , 0.1 ) ;
break ;
case Variant : : PLANE :
color = Color ( 0.97 , 0.44 , 0.44 ) ;
break ;
2021-01-20 08:02:02 +01:00
case Variant : : QUATERNION :
2020-05-10 13:00:47 +02:00
color = Color ( 0.93 , 0.41 , 0.64 ) ;
break ;
case Variant : : AABB :
color = Color ( 0.93 , 0.47 , 0.57 ) ;
break ;
case Variant : : BASIS :
color = Color ( 0.7 , 0.73 , 0.1 ) ;
break ;
2021-04-28 09:36:08 +02:00
case Variant : : TRANSFORM3D :
2020-05-10 13:00:47 +02:00
color = Color ( 0.96 , 0.56 , 0.28 ) ;
break ;
case Variant : : COLOR :
color = Color ( 0.24 , 0.75 , 0.0 ) ;
break ;
case Variant : : NODE_PATH :
color = Color ( 0.41 , 0.58 , 0.93 ) ;
break ;
2020-11-09 14:53:05 +01:00
case Variant : : RID :
2020-05-10 13:00:47 +02:00
color = Color ( 0.17 , 0.9 , 0.45 ) ;
break ;
case Variant : : OBJECT :
color = Color ( 0.07 , 0.84 , 0.76 ) ;
break ;
case Variant : : DICTIONARY :
color = Color ( 0.34 , 0.91 , 0.62 ) ;
break ;
case Variant : : ARRAY :
color = Color ( 0.45 , 0.45 , 0.45 ) ;
break ;
case Variant : : PACKED_BYTE_ARRAY :
color = Color ( 0.38 , 0.92 , 0.6 ) ;
break ;
case Variant : : PACKED_INT32_ARRAY :
color = Color ( 0.38 , 0.73 , 0.92 ) ;
break ;
case Variant : : PACKED_FLOAT32_ARRAY :
color = Color ( 0.25 , 0.83 , 0.95 ) ;
break ;
case Variant : : PACKED_INT64_ARRAY :
color = Color ( 0.38 , 0.73 , 0.92 ) ;
break ;
case Variant : : PACKED_FLOAT64_ARRAY :
color = Color ( 0.25 , 0.83 , 0.95 ) ;
break ;
case Variant : : PACKED_STRING_ARRAY :
color = Color ( 0.38 , 0.62 , 0.92 ) ;
break ;
case Variant : : PACKED_VECTOR2_ARRAY :
color = Color ( 0.62 , 0.36 , 0.92 ) ;
break ;
case Variant : : PACKED_VECTOR3_ARRAY :
color = Color ( 0.79 , 0.35 , 0.92 ) ;
break ;
case Variant : : PACKED_COLOR_ARRAY :
color = Color ( 0.57 , 0.73 , 0.0 ) ;
break ;
2017-10-03 04:31:32 +02:00
default :
color . set_hsv ( p_type / float ( Variant : : VARIANT_MAX ) , 0.3 , 0.3 ) ;
}
2020-05-14 16:41:43 +02:00
}
2017-10-03 04:31:32 +02:00
2016-08-03 00:11:05 +02:00
return color ;
}
void VisualScriptEditor : : _update_graph_connections ( ) {
graph - > clear_connections ( ) ;
2020-06-17 17:39:25 +02:00
List < VisualScript : : SequenceConnection > sequence_conns ;
script - > get_sequence_connection_list ( & sequence_conns ) ;
2016-08-03 00:11:05 +02:00
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : SequenceConnection & E : sequence_conns ) {
2021-07-16 05:45:57 +02:00
graph - > connect_node ( itos ( E . from_node ) , E . from_output , itos ( E . to_node ) , 0 ) ;
2016-08-03 00:11:05 +02:00
}
2020-06-17 17:39:25 +02:00
List < VisualScript : : DataConnection > data_conns ;
script - > get_data_connection_list ( & data_conns ) ;
2019-09-13 21:14:12 +02:00
2021-07-16 05:45:57 +02:00
for ( VisualScript : : DataConnection & dc : data_conns ) {
Ref < VisualScriptNode > from_node = script - > get_node ( dc . from_node ) ;
Ref < VisualScriptNode > to_node = script - > get_node ( dc . to_node ) ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
if ( to_node - > has_input_sequence_port ( ) ) {
dc . to_port + + ;
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
dc . from_port + = from_node - > get_output_sequence_port_count ( ) ;
2016-08-03 00:11:05 +02:00
2021-07-16 05:45:57 +02:00
graph - > connect_node ( itos ( dc . from_node ) , dc . from_port , itos ( dc . to_node ) , dc . to_port ) ;
2016-08-03 00:11:05 +02:00
}
}
void VisualScriptEditor : : _update_graph ( int p_only_id ) {
2020-05-14 16:41:43 +02:00
if ( updating_graph ) {
2016-08-25 22:45:20 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
updating_graph = true ;
2016-08-07 00:00:54 +02:00
2016-08-03 00:11:05 +02:00
//byebye all nodes
2017-03-05 16:44:50 +01:00
if ( p_only_id > = 0 ) {
2016-08-03 00:11:05 +02:00
if ( graph - > has_node ( itos ( p_only_id ) ) ) {
2017-03-05 16:44:50 +01:00
Node * gid = graph - > get_node ( itos ( p_only_id ) ) ;
2020-05-14 16:41:43 +02:00
if ( gid ) {
2016-08-03 00:11:05 +02:00
memdelete ( gid ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
}
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ) {
2016-08-03 00:11:05 +02:00
memdelete ( graph - > get_child ( i ) ) ;
i - - ;
}
}
}
2016-08-03 16:28:20 +02:00
graph - > show ( ) ;
select_func_text - > hide ( ) ;
2016-08-03 00:11:05 +02:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > type_icons [ Variant : : VARIANT_MAX ] = {
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " Variant " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " bool " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " int " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " float " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " String " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector2 " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector2i " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Rect2 " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Rect2i " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector3 " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector3i " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Transform2D " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Plane " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Quaternion " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " AABB " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Basis " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Transform3D " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Color " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-20 21:31:36 +02:00
Control : : get_theme_icon ( SNAME ( " StringName " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " NodePath " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " RID " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " MiniObject " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Callable " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Signal " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Dictionary " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Array " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedByteArray " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedInt32Array " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-20 21:31:36 +02:00
Control : : get_theme_icon ( SNAME ( " PackedInt64Array " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " PackedFloat32Array " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-20 21:31:36 +02:00
Control : : get_theme_icon ( SNAME ( " PackedFloat64Array " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " PackedStringArray " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedVector2Array " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedVector3Array " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedColorArray " ) , SNAME ( " EditorIcons " ) )
2016-08-03 00:11:05 +02:00
} ;
2022-04-30 03:56:57 +02:00
// Visual script specific theme for MSDF font.
Ref < Theme > vstheme ;
vstheme . instantiate ( ) ;
Ref < Font > label_font = EditorNode : : get_singleton ( ) - > get_editor_theme ( ) - > get_font ( " main_msdf " , " EditorFonts " ) ;
vstheme - > set_font ( " font " , " Label " , label_font ) ;
vstheme - > set_font ( " font " , " LineEdit " , label_font ) ;
vstheme - > set_font ( " font " , " Button " , label_font ) ;
2021-07-17 23:22:52 +02:00
Ref < Texture2D > seq_port = Control : : get_theme_icon ( SNAME ( " VisualShaderPort " ) , SNAME ( " EditorIcons " ) ) ;
2020-06-17 17:39:25 +02:00
List < int > node_ids ;
script - > get_node_list ( & node_ids ) ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
List < int > ids ;
script - > get_node_list ( & ids ) ;
2016-08-03 00:11:05 +02:00
2021-07-16 05:45:57 +02:00
for ( int & E : ids ) {
if ( p_only_id > = 0 & & p_only_id ! = E ) {
2020-06-17 17:39:25 +02:00
continue ;
}
2016-08-03 00:11:05 +02:00
2021-07-16 05:45:57 +02:00
Ref < VisualScriptNode > node = script - > get_node ( E ) ;
Vector2 pos = script - > get_node_position ( E ) ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
GraphNode * gnode = memnew ( GraphNode ) ;
gnode - > set_title ( node - > get_caption ( ) ) ;
gnode - > set_position_offset ( pos * EDSCALE ) ;
2021-07-16 05:45:57 +02:00
if ( error_line = = E ) {
2020-06-17 17:39:25 +02:00
gnode - > set_overlay ( GraphNode : : OVERLAY_POSITION ) ;
} else if ( node - > is_breakpoint ( ) ) {
gnode - > set_overlay ( GraphNode : : OVERLAY_BREAKPOINT ) ;
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
gnode - > set_meta ( " __vnode " , node ) ;
2021-07-16 05:45:57 +02:00
gnode - > set_name ( itos ( E ) ) ;
2022-07-28 22:56:41 +02:00
gnode - > connect ( " dragged " , callable_mp ( this , & VisualScriptEditor : : _node_moved ) . bind ( E ) ) ;
gnode - > connect ( " close_request " , callable_mp ( this , & VisualScriptEditor : : _remove_node ) . bind ( E ) , CONNECT_DEFERRED ) ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
{
Ref < VisualScriptFunction > v = node ;
if ( ! v . is_valid ( ) ) {
2019-09-13 21:14:12 +02:00
gnode - > set_show_close_button ( true ) ;
}
2020-06-17 17:39:25 +02:00
}
2016-09-07 01:34:24 +02:00
2020-06-17 17:39:25 +02:00
bool has_gnode_text = false ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > nd_list = node ;
bool is_vslist = nd_list . is_valid ( ) ;
if ( is_vslist ) {
HBoxContainer * hbnc = memnew ( HBoxContainer ) ;
if ( nd_list - > is_input_port_editable ( ) ) {
has_gnode_text = true ;
Button * btn = memnew ( Button ) ;
btn - > set_text ( TTR ( " Add Input Port " ) ) ;
hbnc - > add_child ( btn ) ;
2022-07-28 22:56:41 +02:00
btn - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _add_input_port ) . bind ( E ) , CONNECT_DEFERRED ) ;
2020-06-17 17:39:25 +02:00
}
if ( nd_list - > is_output_port_editable ( ) ) {
2019-09-13 21:14:12 +02:00
if ( nd_list - > is_input_port_editable ( ) ) {
2020-06-17 17:39:25 +02:00
hbnc - > add_spacer ( ) ;
2019-09-13 21:14:12 +02:00
}
2018-04-30 01:28:31 +02:00
has_gnode_text = true ;
2020-06-17 17:39:25 +02:00
Button * btn = memnew ( Button ) ;
btn - > set_text ( TTR ( " Add Output Port " ) ) ;
hbnc - > add_child ( btn ) ;
2022-07-28 22:56:41 +02:00
btn - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _add_output_port ) . bind ( E ) , CONNECT_DEFERRED ) ;
2018-04-30 01:28:31 +02:00
}
2020-06-17 17:39:25 +02:00
gnode - > add_child ( hbnc ) ;
} else if ( Object : : cast_to < VisualScriptExpression > ( node . ptr ( ) ) ) {
has_gnode_text = true ;
LineEdit * line_edit = memnew ( LineEdit ) ;
line_edit - > set_text ( node - > get_text ( ) ) ;
2021-03-28 20:31:25 +02:00
line_edit - > set_expand_to_text_length_enabled ( true ) ;
2022-02-08 10:14:58 +01:00
line_edit - > add_theme_font_override ( " font " , get_theme_font ( SNAME ( " source " ) , SNAME ( " EditorFonts " ) ) ) ;
2020-06-17 17:39:25 +02:00
gnode - > add_child ( line_edit ) ;
2022-07-28 22:56:41 +02:00
line_edit - > connect ( " text_changed " , callable_mp ( this , & VisualScriptEditor : : _expression_text_changed ) . bind ( E ) ) ;
2020-06-17 17:39:25 +02:00
} else {
String text = node - > get_text ( ) ;
if ( ! text . is_empty ( ) ) {
has_gnode_text = true ;
Label * label = memnew ( Label ) ;
label - > set_text ( text ) ;
gnode - > add_child ( label ) ;
2017-09-14 07:45:00 +02:00
}
2020-06-17 17:39:25 +02:00
}
2017-09-14 07:45:00 +02:00
2020-06-17 17:39:25 +02:00
if ( Object : : cast_to < VisualScriptComment > ( node . ptr ( ) ) ) {
Ref < VisualScriptComment > vsc = node ;
gnode - > set_comment ( true ) ;
gnode - > set_resizable ( true ) ;
gnode - > set_custom_minimum_size ( vsc - > get_size ( ) * EDSCALE ) ;
2022-07-28 22:56:41 +02:00
gnode - > connect ( " resize_request " , callable_mp ( this , & VisualScriptEditor : : _comment_node_resized ) . bind ( E ) ) ;
2020-06-17 17:39:25 +02:00
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
if ( node_styles . has ( node - > get_category ( ) ) ) {
Ref < StyleBoxFlat > sbf = node_styles [ node - > get_category ( ) ] ;
if ( gnode - > is_comment ( ) ) {
2021-07-17 23:22:52 +02:00
sbf = EditorNode : : get_singleton ( ) - > get_theme_base ( ) - > get_theme ( ) - > get_stylebox ( SNAME ( " comment " ) , SNAME ( " GraphNode " ) ) ;
2020-06-17 17:39:25 +02:00
}
Color c = sbf - > get_border_color ( ) ;
2021-06-06 19:58:27 +02:00
c = ( ( c . r + c . g + c . b ) / 3 ) < 0.7 ? Color ( 1.0 , 1.0 , 1.0 , 0.85 ) : Color ( 0.0 , 0.0 , 0.0 , 0.85 ) ;
2020-06-17 17:39:25 +02:00
Color ic = c ;
2022-02-08 10:14:58 +01:00
gnode - > add_theme_color_override ( " title_color " , c ) ;
2019-03-23 01:57:28 +01:00
c . a = 1 ;
2022-02-08 10:14:58 +01:00
gnode - > add_theme_color_override ( " close_color " , c ) ;
gnode - > add_theme_color_override ( " resizer_color " , ic ) ;
gnode - > add_theme_style_override ( " frame " , sbf ) ;
2020-06-17 17:39:25 +02:00
}
2016-08-03 00:11:05 +02:00
2021-07-17 23:22:52 +02:00
const Color mono_color = get_theme_color ( SNAME ( " mono_color " ) , SNAME ( " Editor " ) ) ;
2016-09-02 01:04:17 +02:00
2020-06-17 17:39:25 +02:00
int slot_idx = 0 ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
bool single_seq_output = node - > get_output_sequence_port_count ( ) = = 1 & & node - > get_output_sequence_port_text ( 0 ) = = String ( ) ;
if ( ( node - > has_input_sequence_port ( ) | | single_seq_output ) | | has_gnode_text ) {
// IF has_gnode_text is true BUT we have no sequence ports to draw (in here),
// we still draw the disabled default ones to shift up the slots by one,
// so the slots DON'T start with the content text.
2016-09-02 01:04:17 +02:00
2020-06-17 17:39:25 +02:00
// IF has_gnode_text is false, but we DO want to draw default sequence ports,
// we draw a dummy text to take up the position of the sequence nodes, so all the other ports are still aligned correctly.
if ( ! has_gnode_text ) {
Label * dummy = memnew ( Label ) ;
dummy - > set_text ( " " ) ;
gnode - > add_child ( dummy ) ;
2016-08-03 00:11:05 +02:00
}
2020-06-17 17:39:25 +02:00
gnode - > set_slot ( 0 , node - > has_input_sequence_port ( ) , TYPE_SEQUENCE , mono_color , single_seq_output , TYPE_SEQUENCE , mono_color , seq_port , seq_port ) ;
slot_idx + + ;
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
int mixed_seq_ports = 0 ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
if ( ! single_seq_output ) {
if ( node - > has_mixed_input_and_sequence_ports ( ) ) {
mixed_seq_ports = node - > get_output_sequence_port_count ( ) ;
} else {
for ( int i = 0 ; i < node - > get_output_sequence_port_count ( ) ; i + + ) {
Label * text2 = memnew ( Label ) ;
text2 - > set_text ( node - > get_output_sequence_port_text ( i ) ) ;
2021-11-25 03:58:47 +01:00
text2 - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_RIGHT ) ;
2020-06-17 17:39:25 +02:00
gnode - > add_child ( text2 ) ;
gnode - > set_slot ( slot_idx , false , 0 , Color ( ) , true , TYPE_SEQUENCE , mono_color , seq_port , seq_port ) ;
slot_idx + + ;
2019-09-13 21:14:12 +02:00
}
2016-08-03 00:11:05 +02:00
}
2020-06-17 17:39:25 +02:00
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
for ( int i = 0 ; i < MAX ( node - > get_output_value_port_count ( ) , MAX ( mixed_seq_ports , node - > get_input_value_port_count ( ) ) ) ; i + + ) {
bool left_ok = false ;
Variant : : Type left_type = Variant : : NIL ;
String left_name ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
if ( i < node - > get_input_value_port_count ( ) ) {
PropertyInfo pi = node - > get_input_value_port_info ( i ) ;
left_ok = true ;
left_type = pi . type ;
left_name = pi . name ;
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
bool right_ok = false ;
Variant : : Type right_type = Variant : : NIL ;
String right_name ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
if ( i > = mixed_seq_ports & & i < node - > get_output_value_port_count ( ) + mixed_seq_ports ) {
PropertyInfo pi = node - > get_output_value_port_info ( i - mixed_seq_ports ) ;
right_ok = true ;
right_type = pi . type ;
right_name = pi . name ;
}
VBoxContainer * vbc = memnew ( VBoxContainer ) ;
HBoxContainer * hbc = memnew ( HBoxContainer ) ;
HBoxContainer * hbc2 = memnew ( HBoxContainer ) ;
vbc - > add_child ( hbc ) ;
vbc - > add_child ( hbc2 ) ;
if ( left_ok ) {
Ref < Texture2D > t ;
if ( left_type > = 0 & & left_type < Variant : : VARIANT_MAX ) {
t = type_icons [ left_type ] ;
}
if ( t . is_valid ( ) ) {
TextureRect * tf = memnew ( TextureRect ) ;
tf - > set_texture ( t ) ;
tf - > set_stretch_mode ( TextureRect : : STRETCH_KEEP_CENTERED ) ;
hbc - > add_child ( tf ) ;
2016-08-03 00:11:05 +02:00
}
2016-08-26 22:34:25 +02:00
2020-06-17 17:39:25 +02:00
if ( is_vslist ) {
if ( nd_list - > is_input_port_name_editable ( ) ) {
LineEdit * name_box = memnew ( LineEdit ) ;
hbc - > add_child ( name_box ) ;
name_box - > set_custom_minimum_size ( Size2 ( 60 * EDSCALE , 0 ) ) ;
name_box - > set_text ( left_name ) ;
2021-03-28 20:31:25 +02:00
name_box - > set_expand_to_text_length_enabled ( true ) ;
2022-07-28 22:56:41 +02:00
name_box - > connect ( " resized " , callable_mp ( this , & VisualScriptEditor : : _update_node_size ) . bind ( E ) ) ;
name_box - > connect ( " focus_exited " , callable_mp ( this , & VisualScriptEditor : : _port_name_focus_out ) . bind ( name_box , E , i , true ) ) ;
2019-09-13 21:14:12 +02:00
} else {
hbc - > add_child ( memnew ( Label ( left_name ) ) ) ;
2016-08-04 03:06:39 +02:00
}
2020-06-17 17:39:25 +02:00
if ( nd_list - > is_input_port_type_editable ( ) ) {
OptionButton * opbtn = memnew ( OptionButton ) ;
for ( int j = Variant : : NIL ; j < Variant : : VARIANT_MAX ; j + + ) {
opbtn - > add_item ( Variant : : get_type_name ( Variant : : Type ( j ) ) ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
opbtn - > select ( left_type ) ;
opbtn - > set_custom_minimum_size ( Size2 ( 100 * EDSCALE , 0 ) ) ;
hbc - > add_child ( opbtn ) ;
2022-07-28 22:56:41 +02:00
opbtn - > connect ( " item_selected " , callable_mp ( this , & VisualScriptEditor : : _change_port_type ) . bind ( E , i , true ) , CONNECT_DEFERRED ) ;
2016-08-26 22:34:25 +02:00
}
2020-06-17 17:39:25 +02:00
Button * rmbtn = memnew ( Button ) ;
2021-07-17 23:22:52 +02:00
rmbtn - > set_icon ( EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-06-17 17:39:25 +02:00
hbc - > add_child ( rmbtn ) ;
2022-07-28 22:56:41 +02:00
rmbtn - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _remove_input_port ) . bind ( E , i ) , CONNECT_DEFERRED ) ;
2019-09-13 21:14:12 +02:00
} else {
2020-06-17 17:39:25 +02:00
hbc - > add_child ( memnew ( Label ( left_name ) ) ) ;
2016-08-04 03:06:39 +02:00
}
2016-08-03 00:11:05 +02:00
2021-07-16 05:45:57 +02:00
if ( left_type ! = Variant : : NIL & & ! script - > is_input_value_port_connected ( E , i ) ) {
2020-06-17 17:39:25 +02:00
PropertyInfo pi = node - > get_input_value_port_info ( i ) ;
Button * button = memnew ( Button ) ;
Variant value = node - > get_default_input_value ( i ) ;
if ( value . get_type ( ) ! = left_type ) {
//different type? for now convert
//not the same, reconvert
Callable : : CallError ce ;
const Variant * existingp = & value ;
Variant : : construct ( left_type , value , & existingp , 1 , ce ) ;
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
if ( left_type = = Variant : : COLOR ) {
button - > set_custom_minimum_size ( Size2 ( 30 , 0 ) * EDSCALE ) ;
2022-07-28 22:56:41 +02:00
button - > connect ( " draw " , callable_mp ( this , & VisualScriptEditor : : _draw_color_over_button ) . bind ( button , value ) ) ;
2020-06-17 17:39:25 +02:00
} else if ( left_type = = Variant : : OBJECT & & Ref < Resource > ( value ) . is_valid ( ) ) {
Ref < Resource > res = value ;
Array arr ;
arr . push_back ( button - > get_instance_id ( ) ) ;
arr . push_back ( String ( value ) ) ;
EditorResourcePreview : : get_singleton ( ) - > queue_edited_resource_preview ( res , this , " _button_resource_previewed " , arr ) ;
} else if ( pi . type = = Variant : : INT & & pi . hint = = PROPERTY_HINT_ENUM ) {
2022-03-06 18:04:29 +01:00
bool found = false ;
const Vector < String > options = pi . hint_string . split ( " , " ) ;
int64_t current_val = 0 ;
for ( const String & option : options ) {
Vector < String > text_split = option . split ( " : " ) ;
if ( text_split . size ( ) ! = 1 ) {
current_val = text_split [ 1 ] . to_int ( ) ;
}
if ( value . operator int ( ) = = current_val ) {
button - > set_text ( text_split [ 0 ] ) ;
found = true ;
break ;
}
current_val + = 1 ;
}
if ( ! found ) {
button - > set_text ( value ) ;
}
} else if ( pi . type = = Variant : : INT & & pi . hint = = PROPERTY_HINT_FLAGS ) {
Vector < String > value_texts ;
const Vector < String > options = pi . hint_string . split ( " , " ) ;
uint32_t v = value ;
for ( const String & option : options ) {
uint32_t current_val ;
Vector < String > text_split = option . split ( " : " ) ;
if ( text_split . size ( ) ! = - 1 ) {
current_val = text_split [ 1 ] . to_int ( ) ;
} else {
current_val = 1 < < i ;
}
if ( ( v & current_val ) = = current_val ) {
value_texts . push_back ( text_split [ 0 ] ) ;
}
}
if ( value_texts . size ( ) ! = 0 ) {
String value_text = value_texts [ 0 ] ;
for ( const String & text : value_texts ) {
value_text + = " | " + text ;
}
button - > set_text ( value_text ) ;
} else {
button - > set_text ( value ) ;
}
2020-06-17 17:39:25 +02:00
} else {
button - > set_text ( value ) ;
}
2022-07-28 22:56:41 +02:00
button - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _default_value_edited ) . bind ( button , E , i ) ) ;
2020-06-17 17:39:25 +02:00
hbc2 - > add_child ( button ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
} else {
Control * c = memnew ( Control ) ;
c - > set_custom_minimum_size ( Size2 ( 10 , 0 ) * EDSCALE ) ;
hbc - > add_child ( c ) ;
}
2016-09-02 01:04:17 +02:00
2020-06-17 17:39:25 +02:00
hbc - > add_spacer ( ) ;
hbc2 - > add_spacer ( ) ;
if ( i < mixed_seq_ports ) {
Label * text2 = memnew ( Label ) ;
text2 - > set_text ( node - > get_output_sequence_port_text ( i ) ) ;
2021-11-25 03:58:47 +01:00
text2 - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_RIGHT ) ;
2020-06-17 17:39:25 +02:00
hbc - > add_child ( text2 ) ;
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
if ( right_ok ) {
if ( is_vslist ) {
Button * rmbtn = memnew ( Button ) ;
2021-07-17 23:22:52 +02:00
rmbtn - > set_icon ( EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-06-17 17:39:25 +02:00
hbc - > add_child ( rmbtn ) ;
2022-07-28 22:56:41 +02:00
rmbtn - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _remove_output_port ) . bind ( E , i ) , CONNECT_DEFERRED ) ;
2020-06-17 17:39:25 +02:00
if ( nd_list - > is_output_port_type_editable ( ) ) {
OptionButton * opbtn = memnew ( OptionButton ) ;
for ( int j = Variant : : NIL ; j < Variant : : VARIANT_MAX ; j + + ) {
opbtn - > add_item ( Variant : : get_type_name ( Variant : : Type ( j ) ) ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
opbtn - > select ( right_type ) ;
opbtn - > set_custom_minimum_size ( Size2 ( 100 * EDSCALE , 0 ) ) ;
hbc - > add_child ( opbtn ) ;
2022-07-28 22:56:41 +02:00
opbtn - > connect ( " item_selected " , callable_mp ( this , & VisualScriptEditor : : _change_port_type ) . bind ( E , i , false ) , CONNECT_DEFERRED ) ;
2019-09-13 21:14:12 +02:00
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
if ( nd_list - > is_output_port_name_editable ( ) ) {
LineEdit * name_box = memnew ( LineEdit ) ;
hbc - > add_child ( name_box ) ;
name_box - > set_custom_minimum_size ( Size2 ( 60 * EDSCALE , 0 ) ) ;
name_box - > set_text ( right_name ) ;
2021-03-28 20:31:25 +02:00
name_box - > set_expand_to_text_length_enabled ( true ) ;
2022-07-28 22:56:41 +02:00
name_box - > connect ( " resized " , callable_mp ( this , & VisualScriptEditor : : _update_node_size ) . bind ( E ) ) ;
name_box - > connect ( " focus_exited " , callable_mp ( this , & VisualScriptEditor : : _port_name_focus_out ) . bind ( name_box , E , i , false ) ) ;
2020-06-17 17:39:25 +02:00
} else {
hbc - > add_child ( memnew ( Label ( right_name ) ) ) ;
2019-09-13 21:14:12 +02:00
}
} else {
2020-06-17 17:39:25 +02:00
hbc - > add_child ( memnew ( Label ( right_name ) ) ) ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
Ref < Texture2D > t ;
if ( right_type > = 0 & & right_type < Variant : : VARIANT_MAX ) {
t = type_icons [ right_type ] ;
}
if ( t . is_valid ( ) ) {
TextureRect * tf = memnew ( TextureRect ) ;
tf - > set_texture ( t ) ;
tf - > set_stretch_mode ( TextureRect : : STRETCH_KEEP_CENTERED ) ;
hbc - > add_child ( tf ) ;
}
2016-08-03 00:11:05 +02:00
}
2020-06-17 17:39:25 +02:00
gnode - > add_child ( vbc ) ;
2016-08-03 00:11:05 +02:00
2021-07-17 23:22:52 +02:00
bool dark_theme = get_theme_constant ( SNAME ( " dark_theme " ) , SNAME ( " Editor " ) ) ;
2020-06-17 17:39:25 +02:00
if ( i < mixed_seq_ports ) {
gnode - > set_slot ( slot_idx , left_ok , left_type , _color_from_type ( left_type , dark_theme ) , true , TYPE_SEQUENCE , mono_color , Ref < Texture2D > ( ) , seq_port ) ;
} else {
gnode - > set_slot ( slot_idx , left_ok , left_type , _color_from_type ( left_type , dark_theme ) , right_ok , right_type , _color_from_type ( right_type , dark_theme ) ) ;
2016-09-02 01:04:17 +02:00
}
2020-06-17 17:39:25 +02:00
slot_idx + + ;
}
graph - > add_child ( gnode ) ;
2022-04-30 03:56:57 +02:00
gnode - > set_theme ( vstheme ) ;
2020-06-17 17:39:25 +02:00
if ( gnode - > is_comment ( ) ) {
graph - > move_child ( gnode , 0 ) ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
2019-09-13 21:14:12 +02:00
_update_graph_connections ( ) ;
2021-01-25 15:37:05 +01:00
float graph_minimap_opacity = EditorSettings : : get_singleton ( ) - > get ( " editors/visual_editors/minimap_opacity " ) ;
graph - > set_minimap_opacity ( graph_minimap_opacity ) ;
2022-05-30 15:38:13 +02:00
float graph_lines_curvature = EditorSettings : : get_singleton ( ) - > get ( " editors/visual_editors/lines_curvature " ) ;
graph - > set_connection_lines_curvature ( graph_lines_curvature ) ;
2020-06-17 17:39:25 +02:00
// Use default_func instead of default_func for now I think that should be good stop gap solution to ensure not breaking anything.
2021-07-17 23:22:52 +02:00
graph - > call_deferred ( SNAME ( " set_scroll_ofs " ) , script - > get_scroll ( ) * EDSCALE ) ;
2019-09-13 21:14:12 +02:00
updating_graph = false ;
}
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _change_port_type ( int p_select , int p_id , int p_port , bool is_input ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
2021-07-31 16:19:51 +02:00
undo_redo - > create_action ( TTR ( " Change Port Type " ) ) ;
2019-09-13 21:14:12 +02:00
if ( is_input ) {
undo_redo - > add_do_method ( vsn . ptr ( ) , " set_input_data_port_type " , p_port , Variant : : Type ( p_select ) ) ;
undo_redo - > add_undo_method ( vsn . ptr ( ) , " set_input_data_port_type " , p_port , vsn - > get_input_value_port_info ( p_port ) . type ) ;
} else {
undo_redo - > add_do_method ( vsn . ptr ( ) , " set_output_data_port_type " , p_port , Variant : : Type ( p_select ) ) ;
undo_redo - > add_undo_method ( vsn . ptr ( ) , " set_output_data_port_type " , p_port , vsn - > get_output_value_port_info ( p_port ) . type ) ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
undo_redo - > commit_action ( ) ;
}
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _update_node_size ( int p_id ) {
Node * node = graph - > get_node ( itos ( p_id ) ) ;
2020-05-14 16:41:43 +02:00
if ( Object : : cast_to < Control > ( node ) ) {
2021-11-20 09:04:57 +01:00
Object : : cast_to < Control > ( node ) - > reset_size ( ) ; // Shrink if text is smaller.
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
}
2020-05-14 14:29:06 +02:00
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _port_name_focus_out ( const Node * p_name_box , int p_id , int p_port , bool is_input ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
String text ;
2020-05-14 16:41:43 +02:00
if ( Object : : cast_to < LineEdit > ( p_name_box ) ) {
2019-09-13 21:14:12 +02:00
text = Object : : cast_to < LineEdit > ( p_name_box ) - > get_text ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
2021-07-31 16:19:51 +02:00
undo_redo - > create_action ( TTR ( " Change Port Name " ) ) ;
2019-09-13 21:14:12 +02:00
if ( is_input ) {
undo_redo - > add_do_method ( vsn . ptr ( ) , " set_input_data_port_name " , p_port , text ) ;
undo_redo - > add_undo_method ( vsn . ptr ( ) , " set_input_data_port_name " , p_port , vsn - > get_input_value_port_info ( p_port ) . name ) ;
} else {
undo_redo - > add_do_method ( vsn . ptr ( ) , " set_output_data_port_name " , p_port , text ) ;
undo_redo - > add_undo_method ( vsn . ptr ( ) , " set_output_data_port_name " , p_port , vsn - > get_output_value_port_info ( p_port ) . name ) ;
}
undo_redo - > commit_action ( ) ;
2016-08-03 00:11:05 +02:00
}
void VisualScriptEditor : : _update_members ( ) {
2018-11-05 22:15:42 +01:00
ERR_FAIL_COND ( ! script . is_valid ( ) ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
updating_members = true ;
2016-08-03 00:11:05 +02:00
members - > clear ( ) ;
TreeItem * root = members - > create_item ( ) ;
TreeItem * functions = members - > create_item ( root ) ;
2017-03-05 16:44:50 +01:00
functions - > set_selectable ( 0 , false ) ;
functions - > set_text ( 0 , TTR ( " Functions: " ) ) ;
2021-07-17 23:22:52 +02:00
functions - > add_button ( 0 , Control : : get_theme_icon ( SNAME ( " Override " ) , SNAME ( " EditorIcons " ) ) , 1 , false , TTR ( " Override an existing built-in function. " ) ) ;
functions - > add_button ( 0 , Control : : get_theme_icon ( SNAME ( " Add " ) , SNAME ( " EditorIcons " ) ) , 0 , false , TTR ( " Create a new function. " ) ) ;
functions - > set_custom_color ( 0 , Control : : get_theme_color ( SNAME ( " mono_color " ) , SNAME ( " Editor " ) ) ) ;
2016-08-03 00:11:05 +02:00
List < StringName > func_names ;
script - > get_function_list ( & func_names ) ;
2020-06-17 17:39:25 +02:00
func_names . sort_custom < StringName : : AlphCompare > ( ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & E : func_names ) {
2017-03-05 16:44:50 +01:00
TreeItem * ti = members - > create_item ( functions ) ;
2021-07-16 05:45:57 +02:00
ti - > set_text ( 0 , E ) ;
2017-03-05 16:44:50 +01:00
ti - > set_selectable ( 0 , true ) ;
2021-07-16 05:45:57 +02:00
ti - > set_metadata ( 0 , E ) ;
2021-07-17 23:22:52 +02:00
ti - > add_button ( 0 , Control : : get_theme_icon ( SNAME ( " Edit " ) , SNAME ( " EditorIcons " ) ) , 0 ) ;
2021-07-16 05:45:57 +02:00
if ( selected = = E ) {
2016-08-03 00:11:05 +02:00
ti - > select ( 0 ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
}
TreeItem * variables = members - > create_item ( root ) ;
2017-03-05 16:44:50 +01:00
variables - > set_selectable ( 0 , false ) ;
variables - > set_text ( 0 , TTR ( " Variables: " ) ) ;
2021-07-17 23:22:52 +02:00
variables - > add_button ( 0 , Control : : get_theme_icon ( SNAME ( " Add " ) , SNAME ( " EditorIcons " ) ) , - 1 , false , TTR ( " Create a new variable. " ) ) ;
variables - > set_custom_color ( 0 , Control : : get_theme_color ( SNAME ( " mono_color " ) , SNAME ( " Editor " ) ) ) ;
2017-03-05 16:44:50 +01:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > type_icons [ Variant : : VARIANT_MAX ] = {
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " Variant " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " bool " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " int " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " float " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " String " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector2 " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector2i " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Rect2 " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Rect2i " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector3 " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Vector3i " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Transform2D " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Plane " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Quaternion " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " AABB " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Basis " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Transform3D " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Color " ) , SNAME ( " EditorIcons " ) ) ,
2022-02-16 16:01:18 +01:00
Control : : get_theme_icon ( SNAME ( " StringName " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " NodePath " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " RID " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " MiniObject " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Callable " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Signal " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Dictionary " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " Array " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedByteArray " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedInt32Array " ) , SNAME ( " EditorIcons " ) ) ,
2022-02-16 16:01:18 +01:00
Control : : get_theme_icon ( SNAME ( " PackedInt64Array " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " PackedFloat32Array " ) , SNAME ( " EditorIcons " ) ) ,
2022-02-16 16:01:18 +01:00
Control : : get_theme_icon ( SNAME ( " PackedFloat64Array " ) , SNAME ( " EditorIcons " ) ) ,
2021-07-17 23:22:52 +02:00
Control : : get_theme_icon ( SNAME ( " PackedStringArray " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedVector2Array " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedVector3Array " ) , SNAME ( " EditorIcons " ) ) ,
Control : : get_theme_icon ( SNAME ( " PackedColorArray " ) , SNAME ( " EditorIcons " ) )
2016-08-31 04:44:14 +02:00
} ;
2016-08-03 00:11:05 +02:00
List < StringName > var_names ;
script - > get_variable_list ( & var_names ) ;
2022-02-24 21:18:02 +01:00
var_names . sort_custom < StringName : : AlphCompare > ( ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & E : var_names ) {
2016-08-03 07:26:36 +02:00
TreeItem * ti = members - > create_item ( variables ) ;
2016-08-31 04:44:14 +02:00
2021-07-16 05:45:57 +02:00
ti - > set_text ( 0 , E ) ;
2020-09-07 20:51:51 +02:00
2021-07-16 05:45:57 +02:00
ti - > set_suffix ( 0 , " = " + _sanitized_variant_text ( E ) ) ;
ti - > set_icon ( 0 , type_icons [ script - > get_variable_info ( E ) . type ] ) ;
2017-03-05 16:44:50 +01:00
ti - > set_selectable ( 0 , true ) ;
ti - > set_editable ( 0 , true ) ;
2021-07-16 05:45:57 +02:00
ti - > set_metadata ( 0 , E ) ;
if ( selected = = E ) {
2016-08-03 00:11:05 +02:00
ti - > select ( 0 ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
}
TreeItem * _signals = members - > create_item ( root ) ;
2017-03-05 16:44:50 +01:00
_signals - > set_selectable ( 0 , false ) ;
_signals - > set_text ( 0 , TTR ( " Signals: " ) ) ;
2021-07-17 23:22:52 +02:00
_signals - > add_button ( 0 , Control : : get_theme_icon ( SNAME ( " Add " ) , SNAME ( " EditorIcons " ) ) , - 1 , false , TTR ( " Create a new signal. " ) ) ;
_signals - > set_custom_color ( 0 , Control : : get_theme_color ( SNAME ( " mono_color " ) , SNAME ( " Editor " ) ) ) ;
2016-08-03 00:11:05 +02:00
List < StringName > signal_names ;
script - > get_custom_signal_list ( & signal_names ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & E : signal_names ) {
2016-08-03 07:26:36 +02:00
TreeItem * ti = members - > create_item ( _signals ) ;
2021-07-16 05:45:57 +02:00
ti - > set_text ( 0 , E ) ;
2017-03-05 16:44:50 +01:00
ti - > set_selectable ( 0 , true ) ;
ti - > set_editable ( 0 , true ) ;
2021-07-16 05:45:57 +02:00
ti - > set_metadata ( 0 , E ) ;
if ( selected = = E ) {
2016-08-03 00:11:05 +02:00
ti - > select ( 0 ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
String base_type = script - > get_instance_base_type ( ) ;
String icon_type = base_type ;
2021-07-17 23:22:52 +02:00
if ( ! Control : : has_theme_icon ( base_type , SNAME ( " EditorIcons " ) ) ) {
2017-03-05 16:44:50 +01:00
icon_type = " Object " ;
2016-08-03 00:11:05 +02:00
}
base_type_select - > set_text ( base_type ) ;
2021-07-17 23:22:52 +02:00
base_type_select - > set_icon ( Control : : get_theme_icon ( icon_type , SNAME ( " EditorIcons " ) ) ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
updating_members = false ;
2016-08-03 00:11:05 +02:00
}
2020-09-07 20:51:51 +02:00
String VisualScriptEditor : : _sanitized_variant_text ( const StringName & property_name ) {
Variant var = script - > get_variable_default_value ( property_name ) ;
if ( script - > get_variable_info ( property_name ) . type ! = Variant : : NIL ) {
Callable : : CallError ce ;
const Variant * converted = & var ;
2020-11-09 04:19:09 +01:00
Variant n ;
Variant : : construct ( script - > get_variable_info ( property_name ) . type , n , & converted , 1 , ce ) ;
var = n ;
2020-09-07 20:51:51 +02:00
}
return String ( var ) ;
}
2016-08-03 00:11:05 +02:00
void VisualScriptEditor : : _member_selected ( ) {
2020-05-14 16:41:43 +02:00
if ( updating_members ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
TreeItem * ti = members - > get_selected ( ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! ti ) ;
2017-03-05 16:44:50 +01:00
selected = ti - > get_metadata ( 0 ) ;
2016-08-03 00:11:05 +02:00
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = members - > get_root ( ) - > get_first_child ( ) ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
bool held_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ;
2019-09-13 21:14:12 +02:00
# else
2021-08-13 23:31:57 +02:00
bool held_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2019-09-13 21:14:12 +02:00
# endif
if ( held_ctrl ) {
ERR_FAIL_COND ( ! script - > has_function ( selected ) ) ;
2020-06-17 17:39:25 +02:00
_center_on_node ( script - > get_function_node_id ( selected ) ) ;
2016-08-03 00:11:05 +02:00
}
}
}
void VisualScriptEditor : : _member_edited ( ) {
2020-05-14 16:41:43 +02:00
if ( updating_members ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
TreeItem * ti = members - > get_edited ( ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! ti ) ;
String name = ti - > get_metadata ( 0 ) ;
String new_name = ti - > get_text ( 0 ) ;
2020-05-14 16:41:43 +02:00
if ( name = = new_name ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
if ( ! new_name . is_valid_identifier ( ) ) {
2017-03-05 16:44:50 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Name is not a valid identifier: " ) + " " + new_name ) ;
updating_members = true ;
ti - > set_text ( 0 , name ) ;
updating_members = false ;
2016-08-03 00:11:05 +02:00
return ;
}
if ( script - > has_function ( new_name ) | | script - > has_variable ( new_name ) | | script - > has_custom_signal ( new_name ) ) {
2017-03-05 16:44:50 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Name already in use by another func/var/signal: " ) + " " + new_name ) ;
updating_members = true ;
ti - > set_text ( 0 , name ) ;
updating_members = false ;
2016-08-03 00:11:05 +02:00
return ;
}
2017-03-05 16:44:50 +01:00
TreeItem * root = members - > get_root ( ) ;
2016-08-03 00:11:05 +02:00
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) ) {
2017-03-05 16:44:50 +01:00
selected = new_name ;
2016-08-03 00:11:05 +02:00
2017-08-08 16:32:09 +02:00
int node_id = script - > get_function_node_id ( name ) ;
Ref < VisualScriptFunction > func ;
2020-06-17 17:39:25 +02:00
if ( script - > has_node ( node_id ) ) {
func = script - > get_node ( node_id ) ;
2017-08-08 16:32:09 +02:00
}
2016-08-03 00:11:05 +02:00
undo_redo - > create_action ( TTR ( " Rename Function " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " rename_function " , name , new_name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " rename_function " , new_name , name ) ;
2017-08-08 16:32:09 +02:00
if ( func . is_valid ( ) ) {
undo_redo - > add_do_method ( func . ptr ( ) , " set_name " , new_name ) ;
undo_redo - > add_undo_method ( func . ptr ( ) , " set_name " , name ) ;
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
// Also fix all function calls.
List < int > lst ;
script - > get_node_list ( & lst ) ;
2021-07-16 05:45:57 +02:00
for ( int & F : lst ) {
Ref < VisualScriptFunctionCall > fncall = script - > get_node ( F ) ;
2020-06-17 17:39:25 +02:00
if ( ! fncall . is_valid ( ) ) {
continue ;
}
if ( fncall - > get_function ( ) = = name ) {
undo_redo - > add_do_method ( fncall . ptr ( ) , " set_function " , new_name ) ;
undo_redo - > add_undo_method ( fncall . ptr ( ) , " set_function " , name ) ;
2019-09-13 21:14:12 +02:00
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
2017-08-08 16:32:09 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2017-08-29 12:00:37 +02:00
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
2020-06-17 17:39:25 +02:00
return ; // Or crash because it will become invalid.
2016-08-03 00:11:05 +02:00
}
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) ) {
2017-03-05 16:44:50 +01:00
selected = new_name ;
2016-08-03 00:11:05 +02:00
undo_redo - > create_action ( TTR ( " Rename Variable " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " rename_variable " , name , new_name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " rename_variable " , new_name , name ) ;
2021-11-24 19:25:25 +01:00
// Also fix all variable setter & getter calls
List < int > lst ;
script - > get_node_list ( & lst ) ;
for ( int & P : lst ) {
Ref < VisualScriptPropertySet > pset = script - > get_node ( P ) ;
if ( pset . is_valid ( ) & & pset - > get_property ( ) = = name ) {
undo_redo - > add_do_method ( pset . ptr ( ) , " set_property " , new_name ) ;
undo_redo - > add_undo_method ( pset . ptr ( ) , " set_property " , name ) ;
}
Ref < VisualScriptPropertyGet > pget = script - > get_node ( P ) ;
if ( pget . is_valid ( ) & & pget - > get_property ( ) = = name ) {
undo_redo - > add_do_method ( pget . ptr ( ) , " set_property " , new_name ) ;
undo_redo - > add_undo_method ( pget . ptr ( ) , " set_property " , name ) ;
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
2020-04-03 11:35:26 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2017-08-29 12:00:37 +02:00
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
2020-06-17 17:39:25 +02:00
return ; // Or crash because it will become invalid.
2016-08-03 00:11:05 +02:00
}
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) - > get_next ( ) ) {
2017-03-05 16:44:50 +01:00
selected = new_name ;
2016-08-03 00:11:05 +02:00
undo_redo - > create_action ( TTR ( " Rename Signal " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " rename_custom_signal " , name , new_name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " rename_custom_signal " , new_name , name ) ;
2021-11-24 19:25:25 +01:00
// Also fix all signal emitting nodes
List < int > lst ;
script - > get_node_list ( & lst ) ;
for ( int & P : lst ) {
Ref < VisualScriptEmitSignal > psig = script - > get_node ( P ) ;
if ( psig . is_valid ( ) & & psig - > get_signal ( ) = = name ) {
undo_redo - > add_do_method ( psig . ptr ( ) , " set_signal " , new_name ) ;
undo_redo - > add_undo_method ( psig . ptr ( ) , " set_signal " , name ) ;
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
2017-08-29 12:00:37 +02:00
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
2020-06-17 17:39:25 +02:00
return ; // Or crash because it will become invalid.
2016-08-03 00:11:05 +02:00
}
}
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _create_function_dialog ( ) {
2019-09-28 00:59:53 +02:00
function_create_dialog - > popup_centered ( ) ;
2019-09-13 21:14:12 +02:00
func_name_box - > set_text ( " " ) ;
func_name_box - > grab_focus ( ) ;
for ( int i = 0 ; i < func_input_vbox - > get_child_count ( ) ; i + + ) {
Node * nd = func_input_vbox - > get_child ( i ) ;
nd - > queue_delete ( ) ;
}
}
void VisualScriptEditor : : _create_function ( ) {
2021-12-09 10:42:46 +01:00
String name = _validate_name ( ( func_name_box - > get_text ( ) . is_empty ( ) ) ? " new_func " : func_name_box - > get_text ( ) ) ;
2019-09-13 21:14:12 +02:00
selected = name ;
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_available_pos ( ) ;
2019-09-13 21:14:12 +02:00
Ref < VisualScriptFunction > func_node ;
2021-06-18 00:03:09 +02:00
func_node . instantiate ( ) ;
2019-09-13 21:14:12 +02:00
func_node - > set_name ( name ) ;
for ( int i = 0 ; i < func_input_vbox - > get_child_count ( ) ; i + + ) {
OptionButton * opbtn = Object : : cast_to < OptionButton > ( func_input_vbox - > get_child ( i ) - > get_child ( 3 ) ) ;
LineEdit * lne = Object : : cast_to < LineEdit > ( func_input_vbox - > get_child ( i ) - > get_child ( 1 ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! opbtn | | ! lne ) {
2019-09-13 21:14:12 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
Variant : : Type arg_type = Variant : : Type ( opbtn - > get_selected ( ) ) ;
String arg_name = lne - > get_text ( ) ;
func_node - > add_argument ( arg_type , arg_name ) ;
}
2020-06-17 17:39:25 +02:00
int func_node_id = script - > get_available_id ( ) ;
2019-09-13 21:14:12 +02:00
undo_redo - > create_action ( TTR ( " Add Function " ) ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_function " , name , func_node_id ) ;
2019-09-13 21:14:12 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_function " , name ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , func_node_id , func_node , pos ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , func_node_id ) ;
2019-09-13 21:14:12 +02:00
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > commit_action ( ) ;
_update_graph ( ) ;
}
void VisualScriptEditor : : _add_node_dialog ( ) {
2021-11-20 13:52:37 +01:00
_generic_search ( graph - > get_global_position ( ) + Vector2 ( 55 , 80 ) , true ) ;
2019-09-13 21:14:12 +02:00
}
void VisualScriptEditor : : _add_func_input ( ) {
HBoxContainer * hbox = memnew ( HBoxContainer ) ;
hbox - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
Label * name_label = memnew ( Label ) ;
name_label - > set_text ( TTR ( " Name: " ) ) ;
hbox - > add_child ( name_label ) ;
LineEdit * name_box = memnew ( LineEdit ) ;
name_box - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
name_box - > set_text ( " input " ) ;
2020-02-21 18:28:45 +01:00
name_box - > connect ( " focus_entered " , callable_mp ( this , & VisualScriptEditor : : _deselect_input_names ) ) ;
2019-09-13 21:14:12 +02:00
hbox - > add_child ( name_box ) ;
Label * type_label = memnew ( Label ) ;
type_label - > set_text ( TTR ( " Type: " ) ) ;
hbox - > add_child ( type_label ) ;
OptionButton * type_box = memnew ( OptionButton ) ;
type_box - > set_custom_minimum_size ( Size2 ( 120 * EDSCALE , 0 ) ) ;
2020-05-14 16:41:43 +02:00
for ( int i = Variant : : NIL ; i < Variant : : VARIANT_MAX ; i + + ) {
2019-09-13 21:14:12 +02:00
type_box - > add_item ( Variant : : get_type_name ( Variant : : Type ( i ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
type_box - > select ( 1 ) ;
hbox - > add_child ( type_box ) ;
Button * delete_button = memnew ( Button ) ;
2021-07-17 23:22:52 +02:00
delete_button - > set_icon ( EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) ) ;
2019-09-13 21:14:12 +02:00
delete_button - > set_tooltip ( vformat ( TTR ( " Delete input port " ) ) ) ;
hbox - > add_child ( delete_button ) ;
for ( int i = 0 ; i < func_input_vbox - > get_child_count ( ) ; i + + ) {
LineEdit * line_edit = ( LineEdit * ) func_input_vbox - > get_child ( i ) - > get_child ( 1 ) ;
line_edit - > deselect ( ) ;
}
func_input_vbox - > add_child ( hbox ) ;
2020-04-06 01:06:10 +02:00
hbox - > set_meta ( " id " , hbox - > get_index ( ) ) ;
2019-09-13 21:14:12 +02:00
2022-07-28 22:56:41 +02:00
delete_button - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _remove_func_input ) . bind ( hbox ) ) ;
2019-09-13 21:14:12 +02:00
name_box - > select_all ( ) ;
name_box - > grab_focus ( ) ;
}
void VisualScriptEditor : : _remove_func_input ( Node * p_node ) {
func_input_vbox - > remove_child ( p_node ) ;
p_node - > queue_delete ( ) ;
}
void VisualScriptEditor : : _deselect_input_names ( ) {
int cn = func_input_vbox - > get_child_count ( ) ;
for ( int i = 0 ; i < cn ; i + + ) {
LineEdit * lne = Object : : cast_to < LineEdit > ( func_input_vbox - > get_child ( i ) - > get_child ( 1 ) ) ;
2020-05-14 16:41:43 +02:00
if ( lne ) {
2019-09-13 21:14:12 +02:00
lne - > deselect ( ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
}
}
2021-09-18 09:33:18 +02:00
void VisualScriptEditor : : _member_button ( Object * p_item , int p_column , int p_button , MouseButton p_mouse_button ) {
if ( p_mouse_button ! = MouseButton : : LEFT ) {
return ;
}
2017-08-24 22:58:51 +02:00
TreeItem * ti = Object : : cast_to < TreeItem > ( p_item ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
TreeItem * root = members - > get_root ( ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( ti - > get_parent ( ) = = root ) {
2016-08-03 00:11:05 +02:00
//main buttons
2021-03-07 21:07:30 +01:00
if ( ti = = root - > get_first_child ( ) ) {
2020-06-17 17:39:25 +02:00
// Add function, this one uses menu.
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
if ( p_button = = 1 ) {
2020-06-17 17:39:25 +02:00
// Ensure script base exists otherwise use custom base type.
ERR_FAIL_COND ( script . is_null ( ) ) ;
2021-11-20 13:52:37 +01:00
new_virtual_method_select - > select_method_from_base_type ( script - > get_instance_base_type ( ) , true ) ;
2016-08-03 00:11:05 +02:00
return ;
2017-03-05 16:44:50 +01:00
} else if ( p_button = = 0 ) {
2016-08-03 00:11:05 +02:00
String name = _validate_name ( " new_function " ) ;
2017-03-05 16:44:50 +01:00
selected = name ;
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_available_pos ( ) ;
2016-08-03 00:11:05 +02:00
Ref < VisualScriptFunction > func_node ;
2021-06-18 00:03:09 +02:00
func_node . instantiate ( ) ;
2016-08-03 00:11:05 +02:00
func_node - > set_name ( name ) ;
2020-06-17 17:39:25 +02:00
int fn_id = script - > get_available_id ( ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > create_action ( TTR ( " Add Function " ) ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_function " , name , fn_id ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , fn_id , func_node , pos ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_function " , name ) ;
2021-07-10 13:45:53 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , fn_id ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2017-08-29 12:00:37 +02:00
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
_update_graph ( ) ;
}
2020-06-17 17:39:25 +02:00
return ; // Or crash because it will become invalid.
2016-08-03 00:11:05 +02:00
}
2021-03-07 21:07:30 +01:00
if ( ti = = root - > get_first_child ( ) - > get_next ( ) ) {
2020-06-17 17:39:25 +02:00
// Add variable.
2016-08-03 00:11:05 +02:00
String name = _validate_name ( " new_variable " ) ;
2017-03-05 16:44:50 +01:00
selected = name ;
2016-08-03 00:11:05 +02:00
undo_redo - > create_action ( TTR ( " Add Variable " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_variable " , name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_variable " , name ) ;
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
2017-08-29 12:00:37 +02:00
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
2020-06-17 17:39:25 +02:00
return ; // Or crash because it will become invalid.
2016-08-03 00:11:05 +02:00
}
2021-03-07 21:07:30 +01:00
if ( ti = = root - > get_first_child ( ) - > get_next ( ) - > get_next ( ) ) {
2020-06-17 17:39:25 +02:00
// Add variable.
2016-08-03 00:11:05 +02:00
String name = _validate_name ( " new_signal " ) ;
2017-03-05 16:44:50 +01:00
selected = name ;
2016-08-03 00:11:05 +02:00
undo_redo - > create_action ( TTR ( " Add Signal " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_custom_signal " , name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_custom_signal " , name ) ;
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
2017-08-29 12:00:37 +02:00
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
2020-06-17 17:39:25 +02:00
return ; // Or crash because it will become invalid.
2016-08-03 00:11:05 +02:00
}
2021-03-07 21:07:30 +01:00
} else if ( ti - > get_parent ( ) = = root - > get_first_child ( ) ) {
2019-09-27 22:46:11 +02:00
selected = ti - > get_text ( 0 ) ;
2021-08-31 17:43:35 +02:00
function_name_edit - > set_position ( get_screen_position ( ) + get_local_mouse_position ( ) - Vector2 ( 60 , - 10 ) ) ;
2019-09-13 21:14:12 +02:00
function_name_edit - > popup ( ) ;
2019-09-29 13:55:09 +02:00
function_name_box - > set_text ( selected ) ;
function_name_box - > select_all ( ) ;
2022-02-12 21:28:28 +01:00
function_name_box - > grab_focus ( ) ;
2016-08-03 00:11:05 +02:00
}
}
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _add_input_port ( int p_id ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2016-09-07 01:34:24 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-09-07 01:34:24 +02:00
2017-03-05 16:44:50 +01:00
updating_graph = true ;
2016-09-07 01:34:24 +02:00
2019-09-13 21:14:12 +02:00
undo_redo - > create_action ( TTR ( " Add Input Port " ) , UndoRedo : : MERGE_ENDS ) ;
undo_redo - > add_do_method ( vsn . ptr ( ) , " add_input_data_port " , Variant : : NIL , " arg " , - 1 ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_graph " , p_id ) ;
2019-09-13 21:14:12 +02:00
undo_redo - > add_undo_method ( vsn . ptr ( ) , " remove_input_data_port " , vsn - > get_input_value_port_count ( ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_undo_method ( this , " _update_graph " , p_id ) ;
2019-09-13 21:14:12 +02:00
updating_graph = false ;
2016-09-07 01:34:24 +02:00
undo_redo - > commit_action ( ) ;
2019-09-13 21:14:12 +02:00
}
2016-09-07 01:34:24 +02:00
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _add_output_port ( int p_id ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
updating_graph = true ;
undo_redo - > create_action ( TTR ( " Add Output Port " ) , UndoRedo : : MERGE_ENDS ) ;
undo_redo - > add_do_method ( vsn . ptr ( ) , " add_output_data_port " , Variant : : NIL , " arg " , - 1 ) ;
undo_redo - > add_do_method ( this , " _update_graph " , p_id ) ;
undo_redo - > add_undo_method ( vsn . ptr ( ) , " remove_output_data_port " , vsn - > get_output_value_port_count ( ) ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_id ) ;
2016-09-07 01:34:24 +02:00
2017-03-05 16:44:50 +01:00
updating_graph = false ;
2019-09-13 21:14:12 +02:00
undo_redo - > commit_action ( ) ;
2016-09-07 01:34:24 +02:00
}
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _remove_input_port ( int p_id , int p_port ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2019-05-31 01:10:33 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-05-31 01:10:33 +02:00
2019-09-13 21:14:12 +02:00
updating_graph = true ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
undo_redo - > create_action ( TTR ( " Remove Input Port " ) , UndoRedo : : MERGE_ENDS ) ;
int conn_from = - 1 , conn_port = - 1 ;
2020-06-17 17:39:25 +02:00
script - > get_input_value_port_connection_source ( p_id , p_port , & conn_from , & conn_port ) ;
2019-09-13 21:14:12 +02:00
2020-05-14 16:41:43 +02:00
if ( conn_from ! = - 1 ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " data_disconnect " , conn_from , conn_port , p_id , p_port ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
undo_redo - > add_do_method ( vsn . ptr ( ) , " remove_input_data_port " , p_port ) ;
undo_redo - > add_do_method ( this , " _update_graph " , p_id ) ;
2020-05-14 16:41:43 +02:00
if ( conn_from ! = - 1 ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , conn_from , conn_port , p_id , p_port ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
undo_redo - > add_undo_method ( vsn . ptr ( ) , " add_input_data_port " , vsn - > get_input_value_port_info ( p_port ) . type , vsn - > get_input_value_port_info ( p_port ) . name , p_port ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_id ) ;
updating_graph = false ;
undo_redo - > commit_action ( ) ;
}
void VisualScriptEditor : : _remove_output_port ( int p_id , int p_port ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptLists > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-04 05:05:35 +02:00
2019-09-13 21:14:12 +02:00
updating_graph = true ;
2016-08-04 05:05:35 +02:00
2019-09-13 21:14:12 +02:00
undo_redo - > create_action ( TTR ( " Remove Output Port " ) , UndoRedo : : MERGE_ENDS ) ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
List < VisualScript : : DataConnection > data_connections ;
2020-06-17 17:39:25 +02:00
script - > get_data_connection_list ( & data_connections ) ;
2019-09-13 21:14:12 +02:00
2022-05-13 15:04:37 +02:00
HashMap < int , RBSet < int > > conn_map ;
2021-07-16 05:45:57 +02:00
for ( const VisualScript : : DataConnection & E : data_connections ) {
if ( E . from_node = = p_id & & E . from_port = = p_port ) {
2020-06-17 17:39:25 +02:00
// Push into the connections map.
2021-07-16 05:45:57 +02:00
if ( ! conn_map . has ( E . to_node ) ) {
2022-05-13 15:04:37 +02:00
conn_map . insert ( E . to_node , RBSet < int > ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2021-07-16 05:45:57 +02:00
conn_map [ E . to_node ] . insert ( E . to_port ) ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
}
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
undo_redo - > add_do_method ( vsn . ptr ( ) , " remove_output_data_port " , p_port ) ;
undo_redo - > add_do_method ( this , " _update_graph " , p_id ) ;
2022-05-13 15:04:37 +02:00
for ( const KeyValue < int , RBSet < int > > & E : conn_map ) {
2022-05-19 01:43:40 +02:00
for ( const int & F : E . value ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , p_id , p_port , E . key , F ) ;
2019-09-13 21:14:12 +02:00
}
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
undo_redo - > add_undo_method ( vsn . ptr ( ) , " add_output_data_port " , vsn - > get_output_value_port_info ( p_port ) . type , vsn - > get_output_value_port_info ( p_port ) . name , p_port ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_id ) ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
updating_graph = false ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
undo_redo - > commit_action ( ) ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _expression_text_changed ( const String & p_text , int p_id ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptExpression > vse = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( ! vse . is_valid ( ) ) {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
updating_graph = true ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
undo_redo - > create_action ( TTR ( " Change Expression " ) , UndoRedo : : MERGE_ENDS ) ;
undo_redo - > add_do_property ( vse . ptr ( ) , " expression " , p_text ) ;
undo_redo - > add_undo_property ( vse . ptr ( ) , " expression " , vse - > get ( " expression " ) ) ;
undo_redo - > add_do_method ( this , " _update_graph " , p_id ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_id ) ;
undo_redo - > commit_action ( ) ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
Node * node = graph - > get_node ( itos ( p_id ) ) ;
2020-05-14 16:41:43 +02:00
if ( Object : : cast_to < Control > ( node ) ) {
2021-11-20 09:04:57 +01:00
Object : : cast_to < Control > ( node ) - > reset_size ( ) ; // Shrink if text is smaller.
2020-05-14 16:41:43 +02:00
}
2016-08-04 03:06:39 +02:00
2019-09-13 21:14:12 +02:00
updating_graph = false ;
}
2016-08-03 00:11:05 +02:00
2021-06-23 12:11:06 +02:00
Vector2 VisualScriptEditor : : _get_pos_in_graph ( Vector2 p_point ) const {
Vector2 pos = ( graph - > get_scroll_ofs ( ) + p_point ) / ( graph - > get_zoom ( ) * EDSCALE ) ;
2019-09-13 21:14:12 +02:00
if ( graph - > is_using_snap ( ) ) {
int snap = graph - > get_snap ( ) ;
2021-06-23 12:11:06 +02:00
pos = pos . snapped ( Vector2 ( snap , snap ) ) ;
2019-09-13 21:14:12 +02:00
}
2021-06-23 12:11:06 +02:00
return pos ;
}
2016-08-04 03:06:39 +02:00
2021-06-23 12:11:06 +02:00
Vector2 VisualScriptEditor : : _get_available_pos ( bool p_centered , Vector2 p_pos ) const {
if ( p_centered ) {
p_pos = _get_pos_in_graph ( graph - > get_size ( ) * 0.5 ) ;
}
2016-08-04 03:06:39 +02:00
2019-09-13 21:14:12 +02:00
while ( true ) {
bool exists = false ;
2020-06-17 17:39:25 +02:00
List < int > existing ;
script - > get_node_list ( & existing ) ;
2021-07-16 05:45:57 +02:00
for ( int & E : existing ) {
Point2 pos = script - > get_node_position ( E ) ;
2021-06-23 12:11:06 +02:00
if ( pos . distance_to ( p_pos ) < 50 ) {
p_pos + = Vector2 ( graph - > get_snap ( ) , graph - > get_snap ( ) ) ;
2020-06-17 17:39:25 +02:00
exists = true ;
break ;
2016-08-03 00:11:05 +02:00
}
}
2020-05-14 16:41:43 +02:00
if ( exists ) {
2019-09-13 21:14:12 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
break ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
2021-06-23 12:11:06 +02:00
return p_pos ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
String VisualScriptEditor : : _validate_name ( const String & p_name ) const {
String valid = p_name ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
int counter = 1 ;
while ( true ) {
2016-08-03 00:11:05 +02:00
bool exists = script - > has_function ( valid ) | | script - > has_variable ( valid ) | | script - > has_custom_signal ( valid ) ;
if ( exists ) {
counter + + ;
2017-03-05 16:44:50 +01:00
valid = p_name + " _ " + itos ( counter ) ;
2016-08-03 00:11:05 +02:00
continue ;
}
break ;
}
return valid ;
}
2021-10-02 19:31:48 +02:00
void VisualScriptEditor : : _on_nodes_copy ( ) {
clipboard - > nodes . clear ( ) ;
clipboard - > data_connections . clear ( ) ;
clipboard - > sequence_connections . clear ( ) ;
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
if ( gn ) {
if ( gn - > is_selected ( ) ) {
int id = gn - > get_name ( ) . operator String ( ) . to_int ( ) ;
Ref < VisualScriptNode > node = script - > get_node ( id ) ;
if ( Object : : cast_to < VisualScriptFunction > ( * node ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Can't copy the function node. " ) ) ;
return ;
}
if ( node . is_valid ( ) ) {
clipboard - > nodes [ id ] = node - > duplicate ( true ) ;
clipboard - > nodes_positions [ id ] = script - > get_node_position ( id ) ;
}
}
}
}
if ( clipboard - > nodes . is_empty ( ) ) {
return ;
}
List < VisualScript : : SequenceConnection > sequence_connections ;
script - > get_sequence_connection_list ( & sequence_connections ) ;
for ( const VisualScript : : SequenceConnection & E : sequence_connections ) {
if ( clipboard - > nodes . has ( E . from_node ) & & clipboard - > nodes . has ( E . to_node ) ) {
clipboard - > sequence_connections . insert ( E ) ;
}
}
List < VisualScript : : DataConnection > data_connections ;
script - > get_data_connection_list ( & data_connections ) ;
for ( const VisualScript : : DataConnection & E : data_connections ) {
if ( clipboard - > nodes . has ( E . from_node ) & & clipboard - > nodes . has ( E . to_node ) ) {
clipboard - > data_connections . insert ( E ) ;
}
}
}
void VisualScriptEditor : : _on_nodes_paste ( ) {
if ( clipboard - > nodes . is_empty ( ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Clipboard is empty! " ) ) ;
return ;
}
2022-05-13 15:04:37 +02:00
HashMap < int , int > remap ;
2021-10-02 19:31:48 +02:00
undo_redo - > create_action ( TTR ( " Paste VisualScript Nodes " ) ) ;
int idc = script - > get_available_id ( ) + 1 ;
2022-05-13 15:04:37 +02:00
RBSet < int > to_select ;
2021-10-02 19:31:48 +02:00
2022-05-13 15:04:37 +02:00
RBSet < Vector2 > existing_positions ;
2021-10-02 19:31:48 +02:00
{
List < int > nodes ;
script - > get_node_list ( & nodes ) ;
for ( int & E : nodes ) {
Vector2 pos = script - > get_node_position ( E ) . snapped ( Vector2 ( 2 , 2 ) ) ;
existing_positions . insert ( pos ) ;
}
}
bool first_paste = true ;
Vector2 position_offset = Vector2 ( 0 , 0 ) ;
for ( KeyValue < int , Ref < VisualScriptNode > > & E : clipboard - > nodes ) {
Ref < VisualScriptNode > node = E . value - > duplicate ( ) ;
int new_id = idc + + ;
to_select . insert ( new_id ) ;
remap [ E . key ] = new_id ;
Vector2 paste_pos = clipboard - > nodes_positions [ E . key ] ;
if ( first_paste ) {
position_offset = _get_pos_in_graph ( mouse_up_position - graph - > get_global_position ( ) ) - paste_pos ;
first_paste = false ;
}
paste_pos + = position_offset ;
while ( existing_positions . has ( paste_pos . snapped ( Vector2 ( 2 , 2 ) ) ) ) {
paste_pos + = Vector2 ( 20 , 20 ) * EDSCALE ;
}
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , node , paste_pos ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
}
2022-05-19 01:43:40 +02:00
for ( const VisualScript : : SequenceConnection & E : clipboard - > sequence_connections ) {
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , remap [ E . from_node ] , E . from_output , remap [ E . to_node ] ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_disconnect " , remap [ E . from_node ] , E . from_output , remap [ E . to_node ] ) ;
2021-10-02 19:31:48 +02:00
}
2022-05-19 01:43:40 +02:00
for ( const VisualScript : : DataConnection & E : clipboard - > data_connections ) {
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , remap [ E . from_node ] , E . from_port , remap [ E . to_node ] , E . to_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_disconnect " , remap [ E . from_node ] , E . from_port , remap [ E . to_node ] , E . to_port ) ;
2021-10-02 19:31:48 +02:00
}
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
if ( gn ) {
int id = gn - > get_name ( ) . operator String ( ) . to_int ( ) ;
gn - > set_selected ( to_select . has ( id ) ) ;
}
}
}
2016-08-03 00:11:05 +02:00
void VisualScriptEditor : : _on_nodes_delete ( ) {
2020-06-17 17:39:25 +02:00
// Delete all the selected nodes.
2019-09-13 21:14:12 +02:00
2016-08-03 00:11:05 +02:00
List < int > to_erase ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
2016-08-03 00:11:05 +02:00
if ( gn ) {
if ( gn - > is_selected ( ) & & gn - > is_close_button_visible ( ) ) {
to_erase . push_back ( gn - > get_name ( ) . operator String ( ) . to_int ( ) ) ;
}
}
}
2020-12-15 13:04:21 +01:00
if ( to_erase . is_empty ( ) ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Remove VisualScript Nodes " ) ) ;
2016-08-03 00:11:05 +02:00
2021-07-16 05:45:57 +02:00
for ( int & F : to_erase ) {
int cr_node = F ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " remove_node " , cr_node ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " add_node " , cr_node , script - > get_node ( cr_node ) , script - > get_node_position ( cr_node ) ) ;
2016-08-03 00:11:05 +02:00
List < VisualScript : : SequenceConnection > sequence_conns ;
2020-06-17 17:39:25 +02:00
script - > get_sequence_connection_list ( & sequence_conns ) ;
2016-08-03 00:11:05 +02:00
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : SequenceConnection & E : sequence_conns ) {
2021-07-16 05:45:57 +02:00
if ( E . from_node = = cr_node | | E . to_node = = cr_node ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_connect " , E . from_node , E . from_output , E . to_node ) ;
2016-08-03 00:11:05 +02:00
}
}
List < VisualScript : : DataConnection > data_conns ;
2020-06-17 17:39:25 +02:00
script - > get_data_connection_list ( & data_conns ) ;
2016-08-03 00:11:05 +02:00
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : DataConnection & E : data_conns ) {
2021-07-16 05:45:57 +02:00
if ( E . from_node = = F | | E . to_node = = F ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , E . from_node , E . from_port , E . to_node , E . to_port ) ;
2016-08-03 00:11:05 +02:00
}
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
}
void VisualScriptEditor : : _on_nodes_duplicate ( ) {
2022-05-13 15:04:37 +02:00
RBSet < int > to_duplicate ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
2016-08-03 00:11:05 +02:00
if ( gn ) {
if ( gn - > is_selected ( ) & & gn - > is_close_button_visible ( ) ) {
2019-09-13 21:14:12 +02:00
int id = gn - > get_name ( ) . operator String ( ) . to_int ( ) ;
to_duplicate . insert ( id ) ;
2016-08-03 00:11:05 +02:00
}
}
}
2020-12-15 13:04:21 +01:00
if ( to_duplicate . is_empty ( ) ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Duplicate VisualScript Nodes " ) ) ;
2017-03-05 16:44:50 +01:00
int idc = script - > get_available_id ( ) + 1 ;
2016-08-03 00:11:05 +02:00
2022-05-13 15:04:37 +02:00
RBSet < int > to_select ;
2019-09-13 21:14:12 +02:00
HashMap < int , int > remap ;
2016-08-03 00:11:05 +02:00
2022-05-19 01:43:40 +02:00
for ( const int & F : to_duplicate ) {
2020-06-17 17:39:25 +02:00
// Duplicate from the specific function but place it into the default func as it would lack the connections.
2022-05-19 01:43:40 +02:00
Ref < VisualScriptNode > node = script - > get_node ( F ) ;
2016-08-03 00:11:05 +02:00
2018-07-26 10:31:48 +02:00
Ref < VisualScriptNode > dupe = node - > duplicate ( true ) ;
2016-08-03 00:11:05 +02:00
int new_id = idc + + ;
2022-05-19 01:43:40 +02:00
remap . insert ( F , new_id ) ;
2019-09-13 21:14:12 +02:00
2016-08-03 00:11:05 +02:00
to_select . insert ( new_id ) ;
2022-05-19 01:43:40 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , dupe , script - > get_node_position ( F ) + Vector2 ( 20 , 20 ) ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
List < VisualScript : : SequenceConnection > seqs ;
script - > get_sequence_connection_list ( & seqs ) ;
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : SequenceConnection & E : seqs ) {
2021-07-16 05:45:57 +02:00
if ( to_duplicate . has ( E . from_node ) & & to_duplicate . has ( E . to_node ) ) {
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , remap [ E . from_node ] , E . from_output , remap [ E . to_node ] ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
List < VisualScript : : DataConnection > data ;
script - > get_data_connection_list ( & data ) ;
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : DataConnection & E : data ) {
2021-07-16 05:45:57 +02:00
if ( to_duplicate . has ( E . from_node ) & & to_duplicate . has ( E . to_node ) ) {
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , remap [ E . from_node ] , E . from_port , remap [ E . to_node ] , E . to_port ) ;
2019-09-13 21:14:12 +02:00
}
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
2016-08-03 00:11:05 +02:00
if ( gn ) {
int id = gn - > get_name ( ) . operator String ( ) . to_int ( ) ;
gn - > set_selected ( to_select . has ( id ) ) ;
}
}
if ( to_select . size ( ) ) {
2020-06-17 17:39:25 +02:00
EditorNode : : get_singleton ( ) - > push_item ( script - > get_node ( to_select . front ( ) - > get ( ) ) . ptr ( ) ) ;
2016-08-03 00:11:05 +02:00
}
}
2021-11-20 13:52:37 +01:00
void VisualScriptEditor : : _generic_search ( Vector2 pos , bool node_centered ) {
2020-05-14 16:41:43 +02:00
if ( node_centered ) {
2019-09-13 21:14:12 +02:00
port_action_pos = graph - > get_size ( ) / 2.0f ;
2020-05-14 16:41:43 +02:00
} else {
2019-09-13 21:14:12 +02:00
port_action_pos = graph - > get_viewport ( ) - > get_mouse_position ( ) - graph - > get_global_position ( ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
2021-11-20 13:52:37 +01:00
new_connect_node_select - > select_from_visual_script ( script , false ) ; // do not reset text
2019-09-13 21:14:12 +02:00
}
2021-08-22 17:37:22 +02:00
void VisualScriptEditor : : input ( const Ref < InputEvent > & p_event ) {
2021-04-05 08:52:21 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2019-09-13 21:14:12 +02:00
// GUI input for VS Editor Plugin
Ref < InputEventMouseButton > key = p_event ;
2017-05-20 17:38:03 +02:00
2022-01-09 17:10:17 +01:00
if ( key . is_valid ( ) & & key - > is_pressed ( ) ) {
2021-08-31 17:43:35 +02:00
mouse_up_position = get_screen_position ( ) + get_local_mouse_position ( ) ;
2016-08-03 00:11:05 +02:00
}
2018-07-25 17:25:03 +02:00
}
2018-05-13 05:34:35 +02:00
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _graph_gui_input ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > key = p_event ;
2021-08-13 23:31:57 +02:00
if ( key . is_valid ( ) & & key - > is_pressed ( ) & & key - > get_button_mask ( ) = = MouseButton : : RIGHT ) {
2022-01-09 17:10:17 +01:00
bool is_empty_selection = true ;
2019-09-13 21:14:12 +02:00
2022-01-09 17:10:17 +01:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
if ( gn & & gn - > is_selected ( ) ) {
is_empty_selection = false ;
break ;
}
}
if ( is_empty_selection & & clipboard - > nodes . is_empty ( ) ) {
2021-11-20 13:52:37 +01:00
_generic_search ( ) ;
2022-01-09 17:10:17 +01:00
} else {
popup_menu - > set_item_disabled ( int ( EDIT_CUT_NODES ) , is_empty_selection ) ;
popup_menu - > set_item_disabled ( int ( EDIT_COPY_NODES ) , is_empty_selection ) ;
popup_menu - > set_item_disabled ( int ( EDIT_PASTE_NODES ) , clipboard - > nodes . is_empty ( ) ) ;
popup_menu - > set_item_disabled ( int ( EDIT_DELETE_NODES ) , is_empty_selection ) ;
popup_menu - > set_item_disabled ( int ( EDIT_DUPLICATE_NODES ) , is_empty_selection ) ;
popup_menu - > set_item_disabled ( int ( EDIT_CLEAR_COPY_BUFFER ) , clipboard - > nodes . is_empty ( ) ) ;
popup_menu - > set_position ( mouse_up_position ) ;
popup_menu - > popup ( ) ;
}
2019-09-13 21:14:12 +02:00
}
2016-08-03 00:11:05 +02:00
}
2018-01-05 20:45:54 +01:00
void VisualScriptEditor : : _members_gui_input ( const Ref < InputEvent > & p_event ) {
Ref < InputEventKey > key = p_event ;
if ( key . is_valid ( ) & & key - > is_pressed ( ) & & ! key - > is_echo ( ) ) {
if ( members - > has_focus ( ) ) {
TreeItem * ti = members - > get_selected ( ) ;
if ( ti ) {
TreeItem * root = members - > get_root ( ) ;
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) ) {
2018-01-05 20:45:54 +01:00
member_type = MEMBER_FUNCTION ;
}
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) ) {
2018-01-05 20:45:54 +01:00
member_type = MEMBER_VARIABLE ;
}
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) - > get_next ( ) ) {
2018-01-05 20:45:54 +01:00
member_type = MEMBER_SIGNAL ;
}
member_name = ti - > get_text ( 0 ) ;
}
2021-06-08 19:59:05 +02:00
if ( ED_IS_SHORTCUT ( " ui_graph_delete " , p_event ) ) {
2018-01-05 20:45:54 +01:00
_member_option ( MEMBER_REMOVE ) ;
}
if ( ED_IS_SHORTCUT ( " visual_script_editor/edit_member " , p_event ) ) {
_member_option ( MEMBER_EDIT ) ;
}
}
}
2019-09-13 21:14:12 +02:00
Ref < InputEventMouseButton > btn = p_event ;
2021-04-13 10:25:44 +02:00
if ( btn . is_valid ( ) & & btn - > is_double_click ( ) ) {
2019-09-13 21:14:12 +02:00
TreeItem * ti = members - > get_selected ( ) ;
2021-03-07 21:07:30 +01:00
if ( ti & & ti - > get_parent ( ) = = members - > get_root ( ) - > get_first_child ( ) ) { // to check if it's a function
2020-06-17 17:39:25 +02:00
_center_on_node ( script - > get_function_node_id ( ti - > get_metadata ( 0 ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
}
2018-01-05 20:45:54 +01:00
}
2019-09-13 21:14:12 +02:00
void VisualScriptEditor : : _rename_function ( const String & name , const String & new_name ) {
if ( ! new_name . is_valid_identifier ( ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Name is not a valid identifier: " ) + " " + new_name ) ;
return ;
}
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
if ( script - > has_function ( new_name ) | | script - > has_variable ( new_name ) | | script - > has_custom_signal ( new_name ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Name already in use by another func/var/signal: " ) + " " + new_name ) ;
return ;
2016-08-03 00:11:05 +02:00
}
2019-09-13 21:14:12 +02:00
int node_id = script - > get_function_node_id ( name ) ;
Ref < VisualScriptFunction > func ;
2020-06-17 17:39:25 +02:00
if ( script - > has_node ( node_id ) ) {
func = script - > get_node ( node_id ) ;
2019-09-13 21:14:12 +02:00
}
undo_redo - > create_action ( TTR ( " Rename Function " ) ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " rename_function " , name , new_name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " rename_function " , new_name , name ) ;
if ( func . is_valid ( ) ) {
undo_redo - > add_do_method ( func . ptr ( ) , " set_name " , new_name ) ;
undo_redo - > add_undo_method ( func . ptr ( ) , " set_name " , name ) ;
}
2020-06-17 17:39:25 +02:00
// Also fix all function calls.
List < int > lst ;
script - > get_node_list ( & lst ) ;
2021-07-16 05:45:57 +02:00
for ( int & F : lst ) {
Ref < VisualScriptFunctionCall > fncall = script - > get_node ( F ) ;
2020-06-17 17:39:25 +02:00
if ( ! fncall . is_valid ( ) ) {
continue ;
}
if ( fncall - > get_function ( ) = = name ) {
undo_redo - > add_do_method ( fncall . ptr ( ) , " set_function " , new_name ) ;
undo_redo - > add_undo_method ( fncall . ptr ( ) , " set_function " , name ) ;
2019-09-13 21:14:12 +02:00
}
}
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > commit_action ( ) ;
}
void VisualScriptEditor : : _fn_name_box_input ( const Ref < InputEvent > & p_event ) {
2020-05-14 16:41:43 +02:00
if ( ! function_name_edit - > is_visible ( ) ) {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
Ref < InputEventKey > key = p_event ;
2021-08-13 23:31:57 +02:00
if ( key . is_valid ( ) & & key - > is_pressed ( ) & & key - > get_keycode ( ) = = Key : : ENTER ) {
2019-09-13 21:14:12 +02:00
function_name_edit - > hide ( ) ;
2022-02-12 21:28:28 +01:00
_on_fn_name_box_confirmed ( ) ;
2019-09-13 21:14:12 +02:00
function_name_box - > clear ( ) ;
}
}
2022-02-12 21:28:28 +01:00
void VisualScriptEditor : : _on_fn_name_box_confirmed ( ) {
_rename_function ( selected , function_name_box - > get_text ( ) ) ;
}
2019-09-13 21:14:12 +02:00
Variant VisualScriptEditor : : get_drag_data_fw ( const Point2 & p_point , Control * p_from ) {
2017-03-05 16:44:50 +01:00
if ( p_from = = members ) {
2017-09-10 15:37:49 +02:00
TreeItem * it = members - > get_item_at_position ( p_point ) ;
2020-05-14 16:41:43 +02:00
if ( ! it ) {
2016-08-03 00:11:05 +02:00
return Variant ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
String type = it - > get_metadata ( 0 ) ;
2016-08-03 00:11:05 +02:00
2021-12-09 10:42:46 +01:00
if ( type . is_empty ( ) ) {
2016-08-03 00:11:05 +02:00
return Variant ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
Dictionary dd ;
2017-03-05 16:44:50 +01:00
TreeItem * root = members - > get_root ( ) ;
2016-08-03 00:11:05 +02:00
2021-03-07 21:07:30 +01:00
if ( it - > get_parent ( ) = = root - > get_first_child ( ) ) {
2017-03-05 16:44:50 +01:00
dd [ " type " ] = " visual_script_function_drag " ;
dd [ " function " ] = type ;
2021-03-07 21:07:30 +01:00
} else if ( it - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) ) {
2017-03-05 16:44:50 +01:00
dd [ " type " ] = " visual_script_variable_drag " ;
dd [ " variable " ] = type ;
2021-03-07 21:07:30 +01:00
} else if ( it - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) - > get_next ( ) ) {
2017-03-05 16:44:50 +01:00
dd [ " type " ] = " visual_script_signal_drag " ;
dd [ " signal " ] = type ;
2016-08-03 00:11:05 +02:00
} else {
return Variant ( ) ;
}
Label * label = memnew ( Label ) ;
label - > set_text ( it - > get_text ( 0 ) ) ;
set_drag_preview ( label ) ;
return dd ;
}
return Variant ( ) ;
}
2017-03-05 16:44:50 +01:00
bool VisualScriptEditor : : can_drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) const {
if ( p_from = = graph ) {
2016-08-03 00:11:05 +02:00
Dictionary d = p_data ;
if ( d . has ( " type " ) & &
2017-03-05 16:44:50 +01:00
( String ( d [ " type " ] ) = = " visual_script_node_drag " | |
String ( d [ " type " ] ) = = " visual_script_function_drag " | |
String ( d [ " type " ] ) = = " visual_script_variable_drag " | |
String ( d [ " type " ] ) = = " visual_script_signal_drag " | |
String ( d [ " type " ] ) = = " obj_property " | |
String ( d [ " type " ] ) = = " resource " | |
String ( d [ " type " ] ) = = " files " | |
String ( d [ " type " ] ) = = " nodes " ) ) {
if ( String ( d [ " type " ] ) = = " obj_property " ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
const_cast < VisualScriptEditor * > ( this ) - > _show_hint ( vformat ( TTR ( " Hold %s to drop a Getter. Hold Shift to drop a generic signature. " ) , find_keycode_name ( Key : : META ) ) ) ;
2016-08-26 22:34:25 +02:00
# else
2017-03-05 16:44:50 +01:00
const_cast < VisualScriptEditor * > ( this ) - > _show_hint ( TTR ( " Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature. " ) ) ;
2016-08-26 22:34:25 +02:00
# endif
2017-03-05 16:44:50 +01:00
}
2016-08-26 22:34:25 +02:00
2017-03-05 16:44:50 +01:00
if ( String ( d [ " type " ] ) = = " nodes " ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
const_cast < VisualScriptEditor * > ( this ) - > _show_hint ( vformat ( TTR ( " Hold %s to drop a simple reference to the node. " ) , find_keycode_name ( Key : : META ) ) ) ;
2016-08-03 16:28:20 +02:00
# else
2017-03-05 16:44:50 +01:00
const_cast < VisualScriptEditor * > ( this ) - > _show_hint ( TTR ( " Hold Ctrl to drop a simple reference to the node. " ) ) ;
2016-08-03 16:28:20 +02:00
# endif
2017-03-05 16:44:50 +01:00
}
2016-08-06 03:46:45 +02:00
2017-03-05 16:44:50 +01:00
if ( String ( d [ " type " ] ) = = " visual_script_variable_drag " ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
const_cast < VisualScriptEditor * > ( this ) - > _show_hint ( vformat ( TTR ( " Hold %s to drop a Variable Setter. " ) , find_keycode_name ( Key : : META ) ) ) ;
2016-08-06 03:46:45 +02:00
# else
2017-03-05 16:44:50 +01:00
const_cast < VisualScriptEditor * > ( this ) - > _show_hint ( TTR ( " Hold Ctrl to drop a Variable Setter. " ) ) ;
2016-08-06 03:46:45 +02:00
# endif
2017-03-05 16:44:50 +01:00
}
2016-08-03 16:28:20 +02:00
2017-03-05 16:44:50 +01:00
return true ;
2016-08-03 16:28:20 +02:00
}
2016-08-03 00:11:05 +02:00
}
return false ;
}
2016-08-03 16:28:20 +02:00
2017-03-05 16:44:50 +01:00
static Node * _find_script_node ( Node * p_edited_scene , Node * p_current_node , const Ref < Script > & script ) {
2020-05-14 16:41:43 +02:00
if ( p_edited_scene ! = p_current_node & & p_current_node - > get_owner ( ) ! = p_edited_scene ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 16:28:20 +02:00
Ref < Script > scr = p_current_node - > get_script ( ) ;
2020-05-14 16:41:43 +02:00
if ( scr . is_valid ( ) & & scr = = script ) {
2016-08-03 16:28:20 +02:00
return p_current_node ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 16:28:20 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_current_node - > get_child_count ( ) ; i + + ) {
Node * n = _find_script_node ( p_edited_scene , p_current_node - > get_child ( i ) , script ) ;
2020-05-14 16:41:43 +02:00
if ( n ) {
2016-08-03 16:28:20 +02:00
return n ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 16:28:20 +02:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2016-08-03 16:28:20 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) {
2017-09-09 00:24:54 +02:00
if ( p_from ! = graph ) {
return ;
}
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
Dictionary d = p_data ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
if ( ! d . has ( " type " ) ) {
return ;
}
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " visual_script_node_drag " ) {
if ( ! d . has ( " node_type " ) | | String ( d [ " node_type " ] ) = = " Null " ) {
return ;
}
2016-08-04 05:05:35 +02:00
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-03 00:11:05 +02:00
2021-06-23 12:11:06 +02:00
int new_id = _create_new_node_from_name ( d [ " node_type " ] , pos ) ;
2017-09-09 00:24:54 +02:00
Node * node = graph - > get_node ( itos ( new_id ) ) ;
if ( node ) {
graph - > set_selected ( node ) ;
_node_selected ( node ) ;
2016-08-03 00:11:05 +02:00
}
2017-09-09 00:24:54 +02:00
}
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " visual_script_variable_drag " ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
bool use_set = Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ;
2016-08-06 03:46:45 +02:00
# else
2021-08-13 23:31:57 +02:00
bool use_set = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2016-08-06 03:46:45 +02:00
# endif
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptNode > vnode ;
if ( use_set ) {
2021-11-06 12:31:50 +01:00
Ref < VisualScriptPropertySet > pset ;
pset . instantiate ( ) ;
vnode = pset ;
2017-09-09 00:24:54 +02:00
} else {
2021-11-06 12:31:50 +01:00
Ref < VisualScriptPropertyGet > pget ;
pget . instantiate ( ) ;
vnode = pget ;
2017-09-09 00:24:54 +02:00
}
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
int new_id = script - > get_available_id ( ) ;
undo_redo - > create_action ( TTR ( " Add Node " ) ) ;
2021-11-06 12:31:50 +01:00
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_property " , d [ " variable " ] ) ;
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_base_script " , script - > get_path ( ) ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , vnode , pos ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
Node * node = graph - > get_node ( itos ( new_id ) ) ;
if ( node ) {
graph - > set_selected ( node ) ;
_node_selected ( node ) ;
2016-08-03 00:11:05 +02:00
}
2017-09-09 00:24:54 +02:00
}
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " visual_script_function_drag " ) {
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-26 22:34:25 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptFunctionCall > vnode ;
2021-06-18 00:03:09 +02:00
vnode . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
vnode - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_SELF ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
int new_id = script - > get_available_id ( ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Node " ) ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , vnode , pos ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_base_type " , script - > get_instance_base_type ( ) ) ;
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_function " , d [ " function " ] ) ;
2016-08-29 01:57:27 +02:00
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
Node * node = graph - > get_node ( itos ( new_id ) ) ;
if ( node ) {
graph - > set_selected ( node ) ;
_node_selected ( node ) ;
2016-08-03 00:11:05 +02:00
}
2017-09-09 00:24:54 +02:00
}
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " visual_script_signal_drag " ) {
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptEmitSignal > vnode ;
2021-06-18 00:03:09 +02:00
vnode . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
vnode - > set_signal ( d [ " signal " ] ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
int new_id = script - > get_available_id ( ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Node " ) ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , vnode , pos ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2016-08-03 00:11:05 +02:00
2017-09-09 00:24:54 +02:00
Node * node = graph - > get_node ( itos ( new_id ) ) ;
if ( node ) {
graph - > set_selected ( node ) ;
_node_selected ( node ) ;
2016-08-29 01:57:27 +02:00
}
2017-09-09 00:24:54 +02:00
}
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " resource " ) {
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptPreload > prnode ;
2021-06-18 00:03:09 +02:00
prnode . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
prnode - > set_preload ( d [ " resource " ] ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
int new_id = script - > get_available_id ( ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Preload Node " ) ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , prnode , pos ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
Node * node = graph - > get_node ( itos ( new_id ) ) ;
if ( node ) {
graph - > set_selected ( node ) ;
_node_selected ( node ) ;
2016-08-29 01:57:27 +02:00
}
2017-09-09 00:24:54 +02:00
}
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " files " ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
bool use_preload = Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ;
2021-07-18 14:52:55 +02:00
# else
2021-08-13 23:31:57 +02:00
bool use_preload = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2021-07-18 14:52:55 +02:00
# endif
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
Array files = d [ " files " ] ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
List < int > new_ids ;
int new_id = script - > get_available_id ( ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
if ( files . size ( ) ) {
2021-07-25 13:47:57 +02:00
undo_redo - > create_action ( TTR ( " Add Node(s) " ) ) ;
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
Ref < Resource > res = ResourceLoader : : load ( files [ i ] ) ;
2020-05-14 16:41:43 +02:00
if ( ! res . is_valid ( ) ) {
2017-09-09 00:24:54 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2021-07-18 14:52:55 +02:00
Ref < Script > drop_script = ResourceLoader : : load ( files [ i ] ) ;
if ( drop_script . is_valid ( ) & & drop_script - > is_tool ( ) & & drop_script - > get_instance_base_type ( ) = = " VisualScriptCustomNode " & & ! use_preload ) {
Ref < VisualScriptCustomNode > vscn ;
vscn . instantiate ( ) ;
vscn - > set_script ( drop_script ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , vscn , pos ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
} else {
Ref < VisualScriptPreload > prnode ;
prnode . instantiate ( ) ;
prnode - > set_preload ( res ) ;
2016-08-29 01:57:27 +02:00
2021-07-18 14:52:55 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , prnode , pos ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
}
2017-09-09 00:24:54 +02:00
new_ids . push_back ( new_id ) ;
new_id + + ;
2021-06-23 12:11:06 +02:00
pos + = Vector2 ( 20 , 20 ) ;
2016-08-29 01:57:27 +02:00
}
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
}
2021-07-16 05:45:57 +02:00
for ( int & E : new_ids ) {
Node * node = graph - > get_node ( itos ( E ) ) ;
2017-09-09 00:24:54 +02:00
if ( node ) {
graph - > set_selected ( node ) ;
_node_selected ( node ) ;
2016-08-03 00:11:05 +02:00
}
}
2017-09-09 00:24:54 +02:00
}
2016-08-29 01:57:27 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " nodes " ) {
Node * sn = _find_script_node ( get_tree ( ) - > get_edited_scene_root ( ) , get_tree ( ) - > get_edited_scene_root ( ) , script ) ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
if ( ! sn ) {
2019-10-29 13:57:45 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( vformat ( TTR ( " Can't drop nodes because script '%s' is not used in this scene. " ) , get_name ( ) ) ) ;
2017-09-09 00:24:54 +02:00
return ;
}
2016-08-03 16:28:20 +02:00
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
bool use_node = Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ;
2016-08-26 22:34:25 +02:00
# else
2021-08-13 23:31:57 +02:00
bool use_node = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2016-08-26 22:34:25 +02:00
# endif
2017-09-09 00:24:54 +02:00
Array nodes = d [ " nodes " ] ;
2016-08-03 16:28:20 +02:00
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Node(s) From Tree " ) ) ;
int base_id = script - > get_available_id ( ) ;
2016-08-03 16:28:20 +02:00
2021-06-25 20:03:13 +02:00
if ( use_node | | nodes . size ( ) > 1 ) {
for ( int i = 0 ; i < nodes . size ( ) ; i + + ) {
NodePath np = nodes [ i ] ;
Node * node = get_node ( np ) ;
if ( ! node ) {
continue ;
}
2016-08-03 16:28:20 +02:00
2021-06-25 20:03:13 +02:00
Ref < VisualScriptNode > n ;
2016-08-26 22:34:25 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptSceneNode > scene_node ;
2021-06-18 00:03:09 +02:00
scene_node . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
scene_node - > set_node_path ( sn - > get_path_to ( node ) ) ;
n = scene_node ;
2016-08-26 22:34:25 +02:00
2021-06-25 20:03:13 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , base_id , n , pos ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , base_id ) ;
base_id + + ;
pos + = Vector2 ( 25 , 25 ) ;
}
2016-08-03 16:28:20 +02:00
2021-06-25 20:03:13 +02:00
} else {
NodePath np = nodes [ 0 ] ;
Node * node = get_node ( np ) ;
drop_position = pos ;
drop_node = node ;
drop_path = sn - > get_path_to ( node ) ;
2021-11-20 13:52:37 +01:00
new_connect_node_select - > select_from_instance ( node , false ) ;
2016-08-03 16:28:20 +02:00
}
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
}
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
if ( String ( d [ " type " ] ) = = " obj_property " ) {
Node * sn = _find_script_node ( get_tree ( ) - > get_edited_scene_root ( ) , get_tree ( ) - > get_edited_scene_root ( ) , script ) ;
2016-08-03 16:28:20 +02:00
2021-08-13 23:31:57 +02:00
if ( ! sn & & ! Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2019-10-29 13:57:45 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( vformat ( TTR ( " Can't drop properties because script '%s' is not used in this scene. \n Drop holding 'Shift' to just copy the signature. " ) , get_name ( ) ) ) ;
2017-09-09 00:24:54 +02:00
return ;
}
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
Object * obj = d [ " object " ] ;
2016-08-03 16:28:20 +02:00
2020-05-14 16:41:43 +02:00
if ( ! obj ) {
2017-09-09 00:24:54 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( p_point ) ;
2016-08-04 05:05:35 +02:00
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-13 23:31:57 +02:00
bool use_get = Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ;
2016-08-03 16:28:20 +02:00
# else
2021-08-13 23:31:57 +02:00
bool use_get = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2016-08-03 16:28:20 +02:00
# endif
2021-08-13 23:31:57 +02:00
if ( ! node | | Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2020-05-14 16:41:43 +02:00
if ( use_get ) {
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Getter Property " ) ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Setter Property " ) ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
int base_id = script - > get_available_id ( ) ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptNode > vnode ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
if ( ! use_get ) {
Ref < VisualScriptPropertySet > pset ;
2021-06-18 00:03:09 +02:00
pset . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
pset - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_INSTANCE ) ;
pset - > set_base_type ( obj - > get_class ( ) ) ;
vnode = pset ;
} else {
Ref < VisualScriptPropertyGet > pget ;
2021-06-18 00:03:09 +02:00
pget . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
pget - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_INSTANCE ) ;
pget - > set_base_type ( obj - > get_class ( ) ) ;
vnode = pget ;
}
2016-08-26 22:34:25 +02:00
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , base_id , vnode , pos ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_property " , d [ " property " ] ) ;
2021-11-06 12:31:50 +01:00
if ( ! obj - > get_script ( ) . is_null ( ) ) {
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_base_script " , Ref < Script > ( obj - > get_script ( ) ) - > get_path ( ) ) ;
}
2017-09-09 00:24:54 +02:00
if ( ! use_get ) {
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_default_input_value " , 0 , d [ " value " ] ) ;
}
2016-08-03 16:28:20 +02:00
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , base_id ) ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
} else {
2020-05-14 16:41:43 +02:00
if ( use_get ) {
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Getter Property " ) ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-09-09 00:24:54 +02:00
undo_redo - > create_action ( TTR ( " Add Setter Property " ) ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
int base_id = script - > get_available_id ( ) ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
Ref < VisualScriptNode > vnode ;
2016-08-03 16:28:20 +02:00
2017-09-09 00:24:54 +02:00
if ( ! use_get ) {
Ref < VisualScriptPropertySet > pset ;
2021-06-18 00:03:09 +02:00
pset . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
if ( sn = = node ) {
pset - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_SELF ) ;
2016-08-03 16:28:20 +02:00
} else {
2017-09-09 00:24:54 +02:00
pset - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_NODE_PATH ) ;
pset - > set_base_path ( sn - > get_path_to ( node ) ) ;
2016-08-26 22:34:25 +02:00
}
2017-09-09 00:24:54 +02:00
vnode = pset ;
} else {
Ref < VisualScriptPropertyGet > pget ;
2021-06-18 00:03:09 +02:00
pget . instantiate ( ) ;
2017-09-09 00:24:54 +02:00
if ( sn = = node ) {
pget - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_SELF ) ;
} else {
pget - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_NODE_PATH ) ;
pget - > set_base_path ( sn - > get_path_to ( node ) ) ;
}
vnode = pget ;
2016-08-03 16:28:20 +02:00
}
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , base_id , vnode , pos ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_property " , d [ " property " ] ) ;
2021-11-06 12:31:50 +01:00
if ( ! obj - > get_script ( ) . is_null ( ) ) {
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_base_script " , Ref < Script > ( obj - > get_script ( ) ) - > get_path ( ) ) ;
}
2017-09-09 00:24:54 +02:00
if ( ! use_get ) {
undo_redo - > add_do_method ( vnode . ptr ( ) , " set_default_input_value " , 0 , d [ " value " ] ) ;
}
2021-11-06 12:31:50 +01:00
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , base_id ) ;
2017-09-09 00:24:54 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2016-08-03 16:28:20 +02:00
}
2016-08-03 00:11:05 +02:00
}
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _draw_color_over_button ( Object * obj , Color p_color ) {
2017-08-24 22:58:51 +02:00
Button * button = Object : : cast_to < Button > ( obj ) ;
2020-05-14 16:41:43 +02:00
if ( ! button ) {
2016-08-26 22:34:25 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-26 22:34:25 +02:00
2021-07-17 23:22:52 +02:00
Ref < StyleBox > normal = get_theme_stylebox ( SNAME ( " normal " ) , SNAME ( " Button " ) ) ;
2017-03-05 16:44:50 +01:00
button - > draw_rect ( Rect2 ( normal - > get_offset ( ) , button - > get_size ( ) - normal - > get_minimum_size ( ) ) , p_color ) ;
2016-08-26 22:34:25 +02:00
}
2019-06-11 20:43:37 +02:00
void VisualScriptEditor : : _button_resource_previewed ( const String & p_path , const Ref < Texture2D > & p_preview , const Ref < Texture2D > & p_small_preview , Variant p_ud ) {
2017-03-05 16:44:50 +01:00
Array ud = p_ud ;
ERR_FAIL_COND ( ud . size ( ) ! = 2 ) ;
2016-08-26 22:34:25 +02:00
ObjectID id = ud [ 0 ] ;
Object * obj = ObjectDB : : get_instance ( id ) ;
2020-05-14 16:41:43 +02:00
if ( ! obj ) {
2016-08-26 22:34:25 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-26 22:34:25 +02:00
2017-08-24 22:58:51 +02:00
Button * b = Object : : cast_to < Button > ( obj ) ;
2016-08-26 22:34:25 +02:00
ERR_FAIL_COND ( ! b ) ;
if ( p_preview . is_null ( ) ) {
b - > set_text ( ud [ 1 ] ) ;
} else {
b - > set_icon ( p_preview ) ;
}
}
2016-08-03 00:11:05 +02:00
/////////////////////////
void VisualScriptEditor : : apply_code ( ) {
}
2022-05-03 01:43:50 +02:00
Ref < Resource > VisualScriptEditor : : get_edited_resource ( ) const {
2016-08-03 00:11:05 +02:00
return script ;
}
2022-05-03 01:43:50 +02:00
void VisualScriptEditor : : set_edited_resource ( const Ref < Resource > & p_res ) {
2019-11-20 10:09:59 +01:00
ERR_FAIL_COND ( script . is_valid ( ) ) ;
ERR_FAIL_COND ( p_res . is_null ( ) ) ;
2018-05-28 17:52:28 +02:00
script = p_res ;
signal_editor - > script = script ;
2017-03-05 16:44:50 +01:00
signal_editor - > undo_redo = undo_redo ;
2018-05-28 17:52:28 +02:00
variable_editor - > script = script ;
2017-03-05 16:44:50 +01:00
variable_editor - > undo_redo = undo_redo ;
2016-08-03 00:11:05 +02:00
2020-02-21 18:28:45 +01:00
script - > connect ( " node_ports_changed " , callable_mp ( this , & VisualScriptEditor : : _node_ports_changed ) ) ;
2016-08-03 00:11:05 +02:00
2019-09-13 21:14:12 +02:00
_update_graph ( ) ;
2021-07-17 23:22:52 +02:00
call_deferred ( SNAME ( " _update_members " ) ) ;
2016-08-03 00:11:05 +02:00
}
2019-11-20 10:09:59 +01:00
void VisualScriptEditor : : enable_editor ( ) {
}
2018-05-28 17:52:28 +02:00
Vector < String > VisualScriptEditor : : get_functions ( ) {
return Vector < String > ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : reload_text ( ) {
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
String VisualScriptEditor : : get_name ( ) {
2016-08-03 00:11:05 +02:00
String name ;
2021-11-06 02:15:19 +01:00
name = script - > get_path ( ) . get_file ( ) ;
if ( name . is_empty ( ) ) {
// This appears for newly created built-in scripts before saving the scene.
name = TTR ( " [unsaved] " ) ;
} else if ( script - > is_built_in ( ) ) {
const String & script_name = script - > get_name ( ) ;
2021-12-09 10:42:46 +01:00
if ( ! script_name . is_empty ( ) ) {
2021-11-06 02:15:19 +01:00
// If the built-in script has a custom resource name defined,
// display the built-in script name as follows: `ResourceName (scene_file.tscn)`
name = vformat ( " %s (%s) " , script_name , name . get_slice ( " :: " , 0 ) ) ;
2016-08-03 00:11:05 +02:00
}
2021-11-06 02:15:19 +01:00
}
if ( is_unsaved ( ) ) {
name + = " (*) " ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
return name ;
}
2020-03-12 13:37:40 +01:00
Ref < Texture2D > VisualScriptEditor : : get_theme_icon ( ) {
2021-12-02 13:01:49 +01:00
String icon_name = " VisualScript " ;
if ( script - > is_built_in ( ) ) {
icon_name + = " Internal " ;
}
2022-02-08 10:14:58 +01:00
if ( Control : : has_theme_icon ( icon_name , " EditorIcons " ) ) {
2022-01-15 04:22:18 +01:00
return Control : : get_theme_icon ( icon_name , SNAME ( " EditorIcons " ) ) ;
2021-12-02 13:01:49 +01:00
}
2021-07-17 23:22:52 +02:00
return Control : : get_theme_icon ( SNAME ( " VisualScript " ) , SNAME ( " EditorIcons " ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
bool VisualScriptEditor : : is_unsaved ( ) {
2020-07-23 14:21:28 +02:00
bool unsaved =
script - > is_edited ( ) | |
script - > are_subnodes_edited ( ) | |
2020-12-15 13:04:21 +01:00
script - > get_path ( ) . is_empty ( ) ; // In memory.
2020-07-23 14:21:28 +02:00
return unsaved ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Variant VisualScriptEditor : : get_edit_state ( ) {
2016-08-07 00:00:54 +02:00
Dictionary d ;
2017-03-05 16:44:50 +01:00
d [ " scroll " ] = graph - > get_scroll_ofs ( ) ;
d [ " zoom " ] = graph - > get_zoom ( ) ;
d [ " using_snap " ] = graph - > is_using_snap ( ) ;
d [ " snap " ] = graph - > get_snap ( ) ;
2016-08-07 00:00:54 +02:00
return d ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : set_edit_state ( const Variant & p_state ) {
2016-08-07 00:00:54 +02:00
Dictionary d = p_state ;
_update_graph ( ) ;
_update_members ( ) ;
if ( d . has ( " scroll " ) ) {
graph - > set_scroll_ofs ( d [ " scroll " ] ) ;
}
if ( d . has ( " zoom " ) ) {
graph - > set_zoom ( d [ " zoom " ] ) ;
}
if ( d . has ( " snap " ) ) {
graph - > set_snap ( d [ " snap " ] ) ;
}
if ( d . has ( " snap_enabled " ) ) {
graph - > set_use_snap ( d [ " snap_enabled " ] ) ;
}
2016-08-03 00:11:05 +02:00
}
2020-06-17 17:39:25 +02:00
void VisualScriptEditor : : _center_on_node ( int p_id ) {
2016-08-07 00:00:54 +02:00
Node * n = graph - > get_node ( itos ( p_id ) ) ;
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( n ) ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
// Clear selection.
2019-09-13 21:14:12 +02:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
GraphNode * gnd = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
2020-05-14 16:41:43 +02:00
if ( gnd ) {
2019-09-13 21:14:12 +02:00
gnd - > set_selected ( false ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
}
2016-08-07 00:00:54 +02:00
if ( gn ) {
gn - > set_selected ( true ) ;
2022-04-08 11:18:43 +02:00
Vector2 new_scroll = gn - > get_position_offset ( ) * graph - > get_zoom ( ) - graph - > get_size ( ) * 0.5 + gn - > get_size ( ) * 0.5 ;
2017-03-05 16:44:50 +01:00
graph - > set_scroll_ofs ( new_scroll ) ;
2020-06-17 17:39:25 +02:00
script - > set_scroll ( new_scroll / EDSCALE ) ;
2019-09-13 21:14:12 +02:00
script - > set_edited ( true ) ;
2016-08-07 00:00:54 +02:00
}
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : goto_line ( int p_line , bool p_with_error ) {
2020-06-17 17:39:25 +02:00
p_line + = 1 ; // Add one because script lines begin from 0.
2016-08-07 00:00:54 +02:00
2020-05-14 16:41:43 +02:00
if ( p_with_error ) {
2017-03-05 16:44:50 +01:00
error_line = p_line ;
2020-05-14 16:41:43 +02:00
}
2016-08-07 00:00:54 +02:00
2021-09-18 09:39:22 +02:00
if ( script - > has_node ( p_line ) ) {
_update_graph ( ) ;
_update_members ( ) ;
call_deferred ( SNAME ( " call_deferred " ) , " _center_on_node " , p_line ) ; // The editor might be just created and size might not exist yet.
2016-08-07 00:00:54 +02:00
}
2016-08-03 00:11:05 +02:00
}
2019-04-22 18:20:27 +02:00
void VisualScriptEditor : : set_executing_line ( int p_line ) {
// todo: add a way to show which node is executing right now.
}
void VisualScriptEditor : : clear_executing_line ( ) {
// todo: add a way to show which node is executing right now.
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : trim_trailing_whitespace ( ) {
2016-08-03 00:11:05 +02:00
}
2019-05-28 23:27:32 +02:00
void VisualScriptEditor : : insert_final_newline ( ) {
}
2017-04-17 15:46:00 +02:00
void VisualScriptEditor : : convert_indent_to_spaces ( ) {
}
void VisualScriptEditor : : convert_indent_to_tabs ( ) {
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : ensure_focus ( ) {
2016-08-07 00:00:54 +02:00
graph - > grab_focus ( ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : tag_saved_version ( ) {
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : reload ( bool p_soft ) {
2019-09-13 21:14:12 +02:00
_update_graph ( ) ;
2016-08-03 00:11:05 +02:00
}
2020-07-26 16:57:23 +02:00
Array VisualScriptEditor : : get_breakpoints ( ) {
Array breakpoints ;
2016-08-07 00:00:54 +02:00
List < StringName > functions ;
script - > get_function_list ( & functions ) ;
2021-07-16 05:45:57 +02:00
for ( int i = 0 ; i < functions . size ( ) ; i + + ) {
2016-08-07 00:00:54 +02:00
List < int > nodes ;
2020-06-17 17:39:25 +02:00
script - > get_node_list ( & nodes ) ;
2021-07-16 05:45:57 +02:00
for ( int & F : nodes ) {
Ref < VisualScriptNode > vsn = script - > get_node ( F ) ;
2016-08-07 00:00:54 +02:00
if ( vsn - > is_breakpoint ( ) ) {
2021-07-16 05:45:57 +02:00
breakpoints . push_back ( F - 1 ) ; // Subtract 1 because breakpoints in text start from zero.
2016-08-07 00:00:54 +02:00
}
}
}
2020-07-26 16:57:23 +02:00
return breakpoints ;
2016-08-03 00:11:05 +02:00
}
2020-02-17 22:06:54 +01:00
void VisualScriptEditor : : add_callback ( const String & p_function , PackedStringArray p_args ) {
2016-08-07 00:00:54 +02:00
if ( script - > has_function ( p_function ) ) {
_update_members ( ) ;
_update_graph ( ) ;
2020-06-17 17:39:25 +02:00
_center_on_node ( script - > get_function_node_id ( p_function ) ) ;
2016-08-07 00:00:54 +02:00
return ;
}
Ref < VisualScriptFunction > func ;
2021-06-18 00:03:09 +02:00
func . instantiate ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_args . size ( ) ; i + + ) {
2016-08-07 00:00:54 +02:00
String name = p_args [ i ] ;
2017-03-05 16:44:50 +01:00
Variant : : Type type = Variant : : NIL ;
2016-08-07 00:00:54 +02:00
2022-02-03 17:03:38 +01:00
if ( name . contains ( " : " ) ) {
2017-03-05 16:44:50 +01:00
String tt = name . get_slice ( " : " , 1 ) ;
name = name . get_slice ( " : " , 0 ) ;
for ( int j = 0 ; j < Variant : : VARIANT_MAX ; j + + ) {
2016-08-07 00:00:54 +02:00
String tname = Variant : : get_type_name ( Variant : : Type ( j ) ) ;
2017-03-05 16:44:50 +01:00
if ( tname = = tt ) {
type = Variant : : Type ( j ) ;
2016-08-07 00:00:54 +02:00
break ;
}
}
}
2017-03-05 16:44:50 +01:00
func - > add_argument ( type , name ) ;
2016-08-07 00:00:54 +02:00
}
2020-06-17 17:39:25 +02:00
int fn_id = script - > get_available_id ( ) ;
2016-08-07 00:00:54 +02:00
func - > set_name ( p_function ) ;
2020-06-17 17:39:25 +02:00
script - > add_function ( p_function , fn_id ) ;
script - > add_node ( fn_id , func ) ;
2016-08-07 00:00:54 +02:00
_update_members ( ) ;
_update_graph ( ) ;
2020-06-17 17:39:25 +02:00
_center_on_node ( script - > get_function_node_id ( p_function ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-05-28 16:20:38 +02:00
bool VisualScriptEditor : : show_members_overview ( ) {
return false ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : update_settings ( ) {
2016-08-07 00:00:54 +02:00
_update_graph ( ) ;
2016-08-03 00:11:05 +02:00
}
2016-08-07 00:00:54 +02:00
void VisualScriptEditor : : set_debugger_active ( bool p_active ) {
if ( ! p_active ) {
2017-03-05 16:44:50 +01:00
error_line = - 1 ;
2016-08-07 00:00:54 +02:00
_update_graph ( ) ; //clear line break
}
}
2016-08-03 00:11:05 +02:00
2021-05-13 21:50:25 +02:00
Control * VisualScriptEditor : : get_base_editor ( ) const {
return graph ;
}
2021-11-07 18:26:15 +01:00
void VisualScriptEditor : : set_tooltip_request_func ( const Callable & p_toolip_callback ) {
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
Control * VisualScriptEditor : : get_edit_menu ( ) {
2016-08-07 00:00:54 +02:00
return edit_menu ;
2016-08-03 00:11:05 +02:00
}
void VisualScriptEditor : : _change_base_type ( ) {
2019-05-18 09:59:50 +02:00
select_base_type - > popup_create ( true , true ) ;
2016-08-03 00:11:05 +02:00
}
2019-07-26 22:00:23 +02:00
void VisualScriptEditor : : _toggle_tool_script ( ) {
script - > set_tool_enabled ( ! script - > is_tool ( ) ) ;
}
2017-07-01 02:30:17 +02:00
void VisualScriptEditor : : clear_edit_menu ( ) {
memdelete ( edit_menu ) ;
2019-09-27 22:10:05 +02:00
memdelete ( members_section ) ;
2017-07-01 02:30:17 +02:00
}
2016-08-03 00:11:05 +02:00
void VisualScriptEditor : : _change_base_type_callback ( ) {
String bt = select_base_type - > get_selected_type ( ) ;
2021-12-09 10:42:46 +01:00
ERR_FAIL_COND ( bt . is_empty ( ) ) ;
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Change Base Type " ) ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( script . ptr ( ) , " set_instance_base_type " , bt ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_instance_base_type " , script - > get_instance_base_type ( ) ) ;
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _node_selected ( Node * p_node ) {
2016-08-03 00:11:05 +02:00
Ref < VisualScriptNode > vnode = p_node - > get_meta ( " __vnode " ) ;
2020-05-14 16:41:43 +02:00
if ( vnode . is_null ( ) ) {
2016-08-03 00:11:05 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
EditorNode : : get_singleton ( ) - > push_item ( vnode . ptr ( ) ) ; //edit node in inspector
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
static bool _get_out_slot ( const Ref < VisualScriptNode > & p_node , int p_slot , int & r_real_slot , bool & r_sequence ) {
if ( p_slot < p_node - > get_output_sequence_port_count ( ) ) {
r_sequence = true ;
r_real_slot = p_slot ;
2016-08-03 00:11:05 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
r_real_slot = p_slot - p_node - > get_output_sequence_port_count ( ) ;
r_sequence = false ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
return ( r_real_slot < p_node - > get_output_value_port_count ( ) ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
static bool _get_in_slot ( const Ref < VisualScriptNode > & p_node , int p_slot , int & r_real_slot , bool & r_sequence ) {
if ( p_slot = = 0 & & p_node - > has_input_sequence_port ( ) ) {
r_sequence = true ;
r_real_slot = 0 ;
2016-08-03 00:11:05 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
r_real_slot = p_slot - ( p_node - > has_input_sequence_port ( ) ? 1 : 0 ) ;
r_sequence = false ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
return r_real_slot < p_node - > get_input_value_port_count ( ) ;
2016-08-03 00:11:05 +02:00
}
void VisualScriptEditor : : _begin_node_move ( ) {
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Move Node(s) " ) ) ;
2016-08-03 00:11:05 +02:00
}
void VisualScriptEditor : : _end_node_move ( ) {
undo_redo - > commit_action ( ) ;
}
2020-06-17 17:39:25 +02:00
void VisualScriptEditor : : _move_node ( int p_id , const Vector2 & p_to ) {
if ( ! script - > has_node ( p_id ) ) {
2019-09-13 21:14:12 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
Node * node = graph - > get_node ( itos ( p_id ) ) ;
2020-05-14 16:41:43 +02:00
if ( Object : : cast_to < GraphNode > ( node ) ) {
2020-12-22 17:24:29 +01:00
Object : : cast_to < GraphNode > ( node ) - > set_position_offset ( p_to ) ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
script - > set_node_position ( p_id , p_to / EDSCALE ) ;
2016-08-03 00:11:05 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _node_moved ( Vector2 p_from , Vector2 p_to , int p_id ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( this , " _move_node " , p_id , p_to ) ;
undo_redo - > add_undo_method ( this , " _move_node " , p_id , p_from ) ;
2016-08-03 00:11:05 +02:00
}
void VisualScriptEditor : : _remove_node ( int p_id ) {
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Remove VisualScript Node " ) ) ;
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " remove_node " , p_id ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " add_node " , p_id , script - > get_node ( p_id ) , script - > get_node_position ( p_id ) ) ;
2016-08-03 00:11:05 +02:00
List < VisualScript : : SequenceConnection > sequence_conns ;
2020-06-17 17:39:25 +02:00
script - > get_sequence_connection_list ( & sequence_conns ) ;
2016-08-03 00:11:05 +02:00
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : SequenceConnection & E : sequence_conns ) {
2021-07-16 05:45:57 +02:00
if ( E . from_node = = p_id | | E . to_node = = p_id ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_connect " , E . from_node , E . from_output , E . to_node ) ;
2016-08-03 00:11:05 +02:00
}
}
List < VisualScript : : DataConnection > data_conns ;
2020-06-17 17:39:25 +02:00
script - > get_data_connection_list ( & data_conns ) ;
2016-08-03 00:11:05 +02:00
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : DataConnection & E : data_conns ) {
2021-07-16 05:45:57 +02:00
if ( E . from_node = = p_id | | E . to_node = = p_id ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , E . from_node , E . from_port , E . to_node , E . to_port ) ;
2016-08-03 00:11:05 +02:00
}
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2016-08-03 00:11:05 +02:00
undo_redo - > commit_action ( ) ;
}
2020-06-17 17:39:25 +02:00
void VisualScriptEditor : : _node_ports_changed ( int p_id ) {
2016-08-03 00:11:05 +02:00
_update_graph ( p_id ) ;
}
2020-06-17 17:39:25 +02:00
bool VisualScriptEditor : : node_has_sequence_connections ( int p_id ) {
2019-09-13 21:14:12 +02:00
List < VisualScript : : SequenceConnection > sequence_conns ;
2020-06-17 17:39:25 +02:00
script - > get_sequence_connection_list ( & sequence_conns ) ;
2019-09-13 21:14:12 +02:00
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : SequenceConnection & E : sequence_conns ) {
2021-07-16 05:45:57 +02:00
int from = E . from_node ;
int to = E . to_node ;
2019-09-13 21:14:12 +02:00
2020-05-14 16:41:43 +02:00
if ( to = = p_id | | from = = p_id ) {
2019-09-13 21:14:12 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
}
return false ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _graph_connected ( const String & p_from , int p_from_slot , const String & p_to , int p_to_slot ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > from_node = script - > get_node ( p_from . to_int ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! from_node . is_valid ( ) ) ;
bool from_seq ;
int from_port ;
2020-05-14 16:41:43 +02:00
if ( ! _get_out_slot ( from_node , p_from_slot , from_port , from_seq ) ) {
2018-09-13 03:38:39 +02:00
return ; //can't connect this, it's invalid
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > to_node = script - > get_node ( p_to . to_int ( ) ) ;
2016-08-03 00:11:05 +02:00
ERR_FAIL_COND ( ! to_node . is_valid ( ) ) ;
bool to_seq ;
int to_port ;
2020-05-14 16:41:43 +02:00
if ( ! _get_in_slot ( to_node , p_to_slot , to_port , to_seq ) ) {
2018-09-13 03:38:39 +02:00
return ; //can't connect this, it's invalid
2020-05-14 16:41:43 +02:00
}
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( from_seq ! = to_seq ) ;
2016-08-03 00:11:05 +02:00
2021-07-13 09:39:43 +02:00
// Checking to prevent warnings.
if ( from_seq ) {
if ( script - > has_sequence_connection ( p_from . to_int ( ) , from_port , p_to . to_int ( ) ) ) {
return ;
}
} else if ( script - > has_data_connection ( p_from . to_int ( ) , from_port , p_to . to_int ( ) , to_port ) ) {
return ;
}
// Preventing connection to itself.
if ( p_from . to_int ( ) = = p_to . to_int ( ) ) {
return ;
}
2020-06-17 17:39:25 +02:00
// Do all the checks here.
StringName func ; // This the func where we store the one the nodes at the end of the resolution on having multiple nodes.
2019-09-13 21:14:12 +02:00
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Connect Nodes " ) ) ;
2016-08-03 00:11:05 +02:00
if ( from_seq ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) ) ;
// This undo error on undo after move can't be removed without painful gymnastics
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_disconnect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2016-08-03 00:11:05 +02:00
} else {
2019-09-13 21:14:12 +02:00
bool converted = false ;
Ref < VisualScriptOperator > oper = to_node ;
if ( oper . is_valid ( ) & & oper - > get_typed ( ) = = Variant : : NIL ) {
2020-06-17 17:39:25 +02:00
// It's an operator Node and if the type is already nil
2019-09-13 21:14:12 +02:00
if ( from_node - > get_output_value_port_info ( from_port ) . type ! = Variant : : NIL ) {
oper - > set_typed ( from_node - > get_output_value_port_info ( from_port ) . type ) ;
}
}
Ref < VisualScriptOperator > operf = from_node ;
if ( operf . is_valid ( ) & & operf - > get_typed ( ) = = Variant : : NIL ) {
2020-06-17 17:39:25 +02:00
// It's an operator Node and if the type is already nil
2019-09-13 21:14:12 +02:00
if ( to_node - > get_input_value_port_info ( to_port ) . type ! = Variant : : NIL ) {
operf - > set_typed ( to_node - > get_input_value_port_info ( to_port ) . type ) ;
}
}
2020-06-17 17:39:25 +02:00
// Disconnect current, and connect the new one
if ( script - > is_input_value_port_connected ( p_to . to_int ( ) , to_port ) ) {
2019-09-13 21:14:12 +02:00
if ( can_swap & & data_disconnect_node = = p_to . to_int ( ) ) {
int conn_from ;
int conn_port ;
2020-06-17 17:39:25 +02:00
script - > get_input_value_port_connection_source ( p_to . to_int ( ) , to_port , & conn_from , & conn_port ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " data_disconnect " , conn_from , conn_port , p_to . to_int ( ) , to_port ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , conn_from , conn_port , data_disconnect_node , data_disconnect_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_disconnect " , conn_from , conn_port , data_disconnect_node , data_disconnect_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , conn_from , conn_port , p_to . to_int ( ) , to_port ) ;
2019-09-13 21:14:12 +02:00
can_swap = false ; // swapped
} else {
int conn_from ;
int conn_port ;
2020-06-17 17:39:25 +02:00
script - > get_input_value_port_connection_source ( p_to . to_int ( ) , to_port , & conn_from , & conn_port ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " data_disconnect " , conn_from , conn_port , p_to . to_int ( ) , to_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , conn_from , conn_port , p_to . to_int ( ) , to_port ) ;
2019-09-13 21:14:12 +02:00
}
}
if ( ! converted ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) , to_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_disconnect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) , to_port ) ;
2021-08-13 08:37:38 +02:00
// Update nodes in graph
2019-09-13 21:14:12 +02:00
undo_redo - > add_do_method ( this , " _update_graph " , p_from . to_int ( ) ) ;
undo_redo - > add_do_method ( this , " _update_graph " , p_to . to_int ( ) ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_from . to_int ( ) ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_to . to_int ( ) ) ;
} else {
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
}
}
undo_redo - > commit_action ( ) ;
}
void VisualScriptEditor : : _graph_disconnected ( const String & p_from , int p_from_slot , const String & p_to , int p_to_slot ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > from_node = script - > get_node ( p_from . to_int ( ) ) ;
2019-09-13 21:14:12 +02:00
ERR_FAIL_COND ( ! from_node . is_valid ( ) ) ;
bool from_seq ;
int from_port ;
2020-05-14 16:41:43 +02:00
if ( ! _get_out_slot ( from_node , p_from_slot , from_port , from_seq ) ) {
2020-06-17 17:39:25 +02:00
return ; // Can't connect this, it's invalid.
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > to_node = script - > get_node ( p_to . to_int ( ) ) ;
2019-09-13 21:14:12 +02:00
ERR_FAIL_COND ( ! to_node . is_valid ( ) ) ;
bool to_seq ;
int to_port ;
2020-05-14 16:41:43 +02:00
if ( ! _get_in_slot ( to_node , p_to_slot , to_port , to_seq ) ) {
2020-06-17 17:39:25 +02:00
return ; // Can't connect this, it's invalid.
2020-05-14 16:41:43 +02:00
}
2019-09-13 21:14:12 +02:00
ERR_FAIL_COND ( from_seq ! = to_seq ) ;
undo_redo - > create_action ( TTR ( " Disconnect Nodes " ) ) ;
if ( from_seq ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_disconnect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_connect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
2019-09-13 21:14:12 +02:00
} else {
can_swap = true ;
data_disconnect_node = p_to . to_int ( ) ;
data_disconnect_port = to_port ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " data_disconnect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) , to_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , p_from . to_int ( ) , from_port , p_to . to_int ( ) , to_port ) ;
// Update relevant nodes in the graph.
2019-09-13 21:14:12 +02:00
undo_redo - > add_do_method ( this , " _update_graph " , p_from . to_int ( ) ) ;
undo_redo - > add_do_method ( this , " _update_graph " , p_to . to_int ( ) ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_from . to_int ( ) ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , p_to . to_int ( ) ) ;
}
undo_redo - > commit_action ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _graph_connect_to_empty ( const String & p_from , int p_from_slot , const Vector2 & p_release_pos ) {
Node * node = graph - > get_node ( p_from ) ;
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( node ) ;
2020-05-14 16:41:43 +02:00
if ( ! gn ) {
2016-09-03 19:58:23 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-09-03 19:58:23 +02:00
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > vsn = script - > get_node ( p_from . to_int ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! vsn . is_valid ( ) ) {
2016-09-03 19:58:23 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2021-06-23 12:11:06 +02:00
if ( vsn - > get_output_value_port_count ( ) | | vsn - > get_output_sequence_port_count ( ) ) {
2020-06-17 17:39:25 +02:00
port_action_pos = p_release_pos ;
2021-04-05 14:09:59 +02:00
}
2016-08-24 00:29:07 +02:00
2018-05-13 05:34:35 +02:00
if ( p_from_slot < vsn - > get_output_sequence_port_count ( ) ) {
2017-03-05 16:44:50 +01:00
port_action_node = p_from . to_int ( ) ;
port_action_output = p_from_slot ;
2020-06-17 17:39:25 +02:00
_port_action_menu ( CREATE_ACTION ) ;
2016-09-03 19:58:23 +02:00
} else {
2017-03-05 16:44:50 +01:00
port_action_output = p_from_slot - vsn - > get_output_sequence_port_count ( ) ;
port_action_node = p_from . to_int ( ) ;
2020-06-17 17:39:25 +02:00
_port_action_menu ( CREATE_CALL_SET_GET ) ;
2016-09-03 19:58:23 +02:00
}
2016-08-24 00:29:07 +02:00
}
2022-05-13 15:04:37 +02:00
VisualScriptNode : : TypeGuess VisualScriptEditor : : _guess_output_type ( int p_port_action_node , int p_port_action_output , RBSet < int > & visited_nodes ) {
2016-09-03 19:58:23 +02:00
VisualScriptNode : : TypeGuess tg ;
2017-03-05 16:44:50 +01:00
tg . type = Variant : : NIL ;
2016-09-03 19:58:23 +02:00
2020-05-14 16:41:43 +02:00
if ( visited_nodes . has ( p_port_action_node ) ) {
2016-09-03 19:58:23 +02:00
return tg ; //no loop
2020-05-14 16:41:43 +02:00
}
2016-09-03 19:58:23 +02:00
2017-08-12 18:52:50 +02:00
visited_nodes . insert ( p_port_action_node ) ;
2016-09-03 19:58:23 +02:00
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > node = script - > get_node ( p_port_action_node ) ;
2016-09-03 19:58:23 +02:00
2021-07-13 09:39:43 +02:00
if ( ! node . is_valid ( ) | | node - > get_output_value_port_count ( ) < = p_port_action_output ) {
2016-09-03 19:58:23 +02:00
return tg ;
}
Vector < VisualScriptNode : : TypeGuess > in_guesses ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < node - > get_input_value_port_count ( ) ; i + + ) {
2016-09-03 19:58:23 +02:00
PropertyInfo pi = node - > get_input_value_port_info ( i ) ;
VisualScriptNode : : TypeGuess g ;
2017-03-05 16:44:50 +01:00
g . type = pi . type ;
2016-09-03 19:58:23 +02:00
2017-03-05 16:44:50 +01:00
if ( g . type = = Variant : : NIL | | g . type = = Variant : : OBJECT ) {
2020-06-17 17:39:25 +02:00
// Any or object input, must further guess what this is.
2016-09-03 19:58:23 +02:00
int from_node ;
int from_port ;
2020-06-17 17:39:25 +02:00
if ( script - > get_input_value_port_connection_source ( p_port_action_node , i , & from_node , & from_port ) ) {
2017-03-05 16:44:50 +01:00
g = _guess_output_type ( from_node , from_port , visited_nodes ) ;
2016-09-03 19:58:23 +02:00
} else {
Variant defval = node - > get_default_input_value ( i ) ;
2017-03-05 16:44:50 +01:00
if ( defval . get_type ( ) = = Variant : : OBJECT ) {
2016-09-03 19:58:23 +02:00
Object * obj = defval ;
if ( obj ) {
2017-03-05 16:44:50 +01:00
g . type = Variant : : OBJECT ;
2017-07-01 02:30:17 +02:00
g . gdclass = obj - > get_class ( ) ;
2017-03-05 16:44:50 +01:00
g . script = obj - > get_script ( ) ;
2016-09-03 19:58:23 +02:00
}
}
}
}
in_guesses . push_back ( g ) ;
}
2017-11-25 04:07:54 +01:00
return node - > guess_output_type ( in_guesses . ptrw ( ) , p_port_action_output ) ;
2016-09-03 19:58:23 +02:00
}
2020-06-17 17:39:25 +02:00
void VisualScriptEditor : : _port_action_menu ( int p_option ) {
2022-05-13 15:04:37 +02:00
RBSet < int > vn ;
2016-09-03 19:58:23 +02:00
2017-03-05 16:44:50 +01:00
switch ( p_option ) {
2018-05-13 05:34:35 +02:00
case CREATE_CALL_SET_GET : {
2016-09-03 19:58:23 +02:00
Ref < VisualScriptFunctionCall > n ;
2021-06-18 00:03:09 +02:00
n . instantiate ( ) ;
2016-09-03 19:58:23 +02:00
2017-03-05 16:44:50 +01:00
VisualScriptNode : : TypeGuess tg = _guess_output_type ( port_action_node , port_action_output , vn ) ;
2016-09-03 19:58:23 +02:00
2018-05-13 05:34:35 +02:00
if ( tg . gdclass ! = StringName ( ) ) {
n - > set_base_type ( tg . gdclass ) ;
} else {
n - > set_base_type ( " Object " ) ;
}
2019-09-13 21:14:12 +02:00
String type_string ;
2021-11-20 13:52:37 +01:00
String base_script = " " ;
2020-06-17 17:39:25 +02:00
if ( script - > get_node ( port_action_node ) - > get_output_value_port_count ( ) > 0 ) {
type_string = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint_string ;
2021-11-20 13:52:37 +01:00
VisualScriptFunctionCall * vsfc = Object : : cast_to < VisualScriptFunctionCall > ( * script - > get_node ( port_action_node ) ) ;
if ( vsfc ) {
base_script = vsfc - > get_base_script ( ) ;
} else {
VisualScriptPropertyGet * vspg = Object : : cast_to < VisualScriptPropertyGet > ( * script - > get_node ( port_action_node ) ) ;
if ( vspg ) {
base_script = vspg - > get_base_script ( ) ;
} else {
VisualScriptPropertySet * vsps = Object : : cast_to < VisualScriptPropertySet > ( * script - > get_node ( port_action_node ) ) ;
if ( vsps ) {
base_script = vsps - > get_base_script ( ) ;
}
}
}
2019-09-13 21:14:12 +02:00
}
2018-05-13 05:34:35 +02:00
if ( tg . type = = Variant : : OBJECT ) {
2016-09-03 19:58:23 +02:00
if ( tg . script . is_valid ( ) ) {
2021-11-20 13:52:37 +01:00
new_connect_node_select - > select_from_script ( tg . script ) ;
} else if ( type_string ! = String ( ) ) {
new_connect_node_select - > select_from_base_type ( type_string , base_script ) ;
2016-09-03 19:58:23 +02:00
} else {
2021-11-20 13:52:37 +01:00
new_connect_node_select - > select_from_base_type ( n - > get_base_type ( ) , base_script ) ;
2016-09-03 19:58:23 +02:00
}
2018-05-13 05:34:35 +02:00
} else if ( tg . type = = Variant : : NIL ) {
2021-11-20 13:52:37 +01:00
new_connect_node_select - > select_from_base_type ( " " , base_script ) ;
2016-09-03 19:58:23 +02:00
} else {
2018-05-13 05:34:35 +02:00
new_connect_node_select - > select_from_basic_type ( tg . type ) ;
2016-09-03 19:58:23 +02:00
}
2020-06-17 17:39:25 +02:00
// Ensure that the dialog fits inside the graph.
2019-09-13 21:14:12 +02:00
Vector2 pos = mouse_up_position ;
Size2 bounds = graph - > get_global_position ( ) + graph - > get_size ( ) - new_connect_node_select - > get_size ( ) ;
pos . x = pos . x > bounds . x ? bounds . x : pos . x ;
pos . y = pos . y > bounds . y ? bounds . y : pos . y ;
new_connect_node_select - > set_position ( pos ) ;
2016-09-03 19:58:23 +02:00
} break ;
2018-05-13 05:34:35 +02:00
case CREATE_ACTION : {
2017-03-05 16:44:50 +01:00
VisualScriptNode : : TypeGuess tg = _guess_output_type ( port_action_node , port_action_output , vn ) ;
2019-09-13 21:14:12 +02:00
PropertyInfo property_info ;
2020-06-17 17:39:25 +02:00
if ( script - > get_node ( port_action_node ) - > get_output_value_port_count ( ) > 0 ) {
property_info = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) ;
2019-09-13 21:14:12 +02:00
}
2017-03-05 16:44:50 +01:00
if ( tg . type = = Variant : : OBJECT ) {
2021-12-09 10:42:46 +01:00
if ( property_info . type = = Variant : : OBJECT & & ! property_info . hint_string . is_empty ( ) ) {
2018-05-13 05:34:35 +02:00
new_connect_node_select - > select_from_action ( property_info . hint_string ) ;
2016-09-03 19:58:23 +02:00
} else {
2018-05-13 05:34:35 +02:00
new_connect_node_select - > select_from_action ( " " ) ;
2016-09-03 19:58:23 +02:00
}
2018-05-13 05:34:35 +02:00
} else if ( tg . type = = Variant : : NIL ) {
new_connect_node_select - > select_from_action ( " " ) ;
2016-09-03 19:58:23 +02:00
} else {
2018-05-13 05:34:35 +02:00
new_connect_node_select - > select_from_action ( Variant : : get_type_name ( tg . type ) ) ;
2016-09-03 19:58:23 +02:00
}
2020-06-17 17:39:25 +02:00
// Ensure that the dialog fits inside the graph.
2019-09-13 21:14:12 +02:00
Vector2 pos = mouse_up_position ;
Size2 bounds = graph - > get_global_position ( ) + graph - > get_size ( ) - new_connect_node_select - > get_size ( ) ;
pos . x = pos . x > bounds . x ? bounds . x : pos . x ;
pos . y = pos . y > bounds . y ? bounds . y : pos . y ;
new_connect_node_select - > set_position ( pos ) ;
2016-09-03 19:58:23 +02:00
} break ;
2018-05-13 05:34:35 +02:00
}
}
2016-09-03 19:58:23 +02:00
2018-05-13 05:34:35 +02:00
void VisualScriptEditor : : connect_data ( Ref < VisualScriptNode > vnode_old , Ref < VisualScriptNode > vnode , int new_id ) {
undo_redo - > create_action ( TTR ( " Connect Node Data " ) ) ;
VisualScriptReturn * vnode_return = Object : : cast_to < VisualScriptReturn > ( vnode . ptr ( ) ) ;
2020-04-02 01:20:12 +02:00
if ( vnode_return ! = nullptr & & vnode_old - > get_output_value_port_count ( ) > 0 ) {
2018-05-13 05:34:35 +02:00
vnode_return - > set_enable_return_value ( true ) ;
}
if ( vnode_old - > get_output_value_port_count ( ) < = 0 ) {
undo_redo - > commit_action ( ) ;
return ;
}
if ( vnode - > get_input_value_port_count ( ) < = 0 ) {
undo_redo - > commit_action ( ) ;
return ;
}
int port = port_action_output ;
int value_count = vnode_old - > get_output_value_port_count ( ) ;
if ( port > = value_count ) {
port = 0 ;
}
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , port_action_node , port , new_id , 0 ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_disconnect " , port_action_node , port , new_id , 0 ) ;
2018-05-13 05:34:35 +02:00
undo_redo - > commit_action ( ) ;
}
2016-09-03 19:58:23 +02:00
2018-07-25 20:49:41 +02:00
void VisualScriptEditor : : _selected_connect_node ( const String & p_text , const String & p_category , const bool p_connecting ) {
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-11-20 13:52:37 +01:00
bool held_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( Key : : META ) ;
# else
bool held_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
# endif
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_pos_in_graph ( port_action_pos ) ;
2016-09-03 19:58:23 +02:00
2022-05-13 15:04:37 +02:00
RBSet < int > vn ;
2021-11-20 13:52:37 +01:00
bool port_node_exists = true ;
2016-09-03 19:58:23 +02:00
2021-06-25 20:03:13 +02:00
if ( drop_position ! = Vector2 ( ) ) {
pos = drop_position ;
}
drop_position = Vector2 ( ) ;
2021-11-20 13:52:37 +01:00
Ref < VisualScriptNode > vnode ;
Ref < VisualScriptNode > vnode_old ;
if ( port_node_exists & & p_connecting ) {
vnode_old = script - > get_node ( port_action_node ) ;
}
2018-05-13 05:34:35 +02:00
2021-11-20 13:52:37 +01:00
if ( p_category . begins_with ( " VisualScriptNode " ) ) {
Ref < VisualScriptNode > n = VisualScriptLanguage : : singleton - > create_node_from_name ( p_text ) ;
2018-05-13 05:34:35 +02:00
2021-11-20 13:52:37 +01:00
if ( Object : : cast_to < VisualScriptTypeCast > ( n . ptr ( ) ) & & vnode_old . is_valid ( ) ) {
2019-09-13 21:14:12 +02:00
Variant : : Type type = vnode_old - > get_output_value_port_info ( port_action_output ) . type ;
String hint_name = vnode_old - > get_output_value_port_info ( port_action_output ) . hint_string ;
2018-05-13 05:34:35 +02:00
if ( type = = Variant : : OBJECT ) {
2021-11-20 13:52:37 +01:00
Object : : cast_to < VisualScriptTypeCast > ( n . ptr ( ) ) - > set_base_type ( hint_name ) ;
2018-05-13 05:34:35 +02:00
} else if ( type = = Variant : : NIL ) {
2021-11-20 13:52:37 +01:00
Object : : cast_to < VisualScriptTypeCast > ( n . ptr ( ) ) - > set_base_type ( " " ) ;
2016-09-03 19:58:23 +02:00
} else {
2021-11-20 13:52:37 +01:00
Object : : cast_to < VisualScriptTypeCast > ( n . ptr ( ) ) - > set_base_type ( Variant : : get_type_name ( type ) ) ;
2016-09-03 19:58:23 +02:00
}
2018-05-13 05:34:35 +02:00
}
2021-11-20 13:52:37 +01:00
vnode = n ;
2018-05-13 05:34:35 +02:00
}
2016-09-03 19:58:23 +02:00
2021-11-20 13:52:37 +01:00
if ( p_category = = String ( " Class " ) & & ! p_connecting ) {
Ref < VisualScriptFunctionCall > n ;
n . instantiate ( ) ;
n - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_SINGLETON ) ;
n - > set_singleton ( " ClassDB " ) ;
n - > set_function ( " instantiate " ) ;
// Did not find a way to edit the input port value
vnode = n ;
} else if ( p_category = = String ( " class_method " ) ) {
2018-05-13 05:34:35 +02:00
Ref < VisualScriptFunctionCall > n ;
2021-06-18 00:03:09 +02:00
n . instantiate ( ) ;
2021-06-25 20:03:13 +02:00
if ( ! drop_path . is_empty ( ) ) {
if ( drop_path = = " . " ) {
n - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_SELF ) ;
} else {
n - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_NODE_PATH ) ;
n - > set_base_path ( drop_path ) ;
}
2022-03-30 18:42:17 +02:00
} else {
n - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_INSTANCE ) ;
2021-06-25 20:03:13 +02:00
}
if ( drop_node ) {
n - > set_base_type ( drop_node - > get_class ( ) ) ;
if ( drop_node - > get_script_instance ( ) ) {
n - > set_base_script ( drop_node - > get_script_instance ( ) - > get_script ( ) - > get_path ( ) ) ;
}
}
2018-05-13 05:34:35 +02:00
vnode = n ;
2021-11-20 13:52:37 +01:00
} else if ( p_category = = String ( " class_property " ) ) {
Vector < String > property_path = p_text . split ( " : " ) ;
if ( held_ctrl ) {
Ref < VisualScriptPropertySet > n ;
n . instantiate ( ) ;
n - > set_property ( property_path [ 1 ] ) ;
if ( ! drop_path . is_empty ( ) ) {
if ( drop_path = = " . " ) {
n - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_SELF ) ;
} else {
n - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_NODE_PATH ) ;
n - > set_base_path ( drop_path ) ;
}
2021-06-25 20:03:13 +02:00
}
2021-11-20 13:52:37 +01:00
if ( drop_node ) {
n - > set_base_type ( drop_node - > get_class ( ) ) ;
if ( drop_node - > get_script_instance ( ) ) {
n - > set_base_script ( drop_node - > get_script_instance ( ) - > get_script ( ) - > get_path ( ) ) ;
}
2021-06-25 20:03:13 +02:00
}
2021-11-20 13:52:37 +01:00
vnode = n ;
} else {
Ref < VisualScriptPropertyGet > n ;
n . instantiate ( ) ;
n - > set_property ( property_path [ 1 ] ) ;
if ( ! drop_path . is_empty ( ) ) {
if ( drop_path = = " . " ) {
n - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_SELF ) ;
} else {
n - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_NODE_PATH ) ;
n - > set_base_path ( drop_path ) ;
}
2021-06-25 20:03:13 +02:00
}
2021-11-20 13:52:37 +01:00
if ( drop_node ) {
n - > set_base_type ( drop_node - > get_class ( ) ) ;
if ( drop_node - > get_script_instance ( ) ) {
n - > set_base_script ( drop_node - > get_script_instance ( ) - > get_script ( ) - > get_path ( ) ) ;
}
2021-06-25 20:03:13 +02:00
}
2017-03-05 16:44:50 +01:00
vnode = n ;
2018-05-13 05:34:35 +02:00
}
2021-11-20 13:52:37 +01:00
} else if ( p_category = = String ( " class_constant " ) ) {
Vector < String > property_path = p_text . split ( " : " ) ;
if ( ClassDB : : class_exists ( property_path [ 0 ] ) ) {
Ref < VisualScriptClassConstant > n ;
2021-06-18 00:03:09 +02:00
n . instantiate ( ) ;
2021-11-20 13:52:37 +01:00
n - > set_base_type ( property_path [ 0 ] ) ;
n - > set_class_constant ( property_path [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
vnode = n ;
2021-11-20 13:52:37 +01:00
} else {
Ref < VisualScriptBasicTypeConstant > n ;
2021-06-18 00:03:09 +02:00
n . instantiate ( ) ;
2021-11-20 13:52:37 +01:00
if ( property_path [ 0 ] = = " Nil " ) {
n - > set_basic_type ( Variant : : NIL ) ;
} else if ( property_path [ 0 ] = = " bool " ) {
n - > set_basic_type ( Variant : : BOOL ) ;
} else if ( property_path [ 0 ] = = " int " ) {
n - > set_basic_type ( Variant : : INT ) ;
} else if ( property_path [ 0 ] = = " float " ) {
n - > set_basic_type ( Variant : : FLOAT ) ;
} else if ( property_path [ 0 ] = = " String " ) {
n - > set_basic_type ( Variant : : STRING ) ;
} else if ( property_path [ 0 ] = = " Vector2 " ) {
n - > set_basic_type ( Variant : : VECTOR2 ) ;
} else if ( property_path [ 0 ] = = " Vector2i " ) {
n - > set_basic_type ( Variant : : VECTOR2I ) ;
} else if ( property_path [ 0 ] = = " Rect2 " ) {
n - > set_basic_type ( Variant : : RECT2 ) ;
} else if ( property_path [ 0 ] = = " Rect2i " ) {
n - > set_basic_type ( Variant : : RECT2I ) ;
} else if ( property_path [ 0 ] = = " Transform2D " ) {
n - > set_basic_type ( Variant : : TRANSFORM2D ) ;
} else if ( property_path [ 0 ] = = " Vector3 " ) {
n - > set_basic_type ( Variant : : VECTOR3 ) ;
} else if ( property_path [ 0 ] = = " Vector3i " ) {
n - > set_basic_type ( Variant : : VECTOR3I ) ;
} else if ( property_path [ 0 ] = = " Plane " ) {
n - > set_basic_type ( Variant : : PLANE ) ;
} else if ( property_path [ 0 ] = = " ABB " ) {
n - > set_basic_type ( Variant : : AABB ) ;
} else if ( property_path [ 0 ] = = " Quaternion " ) {
n - > set_basic_type ( Variant : : QUATERNION ) ;
} else if ( property_path [ 0 ] = = " Basis " ) {
n - > set_basic_type ( Variant : : BASIS ) ;
} else if ( property_path [ 0 ] = = " Transform3D " ) {
n - > set_basic_type ( Variant : : TRANSFORM3D ) ;
} else if ( property_path [ 0 ] = = " Color " ) {
n - > set_basic_type ( Variant : : COLOR ) ;
} else if ( property_path [ 0 ] = = " RID " ) {
n - > set_basic_type ( Variant : : RID ) ;
} else if ( property_path [ 0 ] = = " Object " ) {
n - > set_basic_type ( Variant : : OBJECT ) ;
} else if ( property_path [ 0 ] = = " Callable " ) {
n - > set_basic_type ( Variant : : CALLABLE ) ;
} else if ( property_path [ 0 ] = = " Signal " ) {
n - > set_basic_type ( Variant : : SIGNAL ) ;
} else if ( property_path [ 0 ] = = " StringName " ) {
n - > set_basic_type ( Variant : : STRING_NAME ) ;
} else if ( property_path [ 0 ] = = " NodePath " ) {
n - > set_basic_type ( Variant : : NODE_PATH ) ;
} else if ( property_path [ 0 ] = = " Dictionary " ) {
n - > set_basic_type ( Variant : : DICTIONARY ) ;
} else if ( property_path [ 0 ] = = " Array " ) {
n - > set_basic_type ( Variant : : ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedByteArray " ) {
n - > set_basic_type ( Variant : : PACKED_BYTE_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedInt32Array " ) {
n - > set_basic_type ( Variant : : PACKED_INT32_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedInt64Array " ) {
n - > set_basic_type ( Variant : : PACKED_INT64_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedFloat32Array " ) {
n - > set_basic_type ( Variant : : PACKED_FLOAT32_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedStringArray " ) {
n - > set_basic_type ( Variant : : PACKED_STRING_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedVector2Array " ) {
n - > set_basic_type ( Variant : : PACKED_VECTOR2_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedVector3Array " ) {
n - > set_basic_type ( Variant : : PACKED_VECTOR3_ARRAY ) ;
} else if ( property_path [ 0 ] = = " PackedColorArray " ) {
n - > set_basic_type ( Variant : : PACKED_COLOR_ARRAY ) ;
}
n - > set_basic_type_constant ( property_path [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
vnode = n ;
2018-05-13 05:34:35 +02:00
}
2016-09-03 19:58:23 +02:00
2021-11-20 13:52:37 +01:00
} else if ( p_category = = String ( " class_signal " ) ) {
Vector < String > property_path = p_text . split ( " : " ) ;
ERR_FAIL_COND ( ! ( script - > has_custom_signal ( property_path [ 1 ] ) | | ClassDB : : has_signal ( script - > get_instance_base_type ( ) , property_path [ 1 ] ) ) ) ;
2019-09-13 21:14:12 +02:00
2021-11-20 13:52:37 +01:00
Ref < VisualScriptEmitSignal > n ;
n . instantiate ( ) ;
n - > set_signal ( property_path [ 1 ] ) ;
vnode = n ;
}
if ( vnode = = nullptr ) {
print_error ( " Category not handled: " + p_category . quote ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2019-10-15 20:42:48 +02:00
2022-02-19 20:33:27 +01:00
if ( Object : : cast_to < VisualScriptFunctionCall > ( vnode . ptr ( ) ) & & p_category ! = " Class " & & p_category ! = " VisualScriptNode " ) {
2021-11-20 13:52:37 +01:00
Vector < String > property_path = p_text . split ( " : " ) ;
String class_of_method = property_path [ 0 ] ;
String method_name = property_path [ 1 ] ;
2016-09-03 19:58:23 +02:00
2021-11-20 13:52:37 +01:00
Ref < VisualScriptFunctionCall > vsfc = vnode ;
vsfc - > set_function ( method_name ) ;
2018-05-13 05:34:35 +02:00
2019-09-13 21:14:12 +02:00
if ( port_node_exists & & p_connecting ) {
2019-05-12 09:27:05 +02:00
VisualScriptNode : : TypeGuess tg = _guess_output_type ( port_action_node , port_action_output , vn ) ;
2018-05-13 05:34:35 +02:00
2019-05-12 09:27:05 +02:00
if ( tg . type = = Variant : : OBJECT ) {
vsfc - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_INSTANCE ) ;
vsfc - > set_base_type ( String ( " " ) ) ;
if ( tg . gdclass ! = StringName ( ) ) {
vsfc - > set_base_type ( tg . gdclass ) ;
2020-06-17 17:39:25 +02:00
} else if ( script - > get_node ( port_action_node ) . is_valid ( ) ) {
PropertyHint hint = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint ;
String base_type = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint_string ;
2019-05-12 09:27:05 +02:00
2021-12-09 10:42:46 +01:00
if ( ! base_type . is_empty ( ) & & hint = = PROPERTY_HINT_TYPE_STRING ) {
2019-05-12 09:27:05 +02:00
vsfc - > set_base_type ( base_type ) ;
}
2021-11-20 13:52:37 +01:00
if ( method_name = = " call " | | method_name = = " call_deferred " ) {
2019-05-12 09:27:05 +02:00
vsfc - > set_function ( String ( " " ) ) ;
}
2018-05-13 05:34:35 +02:00
}
2019-05-12 09:27:05 +02:00
if ( tg . script . is_valid ( ) ) {
vsfc - > set_base_script ( tg . script - > get_path ( ) ) ;
2018-05-13 05:34:35 +02:00
}
2019-05-12 09:27:05 +02:00
} else if ( tg . type = = Variant : : NIL ) {
vsfc - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_INSTANCE ) ;
vsfc - > set_base_type ( String ( " " ) ) ;
} else {
vsfc - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_BASIC_TYPE ) ;
vsfc - > set_basic_type ( tg . type ) ;
2018-05-13 05:34:35 +02:00
}
}
2016-09-03 19:58:23 +02:00
}
2019-09-13 21:14:12 +02:00
if ( port_node_exists & & p_connecting ) {
2021-11-20 13:52:37 +01:00
if ( Object : : cast_to < VisualScriptPropertySet > ( vnode . ptr ( ) ) ) {
Ref < VisualScriptPropertySet > vsp = vnode ;
2016-09-03 19:58:23 +02:00
2019-05-12 09:27:05 +02:00
VisualScriptNode : : TypeGuess tg = _guess_output_type ( port_action_node , port_action_output , vn ) ;
if ( tg . type = = Variant : : OBJECT ) {
vsp - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_INSTANCE ) ;
vsp - > set_base_type ( String ( " " ) ) ;
if ( tg . gdclass ! = StringName ( ) ) {
vsp - > set_base_type ( tg . gdclass ) ;
2018-05-13 05:34:35 +02:00
2020-06-17 17:39:25 +02:00
} else if ( script - > get_node ( port_action_node ) . is_valid ( ) ) {
PropertyHint hint = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint ;
String base_type = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint_string ;
2018-05-13 05:34:35 +02:00
2021-12-09 10:42:46 +01:00
if ( ! base_type . is_empty ( ) & & hint = = PROPERTY_HINT_TYPE_STRING ) {
2019-05-12 09:27:05 +02:00
vsp - > set_base_type ( base_type ) ;
}
2018-05-13 05:34:35 +02:00
}
2019-05-12 09:27:05 +02:00
if ( tg . script . is_valid ( ) ) {
vsp - > set_base_script ( tg . script - > get_path ( ) ) ;
}
} else if ( tg . type = = Variant : : NIL ) {
vsp - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_INSTANCE ) ;
vsp - > set_base_type ( String ( " " ) ) ;
} else {
vsp - > set_call_mode ( VisualScriptPropertySet : : CALL_MODE_BASIC_TYPE ) ;
vsp - > set_basic_type ( tg . type ) ;
2018-05-13 05:34:35 +02:00
}
}
2021-11-20 13:52:37 +01:00
if ( Object : : cast_to < VisualScriptPropertyGet > ( vnode . ptr ( ) ) ) {
Ref < VisualScriptPropertyGet > vsp = vnode ;
2018-05-13 05:34:35 +02:00
2019-05-12 09:27:05 +02:00
VisualScriptNode : : TypeGuess tg = _guess_output_type ( port_action_node , port_action_output , vn ) ;
if ( tg . type = = Variant : : OBJECT ) {
vsp - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_INSTANCE ) ;
vsp - > set_base_type ( String ( " " ) ) ;
if ( tg . gdclass ! = StringName ( ) ) {
vsp - > set_base_type ( tg . gdclass ) ;
2020-06-17 17:39:25 +02:00
} else if ( script - > get_node ( port_action_node ) . is_valid ( ) ) {
PropertyHint hint = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint ;
String base_type = script - > get_node ( port_action_node ) - > get_output_value_port_info ( port_action_output ) . hint_string ;
2021-12-09 10:42:46 +01:00
if ( ! base_type . is_empty ( ) & & hint = = PROPERTY_HINT_TYPE_STRING ) {
2019-05-12 09:27:05 +02:00
vsp - > set_base_type ( base_type ) ;
}
2018-05-13 05:34:35 +02:00
}
2019-05-12 09:27:05 +02:00
if ( tg . script . is_valid ( ) ) {
vsp - > set_base_script ( tg . script - > get_path ( ) ) ;
}
} else if ( tg . type = = Variant : : NIL ) {
vsp - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_INSTANCE ) ;
vsp - > set_base_type ( String ( " " ) ) ;
} else {
vsp - > set_call_mode ( VisualScriptPropertyGet : : CALL_MODE_BASIC_TYPE ) ;
vsp - > set_basic_type ( tg . type ) ;
2018-05-13 05:34:35 +02:00
}
}
2016-09-03 19:58:23 +02:00
}
2021-11-20 13:52:37 +01:00
if ( vnode = = nullptr ) {
print_error ( " Not able to create node from category: \" " + p_category + " \" and text \" " + p_text + " \" Not created " ) ;
return ;
}
int new_id = script - > get_available_id ( ) ;
undo_redo - > create_action ( TTR ( " Add Node " ) ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , vnode , pos ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
undo_redo - > add_do_method ( this , " _update_graph " , new_id ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , new_id ) ;
undo_redo - > commit_action ( ) ;
port_action_new_node = new_id ;
String base_script = " " ;
String base_type = " " ;
2019-09-13 21:14:12 +02:00
if ( port_node_exists ) {
2021-11-20 13:52:37 +01:00
if ( vnode_old . is_valid ( ) ) {
if ( Object : : cast_to < VisualScriptTypeCast > ( vnode_old . ptr ( ) ) ) {
base_type = Object : : cast_to < VisualScriptTypeCast > ( vnode_old . ptr ( ) ) - > get_base_type ( ) ;
base_script = Object : : cast_to < VisualScriptTypeCast > ( vnode_old . ptr ( ) ) - > get_base_script ( ) ;
} else if ( Object : : cast_to < VisualScriptFunctionCall > ( vnode_old . ptr ( ) ) ) {
base_type = Object : : cast_to < VisualScriptFunctionCall > ( vnode_old . ptr ( ) ) - > get_base_type ( ) ;
base_script = Object : : cast_to < VisualScriptFunctionCall > ( vnode_old . ptr ( ) ) - > get_base_script ( ) ;
} else if ( Object : : cast_to < VisualScriptPropertySet > ( vnode_old . ptr ( ) ) ) {
base_type = Object : : cast_to < VisualScriptPropertySet > ( vnode_old . ptr ( ) ) - > get_base_type ( ) ;
base_script = Object : : cast_to < VisualScriptPropertySet > ( vnode_old . ptr ( ) ) - > get_base_script ( ) ;
} else if ( Object : : cast_to < VisualScriptPropertyGet > ( vnode_old . ptr ( ) ) ) {
base_type = Object : : cast_to < VisualScriptPropertyGet > ( vnode_old . ptr ( ) ) - > get_base_type ( ) ;
base_script = Object : : cast_to < VisualScriptPropertyGet > ( vnode_old . ptr ( ) ) - > get_base_script ( ) ;
}
}
Vector < String > property_path = p_text . split ( " : " ) ;
if ( ClassDB : : is_parent_class ( script - > get_instance_base_type ( ) , property_path [ 0 ] ) | | script - > get_path ( ) . ends_with ( property_path [ 0 ] . unquote ( ) ) ) {
if ( ! p_connecting ) {
base_type = script - > get_instance_base_type ( ) ;
base_script = script - > get_path ( ) ;
}
} else {
base_type = property_path [ 0 ] ;
base_script = " " ;
}
if ( drop_node ) {
Ref < Script > script = drop_node - > get_script ( ) ;
if ( script ! = nullptr ) {
base_script = script - > get_path ( ) ;
}
}
2019-09-13 21:14:12 +02:00
if ( vnode_old . is_valid ( ) & & p_connecting ) {
2021-11-20 13:52:37 +01:00
if ( base_type = = " " ) {
base_type = property_path [ 0 ] ;
} else if ( ClassDB : : is_parent_class ( property_path [ 0 ] , base_type ) ) {
base_type = property_path [ 0 ] ;
}
2019-09-13 21:14:12 +02:00
connect_seq ( vnode_old , vnode , port_action_new_node ) ;
connect_data ( vnode_old , vnode , port_action_new_node ) ;
}
2018-07-25 20:49:41 +02:00
}
2021-11-20 13:52:37 +01:00
if ( Object : : cast_to < VisualScriptTypeCast > ( vnode . ptr ( ) ) ) {
Object : : cast_to < VisualScriptTypeCast > ( vnode . ptr ( ) ) - > set_base_type ( base_type ) ;
Object : : cast_to < VisualScriptTypeCast > ( vnode . ptr ( ) ) - > set_base_script ( base_script ) ;
} else if ( Object : : cast_to < VisualScriptFunctionCall > ( vnode . ptr ( ) ) ) {
2022-03-30 18:42:17 +02:00
if ( base_type_map . has ( base_type ) ) {
Object : : cast_to < VisualScriptFunctionCall > ( vnode . ptr ( ) ) - > set_basic_type ( base_type_map [ base_type ] ) ;
Object : : cast_to < VisualScriptFunctionCall > ( vnode . ptr ( ) ) - > set_call_mode ( VisualScriptFunctionCall : : CALL_MODE_BASIC_TYPE ) ;
} else {
Object : : cast_to < VisualScriptFunctionCall > ( vnode . ptr ( ) ) - > set_base_type ( base_type ) ;
Object : : cast_to < VisualScriptFunctionCall > ( vnode . ptr ( ) ) - > set_base_script ( base_script ) ;
}
2021-11-20 13:52:37 +01:00
} else if ( Object : : cast_to < VisualScriptPropertySet > ( vnode . ptr ( ) ) ) {
Object : : cast_to < VisualScriptPropertySet > ( vnode . ptr ( ) ) - > set_base_type ( base_type ) ;
Object : : cast_to < VisualScriptPropertySet > ( vnode . ptr ( ) ) - > set_base_script ( base_script ) ;
} else if ( Object : : cast_to < VisualScriptPropertyGet > ( vnode . ptr ( ) ) ) {
Object : : cast_to < VisualScriptPropertyGet > ( vnode . ptr ( ) ) - > set_base_type ( base_type ) ;
Object : : cast_to < VisualScriptPropertyGet > ( vnode . ptr ( ) ) - > set_base_script ( base_script ) ;
}
drop_path = String ( ) ;
drop_node = nullptr ;
2016-09-03 19:59:44 +02:00
_update_graph ( port_action_new_node ) ;
2016-09-03 19:58:23 +02:00
}
2018-05-13 05:34:35 +02:00
void VisualScriptEditor : : connect_seq ( Ref < VisualScriptNode > vnode_old , Ref < VisualScriptNode > vnode_new , int new_id ) {
VisualScriptOperator * vnode_operator = Object : : cast_to < VisualScriptOperator > ( vnode_new . ptr ( ) ) ;
2020-04-02 01:20:12 +02:00
if ( vnode_operator ! = nullptr & & ! vnode_operator - > has_input_sequence_port ( ) ) {
2018-05-13 05:34:35 +02:00
return ;
}
VisualScriptConstructor * vnode_constructor = Object : : cast_to < VisualScriptConstructor > ( vnode_new . ptr ( ) ) ;
2020-04-02 01:20:12 +02:00
if ( vnode_constructor ! = nullptr ) {
2018-05-13 05:34:35 +02:00
return ;
}
if ( vnode_old - > get_output_sequence_port_count ( ) < = 0 ) {
return ;
}
2018-10-06 22:20:41 +02:00
if ( ! vnode_new - > has_input_sequence_port ( ) ) {
2018-05-13 05:34:35 +02:00
return ;
}
2018-09-27 11:24:41 +02:00
2018-05-13 05:34:35 +02:00
undo_redo - > create_action ( TTR ( " Connect Node Sequence " ) ) ;
int pass_port = - vnode_old - > get_output_sequence_port_count ( ) + 1 ;
int return_port = port_action_output - 1 ;
if ( vnode_old - > get_output_value_port_info ( port_action_output ) . name = = String ( " pass " ) & &
2020-06-17 17:39:25 +02:00
! script - > get_output_sequence_ports_connected ( port_action_node ) . has ( pass_port ) ) {
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , port_action_node , pass_port , new_id ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_disconnect " , port_action_node , pass_port , new_id ) ;
2018-05-13 05:34:35 +02:00
} else if ( vnode_old - > get_output_value_port_info ( port_action_output ) . name = = String ( " return " ) & &
2021-10-28 15:19:35 +02:00
! script - > get_output_sequence_ports_connected ( port_action_node ) . has ( return_port ) ) {
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , port_action_node , return_port , new_id ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_disconnect " , port_action_node , return_port , new_id ) ;
2018-05-13 05:34:35 +02:00
} else {
for ( int port = 0 ; port < vnode_old - > get_output_sequence_port_count ( ) ; port + + ) {
int count = vnode_old - > get_output_sequence_port_count ( ) ;
2020-06-17 17:39:25 +02:00
if ( port_action_output < count & & ! script - > get_output_sequence_ports_connected ( port_action_node ) . has ( port_action_output ) ) {
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , port_action_node , port_action_output , new_id ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_disconnect " , port_action_node , port_action_output , new_id ) ;
2018-05-13 05:34:35 +02:00
break ;
2020-06-17 17:39:25 +02:00
} else if ( ! script - > get_output_sequence_ports_connected ( port_action_node ) . has ( port ) ) {
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , port_action_node , port , new_id ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_disconnect " , port_action_node , port , new_id ) ;
2018-05-13 05:34:35 +02:00
break ;
}
}
}
undo_redo - > commit_action ( ) ;
}
2018-07-25 20:49:41 +02:00
void VisualScriptEditor : : _selected_new_virtual_method ( const String & p_text , const String & p_category , const bool p_connecting ) {
2021-11-20 13:52:37 +01:00
String name = p_text . substr ( p_text . find_char ( ' : ' ) + 1 ) ;
2017-09-12 12:58:18 +02:00
if ( script - > has_function ( name ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( vformat ( TTR ( " Script already has function '%s' " ) , name ) ) ;
return ;
}
MethodInfo minfo ;
{
List < MethodInfo > methods ;
bool found = false ;
ClassDB : : get_virtual_methods ( script - > get_instance_base_type ( ) , & methods ) ;
2021-07-24 15:46:25 +02:00
for ( const MethodInfo & E : methods ) {
2021-07-16 05:45:57 +02:00
if ( E . name = = name ) {
minfo = E ;
2017-09-12 12:58:18 +02:00
found = true ;
}
}
ERR_FAIL_COND ( ! found ) ;
}
selected = name ;
Ref < VisualScriptFunction > func_node ;
2021-06-18 00:03:09 +02:00
func_node . instantiate ( ) ;
2017-09-12 12:58:18 +02:00
func_node - > set_name ( name ) ;
2020-06-17 17:39:25 +02:00
int fn_id = script - > get_available_id ( ) ;
2017-09-12 12:58:18 +02:00
undo_redo - > create_action ( TTR ( " Add Function " ) ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_function " , name , fn_id ) ;
2017-09-12 12:58:18 +02:00
for ( int i = 0 ; i < minfo . arguments . size ( ) ; i + + ) {
2018-07-25 23:23:26 +02:00
func_node - > add_argument ( minfo . arguments [ i ] . type , minfo . arguments [ i ] . name , - 1 , minfo . arguments [ i ] . hint , minfo . arguments [ i ] . hint_string ) ;
2017-09-12 12:58:18 +02:00
}
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_available_pos ( ) ;
2019-09-13 21:14:12 +02:00
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , fn_id , func_node , pos ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , fn_id ) ;
2017-09-12 12:58:18 +02:00
if ( minfo . return_val . type ! = Variant : : NIL | | minfo . return_val . usage & PROPERTY_USAGE_NIL_IS_VARIANT ) {
Ref < VisualScriptReturn > ret_node ;
2021-06-18 00:03:09 +02:00
ret_node . instantiate ( ) ;
2017-09-12 12:58:18 +02:00
ret_node - > set_return_type ( minfo . return_val . type ) ;
ret_node - > set_enable_return_value ( true ) ;
ret_node - > set_name ( name ) ;
2020-06-17 17:39:25 +02:00
int nid = script - > get_available_id ( ) + 1 ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , nid , ret_node , _get_available_pos ( false , pos + Vector2 ( 500 , 0 ) ) ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , nid ) ;
2017-09-12 12:58:18 +02:00
}
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_function " , name ) ;
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
_update_graph ( ) ;
}
2018-05-13 05:34:35 +02:00
void VisualScriptEditor : : _cancel_connect_node ( ) {
2020-06-17 17:39:25 +02:00
// Ensure the cancel is done.
2019-09-13 21:14:12 +02:00
port_action_new_node = - 1 ;
2017-08-22 21:55:50 +02:00
}
2020-06-17 17:39:25 +02:00
int VisualScriptEditor : : _create_new_node_from_name ( const String & p_text , const Vector2 & p_point ) {
2018-05-13 05:34:35 +02:00
Ref < VisualScriptNode > vnode = VisualScriptLanguage : : singleton - > create_node_from_name ( p_text ) ;
int new_id = script - > get_available_id ( ) ;
undo_redo - > create_action ( TTR ( " Add Node " ) ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , new_id , vnode , p_point ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , new_id ) ;
2018-05-13 05:34:35 +02:00
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2019-09-13 21:14:12 +02:00
return new_id ;
2018-05-13 05:34:35 +02:00
}
2022-08-01 20:01:48 +02:00
void VisualScriptEditor : : _default_value_changed ( const StringName & p_property , const Variant & p_value , const String & p_field , bool p_changing ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > vsn = script - > get_node ( editing_id ) ;
2020-05-14 16:41:43 +02:00
if ( vsn . is_null ( ) ) {
2016-08-04 03:06:39 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-04 03:06:39 +02:00
2017-08-23 22:25:14 +02:00
undo_redo - > create_action ( TTR ( " Change Input Value " ) ) ;
2022-08-01 20:01:48 +02:00
undo_redo - > add_do_method ( vsn . ptr ( ) , " set_default_input_value " , editing_input , p_value ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_undo_method ( vsn . ptr ( ) , " set_default_input_value " , editing_input , vsn - > get_default_input_value ( editing_input ) ) ;
2016-08-04 03:06:39 +02:00
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( this , " _update_graph " , editing_id ) ;
undo_redo - > add_undo_method ( this , " _update_graph " , editing_id ) ;
2016-08-04 03:06:39 +02:00
undo_redo - > commit_action ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _default_value_edited ( Node * p_button , int p_id , int p_input_port ) {
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > vsn = script - > get_node ( p_id ) ;
2020-05-14 16:41:43 +02:00
if ( vsn . is_null ( ) ) {
2016-08-04 03:06:39 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-04 03:06:39 +02:00
PropertyInfo pinfo = vsn - > get_input_value_port_info ( p_input_port ) ;
Variant existing = vsn - > get_default_input_value ( p_input_port ) ;
2017-03-05 16:44:50 +01:00
if ( pinfo . type ! = Variant : : NIL & & existing . get_type ( ) ! = pinfo . type ) {
2020-02-19 20:27:19 +01:00
Callable : : CallError ce ;
2020-11-09 04:19:09 +01:00
Variant e = existing ;
const Variant * existingp = & e ;
Variant : : construct ( pinfo . type , existing , & existingp , 1 , ce ) ;
2016-08-04 03:06:39 +02:00
}
2017-11-12 13:20:38 +01:00
if ( pinfo . type = = Variant : : NODE_PATH ) {
Node * edited_scene = get_tree ( ) - > get_edited_scene_root ( ) ;
2020-06-17 17:39:25 +02:00
if ( edited_scene ) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open).
2019-09-13 21:14:12 +02:00
Node * script_node = _find_script_node ( edited_scene , edited_scene , script ) ;
2017-11-12 13:20:38 +01:00
2019-09-13 21:14:12 +02:00
if ( script_node ) {
2020-06-17 17:39:25 +02:00
// Pick a node relative to the script, IF the script exists.
2019-09-13 21:14:12 +02:00
pinfo . hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE ;
pinfo . hint_string = script_node - > get_path ( ) ;
} else {
2020-06-17 17:39:25 +02:00
// Pick a path relative to edited scene.
2019-09-13 21:14:12 +02:00
pinfo . hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE ;
pinfo . hint_string = get_tree ( ) - > get_edited_scene_root ( ) - > get_path ( ) ;
}
2017-11-12 13:20:38 +01:00
}
}
2022-08-01 20:01:48 +02:00
edited_default_property_holder - > set_edited_property ( existing ) ;
if ( default_property_editor ) {
default_property_editor - > disconnect ( " property_changed " , callable_mp ( this , & VisualScriptEditor : : _default_value_changed ) ) ;
default_property_editor_popup - > remove_child ( default_property_editor ) ;
}
default_property_editor = EditorInspector : : instantiate_property_editor ( edited_default_property_holder . ptr ( ) , pinfo . type , " edited_property " , pinfo . hint , pinfo . hint_string , PROPERTY_USAGE_NONE ) ;
if ( default_property_editor ) {
default_property_editor - > set_object_and_property ( edited_default_property_holder . ptr ( ) , " edited_property " ) ;
default_property_editor - > update_property ( ) ;
default_property_editor - > set_name_split_ratio ( 0 ) ;
default_property_editor_popup - > add_child ( default_property_editor ) ;
default_property_editor - > connect ( " property_changed " , callable_mp ( this , & VisualScriptEditor : : _default_value_changed ) ) ;
Button * button = Object : : cast_to < Button > ( p_button ) ;
if ( button ) {
default_property_editor_popup - > set_position ( button - > get_screen_position ( ) + Vector2 ( 0 , button - > get_size ( ) . height ) * graph - > get_zoom ( ) ) ;
}
default_property_editor_popup - > reset_size ( ) ;
if ( pinfo . hint = = PROPERTY_HINT_MULTILINE_TEXT | | ! button ) {
default_property_editor_popup - > popup_centered_ratio ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2022-08-01 20:01:48 +02:00
default_property_editor_popup - > popup ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-26 22:34:25 +02:00
}
2016-08-04 03:06:39 +02:00
editing_id = p_id ;
2017-03-05 16:44:50 +01:00
editing_input = p_input_port ;
2016-08-04 03:06:39 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _show_hint ( const String & p_hint ) {
2016-08-03 16:28:20 +02:00
hint_text - > set_text ( p_hint ) ;
hint_text - > show ( ) ;
hint_text_timer - > start ( ) ;
}
void VisualScriptEditor : : _hide_timer ( ) {
hint_text - > hide ( ) ;
}
2021-09-14 11:17:47 +02:00
void VisualScriptEditor : : _toggle_scripts_pressed ( ) {
ScriptEditor : : get_singleton ( ) - > toggle_scripts_panel ( ) ;
update_toggle_scripts_button ( ) ;
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _notification ( int p_what ) {
2019-09-28 00:59:53 +02:00
switch ( p_what ) {
2021-09-28 18:00:16 +02:00
case NOTIFICATION_ENTER_TREE :
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
2022-01-23 13:49:53 +01:00
graph - > get_panner ( ) - > setup ( ( ViewPanner : : ControlScheme ) EDITOR_GET ( " editors/panning/sub_editors_panning_scheme " ) . operator int ( ) , ED_GET_SHORTCUT ( " canvas_item_editor/pan_view " ) , bool ( EditorSettings : : get_singleton ( ) - > get ( " editors/panning/simple_panning " ) ) ) ;
2022-01-19 19:59:12 +01:00
graph - > set_warped_panning ( bool ( EditorSettings : : get_singleton ( ) - > get ( " editors/panning/warped_mouse_panning " ) ) ) ;
2022-06-07 19:17:47 +02:00
graph - > set_minimap_opacity ( EditorSettings : : get_singleton ( ) - > get ( " editors/visual_editors/minimap_opacity " ) ) ;
graph - > set_connection_lines_curvature ( EditorSettings : : get_singleton ( ) - > get ( " editors/visual_editors/lines_curvature " ) ) ;
_update_graph ( ) ;
2021-09-28 18:00:16 +02:00
} break ;
2019-09-28 00:59:53 +02:00
case NOTIFICATION_READY : {
2020-02-21 18:28:45 +01:00
variable_editor - > connect ( " changed " , callable_mp ( this , & VisualScriptEditor : : _update_members ) ) ;
2022-07-28 22:56:41 +02:00
variable_editor - > connect ( " changed " , callable_mp ( this , & VisualScriptEditor : : _update_graph ) . bind ( - 1 ) , CONNECT_DEFERRED ) ;
2020-02-21 18:28:45 +01:00
signal_editor - > connect ( " changed " , callable_mp ( this , & VisualScriptEditor : : _update_members ) ) ;
2022-07-28 22:56:41 +02:00
signal_editor - > connect ( " changed " , callable_mp ( this , & VisualScriptEditor : : _update_graph ) . bind ( - 1 ) , CONNECT_DEFERRED ) ;
2020-02-22 20:47:50 +01:00
[[fallthrough]] ;
2018-10-28 14:14:14 +01:00
}
2019-09-28 00:59:53 +02:00
case NOTIFICATION_THEME_CHANGED : {
if ( p_what ! = NOTIFICATION_READY & & ! is_visible_in_tree ( ) ) {
return ;
}
2017-09-08 21:41:44 +02:00
2021-09-14 11:17:47 +02:00
update_toggle_scripts_button ( ) ;
2022-02-08 10:14:58 +01:00
edit_variable_edit - > add_theme_style_override ( " bg " , get_theme_stylebox ( SNAME ( " bg " ) , SNAME ( " Tree " ) ) ) ;
edit_signal_edit - > add_theme_style_override ( " bg " , get_theme_stylebox ( SNAME ( " bg " ) , SNAME ( " Tree " ) ) ) ;
func_input_scroll - > add_theme_style_override ( " bg " , get_theme_stylebox ( SNAME ( " bg " ) , SNAME ( " Tree " ) ) ) ;
2017-10-03 04:31:32 +02:00
2019-09-28 00:59:53 +02:00
Ref < Theme > tm = EditorNode : : get_singleton ( ) - > get_theme_base ( ) - > get_theme ( ) ;
2017-10-03 04:31:32 +02:00
2022-02-08 10:14:58 +01:00
bool dark_theme = tm - > get_constant ( " dark_theme " , " Editor " ) ;
2017-09-08 21:41:44 +02:00
2019-09-28 00:59:53 +02:00
if ( dark_theme ) {
2019-03-23 01:57:28 +01:00
node_colors [ " flow_control " ] = Color ( 0.96 , 0.96 , 0.96 ) ;
node_colors [ " functions " ] = Color ( 0.96 , 0.52 , 0.51 ) ;
node_colors [ " data " ] = Color ( 0.5 , 0.96 , 0.81 ) ;
node_colors [ " operators " ] = Color ( 0.67 , 0.59 , 0.87 ) ;
node_colors [ " custom " ] = Color ( 0.5 , 0.73 , 0.96 ) ;
node_colors [ " constants " ] = Color ( 0.96 , 0.5 , 0.69 ) ;
2019-09-28 00:59:53 +02:00
} else {
2019-03-23 01:57:28 +01:00
node_colors [ " flow_control " ] = Color ( 0.26 , 0.26 , 0.26 ) ;
node_colors [ " functions " ] = Color ( 0.95 , 0.4 , 0.38 ) ;
node_colors [ " data " ] = Color ( 0.07 , 0.73 , 0.51 ) ;
node_colors [ " operators " ] = Color ( 0.51 , 0.4 , 0.82 ) ;
node_colors [ " custom " ] = Color ( 0.31 , 0.63 , 0.95 ) ;
node_colors [ " constants " ] = Color ( 0.94 , 0.18 , 0.49 ) ;
2017-09-08 21:41:44 +02:00
}
2018-10-28 14:14:14 +01:00
2021-08-09 22:13:42 +02:00
for ( const KeyValue < StringName , Color > & E : node_colors ) {
2021-07-17 23:22:52 +02:00
const Ref < StyleBoxFlat > sb = tm - > get_stylebox ( SNAME ( " frame " ) , SNAME ( " GraphNode " ) ) ;
2019-03-23 01:57:28 +01:00
2019-09-28 00:59:53 +02:00
if ( ! sb . is_null ( ) ) {
Ref < StyleBoxFlat > frame_style = sb - > duplicate ( ) ;
2019-03-23 01:57:28 +01:00
// Adjust the border color to be close to the GraphNode's background color.
// This keeps the node's title area from being too distracting.
2021-08-09 22:13:42 +02:00
Color color = dark_theme ? E . value . darkened ( 0.75 ) : E . value . lightened ( 0.75 ) ;
2019-03-23 01:57:28 +01:00
color . a = 0.9 ;
frame_style - > set_border_color ( color ) ;
2021-08-09 22:13:42 +02:00
node_styles [ E . key ] = frame_style ;
2019-09-28 00:59:53 +02:00
}
}
if ( is_visible_in_tree ( ) & & script . is_valid ( ) ) {
_update_members ( ) ;
_update_graph ( ) ;
}
} break ;
2022-02-16 15:17:55 +01:00
2019-09-28 00:59:53 +02:00
case NOTIFICATION_VISIBILITY_CHANGED : {
2021-09-14 11:17:47 +02:00
update_toggle_scripts_button ( ) ;
2019-09-28 00:59:53 +02:00
members_section - > set_visible ( is_visible_in_tree ( ) ) ;
} break ;
2016-08-04 03:06:39 +02:00
}
}
2016-08-03 16:28:20 +02:00
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _graph_ofs_changed ( const Vector2 & p_ofs ) {
2020-05-14 16:41:43 +02:00
if ( updating_graph | | ! script . is_valid ( ) ) {
2016-08-07 00:00:54 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
updating_graph = true ;
2016-08-07 00:00:54 +02:00
2020-06-17 17:39:25 +02:00
script - > set_scroll ( graph - > get_scroll_ofs ( ) / EDSCALE ) ;
script - > set_edited ( true ) ;
2017-03-05 16:44:50 +01:00
updating_graph = false ;
2016-08-07 00:00:54 +02:00
}
2017-03-05 16:44:50 +01:00
void VisualScriptEditor : : _comment_node_resized ( const Vector2 & p_new_size , int p_node ) {
2020-05-14 16:41:43 +02:00
if ( updating_graph ) {
2016-08-25 22:45:20 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-06-17 17:39:25 +02:00
Ref < VisualScriptComment > vsc = script - > get_node ( p_node ) ;
2020-05-14 16:41:43 +02:00
if ( vsc . is_null ( ) ) {
2016-08-25 22:45:20 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-25 22:45:20 +02:00
Node * node = graph - > get_node ( itos ( p_node ) ) ;
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( node ) ;
2020-05-14 16:41:43 +02:00
if ( ! gn ) {
2016-08-25 22:45:20 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-08-25 22:45:20 +02:00
2021-02-06 21:39:35 +01:00
Vector2 new_size = p_new_size ;
if ( graph - > is_using_snap ( ) ) {
Vector2 snap = Vector2 ( graph - > get_snap ( ) , graph - > get_snap ( ) ) ;
Vector2 min_size = ( gn - > get_minimum_size ( ) + ( snap * 0.5 ) ) . snapped ( snap ) ;
new_size = new_size . snapped ( snap ) . max ( min_size ) ;
}
2017-03-05 16:44:50 +01:00
updating_graph = true ;
2016-08-25 22:45:20 +02:00
graph - > set_block_minimum_size_adjust ( true ) ; //faster resize
2019-02-21 20:41:01 +01:00
undo_redo - > create_action ( TTR ( " Resize Comment " ) , UndoRedo : : MERGE_ENDS ) ;
2021-02-06 21:39:35 +01:00
undo_redo - > add_do_method ( vsc . ptr ( ) , " set_size " , new_size / EDSCALE ) ;
2017-03-05 16:44:50 +01:00
undo_redo - > add_undo_method ( vsc . ptr ( ) , " set_size " , vsc - > get_size ( ) ) ;
2016-08-25 22:45:20 +02:00
undo_redo - > commit_action ( ) ;
2021-02-06 21:39:35 +01:00
gn - > set_custom_minimum_size ( new_size ) ;
2021-11-20 09:04:57 +01:00
gn - > reset_size ( ) ;
2016-08-25 22:45:20 +02:00
graph - > set_block_minimum_size_adjust ( false ) ;
2017-03-05 16:44:50 +01:00
updating_graph = false ;
2016-08-25 22:45:20 +02:00
}
2016-08-07 00:00:54 +02:00
void VisualScriptEditor : : _menu_option ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2022-01-09 17:10:17 +01:00
case EDIT_ADD_NODE : {
2021-11-20 13:52:37 +01:00
_generic_search ( ) ;
2022-01-09 17:10:17 +01:00
} break ;
2016-08-07 00:00:54 +02:00
case EDIT_DELETE_NODES : {
_on_nodes_delete ( ) ;
} break ;
case EDIT_TOGGLE_BREAKPOINT : {
List < String > reselect ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
2017-08-24 22:58:51 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
2016-08-07 00:00:54 +02:00
if ( gn ) {
if ( gn - > is_selected ( ) ) {
int id = String ( gn - > get_name ( ) ) . to_int ( ) ;
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > vsn = script - > get_node ( id ) ;
2016-08-07 00:00:54 +02:00
if ( vsn . is_valid ( ) ) {
vsn - > set_breakpoint ( ! vsn - > is_breakpoint ( ) ) ;
reselect . push_back ( gn - > get_name ( ) ) ;
}
}
}
}
_update_graph ( ) ;
2021-07-24 15:46:25 +02:00
for ( const String & E : reselect ) {
2021-07-16 05:45:57 +02:00
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_node ( E ) ) ;
2016-08-07 00:00:54 +02:00
gn - > set_selected ( true ) ;
}
} break ;
2016-08-08 06:41:57 +02:00
case EDIT_FIND_NODE_TYPE : {
2021-11-20 13:52:37 +01:00
_generic_search ( ) ;
2017-01-13 23:23:42 +01:00
} break ;
2021-10-02 19:31:48 +02:00
case EDIT_COPY_NODES : {
_on_nodes_copy ( ) ;
} break ;
2016-08-25 22:45:20 +02:00
case EDIT_CUT_NODES : {
2021-10-02 19:31:48 +02:00
_on_nodes_copy ( ) ;
_on_nodes_delete ( ) ;
2016-08-08 06:41:57 +02:00
} break ;
2016-08-25 22:45:20 +02:00
case EDIT_PASTE_NODES : {
2021-10-02 19:31:48 +02:00
_on_nodes_paste ( ) ;
2016-08-25 22:45:20 +02:00
} break ;
2022-01-09 17:10:17 +01:00
case EDIT_DUPLICATE_NODES : {
_on_nodes_duplicate ( ) ;
} break ;
2019-09-13 21:14:12 +02:00
case EDIT_CREATE_FUNCTION : {
2020-06-17 17:39:25 +02:00
// Create Function.
2022-05-13 15:04:37 +02:00
HashMap < int , Ref < VisualScriptNode > > nodes ;
RBSet < int > selections ;
2019-09-13 21:14:12 +02:00
for ( int i = 0 ; i < graph - > get_child_count ( ) ; i + + ) {
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( i ) ) ;
if ( gn ) {
if ( gn - > is_selected ( ) ) {
int id = String ( gn - > get_name ( ) ) . to_int ( ) ;
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > node = script - > get_node ( id ) ;
2019-09-13 21:14:12 +02:00
if ( Object : : cast_to < VisualScriptFunction > ( * node ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Can't create function with a function node. " ) ) ;
return ;
}
if ( node . is_valid ( ) ) {
nodes . insert ( id , node ) ;
selections . insert ( id ) ;
}
}
}
}
if ( nodes . size ( ) = = 0 ) {
return ; // nothing to be done if there are no valid nodes selected
}
2022-05-13 15:04:37 +02:00
RBSet < VisualScript : : SequenceConnection > seqmove ;
RBSet < VisualScript : : DataConnection > datamove ;
2019-09-13 21:14:12 +02:00
2022-05-13 15:04:37 +02:00
RBSet < VisualScript : : SequenceConnection > seqext ;
RBSet < VisualScript : : DataConnection > dataext ;
2019-09-13 21:14:12 +02:00
int start_node = - 1 ;
2022-05-13 15:04:37 +02:00
RBSet < int > end_nodes ;
2019-09-13 21:14:12 +02:00
if ( nodes . size ( ) = = 1 ) {
2022-05-13 15:04:37 +02:00
Ref < VisualScriptNode > nd = script - > get_node ( nodes . begin ( ) - > key ) ;
2020-05-14 16:41:43 +02:00
if ( nd . is_valid ( ) & & nd - > has_input_sequence_port ( ) ) {
2022-05-13 15:04:37 +02:00
start_node = nodes . begin ( ) - > key ;
2020-05-14 16:41:43 +02:00
} else {
2019-11-01 16:10:21 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Select at least one node with sequence port. " ) ) ;
2019-09-13 21:14:12 +02:00
return ;
}
} else {
List < VisualScript : : SequenceConnection > seqs ;
2020-06-17 17:39:25 +02:00
script - > get_sequence_connection_list ( & seqs ) ;
2019-09-13 21:14:12 +02:00
if ( seqs . size ( ) = = 0 ) {
2020-06-17 17:39:25 +02:00
// In case there are no sequence connections,
// select the top most node cause that's probably how,
// the user wants to connect the nodes.
2019-09-13 21:14:12 +02:00
int top_nd = - 1 ;
Vector2 top ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < int , Ref < VisualScriptNode > > & E : nodes ) {
Ref < VisualScriptNode > nd = script - > get_node ( E . key ) ;
2019-09-13 21:14:12 +02:00
if ( nd . is_valid ( ) & & nd - > has_input_sequence_port ( ) ) {
if ( top_nd < 0 ) {
2021-08-09 22:13:42 +02:00
top_nd = E . key ;
2020-06-17 17:39:25 +02:00
top = script - > get_node_position ( top_nd ) ;
2019-09-13 21:14:12 +02:00
}
2021-08-09 22:13:42 +02:00
Vector2 pos = script - > get_node_position ( E . key ) ;
2019-09-13 21:14:12 +02:00
if ( top . y > pos . y ) {
2021-08-09 22:13:42 +02:00
top_nd = E . key ;
2019-09-13 21:14:12 +02:00
top = pos ;
}
}
}
2020-06-17 17:39:25 +02:00
Ref < VisualScriptNode > nd = script - > get_node ( top_nd ) ;
2020-05-14 16:41:43 +02:00
if ( nd . is_valid ( ) & & nd - > has_input_sequence_port ( ) ) {
2019-09-13 21:14:12 +02:00
start_node = top_nd ;
2020-05-14 16:41:43 +02:00
} else {
2019-11-01 16:10:21 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Select at least one node with sequence port. " ) ) ;
2019-09-13 21:14:12 +02:00
return ;
}
} else {
2020-06-17 17:39:25 +02:00
// Pick the node with input sequence.
2022-05-13 15:04:37 +02:00
RBSet < int > nodes_from ;
RBSet < int > nodes_to ;
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : SequenceConnection & E : seqs ) {
2021-07-16 05:45:57 +02:00
if ( nodes . has ( E . from_node ) & & nodes . has ( E . to_node ) ) {
seqmove . insert ( E ) ;
nodes_from . insert ( E . from_node ) ;
} else if ( nodes . has ( E . from_node ) & & ! nodes . has ( E . to_node ) ) {
seqext . insert ( E ) ;
} else if ( ! nodes . has ( E . from_node ) & & nodes . has ( E . to_node ) ) {
2019-09-13 21:14:12 +02:00
if ( start_node = = - 1 ) {
2021-07-16 05:45:57 +02:00
seqext . insert ( E ) ;
start_node = E . to_node ;
2019-09-13 21:14:12 +02:00
} else {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Try to only have one sequence input in selection. " ) ) ;
return ;
}
}
2021-07-16 05:45:57 +02:00
nodes_to . insert ( E . to_node ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
// To use to add return nodes.
2019-09-13 21:14:12 +02:00
_get_ends ( start_node , seqs , selections , end_nodes ) ;
if ( start_node = = - 1 ) {
2020-06-17 17:39:25 +02:00
// If we still don't have a start node then,
// run through the nodes and select the first tree node,
2021-03-12 14:35:16 +01:00
// i.e. node without any input sequence but output sequence.
2022-05-19 01:43:40 +02:00
for ( const int & E : nodes_from ) {
if ( ! nodes_to . has ( E ) ) {
start_node = E ;
2019-09-13 21:14:12 +02:00
}
}
}
}
}
if ( start_node = = - 1 ) {
2020-06-17 17:39:25 +02:00
return ; // This should not happen, but just in case something goes wrong.
2019-09-13 21:14:12 +02:00
}
List < Variant : : Type > inputs ; // input types
2020-03-17 07:33:00 +01:00
List < Pair < int , int > > input_connections ;
2019-09-13 21:14:12 +02:00
{
List < VisualScript : : DataConnection > dats ;
2020-06-17 17:39:25 +02:00
script - > get_data_connection_list ( & dats ) ;
2021-07-24 15:46:25 +02:00
for ( const VisualScript : : DataConnection & E : dats ) {
2021-07-16 05:45:57 +02:00
if ( nodes . has ( E . from_node ) & & nodes . has ( E . to_node ) ) {
datamove . insert ( E ) ;
} else if ( ! nodes . has ( E . from_node ) & & nodes . has ( E . to_node ) ) {
2020-06-17 17:39:25 +02:00
// Add all these as inputs for the Function.
2021-07-16 05:45:57 +02:00
Ref < VisualScriptNode > node = script - > get_node ( E . to_node ) ;
2019-09-13 21:14:12 +02:00
if ( node . is_valid ( ) ) {
2021-07-16 05:45:57 +02:00
dataext . insert ( E ) ;
PropertyInfo pi = node - > get_input_value_port_info ( E . to_port ) ;
2019-09-13 21:14:12 +02:00
inputs . push_back ( pi . type ) ;
2021-07-16 05:45:57 +02:00
input_connections . push_back ( Pair < int , int > ( E . to_node , E . to_port ) ) ;
2019-09-13 21:14:12 +02:00
}
2021-07-16 05:45:57 +02:00
} else if ( nodes . has ( E . from_node ) & & ! nodes . has ( E . to_node ) ) {
dataext . insert ( E ) ;
2019-09-13 21:14:12 +02:00
}
}
}
int fn_id = script - > get_available_id ( ) ;
2020-06-17 17:39:25 +02:00
{
String new_fn = _validate_name ( " new_function " ) ;
2019-09-13 21:14:12 +02:00
2021-06-23 12:11:06 +02:00
Vector2 pos = _get_available_pos ( false , script - > get_node_position ( start_node ) - Vector2 ( 80 , 150 ) ) ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
Ref < VisualScriptFunction > func_node ;
2021-06-18 00:03:09 +02:00
func_node . instantiate ( ) ;
2020-06-17 17:39:25 +02:00
func_node - > set_name ( new_fn ) ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
undo_redo - > create_action ( TTR ( " Create Function " ) ) ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_function " , new_fn , fn_id ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , fn_id , func_node , pos ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_function " , new_fn ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , fn_id ) ;
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " edited_script_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " edited_script_changed " ) ;
// Might make the system more intelligent by checking port from info.
int i = 0 ;
List < Pair < int , int > > : : Element * F = input_connections . front ( ) ;
for ( List < Variant : : Type > : : Element * E = inputs . front ( ) ; E & & F ; E = E - > next ( ) , F = F - > next ( ) ) {
func_node - > add_argument ( E - > get ( ) , " arg_ " + String : : num_int64 ( i ) , i ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , fn_id , i , F - > get ( ) . first , F - > get ( ) . second ) ;
i + + ; // increment i
}
// Ensure Preview Selection is of newly created function node.
if ( selections . size ( ) ) {
EditorNode : : get_singleton ( ) - > push_item ( func_node . ptr ( ) ) ;
}
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
// Move the nodes.
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
// Handles reconnection of sequence connections on undo, start here in case of issues.
2022-05-19 01:43:40 +02:00
for ( const VisualScript : : SequenceConnection & E : seqext ) {
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_disconnect " , E . from_node , E . from_output , E . to_node ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_connect " , E . from_node , E . from_output , E . to_node ) ;
2019-09-13 21:14:12 +02:00
}
2022-05-19 01:43:40 +02:00
for ( const VisualScript : : DataConnection & E : dataext ) {
undo_redo - > add_do_method ( script . ptr ( ) , " data_disconnect " , E . from_node , E . from_port , E . to_node , E . to_port ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , E . from_node , E . from_port , E . to_node , E . to_port ) ;
2019-09-13 21:14:12 +02:00
}
2020-06-17 17:39:25 +02:00
// I don't really think we need support for non sequenced functions at this moment.
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , fn_id , 0 , start_node ) ;
2019-09-13 21:14:12 +02:00
2020-06-17 17:39:25 +02:00
// Could fail with the new changes, start here when searching for bugs in create function shortcut.
2019-09-13 21:14:12 +02:00
int m = 1 ;
2022-05-19 01:43:40 +02:00
for ( const int & G : end_nodes ) {
2019-09-13 21:14:12 +02:00
Ref < VisualScriptReturn > ret_node ;
2021-06-18 00:03:09 +02:00
ret_node . instantiate ( ) ;
2019-09-13 21:14:12 +02:00
int ret_id = fn_id + ( m + + ) ;
selections . insert ( ret_id ) ;
2022-05-19 01:43:40 +02:00
Vector2 posi = _get_available_pos ( false , script - > get_node_position ( G ) + Vector2 ( 80 , - 100 ) ) ;
2021-06-23 12:11:06 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " add_node " , ret_id , ret_node , posi ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_undo_method ( script . ptr ( ) , " remove_node " , ret_id ) ;
2019-09-13 21:14:12 +02:00
2022-05-19 01:43:40 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " sequence_connect " , G , 0 , ret_id ) ;
2020-06-17 17:39:25 +02:00
// Add data outputs from each of the end_nodes.
2022-05-19 01:43:40 +02:00
Ref < VisualScriptNode > vsn = script - > get_node ( G ) ;
2019-09-13 21:14:12 +02:00
if ( vsn . is_valid ( ) & & vsn - > get_output_value_port_count ( ) > 0 ) {
ret_node - > set_enable_return_value ( true ) ;
2020-06-17 17:39:25 +02:00
// Use the zeroth data port cause that's the likely one that is planned to be used.
2019-09-13 21:14:12 +02:00
ret_node - > set_return_type ( vsn - > get_output_value_port_info ( 0 ) . type ) ;
2022-05-19 01:43:40 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " data_connect " , G , 0 , ret_id , 0 ) ;
2019-09-13 21:14:12 +02:00
}
}
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2020-06-17 17:39:25 +02:00
// Make sure all Nodes get marked for selection so that they can be moved together.
2019-09-13 21:14:12 +02:00
selections . insert ( fn_id ) ;
for ( int k = 0 ; k < graph - > get_child_count ( ) ; k + + ) {
GraphNode * gn = Object : : cast_to < GraphNode > ( graph - > get_child ( k ) ) ;
if ( gn ) {
int id = gn - > get_name ( ) . operator String ( ) . to_int ( ) ;
gn - > set_selected ( selections . has ( id ) ) ;
}
}
} break ;
case REFRESH_GRAPH : {
_update_graph ( ) ;
} break ;
2022-01-09 17:10:17 +01:00
case EDIT_CLEAR_COPY_BUFFER : {
clipboard - > nodes . clear ( ) ;
clipboard - > nodes_positions . clear ( ) ;
clipboard - > data_connections . clear ( ) ;
clipboard - > sequence_connections . clear ( ) ;
} break ;
2019-09-13 21:14:12 +02:00
}
}
2020-06-17 17:39:25 +02:00
// This is likely going to be very slow and I am not sure if I should keep it,
// but I hope that it will not be a problem considering that we won't be creating functions so frequently,
// and cyclic connections would be a problem but hopefully we won't let them get to this point.
2022-05-13 15:04:37 +02:00
void VisualScriptEditor : : _get_ends ( int p_node , const List < VisualScript : : SequenceConnection > & p_seqs , const RBSet < int > & p_selected , RBSet < int > & r_end_nodes ) {
2021-07-16 05:45:57 +02:00
for ( const VisualScript : : SequenceConnection & E : p_seqs ) {
int from = E . from_node ;
int to = E . to_node ;
2019-09-13 21:14:12 +02:00
if ( from = = p_node & & p_selected . has ( to ) ) {
2020-06-17 17:39:25 +02:00
// This is an interior connection move forward to the to node.
2019-09-13 21:14:12 +02:00
_get_ends ( to , p_seqs , p_selected , r_end_nodes ) ;
} else if ( from = = p_node & & ! p_selected . has ( to ) ) {
r_end_nodes . insert ( from ) ;
}
2016-08-07 00:00:54 +02:00
}
}
2021-09-18 09:33:18 +02:00
void VisualScriptEditor : : _member_rmb_selected ( const Vector2 & p_pos , MouseButton p_button ) {
if ( p_button ! = MouseButton : : RIGHT ) {
return ;
}
2017-07-01 02:30:17 +02:00
TreeItem * ti = members - > get_selected ( ) ;
ERR_FAIL_COND ( ! ti ) ;
member_popup - > clear ( ) ;
2021-08-31 17:43:35 +02:00
member_popup - > set_position ( members - > get_screen_position ( ) + p_pos ) ;
2021-11-20 09:04:57 +01:00
member_popup - > reset_size ( ) ;
2017-07-01 02:30:17 +02:00
2021-08-31 17:43:35 +02:00
function_name_edit - > set_position ( members - > get_screen_position ( ) + p_pos ) ;
2021-11-20 09:04:57 +01:00
function_name_edit - > reset_size ( ) ;
2019-09-13 21:14:12 +02:00
2017-07-01 02:30:17 +02:00
TreeItem * root = members - > get_root ( ) ;
2021-07-17 23:22:52 +02:00
Ref < Texture2D > del_icon = Control : : get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) ;
2017-07-01 02:30:17 +02:00
2021-07-17 23:22:52 +02:00
Ref < Texture2D > edit_icon = Control : : get_theme_icon ( SNAME ( " Edit " ) , SNAME ( " EditorIcons " ) ) ;
2017-07-01 02:30:17 +02:00
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) ) {
2017-07-01 02:30:17 +02:00
member_type = MEMBER_FUNCTION ;
member_name = ti - > get_text ( 0 ) ;
2019-09-13 21:14:12 +02:00
member_popup - > add_icon_shortcut ( edit_icon , ED_GET_SHORTCUT ( " visual_script_editor/edit_member " ) , MEMBER_EDIT ) ;
member_popup - > add_separator ( ) ;
2021-06-08 19:59:05 +02:00
member_popup - > add_icon_shortcut ( del_icon , ED_GET_SHORTCUT ( " ui_graph_delete " ) , MEMBER_REMOVE ) ;
2017-07-01 02:30:17 +02:00
member_popup - > popup ( ) ;
return ;
}
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) ) {
2017-07-01 02:30:17 +02:00
member_type = MEMBER_VARIABLE ;
member_name = ti - > get_text ( 0 ) ;
2018-01-05 20:45:54 +01:00
member_popup - > add_icon_shortcut ( edit_icon , ED_GET_SHORTCUT ( " visual_script_editor/edit_member " ) , MEMBER_EDIT ) ;
2017-07-01 02:30:17 +02:00
member_popup - > add_separator ( ) ;
2021-06-08 19:59:05 +02:00
member_popup - > add_icon_shortcut ( del_icon , ED_GET_SHORTCUT ( " ui_graph_delete " ) , MEMBER_REMOVE ) ;
2017-07-01 02:30:17 +02:00
member_popup - > popup ( ) ;
return ;
}
2021-03-07 21:07:30 +01:00
if ( ti - > get_parent ( ) = = root - > get_first_child ( ) - > get_next ( ) - > get_next ( ) ) {
2017-07-01 02:30:17 +02:00
member_type = MEMBER_SIGNAL ;
member_name = ti - > get_text ( 0 ) ;
2018-01-05 20:45:54 +01:00
member_popup - > add_icon_shortcut ( edit_icon , ED_GET_SHORTCUT ( " visual_script_editor/edit_member " ) , MEMBER_EDIT ) ;
2017-07-01 02:30:17 +02:00
member_popup - > add_separator ( ) ;
2021-06-08 19:59:05 +02:00
member_popup - > add_icon_shortcut ( del_icon , ED_GET_SHORTCUT ( " ui_graph_delete " ) , MEMBER_REMOVE ) ;
2017-07-01 02:30:17 +02:00
member_popup - > popup ( ) ;
return ;
}
}
void VisualScriptEditor : : _member_option ( int p_option ) {
switch ( member_type ) {
case MEMBER_FUNCTION : {
if ( p_option = = MEMBER_REMOVE ) {
2020-06-17 17:39:25 +02:00
// Delete the function.
2017-07-01 02:30:17 +02:00
String name = member_name ;
2020-06-17 17:39:25 +02:00
List < String > lst ;
int fn_node = script - > get_function_node_id ( name ) ;
2017-07-01 02:30:17 +02:00
undo_redo - > create_action ( TTR ( " Remove Function " ) ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " remove_function " , name ) ;
2020-06-17 17:39:25 +02:00
undo_redo - > add_do_method ( script . ptr ( ) , " remove_node " , fn_node ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " add_function " , name , fn_node ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " add_node " , fn_node , script - > get_node ( fn_node ) , script - > get_node_position ( fn_node ) ) ;
List < VisualScript : : SequenceConnection > seqcons ;
script - > get_sequence_connection_list ( & seqcons ) ;
2021-07-16 05:45:57 +02:00
for ( const VisualScript : : SequenceConnection & E : seqcons ) {
if ( E . from_node = = fn_node ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " sequence_connect " , fn_node , E . from_output , E . to_node ) ;
2020-06-17 17:39:25 +02:00
}
2017-07-01 02:30:17 +02:00
}
2020-06-17 17:39:25 +02:00
List < VisualScript : : DataConnection > datcons ;
script - > get_data_connection_list ( & datcons ) ;
2021-07-16 05:45:57 +02:00
for ( const VisualScript : : DataConnection & E : datcons ) {
if ( E . from_node = = fn_node ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " data_connect " , fn_node , E . from_port , E . to_node , E . to_port ) ;
2020-06-17 17:39:25 +02:00
}
2017-07-01 02:30:17 +02:00
}
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > add_do_method ( this , " _update_graph " ) ;
undo_redo - > add_undo_method ( this , " _update_graph " ) ;
undo_redo - > commit_action ( ) ;
2019-09-13 21:14:12 +02:00
} else if ( p_option = = MEMBER_EDIT ) {
selected = members - > get_selected ( ) - > get_text ( 0 ) ;
function_name_edit - > popup ( ) ;
2019-09-29 13:55:09 +02:00
function_name_box - > set_text ( selected ) ;
function_name_box - > select_all ( ) ;
2022-02-12 21:28:28 +01:00
function_name_box - > grab_focus ( ) ;
2017-07-01 02:30:17 +02:00
}
} break ;
case MEMBER_VARIABLE : {
String name = member_name ;
if ( p_option = = MEMBER_REMOVE ) {
undo_redo - > create_action ( TTR ( " Remove Variable " ) ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " remove_variable " , name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " add_variable " , name , script - > get_variable_default_value ( name ) ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " set_variable_info " , name , script - > call ( " get_variable_info " , name ) ) ; //return as dict
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > commit_action ( ) ;
} else if ( p_option = = MEMBER_EDIT ) {
variable_editor - > edit ( name ) ;
edit_variable_dialog - > set_title ( TTR ( " Editing Variable: " ) + " " + name ) ;
2020-03-06 18:00:16 +01:00
edit_variable_dialog - > popup_centered ( Size2 ( 400 , 200 ) * EDSCALE ) ;
2017-07-01 02:30:17 +02:00
}
} break ;
case MEMBER_SIGNAL : {
String name = member_name ;
if ( p_option = = MEMBER_REMOVE ) {
undo_redo - > create_action ( TTR ( " Remove Signal " ) ) ;
undo_redo - > add_do_method ( script . ptr ( ) , " remove_custom_signal " , name ) ;
undo_redo - > add_undo_method ( script . ptr ( ) , " add_custom_signal " , name ) ;
for ( int i = 0 ; i < script - > custom_signal_get_argument_count ( name ) ; i + + ) {
undo_redo - > add_undo_method ( script . ptr ( ) , " custom_signal_add_argument " , name , script - > custom_signal_get_argument_name ( name , i ) , script - > custom_signal_get_argument_type ( name , i ) ) ;
}
undo_redo - > add_do_method ( this , " _update_members " ) ;
undo_redo - > add_undo_method ( this , " _update_members " ) ;
undo_redo - > commit_action ( ) ;
} else if ( p_option = = MEMBER_EDIT ) {
signal_editor - > edit ( name ) ;
edit_signal_dialog - > set_title ( TTR ( " Editing Signal: " ) + " " + name ) ;
2020-03-06 18:00:16 +01:00
edit_signal_dialog - > popup_centered ( Size2 ( 400 , 300 ) * EDSCALE ) ;
2017-07-01 02:30:17 +02:00
}
} break ;
}
}
2020-05-03 18:08:15 +02:00
void VisualScriptEditor : : add_syntax_highlighter ( Ref < EditorSyntaxHighlighter > p_highlighter ) {
2018-04-02 13:41:44 +02:00
}
2020-05-03 18:08:15 +02:00
void VisualScriptEditor : : set_syntax_highlighter ( Ref < EditorSyntaxHighlighter > p_highlighter ) {
2018-04-02 13:41:44 +02:00
}
2021-09-14 11:17:47 +02:00
void VisualScriptEditor : : update_toggle_scripts_button ( ) {
if ( is_layout_rtl ( ) ) {
toggle_scripts_button - > set_icon ( Control : : get_theme_icon ( ScriptEditor : : get_singleton ( ) - > is_scripts_panel_toggled ( ) ? SNAME ( " Forward " ) : SNAME ( " Back " ) , SNAME ( " EditorIcons " ) ) ) ;
} else {
toggle_scripts_button - > set_icon ( Control : : get_theme_icon ( ScriptEditor : : get_singleton ( ) - > is_scripts_panel_toggled ( ) ? SNAME ( " Back " ) : SNAME ( " Forward " ) , SNAME ( " EditorIcons " ) ) ) ;
}
toggle_scripts_button - > set_tooltip ( vformat ( " %s (%s) " , TTR ( " Toggle Scripts Panel " ) , ED_GET_SHORTCUT ( " script_editor/toggle_scripts_panel " ) - > get_as_text ( ) ) ) ;
}
2016-08-03 00:11:05 +02:00
void VisualScriptEditor : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _move_node " , & VisualScriptEditor : : _move_node ) ;
ClassDB : : bind_method ( " _update_graph " , & VisualScriptEditor : : _update_graph , DEFVAL ( - 1 ) ) ;
2020-02-21 18:28:45 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _center_on_node " , & VisualScriptEditor : : _center_on_node ) ;
ClassDB : : bind_method ( " _button_resource_previewed " , & VisualScriptEditor : : _button_resource_previewed ) ;
ClassDB : : bind_method ( " _port_action_menu " , & VisualScriptEditor : : _port_action_menu ) ;
2017-09-12 12:58:18 +02:00
2019-09-13 21:14:12 +02:00
ClassDB : : bind_method ( " _create_new_node_from_name " , & VisualScriptEditor : : _create_new_node_from_name ) ;
2017-03-05 16:44:50 +01:00
2021-05-15 23:48:59 +02:00
ClassDB : : bind_method ( " _get_drag_data_fw " , & VisualScriptEditor : : get_drag_data_fw ) ;
ClassDB : : bind_method ( " _can_drop_data_fw " , & VisualScriptEditor : : can_drop_data_fw ) ;
ClassDB : : bind_method ( " _drop_data_fw " , & VisualScriptEditor : : drop_data_fw ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _update_graph_connections " , & VisualScriptEditor : : _update_graph_connections ) ;
2020-04-03 11:35:26 +02:00
ClassDB : : bind_method ( " _update_members " , & VisualScriptEditor : : _update_members ) ;
2017-03-05 16:44:50 +01:00
2018-07-25 17:25:03 +02:00
ClassDB : : bind_method ( " _generic_search " , & VisualScriptEditor : : _generic_search ) ;
2016-08-03 00:11:05 +02:00
}
VisualScriptEditor : : VisualScriptEditor ( ) {
2016-08-31 22:58:51 +02:00
if ( ! clipboard ) {
2017-03-05 16:44:50 +01:00
clipboard = memnew ( Clipboard ) ;
2016-08-31 22:58:51 +02:00
}
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
edit_menu = memnew ( MenuButton ) ;
2020-09-17 03:40:00 +02:00
edit_menu - > set_shortcut_context ( this ) ;
2016-08-07 00:00:54 +02:00
edit_menu - > set_text ( TTR ( " Edit " ) ) ;
2018-07-30 00:26:43 +02:00
edit_menu - > set_switch_on_hover ( true ) ;
2020-12-07 12:32:00 +01:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_graph_delete " ) , EDIT_DELETE_NODES ) ;
2016-08-07 00:00:54 +02:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " visual_script_editor/toggle_breakpoint " ) , EDIT_TOGGLE_BREAKPOINT ) ;
2016-08-08 06:41:57 +02:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " visual_script_editor/find_node_type " ) , EDIT_FIND_NODE_TYPE ) ;
2016-08-25 22:45:20 +02:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
2020-12-07 12:32:00 +01:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_copy " ) , EDIT_COPY_NODES ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_cut " ) , EDIT_CUT_NODES ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_paste " ) , EDIT_PASTE_NODES ) ;
2019-09-13 21:14:12 +02:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " visual_script_editor/create_function " ) , EDIT_CREATE_FUNCTION ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " visual_script_editor/refresh_nodes " ) , REFRESH_GRAPH ) ;
2020-02-21 18:28:45 +01:00
edit_menu - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & VisualScriptEditor : : _menu_option ) ) ;
2016-08-07 00:00:54 +02:00
2019-09-27 22:10:05 +02:00
members_section = memnew ( VBoxContainer ) ;
// Add but wait until done setting up this.
2021-07-17 23:22:52 +02:00
ScriptEditor : : get_singleton ( ) - > get_left_list_split ( ) - > call_deferred ( SNAME ( " add_child " ) , members_section ) ;
2019-09-27 22:10:05 +02:00
members_section - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2016-08-03 00:11:05 +02:00
2019-07-26 22:00:23 +02:00
CheckButton * tool_script_check = memnew ( CheckButton ) ;
tool_script_check - > set_text ( TTR ( " Make Tool: " ) ) ;
2019-09-27 22:10:05 +02:00
members_section - > add_child ( tool_script_check ) ;
2020-02-21 18:28:45 +01:00
tool_script_check - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _toggle_tool_script ) ) ;
2019-07-26 22:00:23 +02:00
2019-09-13 21:14:12 +02:00
/// Members ///
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
members = memnew ( Tree ) ;
2019-09-27 22:10:05 +02:00
members_section - > add_margin_child ( TTR ( " Members: " ) , members , true ) ;
members - > set_custom_minimum_size ( Size2 ( 0 , 50 * EDSCALE ) ) ;
2016-08-03 00:11:05 +02:00
members - > set_hide_root ( true ) ;
2021-09-18 09:33:18 +02:00
members - > connect ( " button_clicked " , callable_mp ( this , & VisualScriptEditor : : _member_button ) ) ;
2020-02-21 18:28:45 +01:00
members - > connect ( " item_edited " , callable_mp ( this , & VisualScriptEditor : : _member_edited ) ) ;
2022-07-28 22:56:41 +02:00
members - > connect ( " cell_selected " , callable_mp ( this , & VisualScriptEditor : : _member_selected ) , CONNECT_DEFERRED ) ;
2020-02-21 18:28:45 +01:00
members - > connect ( " gui_input " , callable_mp ( this , & VisualScriptEditor : : _members_gui_input ) ) ;
2021-09-18 09:33:18 +02:00
members - > connect ( " item_mouse_selected " , callable_mp ( this , & VisualScriptEditor : : _member_rmb_selected ) ) ;
2019-09-13 21:14:12 +02:00
members - > set_allow_rmb_select ( true ) ;
2017-08-18 23:19:12 +02:00
members - > set_allow_reselect ( true ) ;
2016-08-03 00:11:05 +02:00
members - > set_hide_folding ( true ) ;
members - > set_drag_forwarding ( this ) ;
2019-09-13 21:14:12 +02:00
member_popup = memnew ( PopupMenu ) ;
add_child ( member_popup ) ;
2020-02-21 18:28:45 +01:00
member_popup - > connect ( " id_pressed " , callable_mp ( this , & VisualScriptEditor : : _member_option ) ) ;
2019-09-13 21:14:12 +02:00
2020-03-06 18:00:16 +01:00
function_name_edit = memnew ( AcceptDialog ) ;
2022-02-12 21:28:28 +01:00
function_name_edit - > set_title ( TTR ( " Rename Function " ) ) ;
2019-09-13 21:14:12 +02:00
function_name_box = memnew ( LineEdit ) ;
function_name_edit - > add_child ( function_name_box ) ;
2020-02-21 18:28:45 +01:00
function_name_box - > connect ( " gui_input " , callable_mp ( this , & VisualScriptEditor : : _fn_name_box_input ) ) ;
2022-02-12 21:28:28 +01:00
function_name_edit - > get_ok_button ( ) - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _on_fn_name_box_confirmed ) ) ;
2021-03-28 20:31:25 +02:00
function_name_box - > set_expand_to_text_length_enabled ( true ) ;
2019-09-13 21:14:12 +02:00
add_child ( function_name_edit ) ;
/// Actual Graph ///
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
graph = memnew ( GraphEdit ) ;
2017-07-01 02:30:17 +02:00
add_child ( graph ) ;
2018-07-10 15:30:26 +02:00
graph - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2022-03-19 01:02:57 +01:00
graph - > set_anchors_and_offsets_preset ( Control : : PRESET_FULL_RECT ) ;
2022-04-30 03:56:57 +02:00
graph - > set_show_zoom_label ( true ) ;
2020-02-21 18:28:45 +01:00
graph - > connect ( " node_selected " , callable_mp ( this , & VisualScriptEditor : : _node_selected ) ) ;
2020-10-20 08:22:40 +02:00
graph - > connect ( " begin_node_move " , callable_mp ( this , & VisualScriptEditor : : _begin_node_move ) ) ;
graph - > connect ( " end_node_move " , callable_mp ( this , & VisualScriptEditor : : _end_node_move ) ) ;
2021-10-02 19:31:48 +02:00
graph - > connect ( " copy_nodes_request " , callable_mp ( this , & VisualScriptEditor : : _on_nodes_copy ) ) ;
graph - > connect ( " paste_nodes_request " , callable_mp ( this , & VisualScriptEditor : : _on_nodes_paste ) ) ;
2020-02-21 18:28:45 +01:00
graph - > connect ( " delete_nodes_request " , callable_mp ( this , & VisualScriptEditor : : _on_nodes_delete ) ) ;
graph - > connect ( " duplicate_nodes_request " , callable_mp ( this , & VisualScriptEditor : : _on_nodes_duplicate ) ) ;
graph - > connect ( " gui_input " , callable_mp ( this , & VisualScriptEditor : : _graph_gui_input ) ) ;
2016-08-03 00:11:05 +02:00
graph - > set_drag_forwarding ( this ) ;
2021-01-25 15:37:05 +01:00
float graph_minimap_opacity = EditorSettings : : get_singleton ( ) - > get ( " editors/visual_editors/minimap_opacity " ) ;
graph - > set_minimap_opacity ( graph_minimap_opacity ) ;
2022-05-30 15:38:13 +02:00
float graph_lines_curvature = EditorSettings : : get_singleton ( ) - > get ( " editors/visual_editors/lines_curvature " ) ;
graph - > set_connection_lines_curvature ( graph_lines_curvature ) ;
2016-08-03 16:28:20 +02:00
graph - > hide ( ) ;
2020-02-21 18:28:45 +01:00
graph - > connect ( " scroll_offset_changed " , callable_mp ( this , & VisualScriptEditor : : _graph_ofs_changed ) ) ;
2016-08-03 16:28:20 +02:00
2021-09-14 11:17:47 +02:00
status_bar = memnew ( HBoxContainer ) ;
add_child ( status_bar ) ;
status_bar - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
status_bar - > set_custom_minimum_size ( Size2 ( 0 , 24 * EDSCALE ) ) ;
toggle_scripts_button = memnew ( Button ) ;
toggle_scripts_button - > set_flat ( true ) ;
toggle_scripts_button - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _toggle_scripts_pressed ) ) ;
status_bar - > add_child ( toggle_scripts_button ) ;
2019-09-27 22:10:05 +02:00
/// Add Buttons to Top Bar/Zoom bar.
2019-09-13 21:14:12 +02:00
HBoxContainer * graph_hbc = graph - > get_zoom_hbox ( ) ;
Label * base_lbl = memnew ( Label ) ;
2019-12-16 06:18:44 +01:00
base_lbl - > set_text ( TTR ( " Change Base Type: " ) + " " ) ;
2019-09-13 21:14:12 +02:00
graph_hbc - > add_child ( base_lbl ) ;
base_type_select = memnew ( Button ) ;
2020-02-21 18:28:45 +01:00
base_type_select - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _change_base_type ) ) ;
2019-09-13 21:14:12 +02:00
graph_hbc - > add_child ( base_type_select ) ;
Button * add_nds = memnew ( Button ) ;
2019-12-16 06:18:44 +01:00
add_nds - > set_text ( TTR ( " Add Nodes... " ) ) ;
2019-09-13 21:14:12 +02:00
graph_hbc - > add_child ( add_nds ) ;
2020-02-21 18:28:45 +01:00
add_nds - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _add_node_dialog ) ) ;
2019-09-13 21:14:12 +02:00
Button * fn_btn = memnew ( Button ) ;
2019-12-16 06:18:44 +01:00
fn_btn - > set_text ( TTR ( " Add Function... " ) ) ;
2019-09-13 21:14:12 +02:00
graph_hbc - > add_child ( fn_btn ) ;
2020-02-21 18:28:45 +01:00
fn_btn - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _create_function_dialog ) ) ;
2019-09-13 21:14:12 +02:00
2019-09-27 22:10:05 +02:00
// Add Function Dialog.
2019-09-13 21:14:12 +02:00
VBoxContainer * function_vb = memnew ( VBoxContainer ) ;
function_vb - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2019-12-17 02:04:30 +01:00
function_vb - > set_custom_minimum_size ( Size2 ( 450 , 300 ) * EDSCALE ) ;
2019-09-13 21:14:12 +02:00
HBoxContainer * func_name_hbox = memnew ( HBoxContainer ) ;
function_vb - > add_child ( func_name_hbox ) ;
Label * func_name_label = memnew ( Label ) ;
func_name_label - > set_text ( TTR ( " Name: " ) ) ;
func_name_hbox - > add_child ( func_name_label ) ;
func_name_box = memnew ( LineEdit ) ;
func_name_box - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
func_name_box - > set_placeholder ( TTR ( " function_name " ) ) ;
func_name_box - > set_text ( " " ) ;
2020-02-21 18:28:45 +01:00
func_name_box - > connect ( " focus_entered " , callable_mp ( this , & VisualScriptEditor : : _deselect_input_names ) ) ;
2019-09-13 21:14:12 +02:00
func_name_hbox - > add_child ( func_name_box ) ;
2019-09-27 22:10:05 +02:00
// Add minor setting for function if needed, here!
2019-09-13 21:14:12 +02:00
function_vb - > add_child ( memnew ( HSeparator ) ) ;
Button * add_input_button = memnew ( Button ) ;
add_input_button - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2019-09-28 00:59:53 +02:00
add_input_button - > set_text ( TTR ( " Add Input " ) ) ;
2020-02-21 18:28:45 +01:00
add_input_button - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _add_func_input ) ) ;
2019-09-13 21:14:12 +02:00
function_vb - > add_child ( add_input_button ) ;
2019-09-28 00:59:53 +02:00
func_input_scroll = memnew ( ScrollContainer ) ;
func_input_scroll - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
function_vb - > add_child ( func_input_scroll ) ;
2019-09-13 21:14:12 +02:00
2019-09-28 00:59:53 +02:00
func_input_vbox = memnew ( VBoxContainer ) ;
func_input_vbox - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
func_input_scroll - > add_child ( func_input_vbox ) ;
2019-09-13 21:14:12 +02:00
function_create_dialog = memnew ( ConfirmationDialog ) ;
function_create_dialog - > set_title ( TTR ( " Create Function " ) ) ;
function_create_dialog - > add_child ( function_vb ) ;
2022-07-08 02:31:19 +02:00
function_create_dialog - > set_ok_button_text ( TTR ( " Create " ) ) ;
2020-12-14 19:37:30 +01:00
function_create_dialog - > get_ok_button ( ) - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _create_function ) ) ;
2019-09-13 21:14:12 +02:00
add_child ( function_create_dialog ) ;
2017-03-05 16:44:50 +01:00
select_func_text = memnew ( Label ) ;
2019-03-25 01:54:29 +01:00
select_func_text - > set_text ( TTR ( " Select or create a function to edit its graph. " ) ) ;
2021-11-25 03:58:47 +01:00
select_func_text - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
select_func_text - > set_vertical_alignment ( VERTICAL_ALIGNMENT_CENTER ) ;
2016-08-03 16:28:20 +02:00
select_func_text - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-07-01 02:30:17 +02:00
add_child ( select_func_text ) ;
2016-08-03 16:28:20 +02:00
2017-03-05 16:44:50 +01:00
hint_text = memnew ( Label ) ;
2020-12-22 17:24:29 +01:00
hint_text - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_END , - 100 ) ;
hint_text - > set_anchor_and_offset ( SIDE_BOTTOM , ANCHOR_END , 0 ) ;
hint_text - > set_anchor_and_offset ( SIDE_RIGHT , ANCHOR_END , 0 ) ;
2021-11-25 03:58:47 +01:00
hint_text - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
hint_text - > set_vertical_alignment ( VERTICAL_ALIGNMENT_CENTER ) ;
2016-08-03 16:28:20 +02:00
graph - > add_child ( hint_text ) ;
2017-03-05 16:44:50 +01:00
hint_text_timer = memnew ( Timer ) ;
2016-08-03 16:28:20 +02:00
hint_text_timer - > set_wait_time ( 4 ) ;
2020-02-21 18:28:45 +01:00
hint_text_timer - > connect ( " timeout " , callable_mp ( this , & VisualScriptEditor : : _hide_timer ) ) ;
2016-08-03 16:28:20 +02:00
add_child ( hint_text_timer ) ;
2016-08-03 00:11:05 +02:00
2019-09-27 22:10:05 +02:00
// Allowed casts (connections).
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < Variant : : VARIANT_MAX ; i + + ) {
graph - > add_valid_connection_type ( Variant : : NIL , i ) ;
graph - > add_valid_connection_type ( i , Variant : : NIL ) ;
for ( int j = 0 ; j < Variant : : VARIANT_MAX ; j + + ) {
if ( Variant : : can_convert ( Variant : : Type ( i ) , Variant : : Type ( j ) ) ) {
graph - > add_valid_connection_type ( i , j ) ;
2016-08-03 00:11:05 +02:00
}
}
graph - > add_valid_right_disconnect_type ( i ) ;
}
graph - > add_valid_left_disconnect_type ( TYPE_SEQUENCE ) ;
2020-02-21 18:28:45 +01:00
graph - > connect ( " connection_request " , callable_mp ( this , & VisualScriptEditor : : _graph_connected ) ) ;
graph - > connect ( " disconnection_request " , callable_mp ( this , & VisualScriptEditor : : _graph_disconnected ) ) ;
graph - > connect ( " connection_to_empty " , callable_mp ( this , & VisualScriptEditor : : _graph_connect_to_empty ) ) ;
2016-08-03 00:11:05 +02:00
2017-03-05 16:44:50 +01:00
edit_signal_dialog = memnew ( AcceptDialog ) ;
2022-07-08 02:31:19 +02:00
edit_signal_dialog - > set_ok_button_text ( TTR ( " Close " ) ) ;
2016-08-03 00:11:05 +02:00
add_child ( edit_signal_dialog ) ;
2017-03-05 16:44:50 +01:00
signal_editor = memnew ( VisualScriptEditorSignalEdit ) ;
2018-09-08 11:51:23 +02:00
edit_signal_edit = memnew ( EditorInspector ) ;
2016-08-03 00:11:05 +02:00
edit_signal_dialog - > add_child ( edit_signal_edit ) ;
2017-01-10 05:49:55 +01:00
2016-08-03 00:11:05 +02:00
edit_signal_edit - > edit ( signal_editor ) ;
2017-03-05 16:44:50 +01:00
edit_variable_dialog = memnew ( AcceptDialog ) ;
2022-07-08 02:31:19 +02:00
edit_variable_dialog - > set_ok_button_text ( TTR ( " Close " ) ) ;
2016-08-03 00:11:05 +02:00
add_child ( edit_variable_dialog ) ;
2017-03-05 16:44:50 +01:00
variable_editor = memnew ( VisualScriptEditorVariableEdit ) ;
2018-09-08 11:51:23 +02:00
edit_variable_edit = memnew ( EditorInspector ) ;
2016-08-03 00:11:05 +02:00
edit_variable_dialog - > add_child ( edit_variable_edit ) ;
2017-01-10 05:49:55 +01:00
2016-08-03 00:11:05 +02:00
edit_variable_edit - > edit ( variable_editor ) ;
2017-03-05 16:44:50 +01:00
select_base_type = memnew ( CreateDialog ) ;
2019-09-27 22:10:05 +02:00
select_base_type - > set_base_type ( " Object " ) ; // Anything goes.
2020-02-21 18:28:45 +01:00
select_base_type - > connect ( " create " , callable_mp ( this , & VisualScriptEditor : : _change_base_type_callback ) ) ;
2016-08-03 00:11:05 +02:00
add_child ( select_base_type ) ;
undo_redo = EditorNode : : get_singleton ( ) - > get_undo_redo ( ) ;
2019-09-13 21:14:12 +02:00
set_process_input ( true ) ;
2016-08-04 03:06:39 +02:00
2022-08-01 20:01:48 +02:00
default_property_editor_popup = memnew ( PopupPanel ) ;
default_property_editor_popup - > set_min_size ( Size2i ( 180 , 0 ) * EDSCALE ) ;
add_child ( default_property_editor_popup ) ;
edited_default_property_holder . instantiate ( ) ;
2016-08-04 03:06:39 +02:00
2018-05-13 05:34:35 +02:00
new_connect_node_select = memnew ( VisualScriptPropertySelector ) ;
2016-09-03 19:58:23 +02:00
add_child ( new_connect_node_select ) ;
2020-02-21 18:28:45 +01:00
new_connect_node_select - > connect ( " selected " , callable_mp ( this , & VisualScriptEditor : : _selected_connect_node ) ) ;
2020-12-14 19:37:30 +01:00
new_connect_node_select - > get_cancel_button ( ) - > connect ( " pressed " , callable_mp ( this , & VisualScriptEditor : : _cancel_connect_node ) ) ;
2016-09-03 19:58:23 +02:00
2018-05-13 05:34:35 +02:00
new_virtual_method_select = memnew ( VisualScriptPropertySelector ) ;
2017-09-12 12:58:18 +02:00
add_child ( new_virtual_method_select ) ;
2020-02-21 18:28:45 +01:00
new_virtual_method_select - > connect ( " selected " , callable_mp ( this , & VisualScriptEditor : : _selected_new_virtual_method ) ) ;
2022-01-09 17:10:17 +01:00
popup_menu = memnew ( PopupMenu ) ;
add_child ( popup_menu ) ;
popup_menu - > add_item ( TTR ( " Add Node " ) , EDIT_ADD_NODE ) ;
popup_menu - > add_separator ( ) ;
popup_menu - > add_item ( TTR ( " Cut " ) , EDIT_CUT_NODES ) ;
popup_menu - > add_item ( TTR ( " Copy " ) , EDIT_COPY_NODES ) ;
popup_menu - > add_item ( TTR ( " Paste " ) , EDIT_PASTE_NODES ) ;
popup_menu - > add_item ( TTR ( " Delete " ) , EDIT_DELETE_NODES ) ;
popup_menu - > add_item ( TTR ( " Duplicate " ) , EDIT_DUPLICATE_NODES ) ;
popup_menu - > add_item ( TTR ( " Clear Copy Buffer " ) , EDIT_CLEAR_COPY_BUFFER ) ;
popup_menu - > connect ( " id_pressed " , callable_mp ( this , & VisualScriptEditor : : _menu_option ) ) ;
2022-03-30 18:42:17 +02:00
base_type_map . insert ( " String " , Variant : : STRING ) ;
base_type_map . insert ( " Vector2 " , Variant : : VECTOR2 ) ;
base_type_map . insert ( " Vector2i " , Variant : : VECTOR2I ) ;
base_type_map . insert ( " Rect2 " , Variant : : RECT2 ) ;
base_type_map . insert ( " Rect2i " , Variant : : RECT2I ) ;
base_type_map . insert ( " Vector3 " , Variant : : VECTOR3 ) ;
base_type_map . insert ( " Vector3i " , Variant : : VECTOR3I ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
base_type_map . insert ( " Vector4 " , Variant : : VECTOR4 ) ;
base_type_map . insert ( " Vector4i " , Variant : : VECTOR4I ) ;
2022-03-30 18:42:17 +02:00
base_type_map . insert ( " Transform2D " , Variant : : TRANSFORM2D ) ;
base_type_map . insert ( " Plane " , Variant : : PLANE ) ;
base_type_map . insert ( " Quaternion " , Variant : : QUATERNION ) ;
base_type_map . insert ( " AABB " , Variant : : AABB ) ;
base_type_map . insert ( " Basis " , Variant : : BASIS ) ;
base_type_map . insert ( " Transform3D " , Variant : : TRANSFORM3D ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
base_type_map . insert ( " Projection " , Variant : : PROJECTION ) ;
2022-03-30 18:42:17 +02:00
base_type_map . insert ( " Color " , Variant : : COLOR ) ;
base_type_map . insert ( " NodePath " , Variant : : NODE_PATH ) ;
base_type_map . insert ( " RID " , Variant : : RID ) ;
base_type_map . insert ( " Callable " , Variant : : CALLABLE ) ;
base_type_map . insert ( " Dictionary " , Variant : : DICTIONARY ) ;
base_type_map . insert ( " Array " , Variant : : ARRAY ) ;
base_type_map . insert ( " PackedByteArray " , Variant : : PACKED_BYTE_ARRAY ) ;
base_type_map . insert ( " PackedInt32Array " , Variant : : PACKED_INT32_ARRAY ) ;
base_type_map . insert ( " PackedFloat32Array " , Variant : : PACKED_FLOAT32_ARRAY ) ;
base_type_map . insert ( " PackedInt64Array " , Variant : : PACKED_INT64_ARRAY ) ;
base_type_map . insert ( " PackedFloat64Array " , Variant : : PACKED_FLOAT64_ARRAY ) ;
base_type_map . insert ( " PackedStringArray " , Variant : : PACKED_STRING_ARRAY ) ;
base_type_map . insert ( " PackedVector2Array " , Variant : : PACKED_VECTOR2_ARRAY ) ;
base_type_map . insert ( " PackedVector3Array " , Variant : : PACKED_VECTOR3_ARRAY ) ;
base_type_map . insert ( " PackedColorArray " , Variant : : PACKED_COLOR_ARRAY ) ;
2016-08-03 00:11:05 +02:00
}
VisualScriptEditor : : ~ VisualScriptEditor ( ) {
2019-09-27 22:10:05 +02:00
undo_redo - > clear_history ( ) ; // Avoid crashes.
2016-08-03 00:11:05 +02:00
memdelete ( signal_editor ) ;
memdelete ( variable_editor ) ;
}
2022-05-03 01:43:50 +02:00
static ScriptEditorBase * create_editor ( const Ref < Resource > & p_resource ) {
2018-05-28 17:52:28 +02:00
if ( Object : : cast_to < VisualScript > ( * p_resource ) ) {
2017-03-05 16:44:50 +01:00
return memnew ( VisualScriptEditor ) ;
2016-08-03 00:11:05 +02:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2016-08-03 00:11:05 +02:00
}
2020-04-02 01:20:12 +02:00
VisualScriptEditor : : Clipboard * VisualScriptEditor : : clipboard = nullptr ;
2016-08-31 22:58:51 +02:00
void VisualScriptEditor : : free_clipboard ( ) {
2020-05-14 16:41:43 +02:00
if ( clipboard ) {
2016-08-31 22:58:51 +02:00
memdelete ( clipboard ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-31 22:58:51 +02:00
}
2016-08-07 00:00:54 +02:00
static void register_editor_callback ( ) {
ScriptEditor : : register_create_script_editor_function ( create_editor ) ;
2021-08-13 23:31:57 +02:00
ED_SHORTCUT ( " visual_script_editor/toggle_breakpoint " , TTR ( " Toggle Breakpoint " ) , Key : : F9 ) ;
ED_SHORTCUT ( " visual_script_editor/find_node_type " , TTR ( " Find Node Type " ) , KeyModifierMask : : CMD + Key : : F ) ;
ED_SHORTCUT ( " visual_script_editor/create_function " , TTR ( " Make Function " ) , KeyModifierMask : : CMD + Key : : G ) ;
ED_SHORTCUT ( " visual_script_editor/refresh_nodes " , TTR ( " Refresh Graph " ) , KeyModifierMask : : CMD + Key : : R ) ;
ED_SHORTCUT ( " visual_script_editor/edit_member " , TTR ( " Edit Member " ) , KeyModifierMask : : CMD + Key : : E ) ;
2016-08-07 00:00:54 +02:00
}
2016-08-03 00:11:05 +02:00
void VisualScriptEditor : : register_editor ( ) {
2019-09-27 22:10:05 +02:00
// Too early to register stuff here, request a callback.
2016-08-07 00:00:54 +02:00
EditorNode : : add_plugin_init_callback ( register_editor_callback ) ;
2016-08-03 00:11:05 +02:00
}
2021-08-13 16:46:14 +02:00
void VisualScriptEditor : : validate ( ) {
}
2021-08-23 18:15:50 +02:00
// VisualScriptCustomNodes
2021-08-13 16:46:14 +02:00
2021-08-23 18:15:50 +02:00
Ref < VisualScriptNode > VisualScriptCustomNodes : : create_node_custom ( const String & p_name ) {
2017-11-15 16:57:24 +01:00
Ref < VisualScriptCustomNode > node ;
2021-06-18 00:03:09 +02:00
node . instantiate ( ) ;
2017-11-15 16:57:24 +01:00
node - > set_script ( singleton - > custom_nodes [ p_name ] ) ;
return node ;
}
2021-08-23 18:15:50 +02:00
VisualScriptCustomNodes * VisualScriptCustomNodes : : singleton = nullptr ;
2022-05-13 15:04:37 +02:00
HashMap < String , Ref < RefCounted > > VisualScriptCustomNodes : : custom_nodes ;
2017-11-15 16:57:24 +01:00
2021-08-23 18:15:50 +02:00
VisualScriptCustomNodes : : VisualScriptCustomNodes ( ) {
2017-11-15 16:57:24 +01:00
singleton = this ;
}
2021-08-23 18:15:50 +02:00
VisualScriptCustomNodes : : ~ VisualScriptCustomNodes ( ) {
2017-11-15 16:57:24 +01:00
custom_nodes . clear ( ) ;
}
2021-08-23 18:15:50 +02:00
void VisualScriptCustomNodes : : add_custom_node ( const String & p_name , const String & p_category , const Ref < Script > & p_script ) {
2017-11-15 16:57:24 +01:00
String node_name = " custom/ " + p_category + " / " + p_name ;
2020-02-13 20:03:10 +01:00
custom_nodes . insert ( node_name , p_script ) ;
2021-08-23 18:15:50 +02:00
VisualScriptLanguage : : singleton - > add_register_func ( node_name , & VisualScriptCustomNodes : : create_node_custom ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " custom_nodes_updated " ) ) ;
2017-11-15 16:57:24 +01:00
}
2021-08-23 18:15:50 +02:00
void VisualScriptCustomNodes : : remove_custom_node ( const String & p_name , const String & p_category ) {
2017-11-15 16:57:24 +01:00
String node_name = " custom/ " + p_category + " / " + p_name ;
custom_nodes . erase ( node_name ) ;
VisualScriptLanguage : : singleton - > remove_register_func ( node_name ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " custom_nodes_updated " ) ) ;
2017-11-15 16:57:24 +01:00
}
2021-08-23 18:15:50 +02:00
void VisualScriptCustomNodes : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " add_custom_node " , " name " , " category " , " script " ) , & VisualScriptCustomNodes : : add_custom_node ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_custom_node " , " name " , " category " ) , & VisualScriptCustomNodes : : remove_custom_node ) ;
2017-11-15 16:57:24 +01:00
ADD_SIGNAL ( MethodInfo ( " custom_nodes_updated " ) ) ;
}
2019-05-08 18:49:49 +02:00
2016-08-15 09:54:02 +02:00
# endif