Naive questions about textures and delegates

I have learned that delegates in Gamma are a way to somehow insert nodes right in a link from the outside, and therefore naively perceived it somehow like the opposite of the concept of input and output pins. So I tried to create a process that allows to insert texture effects with a delegate which does not work… already talked about it in the chat, but I still don’t get why.

Attached is an example patch that works with a delegate for a number and a texture and I expected both to work the same way. What did I get wrong?


Texture Delegates.vl (19.7 KB)

In your screenshot you see that the Blur node has a warning (orange border). What does it say?

As discussed in the chat, the correct solution is to use interfaces. Delegates cannot hold state, they are only a function and will recreate the entire node + texture on every call.

if you really want to use delegates, you have to wrap the texturefx in a class and then create an instance of that class, hold it in a pad and only put the update operation into the delegate.

in any case, you have to wrap each texturefx in a class.

if you don’t want to do that, there is also a region called Anonymous it is a class definition in place, with create and update. you use it in a similar way as a delegate and call the create of it on the create of the surrounding context and the update in a delegate, like you tried in the first attempt.

Okay thank you. I have now some solutions how to implement this, but I still don’t understand why it is working with the float in the other example. Does this only apply for textures? Just trying to gain some understanding here about the case, because that might mean I have understood some principles a bit wrong in general.

@joreg, it says: “The node is short-lived. Its state will be re-created (and destroyed) every time this patch executes.”

The the + node in your float example is stateless, it doesn’t (have to) “remember” anything between two frames. You input a value, the result gets calculated and is returned all in one frame.
With nodes that (can) hold state the output may be dependend on a previous frame.

Okay I see… the warning in the delegate is the same like in an operation region. Everytime I had a warning about some stateful nodes in operations, I’ve put them into a process node, because in these it works.

The confusing thing for me is just that I’ve learned delegates as a way to insert nodes into a patch from the outside, so when dealing with a process node I would have expected it to work like that. But well, now I know that they don’t work with stateful nodes, thank you.

Hi, in regards to what you were trying to achieve in your first post. This is called “Strategy Pattern”, @sebescudie made an example here :
https://discourse.vvvv.org/t/community-coding-design-patterns/17193/24

Also what you refer to as " naively perceived it somehow like the opposite of the concept of input and output pins" is called “Inversion Of Control”.

Anyway, here is how you could do something similar to what you were trying with Delegates but with Interface : TextureFXStrategy.vl (22.5 KB)

You wrap each TextureFX inside a class that implement a common interface. In my patch that interface is called ITextureFX and define one input and one output both of type Texture for one operation called Filter.

image

Every class that implement this interface MUST have the process Filter with one input and one output of type Texture. Think about an interface as a contract.

image

Now because both BlurFX and EdgeFX are of the same type (ITextureFX) and FXProcessor is using the operation Filter (common to all ITextureFX) you can swap BlurFX and EdgeFX easily.

Finally you have the FXProcessor node using the Filter operation.

Biggest advantage here is that FXProcessor doesn’t care about what specific you input, as long as it is of type ITextureFX it is the guarantee that it as the Filter operation, so you can create new TextureFX class, FXProcessor remains untouched.

FXProcessor could also be modified, the ITextureFX remains the same, so both part of the system aren’t tightly coupled and can grow separately. This would make sense later as the system gets bigger.

5 Likes

Gotcha! Thank you very much for this detailed information, learned a lot from it! Also really great to have learned through this example how to make a node with variable input pins, that can be changed using ctrl + plus/minus :)

One question on this one though - why did you decide to put the filter in the if region with the IsAssigned node? Just good practice or is there a specific reason?

It’s a NULL check because if there is no ITexture then the Filter will throw a not set to an instance of an object but it can be the case for the input texture too so you could have it for both.

It’s not specifically a good practice, sometimes you want to do something if the incoming data is NULL, let say replace the NULL texture by a default one. But sometimes you want to trigger an error because the incoming data should never be NULL and you must know that while developing.

Depends on the context.

2 Likes

For the sake of completeness, this thread on GitHub should be mentioned here (as it is related to the topic and also references the forum thread)

Thanks a lot to @tobyk for mentioning the example in his tutorials!

Hey all - after the recent Fuse workshop I feel like I have to bump this thread again. Sorry for being so annoying about it, but I can not get my head around that I can not use a Delegate to throw in stateful nodes into a graph from the outside. It is basically exactly what the Delegate region of Fuse is doing now, right?

grafik

In here the JuliaSDF is a stateful Process, which will throw again the error from the first post in this thread when used in a VL Delegate.

grafik

I know that the Delegate of Fuse is a custom region and that is in fact not a Delegate of VL… but it has basically the same behaviour and intention, right? Both regions are named the same and do the same thing conceptually. What am I not getting right here? Any comments, explanations or pointers to other discussions about this? Are there plans to implement a similar behaviour for stateful nodes in VL Delegates?

@chk I think it’s important to learn about the fact that Fuse is essentially a factory that builds the shader. The nodes that you see tell this factory at the end how to build this shader. I would even say it’s worth considering Fuse not from top to bottom, but from bottom to top.

Unlike the VVVV Runtime. This is happening to objects right now.

Once again. VVVV nodes are executing right now. Fuse nodes just tell the environment how to build it all at the end.

Let me emphasize, I’m not a developer. But I’ve been looking into what it is and how it works. And I think this is the best explanation for a person who is just starting to work with Fuse.

You could say that this is another pipeline. But in order not to introduce unnecessary entities, it is better to think about what is going on. Fuse nodes are executed as VVVV nodes, but their function is to assemble the shader. They form a graph that constructs the shader. If you place such a node in a stateful region, you will simply recreate the VVVV node, but not the shader assembly mechanism that the node implements.

@chk I made some kind of illustration
Tell me if you find it useful

illustration.vl (28.7 KB)

1 Like

I am not talking about the way Fuse works and the logic behind the library, but the ambiguity of the term “Delegate” and its basic language feature to insert nodes into an existing graph from the outside - with the only difference that in Fuse world it also works with stateful nodes. At least this is how I perceive it.

Delegate is a concept common to all programming.
Detach your understanding from the nodes.
It’s more about how the code is executed.

How exactly to use the delegate and what side effects it will have in the code also depends on you and your intentions. It is an entity and there will be no uncertainty if you understand why such an entity is introduced in Computer Science.

And most importantly. The ambiguity disappears if you realise that the delegate in VVVV is essentially executed as a function (it is not a function in pure form). And a delegate in Fuse is an instruction to instantiate such an entity as a result of assembly.

1 Like