extends Spatial
class_name PolyTree

export (float, 0, 100) var audible_range_max = 30.0
export (int, 1, 32) var preset = 1

export (bool) var use_embeded_patch = true
export (String, MULTILINE) var patch = """#N canvas 0 82 1045 747 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 0 23 1440 807 synth 0;
#X obj 334 43 inlet;
#X obj 254 630 +~ 1;
#X obj 254 658 *~ 50;
#X obj 572 671 *~;
#X obj 95 350 metro 0.5 120 permin;
#X obj 95 380 bng 16 250 50 0 empty empty empty 0 -12 0 16 #fcfcfc #000000 #000000;
#X obj 21 192 tgl 24 0 empty empty empty 0 -12 0 16 #fcfcfc #000000 #000000 0 1;
#X msg 95 310 tempo \\$1 permin;
#X floatatom 95 281 5 0 0 1 bpm - - 0;
#X obj 95 407 f;
#X obj 141 407 + 1;
#X floatatom 95 437 5 0 0 0 - - - 0;
#X obj 95 526 bng 16 250 50 0 empty empty empty 0 -16 0 24 #fcfcfc #000000 #000000;
#X obj 122 526 bng 16 250 50 0 empty empty empty 0 -16 0 24 #fcfcfc #000000 #000000;
#X obj 149 526 bng 16 250 50 0 empty empty empty 0 -16 0 24 #fcfcfc #000000 #000000;
#X floatatom 95 563 5 0 0 0 - - - 0;
#X obj 95 602 sel 0;
#X obj 127 632 mtof;
#X obj 127 750 line~;
#X msg 127 721 \\$1 \\$2;
#X obj 127 694 pack;
#X floatatom 127 668 5 0 0 0 - - - 0;
#X floatatom 171 606 5 0 0 1 ramp - - 0;
#X floatatom 458 475 5 0 0 1 AM - - 0;
#X obj 404 594 expr~ ($v1+1)/2;
#X obj 404 622 expr~ 1-$v1;
#X obj 404 649 *~;
#X floatatom 275 476 5 0 3 1 VolAM - - 0;
#X obj 493 721 *~;
#X obj 404 561 osc~;
#X obj 254 605 osc~ 440;
#X obj 275 452 line;
#X msg 95 243 10;
#X msg 133 244 20;
#X msg 170 243 30;
#X msg 210 243 40;
#X obj 275 315 random 3;
#X obj 275 339 sel 0 1 2;
#X obj 95 171 random 4;
#X obj 95 209 sel 0 1 2 3;
#X obj 95 111 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 95 140 metro 3000;
#X msg 238 513 1 200;
#X msg 315 415 0 1800;
#X obj 180 526 bng 16 250 50 0 empty empty empty 0 -16 0 24 #fcfcfc #000000 #000000;
#X floatatom 200 563 5 0 0 0 - - - 0;
#X obj 95 496 sel 0 1 2 3 4 5;
#X obj 95 466 mod 6;
#X obj 430 225 osc~;
#X obj 430 253 +~ 1;
#X obj 430 309 snapshot~;
#X obj 504 266 metro 100;
#X obj 506 231 tgl 20 0 empty empty empty 0 -16 0 24 #fcfcfc #000000 #000000 0 1;
#X obj 433 338 hsl 100 18 0 300 0 0 empty empty empty -2 -16 0 24 #fcfcfc #000000 #000000 0 1;
#X floatatom 430 367 5 0 0 0 - - - 0;
#X floatatom 404 537 5 0 0 0 - - - 0;
#X obj 404 513 +;
#X obj 430 279 *~ 150;
#X obj 20 136 loadbang;
#X msg 21 159 1;
#X obj 95 11 loadbang;
#X msg 95 51 1;
#X obj 507 170 loadbang;
#X msg 508 193 1;
#X floatatom 388 117 5 0 0 0 - - - 0;
#X floatatom 430 117 5 0 0 0 - - - 0;
#X floatatom 305 117 5 0 0 0 - - - 0;
#X floatatom 347 117 5 0 0 0 - - - 0;
#X obj 334 74 unpack f f f f f;
#X floatatom 589 117 5 0 0 0 - - - 0;
#X obj 206 40 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 206 88 t b b;
#X obj 341 225 +;
#X floatatom 341 249 5 0 0 0 - - - 0;
#X obj 206 136 * 10;
#X obj 206 112 random 4;
#X obj 206 64 metro 3000;
#X obj 254 691 tabread~ \\$0-shaping;
#N canvas 0 22 450 278 (subpatch) 0;
#X array \\$0-shaping 100 float 1;
#A 0 0.159999 0.159999 0.159999 0.159999 0.159999 0.159999 0.159999 0.159999 0.159999 0.15 0.14 0.14 0.13 0.12 0.110001 0.110001 0.110001 0.100001 0.100001 0.100001 0.100001 0.100001 0.0900012 0.0900012 0.0900012 0.0800015 0.060002 0.0500022 7.15256e-07 -0.0399983 -0.0599978 -0.0899971 -0.119996 -0.134996 -0.159995 -0.189995 -0.209994 -0.229994 -0.249993 -0.269993 -0.299992 -0.339991 -0.35999 -0.38999 -0.429989 -0.479987 -0.509987 -0.519986 -0.489987 -0.459988 -0.439988 -0.419989 -0.37999 -0.329991 -0.299992 -0.269993 -0.249993 -0.219994 -0.199994 -0.179995 -0.169995 -0.159995 -0.129996 -0.109997 -0.0799973 -0.0699975 -0.049998 -0.0399983 -0.0199988 7.15256e-07 0.0100005 0.0200002 0.03 0.03 0.03 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.0399997 0.03 0.03 0.0200002 0.0100005 0.0100005 7.15256e-07 -0.00999904 -0.00999904 -0.00999904;
#X coords 0 -1 100 1 200 200 1 0 0;
#X restore 676 38 graph;
#X obj 394 43 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 msg 275 367 0 2200;
#X msg 295 391 0 2000;
#X msg 770 305 1 -2 3596 30 0.5;
#X msg 770 329 -1 1 2789 80 0.6;
#X msg 770 353 2 -5 1839 30 0.4;
#X msg 770 377 2 -5 1220 60 0.5;
#X msg 770 401 -3 2 1615 10 0.5;
#X msg 770 425 4 -7 2380 100 0.5;
#X msg 770 449 -7 -2 3996 30 0.7;
#X msg 769 473 1 7 11086 390 0.6;
#X msg 771 498 1 -9 9 10 0.5;
#X msg 770 521 2 4 12644 1962 0.7;
#X msg 770 545 -1 -11 11200 120 0.7;
#X msg 770 569 -1 -1 -11111 90 0.6;
#X msg 770 593 -2 2 1 -10 0.5;
#X msg 770 617 -1 -2 -20 60 0.6;
#X msg 770 641 1 -2 100 10 0.4;
#X msg 770 665 1 7 11086 390 0.6;
#X obj 571 724 outlet~;
#X connect 0 0 68 0;
#X connect 1 0 2 0;
#X connect 2 0 77 0;
#X connect 3 0 101 0;
#X connect 4 0 5 0;
#X connect 5 0 9 0;
#X connect 6 0 4 0;
#X connect 7 0 4 0;
#X connect 8 0 7 0;
#X connect 9 0 10 0;
#X connect 9 0 11 0;
#X connect 10 0 9 1;
#X connect 11 0 47 0;
#X connect 12 0 15 0;
#X connect 13 0 36 0;
#X connect 15 0 16 0;
#X connect 16 1 17 0;
#X connect 17 0 21 0;
#X connect 18 0 30 0;
#X connect 19 0 18 0;
#X connect 20 0 19 0;
#X connect 21 0 20 0;
#X connect 22 0 20 1;
#X connect 23 0 56 1;
#X connect 24 0 25 0;
#X connect 25 0 26 0;
#X connect 26 0 28 1;
#X connect 27 0 26 1;
#X connect 28 0 3 0;
#X connect 29 0 24 0;
#X connect 30 0 1 0;
#X connect 31 0 27 0;
#X connect 32 0 8 0;
#X connect 33 0 8 0;
#X connect 34 0 8 0;
#X connect 35 0 8 0;
#X connect 36 0 37 0;
#X connect 37 0 83 0;
#X connect 37 1 84 0;
#X connect 37 2 43 0;
#X connect 38 0 39 0;
#X connect 39 0 32 0;
#X connect 39 1 33 0;
#X connect 39 2 34 0;
#X connect 39 3 35 0;
#X connect 40 0 41 0;
#X connect 41 0 38 0;
#X connect 42 0 31 0;
#X connect 43 0 31 0;
#X connect 44 0 45 0;
#X connect 44 0 42 0;
#X connect 45 0 16 0;
#X connect 46 0 12 0;
#X connect 46 1 13 0;
#X connect 46 2 14 0;
#X connect 46 5 44 0;
#X connect 47 0 46 0;
#X connect 48 0 49 0;
#X connect 49 0 57 0;
#X connect 50 0 53 0;
#X connect 51 0 50 0;
#X connect 52 0 51 0;
#X connect 53 0 54 0;
#X connect 54 0 56 0;
#X connect 55 0 29 0;
#X connect 56 0 55 0;
#X connect 57 0 50 0;
#X connect 58 0 59 0;
#X connect 59 0 6 0;
#X connect 60 0 61 0;
#X connect 60 0 70 0;
#X connect 61 0 40 0;
#X connect 62 0 63 0;
#X connect 63 0 52 0;
#X connect 64 0 56 1;
#X connect 64 0 72 0;
#X connect 65 0 48 0;
#X connect 66 0 15 0;
#X connect 67 0 45 0;
#X connect 68 0 66 0;
#X connect 68 1 67 0;
#X connect 68 2 64 0;
#X connect 68 3 65 0;
#X connect 68 4 69 0;
#X connect 69 0 3 1;
#X connect 70 0 76 0;
#X connect 71 0 75 0;
#X connect 71 1 64 0;
#X connect 72 0 73 0;
#X connect 73 0 56 1;
#X connect 74 0 72 1;
#X connect 75 0 74 0;
#X connect 76 0 71 0;
#X connect 77 0 28 0;
#X connect 79 0 68 0;
#X connect 81 0 82 0;
#X connect 82 0 85 0;
#X connect 82 1 86 0;
#X connect 82 2 87 0;
#X connect 82 3 88 0;
#X connect 82 4 89 0;
#X connect 82 5 90 0;
#X connect 82 6 91 0;
#X connect 82 7 92 0;
#X connect 82 8 94 0;
#X connect 82 9 95 0;
#X connect 82 10 96 0;
#X connect 82 11 97 0;
#X connect 82 12 98 0;
#X connect 82 13 99 0;
#X connect 82 14 100 0;
#X connect 82 15 93 0;
#X connect 83 0 31 0;
#X connect 84 0 31 0;
#X connect 85 0 80 0;
#X connect 86 0 80 0;
#X connect 87 0 80 0;
#X connect 88 0 80 0;
#X connect 89 0 80 0;
#X connect 90 0 80 0;
#X connect 91 0 80 0;
#X connect 92 0 80 0;
#X connect 93 0 80 0;
#X connect 94 0 80 0;
#X connect 95 0 80 0;
#X connect 96 0 80 0;
#X connect 97 0 80 0;
#X connect 98 0 80 0;
#X connect 99 0 80 0;
#X connect 100 0 80 0;
#X restore 40 300 pd synth;
#X obj 203 339 *~;
#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/cricket.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(Branch.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()
