写者 (Writer) 入门

写者 是一种将数据节点的数据同步到原版数据的 关系

写者观察数据节点,绑定目标数据,当观察的数据节点发生改变, 写者会读取数据节点的数据,写入目标数据。

数据节点自带改变信号,所以一个写者有两个基本要素,源数据节点、目标数据。

写者默认有四种类型,都继承自写者基类 Writer

属性型(Property)

WriterProperty

属性型只同步一个属性,有别于属性型观察者,属性型写者只支持基础数据类型。

下面这个例子就是用一个DataNodeInt来将数据同步到TestObj的 a 属性。

class TestObj:
  var a: int

# ...

func _ready():
  var target_obj := TestObj.new()
  var source_data_node := DataNodeInt.new(0)
  prints(target_obj.a) # 0

  var _writer := WriterProperty.new(target_obj, ^"a", source_data_node)
  source_data_node.render(1)
  prints(target_obj.a) # 1

属性数组型(PropertyArray)

WriterPropertyArray

将数组型数据节点同步到目标对象的数组类型成员。

简单数组,也就是元素是基本数据类型的数组,无需指定子写者。

class TestSimpleList:
  var test_array: Array[int]

# ...

func _ready() -> void:
  var target_obj := TestSimpleList.new()
  var source_data_node := DataNodeList.new(TYPE_INT, func(): return DataNodeInt.new(0))

  var _writer := WriterPropertyArray.new(target_obj, ^":test_array", source_data_node)
  prints(target_obj.test_array) # []
  source_data_node.append(1)
  await get_tree().process_frame # Struct updates asynchronously
  prints(target_obj.test_array) # [1]

元素是对象的数组,需要指定子写者。

class TestList:
  var test_array: Array[TestObj]

class TestObj:
  var a: int

# ...

func _ready() -> void:
  var target_obj := TestList.new()
  var source_data_node := DataNodeList.new(TYPE_INT, func(): return DataNodeInt.new(0))
  var _writer := WriterPropertyArray.new(
    target_obj,
    ^":test_array",
    source_data_node,
    WriterPropertyArray.ElementSubWriter.new(
      func(element_data_node: DataNodeInt):
        var result := TestObj.new()
        result.a = element_data_node.value()
        return result
        ,
      func(element_data_node: DataNodeInt, target_object: TestObj) -> Array:
        return [WriterProperty.new(target_object, ^":a", element_data_node)]
        )
  )

  prints(target_obj.test_array) # []
  source_data_node.append(1)

  await get_tree().process_frame # Struct updates asynchronously
  prints(target_obj.test_array.size()) # 1
  prints(target_obj.test_array[0].a) # 1

属性字典型(PropertyDictionary)

WriterPropertyDictionary

将字典型数据节点同步到目标对象的字典类型成员。

简单字典,也就是元素是基本数据类型的字典,无需指定子写者。

class TestSimpleDictionary:
  var test_dictionary: Dictionary[StringName, int]

# ...

func _ready() -> void:
  var target_obj := TestSimpleDictionary.new()
  var source_data_node := DataNodeDict.new(TYPE_STRING_NAME, TYPE_INT, func(): return DataNodeInt.new(0))

  var _writer := WriterPropertyDictionary.new(target_obj, ^":test_dictionary", source_data_node)
  prints(target_obj.test_dictionary) # {}
  source_data_node.set_element(&"new_element", 1)

  await get_tree().process_frame # Struct updates asynchronously
  prints(target_obj.test_dictionary) # {&"new_element": 1}

值是对象的字典,需要指定子写者。键没有子写者。

class TestDictionary:
  var test_dictionary: Dictionary[StringName, TestObj]

class TestObj:
  var a: int

# ...

func _ready() -> void:
  var target_obj := TestDictionary.new()
  var source_data_node := DataNodeDict.new(TYPE_STRING_NAME, TYPE_INT, func(): return DataNodeInt.new(0))
  var _writer := WriterPropertyDictionary.new(
    target_obj,
    ^":test_dictionary",
    source_data_node,
    WriterPropertyDictionary.ElementSubWriter.new(
      func(element_data_node: DataNodeInt):
        var result := TestObj.new()
        result.a = element_data_node.value()
        return result
        ,
      func(element_data_node: DataNodeInt, target_object: TestObj) -> Array:
        return [WriterProperty.new(target_object, ^":a", element_data_node)]
        )
  )
  prints(target_obj.test_dictionary) # {}
  source_data_node.set_element(&"new_element", 1)
  await get_tree().process_frame # Struct updates asynchronously
  prints(target_obj.test_dictionary.size()) # 1
  prints(target_obj.test_dictionary[&"new_element"].a) # 1

节点型(Node)

WriterNode

将节点型数据节点同步到目标节点。

只负责子节点的增删排序。

class TestSuperNode extends Node:
  pass

class TestSubNode extends Node:
  var a: int

# ...

func _ready() -> void:
  var target_obj := TestSuperNode.new()
  var source_data_node := DataNodeList.new(TYPE_INT, func(): return DataNodeInt.new(0))
  var _writer := WriterNode.new(
    target_obj,
    source_data_node,
    WriterNode.ChildSubWriter.new(
      func(chlid_data_node: DataNodeInt) -> Node:
        var result := TestSubNode.new()
        result.a = chlid_data_node.value()
        return result
        ,
      func(chlid_data_node: DataNodeInt, target_node: Node) -> Array:
        return [WriterProperty.new(target_node, ^":a", chlid_data_node)]
        )
  )
  prints(target_obj.get_child_count()) # 0
  source_data_node.append(1)
  await get_tree().process_frame # Struct updates asynchronously
  prints(target_obj.get_child_count()) # 1
  prints(target_obj.get_child(0).a) # 1
  target_obj.queue_free()