Skip to main content
Inspiring
July 31, 2023
Answered

SDK: Set keyframes of effect parameters

  • July 31, 2023
  • 1 reply
  • 443 views

Hey

I'm working on a c++ effect for After Effects. When the effect is added to the layer, one of the parameters should already have two keyframes. What would be the best way to do that? My idea was to put the code in the GlobalSetup function. I do realise that if that works I will probably need an if statement checking if it is already keyframed.

My problem is simply how to write a keyframe to the effects parameter. I feel close but I'm not sure how to actually set the desired value. I have this:

static PF_Err 
GlobalSetup (	
	PF_InData		*in_data,
	PF_OutData		*out_data,
	PF_ParamDef		*params[],
	PF_LayerDef		*output )
{
	PF_Err 					err 		= PF_Err_NONE;
	
	PF_Handle				globH		= NULL;
	my_global_dataP			globP		= NULL;
	AEGP_PluginID			pluginID;
	AEGP_StreamRefH			streamH = NULL;
	AEGP_AddKeyframesInfoH	akH = NULL;
	AEGP_EffectRefH			effectPH = NULL;
	A_long					indexPL = NULL;
	AEGP_StreamValue2		valueP;

	AEGP_SuiteHandler		suites(in_data->pica_basicP);

	out_data->my_version = PF_VERSION(	MAJOR_VERSION, 
										MINOR_VERSION,	
										BUG_VERSION, 
										STAGE_VERSION, 
										BUILD_VERSION);

	out_data->out_flags = PF_OutFlag_PIX_INDEPENDENT |
								PF_OutFlag_SEND_UPDATE_PARAMS_UI	|
								PF_OutFlag_USE_OUTPUT_EXTENT		|
								PF_OutFlag_DEEP_COLOR_AWARE			|
								PF_OutFlag_WIDE_TIME_INPUT;
	
	out_data->out_flags2 = PF_OutFlag2_PARAM_GROUP_START_COLLAPSED_FLAG |
								PF_OutFlag2_DOESNT_NEED_EMPTY_PIXELS	|
								PF_OutFlag2_AUTOMATIC_WIDE_TIME_INPUT	|
								PF_OutFlag2_SUPPORTS_THREADED_RENDERING;

	globH	=	suites.HandleSuite1()->host_new_handle(sizeof(my_global_data));
	
	if (globH) {
		globP = reinterpret_cast<my_global_dataP>(suites.HandleSuite1()->host_lock_handle(globH));
		if (globP) {
			globP->initializedB 	= TRUE;

			if (in_data->appl_id != 'PrMr') {
				ERR(suites.UtilitySuite3()->AEGP_RegisterWithAEGP(NULL, STR(StrID_Name), &globP->my_id));
			}
				if (!err){
					out_data->global_data 	= globH;
			}
		}
		suites.HandleSuite1()->host_unlock_handle(globH);
	} else	{
		err = PF_Err_INTERNAL_STRUCT_DAMAGED;
	}

	const A_char* pluginName = STR(StrID_Name);
	ERR(suites.UtilitySuite5()->AEGP_RegisterWithAEGP(NULL, pluginName, &pluginID));

	ERR(suites.PFInterfaceSuite1()->AEGP_GetNewEffectForEffect(pluginID, in_data->effect_ref, &effectPH));

	ERR(suites.StreamSuite5()->AEGP_GetNewEffectStreamByIndex(pluginID, effectPH, 25, &streamH));
	
	ERR(suites.KeyframeSuite4()->AEGP_StartAddKeyframes(streamH, &akH));
	
	ERR(suites.KeyframeSuite4()->AEGP_AddKeyframes(akH, AEGP_LTimeMode_CompTime, 0, &indexPL));

	valueP.one_d = 20; // How do I set the value?
	
	ERR(suites.KeyframeSuite4()->AEGP_SetAddKeyframe(akH, indexPL, &valueP));
	
	ERR(suites.StreamSuite3()->AEGP_DisposeStreamValue(&valueP));

	AEFX_CLR_STRUCT(valueP);

	ERR(suites.KeyframeSuite4()->AEGP_EndAddKeyframes(true, akH));

	ERR(suites.StreamSuite2()->AEGP_DisposeStream(streamH));
	ERR(suites.EffectSuite2()->AEGP_DisposeEffect(effectPH));

	return err;
}

I get this error: class "AEGP_StreamValue2" has no member "one_d.
Any help will be greatly appreciated. 

 

Thanks,

Jakob

This topic has been closed for replies.
Correct answer shachar carmi

the effect_ref refers to a specific instance of an effect. during global setup there's still no instance, so the passed effect_ref is actually garbage.

you should try setting the keyframes on the first call to UPDATE_PARAMS_UI. that call is not intended for such actions, but what the heck...

1 reply

Inspiring
August 1, 2023

OK. I need to get the value before setting the value. I think. I tried this, but I'm getting an "internal structure inconsistency" error. What is wrong with this?

 

 

const A_char* pluginName = STR(StrID_Name);
ERR(suites.UtilitySuite5()->AEGP_RegisterWithAEGP(NULL, pluginName, &pluginID));

ERR(suites.PFInterfaceSuite1()->AEGP_GetNewEffectForEffect(pluginID, in_data->effect_ref, &effectPH));

ERR(suites.StreamSuite5()->AEGP_GetNewEffectStreamByIndex(pluginID, effectPH, 25, &streamH));
ERR(suites.StreamSuite5()->AEGP_GetNewStreamValue(pluginID, streamH, AEGP_LTimeMode_CompTime, 0, TRUE, &valueP));
	
valueP.val.one_d = 20;

ERR(suites.KeyframeSuite4()->AEGP_StartAddKeyframes(streamH, &akH));
ERR(suites.KeyframeSuite4()->AEGP_AddKeyframes(akH, AEGP_LTimeMode_CompTime, 0, &indexPL));
ERR(suites.KeyframeSuite4()->AEGP_SetAddKeyframe(akH, indexPL, &valueP));
	
ERR(suites.KeyframeSuite4()->AEGP_EndAddKeyframes(true, akH));

ERR(suites.StreamSuite5()->AEGP_DisposeStreamValue(&valueP));
ERR(suites.StreamSuite5()->AEGP_DisposeStream(streamH));
ERR(suites.EffectSuite2()->AEGP_DisposeEffect(effectPH));

 

Update: Deleting everything above and leaving only this line will cause the error. But how else to get the effect reference?

 

ERR(suites.PFInterfaceSuite1()->AEGP_GetNewEffectForEffect(pluginID, in_data->effect_ref, &effectPH));

 

 

shachar carmiCommunity ExpertCorrect answer
Community Expert
August 2, 2023

the effect_ref refers to a specific instance of an effect. during global setup there's still no instance, so the passed effect_ref is actually garbage.

you should try setting the keyframes on the first call to UPDATE_PARAMS_UI. that call is not intended for such actions, but what the heck...

Inspiring
August 3, 2023

My thought was, that this would be something that logically should happen in the initiliazation of the effect. But I see the problem.

I actually add the effect with a script, so I'll set the keyframes with the script instead.

Thanks, for the input. 🙂