Showing a flash light in VR

VRFlashlightModule.py
  1from PySide6 import QtCore,QtWidgets
  2from vrScenegraph import *
  3from vrController import *
  4from vrNodePtr import *
  5from vrNodeUtils import *
  6from vrFileIO import *
  7#test
  8class Flashlight():
  9    def __init__(self):
 10        QtCore.QTimer.singleShot(0, self.init)
 11    def init(self):
 12        self.geo = None
 13        self.on = False
 14        self.createMenu()
 15        pointer = vrDeviceService.getInteraction("Tools Menu")
 16        start = pointer.getControllerAction("showMenu") 
 17        start.signal().triggered.connect(self.onMenuOpened)
 18        self.handNode = vrDeviceService.getVRDevice("right-controller").getNode()
 19        self.activeController = vrDeviceService.getVRDevice("right-controller")
 20        vrHMDService.hmdStatusWillChange.connect(self.__onHMDStatusWillChange)
 21    def onMenuOpened(self,action,device):
 22        # place the flashlight on the other hand
 23        if device.getName() == "left-controller":
 24            self.handNode = vrDeviceService.getVRDevice("right-controller").getNode()
 25            self.activeController = vrDeviceService.getVRDevice("right-controller")        
 26        else:
 27            self.handNode = vrDeviceService.getVRDevice("left-controller").getNode()
 28            self.activeController = vrDeviceService.getVRDevice("left-controller")        
 29    def switchOn(self):
 30        if not self.on:
 31            self.getGeo().setActive(True)
 32            self.on = True
 33            # move the flashlight with the hand
 34            self.constraint = vrConstraintService.createParentConstraint([self.handNode],self.geo,False)            
 35            self.activeController.signal().moved.connect(self.updateFlashlight)
 36            self.visualizationMode = self.activeController.getVisualizationMode()
 37            self.adjustFlashlight(self.activeController)
 38    def switchOff(self):
 39        if self.on:
 40            self.getGeo().setActive(False)
 41            self.on = False
 42            vrConstraintService.deleteConstraint(self.constraint)
 43            self.activeController.signal().moved.disconnect(self.updateFlashlight)
 44    def createMenu(self):
 45        # png icons as base64 string
 46        onIcon = "iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAilBMVEX9oRTreSj6twb3qw3ylxjtfibvlBv1pBHxjB/rfSjviiDvix/7vQPxkxvugiPtfiXwix/0nBXuhSL1oRLwjB7rfCf0qQ7ugyP8wQH4swn1pRDwix/ylBn0nBXwiCHtgST1pBHvih/7uwT5tAj4rgv7wAH1oRPvix77ugXuhCP0oBP1oxHwjh3uhCJVyFMlAAAAK3RSTlMAM/////4QJEKBpVHxjTq5FrBj8NjEG+exwjzY7eWF7tbo3eTcTFj8W26hmZCkDQAAAAlwSFlzAAAk6QAAJOkBUCTn+AAAA31JREFUWAntWO12ojAQDUkIVJRGrEpXrVq7220T3v/19uYDRIviYvqvOT1lmjA3dzKTmaGEDB8RxWCMKcUV51xXGPFwOGgeERXjWhvE+wAFEMEQFJMofUj1KIvvAyQkGTuTxSTLxaMc3Q1orVaMiWmRPYhI3w8IRHCkBGBaPP4HoBRH97VE45mZUko8wSty3uMUOZE1yoKqRk4eGtEuJ1ypfImwyZY9gCV9rgF/URrV8kpPatE9YTXgbNhcP8OSUulVM6oWXoy4LrxYP8CxDsOrYSOZqrnkVNUMJ0ovTk8R58g84nWGZMq4UxUp5R5QMDaqmR2fkb96PYApValTSqn2Jmeshj7CEURNBaPhk6smE7JWnk1OtWe4oVUbqZGTm+5yybm0Kg1gxNi5SzxmFN/AUHLvFpicWMUXxtwWHqb1SLb9JpMd21u3INScyYzNWxinYhJjnE59+Stz3oWXlWWYU5Z/eamZiPoBxWtsGUq6tWoJ3TXqHQIQO2bvmUqGALpYv7BtfZ+6l0X5+nrYvL1tnja79f5pv1otV8v9XHa/fcPsb1PWMFA0UNmYMrHLq/hCIPYDij8OzwListqMou8AJAAcz2ZUzTC4fn/fr3FZ4+EMcec7zeie7Xz1bFIs5JchZLu8nCn0/Zn6M0Rho6bZUBr9RlxlfXoX1zMHyOAV4xOX5uP4yuW7COUWxNggumbDtkM2h1aLHrUryyhT53hVvLyi0Lf0t2bIXMNm+ytfFfp0u9efwRAc7U0xRwjEewgSIhubDUUDGMvurW+dNT2lZVi7eXjM+C0Lb7H38setTC6/92mOkSqKfMP14+X3bl4Rk3JUj5fh17i1H0Can9b0cDEtMDLzqxh+6drb47ogEHGAVXW5JrcV+uSpDRwThYEADUOTbsAwhJMJsQxt0xuOIThak8MwRGRjhD3DQy5EtOTBTD64QFgFApxSl2FEHgiwpK55JSIYYP1dEghw2nxPBQIs6UKk03kezORPKlHxuU7DnaF8ZvgcnpNAJoPh1AKGY5jBZMbzHCRDjE86Flm5ysQ2kMnIh4dM4i6HytgANNnGtA1hTLaAps6HZGhLQECGtqbgX2XBTA5bRs0Z+qoXjKGt9MEK/bd5OVjYFP4M0ToM/g49SQFike+QbZAQkyDtIcBFgWTDAnTDDVFRbNYfoeg1qD/Czwl82wn8A1RuSwNXqFYLAAAAAElFTkSuQmCC"
 47        offIcon = "iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAe1BMVEWwsbWwsrO1triwsbOur7Gmp6men6GdnqCcnp64ubu1t7ump6mkpKavr7GkpaenqKqmpqm7u72kpaesrK+jpKa0tbeztbeztLWgoaOfoKGoqaurrK+5ury6vL2vsLKnqKqcnZ+trrCbm6CjpKaxsrSmqKi6ur2ioqS5ubt/L2nWAAAAKXRSTlMAI//+/v/+/DFcLkOGZ5KkE6/qHNfsTLP9Ylbq3e7d2sTrM7jMYbN2V7lTpSMAAAAJcEhZcwAAJOkAACTpAVAk5/gAAAMoSURBVFgJ7Zh7c6MgEMBxEVPFJIh4tbVec73n9/+EtzxWc0mrNnAz/aM708AY+LkvdkkZu10yIOE8z4WVYnc7DnfezUBwvFggKz2R86qS9V4cyqKI0pAxbzXn7CilOmaHSJNnq1lT7msm83hg8KNSUgt2FNtNbtVbzpEC0GSDQVGmWNawrVuitAATsa0reuzGrAMuNabN3qxo2IChnV8A7mhuxD1N/VjllIb9soYPAKTLI0AWKK0Q5b9AJrucEnsxbSqAOmyVs4ZNLtQFkFWC28TuVzRkDXTXQM4vLLZLKmGPXr92UvAg7D0RNQwm7wFkeMv5IDsEFmsasgEOEzAExcBwDprmFQLXi8M9gM+cyYeYP0HpCRUmlV73IcPtPiwI9ORmsv0SyOSAXlwrX0+g3cYScp9BHTRXJHpQ6WK3BnwE4UAyjBim10ISkBKJRH9jVKN20cXRraj4dHhe2yH1GvC1XUvPpH/v0pJ3frfgEEtqxrEzX587YzptumdtjNb6pN75knk5VgdqGlhPODU2OuDzwq2zCQiAQM/DkndZbLbiGHPAEWBE6YZvw4AGa727Hbj91RtXqlah4EdVqSyIajO1cfv1MqzTk4SQ2Ipyu8lYEibBmLioYMlbybVrxeYnEw7gLMrUXeZ1m2cmEPmUNr0Qi6d5BY3FhZCkYS8iLGbsiYBosvdhEaMgY+oMGGIS4UHrjxci0tmLMtgS6TxjHtpUvL0wWJgTbEsoGGe8SMNRhacRg6oblKOVwyEBj1RJiCr3Zen+6jI6Ik4970T0Y14cSd+okYBYaE5RINocwmzvQt/pWdToga6lnKJAtDkArYZJgXhMimTApxfFpBF9KuDordd9qrQJXUkm82H4taKS+VB5k1kyIP2eShYUxcrGYGFIB8Tul2O3S2aywv6cYz9OB2yw0YuTSpY2Ei85QkiZrtoo+cP8ZDqZhgCP+F8Kk77aJNTQRvlD10Pb8lDBZHlo7yIWmOjo/bI8Jx8byPECm8iH3uSEffm3858LSoLrpi3+mcS7e57rP5HX69BI7ID34jxPpJ7DqodxSMk70/Vz+umB/+GBv9HkI1uzfxLJAAAAAElFTkSuQmCC"
 48        self.tool = vrImmersiveUiService.createTool("vrFlashlightTool")
 49        self.tool.setText("Flashlight")
 50        self.tool.setCheckable(True)
 51        self.tool.setOnOffIconData(onIcon,offIcon)   
 52        self.tool.signal().checked.connect(self.switchOn)
 53        self.tool.signal().unchecked.connect(self.switchOff)
 54        self.tool.hideAway(True)
 55    def deleteMenu(self):
 56        vrImmersiveUiService.deleteTool(self.tool)
 57    def getGeo(self):
 58        if not self.geo is None and  self.geo.isValid():
 59            return self.geo
 60        self.createGeo()
 61        return self.geo
 62    def createGeo(self):
 63        for node in findNodes("VR_Flashlight"):
 64            node.getParent().subChild(node)
 65        rootNode = getInternalRootNode()
 66        self.geo = createNode("Transform3D","VR_Flashlight", rootNode, False)
 67        self.trans = createNode("Transform3D","FlashlightPos",self.geo,False)
 68        self.loadModel()
 69        self.flashlightHandle = vrNodeService.findNode("Housing_02", False, False, self.trans)
 70        self.geo.setActive(False)
 71        setIsVRNode(self.trans, True)
 72        setIsVRNode(self.geo, True)
 73    def loadModel(self):
 74        path = vrFileIOService.getVREDDataDir() + "/Internal/VR/Flashlight.osb"
 75        files = [path]    
 76        nodes = loadOSB(files)
 77        for node in nodes:
 78            self.trans.addChild(node)
 79    def removeGeo(self):
 80        subChilds(self.geo.getParent(),[self.geo])
 81    def updateFlashlight(self, device):        
 82        if device.getVisualizationMode() != self.visualizationMode:
 83            self.adjustFlashlight(device)
 84            self.visualizationMode = device.getVisualizationMode()
 85    def adjustFlashlight(self, device):
 86        if device.getVisualizationMode() == 1:
 87            self.setHandTransform()
 88            self.flashlightHandle.setVisibilityFlag(True)
 89        else:
 90            self.setControllerTransform()
 91            self.flashlightHandle.setVisibilityFlag(False)        
 92
 93    def setHandTransform(self):
 94        setTransformNodeTranslation(self.trans,13,-5,60,False)
 95        setTransformNodeRotation(self.trans,180,0,0)
 96    def setControllerTransform(self):
 97        setTransformNodeTranslation(self.trans,0,-50,50,False)
 98        setTransformNodeRotation(self.trans,110,0,0)
 99
100    def __onHMDStatusWillChange(self, active):
101        if not active:
102            self.tool.setChecked(False)
103            self.switchOff()
104        
105flashlight = Flashlight()
106
107label = QtWidgets.QLabel(VREDPluginWidget)
108label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
109label.setScaledContents(True)
110label.setText("Python VR flashlight avatars tool\n" + __file__)
111VREDPluginWidget.layout().addWidget(label)