diff --git a/direct/src/directnotify/Notifier.py b/direct/src/directnotify/Notifier.py index 7ed5ae6144..5b3be84967 100644 --- a/direct/src/directnotify/Notifier.py +++ b/direct/src/directnotify/Notifier.py @@ -4,6 +4,7 @@ from LoggerGlobal import * from direct.showbase import PythonUtil import time +import types class Notifier: serverDelta = 0 @@ -194,7 +195,7 @@ class Notifier: could put it here. """ print string - + def debugStateCall(self, obj=None, fsmMemberName='fsm'): """ If this notify is in debug mode, print the time of the @@ -207,11 +208,15 @@ class Notifier: if hasattr(obj, fsmMemberName) and obj.fsm.getCurrentState() is not None: #state = "%s=%s"%(obj.fsm.getName(), obj.fsm.getCurrentState().getName()) state = obj.fsm.getCurrentState().getName() - string = ":%s [%-7s] %s %s.%s"%( + if 1 or type(obj) == types.ClassType: + name = "%s."%(obj.__class__.__name__,) + else: + name = "%s "%(self.__name,) + string = ":%s [%-7s] %s %s%s"%( self.getOnlyTime(), state, id(obj), - self.__name, + name, PythonUtil.traceParentCall()) self.__log(string) self.__print(string) diff --git a/direct/src/distributed/ClientRepository.py b/direct/src/distributed/ClientRepository.py index 3d6a5c7d3c..1590ce2708 100644 --- a/direct/src/distributed/ClientRepository.py +++ b/direct/src/distributed/ClientRepository.py @@ -31,6 +31,10 @@ class ClientRepository(ConnectionRepository.ConnectionRepository): self.bootedIndex = None self.bootedText = None + self.worldScale = render.attachNewNode("worldScale") # for grid zones. + self.worldScale.setScale(base.config.GetFloat('world-scale', 100)) + self.priorWorldPos = None + # create a parentMgr to handle distributed reparents # this used to be 'token2nodePath' self.parentMgr = ParentMgr.ParentMgr() @@ -65,6 +69,40 @@ class ClientRepository(ConnectionRepository.ConnectionRepository): self.disconnect() self.stopHeartbeat() + def setWorldOffset(self, xOffset=0, yOffset=0): + self.worldXOffset=xOffset + self.worldYOffset=yOffset + + def getWorldPos(self, nodePath): + pos = nodePath.getPos(self.worldScale) + return (int(round(pos.getX())), int(round(pos.getY()))) + + def sendWorldPos(self, x, y): + # The server will need to know the world + # offset of our current render node path + # and adjust the x, y accordingly. At one + # point I considered adding the world offset + # here, but that would just use extra bits. + + onScreenDebug.add("worldPos", "%-4d, %-4d"%(x, y)) + return #*# + + datagram = PyDatagram() + # Add message type + datagram.addUint16(CLIENT_SET_WORLD_POS) + # Add x + datagram.addInt16(x) + # Add y + datagram.addSint16(y) + # send the message + self.send(datagram) + + def checkWorldPos(self, nodePath): + worldPos = self.getWorldPos(nodePath) + if self.priorWorldPos != worldPos: + self.priorWorldPos = worldPos + self.sendWorldPos(worldPos[0], worldPos[1]) + def setServerDelta(self, delta): """ Indicates the approximate difference in seconds between the @@ -408,6 +446,175 @@ class ClientRepository(ConnectionRepository.ConnectionRepository): # send the message self.send(datagram) + def gridZoneCenter(self, x, y, zoneBase=0, resolution=500): + """ + x is a float in the range 0.0 to 1.0 + y is a float in the range 0.0 to 1.0 + resolution is the number of cells on each axsis. + """ + if x < 0.0 or x > 1.0 or y < 0.0 or y > 1.0: + return None + resolution=int(resolution) + print "resolution", resolution, + xCell=min(int(x*resolution), resolution-1) + yCell=min(int(y*resolution), resolution-1) + cell=yCell*resolution+xCell + print "cell", cell, + zone=zoneBase+cell + print "zone", zone + assert zone >= zoneBase and zone < zoneBase+resolution*resolution + return zone + + def gridZoneList(self, x, y, zoneBase=0, zoneList=[], resolution=500): + """ + x is a float in the range 0.0 to 1.0 + y is a float in the range 0.0 to 1.0 + resolution is the number of cells on each axsis. + returns a list of zone ids. + + Create a box of cell numbers, while clipping + to the edges of the set of cells. + """ + if x < 0.0 or x > 1.0 or y < 0.0 or y > 1.0: + return None + resolution=int(resolution) + print "resolution", resolution, + xCell=min(int(x*resolution), resolution-1) + yCell=min(int(y*resolution), resolution-1) + cell=yCell*resolution+xCell + print "cell", cell, + zone=zoneBase+cell + print "zone", zone + + zone=zone-2*resolution + endZone=zone+5*resolution + yCell=yCell-2 + while zone < endZone: + if yCell >= 0 and yCell < resolution: + if xCell > 1: + zoneList.append(zone-2) + zoneList.append(zone-1) + elif xCell > 0: + zoneList.append(zone-1) + r.append(zone) + if xCell < resolution-2: + zoneList.append(zone+1) + zoneList.append(zone+2) + elif xCell < resolution-1: + zoneList.append(zone+1) + yCell+=1 + zone+=resolution + return zoneList + + def gridZone(self, zoneId, pos): + """ + zoneId is an integer. + pos is a Vec3 with x,y,z float values. + + Figure out which zones in the multi-zone heirarchy + the avatar is currently. Use sendSetZoneMsg() to + send the info to the server. + + So, one possibility is to use a 3x3 grid and have + each cell be the movement distance in the load time + plus the vision distance. + + Another possibility is to use a 5x5 grid and have + each cell be the greater of the movement distance + or the vision distance. + + Yet another possibility is to use a nxn grid inside + of a mxm grid. The nxn grid is used to add cells + to the visible set, while the mxm grid is used to + retain old cells a little longer. This avoids + jitter (i.e. rapid generation and deletion of zones + as the avatar runs down the line separating two cells). + Also, the mxm grid is not neccessarily + full (and is likely not to be full). So, cell in + the nxn grid are added and cells outside of the + mxm grid are removed. + + When choosing a method, the generation (inlcluding + loading and setup) time should be compared to the + cost of having extra distributed objects. + + The third option optimizes for expensive generation, + while the second option optimizes for epensive + maintenance. + + o o o o o o o + o o o o o o o + o o[k k o]o o + o o|k a a|o o + o o[o a a]o o + o o o o o o o + o o o o o o o + """ + # The teirs are offset from each other to spread the + # generates. + width=2000.0 + height=2000.0 + teirBase=1000 + # The teirBase is a teir unto itself, all avatars in + # in the given teir system are also in the main teir: + r=[teirBase] + teirBase+=1 + + x=pos.getX()/width + y=pos.getY()/height + getGridZones(x, y, teirBase, r, 500) + + return r + + #*# + # The teirs are offset from each other to spread the + # generates. + width=2000.0 + height=2000.0 + teirs=[20, 100, 500] + teirOffsets=[0.33, 0.5, 0.0] + teirBase=1000 + # The teirBase is a teir unto itself, all avatars in + # in the given teir system are also in the main teir: + r=[teirBase] + teirBase+=1 + + x=pos.getX() + y=pos.getY() + for i, offset in zip(teirs, teirOffsets): + print "teirBase", teirBase, + xCell=min(int((x-width/i*offset)/i), i-1) + yCell=min(int((y-height/i*offset)/i), i-1) + print "xCell", xCell, "yCell", yCell, + cell=yCell*i+xCell + print "cell", cell, + zone=teirBase+cell + print "zone", zone + #for zone in range(teirBase+cell, teirBase+cell+5*i, i): + zone=zone-2*i + endZone=teirBase+cell+5*i + yCell=yCell-2 + while zone < endZone: + if yCell >= 0 and yCell < i: + if xCell > 1: + r.append(zone-2) + r.append(zone-1) + elif xCell > 0: + r.append(zone-1) + r.append(zone) + if xCell < i-2: + r.append(zone+1) + r.append(zone+2) + elif xCell < i-1: + r.append(zone+1) + yCell+=1 + zone+=i + print "" + teirBase+=i*i + print "teirBase", teirBase + + return r + def handleDatagram(self, di): if self.notify.getDebug(): print "ClientRepository received datagram:" diff --git a/direct/src/distributed/MsgTypes.py b/direct/src/distributed/MsgTypes.py index 06737250bf..9a0606b147 100644 --- a/direct/src/distributed/MsgTypes.py +++ b/direct/src/distributed/MsgTypes.py @@ -69,6 +69,8 @@ CLIENT_SET_AVTYPE = 80 CLIENT_GET_PET_DETAILS = 81 CLIENT_GET_PET_DETAILS_RESP = 82 +CLIENT_SET_WORLD_POS = 83 + # These messages are ignored when the client is headed to the quiet zone QUIET_ZONE_IGNORED_LIST = [ diff --git a/direct/src/particles/ParticleEffect.py b/direct/src/particles/ParticleEffect.py index 42f76ea767..75b323d668 100644 --- a/direct/src/particles/ParticleEffect.py +++ b/direct/src/particles/ParticleEffect.py @@ -124,7 +124,6 @@ class ParticleEffect(NodePath): particles.addForce(fg[i]) def removeParticles(self, particles): - """removeParticles(particles)""" if (particles == None): self.notify.warning('removeParticles() - particles == None!') return @@ -141,23 +140,18 @@ class ParticleEffect(NodePath): self.removeParticles(p) def getParticlesList(self): - """getParticles()""" return self.particlesDict.values() def getParticlesNamed(self, name): - """getParticlesNamed(name)""" return self.particlesDict.get(name, None) def getParticlesDict(self): - """getParticlesDict()""" return self.particlesDict def getForceGroupList(self): - """getForceGroup()""" return self.forceGroupDict.values() def getForceGroupNamed(self, name): - """getForceGroupNamed(name)""" return self.forceGroupDict.get(name, None) def getForceGroupDict(self): diff --git a/direct/src/particles/ParticleTest.py b/direct/src/particles/ParticleTest.py index bab8326765..6bd51d9e37 100644 --- a/direct/src/particles/ParticleTest.py +++ b/direct/src/particles/ParticleTest.py @@ -1,4 +1,4 @@ -from direct.directbase.DirectStart import * +from direct.directbase.TestStart import * from pandac.LinearVectorForce import LinearVectorForce from pandac.Vec3 import Vec3 @@ -10,15 +10,17 @@ import ForceGroup base.enableParticles() # ForceGroup -gravity = LinearVectorForce(Vec3(0.0, 0.0, -10.0)) fg = ForceGroup.ForceGroup() -fg.addForce(gravity) +if 0: + gravity = LinearVectorForce(Vec3(0.0, 0.0, -10.0)) + fg.addForce(gravity) # Particle effect pe = ParticleEffect.ParticleEffect('particle-fx') pe.reparentTo(render) -pe.setPos(0.0, 5.0, 4.0) +#pe.setPos(0.0, 5.0, 4.0) pe.addForceGroup(fg) # Particle Panel -pp = ParticlePanel.ParticlePanel(pe) +#*#pp = ParticlePanel.ParticlePanel(pe) +pp = ParticlePanel.ParticlePanel() diff --git a/direct/src/particles/Particles.py b/direct/src/particles/Particles.py index 32d0ba670b..2c3719cc08 100644 --- a/direct/src/particles/Particles.py +++ b/direct/src/particles/Particles.py @@ -34,8 +34,6 @@ class Particles(ParticleSystem.ParticleSystem): id = 1 def __init__(self, name=None, poolSize=1024): - """__init__(name, poolSize)""" - if (name == None): self.name = 'particles-%d' % Particles.id Particles.id += 1 @@ -80,14 +78,12 @@ class Particles(ParticleSystem.ParticleSystem): del self.emitter def enable(self): - """enable()""" if (self.fEnabled == 0): physicsMgr.attachPhysical(self) particleMgr.attachParticlesystem(self) self.fEnabled = 1 def disable(self): - """disable()""" if (self.fEnabled == 1): physicsMgr.removePhysical(self) particleMgr.removeParticlesystem(self) @@ -100,7 +96,6 @@ class Particles(ParticleSystem.ParticleSystem): return self.node def setFactory(self, type): - """setFactory(type)""" if (self.factoryType == type): return None if (self.factory): @@ -119,7 +114,6 @@ class Particles(ParticleSystem.ParticleSystem): ParticleSystem.ParticleSystem.setFactory(self, self.factory) def setRenderer(self, type): - """setRenderer(type)""" if (self.rendererType == type): return None if (self.renderer): @@ -188,14 +182,12 @@ class Particles(ParticleSystem.ParticleSystem): ParticleSystem.ParticleSystem.setEmitter(self, self.emitter) def addForce(self, force): - """addForce(force)""" if (force.isLinear()): self.addLinearForce(force) else: self.addAngularForce(force) def removeForce(self, force): - """removeForce(force)""" if (force == None): self.notify.warning('removeForce() - force == None!') return @@ -209,20 +201,18 @@ class Particles(ParticleSystem.ParticleSystem): ## Getters ## def getName(self): - """getName()""" return self.name + def getFactory(self): - """getFactory()""" return self.factory + def getEmitter(self): - """getEmitter()""" return self.emitter + def getRenderer(self): - """getRenderer()""" return self.renderer def printParams(self, file = sys.stdout, targ = 'self'): - """printParams(file, targ)""" file.write('# Particles parameters\n') file.write(targ + '.setFactory(\"' + self.factoryType + '\")\n') file.write(targ + '.setRenderer(\"' + self.rendererType + '\")\n') diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index a8706c9765..c4377548e8 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -979,8 +979,9 @@ class ShowBase(DirectObject.DirectObject): aspectRatio = self.getAspectRatio() # Scale the smiley face to 32x32 pixels. - lilsmiley.setScale(32.0 / self.win.getHeight() / aspectRatio, - 1.0, 32.0 / self.win.getHeight()) + lilsmiley.setScale( + 32.0 / self.win.getHeight() / aspectRatio, + 1.0, 32.0 / self.win.getHeight()) #self.mouseWatcherNode.setGeometry(mouseViz) def getAlt(self): @@ -1272,7 +1273,6 @@ class ShowBase(DirectObject.DirectObject): The color may be either a VBase3 or a VBase4, or a 3-component tuple, or the individual r, g, b parameters. """ - if g != None: color = VBase4(r, g, b, 1.0) else: @@ -1410,10 +1410,8 @@ class ShowBase(DirectObject.DirectObject): This is a toggle; the second time this function is called, it disables the mode. """ - # If oobeMode was never set, set it to false and create the # structures we need to implement OOBE. - try: self.oobeMode except: @@ -1438,7 +1436,6 @@ class ShowBase(DirectObject.DirectObject): if self.oobeMode: # Disable OOBE mode. - if self.oobeCullFrustum != None: # First, disable OOBE cull mode. self.oobeCull() @@ -1485,7 +1482,6 @@ class ShowBase(DirectObject.DirectObject): it were still attached to our original camera. This allows us to visualize the effectiveness of our bounding volumes. """ - # First, make sure OOBE mode is enabled. try: if not self.oobeMode: @@ -1509,7 +1505,6 @@ class ShowBase(DirectObject.DirectObject): # Tell the camera to cull from here instead of its own # origin. self.camNode.setCullCenter(self.oobeCullFrustum) - else: # Disable OOBE culling. @@ -1591,7 +1586,6 @@ class ShowBase(DirectObject.DirectObject): # stop the music. self.mainWinMinimized = 1 messenger.send('PandaPaused') - elif not properties.getMinimized() and self.mainWinMinimized: # If the main window is restored, throw an event to # restart the music. diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 972c123d44..1da7403e69 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -2,7 +2,7 @@ from ShowBase import * -CollisionHandlerRayStart = 10.0 # This is a hack, it may be better to use a line instead of a ray. +CollisionHandlerRayStart = 4000.0 # This is a hack, it may be better to use a line instead of a ray. # Create the showbase instance # This should be created by the game specific "start" file diff --git a/direct/src/showbase/showBase.cxx b/direct/src/showbase/showBase.cxx index 1f93ee9117..c27dffb685 100644 --- a/direct/src/showbase/showBase.cxx +++ b/direct/src/showbase/showBase.cxx @@ -87,3 +87,130 @@ query_fullscreen_testresult(int xsize, int ysize) { return false; } +#if 0 +int TempGridZoneManager:: +add_grid_zone(unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + unsigned int zoneBase, + unsigned int xZoneResolution, + unsigned int yZoneResolution) { + // zoneBase is the first zone in the grid (e.g. the upper left) + // zoneResolution is the number of cells on each axsis. + // returns the next available zoneBase (i.e. zoneBase+xZoneResolution*yZoneResolution) + cerr<<"adding grid zone with a zoneBase of "<= i._xMinVis && x < i._xMaxVis && y >= i._yMinVis && y < i._yMaxVis) { + add_to_zone_list(i, x, y, canSee); + } + } +} + +void TempGridZoneManager:: +add_to_zone_list(const TempGridZoneManager::GridZone &gridZone, + unsigned int x, + unsigned int y, + TempGridZoneManager::ZoneSet &zoneSet) { + unsigned int xRes=gridZone._xZoneResolution; + unsigned int yRes=gridZone._yZoneResolution; + float xP=((float)(x-gridZone._x))/gridZone._width; + float yP=((float)(y-gridZone._y))/gridZone._height; + int xCell=(int)(xP*xRes); + int yCell=(int)(yP*yRes); + + // range is how many cells can be seen in each direction: + const int range=2; + int yBegin=max(0, yCell-range); + int yEnd=min(yRes, yCell+range); + int xBegin=max(0, xCell-range); + int xEnd=min(xRes, xCell+range); + unsigned int zone=gridZone._zoneBase+yBegin*xRes+xBegin; + + for (yCell=yBegin; yCell < yEnd; ++yCell) { + for (xCell=xBegin; xCell < xEnd; ++xCell) { + zoneSet.append(zone+xCell); + } + zone+=xRes; + } +} + +int TempGridZoneManager:: +get_zone_list(int x, int y, int resolution) { + // x is a float in the range 0.0 to 1.0 + // y is a float in the range 0.0 to 1.0 + // resolution is the number of cells on each axsis. + // returns a list of zone ids. + // + // Create a box of cell numbers, while clipping + // to the edges of the set of cells. + if (x < 0.0 || x > 1.0 || y < 0.0 || y > 1.0) { + return 0; + } + cerr<<"resolution="<= 0 and yCell < resolution: + if xCell > 1: + zoneList.append(zone-2) + zoneList.append(zone-1) + elif xCell > 0: + zoneList.append(zone-1) + r.append(zone) + if xCell < resolution-2: + zoneList.append(zone+1) + zoneList.append(zone+2) + elif xCell < resolution-1: + zoneList.append(zone+1) + yCell+=1 + zone+=resolution + return zoneList + return 5; +} +#endif + diff --git a/direct/src/showbase/showBase.h b/direct/src/showbase/showBase.h index b825c5e2af..a3cdeb9897 100644 --- a/direct/src/showbase/showBase.h +++ b/direct/src/showbase/showBase.h @@ -53,4 +53,42 @@ EXPCL_DIRECT bool query_fullscreen_testresult(int xsize, int ysize); END_PUBLISH + +#if 0 +class TempGridZoneManager { +PUBLISHED: + TempGridZoneManager() {} + ~TempGridZoneManager() {} + + unsigned int add_grid_zone( + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + unsigned int zoneBase, + unsigned int xZoneResolution, + unsigned int yZoneResolution); + int get_zone_list(int x, int y); + +protected: + class GridZone { + public: + unsigned int base; + unsigned int resolution; + GridZone( + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + unsigned int zoneBase, + unsigned int xZoneResolution, + unsigned int yZoneResolution) { + base=zoneBase; + resolution=zoneResolution; + } + }; + Set _grids; +}; +#endif + #endif