-
Notifications
You must be signed in to change notification settings - Fork 1
/
GrammarSymbol.gd
138 lines (103 loc) · 2.98 KB
/
GrammarSymbol.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
@tool
extends RefCounted
class_name GrammarSymbol
var id = -1
var text = ""
var nr_of_vertices = 0
var faces = []
var terminal = true
var rules = {}
var rule_weigths = {}
var rule_weights_sum = 0
func save():
return [id, text, nr_of_vertices, faces, terminal]
func l(data):
self.id = data[0]
self.text = data[1]
self.nr_of_vertices = data[2]
self.faces = data[3]
self.terminal = data[4]
func pack():
var sym_data = self.save()
var rule_indices = []
var rule_array = []
for rule_i in self.rules:
var rule = self.rules[rule_i]
rule_indices.append(rule_i)
rule_array.append(rule.pack())
return [sym_data, rule_indices, rule_array]
static func from_data(data):
var new_sym = GrammarSymbol.new(data[2], data[3], data[4])
new_sym.id = data[0]
new_sym.text = data[1]
return new_sym
static func from_packed(p):
var gs = from_data(p[0])
return gs
func unpack_rules(p, symbol_map):
var rule_array = p[2]
for i in rule_array.size():
var rule_packed = rule_array[i]
# This adds the rule to the symbol automatically as well
GrammarRule.from_packed(rule_packed, self, symbol_map)
func serialize():
# Sizes
var data = PackedByteArray()
data.resize(2)
data.encode_u16(0, self.nr_of_vertices)
data.append(text.length())
data.append(self.rules.size())
data.append(self.faces.size())
data.append(self.terminal)
var total_size = 0
for face in self.faces:
total_size += face.size()
data.append(face.size())
# Faces
var i = data.size()
i = snappedi(i + 1.5, 4)
data.resize(i + total_size * 2)
for face in self.faces:
for vi in face:
data.encode_u16(i, vi)
i += 2
data.append_array(self.text.to_utf8_buffer())
# Pad
var new_size = snappedi(data.size() + 5.5, 4)
if new_size != data.size():
data.resize(new_size)
return data
func _init(_nr_of_verts,_faces,_terminal=true):
self.nr_of_vertices = _nr_of_verts
self.faces = _faces.duplicate(true)
self.terminal = _terminal
func has_same_topology_as(other):
return self.nr_of_vertices == other.nr_of_vertices and self.faces == other.faces
func can_be_assigned_to(poly):
return self.nr_of_vertices == poly.vertices.size() and self.faces == poly.faces
func is_terminal():
return self.rules.size() == 0
func add_rule(index, rule, weight=1):
# Remove the old version of the rule if it exists
self.remove_rule(index)
self.rules[index] = rule
self.rule_weigths[index] = weight
self.rule_weights_sum += weight
func update_rule(index, rule, weight=1):
self.add_rule(index, rule, weight)
func remove_rule(index):
if self.rule_weigths.has(index):
self.rule_weights_sum -= self.rule_weigths[index]
self.rules.erase(index)
self.rule_weigths.erase(index)
func get_rule(index):
return self.rules[index]
# Selects rule randomly
func select_rule(rng : RandomNumberGenerator):
var random_tresh = rng.randf_range(0, self.rule_weights_sum)
var keys = self.rules.keys()
var weight = 0
for key in keys:
weight += self.rule_weigths[key]
if weight >= random_tresh:
return self.rules[key]