Recommended way of attaching Text DAT with callbacks on placement of custom component

Hello,
please may I ask whether there is some preferred way of attaching callbacks (Text DAT) to custom component during its node placement?

I have written this simple function that does what I need, but I am not entirely sure what might be the best way to call it. I have tried calling it on extension initialization, but it resulted is some funky behavior (sometimes I couldn’t delete callbacks without triggering extension re-initialization which instantly added default callbacks back).

	def createDefaultCallbacks(self):
		"""Creates textDAT with default callbacks"""
		callbacks = self.ownerComp.par.Callbacks
		if callbacks == None and len(self.ownerComp.docked) == 0:
			n = self.ownerComp.parent().create(textDAT, 'compname_callbacks')
			n.text = op('compname_default_callbacks').text
			n.par.language = 'python'
			n.viewer = True
			n.nodeX = self.ownerComp.nodeX
			n.nodeY = self.ownerComp.nodeY - 160
			n.nodeWidth = self.ownerComp.nodeWidth
			n.nodeHeight = self.ownerComp.nodeHeight
			n.dock = self.ownerComp
			self.ownerComp.par.Callbacks = n.name

My second though was to look for some “node placement” action in OP Execute DAT, but since I haven’t found anything related, I though I might better ask here. :slight_smile: Thanks

I personaly like to simply have a create pulseParameter instead of doing it automaticaly because, as you said, there are so many edge-cases to cover that it is just not worth it. Sometimes I also like to simply reuse callbacks without having to delete all of them.
I might interrest you in my callbackManager maybe? It fights many of the issues you describe by relegating the callbacks to thei own namespace. So instead of calling a callback directly you tell the callbackManager to call it.This cimplelty decouples callbacks from your internal logic.

Another Trick is to do it on demand. So instead of creating it beforehand, you can write:

@property
def callback(self):
	callback = self.ownerComp.par.Callback.eval()
	if not callback:
		callback = self.createCallback()
	return callback.module
	
def Foo(self):
	self.callback.DoSomething

But in general I find using userdefined python directly as a module super iffy!

I see, thanks, I guess I will use some pulse parameter as suggested :slight_smile:
Thanks, I will take a look at Callback Manager :+1:

I haven’t noticed this sentence before. Now it makes me wonder why is that so? If there is some problem, the call will throw an error - which is kind of expected. Therefore I am a bit confused why it might not be a great thing to do… :thinking:

You will create a direct link and a dependency between a user-written dat and your own data, which will result in recooks of your extensionDAT resulting in an reinit of all your extensions. Also, depending on where you get it (doing the on demand thing is more safe in that regard), an error in the dat might result in the init of the extension failing complelty, generating unwanted behavior.

Aha, I see… I wasn’t aware there is dependency created automatically when calling function from some other module. But it makes sense from TouchDesigner point of view. That’s good to know, thank you very much for explanation.

Please do you know about some way of viewing these dependencies / links between extension and other modules? I guess there should be a dashed line visible in network view (in case other module would be at the same level). However this dashed line seems to appear only when doing import other_module, and not when using mod('other_module').

I have realized I might be missing more of these cases and though it would be nice to find some overview listing dependencies / links.

Nevertheless, I have tried approaching callbacks same way you did it in CallbackManager (at least at a very basic level), but it seems to create dependency too. (Meaning that if I change print statement in hello(), extension reinits.)

there is also a build in callback system: see callbacksExt Extension - Derivative