天天看點

Godot 動态擷取子節點的屬性導出到父節點的面闆上,并可以同步修改

Godot 3.2.3

GDScript 1.0

可以動态擷取子節點的自定義的導出到面闆中的變量,顯示到目前的屬性面闆中,并可以同步修改,就是修改導出到這個節點的屬性,也會修改對應子節點的這個屬性

代碼如下:

"""=====================================================================
				PropertyList
========================================================================
 [屬性清單]
========================================================================
@datetime: 2020-8-7 19:00
@Godot version: 3.2.3
@author: [email protected]
@version: 1.0
====================================================================="""

tool
extends Node
class_name PropertyList


"""私有變量"""
var _custom_property_list : Array = []


##==============================
##		内置方法
##==============================
func _set(property: String, value) -> bool:
	# 修改屬性時,将對應子節點的值也修改
	for custom_property in _custom_property_list:
		if custom_property['name'] == property:
			# 轉換 NodePath 類型節點跟子節點比對
			if custom_property['type'] == TYPE_NODE_PATH:
				if value != '':
					var tmp_node = get_node_or_null(value)
					if tmp_node != null:
						value = custom_property['host'].get_path_to(tmp_node)
			# 修改子節點的屬性
			custom_property['host'].set(custom_property['origin_name'], value)
	return true


func _get(property: String):
	# 擷取對應子節點的屬性值
	for custom_property in _custom_property_list:
		if custom_property['name'] == property && custom_property.has('host'):
			var property_value = custom_property['host'].get(custom_property['origin_name'])
			if custom_property['type'] == TYPE_NODE_PATH:
				property_value = self.get_path_to(custom_property['host'].get_node_or_null(property_value))
			return property_value
	return true


func _get_property_list() -> Array:
	# 更新屬性清單
	update_custom_property_list()
	# 設定自定義屬性,更新到屬性面闆中
	return _custom_property_list


func _enter_tree() -> void:
	update_custom_property_list()



##==============================
##		自定義方法
##==============================
func update_custom_property_list() -> void:
	"""更新自定義屬性清單"""
	_custom_property_list = []
	# 屬性欄面闆顯示方式
#	_custom_property_list.append({
#		name='Property List',
#		type=TYPE_NIL,
#		usage=PROPERTY_USAGE_DEFAULT_INTL | PROPERTY_USAGE_CATEGORY
#	})
	
	# 周遊搜尋 PropertyBase 類節點
	for property_node in get_children():
		if property_node is PropertyBase:  # 這一行if可以去掉,這個主要是判斷對應的節點而寫的,自己用的話可以去掉
			# 添加 [屬性節點的屬性] 到 [自身自定義的屬性]
			append_custom_property_list(property_node)


func append_custom_property_list(property_node) -> void:
	"""添加自定義屬性
	@property_node: 屬性節點
	"""
	# 添加屬性
	for property_data in get_custom_property_list(property_node):
		# 記錄這個屬性的 [host]
		property_data['host'] = property_node
		property_data['origin_name'] = property_data['name']
		property_data['name'] = property_node.name + '/' + property_data['name']
		
		# 将 “屬性節點” 的 “自定義屬性” 添加到目前的 “_custom_property_list” 中
		_custom_property_list.append(property_data)



# ==================== 注意事項 =======================
# get_custom_property_list 和 is_custom_property 這兩個
# 函數在這個腳本裡是必須要有的,否則動态屬性清單将不起作用
# ===================================================
func get_custom_property_list(obj: Object) -> Array:
	"""擷取節點的自定義屬性清單"""
	var property_list : Array = []
	for i in obj.get_property_list():
		# 這是一個 [自定義] 的屬性 [usage] 則添加
		if is_custom_property(i['usage']):
			property_list.append(i)
	return property_list


func is_custom_property(var_usage) -> bool:
	"""傳回變量是否是自定義屬性
	@var_usage 變量辨別
	"""
	if (var_usage == PROPERTY_USAGE_SCRIPT_VARIABLE || 
		var_usage == PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_STORAGE 
						| PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK
	):
		return true
	return false