Welcome to WSL!

Make yourself at home, but before posting, please may I ask you to read the following topics.


Posting 101
Server space, screenshots, and you

Thank you!

PS. please pretty please:


Image

Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#1

Post by tida » Wed Aug 12, 2020 8:21 am

I try to write into a slider control using "function Process" by means of SetSource. In this case the node starts to to flicker even if I do not hit play, which is an indication for me, that it doesn't stop to process. Furthermore, I see that a render cache cannot be developed as it seems to clear off immediately. (I registered the fuse as CT_SourceTool)

Is there a trick to prevent that steady processing....
by tida » Tue Aug 25, 2020 4:13 am
Now I get the CT_SourceTool based fuse running as wanted with ability to use multiple node copies.
The only drawback is, that you need to Disc Cache pre-render in Fusion Page whereas you need to enable Enable Cache and Lock Cache. Otherwise you loose connection to Simple Expression where you refer to Function f latest in the Edit Page.

Note: As soon as you want to change something, you need to "delete cache" and disable Enable Cache and Lock Cache otherwise you wonder, that nothing is happening.

Important is, that you need to use for the control settings INP_Passive = true. Furthermore you can use INP_Active = true which seems to be default value. Don't use INP_Active = false which would give the problem as soon as you want to use multiple SetSource controls.

Below you can also see, that you need to break a loop in the process by requesting time variables. timeOld should be at least be public and not local as you need the value when the next process occurs.

Code: Select all

