- Edited
Hello. I have a good programming background but almost no experience in Godot. I would like to learn how to create a new Node type that is a composition of existing node types and exposes its fields through the editor. For that end, I will give my current use case for this:
I am trying to program a pixel art game with a few screens in which I would like something like an inventory grid of arbitrary size for an inventory of arbitrary size. Because it is a pixel art game I don't want to add scroll bars; I would like to be an arrow on the top and bottom or the left and right which switches through the items on click. Because I have this component on multiple screens with different types of content (say on one screen one is scrolling through a 6x4 grid of inventory items, on the next it is a 8x2 grid of characters to select), my need for abstraction and aversion to code repetition commands me to not implement this separately for every screen, but instead create a Node that has the needed capabilities. Basically, I want some type of Container Node that takes Textures for the arrows and background, whether it has horizontal or vertical orientation, maybe margin sizes around the arrows as well as whatever is supposed to be shown in the inventory and determines how it is supposed to be displayed by itself by its own rules similar to how GridContainer or VBoxContainer do. I of course also want this to be visualized in Godot when it is edited.
In other languages this would mean a new class that implements the Container or BoxContainer interface, calls methods for resizing and re-rendering, and has setters for all important parameters which call those methods when needed. Its components would be added by composition. In the vertical case it might contain a VBoxContainer containing the arrows and a GridContainer, for example.
How do I go about this in Godot with GDScript? I could not find a good tutorial for this type of challenge.
Here are some things I've already tried for reference. Maybe that makes it easier to point out mistakes in my approach:
My new class: extends Container
class_name ArrowGridContainer
I have already exposed some needed parameters like this: enum ORIENTATION {HORIZONTAL, VERTICAL}
export(ORIENTATION) var orientation = ORIENTATION.VERTICAL \
setget set_orientation
export(Texture) var arrow_texture_previous setget set_arrow_texture_previous
export(Texture) var arrow_texture_next setget set_arrow_texture_next
Some things I think I need later: var contents: GridContainer = GridContainer.new() var arrow_previous: TextureButton = TextureButton.new() var _arrow_next: TextureButton = TextureButton.new()
My signal to self to recompute everything ... I can worry about optimizing this later. I want to get to a working prototype as fast as possible: func ready(): connect("sort_children", self, "on_ArrowGridContainer_sort_children") emit_signal("sort_children")
I have a bunch of methods that emit that signal when something is changed that might affect display. Maybe 20 of those: func set_orientation(new_orientation): self.orientation = new_orientation emit_signal("sort_children")
func set_arrow_texture_previous(texture: Texture):
self.arrow_texture_previous = texture
emit_signal("sort_children")
My update method is a monster, of course, and unfinished to say the least. It starts by computing a lot of the sizes and then sets them on the children: func _on_ArrowGridContainer_sort_children():
Set arrow textures
arrow_previous.texture_normal = arrow_texture_previous arrow_next.texture_normal = arrow_texture_next
Get sizes in scroll direction
var scroll_direction_total = get_scroll_direction_size(self) var scroll_direction_arrow_previous_size = get_scroll_direction_size(arrow_previous) var scroll_direction_arrow_next_size = get_scroll_direction_size(arrow_next) var scroll_direction_content_size = get_scroll_direction_content_size( scroll_direction_total, scroll_direction_arrow_previous_size, scroll_direction_arrow_next_size )
What I don't like about my approach so far: - I feel like I'm re-implementing what should already be available by subclassing from something else. - Some fields I want to expose in the editor are already exposed for components of my Node. I would like to just tell Godot to expose these fields of the subcomponents instead of creating them anew on the parent and then manually setting them on subcomponents through code. - I don't know how to make this construction update in the editor once finished. - I don't know whether this will work at all.
Sorry I cannot get some of the code sections to format as code.
Help, no matter in what form, would be appreciated.
Thanks in advance, DarkNetFan