tool extends MarginContainer export(bool) var is_movable = true export(bool) var is_resizable = true export(bool) var is_borderless = false export(String) var title = "Window" export(Color) var background_color = Color( 1.0, 1.0, 1.0, 1.0 ) export(String) var background_texture = "res://assets/GUI/images/background_test.png" signal window_clicked( window ) onready var header_box = $parts/header_box onready var content_box = $parts/content_box onready var footer_box = $parts/footer_box var current_rect_size = Vector2( 0, 0 ) var current_rect_position = Vector2( -1, -1 ) var is_resizing = false var is_moving = false func add_child( node): if self.get_content(): self.get_content().add_child(node) # else: # .add_child( node ) # prints(self.get_name()+" just fathered", node.get_name()) func add_window_part( node ): .add_child( node ) func set_mouse_pass_to_children( node ): for child in node.get_children(): set_mouse_pass_to_children( child ) if node is Control: node.mouse_filter = MOUSE_FILTER_PASS #func _ready(): func _enter_tree(): ######## #### Window's part création. # The interal elements structure is: # self - MarginContainer # background - NinePatchRect # parts - VBoxContainer # header_box - MarginContainer # header - HBoxContainer # quit - TextureButton # close - TextureButton # open - TextureButton # label - Label # content_box - MarginContainer # scroll_container - Scrollcontainer # content - VBoxContainer # footer_box - MarginContainer # footer - HBoxContainer # contextual_help - Label # resize - TextureButton ### # self self.size_flags_horizontal = SIZE_EXPAND self.size_flags_vertical = SIZE_EXPAND self.set( "custom_constants/margin_right", 0) self.set( "custom_constants/margin_top", 0) self.set( "custom_constants/margin_left", 0) self.set( "custom_constants/margin_bottom", 0) self.connect ( "gui_input", self, "_on_window_gui_input" ) ### ### # background var background if not self.has_node( "background" ): background = NinePatchRect.new() background.name = "background" var background_image = Image.new() if not background_image.load( background_texture ): print("Erreur lors du chargement de l'image: "+background_texture ) background.texture = ImageTexture.new() background.texture.create_from_image( background_image ) background.texture.flags = Texture.FLAG_FILTER | Texture.FLAG_REPEAT background.axis_stretch_horizontal = NinePatchRect.AXIS_STRETCH_MODE_TILE background.axis_stretch_vertical = NinePatchRect.AXIS_STRETCH_MODE_TILE background.size_flags_horizontal = SIZE_EXPAND_FILL background.size_flags_vertical = SIZE_EXPAND_FILL background.region_rect = Rect2( 0, 0, 0, 0 ) background.patch_margin_left = 4 background.patch_margin_top = 32 background.patch_margin_right = 4 background.patch_margin_bottom = 4 background.self_modulate = background_color self.add_window_part( background ) background.set_owner( self ) ### ### # parts var parts if not self.has_node( "parts" ): parts = VBoxContainer.new() parts.name = "parts" parts.size_flags_horizontal = SIZE_EXPAND_FILL parts.size_flags_vertical = SIZE_EXPAND_FILL self.add_window_part( parts ) parts.set_owner( self ) ### ### # header_box var header_box if not parts.has_node( "header_box" ): header_box = MarginContainer.new() header_box.name = "header_box" header_box.size_flags_horizontal = SIZE_EXPAND_FILL header_box.size_flags_vertical = SIZE_SHRINK_CENTER header_box.set( "custom_constants/margin_right", 0) header_box.set( "custom_constants/margin_top", 4) header_box.set( "custom_constants/margin_left", 4) header_box.set( "custom_constants/margin_bottom", 4) if is_movable: header_box.mouse_default_cursor_shape = CURSOR_MOVE parts.add_child( header_box ) header_box.set_owner( parts ) header_box.connect ( "gui_input", self, "_on_Header_gui_input" ) ### ### # header var header if not header_box.has_node( "header" ): header = HBoxContainer.new() header.name = "header" header.size_flags_horizontal = SIZE_EXPAND_FILL header.size_flags_vertical = SIZE_EXPAND | SIZE_SHRINK_CENTER if is_movable: header.mouse_default_cursor_shape = CURSOR_MOVE header_box.add_child( header ) header.set_owner( header ) ### ### # quit var quit_button if not header.has_node( "quit" ): quit_button = TextureButton.new() quit_button.name = "quit" quit_button.size_flags_horizontal = SIZE_SHRINK_END quit_button.size_flags_vertical = SIZE_SHRINK_CENTER var tex_quit = ImageTexture.new() var img_quit = Image.new() img_quit.load( "res://assets/GUI/images/button_quit.png" ) tex_quit.create_from_image( img_quit ) quit_button.texture_normal = tex_quit header.add_child( quit_button ) quit_button.set_owner( header ) quit_button.connect ( "pressed", self, "_on_Quit_pressed" ) ### # close var close_button = TextureButton.new() if not header.has_node( "close" ): close_button = TextureButton.new() close_button.name = "close" close_button.size_flags_horizontal = SIZE_SHRINK_END close_button.size_flags_vertical = SIZE_SHRINK_CENTER var tex_close = ImageTexture.new() var img_close = Image.new() img_close.load( "res://assets/GUI/images/button_close.png" ) tex_close.create_from_image( img_close ) close_button.texture_normal = tex_close header.add_child( close_button ) close_button.set_owner( header ) close_button.connect ( "pressed", self, "_on_Close_pressed" ) ### # open var open_button if not header.has_node( "open" ): open_button = TextureButton.new() open_button.name = "open" open_button.size_flags_horizontal = SIZE_SHRINK_END open_button.size_flags_vertical = SIZE_SHRINK_CENTER var tex_open = ImageTexture.new() var img_open = Image.new() img_open.load( "res://assets/GUI/images/button_open.png" ) tex_open.create_from_image( img_open ) open_button.texture_normal = tex_open open_button.visible = false header.add_child( open_button ) open_button.set_owner( header ) open_button.connect ( "pressed", self, "_on_Open_pressed" ) ### ### # Title Label var title_label if not header.has_node( "label" ): title_label = Label.new() title_label.name = "label" title_label.text = title title_label.size_flags_horizontal = SIZE_EXPAND_FILL title_label.size_flags_vertical = SIZE_SHRINK_CENTER if is_movable: title_label.mouse_default_cursor_shape = CURSOR_MOVE header.add_child( title_label ) title_label.set_owner( header ) ### ### # Content var content_box if not parts.has_node( "content_box" ): content_box = MarginContainer.new() content_box.name = "content_box" content_box.size_flags_horizontal = SIZE_EXPAND_FILL content_box.size_flags_vertical = SIZE_EXPAND_FILL content_box.set( "custom_constants/margin_right", 8) content_box.set( "custom_constants/margin_top", 8) content_box.set( "custom_constants/margin_left", 8) content_box.set( "custom_constants/margin_bottom", 8) parts.add_child( content_box ) content_box.set_owner( parts ) ### ### # content_box/scroll_container var content_scroll_container if not content_box.has_node( "scroll_container" ): content_scroll_container = ScrollContainer.new() content_scroll_container.name = "scroll_container" content_scroll_container.size_flags_horizontal = SIZE_FILL content_scroll_container.size_flags_vertical = SIZE_FILL content_scroll_container.scroll_deadzone = 0 content_box.add_child( content_scroll_container ) content_scroll_container.set_owner( content_box ) ### ### # content var content if not content_scroll_container.has_node( "content" ): content = VBoxContainer.new() content.name = "content" content.size_flags_horizontal = SIZE_EXPAND_FILL content.size_flags_vertical = SIZE_EXPAND_FILL content_scroll_container.add_child( content ) content.set_owner( content_scroll_container ) ### ### # Footer var footer_box if not parts.has_node( "footer_box" ): footer_box = MarginContainer.new() footer_box.name = "footer_box" footer_box.size_flags_horizontal = SIZE_FILL footer_box.size_flags_vertical = SIZE_FILL footer_box.set( "custom_constants/margin_right", 6) footer_box.set( "custom_constants/margin_top", 2) footer_box.set( "custom_constants/margin_left", 6) footer_box.set( "custom_constants/margin_bottom", 6) parts.add_child( footer_box ) footer_box.set_owner( parts ) ### ### # footer_box/footer var footer if not footer_box.has_node( "footer" ): footer = HBoxContainer.new() footer.name = "footer" footer.size_flags_horizontal = SIZE_EXPAND_FILL footer.size_flags_vertical = SIZE_EXPAND_FILL footer_box.add_child( footer ) footer.set_owner( footer_box ) ### ### # footer_label var footer_label if not footer.has_node( "footer_label" ): footer_label = Label.new() footer_label.name = "footer_label" footer_label.size_flags_horizontal = SIZE_EXPAND footer_label.size_flags_vertical = SIZE_EXPAND footer.add_child( footer_label ) ### # resize var resize_button if not footer.has_node( "resize" ): resize_button = TextureButton.new() resize_button.name = "resize" resize_button.size_flags_horizontal = SIZE_FILL | SIZE_SHRINK_END resize_button.size_flags_vertical = SIZE_SHRINK_END var tex_resize = ImageTexture.new() var img_resize = Image.new() img_resize.load( "res://assets/GUI/images/button_resize.png" ) tex_resize.create_from_image( img_resize ) resize_button.texture_normal = tex_resize resize_button.mouse_default_cursor_shape = CURSOR_FDIAGSIZE resize_button.action_mode = Button.ACTION_MODE_BUTTON_PRESS footer.add_child( resize_button ) resize_button.set_owner( footer ) resize_button.connect ( "pressed", self, "_on_Resize_pressed" ) ###er_label.set_owner( footer ) ### current_rect_size = self.rect_min_size if is_borderless: $background.region_rect = Rect2( $background.patch_margin_left-1 , $background.patch_margin_top-1 , 256-($background.patch_margin_left+$background.patch_margin_right)+2 , 256-($background.patch_margin_top+$background.patch_margin_bottom)+2 ) $background.patch_margin_left = 1 $background.patch_margin_top = 1 $background.patch_margin_right = 1 $background.patch_margin_bottom = 1 close_button.visible = false open_button.visible = false quit_button.visible = false title_label.visible = false if not is_resizable: $v_box_container/Footer/HBoxContainer/Resize.visible = false func _ready(): # On déplace les enfants ajouter via l'editeur sous content. for child in self.get_children(): if not child.name =="parts" and not child.name =="background": if child.name.begins_with( "footer_" ): if footer_box.get_node("footer").has_node("footer_label"): footer_box.get_node("footer").remove_child( footer_box.get_node("footer").get_node("footer_label") ) self.remove_child( child ) get_footer().add_child( child ) get_footer().move_child( child, 0 ) else: self.remove_child( child ) get_content().add_child( child ) set_mouse_pass_to_children( self ) func _on_Window_mouse_entered(): print("mouse_entered") func _on_Window_focus_entered(): print("focus_entered") func _on_Quit_pressed(): self.visible = false func get_content(): return content_box.get_node( "scroll_container/content" ) func get_footer(): return footer_box.get_node( "footer" ) func close(): if not is_borderless: header_box.get_node( "header/close" ).visible = false header_box.get_node( "header/open" ).visible = true content_box.visible = false footer_box.visible = false current_rect_size = self.rect_size self.rect_size = Vector2( 0, 0 ) else: header_box.get_node( "header/close" ).visible = false header_box.get_node( "header/open" ).visible = false content_box.visible = false footer_box.visible = false current_rect_size = self.rect_size self.rect_size = Vector2( 0, 0 ) func _on_Close_pressed(): close() func open(): if not is_borderless: header_box.get_node( "header/close" ).visible = true header_box.get_node( "header/open" ).visible = false content_box.visible = true footer_box.visible = true self.rect_size = current_rect_size else: header_box.get_node( "header/close" ).visible = false header_box.get_node( "header/open" ).visible = false content_box.visible = true footer_box.visible = true self.rect_size = current_rect_size func _on_Open_pressed(): open() func _on_Resize_pressed(): is_resizing = true func _input( event ): if is_resizable: if is_resizing and event is InputEventMouseButton and not event.pressed: is_resizing = false if event is InputEventMouseMotion and is_resizing: var delta = event.relative self.rect_size += delta func check_if_clicked( event ): if not is_moving and event is InputEventMouseButton and event.is_pressed() and not event.is_echo() and event.button_index == 1 : emit_signal( "window_clicked", self ) func _on_Header_gui_input( event ): check_if_clicked( event ) if is_movable: if is_moving and event is InputEventMouseButton and not event.pressed: is_moving = false elif not is_moving and event is InputEventMouseButton and event.pressed: is_moving = true if event is InputEventMouseMotion and is_moving: var delta = event.relative self.rect_position += delta func _on_window_gui_input( event ): check_if_clicked( event ) func load_from_file( config_file ): if config_file.has_section( self.name ): self.rect_position = config_file.get_value( self.name, "position" ) self.rect_size = config_file.get_value( self.name, "size" ) self.is_borderless = config_file.get_value( self.name, "borderless" ) current_rect_position = self.rect_position current_rect_size = self.rect_size if config_file.get_value( self.name, "opened" ): open() else: close() func save_to_file( config_file ): var is_open = content_box.visible config_file.set_value(self.name, "position", self.rect_position) if not is_open: config_file.set_value(self.name, "size", current_rect_size) else: config_file.set_value(self.name, "size", self.rect_size) if is_open: config_file.set_value(self.name, "opened", true) else: config_file.set_value(self.name, "opened", false) config_file.set_value(self.name, "borderless", is_borderless)