FuRegisterClass("SourceToolExample", CT_SourceTool, {
...
timeOld = 0 --public variable

function Create()
...
varF = self:AddInput("Function f", "f", {
LINKID_DataType = "Number",
INPID_InputControl = "ScrewControl",
INP_Integer = false,
INP_Default = 0,
INP_MinScale = -1,
INP_MaxScale = 1,
INP_Active = true,
INP_Passive = true,
})
...
end

function Process(req)
local timeNew = self.Comp.CurrentTime
...
if math.abs(timeNew-timeOld)>0 then varF:SetSource(Number(fx),0) end
...
OutImage:Set(req, img)
timeOld = self.Comp.CurrentTime
end
Go to full post

User avatar
TheBloke
Fusioneer
Posts: 139
Joined: Wed Jun 17, 2020 6:02 am
Answers: 1
Been thanked: 22 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#2

Post by TheBloke » Wed Aug 12, 2020 8:30 am

This is exactly the issue I had in my new Fuse. See my description of the problem, and @Chad 's suggested fix in this thread:
viewtopic.php?f=6&t=4309

You are right that it's processing the script over and over again, which seems to happen when SetSource is called on an Input. If you add a print("Hello") statement into your Process(req) function, you will see it gets repeated over and over in the Console.

In my case I tried Chad's suggested solution - which was to add INP_Passive = true to the Input I was modifying with SetSource(), and it did solve the problem. But it added a new problem, which is the slider stopped updating after a couple of manual playhead movements.

I have a feeling these might be Fusion bugs.

What is this slider for? If you update an Input with SetSource, the user cannot also change that control, so if its purpose is just to communicate a value to the user, could you use a LabelControl instead?

Or maybe you could add an Output instead of an Input? Then the user could Connect To it. That's what I'm doing in my Modifier Fuse.

What does your Fuse do exactly? Maybe if you describe the purpose and show some code, someone can make a suggestion for an alternative.

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#3

Post by tida » Wed Aug 12, 2020 8:43 am

I would like to develop an Easing Fuse. This should use this https://www.desmos.com/calculator/cmuzqkzf6g function, which I developed and is very flexible. The user should use the result by Publishing the Control where I would like to set the result, and it should be used by Expressions as connection to another node.

All that works fast, but I see now the trouble, that it doesn't cache.

The other trick is, that I already can show the graph online in the viewer.

User avatar
TheBloke
Fusioneer
Posts: 139
Joined: Wed Jun 17, 2020 6:02 am
Answers: 1
Been thanked: 22 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#4

Post by TheBloke » Wed Aug 12, 2020 8:50 am

Here is an example modifier Fuse that demonstrates the issue. Adding this Modifier to a control will generate a random value for the control on which it is placed, and another random value in the slider control named "One" in the Modifier controls.

As soon as you place this modifier on a control, you will likely see the slider generating new values over and over, even with no playback occurring. And if you have the Console open, you will see a flood of messages, indicating it's processing over and over on the same frame. This can be stopped by manually moving playback to another frame, but it will likely occur again after stopping playback.

The same issue occurs in both Fusion Studio 16.2.4, and Fusion 9.0.2. I don't know if it's a bug or an expected result of the code.

Chad's suggestion, setting INP_Active = false and INP_Passive = true does fix the problem fully in this example modifier, in both Fusion 9 and 16. So @tida this is the solution you should try first.

EDIT: I just discovered that while setting INP_Active = false and Passive=true do seem to fix the issue initially, it will re-occur if you Publish the Input slider. So maybe Publish undoes making the control passive?

However I think that adding Active = false and Passive = true seems to cause a different issue to occur: the sliders no longer update when the frame changes. This is what happened when I tried that change on my real Fuse, and it is happening sometimes - though not always, for reasons I can't yet figure out - in this simple example Fuse.
Code: [Select all] [Expand/Collapse] [Download] (TestModInputSetSource.fuse)
  1. FuRegisterClass("TestModInputSetSource", CT_Modifier, {
  2.     REGS_Category       = "Fuses",
  3.     REGS_OpDescription  = "Test modifier that uses SetSource on an Input",
  4.     REGS_Name           = "TestModInputSetSource",
  5.     REGID_DataType      = "Number",
  6.     REGID_InputDataType = "Number",
  7.     --REG_TimeVariant     = true,
  8.     --REGB_Temporal       = true,
  9.     REG_Fuse_NoEdit     = false,
  10.     REG_Fuse_NoReload   = false,
  11.     REG_Version         = 100,
  12.     })
  13.    
  14. function Create()
  15.     local inDef = {
  16.         LINKID_DataType = "Number",
  17.         INPID_InputControl = "SliderControl",
  18.         INP_Active = false,
  19.         INP_Passive = true,
  20.         INP_Default = 0
  21.         }
  22.  
  23.     InOne = self:AddInput("One", "InputOne", inDef)
  24.  
  25.     OutValue = self:AddOutput("Output", "Output", {
  26.         LINKID_DataType = "Number",
  27.         LINK_Main = 1,
  28.         })  
  29. end
  30.  
  31. function Process(req)
  32.     local time = req.Time
  33.     print("Starting Process at frame: " .. time)
  34.  
  35.     InOne:SetSource(Number(math.random(0,1000)), time)
  36.  
  37.     OutValue:Set(req, Number(math.random(0,1000)))
  38. end

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#5

Post by tida » Wed Aug 12, 2020 9:37 am

Again, you saved a lot of my time. If I link from another Node via Expressions it works like a charm and does cache. As soon as I publish the control the node starts to suck with processing in a loop. Unpublishing immediately stops the loop. If I publish the control of the other node, where I have placed a connection via Expression, it's not starting to loop.

Thanks, thanks, thanks again...
Last edited by tida on Wed Aug 12, 2020 9:53 am, edited 2 times in total.

User avatar
TheBloke
Fusioneer
Posts: 139
Joined: Wed Jun 17, 2020 6:02 am
Answers: 1
Been thanked: 22 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#6

Post by TheBloke » Wed Aug 12, 2020 9:41 am

OK, great to hear you have something working for you. I don't know why this issue/bug occurs, and maybe someone more knowledgeable can help us with a solution. But if you can just avoid using SetSource, then you don't need to worry about it.

Your Fuse sounds really excellent! When I was learning After Effects I installed several plugins that provided loads of ways to do fancy easing controls, so it'd be really awesome to have something new for this in Fusion as well.

Will you be uploading it here when it's done?

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#7

Post by tida » Wed Aug 12, 2020 10:02 am

It's the first time I try to program fuse. In general, I would like to leave it for the public and I assume this is one of the best places.

Now I realize, that the above method seems to crash my computer. I know that I could run it with expressions, but this would result in a combination of a fuse and a settings file. I believe that there is no method to activate the controls-expression input and just add the expression programmatically.

User avatar
TheBloke
Fusioneer
Posts: 139
Joined: Wed Jun 17, 2020 6:02 am
Answers: 1
Been thanked: 22 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#8

Post by TheBloke » Wed Aug 12, 2020 1:54 pm

OK @tida I think I've solved it. Here is a very basic modifier Fuse which has an Input slider which gets updated on every frame, and also provides an Output number which is updated on every frame (as it's a modifier, it outputs Number, not Image).

It does not loop endlessly, the slider gets updated correctly, and you can Publish that slider with no problems.
Code: [Select all] [Expand/Collapse] [Download] (TestModInputSetSourceTimeVariant.lua)
  1. FuRegisterClass("TestModInputSetSourceTimeVariant", CT_Modifier, {
  2.     REGS_Category       = "Fuses",
  3.     REGS_OpDescription  = "Test modifier that uses SetSource on an Input",
  4.     REGS_Name           = "TestModInputSetSourceTimeVariant",
  5.     REGID_DataType      = "Number",
  6.     REGID_InputDataType = "Number",
  7.     REG_TimeVariant     = true,
  8.     REG_Fuse_NoEdit     = false,
  9.     REG_Fuse_NoReload   = false,
  10.     REG_Version         = 100,
  11.     })
  12.    
  13. function Create()
  14.     local inDef = {
  15.         LINKID_DataType = "Number",
  16.         INPID_InputControl = "SliderControl",
  17.         INP_Default = 0
  18.         }
  19.  
  20.     InOne = self:AddInput("One", "InputOne", inDef)
  21.  
  22.     OutValue = self:AddOutput("Output", "Output", {
  23.         LINKID_DataType = "Number",
  24.         LINK_Main = 1,
  25.         })  
  26. end
  27.  
  28. function PreCalcProcess(req)
  29.     local time = req.Time
  30.     OutValue:Set(req, Number(time))
  31. end
  32.  
  33. function Process(req)
  34.     local time = req.Time
  35.     print("Process() at frame: " .. time)
  36.     InOne:SetSource(Number(time), time)
  37.     OutValue:Set(req, Number(time))
  38. end
OK, so what is different?

1. From my testing I found that I must set REG_TimeVariant = true, otherwise it is not guaranteed my modifier is executed on every frame.

From the VFXPedia documentation:
VFXPedia Fuse Documentation wrote:REG_TimeVariant

(default FALSE) This tool will produce different results when time changes, even if the inputs don't.
So this makes sense that I would need this set on my modifier Fuse, because I do not have a real 'input' (like an image), but I still want the Fuse to run always on every frame.

2. The key to the endless-loop problem: The output value must be set up also in the PreCalcProcess(req). If it is only set in Process(req), the loop issue is caused. Again, I still don't fully understand why, because it is the output that must be set in PreCalcProcess, not the Input that we are changing with SetSource. But this is definitely the cause!

For more information on PreCalcProcess, and Fuse processing in general, I recommend you read these VFXPedia pages:
Fuse: Process
Fuse: PreCalc and Process

Note that there is a FuRegisterClass attribute called REG_NoPreCalcProcess which says "Don't run PreCalcProcess, my Process() will do everything". But for some reason I can't get this to help solve the endless loop. I may well be doing it wrong though, I'd need to experiment more with that.

So for now I will just use a separate PreCalcProcess(req) in which I will set my OutValue. Therefore I am in fact setting my OutValue twice, but I don't think this really matters.

I am now going to try to apply this to my real Fuse, and will report back if I learn anything more. Edited to add: I've implemented this in my modifier fuse and it's working well.

I hope this helps solve your problem also!

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#9

Post by tida » Thu Aug 13, 2020 7:06 am

@TheBloke, thanks for the great explanation. I'll try it this evening when I'm back home. It's funny as before I read your comment I was trying to figure out what PreCalcProcess would do from the VFXPedia Page. But I couldn't imagine that this would help for this issue. Yesterday I tried to do something via NotifyChanged in combination with INP_DoNotifyChanged and SetSource. But as soon as I started to open the expression input of the control to place time expression, the loop started again.

User avatar
Midgardsormr
Fusionator
Posts: 1908
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 18
Location: Los Angeles, CA, USA
Been thanked: 143 times
Contact:

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#10

Post by Midgardsormr » Thu Aug 13, 2020 11:30 am

A bit of a guess, as I haven't taken the time to test:

If you try to update the value of an Input from Process(), you'll generate a new request, which forces Process() to run again. That's the source of the loop. The PreCalc Process is, I believe, a part of the request generation. So it doesn't invalidate the request or prompt a new one upon changing the input because the request hasn't been completely resolved until the PreCalc is complete.

User avatar
TheBloke
Fusioneer
Posts: 139
Joined: Wed Jun 17, 2020 6:02 am
Answers: 1
Been thanked: 22 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#11

Post by TheBloke » Thu Aug 13, 2020 3:02 pm

Midgardsormr wrote:
Thu Aug 13, 2020 11:30 am
If you try to update the value of an Input from Process(), you'll generate a new request, which forces Process() to run again. That's the source of the loop.
Yeah I think that must be the case. I had been thinking of those sliders more as GUI elements or parameters, but have since realised that in Fusion they're effectively the same as an Image dragged to the input of a node. So it makes total sense that another request is generated whenever their value changes.

Though I am still a little confused by the difference between normal playback and manual playhead seeking; I've not got my head around why Fusion does not call PreCalcProcess after a manual playhead movement when it always does so on normal playback. When I manually click around frames I expect every tool to show me the same image or output it would in a full render (Proxy settings aside), so I've not figured out why this requires a PreCalc during a playback/render, but not on manual playhead movement.

I have been working exclusively on modifiers thus far, so I'll have to test this in more detail on a tool Fuse. Maybe that will make things a bit clearer.
Midgardsormr wrote:
Thu Aug 13, 2020 11:30 am
The PreCalc Process is, I believe, a part of the request generation. So it doesn't invalidate the request or prompt a new one upon changing the input because the request hasn't been completely resolved until the PreCalc is complete.
That makes sense, but I still don't fully understand what's happening here, because the problem is fixed by setting the Output in the PreCalc. The method of updating the Input doesn't change at all - at least not in the Fuse code.

So this works, with no endless loop:
Code: [Select all] [Expand/Collapse] [Download] (ThisWorks.lua)
  1. function PreCalcProcess(req)
  2.     OutNumber:Set(req, Number(1))
  3. end
  4.  
  5. function Process(req)
  6.     OutNumber:Set(req, Number(1))
  7.     InSlider:SetSource(Number(1), req.Time)
  8. end
But this causes an endless loop when the modifier is first added, and when playback is stopped (but not on manual playhead movement, which, at least in a modifier, doesn't call PreCalcProcess):
Code: [Select all] [Expand/Collapse] [Download] (EndlessLoop.lua)
  1. --function PreCalcProcess(req)
  2. --    OutNumber:Set(req, Number(1))
  3. --end
  4.  
  5. function Process(req)
  6.     OutNumber:Set(req, Number(1))
  7.     InSlider:SetSource(Number(1), req.Time)
  8. end
In both cases, the Input is only set in Process. It's only the handling of the Output that differs, in that it's now set both in the PreCalc and in the Process.

VFXPedia talks about Number outputs being set in PreCalc, saying:
VFXPedia wrote: [You need PreCalcProcess if] you have more than one output (another image or - more common - an auxiliary number or point output that other tools can connect to).

This [PreCalcProcess function] returns values for two additional outputs. These have to be calculated correctly (other tools might depend on them), while the output image is just a dummy object.
So I was definitely in error in not creating a PreCalcProcess to handle my additional number outputs. I'm just a little confused as why it only showed as a problem when I was also updating an Input via SetSource(). That said I'm sure there are many subtleties involved here, and ultimately it doesn't matter much now I know how to do it the right way.

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#12

Post by tida » Thu Aug 13, 2020 3:38 pm

I think I have good news. The fuse seems to be stable, it doesn't loop anymore and it caches. Following trick made it

a) set

Code: Select all

INP_Active = false and INP_Passive = true
for all control inputs, which should be changed from the program.
b) place an additional control, i called it varFrame as follows

Code: Select all

varFrame = self:AddInput("frame", "frame", {
		  LINKID_DataType = "Number",
		  INPID_InputControl = "SliderControl",
		  INP_Integer = false,
		  INP_Default = 0,
		  INP_MinScale = -1,
		  INP_MaxScale = 1,		
		  INP_Active = false,
          INP_Passive = true,
		})

c) Now you need a request, whether SetSource should be executed as follows

Code: Select all

function Process(req) 
	local calc = 0  -- indicator, whether SetSource should be executed
	local frame = varFrame:GetValue(req).Value	
	if (frame ~= req.Time) then 
		calc = 1 
		varFrame:SetSource(Number(req.Time),0)
	end
d) for all the other SetSource codes you have to do the same like:

Code: Select all

if (calc == 1) then 
		varTRate:SetSource(Number(req.Time/self.Comp.GlobalEnd),0)	
end
Last edited by tida on Thu Aug 13, 2020 3:53 pm, edited 1 time in total.

User avatar
Midgardsormr
Fusionator
Posts: 1908
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 18
Location: Los Angeles, CA, USA
Been thanked: 143 times
Contact:

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#13

Post by Midgardsormr » Thu Aug 13, 2020 3:44 pm

Oh... Well, that's what I get for commenting without actually examining the code. :D

User avatar
tida
Posts: 31
Joined: Mon Jan 27, 2020 4:37 am
Answers: 1
Real name: none
Been thanked: 6 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#14

Post by tida » Thu Aug 13, 2020 4:02 pm

Yes thanks, to all of you. @Midgardsormr, your hint made me rethink and limitation stopped the loop. Caching was still the problem. But the INP_Active = false and INP_Passive = true trick form @TheBloke made the rest...

You don't need anymore the PreCalcProcess event. It works with CT_SourceTool/OutImage :-)

User avatar
TheBloke
Fusioneer
Posts: 139
Joined: Wed Jun 17, 2020 6:02 am
Answers: 1
Been thanked: 22 times

Re: Fuses: Does clean cache using inVar:SetSource(Number(inVar),0,0)

#15

Post by TheBloke » Fri Aug 14, 2020 12:23 am

Hey @tida, glad you've got something working OK for you.

I tried INP_Passive and INP_Active and it did solve the endless loop / no caching, however it created two extra problems:

1. The slider would stop updating after a couple of manual playhead movements
2. The endless loop would come back if the user did a Publish on the slider

Is your code not experiencing those issues?