Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Force rendering on an event in a separate thread/Coming back to the main UI thread on an event

Explorer ,
Mar 05, 2023 Mar 05, 2023

Hi,
    I'm new to the After Effects sdk. I've set the out_data->out_flags to include PF_OutFlag_REFRESH_UI and PF_OutFlag_FORCE_RERENDER in the PF_Cmd_USER_CHANGED_PARAM handler. This works correctly when the parameter value is changed within the user interface.

I recently integrated WebSocket using easywsclient to receive messages from an external application, and I'm handling the messages in a separate thread using tinythread, which is from easywsclient.

Whenever I want to force render on a button tap or anywhere, I set the out_data->out_flags with PF_OutFlag_REFRESH_UI andPF_OutFlag_FORCE_RERENDER. 
But if I set these out_flags in the separate thread in which I'm handling the messages received from the websocket, the UI isn't force rendered.
Is there a way to come back to the main UI thread or call a function in the main thraed when receiving message in the other thread?
Or another way to force render when I receive a message in the separate thread.
Thank you!

TOPICS
How to , SDK
2.3K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 3 Correct answers

Community Expert , Mar 06, 2023 Mar 06, 2023

it's possible only via idle hook. wait for an idle event (happens 30-50 times per second), check your other thread for messages and act. idle calls happen on the UI thread, so it's a valid time to make changes to the project.

you can either:
1. change some invisible param value that would force a re-render.

2. call the command number to purge the cache.

3. call AEGP_EffectCallGeneric and have the effect instance act on itself.

Translate
Community Expert , Apr 05, 2023 Apr 05, 2023

anything happening on a separate thread can be synced back to the main thread only during main thread events. for rapid updating, idle_hook is the best way to go.

AEGP_EffectCallGeneric won't help in that regard, as it can't change the project from render threads, and can only operate during main thread events. it only helps if you want the effect to operate on itself in ways not accessible via external effect. for example, accessing the sequence data.

Translate
Community Expert , Apr 27, 2023 Apr 27, 2023

add some hidden param, and change it's value when you can to force a re-render in idle_hook.

Translate
Community Expert ,
Mar 06, 2023 Mar 06, 2023

it's possible only via idle hook. wait for an idle event (happens 30-50 times per second), check your other thread for messages and act. idle calls happen on the UI thread, so it's a valid time to make changes to the project.

you can either:
1. change some invisible param value that would force a re-render.

2. call the command number to purge the cache.

3. call AEGP_EffectCallGeneric and have the effect instance act on itself.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 04, 2023 Apr 04, 2023

1. I tried changing an invisible param value, which does force a re-render, but not in a separate thread. Is there a right way to change the param value in the main UI thread?
2. If I call the commands 2372 or 2373, it usually doesn't cause the re-render (although sometimes it does). If I call the command 10200, it does force a render but it gives me a popup "Are you sure you want to delete caches". And I don't want a popup to be there everytime.

3. I tried to find about the AEGP_EffectCallGeneric but not sure how it can help me

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 05, 2023 Apr 05, 2023

anything happening on a separate thread can be synced back to the main thread only during main thread events. for rapid updating, idle_hook is the best way to go.

AEGP_EffectCallGeneric won't help in that regard, as it can't change the project from render threads, and can only operate during main thread events. it only helps if you want the effect to operate on itself in ways not accessible via external effect. for example, accessing the sequence data.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 27, 2023 Apr 27, 2023

If I try to force render in an Idle hook, how will I get out_data, to call the

out_data->out_flags |= PF_OutFlag_REFRESH_UI | PF_OutFlag_FORCE_RERENDER
Storing the out_data as global however doesn't work


I had another workaround in mind. Can I add a command in Edit menu to force a rerender? And when in the other thread I want to re-render, I can call the command with the DO_Command. But the problem is again that I don't have the out_data for which to call force render and refreshUI

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 27, 2023 Apr 27, 2023

add some hidden param, and change it's value when you can to force a re-render in idle_hook.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 30, 2023 Apr 30, 2023

