poser.RegisterAddon() – can't get it work



  • I'm almost ready with Poser-MQTTClient.lib. It works so far, but to make it able to survive things like reload of a Scene I need the Observer-part from a registered addon.

    I tried to use the sample from :Runtime:Python:addons, but with no success so far. There is more ore less no (correct) documentation for RegisterAddon. And no word how to activate an Observer.

    Anybody with some knowledge about RegisterAddon?



  • @adp can't say as I've tried to work with it, but I've certainly looked through all the accessible parts of the addons I've installed.

    Does this one from the DSON addon's init.py give any further clues?

    import poser
    #import poseraddon
    import wx
    import dson.dzdsonimporter
    
    class DzDAZSceneObjectNotationAddOn:#(poseraddon.Addon, poseraddon.SceneObserver, poseraddon.SceneDataSaver, poseraddon.PrefsSaver):
    	def __init__(self):
    		dson.dzdsonimporter.initAddon(self)
    	def load(self):
    		dson.dzdsonimporter.loadAddon(self)
    	def unload(self):
    		dson.dzdsonimporter.unloadAddon(self)
    	def objectsAdded(self, objects):
    		dson.dzdsonimporter.objectsAddonAdded(self,objects)
    	def objectsDeleted(self, objects):
    		dson.dzdsonimporter.objectsAddonDeleted(self,objects)
    	def objectsRenamed(self, objectsOldNames):
    		dson.dzdsonimporter.objectsAddonRenamed(self,objectsOldNames)
    	def objectSelected(self, selection):
    		dson.dzdsonimporter.objectsAddonSelected(self,selection)
    	def sceneDeleting(self, scene):
    		dson.dzdsonimporter.sceneAddonDeleting(self,scene)
    	def sceneCreated(self, scene):
    		dson.dzdsonimporter.sceneAddonCreated(self,scene)
    	def frameChanged(self):
    		dson.dzdsonimporter.frameChanged(self)
    	def saveData(self):
    		return dson.dzdsonimporter.saveAddonData(self)
    	def loadData(self, data):
    		dson.dzdsonimporter.loadAddonData(self,data)
    	def savePrefs(self):
    		return dson.dzdsonimporter.saveAddonPrefData(self)
    	def loadPrefs(self, data):
    		dson.dzdsonimporter.loadAddonPrefData(self,data)
    	def materialsChanged(self, data):
    		dson.dzdsonimporter.materialsAddonChanged(self,data)
    
    poser.RegisterAddon("com.daz3d.dson_support", DzDAZSceneObjectNotationAddOn())
    
    
    class DzGeneralEvtHandler(wx.PyEvtHandler):
    	def __init__(self,data):
    		self.data = data;
    	def ProcessEvent(self, evt):
    		return dson.dzdsonimporter.processGeneralEvent(self,evt,self.data)
    


  • @anomalaus Looks good! Thank you!



  • @anomalaus said in poser.RegisterAddon() – can't get it work:
    It's pretty simple if one has enough information :)
    Thanks again!

    Now I'm going to work on an Interface for Tablets/Mobile based on MQTT. First Step: My Tablet as an extension to Posers User-Interface.

    By the way: Did you know that Threads do work in newer Poser-Versions? Don't know since when, but I made a script with some Threads recently, started it in Poser-Python and it worked!
    The Threads are updated even if a render is running or Poser does some other blocking things.



  • Tablet extending Poser interface ...
    Very interesting thought.



  • A Class to create different timers using Threads :

    from __future__ import print_function
    from threading import Thread, Event
    
    __all__ = ["Timer", ]
    
    
    class _TimerThread(Thread):
        __slots__ = ("delay", "stopped", "callback", "args", "_lock")
    
        def __init__(self):
            self._lock = Event()
    
            Thread.__init__(self)
    
        def run(self):
            while not self.stopped.wait(self.delay):
                self._lock.set()
                self.callback(self)
                self._lock.clear()
    
    
    
    class Timer(Thread):
    
        def __init__(self, delay=1.0, callback=None, *args, **kwargs):
            assert isinstance(delay, float)
            Thread.__init__(self)
            self._lock = Event()
            self._stopped = Event()
            self._delay = delay
            self.callback = callback
            self.args = args
            for k, v in kwargs.items():
                setattr(self, k, v)
    
            if callback is not None:
                assert callable(callback)
                self.start()
    
        def run(self):
            if callable(self.callback):
                while not self._stopped.wait(self.delay):
                    self._lock.set()
                    self.callback(self)
                    self._lock.clear()
    
    
        @property
        def stopped(self): return not self._stopped.isSet()
    
        @stopped.setter
        def stopped(self, v):
            if bool(v):
                if not self._stopped.isSet():
                    self._stopped.set()
            else:
                if self.delay > 0.0 and self._stopped.isSet():
                    self._stopped.clear()
                    self.run()
    
        @property
        def delay(self): return self._delay
    
        @delay.setter
        def delay(self, v):
            if v > 0.0:
                self._delay = float(v)
    
        def __del__(self):
            self._lock.wait()
    
    
    if __name__ == "__main__":
        from time import time, asctime
        from random import random
    
        def cb1(timer):
            timer.counter += 1
            print(asctime(), "CB1: %s times called (delay=%s)" % (timer.counter, timer.delay))
            timer.delay = random() * 2 # new delay between 1.0 and 3.0 secs.
            # Stop timer after ~5 secs.
            if time() > timer.time+1:
                print(asctime(), "CB1: Timer stopped.")
                timer.stopped = True
    
        def cb2(timer):
            timer.args += 1
            print(asctime(), "CB2: %s times called (delay=%s)" % (timer.args, timer.delay))
    
    
        # create and start a timer with some private variables set and used in callback (counter, time).
        Timer(delay=2.0, callback=cb1, counter=1, time=time()+5)
        # second timer is activated step by step.
        timer2 = Timer(3.0)
        timer2.args = 0
        timer2.callback = cb2
        timer2.start()
    

    2 timers are created if the script is started from Poser. First timer stops after ~5 Seconds, second timer runs forever. Both timers writes to the Python console.

    callback function receives the timer object as argument. One may set some variables inside the timer to use between calls.

    Timers can be stopped, but not started again (still working on that problem).

    You can load scenes or whatever, the timer stays stable and prints to the console. But if Poser is closed there will be an error message if the timer is active. This could be catched if the timer is registered as an addon.



  • Ignore the first class named "TimerThread".



  • @f_verbaas said in poser.RegisterAddon() – can't get it work:

    Tablet extending Poser interface ...
    Very interesting thought.

    Yes, and because MQTT is a very fast TCP protocol, it should also be possible to use sensordata from phone/tablet.
    It works technically already, but to make it usable a nice interface for tablets is required. This is a lot of work. Especially because I'm not deep into making user-interfaces. But I will try with QT5 beside of finetuning the communication part.