Kehom / GodotAddonPack

A collection of pure GDScript addons for Godot
http://kehomsforge.com
MIT License
183 stars 15 forks source link

[UI - Inventory] Infinite Scrolling or (grow as needed) Inventory Bag #28

Closed hydexon closed 3 years ago

hydexon commented 3 years ago

Hi, i just recently discovered your addon pack while looking for an grid-based inventory system. and it matches all i need!, thanks you very much!.

So, for trying to implement an sort of S.T.A.L.K.E.R-like inventory system where the grid is infinite as long the weight capacity limit is not reached, i cannot find an way to grow the grid as needed (like grow the grid after 90% of the grid was used in items), tried using scrolling bars and some hackery but with no luck. do you have an better idea or code how could be achieved?

As well would be nice of selecting the item by dragging them until drop to an special slot and not just clicking it once and then clicking it again to putting in an special slot.

Thanks.

Kehom commented 3 years ago

So, for trying to implement an sort of S.T.A.L.K.E.R-like inventory system where the grid is infinite as long the weight capacity limit is not reached, i cannot find an way to grow the grid as needed (like grow the grid after 90% of the grid was used in items), tried using scrolling bars and some hackery but with no luck. do you have an better idea or code how could be achieved?

I assume you are already using the add_row() and remove_row() functions in order to grow/shrink the inventory bag. When growing this will obviously expand the widget and the desired here is to keep it confined in a predetermined space. For that you need to use Godot's ScrollContainer, which will determine this space for the bag. However it also requires another container within it. So you can simply add one VBoxContainer into it then set the SizeFlags property to Expand on both Vertical and Horizontal directions. After that you can add the inventory bag into the vertical box. In here, instead of the VBoxContainer you can also use CenterContainer, MarginContainer or PanelContainer. Each one will require some property tweaks. I mentioned the vertical box because it's the one I use the most for this case and I have already tested the settings.

As well would be nice of selecting the item by dragging them until drop to an special slot and not just clicking it once and then clicking it again to putting in an special slot.

I have tried to do that but I remember I had issues related to how the events are handled. If I recall correctly, I wasn't able to properly detect the mouse release once the item was grabbed. I'm probably overthinking something in here but I will definitely take a look into it again at some point in time because I understand it's more intuitive.

Best regards

hydexon commented 3 years ago

Thanks you for the information, shame about the last point. About the first point, still have some difficulties of how is the best strategy to make it grow or shrink the bag to fit the ScrollContainer without any scrolling yet until the player fit it with items or remove items until certain threshold to make it grow or shrink according some big factor:

I did some experiments and probably should look more at the InventoryBag code, but just heads up, again. Thanks you very much.

Kehom commented 3 years ago

Well, because you have full control over the item sizes (how many slots those occupy) and the inventory bag size (columns * rows), you can:

  1. Listen to the "item_added" event and when it happen you keep an internal total counter of how many slots of the bag are being used.
  2. Take the total used amount and compare to the current size of the bag. If it reached the threshold, expand the bag.
  3. Listen to the "item_removed" event and when it happen update the total bag usage counter.
  4. Compare the new total usage counter and if has gone bellow the threshold, shrink the bag.

Remember something here. If you cache the total size of the bag you have to update the stored value when you expand or shrink the bag. Since the verification is done only when a new item is added or one is removed, I don't think it's necessary to cache the total size, specially because it is calculate through a simple multiplication.

Another thing, the threshold to actually shrink the bag is slightly different. You have to check if the slot usage is still bellow the threshold even when the bag is shrinked. So, in this case you would have to calculate the total bag size by columns * (rows - 1).

hydexon commented 3 years ago

Thanks i got it clearer and working fully now!, yet some single row o col off due the inexact size of my parent container, but not an terrible thing to worry about, albeit the special slot is not something easy to resize unfortunately, i thought i could resize those special slots cell sizes as child nodes from my parent container script onResize event in godot but it fails somehow.

BTW this is the code i use for fill the empty inventory grid upon start and resize if someone is looking for something similar in the future:

extends ScrollContainer

onready var invBag = $InventoryBag
onready var scrlCont = self
# Called when the node enters the scene tree for the first time.
func _ready():
    # Calculate rows
    propagate_notification(NOTIFICATION_VISIBILITY_CHANGED) # We should remove it?
    var newRows = int(floor(scrlCont.rect_size.y / invBag.cell_width))
    var newCols = int(floor(scrlCont.rect_size.x / invBag.cell_height))
    invBag.row_count = (newRows)
    invBag.column_count = (newCols)

func resizedBag(): # Call this on your parent's resize signal.
    var newRows = int(floor(scrlCont.rect_size.y / invBag.cell_width)) - invBag.row_count
    var newCols = int(floor(scrlCont.rect_size.x / invBag.cell_height)) - invBag.column_count
    invBag.add_rows(newRows)
    invBag.add_columns(newCols)
Kehom commented 3 years ago

The special slots are not designed to be visually resized at runtime. They are meant precisely for special usage like those representing the equipped items or special storage within a stash or something like that.

Why exactly do you want to resize the special slot? Perhaps this is a use case I didn't think about!

hydexon commented 3 years ago

Okay, i probably i wrote that in an rush in a way is not understandable, i'm sorry if it caused any inconvenience, i think this is an separate issue related directly more with Godot UI system than this addon. When i played S.T.A.L.K.E.R again and noticed the inventory UI in different display resolutions doesn't change any time; occupies the same screen space and the grid remains the same, from in my case, it grows or shrinks if the user changes the display resolution of my game or resizes the window manually.

Kehom commented 3 years ago

Ahhh, you want to deal with UI scaling then. Well, I believe https://docs.godotengine.org/en/stable/tutorials/viewports/multiple_resolutions.html can be of help. I'm not entirely sure if any of my widgets will be affected by those settings. If those don't do anything to my widgets please open another issue here so it reminds me to take a look into it.