Thanks for your time Shachar, but even IdleHook doesn't work for me.
All the print logs I add in IdleHook, they show up. But when my value is updated, param is not actually updating in the UI, neither render is called.
If i add a button and update the param on buton click, it works.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 30, 2023 Apr 30, 2023

Nvm, This answer of yours helped me to achieve it. https://community.adobe.com/t5/after-effects-discussions/using-aegp-startundogroup-endundo-to-force-...
I had been trying to setup the idlehook in global setup, but setting up in sequence setup worked for me.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 01, 2023 May 01, 2023

hmmm... interesting...

sequcnce_setup is called only once per *new* instance of the effect. meaning, it's called when the user creates a new instance via selecting the effect from the effect's menu. copy/pasted or duplicated instances don't get a sequence_setup call, but rather a sequence_resetup call, and so do existing instances when a project is loaded.

if your desing is that there should be one idle_hook for all instances together, then global setup is the place to set it up on. if you're aiming for an idle_hook PER instance, then sequence_setup doesn't guarntee that.

what is the problem with setting it up during global setup? that's where i implement idle hook on effect plugins.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 01, 2023 May 01, 2023

If I set it up in the GlobalSetup, there is an error popup which says 'Effect cannot be initialized'

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 01, 2023 May 01, 2023

so probably some error code is generated by AE from one of the callbacks, which in turn is returned to AE from the global setup call. an error during global setup would indeed cause the plugin to not work.

what line causes the problem? what is the error returned?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 01, 2023 May 01, 2023

Sorry for the misunderstanding, that was not the error.
The error was "Internal structure inconsistency 25:227"
which I get when I try to call AEGP_GetEffectLayer, not while registring commandHook

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 01, 2023 May 01, 2023

ah, yes. makes sense. there is no effect isntance at the time of global_setup, so there's no way to get an effect ref.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 01, 2023 May 01, 2023

I had another concern. If I have a param of type double with value 0. In the IdleHook, I updated the value to 5, Render will be called. Now next time when I want to force a rerender, I again update the param value to 0, it stores the last instance and doesn't call render for new data

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 01, 2023 May 01, 2023

yeah, either incremet, or put some random value, like the time stamp or simething unlikely to ever repeat.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 01, 2023 May 01, 2023

Ok currently I'm incrementing. But my param is a slider type, which will have a max value. Is there a param that can have infinite values?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 01, 2023 May 01, 2023

well, maybe an arb param, bu that's a bit of an overkill.

i'd go with a timestamp. the chances of hitting 2 equal values that happen to be cached are negligible.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 02, 2023 May 02, 2023

Can I add a timeStamp param in the paramsSetup?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 02, 2023 May 02, 2023

Yes, but param setup happens only once per session and applies to all instnances created in that session, so they would all have the same value.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 02, 2023 May 02, 2023

Hey,
Thanks for all your answers
I found this in the 
AE_GeneralPlug.h, which makes me doubt updating an arb param in the SetStreamValue. It says it is illegal on AEGP_ArbBlockVal. Not sure if it is written for AEGP_SetStreamValue or AEGP_GetLayerStreamValue.


SPAPI
A_Err (*AEGP_SetStreamValue)( // only legal to call when AEGP_GetStreamNumKFs==0 or NO_DATA

AEGP_PluginIDaegp_plugin_id,/* >> */

AEGP_StreamRefH streamH,/* >> */

AEGP_StreamValue2*valueP);/* << */

 

// this is only valid on streams with primitive types. It is illegal on

// AEGP_ArbBlockVal || AEGP_MarkerValP || AEGP_MaskOutlineValH

 

SPAPI A_Err (*AEGP_GetLayerStreamValue)(

AEGP_LayerHlayerH,/* >> */

AEGP_LayerStreamwhich_stream,/* >> */

AEGP_LTimeModetime_mode,/* >> */

const A_Time *timePT, /* >> */

A_Boolean pre_expressionB, /* >> sample the stream before evaluating the expression */

AEGP_StreamVal2*stream_valP,/* << */

AEGP_StreamType *stream_typeP0);/* << */


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 02, 2023 May 02, 2023
LATEST

then use AEGP_GetNewStreamValue.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines