otherworldly_simulation/tool/drawer_container/drawer_container.gd

247 lines
6.7 KiB
GDScript3
Raw Permalink Normal View History

2024-10-25 15:41:39 +08:00
@tool
extends Container
##抽屉容器节点可以用于将子节点侧滑开启clip content可以做到完全隐藏子节点
class_name DrawerContainer
##按钮大小
@export var custom_button_size:Vector2=Vector2.ZERO:
set(val):
custom_button_size=val
side_button_size_changed()
fit_children()
fit_side_button()
var button_size:Vector2=Vector2(100,200):
set(val):
button_size=val
fit_children()
fit_side_button()
##按钮场景根节点必须为basebutton或继承自basebutton留空则使用默认按钮
@export var button_tscn:PackedScene
##布局模式
@export var button_model:BUTTON_MODEL=BUTTON_MODEL.TOP
enum BUTTON_MODEL{
##按钮在上方,向下收纳
TOP=0,
##按钮在下方,向上收纳
END=1,
##按钮在左方,向右收纳
LEFT=2,
##按钮在右方,向左收纳
RIGHT=3,
}
##动画时间
@export var animation_time:float=0.5
##是否自动隐藏
@export var is_auto_hide:bool=false
#隐藏计时器
@onready var hide_timer:Timer=Timer.new()
##是否自动收缩
@export var is_auto_shrink:bool=false
##是否禁用按钮
@export var disable_button:bool=false:
set(val):
disable_button=val
fit_side_button()
fit_side_button()
if side_button!=null:
if val :
side_button.hide()
else:
side_button.show()
##动画过渡模式
@export var animation_model:Tween.TransitionType=Tween.TransitionType.TRANS_BACK
##当前持有的动画
var now_keep_tween:Tween
##当前是否打开
@export var is_open:bool=true
##持有的抽屉控制按钮的实例(内部节点)
var side_button:BaseButton
##获取当前持有的侧边按钮
func get_side_button()->BaseButton:
return side_button
##当前动画状态0为完全打开1为完全关闭
@export var rag:float=0:
set(val):
rag=val
fit_side_button()
fit_children()
minimum_size_changed.emit()
func _ready() -> void:
add_child(hide_timer,false,Node.INTERNAL_MODE_FRONT)
hide_timer.one_shot=true
hide_timer.timeout.connect(hide_time_out)
if is_open:
rag=0
else:
rag=1
if button_tscn!=null:
var new_btn=button_tscn.instantiate()
if new_btn is BaseButton:
side_button=new_btn
add_child(new_btn,false,Node.INTERNAL_MODE_FRONT)
else:
new_btn=Button.new()
side_button=new_btn
add_child(new_btn,false,Node.INTERNAL_MODE_FRONT)
else:
var new_btn=Button.new()
side_button=new_btn
add_child(new_btn,false,Node.INTERNAL_MODE_FRONT)
side_button.pressed.connect(change_open)
side_button.minimum_size_changed.connect(side_button_size_changed)
side_button_size_changed()
if disable_button:
side_button.hide()
resized.connect(resize)
resize()
_re_ready()
pass # Replace with function body.
##因为占用了ready函数所以留了一个新的虚函数给使用节点重写
func _re_ready()->void:
pass
##对侧边栏按钮进行适配
func fit_side_button()->void:
var rect:Rect2
if side_button!=null:
match button_model:
BUTTON_MODEL.TOP:
rect=Rect2(0,(size.y-button_size.y)*rag,size.x,button_size.y)
BUTTON_MODEL.END:
rect=Rect2(0,(size.y-button_size.y)*(1-rag),size.x,button_size.y)
BUTTON_MODEL.LEFT:
rect=Rect2((size.x-button_size.x)*rag,0,button_size.x,size.y)
BUTTON_MODEL.RIGHT:
rect=Rect2((size.x-button_size.x)*(1-rag),0,button_size.x,size.y)
_:
rect=Rect2()
fit_child_in_rect(side_button,rect)
##对子节点进行适配
func fit_children()->void:
var rect:Rect2
if !disable_button:
match button_model:
BUTTON_MODEL.TOP:
rect=Rect2(0,(size.y-button_size.y)*rag+button_size.y,size.x,size.y-button_size.y)
BUTTON_MODEL.END:
rect=Rect2(0,(size.y-button_size.y)*(-rag),size.x,size.y-button_size.y)
BUTTON_MODEL.LEFT:
rect=Rect2((size.x-button_size.x)*rag+button_size.x,0,size.x-button_size.x,size.y)
BUTTON_MODEL.RIGHT:
rect=Rect2((size.x-button_size.x)*(-rag),0,size.x-button_size.x,size.y)
_:
rect=Rect2()
else:
match button_model:
BUTTON_MODEL.TOP:
rect=Rect2(0,(size.y)*rag+button_size.y,size.x,size.y)
BUTTON_MODEL.END:
rect=Rect2(0,(size.y)*(-rag),size.x,size.y)
BUTTON_MODEL.LEFT:
rect=Rect2((size.x)*rag,0,size.x,size.y)
BUTTON_MODEL.RIGHT:
rect=Rect2((size.x)*(-rag),0,size.x,size.y)
_:
rect=Rect2()
pass
for i in get_children():
if i is Control:
fit_child_in_rect(i,rect)
##更改窗口的开闭状态,使用动画
func change_open(opened:bool=false):
if opened==is_open:
return
if now_keep_tween!=null:
now_keep_tween.kill()
if !opened:
if is_auto_hide:
hide_timer.start(animation_time)
pass
now_keep_tween=create_tween()
now_keep_tween.set_trans(animation_model)
now_keep_tween.tween_property(self,"rag",1,animation_time)
else:
now_keep_tween=create_tween()
now_keep_tween.set_trans(animation_model)
now_keep_tween.tween_property(self,"rag",0,animation_time)
if is_auto_hide:
show()
hide_timer.stop()
is_open=opened
pass
##当此节点大小改变时触发
func resize():
fit_side_button()
fit_children()
##重写的虚函数,用于获取当前节点的最小大小
func _get_minimum_size() -> Vector2:
var res:Vector2=Vector2.ZERO
for i in get_children():
if i is Control:
var i_size:Vector2=i.get_minimum_size()
res=Vector2(max(res.x,i_size.x),max(res.y,i_size.y))
if not is_auto_shrink:
if !disable_button:
match button_model:
BUTTON_MODEL.TOP:
res=Vector2(max(res.x,button_size.x),res.y+button_size.y)
BUTTON_MODEL.END:
res=Vector2(max(res.x,button_size.x),res.y+button_size.y)
BUTTON_MODEL.LEFT:
res=Vector2(res.x+button_size.x,max(res.y,button_size.y))
BUTTON_MODEL.RIGHT:
res=Vector2(res.x+button_size.x,max(res.y,button_size.y))
_:
res=Vector2.ZERO
else:
if !disable_button:
match button_model:
BUTTON_MODEL.TOP:
res=Vector2(max(res.x,button_size.x),res.y*rag+button_size.y)
BUTTON_MODEL.END:
res=Vector2(max(res.x,button_size.x),res.y*rag+button_size.y)
BUTTON_MODEL.LEFT:
res=Vector2(res.x*rag+button_size.x,max(res.y,button_size.y))
BUTTON_MODEL.RIGHT:
res=Vector2(res.x*rag+button_size.x,max(res.y,button_size.y))
_:
res=Vector2.ZERO
else:
match button_model:
BUTTON_MODEL.TOP:
res=Vector2(res.x,res.y*(1-rag))
BUTTON_MODEL.END:
res=Vector2(res.x*rag,res.y*(1-rag))
BUTTON_MODEL.LEFT:
res=Vector2(res.x*(1-rag),res.y)
BUTTON_MODEL.RIGHT:
res=Vector2(res.x*rag,res.y*(1-rag))
_:
res=Vector2.ZERO
pass
return res
##当侧边栏按钮大小更改时调用
func side_button_size_changed()->void:
if side_button:
var new_size=side_button.get_minimum_size()
button_size=Vector2(max(custom_button_size.x,new_size.x),max(custom_button_size.y,new_size.y))
func _process(delta: float) -> void:
if Engine.is_editor_hint():
fit_children()
pass
func hide_time_out():
hide()