2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* graph_node.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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
2014-12-20 16:32:14 +01:00
# include "graph_node.h"
2018-09-11 18:13:45 +02:00
2020-09-03 13:22:16 +02:00
# include "core/string/translation.h"
2023-08-09 18:31:15 +02:00
# include "scene/gui/box_container.h"
# include "scene/gui/label.h"
2023-09-12 15:01:42 +02:00
# include "scene/theme/theme_db.h"
2020-09-03 13:22:16 +02:00
2017-03-05 16:44:50 +01:00
bool GraphNode : : _set ( const StringName & p_name , const Variant & p_value ) {
2020-09-03 13:22:16 +02:00
String str = p_name ;
if ( ! str . begins_with ( " slot/ " ) ) {
2015-07-21 03:15:06 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-12-21 15:42:44 +01:00
2020-09-03 13:22:16 +02:00
int idx = str . get_slice ( " / " , 1 ) . to_int ( ) ;
2023-08-09 18:31:15 +02:00
String slot_property_name = str . get_slice ( " / " , 2 ) ;
Slot slot ;
if ( slot_table . has ( idx ) ) {
slot = slot_table [ idx ] ;
}
if ( slot_property_name = = " left_enabled " ) {
slot . enable_left = p_value ;
} else if ( slot_property_name = = " left_type " ) {
slot . type_left = p_value ;
} else if ( slot_property_name = = " left_icon " ) {
slot . custom_port_icon_left = p_value ;
} else if ( slot_property_name = = " left_color " ) {
slot . color_left = p_value ;
} else if ( slot_property_name = = " right_enabled " ) {
slot . enable_right = p_value ;
} else if ( slot_property_name = = " right_type " ) {
slot . type_right = p_value ;
} else if ( slot_property_name = = " right_color " ) {
slot . color_right = p_value ;
} else if ( slot_property_name = = " right_icon " ) {
slot . custom_port_icon_right = p_value ;
} else if ( slot_property_name = = " draw_stylebox " ) {
slot . draw_stylebox = p_value ;
2020-05-14 16:41:43 +02:00
} else {
2015-07-21 03:15:06 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
set_slot ( idx ,
slot . enable_left ,
slot . type_left ,
slot . color_left ,
slot . enable_right ,
slot . type_right ,
slot . color_right ,
slot . custom_port_icon_left ,
slot . custom_port_icon_right ,
slot . draw_stylebox ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-07-21 03:15:06 +02:00
return true ;
2014-12-21 15:42:44 +01:00
}
2017-03-05 16:44:50 +01:00
bool GraphNode : : _get ( const StringName & p_name , Variant & r_ret ) const {
2020-09-03 13:22:16 +02:00
String str = p_name ;
2023-08-09 18:31:15 +02:00
2020-09-03 13:22:16 +02:00
if ( ! str . begins_with ( " slot/ " ) ) {
2015-07-21 03:15:06 +02:00
return false ;
}
2014-12-21 15:42:44 +01:00
2020-09-03 13:22:16 +02:00
int idx = str . get_slice ( " / " , 1 ) . to_int ( ) ;
2023-08-09 18:31:15 +02:00
StringName slot_property_name = str . get_slice ( " / " , 2 ) ;
Slot slot ;
if ( slot_table . has ( idx ) ) {
slot = slot_table [ idx ] ;
}
if ( slot_property_name = = " left_enabled " ) {
r_ret = slot . enable_left ;
} else if ( slot_property_name = = " left_type " ) {
r_ret = slot . type_left ;
} else if ( slot_property_name = = " left_color " ) {
r_ret = slot . color_left ;
} else if ( slot_property_name = = " left_icon " ) {
r_ret = slot . custom_port_icon_left ;
} else if ( slot_property_name = = " right_enabled " ) {
r_ret = slot . enable_right ;
} else if ( slot_property_name = = " right_type " ) {
r_ret = slot . type_right ;
} else if ( slot_property_name = = " right_color " ) {
r_ret = slot . color_right ;
} else if ( slot_property_name = = " right_icon " ) {
r_ret = slot . custom_port_icon_right ;
} else if ( slot_property_name = = " draw_stylebox " ) {
r_ret = slot . draw_stylebox ;
2020-05-14 16:41:43 +02:00
} else {
2015-07-21 03:15:06 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-12-21 15:42:44 +01:00
2015-07-21 03:15:06 +02:00
return true ;
2014-12-21 15:42:44 +01:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void GraphNode : : _get_property_list ( List < PropertyInfo > * p_list ) const {
int idx = 0 ;
2023-08-09 18:31:15 +02:00
for ( int i = 0 ; i < get_child_count ( false ) ; i + + ) {
Control * child = Object : : cast_to < Control > ( get_child ( i , false ) ) ;
if ( ! child | | child - > is_set_as_top_level ( ) ) {
2015-07-21 03:15:06 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-12-21 15:42:44 +01:00
2017-03-05 16:44:50 +01:00
String base = " slot/ " + itos ( idx ) + " / " ;
2014-12-21 15:42:44 +01:00
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , base + " left_enabled " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : INT , base + " left_type " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , base + " left_color " ) ) ;
2021-01-26 08:21:27 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : OBJECT , base + " left_icon " , PROPERTY_HINT_RESOURCE_TYPE , " Texture2D " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL ) ) ;
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , base + " right_enabled " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : INT , base + " right_type " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , base + " right_color " ) ) ;
2021-01-26 08:21:27 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : OBJECT , base + " right_icon " , PROPERTY_HINT_RESOURCE_TYPE , " Texture2D " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL ) ) ;
2022-04-30 03:56:57 +02:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , base + " draw_stylebox " ) ) ;
2015-07-21 03:15:06 +02:00
idx + + ;
}
2014-12-21 15:42:44 +01:00
}
2014-12-20 16:32:14 +01:00
void GraphNode : : _resort ( ) {
2023-08-09 18:31:15 +02:00
Size2 new_size = get_size ( ) ;
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_panel = theme_cache . panel ;
Ref < StyleBox > sb_titlebar = theme_cache . titlebar ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
// Resort titlebar first.
Size2 titlebar_size = Size2 ( new_size . width , titlebar_hbox - > get_size ( ) . height ) ;
titlebar_size - = sb_titlebar - > get_minimum_size ( ) ;
Rect2 titlebar_rect = Rect2 ( sb_titlebar - > get_offset ( ) , titlebar_size ) ;
fit_child_in_rect ( titlebar_hbox , titlebar_rect ) ;
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
// After resort, the children of the titlebar container may have changed their height (e.g. Label autowrap).
Size2i titlebar_min_size = titlebar_hbox - > get_combined_minimum_size ( ) ;
// First pass, determine minimum size AND amount of stretchable elements.
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_slot = theme_cache . slot ;
int separation = theme_cache . separation ;
2020-06-24 21:59:41 +02:00
int children_count = 0 ;
int stretch_min = 0 ;
2023-08-09 18:31:15 +02:00
int available_stretch_space = 0 ;
2020-06-24 21:59:41 +02:00
float stretch_ratio_total = 0 ;
2022-05-13 15:04:37 +02:00
HashMap < Control * , _MinSizeCache > min_size_cache ;
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
for ( int i = 0 ; i < get_child_count ( false ) ; i + + ) {
2024-05-06 12:38:51 +02:00
Control * child = as_sortable_control ( get_child ( i , false ) ) ;
if ( ! child ) {
2015-07-21 03:15:06 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
Size2i size = child - > get_combined_minimum_size ( ) + ( slot_table [ i ] . draw_stylebox ? sb_slot - > get_minimum_size ( ) : Size2 ( ) ) ;
2014-12-20 16:32:14 +01:00
2020-06-24 21:59:41 +02:00
stretch_min + = size . height ;
2023-08-09 18:31:15 +02:00
_MinSizeCache msc ;
2020-06-24 21:59:41 +02:00
msc . min_size = size . height ;
2023-08-09 18:31:15 +02:00
msc . will_stretch = child - > get_v_size_flags ( ) . has_flag ( SIZE_EXPAND ) ;
msc . final_size = msc . min_size ;
min_size_cache [ child ] = msc ;
2014-12-20 16:32:14 +01:00
2020-06-24 21:59:41 +02:00
if ( msc . will_stretch ) {
2023-08-09 18:31:15 +02:00
available_stretch_space + = msc . min_size ;
stretch_ratio_total + = child - > get_stretch_ratio ( ) ;
2020-06-24 21:59:41 +02:00
}
2023-08-09 18:31:15 +02:00
2020-06-24 21:59:41 +02:00
children_count + + ;
}
if ( children_count = = 0 ) {
return ;
}
2023-08-09 18:31:15 +02:00
int stretch_max = new_size . height - ( children_count - 1 ) * separation ;
2020-06-24 21:59:41 +02:00
int stretch_diff = stretch_max - stretch_min ;
2023-08-09 18:31:15 +02:00
// Avoid negative stretch space.
stretch_diff = MAX ( stretch_diff , 0 ) ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
available_stretch_space + = stretch_diff - sb_panel - > get_margin ( SIDE_BOTTOM ) - sb_panel - > get_margin ( SIDE_TOP ) ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
// Second pass, discard elements that can't be stretched, this will run while stretchable elements exist.
while ( stretch_ratio_total > 0 ) {
// First of all, don't even be here if no stretchable objects exist.
bool refit_successful = true ;
for ( int i = 0 ; i < get_child_count ( false ) ; i + + ) {
2024-05-06 12:38:51 +02:00
Control * child = as_sortable_control ( get_child ( i , false ) ) ;
if ( ! child ) {
2020-06-24 21:59:41 +02:00
continue ;
}
2023-08-09 18:31:15 +02:00
ERR_FAIL_COND ( ! min_size_cache . has ( child ) ) ;
_MinSizeCache & msc = min_size_cache [ child ] ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
if ( msc . will_stretch ) {
int final_pixel_size = available_stretch_space * child - > get_stretch_ratio ( ) / stretch_ratio_total ;
2020-06-24 21:59:41 +02:00
if ( final_pixel_size < msc . min_size ) {
2023-08-09 18:31:15 +02:00
// If the available stretching area is too small for a Control,
// then remove it from stretching area.
2020-06-24 21:59:41 +02:00
msc . will_stretch = false ;
2023-08-09 18:31:15 +02:00
stretch_ratio_total - = child - > get_stretch_ratio ( ) ;
2020-06-24 21:59:41 +02:00
refit_successful = false ;
2023-08-09 18:31:15 +02:00
available_stretch_space - = msc . min_size ;
2020-06-24 21:59:41 +02:00
msc . final_size = msc . min_size ;
break ;
} else {
msc . final_size = final_pixel_size ;
}
}
}
2023-08-09 18:31:15 +02:00
if ( refit_successful ) {
2020-06-24 21:59:41 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2015-07-21 03:15:06 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
// Final pass, draw and stretch elements.
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
int ofs_y = sb_panel - > get_margin ( SIDE_TOP ) + titlebar_min_size . height + sb_titlebar - > get_minimum_size ( ) . height ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
slot_y_cache . clear ( ) ;
int width = new_size . width - sb_panel - > get_minimum_size ( ) . width ;
int valid_children_idx = 0 ;
for ( int i = 0 ; i < get_child_count ( false ) ; i + + ) {
2024-05-06 12:38:51 +02:00
Control * child = as_sortable_control ( get_child ( i , false ) ) ;
if ( ! child ) {
2015-07-21 03:15:06 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
_MinSizeCache & msc = min_size_cache [ child ] ;
if ( valid_children_idx > 0 ) {
ofs_y + = separation ;
2020-05-14 16:41:43 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
int from_y_pos = ofs_y ;
int to_y_pos = ofs_y + msc . final_size ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
// Adjust so the last valid child always fits perfect, compensating for numerical imprecision.
if ( msc . will_stretch & & valid_children_idx = = children_count - 1 ) {
to_y_pos = new_size . height - sb_panel - > get_margin ( SIDE_BOTTOM ) ;
2020-06-24 21:59:41 +02:00
}
2023-08-09 18:31:15 +02:00
int height = to_y_pos - from_y_pos ;
float margin = sb_panel - > get_margin ( SIDE_LEFT ) + ( slot_table [ i ] . draw_stylebox ? sb_slot - > get_margin ( SIDE_LEFT ) : 0 ) ;
float final_width = width - ( slot_table [ i ] . draw_stylebox ? sb_slot - > get_minimum_size ( ) . x : 0 ) ;
Rect2 rect ( margin , from_y_pos , final_width , height ) ;
fit_child_in_rect ( child , rect ) ;
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
slot_y_cache . push_back ( from_y_pos - sb_panel - > get_margin ( SIDE_TOP ) + height * 0.5 ) ;
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
ofs_y = to_y_pos ;
valid_children_idx + + ;
}
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
queue_redraw ( ) ;
port_pos_dirty = true ;
}
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
void GraphNode : : draw_port ( int p_slot_index , Point2i p_pos , bool p_left , const Color & p_color ) {
if ( GDVIRTUAL_CALL ( _draw_port , p_slot_index , p_pos , p_left , p_color ) ) {
return ;
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
Slot slot = slot_table [ p_slot_index ] ;
Ref < Texture2D > port_icon = p_left ? slot . custom_port_icon_left : slot . custom_port_icon_right ;
2020-06-24 21:59:41 +02:00
2023-08-09 18:31:15 +02:00
Point2 icon_offset ;
if ( ! port_icon . is_valid ( ) ) {
2023-09-12 15:01:42 +02:00
port_icon = theme_cache . port ;
2015-07-21 03:15:06 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
icon_offset = - port_icon - > get_size ( ) * 0.5 ;
port_icon - > draw ( get_canvas_item ( ) , p_pos + icon_offset , p_color ) ;
2014-12-20 16:32:14 +01:00
}
void GraphNode : : _notification ( int p_what ) {
2019-01-24 22:31:33 +01:00
switch ( p_what ) {
case NOTIFICATION_DRAW : {
2023-08-09 18:31:15 +02:00
// Used for layout calculations.
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_panel = theme_cache . panel ;
Ref < StyleBox > sb_titlebar = theme_cache . titlebar ;
2023-08-09 18:31:15 +02:00
// Used for drawing.
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_to_draw_panel = selected ? theme_cache . panel_selected : theme_cache . panel ;
Ref < StyleBox > sb_to_draw_titlebar = selected ? theme_cache . titlebar_selected : theme_cache . titlebar ;
2016-08-25 22:45:20 +02:00
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_slot = theme_cache . slot ;
2022-04-30 03:56:57 +02:00
2023-09-12 15:01:42 +02:00
int port_h_offset = theme_cache . port_h_offset ;
2016-08-07 00:00:54 +02:00
2023-08-09 18:31:15 +02:00
Rect2 titlebar_rect ( Point2 ( ) , titlebar_hbox - > get_size ( ) + sb_titlebar - > get_minimum_size ( ) ) ;
Size2 body_size = get_size ( ) ;
titlebar_rect . size . width = body_size . width ;
body_size . height - = titlebar_rect . size . height ;
Rect2 body_rect ( 0 , titlebar_rect . size . height , body_size . width , body_size . height ) ;
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
// Draw body (slots area) stylebox.
draw_style_box ( sb_to_draw_panel , body_rect ) ;
// Draw title bar stylebox above.
draw_style_box ( sb_to_draw_titlebar , titlebar_rect ) ;
int width = get_size ( ) . width - sb_panel - > get_minimum_size ( ) . x ;
2015-01-03 20:52:37 +01:00
2024-04-02 17:33:42 +02:00
// Take the HboxContainer child into account.
if ( get_child_count ( false ) > 0 ) {
2023-08-09 18:31:15 +02:00
int slot_index = 0 ;
for ( const KeyValue < int , Slot > & E : slot_table ) {
if ( E . key < 0 | | E . key > = slot_y_cache . size ( ) ) {
2022-11-29 02:10:45 +01:00
continue ;
2019-01-24 22:31:33 +01:00
}
2023-08-09 18:31:15 +02:00
if ( ! slot_table . has ( E . key ) ) {
2022-11-29 02:10:45 +01:00
continue ;
}
2023-08-09 18:31:15 +02:00
const Slot & slot = slot_table [ E . key ] ;
2022-11-29 02:10:45 +01:00
// Left port.
2023-08-09 18:31:15 +02:00
if ( slot . enable_left ) {
draw_port ( slot_index , Point2i ( port_h_offset , slot_y_cache [ E . key ] + sb_panel - > get_margin ( SIDE_TOP ) ) , true , slot . color_left ) ;
2022-11-29 02:10:45 +01:00
}
2023-08-09 18:31:15 +02:00
2022-11-29 02:10:45 +01:00
// Right port.
2023-08-09 18:31:15 +02:00
if ( slot . enable_right ) {
draw_port ( slot_index , Point2i ( get_size ( ) . x - port_h_offset , slot_y_cache [ E . key ] + sb_panel - > get_margin ( SIDE_TOP ) ) , false , slot . color_right ) ;
2019-01-24 22:31:33 +01:00
}
2022-04-30 03:56:57 +02:00
2022-11-29 02:10:45 +01:00
// Draw slot stylebox.
2023-08-09 18:31:15 +02:00
if ( slot . draw_stylebox ) {
Control * child = Object : : cast_to < Control > ( get_child ( E . key , false ) ) ;
if ( ! child | | ! child - > is_visible_in_tree ( ) ) {
2022-11-29 02:10:45 +01:00
continue ;
}
2023-08-09 18:31:15 +02:00
Rect2 child_rect = child - > get_rect ( ) ;
child_rect . position . x = sb_panel - > get_margin ( SIDE_LEFT ) ;
child_rect . size . width = width ;
draw_style_box ( sb_slot , child_rect ) ;
2022-11-29 02:10:45 +01:00
}
2023-08-09 18:31:15 +02:00
slot_index + + ;
2022-04-30 03:56:57 +02:00
}
2016-08-03 00:11:05 +02:00
}
2016-08-25 22:45:20 +02:00
2019-01-24 22:31:33 +01:00
if ( resizable ) {
2023-09-12 15:01:42 +02:00
draw_texture ( theme_cache . resizer , get_size ( ) - theme_cache . resizer - > get_size ( ) , theme_cache . resizer_color ) ;
2019-01-24 22:31:33 +01:00
}
} break ;
2015-07-21 03:15:06 +02:00
}
2014-12-20 16:32:14 +01:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot ( int p_slot_index , bool p_enable_left , int p_type_left , const Color & p_color_left , bool p_enable_right , int p_type_right , const Color & p_color_right , const Ref < Texture2D > & p_custom_left , const Ref < Texture2D > & p_custom_right , bool p_draw_stylebox ) {
ERR_FAIL_COND_MSG ( p_slot_index < 0 , vformat ( " Cannot set slot with index (%d) lesser than zero. " , p_slot_index ) ) ;
2014-12-21 15:42:44 +01:00
2021-01-26 08:21:27 +01:00
if ( ! p_enable_left & & p_type_left = = 0 & & p_color_left = = Color ( 1 , 1 , 1 , 1 ) & &
! p_enable_right & & p_type_right = = 0 & & p_color_right = = Color ( 1 , 1 , 1 , 1 ) & &
! p_custom_left . is_valid ( ) & & ! p_custom_right . is_valid ( ) ) {
2023-08-09 18:31:15 +02:00
slot_table . erase ( p_slot_index ) ;
2015-07-21 03:15:06 +02:00
return ;
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
Slot slot ;
slot . enable_left = p_enable_left ;
slot . type_left = p_type_left ;
slot . color_left = p_color_left ;
slot . enable_right = p_enable_right ;
slot . type_right = p_type_right ;
slot . color_right = p_color_right ;
slot . custom_port_icon_left = p_custom_left ;
slot . custom_port_icon_right = p_custom_right ;
slot . draw_stylebox = p_draw_stylebox ;
slot_table [ p_slot_index ] = slot ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-02-10 15:18:34 +01:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2014-12-20 16:32:14 +01:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : clear_slot ( int p_slot_index ) {
slot_table . erase ( p_slot_index ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2014-12-20 16:32:14 +01:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void GraphNode : : clear_all_slots ( ) {
2023-08-09 18:31:15 +02:00
slot_table . clear ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2014-12-20 16:32:14 +01:00
}
2020-05-14 14:29:06 +02:00
2023-08-09 18:31:15 +02:00
bool GraphNode : : is_slot_enabled_left ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2015-07-21 03:15:06 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . enable_left ;
2014-12-20 16:32:14 +01:00
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_enabled_left ( int p_slot_index , bool p_enable ) {
ERR_FAIL_COND_MSG ( p_slot_index < 0 , vformat ( " Cannot set enable_left for the slot with index (%d) lesser than zero. " , p_slot_index ) ) ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
if ( slot_table [ p_slot_index ] . enable_left = = p_enable ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . enable_left = p_enable ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2021-05-11 09:17:47 +02:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_type_left ( int p_slot_index , int p_type ) {
ERR_FAIL_COND_MSG ( ! slot_table . has ( p_slot_index ) , vformat ( " Cannot set type_left for the slot with index '%d' because it hasn't been enabled. " , p_slot_index ) ) ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
if ( slot_table [ p_slot_index ] . type_left = = p_type ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . type_left = p_type ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2021-05-11 09:17:47 +02:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_slot_type_left ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2015-07-21 03:15:06 +02:00
return 0 ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . type_left ;
2014-12-20 16:32:14 +01:00
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_color_left ( int p_slot_index , const Color & p_color ) {
ERR_FAIL_COND_MSG ( ! slot_table . has ( p_slot_index ) , vformat ( " Cannot set color_left for the slot with index '%d' because it hasn't been enabled. " , p_slot_index ) ) ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
if ( slot_table [ p_slot_index ] . color_left = = p_color ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . color_left = p_color ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2021-05-11 09:17:47 +02:00
}
2023-08-09 18:31:15 +02:00
Color GraphNode : : get_slot_color_left ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2017-03-05 16:44:50 +01:00
return Color ( 1 , 1 , 1 , 1 ) ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . color_left ;
2014-12-20 16:32:14 +01:00
}
2023-10-02 07:40:21 +02:00
void GraphNode : : set_slot_custom_icon_left ( int p_slot_index , const Ref < Texture2D > & p_custom_icon ) {
ERR_FAIL_COND_MSG ( ! slot_table . has ( p_slot_index ) , vformat ( " Cannot set custom_port_icon_left for the slot with index '%d' because it hasn't been enabled. " , p_slot_index ) ) ;
if ( slot_table [ p_slot_index ] . custom_port_icon_left = = p_custom_icon ) {
return ;
}
slot_table [ p_slot_index ] . custom_port_icon_left = p_custom_icon ;
queue_redraw ( ) ;
port_pos_dirty = true ;
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
}
Ref < Texture2D > GraphNode : : get_slot_custom_icon_left ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
return Ref < Texture2D > ( ) ;
}
return slot_table [ p_slot_index ] . custom_port_icon_left ;
}
2023-08-09 18:31:15 +02:00
bool GraphNode : : is_slot_enabled_right ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2015-07-21 03:15:06 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . enable_right ;
2014-12-20 16:32:14 +01:00
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_enabled_right ( int p_slot_index , bool p_enable ) {
ERR_FAIL_COND_MSG ( p_slot_index < 0 , vformat ( " Cannot set enable_right for the slot with index (%d) lesser than zero. " , p_slot_index ) ) ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
if ( slot_table [ p_slot_index ] . enable_right = = p_enable ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . enable_right = p_enable ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2021-05-11 09:17:47 +02:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_type_right ( int p_slot_index , int p_type ) {
ERR_FAIL_COND_MSG ( ! slot_table . has ( p_slot_index ) , vformat ( " Cannot set type_right for the slot with index '%d' because it hasn't been enabled. " , p_slot_index ) ) ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
if ( slot_table [ p_slot_index ] . type_right = = p_type ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . type_right = p_type ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2021-05-11 09:17:47 +02:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_slot_type_right ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2015-07-21 03:15:06 +02:00
return 0 ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . type_right ;
2014-12-20 16:32:14 +01:00
}
2014-12-21 15:42:44 +01:00
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_color_right ( int p_slot_index , const Color & p_color ) {
ERR_FAIL_COND_MSG ( ! slot_table . has ( p_slot_index ) , vformat ( " Cannot set color_right for the slot with index '%d' because it hasn't been enabled. " , p_slot_index ) ) ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
if ( slot_table [ p_slot_index ] . color_right = = p_color ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . color_right = p_color ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2021-05-11 09:17:47 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2021-05-11 09:17:47 +02:00
}
2023-08-09 18:31:15 +02:00
Color GraphNode : : get_slot_color_right ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2017-03-05 16:44:50 +01:00
return Color ( 1 , 1 , 1 , 1 ) ;
2020-05-14 16:41:43 +02:00
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . color_right ;
2014-12-20 16:32:14 +01:00
}
2023-10-02 07:40:21 +02:00
void GraphNode : : set_slot_custom_icon_right ( int p_slot_index , const Ref < Texture2D > & p_custom_icon ) {
ERR_FAIL_COND_MSG ( ! slot_table . has ( p_slot_index ) , vformat ( " Cannot set custom_port_icon_right for the slot with index '%d' because it hasn't been enabled. " , p_slot_index ) ) ;
if ( slot_table [ p_slot_index ] . custom_port_icon_right = = p_custom_icon ) {
return ;
}
slot_table [ p_slot_index ] . custom_port_icon_right = p_custom_icon ;
queue_redraw ( ) ;
port_pos_dirty = true ;
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
}
Ref < Texture2D > GraphNode : : get_slot_custom_icon_right ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
return Ref < Texture2D > ( ) ;
}
return slot_table [ p_slot_index ] . custom_port_icon_right ;
}
2023-08-09 18:31:15 +02:00
bool GraphNode : : is_slot_draw_stylebox ( int p_slot_index ) const {
if ( ! slot_table . has ( p_slot_index ) ) {
2022-04-30 03:56:57 +02:00
return false ;
}
2023-08-09 18:31:15 +02:00
return slot_table [ p_slot_index ] . draw_stylebox ;
2022-04-30 03:56:57 +02:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : set_slot_draw_stylebox ( int p_slot_index , bool p_enable ) {
ERR_FAIL_COND_MSG ( p_slot_index < 0 , vformat ( " Cannot set draw_stylebox for the slot with p_index (%d) lesser than zero. " , p_slot_index ) ) ;
2022-04-30 03:56:57 +02:00
2023-08-09 18:31:15 +02:00
slot_table [ p_slot_index ] . draw_stylebox = p_enable ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-08-09 18:31:15 +02:00
port_pos_dirty = true ;
2022-04-30 03:56:57 +02:00
2023-08-09 18:31:15 +02:00
emit_signal ( SNAME ( " slot_updated " ) , p_slot_index ) ;
2022-04-30 03:56:57 +02:00
}
2024-05-07 16:48:03 +02:00
void GraphNode : : set_ignore_invalid_connection_type ( bool p_ignore ) {
ignore_invalid_connection_type = p_ignore ;
}
bool GraphNode : : is_ignoring_valid_connection_type ( ) const {
return ignore_invalid_connection_type ;
}
2014-12-20 16:32:14 +01:00
Size2 GraphNode : : get_minimum_size ( ) const {
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_panel = theme_cache . panel ;
Ref < StyleBox > sb_titlebar = theme_cache . titlebar ;
Ref < StyleBox > sb_slot = theme_cache . slot ;
2022-04-30 03:56:57 +02:00
2023-09-12 15:01:42 +02:00
int separation = theme_cache . separation ;
2023-08-09 18:31:15 +02:00
Size2 minsize = titlebar_hbox - > get_minimum_size ( ) + sb_titlebar - > get_minimum_size ( ) ;
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
for ( int i = 0 ; i < get_child_count ( false ) ; i + + ) {
2024-05-06 12:38:51 +02:00
Control * child = as_sortable_control ( get_child ( i , false ) ) ;
if ( ! child ) {
2015-07-21 03:15:06 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
Size2i size = child - > get_combined_minimum_size ( ) ;
size . width + = sb_panel - > get_minimum_size ( ) . width ;
if ( slot_table . has ( i ) ) {
size + = slot_table [ i ] . draw_stylebox ? sb_slot - > get_minimum_size ( ) : Size2 ( ) ;
2022-04-30 03:56:57 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
minsize . height + = size . height ;
minsize . width = MAX ( minsize . width , size . width ) ;
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
if ( i > 0 ) {
minsize . height + = separation ;
2020-05-14 16:41:43 +02:00
}
2015-07-21 03:15:06 +02:00
}
2014-12-20 16:32:14 +01:00
2023-08-09 18:31:15 +02:00
minsize . height + = sb_panel - > get_minimum_size ( ) . height ;
2020-09-03 13:22:16 +02:00
2023-08-09 18:31:15 +02:00
return minsize ;
2020-09-03 13:22:16 +02:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : _port_pos_update ( ) {
2023-09-12 15:01:42 +02:00
int edgeofs = theme_cache . port_h_offset ;
int separation = theme_cache . separation ;
2020-09-03 13:22:16 +02:00
2023-09-12 15:01:42 +02:00
Ref < StyleBox > sb_panel = theme_cache . panel ;
Ref < StyleBox > sb_titlebar = theme_cache . titlebar ;
2020-09-03 13:22:16 +02:00
2022-09-09 15:29:51 +02:00
left_port_cache . clear ( ) ;
right_port_cache . clear ( ) ;
2023-08-09 18:31:15 +02:00
int vertical_ofs = titlebar_hbox - > get_size ( ) . height + sb_titlebar - > get_minimum_size ( ) . height + sb_panel - > get_margin ( SIDE_TOP ) ;
2024-04-24 10:03:38 +02:00
int slot_index = 0 ;
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
for ( int i = 0 ; i < get_child_count ( false ) ; i + + ) {
Control * child = Object : : cast_to < Control > ( get_child ( i , false ) ) ;
if ( ! child | | child - > is_set_as_top_level ( ) ) {
2015-07-21 03:15:06 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
Size2i size = child - > get_rect ( ) . size ;
2015-01-03 20:52:37 +01:00
2024-04-24 10:03:38 +02:00
if ( slot_table . has ( slot_index ) ) {
if ( slot_table [ slot_index ] . enable_left ) {
2023-08-09 18:31:15 +02:00
PortCache port_cache ;
port_cache . pos = Point2i ( edgeofs , vertical_ofs + size . height / 2 ) ;
2024-04-24 10:03:38 +02:00
port_cache . type = slot_table [ slot_index ] . type_left ;
port_cache . color = slot_table [ slot_index ] . color_left ;
port_cache . slot_index = slot_index ;
2023-08-09 18:31:15 +02:00
left_port_cache . push_back ( port_cache ) ;
2015-07-21 03:15:06 +02:00
}
2024-04-24 10:03:38 +02:00
if ( slot_table [ slot_index ] . enable_right ) {
2023-08-09 18:31:15 +02:00
PortCache port_cache ;
port_cache . pos = Point2i ( get_size ( ) . width - edgeofs , vertical_ofs + size . height / 2 ) ;
2024-04-24 10:03:38 +02:00
port_cache . type = slot_table [ slot_index ] . type_right ;
port_cache . color = slot_table [ slot_index ] . color_right ;
port_cache . slot_index = slot_index ;
2023-08-09 18:31:15 +02:00
right_port_cache . push_back ( port_cache ) ;
2015-07-21 03:15:06 +02:00
}
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
vertical_ofs + = separation ;
vertical_ofs + = size . height ;
2024-04-24 10:03:38 +02:00
slot_index + + ;
2015-07-21 03:15:06 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
port_pos_dirty = false ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_input_port_count ( ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2022-09-09 15:29:51 +02:00
return left_port_cache . size ( ) ;
2015-01-03 20:52:37 +01:00
}
2020-05-14 14:29:06 +02:00
2023-08-09 18:31:15 +02:00
int GraphNode : : get_output_port_count ( ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
return right_port_cache . size ( ) ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
Vector2 GraphNode : : get_input_port_position ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , left_port_cache . size ( ) , Vector2 ( ) ) ;
Vector2 pos = left_port_cache [ p_port_idx ] . pos ;
2016-01-19 00:32:37 +01:00
return pos ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_input_port_type ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , left_port_cache . size ( ) , 0 ) ;
return left_port_cache [ p_port_idx ] . type ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
Color GraphNode : : get_input_port_color ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2022-05-30 15:48:58 +02:00
}
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , left_port_cache . size ( ) , Color ( ) ) ;
return left_port_cache [ p_port_idx ] . color ;
2022-05-30 15:48:58 +02:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_input_port_slot ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2022-05-30 15:48:58 +02:00
}
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , left_port_cache . size ( ) , - 1 ) ;
return left_port_cache [ p_port_idx ] . slot_index ;
2022-05-30 15:48:58 +02:00
}
2023-08-09 18:31:15 +02:00
Vector2 GraphNode : : get_output_port_position ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , right_port_cache . size ( ) , Vector2 ( ) ) ;
Vector2 pos = right_port_cache [ p_port_idx ] . pos ;
2016-01-19 00:32:37 +01:00
return pos ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_output_port_type ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2022-09-09 15:29:51 +02:00
}
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , right_port_cache . size ( ) , 0 ) ;
return right_port_cache [ p_port_idx ] . type ;
2022-09-09 15:29:51 +02:00
}
2023-08-09 18:31:15 +02:00
Color GraphNode : : get_output_port_color ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , right_port_cache . size ( ) , Color ( ) ) ;
return right_port_cache [ p_port_idx ] . color ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
int GraphNode : : get_output_port_slot ( int p_port_idx ) {
if ( port_pos_dirty ) {
_port_pos_update ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-01-03 20:52:37 +01:00
2023-08-09 18:31:15 +02:00
ERR_FAIL_INDEX_V ( p_port_idx , right_port_cache . size ( ) , - 1 ) ;
return right_port_cache [ p_port_idx ] . slot_index ;
2015-01-03 20:52:37 +01:00
}
2023-08-09 18:31:15 +02:00
void GraphNode : : set_title ( const String & p_title ) {
if ( title = = p_title ) {
2022-03-16 08:50:48 +01:00
return ;
}
2023-08-09 18:31:15 +02:00
title = p_title ;
if ( title_label ) {
title_label - > set_text ( title ) ;
2022-03-16 08:50:48 +01:00
}
2023-08-09 18:31:15 +02:00
update_minimum_size ( ) ;
2022-05-04 07:31:53 +02:00
}
2023-08-09 18:31:15 +02:00
String GraphNode : : get_title ( ) const {
return title ;
2022-05-04 07:31:53 +02:00
}
2023-08-09 18:31:15 +02:00
HBoxContainer * GraphNode : : get_titlebar_hbox ( ) {
return titlebar_hbox ;
2022-05-04 07:31:53 +02:00
}
2023-05-07 16:14:57 +02:00
Control : : CursorShape GraphNode : : get_cursor_shape ( const Point2 & p_pos ) const {
if ( resizable ) {
2023-09-12 15:01:42 +02:00
if ( resizing | | ( p_pos . x > get_size ( ) . x - theme_cache . resizer - > get_width ( ) & & p_pos . y > get_size ( ) . y - theme_cache . resizer - > get_height ( ) ) ) {
2023-05-07 16:14:57 +02:00
return CURSOR_FDIAGSIZE ;
}
}
return Control : : get_cursor_shape ( p_pos ) ;
}
2021-11-08 21:53:41 +01:00
Vector < int > GraphNode : : get_allowed_size_flags_horizontal ( ) const {
Vector < int > flags ;
flags . append ( SIZE_FILL ) ;
flags . append ( SIZE_SHRINK_BEGIN ) ;
flags . append ( SIZE_SHRINK_CENTER ) ;
flags . append ( SIZE_SHRINK_END ) ;
return flags ;
}
Vector < int > GraphNode : : get_allowed_size_flags_vertical ( ) const {
Vector < int > flags ;
flags . append ( SIZE_FILL ) ;
flags . append ( SIZE_EXPAND ) ;
flags . append ( SIZE_SHRINK_BEGIN ) ;
flags . append ( SIZE_SHRINK_CENTER ) ;
flags . append ( SIZE_SHRINK_END ) ;
return flags ;
}
2014-12-20 16:32:14 +01:00
void GraphNode : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_title " , " title " ) , & GraphNode : : set_title ) ;
ClassDB : : bind_method ( D_METHOD ( " get_title " ) , & GraphNode : : get_title ) ;
2023-08-09 18:31:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_titlebar_hbox " ) , & GraphNode : : get_titlebar_hbox ) ;
2020-09-03 13:22:16 +02:00
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot " , " slot_index " , " enable_left_port " , " type_left " , " color_left " , " enable_right_port " , " type_right " , " color_right " , " custom_icon_left " , " custom_icon_right " , " draw_stylebox " ) , & GraphNode : : set_slot , DEFVAL ( Ref < Texture2D > ( ) ) , DEFVAL ( Ref < Texture2D > ( ) ) , DEFVAL ( true ) ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_slot " , " slot_index " ) , & GraphNode : : clear_slot ) ;
2017-08-09 13:54:55 +02:00
ClassDB : : bind_method ( D_METHOD ( " clear_all_slots " ) , & GraphNode : : clear_all_slots ) ;
2021-05-11 09:17:47 +02:00
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_slot_enabled_left " , " slot_index " ) , & GraphNode : : is_slot_enabled_left ) ;
2023-08-09 18:31:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_enabled_left " , " slot_index " , " enable " ) , & GraphNode : : set_slot_enabled_left ) ;
2021-05-11 09:17:47 +02:00
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_type_left " , " slot_index " , " type " ) , & GraphNode : : set_slot_type_left ) ;
ClassDB : : bind_method ( D_METHOD ( " get_slot_type_left " , " slot_index " ) , & GraphNode : : get_slot_type_left ) ;
2021-05-11 09:17:47 +02:00
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_color_left " , " slot_index " , " color " ) , & GraphNode : : set_slot_color_left ) ;
ClassDB : : bind_method ( D_METHOD ( " get_slot_color_left " , " slot_index " ) , & GraphNode : : get_slot_color_left ) ;
2021-05-11 09:17:47 +02:00
2023-10-02 07:40:21 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_custom_icon_left " , " slot_index " , " custom_icon " ) , & GraphNode : : set_slot_custom_icon_left ) ;
ClassDB : : bind_method ( D_METHOD ( " get_slot_custom_icon_left " , " slot_index " ) , & GraphNode : : get_slot_custom_icon_left ) ;
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_slot_enabled_right " , " slot_index " ) , & GraphNode : : is_slot_enabled_right ) ;
2023-08-09 18:31:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_enabled_right " , " slot_index " , " enable " ) , & GraphNode : : set_slot_enabled_right ) ;
2021-05-11 09:17:47 +02:00
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_type_right " , " slot_index " , " type " ) , & GraphNode : : set_slot_type_right ) ;
ClassDB : : bind_method ( D_METHOD ( " get_slot_type_right " , " slot_index " ) , & GraphNode : : get_slot_type_right ) ;
2021-05-11 09:17:47 +02:00
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_color_right " , " slot_index " , " color " ) , & GraphNode : : set_slot_color_right ) ;
ClassDB : : bind_method ( D_METHOD ( " get_slot_color_right " , " slot_index " ) , & GraphNode : : get_slot_color_right ) ;
2017-02-13 12:47:24 +01:00
2023-10-02 07:40:21 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_slot_custom_icon_right " , " slot_index " , " custom_icon " ) , & GraphNode : : set_slot_custom_icon_right ) ;
ClassDB : : bind_method ( D_METHOD ( " get_slot_custom_icon_right " , " slot_index " ) , & GraphNode : : get_slot_custom_icon_right ) ;
2022-09-09 15:29:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_slot_draw_stylebox " , " slot_index " ) , & GraphNode : : is_slot_draw_stylebox ) ;
ClassDB : : bind_method ( D_METHOD ( " set_slot_draw_stylebox " , " slot_index " , " enable " ) , & GraphNode : : set_slot_draw_stylebox ) ;
2022-04-30 03:56:57 +02:00
2024-05-07 16:48:03 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_ignore_invalid_connection_type " , " ignore " ) , & GraphNode : : set_ignore_invalid_connection_type ) ;
ClassDB : : bind_method ( D_METHOD ( " is_ignoring_valid_connection_type " ) , & GraphNode : : is_ignoring_valid_connection_type ) ;
2023-08-09 18:31:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_input_port_count " ) , & GraphNode : : get_input_port_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_input_port_position " , " port_idx " ) , & GraphNode : : get_input_port_position ) ;
ClassDB : : bind_method ( D_METHOD ( " get_input_port_type " , " port_idx " ) , & GraphNode : : get_input_port_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_input_port_color " , " port_idx " ) , & GraphNode : : get_input_port_color ) ;
ClassDB : : bind_method ( D_METHOD ( " get_input_port_slot " , " port_idx " ) , & GraphNode : : get_input_port_slot ) ;
2022-05-04 07:31:53 +02:00
2023-08-09 18:31:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_output_port_count " ) , & GraphNode : : get_output_port_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_output_port_position " , " port_idx " ) , & GraphNode : : get_output_port_position ) ;
ClassDB : : bind_method ( D_METHOD ( " get_output_port_type " , " port_idx " ) , & GraphNode : : get_output_port_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_output_port_color " , " port_idx " ) , & GraphNode : : get_output_port_color ) ;
ClassDB : : bind_method ( D_METHOD ( " get_output_port_slot " , " port_idx " ) , & GraphNode : : get_output_port_slot ) ;
2022-05-04 07:31:53 +02:00
2023-08-09 18:31:15 +02:00
GDVIRTUAL_BIND ( _draw_port , " slot_index " , " position " , " left " , " color " )
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " title " ) , " set_title " , " get_title " ) ;
2024-05-07 16:48:03 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " ignore_invalid_connection_type " ) , " set_ignore_invalid_connection_type " , " is_ignoring_valid_connection_type " ) ;
2023-08-09 18:31:15 +02:00
ADD_SIGNAL ( MethodInfo ( " slot_updated " , PropertyInfo ( Variant : : INT , " slot_index " ) ) ) ;
2023-09-12 15:01:42 +02:00
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , GraphNode , panel ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , GraphNode , panel_selected ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , GraphNode , titlebar ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , GraphNode , titlebar_selected ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , GraphNode , slot ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , GraphNode , separation ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , GraphNode , port_h_offset ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_ICON , GraphNode , port ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_ICON , GraphNode , resizer ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , GraphNode , resizer_color ) ;
2014-12-20 16:32:14 +01:00
}
2014-12-21 15:42:44 +01:00
GraphNode : : GraphNode ( ) {
2023-08-09 18:31:15 +02:00
titlebar_hbox = memnew ( HBoxContainer ) ;
titlebar_hbox - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
add_child ( titlebar_hbox , false , INTERNAL_MODE_FRONT ) ;
title_label = memnew ( Label ) ;
title_label - > set_theme_type_variation ( " GraphNodeTitleLabel " ) ;
title_label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
titlebar_hbox - > add_child ( title_label ) ;
2017-08-08 15:57:33 +02:00
set_mouse_filter ( MOUSE_FILTER_STOP ) ;
2014-12-20 16:32:14 +01:00
}