def Box(width=1, depth=1, height=1, origin=pm.Point3(0, 0, 0)): """Return a geom node representing a box.""" # Create vetex data format gvf = pm.GeomVertexFormat.getV3n3() gvd = pm.GeomVertexData('vertexData', gvf, pm.Geom.UHStatic) # Create vetex writers for each type of data we are going to store gvwV = pm.GeomVertexWriter(gvd, 'vertex') gvwN = pm.GeomVertexWriter(gvd, 'normal') # Write out all points for p in GetPointsForBox(width, depth, height): gvwV.addData3f(pm.Point3(p) - origin) # Write out all the normals for n in ((-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1), (0, 0, 1)): for i in range(4): gvwN.addData3f(n) geom = pm.Geom(gvd) for i in range(0, gvwV.getWriteRow(), 4): # Create and add both triangles geom.addPrimitive(GetGeomTriangle(i, i + 1, i + 2)) geom.addPrimitive(GetGeomTriangle(i, i + 2, i + 3)) # Return the box GeomNode geomNode = pm.GeomNode('box') geomNode.addGeom(geom) return geomNode
def Line(start, end, thickness=1.0): """Return a geom node representing a simple line.""" # Create line segments ls = pm.LineSegs() ls.setThickness(thickness) ls.drawTo(pm.Point3(start)) ls.drawTo(pm.Point3(end)) # Return the geom node return ls.create()
def Cone(radius=1.0, height=2.0, numSegs=16, degrees=360, axis=pm.Vec3(0, 0, 1), origin=pm.Point3(0, 0, 0)): """Return a geom node representing a cone.""" # Create vetex data format gvf = pm.GeomVertexFormat.getV3n3() gvd = pm.GeomVertexData('vertexData', gvf, pm.Geom.UHStatic) # Create vetex writers for each type of data we are going to store gvwV = pm.GeomVertexWriter(gvd, 'vertex') gvwN = pm.GeomVertexWriter(gvd, 'normal') # Get the points for an arc axis2 = pm.Vec3(axis) axis2.normalize() offset = axis2 * height / 2.0 points = GetPointsForArc(degrees, numSegs, True) for i in range(len(points) - 1): # Rotate the points around the desired axis p1 = pm.Point3(points[i][0], points[i][1], 0) * radius p1 = RotatePoint3(p1, pm.Vec3(0, 0, 1), axis) - origin p2 = pm.Point3(points[i + 1][0], points[i + 1][1], 0) * radius p2 = RotatePoint3(p2, pm.Vec3(0, 0, 1), axis) - origin cross = (p2 - axis).cross(p1 - axis) cross.normalize() # Facet gvwV.addData3f(p1 - offset) gvwV.addData3f(offset - origin) gvwV.addData3f(p2 - offset) for i in range(3): gvwN.addData3f(cross) # Base gvwV.addData3f(p2 - offset) gvwV.addData3f(-offset - origin) gvwV.addData3f(p1 - offset) for i in range(3): gvwN.addData3f(-axis) geom = pm.Geom(gvd) for i in range(0, gvwV.getWriteRow(), 3): # Create and add triangle geom.addPrimitive(GetGeomTriangle(i, i + 1, i + 2)) # Return the cone GeomNode geomNode = pm.GeomNode('cone') geomNode.addGeom(geom) return geomNode
def Frame(self, nps): # Get a list of bounding spheres for each NodePath in world space. allBnds = [] allCntr = pm.Vec3() for np in nps: bnds = np.getBounds() if bnds.isInfinite(): continue mat = np.getParent().getMat(self.rootNp) bnds.xform(mat) allBnds.append(bnds) allCntr += bnds.getCenter() # Now create a bounding sphere at the center point of all the # NodePaths and extend it to encapsulate each one. bnds = pm.BoundingSphere(pm.Point3(allCntr / len(nps)), 0) for bnd in allBnds: bnds.extendBy(bnd) # Move the camera and the target the the bounding sphere's center. self.target.setPos(bnds.getCenter()) self.setPos(bnds.getCenter()) # Now move the camera back so the view accomodates all NodePaths. # Default the bounding radius to something reasonable if the object # has no size. fov = self.GetLens().getFov() radius = bnds.getRadius() or 0.5 dist = radius / math.tan(math.radians(min(fov[0], fov[1]) * 0.5)) self.setY(self, -dist)
def __init__(self, *args, **kwargs): PrimitiveNPO.__init__(self, *args, **kwargs) self._width = 1 self._depth = 1 self._height = 1 self._origin = pm.Point3(0, 0, 0)
def privGotSpec(self, levelSpec): DistCogdoLevelGame.privGotSpec(self, levelSpec) levelMgr = self.getEntity(LevelConstants.LevelMgrEntId) self.endVault = levelMgr.geom self.endVault.reparentTo(self.geomRoot) self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask | PM.BitMask32.lowerOn(3) << 21) walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) self.evWalls.stash() floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') plane = PM.CollisionPlane( PM.Plane(PM.Vec3(0, 0, 1), PM.Point3(0, 0, -50))) planeNode = PM.CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geomRoot.attachNewNode(planeNode)
def __init__(self, points, normals=None, texcoords=None, origin=pm.Point3(0, 0, 0)): # Create vetex data format gvf = pm.GeomVertexFormat.getV3n3t2() gvd = pm.GeomVertexData('vertexData', gvf, pm.Geom.UHStatic) # Create vetex writers for each type of data we are going to store gvwV = pm.GeomVertexWriter(gvd, 'vertex') gvwN = pm.GeomVertexWriter(gvd, 'normal') gvwT = pm.GeomVertexWriter(gvd, 'texcoord') # Write out all points and normals for i, point in enumerate(points): p = pm.Point3(point) - origin gvwV.addData3f(p) # Calculate tex coords if none specified if texcoords is None: gvwT.addData2f(p.x / 10.0, p.y / 10.0) else: gvwT.addData2f(texcoords[i]) # Calculate normals if none specified if normals is None: prevPoint = (points[-1] if i == 0 else points[i - 1]) nextPoint = (points[0] if i == len(points) - 1 else points[i + 1]) cross = (nextPoint - point).cross(prevPoint - point) cross.normalize() gvwN.addData3f(cross) else: gvwN.addData3f(normals[i]) geom = pm.Geom(gvd) for i in range(len(points) - 1): # Create and add both triangles geom.addPrimitive(GetGeomTriangle(0, i, i + 1)) # Init the node path, wrapping the polygon geomNode = pm.GeomNode('poly') geomNode.addGeom(geom) pm.NodePath.__init__(self, geomNode)
def __init__(self, *args, **kwargs): PrimitiveNPO.__init__(self, *args, **kwargs) self._radius = 1 self._height = 2 self._numSegs = 16 self._degrees = 360 self._axis = pm.Vec3(0, 0, 1) self._origin = pm.Point3(0, 0, 0)
def Circle(radius=1.0, numSegs=16, axis=pm.Vec3(1, 0, 0), thickness=1.0, origin=pm.Point3(0, 0, 0)): # Create line segments ls = pm.LineSegs() ls.setThickness(thickness) # Get the points for an arc for p in GetPointsForArc(360, numSegs): # Draw the point rotated around the desired axis p = pm.Point3(p[0], p[1], 0) - origin p = RotatePoint3(p, pm.Vec3(0, 0, 1), pm.Vec3(axis)) ls.drawTo(p * radius) return ls.create()
def ClosestPointToLine(c, a, b): """Returns the closest point on line ab to input point c.""" u = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1]) + ( c[2] - a[2]) * (b[2] - a[2]) u = u / ((a - b).length() * (a - b).length()) x = a[0] + u * (b[0] - a[0]) y = a[1] + u * (b[1] - a[1]) z = a[2] + u * (b[2] - a[2]) return pm.Point3(x, y, z)
def setDist(self, newDist): """Set camera distance from the target.""" vec = camera.getPos() vec.normalize() #set length to 1 vec *= newDist #set length to clamped value camera.setFluidPos(vec) #move the camera to new distance #Move the segment end but keep it a little behind and below the camera. ##zuck ###self.segment.node().getSolid(0).setPointB( ###self.target.getRelativePoint(camera, P.Point3(0,-2,-1))) self.segment.node().modifySolid(0).setPointB( self.target.getRelativePoint(camera, P.Point3(0, -2, -1)))
def __init__(self, *args, **kwargs): Base.__init__(self, *args, **kwargs) self.AddAttributes(Attr('Point A', pm.Point3, CT.getPointA, CT.setPointA, initDefault=pm.Point3(0), initName='a'), Attr('Point B', pm.Point3, CT.getPointB, CT.setPointB, initDefault=pm.Point3(0, 0, 1), initName='db'), Attr('Radius', float, CT.getRadius, CT.setRadius, initDefault=0.5), parent='CollisionTube')
def __init__(self, *args, **kwargs): Base.__init__(self, *args, **kwargs) self.AddAttributes(Attr('X', float, initDefault=0.5), Attr('Y', float, initDefault=0.5), Attr('Z', float, initDefault=0.5), Attr('Center', pm.Point3, CB.getCenter, CB.setCenter, initDefault=pm.Point3(0)), parent='CollisionBox')
def Square(width=1, height=1, axis=pm.Vec3(1, 0, 0), thickness=1.0, origin=pm.Point3(0, 0, 0)): """Return a geom node representing a wire square.""" # Create line segments ls = pm.LineSegs() ls.setThickness(thickness) # Get the points for a square points = GetPointsForSquare(width, height) points.append(points[0]) for p in points: # Draw the point rotated around the desired axis p = pm.Point3(p[0], p[1], 0) - origin p = RotatePoint3(p, pm.Vec3(0, 0, 1), axis) ls.drawTo(p) # Return the geom node return ls.create()
def __init__(self, *args, **kwargs): Base.__init__(self, *args, **kwargs) self.AddAttributes(Attr('Center', pm.Point3, CS.getCenter, CS.setCenter, initDefault=pm.Point3(0)), Attr('Radius', float, CS.getRadius, CS.setRadius, initDefault=0.5), parent='CollisionSphere')
def OnNodeMouse1Down( self, planar, collEntry ): Base.OnNodeMouse1Down( self, planar, collEntry ) self._s = pm.Vec3( 0 ) # If in planar mode, clear the billboard effect on the center square # and make it face the selected axis axis = self.GetSelectedAxis() if self.planar and not axis.planar: self.square.clearBillboard() self.square.lookAt( self, pm.Point3( axis.vector ) ) else: self.square.setHpr( pm.Vec3(0, 0, 0) ) self.square.setBillboardPointEye()
def __init__(self, radius=1.0, numSegs=16, degrees=360, axis=pm.Vec3(1, 0, 0), thickness=1.0, origin=pm.Point3(0, 0, 0)): # Create line segments self.ls = pm.LineSegs() self.ls.setThickness(thickness) # Get the points for an arc for p in GetPointsForArc(degrees, numSegs): # Draw the point rotated around the desired axis p = pm.Point3(p[0], p[1], 0) - origin p = RotatePoint3(p, pm.Vec3(0, 0, 1), pm.Vec3(axis)) self.ls.drawTo(p * radius) # Init the node path, wrapping the lines node = self.ls.create() pm.NodePath.__init__(self, node)
def __init__(self, *args, **kwargs): Base.__init__(self, *args, **kwargs) self.AddAttributes(Attr('Origin', pm.Point3, CR.getOrigin, CR.setOrigin, initDefault=pm.Point3(0)), Attr('Direction', pm.Vec3, CR.getDirection, CR.setDirection, initDefault=pm.Vec3(0, 0, 1)), parent='CollisionRay')
def privGotSpec(self, levelSpec): DistCogdoLevelGame.privGotSpec(self, levelSpec) levelMgr = self.getEntity(LevelConstants.LevelMgrEntId) self.endVault = levelMgr.geom self.endVault.reparentTo(self.geomRoot) # Clear out unneeded backstage models from the EndVault, if # they're in the file. self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() # Flag the collisions in the end vault so safes and magnets # don't try to go through the wall. cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask | (PM.BitMask32.lowerOn(3) << 21)) # Find all the wall polygons and replace them with planes, # which are solid, so there will be zero chance of safes or # toons slipping through a wall. walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) # Initially, these new planar walls are stashed, so they don't # cause us trouble in the intro movie or in battle one. We # will unstash them when we move to battle three. self.evWalls.stash() # Also replace the floor polygon with a plane, and rename it # so we can detect a collision with it. floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') # Also, put a big plane across the universe a few feet below # the floor, to catch things that fall out of the world. plane = PM.CollisionPlane( PM.Plane(PM.Vec3(0, 0, 1), PM.Point3(0, 0, -50))) planeNode = PM.CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geomRoot.attachNewNode(planeNode)
def CreateArrow( self, vec, colour ): # Create the geometry and collision vec.normalize() line = pm.NodePath( Line( (0, 0, 0), vec ) ) cone = pm.NodePath( Cone( 0.05, 0.25, axis=vec, origin=vec * 0.125 ) ) collTube = pm.CollisionTube( (0,0,0), pm.Point3( vec ) * 0.95, 0.05 ) # Create the axis, add the geometry and collision axis = Axis( self.name, vec, colour ) axis.AddGeometry( line, sizeStyle=SCALE ) axis.AddGeometry( cone, vec, colour ) axis.AddCollisionSolid( collTube, sizeStyle=TRANSLATE_POINT_B ) axis.reparentTo( self ) return axis
def RecursePoly(node, geo): if isinstance(node, pm.EggPolygon): # Get each vert position poss = [] for vert in node.getVertices(): pos3 = vert.getPos3() pos = pm.Point3(pos3.getX(), pos3.getY(), pos3.getZ()) poss.append(pos) # Build lines geo.combineWith(Line(poss[0], poss[1])) geo.combineWith(Line(poss[1], poss[2])) geo.combineWith(Line(poss[2], poss[3])) geo.combineWith(Line(poss[3], poss[0])) # Recurse down hierarchy if hasattr(node, 'getChildren'): for child in node.getChildren(): RecursePoly(child, geo) return geo
def __init__(self): """Initialise the scene.""" # Show the framerate base.setFrameRateMeter(True) # Initialise terrain: # Make 4 terrain nodepath objects with different hilliness values # and arrange them side-by-side in a 2x2 grid, giving a big terrain # with variable hilly and flat areas. color = (0.6, 0.8, 0.5, 1) # Bright green-ish scale = 12 height = 18 # FIXME: For now we are raising the terrain so it # floats above the sea to prevent lakes from # appearing (but you still get them sometimes) t1 = Terrain(color=color, scale=scale, trees=0.7, pos=P.Point3(0, 0, height)) t1.prime.reparentTo(render) t2 = Terrain(color=color, scale=scale, h=24, pos=P.Point3(32 * scale, 0, height), trees=0.5) t2.prime.reparentTo(render) t3 = Terrain(color=color, scale=scale, h=16, pos=P.Point3(32 * scale, 32 * scale, height), trees=0.3) t3.prime.reparentTo(render) t4 = Terrain(color=color, scale=scale, h=2, pos=P.Point3(0, 32 * scale, height), trees=0.9) t4.prime.reparentTo(render) #tnp1.setPos(tnp1,-32,-32,terrainHeight) # Initialise sea sea = Sea() # Initialise skybox. self.box = loader.loadModel("models/skybox/space_sky_box.x") self.box.setScale(6) self.box.reparentTo(render) # Initialise characters self.characters = [] self.player = C.Character(model='models/eve', run='models/eve-run', walk='models/eve-walk') self.player.prime.setZ(100) self.player._pos = SteerVec(32 * 12 + random.random() * 100, 32 * 12 + random.random() * 100) self.player.maxforce = 0.4 self.player.maxspeed = 0.55 EdgeScreenTracker(self.player.prime, dist=200) # Setup camera for i in range(0, 11): self.characters.append(C.Character()) self.characters[i].prime.setZ(100) self.characters[i].wander() self.characters[i].maxforce = 0.3 self.characters[i].maxspeed = 0.2 self.characters[i]._pos = SteerVec(32 * 12 + random.random() * 100, 32 * 12 + random.random() * 100) C.setContainer( ContainerSquare(pos=SteerVec(32 * 12, 32 * 12), radius=31 * 12)) #C.toggleAnnotation() # Initialise keyboard controls. self.accept("c", C.toggleAnnotation) self.accept("escape", sys.exit) # Setup CollisionRay and CollisionHandlerQueue for mouse picking. self.pickerQ = P.CollisionHandlerQueue() self.picker = camera.attachNewNode( P.CollisionNode('Picker CollisionNode')) self.picker.node().addSolid(P.CollisionRay()) # We want the picker ray to collide with the floor and nothing else. self.picker.node().setFromCollideMask(C.floorMASK) self.picker.setCollideMask(P.BitMask32.allOff()) base.cTrav.addCollider(self.picker, self.pickerQ) try: handler.addCollider(self.picker, camera) except: pass self.accept('mouse1', self.onClick) # Set the far clipping plane to be far enough away that we can see the # skybox. base.camLens.setFar(10000) # Initialise lighting self.alight = AmbientLight('alight') self.alight.setColor(VBase4(0.35, 0.35, 0.35, 1)) self.alnp = render.attachNewNode(self.alight) render.setLight(self.alnp) self.dlight = DirectionalLight('dlight') self.dlight.setColor(VBase4(0.4, 0.4, 0.4, 1)) self.dlnp = render.attachNewNode(self.dlight) self.dlnp.setHpr(45, -45, 0) render.setLight(self.dlnp) self.plight = PointLight('plight') self.plight.setColor(VBase4(0.8, 0.8, 0.5, 1)) self.plnp = render.attachNewNode(self.plight) self.plnp.setPos(160, 160, 50) self.slight = Spotlight('slight') self.slight.setColor(VBase4(1, 1, 1, 1)) lens = PerspectiveLens() self.slight.setLens(lens) self.slnp = render.attachNewNode(self.slight) self.slnp.setPos(-20, -20, 20) self.slnp.lookAt(50, 50, 0) # Initialise some scene-wide exponential fog colour = (0.5, 0.8, 0.8) self.expfog = Fog("Scene-wide exponential Fog object") self.expfog.setColor(*colour) self.expfog.setExpDensity(0.0005) render.setFog(self.expfog) base.setBackgroundColor(*colour) # Add a task for this Plant to the global task manager. self.stepcount = 0 taskMgr.add(self.step, "Plant step task")
def Sphere(radius=1.0, numSegs=16, degrees=360, axis=pm.Vec3(0, 0, 1), origin=pm.Point3(0, 0, 0)): """Return a geom node representing a cylinder.""" # Create vetex data format gvf = pm.GeomVertexFormat.getV3n3() gvd = pm.GeomVertexData('vertexData', gvf, pm.Geom.UHStatic) # Create vetex writers for each type of data we are going to store gvwV = pm.GeomVertexWriter(gvd, 'vertex') gvwN = pm.GeomVertexWriter(gvd, 'normal') # Get the points for an arc axis = pm.Vec3(axis) axis.normalize() points = GetPointsForArc(degrees, numSegs, True) zPoints = GetPointsForArc(180, numSegs / 2, True) for z in range(1, len(zPoints) - 2): rad1 = zPoints[z][1] * radius rad2 = zPoints[z + 1][1] * radius offset1 = axis * zPoints[z][0] * radius offset2 = axis * zPoints[z + 1][0] * radius for i in range(len(points) - 1): # Get points p1 = pm.Point3(points[i][0], points[i][1], 0) * rad1 p2 = pm.Point3(points[i + 1][0], points[i + 1][1], 0) * rad1 p3 = pm.Point3(points[i + 1][0], points[i + 1][1], 0) * rad2 p4 = pm.Point3(points[i][0], points[i][1], 0) * rad2 # Rotate the points around the desired axis p1, p2, p3, p4 = [ RotatePoint3(p, pm.Vec3(0, 0, 1), axis) for p in [p1, p2, p3, p4] ] a = p1 + offset1 - origin b = p2 + offset1 - origin c = p3 + offset2 - origin d = p4 + offset2 - origin # Quad gvwV.addData3f(d) gvwV.addData3f(b) gvwV.addData3f(a) gvwV.addData3f(d) gvwV.addData3f(c) gvwV.addData3f(b) # Normals cross = (b - c).cross(a - c) for i in range(6): gvwN.addData3f(cross) # Get points rad1 = zPoints[1][1] * radius for m in [1, -2]: offset1 = axis * zPoints[m][0] * radius clampedM = max(-1, min(m, 1)) * radius for i in range(len(points) - 1): p1 = pm.Point3(points[i][0], points[i][1], 0) * rad1 p2 = pm.Point3(points[i + 1][0], points[i + 1][1], 0) * rad1 # Rotate the points around the desired axis p1, p2 = [ RotatePoint3(p, pm.Vec3(0, 0, 1), axis) for p in [p1, p2] ] a = p1 + offset1 - origin b = p2 + offset1 - origin c = -axis * clampedM # Quad if clampedM > 0: gvwV.addData3f(a) gvwV.addData3f(b) gvwV.addData3f(c) else: gvwV.addData3f(c) gvwV.addData3f(b) gvwV.addData3f(a) # Normals cross = (b - c).cross(a - c) for i in range(3): gvwN.addData3f(cross * -m) geom = pm.Geom(gvd) for i in range(0, gvwV.getWriteRow(), 3): # Create and add triangle geom.addPrimitive(GetGeomTriangle(i, i + 1, i + 2)) # Return the cylinder GeomNode geomNode = pm.GeomNode('cylinder') geomNode.addGeom(geom) return geomNode
def Str2Point3(string): buffer = string.split(' ') return pm.Point3(*[float(buffer[i]) for i in range(3)])
def Transform( self ): axis = self.GetSelectedAxis() axisPoint = self.GetAxisPoint( axis ) # Calculate delta and snapping. d = axisPoint - self.lastAxisPoint lastSnap = self._Snap( self._s ) self._s += d thisSnap = self._Snap( self._s ) if self._snp: # If snapping in planar mode or using the camera axis, snap to a # point on the ground plane. if axis.vector == CAMERA_VECTOR or self.planar: pnt = self.GetMousePlaneCollisionPoint( pm.Point3( 0 ), pm.Vec3( 0, 0, 1 ) ) pnt = utils.SnapPoint( pnt, self._snpAmt ) self.setPos( render, pnt ) for np in self.attachedNps: np.setPos( render, pnt ) return # If snapping in world space, construct a plane where the mouse # clicked the axis and move all NodePaths so they intersect it. elif not self.local: pnt = utils.SnapPoint( self.startAxisPoint + d, self._snpAmt ) pl = pm.Plane( axis.vector, pm.Point3( pnt ) ) self.setPos( render, pl.project( self.getPos( render ) ) ) for np in self.attachedNps: np.setPos( render, pl.project( np.getPos( render ) ) ) return # Gone over the snap threshold - set the delta to the snap amount. elif thisSnap.compareTo( lastSnap, TOL ): d.normalize() d *= self._snpAmt # BUG - need to resize to compensate for cam dist? # In snapping mode but haven't gone past the snap threshold. else: d = pm.Vec3( 0 ) d = self.getRelativeVector( self.rootNp, d ) self.setMat( pm.Mat4().translateMat( d ) * self.getMat() ) # Adjust the size of delta by the gizmo size to get real world units. d = utils.ScalePoint( d, self.getScale() ) # Hack for fixing camera vector xforming in local mode. if self.local and axis.vector == CAMERA_VECTOR: d = self.rootNp.getRelativeVector( self, d ) d = utils.ScalePoint( d, self.getScale(), True ) # Xform attached NodePaths. for np in ( self.attachedNps ): if self.local and axis.vector != CAMERA_VECTOR: sclD = utils.ScalePoint( d, np.getScale( self.rootNp ), True ) np.setMat( pm.Mat4().translateMat( sclD ) * np.getMat() ) else: np.setMat( self.rootNp, np.getMat( self.rootNp ) * pm.Mat4().translateMat( d ) ) self.lastAxisPoint = axisPoint