Skip to content

Commit 4d09fc3

Browse files
committed
parse multi-array objects; includes additional array parsing tests
1 parent 19666ab commit 4d09fc3

3 files changed

Lines changed: 112 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Bugfixes:
1818

1919
* Skip empty values when restoring tables (#348)
2020
* Only append to table when first value is a float
21+
* Fix parsing multi-array objects (#373)
2122
* GUI send/receive config for objects in subpatches
2223
* DPF: also send BPM value to `__hv_dpf_bpm` when transport is not playing
2324
* Wwise: use latest Windows SDK available locally instead of hardcoded version

hvcc/interpreters/pd2hv/PdParser.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,25 @@ def graph_from_canvas(
239239
"""
240240
obj_array: Optional[HeavyObject] = None # an #A (table) object which is currently being parsed
241241

242+
def finalize_array(array: HeavyObject) -> None:
243+
declared_size = array.obj_dict["size"]
244+
values_size = len(array.obj_dict["values"])
245+
if declared_size != values_size:
246+
new_size = max(declared_size, values_size)
247+
array.add_warning(
248+
"Table \"{0}\" was declared as having {1} values, "
249+
"but {2} were supplied. It will be resized to {3} "
250+
"values (any unsupplied values will be zeroed).".format(
251+
array.obj_dict["name"],
252+
declared_size,
253+
values_size,
254+
new_size))
255+
array.obj_dict["size"] = new_size
256+
if new_size < declared_size:
257+
array.obj_dict["values"] = obj_args["values"][:new_size]
258+
else:
259+
array.obj_dict["values"].extend([0.0 for _ in range(new_size - declared_size)])
260+
242261
g = pd_graph_class(graph_args, pd_path, pos_x, pos_y)
243262

244263
msg_send: dict = {}
@@ -299,24 +318,8 @@ def graph_from_canvas(
299318
# are we restoring an array object?
300319
# do some final sanity checks
301320
if obj_array is not None:
302-
declared_size = obj_array.obj_dict["size"]
303-
values_size = len(obj_array.obj_dict["values"])
304-
if declared_size != values_size:
305-
new_size = max(declared_size, values_size)
306-
obj_array.add_warning(
307-
"Table \"{0}\" was declared as having {1} values, "
308-
"but {2} were supplied. It will be resized to {3} "
309-
"values (any unsupplied values will be zeroed).".format(
310-
obj_array.obj_dict["name"],
311-
declared_size,
312-
values_size,
313-
new_size))
314-
obj_array.obj_dict["size"] = new_size
315-
if new_size < declared_size:
316-
obj_array.obj_dict["values"] = obj_args["values"][:new_size]
317-
else:
318-
obj_array.obj_dict["values"].extend([0.0 for _ in
319-
range(new_size - declared_size)])
321+
finalize_array(obj_array)
322+
320323
obj_array = None # done parsing the array
321324

322325
# set the subpatch name
@@ -556,7 +559,10 @@ def graph_from_canvas(
556559
gui_recv[index] = obj_args[8]
557560

558561
elif line[1] == "array":
559-
assert obj_array is None, "#X array object is already being parsed."
562+
# are we still parsing a previous array? finalize it.
563+
if obj_array is not None:
564+
finalize_array(obj_array)
565+
560566
# array names can have dollar arguments in them.
561567
# ensure that they are resolved
562568
table_def = self.__resolve_object_args(

tests/unit/test_pdparser.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from pathlib import Path
2+
3+
from hvcc.interpreters.pd2hv.PdParser import PdParser
4+
5+
6+
def test_single_array_in_subpatch(tmp_path: Path):
7+
pd_path = tmp_path / "single_array_subpatch.pd"
8+
pd_path.write_text(
9+
"""#N canvas 827 239 734 565 12;
10+
#N canvas 0 0 450 250 (subpatch) 0;
11+
#X array array1 4 float 2;
12+
#A color 0;
13+
#A width 2;
14+
#X coords 0 1 100 -1 200 140 1;
15+
#X restore 308 106 graph;
16+
"""
17+
)
18+
19+
graph = PdParser().graph_from_file(pd_path)
20+
21+
assert not graph.get_notices().has_error
22+
23+
subpatch = graph.get_objects()[0]
24+
tables = [obj for obj in subpatch.get_objects() if obj.obj_type == "table"]
25+
26+
assert [table.obj_dict["name"] for table in tables] == ["array1"]
27+
28+
29+
def test_multiple_arrays_in_subpatch(tmp_path: Path):
30+
pd_path = tmp_path / "multi_array_subpatch.pd"
31+
pd_path.write_text(
32+
"""#N canvas 827 239 734 565 12;
33+
#N canvas 0 0 450 250 (subpatch) 0;
34+
#X array array1 100 float 2;
35+
#A color 0;
36+
#A width 2;
37+
#X array array2 100 float 0;
38+
#A color 0;
39+
#A width 1;
40+
#X coords 0 1 100 -1 200 140 1;
41+
#X restore 308 106 graph;
42+
"""
43+
)
44+
45+
graph = PdParser().graph_from_file(pd_path)
46+
47+
assert not graph.get_notices().has_error
48+
49+
subpatch = graph.get_objects()[0]
50+
tables = [obj for obj in subpatch.get_objects() if obj.obj_type == "table"]
51+
52+
assert [table.obj_dict["name"] for table in tables] == ["array1", "array2"]
53+
54+
55+
def test_subpatch_parses_multi_line_arrays(tmp_path: Path):
56+
pd_path = tmp_path / "multiline_arrays_subpatch.pd"
57+
pd_path.write_text(
58+
"""#N canvas 827 239 734 565 12;
59+
#N canvas 0 0 450 250 (subpatch) 0;
60+
#X array array1 4 float 2;
61+
#A 0 0 1;
62+
#A 2 2 3;
63+
#A color 0;
64+
#A width 2;
65+
#X array array2 4 float 0;
66+
#A 0 4 5;
67+
#A 2 6 7;
68+
#A color 0;
69+
#A width 1;
70+
#X coords 0 1 100 -1 200 140 1;
71+
#X restore 308 106 graph;
72+
"""
73+
)
74+
75+
graph = PdParser().graph_from_file(pd_path)
76+
77+
assert not graph.get_notices().has_error
78+
79+
subpatch = graph.get_objects()[0]
80+
tables = [obj for obj in subpatch.get_objects() if obj.obj_type == "table"]
81+
82+
assert [table.obj_dict["name"] for table in tables] == ["array1", "array2"]
83+
assert [table.obj_dict["values"] for table in tables] == [
84+
[0.0, 1.0, 2.0, 3.0],
85+
[4.0, 5.0, 6.0, 7.0],
86+
]

0 commit comments

Comments
 (0)