Consistency issues

During the preparations for the upcoming video tutorial series I collected a few issues regarding consistency. So here is a thread to collect them all.

Adaptive vs. Generic
I am a bit unclear which of these terms is now being used for what. The Gray Book is also delivering results for both terms. I started wondering about it when I came across this error message - I would have expected it to say “Unable to resolve generic node”

Pin Groups
When exposing pin groups (like Math nodes or a Switch), only the first input gets a label.


When hovering the camera icon of a frame.

Why is there a generic/adaptive node, when it is only accepting floats?

Skia Renderer
Should have Control Box activated by default and have a title input pin, to align with the window style of Stride windows.

Stride Cameras
IMO the default camera for a SceneTexture and the normal Camera (without Orbit) should look exactly like the default OrbitCamera on a SceneWindow

Stride Windows
They don’t save their positions.

Circle / Rectangle
Maybe their defaults and label namings should be the same like their equivalents in Skia? Also the circle datatype does not have an anchor input.

Output bang

Animation Nodes
Can we please also have generic Oscillator and Damper nodes in the standard node set, instead of the single value, 2D and 3D versions?


3D Text
Simple 3D text rendering in the standard node set would be awesome… maybe the 3D text models of @bjoern could go into vanilla Stride?

Spread Nodes
The naming of RemoveSliceAt is not in line with the other nodes. Also InsertSlice should have the index pin on the very right.

Mouse Wheel
Has to be used differently in Stride and Skia. At least the naming should be fixed here.

Everything about angles in 3D feels contra everything else in VL (LFO direction, angles in 2D). One day I will create a separate forum post about it.



Generic is a term that was introduced by others. It refers to the existence of type parameters. Because of those it’s also known as parametric polymorphism. VL is a .Net language and thus shares a lot in this regard with C# and F#. So we also stuck the established term “generic”.

Parametric Polymorphism / Generics is mainly about type safety inside your code/patch, not so much about actually doing something. It’s just convenient to know that in a collection are only items of a certain type. Less guessing and less cast operations as if everything in a collection would be of type object (as it was in the early days of .Net).

There is more that could be said about the Generics in .Net (like restricting a type parameter with constraints), but the main point will not change: Parametric Polymorphism / Generics is about abstracting over the final data type, but it’s not abstracting over what to do.

Subtype polymorphism
The idea of having an abstract data type (like an interface) + many different implementations of that abstract datatype does allow to abtract over “what to do”. And when used together with generics you can trick yourself into believing that this is a feature of Generics, but actually it’s just the subtyping / virtual call idea that does the trick. It’s unrelated to the Generics feature.


Adaptive is a term we came up with, which is abstracting over what to do per type.
And we wanted to abstract over what to do in a very performant way without paying one tick at runtime. We didn’t want to go via a virtual call at runtime, because we wanted to induce the per-type implementations pretty much everwhere (+, *, …). So subtyping wasn’t an option.

And as this was quite some years before the C# team started to tackle the topic, we were free to pick a term for that. We were inspired by Haskells type classes, picked certain ideas, rejected others and finally came up with the idea that you want to able to abstract over “what to do” on a per-node-basis.

The adaptive system in short:

  • an adaptive node serves as a definition, which outlines the signature of the node
  • implementations for those adaptive nodes get found automatically
  • a generic patch can make use of adaptive nodes, postponing the decision on which implementations to pick. Such patch now not only has type parameters, but also node parameters. However we managed to hide this complexity from the user.
  • The implementations (+ for Float32, * for Float32, …) get fed to the generic Damper when using the Damper with that particular type. The nodes get picked and somehow get wired up at compile-time with the algorithm inside the generic Damper patch resulting in a very performant patch that works for the particular data type.

In short: Adaptive refers for what to do per type. Generic refers to the existence of a type parameter.

Another example on how to use the terms:

  • Lerp [Adaptive] defines the idea of lerping. It uses one type parameter. Thus it can also be refered to something “generic”. However we like to just call it the adaptive node.
  • All the implementations are typically not generic anymore. As they focus on different concrete types.
  • However, in this specific example, you can imagine to offer an implementation for all types that don’t come with a handcrafted solution: A generic Lerp operation, that makes use of adaptive +, * (Scale) and -, like so:
    Let’s call this a generic implementation of an adaptive node.

Thanks for the detailed answer! Maybe it should be included it in the Gray Book in the Looking at Things section? Also there is a blank page about Generics in the Reference.

1 Like

@chk thanks for all those. we’ll be editing your original post and add a ✅ on things that have been tackled.


Thank you, especially for the bang output!

I noticed that on nodes with pin groups no input gets a label now (tested with +, - and Switch). The MultiFlipFlop does though.