Lots of work to make the rtdist work with the new library building system
This commit is contained in:
parent
88dbb31daa
commit
0aa0f34c74
|
|
@ -4,7 +4,7 @@ for the programmer/user
|
|||
"""
|
||||
from LoggerGlobal import defaultLogger
|
||||
from direct.showbase import PythonUtil
|
||||
from panda3d.core import ConfigVariableBool
|
||||
from panda3d.core import ConfigVariableBool, NotifyCategory, StreamWriter, Notify
|
||||
import time
|
||||
import types
|
||||
import sys
|
||||
|
|
@ -18,9 +18,8 @@ class Notifier:
|
|||
# with the C++ notify system.
|
||||
streamWriter = None
|
||||
if ConfigVariableBool('notify-integrate', True):
|
||||
from panda3d.core import StreamWriter, Notify
|
||||
streamWriter = StreamWriter(Notify.out(), False)
|
||||
|
||||
|
||||
showTime = ConfigVariableBool('notify-timestamp', False)
|
||||
|
||||
def __init__(self, name, logger=None):
|
||||
|
|
@ -44,9 +43,6 @@ class Notifier:
|
|||
self.__warning = 1
|
||||
self.__debug = 0
|
||||
self.__logging = 0
|
||||
|
||||
|
||||
|
||||
|
||||
def setServerDelta(self, delta, timezone):
|
||||
"""
|
||||
|
|
@ -62,7 +58,6 @@ class Notifier:
|
|||
# The following call is necessary to make the output from C++
|
||||
# notify messages show the same timestamp as those generated
|
||||
# from Python-level notify messages.
|
||||
from pandac.PandaModules import NotifyCategory
|
||||
NotifyCategory.setServerDelta(self.serverDelta)
|
||||
|
||||
self.info("Notify clock adjusted by %s (and timezone adjusted by %s hours) to synchronize with server." % (PythonUtil.formatElapsedSeconds(delta), (time.timezone - timezone) / 3600))
|
||||
|
|
@ -92,7 +87,7 @@ class Notifier:
|
|||
|
||||
# Severity funcs
|
||||
def setSeverity(self, severity):
|
||||
from pandac.PandaModules import NSDebug, NSInfo, NSWarning, NSError
|
||||
from panda3d.core import NSDebug, NSInfo, NSWarning, NSError
|
||||
if severity >= NSError:
|
||||
self.setWarning(0)
|
||||
self.setInfo(0)
|
||||
|
|
@ -111,7 +106,7 @@ class Notifier:
|
|||
self.setDebug(1)
|
||||
|
||||
def getSeverity(self):
|
||||
from pandac.PandaModules import NSDebug, NSInfo, NSWarning, NSError
|
||||
from panda3d.core import NSDebug, NSInfo, NSWarning, NSError
|
||||
if self.getDebug():
|
||||
return NSDebug
|
||||
elif self.getInfo():
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ def doGetopts():
|
|||
doSqueeze = False
|
||||
elif (flag == '-s'):
|
||||
deleteSourceAfterSqueeze = False
|
||||
|
||||
|
||||
else:
|
||||
FFIConstants.notify.error('illegal option: ' + flag)
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ def doGetopts():
|
|||
if codeLib not in newLibs:
|
||||
newLibs.append(codeLib)
|
||||
codeLibs = newLibs
|
||||
|
||||
|
||||
|
||||
def doErrorCheck():
|
||||
global outputCodeDir
|
||||
|
|
@ -278,9 +278,9 @@ def generateNativeWrappers():
|
|||
# in the runtime (plugin) environment, where all libraries are
|
||||
# not necessarily downloaded.
|
||||
if sys.version_info >= (3, 0):
|
||||
pandaModules.write('try:\n from .%s import *\nexcept ImportError as err:\n if "DLL loader cannot find" not in str(err):\n raise\n' % (metaModuleName))
|
||||
pandaModules.write('try:\n from .%s import *\nexcept ImportError as err:\n if "DLL loader cannot find" not in str(err):\n raise\n' % (metaModuleName))
|
||||
else:
|
||||
pandaModules.write('try:\n from %s import *\nexcept ImportError, err:\n if "DLL loader cannot find" not in str(err):\n raise\n' % (metaModuleName))
|
||||
pandaModules.write('try:\n from %s import *\nexcept ImportError, err:\n if "DLL loader cannot find" not in str(err):\n raise\n' % (metaModuleName))
|
||||
|
||||
# Not sure if this message is helpful or annoying.
|
||||
#pandaModules.write(' print("Failed to import %s")\n' % (moduleName))
|
||||
|
|
@ -306,7 +306,7 @@ def generateNativeWrappers():
|
|||
extension = open(extensionFilename, 'r')
|
||||
moduleModules.write(extension.read())
|
||||
moduleModules.write('\n')
|
||||
|
||||
|
||||
|
||||
def run():
|
||||
global outputCodeDir
|
||||
|
|
|
|||
|
|
@ -25,16 +25,13 @@ if 'VFSImporter' in sys.modules:
|
|||
direct.showbase.VFSImporter = VFSImporter
|
||||
sys.modules['direct.showbase.VFSImporter'] = VFSImporter
|
||||
else:
|
||||
# Otherwise, we can import the VFSImporter normally. We have to
|
||||
# import PandaModules first, to get the funny renaming with
|
||||
# pandaexpress.
|
||||
import direct
|
||||
from pandac import PandaModules
|
||||
# Otherwise, we can import the VFSImporter normally.
|
||||
from direct.showbase import VFSImporter
|
||||
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, ConfigPageManager, initAppForGui
|
||||
from pandac import PandaModules
|
||||
from panda3d.core import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, ConfigPageManager
|
||||
from panda3d.direct import init_app_for_gui
|
||||
from panda3d import core
|
||||
from direct.stdpy import file, glob
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
|
|
@ -83,7 +80,7 @@ class AppRunner(DirectObject):
|
|||
|
||||
# Also from p3d_plugin.h
|
||||
P3D_CONTENTS_DEFAULT_MAX_AGE = 5
|
||||
|
||||
|
||||
def __init__(self):
|
||||
DirectObject.__init__(self)
|
||||
|
||||
|
|
@ -119,8 +116,8 @@ class AppRunner(DirectObject):
|
|||
self.windowPrc = None
|
||||
|
||||
self.http = None
|
||||
if hasattr(PandaModules, 'HTTPClient'):
|
||||
self.http = PandaModules.HTTPClient.getGlobalPtr()
|
||||
if hasattr(core, 'HTTPClient'):
|
||||
self.http = core.HTTPClient.getGlobalPtr()
|
||||
|
||||
self.Undefined = Undefined
|
||||
self.ConcreteStruct = ConcreteStruct
|
||||
|
|
@ -213,7 +210,7 @@ class AppRunner(DirectObject):
|
|||
# this instance, e.g. the WindowProperties necessary to
|
||||
# re-embed a window in the browser frame.
|
||||
self.windowProperties = None
|
||||
|
||||
|
||||
# Store our pointer so DirectStart-based apps can find us.
|
||||
if AppRunnerGlobal.appRunner is None:
|
||||
AppRunnerGlobal.appRunner = self
|
||||
|
|
@ -263,7 +260,7 @@ class AppRunner(DirectObject):
|
|||
value = bool(value)
|
||||
return value
|
||||
|
||||
|
||||
|
||||
|
||||
def installPackage(self, packageName, version = None, hostUrl = None):
|
||||
|
||||
|
|
@ -353,7 +350,7 @@ class AppRunner(DirectObject):
|
|||
|
||||
# No shenanigans, just return the requested host.
|
||||
return host
|
||||
|
||||
|
||||
def getHost(self, hostUrl, hostDir = None):
|
||||
""" Returns a new HostInfo object corresponding to the
|
||||
indicated host URL. If we have already seen this URL
|
||||
|
|
@ -419,7 +416,7 @@ class AppRunner(DirectObject):
|
|||
# the host directory too.
|
||||
del self.hosts[hostUrl]
|
||||
self.__deleteHostFiles(host)
|
||||
|
||||
|
||||
return packages
|
||||
|
||||
def __deleteHostFiles(self, host):
|
||||
|
|
@ -431,7 +428,7 @@ class AppRunner(DirectObject):
|
|||
self.rmtree(host.hostDir)
|
||||
|
||||
self.sendRequest('forget_package', host.hostUrl, '', '')
|
||||
|
||||
|
||||
|
||||
def freshenFile(self, host, fileSpec, localPathname):
|
||||
""" Ensures that the localPathname is the most current version
|
||||
|
|
@ -449,18 +446,18 @@ class AppRunner(DirectObject):
|
|||
doc = None
|
||||
if self.superMirrorUrl:
|
||||
# Use the "super mirror" first.
|
||||
url = PandaModules.URLSpec(self.superMirrorUrl + fileSpec.filename)
|
||||
url = core.URLSpec(self.superMirrorUrl + fileSpec.filename)
|
||||
self.notify.info("Freshening %s" % (url))
|
||||
doc = self.http.getDocument(url)
|
||||
|
||||
|
||||
if not doc or not doc.isValid():
|
||||
# Failing the super mirror, contact the actual host.
|
||||
url = PandaModules.URLSpec(host.hostUrlPrefix + fileSpec.filename)
|
||||
url = core.URLSpec(host.hostUrlPrefix + fileSpec.filename)
|
||||
self.notify.info("Freshening %s" % (url))
|
||||
doc = self.http.getDocument(url)
|
||||
if not doc.isValid():
|
||||
return False
|
||||
|
||||
|
||||
file = Filename.temporary('', 'p3d_')
|
||||
if not doc.downloadToFile(file):
|
||||
# Failed to download.
|
||||
|
|
@ -522,12 +519,11 @@ class AppRunner(DirectObject):
|
|||
""" Reads the config.xml file that may be present in the root
|
||||
directory. """
|
||||
|
||||
if not hasattr(PandaModules, 'TiXmlDocument'):
|
||||
if not hasattr(core, 'TiXmlDocument'):
|
||||
return
|
||||
from pandac.PandaModules import TiXmlDocument
|
||||
|
||||
filename = Filename(self.rootDir, self.ConfigBasename)
|
||||
doc = TiXmlDocument(filename.toOsSpecific())
|
||||
doc = core.TiXmlDocument(filename.toOsSpecific())
|
||||
if not doc.LoadFile():
|
||||
return
|
||||
|
||||
|
|
@ -544,7 +540,7 @@ class AppRunner(DirectObject):
|
|||
called automatically; an application may call this after
|
||||
adjusting some parameters (such as self.maxDiskUsage). """
|
||||
|
||||
from pandac.PandaModules import TiXmlDocument, TiXmlDeclaration, TiXmlElement
|
||||
from panda3d.core import TiXmlDocument, TiXmlDeclaration, TiXmlElement
|
||||
|
||||
filename = Filename(self.rootDir, self.ConfigBasename)
|
||||
doc = TiXmlDocument(filename.toOsSpecific())
|
||||
|
|
@ -561,7 +557,7 @@ class AppRunner(DirectObject):
|
|||
tfile = Filename.temporary(self.rootDir.cStr(), '.xml')
|
||||
if doc.SaveFile(tfile.toOsSpecific()):
|
||||
tfile.renameTo(filename)
|
||||
|
||||
|
||||
|
||||
def checkDiskUsage(self):
|
||||
""" Checks the total disk space used by all packages, and
|
||||
|
|
@ -574,11 +570,11 @@ class AppRunner(DirectObject):
|
|||
totalSize += packageData.totalSize
|
||||
self.notify.info("Total Panda3D disk space used: %s MB" % (
|
||||
(totalSize + 524288) / 1048576))
|
||||
|
||||
|
||||
if self.verifyContents == self.P3DVCNever:
|
||||
# We're not allowed to delete anything anyway.
|
||||
return
|
||||
|
||||
|
||||
self.notify.info("Configured max usage is: %s MB" % (
|
||||
(self.maxDiskUsage + 524288) / 1048576))
|
||||
if totalSize <= self.maxDiskUsage:
|
||||
|
|
@ -592,7 +588,7 @@ class AppRunner(DirectObject):
|
|||
if packageData.package and packageData.package.installed:
|
||||
# Don't uninstall any packages we're currently using.
|
||||
continue
|
||||
|
||||
|
||||
usedPackages.append((packageData.lastUse, packageData))
|
||||
|
||||
# Sort the packages into oldest-first order.
|
||||
|
|
@ -609,13 +605,13 @@ class AppRunner(DirectObject):
|
|||
packages.append(packageData.package)
|
||||
else:
|
||||
# If it's an unknown package, just delete it directly.
|
||||
print "Deleting unknown package %s" % (packageData.pathname)
|
||||
print("Deleting unknown package %s" % (packageData.pathname))
|
||||
self.rmtree(packageData.pathname)
|
||||
|
||||
packages = self.deletePackages(packages)
|
||||
if packages:
|
||||
print "Unable to delete %s packages" % (len(packages))
|
||||
|
||||
print("Unable to delete %s packages" % (len(packages)))
|
||||
|
||||
return
|
||||
|
||||
def stop(self):
|
||||
|
|
@ -663,10 +659,10 @@ class AppRunner(DirectObject):
|
|||
for child in filename.scanDirectory():
|
||||
self.rmtree(Filename(filename, child))
|
||||
if not filename.rmdir():
|
||||
print "could not remove directory %s" % (filename)
|
||||
print("could not remove directory %s" % (filename))
|
||||
else:
|
||||
if not filename.unlink():
|
||||
print "could not delete %s" % (filename)
|
||||
print("could not delete %s" % (filename))
|
||||
|
||||
def setSessionId(self, sessionId):
|
||||
""" This message should come in at startup. """
|
||||
|
|
@ -747,10 +743,23 @@ class AppRunner(DirectObject):
|
|||
# will properly get ignored by ShowBase.
|
||||
self.initialAppImport = True
|
||||
|
||||
__import__(moduleName)
|
||||
main = sys.modules[moduleName]
|
||||
if hasattr(main, 'main') and hasattr(main.main, '__call__'):
|
||||
main.main(self)
|
||||
# Python won't let us import a module named __main__. So,
|
||||
# we have to do that manually, via the VFSImporter.
|
||||
if moduleName == '__main__':
|
||||
dirName = Filename(self.multifileRoot).toOsSpecific()
|
||||
importer = VFSImporter.VFSImporter(dirName)
|
||||
loader = importer.find_module('__main__')
|
||||
if loader is None:
|
||||
raise ImportError('No module named __main__')
|
||||
|
||||
mainModule = loader.load_module('__main__')
|
||||
else:
|
||||
__import__(moduleName)
|
||||
mainModule = sys.modules[moduleName]
|
||||
|
||||
# Check if it has a main() function. If so, call it.
|
||||
if hasattr(mainModule, 'main') and hasattr(mainModule.main, '__call__'):
|
||||
mainModule.main(self)
|
||||
|
||||
# Now clear this flag.
|
||||
self.initialAppImport = False
|
||||
|
|
@ -814,7 +823,7 @@ class AppRunner(DirectObject):
|
|||
|
||||
# Now that we have rootDir, we can read the config file.
|
||||
self.readConfigXml()
|
||||
|
||||
|
||||
|
||||
def addPackageInfo(self, name, platform, version, hostUrl, hostDir = None,
|
||||
recurse = False):
|
||||
|
|
@ -858,7 +867,7 @@ class AppRunner(DirectObject):
|
|||
# Maybe the contents.xml file isn't current. Re-fetch it.
|
||||
if host.redownloadContentsFile(self.http):
|
||||
return self.addPackageInfo(name, platform, version, hostUrl, hostDir = hostDir, recurse = True)
|
||||
|
||||
|
||||
message = "Couldn't find %s %s on %s" % (name, version, hostUrl)
|
||||
raise OSError, message
|
||||
|
||||
|
|
@ -866,18 +875,18 @@ class AppRunner(DirectObject):
|
|||
if not package.downloadDescFile(self.http):
|
||||
message = "Couldn't get desc file for %s" % (name)
|
||||
raise OSError, message
|
||||
|
||||
|
||||
if not package.downloadPackage(self.http):
|
||||
message = "Couldn't download %s" % (name)
|
||||
raise OSError, message
|
||||
|
||||
|
||||
if not package.installPackage(self):
|
||||
message = "Couldn't install %s" % (name)
|
||||
raise OSError, message
|
||||
|
||||
if package.guiApp:
|
||||
self.guiApp = True
|
||||
initAppForGui()
|
||||
init_app_for_gui()
|
||||
|
||||
def setP3DFilename(self, p3dFilename, tokens, argv, instanceId,
|
||||
interactiveConsole, p3dOffset = 0, p3dUrl = None):
|
||||
|
|
@ -885,7 +894,7 @@ class AppRunner(DirectObject):
|
|||
contains the application itself, along with the web tokens
|
||||
and/or command-line arguments. Once this method has been
|
||||
called, the application is effectively started. """
|
||||
|
||||
|
||||
# One day we will have support for multiple instances within a
|
||||
# Python session. Against that day, we save the instance ID
|
||||
# for this instance.
|
||||
|
|
@ -937,9 +946,9 @@ class AppRunner(DirectObject):
|
|||
self.allowPythonDev = False
|
||||
|
||||
i = mf.findSubfile('p3d_info.xml')
|
||||
if i >= 0 and hasattr(PandaModules, 'readXmlStream'):
|
||||
if i >= 0 and hasattr(core, 'readXmlStream'):
|
||||
stream = mf.openReadSubfile(i)
|
||||
self.p3dInfo = PandaModules.readXmlStream(stream)
|
||||
self.p3dInfo = core.readXmlStream(stream)
|
||||
mf.closeReadSubfile(stream)
|
||||
if self.p3dInfo:
|
||||
self.p3dPackage = self.p3dInfo.FirstChildElement('package')
|
||||
|
|
@ -975,7 +984,7 @@ class AppRunner(DirectObject):
|
|||
ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps')
|
||||
|
||||
if self.guiApp:
|
||||
initAppForGui()
|
||||
init_app_for_gui()
|
||||
|
||||
self.initPackedAppEnvironment()
|
||||
|
||||
|
|
@ -992,7 +1001,7 @@ class AppRunner(DirectObject):
|
|||
# provided if available. It is only for documentation
|
||||
# purposes; the actual p3d file has already been
|
||||
# downloaded to p3dFilename.
|
||||
self.p3dUrl = PandaModules.URLSpec(p3dUrl)
|
||||
self.p3dUrl = core.URLSpec(p3dUrl)
|
||||
|
||||
# Send this call to the main thread; don't call it directly.
|
||||
messenger.send('AppRunner_startIfReady', taskChain = 'default')
|
||||
|
|
@ -1015,14 +1024,14 @@ class AppRunner(DirectObject):
|
|||
newUrl = xalthost.Attribute('url')
|
||||
self.altHostMap[origUrl] = newUrl
|
||||
break
|
||||
|
||||
|
||||
xalthost = xalthost.NextSiblingElement('alt_host')
|
||||
|
||||
|
||||
def loadMultifilePrcFiles(self, mf, root):
|
||||
""" Loads any prc files in the root of the indicated
|
||||
Multifile, which is presumed to have been mounted already
|
||||
under root. """
|
||||
|
||||
|
||||
# We have to load these prc files explicitly, since the
|
||||
# ConfigPageManager can't directly look inside the vfs. Use
|
||||
# the Multifile interface to find the prc files, rather than
|
||||
|
|
@ -1046,12 +1055,12 @@ class AppRunner(DirectObject):
|
|||
cp = loadPrcFileData(pathname, data)
|
||||
# Set it to sort value 20, behind the implicit pages.
|
||||
cp.setSort(20)
|
||||
|
||||
|
||||
|
||||
|
||||
def __clearWindowProperties(self):
|
||||
""" Clears the windowPrc file that was created in a previous
|
||||
call to setupWindow(), if any. """
|
||||
|
||||
|
||||
if self.windowPrc:
|
||||
unloadPrcFile(self.windowPrc)
|
||||
self.windowPrc = None
|
||||
|
|
@ -1127,12 +1136,12 @@ class AppRunner(DirectObject):
|
|||
function that can be used to deliver requests upstream, to the
|
||||
core API, and thereby to the browser. """
|
||||
self.requestFunc = func
|
||||
|
||||
|
||||
def sendRequest(self, request, *args):
|
||||
""" Delivers a request to the browser via self.requestFunc.
|
||||
This low-level function is not intended to be called directly
|
||||
by user code. """
|
||||
|
||||
|
||||
assert self.requestFunc
|
||||
return self.requestFunc(self.instanceId, request, args)
|
||||
|
||||
|
|
@ -1176,7 +1185,7 @@ class AppRunner(DirectObject):
|
|||
# Evaluate it now.
|
||||
return self.scriptRequest('eval', self.dom, value = expression,
|
||||
needsResponse = needsResponse)
|
||||
|
||||
|
||||
def scriptRequest(self, operation, object, propertyName = '',
|
||||
value = None, needsResponse = True):
|
||||
""" Issues a new script request to the browser. This queries
|
||||
|
|
@ -1184,7 +1193,7 @@ class AppRunner(DirectObject):
|
|||
low-level method that user code should not call directly;
|
||||
instead, just operate on the Python wrapper objects that
|
||||
shadow the DOM objects, beginning with appRunner.dom.
|
||||
|
||||
|
||||
operation may be one of [ 'get_property', 'set_property',
|
||||
'call', 'evaluate' ].
|
||||
|
||||
|
|
@ -1233,7 +1242,7 @@ def dummyAppRunner(tokens = [], argv = None):
|
|||
first-look sanity check. """
|
||||
|
||||
if AppRunnerGlobal.appRunner:
|
||||
print "Already have AppRunner, not creating a new one."
|
||||
print("Already have AppRunner, not creating a new one.")
|
||||
return AppRunnerGlobal.appRunner
|
||||
|
||||
appRunner = AppRunner()
|
||||
|
|
@ -1243,7 +1252,7 @@ def dummyAppRunner(tokens = [], argv = None):
|
|||
platform = PandaSystem.getPlatform()
|
||||
version = PandaSystem.getPackageVersionString()
|
||||
hostUrl = PandaSystem.getPackageHostUrl()
|
||||
|
||||
|
||||
if platform.startswith('win'):
|
||||
rootDir = Filename(Filename.getUserAppdataDirectory(), 'Panda3D')
|
||||
elif platform.startswith('osx'):
|
||||
|
|
@ -1256,7 +1265,7 @@ def dummyAppRunner(tokens = [], argv = None):
|
|||
|
||||
# Of course we will have the panda3d application loaded.
|
||||
appRunner.addPackageInfo('panda3d', platform, version, hostUrl)
|
||||
|
||||
|
||||
appRunner.tokens = tokens
|
||||
appRunner.tokenDict = dict(tokens)
|
||||
if argv is None:
|
||||
|
|
@ -1274,6 +1283,6 @@ def dummyAppRunner(tokens = [], argv = None):
|
|||
vfs.mount(cwd, appRunner.multifileRoot, vfs.MFReadOnly)
|
||||
|
||||
appRunner.initPackedAppEnvironment()
|
||||
|
||||
|
||||
return appRunner
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import os, sys, subprocess, tarfile, shutil, time, zipfile, glob, socket, getpas
|
|||
from cStringIO import StringIO
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from direct.showbase.AppRunnerGlobal import appRunner
|
||||
from pandac.PandaModules import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
|
||||
from pandac.PandaModules import TiXmlDocument, TiXmlDeclaration, TiXmlElement, readXmlStream
|
||||
from pandac.PandaModules import PNMImage, PNMFileTypeRegistry
|
||||
from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
|
||||
from panda3d.core import TiXmlDocument, TiXmlDeclaration, TiXmlElement, readXmlStream
|
||||
from panda3d.core import PNMImage, PNMFileTypeRegistry
|
||||
from direct.stdpy.file import *
|
||||
from direct.p3d.HostInfo import HostInfo
|
||||
# This is important for some reason
|
||||
|
|
@ -296,7 +296,7 @@ class Icon:
|
|||
|
||||
def __init__(self):
|
||||
self.images = {}
|
||||
|
||||
|
||||
def addImage(self, image):
|
||||
""" Adds an image to the icon. Returns False on failure, True on success.
|
||||
Only one image per size can be loaded, and the image size must be square. """
|
||||
|
|
@ -1097,7 +1097,7 @@ class Installer:
|
|||
|
||||
# Tell Vista that we require admin rights
|
||||
print >>nsi, 'RequestExecutionLevel admin'
|
||||
print >>nsi
|
||||
print >>nsi
|
||||
if self.offerRun:
|
||||
print >>nsi, 'Function launch'
|
||||
print >>nsi, ' ExecShell "open" "$INSTDIR\\%s.exe"' % self.shortname
|
||||
|
|
@ -1112,7 +1112,7 @@ class Installer:
|
|||
print >>nsi, ' CreateShortcut "$DESKTOP\\%s.lnk" "$INSTDIR\\%s.exe" "" "$INSTDIR\\%s.ico"' % (self.fullname, self.shortname, self.shortname)
|
||||
print >>nsi, 'FunctionEnd'
|
||||
print >>nsi
|
||||
|
||||
|
||||
print >>nsi, '!include "MUI2.nsh"'
|
||||
print >>nsi, '!define MUI_ABORTWARNING'
|
||||
if self.offerRun:
|
||||
|
|
@ -1213,7 +1213,7 @@ class Installer:
|
|||
|
||||
if icofile is not None:
|
||||
icofile.unlink()
|
||||
|
||||
|
||||
return output
|
||||
|
||||
def os_walk(self, top):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
import time
|
||||
from pandac.PandaModules import Filename, HashVal, VirtualFileSystem
|
||||
from panda3d.core import Filename, HashVal, VirtualFileSystem
|
||||
|
||||
class FileSpec:
|
||||
""" This class represents a disk file whose hash and size
|
||||
|
|
@ -18,13 +18,13 @@ class FileSpec:
|
|||
def fromFile(self, packageDir, filename, pathname = None, st = None):
|
||||
""" Reads the file information from the indicated file. If st
|
||||
is supplied, it is the result of os.stat on the filename. """
|
||||
|
||||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
|
||||
filename = Filename(filename)
|
||||
if pathname is None:
|
||||
pathname = Filename(packageDir, filename)
|
||||
|
||||
|
||||
self.filename = filename.cStr()
|
||||
self.basename = filename.getBasename()
|
||||
|
||||
|
|
@ -41,17 +41,17 @@ class FileSpec:
|
|||
hv = HashVal()
|
||||
hv.hashFile(pathname)
|
||||
self.hash = hv.asHex()
|
||||
|
||||
|
||||
|
||||
def loadXml(self, xelement):
|
||||
""" Reads the file information from the indicated XML
|
||||
element. """
|
||||
|
||||
|
||||
self.filename = xelement.Attribute('filename')
|
||||
self.basename = None
|
||||
if self.filename:
|
||||
self.basename = Filename(self.filename).getBasename()
|
||||
|
||||
|
||||
size = xelement.Attribute('size')
|
||||
try:
|
||||
self.size = int(size)
|
||||
|
|
@ -87,7 +87,7 @@ class FileSpec:
|
|||
xelement.SetAttribute('size', str(self.size))
|
||||
if self.hash:
|
||||
xelement.SetAttribute('hash', self.hash)
|
||||
|
||||
|
||||
def quickVerify(self, packageDir = None, pathname = None,
|
||||
notify = None, correctSelf = False):
|
||||
""" Performs a quick test to ensure the file has not been
|
||||
|
|
@ -157,8 +157,8 @@ class FileSpec:
|
|||
self.__updateTimestamp(pathname, st)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
def fullVerify(self, packageDir = None, pathname = None, notify = None):
|
||||
""" Performs a more thorough test to ensure the file has not
|
||||
been modified. This test is less vulnerable to malicious
|
||||
|
|
@ -235,7 +235,7 @@ class FileSpec:
|
|||
""" Corrects the internal hash to match the one on disk. """
|
||||
if not self.actualFile:
|
||||
self.checkHash(packageDir, pathname, st)
|
||||
|
||||
|
||||
if notify:
|
||||
notify.info("Correcting hash %s to %s" % (
|
||||
self.filename, self.actualFile.hash))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from pandac.PandaModules import HashVal, Filename, PandaSystem, DocumentSpec, Ramfile
|
||||
from pandac.PandaModules import HTTPChannel
|
||||
from pandac import PandaModules
|
||||
from libpandaexpress import ConfigVariableInt
|
||||
from panda3d.core import HashVal, Filename, PandaSystem, DocumentSpec, Ramfile
|
||||
from panda3d.core import HTTPChannel, ConfigVariableInt
|
||||
from panda3d import core
|
||||
from direct.p3d.PackageInfo import PackageInfo
|
||||
from direct.p3d.FileSpec import FileSpec
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
|
|
@ -49,7 +48,7 @@ class HostInfo:
|
|||
|
||||
if hostDir and not isinstance(hostDir, Filename):
|
||||
hostDir = Filename.fromOsSpecific(hostDir)
|
||||
|
||||
|
||||
self.hostDir = hostDir
|
||||
self.asMirror = asMirror
|
||||
self.perPlatform = perPlatform
|
||||
|
|
@ -175,7 +174,7 @@ class HostInfo:
|
|||
statusString = channel.getStatusString()
|
||||
self.notify.warning("Could not contact download server at %s" % (url,))
|
||||
self.notify.warning("Status code = %s %s" % (statusCode, statusString))
|
||||
|
||||
|
||||
if not rf:
|
||||
self.notify.warning("Unable to download %s" % (url,))
|
||||
try:
|
||||
|
|
@ -206,7 +205,7 @@ class HostInfo:
|
|||
self.notify.warning("%s" % (str(e),))
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
tempFilename = Filename.temporary('', 'p3d_', '.xml')
|
||||
if rf:
|
||||
f = open(tempFilename.toOsSpecific(), 'wb')
|
||||
|
|
@ -278,7 +277,7 @@ class HostInfo:
|
|||
|
||||
now = int(time.time())
|
||||
return now < self.contentsExpiration and self.hasContentsFile
|
||||
|
||||
|
||||
def readContentsFile(self, tempFilename = None, freshDownload = False):
|
||||
""" Reads the contents.xml file for this particular host, once
|
||||
it has been downloaded into the indicated temporary file.
|
||||
|
|
@ -290,7 +289,7 @@ class HostInfo:
|
|||
there already. If tempFilename is not specified, the standard
|
||||
filename is read if it is known. """
|
||||
|
||||
if not hasattr(PandaModules, 'TiXmlDocument'):
|
||||
if not hasattr(core, 'TiXmlDocument'):
|
||||
return False
|
||||
|
||||
if not tempFilename:
|
||||
|
|
@ -304,7 +303,7 @@ class HostInfo:
|
|||
|
||||
tempFilename = Filename(hostDir, 'contents.xml')
|
||||
|
||||
doc = PandaModules.TiXmlDocument(tempFilename.toOsSpecific())
|
||||
doc = core.TiXmlDocument(tempFilename.toOsSpecific())
|
||||
if not doc.LoadFile():
|
||||
return False
|
||||
|
||||
|
|
@ -337,12 +336,12 @@ class HostInfo:
|
|||
xcontents.RemoveChild(xorig)
|
||||
xorig = xcontents.FirstChildElement('orig')
|
||||
|
||||
xorig = PandaModules.TiXmlElement('orig')
|
||||
xorig = core.TiXmlElement('orig')
|
||||
self.contentsSpec.storeXml(xorig)
|
||||
xorig.SetAttribute('expiration', str(self.contentsExpiration))
|
||||
|
||||
xcontents.InsertEndChild(xorig)
|
||||
|
||||
|
||||
else:
|
||||
# Read the download hash and expiration time from the XML.
|
||||
expiration = None
|
||||
|
|
@ -385,7 +384,7 @@ class HostInfo:
|
|||
perPlatform = int(xpackage.Attribute('per_platform') or '')
|
||||
except ValueError:
|
||||
perPlatform = False
|
||||
|
||||
|
||||
package = self.__makePackage(name, platform, version, solo, perPlatform)
|
||||
package.descFile = FileSpec()
|
||||
package.descFile.loadXml(xpackage)
|
||||
|
|
@ -418,7 +417,7 @@ class HostInfo:
|
|||
""" Looks for the <host> or <alt_host> entry in the
|
||||
contents.xml that corresponds to the URL that we actually
|
||||
downloaded from. """
|
||||
|
||||
|
||||
xhost = xcontents.FirstChildElement('host')
|
||||
while xhost:
|
||||
url = xhost.Attribute('url')
|
||||
|
|
@ -433,7 +432,7 @@ class HostInfo:
|
|||
self.readHostXml(xalthost)
|
||||
return
|
||||
xalthost = xalthost.NextSiblingElement('alt_host')
|
||||
|
||||
|
||||
xhost = xhost.NextSiblingElement('host')
|
||||
|
||||
def __findHostXmlForHostDir(self, xcontents):
|
||||
|
|
@ -442,7 +441,7 @@ class HostInfo:
|
|||
contents.xml from. This is used when reading a contents.xml
|
||||
file found on disk, as opposed to downloading it from a
|
||||
site. """
|
||||
|
||||
|
||||
xhost = xcontents.FirstChildElement('host')
|
||||
while xhost:
|
||||
url = xhost.Attribute('url')
|
||||
|
|
@ -463,7 +462,7 @@ class HostInfo:
|
|||
self.readHostXml(xalthost)
|
||||
return
|
||||
xalthost = xalthost.NextSiblingElement('alt_host')
|
||||
|
||||
|
||||
xhost = xhost.NextSiblingElement('host')
|
||||
|
||||
def readHostXml(self, xhost):
|
||||
|
|
@ -487,7 +486,7 @@ class HostInfo:
|
|||
self.downloadUrlPrefix += '/'
|
||||
else:
|
||||
self.downloadUrlPrefix = self.hostUrlPrefix
|
||||
|
||||
|
||||
xmirror = xhost.FirstChildElement('mirror')
|
||||
while xmirror:
|
||||
url = xmirror.Attribute('url')
|
||||
|
|
@ -611,7 +610,7 @@ class HostInfo:
|
|||
the list of packages that were NOT found. """
|
||||
|
||||
packages = packages[:]
|
||||
|
||||
|
||||
for key, platforms in self.packages.items():
|
||||
for platform, package in platforms.items():
|
||||
if package in packages:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from pandac.PandaModules import URLSpec
|
||||
from panda3d.core import URLSpec
|
||||
|
||||
class InstalledHostData:
|
||||
""" A list of instances of this class is returned by
|
||||
AppRunner.scanInstalledPackages(). Each of these corresponds to a
|
||||
particular host that has provided packages that have been
|
||||
installed on the local client. """
|
||||
|
||||
|
||||
def __init__(self, host, dirnode):
|
||||
self.host = host
|
||||
self.pathname = dirnode.pathname
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from pandac.PandaModules import Filename, URLSpec, DocumentSpec, Ramfile, Multifile, Decompressor, EUOk, EUSuccess, VirtualFileSystem, Thread, getModelPath, ExecutionEnvironment, PStatCollector, TiXmlDocument, TiXmlDeclaration, TiXmlElement
|
||||
from pandac import PandaModules
|
||||
from libpandaexpress import ConfigVariableInt
|
||||
from panda3d.core import Filename, URLSpec, DocumentSpec, Ramfile, Multifile, Decompressor, EUOk, EUSuccess, VirtualFileSystem, Thread, getModelPath, ExecutionEnvironment, PStatCollector, TiXmlDocument, TiXmlDeclaration, TiXmlElement
|
||||
import panda3d.core as core
|
||||
from direct.p3d.FileSpec import FileSpec
|
||||
from direct.p3d.ScanDirectoryNode import ScanDirectoryNode
|
||||
from direct.showbase import VFSImporter
|
||||
|
|
@ -55,7 +54,7 @@ class PackageInfo:
|
|||
tokens. This function defines a new generator that yields
|
||||
each of those tokens, but wraps each call into the nested
|
||||
generator within a pair of start/stop collector calls. """
|
||||
|
||||
|
||||
self.pStatCol.start()
|
||||
for token in self.__funcPtr(self):
|
||||
self.pStatCol.stop()
|
||||
|
|
@ -76,7 +75,7 @@ class PackageInfo:
|
|||
if self.bytesNeeded == 0:
|
||||
return 1
|
||||
return min(float(self.bytesDone) / float(self.bytesNeeded), 1)
|
||||
|
||||
|
||||
def __init__(self, host, packageName, packageVersion, platform = None,
|
||||
solo = False, asMirror = False, perPlatform = False):
|
||||
self.host = host
|
||||
|
|
@ -94,7 +93,7 @@ class PackageInfo:
|
|||
# This will be filled in when the host's contents.xml file is
|
||||
# read.
|
||||
self.packageDir = None
|
||||
|
||||
|
||||
# These will be filled in by HostInfo when the package is read
|
||||
# from contents.xml.
|
||||
self.descFile = None
|
||||
|
|
@ -110,11 +109,11 @@ class PackageInfo:
|
|||
self.extracts = []
|
||||
self.requires = []
|
||||
self.installPlans = None
|
||||
|
||||
|
||||
# This is updated during downloadPackage(). It is in the
|
||||
# range 0..1.
|
||||
self.downloadProgress = 0
|
||||
|
||||
|
||||
# This is set true when the package file has been fully
|
||||
# downloaded and unpacked.
|
||||
self.hasPackage = False
|
||||
|
|
@ -133,12 +132,12 @@ class PackageInfo:
|
|||
This may not be known until the host's contents.xml file has
|
||||
been downloaded, which informs us of the host's own install
|
||||
directory. """
|
||||
|
||||
|
||||
if not self.packageDir:
|
||||
if not self.host.hasContentsFile:
|
||||
if not self.host.readContentsFile():
|
||||
self.host.downloadContentsFile(self.http)
|
||||
|
||||
|
||||
# Derive the packageDir from the hostDir.
|
||||
self.packageDir = Filename(self.host.hostDir, self.packageName)
|
||||
if self.packageVersion:
|
||||
|
|
@ -159,7 +158,7 @@ class PackageInfo:
|
|||
# plugin--and we therefore shouldn't include the
|
||||
# platform in the directory hierarchy.
|
||||
includePlatform = False
|
||||
|
||||
|
||||
if includePlatform and self.platform:
|
||||
self.packageDir = Filename(self.packageDir, self.platform)
|
||||
|
||||
|
|
@ -176,7 +175,7 @@ class PackageInfo:
|
|||
# Return the size of plan A, assuming it will work.
|
||||
plan = self.installPlans[0]
|
||||
size = sum([step.getEffort() for step in plan])
|
||||
|
||||
|
||||
return size
|
||||
|
||||
def getPrevDownloadedEffort(self):
|
||||
|
|
@ -209,13 +208,13 @@ class PackageInfo:
|
|||
name += ' rev %s' % (self.patchVersion)
|
||||
|
||||
return name
|
||||
|
||||
|
||||
|
||||
def setupFilenames(self):
|
||||
""" This is called by the HostInfo when the package is read
|
||||
from contents.xml, to set up the internal filenames and such
|
||||
that rely on some of the information from contents.xml. """
|
||||
|
||||
|
||||
dirname, basename = self.descFile.filename.rsplit('/', 1)
|
||||
self.descFileDirname = dirname
|
||||
self.descFileBasename = basename
|
||||
|
|
@ -264,7 +263,7 @@ class PackageInfo:
|
|||
Thread.considerYield()
|
||||
|
||||
return (token == self.stepComplete)
|
||||
|
||||
|
||||
def downloadDescFileGenerator(self, http):
|
||||
""" A generator function that implements downloadDescFile()
|
||||
one piece at a time. It yields one of stepComplete,
|
||||
|
|
@ -343,9 +342,9 @@ class PackageInfo:
|
|||
|
||||
filename = Filename(self.getPackageDir(), self.descFileBasename)
|
||||
|
||||
if not hasattr(PandaModules, 'TiXmlDocument'):
|
||||
if not hasattr(core, 'TiXmlDocument'):
|
||||
return False
|
||||
doc = PandaModules.TiXmlDocument(filename.toOsSpecific())
|
||||
doc = core.TiXmlDocument(filename.toOsSpecific())
|
||||
if not doc.LoadFile():
|
||||
return False
|
||||
|
||||
|
|
@ -432,7 +431,7 @@ class PackageInfo:
|
|||
pc.start()
|
||||
|
||||
self.hasPackage = False
|
||||
|
||||
|
||||
if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
|
||||
# We're not allowed to download anything.
|
||||
self.installPlans = []
|
||||
|
|
@ -447,12 +446,12 @@ class PackageInfo:
|
|||
# archive.
|
||||
downloadSize = self.compressedArchive.size
|
||||
func = lambda step, fileSpec = self.compressedArchive: self.__downloadFile(step, fileSpec, allowPartial = True)
|
||||
|
||||
|
||||
step = self.InstallStep(func, downloadSize, self.downloadFactor, 'download')
|
||||
installPlan = [step]
|
||||
self.installPlans = [installPlan]
|
||||
pc.stop()
|
||||
return
|
||||
return
|
||||
|
||||
# The normal download process. Determine what we will need to
|
||||
# download, and build a plan (or two) to download it all.
|
||||
|
|
@ -520,9 +519,9 @@ class PackageInfo:
|
|||
# plan B as the only plan.
|
||||
self.installPlans = [planB]
|
||||
|
||||
# In case of unexpected failures on the internet, we will retry
|
||||
# In case of unexpected failures on the internet, we will retry
|
||||
# the full download instead of just giving up.
|
||||
for retry in range(ConfigVariableInt('package-full-dl-retries', 1)):
|
||||
for retry in range(core.ConfigVariableInt('package-full-dl-retries', 1)):
|
||||
self.installPlans.append(planB[:])
|
||||
|
||||
pc.stop()
|
||||
|
|
@ -530,7 +529,7 @@ class PackageInfo:
|
|||
def __scanDirectoryRecursively(self, dirname):
|
||||
""" Generates a list of Filename objects: all of the files
|
||||
(not directories) within and below the indicated dirname. """
|
||||
|
||||
|
||||
contents = []
|
||||
for dirpath, dirnames, filenames in os.walk(dirname.toOsSpecific()):
|
||||
dirpath = Filename.fromOsSpecific(dirpath)
|
||||
|
|
@ -560,7 +559,7 @@ class PackageInfo:
|
|||
|
||||
# Get a list of all of the files in the directory, so we can
|
||||
# remove files that don't belong.
|
||||
contents = self.__scanDirectoryRecursively(self.getPackageDir())
|
||||
contents = self.__scanDirectoryRecursively(self.getPackageDir())
|
||||
self.__removeFileFromList(contents, self.descFileBasename)
|
||||
self.__removeFileFromList(contents, self.compressedArchive.filename)
|
||||
self.__removeFileFromList(contents, self.UsageBasename)
|
||||
|
|
@ -582,7 +581,7 @@ class PackageInfo:
|
|||
|
||||
if self.asMirror:
|
||||
return self.compressedArchive.quickVerify(self.getPackageDir(), notify = self.notify)
|
||||
|
||||
|
||||
allExtractsOk = True
|
||||
if not self.uncompressedArchive.quickVerify(self.getPackageDir(), notify = self.notify):
|
||||
self.notify.debug("File is incorrect: %s" % (self.uncompressedArchive.filename))
|
||||
|
|
@ -593,7 +592,7 @@ class PackageInfo:
|
|||
# shouldn't be a compressed archive file here.
|
||||
pathname = Filename(self.getPackageDir(), self.compressedArchive.filename)
|
||||
pathname.unlink()
|
||||
|
||||
|
||||
for file in self.extracts:
|
||||
if not file.quickVerify(self.getPackageDir(), notify = self.notify):
|
||||
self.notify.debug("File is incorrect: %s" % (file.filename))
|
||||
|
|
@ -614,7 +613,7 @@ class PackageInfo:
|
|||
|
||||
size = self.totalPlanCompleted + self.currentStepEffort * step.getProgress()
|
||||
self.downloadProgress = min(float(size) / float(self.totalPlanSize), 1)
|
||||
|
||||
|
||||
def downloadPackage(self, http):
|
||||
""" Downloads the package file, synchronously, then
|
||||
uncompresses and unpacks it. Returns true on success, false
|
||||
|
|
@ -630,7 +629,7 @@ class PackageInfo:
|
|||
Thread.considerYield()
|
||||
|
||||
return (token == self.stepComplete)
|
||||
|
||||
|
||||
def downloadPackageGenerator(self, http):
|
||||
""" A generator function that implements downloadPackage() one
|
||||
piece at a time. It yields one of stepComplete, stepFailed,
|
||||
|
|
@ -655,7 +654,7 @@ class PackageInfo:
|
|||
yield token
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
while token == self.restartDownload:
|
||||
# Try again.
|
||||
for token in self.downloadDescFileGenerator(http):
|
||||
|
|
@ -675,7 +674,7 @@ class PackageInfo:
|
|||
|
||||
assert token == self.stepComplete
|
||||
yield self.stepComplete; return
|
||||
|
||||
|
||||
|
||||
def __followInstallPlans(self):
|
||||
""" Performs all of the steps in self.installPlans. Yields
|
||||
|
|
@ -701,16 +700,16 @@ class PackageInfo:
|
|||
yield token
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
if token == self.restartDownload:
|
||||
yield token
|
||||
if token == self.stepFailed:
|
||||
planFailed = True
|
||||
break
|
||||
assert token == self.stepComplete
|
||||
|
||||
|
||||
self.totalPlanCompleted += self.currentStepEffort
|
||||
|
||||
|
||||
if not planFailed:
|
||||
# Successfully downloaded!
|
||||
yield self.stepComplete; return
|
||||
|
|
@ -754,7 +753,7 @@ class PackageInfo:
|
|||
def __downloadFile(self, step, fileSpec, urlbase = None, filename = None,
|
||||
allowPartial = False):
|
||||
""" Downloads the indicated file from the host into
|
||||
packageDir. Yields one of stepComplete, stepFailed,
|
||||
packageDir. Yields one of stepComplete, stepFailed,
|
||||
restartDownload, or stepContinue. """
|
||||
|
||||
if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
|
||||
|
|
@ -806,7 +805,7 @@ class PackageInfo:
|
|||
url += '?' + str(int(time.time()))
|
||||
request = DocumentSpec(url)
|
||||
request.setCacheControl(DocumentSpec.CCNoCache)
|
||||
|
||||
|
||||
self.notify.info("%s downloading %s" % (self.packageName, url))
|
||||
|
||||
if not filename:
|
||||
|
|
@ -839,7 +838,7 @@ class PackageInfo:
|
|||
targetPathname.makeDir()
|
||||
targetPathname.unlink()
|
||||
channel.beginGetDocument(request)
|
||||
|
||||
|
||||
channel.downloadToFile(targetPathname)
|
||||
while channel.run():
|
||||
if step:
|
||||
|
|
@ -849,7 +848,7 @@ class PackageInfo:
|
|||
# it's the wrong file.
|
||||
self.notify.warning("Got more data than expected for download %s" % (url))
|
||||
break
|
||||
|
||||
|
||||
self.__updateStepProgress(step)
|
||||
|
||||
if taskMgr.destroyed:
|
||||
|
|
@ -857,9 +856,9 @@ class PackageInfo:
|
|||
# be shutting down. Get out of here.
|
||||
self.notify.warning("Task Manager destroyed, aborting %s" % (url))
|
||||
yield self.stepFailed; return
|
||||
|
||||
|
||||
yield self.stepContinue
|
||||
|
||||
|
||||
if step:
|
||||
step.bytesDone = channel.getBytesDownloaded() + channel.getFirstByteDelivered()
|
||||
self.__updateStepProgress(step)
|
||||
|
|
@ -897,7 +896,7 @@ class PackageInfo:
|
|||
def __applyPatch(self, step, patchfile):
|
||||
""" Applies the indicated patching in-place to the current
|
||||
uncompressed archive. The patchfile is removed after the
|
||||
operation. Yields one of stepComplete, stepFailed,
|
||||
operation. Yields one of stepComplete, stepFailed,
|
||||
restartDownload, or stepContinue. """
|
||||
|
||||
self.updated = True
|
||||
|
|
@ -907,7 +906,7 @@ class PackageInfo:
|
|||
result = Filename.temporary('', 'patch_')
|
||||
self.notify.info("Patching %s with %s" % (origPathname, patchPathname))
|
||||
|
||||
p = PandaModules.Patchfile() # The C++ class
|
||||
p = core.Patchfile() # The C++ class
|
||||
|
||||
ret = p.initiate(patchPathname, origPathname, result)
|
||||
if ret == EUSuccess:
|
||||
|
|
@ -925,7 +924,7 @@ class PackageInfo:
|
|||
ret = p.run()
|
||||
del p
|
||||
patchPathname.unlink()
|
||||
|
||||
|
||||
if ret < 0:
|
||||
self.notify.warning("Patching of %s failed." % (origPathname))
|
||||
result.unlink()
|
||||
|
|
@ -934,12 +933,12 @@ class PackageInfo:
|
|||
if not result.renameTo(origPathname):
|
||||
self.notify.warning("Couldn't rename %s to %s" % (result, origPathname))
|
||||
yield self.stepFailed; return
|
||||
|
||||
|
||||
yield self.stepComplete; return
|
||||
|
||||
def __uncompressArchive(self, step):
|
||||
""" Turns the compressed archive into the uncompressed
|
||||
archive. Yields one of stepComplete, stepFailed,
|
||||
archive. Yields one of stepComplete, stepFailed,
|
||||
restartDownload, or stepContinue. """
|
||||
|
||||
if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
|
||||
|
|
@ -970,7 +969,7 @@ class PackageInfo:
|
|||
|
||||
if result != EUSuccess:
|
||||
yield self.stepFailed; return
|
||||
|
||||
|
||||
step.bytesDone = totalBytes
|
||||
self.__updateStepProgress(step)
|
||||
|
||||
|
|
@ -985,10 +984,10 @@ class PackageInfo:
|
|||
# Now we can safely remove the compressed archive.
|
||||
sourcePathname.unlink()
|
||||
yield self.stepComplete; return
|
||||
|
||||
|
||||
def __unpackArchive(self, step):
|
||||
""" Unpacks any files in the archive that want to be unpacked
|
||||
to disk. Yields one of stepComplete, stepFailed,
|
||||
to disk. Yields one of stepComplete, stepFailed,
|
||||
restartDownload, or stepContinue. """
|
||||
|
||||
if not self.extracts:
|
||||
|
|
@ -1008,7 +1007,7 @@ class PackageInfo:
|
|||
if not mf.openRead(mfPathname):
|
||||
self.notify.warning("Couldn't open %s" % (mfPathname))
|
||||
yield self.stepFailed; return
|
||||
|
||||
|
||||
allExtractsOk = True
|
||||
step.bytesDone = 0
|
||||
for file in self.extracts:
|
||||
|
|
@ -1025,7 +1024,7 @@ class PackageInfo:
|
|||
self.notify.warning("Couldn't extract: %s" % (file.filename))
|
||||
allExtractsOk = False
|
||||
continue
|
||||
|
||||
|
||||
if not file.quickVerify(self.getPackageDir(), notify = self.notify):
|
||||
self.notify.warning("After extracting, still incorrect: %s" % (file.filename))
|
||||
allExtractsOk = False
|
||||
|
|
@ -1157,7 +1156,7 @@ class PackageInfo:
|
|||
""" Marks the package as having been used. This is normally
|
||||
called automatically by installPackage(). """
|
||||
|
||||
if not hasattr(PandaModules, 'TiXmlDocument'):
|
||||
if not hasattr(core, 'TiXmlDocument'):
|
||||
return
|
||||
|
||||
if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
|
||||
|
|
@ -1174,14 +1173,14 @@ class PackageInfo:
|
|||
if not doc.LoadFile():
|
||||
decl = TiXmlDeclaration("1.0", "utf-8", "")
|
||||
doc.InsertEndChild(decl)
|
||||
|
||||
|
||||
xusage = doc.FirstChildElement('usage')
|
||||
if not xusage:
|
||||
doc.InsertEndChild(TiXmlElement('usage'))
|
||||
xusage = doc.FirstChildElement('usage')
|
||||
|
||||
now = int(time.time())
|
||||
|
||||
|
||||
count = xusage.Attribute('count_app')
|
||||
try:
|
||||
count = int(count or '')
|
||||
|
|
@ -1214,22 +1213,22 @@ class PackageInfo:
|
|||
tfile = Filename.temporary(self.getPackageDir().cStr(), '.xml')
|
||||
if doc.SaveFile(tfile.toOsSpecific()):
|
||||
tfile.renameTo(filename)
|
||||
|
||||
|
||||
def getUsage(self):
|
||||
""" Returns the xusage element that is read from the usage.xml
|
||||
file, or None if there is no usage.xml file. """
|
||||
|
||||
if not hasattr(PandaModules, 'TiXmlDocument'):
|
||||
if not hasattr(core, 'TiXmlDocument'):
|
||||
return None
|
||||
|
||||
filename = Filename(self.getPackageDir(), self.UsageBasename)
|
||||
doc = TiXmlDocument(filename.toOsSpecific())
|
||||
if not doc.LoadFile():
|
||||
return None
|
||||
|
||||
|
||||
xusage = doc.FirstChildElement('usage')
|
||||
if not xusage:
|
||||
return None
|
||||
|
||||
return copy.copy(xusage)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from direct.stdpy.threading import Lock, RLock
|
|||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.p3d.PackageInfo import PackageInfo
|
||||
from pandac.PandaModules import TPLow, PStatCollector
|
||||
from panda3d.core import TPLow, PStatCollector
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
|
||||
class PackageInstaller(DirectObject):
|
||||
|
|
@ -33,7 +33,7 @@ class PackageInstaller(DirectObject):
|
|||
S_ready = 1 # donePackages() has been called
|
||||
S_started = 2 # download has started
|
||||
S_done = 3 # download is over
|
||||
|
||||
|
||||
class PendingPackage:
|
||||
""" This class describes a package added to the installer for
|
||||
download. """
|
||||
|
|
@ -121,12 +121,12 @@ class PackageInstaller(DirectObject):
|
|||
self.prevDownloadedEffort = self.package.getPrevDownloadedEffort()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def getDescFile(self, http):
|
||||
""" Synchronously downloads the desc files required for
|
||||
the package. """
|
||||
|
||||
|
||||
if not self.host.downloadContentsFile(http):
|
||||
return False
|
||||
|
||||
|
|
@ -156,10 +156,10 @@ class PackageInstaller(DirectObject):
|
|||
PackageInstaller.nextUniqueId += 1
|
||||
finally:
|
||||
self.globalLock.release()
|
||||
|
||||
|
||||
self.appRunner = appRunner
|
||||
self.taskChain = taskChain
|
||||
|
||||
|
||||
# If we're to be running on an asynchronous task chain, and
|
||||
# the task chain hasn't yet been set up already, create the
|
||||
# default parameters now.
|
||||
|
|
@ -180,7 +180,7 @@ class PackageInstaller(DirectObject):
|
|||
# A list of packages that are waiting for their desc files.
|
||||
self.needsDescFile = []
|
||||
self.descFileTask = None
|
||||
|
||||
|
||||
# A list of packages that are waiting to be downloaded and
|
||||
# installed.
|
||||
self.needsDownload = []
|
||||
|
|
@ -198,7 +198,7 @@ class PackageInstaller(DirectObject):
|
|||
# This task is spawned on the default task chain, to update
|
||||
# the status during the download.
|
||||
self.progressTask = None
|
||||
|
||||
|
||||
self.accept('PackageInstaller-%s-allHaveDesc' % self.uniqueId,
|
||||
self.__allHaveDesc)
|
||||
self.accept('PackageInstaller-%s-packageStarted' % self.uniqueId,
|
||||
|
|
@ -231,7 +231,7 @@ class PackageInstaller(DirectObject):
|
|||
self.progressTask = None
|
||||
|
||||
self.ignoreAll()
|
||||
|
||||
|
||||
def addPackage(self, packageName, version = None, hostUrl = None):
|
||||
""" Adds the named package to the list of packages to be
|
||||
downloaded. Call donePackages() to finish the list. """
|
||||
|
|
@ -256,7 +256,7 @@ class PackageInstaller(DirectObject):
|
|||
if pp in self.packages:
|
||||
# Already added.
|
||||
return
|
||||
|
||||
|
||||
self.packages.append(pp)
|
||||
|
||||
# We always add the package to needsDescFile, even if we
|
||||
|
|
@ -323,7 +323,7 @@ class PackageInstaller(DirectObject):
|
|||
(beginning) to 1 (complete). """
|
||||
|
||||
self.notify.debug("packageProgress: %s %s" % (package.packageName, progress))
|
||||
|
||||
|
||||
def downloadProgress(self, overallProgress):
|
||||
""" This callback is made repeatedly between downloadStarted()
|
||||
and downloadFinished() to update the current progress through
|
||||
|
|
@ -384,7 +384,7 @@ class PackageInstaller(DirectObject):
|
|||
""" This method is called internally when all of the pending
|
||||
packages have their desc info. """
|
||||
working = True
|
||||
|
||||
|
||||
self.packageLock.acquire()
|
||||
try:
|
||||
if self.state == self.S_ready:
|
||||
|
|
@ -489,7 +489,7 @@ class PackageInstaller(DirectObject):
|
|||
it extracts one package from self.needsDescFile and downloads
|
||||
its desc file. On success, it adds the package to
|
||||
self.needsDownload. """
|
||||
|
||||
|
||||
self.packageLock.acquire()
|
||||
try:
|
||||
# If we've finished all of the packages that need desc
|
||||
|
|
@ -515,7 +515,7 @@ class PackageInstaller(DirectObject):
|
|||
# This package is now ready to be downloaded. We always add
|
||||
# it to needsDownload, even if it's already downloaded, to
|
||||
# guarantee ordering of packages.
|
||||
|
||||
|
||||
self.packageLock.acquire()
|
||||
try:
|
||||
# Also add any packages required by this one.
|
||||
|
|
@ -527,7 +527,7 @@ class PackageInstaller(DirectObject):
|
|||
self.packageLock.release()
|
||||
|
||||
return task.cont
|
||||
|
||||
|
||||
def __downloadPackageTask(self, task):
|
||||
|
||||
""" This task runs on the aysynchronous task chain; each pass,
|
||||
|
|
@ -543,7 +543,7 @@ class PackageInstaller(DirectObject):
|
|||
self.packageLock.release()
|
||||
yield task.done; return
|
||||
|
||||
assert self.state == self.S_started
|
||||
assert self.state == self.S_started
|
||||
pp = self.needsDownload[0]
|
||||
del self.needsDownload[0]
|
||||
except:
|
||||
|
|
@ -578,7 +578,7 @@ class PackageInstaller(DirectObject):
|
|||
|
||||
# Continue the loop without yielding, so we pick up the
|
||||
# next package within this same frame.
|
||||
|
||||
|
||||
def __donePackage(self, pp, success):
|
||||
""" Marks the indicated package as done, either successfully
|
||||
or otherwise. """
|
||||
|
|
@ -630,9 +630,9 @@ class PackageInstaller(DirectObject):
|
|||
else:
|
||||
progress = float(currentDownloadSize) / float(downloadEffort)
|
||||
self.downloadProgress(progress)
|
||||
|
||||
|
||||
finally:
|
||||
self.callbackLock.release()
|
||||
|
||||
return task.cont
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from direct.p3d.FileSpec import FileSpec
|
||||
from direct.p3d.SeqValue import SeqValue
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
import copy
|
||||
import shutil
|
||||
import os
|
||||
|
|
@ -18,11 +18,11 @@ class PackageMerger:
|
|||
always the most current version of the file. """
|
||||
|
||||
notify = directNotify.newCategory("PackageMerger")
|
||||
|
||||
|
||||
class PackageEntry:
|
||||
""" This corresponds to a <package> entry in the contents.xml
|
||||
file. """
|
||||
|
||||
|
||||
def __init__(self, xpackage, sourceDir):
|
||||
self.sourceDir = sourceDir
|
||||
self.loadXml(xpackage)
|
||||
|
|
@ -48,7 +48,7 @@ class PackageMerger:
|
|||
self.descFile.loadXml(xpackage)
|
||||
|
||||
self.validatePackageContents()
|
||||
|
||||
|
||||
self.descFile.quickVerify(packageDir = self.sourceDir, notify = PackageMerger.notify, correctSelf = True)
|
||||
|
||||
self.packageSeq = SeqValue()
|
||||
|
|
@ -84,7 +84,7 @@ class PackageMerger:
|
|||
ximport = TiXmlElement('import')
|
||||
self.importDescFile.storeXml(ximport)
|
||||
xpackage.InsertEndChild(ximport)
|
||||
|
||||
|
||||
return xpackage
|
||||
|
||||
def validatePackageContents(self):
|
||||
|
|
@ -170,7 +170,7 @@ class PackageMerger:
|
|||
xhost = xcontents.FirstChildElement('host')
|
||||
if xhost:
|
||||
self.xhost = xhost.Clone()
|
||||
|
||||
|
||||
xpackage = xcontents.FirstChildElement('package')
|
||||
while xpackage:
|
||||
pe = self.PackageEntry(xpackage, sourceDir)
|
||||
|
|
@ -183,7 +183,7 @@ class PackageMerger:
|
|||
if not other or pe.isNewer(other):
|
||||
# Store this package in the resulting output.
|
||||
self.contents[pe.getKey()] = pe
|
||||
|
||||
|
||||
xpackage = xpackage.NextSiblingElement('package')
|
||||
|
||||
self.contentsDoc = doc
|
||||
|
|
@ -247,7 +247,7 @@ class PackageMerger:
|
|||
else:
|
||||
# Both the source file and target file are
|
||||
# directories.
|
||||
|
||||
|
||||
# We have to clean out the target directory first.
|
||||
# Instead of using shutil.rmtree(), remove the files in
|
||||
# this directory one at a time, so we don't inadvertently
|
||||
|
|
@ -282,10 +282,10 @@ class PackageMerger:
|
|||
the current pool. If packageNames is not None, it is a list
|
||||
of package names that we wish to include from the source;
|
||||
packages not named in this list will be unchanged. """
|
||||
|
||||
|
||||
if not self.__readContentsFile(sourceDir, packageNames):
|
||||
message = "Couldn't read %s" % (sourceDir)
|
||||
raise PackageMergerError, message
|
||||
raise PackageMergerError, message
|
||||
|
||||
def close(self):
|
||||
""" Finalizes the results of all of the previous calls to
|
||||
|
|
@ -302,4 +302,4 @@ class PackageMerger:
|
|||
|
||||
self.contentsSeq += 1
|
||||
self.__writeContentsFile()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import types
|
|||
import getpass
|
||||
import platform
|
||||
import struct
|
||||
import subprocess
|
||||
from direct.p3d.FileSpec import FileSpec
|
||||
from direct.p3d.SeqValue import SeqValue
|
||||
from direct.showbase import Loader
|
||||
|
|
@ -58,7 +59,7 @@ class Packager:
|
|||
self.required = required
|
||||
|
||||
if not self.newName:
|
||||
self.newName = self.filename.cStr()
|
||||
self.newName = str(self.filename)
|
||||
|
||||
ext = Filename(self.newName).getExtension()
|
||||
if ext == 'pz':
|
||||
|
|
@ -66,7 +67,7 @@ class Packager:
|
|||
# within the Multifile without it.
|
||||
filename = Filename(self.newName)
|
||||
filename.setExtension('')
|
||||
self.newName = filename.cStr()
|
||||
self.newName = str(filename)
|
||||
ext = Filename(self.newName).getExtension()
|
||||
if self.compress is None:
|
||||
self.compress = True
|
||||
|
|
@ -80,8 +81,8 @@ class Packager:
|
|||
|
||||
if self.executable and self.dependencyDir is None:
|
||||
# By default, install executable dependencies in the
|
||||
# same directory with the executable itself.
|
||||
self.dependencyDir = Filename(self.newName).getDirname()
|
||||
# root directory, which is the one that's added to PATH.
|
||||
self.dependencyDir = ''
|
||||
|
||||
if self.extract is None:
|
||||
self.extract = self.executable or (ext in packager.extractExtensions)
|
||||
|
|
@ -93,13 +94,13 @@ class Packager:
|
|||
|
||||
if self.executable:
|
||||
# Look up the filename along the system PATH, if necessary.
|
||||
if not self.filename.resolveFilename(packager.executablePath):
|
||||
if not packager.resolveLibrary(self.filename):
|
||||
# If it wasn't found, try looking it up under its
|
||||
# basename only. Sometimes a Mac user will copy
|
||||
# the library file out of a framework and put that
|
||||
# along the PATH, instead of the framework itself.
|
||||
basename = Filename(self.filename.getBasename())
|
||||
if basename.resolveFilename(packager.executablePath):
|
||||
if packager.resolveLibrary(basename):
|
||||
self.filename = basename
|
||||
|
||||
if ext in packager.textExtensions and not self.executable:
|
||||
|
|
@ -156,7 +157,7 @@ class Packager:
|
|||
if not self.localOnly:
|
||||
filename = Filename(filename)
|
||||
filename.makeCanonical()
|
||||
self.glob = GlobPattern(filename.cStr())
|
||||
self.glob = GlobPattern(str(filename))
|
||||
|
||||
if self.packager.platform.startswith('win'):
|
||||
self.glob.setCaseSensitive(False)
|
||||
|
|
@ -167,7 +168,7 @@ class Packager:
|
|||
if self.localOnly:
|
||||
return self.glob.matches(filename.getBasename())
|
||||
else:
|
||||
return self.glob.matches(filename.cStr())
|
||||
return self.glob.matches(str(filename))
|
||||
|
||||
class PackageEntry:
|
||||
""" This corresponds to a <package> entry in the contents.xml
|
||||
|
|
@ -586,9 +587,9 @@ class Packager:
|
|||
# (i.e. missing) modules.
|
||||
continue
|
||||
|
||||
if newName == '__main__':
|
||||
# Ignore this special case.
|
||||
continue
|
||||
#if newName == '__main__':
|
||||
# # Ignore this special case.
|
||||
# continue
|
||||
|
||||
self.moduleNames[newName] = mdef
|
||||
|
||||
|
|
@ -937,7 +938,7 @@ class Packager:
|
|||
# means we should include the manifest
|
||||
# file itself in the package.
|
||||
newName = Filename(file.dependencyDir, mfile.getBasename())
|
||||
self.addFile(mfile, newName = newName.cStr(),
|
||||
self.addFile(mfile, newName = str(newName),
|
||||
explicit = False, executable = True)
|
||||
|
||||
if afilenames is None and out != 31:
|
||||
|
|
@ -957,7 +958,7 @@ class Packager:
|
|||
filename.makeTrueCase()
|
||||
|
||||
newName = Filename(file.dependencyDir, filename.getBasename())
|
||||
self.addFile(filename, newName = newName.cStr(),
|
||||
self.addFile(filename, newName = str(newName),
|
||||
explicit = False, executable = True)
|
||||
|
||||
def __parseDependenciesWindows(self, tempFile):
|
||||
|
|
@ -1172,7 +1173,7 @@ class Packager:
|
|||
# It's a fully-specified filename; look
|
||||
# for it under the system root first.
|
||||
if self.packager.systemRoot:
|
||||
f2 = Filename(self.packager.systemRoot + filename.cStr())
|
||||
f2 = Filename(self.packager.systemRoot, filename)
|
||||
if f2.exists():
|
||||
filename = f2
|
||||
|
||||
|
|
@ -1181,7 +1182,7 @@ class Packager:
|
|||
continue
|
||||
|
||||
newName = Filename(file.dependencyDir, filename.getBasename())
|
||||
self.addFile(filename, newName = newName.cStr(),
|
||||
self.addFile(filename, newName = str(newName),
|
||||
explicit = False, executable = True)
|
||||
|
||||
def __parseDependenciesOSX(self, tempFile):
|
||||
|
|
@ -1346,6 +1347,7 @@ class Packager:
|
|||
|
||||
# If that failed, perhaps ldd will help us.
|
||||
if filenames is None:
|
||||
self.notify.warning("Reading ELF library %s failed, using ldd instead" % (file.filename))
|
||||
tempFile = Filename.temporary('', 'p3d_', '.txt')
|
||||
command = 'ldd "%s" >"%s"' % (
|
||||
file.filename.toOsSpecific(),
|
||||
|
|
@ -1379,7 +1381,7 @@ class Packager:
|
|||
filename.setBinary()
|
||||
|
||||
newName = Filename(file.dependencyDir, filename.getBasename())
|
||||
self.addFile(filename, newName = newName.cStr(),
|
||||
self.addFile(filename, newName = str(newName),
|
||||
explicit = False, executable = True)
|
||||
|
||||
def __parseDependenciesPosix(self, tempFile):
|
||||
|
|
@ -1470,7 +1472,7 @@ class Packager:
|
|||
# compatible with older versions of the core API that
|
||||
# didn't understand the SF_text flag.
|
||||
filename.setBinary()
|
||||
|
||||
|
||||
doc.SaveFile(filename.toOsSpecific())
|
||||
|
||||
# It's important not to compress this file: the core API
|
||||
|
|
@ -1772,8 +1774,6 @@ class Packager:
|
|||
|
||||
return xspec
|
||||
|
||||
|
||||
|
||||
def addPyFile(self, file):
|
||||
""" Adds the indicated python file, identified by filename
|
||||
instead of by module name, to the package. """
|
||||
|
|
@ -1793,6 +1793,18 @@ class Packager:
|
|||
# deal with it again.
|
||||
return
|
||||
|
||||
# Make sure that it is actually in a package.
|
||||
parentName = moduleName
|
||||
while '.' in parentName:
|
||||
parentName = parentName.rsplit('.', 1)[0]
|
||||
if parentName not in self.freezer.modules:
|
||||
message = 'Cannot add Python file %s; not in package' % (file.newName)
|
||||
if file.required or file.explicit:
|
||||
raise StandardError, message
|
||||
else:
|
||||
self.notify.warning(message)
|
||||
return
|
||||
|
||||
self.freezer.addModule(moduleName, filename = file.filename)
|
||||
|
||||
def addEggFile(self, file):
|
||||
|
|
@ -1803,7 +1815,7 @@ class Packager:
|
|||
|
||||
bamName = Filename(file.newName)
|
||||
bamName.setExtension('bam')
|
||||
self.addNode(np.node(), file.filename, bamName.cStr())
|
||||
self.addNode(np.node(), file.filename, str(bamName))
|
||||
|
||||
def addBamFile(self, file):
|
||||
# Load the bam file so we can massage its textures.
|
||||
|
|
@ -2207,6 +2219,9 @@ class Packager:
|
|||
cvar = ConfigVariableSearchPath('pdef-path')
|
||||
self.installSearch = list(map(Filename, cvar.getDirectories()))
|
||||
|
||||
# This is where we cache the location of libraries.
|
||||
self.libraryCache = {}
|
||||
|
||||
# The system PATH, for searching dll's and exe's.
|
||||
self.executablePath = DSearchPath()
|
||||
|
||||
|
|
@ -2219,22 +2234,36 @@ class Packager:
|
|||
# Now add the actual system search path.
|
||||
if self.platform.startswith('win'):
|
||||
self.addWindowsSearchPath(self.executablePath, "PATH")
|
||||
elif self.platform.startswith('osx'):
|
||||
self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH")
|
||||
self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
|
||||
self.addPosixSearchPath(self.executablePath, "PATH")
|
||||
self.executablePath.appendDirectory('/lib')
|
||||
self.executablePath.appendDirectory('/usr/lib')
|
||||
self.executablePath.appendDirectory('/usr/local/lib')
|
||||
else:
|
||||
self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
|
||||
self.addPosixSearchPath(self.executablePath, "PATH")
|
||||
self.executablePath.appendDirectory('/lib')
|
||||
self.executablePath.appendDirectory('/usr/lib')
|
||||
self.executablePath.appendDirectory('/usr/local/lib')
|
||||
|
||||
import platform
|
||||
if platform.uname()[1]=="pcbsd":
|
||||
else:
|
||||
if self.platform.startswith('osx'):
|
||||
self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH")
|
||||
|
||||
self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
|
||||
self.addPosixSearchPath(self.executablePath, "PATH")
|
||||
|
||||
if self.platform.startswith('linux'):
|
||||
# It used to be okay to just add some common paths on Linux.
|
||||
# But nowadays, each distribution has their own convention for
|
||||
# where they put their libraries. Instead, we query the ldconfig
|
||||
# cache, which contains the location of all libraries.
|
||||
|
||||
if not self.loadLdconfigCache():
|
||||
# Ugh, failure. All that remains is to guess. This should
|
||||
# work for the most common Debian configurations.
|
||||
multiarchDir = "/lib/%s-linux-gnu" % (os.uname()[4])
|
||||
if os.path.isdir(multiarchDir):
|
||||
self.executablePath.appendDirectory(multiarchDir)
|
||||
if os.path.isdir("/usr/" + multiarchDir):
|
||||
self.executablePath.appendDirectory("/usr/" + multiarchDir)
|
||||
|
||||
else:
|
||||
# FreeBSD, or some other system that still makes sense.
|
||||
self.executablePath.appendDirectory('/lib')
|
||||
self.executablePath.appendDirectory('/usr/lib')
|
||||
self.executablePath.appendDirectory('/usr/local/lib')
|
||||
|
||||
if os.uname()[1] == "pcbsd":
|
||||
self.executablePath.appendDirectory('/usr/PCBSD/local/lib')
|
||||
|
||||
# Set this flag true to automatically add allow_python_dev to
|
||||
|
|
@ -2388,6 +2417,7 @@ class Packager:
|
|||
GlobPattern('libpthread.so*'),
|
||||
GlobPattern('libthr.so*'),
|
||||
GlobPattern('ld-linux.so*'),
|
||||
GlobPattern('ld-linux-*.so*'),
|
||||
]
|
||||
|
||||
# A Loader for loading models.
|
||||
|
|
@ -2405,6 +2435,60 @@ class Packager:
|
|||
# file.
|
||||
self.contents = {}
|
||||
|
||||
def loadLdconfigCache(self):
|
||||
""" On GNU/Linux, runs ldconfig -p to find out where all the
|
||||
libraries on the system are located. Assumes that the platform
|
||||
has already been set. """
|
||||
|
||||
if not os.path.isfile('/sbin/ldconfig'):
|
||||
return False
|
||||
|
||||
handle = subprocess.Popen(['/sbin/ldconfig', '-p'], stdout=subprocess.PIPE)
|
||||
out, err = handle.communicate()
|
||||
|
||||
if handle.returncode != 0:
|
||||
self.notify.warning("/sbin/ldconfig -p returned code %d" %(handle.returncode))
|
||||
return False
|
||||
|
||||
for line in out.splitlines():
|
||||
if '=>' not in line:
|
||||
continue
|
||||
|
||||
prefix, location = line.rsplit('=>', 1)
|
||||
prefix = prefix.strip()
|
||||
location = location.strip()
|
||||
|
||||
if not location or not prefix or ' ' not in prefix:
|
||||
self.notify.warning("Ignoring malformed ldconfig -p line: " + line)
|
||||
continue
|
||||
|
||||
lib, opts = prefix.split(' ', 1)
|
||||
if ('x86-64' in opts) != self.platform.endswith('_amd64'):
|
||||
# This entry isn't meant for our architecture. I think
|
||||
# x86-64 is the only platform where ldconfig supplies
|
||||
# this extra arch string.
|
||||
continue
|
||||
|
||||
self.libraryCache[lib] = Filename.fromOsSpecific(location)
|
||||
|
||||
return True
|
||||
|
||||
def resolveLibrary(self, filename):
|
||||
""" Resolves the given shared library filename along the executable path,
|
||||
or by cross-referencing it with the library cache. """
|
||||
|
||||
path = str(filename)
|
||||
|
||||
if path in self.libraryCache:
|
||||
filename.setFullpath(self.libraryCache[path].getFullpath())
|
||||
return True
|
||||
|
||||
if filename.resolveFilename(self.executablePath):
|
||||
self.libraryCache[path] = Filename(filename)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def setPlatform(self, platform = None):
|
||||
""" Sets the platform that this Packager will compute for. On
|
||||
OSX, this can be used to specify the particular architecture
|
||||
|
|
@ -3143,9 +3227,17 @@ class Packager:
|
|||
for moduleName in args:
|
||||
self.currentPackage.freezer.excludeModule(moduleName)
|
||||
|
||||
def do_main(self, filename):
|
||||
""" Includes the indicated file as __main__ module of the application.
|
||||
Also updates mainModule to point to this module. """
|
||||
|
||||
self.addModule(['__main__'], '__main__', filename, required = True)
|
||||
self.currentPackage.mainModule = ('__main__', '__main__')
|
||||
|
||||
def do_mainModule(self, moduleName, newName = None, filename = None):
|
||||
""" Names the indicated module as the "main" module of the
|
||||
application or exe. """
|
||||
application or exe. In most cases, you will want to use main()
|
||||
instead. """
|
||||
|
||||
if not self.currentPackage:
|
||||
raise OutsideOfPackageError
|
||||
|
|
@ -3162,7 +3254,7 @@ class Packager:
|
|||
newFilename = Filename('/'.join(moduleName.split('.')))
|
||||
newFilename.setExtension(filename.getExtension())
|
||||
self.currentPackage.addFile(
|
||||
filename, newName = newFilename.cStr(),
|
||||
filename, newName = str(newFilename),
|
||||
explicit = True, extract = True, required = True)
|
||||
|
||||
self.currentPackage.mainModule = (moduleName, newName)
|
||||
|
|
@ -3194,7 +3286,9 @@ class Packager:
|
|||
# Multifile, so this file can't itself be in the Multifile.
|
||||
|
||||
# This requires a bit of care, because we only want to freeze
|
||||
# VFSImporter.py, and not any other part of direct.
|
||||
# VFSImporter.py, and not any other part of direct. We do
|
||||
# also want panda3d/__init__.py, though, since it would
|
||||
# otherwise be part of the multifile.
|
||||
self.do_excludeModule('direct')
|
||||
|
||||
# Import the actual VFSImporter module to get its filename on
|
||||
|
|
@ -3205,7 +3299,7 @@ class Packager:
|
|||
self.do_module('VFSImporter', filename = filename)
|
||||
self.do_freeze('_vfsimporter', compileToExe = False)
|
||||
|
||||
self.do_file('libpandaexpress.dll');
|
||||
self.do_file('panda3d/core.pyd');
|
||||
|
||||
# Now that we're done freezing, explicitly add 'direct' to
|
||||
# counteract the previous explicit excludeModule().
|
||||
|
|
@ -3438,13 +3532,13 @@ class Packager:
|
|||
# build.
|
||||
dllFilename = Filename(filename)
|
||||
dllFilename.setExtension('so')
|
||||
dllFilename = Filename.dsoFilename(dllFilename.cStr())
|
||||
dllFilename = Filename.dsoFilename(str(dllFilename))
|
||||
if dllFilename != filename:
|
||||
thisFiles = glob.glob(filename.toOsSpecific())
|
||||
if not thisFiles:
|
||||
# We have to resolve this filename to
|
||||
# determine if it's a _d or not.
|
||||
if dllFilename.resolveFilename(self.executablePath):
|
||||
if self.resolveLibrary(dllFilename):
|
||||
thisFiles = [dllFilename.toOsSpecific()]
|
||||
else:
|
||||
thisFiles = [filename.toOsSpecific()]
|
||||
|
|
@ -3455,7 +3549,7 @@ class Packager:
|
|||
|
||||
prefix = ''
|
||||
if newDir is not None:
|
||||
prefix = Filename(newDir).cStr()
|
||||
prefix = str(Filename(newDir))
|
||||
if prefix and prefix[-1] != '/':
|
||||
prefix += '/'
|
||||
|
||||
|
|
@ -3527,13 +3621,22 @@ class Packager:
|
|||
sys.path.append(dirname.toOsSpecific())
|
||||
self.__recurseDir(dirname, newDir, unprocessed = unprocessed)
|
||||
|
||||
def __recurseDir(self, filename, newName, unprocessed = None):
|
||||
def __recurseDir(self, filename, newName, unprocessed = None, packageTree = None):
|
||||
dirList = vfs.scanDirectory(filename)
|
||||
if dirList:
|
||||
# It's a directory name. Recurse.
|
||||
prefix = newName
|
||||
if prefix and prefix[-1] != '/':
|
||||
prefix += '/'
|
||||
|
||||
# First check if this is a Python package tree. If so, add it
|
||||
# implicitly as a module.
|
||||
for subfile in dirList:
|
||||
filename = subfile.getFilename()
|
||||
if filename.getBasename() == '__init__.py':
|
||||
moduleName = newName.replace("/", ".").rsplit('.', 1)[0]
|
||||
self.addModule([moduleName], filename=filename)
|
||||
|
||||
for subfile in dirList:
|
||||
filename = subfile.getFilename()
|
||||
self.__recurseDir(filename, prefix + filename.getBasename(),
|
||||
|
|
@ -3550,7 +3653,7 @@ class Packager:
|
|||
# Strip off an implicit .pz extension.
|
||||
newFilename = Filename(filename)
|
||||
newFilename.setExtension('')
|
||||
newFilename = Filename(newFilename.cStr())
|
||||
newFilename = Filename(str(newFilename))
|
||||
ext = newFilename.getExtension()
|
||||
|
||||
if ext in self.knownExtensions:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from direct.p3d.FileSpec import FileSpec
|
||||
from direct.p3d.SeqValue import SeqValue
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
import copy
|
||||
|
||||
class PatchMaker:
|
||||
|
|
@ -14,7 +14,7 @@ class PatchMaker:
|
|||
the package's "version" string; it also corresponds to the
|
||||
particular patch version, which increments independently of
|
||||
the "version". """
|
||||
|
||||
|
||||
def __init__(self, packageName, platform, version, hostUrl, file):
|
||||
self.packageName = packageName
|
||||
self.platform = platform
|
||||
|
|
@ -84,7 +84,7 @@ class PatchMaker:
|
|||
apply in sequence, and the packageVersion object
|
||||
associated with each patch. Returns (None, None, None) if
|
||||
there is no way to recreate this archive file. """
|
||||
|
||||
|
||||
if self.tempFile:
|
||||
return (self.tempFile, self, [])
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ class PatchMaker:
|
|||
# version of some package.
|
||||
package = self.packageCurrent
|
||||
return (Filename(package.packageDir, package.compressedFilename), self, [])
|
||||
|
||||
|
||||
if self.packageBase:
|
||||
# This PackageVersion instance represents the base
|
||||
# (oldest) version of some package.
|
||||
|
|
@ -144,7 +144,7 @@ class PatchMaker:
|
|||
# Failure trying to decompress the file.
|
||||
return None
|
||||
startFile = startPv.tempFile
|
||||
|
||||
|
||||
if not plan:
|
||||
# If plan is a zero-length list, we're already
|
||||
# here--return startFile. If plan is None, there's no
|
||||
|
|
@ -162,7 +162,7 @@ class PatchMaker:
|
|||
if not result:
|
||||
# Failure trying to re-create the file.
|
||||
return None
|
||||
|
||||
|
||||
pv.tempFile = result
|
||||
prevFile = result
|
||||
|
||||
|
|
@ -194,10 +194,10 @@ class PatchMaker:
|
|||
return patch.toPv
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class Patchfile:
|
||||
""" A single patchfile for a package. """
|
||||
|
||||
|
||||
def __init__(self, package):
|
||||
self.package = package
|
||||
self.packageName = package.packageName
|
||||
|
|
@ -233,7 +233,7 @@ class PatchMaker:
|
|||
def fromFile(self, packageDir, patchFilename, sourceFile, targetFile):
|
||||
""" Creates the data structures from an existing patchfile
|
||||
on disk. """
|
||||
|
||||
|
||||
self.file = FileSpec()
|
||||
self.file.fromFile(packageDir, patchFilename)
|
||||
self.sourceFile = sourceFile
|
||||
|
|
@ -241,7 +241,7 @@ class PatchMaker:
|
|||
|
||||
def loadXml(self, xpatch):
|
||||
""" Reads the data structures from an xml file. """
|
||||
|
||||
|
||||
self.packageName = xpatch.Attribute('name') or self.packageName
|
||||
self.platform = xpatch.Attribute('platform') or self.platform
|
||||
self.version = xpatch.Attribute('version') or self.version
|
||||
|
|
@ -287,7 +287,7 @@ class PatchMaker:
|
|||
class Package:
|
||||
""" This is a particular package. This contains all of the
|
||||
information needed to reconstruct the package's desc file. """
|
||||
|
||||
|
||||
def __init__(self, packageDesc, patchMaker, xpackage = None):
|
||||
self.packageDir = Filename(patchMaker.installDir, packageDesc.getDirname())
|
||||
self.packageDesc = packageDesc
|
||||
|
|
@ -312,19 +312,19 @@ class PatchMaker:
|
|||
def getCurrentKey(self):
|
||||
""" Returns the key to locate the current version of this
|
||||
package. """
|
||||
|
||||
|
||||
return (self.packageName, self.platform, self.version, self.hostUrl, self.currentFile)
|
||||
|
||||
def getBaseKey(self):
|
||||
""" Returns the key to locate the "base" or oldest version
|
||||
of this package. """
|
||||
|
||||
|
||||
return (self.packageName, self.platform, self.version, self.hostUrl, self.baseFile)
|
||||
|
||||
def getTopKey(self):
|
||||
""" Returns the key to locate the "top" or newest version
|
||||
of this package. """
|
||||
|
||||
|
||||
return (self.packageName, self.platform, self.version, self.hostUrl, self.topFile)
|
||||
|
||||
def getGenericKey(self, fileSpec):
|
||||
|
|
@ -345,7 +345,7 @@ class PatchMaker:
|
|||
if not self.doc.LoadFile():
|
||||
print "Couldn't read %s" % (packageDescFullpath)
|
||||
return False
|
||||
|
||||
|
||||
xpackage = self.doc.FirstChildElement('package')
|
||||
if not xpackage:
|
||||
return False
|
||||
|
|
@ -358,7 +358,7 @@ class PatchMaker:
|
|||
# other hosts, which means we'll need to fill in a value
|
||||
# here for those hosts.
|
||||
self.hostUrl = None
|
||||
|
||||
|
||||
self.currentFile = None
|
||||
self.baseFile = None
|
||||
self.topFile = None
|
||||
|
|
@ -388,7 +388,7 @@ class PatchMaker:
|
|||
else:
|
||||
# There's a new version this pass. Update it.
|
||||
self.anyChanges = True
|
||||
|
||||
|
||||
else:
|
||||
# If there isn't a top_version yet, we have to make
|
||||
# one, by duplicating the currentFile.
|
||||
|
|
@ -516,7 +516,7 @@ class PatchMaker:
|
|||
xarchive = TiXmlElement('top_version')
|
||||
self.currentFile.storeXml(xarchive)
|
||||
xpackage.InsertEndChild(xarchive)
|
||||
|
||||
|
||||
for patchfile in self.patches:
|
||||
xpatch = patchfile.makeXml(self)
|
||||
xpackage.InsertEndChild(xpatch)
|
||||
|
|
@ -571,7 +571,7 @@ class PatchMaker:
|
|||
patches for all packages; otherwise, it should be a list of
|
||||
package name strings, limiting the set of packages that are
|
||||
processed. """
|
||||
|
||||
|
||||
if not self.readContentsFile():
|
||||
return False
|
||||
self.buildPatchChains()
|
||||
|
|
@ -587,7 +587,7 @@ class PatchMaker:
|
|||
def cleanup(self):
|
||||
""" Should be called on exit to remove temporary files and
|
||||
such created during processing. """
|
||||
|
||||
|
||||
for pv in self.packageVersions.values():
|
||||
pv.cleanup()
|
||||
|
||||
|
|
@ -596,11 +596,11 @@ class PatchMaker:
|
|||
constructs a patch chain from the version represented by
|
||||
fileSpec to the current version of this package, if possible.
|
||||
Returns the patch chain if successful, or None otherwise. """
|
||||
|
||||
|
||||
package = self.readPackageDescFile(descFilename)
|
||||
if not package:
|
||||
return None
|
||||
|
||||
|
||||
self.buildPatchChains()
|
||||
fromPv = self.getPackageVersion(package.getGenericKey(fileSpec))
|
||||
toPv = package.currentPv
|
||||
|
|
@ -619,7 +619,7 @@ class PatchMaker:
|
|||
package = self.Package(Filename(descFilename), self)
|
||||
if not package.readDescFile(doProcessing = False):
|
||||
return None
|
||||
|
||||
|
||||
self.packages.append(package)
|
||||
return package
|
||||
|
||||
|
|
@ -640,7 +640,7 @@ class PatchMaker:
|
|||
contentsSeq.loadXml(xcontents)
|
||||
contentsSeq += 1
|
||||
contentsSeq.storeXml(xcontents)
|
||||
|
||||
|
||||
xpackage = xcontents.FirstChildElement('package')
|
||||
while xpackage:
|
||||
solo = xpackage.Attribute('solo')
|
||||
|
|
@ -651,7 +651,7 @@ class PatchMaker:
|
|||
package = self.Package(filename, self, xpackage)
|
||||
package.readDescFile(doProcessing = True)
|
||||
self.packages.append(package)
|
||||
|
||||
|
||||
xpackage = xpackage.NextSiblingElement('package')
|
||||
|
||||
self.contentsDoc = doc
|
||||
|
|
@ -685,7 +685,7 @@ class PatchMaker:
|
|||
pv = self.PackageVersion(*key)
|
||||
self.packageVersions[k] = pv
|
||||
return pv
|
||||
|
||||
|
||||
def buildPatchChains(self):
|
||||
""" Builds up the chains of PackageVersions and the patchfiles
|
||||
that connect them. """
|
||||
|
|
@ -696,7 +696,7 @@ class PatchMaker:
|
|||
if not package.baseFile:
|
||||
# This package doesn't have any versions yet.
|
||||
continue
|
||||
|
||||
|
||||
currentPv = self.getPackageVersion(package.getCurrentKey())
|
||||
package.currentPv = currentPv
|
||||
currentPv.packageCurrent = package
|
||||
|
|
@ -710,7 +710,7 @@ class PatchMaker:
|
|||
topPv = self.getPackageVersion(package.getTopKey())
|
||||
package.topPv = topPv
|
||||
topPv.packageTop = package
|
||||
|
||||
|
||||
for patchfile in package.patches:
|
||||
self.recordPatchfile(patchfile)
|
||||
|
||||
|
|
@ -757,7 +757,7 @@ class PatchMaker:
|
|||
# What's the current version on the top of the tree?
|
||||
topPv = package.topPv
|
||||
currentPv = package.currentPv
|
||||
|
||||
|
||||
if topPv != currentPv:
|
||||
# They're different, so build a new patch.
|
||||
filename = Filename(package.currentFile.filename + '.%s.patch' % (package.patchVersion))
|
||||
|
|
@ -786,7 +786,7 @@ class PatchMaker:
|
|||
v1.file, v2.file)
|
||||
package.patches.append(patchfile)
|
||||
package.anyChanges = True
|
||||
|
||||
|
||||
self.recordPatchfile(patchfile)
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from pandac.PandaModules import VirtualFileSystem, VirtualFileMountSystem, Filename, TiXmlDocument
|
||||
from panda3d.core import VirtualFileSystem, VirtualFileMountSystem, Filename, TiXmlDocument
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
|
||||
class ScanDirectoryNode:
|
||||
""" This class is used to scan a list of files on disk. """
|
||||
|
||||
|
||||
def __init__(self, pathname, ignoreUsageXml = False):
|
||||
self.pathname = pathname
|
||||
self.filenames = []
|
||||
|
|
@ -38,7 +38,7 @@ class ScanDirectoryNode:
|
|||
if not isinstance(vfile.getMount(), VirtualFileMountSystem):
|
||||
# Not a real file; ignore it.
|
||||
continue
|
||||
|
||||
|
||||
if vfile.isDirectory():
|
||||
# A nested directory.
|
||||
subdir = ScanDirectoryNode(vfile.getFilename(), ignoreUsageXml = ignoreUsageXml)
|
||||
|
|
@ -49,7 +49,7 @@ class ScanDirectoryNode:
|
|||
# A nested file.
|
||||
self.filenames.append(vfile.getFilename())
|
||||
self.fileSize += vfile.getFileSize()
|
||||
|
||||
|
||||
else:
|
||||
# Some other wacky file thing.
|
||||
self.filenames.append(vfile.getFilename())
|
||||
|
|
@ -78,7 +78,7 @@ class ScanDirectoryNode:
|
|||
self.nested.remove(subdir)
|
||||
self.nestedSize -= subdir.getTotalSize()
|
||||
return subdir
|
||||
|
||||
|
||||
result = subdir.extractSubdir(pathname)
|
||||
if result:
|
||||
self.nestedSize -= result.getTotalSize()
|
||||
|
|
@ -89,5 +89,5 @@ class ScanDirectoryNode:
|
|||
return result
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from pandac.PandaModules import getModelPath, Filename, ConfigVariableFilename, DSearchPath, ExecutionEnvironment, PandaSystem
|
||||
from panda3d.core import getModelPath, Filename, ConfigVariableFilename, DSearchPath, ExecutionEnvironment, PandaSystem
|
||||
|
||||
# This file defines a number of standard "packages" that correspond to
|
||||
# a Panda3D distribution. These packages are built by passing this
|
||||
|
|
@ -57,7 +57,7 @@ class images(package):
|
|||
basename = '%s.jpg' % (name)
|
||||
filename = Filename(basename)
|
||||
found = filename.resolveFilename(search)
|
||||
|
||||
|
||||
if found:
|
||||
# Add the image file to the package
|
||||
file(filename, newName = basename, extract = True)
|
||||
|
|
@ -91,7 +91,7 @@ class certlist(package):
|
|||
# ".pem" or ".crt" extension, and they should be added with the
|
||||
# extract = True flag so they will be extracted to disk.
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class p3dcert(package):
|
||||
# This special application, used to pop up a dialog to prompt the
|
||||
|
|
@ -102,7 +102,7 @@ class p3dcert(package):
|
|||
# On Mac, we package up a P3DCert.app bundle. This includes
|
||||
# specifications in the plist file to avoid creating a dock
|
||||
# icon and stuff.
|
||||
|
||||
|
||||
# Find p3dcert.plist in the direct source tree.
|
||||
import direct
|
||||
plist = Filename(direct.__path__[0], 'plugin/p3dcert.plist')
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ import os
|
|||
import getopt
|
||||
import glob
|
||||
import direct
|
||||
from direct.p3d import Packager
|
||||
from pandac.PandaModules import *
|
||||
from direct.p3d import Packager
|
||||
from panda3d.core import *
|
||||
|
||||
# Temp hack for debugging.
|
||||
#from direct.p3d.AppRunner import dummyAppRunner; dummyAppRunner()
|
||||
|
|
@ -113,7 +113,7 @@ def makePackedApp(args):
|
|||
configFlags = []
|
||||
requires = []
|
||||
allowPythonDev = False
|
||||
|
||||
|
||||
for option, value in opts:
|
||||
if option == '-o':
|
||||
appFilename = Filename.fromOsSpecific(value)
|
||||
|
|
@ -183,11 +183,7 @@ def makePackedApp(args):
|
|||
main = os.path.split(main[0])[1]
|
||||
|
||||
main = Filename.fromOsSpecific(main)
|
||||
mainModule = Filename(main)
|
||||
mainModule.setExtension('')
|
||||
|
||||
mainModule = mainModule.cStr().replace('/', '.')
|
||||
|
||||
packager.installDir = appDir
|
||||
packager.allowPythonDev = allowPythonDev
|
||||
|
||||
|
|
@ -206,7 +202,7 @@ def makePackedApp(args):
|
|||
# panda3d.
|
||||
if 'panda3d' not in [t[0] for t in requires]:
|
||||
packager.do_require('panda3d')
|
||||
|
||||
|
||||
for name, version, host in requires:
|
||||
packager.do_require(name, version = version, host = host)
|
||||
|
||||
|
|
@ -214,10 +210,10 @@ def makePackedApp(args):
|
|||
packager.do_config(**dict(configFlags))
|
||||
|
||||
packager.do_dir(root)
|
||||
packager.do_mainModule(mainModule)
|
||||
packager.do_main(main)
|
||||
packager.endPackage()
|
||||
packager.close()
|
||||
|
||||
|
||||
except Packager.PackagerError:
|
||||
# Just print the error message and exit gracefully.
|
||||
inst = sys.exc_info()[1]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from pandac.PandaModules import Filename, PandaSystem, getModelPath
|
||||
from panda3d.core import Filename, PandaSystem, getModelPath
|
||||
|
||||
# This file defines a number of standard "packages" that correspond to
|
||||
# a Panda3D distribution. These packages are built by passing this
|
||||
|
|
@ -54,7 +54,11 @@ class panda3d(package):
|
|||
'direct.showutil.*',
|
||||
'direct.stdpy.*',
|
||||
'direct.task.*')
|
||||
module('panda3d')
|
||||
|
||||
module('panda3d.core',
|
||||
'panda3d.direct',
|
||||
'panda3d.fx',
|
||||
'panda3d.physics')
|
||||
|
||||
# Include various standard Python encodings. The rest is in morepy.
|
||||
module('encodings', 'encodings.aliases', 'encodings.undefined,'
|
||||
|
|
@ -65,9 +69,19 @@ class panda3d(package):
|
|||
import direct
|
||||
file(Filename(direct.__path__[0], 'filter/*.sha'), newDir = 'direct/filter')
|
||||
|
||||
# pandac.PandaModules pulls in other Panda3D libs automatically.
|
||||
# Exclude these Panda3D libs; they are big and many applications don't
|
||||
# use them. We define them as separate, optional packages, below,
|
||||
# except for skel - this is useless in a shipped game anyways.
|
||||
excludeModule('panda3d.egg')
|
||||
excludeModule('panda3d.ode')
|
||||
excludeModule('panda3d.bullet')
|
||||
excludeModule('panda3d.vision')
|
||||
excludeModule('panda3d.skel')
|
||||
excludeModule('panda3d.physx')
|
||||
excludeModule('panda3d.ai')
|
||||
excludeModule('panda3d.vrpn')
|
||||
|
||||
excludeModule('libpandaegg')
|
||||
excludeModule('libpandaode')
|
||||
excludeModule('libpandabullet')
|
||||
|
|
@ -89,6 +103,8 @@ class panda3d(package):
|
|||
|
||||
excludeModule('MySQLdb', '_mysql')
|
||||
|
||||
excludeModule('xml', 'xml.parsers.expat', 'xml.sax')
|
||||
|
||||
# Most of the core Panda3D DLL's will be included implicitly due to
|
||||
# being referenced by the above Python code. Here we name a few more
|
||||
# that are also needed, but aren't referenced by any code. Again,
|
||||
|
|
@ -269,6 +285,7 @@ class egg(package):
|
|||
config(display_name = "Panda3D egg loader")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.egg', required = True)
|
||||
file('libpandaegg.dll', required = True)
|
||||
file('libp3ptloader.dll', required = True)
|
||||
|
||||
|
|
@ -286,6 +303,7 @@ class ode(package):
|
|||
config(display_name = "Panda3D Open Dynamics Engine integration")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.ode', required = True)
|
||||
file('libpandaode.dll', required = True)
|
||||
|
||||
class bullet(package):
|
||||
|
|
@ -296,6 +314,7 @@ class bullet(package):
|
|||
config(display_name = "Panda3D Bullet integration")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.bullet', required = True)
|
||||
file('libpandabullet.dll', required = True)
|
||||
|
||||
class physx(package):
|
||||
|
|
@ -306,6 +325,7 @@ class physx(package):
|
|||
config(display_name = "Panda3D PhysX integration")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.physx', required = True)
|
||||
file('libpandaphysx.dll', required = True)
|
||||
file('physxcudart_20.dll')
|
||||
file('PhysXDevice.dll')
|
||||
|
|
@ -319,6 +339,7 @@ class ai(package):
|
|||
config(display_name = "Panda3D AI modules")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.ai', required = True)
|
||||
file('libpandaai.dll', required = True)
|
||||
|
||||
class vision(package):
|
||||
|
|
@ -330,6 +351,7 @@ class vision(package):
|
|||
config(display_name = "Panda3D vision modules")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.vision', required = True)
|
||||
file('libp3vision.dll', required = True)
|
||||
|
||||
class rocket(package):
|
||||
|
|
@ -340,6 +362,7 @@ class rocket(package):
|
|||
config(display_name = "Panda3D libRocket support")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.rocket', required = True)
|
||||
module('_rocketcore', '_rocketcontrols')
|
||||
file('libp3rocket.dll', required = True)
|
||||
|
||||
|
|
@ -350,6 +373,7 @@ class vrpn(package):
|
|||
config(display_name = "Panda3D VRPN support")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.vrpn')
|
||||
file('libp3vrpn.dll', required = True)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ Options:
|
|||
is licensed under.
|
||||
Only relevant when generating a graphical installer.
|
||||
|
||||
-O
|
||||
-O
|
||||
Specify this option when generating a graphical installer to omit
|
||||
the default checkboxes for "run this program" and "install a
|
||||
desktop shortcut" on completion.
|
||||
|
|
@ -147,7 +147,7 @@ import sys
|
|||
import os
|
||||
import getopt
|
||||
from direct.p3d.DeploymentTools import Standalone, Installer, Icon
|
||||
from pandac.PandaModules import Filename, PandaSystem
|
||||
from panda3d.core import Filename, PandaSystem
|
||||
|
||||
def usage(code, msg = ''):
|
||||
if not msg:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import getopt
|
|||
import os
|
||||
|
||||
from direct.p3d import PackageMerger
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
|
||||
def usage(code, msg = ''):
|
||||
print >> sys.stderr, usageText % {'prog' : os.path.split(sys.argv[0])[1]}
|
||||
|
|
@ -66,7 +66,7 @@ for opt, arg in opts:
|
|||
installDir = Filename.fromOsSpecific(arg)
|
||||
elif opt == '-p':
|
||||
packageNames += arg.split(',')
|
||||
|
||||
|
||||
elif opt == '-h':
|
||||
usage(0)
|
||||
else:
|
||||
|
|
@ -92,7 +92,7 @@ try:
|
|||
for dir in inputDirs:
|
||||
pm.merge(dir, packageNames = packageNames)
|
||||
pm.close()
|
||||
|
||||
|
||||
except PackageMerger.PackageMergerError:
|
||||
# Just print the error message and exit gracefully.
|
||||
inst = sys.exc_info()[1]
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ import getopt
|
|||
import os
|
||||
|
||||
from direct.p3d import Packager
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
|
||||
def usage(code, msg = ''):
|
||||
print >> sys.stderr, usageText % {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ import getopt
|
|||
import os
|
||||
|
||||
from direct.p3d.PatchMaker import PatchMaker
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
|
||||
def usage(code, msg = ''):
|
||||
print >> sys.stderr, usageText % {'prog' : os.path.split(sys.argv[0])[1]}
|
||||
|
|
@ -76,7 +76,7 @@ installDir = None
|
|||
for opt, arg in opts:
|
||||
if opt == '-i':
|
||||
installDir = Filename.fromOsSpecific(arg)
|
||||
|
||||
|
||||
elif opt == '-h':
|
||||
usage(0)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import sys
|
|||
import getopt
|
||||
from AppRunner import AppRunner, ArgumentError
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from pandac.PandaModules import Filename
|
||||
from panda3d.core import Filename
|
||||
|
||||
def parseSysArgs():
|
||||
""" Handles sys.argv, if there are any local arguments, and
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
# Also see panda3d.pdef.
|
||||
|
||||
from pandac.PandaModules import Filename
|
||||
from panda3d.core import Filename
|
||||
import sys
|
||||
|
||||
class wx(package):
|
||||
|
|
@ -95,7 +95,7 @@ class twisted(package):
|
|||
'twisted.runner', 'twisted.scripts', 'twisted.spread',
|
||||
'twisted.tap', 'twisted.trial', 'twisted.vfs',
|
||||
'twisted.web', 'twisted.web2', 'twisted.words')
|
||||
|
||||
|
||||
module('twisted.*', 'twisted.*.*')
|
||||
|
||||
class pil(package):
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ TypeHandle P3DPythonRun::P3DWindowHandle::_type_handle;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DPythonRun::
|
||||
P3DPythonRun(const char *program_name, const char *archive_file,
|
||||
FHandle input_handle, FHandle output_handle,
|
||||
FHandle input_handle, FHandle output_handle,
|
||||
const char *log_pathname, bool interactive_console) {
|
||||
P3DWindowHandle::init_type();
|
||||
init_xml();
|
||||
|
|
@ -115,7 +115,7 @@ P3DPythonRun(const char *program_name, const char *archive_file,
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DPythonRun::
|
||||
~P3DPythonRun() {
|
||||
|
|
@ -150,72 +150,32 @@ run_python() {
|
|||
PyRun_SimpleString("import sys; sys.dll_suffix = '_d'");
|
||||
#endif
|
||||
|
||||
// We'll need libpandaexpress to be imported before we can load
|
||||
// _vfsimporter. So, find it and load it.
|
||||
Filename libpandaexpress;
|
||||
Filename dir = _archive_file.get_dirname();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Of course it's already resident, so use that version.
|
||||
wstring basename = Filename::dso_filename("libpandaexpress.so").to_os_specific_w();
|
||||
HMODULE h = GetModuleHandleW(basename.c_str());
|
||||
|
||||
if (h == NULL) {
|
||||
nout << "Can't find libpandaexpress in memory.\n";
|
||||
} else {
|
||||
static const int buffer_size = 4096;
|
||||
wchar_t buffer[buffer_size];
|
||||
GetModuleFileNameW(h, buffer, buffer_size);
|
||||
libpandaexpress = Filename::from_os_specific_w(buffer);
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
if (libpandaexpress.empty()) {
|
||||
// Go look for it on disk.
|
||||
libpandaexpress = Filename(_archive_file.get_dirname(),
|
||||
Filename::dso_filename("libpandaexpress.so"));
|
||||
#if defined(__APPLE__) && PY_VERSION_HEX < 0x02050000
|
||||
// On OSX, for Python versions 2.4 and before, we have to load the
|
||||
// .so file, not the .dylib file.
|
||||
libpandaexpress.set_type(Filename::T_general);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!libpandaexpress.exists()) {
|
||||
nout << "Can't find " << libpandaexpress << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need the "imp" built-in module for that.
|
||||
PyObject *imp_module = PyImport_ImportModule("imp");
|
||||
if (imp_module == NULL) {
|
||||
nout << "Failed to import module imp\n";
|
||||
// We'll need to synthesize a 'panda3d' module before loading
|
||||
// VFSImporter. We could simply freeze it, but Python has a bug
|
||||
// setting __path__ of frozen modules properly.
|
||||
PyObject *panda3d_module = PyImport_AddModule("panda3d");
|
||||
if (panda3d_module == NULL) {
|
||||
nout << "Failed to create panda3d module:\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// And here's where we run into a brick wall attempting to make the
|
||||
// whole plugin system Unicode-safe for Windows. It turns out that
|
||||
// this Python call, imp.load_dynamic(), will not accept a Unicode
|
||||
// pathname. So if the DLL in question is in a location that
|
||||
// contains non-ASCII characters, it can't be loaded.
|
||||
string os_specific = libpandaexpress.to_os_specific();
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(imp_module, (char *)"load_dynamic", (char *)"ss",
|
||||
"libpandaexpress", os_specific.c_str());
|
||||
if (result == NULL) {
|
||||
nout << "Failed to import libpandaexpress as a module\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
Py_DECREF(result);
|
||||
Py_DECREF(imp_module);
|
||||
// Set the __path__ such that it can find panda3d/core.pyd, etc.
|
||||
Filename panda3d_dir(dir, "panda3d");
|
||||
string dir_str = panda3d_dir.to_os_specific();
|
||||
PyObject *panda3d_dict = PyModule_GetDict(panda3d_module);
|
||||
PyObject *panda3d_path = Py_BuildValue("[s#]", dir_str.data(), dir_str.length());
|
||||
PyDict_SetItemString(panda3d_dict, "__path__", panda3d_path);
|
||||
Py_DECREF(panda3d_path);
|
||||
|
||||
// Now we can load _vfsimporter.pyd. Since this is a magic frozen
|
||||
// pyd, importing it automatically makes all of its frozen contents
|
||||
// available to import as well.
|
||||
PyObject *vfsimporter = PyImport_ImportModule("_vfsimporter");
|
||||
if (vfsimporter == NULL) {
|
||||
nout << "Failed to import _vfsimporter\n";
|
||||
nout << "Failed to import _vfsimporter:\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -224,15 +184,15 @@ run_python() {
|
|||
// And now we can import the VFSImporter module that was so defined.
|
||||
PyObject *vfsimporter_module = PyImport_ImportModule("VFSImporter");
|
||||
if (vfsimporter_module == NULL) {
|
||||
nout << "Failed to import VFSImporter\n";
|
||||
nout << "Failed to import VFSImporter:\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// And register the VFSImporter.
|
||||
result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
|
||||
PyObject *result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
|
||||
if (result == NULL) {
|
||||
nout << "Failed to call VFSImporter.register()\n";
|
||||
nout << "Failed to call VFSImporter.register():\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -248,7 +208,6 @@ run_python() {
|
|||
nout << "Could not read " << _archive_file << "\n";
|
||||
return false;
|
||||
}
|
||||
Filename dir = _archive_file.get_dirname();
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
if (!vfs->mount(mf, dir, VirtualFileSystem::MF_read_only)) {
|
||||
nout << "Could not mount " << _archive_file << "\n";
|
||||
|
|
@ -346,7 +305,7 @@ run_python() {
|
|||
}
|
||||
Py_DECREF(result);
|
||||
Py_DECREF(request_func);
|
||||
|
||||
|
||||
|
||||
// Now add check_comm() as a task. It can be a threaded task, but
|
||||
// this does mean that application programmers will have to be alert
|
||||
|
|
@ -545,7 +504,7 @@ handle_command(TiXmlDocument *doc) {
|
|||
assert(!needs_response);
|
||||
int instance_id;
|
||||
TiXmlElement *xwparams = xcommand->FirstChildElement("wparams");
|
||||
if (xwparams != (TiXmlElement *)NULL &&
|
||||
if (xwparams != (TiXmlElement *)NULL &&
|
||||
xcommand->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS) {
|
||||
setup_window(instance_id, xwparams);
|
||||
}
|
||||
|
|
@ -591,7 +550,7 @@ handle_command(TiXmlDocument *doc) {
|
|||
_sent_objects.erase(si);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
nout << "Unhandled command " << cmd << "\n";
|
||||
if (needs_response) {
|
||||
|
|
@ -678,7 +637,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||
if (method_name == NULL) {
|
||||
// No method name; call the object directly.
|
||||
result = PyObject_CallObject(obj, params);
|
||||
|
||||
|
||||
// Several special-case "method" names.
|
||||
} else if (strcmp(method_name, "__bool__") == 0) {
|
||||
result = PyBool_FromLong(PyObject_IsTrue(obj));
|
||||
|
|
@ -713,7 +672,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the object supports the mapping protocol, store it
|
||||
// in the object's dictionary.
|
||||
if (!success && PyMapping_Check(obj)) {
|
||||
|
|
@ -761,7 +720,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (success) {
|
||||
result = Py_True;
|
||||
} else {
|
||||
|
|
@ -1066,8 +1025,8 @@ py_request_func(PyObject *args) {
|
|||
PyObject *value;
|
||||
int needs_response;
|
||||
int unique_id;
|
||||
if (!PyArg_ParseTuple(extra_args, "sOsOii",
|
||||
&operation, &object, &property_name, &value,
|
||||
if (!PyArg_ParseTuple(extra_args, "sOsOii",
|
||||
&operation, &object, &property_name, &value,
|
||||
&needs_response, &unique_id)) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1256,7 +1215,7 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
|
|||
xinstance->Attribute("respect_per_platform", &respect_per_platform);
|
||||
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char *)"setInstanceInfo", (char *)"sssiOi", root_dir,
|
||||
(_runner, (char *)"setInstanceInfo", (char *)"sssiOi", root_dir,
|
||||
log_directory, super_mirror, verify_contents, main, respect_per_platform);
|
||||
Py_DECREF(main);
|
||||
|
||||
|
|
@ -1347,7 +1306,7 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
|
|||
value = value_c;
|
||||
}
|
||||
|
||||
PyObject *tuple = Py_BuildValue("(ss)", keyword.c_str(),
|
||||
PyObject *tuple = Py_BuildValue("(ss)", keyword.c_str(),
|
||||
value.c_str());
|
||||
PyList_Append(token_list, tuple);
|
||||
Py_DECREF(tuple);
|
||||
|
|
@ -1419,7 +1378,7 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
|
|||
}
|
||||
|
||||
int win_x, win_y, win_width, win_height;
|
||||
|
||||
|
||||
xwparams->Attribute("win_x", &win_x);
|
||||
xwparams->Attribute("win_y", &win_y);
|
||||
xwparams->Attribute("win_width", &win_width);
|
||||
|
|
@ -1531,7 +1490,7 @@ terminate_session() {
|
|||
Py_DECREF(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_session_terminated = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1772,7 +1731,7 @@ xml_to_pyobj(TiXmlElement *xvalue) {
|
|||
int object_id;
|
||||
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
|
||||
// Construct a new BrowserObject wrapper around this object.
|
||||
return PyObject_CallFunction(_browser_object_class, (char *)"Oi",
|
||||
return PyObject_CallFunction(_browser_object_class, (char *)"Oi",
|
||||
_runner, object_id);
|
||||
}
|
||||
|
||||
|
|
@ -1852,7 +1811,7 @@ rt_thread_run() {
|
|||
}
|
||||
|
||||
// Successfully read an XML document.
|
||||
|
||||
|
||||
// Check for one special case: the "exit" command means we shut
|
||||
// down the read thread along with everything else.
|
||||
TiXmlElement *xcommand = doc->FirstChildElement("command");
|
||||
|
|
@ -1875,7 +1834,7 @@ rt_thread_run() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::P3DWindowHandle::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DPythonRun::P3DWindowHandle::
|
||||
P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DX11SplashWindow::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DX11SplashWindow::
|
||||
P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
|
||||
P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
|
||||
P3DSplashWindow(inst, make_visible)
|
||||
{
|
||||
// Init for parent process
|
||||
|
|
@ -61,7 +61,7 @@ P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DX11SplashWindow::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DX11SplashWindow::
|
||||
~P3DX11SplashWindow() {
|
||||
|
|
@ -312,13 +312,13 @@ stop_subprocess() {
|
|||
_pipe_write.close();
|
||||
|
||||
static const int max_wait_ms = 2000;
|
||||
|
||||
|
||||
// Wait for a certain amount of time for the process to stop by
|
||||
// itself.
|
||||
struct timeval start;
|
||||
gettimeofday(&start, NULL);
|
||||
int start_ms = start.tv_sec * 1000 + start.tv_usec / 1000;
|
||||
|
||||
|
||||
int status;
|
||||
pid_t result = waitpid(_subprocess_pid, &status, WNOHANG);
|
||||
while (result != _subprocess_pid) {
|
||||
|
|
@ -326,20 +326,20 @@ stop_subprocess() {
|
|||
perror("waitpid");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
int now_ms = now.tv_sec * 1000 + now.tv_usec / 1000;
|
||||
int elapsed = now_ms - start_ms;
|
||||
|
||||
|
||||
if (elapsed > max_wait_ms) {
|
||||
// Tired of waiting. Kill the process.
|
||||
nout << "Force-killing splash window process, pid " << _subprocess_pid
|
||||
nout << "Force-killing splash window process, pid " << _subprocess_pid
|
||||
<< "\n";
|
||||
kill(_subprocess_pid, SIGKILL);
|
||||
start_ms = now_ms;
|
||||
}
|
||||
|
||||
|
||||
// Yield the timeslice and wait some more.
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
|
|
@ -353,7 +353,7 @@ stop_subprocess() {
|
|||
nout << " exited normally, status = "
|
||||
<< WEXITSTATUS(status) << "\n";
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
<< WCOREDUMP(status) << "\n";
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
nout << " stopped by " << WSTOPSIG(status) << "\n";
|
||||
|
|
@ -396,7 +396,7 @@ check_stopped() {
|
|||
nout << " exited normally, status = "
|
||||
<< WEXITSTATUS(status) << "\n";
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
<< WCOREDUMP(status) << "\n";
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
nout << " stopped by " << WSTOPSIG(status) << "\n";
|
||||
|
|
@ -522,14 +522,14 @@ subprocess_run() {
|
|||
_win_height = event.xconfigure.height;
|
||||
|
||||
set_button_range(_button_ready_image);
|
||||
|
||||
|
||||
// If the window changes size, we need to recompute the
|
||||
// composed image.
|
||||
_needs_new_composite = true;
|
||||
}
|
||||
needs_redraw = true;
|
||||
break;
|
||||
|
||||
|
||||
case MotionNotify:
|
||||
set_mouse_data(event.xmotion.x, event.xmotion.y, _mouse_down);
|
||||
break;
|
||||
|
|
@ -537,7 +537,7 @@ subprocess_run() {
|
|||
case ButtonPress:
|
||||
set_mouse_data(_mouse_x, _mouse_y, true);
|
||||
break;
|
||||
|
||||
|
||||
case ButtonRelease:
|
||||
set_mouse_data(_mouse_x, _mouse_y, false);
|
||||
break;
|
||||
|
|
@ -563,7 +563,7 @@ subprocess_run() {
|
|||
needs_redraw = true;
|
||||
prev_label = _install_label;
|
||||
}
|
||||
|
||||
|
||||
if (_progress_known != prev_progress_known) {
|
||||
needs_update_progress = true;
|
||||
needs_redraw_progress = true;
|
||||
|
|
@ -592,7 +592,7 @@ subprocess_run() {
|
|||
needs_redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (needs_redraw) {
|
||||
redraw();
|
||||
XFlush(_display);
|
||||
|
|
@ -619,23 +619,23 @@ subprocess_run() {
|
|||
text_width + 4, text_height + 4, false);
|
||||
XDrawString(_display, _window, _graphics_context, text_x, text_y,
|
||||
_install_label.c_str(), _install_label.size());
|
||||
|
||||
|
||||
needs_draw_label = false;
|
||||
}
|
||||
|
||||
|
||||
if (needs_redraw_progress) {
|
||||
XClearArea(_display, _window,
|
||||
XClearArea(_display, _window,
|
||||
bar_x, bar_y, bar_width, bar_height, false);
|
||||
XDrawRectangle(_display, _window, _graphics_context,
|
||||
XDrawRectangle(_display, _window, _graphics_context,
|
||||
bar_x, bar_y, bar_width, bar_height);
|
||||
needs_update_progress = true;
|
||||
needs_redraw_progress = false;
|
||||
}
|
||||
|
||||
|
||||
if (needs_update_progress) {
|
||||
if (_progress_known) {
|
||||
int progress_width = (int)((bar_width - 2) * _install_progress + 0.5);
|
||||
XFillRectangle(_display, _window, _bar_context,
|
||||
XFillRectangle(_display, _window, _bar_context,
|
||||
bar_x + 1, bar_y + 1,
|
||||
progress_width + 1, bar_height - 1);
|
||||
} else {
|
||||
|
|
@ -649,7 +649,7 @@ subprocess_run() {
|
|||
progress = block_travel * 2 - progress;
|
||||
}
|
||||
|
||||
XFillRectangle(_display, _window, _bar_context,
|
||||
XFillRectangle(_display, _window, _bar_context,
|
||||
bar_x + 1 + progress, bar_y + 1,
|
||||
block_width + 1, bar_height - 1);
|
||||
}
|
||||
|
|
@ -665,7 +665,7 @@ subprocess_run() {
|
|||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(read_fd, &fds);
|
||||
|
||||
|
||||
// Sleep a bit to yield the timeslice if there's nothing new.
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
|
|
@ -729,27 +729,30 @@ receive_command() {
|
|||
} else if (strcmp(cmd, "set_image_filename") == 0) {
|
||||
const string *image_filename = xcommand->Attribute(string("image_filename"));
|
||||
int image_placement;
|
||||
if (image_filename != NULL &&
|
||||
if (image_filename != NULL &&
|
||||
xcommand->QueryIntAttribute("image_placement", &image_placement) == TIXML_SUCCESS) {
|
||||
|
||||
|
||||
X11ImageData *image = NULL;
|
||||
switch ((ImagePlacement)image_placement) {
|
||||
case IP_background:
|
||||
image = &_background_image;
|
||||
break;
|
||||
|
||||
|
||||
case IP_button_ready:
|
||||
image = &_button_ready_image;
|
||||
set_button_range(_button_ready_image);
|
||||
break;
|
||||
|
||||
|
||||
case IP_button_rollover:
|
||||
image = &_button_rollover_image;
|
||||
break;
|
||||
|
||||
|
||||
case IP_button_click:
|
||||
image = &_button_click_image;
|
||||
break;
|
||||
|
||||
case IP_none:
|
||||
break;
|
||||
}
|
||||
if (image != NULL) {
|
||||
if (image->_filename != *image_filename) {
|
||||
|
|
@ -804,7 +807,7 @@ redraw() {
|
|||
// If we have an image, draw it.
|
||||
int xo = (_win_width - _composite_width) / 2;
|
||||
int yo = (_win_height - _composite_height) / 2;
|
||||
XPutImage(_display, _window, _graphics_context, _composite_image, 0, 0,
|
||||
XPutImage(_display, _window, _graphics_context, _composite_image, 0, 0,
|
||||
xo, yo, _composite_width, _composite_height);
|
||||
|
||||
// Then clear the rectangles around it carefully (rather than just
|
||||
|
|
@ -840,12 +843,12 @@ make_window() {
|
|||
}
|
||||
|
||||
X11_Window parent = 0;
|
||||
|
||||
|
||||
// Hum, if we use the display provided by the browser,
|
||||
// it causes a crash in some browsers when you make an Xlib
|
||||
// call with the plugin window minimized.
|
||||
// So I kept XOpenDisplay until we have a better workaround.
|
||||
|
||||
|
||||
//_display = (X11_Display*) _wparams.get_parent_window()._xdisplay;
|
||||
//_own_display = false;
|
||||
//if (_display == 0) {
|
||||
|
|
@ -871,7 +874,7 @@ make_window() {
|
|||
// Create a toplevel window.
|
||||
parent = XRootWindow(_display, _screen);
|
||||
}
|
||||
|
||||
|
||||
assert(parent != None);
|
||||
|
||||
int depth = DefaultDepth(_display, _screen);
|
||||
|
|
@ -955,7 +958,7 @@ setup_gc() {
|
|||
XFontStruct* fs = XLoadQueryFont(_display, "6x13");
|
||||
|
||||
XGCValues gcval;
|
||||
gcval.font = fs->fid;
|
||||
gcval.font = fs->fid;
|
||||
gcval.function = GXcopy;
|
||||
gcval.plane_mask = AllPlanes;
|
||||
gcval.foreground = BlackPixel(_display, _screen);
|
||||
|
|
@ -966,8 +969,8 @@ setup_gc() {
|
|||
if (_bg_pixel != -1) {
|
||||
gcval.background = _bg_pixel;
|
||||
}
|
||||
_graphics_context = XCreateGC(_display, _window,
|
||||
GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
|
||||
_graphics_context = XCreateGC(_display, _window,
|
||||
GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
|
||||
|
||||
// Also create a gc for filling in the interior of the progress bar
|
||||
// in a pleasant blue color (or whatever color the user requested).
|
||||
|
|
@ -983,7 +986,7 @@ setup_gc() {
|
|||
gcval.foreground = bar.pixel;
|
||||
}
|
||||
|
||||
_bar_context = XCreateGC(_display, _window,
|
||||
_bar_context = XCreateGC(_display, _window,
|
||||
GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
|
||||
}
|
||||
|
||||
|
|
@ -998,7 +1001,7 @@ close_window() {
|
|||
XDestroyImage(_composite_image);
|
||||
_composite_image = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (_bar_context != None) {
|
||||
if (_bar_context != _graphics_context) {
|
||||
XFreeGC(_display, _bar_context);
|
||||
|
|
@ -1009,22 +1012,22 @@ close_window() {
|
|||
Colormap colormap = DefaultColormap(_display, _screen);
|
||||
XFreeColors(_display, colormap, &_bar_pixel, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
if (_fg_pixel != -1) {
|
||||
Colormap colormap = DefaultColormap(_display, _screen);
|
||||
XFreeColors(_display, colormap, &_fg_pixel, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
if (_bg_pixel != -1) {
|
||||
Colormap colormap = DefaultColormap(_display, _screen);
|
||||
XFreeColors(_display, colormap, &_bg_pixel, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
if (_graphics_context != None) {
|
||||
XFreeGC(_display, _graphics_context);
|
||||
_graphics_context = None;
|
||||
}
|
||||
|
||||
|
||||
if (_window != None) {
|
||||
XDestroyWindow(_display, _window);
|
||||
_window = None;
|
||||
|
|
@ -1150,7 +1153,7 @@ compose_image() {
|
|||
}
|
||||
|
||||
// Now load the image.
|
||||
_composite_image = XCreateImage(_display, CopyFromParent, DefaultDepth(_display, _screen),
|
||||
_composite_image = XCreateImage(_display, CopyFromParent, DefaultDepth(_display, _screen),
|
||||
ZPixmap, 0, (char *)new_data, image1_width, image1_height, 32, 0);
|
||||
_composite_width = image1_width;
|
||||
_composite_height = image1_height;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
__all__ = ['BufferViewer']
|
||||
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
from direct.task import Task
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ __all__ = ['DirectObject']
|
|||
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from MessengerGlobal import messenger
|
||||
from direct.showbase.PythonUtil import ClassTree
|
||||
|
||||
class DirectObject:
|
||||
"""
|
||||
|
|
@ -42,9 +41,6 @@ class DirectObject:
|
|||
def isIgnoring(self, event):
|
||||
return messenger.isIgnoring(event, self)
|
||||
|
||||
def classTree(self):
|
||||
return ClassTree(self)
|
||||
|
||||
#This function must be used if you want a managed task
|
||||
def addTask(self, *args, **kwargs):
|
||||
if(not hasattr(self,"_taskList")):
|
||||
|
|
|
|||
|
|
@ -5,11 +5,8 @@ __all__ = ['EventManager']
|
|||
|
||||
from MessengerGlobal import *
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
|
||||
# This module may not import pandac.PandaModules, since it is imported
|
||||
# by the Toontown Launcher before the complete PandaModules have been
|
||||
# downloaded.
|
||||
#from pandac.PandaModules import *
|
||||
from panda3d.core import PStatCollector, EventQueue, EventHandler
|
||||
from panda3d.core import EventStorePandaNode
|
||||
|
||||
class EventManager:
|
||||
|
||||
|
|
@ -43,7 +40,6 @@ class EventManager:
|
|||
"""
|
||||
if self._wantPstats is None:
|
||||
self._wantPstats = config.GetBool('pstats-eventmanager', 0)
|
||||
from pandac.PandaModules import PStatCollector
|
||||
EventManager.PStatCollector = PStatCollector
|
||||
# use different methods for handling events with and without pstats tracking
|
||||
# for efficiency
|
||||
|
|
@ -83,10 +79,7 @@ class EventManager:
|
|||
# which will be downcast to that type
|
||||
ptr = eventParameter.getPtr()
|
||||
|
||||
if EventManager.EventStorePandaNode is None:
|
||||
from pandac.PandaModules import EventStorePandaNode
|
||||
EventManager.EventStorePandaNode = EventStorePandaNode
|
||||
if isinstance(ptr, EventManager.EventStorePandaNode):
|
||||
if isinstance(ptr, EventStorePandaNode):
|
||||
# Actually, it's a kludgey wrapper around a PandaNode
|
||||
# pointer. Return the node.
|
||||
ptr = ptr.getValue()
|
||||
|
|
@ -190,22 +183,17 @@ class EventManager:
|
|||
|
||||
|
||||
def restart(self):
|
||||
if None in (EventManager.EventQueue, EventManager.EventHandler):
|
||||
from pandac.PandaModules import EventQueue, EventHandler
|
||||
EventManager.EventQueue = EventQueue
|
||||
EventManager.EventHandler = EventHandler
|
||||
|
||||
if self.eventQueue == None:
|
||||
self.eventQueue = EventManager.EventQueue.getGlobalEventQueue()
|
||||
self.eventQueue = EventQueue.getGlobalEventQueue()
|
||||
|
||||
if self.eventHandler == None:
|
||||
if self.eventQueue == EventManager.EventQueue.getGlobalEventQueue():
|
||||
if self.eventQueue == EventQueue.getGlobalEventQueue():
|
||||
# If we are using the global event queue, then we also
|
||||
# want to use the global event handler.
|
||||
self.eventHandler = EventManager.EventHandler.getGlobalEventHandler()
|
||||
self.eventHandler = EventHandler.getGlobalEventHandler()
|
||||
else:
|
||||
# Otherwise, we need our own event handler.
|
||||
self.eventHandler = EventManager.EventHandler(self.eventQueue)
|
||||
self.eventHandler = EventHandler(self.eventQueue)
|
||||
|
||||
# Should be safe to import the global taskMgr by now.
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from pandac.PandaModules import getConfigShowbase
|
||||
from panda3d.direct import get_config_showbase
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.showbase.PythonUtil import fastRepr
|
||||
import sys
|
||||
|
|
@ -6,7 +6,7 @@ import types
|
|||
import traceback
|
||||
|
||||
notify = directNotify.newCategory("ExceptionVarDump")
|
||||
config = getConfigShowbase()
|
||||
config = get_config_showbase()
|
||||
|
||||
reentry = 0
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ def _excepthookDumpVars(eType, eValue, tb):
|
|||
for attrName in attrNames:
|
||||
obj = attrName2obj[attrName]
|
||||
stateStack.push(['%s.%s' % (name, attrName), obj, ids])
|
||||
|
||||
|
||||
tb = tb.tb_next
|
||||
|
||||
if foundRun:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from direct.showbase.DirectObject import DirectObject
|
||||
|
||||
if __debug__:
|
||||
from pandac.PandaModules import PStatCollector
|
||||
from panda3d.core import PStatCollector
|
||||
|
||||
class Job(DirectObject):
|
||||
# Base class for cpu-intensive or non-time-critical operations that
|
||||
|
|
|
|||
|
|
@ -7,78 +7,8 @@ from PythonUtil import *
|
|||
from direct.directnotify import DirectNotifyGlobal
|
||||
import types
|
||||
|
||||
from panda3d.core import ConfigVariableBool
|
||||
|
||||
# If using the Toontown ActiveX launcher, this must be set true.
|
||||
# Also, Panda must be compiled with SIMPLE_THREADS or no HAVE_THREADS
|
||||
# at all. In the normal Panda case, this should be set false.
|
||||
if ConfigVariableBool('delay-messenger-lock', False).getValue():
|
||||
class Lock:
|
||||
""" This is a cheesy delayed implementation of Lock, designed to
|
||||
support the Toontown ActiveX launch, which must import Messenger
|
||||
before it has downloaded the rest of Panda. Note that this
|
||||
cheesy lock isn't thread-safe if the application starts any
|
||||
threads before acquiring the Messenger lock the first time.
|
||||
(However, it's mostly thread-safe if Panda is compiled with
|
||||
SIMPLE_THREADS.) """
|
||||
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("Messenger.Lock")
|
||||
|
||||
def __init__(self):
|
||||
self.locked = 0
|
||||
|
||||
def acquire(self):
|
||||
# Before we download Panda, we can't use any threading
|
||||
# interfaces. So don't, until we observe that we have some
|
||||
# actual contention on the lock.
|
||||
|
||||
if self.locked:
|
||||
# We have contention.
|
||||
return self.__getLock()
|
||||
|
||||
# This relies on the fact that any individual Python statement
|
||||
# is atomic.
|
||||
self.locked += 1
|
||||
if self.locked > 1:
|
||||
# Whoops, we have contention.
|
||||
self.locked -= 1
|
||||
return self.__getLock()
|
||||
|
||||
def release(self):
|
||||
if self.locked:
|
||||
# Still using the old, cheesy lock.
|
||||
self.locked -= 1
|
||||
return
|
||||
|
||||
# The new lock must have been put in place.
|
||||
self.release = self.lock.release
|
||||
return self.lock.release()
|
||||
|
||||
def __getLock(self):
|
||||
# Now that we've started Panda, it's safe to import the Mutex
|
||||
# class, which becomes our actual lock.
|
||||
# From now on, this lock will be used.
|
||||
|
||||
self.notify.info("Acquiring Panda lock for the first time.")
|
||||
|
||||
from pandac.PandaModules import Thread, Mutex
|
||||
self.__dict__.setdefault('lock', Mutex('Messenger'))
|
||||
self.lock.acquire()
|
||||
|
||||
self.acquire = self.lock.acquire
|
||||
|
||||
# Wait for the cheesy lock to be released before we return.
|
||||
self.notify.info("Waiting for cheesy lock to be released.")
|
||||
while self.locked:
|
||||
Thread.forceYield()
|
||||
self.notify.info("Got cheesy lock.")
|
||||
|
||||
# We return with the lock acquired.
|
||||
else:
|
||||
# In the normal case, there's no reason not to import all of
|
||||
# libpanda right away, and so we can just use Lock directly. This
|
||||
# is perfectly thread-safe.
|
||||
from direct.stdpy.threading import Lock
|
||||
from panda3d.core import ConfigVariableBool, Thread, Mutex
|
||||
from direct.stdpy.threading import Lock
|
||||
|
||||
class Messenger:
|
||||
|
||||
|
|
@ -215,7 +145,7 @@ class Messenger:
|
|||
# on this particular object.
|
||||
if id in acceptorDict:
|
||||
# TODO: we're replacing the existing callback. should this be an error?
|
||||
if notifyDebug:
|
||||
if notifyDebug:
|
||||
oldMethod = acceptorDict[id][0]
|
||||
if oldMethod == method:
|
||||
self.notify.warning(
|
||||
|
|
@ -420,7 +350,7 @@ class Messenger:
|
|||
if not eventTuple:
|
||||
# No event; we're done.
|
||||
return task.done
|
||||
|
||||
|
||||
self.__dispatch(*eventTuple)
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
|
@ -450,7 +380,7 @@ class Messenger:
|
|||
if (len(eventDict) == 0):
|
||||
del self.__objectEvents[id]
|
||||
self._releaseObject(self._getObject(id))
|
||||
|
||||
|
||||
del acceptorDict[id]
|
||||
# If the dictionary at this event is now empty, remove
|
||||
# the event entry from the Messenger altogether
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
"""Undocumented Module"""
|
||||
|
||||
__all__ = []
|
||||
|
||||
## from DirectObject import *
|
||||
## from pandac.PandaModules import *
|
||||
##
|
||||
## class PandaObject(DirectObject):
|
||||
## """
|
||||
## This is the class that all Panda/Show classes should inherit from
|
||||
## """
|
||||
## pass
|
||||
|
|
@ -8,11 +8,11 @@ __all__ = ['ShowBase', 'WindowControls']
|
|||
#import VerboseImport
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.direct import *
|
||||
from panda3d.direct import get_config_showbase, throw_new_frame
|
||||
|
||||
# This needs to be available early for DirectGUI imports
|
||||
import __builtin__
|
||||
__builtin__.config = getConfigShowbase()
|
||||
__builtin__.config = get_config_showbase()
|
||||
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from MessengerGlobal import *
|
||||
|
|
@ -46,7 +46,7 @@ import AppRunnerGlobal
|
|||
|
||||
__builtin__.FADE_SORT_INDEX = 1000
|
||||
__builtin__.NO_FADE_SORT_INDEX = 2000
|
||||
|
||||
|
||||
|
||||
# Now ShowBase is a DirectObject. We need this so ShowBase can hang
|
||||
# hooks on messages, particularly on window-event. This doesn't
|
||||
|
|
@ -58,7 +58,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
def __init__(self, fStartDirect = True, windowType = None):
|
||||
self.__dev__ = config.GetBool('want-dev', __debug__)
|
||||
__builtin__.__dev__ = self.__dev__
|
||||
|
||||
|
||||
logStackDump = (config.GetBool('log-stack-dump', False) or
|
||||
config.GetBool('client-log-stack-dump', False))
|
||||
uploadStackDump = config.GetBool('upload-stack-dump', False)
|
||||
|
|
@ -74,7 +74,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
#debug running multiplier
|
||||
self.debugRunningMultiplier = 4
|
||||
|
||||
|
||||
# Get the dconfig object
|
||||
self.config = config
|
||||
# Setup wantVerifyPdb as soon as reasonable:
|
||||
|
|
@ -91,7 +91,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.nextWindowIndex = 1
|
||||
self.__directStarted = False
|
||||
self.__deadInputs = 0
|
||||
|
||||
|
||||
# Store dconfig variables
|
||||
self.sfxActive = self.config.GetBool('audio-sfx-active', 1)
|
||||
self.musicActive = self.config.GetBool('audio-music-active', 1)
|
||||
|
|
@ -253,7 +253,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
self.loader = Loader.Loader(self)
|
||||
self.graphicsEngine.setDefaultLoader(self.loader.loader)
|
||||
|
||||
|
||||
self.eventMgr = eventMgr
|
||||
self.messenger = messenger
|
||||
self.bboard = bulletinBoard
|
||||
|
|
@ -315,7 +315,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# Make sure we're not making more than one ShowBase.
|
||||
if 'base' in __builtin__.__dict__:
|
||||
raise StandardError, "Attempt to spawn multiple ShowBase instances!"
|
||||
|
||||
|
||||
__builtin__.base = self
|
||||
__builtin__.render2d = self.render2d
|
||||
__builtin__.aspect2d = self.aspect2d
|
||||
|
|
@ -357,7 +357,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
# set up recording of Functor creation stacks in __dev__
|
||||
PythonUtil.recordFunctorCreationStacks()
|
||||
|
||||
|
||||
if __dev__ or self.config.GetBool('want-e3-hacks', False):
|
||||
if self.config.GetBool('track-gui-items', True):
|
||||
# dict of guiId to gui item, for tracking down leaks
|
||||
|
|
@ -386,7 +386,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
sleepTime = self.config.GetFloat('client-sleep', 0.0)
|
||||
self.clientSleep = 0.0
|
||||
self.setSleep(sleepTime)
|
||||
|
||||
|
||||
# Extra sleep for running 4+ clients on a single machine
|
||||
# adds a sleep right after the main render in igloop
|
||||
# tends to even out the frame rate and keeps it from going
|
||||
|
|
@ -414,7 +414,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
# Start IGLOOP
|
||||
self.restart()
|
||||
|
||||
|
||||
# add a collision traverser via pushCTrav and remove it via popCTrav
|
||||
# that way the owner of the new cTrav doesn't need to hold onto the
|
||||
# previous one in order to put it back
|
||||
|
|
@ -427,7 +427,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
def __setupProfile(self):
|
||||
""" Sets up the Python profiler, if avaialable, according to
|
||||
some Panda config settings. """
|
||||
|
||||
|
||||
try:
|
||||
import profile, pstats
|
||||
except ImportError:
|
||||
|
|
@ -499,7 +499,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
vfs.unmountAll()
|
||||
|
||||
|
||||
|
||||
def exitfunc(self):
|
||||
"""
|
||||
|
|
@ -609,7 +609,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
If requireWindow is true, it means that the function should
|
||||
raise an exception if the window fails to open correctly.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# Save this lambda here for convenience; we'll use it to call
|
||||
|
|
@ -622,19 +622,19 @@ class ShowBase(DirectObject.DirectObject):
|
|||
keepCamera = keepCamera, scene = scene, stereo = stereo,
|
||||
unexposedDraw = unexposedDraw,
|
||||
callbackWindowDict = callbackWindowDict)
|
||||
|
||||
|
||||
if self.win:
|
||||
# If we've already opened a window before, this is just a
|
||||
# pass-through to _doOpenWindow().
|
||||
win = func()
|
||||
self.graphicsEngine.openWindows()
|
||||
return win
|
||||
|
||||
|
||||
if type is None:
|
||||
type = self.windowType
|
||||
if requireWindow is None:
|
||||
requireWindow = self.requireWindow
|
||||
|
||||
|
||||
win = func()
|
||||
|
||||
# Give the window a chance to truly open.
|
||||
|
|
@ -699,7 +699,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# GSG from that buffer.
|
||||
host = gsg
|
||||
gsg = gsg.getGsg()
|
||||
|
||||
|
||||
# If we are using DirectX, force a new GSG to be created,
|
||||
# since at the moment DirectX seems to misbehave if we do
|
||||
# not do this. This will cause a delay while all textures
|
||||
|
|
@ -764,7 +764,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
func = callbackWindowDict.get(callbackName, None)
|
||||
if not func:
|
||||
continue
|
||||
|
||||
|
||||
setCallbackName = 'set%sCallback' % (callbackName)
|
||||
setCallback = getattr(win, setCallbackName)
|
||||
setCallback(PythonCallbackObject(func))
|
||||
|
|
@ -804,10 +804,10 @@ class ShowBase(DirectObject.DirectObject):
|
|||
pointer to None.
|
||||
"""
|
||||
win.setActive(False)
|
||||
|
||||
|
||||
# First, remove all of the cameras associated with display
|
||||
# regions on the window.
|
||||
numRegions = win.getNumDisplayRegions()
|
||||
numRegions = win.getNumDisplayRegions()
|
||||
for i in range(numRegions):
|
||||
dr = win.getDisplayRegion(i)
|
||||
# [gjeon] remove drc in base.direct.drList
|
||||
|
|
@ -816,9 +816,9 @@ class ShowBase(DirectObject.DirectObject):
|
|||
if drc.cam == dr.getCamera():
|
||||
base.direct.drList.displayRegionList.remove(drc)
|
||||
break
|
||||
|
||||
|
||||
cam = NodePath(dr.getCamera())
|
||||
|
||||
|
||||
dr.setCamera(NodePath())
|
||||
|
||||
if not cam.isEmpty() and \
|
||||
|
|
@ -905,7 +905,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
closed window).
|
||||
"""
|
||||
keepCamera = kw.get('keepCamera', False)
|
||||
|
||||
|
||||
success = 1
|
||||
oldWin = self.win
|
||||
oldLens = self.camLens
|
||||
|
|
@ -1066,7 +1066,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.aspect2d = self.render2d.attachNewNode(PGTop("aspect2d"))
|
||||
self.aspect2d.setScale(1.0 / aspectRatio, 1.0, 1.0)
|
||||
|
||||
self.a2dBackground = self.aspect2d.attachNewNode("a2dBackground")
|
||||
self.a2dBackground = self.aspect2d.attachNewNode("a2dBackground")
|
||||
|
||||
# It's important to know the bounds of the aspect2d screen.
|
||||
self.a2dTop = 1.0
|
||||
|
|
@ -1110,7 +1110,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.a2dBottomLeftNs.setPos(self.a2dLeft, 0, self.a2dBottom)
|
||||
self.a2dBottomRight.setPos(self.a2dRight, 0, self.a2dBottom)
|
||||
self.a2dBottomRightNs.setPos(self.a2dRight, 0, self.a2dBottom)
|
||||
|
||||
|
||||
# This special root, pixel2d, uses units in pixels that are relative
|
||||
# to the window. The upperleft corner of the window is (0, 0),
|
||||
# the lowerleft corner is (xsize, -ysize), in this coordinate system.
|
||||
|
|
@ -1182,7 +1182,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.a2dpTopRight.setPos(self.a2dpRight, 0, self.a2dpTop)
|
||||
self.a2dpBottomLeft.setPos(self.a2dpLeft, 0, self.a2dpBottom)
|
||||
self.a2dpBottomRight.setPos(self.a2dpRight, 0, self.a2dpBottom)
|
||||
|
||||
|
||||
# This special root, pixel2d, uses units in pixels that are relative
|
||||
# to the window. The upperleft corner of the window is (0, 0),
|
||||
# the lowerleft corner is (xsize, -ysize), in this coordinate system.
|
||||
|
|
@ -1229,7 +1229,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
if aspectRatio == 0:
|
||||
return 1
|
||||
|
||||
|
||||
return aspectRatio
|
||||
|
||||
def getSize(self, win = None):
|
||||
|
|
@ -1337,7 +1337,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# we will if clearDepth is specified.
|
||||
if clearDepth:
|
||||
dr.setClearDepthActive(1)
|
||||
|
||||
|
||||
if clearColor:
|
||||
dr.setClearColorActive(1)
|
||||
dr.setClearColor(clearColor)
|
||||
|
|
@ -1370,7 +1370,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
cam2dNode = Camera('cam2d_' + cameraName)
|
||||
else:
|
||||
cam2dNode = Camera('cam2d')
|
||||
|
||||
|
||||
if lens == None:
|
||||
lens = OrthographicLens()
|
||||
lens.setFilmSize(right - left, top - bottom)
|
||||
|
|
@ -1480,12 +1480,12 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
if fMultiWin:
|
||||
return bts[0]
|
||||
|
||||
|
||||
self.buttonThrowers = bts[:]
|
||||
self.pointerWatcherNodes = pws[:]
|
||||
|
||||
self.mouseWatcher = self.buttonThrowers[0].getParent()
|
||||
self.mouseWatcherNode = self.mouseWatcher.node()
|
||||
self.mouseWatcherNode = self.mouseWatcher.node()
|
||||
|
||||
if self.mouseInterface:
|
||||
self.mouseInterface.reparentTo(self.mouseWatcher)
|
||||
|
|
@ -1553,7 +1553,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# track the left and right halves of the screen
|
||||
# individually.
|
||||
mw.node().setDisplayRegion(win.getOverlayDisplayRegion())
|
||||
|
||||
|
||||
mb = mw.node().getModifierButtons()
|
||||
mb.addButton(KeyboardButton.shift())
|
||||
mb.addButton(KeyboardButton.control())
|
||||
|
|
@ -1675,7 +1675,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
port = -1
|
||||
PStatClient.connect(hostname, port)
|
||||
return PStatClient.isConnected()
|
||||
|
||||
|
||||
|
||||
def addSfxManager(self, extraSfxManager):
|
||||
# keep a list of sfx manager objects to apply settings to,
|
||||
|
|
@ -1841,11 +1841,11 @@ class ShowBase(DirectObject.DirectObject):
|
|||
case we're responsible for taking out Panda's garbage from
|
||||
time to time. This is not to be confused with Python's
|
||||
garbage collection. """
|
||||
|
||||
|
||||
TransformState.garbageCollect()
|
||||
RenderState.garbageCollect()
|
||||
return Task.cont
|
||||
|
||||
|
||||
def __igLoop(self, state):
|
||||
# We render the watch variables for the onScreenDebug as soon
|
||||
# as we reasonably can before the renderFrame().
|
||||
|
|
@ -1881,7 +1881,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
# Lerp stuff needs this event, and it must be generated in
|
||||
# C++, not in Python.
|
||||
throwNewFrame()
|
||||
throw_new_frame()
|
||||
return Task.cont
|
||||
|
||||
|
||||
|
|
@ -1927,8 +1927,8 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
# Lerp stuff needs this event, and it must be generated in
|
||||
# C++, not in Python.
|
||||
throwNewFrame()
|
||||
return Task.cont
|
||||
throw_new_frame()
|
||||
return Task.cont
|
||||
|
||||
def restart(self,clusterSync=False,cluster=None):
|
||||
self.shutdown()
|
||||
|
|
@ -2196,7 +2196,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
self.showVertices = self.cam.attachNewNode(cam)
|
||||
dr.setCamera(self.showVertices)
|
||||
|
||||
|
||||
|
||||
def oobe(self, cam = None):
|
||||
"""
|
||||
|
|
@ -2221,7 +2221,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
"""
|
||||
if cam is None:
|
||||
cam = self.cam
|
||||
|
||||
|
||||
# If oobeMode was never set, set it to false and create the
|
||||
# structures we need to implement OOBE.
|
||||
if not hasattr(self, 'oobeMode'):
|
||||
|
|
@ -2645,7 +2645,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# If we have not forced the aspect ratio, let's see if it has
|
||||
# changed and update the camera lenses and aspect2d parameters
|
||||
self.adjustWindowAspectRatio(self.getAspectRatio())
|
||||
|
||||
|
||||
# Temporary hasattr for old Pandas
|
||||
if not hasattr(win, 'getSbsLeftXSize'):
|
||||
self.pixel2d.setScale(2.0 / win.getXSize(), 1.0, 2.0 / win.getYSize())
|
||||
|
|
@ -2659,7 +2659,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
windowEvent(), but it may also be called to explicitly adjust
|
||||
the aspect ratio of the render/render2d DisplayRegion, by a
|
||||
class that has redefined these. """
|
||||
|
||||
|
||||
if self.__configAspectRatio:
|
||||
aspectRatio = self.__configAspectRatio
|
||||
|
||||
|
|
@ -2694,13 +2694,13 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.a2dpTop = 1.0
|
||||
self.a2dpBottom = -1.0
|
||||
self.a2dpLeft = -aspectRatio
|
||||
self.a2dpRight = aspectRatio
|
||||
self.a2dpRight = aspectRatio
|
||||
|
||||
# Reposition the aspect2d marker nodes
|
||||
self.a2dTopCenter.setPos(0, self.a2dTop, self.a2dTop)
|
||||
self.a2dBottomCenter.setPos(0, self.a2dBottom, self.a2dBottom)
|
||||
self.a2dLeftCenter.setPos(self.a2dLeft, 0, 0)
|
||||
self.a2dRightCenter.setPos(self.a2dRight, 0, 0)
|
||||
self.a2dRightCenter.setPos(self.a2dRight, 0, 0)
|
||||
self.a2dTopLeft.setPos(self.a2dLeft, self.a2dTop, self.a2dTop)
|
||||
self.a2dTopRight.setPos(self.a2dRight, self.a2dTop, self.a2dTop)
|
||||
self.a2dBottomLeft.setPos(self.a2dLeft, self.a2dBottom, self.a2dBottom)
|
||||
|
|
@ -2710,17 +2710,17 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.a2dTopCenterNs.setPos(0, self.a2dTop, self.a2dTop)
|
||||
self.a2dBottomCenterNs.setPos(0, self.a2dBottom, self.a2dBottom)
|
||||
self.a2dLeftCenterNs.setPos(self.a2dLeft, 0, 0)
|
||||
self.a2dRightCenterNs.setPos(self.a2dRight, 0, 0)
|
||||
self.a2dRightCenterNs.setPos(self.a2dRight, 0, 0)
|
||||
self.a2dTopLeftNs.setPos(self.a2dLeft, self.a2dTop, self.a2dTop)
|
||||
self.a2dTopRightNs.setPos(self.a2dRight, self.a2dTop, self.a2dTop)
|
||||
self.a2dBottomLeftNs.setPos(self.a2dLeft, self.a2dBottom, self.a2dBottom)
|
||||
self.a2dBottomRightNs.setPos(self.a2dRight, self.a2dBottom, self.a2dBottom)
|
||||
self.a2dBottomRightNs.setPos(self.a2dRight, self.a2dBottom, self.a2dBottom)
|
||||
|
||||
# Reposition the aspect2dp marker nodes
|
||||
self.a2dpTopCenter.setPos(0, self.a2dpTop, self.a2dpTop)
|
||||
self.a2dpBottomCenter.setPos(0, self.a2dpBottom, self.a2dpBottom)
|
||||
self.a2dpLeftCenter.setPos(self.a2dpLeft, 0, 0)
|
||||
self.a2dpRightCenter.setPos(self.a2dpRight, 0, 0)
|
||||
self.a2dpRightCenter.setPos(self.a2dpRight, 0, 0)
|
||||
self.a2dpTopLeft.setPos(self.a2dpLeft, self.a2dpTop, self.a2dpTop)
|
||||
self.a2dpTopRight.setPos(self.a2dpRight, self.a2dpTop, self.a2dpTop)
|
||||
self.a2dpBottomLeft.setPos(self.a2dpLeft, self.a2dpBottom, self.a2dpBottom)
|
||||
|
|
@ -2728,7 +2728,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
# If anybody needs to update their GUI, put a callback on this event
|
||||
messenger.send("aspectRatioChanged")
|
||||
|
||||
|
||||
def userExit(self):
|
||||
# The user has requested we exit the program. Deal with this.
|
||||
if self.exitFunc:
|
||||
|
|
@ -2752,7 +2752,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
This sets up a wxTimer callback so that Panda still gets
|
||||
updated, but wxPython owns the main loop (which seems to make
|
||||
it happier than the other way around). """
|
||||
|
||||
|
||||
if self.wxApp:
|
||||
# Don't do this twice.
|
||||
return
|
||||
|
|
@ -2767,7 +2767,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# Put wxPython in charge of the main loop. It really
|
||||
# seems to like this better; some features of wx don't
|
||||
# work properly unless this is true.
|
||||
|
||||
|
||||
# Set a timer to run the Panda frame 60 times per second.
|
||||
wxFrameRate = ConfigVariableDouble('wx-frame-rate', 60.0)
|
||||
self.wxTimer = wx.Timer(self.wxApp)
|
||||
|
|
@ -2802,19 +2802,19 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# This happens when the wxTimer expires while igLoop is
|
||||
# rendering. Ignore it.
|
||||
return
|
||||
|
||||
|
||||
self.taskMgr.step()
|
||||
|
||||
def wxRun(self):
|
||||
""" This method replaces base.run() after we have called
|
||||
spawnWxLoop(). Since at this point wxPython now owns the main
|
||||
loop, this method is a call to wxApp.MainLoop(). """
|
||||
|
||||
|
||||
if Thread.getCurrentThread().getCurrentTask():
|
||||
# This happens in the p3d environment during startup.
|
||||
# Ignore it.
|
||||
return
|
||||
|
||||
|
||||
self.wxApp.MainLoop()
|
||||
|
||||
def startTk(self, fWantTk = True):
|
||||
|
|
@ -2829,7 +2829,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
This sets up a timer callback so that Panda still gets
|
||||
updated, but Tkinter owns the main loop (which seems to make
|
||||
it happier than the other way around). """
|
||||
|
||||
|
||||
if self.tkRoot:
|
||||
# Don't do this twice.
|
||||
return
|
||||
|
|
@ -2847,7 +2847,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# Put Tkinter in charge of the main loop. It really
|
||||
# seems to like this better; the GUI otherwise becomes
|
||||
# largely unresponsive on Mac OS X unless this is true.
|
||||
|
||||
|
||||
# Set a timer to run the Panda frame 60 times per second.
|
||||
tkFrameRate = ConfigVariableDouble('tk-frame-rate', 60.0)
|
||||
self.tkDelay = int(1000.0 / tkFrameRate.getValue())
|
||||
|
|
@ -2885,12 +2885,12 @@ class ShowBase(DirectObject.DirectObject):
|
|||
""" This method replaces base.run() after we have called
|
||||
spawnTkLoop(). Since at this point Tkinter now owns the main
|
||||
loop, this method is a call to tkRoot.mainloop(). """
|
||||
|
||||
|
||||
if Thread.getCurrentThread().getCurrentTask():
|
||||
# This happens in the p3d environment during startup.
|
||||
# Ignore it.
|
||||
return
|
||||
|
||||
|
||||
self.tkRoot.mainloop()
|
||||
|
||||
def startDirect(self, fWantDirect = 1, fWantTk = 1, fWantWx = 0):
|
||||
|
|
@ -2913,7 +2913,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
if self.__directStarted:
|
||||
return
|
||||
self.__directStarted = False
|
||||
|
||||
|
||||
# Start Tk, Wx and DIRECT if specified by Config.prc
|
||||
fTk = self.config.GetBool('want-tk', 0)
|
||||
fWx = self.config.GetBool('want-wx', 0)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
__all__ = ['register', 'sharedPackages',
|
||||
'reloadSharedPackage', 'reloadSharedPackages']
|
||||
|
||||
from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
|
||||
import sys
|
||||
import os
|
||||
import marshal
|
||||
import imp
|
||||
import types
|
||||
import __builtin__
|
||||
|
||||
__all__ = ['register', 'sharedPackages',
|
||||
'reloadSharedPackage', 'reloadSharedPackages']
|
||||
|
||||
# The sharedPackages dictionary lists all of the "shared packages",
|
||||
# special Python packages that automatically span multiple directories
|
||||
# via magic in the VFSImporter. You can make a package "shared"
|
||||
|
|
@ -76,14 +75,13 @@ class VFSImporter:
|
|||
for desc in imp.get_suffixes():
|
||||
if desc[2] != imp.C_EXTENSION:
|
||||
continue
|
||||
|
||||
|
||||
filename = Filename(path)
|
||||
filename.setExtension(desc[0][1:])
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(dir_path, vfile, filename, FTExtensionModule,
|
||||
desc = desc)
|
||||
|
||||
|
||||
# Finally, consider a package, i.e. a directory containing
|
||||
# __init__.py.
|
||||
|
|
@ -105,7 +103,7 @@ class VFSImporter:
|
|||
class VFSLoader:
|
||||
""" The second part of VFSImporter, this is created for a
|
||||
particular .py file or directory. """
|
||||
|
||||
|
||||
def __init__(self, dir_path, vfile, filename, fileType,
|
||||
desc = None, packagePath = None):
|
||||
self.dir_path = dir_path
|
||||
|
|
@ -116,7 +114,7 @@ class VFSLoader:
|
|||
self.fileType = fileType
|
||||
self.desc = desc
|
||||
self.packagePath = packagePath
|
||||
|
||||
|
||||
def load_module(self, fullname, loadingShared = False):
|
||||
#print >>sys.stderr, "load_module(%s), dir_path = %s, filename = %s" % (fullname, self.dir_path, self.filename)
|
||||
if self.fileType == FTFrozenModule:
|
||||
|
|
@ -136,11 +134,11 @@ class VFSLoader:
|
|||
loader = importer.find_module(fullname, path = path)
|
||||
assert loader
|
||||
return loader.load_module(fullname)
|
||||
|
||||
|
||||
code = self._read_code()
|
||||
if not code:
|
||||
raise ImportError, 'No Python code in %s' % (fullname)
|
||||
|
||||
|
||||
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
|
||||
mod.__file__ = self.filename.toOsSpecific()
|
||||
mod.__loader__ = self
|
||||
|
|
@ -169,15 +167,15 @@ class VFSLoader:
|
|||
|
||||
def get_filename(self, fullname):
|
||||
return self.filename.toOsSpecific()
|
||||
|
||||
|
||||
def _read_source(self):
|
||||
""" Returns the Python source for this file, if it is
|
||||
available, or None if it is not. May raise IOError. """
|
||||
|
||||
|
||||
if self.fileType == FTPythonCompiled or \
|
||||
self.fileType == FTExtensionModule:
|
||||
return None
|
||||
|
||||
|
||||
filename = Filename(self.filename)
|
||||
filename.setExtension('py')
|
||||
filename.setText()
|
||||
|
|
@ -281,7 +279,7 @@ class VFSLoader:
|
|||
def _loadPyc(self, vfile, timestamp):
|
||||
""" Reads and returns the marshal data from a .pyc file.
|
||||
Raises ValueError if there is a problem. """
|
||||
|
||||
|
||||
code = None
|
||||
data = vfile.readFile(True)
|
||||
if data[:4] == imp.get_magic():
|
||||
|
|
@ -294,13 +292,13 @@ class VFSLoader:
|
|||
else:
|
||||
raise ValueError, 'Bad magic number in %s' % (vfile)
|
||||
return code
|
||||
|
||||
|
||||
|
||||
def _compile(self, filename, source):
|
||||
""" Compiles the Python source code to a code object and
|
||||
attempts to write it to an appropriate .pyc file. May raise
|
||||
SyntaxError or other errors generated by the compiler. """
|
||||
|
||||
|
||||
if source and source[-1] != '\n':
|
||||
source = source + '\n'
|
||||
code = __builtin__.compile(source, filename.toOsSpecific(), 'exec')
|
||||
|
|
@ -335,7 +333,7 @@ class VFSSharedImporter:
|
|||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def find_module(self, fullname, path = None, reload = False):
|
||||
#print >>sys.stderr, "shared find_module(%s), path = %s" % (fullname, path)
|
||||
|
||||
|
|
@ -364,14 +362,14 @@ class VFSSharedImporter:
|
|||
for dir in path:
|
||||
if dir in excludePaths:
|
||||
continue
|
||||
|
||||
|
||||
importer = sys.path_importer_cache.get(dir, None)
|
||||
if importer is None:
|
||||
try:
|
||||
importer = VFSImporter(dir)
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
|
||||
sys.path_importer_cache[dir] = importer
|
||||
|
||||
try:
|
||||
|
|
@ -391,6 +389,9 @@ class VFSSharedImporter:
|
|||
""" Returns the directory name that the indicated
|
||||
conventionally-loaded module must have been loaded from. """
|
||||
|
||||
if not hasattr(mod, __file__) or mod.__file__ is None:
|
||||
return None
|
||||
|
||||
fullname = mod.__name__
|
||||
dirname = Filename.fromOsSpecific(mod.__file__).getDirname()
|
||||
|
||||
|
|
@ -414,15 +415,15 @@ class VFSSharedImporter:
|
|||
|
||||
# Couldn't figure it out.
|
||||
return None
|
||||
|
||||
|
||||
class VFSSharedLoader:
|
||||
""" The second part of VFSSharedImporter, this imports a list of
|
||||
packages and combines them. """
|
||||
|
||||
|
||||
def __init__(self, loaders, reload):
|
||||
self.loaders = loaders
|
||||
self.reload = reload
|
||||
|
||||
|
||||
def load_module(self, fullname):
|
||||
#print >>sys.stderr, "shared load_module(%s), loaders = %s" % (fullname, map(lambda l: l.dir_path, self.loaders))
|
||||
|
||||
|
|
@ -475,7 +476,7 @@ def register():
|
|||
_registered = True
|
||||
sys.path_hooks.insert(0, VFSImporter)
|
||||
sys.meta_path.insert(0, VFSSharedImporter())
|
||||
|
||||
|
||||
# Blow away the importer cache, so we'll come back through the
|
||||
# VFSImporter for every folder in the future, even those
|
||||
# folders that previously were loaded directly.
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@ except ImportError:
|
|||
p3extend_frozen = None
|
||||
|
||||
import direct
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
from pandac.extension_native_helpers import dll_suffix, dll_ext
|
||||
import panda3d
|
||||
|
||||
# Check to see if we are running python_d, which implies we have a
|
||||
# debug build, and we have to build the module with debug options.
|
||||
|
|
@ -578,6 +577,8 @@ class Freezer:
|
|||
if self.platform.startswith('win'):
|
||||
self.objectExtension = '.obj'
|
||||
|
||||
self.keepTemporaryFiles = True
|
||||
|
||||
# Change any of these to change the generated startup and glue
|
||||
# code.
|
||||
self.frozenMainCode = frozenMainCode
|
||||
|
|
@ -912,7 +913,7 @@ class Freezer:
|
|||
continue
|
||||
if origName in self.modules:
|
||||
continue
|
||||
|
||||
|
||||
# This module is missing. Let it be missing in the
|
||||
# runtime also.
|
||||
self.modules[origName] = self.ModuleDef(origName, exclude = True,
|
||||
|
|
@ -1110,7 +1111,7 @@ class Freezer:
|
|||
# The "module" may end in __init__, but that really means
|
||||
# the parent directory.
|
||||
dirnames = dirnames[:-1]
|
||||
|
||||
|
||||
self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1], compressionLevel)
|
||||
|
||||
filename = '/'.join(dirnames)
|
||||
|
|
@ -1328,10 +1329,11 @@ class Freezer:
|
|||
try:
|
||||
compileFunc(filename, basename)
|
||||
finally:
|
||||
if (os.path.exists(filename)):
|
||||
os.unlink(filename)
|
||||
if (os.path.exists(basename + self.objectExtension)):
|
||||
os.unlink(basename + self.objectExtension)
|
||||
if not self.keepTemporaryFiles:
|
||||
if os.path.exists(filename):
|
||||
os.unlink(filename)
|
||||
if os.path.exists(basename + self.objectExtension):
|
||||
os.unlink(basename + self.objectExtension)
|
||||
|
||||
return target
|
||||
|
||||
|
|
@ -1378,19 +1380,6 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
def __init__(self, *args, **kw):
|
||||
modulefinder.ModuleFinder.__init__(self, *args, **kw)
|
||||
|
||||
def import_module(self, partname, fqname, parent):
|
||||
if parent and parent.__name__ == 'panda3d':
|
||||
# A special case: map a reference to the "panda3d.blah"
|
||||
# module into the appropriate Panda3D dll.
|
||||
m = getattr(panda3d, partname, None)
|
||||
if m and hasattr(m, '__libraries__'):
|
||||
libname = m.__libraries__[-1]
|
||||
partname = libname
|
||||
fqname = libname
|
||||
parent = None
|
||||
|
||||
return modulefinder.ModuleFinder.import_module(self, partname, fqname, parent)
|
||||
|
||||
def find_module(self, name, path, parent=None):
|
||||
try:
|
||||
return modulefinder.ModuleFinder.find_module(self, name, path, parent = parent)
|
||||
|
|
@ -1425,7 +1414,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
m = self.add_module(fqname)
|
||||
m.__file__ = '<frozen>'
|
||||
if isPackage:
|
||||
m.__path__ = pathname
|
||||
m.__path__ = [pathname]
|
||||
co = marshal.loads(co)
|
||||
if self.replace_paths:
|
||||
co = self.replace_paths_in_code(co)
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ __all__ = [
|
|||
'execfile',
|
||||
]
|
||||
|
||||
from pandac import PandaModules as pm
|
||||
from panda3d import core
|
||||
import types
|
||||
|
||||
_vfs = pm.VirtualFileSystem.getGlobalPtr()
|
||||
_vfs = core.VirtualFileSystem.getGlobalPtr()
|
||||
|
||||
class file:
|
||||
def __init__(self, filename, mode = 'r', bufsize = None,
|
||||
|
|
@ -36,14 +36,14 @@ class file:
|
|||
readMode = False
|
||||
writeMode = False
|
||||
|
||||
if isinstance(filename, pm.Istream) or isinstance(filename, pm.Ostream):
|
||||
if isinstance(filename, core.Istream) or isinstance(filename, core.Ostream):
|
||||
# If we were given a stream instead of a filename, assign
|
||||
# it directly.
|
||||
self.__stream = filename
|
||||
readMode = isinstance(filename, pm.Istream)
|
||||
writeMode = isinstance(filename, pm.Ostream)
|
||||
readMode = isinstance(filename, core.Istream)
|
||||
writeMode = isinstance(filename, core.Ostream)
|
||||
|
||||
elif isinstance(filename, pm.VirtualFile):
|
||||
elif isinstance(filename, core.VirtualFile):
|
||||
# We can also "open" a VirtualFile object for reading.
|
||||
self.__stream = filename.openReadFile(autoUnwrap)
|
||||
if not self.__stream:
|
||||
|
|
@ -57,10 +57,10 @@ class file:
|
|||
if isinstance(filename, types.StringTypes):
|
||||
# If a raw string is given, assume it's an os-specific
|
||||
# filename.
|
||||
filename = pm.Filename.fromOsSpecific(filename)
|
||||
filename = core.Filename.fromOsSpecific(filename)
|
||||
else:
|
||||
# If a Filename is given, make a writable copy anyway.
|
||||
filename = pm.Filename(filename)
|
||||
filename = core.Filename(filename)
|
||||
|
||||
self.filename = filename
|
||||
self.name = filename.toOsSpecific()
|
||||
|
|
@ -97,7 +97,7 @@ class file:
|
|||
message = 'Could not open %s for writing' % (filename)
|
||||
raise IOError, message
|
||||
writeMode = True
|
||||
|
||||
|
||||
elif mode == 'a':
|
||||
self.__stream = _vfs.openAppendFile(filename)
|
||||
if not self.__stream:
|
||||
|
|
@ -142,14 +142,14 @@ class file:
|
|||
self.__needsVfsClose = True
|
||||
|
||||
if readMode:
|
||||
self.__reader = pm.StreamReader(self.__stream, False)
|
||||
self.__reader = core.StreamReader(self.__stream, False)
|
||||
if writeMode:
|
||||
self.__writer = pm.StreamWriter(self.__stream, False)
|
||||
self.__writer = core.StreamWriter(self.__stream, False)
|
||||
self.__lastWrite = True
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
|
||||
def close(self):
|
||||
if self.__needsVfsClose:
|
||||
if self.__reader and self.__writer:
|
||||
|
|
@ -158,13 +158,13 @@ class file:
|
|||
_vfs.closeReadFile(self.__stream)
|
||||
else: # self.__writer:
|
||||
_vfs.closeWriteFile(self.__stream)
|
||||
|
||||
|
||||
self.__needsVfsClose = False
|
||||
self.__stream = None
|
||||
self.__needsVfsClose = False
|
||||
self.__reader = None
|
||||
self.__writer = None
|
||||
|
||||
|
||||
def flush(self):
|
||||
if self.__stream:
|
||||
self.__stream.clear() # clear eof flag
|
||||
|
|
@ -188,7 +188,7 @@ class file:
|
|||
# The stream is open only in write mode.
|
||||
message = 'Attempt to read from write-only stream'
|
||||
raise IOError, message
|
||||
|
||||
|
||||
self.__stream.clear() # clear eof flag
|
||||
self.__lastWrite = False
|
||||
if size >= 0:
|
||||
|
|
@ -199,7 +199,7 @@ class file:
|
|||
while not self.__stream.eof():
|
||||
result += self.__reader.extractBytes(1024)
|
||||
return result
|
||||
|
||||
|
||||
def readline(self, size = -1):
|
||||
if not self.__reader:
|
||||
if not self.__writer:
|
||||
|
|
@ -213,7 +213,7 @@ class file:
|
|||
self.__stream.clear() # clear eof flag
|
||||
self.__lastWrite = False
|
||||
return self.__reader.readline()
|
||||
|
||||
|
||||
def readlines(self, sizehint = -1):
|
||||
lines = []
|
||||
line = self.readline()
|
||||
|
|
@ -241,7 +241,7 @@ class file:
|
|||
return self.__stream.tellg()
|
||||
message = 'I/O operation on closed file'
|
||||
raise ValueError, message
|
||||
|
||||
|
||||
def truncate(self):
|
||||
""" Sorry, this isn't supported by Panda's low-level I/O,
|
||||
because it isn't supported by the standard C++ library. """
|
||||
|
|
@ -287,7 +287,7 @@ open = file
|
|||
def listdir(path):
|
||||
""" Implements os.listdir over vfs. """
|
||||
files = []
|
||||
dirlist = _vfs.scanDirectory(pm.Filename.fromOsSpecific(path))
|
||||
dirlist = _vfs.scanDirectory(core.Filename.fromOsSpecific(path))
|
||||
if dirlist is None:
|
||||
message = 'No such file or directory: %s' % (path)
|
||||
raise OSError, message
|
||||
|
|
@ -338,31 +338,31 @@ def join(path, *args):
|
|||
return path
|
||||
|
||||
def isfile(path):
|
||||
return _vfs.isRegularFile(pm.Filename.fromOsSpecific(path))
|
||||
return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))
|
||||
|
||||
def isdir(path):
|
||||
return _vfs.isDirectory(pm.Filename.fromOsSpecific(path))
|
||||
return _vfs.isDirectory(core.Filename.fromOsSpecific(path))
|
||||
|
||||
def exists(path):
|
||||
return _vfs.exists(pm.Filename.fromOsSpecific(path))
|
||||
return _vfs.exists(core.Filename.fromOsSpecific(path))
|
||||
|
||||
def lexists(path):
|
||||
return _vfs.exists(pm.Filename.fromOsSpecific(path))
|
||||
|
||||
return _vfs.exists(core.Filename.fromOsSpecific(path))
|
||||
|
||||
def getmtime(path):
|
||||
file = _vfs.getFile(pm.Filename.fromOsSpecific(path), True)
|
||||
file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
|
||||
if not file:
|
||||
raise os.error
|
||||
return file.getTimestamp()
|
||||
|
||||
|
||||
def getsize(path):
|
||||
file = _vfs.getFile(pm.Filename.fromOsSpecific(path), True)
|
||||
file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
|
||||
if not file:
|
||||
raise os.error
|
||||
return file.getFileSize()
|
||||
|
||||
def execfile(path, globals=None, locals=None):
|
||||
file = _vfs.getFile(pm.Filename.fromOsSpecific(path), True)
|
||||
file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
|
||||
if not file:
|
||||
raise os.error
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ support extensions of this nature. """
|
|||
|
||||
from types import *
|
||||
from copy_reg import dispatch_table
|
||||
from pandac.PandaModules import BamWriter, BamReader
|
||||
from panda3d.core import BamWriter, BamReader
|
||||
|
||||
# A funny replacement for "import pickle" so we don't get confused
|
||||
# with the local pickle.py.
|
||||
|
|
@ -37,7 +37,7 @@ class Pickler(pickle.Pickler):
|
|||
|
||||
# We have to duplicate most of the save() method, so we can add
|
||||
# support for __reduce_persist__().
|
||||
|
||||
|
||||
def save(self, obj):
|
||||
# Check for persistent id (defined by a subclass)
|
||||
pid = self.persistent_id(obj)
|
||||
|
|
@ -116,7 +116,7 @@ class Unpickler(pickle.Unpickler):
|
|||
|
||||
# Duplicate the load_reduce() function, to provide a special case
|
||||
# for the reduction function.
|
||||
|
||||
|
||||
def load_reduce(self):
|
||||
stack = self.stack
|
||||
args = stack.pop()
|
||||
|
|
|
|||
|
|
@ -14,13 +14,12 @@ __all__ = [
|
|||
'forceYield', 'considerYield',
|
||||
]
|
||||
|
||||
# Import PandaModules as pm, so we don't have any namespace collisions.
|
||||
from pandac import PandaModules as pm
|
||||
from panda3d import core
|
||||
|
||||
# These methods are defined in Panda, and are particularly useful if
|
||||
# you may be running in Panda's SIMPLE_THREADS compilation mode.
|
||||
forceYield = pm.Thread.forceYield
|
||||
considerYield = pm.Thread.considerYield
|
||||
forceYield = core.Thread.forceYield
|
||||
considerYield = core.Thread.considerYield
|
||||
|
||||
class error(StandardError):
|
||||
pass
|
||||
|
|
@ -31,10 +30,10 @@ class LockType:
|
|||
provide the described Python lock semantics. In particular, this
|
||||
allows a different thread to release the lock than the one that
|
||||
acquired it. """
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.__lock = pm.Mutex('PythonLock')
|
||||
self.__cvar = pm.ConditionVar(self.__lock)
|
||||
self.__lock = core.Mutex('PythonLock')
|
||||
self.__cvar = core.ConditionVar(self.__lock)
|
||||
self.__locked = False
|
||||
|
||||
def acquire(self, waitflag = 1):
|
||||
|
|
@ -44,7 +43,7 @@ class LockType:
|
|||
return False
|
||||
while self.__locked:
|
||||
self.__cvar.wait()
|
||||
|
||||
|
||||
self.__locked = True
|
||||
return True
|
||||
|
||||
|
|
@ -56,16 +55,16 @@ class LockType:
|
|||
try:
|
||||
if not self.__locked:
|
||||
raise error, 'Releasing unheld lock.'
|
||||
|
||||
|
||||
self.__locked = False
|
||||
self.__cvar.notify()
|
||||
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
|
||||
def locked(self):
|
||||
return self.__locked
|
||||
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
|
|
@ -73,7 +72,7 @@ class LockType:
|
|||
|
||||
_threads = {}
|
||||
_nextThreadId = 0
|
||||
_threadsLock = pm.Mutex('thread._threadsLock')
|
||||
_threadsLock = core.Mutex('thread._threadsLock')
|
||||
|
||||
def start_new_thread(function, args, kwargs = {}, name = None):
|
||||
def threadFunc(threadId, function = function, args = args, kwargs = kwargs):
|
||||
|
|
@ -94,31 +93,31 @@ def start_new_thread(function, args, kwargs = {}, name = None):
|
|||
|
||||
if name is None:
|
||||
name = 'PythonThread-%s' % (threadId)
|
||||
|
||||
thread = pm.PythonThread(threadFunc, [threadId], name, name)
|
||||
|
||||
thread = core.PythonThread(threadFunc, [threadId], name, name)
|
||||
thread.setPythonData(threadId)
|
||||
_threads[threadId] = (thread, {}, None)
|
||||
|
||||
thread.start(pm.TPNormal, False)
|
||||
|
||||
thread.start(core.TPNormal, False)
|
||||
return threadId
|
||||
|
||||
finally:
|
||||
_threadsLock.release()
|
||||
|
||||
def _add_thread(thread, wrapper):
|
||||
""" Adds the indicated pm.Thread object, with the indicated Python
|
||||
""" Adds the indicated core.Thread object, with the indicated Python
|
||||
wrapper, to the thread list. Returns the new thread ID. """
|
||||
|
||||
|
||||
global _nextThreadId
|
||||
_threadsLock.acquire()
|
||||
try:
|
||||
threadId = _nextThreadId
|
||||
_nextThreadId += 1
|
||||
|
||||
|
||||
thread.setPythonData(threadId)
|
||||
_threads[threadId] = (thread, {}, wrapper)
|
||||
return threadId
|
||||
|
||||
|
||||
finally:
|
||||
_threadsLock.release()
|
||||
|
||||
|
|
@ -130,7 +129,7 @@ def _get_thread_wrapper(thread, wrapperClass):
|
|||
threadId = thread.getPythonData()
|
||||
if threadId is None:
|
||||
# The thread has never been assigned a threadId. Go assign one.
|
||||
|
||||
|
||||
global _nextThreadId
|
||||
_threadsLock.acquire()
|
||||
try:
|
||||
|
|
@ -166,7 +165,7 @@ def _get_thread_locals(thread, i):
|
|||
threadId = thread.getPythonData()
|
||||
if threadId is None:
|
||||
# The thread has never been assigned a threadId. Go assign one.
|
||||
|
||||
|
||||
global _nextThreadId
|
||||
_threadsLock.acquire()
|
||||
try:
|
||||
|
|
@ -195,14 +194,14 @@ def _get_thread_locals(thread, i):
|
|||
|
||||
def _remove_thread_id(threadId):
|
||||
""" Removes the thread with the indicated ID from the thread list. """
|
||||
|
||||
|
||||
_threadsLock.acquire()
|
||||
try:
|
||||
thread, locals, wrapper = _threads[threadId]
|
||||
assert thread.getPythonData() == threadId
|
||||
del _threads[threadId]
|
||||
thread.setPythonData(None)
|
||||
|
||||
|
||||
finally:
|
||||
_threadsLock.release()
|
||||
|
||||
|
|
@ -218,7 +217,7 @@ def allocate_lock():
|
|||
return LockType()
|
||||
|
||||
def get_ident():
|
||||
return pm.Thread.getCurrentThread().this
|
||||
return core.Thread.getCurrentThread().this
|
||||
|
||||
def stack_size(size = 0):
|
||||
raise error
|
||||
|
|
@ -244,18 +243,18 @@ class _local(object):
|
|||
_threadsLock.release()
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
d = _get_thread_locals(pm.Thread.getCurrentThread(), id(self))
|
||||
d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
|
||||
d[key] = value
|
||||
|
||||
|
||||
## def __getattr__(self, key):
|
||||
## d = _get_thread_locals(pm.Thread.getCurrentThread(), id(self))
|
||||
## d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
|
||||
## try:
|
||||
## return d[key]
|
||||
## except KeyError:
|
||||
## raise AttributeError
|
||||
|
||||
def __getattribute__(self, key):
|
||||
d = _get_thread_locals(pm.Thread.getCurrentThread(), id(self))
|
||||
d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
|
||||
if key == '__dict__':
|
||||
return d
|
||||
try:
|
||||
|
|
@ -263,5 +262,5 @@ class _local(object):
|
|||
except KeyError:
|
||||
return object.__getattribute__(self, key)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,11 +21,8 @@ easier to use and understand.
|
|||
It is permissible to mix-and-match both threading and threading2
|
||||
within the same application. """
|
||||
|
||||
# We import PandaModules as the name pm, so we can avoid namespace
|
||||
# collisions between native Panda objects, and our own class
|
||||
# definitions in this module. """
|
||||
import direct
|
||||
from pandac import PandaModules as pm
|
||||
from panda3d import core
|
||||
from direct.stdpy import thread as _thread
|
||||
import sys as _sys
|
||||
|
||||
|
|
@ -55,10 +52,10 @@ class ThreadBase:
|
|||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
|
||||
def is_alive(self):
|
||||
return self.__thread.isStarted()
|
||||
|
||||
|
||||
def isAlive(self):
|
||||
return self.__thread.isStarted()
|
||||
|
||||
|
|
@ -68,9 +65,9 @@ class ThreadBase:
|
|||
def setDaemon(self, daemon):
|
||||
if self.is_alive():
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
self.__dict__['daemon'] = daemon
|
||||
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key == 'name':
|
||||
self.setName(value)
|
||||
|
|
@ -84,8 +81,8 @@ class ThreadBase:
|
|||
# Copy these static methods from Panda's Thread object. These are
|
||||
# useful if you may be running in Panda's SIMPLE_THREADS compilation
|
||||
# mode.
|
||||
ThreadBase.forceYield = pm.Thread.forceYield
|
||||
ThreadBase.considerYield = pm.Thread.considerYield
|
||||
ThreadBase.forceYield = core.Thread.forceYield
|
||||
ThreadBase.considerYield = core.Thread.considerYield
|
||||
|
||||
class Thread(ThreadBase):
|
||||
""" This class provides a wrapper around Panda's PythonThread
|
||||
|
|
@ -108,21 +105,21 @@ class Thread(ThreadBase):
|
|||
self.__dict__['daemon'] = current.daemon
|
||||
self.__dict__['name'] = name
|
||||
|
||||
self.__thread = pm.PythonThread(self.run, None, name, name)
|
||||
self.__thread = core.PythonThread(self.run, None, name, name)
|
||||
threadId = _thread._add_thread(self.__thread, weakref.proxy(self))
|
||||
self.__dict__['ident'] = threadId
|
||||
|
||||
def __del__(self):
|
||||
# On interpreter shutdown, the _thread module might have
|
||||
# already been cleaned up.
|
||||
if _thread and _thread._remove_thread_id:
|
||||
if _thread and _thread._remove_thread_id:
|
||||
_thread._remove_thread_id(self.ident)
|
||||
|
||||
def start(self):
|
||||
if self.__thread.isStarted():
|
||||
raise RuntimeError
|
||||
|
||||
if not self.__thread.start(pm.TPNormal, True):
|
||||
|
||||
if not self.__thread.start(core.TPNormal, True):
|
||||
raise RuntimeError
|
||||
|
||||
def run(self):
|
||||
|
|
@ -132,7 +129,7 @@ class Thread(ThreadBase):
|
|||
_sys.setprofile(_setprofile_func)
|
||||
|
||||
self.__target(*self.__args, **self.__kwargs)
|
||||
|
||||
|
||||
def join(self, timeout = None):
|
||||
# We don't support a timed join here, sorry.
|
||||
assert timeout is None
|
||||
|
|
@ -146,10 +143,10 @@ class Thread(ThreadBase):
|
|||
class ExternalThread(ThreadBase):
|
||||
""" Returned for a Thread object that wasn't created by this
|
||||
interface. """
|
||||
|
||||
|
||||
def __init__(self, extThread, threadId):
|
||||
ThreadBase.__init__(self)
|
||||
|
||||
|
||||
self.__thread = extThread
|
||||
self.__dict__['daemon'] = True
|
||||
self.__dict__['name'] = self.__thread.getName()
|
||||
|
|
@ -157,10 +154,10 @@ class ExternalThread(ThreadBase):
|
|||
|
||||
def start(self):
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
def run(self):
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
def join(self, timeout = None):
|
||||
raise RuntimeError
|
||||
|
||||
|
|
@ -169,53 +166,53 @@ class ExternalThread(ThreadBase):
|
|||
|
||||
class MainThread(ExternalThread):
|
||||
""" Returned for the MainThread object. """
|
||||
|
||||
|
||||
def __init__(self, extThread, threadId):
|
||||
ExternalThread.__init__(self, extThread, threadId)
|
||||
self.__dict__['daemon'] = False
|
||||
|
||||
class Lock(pm.Mutex):
|
||||
class Lock(core.Mutex):
|
||||
""" This class provides a wrapper around Panda's Mutex object.
|
||||
The wrapper is designed to emulate Python's own threading.Lock
|
||||
object. """
|
||||
|
||||
def __init__(self, name = "PythonLock"):
|
||||
pm.Mutex.__init__(self, name)
|
||||
core.Mutex.__init__(self, name)
|
||||
|
||||
def acquire(self, blocking = True):
|
||||
if blocking:
|
||||
pm.Mutex.acquire(self)
|
||||
core.Mutex.acquire(self)
|
||||
return True
|
||||
else:
|
||||
return pm.Mutex.tryAcquire(self)
|
||||
|
||||
return core.Mutex.tryAcquire(self)
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
self.release()
|
||||
|
||||
class RLock(pm.ReMutex):
|
||||
class RLock(core.ReMutex):
|
||||
""" This class provides a wrapper around Panda's ReMutex object.
|
||||
The wrapper is designed to emulate Python's own threading.RLock
|
||||
object. """
|
||||
|
||||
def __init__(self, name = "PythonRLock"):
|
||||
pm.ReMutex.__init__(self, name)
|
||||
core.ReMutex.__init__(self, name)
|
||||
|
||||
def acquire(self, blocking = True):
|
||||
if blocking:
|
||||
pm.ReMutex.acquire(self)
|
||||
core.ReMutex.acquire(self)
|
||||
return True
|
||||
else:
|
||||
return pm.ReMutex.tryAcquire(self)
|
||||
|
||||
return core.ReMutex.tryAcquire(self)
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
self.release()
|
||||
|
||||
|
||||
class Condition(pm.ConditionVarFull):
|
||||
class Condition(core.ConditionVarFull):
|
||||
""" This class provides a wrapper around Panda's ConditionVarFull
|
||||
object. The wrapper is designed to emulate Python's own
|
||||
threading.Condition object. """
|
||||
|
|
@ -229,7 +226,7 @@ class Condition(pm.ConditionVarFull):
|
|||
assert isinstance(lock, Lock)
|
||||
|
||||
self.__lock = lock
|
||||
pm.ConditionVarFull.__init__(self, self.__lock)
|
||||
core.ConditionVarFull.__init__(self, self.__lock)
|
||||
|
||||
def acquire(self, *args, **kw):
|
||||
return self.__lock.acquire(*args, **kw)
|
||||
|
|
@ -239,35 +236,35 @@ class Condition(pm.ConditionVarFull):
|
|||
|
||||
def wait(self, timeout = None):
|
||||
if timeout is None:
|
||||
pm.ConditionVarFull.wait(self)
|
||||
core.ConditionVarFull.wait(self)
|
||||
else:
|
||||
pm.ConditionVarFull.wait(self, timeout)
|
||||
core.ConditionVarFull.wait(self, timeout)
|
||||
|
||||
def notifyAll(self):
|
||||
pm.ConditionVarFull.notifyAll(self)
|
||||
core.ConditionVarFull.notifyAll(self)
|
||||
|
||||
notify_all = notifyAll
|
||||
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
self.release()
|
||||
|
||||
class Semaphore(pm.Semaphore):
|
||||
class Semaphore(core.Semaphore):
|
||||
""" This class provides a wrapper around Panda's Semaphore
|
||||
object. The wrapper is designed to emulate Python's own
|
||||
threading.Semaphore object. """
|
||||
|
||||
def __init__(self, value = 1):
|
||||
pm.Semaphore.__init__(self, value)
|
||||
core.Semaphore.__init__(self, value)
|
||||
|
||||
def acquire(self, blocking = True):
|
||||
if blocking:
|
||||
pm.Semaphore.acquire(self)
|
||||
core.Semaphore.acquire(self)
|
||||
return True
|
||||
else:
|
||||
return pm.Semaphore.tryAcquire(self)
|
||||
|
||||
return core.Semaphore.tryAcquire(self)
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
|
|
@ -293,8 +290,8 @@ class Event:
|
|||
object. """
|
||||
|
||||
def __init__(self):
|
||||
self.__lock = pm.Lock("Python Event")
|
||||
self.__cvar = pm.ConditionVarFull(self.__lock)
|
||||
self.__lock = core.Lock("Python Event")
|
||||
self.__cvar = core.ConditionVarFull(self.__lock)
|
||||
self.__flag = False
|
||||
|
||||
def is_set(self):
|
||||
|
|
@ -310,7 +307,7 @@ class Event:
|
|||
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
|
||||
def clear(self):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
|
|
@ -318,7 +315,7 @@ class Event:
|
|||
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
|
||||
def wait(self, timeout = None):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
|
|
@ -326,15 +323,15 @@ class Event:
|
|||
while not self.__flag:
|
||||
self.__cvar.wait()
|
||||
else:
|
||||
clock = pm.TrueClock.getGlobalPtr()
|
||||
clock = core.TrueClock.getGlobalPtr()
|
||||
expires = clock.getShortTime() + timeout
|
||||
while not self.__flag:
|
||||
wait = expires - clock.getShortTime()
|
||||
if wait < 0:
|
||||
return
|
||||
|
||||
|
||||
self.__cvar.wait(wait)
|
||||
|
||||
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
|
|
@ -366,7 +363,7 @@ class Timer(Thread):
|
|||
|
||||
def _create_thread_wrapper(t, threadId):
|
||||
""" Creates a thread wrapper for the indicated external thread. """
|
||||
if isinstance(t, pm.MainThread):
|
||||
if isinstance(t, core.MainThread):
|
||||
pyt = MainThread(t, threadId)
|
||||
else:
|
||||
pyt = ExternalThread(t, threadId)
|
||||
|
|
@ -374,7 +371,7 @@ def _create_thread_wrapper(t, threadId):
|
|||
return pyt
|
||||
|
||||
def current_thread():
|
||||
t = pm.Thread.getCurrentThread()
|
||||
t = core.Thread.getCurrentThread()
|
||||
return _thread._get_thread_wrapper(t, _create_thread_wrapper)
|
||||
|
||||
currentThread = current_thread
|
||||
|
|
@ -410,7 +407,7 @@ def stack_size(size = None):
|
|||
def _test():
|
||||
|
||||
from collections import deque
|
||||
_sleep = pm.Thread.sleep
|
||||
_sleep = core.Thread.sleep
|
||||
|
||||
_VERBOSE = False
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import sys as _sys
|
|||
|
||||
from direct.stdpy import thread
|
||||
from direct.stdpy.thread import stack_size, _local as local
|
||||
from pandac import PandaModules as pm
|
||||
_sleep = pm.Thread.sleep
|
||||
from panda3d import core
|
||||
_sleep = core.Thread.sleep
|
||||
|
||||
from time import time as _time
|
||||
from traceback import format_exc as _format_exc
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import time
|
|||
import random
|
||||
import string
|
||||
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
|
||||
def print_exc_plus():
|
||||
"""
|
||||
|
|
@ -114,7 +114,7 @@ class TaskManager:
|
|||
|
||||
self._frameProfileQueue = Queue()
|
||||
|
||||
# this will be set when it's safe to import StateVar
|
||||
# this will be set when it's safe to import StateVar
|
||||
self._profileFrames = None
|
||||
self._frameProfiler = None
|
||||
self._profileTasks = None
|
||||
|
|
@ -231,7 +231,7 @@ class TaskManager:
|
|||
in proportion to their time used and to their priority value.
|
||||
See AsyncTaskManager.setTimeslicePriority() for more.
|
||||
"""
|
||||
|
||||
|
||||
chain = self.mgr.makeTaskChain(chainName)
|
||||
if numThreads is not None:
|
||||
chain.setNumThreads(numThreads)
|
||||
|
|
@ -249,7 +249,7 @@ class TaskManager:
|
|||
def hasTaskNamed(self, taskName):
|
||||
"""Returns true if there is at least one task, active or
|
||||
sleeping, with the indicated name. """
|
||||
|
||||
|
||||
return bool(self.mgr.findTask(taskName))
|
||||
|
||||
def getTasksNamed(self, taskName):
|
||||
|
|
@ -261,7 +261,7 @@ class TaskManager:
|
|||
"""Returns a list of all tasks, active or sleeping, with a
|
||||
name that matches the pattern, which can include standard
|
||||
shell globbing characters like *, ?, and []. """
|
||||
|
||||
|
||||
return self.__makeTaskList(self.mgr.findTasksMatching(GlobPattern(taskPattern)))
|
||||
|
||||
def getAllTasks(self):
|
||||
|
|
@ -298,7 +298,7 @@ class TaskManager:
|
|||
wish to specify a task that will run in the next frame, use a
|
||||
delayTime of 0.
|
||||
"""
|
||||
|
||||
|
||||
if delayTime < 0:
|
||||
assert self.notify.warning('doMethodLater: added task: %s with negative delay: %s' % (name, delayTime))
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ class TaskManager:
|
|||
def add(self, funcOrTask, name = None, sort = None, extraArgs = None,
|
||||
priority = None, uponDeath = None, appendTask = False,
|
||||
taskChain = None, owner = None):
|
||||
|
||||
|
||||
"""
|
||||
Add a new task to the taskMgr. The task will begin executing
|
||||
immediately, or next frame if its sort value has already
|
||||
|
|
@ -363,7 +363,7 @@ class TaskManager:
|
|||
added, or the original Task object that was passed in.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath)
|
||||
self.mgr.add(task)
|
||||
return task
|
||||
|
|
@ -412,7 +412,7 @@ class TaskManager:
|
|||
task.setUponDeath(uponDeath)
|
||||
|
||||
return task
|
||||
|
||||
|
||||
def remove(self, taskOrName):
|
||||
"""Removes a task from the task manager. The task is stopped,
|
||||
almost as if it had returned task.done. (But if the task is
|
||||
|
|
@ -421,7 +421,7 @@ class TaskManager:
|
|||
Task object, or the name of a task. If you specify a name,
|
||||
all tasks with the indicated name are removed. Returns the
|
||||
number of tasks removed. """
|
||||
|
||||
|
||||
if isinstance(taskOrName, types.StringTypes):
|
||||
tasks = self.mgr.findTasks(taskOrName)
|
||||
return self.mgr.remove(tasks)
|
||||
|
|
@ -463,7 +463,7 @@ class TaskManager:
|
|||
# This is the spot for an internal yield function
|
||||
nextTaskTime = self.mgr.getNextWakeTime()
|
||||
self.doYield(startFrameTime, nextTaskTime)
|
||||
|
||||
|
||||
# Restore default interrupt handler
|
||||
signal.signal(signal.SIGINT, signal.default_int_handler)
|
||||
if self.fKeyboardInterrupt:
|
||||
|
|
@ -472,7 +472,7 @@ class TaskManager:
|
|||
def run(self):
|
||||
"""Starts the task manager running. Does not return until an
|
||||
exception is encountered (including KeyboardInterrupt). """
|
||||
|
||||
|
||||
# Set the clock to have last frame's time in case we were
|
||||
# Paused at the prompt for a long time
|
||||
t = self.globalClock.getFrameTime()
|
||||
|
|
@ -554,7 +554,7 @@ class TaskManager:
|
|||
def __tryReplaceTaskMethod(self, task, oldMethod, newFunction):
|
||||
if not isinstance(task, PythonTask):
|
||||
return 0
|
||||
|
||||
|
||||
method = task.getFunction()
|
||||
if (type(method) == types.MethodType):
|
||||
function = method.im_func
|
||||
|
|
@ -730,10 +730,10 @@ class TaskManager:
|
|||
delta = minFinTime - self.globalClock.getRealTime()
|
||||
while(delta > 0.002):
|
||||
print ' sleep %s'% (delta)
|
||||
time.sleep(delta)
|
||||
time.sleep(delta)
|
||||
delta = minFinTime - self.globalClock.getRealTime()
|
||||
"""
|
||||
|
||||
|
||||
if __debug__:
|
||||
# to catch memory leaks during the tests at the bottom of the file
|
||||
def _startTrackingMemLeaks(self):
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ COREAPI_VERSION=None
|
|||
PLUGIN_VERSION=None
|
||||
OSXTARGET=None
|
||||
UNIVERSAL=False
|
||||
HOST_URL="https://runtime.panda3d.org/"
|
||||
HOST_URL=None
|
||||
global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER
|
||||
STRDXSDKVERSION = 'default'
|
||||
STRMSPLATFORMVERSION = 'default'
|
||||
|
|
@ -429,11 +429,16 @@ SdkAutoDisablePhysX()
|
|||
SdkAutoDisableSpeedTree()
|
||||
|
||||
if (RTDIST and DISTRIBUTOR == "cmu"):
|
||||
HOST_URL = "https://runtime.panda3d.org/"
|
||||
|
||||
if (RTDIST_VERSION == "cmu_1.7" and SDK["PYTHONVERSION"] != "python2.6"):
|
||||
exit("The CMU 1.7 runtime distribution must be built against Python 2.6!")
|
||||
elif (RTDIST_VERSION == "cmu_1.8" and SDK["PYTHONVERSION"] != "python2.7"):
|
||||
exit("The CMU 1.8 runtime distribution must be built against Python 2.7!")
|
||||
|
||||
elif RTDIST and not HOST_URL:
|
||||
exit("You must specify a host URL when building the rtdist!")
|
||||
|
||||
########################################################################
|
||||
##
|
||||
## Choose a Compiler.
|
||||
|
|
@ -1562,8 +1567,8 @@ def CompileLink(dll, obj, opts):
|
|||
CopyFile(new_path, dll)
|
||||
oscmd('%s --strip-unneeded %s' % (GetStrip(), BracketNameWithQuotes(new_path)))
|
||||
|
||||
elif (GetOrigExt(dll)==".exe" and GetOptimizeOption(opts)==4 and "NOSTRIP" not in opts):
|
||||
oscmd(GetStrip() + " -x " + BracketNameWithQuotes(dll))
|
||||
elif (GetOptimizeOption(opts)==4 and GetTarget() == 'linux'):
|
||||
oscmd(GetStrip() + " --strip-unneeded " + BracketNameWithQuotes(dll))
|
||||
|
||||
os.system("chmod +x " + BracketNameWithQuotes(dll))
|
||||
|
||||
|
|
@ -4681,7 +4686,7 @@ if (RTDIST or RUNTIME):
|
|||
TargetAdd('p3dpython.exe', input='p3dpython_p3dPythonMain.obj')
|
||||
TargetAdd('p3dpython.exe', input=COMMON_PANDA_LIBS)
|
||||
TargetAdd('p3dpython.exe', input='libp3tinyxml.ilb')
|
||||
TargetAdd('p3dpython.exe', opts=['NOSTRIP', 'PYTHON', 'WINUSER'])
|
||||
TargetAdd('p3dpython.exe', opts=['PYTHON', 'WINUSER'])
|
||||
|
||||
TargetAdd('libp3dpython.dll', input='p3dpython_p3dpython_composite1.obj')
|
||||
TargetAdd('libp3dpython.dll', input=COMMON_PANDA_LIBS)
|
||||
|
|
@ -4719,7 +4724,7 @@ if (RTDIST or RUNTIME):
|
|||
TargetAdd('p3dcert.exe', input='plugin_mkdir_complete.obj')
|
||||
TargetAdd('p3dcert.exe', input='plugin_wstring_encode.obj')
|
||||
TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj')
|
||||
OPTS=['NOSTRIP', 'OPENSSL', 'WX', 'CARBON', 'WINOLE', 'WINOLEAUT', 'WINUSER', 'ADVAPI', 'WINSHELL', 'WINCOMCTL', 'WINGDI', 'WINCOMDLG']
|
||||
OPTS=['OPENSSL', 'WX', 'CARBON', 'WINOLE', 'WINOLEAUT', 'WINUSER', 'ADVAPI', 'WINSHELL', 'WINCOMCTL', 'WINGDI', 'WINCOMDLG']
|
||||
if GetTarget() == "darwin":
|
||||
OPTS += ['GL', 'OPT:2']
|
||||
TargetAdd('p3dcert.exe', opts=OPTS)
|
||||
|
|
@ -4836,7 +4841,7 @@ if (RUNTIME):
|
|||
TargetAdd('Panda3D.app', input='libp3tinyxml.ilb')
|
||||
TargetAdd('Panda3D.app', input='panda3d_mac.plist', ipath=OPTS)
|
||||
TargetAdd('Panda3D.app', input='models/plugin_images/panda3d.icns')
|
||||
TargetAdd('Panda3D.app', opts=['NOSTRIP', 'OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER', 'WINSHELL', 'ADVAPI', 'WINSOCK2', 'WINOLE', 'CARBON'])
|
||||
TargetAdd('Panda3D.app', opts=['OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER', 'WINSHELL', 'ADVAPI', 'WINSOCK2', 'WINOLE', 'CARBON'])
|
||||
elif (GetTarget() == 'windows'):
|
||||
TargetAdd('plugin_standalone_panda3dWinMain.obj', opts=OPTS, input='panda3dWinMain.cxx')
|
||||
TargetAdd('panda3dw.exe', input='plugin_standalone_panda3d.obj')
|
||||
|
|
@ -4899,7 +4904,7 @@ if (RTDIST):
|
|||
TargetAdd('p3dembed.exe', input='libp3subprocbuffer.ilb')
|
||||
TargetAdd('p3dembed.exe', input='libp3tinyxml.ilb')
|
||||
TargetAdd('p3dembed.exe', input='libp3d_plugin_static.ilb')
|
||||
TargetAdd('p3dembed.exe', opts=['NOICON', 'NOSTRIP', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'CARBON', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'X11', 'PNG'])
|
||||
TargetAdd('p3dembed.exe', opts=['NOICON', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'CARBON', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'X11', 'PNG'])
|
||||
|
||||
if GetTarget() == 'windows':
|
||||
OPTS.append("P3DEMBEDW")
|
||||
|
|
@ -4925,7 +4930,7 @@ if (RTDIST):
|
|||
TargetAdd('p3dembedw.exe', input='plugin_common.obj')
|
||||
TargetAdd('p3dembedw.exe', input='libp3tinyxml.ilb')
|
||||
TargetAdd('p3dembedw.exe', input='libp3d_plugin_static.ilb')
|
||||
TargetAdd('p3dembedw.exe', opts=['NOICON', 'NOSTRIP', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'PNG'])
|
||||
TargetAdd('p3dembedw.exe', opts=['NOICON', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'PNG'])
|
||||
|
||||
#
|
||||
# DIRECTORY: pandatool/src/pandatoolbase/
|
||||
|
|
|
|||
Loading…
Reference in New Issue