aboutsummaryrefslogtreecommitdiff
path: root/src/addons/rmsmartshape/shapes/edge.gd
blob: a1d01ca591621ad5325947d2d155c65af15e7f32 (plain)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
tool
extends Reference
class_name SS2D_Edge

var quads: Array = []
var first_point_key: int = -1
var last_point_key: int = -1
var z_index: int = 0
var z_as_relative: bool = false
# If final point is connected to first point
var wrap_around: bool = false
var material: Material = null

static func different_render(q1: SS2D_Quad, q2: SS2D_Quad) -> bool:
	"""
	Will return true if the 2 quads must be drawn in two calls
	"""
	if q1.matches_quad(q2):
		return false
	return true

static func get_consecutive_quads_for_mesh(_quads: Array) -> Array:
	if _quads.empty():
		return []

	var quad_ranges = []
	var quad_range = []
	quad_range.push_back(_quads[0])
	for i in range(1, _quads.size(), 1):
		var quad_prev = _quads[i - 1]
		var quad = _quads[i]
		if different_render(quad, quad_prev):
			quad_ranges.push_back(quad_range)
			quad_range = [quad]
		else:
			quad_range.push_back(quad)

	quad_ranges.push_back(quad_range)
	return quad_ranges

static func generate_array_mesh_from_quad_sequence(_quads: Array, wrap_around: bool) -> ArrayMesh:
	"""
	Assumes each quad in the sequence is of the same render type
	same textures, values, etc...
	quads passed in as an argument should have been generated by get_consecutive_quads_for_mesh
	"""
	if _quads.empty():
		return ArrayMesh.new()

	var total_length: float = 0.0
	for q in _quads:
		total_length += q.get_length_average()
	if total_length == 0.0:
		return ArrayMesh.new()

	var first_quad = _quads[0]
	var tex: Texture = first_quad.texture
	# The change in length required to apply to each quad
	# to make the textures begin and end at the start and end of each texture
	var change_in_length: float = -1.0
	if tex != null:
		# How many times the texture is repeated
		var texture_reps = round(total_length / tex.get_size().x)
		# Length required to display all the reps with the texture's full width
		var texture_full_length = texture_reps * tex.get_size().x
		# How much each quad's texture must be offset to make up the difference in full length vs total length
		change_in_length = (texture_full_length / total_length)

	if first_quad.fit_texture == SS2D_Material_Edge.FITMODE.CROP:
		change_in_length = 1.0

	var length_elapsed: float = 0.0
	var st = SurfaceTool.new()
	st.begin(Mesh.PRIMITIVE_TRIANGLES)
	for q in _quads:
		var section_length: float = q.get_length_average() * change_in_length
		var highest_value: float = max(q.get_height_left(), q.get_height_right())
		# When welding and using different widths, quads can look a little weird
		# This is because they are no longer parallelograms
		# This is a tough problem to solve
		# See http://reedbeta.com/blog/quadrilateral-interpolation-part-1/
		var uv_a = Vector2(0, 0)
		var uv_b = Vector2(0, 1)
		var uv_c = Vector2(1, 1)
		var uv_d = Vector2(1, 0)
		# If we have a valid texture and this quad isn't a corner
		if tex != null and q.corner == q.CORNER.NONE:
			var x_left = (length_elapsed) / tex.get_size().x
			var x_right = (length_elapsed + section_length) / tex.get_size().x
			uv_a.x = x_left
			uv_b.x = x_left
			uv_c.x = x_right
			uv_d.x = x_right
		if q.flip_texture:
			var t = uv_a
			uv_a = uv_b
			uv_b = t
			t = uv_c
			uv_c = uv_d
			uv_d = t

		# A
		_add_uv_to_surface_tool(st, uv_a)
		st.add_color(q.color)
		st.add_vertex(SS2D_Common_Functions.to_vector3(q.pt_a))

		# B
		_add_uv_to_surface_tool(st, uv_b)
		st.add_color(q.color)
		st.add_vertex(SS2D_Common_Functions.to_vector3(q.pt_b))

		# C
		_add_uv_to_surface_tool(st, uv_c)
		st.add_color(q.color)
		st.add_vertex(SS2D_Common_Functions.to_vector3(q.pt_c))

		# A
		_add_uv_to_surface_tool(st, uv_a)
		st.add_color(q.color)
		st.add_vertex(SS2D_Common_Functions.to_vector3(q.pt_a))

		# C
		_add_uv_to_surface_tool(st, uv_c)
		st.add_color(q.color)
		st.add_vertex(SS2D_Common_Functions.to_vector3(q.pt_c))

		# D
		_add_uv_to_surface_tool(st, uv_d)
		st.add_color(q.color)
		st.add_vertex(SS2D_Common_Functions.to_vector3(q.pt_d))

		length_elapsed += section_length

	st.index()
	st.generate_normals()
	return st.commit()


func get_meshes() -> Array:
	"""
	Returns an array of SS2D_Mesh
	# Get Arrays of consecutive quads with the same mesh data
	# For each array
	## Generate Mesh Data from the quad
	"""

	var consecutive_quad_arrays = get_consecutive_quads_for_mesh(quads)
	#print("Arrays: %s" % consecutive_quad_arrays.size())
	var meshes = []
	for consecutive_quads in consecutive_quad_arrays:
		if consecutive_quads.empty():
			continue
		var st: SurfaceTool = SurfaceTool.new()
		var array_mesh: ArrayMesh = generate_array_mesh_from_quad_sequence(
			consecutive_quads, wrap_around
		)
		var tex: Texture = consecutive_quads[0].texture
		var tex_normal: Texture = consecutive_quads[0].texture_normal
		var flip = consecutive_quads[0].flip_texture
		var transform = Transform2D()
		var mesh_data = SS2D_Mesh.new(tex, tex_normal, flip, transform, [array_mesh], material)
		mesh_data.z_index = z_index
		mesh_data.z_as_relative = z_as_relative
		meshes.push_back(mesh_data)

	return meshes


static func _add_uv_to_surface_tool(surface_tool: SurfaceTool, uv: Vector2):
	surface_tool.add_uv(uv)
	surface_tool.add_uv2(uv)