ossia: deduce a port's unit from the arity of its value - #200
Merged
Merged
Conversation
xy_value, xyz_value and xyzw_value nest - a value with x, y and z also has x and y - so the single xy_parameter overload matched all three and every three- or four-component port was declared to be in position.cart2D. That hit TinyObj's Position / Rotation / Scale, Point Tracker 3D's anchor and SolvePnP's object points, among others; nothing acted on the unit at the time, so it went unnoticed. Each overload now excludes the wider ones, the way the TouchDesigner binding picks between appendXY / appendXYZ / appendXYZW: xy stays cart2D, xyz becomes cart3D, and xyzw gets its arity but no unit - the only four-component unit in ossia is orientation.axis, which would claim a meaning a plain xyzw control does not have. Same nesting for colours: rgba_value satisfies rgb_value, so a three-component colour was declared rgba. halp_meta(unit, "...") went through parse_dataspace, which knows only the eight dataspace names, so "midipitch", "distance.mm", "color.rgb" and everything else a process might actually want to name resolved to an empty unit. parse_pretty_unit accepts all of them, and answers with a concrete unit rather than a dataspace with nothing picked inside it. A name that does not parse now leaves the port alone rather than wiping the value type deduced just above it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197hSihNtB1bPw9WDUV3SR2
jcelerier
force-pushed
the
ossia-port-unit-arity
branch
from
September 5, 2026 10:07
1fcfe25 to
ccd5dc3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The concepts behind the ossia binding's unit deduction nest: a value with
x, y, zalso hasx, y, and one withr, g, b, aalso hasr, g, b. Therewas a single
xy_parameteroverload and a singlergb_parameterone, so everythree- and four-component port was declared to be in
position.cart2D, and everycolour in
color.rgba.Each overload now excludes the wider ones, which is how the TouchDesigner binding
already chooses between
appendXY/appendXYZ/appendXYZW:.x .ycartesian_2d_u— unchanged.x .y .zcartesian_3d_u.x .y .z .wval_type::VEC4F.r .g .brgb_u.r .g .b .argba_u— unchangedxyzwdeliberately gets no unit: the only four-component unit in ossia isorientation.axis, and claiming axis-angle for a generic vec4 control would beexactly the kind of wrong inference this fixes. The arity is what the conversion
machinery needs there.
Affected in score: TinyObj's
Position/Rotation/Scale, Point Tracker 3D'sAnchor, and in the addons SolvePnP's object points. Nothing in tree declares athree-component colour today, so the
rgb_ubranch is new ground.halp_meta(unit, "...")That declaration went through
ossia::parse_dataspace, which knows only the eightdataspace names — so
"midipitch","distance.mm","color.rgb"and everythingelse a process might actually want to name resolved to an empty unit. It now goes
through
parse_pretty_unit, which accepts all of those and answers with a concreteunit rather than a dataspace with nothing picked inside it. A name that does not
parse leaves the port alone instead of wiping the value type deduced just above.
The only in-tree user is score's Pitch To Value (
unit, "midipitch"), whose outletconsequently gains a real unit (
time.midinote) where it previously had none.The two duplicated blocks in
setup_inlets/setup_outletsare folded into onesetup_value_port::setup_port<Field>(), which is also what the test drives.Testing
Covered by a new test on the score side (
Avnd_port_unit_Test, 16 assertions),since that is where the binding is instantiated: arity for xy / xyz / xyzw and
rgb / rgba, a declared unit resolving, a declared unit winning over the shape of
the value, and a bare dataspace name giving its neutral unit. Reverting the
overload constraints fails 4 of its assertions; reverting the
parse_pretty_unitchange fails 3 more.
A full score build is clean — every avnd process in the tree recompiles against
the new overloads.
Ordering
Part of a three-repo change. This one stands alone; ossia/libossia and ossia/score
carry the rest, and the score PR needs all three.
🤖 Generated with Claude Code
https://claude.ai/code/session_0197hSihNtB1bPw9WDUV3SR2