extends Spatial
class_name PolyTree2

export (float, 0, 100) var audible_range_max = 40.0
export (int, 1, 16) var preset = 1

export (bool) var use_embeded_patch = true
export (String, MULTILINE) var patch = """#N canvas 0 82 446 513 12;
#X obj 21 22 r fromGodot\\$0;
#X obj 21 46 list trim;
#X obj 303 253 hsl 100 20 -1 1 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 300 349 line~;
#X msg 300 325 \\$1 100;
#X obj 300 278 expr ($f1 + 1)/8;
#X floatatom 300 302 5 0 0 0 - - - 0;
#N canvas 68 97 450 300 pan2~ 0;
#X obj 51 98 cos~;
#X obj 111 98 cos~;
#X obj 33 128 *~;
#X obj 93 128 *~;
#X obj 33 158 outlet~;
#X obj 93 158 outlet~;
#X obj 33 24 inlet~;
#X obj 111 24 inlet~;
#X obj 111 74 +~ 0.75;
#X connect 0 0 2 1;
#X connect 1 0 3 1;
#X connect 2 0 4 0;
#X connect 3 0 5 0;
#X connect 6 0 2 0;
#X connect 6 0 3 0;
#X connect 7 0 8 0;
#X connect 7 0 0 0;
#X connect 8 0 1 0;
#X restore 199 437 pd pan2~;
#X obj 199 467 dac~ 1 2;
#X obj 199 407 *~;
#X obj 189 127 unpack f f;
#X floatatom 296 159 5 0 0 0 - - - 0;
#X obj 296 182 sin;
#X floatatom 296 206 5 0 0 0 - - - 0;
#X obj 21 120 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 361 21 loadbang;
#X obj 21 70 route bang panvol param preset;
#X obj 20 470 *~;
#X obj 38 446 vline~;
#X msg 38 422 0 \\, 1 1000 300;
#X obj 38 398 loadbang;
#X msg 361 51 \\; pd dsp 1;
#N canvas 478 23 962 799 synth 0;
#X obj 403 150 inlet;
#X obj 404 553 +;
#X floatatom 457 224 5 0 0 0 - - - 0;
#X floatatom 499 224 5 0 0 0 - - - 0;
#X floatatom 374 224 5 0 0 0 - - - 0;
#X floatatom 416 224 5 0 0 0 - - - 0;
#X obj 403 181 unpack f f f f f;
#X floatatom 544 224 5 0 0 0 - - - 0;
#X obj 463 150 r \\$0-preset;
#X obj 697 720 s \\$0-preset;
#X obj 630 241 inlet;
#X obj 630 265 sel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16;
#X obj 243 375 mtof;
#X floatatom 243 352 5 0 150 0 - \\$0-pit - 0;
#X obj 234 322 noise~;
#X floatatom 243 400 5 0 0 0 - - - 0;
#X obj 234 458 bp~;
#X text 275 460 band-pass filter;
#X text 288 400 <= cutoff (Hertz);
#X obj 302 557 *~;
#X obj 401 552 hsl 60 19 0 1 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 345 342 line;
#X floatatom 299 440 5 0 0 0 - - - 0;
#X obj 280 167 random 3;
#X obj 280 191 sel 0 1 2;
#X obj 354 278 pack 0 0;
#X msg 352 312 \\$1 \\$2;
#X obj 185 197 + 500;
#X floatatom 403 592 5 0 0 0 - - - 0;
#X obj 185 170 random 800;
#X obj 301 602 outlet~;
#X msg 770 305 915 987 1070 290 0.8;
#X msg 770 329 103 126 205 10 0.8;
#X msg 770 353 260 366 317 61 0.8;
#X msg 771 378 123 80 184 22 0.9;
#X msg 770 401 1833 1998 2100 272 0.7;
#X msg 770 425 415 498 286 323 0.9;
#X msg 770 449 1567 1648 1606 323 0.8;
#X msg 770 473 195 186 150 102 0.9;
#X msg 771 498 219 294 279 269 1;
#X msg 770 521 330 305 354 31 0.7;
#X msg 770 545 92 55 66 22 0.8;
#X msg 770 569 37 43 22 9 0.9;
#X msg 770 593 3183 3117 3224 538 0.6;
#X msg 770 617 2878 2589 2357 996 0.6;
#X msg 770 641 378 396 267 996 0.8;
#X msg 770 665 538 567 735 191 0.7;
#N canvas 386 23 374 377 retro 0;
#X obj 43 211 del;
#X obj 43 261 spigot;
#X obj 139 72 tgl 15 0 empty empty empty 17 7 0 10 #0400fc #f8fc00 #000000 0 1;
#X obj 145 216 random;
#X obj 82 235 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 50 47 inlet;
#X obj 43 286 outlet;
#X obj 50 104 t b f;
#X obj 113 191 t b b;
#X obj 158 72 bng 10 250 50 0 empty empty empty 17 7 0 10 #f8fc00 #0400fc #000000;
#X obj 234 37 inlet;
#X obj 266 135 unpack f f;
#X obj 234 107 expr $f2-$f1;
#X floatatom 234 197 5 0 0 0 range - - 0;
#X floatatom 266 223 5 0 0 0 start - - 0;
#X obj 145 242 +;
#X floatatom 171 69 5 0 0 1 r - - 0;
#X obj 145 286 outlet;
#X obj 234 71 t a a;
#X connect 0 0 1 0;
#X connect 1 0 6 0;
#X connect 1 0 9 0;
#X connect 2 0 7 0;
#X connect 3 0 15 0;
#X connect 4 0 1 1;
#X connect 5 0 2 0;
#X connect 7 0 9 0;
#X connect 7 1 4 0;
#X connect 8 0 0 0;
#X connect 8 1 3 0;
#X connect 9 0 8 0;
#X connect 10 0 18 0;
#X connect 11 0 14 0;
#X connect 12 0 13 0;
#X connect 13 0 3 1;
#X connect 14 0 15 1;
#X connect 15 0 0 1;
#X connect 15 0 16 0;
#X connect 15 0 17 0;
#X connect 18 0 12 0;
#X connect 18 1 11 0;
#X coords 0 -1 1 1 85 40 1 135 50;
#X restore 202 74 pd retro;
#X obj 202 7 loadbang;
#X obj 202 31 t b b;
#X msg 280 50 500 2500;
#X obj 202 119 t b b;
#X connect 0 0 6 0;
#X connect 2 0 25 0;
#X connect 3 0 22 0;
#X connect 4 0 25 0;
#X connect 5 0 25 0;
#X connect 6 0 4 0;
#X connect 6 1 5 0;
#X connect 6 2 2 0;
#X connect 6 3 3 0;
#X connect 6 4 7 0;
#X connect 7 0 20 0;
#X connect 8 0 6 0;
#X connect 10 0 11 0;
#X connect 11 0 31 0;
#X connect 11 1 32 0;
#X connect 11 2 33 0;
#X connect 11 3 34 0;
#X connect 11 4 35 0;
#X connect 11 5 36 0;
#X connect 11 6 37 0;
#X connect 11 7 38 0;
#X connect 11 8 40 0;
#X connect 11 9 41 0;
#X connect 11 10 42 0;
#X connect 11 11 43 0;
#X connect 11 12 44 0;
#X connect 11 13 45 0;
#X connect 11 14 46 0;
#X connect 11 15 39 0;
#X connect 12 0 15 0;
#X connect 13 0 12 0;
#X connect 14 0 16 0;
#X connect 15 0 16 1;
#X connect 16 0 19 0;
#X connect 19 0 30 0;
#X connect 20 0 19 1;
#X connect 20 0 28 0;
#X connect 21 0 15 0;
#X connect 22 0 16 2;
#X connect 23 0 24 0;
#X connect 24 0 4 0;
#X connect 24 1 5 0;
#X connect 24 2 2 0;
#X connect 25 0 26 0;
#X connect 26 0 21 0;
#X connect 27 0 25 1;
#X connect 29 0 27 0;
#X connect 31 0 9 0;
#X connect 32 0 9 0;
#X connect 33 0 9 0;
#X connect 34 0 9 0;
#X connect 35 0 9 0;
#X connect 36 0 9 0;
#X connect 37 0 9 0;
#X connect 38 0 9 0;
#X connect 39 0 9 0;
#X connect 40 0 9 0;
#X connect 41 0 9 0;
#X connect 42 0 9 0;
#X connect 43 0 9 0;
#X connect 44 0 9 0;
#X connect 45 0 9 0;
#X connect 46 0 9 0;
#X connect 47 0 51 0;
#X connect 48 0 49 0;
#X connect 49 0 47 0;
#X connect 49 1 50 0;
#X connect 50 0 47 1;
#X connect 51 0 23 0;
#X connect 51 1 29 0;
#X restore 40 300 pd synth;
#X obj 208 330 *~;
#X obj 189 264 line~;
#X msg 189 240 \\$1 100;
#X floatatom 189 177 5 0 0 0 - - - 0;
#X obj 132 310 switch~;
#X obj 132 286 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 132 262 change;
#X text 89 155 switch on/off before 0 to stop startup pops, f 12;
#X obj 189 216 max 0;
#X obj 132 238 > -0.3;
#X connect 0 0 1 0;
#X connect 1 0 16 0;
#X connect 2 0 5 0;
#X connect 3 0 7 1;
#X connect 4 0 3 0;
#X connect 5 0 6 0;
#X connect 6 0 4 0;
#X connect 7 0 8 0;
#X connect 7 1 8 1;
#X connect 9 0 7 0;
#X connect 10 0 26 0;
#X connect 10 1 11 0;
#X connect 11 0 12 0;
#X connect 12 0 13 0;
#X connect 13 0 2 0;
#X connect 16 0 14 0;
#X connect 16 1 10 0;
#X connect 16 2 22 0;
#X connect 16 3 22 1;
#X connect 18 0 17 1;
#X connect 19 0 18 0;
#X connect 20 0 19 0;
#X connect 22 0 9 0;
#X connect 23 0 9 1;
#X connect 24 0 23 0;
#X connect 24 0 23 1;
#X connect 25 0 24 0;
#X connect 26 0 31 0;
#X connect 26 0 32 0;
#X connect 28 0 27 0;
#X connect 29 0 28 0;
#X connect 31 0 25 0;
#X connect 32 0 29 0;
"""

