Hello! I have an inventory and a hotbar. I have a working script to drag things between the two and add objects to the main inventory from the world. For some reason though the preview for the item being dragged doesn't follow the mouse properly. I followed a tutorial initally to learn how to make things draggable, so I went back and recreated that project exactly and it works perfectly. The preview follows the mouse normally. I can't see what went wrong with the version in my game. The tutorial has a TextureRect as the base and mine is a panel container, but I've checked and rechecked and it should still be fine. Here's a video of what's happening. https://1drv.ms/u/s!AhFDhdExpRP1hOxijqXB8DfItEsY0w?e=vpQ6T8
#preview texture behaving strangely
40 messages · Page 1 of 1 (latest)
This is my script
||extends PanelContainer
class_name Slot
@onready var texture_rect = $TextureRect
var filled : bool = false
func _get_drag_data(at_position):
set_drag_preview(get_preview())
return texture_rect
func _can_drop_data(at_position, data):
return data is TextureRect
func _drop_data(at_position, data):
var temp = texture_rect.property
texture_rect.property = data.property
data.property = temp
func get_preview():
var preview_texture = TextureRect.new()
preview_texture.texture = texture_rect.texture
var preview = Control.new()
preview.add_child(preview_texture)
return preview
func set_property(data):
texture_rect.property = data
if data["TEXTURE"] == null:
filled = false
else:
filled = true||
This is the script that works properly, though it's not connected to the inventory.
||extends TextureRect
@export var slot_type: int = 0
@onready var property: Dictionary = {"TEXTURE": texture,
"SLOT_TYPE": slot_type}:
set(value):
property = value
texture = property["TEXTURE"]
slot_type = property["SLOT_TYPE"]
func _get_drag_data(at_position):
var preview_texture = TextureRect.new()
preview_texture.texture = texture
preview_texture.expand_mode = 1
preview_texture.size = Vector2(30,30)
var preview = Control.new()
preview.add_child(preview_texture)
set_drag_preview(preview)
texture = null
return preview_texture.texture
func _can_drop_data(at_position, data):
return data is Texture2D
func _drop_data(at_position, data):
texture = data||
May I see the set_drag_preview() function?
I would like to know what node preview becomes child of.
And if you set its position at any point.
Probably has something to do with local vs global position, or children inheriting the position of their parent
@turbid dune
@echo kite This is what I have to determine what the preview is
`func get_preview():
var preview_texture = TextureRect.new()
preview_texture.texture = texture_rect.texture
var preview = Control.new()
preview.add_child(preview_texture)
return preview`
preview_texture is added as child of preview, but what is preview added as child of?
This is done in the set_drag_preview() function, I assume. Which is not shown.
Ah. That's the entirety of the script. So perhaps that's what's happening. When the game is running the new Control node is a child of the Inventory Control node.
This is the only part with the set_drag_preview
func _get_drag_data(at_position): set_drag_preview(get_preview()) return texture_rect
func _get_drag_data(at_position):
set_drag_preview(get_preview())
return texture_rect
You can see set_drag_preview() is being called here. But that function is not shown which is confusing.
To lock the texture to the mouse, are you:
- Changing its position
- Adding it as child of a certain node and then changing the position of that node to follow the mouse
- Both?
When the game is running the new Control node is a child of the Inventory Control node.
What causes it to become child of the Inventory Control node? It must happen in code somewhere.
Sorry. I'm trying to see where it's happening.
And yeah, I don't see the set_drag_preview function anywhere. How do I have no memory of doing this 🤦♀️
I realized set_drag_preview() is a built-in function of PanelContainer - sorry for the confusion
ohhh okay
But still, that new Control node named preview must be being added as child of something, somewhere
And that's where the problem lies I think
Mm I see
Okay, slight update. The preview only works right with the hot bar. If I try to drag something from the regular inventory is does the weird position thing. With both the original slot and the one I redid.
So, it's got to be something with the Inventory set up right? Both it and the hot bar have instances of the same slot scene
The hot bar Control nodes are appearing as children on the Hotbar Control node
Reading into set_drag_preview() a bit more, it does some neat stuff I'm not familiar with. Doesn't add anything to the current scene's tree... the new node is on some upper level. (Child of Viewport?)
I'm not sure why set_drag_preview() would be giving you results like this, assuming it works with global_position...
Maybe it works with local position? Meaning you'd have to call it on a control node that is at global position (0, 0)...
I think it is though
Not sure then
Thanks for bearing with me anyway
You could try a different method if you'd like (not using set_drag_preview())
The idea is to make an invisible Node2D/Control that's child of main node, which follows the mouse at all times.
And you add the TextureRect as child of that node during the drag.
Otherwise you can upload your project and I'll mess around with it to see if I can get set_drag_preview() working
Okay, I think I follow that, and honestly thank you for bearing with me. I might start with just redoing the whole Inventory bit. Sometimes I get so tangled up in a problem I can't find the end of the string again y'know?
Oh, I could do that
I'll have some more time in 30-60 mins or so - good luck in the meantime!
Thank you so much! It's a bit of mess I think, so sorry 😅
Okay so if I move Inventory into the CanvasLayer...
then in Player.gd change
@onready var inv_display = $Inventory
to
@onready var inv_display = $UI/Inventory
and then reposition the Inventory in the center of the blue square ... it works
If you want to use set_drag_preview() you will need to make your Inventory part of a CanvasLayer.
Because if the inventory is a child of the Player:
- The camera is zoomed in on the player which screws up the coordinates used in
set_drag_preview() - Its position will change with the Player's position , which can also mess with the coordinates
You can scale it up here and it still appears to work (although the drag preview is small)
@turbid dune
Thank you! That does make sense
np good luck
I see you've dove in and explored a lot of the engine's features, good work so far, it's not as messy as you might think!