cirnogodot/addons/scene_palette/components/scene_thumbnail/scene_drop.gd
2025-02-24 11:57:09 +01:00

116 lines
3.2 KiB
GDScript

@tool
extends Control
const pp = 'ScenePalettePlugin: ' # prepended to printed messages
const MOUSE_HOVER_SCALE_ADJUST = 0.05
@onready var picture_point = %PicturePoint
@onready var name_label = %NameLabel
@onready var texture_rect: TextureRect = %TextureRect
var _scene_path:String
var instantiate_scene_preview:
set(value):
instantiate_scene_preview = value
# refresh the preview
if _scene_path:
set_scene(_scene_path)
func adjust_scale(amt:float):
picture_point.scale = Vector2(amt, amt)
func show_file_label(show:bool):
# setting text here instead of in set_scene seems to work better
name_label.text = _create_display_label(_scene_path)
name_label.visible = show
func _create_display_label(path:String) -> String:
var display_label = path.split('.tscn')[0].split('/')[-1]
display_label = display_label.replace('_', ' ').replace('-', ' ')
return display_label
func set_scene(path:String):
tooltip_text = path
_scene_path = path
var file_extension = path.split('.')[-1]
for node in picture_point.get_children():
node.queue_free()
match file_extension:
'png':
texture_rect.texture = load(_scene_path)
'tscn':
if instantiate_scene_preview:
var node:Node = load(_scene_path).instantiate()
if _scene_is_safe(node):
picture_point.add_child(node)
return
# if scene is not safe to instantiate, just keep a preview
_make_preview()
'obj':
_make_preview()
func _make_preview():
var resource_previewer = EditorInterface.get_resource_previewer()
resource_previewer.queue_resource_preview(_scene_path, self, '_on_resource_preview', null)
func _on_resource_preview(path:String, preview:Texture2D, thumbnail_preview:Texture2D, _user_data):
var texture_rect = TextureRect.new()
add_child(texture_rect)
texture_rect.texture = preview
hide()
show()
## determine if scene is safe to instantiate as a preview
func _scene_is_safe(scene:Node) -> bool:
# if scene is a Node then it can't be positioned within the panel and
# clip_contents does not work.
if not scene is Node2D:
print("%Not instantiating preview for %s because it is not a Node2D" %
[pp, scene.scene_file_path]
)
return false
# if scene contains a camera, the entire editor is repositioned
if _scene_contains_camera(scene):
print("%Not instantiating preview for %s because it contains a camera." %
[pp, scene.scene_file_path]
)
return false
return true
func _scene_contains_camera(scene:Node) -> bool:
if scene is Camera2D:
return true
for node in scene.get_children():
var result:bool = _scene_contains_camera(node)
if result:
return result
return false
## Mimics the data that would be provided if a file were dragged from the
## FileSystem browser
func _make_file_data() -> Dictionary:
return {
'type': 'files',
'files': [_scene_path],
'from': ''
}
func _make_drag_preview() -> Control:
var control:Control = Control.new()
if instantiate_scene_preview:
var scene = load(_scene_path).instantiate()
control.add_child(scene)
# TODO add an alternate image here
return control
func _get_drag_data(at_position):
set_drag_preview(_make_drag_preview())
return _make_file_data()
func _on_mouse_entered():
scale = Vector2.ONE + Vector2(MOUSE_HOVER_SCALE_ADJUST, MOUSE_HOVER_SCALE_ADJUST)
func _on_mouse_exited():
scale = Vector2.ONE