var _my_patch = "user://crickets/wind.pd"
var _my_id = 0

func set_size(size):
	$CollisionShape.shape.radius = size
	$MeshInstance.mesh.radius = size
	$MeshInstance.mesh.height = size * 2

func set_freq(freq):
	Global._gdpd.start_message(2)
	Global._gdpd.add_symbol('freq')
	Global._gdpd.add_float(freq)
	Global._gdpd.finish_list("fromGodot" + String(_my_id))

func set_gain(gain):
	Global._gdpd.start_message(2)
	Global._gdpd.add_symbol('gain')
	Global._gdpd.add_float(gain)
	Global._gdpd.finish_list("fromGodot" + String(_my_id))

func set_param(param):
	Global._gdpd.start_message(param.size()+1)
	Global._gdpd.add_symbol("param")
	for i in range(param.size()):
		Global._gdpd.add_float(param[i])
	Global._gdpd.finish_list("fromGodot" + String(_my_id))

func set_preset(prs):
	preset = prs
	Global._gdpd.start_message(2)
	Global._gdpd.add_symbol("preset")
	Global._gdpd.add_float(prs)
	Global._gdpd.finish_list("fromGodot" + String(_my_id))

func set_color(color):
	$MeshInstance.material_override = SpatialMaterial.new()
	$MeshInstance.material_override.albedo_color = color

