
françois leroy
Enthusiast
françois leroy
Enthusiast
Activity
Mar 22, 2017
09:43 PM
Hi Ilya and Shachar, I did use AEGP_RegisterIdleHook in an effect plugin and it worked. I don't remember exactly, but I think you just need to replace A_Err by PF_Err... You'll have to try. Cheers, François
... View more
Mar 21, 2017
07:28 PM
Hi Ilya, I don't think you should dispose of an effect you just deleted. Try removing your last line, see if it's better. Cheers, François
... View more
Mar 20, 2017
06:19 PM
See, I am totally dumb with SmartFX! 😉
... View more
Mar 20, 2017
12:13 AM
By caching data, I mean storing data in sequence_data (most likely), and using this data later without re-checking. But as you say, if you're not sure of what it means, you probably don't do it! 😉 If the plugin reacts differently with smart/non-smart behaviour, I would say it's the way you checkout the input in the smart process that causes the issue... May be the extent_hint? Does your plugin make use of it? You can check the Global outFlags to make sure... But I'm totally dumb with Smart FX, so I hope anyone else can help better... Cheers, François
... View more
Mar 14, 2017
01:50 AM
"I think what you're saying is that if I get the layerToWorld Xform and modify it I would only be modifying it locally and modifying it won't "Set" it back so that my modification effects the transformation of the layer." Exactly. Internally, you can do whatever you want (the matrix is just numbers...) "Therefore if I wanted to do what I said I wanted to do, I would create some parameters (are these called streams?) and output my values in there according to my code." It won't work, as parameters are just input, not output. Modifying parameters is the same than modifying position or whatsoever. You're right, a parameter is a stream, just like position or rotation, and streams cannot be modified at render time... The only thing it can modify is the ouput. "copy the input to the output in the layer effect so that it has no effect (there's no way to skip this step?)" It's been discussed here: Re: Pass Through Effect "how to fill a panel in a aegp plugin with some interactive content" I have no idea! But there must be someone out there knowing 🙂 Cheers, François
... View more
Mar 14, 2017
01:13 AM
"So what is really happening here? Is the transform layer effect simply accessing and modifying the position values internally (but not showing those changes in the layer's position properties? And then the motion happens during compositing? Or is the transform layer effect actually re-rendering the pixels in the new positions and scale, and then growing the layer bounds so that it can be returned to screen without being cropped? I'm starting to think the 2nd. But I wish there was a way to do the first." Sorry, but you're thinking right, this is second solution, and no real way to do the first. I think I see what you're trying to do, but you can't do it the way you describe it. A Layer Effect cannot modify geometry, only output. But to exactly answer your question, a Layer Effect can do 'nothing' by just copying input to output. If you do something like the transform effect, you'll still hit issues. For example, if your layer is scaled 0, it won't be rendered at all, so your effect won't work. If you want to modify the geometry of the layers into the composition, AEGP (or scripts) is the way to go. But it means going through keyframing and/or expressions. Now, for the pickwhip stuff, you can add all the parameters you want in your effect. They don't affect the render. You can modify the ouput based on these parameters, but only you decide to do it. So if you want your effect to have 100 point parameters that you can pickwhip, and still do 'nothing', go ahead! "wait.. so I think what you're saying is that I can read the GetLayerToWorldXform but not modify it." When you get the matrix, you can modify it, no worry. What I meant is it won't modify the actual geometry of the layer itself (its position, scale, rotation), only its output. If you give a bit more details on what you want to achieve, there are probably some workarounds to find... Cheers, François
... View more
Mar 13, 2017
09:24 PM
Hi, these are actually very good questions! So, just to try to make it clear (and the SDK is not always clear...): a 'world' usually refers to a PF_EffectWorld, roughly the pixels of your layer. This world is used by Effect layers. The effect layer's input and output are both worlds. It is different from the '3D' world, meaning the 3D space of your composition, in 3D math or OpenGL. This is no 3D geometry, just a flat bunch of pixels... I think if you really get the difference between a Layer Effect and an AEGP, it'll answer most of your questions 🙂 You can read the descriptions of Layer Effect and AEGP in the SDK. And here's a quick explanation, probably uncomplete, but may be more instinctive: Layer Effect: an effect affecting the output of your layer. Your Checkerboard example is a good example. You're right, it doesn't depend on the layer's geometry inside the composition. AEGP: if you already know 'scripts', you can see AEGPs like more powerfull scripts. If not, well, you can see AEGPs like a way to modify your project like a user would do. An AEGP can add/remove keyframes, change layers order, modify composition settings, add/delete effects, layers, etc... Almost anything except modifying the output of layers. An AEGP can for example move a layer in the 3D space of your composition by modifying its position parameter. Now the tricky part: 3D effects! You mention OpenGL and 3D maths, so I guess you'll end up trying to write a 3D plugin (like a particles effect, may be? let's take this example) This effect will be a Layer Effect plugin, cos' it'll render something on your layer, i.e. particles. BUT! If you want this Layer Effect to depend on composition's 3D geometry and camera (via matrices) you'll need to get infos like an AEGP would do. GetLayerToWorldXform will provide you this kind of info. And in this case, the 'world' is actually a world like in OpenGL and 3D maths... So, what's the difference between this Layer Effect and an AEGP? The AEGP can actually modify the composition's geometry, the Layer Effect can only modify the layer's output. If you take Trapcode Particular, you usually apply it to a 2D solid. It gets the composition's geometry, render particles in this space, but never modifies the composition's geometry. Your solid is still a 'flat' 2D solid, and its position, rotation... don't change. Sorry, my answer is probably a bit messy, and I hope it's not more confusing 😉 Cheers, François
... View more
Mar 12, 2017
05:32 AM
Thanks for the screencast. I don't think PF_Cmd_SEQUENCE_RESETUP is the way to go. Cos' it's not the adjustment layer that changes, but the layer under it... It must be a problem with your input. You could check if params[0] have changed with PF_GetCurrentState and PF_AreStatesIdentical (both in ParamsUtils) It means you'll have to store this state somewhere (most likely in SequenceData). But it's strange, cos' if the render is triggered, it means AE does know that something changed... Do you 'manually' cache data in your plugin? Cheers, François
... View more
Mar 12, 2017
05:22 AM
Well, there is a way, close to what the stroke effect does: _create a PF_EffectWorld the size of your line width. This will be your brush. _fill it with a circle of your color. Here you can make the circle slightly blurry (lets say 1 pixel or 2). _copy your brush along your path with WorldTransform. Tada! You have an antialiased thickline! Not the most efficient in terms of memory, and transparency can be an issue, but it's easy to do. 🙂 Cheers, François
... View more
Mar 09, 2017
02:24 AM
So the render is triggered... Does it rely on some layer parameters? In this case, make sure you check it out at the right current_time, time_scale and time_step. Or does it rely on the params[0]->u.ld? In this case, I don't see why it would not update... You 'll have to tell us more about the effect 😉 Cheers, François
... View more
Mar 07, 2017
12:04 AM
Hi James, when you say it doesn't re-render, do you mean it renders the same result as before or do you mean it doesn't receive the render command at all? Cheers, François
... View more
Mar 06, 2017
10:05 PM
1 Upvote
If you're using Penner's easing (or bezier, or actually a lot of algorithms!), you probably have a 't' variable, varying from 0 to 1 along the curve, right? Instead of drawing pixels one by one, you can draw a small segment with wu's algorithm each time. Here's a pseudo code for a curve split in 100: A_FloatPoint previousPoint = easing( easing_parameter1, easing_parameter2, 0);// startPoint of the curve, i.e at t == 0 A_FloatPoint newPoint; for (float tf = 1; tf <= 100; tf++) { newPoint = easing( easing_parameter1, easing_parameter2, tf * myCurveLength / 100);//get newPosition along the curve drawSmoothLine( previousPoint, newPoint);//draw segment from previous point to new point with wu's algorithm previousPoint = newPoint;//update previous point with new point's position, so you don't need to re-compute it } Hope it helps! Cheers, François
... View more
Mar 06, 2017
04:32 AM
1 Upvote
Well, any card can run it, as long as you write your own shader. Cos' it doesn't rely on any specific function, it is very basic Glsl. I use a slightly modified version of this one: (Tested) Fast Approximate Anti-Aliasing (FXAA) Demo (GLSL) – Page 3 – Geeks3D You can start from there if you want to implement it for an AE iteration function. Now about curves: curves can be seen as straight segments put together! So you can split your curves in pieces and write them already antialiased. 🙂 Cheers, François
... View more
Mar 05, 2017
02:33 AM
1 Upvote
Hi James! 'Super sampling' (writing at higher scale then reducing) gives good results, but you'll have to handle large EffectWorlds. It used to be a bummer, but nowadays, machines can deal with it, so it can be an easy way to go. I don't know of any built in function for FXAA. I'm using OpenGL, so I just added a FXAA shader... But you could adapt it to an iteration function pretty easily. You'll have to try to be sure, but I think Super Sampling can be faster than iteration. Otherwise, if you're only drawing lines, the easiest is to draw antialiased lines directly! You can check this link https://en.wikipedia.org/wiki/Xiaolin_Wu Hope it helps! François
... View more
Mar 01, 2017
10:20 PM
1 Upvote
Hi Ilya, as far as I know, there is no 'general' way of doing it (or if there is one, I'm interested too!), but there are several work arounds: The most common is to create a light, and attach it to the layer you want your plugin to depend on. Then if you set the PF_OutFlag2_I_USE_3D_LIGHTS flag, you'll receive a call everytime this light changes. The good point is you can use this light to react to almost anything in the comp (by setting some expressions, for example linking some parameter to your camera's focus distance). The bad point is you'll end up with a light in your comp when you may want to avoid it... Another way to check for changes is to check for IdleHook. You'll receive a call everytime AE does 'nothing', i.e. right after anything happens. When receiving this call, you can check for any change in the composition that occured since last time you've checked... So, to make it short, the 'Light' way is pretty easy but inelegant, the 'Idle' way is more complicated to implement, but invisible to user. Hope it helps! Cheers, François
... View more
Feb 19, 2017
10:36 PM
Hi! Yes, it should be possible. First, create a string to store all the names. I ususally do it like this: int accum = 0; string myPopupList = ""; Second, scan all project items and check their ItemType. When you hit one, get its name and add it to your popup string: accum++; myPopupList.append(intToString(accum)); myPopupList.append("."); myPopupList.append(myCompName); myPopupList.append("|"); You can have a look at this thread to avoid crashes when updating popuplist: Re: string.append() crash In parallel, you'll probably want to store reference to comps in a std::vector so you can access the comp whithout re-scanning when you use the popup... Cheers, François
... View more
Feb 19, 2017
05:21 AM
Hi! the easiest is to store it into sequence data. Sequence data is unique for each instance of the effect, and you shouldn't get any trouble with UI thread as you want to call it from FrameSetup and Render. Hope it helps, François
... View more
Jan 11, 2017
06:05 AM
Hi Christian, thanks a lot for the detailed answer. Cheers, François
... View more
Jan 04, 2017
09:45 PM
Hi everyone, can anyone tell me the good usage of PF_ABORT and what kind of PF_Err to return? What I usually do, when using a PF_EffectWorld for example, is inserting the following code after all the ERR() functions: if (err = PF_ABORT(in_data)) { ERR2(suites.WorldSuite1()->dispose_world( in_data->effect_ref, &myWorld)); return err; } Of course, I stop using this code after disposing of my world. Now, if I get an EffectRefH, I do the same, so it gives: if (err = PF_ABORT(in_data)) { ERR2(suites.WorldSuite1()->dispose_world( in_data->effect_ref, &myWorld)); ERR2(suites.EffectsSuite3()->AEGP_DisposeEffect( effectRefH); return err; } Do I need to insert it after every single function? Does the code look right? Cos' sometimes I still get leaked effect refs errors when closing After effects. The errors seem to be sent by the main thread, as it is sent after the UI thread closed. And of course, to be really annoying, it never happens while debugging... Also, in general, is it better/safer/faster to use ERR(function()) than err = function(), or even function() directly? Thanks, François
... View more
Jan 04, 2017
09:24 PM
1 Upvote
Hi James, if you want to actually move the layer itself, and so probably keyframe its geometry, then you have to write an AEGP (or even a script, which is easier...). Now you can also write a layer Effect that will mimic these transformations, like the 'Transform' effect does. In this case, look for 'PF_WORLDTRANSFORMSUITE1' in the SDK. The 'Transform_world()' function uses a matrix (or 2 if you handle motion blur) to rotate, scale, move your PF_EffectWorld. Hope it helps you start. François
... View more
Dec 30, 2016
05:27 AM
Hi, I think the easiest way is to work with XML. AE projects can be saved in XML, and then easily edited with a simple 'find and replace'. Hope it helps, François
... View more
Nov 20, 2016
09:13 AM
Got it! 🙂 Toby, you put me on the right track with this one: I would suppose AE reserves exactly the amount of bytes for the param string you give it on the first call in PF_Cmd_PARAMS_SETUP In fact, AE reserves 4096 bytes. you should never send a string with more than the initially allocated number of characters to AE That's where the bug was. To be safe, we should never send a string with more OR LESS than the initially allocated number of char. So, for the record: string stringP = param_copy[PARENT_INDEX].u.pd.u.namesptr; // like this I know the real size of namesptr names.resize(stringP.size(),'|'); // add '|' in the blank space, otherwise, it will be filled with zeros... '|' won't appear in the list strcpy((char*)param_copy[PARENT_INDEX].u.pd.u.namesptr, names.c_str()); // finally copy Thanx for the help! François
... View more
Nov 20, 2016
03:55 AM
Well, it does work most of the time, that's the (really annoying!) point. 😞 I do it like described in this thread: Update popup parameter list dynamically After searching a bit more, I noticed it doesn't crash exactly on the copy, but right after the copy, I mean it crashes on the next PF_Err operation, no matter what is the operation... I even tried to delay the copy, by copying at idle time, just to be sure AE's not working anymore when I copy, but same result... I would say it's a memory issue, but I don't know how to solve it. Cheers, François
... View more
Nov 18, 2016
04:38 AM
Hi Toby, thanx for the answer. I tried to use a try{}catch(...){} but no luck. But I think I know where it crashes now. I think it is on this line: strcpy((char*)param_copy[PARENT_INDEX].u.pd.u.namesptr, popupnames.c_str()); is there a way to check if the copy is safe to do before actually copying? Cheers, François
... View more
Nov 17, 2016
09:25 AM
Hi! I have a popup parameter representing the effects stack. I update it during PF_Cmd_UPDATE_PARAMS_UI. I update it with a std::string set to "(none)", then for each effect, I append "|" + the effect's name. It usually works fine but I sometimes get a crash. I check all possible AE errors with if (err = PF_ABORT(in_data)) {} and return without problems. But when it comes to appending the std::string, I crash. So here's my question: how can I check if it throws an error when it's not a PF_Err function? I tried this way, but still crashes: try{ names.append(effect_nameAC); }catch( std::bad_alloc& ba){ err = PF_Err_OUT_OF_MEMORY;//also tried with PF_Err_INVALID_INDEX ERR2(suites.StreamSuite4()->AEGP_DisposeStream( stream)); ERR2(suites.StreamSuite4()->AEGP_DisposeStream( parStream)); ERR2(suites.EffectSuite3()->AEGP_DisposeEffect( fxH)); ERR2(suites.EffectSuite3()->AEGP_DisposeEffect( effect_refH)); return err; } Thanx, François
... View more
Nov 16, 2016
08:59 AM
I looked into using a cumulative output chain type thing, but couldn't find a suitable way to render into hidden channels. I have one plugin working this way: 1st instance renders output with usefull data (in fact, just a ramp representing coordinates) and sends its input to 2nd instance via AEGP_EffectCallGeneric() Distortion effects alter this ramp. 2nd instance uses the ramp as an input, and receives also 1st effect's input, then map it according to ramp's coordinates. It's pretty easy as long as you don't shrink or extend the output buffer. If you do, it becomes a nightmare! 😉 I don't know if it can help... Cheers, François
... View more
Nov 16, 2016
05:49 AM
Hi Christian, I've been working on a modular plugin too, and got the same kind of problem. What about forcing a re-render of the first effect (Module Selector) once all the effects have been applied? I guess 1st effect would synch, then trigger a render of 2nd... and so on. What about applying the effects in reverse order? first effect will be applied last and probably re-render all the chain... And, do your different effects communicate via AEGP_EffectCallGeneric() or via their outputs? Cheers, François
... View more
Oct 11, 2016
05:03 AM
1 Upvote
If they do, they don't deserve all the hard work you've done for them 😉
... View more
Oct 11, 2016
04:34 AM
Well, you still downsample, so you get better performance than just a full res image. If you have a 4:3 downsample, you still compute at same speed than 3:3... Cheers, François
... View more
Oct 11, 2016
02:37 AM
Hi Christian, honestly, I wouldn't bother... I don't see any 'custom' pixel size anymore, and I'm pretty happy with it 😉 But if you really want to, you could use the smallest downsample factor. Divide by min(downSample.X, downSample.Y), work with 'square' calculation, and stretch it to fit the output. This way, you can use your plugin with almost no change in code, and you keep the highest resolution needed. Cheers, François
... View more