func _ready():
	add_child(Branch2.new(Leaves.new(2)))

	# save patch (for export)
	if use_embeded_patch:
		assert(_my_patch.substr(0, 7) == "user://", "use userpath with embeded_patch enabled !")
		assert(patch != "", "patch is empty?")
		_save_patch()

	# load patch

	_my_id = Global.load_patch(ProjectSettings.globalize_path(_my_patch))

	# listen 'player_transform_updated' event
	Events.connect("player_transform_updated", self, "_on_Events_player_transform_updated")

	# send 'preset'
	set_preset(preset)

func _on_Events_player_transform_updated(playerpos, playerheading):
	var mypos = get_global_translation()
	var mypos2d = Vector2(mypos.x, mypos.z)
	var playerpos2d = Vector2(playerpos.x, playerpos.z)
	# calculate distance
	var distance = mypos.distance_to(playerpos)
	# calculate angle
	var angle = fmod(fmod(playerpos2d.angle_to_point(mypos2d) + playerheading - PI/2, PI*2) + PI*2, PI*2)
	if angle > PI:
		angle = angle - PI*2
	# (check)
#	print(str(_my_id) +" : ("+ str(distance) +","+ str(angle) +")")
	# calculate gain
	var gain = 1 - distance/audible_range_max
	# send to the patch
	Global._gdpd.start_message(3)
	Global._gdpd.add_symbol("panvol")
	Global._gdpd.add_float(gain)
	Global._gdpd.add_float(angle)
	Global._gdpd.finish_list("fromGodot" + String(_my_id))


func _exit_tree():
	Global.close_patch(_my_id)

func _save_patch():
	# save patch
	# prepare directory
	var patch_name = _my_patch.split("/")[-1]
	var patch_dir = _my_patch.trim_suffix(patch_name)
	var dir = Directory.new()
	dir.make_dir_recursive(patch_dir)
	# save to file
	var file = File.new()
	file.open(_my_patch, File.WRITE)
	file.store_string(patch)
	file.close()
