Merge branch 'master' into cmake
This commit is contained in:
commit
c902774cfd
29
README.md
29
README.md
|
|
@ -81,14 +81,18 @@ sudo apt-get install build-essential pkg-config python-dev libpng-dev libjpeg-de
|
|||
```
|
||||
|
||||
Once Panda3D has built, you can either install the .deb or .rpm package that
|
||||
it produced (if relevant to your platform, and you added --installer). On
|
||||
other systems, you will need to use the installpanda script to install it onto
|
||||
your system. Careful: it is not easy to uninstall Panda3D in this way!
|
||||
it produced, depending on which Linux distribution you are using. For example,
|
||||
to install the package on Debian or Ubuntu, use this:
|
||||
|
||||
```bash
|
||||
python2.7 makepanda/installpanda.py --prefix=/usr/local
|
||||
sudo dpkg -i panda3d*.deb
|
||||
```
|
||||
|
||||
If you are not using a Linux distribution that supports .deb or .rpm packages, you
|
||||
may have to use the installpanda.py script instead, which will directly copy the
|
||||
files into the appropriate locations on your computer. You may have to run the
|
||||
`ldconfig` tool in order to update your library cache after installing Panda3D.
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
|
||||
|
|
@ -110,3 +114,20 @@ by the release number, eg. 10.6 or 10.7.
|
|||
If the build was successful, makepanda will have generated a .dmg file in
|
||||
the source directory containing the installer. Simply open it and run the
|
||||
package file in order to install the SDK onto your system.
|
||||
|
||||
Reporting Issues
|
||||
================
|
||||
|
||||
If you encounter any bugs when using Panda3D, please report them in the bug
|
||||
tracker. This is hosted at:
|
||||
|
||||
https://bugs.launchpad.net/panda3d
|
||||
|
||||
Make sure to first use the search function to see if the bug has already been
|
||||
reported. When filling out a bug report, make sure that you include as much
|
||||
information as possible to help the developers track down the issue, such as
|
||||
your version of Panda3D, operating system, architecture, and any code and
|
||||
models that are necessary for the developers to reproduce the issue.
|
||||
|
||||
If you're not sure whether you've encountered a bug, feel free to ask about
|
||||
it in the forums or the IRC channel first.
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
#include "ai_composite1.cxx"
|
||||
|
|
@ -23,6 +23,8 @@ class Actor(DirectObject, NodePath):
|
|||
LoaderOptions.LFConvertAnim)
|
||||
|
||||
validateSubparts = ConfigVariableBool('validate-subparts', True)
|
||||
mergeLODBundles = ConfigVariableBool('merge-lod-bundles', True)
|
||||
allowAsyncBind = ConfigVariableBool('allow-async-bind', True)
|
||||
|
||||
class PartDef:
|
||||
|
||||
|
|
@ -170,10 +172,10 @@ class Actor(DirectObject, NodePath):
|
|||
# ['common']; when it is false, __animControlDict has one key
|
||||
# per each LOD name.
|
||||
|
||||
if mergeLODBundles == None:
|
||||
if mergeLODBundles is None:
|
||||
# If this isn't specified, it comes from the Config.prc
|
||||
# file.
|
||||
self.mergeLODBundles = base.config.GetBool('merge-lod-bundles', True)
|
||||
self.mergeLODBundles = Actor.mergeLODBundles.getValue()
|
||||
else:
|
||||
self.mergeLODBundles = mergeLODBundles
|
||||
|
||||
|
|
@ -181,8 +183,8 @@ class Actor(DirectObject, NodePath):
|
|||
# asynchronous animation binding. This requires that you have
|
||||
# run "egg-optchar -preload" on your animation and models to
|
||||
# generate the appropriate AnimPreloadTable.
|
||||
if allowAsyncBind == None:
|
||||
self.allowAsyncBind = base.config.GetBool('allow-async-bind', True)
|
||||
if allowAsyncBind is None:
|
||||
self.allowAsyncBind = Actor.allowAsyncBind.getValue()
|
||||
else:
|
||||
self.allowAsyncBind = allowAsyncBind
|
||||
|
||||
|
|
|
|||
|
|
@ -179,9 +179,9 @@ class GravityWalker(DirectObject.DirectObject):
|
|||
# a higher or lower value depending on whether you want an avatar
|
||||
# that is outside of the world to step up to the floor when they
|
||||
# get under valid floor:
|
||||
cRay = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0)
|
||||
self.cRay = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0)
|
||||
cRayNode = CollisionNode('GW.cRayNode')
|
||||
cRayNode.addSolid(cRay)
|
||||
cRayNode.addSolid(self.cRay)
|
||||
self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode)
|
||||
cRayNode.setFromCollideMask(bitmask)
|
||||
cRayNode.setIntoCollideMask(BitMask32.allOff())
|
||||
|
|
@ -697,8 +697,4 @@ class GravityWalker(DirectObject.DirectObject):
|
|||
# There are sometimes issues if the collision ray height is
|
||||
# so tall that it collides with multiple levels of floors.
|
||||
def setCollisionRayHeight(self, height):
|
||||
oldNode = self.avatarNodePath.getNode(0)
|
||||
cRayNode = oldNode.getChild(2)
|
||||
cRayNode.removeSolid(0)
|
||||
cRay = CollisionRay(0.0, 0.0, height, 0.0, 0.0, -1.0)
|
||||
cRayNode.addSolid(cRay)
|
||||
self.cRay.setOrigin(0.0, 0.0, height)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@
|
|||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
#undef HAVE_LONG_LONG // NSPR and Python both define this.
|
||||
#define PY_SSIZE_T_CLEAN 1
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
#include <Python.h>
|
||||
|
||||
// Python 2.5 adds Py_ssize_t; earlier versions don't have it.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ int main(int argc, char *mb_argv[]) {
|
|||
size_t len = mbstowcs(NULL, mb_argv[i], 0);
|
||||
argv[i] = new wchar_t[len + 1];
|
||||
mbstowcs(argv[i], mb_argv[i], len);
|
||||
argv[i][len] = NULL;
|
||||
argv[i][len] = 0;
|
||||
}
|
||||
// Just for good measure
|
||||
argv[argc] = NULL;
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ class Notifier:
|
|||
Prints the string to output followed by a newline.
|
||||
"""
|
||||
if self.streamWriter:
|
||||
self.streamWriter.appendData(string + '\n')
|
||||
self.streamWriter.write(string + '\n')
|
||||
else:
|
||||
print >> sys.stderr, string
|
||||
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
##############################################################################
|
||||
#
|
||||
# cleancvstree
|
||||
#
|
||||
# Cleancvstree searches a CVS tree for files that are not in CVS, and
|
||||
# deletes them. Be careful using it --- it's very aggressive.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import sys,os
|
||||
|
||||
def cleanCvsTree(dir):
|
||||
try:
|
||||
sub = os.listdir(dir)
|
||||
except:
|
||||
print "Could not read directory: "+dir
|
||||
return
|
||||
valid = {}
|
||||
try:
|
||||
readentries = 0
|
||||
cvsent = open(dir + "/CVS/Entries")
|
||||
for line in cvsent:
|
||||
words = line.split("/")
|
||||
if (len(words) > 1):
|
||||
valid[words[1]] = 1
|
||||
cvsent.close()
|
||||
readentries = 1
|
||||
except:
|
||||
print "Could not read "+dir+"/CVS/Entries"
|
||||
if (readentries):
|
||||
for file in sub:
|
||||
if (os.path.isfile(dir+"/"+file)):
|
||||
if (valid.has_key(file)==0):
|
||||
os.unlink(dir+"/"+file)
|
||||
for file in sub:
|
||||
if (file != "CVS"):
|
||||
if (os.path.isdir(dir+"/"+file)):
|
||||
cleanCvsTree(dir+"/"+file)
|
||||
|
||||
if (os.path.isdir(sys.argv[1])==0):
|
||||
print "Not a directory: "+sys.argv[1]
|
||||
os.exit(1)
|
||||
|
||||
cleanCvsTree(sys.argv[1])
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""This script generates the panda3d-date.tar.gz tarball for a file
|
||||
release of panda3d onto the SourceForge download site.
|
||||
|
||||
Options:
|
||||
|
||||
-d cvsroot
|
||||
Specifies the CVSROOT string to use to tag and export the
|
||||
tree. The default is $SFROOT if it is defined, or $CVSROOT
|
||||
otherwise.
|
||||
|
||||
-r tag
|
||||
Specifies the tag to export from. If this parameter is
|
||||
specified, the tree is not tagged again; otherwise, the
|
||||
current head of the CVS tree is tagged with the file version
|
||||
name.
|
||||
|
||||
-m module
|
||||
Specifies the module to check out and build. The default is
|
||||
panda3d.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import getopt
|
||||
import time
|
||||
import glob
|
||||
import shutil
|
||||
|
||||
CVSROOT = os.getenv('SFROOT') or os.getenv('CVSROOT')
|
||||
ORIGTAG = ''
|
||||
MODULE = 'panda3d'
|
||||
|
||||
def usage(code, msg = ''):
|
||||
print >> sys.stderr, __doc__
|
||||
print >> sys.stderr, msg
|
||||
sys.exit(code)
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'd:r:m:h')
|
||||
except getopt.error, msg:
|
||||
usage(1, msg)
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt == '-d':
|
||||
CVSROOT = arg
|
||||
elif opt == '-r':
|
||||
ORIGTAG = arg
|
||||
elif opt == '-m':
|
||||
MODULE = arg
|
||||
elif opt == '-h':
|
||||
usage(0)
|
||||
|
||||
if not CVSROOT:
|
||||
usage(1, 'CVSROOT must have a value.')
|
||||
|
||||
if not MODULE:
|
||||
usage(1, 'MODULE must have a value.')
|
||||
|
||||
basename = MODULE + '-' + time.strftime("%Y-%m-%d")
|
||||
tarfile = basename + '.tar.gz'
|
||||
zipfile = basename + '.zip'
|
||||
|
||||
if os.path.exists(basename):
|
||||
print basename, 'already exists in the local directory!'
|
||||
sys.exit(1)
|
||||
|
||||
if not ORIGTAG:
|
||||
# If we weren't given a starting tag, make one.
|
||||
tag = basename
|
||||
|
||||
print 'Tagging sources.'
|
||||
cmd = 'cvs -f -d "%s" rtag -F -r HEAD "%s" "%s"' % (CVSROOT, tag, MODULE)
|
||||
if os.system(cmd) != 0:
|
||||
sys.exit(1)
|
||||
else:
|
||||
# Otherwise, we were given a starting tag, so use it.
|
||||
tag = ORIGTAG
|
||||
|
||||
print 'Checking out "%s" as "%s".' % (MODULE, basename)
|
||||
cmd = 'cvs -z3 -f -d "%s" export -r "%s" -d "%s" "%s"' % (CVSROOT, tag,
|
||||
basename, MODULE)
|
||||
if os.system(cmd) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
# Move the contents of the doc module into the root directory where people
|
||||
# will expect to see it.
|
||||
docdir = basename + os.sep + 'doc'
|
||||
if os.path.exists(docdir):
|
||||
files = glob.glob(docdir + os.sep + '*')
|
||||
for file in files:
|
||||
shutil.copy(file, basename)
|
||||
os.remove(file)
|
||||
os.rmdir(docdir)
|
||||
|
||||
# Generate the autoconf scripts for ppremake.
|
||||
if MODULE == 'ppremake':
|
||||
ppremakedir = basename
|
||||
else:
|
||||
ppremakedir = basename + os.sep + 'ppremake'
|
||||
if os.path.exists(ppremakedir):
|
||||
cmd = 'cd "./%s" && aclocal && autoheader && automake --foreign -a && autoconf' % (ppremakedir)
|
||||
if os.system(cmd) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
# Generate the tarball.
|
||||
print 'Generating %s' % (tarfile)
|
||||
if os.path.exists(tarfile):
|
||||
os.remove(tarfile)
|
||||
cmd = 'tar cf - "%s" | gzip -9 > "%s"' % (basename, tarfile)
|
||||
if os.system(cmd) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
# Also generate a zip file.
|
||||
print 'Generating %s' % (zipfile)
|
||||
if os.path.exists(zipfile):
|
||||
os.remove(zipfile)
|
||||
cmd = 'zip -9rq "%s" "%s"' % (zipfile, basename)
|
||||
if os.system(cmd) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
shutil.rmtree(basename)
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
from direct.distributed.DistributedSmoothNodeBase import DistributedSmoothNodeBase
|
||||
from direct.distributed.GridParent import GridParent
|
||||
from pandac.PandaModules import EmbeddedValue
|
||||
|
||||
class GridChild:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
|
||||
"""
|
||||
CInterval-extensions module: contains methods to extend functionality
|
||||
of the CInterval class
|
||||
"""
|
||||
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
notify = directNotify.newCategory("Interval")
|
||||
|
||||
def setT(self, t):
|
||||
# Overridden from the C++ function to call privPostEvent
|
||||
# afterward. We do this by renaming the C++ function in
|
||||
# FFIRename.
|
||||
self._priv__cSetT(t)
|
||||
self.privPostEvent()
|
||||
|
||||
def play(self, t0 = 0.0, duration = None, scale = 1.0):
|
||||
self.notify.error("using deprecated CInterval.play() interface")
|
||||
if duration: # None or 0 implies full length
|
||||
self.start(t0, t0 + duration, scale)
|
||||
else:
|
||||
self.start(t0, -1, scale)
|
||||
|
||||
def stop(self):
|
||||
self.notify.error("using deprecated CInterval.stop() interface")
|
||||
self.finish()
|
||||
|
||||
def setFinalT(self):
|
||||
self.notify.error("using deprecated CInterval.setFinalT() interface")
|
||||
self.finish()
|
||||
|
||||
def privPostEvent(self):
|
||||
# Call after calling any of the priv* methods to do any required
|
||||
# Python finishing steps.
|
||||
t = self.getT()
|
||||
if hasattr(self, "setTHooks"):
|
||||
for func in self.setTHooks:
|
||||
func(t)
|
||||
|
||||
def popupControls(self, tl = None):
|
||||
"""
|
||||
Popup control panel for interval.
|
||||
"""
|
||||
from direct.showbase.TkGlobal import Toplevel, Frame, Button, LEFT, X, Pmw
|
||||
import math
|
||||
from direct.tkwidgets import EntryScale
|
||||
if tl == None:
|
||||
tl = Toplevel()
|
||||
tl.title('Interval Controls')
|
||||
outerFrame = Frame(tl)
|
||||
def entryScaleCommand(t, s=self):
|
||||
s.setT(t)
|
||||
s.pause()
|
||||
self.es = es = EntryScale.EntryScale(
|
||||
outerFrame, text = self.getName(),
|
||||
min = 0, max = math.floor(self.getDuration() * 100) / 100,
|
||||
command = entryScaleCommand)
|
||||
es.set(self.getT(), fCommand = 0)
|
||||
es.pack(expand = 1, fill = X)
|
||||
bf = Frame(outerFrame)
|
||||
# Jump to start and end
|
||||
def toStart(s=self, es=es):
|
||||
s.clearToInitial()
|
||||
s.setT(0)
|
||||
es.set(0, fCommand = 0)
|
||||
def toEnd(s=self):
|
||||
s.setT(s.getDuration())
|
||||
s.pause()
|
||||
jumpToStart = Button(bf, text = '<<', command = toStart)
|
||||
# Stop/play buttons
|
||||
def doPlay(s=self, es=es):
|
||||
s.resume(es.get())
|
||||
|
||||
stop = Button(bf, text = 'Stop',
|
||||
command = lambda s=self: s.pause())
|
||||
play = Button(
|
||||
bf, text = 'Play',
|
||||
command = doPlay)
|
||||
jumpToEnd = Button(bf, text = '>>', command = toEnd)
|
||||
jumpToStart.pack(side = LEFT, expand = 1, fill = X)
|
||||
play.pack(side = LEFT, expand = 1, fill = X)
|
||||
stop.pack(side = LEFT, expand = 1, fill = X)
|
||||
jumpToEnd.pack(side = LEFT, expand = 1, fill = X)
|
||||
bf.pack(expand = 1, fill = X)
|
||||
outerFrame.pack(expand = 1, fill = X)
|
||||
# Add function to update slider during setT calls
|
||||
def update(t, es=es):
|
||||
es.set(t, fCommand = 0)
|
||||
if not hasattr(self, "setTHooks"):
|
||||
self.setTHooks = []
|
||||
self.setTHooks.append(update)
|
||||
self.setWantsTCallback(1)
|
||||
# Clear out function on destroy
|
||||
def onDestroy(e, s=self, u=update):
|
||||
if u in s.setTHooks:
|
||||
s.setTHooks.remove(u)
|
||||
tl.bind('<Destroy>', onDestroy)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
|
||||
def __str__(self):
|
||||
return self.getStringValue()
|
||||
|
||||
def __hash__(self):
|
||||
raise AttributeError, "ConfigVariables are not immutable."
|
||||
|
||||
def ls(self):
|
||||
from pandac.Notify import Notify
|
||||
self.write(Notify.out())
|
||||
|
||||
def __int__(self):
|
||||
return int(self.getValue())
|
||||
|
||||
def __long__(self):
|
||||
return long(self.getValue())
|
||||
|
||||
def __float__(self):
|
||||
return float(self.getValue())
|
||||
|
||||
def __nonzero__(self):
|
||||
return bool(self.getValue())
|
||||
|
||||
def __oct__(self):
|
||||
return oct(self.getValue())
|
||||
|
||||
def __hex__(self):
|
||||
return hex(self.getValue())
|
||||
|
||||
def __cmp__(self, other):
|
||||
return self.getValue().__cmp__(other)
|
||||
|
||||
def __neg__(self):
|
||||
return -self.getValue()
|
||||
|
||||
def __coerce__(self, other):
|
||||
return (self.getValue(), other)
|
||||
|
||||
def __len__(self):
|
||||
return self.getNumWords()
|
||||
|
||||
def __getitem__(self, n):
|
||||
if n < 0 or n >= self.getNumWords():
|
||||
raise IndexError
|
||||
return self.getWord(n)
|
||||
|
||||
def __setitem__(self, n, value):
|
||||
if n < 0 or n > self.getNumWords():
|
||||
raise IndexError
|
||||
self.setWord(n, value)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
def __getitem__(self, n):
|
||||
if n < 0 or n >= self.getNumWords():
|
||||
raise IndexError
|
||||
return self.getWord(n)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
def __getitem__(self, n):
|
||||
if n < 0 or n >= self.getNumWords():
|
||||
raise IndexError
|
||||
return self.getWord(n)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
def __getitem__(self, n):
|
||||
if n < 0 or n >= self.getNumWords():
|
||||
raise IndexError
|
||||
return self.getWord(n)
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
def __hash__(self):
|
||||
raise AttributeError, "ConfigVariables are not immutable."
|
||||
|
||||
def ls(self):
|
||||
from pandac.Notify import Notify
|
||||
self.write(Notify.out())
|
||||
|
||||
def __cmp__(self, other):
|
||||
return list(self).__cmp__(list(other))
|
||||
|
||||
def __len__(self):
|
||||
return self.getNumValues()
|
||||
|
||||
def __getitem__(self, n):
|
||||
if n < 0 or n >= self.getNumUniqueValues():
|
||||
raise IndexError
|
||||
return self.getUniqueValue(n)
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
def __len__(self):
|
||||
return self.getValue().__len__()
|
||||
|
||||
def __getitem__(self, n):
|
||||
return self.getValue().__getitem__(n)
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
"""
|
||||
HTTPChannel-extensions module: contains methods to extend functionality
|
||||
of the HTTPChannel class
|
||||
"""
|
||||
|
||||
def spawnTask(self, name = None, callback = None, extraArgs = []):
|
||||
"""Spawns a task to service the download recently requested
|
||||
via beginGetDocument(), etc., and/or downloadToFile() or
|
||||
downloadToRam(). If a callback is specified, that function is
|
||||
called when the download is complete, passing in the extraArgs
|
||||
given.
|
||||
|
||||
Returns the newly-spawned task.
|
||||
"""
|
||||
if not name:
|
||||
name = str(self.getUrl())
|
||||
from direct.task import Task
|
||||
task = Task.Task(self.doTask)
|
||||
task.callback = callback
|
||||
task.callbackArgs = extraArgs
|
||||
return taskMgr.add(task, name)
|
||||
|
||||
def doTask(self, task):
|
||||
from direct.task import Task
|
||||
if self.run():
|
||||
return Task.cont
|
||||
if task.callback:
|
||||
task.callback(*task.callbackArgs)
|
||||
return Task.done
|
||||
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
"""
|
||||
Mat3-extensions module: contains methods to extend functionality
|
||||
of the LMatrix3f class.
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(\n%s,\n%s,\n%s)' % (
|
||||
self.__class__.__name__, self.getRow(0).pPrintValues(), self.getRow(1).pPrintValues(), self.getRow(2).pPrintValues())
|
||||
|
||||
def pPrintValues(self):
|
||||
"""
|
||||
Pretty print
|
||||
"""
|
||||
return "\n%s\n%s\n%s" % (
|
||||
self.getRow(0).pPrintValues(), self.getRow(1).pPrintValues(), self.getRow(2).pPrintValues())
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
"""
|
||||
MouseWatcherRegion-extensions module: contains methods to extend
|
||||
functionality of the MouseWatcherRegion class
|
||||
"""
|
||||
|
||||
def setRelative(self, np, left, right, bottom, top):
|
||||
"""setRelation(NodePath np, float left, float right,
|
||||
float bottom, float top)
|
||||
|
||||
Sets the region to represnt the indicated rectangle, relative
|
||||
to the given NodePath. It is assumed that np represents some
|
||||
node parented within the render2d hierarchy.
|
||||
|
||||
"""
|
||||
from pandac import Point3
|
||||
|
||||
# Get the relative transform to the node.
|
||||
mat = np.getMat(render2d)
|
||||
|
||||
# Use this matrix to transform the corners of the region.
|
||||
ll = mat.xformPoint(Point3.Point3(left, 0, bottom))
|
||||
ur = mat.xformPoint(Point3.Point3(right, 0, top))
|
||||
|
||||
# Set the frame to the transformed coordinates.
|
||||
self.setFrame(ll[0], ur[0], ll[2], ur[2])
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
"""
|
||||
Node-extensions module: contains methods to extend functionality
|
||||
of the Node class
|
||||
"""
|
||||
|
||||
def isHidden(self):
|
||||
"""Determine if a node is hidden. Just pick the first parent,
|
||||
since this is an ambiguous question for instanced nodes"""
|
||||
import RenderRelation
|
||||
import PruneTransition
|
||||
rrClass = RenderRelation.RenderRelation.getClassType()
|
||||
if self.getNumParents(rrClass) > 0:
|
||||
arc = self.getParent(rrClass, 0)
|
||||
if arc.hasTransition(PruneTransition.PruneTransition.getClassType()):
|
||||
return 1
|
||||
else:
|
||||
return arc.getParent().isHidden()
|
||||
else:
|
||||
return 0
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
"""
|
||||
NurbsCurveEvaluator-extensions module: contains methods to extend
|
||||
functionality of the NurbsCurveEvaluator class
|
||||
"""
|
||||
|
||||
def getKnots(self):
|
||||
"""Returns the knot vector as a Python list of floats"""
|
||||
knots = []
|
||||
for i in range(self.getNumKnots()):
|
||||
knots.append(self.getKnot(i))
|
||||
return knots
|
||||
|
||||
def getVertices(self, relTo = None):
|
||||
"""Returns the vertices as a Python list of Vec4's, relative
|
||||
to the indicated space if given."""
|
||||
|
||||
verts = []
|
||||
if relTo:
|
||||
for i in range(self.getNumVertices()):
|
||||
verts.append(self.getVertex(i, relTo))
|
||||
else:
|
||||
for i in range(self.getNumVertices()):
|
||||
verts.append(self.getVertex(i))
|
||||
return verts
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
|
||||
"""
|
||||
NurbsSurfaceEvaluator-extensions module: contains methods to extend
|
||||
functionality of the NurbsSurfaceEvaluator class
|
||||
"""
|
||||
|
||||
def getUKnots(self):
|
||||
"""Returns the U knot vector as a Python list of floats"""
|
||||
knots = []
|
||||
for i in range(self.getNumUKnots()):
|
||||
knots.append(self.getUKnot(i))
|
||||
return knots
|
||||
|
||||
def getVKnots(self):
|
||||
"""Returns the V knot vector as a Python list of floats"""
|
||||
knots = []
|
||||
for i in range(self.getNumVKnots()):
|
||||
knots.append(self.getVKnot(i))
|
||||
return knots
|
||||
|
||||
def getVertices(self, relTo = None):
|
||||
"""Returns the vertices as a 2-d Python list of Vec4's, relative
|
||||
to the indicated space if given."""
|
||||
|
||||
verts = []
|
||||
for ui in range(self.getNumUVertices()):
|
||||
v = []
|
||||
if relTo:
|
||||
for vi in range(self.getNumVVertices()):
|
||||
v.append(self.getVertex(ui, vi, relTo))
|
||||
else:
|
||||
for vi in range(self.getNumVVertices()):
|
||||
v.append(self.getVertex(ui, vi))
|
||||
verts.append(v)
|
||||
|
||||
return verts
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
def getSystems(self):
|
||||
l = []
|
||||
for i in range(self.getNumSystems()):
|
||||
l.append(self.getSystem(l))
|
||||
return l
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
// For now, since we are not installing Python files, this file can
|
||||
// remain empty.
|
||||
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
|
||||
"""
|
||||
Contains methods to extend functionality
|
||||
of the SpriteParticleRenderer class
|
||||
"""
|
||||
|
||||
# Initialize class variables for texture, source file and node for texture and
|
||||
# node path textures to None. These will be initialized to a hardcoded default
|
||||
# or whatever the user specifies in his/her Configrc variable the first time they
|
||||
# are accessed
|
||||
# Will use instance copy of this in functions below
|
||||
sourceTextureName = None
|
||||
sourceFileName = None
|
||||
sourceNodeName = None
|
||||
|
||||
def getSourceTextureName(self):
|
||||
if self.sourceTextureName == None:
|
||||
SpriteParticleRenderer.sourceTextureName = base.config.GetString(
|
||||
'particle-sprite-texture', 'phase_3/maps/feyes.jpg')
|
||||
# Return instance copy of class variable
|
||||
return self.sourceTextureName
|
||||
|
||||
def setSourceTextureName(self, name):
|
||||
# Set instance copy of class variable
|
||||
self.sourceTextureName = name
|
||||
|
||||
def setTextureFromFile(self, fileName = None):
|
||||
if fileName == None:
|
||||
fileName = self.getSourceTextureName()
|
||||
else:
|
||||
self.setSourceTextureName(fileName)
|
||||
t = loader.loadTexture(fileName)
|
||||
if (t != None):
|
||||
self.setTexture(t)
|
||||
else:
|
||||
print "Couldn't find rendererSpriteTexture file: %s" % fileName
|
||||
|
||||
def getSourceFileName(self):
|
||||
if self.sourceFileName == None:
|
||||
SpriteParticleRenderer.sourceFileName = base.config.GetString(
|
||||
'particle-sprite-model', 'phase_3.5/models/props/suit-particles')
|
||||
# Return instance copy of class variable
|
||||
return self.sourceFileName
|
||||
|
||||
def setSourceFileName(self, name):
|
||||
# Set instance copy of class variable
|
||||
self.sourceFileName = name
|
||||
|
||||
def getSourceNodeName(self):
|
||||
if self.sourceNodeName == None:
|
||||
SpriteParticleRenderer.sourceNodeName = base.config.GetString(
|
||||
'particle-sprite-node', '**/fire')
|
||||
# Return instance copy of class variable
|
||||
return self.sourceNodeName
|
||||
|
||||
def setSourceNodeName(self, name):
|
||||
# Set instance copy of class variable
|
||||
self.sourceNodeName = name
|
||||
|
||||
def setTextureFromNode(self, modelName = None, nodeName = None):
|
||||
if modelName == None:
|
||||
modelName = self.getSourceFileName()
|
||||
else:
|
||||
self.setSourceFileName(modelName)
|
||||
if nodeName == None:
|
||||
nodeName = self.getSourceNodeName()
|
||||
else:
|
||||
self.setSourceNodeName(nodeName)
|
||||
# Load model and get texture
|
||||
m = loader.loadModel(modelName)
|
||||
if (m == None):
|
||||
print "SpriteParticleRenderer: Couldn't find model: %s!" % modelName
|
||||
return None
|
||||
nodeName = self.getSourceNodeName()
|
||||
np = m.find(nodeName)
|
||||
if np.isEmpty():
|
||||
print "SpriteParticleRenderer: Couldn't find node: %s!" % nodeName
|
||||
m.removeNode()
|
||||
return None
|
||||
self.setFromNode(np)
|
||||
m.removeNode()
|
||||
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
"""
|
||||
VBase3-extensions module: contains methods to extend functionality
|
||||
of the VBase3 class
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s, %s, %s)' % (
|
||||
self.__class__.__name__, self[0], self[1], self[2])
|
||||
|
||||
def pPrintValues(self):
|
||||
"""
|
||||
Pretty print
|
||||
"""
|
||||
return "% 10.4f, % 10.4f, % 10.4f" % (self[0], self[1], self[2])
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
"""
|
||||
VBase4-extensions module: contains methods to extend functionality
|
||||
of the VBase4 class
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s, %s, %s, %s)' % (
|
||||
self.__class__.__name__, self[0], self[1], self[2], self[3])
|
||||
|
||||
def pPrintValues(self):
|
||||
"""
|
||||
Pretty print
|
||||
"""
|
||||
return '% 10.4f, % 10.4f, % 10.4f, % 10.4f' % (self[0], self[1], self[2], self[3])
|
||||
|
|
@ -1 +0,0 @@
|
|||
from PandaModules import *
|
||||
|
|
@ -13,22 +13,9 @@ __all__ = ["AppRunner", "dummyAppRunner", "ArgumentError"]
|
|||
|
||||
import sys
|
||||
import os
|
||||
import __builtin__
|
||||
|
||||
if 'VFSImporter' in sys.modules:
|
||||
# If we've already got a VFSImporter module defined at the
|
||||
# toplevel, we must have come in here by way of the
|
||||
# p3dPythonRun.cxx program, which starts out by importing a frozen
|
||||
# VFSImporter. Let's make sure we don't have two VFSImporter
|
||||
# modules.
|
||||
import VFSImporter
|
||||
import direct.showbase
|
||||
direct.showbase.VFSImporter = VFSImporter
|
||||
sys.modules['direct.showbase.VFSImporter'] = VFSImporter
|
||||
else:
|
||||
# Otherwise, we can import the VFSImporter normally.
|
||||
from direct.showbase import VFSImporter
|
||||
import __builtin__ as builtins
|
||||
|
||||
from direct.showbase import VFSImporter
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from panda3d.core import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, ConfigPageManager
|
||||
from panda3d.direct import init_app_for_gui
|
||||
|
|
@ -472,7 +459,7 @@ class AppRunner(DirectObject):
|
|||
file.unlink()
|
||||
return False
|
||||
|
||||
if not fileSpec.fullVerify(pathname = localPathname):
|
||||
if not fileSpec.fullVerify(pathname = localPathname, notify = self.notify):
|
||||
# No good after download.
|
||||
self.notify.info("%s is still no good after downloading." % (url))
|
||||
return False
|
||||
|
|
@ -570,14 +557,14 @@ class AppRunner(DirectObject):
|
|||
for packageData in hostData.packages:
|
||||
totalSize += packageData.totalSize
|
||||
self.notify.info("Total Panda3D disk space used: %s MB" % (
|
||||
(totalSize + 524288) / 1048576))
|
||||
(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))
|
||||
(self.maxDiskUsage + 524288) // 1048576))
|
||||
if totalSize <= self.maxDiskUsage:
|
||||
# Still within budget; no need to clean up anything.
|
||||
return
|
||||
|
|
@ -635,13 +622,13 @@ class AppRunner(DirectObject):
|
|||
try:
|
||||
taskMgr.run()
|
||||
|
||||
except SystemExit:
|
||||
except SystemExit as err:
|
||||
# Presumably the window has already been shut down here, but shut
|
||||
# it down again for good measure.
|
||||
if hasattr(__builtin__, "base"):
|
||||
if hasattr(builtins, "base"):
|
||||
base.destroy()
|
||||
|
||||
self.notify.info("Normal exit.")
|
||||
self.notify.info("Normal exit with status %s." % repr(err.code))
|
||||
raise
|
||||
|
||||
except:
|
||||
|
|
@ -697,9 +684,10 @@ class AppRunner(DirectObject):
|
|||
# Replace the builtin open and file symbols so user code will get
|
||||
# our versions by default, which can open and read files out of
|
||||
# the multifile.
|
||||
__builtin__.file = file.file
|
||||
__builtin__.open = file.open
|
||||
__builtin__.execfile = file.execfile
|
||||
builtins.open = file.open
|
||||
if sys.version_info < (3, 0):
|
||||
builtins.file = file.open
|
||||
builtins.execfile = file.execfile
|
||||
os.listdir = file.listdir
|
||||
os.walk = file.walk
|
||||
os.path.join = file.join
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ to build for as many platforms as possible. """
|
|||
__all__ = ["Standalone", "Installer"]
|
||||
|
||||
import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct
|
||||
from cStringIO import StringIO
|
||||
from io import BytesIO, TextIOWrapper
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from direct.showbase.AppRunnerGlobal import appRunner
|
||||
from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
|
||||
|
|
@ -21,8 +21,8 @@ try:
|
|||
except ImportError:
|
||||
pwd = None
|
||||
|
||||
# Make sure this matches with the magic in p3dEmbed.cxx.
|
||||
P3DEMBED_MAGIC = "\xFF\x3D\x3D\x00"
|
||||
# Make sure this matches with the magic in p3dEmbedMain.cxx.
|
||||
P3DEMBED_MAGIC = 0xFF3D3D00
|
||||
|
||||
# This filter function is used when creating
|
||||
# an archive that should be owned by root.
|
||||
|
|
@ -73,7 +73,7 @@ class Standalone:
|
|||
|
||||
self.tempDir = Filename.temporary("", self.basename, "") + "/"
|
||||
self.tempDir.makeDir()
|
||||
self.host = HostInfo(PandaSystem.getPackageHostUrl(), appRunner = appRunner, hostDir = self.tempDir, asMirror = False)
|
||||
self.host = HostInfo(PandaSystem.getPackageHostUrl(), appRunner = appRunner, hostDir = self.tempDir, asMirror = False, perPlatform = True)
|
||||
|
||||
self.http = HTTPClient.getGlobalPtr()
|
||||
if not self.host.hasContentsFile:
|
||||
|
|
@ -99,6 +99,9 @@ class Standalone:
|
|||
if len(platforms) == 0:
|
||||
Standalone.notify.warning("No platforms found to build for!")
|
||||
|
||||
if 'win32' in platforms and 'win_i386' in platforms:
|
||||
platforms.remove('win32')
|
||||
|
||||
outputDir = Filename(outputDir + "/")
|
||||
outputDir.makeDir()
|
||||
for platform in platforms:
|
||||
|
|
@ -158,10 +161,10 @@ class Standalone:
|
|||
|
||||
# Find the magic size string and replace it with the real size,
|
||||
# regardless of the endianness of the p3dembed executable.
|
||||
hex_size = hex(size)[2:].rjust(8, "0")
|
||||
enc_size = "".join([chr(int(hex_size[i] + hex_size[i + 1], 16)) for i in range(0, len(hex_size), 2)])
|
||||
p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC, enc_size)
|
||||
p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC[::-1], enc_size[::-1])
|
||||
p3dembed_data = p3dembed_data.replace(struct.pack('>I', P3DEMBED_MAGIC),
|
||||
struct.pack('>I', size))
|
||||
p3dembed_data = p3dembed_data.replace(struct.pack('<I', P3DEMBED_MAGIC),
|
||||
struct.pack('<I', size))
|
||||
|
||||
# Write the output file
|
||||
Standalone.notify.info("Creating %s..." % output)
|
||||
|
|
@ -170,12 +173,15 @@ class Standalone:
|
|||
ohandle.write(p3dembed_data)
|
||||
|
||||
# Write out the tokens. Set log_basename to the basename by default
|
||||
tokens = {"log_basename" : self.basename}
|
||||
tokens = {"log_basename": self.basename}
|
||||
tokens.update(self.tokens)
|
||||
tokens.update(extraTokens)
|
||||
for token in tokens.items():
|
||||
ohandle.write("\0%s=%s" % token)
|
||||
ohandle.write("\0\0")
|
||||
for key, value in tokens.items():
|
||||
ohandle.write(b"\0")
|
||||
ohandle.write(key.encode('ascii'))
|
||||
ohandle.write(b"=")
|
||||
ohandle.write(value.encode())
|
||||
ohandle.write(b"\0\0")
|
||||
|
||||
# Buffer the p3d file to the output file. 1 MB buffer size.
|
||||
phandle = open(self.p3dfile.toOsSpecific(), "rb")
|
||||
|
|
@ -233,7 +239,7 @@ class PackageTree:
|
|||
if hostUrl in self.hosts:
|
||||
return self.hosts[hostUrl]
|
||||
|
||||
host = HostInfo(hostUrl, appRunner = appRunner, hostDir = self.hostDir, asMirror = False)
|
||||
host = HostInfo(hostUrl, appRunner = appRunner, hostDir = self.hostDir, asMirror = False, perPlatform = True)
|
||||
if not host.hasContentsFile:
|
||||
if not host.readContentsFile():
|
||||
if not host.downloadContentsFile(self.http):
|
||||
|
|
@ -391,7 +397,7 @@ class Icon:
|
|||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
stream = vfs.openWriteFile(fn, False, True)
|
||||
icns = open(stream, 'wb')
|
||||
icns.write('icns\0\0\0\0')
|
||||
icns.write(b'icns\0\0\0\0')
|
||||
|
||||
icon_types = {16: 'is32', 32: 'il32', 48: 'ih32', 128: 'it32'}
|
||||
mask_types = {16: 's8mk', 32: 'l8mk', 48: 'h8mk', 128: 't8mk'}
|
||||
|
|
@ -404,7 +410,7 @@ class Icon:
|
|||
if pngtype is None:
|
||||
continue
|
||||
icns.write(png_types[size])
|
||||
icns.write('\0\0\0\0')
|
||||
icns.write(b'\0\0\0\0')
|
||||
start = icns.tell()
|
||||
|
||||
image.write(stream, "", pngtype)
|
||||
|
|
@ -444,6 +450,7 @@ class Installer:
|
|||
notify = directNotify.newCategory("Installer")
|
||||
|
||||
def __init__(self, p3dfile, shortname, fullname, version, tokens = {}):
|
||||
self.p3dFilename = p3dfile
|
||||
if not shortname:
|
||||
shortname = p3dfile.getBasenameWoExtension()
|
||||
self.shortname = shortname
|
||||
|
|
@ -477,22 +484,16 @@ class Installer:
|
|||
if not self.authoremail and ' ' not in uname:
|
||||
self.authoremail = "%s@%s" % (uname, socket.gethostname())
|
||||
|
||||
self.standalone = Standalone(p3dfile, tokens)
|
||||
self.tempDir = Filename.temporary("", self.shortname, "") + "/"
|
||||
self.tempDir.makeDir()
|
||||
self.__tempRoots = {}
|
||||
|
||||
# Load the p3d file to read out the required packages
|
||||
mf = Multifile()
|
||||
if not mf.openRead(p3dfile):
|
||||
if not mf.openRead(self.p3dFilename):
|
||||
Installer.notify.error("Not a Panda3D application: %s" % (p3dfile))
|
||||
return
|
||||
|
||||
# Now load the p3dInfo file.
|
||||
self.hostUrl = PandaSystem.getPackageHostUrl()
|
||||
if not self.hostUrl:
|
||||
self.hostUrl = self.standalone.host.hostUrl
|
||||
self.hostUrl = None
|
||||
self.requires = []
|
||||
self.extracts = []
|
||||
i = mf.findSubfile('p3d_info.xml')
|
||||
if i >= 0:
|
||||
stream = mf.openReadSubfile(i)
|
||||
|
|
@ -511,14 +512,54 @@ class Installer:
|
|||
p3dRequires.Attribute('host')))
|
||||
p3dRequires = p3dRequires.NextSiblingElement('requires')
|
||||
|
||||
p3dExtract = p3dPackage.FirstChildElement('extract')
|
||||
while p3dExtract:
|
||||
filename = p3dExtract.Attribute('filename')
|
||||
self.extracts.append(filename)
|
||||
p3dExtract = p3dExtract.NextSiblingElement('extract')
|
||||
|
||||
if not self.fullname:
|
||||
p3dConfig = p3dPackage.FirstChildElement('config')
|
||||
if p3dConfig:
|
||||
self.fullname = p3dConfig.Attribute('display_name')
|
||||
else:
|
||||
Installer.notify.warning("No p3d_info.xml was found in .p3d archive.")
|
||||
|
||||
mf.close()
|
||||
|
||||
if not self.hostUrl:
|
||||
self.hostUrl = PandaSystem.getPackageHostUrl()
|
||||
if not self.hostUrl:
|
||||
self.hostUrl = self.standalone.host.hostUrl
|
||||
Installer.notify.warning("No host URL was specified by .p3d archive. Falling back to %s" % (self.hostUrl))
|
||||
|
||||
if not self.fullname:
|
||||
self.fullname = self.shortname
|
||||
|
||||
self.tempDir = Filename.temporary("", self.shortname, "") + "/"
|
||||
self.tempDir.makeDir()
|
||||
self.__tempRoots = {}
|
||||
|
||||
if self.extracts:
|
||||
# Copy .p3d to a temporary file so we can remove the extracts.
|
||||
p3dfile = Filename(self.tempDir, self.p3dFilename.getBasename())
|
||||
shutil.copyfile(self.p3dFilename.toOsSpecific(), p3dfile.toOsSpecific())
|
||||
mf = Multifile()
|
||||
if not mf.openReadWrite(p3dfile):
|
||||
Installer.notify.error("Failure to open %s for writing." % (p3dfile))
|
||||
|
||||
# We don't really need this silly thing when embedding, anyway.
|
||||
mf.setHeaderPrefix("")
|
||||
|
||||
for fn in self.extracts:
|
||||
if not mf.removeSubfile(fn):
|
||||
Installer.notify.error("Failure to remove %s from multifile." % (p3dfile))
|
||||
|
||||
mf.repack()
|
||||
mf.close()
|
||||
|
||||
self.standalone = Standalone(p3dfile, tokens)
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
appRunner.rmtree(self.tempDir)
|
||||
|
|
@ -533,6 +574,22 @@ class Installer:
|
|||
if not self.includeRequires:
|
||||
return
|
||||
|
||||
# Write out the extracts from the original .p3d.
|
||||
if self.extracts:
|
||||
mf = Multifile()
|
||||
if not mf.openRead(self.p3dFilename):
|
||||
Installer.notify.error("Failed to open .p3d archive: %s" % (filename))
|
||||
|
||||
for filename in self.extracts:
|
||||
i = mf.findSubfile(filename)
|
||||
if i < 0:
|
||||
Installer.notify.error("Cannot find extract in .p3d archive: %s" % (filename))
|
||||
continue
|
||||
|
||||
if not mf.extractSubfile(i, Filename(hostDir, filename)):
|
||||
Installer.notify.error("Failed to extract file from .p3d archive: %s" % (filename))
|
||||
mf.close()
|
||||
|
||||
pkgTree = PackageTree(platform, hostDir, self.hostUrl)
|
||||
pkgTree.installPackage("images", None, self.standalone.host.hostUrl)
|
||||
|
||||
|
|
@ -618,6 +675,9 @@ class Installer:
|
|||
if len(platforms) == 0:
|
||||
Installer.notify.warning("No platforms found to build for!")
|
||||
|
||||
if 'win32' in platforms and 'win_i386' in platforms:
|
||||
platforms.remove('win32')
|
||||
|
||||
outputDir = Filename(outputDir + "/")
|
||||
outputDir.makeDir()
|
||||
for platform in platforms:
|
||||
|
|
@ -660,7 +720,8 @@ class Installer:
|
|||
|
||||
Filename(tempdir, "usr/bin/").makeDir()
|
||||
if self.includeRequires:
|
||||
extraTokens = {"host_dir" : "/usr/lib/" + self.shortname.lower()}
|
||||
extraTokens = {"host_dir" : "/usr/lib/" + self.shortname.lower(),
|
||||
"start_dir" : "/usr/lib/" + self.shortname.lower()}
|
||||
else:
|
||||
extraTokens = {}
|
||||
self.standalone.build(Filename(tempdir, "usr/bin/" + self.shortname.lower()), platform, extraTokens)
|
||||
|
|
@ -712,7 +773,7 @@ class Installer:
|
|||
print >>desktop, "Type=Application"
|
||||
desktop.close()
|
||||
|
||||
if self.includeRequires:
|
||||
if self.includeRequires or self.extracts:
|
||||
hostDir = Filename(tempdir, "usr/lib/%s/" % self.shortname.lower())
|
||||
hostDir.makeDir()
|
||||
self.installPackagesInto(hostDir, platform)
|
||||
|
|
@ -742,16 +803,18 @@ class Installer:
|
|||
tempdir, totsize = self.__buildTempLinux(platform)
|
||||
|
||||
# Create a control file in memory.
|
||||
controlfile = StringIO()
|
||||
print >>controlfile, "Package: %s" % self.shortname.lower()
|
||||
print >>controlfile, "Version: %s" % self.version
|
||||
print >>controlfile, "Maintainer: %s <%s>" % (self.authorname, self.authoremail)
|
||||
print >>controlfile, "Section: games"
|
||||
print >>controlfile, "Priority: optional"
|
||||
print >>controlfile, "Architecture: %s" % arch
|
||||
print >>controlfile, "Installed-Size: %d" % -(-totsize / 1024)
|
||||
print >>controlfile, "Description: %s" % self.fullname
|
||||
print >>controlfile, "Depends: libc6, libgcc1, libstdc++6, libx11-6"
|
||||
controlfile = BytesIO()
|
||||
cout = TextIOWrapper(controlfile, encoding='utf-8', newline='')
|
||||
cout.write(u"Package: %s\n" % self.shortname.lower())
|
||||
cout.write(u"Version: %s\n" % self.version)
|
||||
cout.write(u"Maintainer: %s <%s>\n" % (self.authorname, self.authoremail))
|
||||
cout.write(u"Section: games\n")
|
||||
cout.write(u"Priority: optional\n")
|
||||
cout.write(u"Architecture: %s\n" % arch)
|
||||
cout.write(u"Installed-Size: %d\n" % -(-totsize // 1024))
|
||||
cout.write(u"Description: %s\n" % self.fullname)
|
||||
cout.write(u"Depends: libc6, libgcc1, libstdc++6, libx11-6\n")
|
||||
cout.flush()
|
||||
controlinfo = TarInfoRoot("control")
|
||||
controlinfo.mtime = modtime
|
||||
controlinfo.size = controlfile.tell()
|
||||
|
|
@ -762,33 +825,43 @@ class Installer:
|
|||
if output.exists():
|
||||
output.unlink()
|
||||
debfile = open(output.toOsSpecific(), "wb")
|
||||
debfile.write("!<arch>\x0A")
|
||||
debfile.write("debian-binary %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 4))
|
||||
debfile.write("2.0\x0A")
|
||||
debfile.write(b"!<arch>\x0A")
|
||||
pad_mtime = str(modtime).encode().ljust(12, b' ')
|
||||
|
||||
# Write the control.tar.gz to the archive.
|
||||
debfile.write("control.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0))
|
||||
# The first entry is a special file that marks it a .deb.
|
||||
debfile.write(b"debian-binary ")
|
||||
debfile.write(pad_mtime)
|
||||
debfile.write(b"0 0 100644 4 \x60\x0A")
|
||||
debfile.write(b"2.0\x0A")
|
||||
|
||||
# Write the control.tar.gz to the archive. We'll leave the
|
||||
# size 0 for now, and go back and fill it in later.
|
||||
debfile.write(b"control.tar.gz ")
|
||||
debfile.write(pad_mtime)
|
||||
debfile.write(b"0 0 100644 0 \x60\x0A")
|
||||
ctaroffs = debfile.tell()
|
||||
ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
|
||||
ctarfile.addfile(controlinfo, controlfile)
|
||||
ctarfile.close()
|
||||
ctarsize = debfile.tell() - ctaroffs
|
||||
if (ctarsize & 1): debfile.write("\x0A")
|
||||
if (ctarsize & 1): debfile.write(b"\x0A")
|
||||
|
||||
# Write the data.tar.gz to the archive.
|
||||
debfile.write("data.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0))
|
||||
# Write the data.tar.gz to the archive. Again, leave size 0.
|
||||
debfile.write(b"data.tar.gz ")
|
||||
debfile.write(pad_mtime)
|
||||
debfile.write(b"0 0 100644 0 \x60\x0A")
|
||||
dtaroffs = debfile.tell()
|
||||
dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
|
||||
dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr")
|
||||
dtarfile.close()
|
||||
dtarsize = debfile.tell() - dtaroffs
|
||||
if (dtarsize & 1): debfile.write("\x0A")
|
||||
if (dtarsize & 1): debfile.write(b"\x0A")
|
||||
|
||||
# Write the correct sizes of the archives.
|
||||
debfile.seek(ctaroffs - 12)
|
||||
debfile.write("%-10ld" % ctarsize)
|
||||
debfile.write(str(ctarsize).encode().ljust(10, b' '))
|
||||
debfile.seek(dtaroffs - 12)
|
||||
debfile.write("%-10ld" % dtarsize)
|
||||
debfile.write(str(dtarsize).encode().ljust(10, b' '))
|
||||
|
||||
debfile.close()
|
||||
|
||||
|
|
@ -815,18 +888,20 @@ class Installer:
|
|||
tempdir, totsize = self.__buildTempLinux(platform)
|
||||
|
||||
# Create a pkginfo file in memory.
|
||||
pkginfo = StringIO()
|
||||
print >>pkginfo, "# Generated using pdeploy"
|
||||
print >>pkginfo, "# %s" % time.ctime(modtime)
|
||||
print >>pkginfo, "pkgname = %s" % self.shortname.lower()
|
||||
print >>pkginfo, "pkgver = %s" % pkgver
|
||||
print >>pkginfo, "pkgdesc = %s" % self.fullname
|
||||
print >>pkginfo, "builddate = %s" % modtime
|
||||
print >>pkginfo, "packager = %s <%s>" % (self.authorname, self.authoremail)
|
||||
print >>pkginfo, "size = %d" % totsize
|
||||
print >>pkginfo, "arch = %s" % arch
|
||||
pkginfo = BytesIO()
|
||||
pout = TextIOWrapper(pkginfo, encoding='utf-8', newline='')
|
||||
pout.write(u"# Generated using pdeploy\n")
|
||||
pout.write(u"# %s\n" % time.ctime(modtime))
|
||||
pout.write(u"pkgname = %s\n" % self.shortname.lower())
|
||||
pout.write(u"pkgver = %s\n" % pkgver)
|
||||
pout.write(u"pkgdesc = %s\n" % self.fullname)
|
||||
pout.write(u"builddate = %s\n" % modtime)
|
||||
pout.write(u"packager = %s <%s>\n" % (self.authorname, self.authoremail))
|
||||
pout.write(u"size = %d\n" % totsize)
|
||||
pout.write(u"arch = %s\n" % arch)
|
||||
if self.licensename != "":
|
||||
print >>pkginfo, "license = %s" % self.licensename
|
||||
pout.write(u"license = %s\n" % self.licensename)
|
||||
pout.flush()
|
||||
pkginfoinfo = TarInfoRoot(".PKGINFO")
|
||||
pkginfoinfo.mtime = modtime
|
||||
pkginfoinfo.size = pkginfo.tell()
|
||||
|
|
@ -853,7 +928,7 @@ class Installer:
|
|||
exefile = Filename(output, "Contents/MacOS/" + self.shortname)
|
||||
exefile.makeDir()
|
||||
if self.includeRequires:
|
||||
extraTokens = {"host_dir" : "../Resources"}
|
||||
extraTokens = {"host_dir": "../Resources", "start_dir": "../Resources"}
|
||||
else:
|
||||
extraTokens = {}
|
||||
self.standalone.build(exefile, platform, extraTokens)
|
||||
|
|
@ -1064,7 +1139,7 @@ class Installer:
|
|||
exefile = Filename(Filename.getTempDirectory(), self.shortname + ".exe")
|
||||
exefile.unlink()
|
||||
if self.includeRequires:
|
||||
extraTokens = {"host_dir" : "."}
|
||||
extraTokens = {"host_dir": ".", "start_dir": "."}
|
||||
else:
|
||||
extraTokens = {}
|
||||
self.standalone.build(exefile, platform, extraTokens)
|
||||
|
|
|
|||
|
|
@ -161,14 +161,14 @@ class HostInfo:
|
|||
self.notify.info("Downloading contents file %s" % (request))
|
||||
statusCode = None
|
||||
statusString = ''
|
||||
for attempt in range(ConfigVariableInt('contents-xml-dl-attempts', 3)):
|
||||
for attempt in range(int(ConfigVariableInt('contents-xml-dl-attempts', 3))):
|
||||
if attempt > 0:
|
||||
self.notify.info("Retrying (%s)..."%(attempt,))
|
||||
rf = Ramfile()
|
||||
channel = http.makeChannel(False)
|
||||
channel.getDocument(request)
|
||||
if channel.downloadToRam(rf):
|
||||
self.notify.warning("Successfully downloaded %s" % (url,))
|
||||
self.notify.info("Successfully downloaded %s" % (url,))
|
||||
break
|
||||
else:
|
||||
rf = None
|
||||
|
|
@ -369,7 +369,7 @@ class HostInfo:
|
|||
assert self.hostDir
|
||||
self.__findHostXmlForHostDir(xcontents)
|
||||
|
||||
if not self.hostDir:
|
||||
if self.rootDir and not self.hostDir:
|
||||
self.hostDir = self.__determineHostDir(None, self.hostUrl)
|
||||
|
||||
# Get the list of packages available for download and/or import.
|
||||
|
|
@ -403,7 +403,7 @@ class HostInfo:
|
|||
self.hasContentsFile = True
|
||||
|
||||
# Now save the contents.xml file into the standard location.
|
||||
if not self.appRunner or self.appRunner.verifyContents != self.appRunner.P3DVCNever:
|
||||
if self.appRunner and self.appRunner.verifyContents != self.appRunner.P3DVCNever:
|
||||
assert self.hostDir
|
||||
filename = Filename(self.hostDir, 'contents.xml')
|
||||
filename.makeDir()
|
||||
|
|
@ -476,7 +476,7 @@ class HostInfo:
|
|||
self.descriptiveName = descriptiveName
|
||||
|
||||
hostDirBasename = xhost.Attribute('host_dir')
|
||||
if not self.hostDir:
|
||||
if self.rootDir and not self.hostDir:
|
||||
self.hostDir = self.__determineHostDir(hostDirBasename, self.hostUrl)
|
||||
|
||||
# Get the "download" URL, which is the source from which we
|
||||
|
|
@ -513,17 +513,15 @@ class HostInfo:
|
|||
PackageInfo, returns it. """
|
||||
|
||||
if not platform:
|
||||
# Ensure that we're on the same page with non-specified
|
||||
# platforms. We always use None, not empty string.
|
||||
platform = None
|
||||
|
||||
platforms = self.packages.setdefault((name, version), {})
|
||||
package = platforms.get(platform, None)
|
||||
platforms = self.packages.setdefault((name, version or ""), {})
|
||||
package = platforms.get("", None)
|
||||
if not package:
|
||||
package = PackageInfo(self, name, version, platform = platform,
|
||||
solo = solo, asMirror = self.asMirror,
|
||||
perPlatform = perPlatform)
|
||||
platforms[platform] = package
|
||||
platforms[platform or ""] = package
|
||||
|
||||
return package
|
||||
|
||||
|
|
@ -533,12 +531,12 @@ class HostInfo:
|
|||
platform, if one is provided by this host, or None if not. """
|
||||
|
||||
assert self.hasContentsFile
|
||||
platforms = self.packages.get((name, version or None), {})
|
||||
platforms = self.packages.get((name, version or ""), {})
|
||||
|
||||
if platform is not None:
|
||||
if platform:
|
||||
# In this case, we are looking for a specific platform
|
||||
# only.
|
||||
return platforms.get(platform or None, None)
|
||||
return platforms.get(platform, None)
|
||||
|
||||
# We are looking for one matching the current runtime
|
||||
# platform. First, look for a package matching the current
|
||||
|
|
@ -547,7 +545,7 @@ class HostInfo:
|
|||
|
||||
# If not found, look for one matching no particular platform.
|
||||
if not package:
|
||||
package = platforms.get(None, None)
|
||||
package = platforms.get("", None)
|
||||
|
||||
return package
|
||||
|
||||
|
|
@ -563,7 +561,7 @@ class HostInfo:
|
|||
if name and pn != name:
|
||||
continue
|
||||
|
||||
if platform is None:
|
||||
if not platform:
|
||||
for p2 in platforms:
|
||||
package = self.getPackage(pn, version, platform = p2)
|
||||
if package:
|
||||
|
|
@ -581,14 +579,12 @@ class HostInfo:
|
|||
|
||||
result = []
|
||||
|
||||
items = self.packages.items()
|
||||
items.sort()
|
||||
items = sorted(self.packages.items())
|
||||
for key, platforms in items:
|
||||
if self.perPlatform or includeAllPlatforms:
|
||||
# If we maintain a different answer per platform,
|
||||
# return all of them.
|
||||
pitems = platforms.items()
|
||||
pitems.sort()
|
||||
pitems = sorted(platforms.items())
|
||||
for pkey, package in pitems:
|
||||
result.append(package)
|
||||
else:
|
||||
|
|
@ -597,7 +593,7 @@ class HostInfo:
|
|||
# current platform, or no particular platform.
|
||||
package = platforms.get(PandaSystem.getPlatform(), None)
|
||||
if not package:
|
||||
package = platforms.get(None, None)
|
||||
package = platforms.get("", None)
|
||||
|
||||
if package:
|
||||
result.append(package)
|
||||
|
|
@ -701,7 +697,7 @@ class HostInfo:
|
|||
|
||||
# If we successfully got a hostname, we don't really need the
|
||||
# full hash. We'll keep half of it.
|
||||
keepHash = keepHash / 2;
|
||||
keepHash = keepHash // 2
|
||||
|
||||
md = HashVal()
|
||||
md.hashString(hostUrl)
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ class PackageInfo:
|
|||
# We've already got one.
|
||||
yield self.stepComplete; return
|
||||
|
||||
if self.host.appRunner and self.host.appRunner.verifyContents != self.host.appRunner.P3DVCNever:
|
||||
if not self.host.appRunner or self.host.appRunner.verifyContents != self.host.appRunner.P3DVCNever:
|
||||
# We're allowed to download it.
|
||||
self.http = http
|
||||
|
||||
|
|
@ -523,7 +523,8 @@ class PackageInfo:
|
|||
|
||||
# In case of unexpected failures on the internet, we will retry
|
||||
# the full download instead of just giving up.
|
||||
for retry in range(core.ConfigVariableInt('package-full-dl-retries', 1)):
|
||||
retries = core.ConfigVariableInt('package-full-dl-retries', 1).getValue()
|
||||
for retry in range(retries):
|
||||
self.installPlans.append(planB[:])
|
||||
|
||||
pc.stop()
|
||||
|
|
@ -1151,7 +1152,7 @@ class PackageInfo:
|
|||
thisDir = ScanDirectoryNode(self.getPackageDir(), ignoreUsageXml = True)
|
||||
diskSpace = thisDir.getTotalSize()
|
||||
self.notify.info("Package %s uses %s MB" % (
|
||||
self.packageName, (diskSpace + 524288) / 1048576))
|
||||
self.packageName, (diskSpace + 524288) // 1048576))
|
||||
return diskSpace
|
||||
|
||||
def markUsed(self):
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import types
|
|||
import getpass
|
||||
import struct
|
||||
import subprocess
|
||||
import copy
|
||||
from direct.p3d.FileSpec import FileSpec
|
||||
from direct.p3d.SeqValue import SeqValue
|
||||
from direct.showbase import Loader
|
||||
|
|
@ -185,7 +186,7 @@ class Packager:
|
|||
def getKey(self):
|
||||
""" Returns a tuple used for sorting the PackageEntry
|
||||
objects uniquely per package. """
|
||||
return (self.packageName, self.platform, self.version)
|
||||
return (self.packageName, self.platform or "", self.version or "")
|
||||
|
||||
def fromFile(self, packageName, platform, version, solo, perPlatform,
|
||||
installDir, descFilename, importDescFilename):
|
||||
|
|
@ -299,8 +300,7 @@ class Packager:
|
|||
xhost.InsertEndChild(xmirror)
|
||||
|
||||
if packager:
|
||||
altHosts = self.altHosts.items()
|
||||
altHosts.sort()
|
||||
altHosts = sorted(self.altHosts.items())
|
||||
for keyword, alt in altHosts:
|
||||
he = packager.hosts.get(alt, None)
|
||||
if he:
|
||||
|
|
@ -372,9 +372,15 @@ class Packager:
|
|||
self.requiredFilenames = []
|
||||
self.requiredModules = []
|
||||
|
||||
# A list of required packages that were missing.
|
||||
self.missingPackages = []
|
||||
|
||||
# This records the current list of modules we have added so
|
||||
# far.
|
||||
self.freezer = FreezeTool.Freezer(platform = self.packager.platform)
|
||||
|
||||
# Map of extensions to files to number (ignored by dir)
|
||||
self.ignoredDirFiles = {}
|
||||
|
||||
def close(self):
|
||||
""" Writes out the contents of the current package. Returns True
|
||||
|
|
@ -385,6 +391,12 @@ class Packager:
|
|||
message = 'Cannot generate packages without an installDir; use -i'
|
||||
raise PackagerError, message
|
||||
|
||||
if self.ignoredDirFiles:
|
||||
exts = sorted(self.ignoredDirFiles.keys())
|
||||
total = sum([x for x in self.ignoredDirFiles.values()])
|
||||
self.notify.warning("excluded %s files not marked for inclusion: %s" \
|
||||
% (total, ", ".join(["'" + ext + "'" for ext in exts])))
|
||||
|
||||
if not self.host:
|
||||
self.host = self.packager.host
|
||||
|
||||
|
|
@ -454,7 +466,7 @@ class Packager:
|
|||
if self.p3dApplication:
|
||||
allowPythonDev = self.configs.get('allow_python_dev', 0)
|
||||
if int(allowPythonDev):
|
||||
print "\n*** Generating %s.p3d with allow_python_dev enabled ***\n" % (self.packageName)
|
||||
print("\n*** Generating %s.p3d with allow_python_dev enabled ***\n" % (self.packageName))
|
||||
|
||||
return result
|
||||
|
||||
|
|
@ -485,6 +497,12 @@ class Packager:
|
|||
as a true package. Either is implemented with a
|
||||
Multifile. """
|
||||
|
||||
if self.missingPackages:
|
||||
missing = ', '.join([name for name, version in self.missingPackages])
|
||||
self.notify.warning("Cannot build package %s due to missing dependencies: %s" % (self.packageName, missing))
|
||||
self.cleanup()
|
||||
return False
|
||||
|
||||
self.multifile = Multifile()
|
||||
|
||||
# Write the multifile to a temporary filename until we
|
||||
|
|
@ -570,8 +588,7 @@ class Packager:
|
|||
|
||||
# Add known module names.
|
||||
self.moduleNames = {}
|
||||
modules = self.freezer.modules.items()
|
||||
modules.sort()
|
||||
modules = sorted(self.freezer.modules.items())
|
||||
for newName, mdef in modules:
|
||||
if mdef.guess:
|
||||
# Not really a module.
|
||||
|
|
@ -702,7 +719,7 @@ class Packager:
|
|||
self.packageDesc = packageDir + self.packageDesc
|
||||
self.packageImportDesc = packageDir + self.packageImportDesc
|
||||
|
||||
print "Generating %s" % (self.packageFilename)
|
||||
print("Generating %s" % (self.packageFilename))
|
||||
|
||||
if self.p3dApplication:
|
||||
self.packageFullpath = Filename(self.packager.p3dInstallDir, self.packageFilename)
|
||||
|
|
@ -820,6 +837,14 @@ class Packager:
|
|||
self.packager.contents[pe.getKey()] = pe
|
||||
self.packager.contentsChanged = True
|
||||
|
||||
# Hack for coreapi package, to preserve backward compatibility
|
||||
# with old versions of the runtime, which still called the
|
||||
# 32-bit Windows platform "win32".
|
||||
if self.packageName == "coreapi" and self.platform == "win_i386":
|
||||
pe2 = copy.copy(pe)
|
||||
pe2.platform = "win32"
|
||||
self.packager.contents[pe2.getKey()] = pe2
|
||||
|
||||
self.cleanup()
|
||||
return True
|
||||
|
||||
|
|
@ -1232,13 +1257,13 @@ class Packager:
|
|||
elf.close()
|
||||
return None
|
||||
|
||||
if not ident.startswith("\177ELF"):
|
||||
if not ident.startswith(b"\177ELF"):
|
||||
# No elf magic! Beware of orcs.
|
||||
return None
|
||||
|
||||
# Make sure we read in the correct endianness and integer size
|
||||
byteOrder = "<>"[ord(ident[5]) - 1]
|
||||
elfClass = ord(ident[4]) - 1 # 0 = 32-bits, 1 = 64-bits
|
||||
byteOrder = "<>"[ord(ident[5:6]) - 1]
|
||||
elfClass = ord(ident[4:5]) - 1 # 0 = 32-bits, 1 = 64-bits
|
||||
headerStruct = byteOrder + ("HHIIIIIHHHHHH", "HHIQQQIHHHHHH")[elfClass]
|
||||
sectionStruct = byteOrder + ("4xI8xIII8xI", "4xI16xQQI12xQ")[elfClass]
|
||||
dynamicStruct = byteOrder + ("iI", "qQ")[elfClass]
|
||||
|
|
@ -1272,17 +1297,17 @@ class Packager:
|
|||
elf.seek(offset)
|
||||
data = elf.read(entsize)
|
||||
tag, val = struct.unpack_from(dynamicStruct, data)
|
||||
newSectionData = ""
|
||||
newSectionData = b""
|
||||
startReplace = None
|
||||
pad = 0
|
||||
|
||||
# Read tags until we find a NULL tag.
|
||||
while tag != 0:
|
||||
if tag == 1: # A NEEDED entry. Read it from the string table.
|
||||
filenames.append(stringTables[link][val : stringTables[link].find('\0', val)])
|
||||
filenames.append(stringTables[link][val : stringTables[link].find(b'\0', val)])
|
||||
|
||||
elif tag == 15 or tag == 29:
|
||||
rpath += stringTables[link][val : stringTables[link].find('\0', val)].split(':')
|
||||
rpath += stringTables[link][val : stringTables[link].find(b'\0', val)].split(b':')
|
||||
# An RPATH or RUNPATH entry.
|
||||
if not startReplace:
|
||||
startReplace = elf.tell() - entsize
|
||||
|
|
@ -1296,7 +1321,7 @@ class Packager:
|
|||
tag, val = struct.unpack_from(dynamicStruct, data)
|
||||
|
||||
if startReplace is not None:
|
||||
newSectionData += data + ("\0" * pad)
|
||||
newSectionData += data + (b"\0" * pad)
|
||||
rewriteSections.append((startReplace, newSectionData))
|
||||
elf.close()
|
||||
|
||||
|
|
@ -1329,7 +1354,7 @@ class Packager:
|
|||
for offset, data in rewriteSections:
|
||||
elf.seek(offset)
|
||||
elf.write(data)
|
||||
elf.write("\0" * pad)
|
||||
elf.write(b"\0" * pad)
|
||||
elf.close()
|
||||
return filenames
|
||||
|
||||
|
|
@ -1468,6 +1493,10 @@ class Packager:
|
|||
xhost = he.makeXml(packager = self.packager)
|
||||
xpackage.InsertEndChild(xhost)
|
||||
|
||||
self.extracts.sort()
|
||||
for name, xextract in self.extracts:
|
||||
xpackage.InsertEndChild(xextract)
|
||||
|
||||
doc.InsertEndChild(xpackage)
|
||||
|
||||
# Write the xml file to a temporary file on disk, so we
|
||||
|
|
@ -1813,7 +1842,10 @@ class Packager:
|
|||
self.notify.warning(message)
|
||||
return
|
||||
|
||||
self.freezer.addModule(moduleName, filename = file.filename)
|
||||
if file.text:
|
||||
self.freezer.addModule(moduleName, filename = file.filename, text = file.text)
|
||||
else:
|
||||
self.freezer.addModule(moduleName, filename = file.filename)
|
||||
|
||||
def addEggFile(self, file):
|
||||
# Precompile egg files to bam's.
|
||||
|
|
@ -2161,8 +2193,10 @@ class Packager:
|
|||
ext = Filename(lowerName).getExtension()
|
||||
if ext not in self.packager.nonuniqueExtensions:
|
||||
self.skipFilenames[lowerName] = True
|
||||
|
||||
for moduleName, mdef in package.moduleNames.items():
|
||||
self.skipModules[moduleName] = mdef
|
||||
if not mdef.exclude:
|
||||
self.skipModules[moduleName] = mdef
|
||||
|
||||
# Packager constructor
|
||||
def __init__(self, platform = None):
|
||||
|
|
@ -2185,6 +2219,9 @@ class Packager:
|
|||
# ignoring any request to specify a particular download host,
|
||||
# e.g. for testing and development.
|
||||
self.ignoreSetHost = False
|
||||
|
||||
# Set this to true to verbosely log files ignored by dir().
|
||||
self.verbosePrint = False
|
||||
|
||||
# This will be appended to the basename of any .p3d package,
|
||||
# before the .p3d extension.
|
||||
|
|
@ -2333,7 +2370,7 @@ class Packager:
|
|||
|
||||
# Binary files that are copied (and compressed) without
|
||||
# processing.
|
||||
self.binaryExtensions = [ 'ttf', 'TTF', 'mid', 'ico' ]
|
||||
self.binaryExtensions = [ 'ttf', 'TTF', 'mid', 'ico', 'cur' ]
|
||||
|
||||
# Files that can have an existence in multiple different
|
||||
# packages simultaneously without conflict.
|
||||
|
|
@ -2373,7 +2410,7 @@ class Packager:
|
|||
}
|
||||
|
||||
# Files that should be extracted to disk.
|
||||
self.extractExtensions = self.executableExtensions[:] + self.manifestExtensions[:] + [ 'ico' ]
|
||||
self.extractExtensions = self.executableExtensions[:] + self.manifestExtensions[:] + [ 'ico', 'cur' ]
|
||||
|
||||
# Files that indicate a platform dependency.
|
||||
self.platformSpecificExtensions = self.executableExtensions[:]
|
||||
|
|
@ -2390,6 +2427,14 @@ class Packager:
|
|||
# should be added exactly byte-for-byte as they are.
|
||||
self.unprocessedExtensions = []
|
||||
|
||||
# Files for which warnings should be suppressed when they are
|
||||
# not handled by dir()
|
||||
self.suppressWarningForExtensions = ['', 'pyc', 'pyo',
|
||||
'p3d', 'pdef',
|
||||
'c', 'C', 'cxx', 'cpp', 'h', 'H',
|
||||
'hpp', 'pp', 'I', 'pem', 'p12', 'crt',
|
||||
'o', 'obj', 'a', 'lib', 'bc', 'll']
|
||||
|
||||
# System files that should never be packaged. For
|
||||
# case-insensitive filesystems (like Windows and OSX), put the
|
||||
# lowercase filename here. Case-sensitive filesystems should
|
||||
|
|
@ -2456,7 +2501,7 @@ class Packager:
|
|||
if not os.path.isfile('/sbin/ldconfig'):
|
||||
return False
|
||||
|
||||
handle = subprocess.Popen(['/sbin/ldconfig', '-p'], stdout=subprocess.PIPE)
|
||||
handle = subprocess.Popen(['/sbin/ldconfig', '-p'], stdout=subprocess.PIPE, universal_newlines=True)
|
||||
out, err = handle.communicate()
|
||||
|
||||
if handle.returncode != 0:
|
||||
|
|
@ -2617,12 +2662,20 @@ class Packager:
|
|||
if dirname.makeTrueCase():
|
||||
searchPath.appendDirectory(dirname)
|
||||
|
||||
def _ensureExtensions(self):
|
||||
self.knownExtensions = \
|
||||
self.imageExtensions + \
|
||||
self.modelExtensions + \
|
||||
self.textExtensions + \
|
||||
self.binaryExtensions + \
|
||||
self.uncompressibleExtensions + \
|
||||
self.unprocessedExtensions
|
||||
|
||||
def setup(self):
|
||||
""" Call this method to initialize the class after filling in
|
||||
some of the values in the constructor. """
|
||||
|
||||
self.knownExtensions = self.imageExtensions + self.modelExtensions + self.textExtensions + self.binaryExtensions + self.uncompressibleExtensions + self.unprocessedExtensions
|
||||
self._ensureExtensions()
|
||||
|
||||
self.currentPackage = None
|
||||
|
||||
|
|
@ -2710,11 +2763,15 @@ class Packager:
|
|||
# errors, and that the pdef file doesn't contain any really
|
||||
# crazy Python code, all this will do is fill in the
|
||||
# '__statements' list in the module scope.
|
||||
fn = packageDef.toOsSpecific()
|
||||
f = open(fn)
|
||||
code = compile(f.read(), fn, 'exec')
|
||||
f.close()
|
||||
|
||||
# It appears that having a separate globals and locals
|
||||
# dictionary causes problems with resolving symbols within a
|
||||
# class scope. So, we just use one dictionary, the globals.
|
||||
execfile(packageDef.toOsSpecific(), globals)
|
||||
exec(code, globals)
|
||||
|
||||
packages = []
|
||||
|
||||
|
|
@ -2979,10 +3036,10 @@ class Packager:
|
|||
# environment.
|
||||
return None
|
||||
|
||||
# Make sure we have a fresh version of the contents file.
|
||||
host = appRunner.getHost(hostUrl)
|
||||
if not host.readContentsFile():
|
||||
if not host.downloadContentsFile(appRunner.http):
|
||||
return None
|
||||
if not host.downloadContentsFile(appRunner.http):
|
||||
return None
|
||||
|
||||
packageInfos = []
|
||||
packageInfo = host.getPackage(packageName, version, platform = platform)
|
||||
|
|
@ -3031,7 +3088,7 @@ class Packager:
|
|||
tuples = []
|
||||
for package in packages:
|
||||
version = self.__makeVersionTuple(package.version)
|
||||
tuples.append((version, file))
|
||||
tuples.append((version, package))
|
||||
tuples.sort(reverse = True)
|
||||
|
||||
return [t[1] for t in tuples]
|
||||
|
|
@ -3044,7 +3101,7 @@ class Packager:
|
|||
tuples = []
|
||||
for package in packages:
|
||||
version = self.__makeVersionTuple(package.packageVersion)
|
||||
tuples.append((version, file))
|
||||
tuples.append((version, package))
|
||||
tuples.sort(reverse = True)
|
||||
|
||||
return [t[1] for t in tuples]
|
||||
|
|
@ -3103,9 +3160,9 @@ class Packager:
|
|||
if panda1.version == panda2.version:
|
||||
return True
|
||||
|
||||
print 'Rejecting package %s, version "%s": depends on %s, version "%s" instead of version "%s"' % (
|
||||
print('Rejecting package %s, version "%s": depends on %s, version "%s" instead of version "%s"' % (
|
||||
package.packageName, package.version,
|
||||
panda1.packageName, panda1.version, panda2.version)
|
||||
panda1.packageName, panda1.version, panda2.version))
|
||||
return False
|
||||
|
||||
def __findPackageInRequires(self, packageName, list):
|
||||
|
|
@ -3188,7 +3245,9 @@ class Packager:
|
|||
requires = self.currentPackage.requires)
|
||||
if not package:
|
||||
message = 'Unknown package %s, version "%s"' % (packageName, version)
|
||||
raise PackagerError, message
|
||||
self.notify.warning(message)
|
||||
self.currentPackage.missingPackages.append((packageName, pversion))
|
||||
continue
|
||||
|
||||
self.requirePackage(package)
|
||||
|
||||
|
|
@ -3293,42 +3352,27 @@ class Packager:
|
|||
producing their own custom panda3d for download. Should be
|
||||
called before any other Python modules are named. """
|
||||
|
||||
# First, freeze just VFSImporter.py into its own
|
||||
# _vfsimporter.pyd file. This one is a special case, because
|
||||
# we need this code in order to load python files from the
|
||||
# Multifile, so this file can't itself be in the Multifile.
|
||||
# This module and all its dependencies come frozen into p3dpython.
|
||||
# We should mark them as having already been added so that we don't
|
||||
# add them again to the Multifile.
|
||||
self.do_module('direct.showbase.VFSImporter')
|
||||
self.currentPackage.freezer.done(addStartupModules=True)
|
||||
self.currentPackage.freezer.writeCode(None)
|
||||
self.currentPackage.addExtensionModules()
|
||||
self.currentPackage.freezer.reset()
|
||||
|
||||
# This requires a bit of care, because we only want to freeze
|
||||
# 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
|
||||
# disk.
|
||||
from direct.showbase import VFSImporter
|
||||
filename = Filename.fromOsSpecific(VFSImporter.__file__)
|
||||
|
||||
self.do_module('VFSImporter', filename = filename)
|
||||
self.do_freeze('_vfsimporter', compileToExe = False)
|
||||
|
||||
self.do_file('panda3d/core.pyd');
|
||||
|
||||
# Now that we're done freezing, explicitly add 'direct' to
|
||||
# counteract the previous explicit excludeModule().
|
||||
self.do_module('direct')
|
||||
self.do_file('panda3d/_core.pyd', newDir='panda3d')
|
||||
|
||||
# This is the key Python module that is imported at runtime to
|
||||
# start an application running.
|
||||
self.do_module('direct.p3d.AppRunner')
|
||||
|
||||
# This is the main program that drives the runtime Python. It
|
||||
# is responsible for loading _vfsimporter.pyd, and then
|
||||
# importing direct.p3d.AppRunner, to start an application
|
||||
# running. The program comes in two parts: an executable, and
|
||||
# an associated dynamic library. Note that the .exe and .dll
|
||||
# extensions are automatically replaced with the appropriate
|
||||
# platform-specific extensions.
|
||||
# is responsible for importing direct.p3d.AppRunner to start an
|
||||
# application running. The program comes in two parts: an
|
||||
# executable, and an associated dynamic library. Note that the
|
||||
# .exe and .dll extensions are automatically replaced with the
|
||||
# appropriate platform-specific extensions.
|
||||
|
||||
if self.platform.startswith('osx'):
|
||||
# On Mac, we package up a P3DPython.app bundle. This
|
||||
|
|
@ -3411,7 +3455,7 @@ class Packager:
|
|||
freezer.addModule(moduleName, newName = newName)
|
||||
else:
|
||||
freezer.modules[newName] = freezer.modules[moduleName]
|
||||
freezer.done(compileToExe = compileToExe)
|
||||
freezer.done(addStartupModules = compileToExe)
|
||||
|
||||
dirname = ''
|
||||
basename = filename
|
||||
|
|
@ -3604,6 +3648,43 @@ class Packager:
|
|||
filename = Filename(filename)
|
||||
self.currentPackage.excludeFile(filename)
|
||||
|
||||
|
||||
def do_includeExtensions(self, executableExtensions = None, extractExtensions = None,
|
||||
imageExtensions = None, textExtensions = None,
|
||||
uncompressibleExtensions = None, unprocessedExtensions = None,
|
||||
suppressWarningForExtensions = None):
|
||||
""" Ensure that dir() will include files with the given extensions.
|
||||
The extensions should not have '.' prefixes.
|
||||
|
||||
All except 'suppressWarningForExtensions' allow the given kinds of files
|
||||
to be packaged with their respective semantics (read the source).
|
||||
|
||||
'suppressWarningForExtensions' lists extensions *expected* to be ignored,
|
||||
so no warnings will be emitted for them.
|
||||
"""
|
||||
if executableExtensions:
|
||||
self.executableExtensions += executableExtensions
|
||||
|
||||
if extractExtensions:
|
||||
self.extractExtensions += extractExtensions
|
||||
|
||||
if imageExtensions:
|
||||
self.imageExtensions += imageExtensions
|
||||
|
||||
if textExtensions:
|
||||
self.textExtensions += textExtensions
|
||||
|
||||
if uncompressibleExtensions:
|
||||
self.uncompressibleExtensions += uncompressibleExtensions
|
||||
|
||||
if unprocessedExtensions:
|
||||
self.unprocessedExtensions += unprocessedExtensions
|
||||
|
||||
if suppressWarningForExtensions:
|
||||
self.suppressWarningForExtensions += suppressWarningForExtensions
|
||||
|
||||
self._ensureExtensions()
|
||||
|
||||
def do_dir(self, dirname, newDir = None, unprocessed = None):
|
||||
|
||||
""" Adds the indicated directory hierarchy to the current
|
||||
|
|
@ -3676,7 +3757,12 @@ class Packager:
|
|||
filename.setBinary()
|
||||
self.currentPackage.addFile(filename, newName = newName,
|
||||
explicit = False, unprocessed = unprocessed)
|
||||
|
||||
elif not ext in self.suppressWarningForExtensions:
|
||||
newCount = self.currentPackage.ignoredDirFiles.get(ext, 0) + 1
|
||||
self.currentPackage.ignoredDirFiles[ext] = newCount
|
||||
|
||||
if self.verbosePrint:
|
||||
self.notify.warning("ignoring file %s" % filename)
|
||||
|
||||
def readContentsFile(self):
|
||||
""" Reads the contents.xml file at the beginning of
|
||||
|
|
@ -3750,8 +3836,7 @@ class Packager:
|
|||
xhost = he.makeXml(packager = self)
|
||||
xcontents.InsertEndChild(xhost)
|
||||
|
||||
contents = self.contents.items()
|
||||
contents.sort()
|
||||
contents = sorted(self.contents.items())
|
||||
for key, pe in contents:
|
||||
xpackage = pe.makeXml()
|
||||
xcontents.InsertEndChild(xpackage)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class images(package):
|
|||
token = '%s_img' % (name)
|
||||
configDict[token] = basename
|
||||
else:
|
||||
print "Could not locate %s" % (filename)
|
||||
print("Could not locate %s" % (filename))
|
||||
|
||||
# Also make a few special cases. We use the same default image
|
||||
# for many of the states.
|
||||
|
|
|
|||
|
|
@ -57,6 +57,14 @@ Options:
|
|||
instead of -e for files that are uncompressible by their nature
|
||||
(e.g. mpg files). This option may be repeated as necessary.
|
||||
|
||||
-x ext
|
||||
Marks files with the given extensions of needing to be physically
|
||||
extracted to disk before they can be loaded. This is used for
|
||||
file types that cannot be loaded via the virtual file system,
|
||||
such as .ico files on Windows.
|
||||
This option is currently only implemented when deploying the
|
||||
application with pdeploy.
|
||||
|
||||
-p python_lib_dir
|
||||
Adds a directory to search for additional Python modules. You
|
||||
can use this to add your system's Python path, to allow packp3d
|
||||
|
|
@ -103,7 +111,7 @@ class ArgumentError(StandardError):
|
|||
pass
|
||||
|
||||
def makePackedApp(args):
|
||||
opts, args = getopt.getopt(args, 'o:d:m:S:e:n:p:c:r:s:Dh')
|
||||
opts, args = getopt.getopt(args, 'o:d:m:S:e:n:x:p:c:r:s:Dh')
|
||||
|
||||
packager = Packager.Packager()
|
||||
|
||||
|
|
@ -134,6 +142,8 @@ def makePackedApp(args):
|
|||
packager.binaryExtensions.append(value)
|
||||
elif option == '-n':
|
||||
packager.uncompressibleExtensions.append(value)
|
||||
elif option == '-x':
|
||||
packager.extractExtensions.append(value)
|
||||
elif option == '-p':
|
||||
sys.path.append(value)
|
||||
elif option == '-c':
|
||||
|
|
@ -154,10 +164,10 @@ def makePackedApp(args):
|
|||
PandaSystem.getPackageHostUrl(),
|
||||
os.path.split(sys.argv[0])[1],
|
||||
'%s.%s' % (sys.version_info[0], sys.version_info[1]))
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
if not appFilename:
|
||||
raise ArgumentError, "No target app specified. Use:\n%s -o app.p3d" % (os.path.split(sys.argv[0])[1])
|
||||
raise ArgumentError, "No target app specified. Use:\n %s -o app.p3d\nUse -h to get more usage information." % (os.path.split(sys.argv[0])[1])
|
||||
|
||||
if args:
|
||||
raise ArgumentError, "Extra arguments on command line."
|
||||
|
|
@ -170,19 +180,20 @@ def makePackedApp(args):
|
|||
appDir = Filename('.')
|
||||
appBase = appFilename.getBasenameWoExtension()
|
||||
|
||||
if not main:
|
||||
if main:
|
||||
main = Filename.fromOsSpecific(main)
|
||||
main.makeAbsolute(root)
|
||||
else:
|
||||
main = Filename(root, 'main.py')
|
||||
if main.exists():
|
||||
main = 'main.py'
|
||||
else:
|
||||
if not main.exists():
|
||||
main = glob.glob(os.path.join(root.toOsSpecific(), '*.py'))
|
||||
if len(main) == 0:
|
||||
raise ArgumentError, 'No Python files in root directory.'
|
||||
elif len(main) > 1:
|
||||
raise ArgumentError, 'Multiple Python files in root directory; specify the main application with -m "main".'
|
||||
main = os.path.split(main[0])[1]
|
||||
|
||||
main = Filename.fromOsSpecific(main)
|
||||
main = Filename.fromOsSpecific(os.path.split(main[0])[1])
|
||||
main.makeAbsolute(root)
|
||||
|
||||
packager.installDir = appDir
|
||||
packager.allowPythonDev = allowPythonDev
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class panda3d(package):
|
|||
'panda3d.physics')
|
||||
|
||||
# Include various standard Python encodings. The rest is in morepy.
|
||||
module('encodings', 'encodings.aliases', 'encodings.undefined,'
|
||||
module('encodings', 'encodings.aliases', 'encodings.undefined',
|
||||
'encodings.utf_8', 'encodings.ascii', 'encodings.string_escape',
|
||||
'encodings.mbcs', 'encodings.latin_1', 'io')
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ class morepy(package):
|
|||
'termios', 'tty', 'pty', 'fcntl', 'pipes', 'posixfile',
|
||||
'resource', 'nis', 'syslog', 'commands', 'ic', 'MacOS',
|
||||
'macostools', 'findertools', 'EasyDialogs', 'FrameWork',
|
||||
'autoGIL', 'ColorPicker')
|
||||
'autoGIL', 'ColorPicker', 'ast')
|
||||
|
||||
# To add the multitude of standard Python string encodings.
|
||||
module('encodings', 'encodings.*')
|
||||
|
|
@ -362,8 +362,16 @@ class rocket(package):
|
|||
config(display_name = "Panda3D libRocket support")
|
||||
require('panda3d')
|
||||
|
||||
module('panda3d.rocket', required = True)
|
||||
module('_rocketcore', '_rocketcontrols')
|
||||
file('rocket.py', extract = True, text = """
|
||||
from _rocketcore import *
|
||||
try:
|
||||
from _rocketcontrols import *
|
||||
except ImportError:
|
||||
pass
|
||||
""")
|
||||
|
||||
module('panda3d.rocket', '_rocketcore', required = True)
|
||||
module('_rocketcontrols')
|
||||
file('libp3rocket.dll', required = True)
|
||||
|
||||
class vrpn(package):
|
||||
|
|
|
|||
|
|
@ -123,6 +123,10 @@ Options:
|
|||
as such. This only applies to .p3d packages, not to other types
|
||||
of packages!
|
||||
|
||||
-v
|
||||
Emit a warning for any file not recognized by the dir() command
|
||||
(indicating there may be a need for addExtensions(...)).
|
||||
|
||||
-h
|
||||
Display this help
|
||||
"""
|
||||
|
|
@ -135,12 +139,12 @@ from direct.p3d import Packager
|
|||
from panda3d.core import *
|
||||
|
||||
def usage(code, msg = ''):
|
||||
print >> sys.stderr, usageText % {
|
||||
sys.stderr.write(usageText % {
|
||||
'version' : PandaSystem.getPackageVersionString(),
|
||||
'host' : PandaSystem.getPackageHostUrl(),
|
||||
'prog' : os.path.split(sys.argv[0])[1]
|
||||
}
|
||||
print >> sys.stderr, msg
|
||||
})
|
||||
sys.stderr.write(msg + '\n')
|
||||
sys.exit(code)
|
||||
|
||||
installDir = None
|
||||
|
|
@ -151,12 +155,13 @@ allowPythonDev = False
|
|||
universalBinaries = False
|
||||
systemRoot = None
|
||||
ignoreSetHost = False
|
||||
verbosePrint = False
|
||||
p3dSuffix = ''
|
||||
platforms = []
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'i:ps:S:DuP:R:Ha:h')
|
||||
except getopt.error, msg:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'i:ps:S:DuP:R:Ha:hv')
|
||||
except getopt.error as msg:
|
||||
usage(1, msg)
|
||||
|
||||
for opt, arg in opts:
|
||||
|
|
@ -188,10 +193,13 @@ for opt, arg in opts:
|
|||
elif opt == '-a':
|
||||
p3dSuffix = arg
|
||||
|
||||
elif opt == '-v':
|
||||
verbosePrint = True
|
||||
|
||||
elif opt == '-h':
|
||||
usage(0)
|
||||
else:
|
||||
print 'illegal option: ' + arg
|
||||
print('illegal option: ' + arg)
|
||||
sys.exit(1)
|
||||
|
||||
if not args:
|
||||
|
|
@ -212,7 +220,7 @@ else:
|
|||
|
||||
if universalBinaries:
|
||||
if platforms:
|
||||
print '\nYou may not specify both -u and -P.\n'
|
||||
print('\nYou may not specify both -u and -P.\n')
|
||||
sys.exit(1)
|
||||
if PandaSystem.getPlatform().startswith('osx_'):
|
||||
platforms = ['osx_i386', 'osx_amd64']
|
||||
|
|
@ -230,6 +238,7 @@ for platform in platforms:
|
|||
packager.allowPythonDev = allowPythonDev
|
||||
packager.systemRoot = systemRoot
|
||||
packager.ignoreSetHost = ignoreSetHost
|
||||
packager.verbosePrint = verbosePrint
|
||||
packager.p3dSuffix = p3dSuffix
|
||||
|
||||
try:
|
||||
|
|
@ -242,7 +251,7 @@ for platform in platforms:
|
|||
except Packager.PackagerError:
|
||||
# Just print the error message and exit gracefully.
|
||||
inst = sys.exc_info()[1]
|
||||
print inst.args[0]
|
||||
print(inst.args[0])
|
||||
sys.exit(1)
|
||||
|
||||
# An explicit call to exit() is required to exit the program, when
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ class pyopengl(package):
|
|||
module('OpenGL.GLU', 'OpenGL.GLUT', 'OpenGL.GLE', 'OpenGL.GLX')
|
||||
|
||||
class httplib2(package):
|
||||
config(display_name = "httplib2")
|
||||
config(display_name = "httplib2", platform_specific = False)
|
||||
require('panda3d')
|
||||
|
||||
module('httplib2', required = True)
|
||||
|
|
@ -149,7 +149,7 @@ class box2d(package):
|
|||
module('Box2D', required = True)
|
||||
|
||||
class pyglet(package):
|
||||
config(display_name = "pyglet")
|
||||
require('panda3d')
|
||||
config(display_name = "pyglet", platform_specific = False)
|
||||
require('panda3d', 'morepy')
|
||||
|
||||
module('pyglet', required = True)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
if __name__ == "__main__":
|
||||
from direct.directbase.TestStart import *
|
||||
|
||||
from pandac.LinearVectorForce import LinearVectorForce
|
||||
from pandac.Vec3 import Vec3
|
||||
from panda3d.physics import LinearVectorForce
|
||||
from panda3d.core import Vec3
|
||||
import ParticleEffect
|
||||
from direct.tkpanels import ParticlePanel
|
||||
import Particles
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ load_plugin(const string &p3d_plugin_filename,
|
|||
const string &log_directory, const string &log_basename,
|
||||
bool trusted_environment, bool console_environment,
|
||||
const string &root_dir, const string &host_dir,
|
||||
ostream &logfile) {
|
||||
const string &start_dir, ostream &logfile) {
|
||||
if (plugin_loaded) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -259,7 +259,7 @@ load_plugin(const string &p3d_plugin_filename,
|
|||
verify_contents, platform,
|
||||
log_directory, log_basename,
|
||||
trusted_environment, console_environment,
|
||||
root_dir, host_dir, logfile)) {
|
||||
root_dir, host_dir, start_dir, logfile)) {
|
||||
unload_dso();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ init_plugin(const string &contents_filename, const string &host_url,
|
|||
const string &log_directory, const string &log_basename,
|
||||
bool trusted_environment, bool console_environment,
|
||||
const string &root_dir, const string &host_dir,
|
||||
ostream &logfile) {
|
||||
const string &start_dir, ostream &logfile) {
|
||||
|
||||
// Ensure that all of the function pointers have been found.
|
||||
if (P3D_initialize_ptr == NULL ||
|
||||
|
|
@ -371,15 +371,26 @@ init_plugin(const string &contents_filename, const string &host_url,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!P3D_initialize_ptr(P3D_API_VERSION, contents_filename.c_str(),
|
||||
// A bit of extra hand-hacked compatibility for using newer plug-ins
|
||||
// with an older version of the core API.
|
||||
int api_version = P3D_API_VERSION;
|
||||
if (api_version == 17 && start_dir.empty()) {
|
||||
api_version = 16;
|
||||
if (host_dir.empty()) {
|
||||
api_version = 15;
|
||||
}
|
||||
}
|
||||
|
||||
if (!P3D_initialize_ptr(api_version, contents_filename.c_str(),
|
||||
host_url.c_str(), verify_contents, platform.c_str(),
|
||||
log_directory.c_str(), log_basename.c_str(),
|
||||
trusted_environment, console_environment,
|
||||
root_dir.c_str(), host_dir.c_str())) {
|
||||
root_dir.c_str(), host_dir.c_str(),
|
||||
start_dir.c_str())) {
|
||||
// Oops, failure to initialize.
|
||||
logfile
|
||||
<< "Failed to initialize plugin (passed API version "
|
||||
<< P3D_API_VERSION << ")\n";
|
||||
<< api_version << ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,15 @@ load_plugin(const string &p3d_plugin_filename,
|
|||
P3D_verify_contents verify_contents, const string &platform,
|
||||
const string &log_directory, const string &log_basename,
|
||||
bool trusted_environment, bool console_environment,
|
||||
const string &root_dir, const string &host_dir, ostream &logfile);
|
||||
const string &root_dir, const string &host_dir,
|
||||
const string &start_dir, ostream &logfile);
|
||||
bool
|
||||
init_plugin(const string &contents_filename, const string &host_url,
|
||||
P3D_verify_contents verify_contents, const string &platform,
|
||||
const string &log_directory, const string &log_basename,
|
||||
bool trusted_environment, bool console_environment,
|
||||
const string &root_dir, const string &host_dir, ostream &logfile);
|
||||
const string &root_dir, const string &host_dir,
|
||||
const string &start_dir, ostream &logfile);
|
||||
|
||||
void unload_plugin(ostream &logfile);
|
||||
bool is_plugin_loaded();
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ start_p3dcert() {
|
|||
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
|
||||
_start_dir = inst_mgr->get_root_dir() + "/start";
|
||||
_start_dir = inst_mgr->get_start_dir();
|
||||
|
||||
string root_dir = _inst->_p3dcert_package->get_package_dir();
|
||||
mkdir_complete(_start_dir, nout);
|
||||
|
|
@ -183,7 +183,7 @@ start_p3dcert() {
|
|||
// These are the enviroment variables we forward from the current
|
||||
// environment, if they are set.
|
||||
const wchar_t *keep[] = {
|
||||
L"TMP", L"TEMP", L"HOME", L"USER",
|
||||
L"TMP", L"TEMP", L"HOME", L"USER",
|
||||
L"SYSTEMROOT", L"USERPROFILE", L"COMSPEC",
|
||||
NULL
|
||||
};
|
||||
|
|
@ -209,7 +209,8 @@ start_p3dcert() {
|
|||
// These are the enviroment variables we forward from the current
|
||||
// environment, if they are set.
|
||||
const char *keep[] = {
|
||||
"TMP", "TEMP", "HOME", "USER",
|
||||
"TMP", "TEMP", "HOME", "USER",
|
||||
"LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG",
|
||||
#ifdef HAVE_X11
|
||||
"DISPLAY", "XAUTHORITY",
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "p3dCert.h"
|
||||
#include "p3dCert_strings.h"
|
||||
#include "wstring_encode.h"
|
||||
#include "mkdir_complete.h"
|
||||
|
||||
|
|
@ -26,8 +27,9 @@
|
|||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define BUTTON_WIDTH 120
|
||||
#define BUTTON_WIDTH 180 // fit the Russian text
|
||||
#define BUTTON_SPACE 10
|
||||
|
||||
#include "ca_bundle_data_src.c"
|
||||
|
|
@ -36,63 +38,152 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
static const char
|
||||
self_signed_cert_text[] =
|
||||
"This Panda3D application uses a self-signed certificate. "
|
||||
"This means the author's name can't be verified, and you have "
|
||||
"no way of knowing for sure who wrote it.\n\n"
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
"We recommend you click Cancel to avoid running this application.";
|
||||
static LanguageIndex li = LI_default;
|
||||
|
||||
static const char
|
||||
unknown_auth_cert_text[] =
|
||||
"This Panda3D application has been signed, but we don't recognize "
|
||||
"the authority that verifies the signature. This means the author's "
|
||||
"name can't be trusted, and you have no way of knowing "
|
||||
"for sure who wrote it.\n\n"
|
||||
#if defined(_WIN32)
|
||||
static LanguageIndex detect_language() {
|
||||
// This function was introduced in Windows Vista; it may not be available
|
||||
// on older systems.
|
||||
typedef BOOL (*GUPL)(DWORD, PULONG, PZZWSTR, PULONG);
|
||||
GUPL pGetUserPreferredUILanguages = (GUPL)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
TEXT("GetUserPreferredUILanguages"));
|
||||
if (pGetUserPreferredUILanguages != NULL) {
|
||||
ULONG num_langs = 0;
|
||||
ULONG buffer_size = 0;
|
||||
pGetUserPreferredUILanguages(8, &num_langs, NULL, &buffer_size);
|
||||
PZZWSTR buffer = (PZZWSTR)_alloca(buffer_size);
|
||||
if (pGetUserPreferredUILanguages(8, &num_langs, buffer, &buffer_size)) {
|
||||
for (ULONG i = 0; i < num_langs; ++i) {
|
||||
size_t len = wcslen(buffer);
|
||||
if (len >= 2 && (buffer[2] == 0 || buffer[2] == L'-')) {
|
||||
// It may be a two-letter code; match it in our list.
|
||||
for (int j = 0; j < LI_COUNT; ++j) {
|
||||
const char *lang_code = language_codes[j];
|
||||
if (lang_code != NULL && lang_code[0] == buffer[0] &&
|
||||
lang_code[1] == buffer[1]) {
|
||||
return (LanguageIndex)j;
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer += len + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"We recommend you click Cancel to avoid running this application.";
|
||||
// Fall back to the old Windows XP function.
|
||||
LANGID lang = GetUserDefaultUILanguage() & 0x3ff;
|
||||
if (lang == 0) {
|
||||
return LI_default;
|
||||
}
|
||||
|
||||
static const char
|
||||
verified_cert_text[] =
|
||||
"This Panda3D application has been signed by %s. "
|
||||
"If you trust %s, then click the Run button below "
|
||||
"to run this application on your computer. This will also "
|
||||
"automatically approve this and any other applications signed by "
|
||||
"%s in the future.\n\n"
|
||||
for (int i = 0; i < LI_COUNT; ++i) {
|
||||
if (language_ids[i] != 0 && language_ids[i] == lang) {
|
||||
return (LanguageIndex)i;
|
||||
}
|
||||
}
|
||||
return LI_default;
|
||||
}
|
||||
|
||||
"If you are unsure about this application, "
|
||||
"you should click Cancel instead.";
|
||||
#elif defined(__APPLE__)
|
||||
static LanguageIndex detect_language() {
|
||||
// Get and iterate through the list of preferred languages.
|
||||
CFArrayRef langs = CFLocaleCopyPreferredLanguages();
|
||||
CFIndex num_langs = CFArrayGetCount(langs);
|
||||
|
||||
static const char
|
||||
expired_cert_text[] =
|
||||
"This Panda3D application has been signed by %s, "
|
||||
"but the certificate has expired.\n\n"
|
||||
for (long i = 0; i < num_langs; ++i) {
|
||||
CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(langs, i);
|
||||
|
||||
"You should check the current date set on your computer's clock "
|
||||
"to make sure it is correct.\n\n"
|
||||
CFIndex length = CFStringGetLength(lang);
|
||||
if (length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
"If your computer's date is correct, we recommend "
|
||||
"you click Cancel to avoid running this application.";
|
||||
CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
|
||||
char *buffer = (char *)alloca(max_size);
|
||||
if (!CFStringGetCString(lang, buffer, max_size, kCFStringEncodingUTF8)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
static const char
|
||||
generic_error_cert_text[] =
|
||||
"This Panda3D application has been signed, but there is a problem "
|
||||
"with the certificate (OpenSSL error code %d).\n\n"
|
||||
if (isalnum(buffer[2])) {
|
||||
// It's not a two-letter code.
|
||||
continue;
|
||||
}
|
||||
|
||||
"We recommend you click Cancel to avoid running this application.";
|
||||
// See if we support this language.
|
||||
for (int j = 0; j < LI_COUNT; ++j) {
|
||||
const char *lang_code = language_codes[j];
|
||||
if (lang_code != NULL && strncasecmp(buffer, lang_code, 2) == 0) {
|
||||
CFRelease(langs);
|
||||
return (LanguageIndex)j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char
|
||||
no_cert_text[] =
|
||||
"This Panda3D application has not been signed. This means you have "
|
||||
"no way of knowing for sure who wrote it.\n\n"
|
||||
CFRelease(langs);
|
||||
return LI_default;
|
||||
}
|
||||
|
||||
"Click Cancel to avoid running this application.";
|
||||
#else
|
||||
static LanguageIndex detect_language() {
|
||||
// First consult the LANGUAGE variable, which is a GNU extension that can
|
||||
// contain multiple languages in order of preference.
|
||||
const char *lang = getenv("LANGUAGE");
|
||||
while (lang != NULL && lang[0] != 0) {
|
||||
size_t len;
|
||||
const char *next = strchr(lang, ':');
|
||||
if (next == NULL) {
|
||||
len = strlen(lang);
|
||||
} else {
|
||||
len = (next - lang);
|
||||
++next;
|
||||
}
|
||||
|
||||
if (len >= 2 && !isalnum(lang[2])) {
|
||||
// It may be a two-letter language code; match it in our list.
|
||||
for (int i = 0; i < LI_COUNT; ++i) {
|
||||
const char *lang_code = language_codes[i];
|
||||
if (lang_code != NULL && strncasecmp(lang, lang_code, 2) == 0) {
|
||||
return (LanguageIndex)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lang = next;
|
||||
}
|
||||
|
||||
// Fall back to the C locale functions.
|
||||
setlocale(LC_ALL, "");
|
||||
lang = setlocale(LC_MESSAGES, NULL);
|
||||
|
||||
if (lang == NULL || lang[0] == 0 || strcmp(lang, "C") == 0) {
|
||||
// Try the LANG variable.
|
||||
lang = getenv("LANG");
|
||||
}
|
||||
|
||||
if (lang == NULL || strlen(lang) < 2 || isalnum(lang[2])) {
|
||||
// Couldn't extract a meaningful two-letter code.
|
||||
return LI_default;
|
||||
}
|
||||
|
||||
// It may be a two-letter language code; match it in our list.
|
||||
for (int i = 0; i < LI_COUNT; ++i) {
|
||||
const char *lang_code = language_codes[i];
|
||||
if (lang_code != NULL && strncasecmp(lang, lang_code, 2) == 0) {
|
||||
return (LanguageIndex)i;
|
||||
}
|
||||
}
|
||||
return LI_default;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
int WINAPI
|
||||
|
|
@ -107,6 +198,8 @@ wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdS
|
|||
return 1;
|
||||
}
|
||||
|
||||
li = detect_language();
|
||||
|
||||
wstring cert_filename (argv[0]);
|
||||
wstring cert_dir (argv[1]);
|
||||
LocalFree(argv);
|
||||
|
|
@ -126,6 +219,8 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
li = detect_language();
|
||||
|
||||
string cert_filename (argv[1]);
|
||||
string cert_dir (argv[2]);
|
||||
|
||||
|
|
@ -148,7 +243,7 @@ AuthDialog(const wstring &cert_filename, const wstring &cert_dir) :
|
|||
AuthDialog::
|
||||
AuthDialog(const string &cert_filename, const string &cert_dir) :
|
||||
#endif
|
||||
Fl_Window(435, 242, "New Panda3D Application"),
|
||||
Fl_Window(435, 242, new_application_title[li]),
|
||||
_cert_dir(cert_dir)
|
||||
{
|
||||
_view_cert_dialog = NULL;
|
||||
|
|
@ -315,12 +410,20 @@ read_cert_file(const string &cert_filename) {
|
|||
#endif // _WIN32
|
||||
|
||||
if (fp == NULL) {
|
||||
#ifdef _WIN32
|
||||
wcerr << L"Couldn't read " << cert_filename.c_str() << L"\n";
|
||||
#else
|
||||
cerr << "Couldn't read " << cert_filename.c_str() << "\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
_cert = PEM_read_X509(fp, NULL, NULL, (void *)"");
|
||||
if (_cert == NULL) {
|
||||
#ifdef _WIN32
|
||||
wcerr << L"Could not read certificate in " << cert_filename.c_str() << L".\n";
|
||||
#else
|
||||
cerr << "Could not read certificate in " << cert_filename.c_str() << ".\n";
|
||||
#endif
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
|
@ -510,19 +613,19 @@ layout() {
|
|||
short bx = (w() - nbuttons * BUTTON_WIDTH - (nbuttons - 1) * BUTTON_SPACE) / 2;
|
||||
|
||||
if (_verify_result == 0 && _cert != NULL) {
|
||||
Fl_Return_Button *run_button = new Fl_Return_Button(bx, next_y, BUTTON_WIDTH, 25, "Run");
|
||||
Fl_Return_Button *run_button = new Fl_Return_Button(bx, next_y, BUTTON_WIDTH, 25, run_title[li]);
|
||||
run_button->callback(this->run_clicked, this);
|
||||
bx += BUTTON_WIDTH + BUTTON_SPACE;
|
||||
}
|
||||
|
||||
if (_cert != NULL) {
|
||||
Fl_Button *view_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, "View Certificate");
|
||||
Fl_Button *view_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, show_cert_title[li]);
|
||||
view_button->callback(this->view_cert_clicked, this);
|
||||
bx += BUTTON_WIDTH + BUTTON_SPACE;
|
||||
}
|
||||
|
||||
Fl_Button *cancel_button;
|
||||
cancel_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, "Cancel");
|
||||
cancel_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, cancel_title[li]);
|
||||
cancel_button->callback(this->cancel_clicked, this);
|
||||
|
||||
next_y += 42;
|
||||
|
|
@ -542,12 +645,12 @@ void AuthDialog::
|
|||
get_text(char *header, size_t hlen, char *text, size_t tlen) {
|
||||
switch (_verify_result) {
|
||||
case -1:
|
||||
strncpy(header, "No signature!", hlen);
|
||||
strncpy(text, no_cert_text, tlen);
|
||||
strncpy(header, no_cert_title[li], hlen);
|
||||
strncpy(text, no_cert_text[li], tlen);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
snprintf(text, tlen, verified_cert_text, _friendly_name.c_str(),
|
||||
snprintf(text, tlen, verified_cert_text[li], _friendly_name.c_str(),
|
||||
_friendly_name.c_str(), _friendly_name.c_str());
|
||||
break;
|
||||
|
||||
|
|
@ -555,24 +658,24 @@ get_text(char *header, size_t hlen, char *text, size_t tlen) {
|
|||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||
case X509_V_ERR_CRL_NOT_YET_VALID:
|
||||
case X509_V_ERR_CRL_HAS_EXPIRED:
|
||||
strncpy(header, "Expired signature!", hlen);
|
||||
snprintf(text, tlen, expired_cert_text, _friendly_name.c_str());
|
||||
strncpy(header, expired_cert_title[li], hlen);
|
||||
snprintf(text, tlen, expired_cert_text[li], _friendly_name.c_str());
|
||||
break;
|
||||
|
||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
||||
strncpy(header, "Unverified signature!", hlen);
|
||||
snprintf(text, tlen, unknown_auth_cert_text);
|
||||
strncpy(header, unverified_cert_title[li], hlen);
|
||||
strncpy(text, unknown_auth_cert_text[li], tlen);
|
||||
break;
|
||||
|
||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
||||
strncpy(header, "Unverified signature!", hlen);
|
||||
strncpy(text, self_signed_cert_text, tlen);
|
||||
strncpy(header, unverified_cert_title[li], hlen);
|
||||
strncpy(text, self_signed_cert_text[li], tlen);
|
||||
break;
|
||||
|
||||
default:
|
||||
strncpy(header, "Unverified signature!", hlen);
|
||||
snprintf(text, tlen, generic_error_cert_text, _verify_result);
|
||||
strncpy(header, unverified_cert_title[li], hlen);
|
||||
snprintf(text, tlen, generic_error_cert_text[li], _verify_result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -583,7 +686,7 @@ get_text(char *header, size_t hlen, char *text, size_t tlen) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
ViewCertDialog::
|
||||
ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) :
|
||||
Fl_Window(600, 400, "View Certificate"),
|
||||
Fl_Window(600, 400, show_cert_title[li]),
|
||||
_auth_dialog(auth_dialog),
|
||||
_cert(cert)
|
||||
{
|
||||
|
|
@ -660,12 +763,12 @@ layout() {
|
|||
|
||||
short bx = (w() - BUTTON_WIDTH * 2 - BUTTON_SPACE) / 2;
|
||||
|
||||
Fl_Return_Button *run_button = new Fl_Return_Button(bx, 360, BUTTON_WIDTH, 25, "Run");
|
||||
Fl_Return_Button *run_button = new Fl_Return_Button(bx, 360, BUTTON_WIDTH, 25, run_title[li]);
|
||||
run_button->callback(this->run_clicked, this);
|
||||
|
||||
bx += BUTTON_WIDTH + BUTTON_SPACE;
|
||||
|
||||
Fl_Button *cancel_button = new Fl_Button(bx, 360, BUTTON_WIDTH, 25, "Cancel");
|
||||
Fl_Button *cancel_button = new Fl_Button(bx, 360, BUTTON_WIDTH, 25, cancel_title[li]);
|
||||
cancel_button->callback(this->cancel_clicked, this);
|
||||
|
||||
end();
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ private:
|
|||
X509 *_cert;
|
||||
STACK_OF(X509) *_stack;
|
||||
|
||||
char _header[32];
|
||||
char _text[512];
|
||||
char _text_clean[1024];
|
||||
char _header[64];
|
||||
char _text[1024];
|
||||
char _text_clean[2048];
|
||||
|
||||
string _friendly_name;
|
||||
int _verify_result;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,571 @@
|
|||
// Filename: p3dCert_strings.h
|
||||
// Created by: rdb (25Mar15)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "p3dCert_strings.h"
|
||||
|
||||
// Translations kindly provided by:
|
||||
// eng: drwr
|
||||
// nld: rdb
|
||||
// deu: Sebastian Hoffmann <TheCheapestPixels at googlemail dot com>
|
||||
// spa: Imanol Celaya <imanol at celaya dot me>
|
||||
// ita: Flavio Clava
|
||||
// rus: montreal
|
||||
|
||||
const char *language_codes[LI_COUNT] =
|
||||
{"en", "nl", "de", "es", "it", "eo", "ru"};
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318693%28v=vs.85%29.aspx
|
||||
const unsigned char language_ids[LI_COUNT] =
|
||||
{0x09, 0x13, 0x07, 0x0A, 0x10, 0x8F, 0x19};
|
||||
|
||||
const char *
|
||||
run_title[LI_COUNT] = {
|
||||
"Run",
|
||||
"Uitvoeren",
|
||||
"Starten",
|
||||
"Ejecutar",
|
||||
"Lancia",
|
||||
"Lan\304\211i",
|
||||
"\320\227\320\260\320\277\321\203\321\201\321\202\320\270\321\202\321\214",
|
||||
};
|
||||
|
||||
const char *
|
||||
cancel_title[LI_COUNT] = {
|
||||
"Cancel",
|
||||
"Annuleren",
|
||||
"Abbrechen",
|
||||
"Cancelar",
|
||||
"Cancella",
|
||||
"Nuligi",
|
||||
"\320\236\321\202\320\274\320\265\320\275\320\260",
|
||||
};
|
||||
|
||||
const char *
|
||||
show_cert_title[LI_COUNT] = {
|
||||
"Show Certificate",
|
||||
"Toon Certificaat",
|
||||
"Zertifikat anzeigen",
|
||||
"Mostrar certificado",
|
||||
"Mostra certificato",
|
||||
"Montri Ateston",
|
||||
"\320\237\320\276\320\272\320\260\320\267\320\260\321\202\321\214 \321\201"
|
||||
"\320\265\321\200\321\202\320\270\321\204\320\270\320\272\320\260\321\202",
|
||||
};
|
||||
|
||||
const char *
|
||||
new_application_title[LI_COUNT] = {
|
||||
"New Panda3D Application",
|
||||
"Nieuwe Panda3D Applicatie",
|
||||
"Neue Panda3D-Anwendung",
|
||||
"Nueva aplicaci\303\263n de Panda3D",
|
||||
"Nuova applicazione Panda3D",
|
||||
"Nova aplika\304\265o de Panda3D",
|
||||
"\320\235\320\276\320\262\320\276\320\265 Panda3D-\320\277\321\200\320\270"
|
||||
"\320\273\320\276\320\266\320\265\320\275\320\270\320\265",
|
||||
};
|
||||
|
||||
const char *
|
||||
no_cert_title[LI_COUNT] = {
|
||||
"No signature!",
|
||||
"Geen handtekening!",
|
||||
"Keine Signatur!",
|
||||
"Sin firma!",
|
||||
"Nessuna firma!",
|
||||
"Neniu subskribo!",
|
||||
"\320\235\320\265\321\202 \320\277\320\276\320\264\320\277\320\270\321\201"
|
||||
"\320\270!",
|
||||
};
|
||||
|
||||
const char *
|
||||
unverified_cert_title[LI_COUNT] = {
|
||||
"Unverified signature!",
|
||||
"Ongeverifieerde handtekening!",
|
||||
"Unbest\303\244tigte Signatur!",
|
||||
"Firma sin verificar!",
|
||||
"Firma non verificata!",
|
||||
"Nekontrolita subskribo!",
|
||||
"\320\235\320\265\320\277\321\200\320\276\320\262\320\265\321\200\320\265"
|
||||
"\320\275\320\275\320\260\321\217 \320\277\320\276\320\264\320\277\320\270"
|
||||
"\321\201\321\214!",
|
||||
};
|
||||
|
||||
const char *
|
||||
expired_cert_title[LI_COUNT] = {
|
||||
"Expired signature!",
|
||||
"Verlopen handtekening!",
|
||||
"Abgelaufene Signatur!",
|
||||
"Firma caducada!",
|
||||
"Firma scaduta!",
|
||||
"Eksvalidi\304\235inta subskribo!",
|
||||
"\320\241\321\200\320\276\320\272 \320\264\320\265\320\271\321\201\321\202"
|
||||
"\320\262\320\270\321\217 \320\277\320\276\320\264\320\277\320\270\321\201"
|
||||
"\320\270 \320\270\321\201\321\202\321\221\320\272!",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
self_signed_cert_text[LI_COUNT] = {
|
||||
// eng
|
||||
"This Panda3D application uses a self-signed certificate. "
|
||||
"This means the author's name can't be verified, and you have "
|
||||
"no way of knowing for sure who wrote it.\n"
|
||||
"\n"
|
||||
"We recommend you click Cancel to avoid running this application.",
|
||||
|
||||
// nld
|
||||
"Deze Panda3D applicatie gebruikt een zelf-getekend certificaat. "
|
||||
"Dit betekent dat de auteursnaam niet kan worden geverifieerd, en het "
|
||||
"niet zeker is of de applicatie te vertrouwen is.\n"
|
||||
"\n"
|
||||
"Het is aanbevolen om op Annuleren te klikken om de applicatie af te "
|
||||
"sluiten.",
|
||||
|
||||
// deu
|
||||
"Diese Panda3D-Anwendung benutzt ein selbst-signiertes Zertifikat. Dies "
|
||||
"bedeutet, dass weder der Name des Autors \303\274berpr\303\274ft werden "
|
||||
"kann, noch dass garantiert werden kann, dass tats\303\244chlich die "
|
||||
"angegebene Person diese Anwendung geschrieben hat.\n"
|
||||
"\n"
|
||||
"Wir empfehlen, dass Sie Abbrechen dr\303\274cken um diese Anwendung nicht "
|
||||
"auszuf\303\274hren.",
|
||||
|
||||
// spa
|
||||
"Esta aplicaci\303\263n de Panda3D usa un certificado autofirmado. "
|
||||
"Esto significa que el nombre del autor no puede ser verificado y no se "
|
||||
"puede conocer seguro quien la ha escrito.\n"
|
||||
"\n"
|
||||
"Se recomienda cancelar para evitar ejecutar esta aplicaci\303\263n.",
|
||||
|
||||
// ita
|
||||
"Questa applicazione Panda3D usa un certificato autofirmato. Ci\303\262 "
|
||||
"significa che il nome dell'autore non pu\303\262 essere verificato, e "
|
||||
"che non hai modo di assicurarti circa chi la abbia scritta.\n"
|
||||
"\n"
|
||||
"Raccomandiamo di cliccare su Cancella per evitare di lanciare questa "
|
||||
"applicazione.",
|
||||
|
||||
// epo
|
||||
"\304\210i tiu aplika\304\265o de Panda3D uzas memsubskribitan ateston. "
|
||||
"Tio signifas ke la nomo de la verkanto ne povas esti kontrolita, kaj vi "
|
||||
"ne havas certan scimanieron pri la vera verkanto de la aplika\304\265o.\n"
|
||||
"\n"
|
||||
"Ni rekomendas ke vi premas la butonon 'Nuligi' por eviti lan\304\211on de "
|
||||
"\304\211i tiu aplika\304\265o.",
|
||||
|
||||
// rus
|
||||
"\320\255\321\202\320\276 \320\277\321\200\320\270\320\273\320\276\320\266"
|
||||
"\320\265\320\275\320\270\320\265 \320\270\321\201\320\277\320\276\320\273"
|
||||
"\321\214\320\267\321\203\320\265\321\202 \321\201\320\260\320\274\320\276"
|
||||
"\320\267\320\260\320\262\320\265\321\200\320\265\320\275\320\275\321\213"
|
||||
"\320\271 \321\201\320\265\321\200\321\202\320\270\321\204\320\270\320\272"
|
||||
"\320\260\321\202. \320\255\321\202\320\276 \320\276\320\267\320\275"
|
||||
"\320\260\321\207\320\260\320\265\321\202, \321\207\321\202\320\276 "
|
||||
"\320\270\320\274\321\217 \320\260\320\262\321\202\320\276\321\200\320\260 "
|
||||
"\320\275\320\265 \320\274\320\276\320\266\320\265\321\202 \320\261\321\213"
|
||||
"\321\202\321\214 \320\277\320\276\320\264\321\202\320\262\320\265\320\266"
|
||||
"\320\264\320\265\320\275\320\276, \320\270 \320\262\321\213 \320\275"
|
||||
"\320\265 \320\274\320\276\320\266\320\265\321\202\320\265 \320\267\320\275"
|
||||
"\320\260\321\202\321\214, \320\272\321\202\320\276 \320\275\320\260"
|
||||
"\320\277\320\270\321\201\320\260\320\273 \321\215\321\202\320\276 \320\277"
|
||||
"\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.\n"
|
||||
"\n"
|
||||
"\320\234\321\213 \321\200\320\265\320\272\320\276\320\274\320\265\320\275"
|
||||
"\320\264\321\203\320\265\320\274 \320\262\320\260\320\274 \320\275\320\260"
|
||||
"\320\266\320\260\321\202\321\214 \"\320\236\321\202\320\274\320\265"
|
||||
"\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
|
||||
"\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
|
||||
"\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
|
||||
"\320\265.",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
unknown_auth_cert_text[LI_COUNT] = {
|
||||
"This Panda3D application has been signed, but we don't recognize "
|
||||
"the authority that verifies the signature. This means the author's "
|
||||
"name can't be verified, and you have no way of knowing "
|
||||
"for sure who wrote it.\n"
|
||||
"\n"
|
||||
"We recommend you click Cancel to avoid running this application.",
|
||||
|
||||
// nld
|
||||
"Deze Panda3D applicatie is ondertekend, maar de certificaatautoriteit "
|
||||
"die het certificaat heeft uitgegeven wordt niet herkend. Dit betekent "
|
||||
"dat de auteursnaam niet te vertrouwen is, en het niet zeker is wie de "
|
||||
"applicatie gemaakt heeft.\n"
|
||||
"\n"
|
||||
"Het is aanbevolen om op Annuleren te klikken om de applicatie af te "
|
||||
"sluiten.",
|
||||
|
||||
// deu
|
||||
"Diese Panda3D-Anwendung wurde signiert, aber die "
|
||||
"\303\234berpr\303\274fungsstelle wurde nicht anerkannt. Dies bedeutet, "
|
||||
"dass weder der Name des Autors \303\274berpr\303\274ft werden kann, noch "
|
||||
"dass garantiert werden kann, dass tats\303\244chlich die angegebene "
|
||||
"Person diese Anwendung geschrieben hat.\n"
|
||||
"\n"
|
||||
"Wir empfehlen, dass Sie Abbrechen dr\303\274cken um diese Anwendung nicht "
|
||||
"auszuf\303\274hren.",
|
||||
|
||||
// spa
|
||||
"Esta aplicaci\303\263n de Panda3D esta firmada, pero no reconocemos la "
|
||||
"autoridad que la verifica. Esto significa que el nombre del autor no "
|
||||
"puede ser verificado y no se puede conocer seguro quien la ha escrito.\n"
|
||||
"\n"
|
||||
"Se recomienda cancelar para evitar ejecutar esta aplicaci\303\263n.",
|
||||
|
||||
// ita
|
||||
"Questa applicazione Panda3D \303\250 stata firmata, ma non riconosciamo "
|
||||
"l'autorit\303\240 che verifica la firma. Ci\303\262 significa che il "
|
||||
"nome dell'autore non pu\303\262 essere verificato, e che non hai modo "
|
||||
"di assicurarti circa chi la abbia scritta.\n"
|
||||
"\n"
|
||||
"Raccomandiamo di cliccare su Cancella per evitare di lanciare questa "
|
||||
"applicazione.",
|
||||
|
||||
// epo
|
||||
"\304\210i tiu aplika\304\265o estas subskribita, sed ni ne rekonas "
|
||||
"la a\305\255toritaton, kiu kontrolas la subskribon. Tio signifas ke la "
|
||||
"nomo de la verkanto ne povas esti konfidata, kaj vi ne havas certan "
|
||||
"scimanieron pri la vera verkanto de la aplika\304\265o.\n"
|
||||
"\n"
|
||||
"Ni rekomendas ke vi premas la butonon 'Nuligi' por eviti lan\304\211on "
|
||||
"de \304\211i tiu aplika\304\265o.",
|
||||
|
||||
// rus
|
||||
"\320\243 \321\215\321\202\320\276\320\263\320\276 \320\277\321\200\320\270"
|
||||
"\320\273\320\276\320\266\320\265\320\275\320\270\321\217 \320\265\321\201"
|
||||
"\321\202\321\214 \320\277\320\276\320\264\320\277\320\270\321\201\321\214,"
|
||||
" \320\277\320\276 \320\272\320\276\321\202\320\276\321\200\320\276\320\271"
|
||||
" \320\274\321\213 \320\275\320\265 \320\274\320\276\320\266\320\265"
|
||||
"\320\274 \321\200\320\260\321\201\320\277\320\276\320\267\320\275\320\260"
|
||||
"\321\202\321\214 \320\262\320\273\320\260\320\264\320\265\320\273\321\214"
|
||||
"\321\206\320\260. \320\255\321\202\320\276 \320\276\320\267\320\275"
|
||||
"\320\260\321\207\320\260\320\265\321\202, \321\207\321\202\320\276 "
|
||||
"\320\270\320\274\321\217 \320\260\320\262\321\202\320\276\321\200\320\260 "
|
||||
"\320\275\320\265 \320\274\320\276\320\266\320\265\321\202 \320\261\321\213"
|
||||
"\321\202\321\214 \320\276\320\277\321\200\320\265\320\264\320\265\320\273"
|
||||
"\320\265\320\275\320\276, \320\270 \320\275\320\265\320\262\320\276"
|
||||
"\320\267\320\274\320\276\320\266\320\275\320\276 \321\202\320\276\321\207"
|
||||
"\320\275\320\276 \321\203\320\267\320\275\320\260\321\202\321\214, "
|
||||
"\320\272\321\202\320\276 \320\275\320\260\320\277\320\270\321\201\320\260"
|
||||
"\320\273 \321\215\321\202\320\276 \320\277\321\200\320\270\320\273\320\276"
|
||||
"\320\266\320\265\320\275\320\270\320\265.\n"
|
||||
"\n"
|
||||
"\320\234\321\213 \321\200\320\265\320\272\320\276\320\274\320\265\320\275"
|
||||
"\320\264\321\203\320\265\320\274 \320\262\320\260\320\274 \320\275\320\260"
|
||||
"\320\266\320\260\321\202\321\214 \"\320\236\321\202\320\274\320\265"
|
||||
"\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
|
||||
"\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
|
||||
"\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
|
||||
"\320\265.",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
verified_cert_text[LI_COUNT] = {
|
||||
// eng
|
||||
"This Panda3D application has been signed by %s. "
|
||||
"If you trust %s, then click the Run button below "
|
||||
"to run this application on your computer. This will also "
|
||||
"automatically approve this and any other applications signed by "
|
||||
"%s in the future.\n"
|
||||
"\n"
|
||||
"If you are unsure about this application, "
|
||||
"you should click Cancel instead.",
|
||||
|
||||
// nld
|
||||
"Deze Panda3D applicatie is ondertekend door %s. "
|
||||
"Als u %s vertrouwt, klik dan de onderstaande knop Uitvoeren om de applicatie "
|
||||
"op uw computer uit te voeren. Dit zal ook deze en andere door %s getekende "
|
||||
"applicaties in het vervolg toestaan.\n"
|
||||
"\n"
|
||||
"Als u niet zeker bent over deze applicatie is het aanbevolen om op "
|
||||
"Annuleren te klikken.",
|
||||
|
||||
// deu
|
||||
"Diese Panda3D-Anwendung wurde von %s signiert. Falls Sie %s vertrauen, "
|
||||
"dr\303\274cken Sie den Starten-Knopf, um diese Anwendung auszuf\303\274hren. "
|
||||
"Zudem werden in der Zukunft diese und alle anderen von %s signierten "
|
||||
"Anwendungen automatisch als vertrauensw\303\274rdig anerkannt.\n"
|
||||
"\n"
|
||||
"Falls Sie sich unsicher \303\274ber diese Anwendung sind, sollten Sie "
|
||||
"Abbrechen dr\303\274cken.",
|
||||
|
||||
// spa
|
||||
"Esta aplicaci\303\263n de Panda3D ha sido firmada por %s. Si se considera %s"
|
||||
"de confianza el bot\303\263n inferior ejecutar\303\241 la aplicaci\303\263n."
|
||||
"Esto validara esta y cualquier otra applizacion firmada por %s en el futuro.\n"
|
||||
"\n"
|
||||
"Si se duda de la aplicaci\303\263nse recomienda cancelar."
|
||||
|
||||
// ita
|
||||
"Questa applicazione Panda3D \303\250 stata firmata da %s. Se %s \303\250 "
|
||||
"un'entit\303\240 fidata, allora clicca il bottone Lancia sottostante per "
|
||||
"lanciare questa applicazione sul tuo computer. Inoltre, ci\303\262 "
|
||||
"approver\303\240 automaticamente questa e ogni altra applicazione "
|
||||
"firmata da %s in futuro.\n"
|
||||
"\n"
|
||||
"Se non sei sicuro circa questa applicazione, dovresti invece cliccare "
|
||||
"su Cancella.",
|
||||
|
||||
// epo
|
||||
"\304\210i tiu aplika\304\265o estas subskribita de %s. "
|
||||
"Se %s estas fidinda la\305\255 vi, premu la butonon 'Lan\304\211i' sube por "
|
||||
"lan\304\211i \304\211i tiun aplika\304\265on per via komputilo. Anka\305\255 "
|
||||
"tio a\305\255tomate estonece aprobos \304\211i tiun kaj alian ajn "
|
||||
"aplika\304\265on, kiu estas subskribita de %s.\n"
|
||||
"\n"
|
||||
"Se vi ne estas certa pri \304\211i tiu aplika\304\265o, "
|
||||
"vi anstata\305\255e povus premi la butonon 'Nuligi'.",
|
||||
|
||||
// rus
|
||||
"\320\255\321\202\320\276 \320\277\321\200\320\270\320\273\320\276\320\266"
|
||||
"\320\265\320\275\320\270\320\265 \320\277\320\276\320\264\320\277\320\270"
|
||||
"\321\201\320\260\320\275\320\276 %s. "
|
||||
"\320\225\321\201\320\273\320\270 \320\262\321\213 \320\264\320\276\320\262"
|
||||
"\320\265\321\200\321\217\320\265\321\202\320\265 %s, \320\275\320\260"
|
||||
"\320\266\320\274\320\270\321\202\320\265 \320\272\320\275\320\276\320\277"
|
||||
"\320\272\321\203 \"\320\227\320\260\320\277\321\203\321\201\321\202"
|
||||
"\320\270\321\202\321\214\" \320\262\320\275\320\270\320\267\321\203, "
|
||||
"\321\207\321\202\320\276\320\261\321\213 \320\267\320\260\320\277\321\203"
|
||||
"\321\201\321\202\320\270\321\202\321\214 \321\215\321\202\320\276 \320\277"
|
||||
"\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265 "
|
||||
"\320\275\320\260 \320\262\320\260\321\210\320\265\320\274 \320\272\320\276"
|
||||
"\320\274\320\277\321\214\321\216\321\202\320\265\321\200\320\265. \320\255"
|
||||
"\321\202\320\276 \321\202\320\260\320\272\320\266\320\265 \320\260\320\262"
|
||||
"\321\202\320\276\320\274\320\260\321\202\320\270\321\207\320\265\321\201"
|
||||
"\320\272\320\270 \320\277\320\276\320\264\321\202\320\262\320\265\321\200"
|
||||
"\320\264\320\270\321\202 \321\215\321\202\320\276 \320\270 \320\264"
|
||||
"\321\200\321\203\320\263\320\270\320\265 \320\277\321\200\320\270\320\273"
|
||||
"\320\276\320\266\320\265\320\275\320\270\321\217, \320\275\320\260\320\277"
|
||||
"\320\270\321\201\320\260\320\275\320\275\321\213\320\265 %s \320\262 "
|
||||
"\320\261\321\203\320\264\321\203\321\211\320\265\320\274.\n"
|
||||
"\n"
|
||||
"\320\225\321\201\320\273\320\270 \320\262\321\213 \320\275\320\265 "
|
||||
"\321\203\320\262\320\265\321\200\320\265\320\275\321\213 \320\262 \321\215"
|
||||
"\321\202\320\276\320\274 \320\277\321\200\320\270\320\273\320\276\320\266"
|
||||
"\320\265\320\275\320\270\320\270, \320\275\320\260\320\266\320\274\320\270"
|
||||
"\321\202\320\265 \320\272\320\275\320\276\320\277\320\272\321\203 \""
|
||||
"\320\236\321\202\320\274\320\265\320\275\320\260\".",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
expired_cert_text[LI_COUNT] = {
|
||||
// eng
|
||||
"This Panda3D application has been signed by %s, "
|
||||
"but the certificate has expired.\n"
|
||||
"\n"
|
||||
"You should check the current date set on your computer's clock "
|
||||
"to make sure it is correct.\n"
|
||||
"\n"
|
||||
"If your computer's date is correct, we recommend "
|
||||
"you click Cancel to avoid running this application.",
|
||||
|
||||
// nld
|
||||
"Deze Panda3D applicatie is ondertekend door %s, maar de geldigheidsdatum "
|
||||
"van het certificaat is verstreken.\n"
|
||||
"\n"
|
||||
"Controleer de datum op uw computerklok om te zorgen dat deze juist is "
|
||||
"ingesteld.\n"
|
||||
"\n"
|
||||
"Als de datum op uw computer juist is, is het aanbevolen om op Annuleren te "
|
||||
"klikken om de applicatie af te sluiten.",
|
||||
|
||||
// deu
|
||||
"Diese Anwendung wurde von %s signiert, aber das Zertifikat ist abgelaufen.\n"
|
||||
"\n"
|
||||
"Sie sollten die aktuelle Uhrzeit auf Ihrem Computer "
|
||||
"\303\274berpr\303\274fen, um sicherzugehen, dass sie korrekt ist.\n"
|
||||
"\n"
|
||||
"Falls die Uhrzeit auf Ihrem Computer korrekt ist, empfehlen wir Ihnen "
|
||||
"Abbrechen zu dr\303\274cken.",
|
||||
|
||||
// spa
|
||||
"Esta aplicaci\303\263n Panda3D ha sido firmada por %s pero el certificado ha"
|
||||
"caducado.\n"
|
||||
"\n"
|
||||
"Se recomienda comprobar la fecha del reloj.\n"
|
||||
"\n"
|
||||
"Si la fecha del reloj es correcta se recomienda cancelar.",
|
||||
|
||||
// ita
|
||||
"Questa applicazione Panda3D \303\250 stata firmata da %s, ma il "
|
||||
"certificato \303\250 scaduto.\n"
|
||||
"\n"
|
||||
"Dovresti controllare la data attuale impostata nell'orologio del tuo "
|
||||
"computer per assicurarti che sia corretta.\n"
|
||||
"\n"
|
||||
"Se la data del tuo computer \303\250 corretta, raccomandiamo di cliccare "
|
||||
"Cancella per evitare di lanciare questa applicazione."
|
||||
|
||||
// epo
|
||||
"\304\210i tiu aplika\304\265o de Panda3D estas subskribita de %s, "
|
||||
"sed la atesto eksvalidi\304\235is.\n"
|
||||
"\n"
|
||||
"Vi povus kontroli la aktualan daton, kiu estas agordata sur la horlo\304\235o de "
|
||||
"via komputilo por certigi ke \304\235i estas korekta.\n"
|
||||
"\n"
|
||||
"Se la dato de via komputilo estas korekta, ni rekomendas ke vi premas la "
|
||||
"butonon 'Nuligi' por eviti lan\304\211on de \304\211i tiu aplika\304\265o.",
|
||||
|
||||
// rus
|
||||
"\320\255\321\202\320\276 \320\277\321\200\320\270\320\273\320\276\320\266"
|
||||
"\320\265\320\275\320\270\320\265 \320\277\320\276\320\264\320\277\320\270"
|
||||
"\321\201\320\260\320\275\320\276 %s, \320\276\320\264\320\275\320\260"
|
||||
"\320\272\320\276 \321\201\321\200\320\276\320\272 \320\264\320\265\320\271"
|
||||
"\321\201\321\202\320\262\320\270\321\217 \321\201\320\265\321\200\321\202"
|
||||
"\320\270\321\204\320\270\320\272\320\260\321\202\320\260 \320\270\321\201"
|
||||
"\321\202\321\221\320\272.\n"
|
||||
"\n"
|
||||
"\320\237\321\200\320\276\320\262\320\265\321\200\321\214\321\202\320\265, "
|
||||
"\320\277\320\276\320\266\320\260\320\273\321\203\320\271\321\201\321\202"
|
||||
"\320\260, \320\264\320\260\321\202\321\203 \320\275\320\260 \320\262"
|
||||
"\320\260\321\210\320\265\320\274 \320\272\320\276\320\274\320\277\321\214"
|
||||
"\321\216\321\202\320\265\321\200\320\265.\n"
|
||||
"\n"
|
||||
"\320\225\321\201\320\273\320\270 \320\275\320\260 \320\262\320\260\321\210"
|
||||
"\320\265\320\274 \320\272\320\276\320\274\320\277\321\214\321\216\321\202"
|
||||
"\320\265\321\200\320\265 \321\203\321\201\321\202\320\260\320\275\320\276"
|
||||
"\320\262\320\273\320\265\320\275\320\276 \320\277\321\200\320\260\320\262"
|
||||
"\320\270\320\273\321\214\320\275\320\276\320\265 \320\262\321\200\320\265"
|
||||
"\320\274\321\217, \320\274\321\213 \321\200\320\265\320\272\320\276"
|
||||
"\320\274\320\265\320\275\320\264\321\203\320\265\320\274 \320\262\320\260"
|
||||
"\320\274 \320\275\320\260\320\266\320\260\321\202\321\214 \320\272\320\275"
|
||||
"\320\276\320\277\320\272\321\203 \"\320\236\321\202\320\274\320\265"
|
||||
"\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
|
||||
"\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
|
||||
"\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
|
||||
"\320\265.",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
generic_error_cert_text[LI_COUNT] = {
|
||||
// eng
|
||||
"This Panda3D application has been signed, but there is a problem "
|
||||
"with the certificate (OpenSSL error code %d).\n"
|
||||
"\n"
|
||||
"We recommend you click Cancel to avoid running this application.",
|
||||
|
||||
// nld
|
||||
"Deze Panda3D applicatie is ondertekend, maar er is een probleem "
|
||||
"met het certificaat opgetreden (OpenSSL foutcode %d).\n"
|
||||
"\n"
|
||||
"Het is aanbevolen om op Annuleren te klikken om de applicatie af te "
|
||||
"sluiten.",
|
||||
|
||||
// deu
|
||||
"Diese Panda3D-Anwendung wurde signiert, aber es gibt ein Problem mit "
|
||||
"dem Zertifikat (OpenSSL Fehlercode %d).\n"
|
||||
"\n"
|
||||
"Wir empfehlen, dass Sie Abbrechen dr\303\274cken um diese Anwendung nicht "
|
||||
"auszuf\303\274hren.",
|
||||
|
||||
// spa
|
||||
"Esta aplicaci\303\263n de Panda3D esta firmada pero hay un problema con el "
|
||||
"certificado (Error de OpenSSL %d).\n"
|
||||
"\n"
|
||||
"Se recomienda cancelar para evitar ejecutar esta aplicaci\303\263n.",
|
||||
|
||||
// ita
|
||||
"Questa applicazione Panda3D \303\250 stata firmata, ma c'\303\250 un "
|
||||
"problema col certificato (codice di errore OpenSSL %s).\n"
|
||||
"\n"
|
||||
"Raccomandiamo di cliccare su Cancella per evitare di lanciare questa "
|
||||
"applicazione.",
|
||||
|
||||
// epo
|
||||
"\304\210i tiu aplika\304\265o de Panda3D estas subskribita, sed la "
|
||||
"atesto havas problemon (OpenSSL erarkodo %d).\n"
|
||||
"\n"
|
||||
"Ni rekomendas ke vi premas la butonon 'Nuligi' por eviti lan\304\211on "
|
||||
"de \304\211i tiu aplika\304\265o.",
|
||||
|
||||
// rus
|
||||
"\320\243 \321\215\321\202\320\276\320\263\320\276 \320\277\321\200\320\270"
|
||||
"\320\273\320\276\320\266\320\265\320\275\320\270\321\217 \320\265\321\201"
|
||||
"\321\202\321\214 \320\277\320\276\320\264\320\277\320\270\321\201\321\214,"
|
||||
" \320\275\320\276 \320\262\320\276\320\267\320\275\320\270\320\272\320\273"
|
||||
"\320\260 \320\277\321\200\320\276\320\261\320\273\320\265\320\274\320\260 "
|
||||
"\321\201 \321\201\320\265\321\200\321\202\320\270\321\204\320\270\320\272"
|
||||
"\320\260\321\202\320\276\320\274 (\320\232\320\276\320\264 \320\276"
|
||||
"\321\210\320\270\320\261\320\272\320\270 OpenSSL %d).\n"
|
||||
"\n"
|
||||
"\320\234\321\213 \321\200\320\265\320\272\320\276\320\274\320\265\320\275"
|
||||
"\320\264\321\203\320\265\320\274 \320\262\320\260\320\274 \320\275\320\260"
|
||||
"\320\266\320\260\321\202\321\214 \"\320\236\321\202\320\274\320\265"
|
||||
"\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
|
||||
"\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
|
||||
"\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
|
||||
"\320\265.",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
no_cert_text[LI_COUNT] = {
|
||||
"This Panda3D application has not been signed. This means you have "
|
||||
"no way of knowing for sure who wrote it.\n"
|
||||
"\n"
|
||||
"Click Cancel to avoid running this application.",
|
||||
|
||||
// nld
|
||||
"Deze Panda3D applicatie is niet ondertekend. Dit betekent dat het niet "
|
||||
"mogelijk is om de auteur te verifi\303\253ren.\n"
|
||||
"\n"
|
||||
"Klik op Annuleren om de applicatie af te sluiten.",
|
||||
|
||||
// deu
|
||||
"Diese Panda3D-Anwendung wurde nicht signiert. Es gibt keine "
|
||||
"M\303\266glichkeit festzustellen, wer diese entwickelt hat.\n"
|
||||
"\n"
|
||||
"Dr\303\274cken Sie Abbrechen, um diese Anwendung nicht auszuf\303\274hren.",
|
||||
|
||||
// spa
|
||||
"Esta aplicaci\303\263n de Panda3D no esta firmada, no hay forma de conocer "
|
||||
"quien la ha escrito.\n"
|
||||
"\n"
|
||||
"Cancelar para evitar ejecutar la aplicaci\303\263n.",
|
||||
|
||||
// ita
|
||||
"Questa applicazione Panda3D non \303\250 stata firmata. Ci\303\262 "
|
||||
"significa che non hai modo di assicurarti circa chi la abbia scritta.\n"
|
||||
"\n"
|
||||
"Clicca Cancella per evitare di lanciare questa applicazione.",
|
||||
|
||||
// epo
|
||||
"\304\210i tiu aplika\304\265o de Panda3D ne estas subskribita. Tio "
|
||||
"signifas ke vi ne havas certan scimanieron pri la vera verkanto de "
|
||||
"la aplika\304\265o.\n"
|
||||
"\n"
|
||||
"Premu la butonon 'Nuligi' por eviti lan\304\211on de \304\211i tiu "
|
||||
"aplika\304\265o.",
|
||||
|
||||
// rus
|
||||
"\320\243 \321\215\321\202\320\276\320\263\320\276 \320\277\321\200\320\270"
|
||||
"\320\273\320\276\320\266\320\265\320\275\320\270\321\217 \320\275\320\265"
|
||||
"\321\202 \320\277\320\276\320\264\320\277\320\270\321\201\320\270. "
|
||||
"\320\255\321\202\320\276 \320\276\320\267\320\275\320\260\321\207\320\260"
|
||||
"\320\265\321\202, \321\207\321\202\320\276 \320\262\321\213 \320\275"
|
||||
"\320\265 \320\274\320\276\320\266\320\265\321\202\320\265 \320\267\320\275"
|
||||
"\320\260\321\202\321\214, \320\272\321\202\320\276 \320\265\320\263"
|
||||
"\320\276 \320\275\320\260\320\277\320\270\321\201\320\260\320\273.\n"
|
||||
"\n"
|
||||
"\320\235\320\260\320\266\320\274\320\270\321\202\320\265 \"\320\236"
|
||||
"\321\202\320\274\320\265\320\275\320\260\", \321\207\321\202\320\276"
|
||||
"\320\261\321\213 \320\275\320\265 \320\267\320\260\320\277\321\203\321\201"
|
||||
"\320\272\320\260\321\202\321\214 \320\277\321\200\320\270\320\273\320\276"
|
||||
"\320\266\320\265\320\275\320\270\320\265.",
|
||||
};
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Filename: p3dCert_strings.h
|
||||
// Created by: rdb (25Mar15)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum LanguageIndex {
|
||||
LI_en, // English
|
||||
LI_nl, // Dutch
|
||||
LI_de, // German
|
||||
LI_es, // Spanish
|
||||
LI_it, // Italian
|
||||
LI_eo, // Esperanto
|
||||
LI_ru, // Russian
|
||||
LI_COUNT,
|
||||
|
||||
LI_default = LI_en
|
||||
};
|
||||
|
||||
extern const char *language_codes[LI_COUNT];
|
||||
extern const unsigned char language_ids[LI_COUNT];
|
||||
|
||||
extern const char *run_title[LI_COUNT];
|
||||
extern const char *cancel_title[LI_COUNT];
|
||||
extern const char *show_cert_title[LI_COUNT];
|
||||
|
||||
extern const char *new_application_title[LI_COUNT];
|
||||
extern const char *no_cert_title[LI_COUNT];
|
||||
extern const char *unverified_cert_title[LI_COUNT];
|
||||
extern const char *expired_cert_title[LI_COUNT];
|
||||
|
||||
extern const char *self_signed_cert_text[LI_COUNT];
|
||||
extern const char *unknown_auth_cert_text[LI_COUNT];
|
||||
extern const char *verified_cert_text[LI_COUNT];
|
||||
extern const char *expired_cert_text[LI_COUNT];
|
||||
extern const char *generic_error_cert_text[LI_COUNT];
|
||||
extern const char *no_cert_text[LI_COUNT];
|
||||
|
|
@ -1564,7 +1564,7 @@ uninstall_packages() {
|
|||
if (inst_mgr->get_verify_contents() != P3D_VC_never) {
|
||||
string start_dir_suffix = get_start_dir_suffix();
|
||||
if (!start_dir_suffix.empty()) {
|
||||
string start_dir = inst_mgr->get_root_dir() + "/start" + start_dir_suffix;
|
||||
string start_dir = inst_mgr->get_start_dir() + start_dir_suffix;
|
||||
nout << "Cleaning up start directory " << start_dir << "\n";
|
||||
inst_mgr->delete_directory_recursively(start_dir);
|
||||
}
|
||||
|
|
@ -2769,6 +2769,7 @@ make_splash_window() {
|
|||
int r, g, b;
|
||||
if (parse_color(r, g, b, _fparams.lookup_token("bgcolor"))) {
|
||||
_splash_window->set_bgcolor(r, g, b);
|
||||
_splash_window->set_bar_bgcolor(r, g, b);
|
||||
} else {
|
||||
nout << "parse failure on bgcolor " << _fparams.lookup_token("bgcolor") << "\n";
|
||||
}
|
||||
|
|
@ -2781,11 +2782,98 @@ make_splash_window() {
|
|||
nout << "parse failure on barcolor " << _fparams.lookup_token("barcolor") << "\n";
|
||||
}
|
||||
}
|
||||
if (_fparams.has_token("bar_bgcolor")) {
|
||||
int r, g, b;
|
||||
if (parse_color(r, g, b, _fparams.lookup_token("bar_bgcolor"))) {
|
||||
_splash_window->set_bar_bgcolor(r, g, b);
|
||||
} else {
|
||||
nout << "parse failure on bar_bgcolor " << _fparams.lookup_token("bar_bgcolor") << "\n";
|
||||
}
|
||||
}
|
||||
if (_fparams.has_token("bar_border")) {
|
||||
int border = _fparams.lookup_token_int("bar_border");
|
||||
_splash_window->set_bar_border(border);
|
||||
}
|
||||
if (_fparams.has_token("bar_bottom")) {
|
||||
int bottom = _fparams.lookup_token_int("bar_bottom");
|
||||
_splash_window->set_bar_bottom(bottom);
|
||||
}
|
||||
if (_fparams.has_token("bar_width")) {
|
||||
string bar_width = _fparams.lookup_token("bar_width");
|
||||
char *endptr;
|
||||
long width = strtol(bar_width.c_str(), &endptr, 10);
|
||||
bool percent = false;
|
||||
|
||||
if (*endptr == '%') {
|
||||
percent = true;
|
||||
++endptr;
|
||||
}
|
||||
if (*endptr == '\0' && width >= 0 && width < 65536) {
|
||||
_splash_window->set_bar_width((int)width, percent);
|
||||
} else {
|
||||
nout << "parse failure on bar_width " << bar_width << "\n";
|
||||
}
|
||||
}
|
||||
if (_fparams.has_token("bar_height")) {
|
||||
string bar_height = _fparams.lookup_token("bar_height");
|
||||
char *endptr;
|
||||
long height = strtol(bar_height.c_str(), &endptr, 10);
|
||||
bool percent = false;
|
||||
|
||||
if (*endptr == '%') {
|
||||
percent = true;
|
||||
++endptr;
|
||||
}
|
||||
if (*endptr == '\0' && height >= 0 && height < 65536) {
|
||||
_splash_window->set_bar_height((int)height, percent);
|
||||
} else {
|
||||
nout << "parse failure on bar_height " << bar_height << "\n";
|
||||
}
|
||||
}
|
||||
if (_fparams.has_token("font_family")) {
|
||||
string family = _fparams.lookup_token("font_family");
|
||||
_splash_window->set_font_family(family);
|
||||
}
|
||||
if (_fparams.has_token("font_size")) {
|
||||
int size = _fparams.lookup_token_int("font_size");
|
||||
_splash_window->set_font_size(size);
|
||||
}
|
||||
if (_fparams.has_token("font_style")) {
|
||||
string style = _fparams.lookup_token("font_style");
|
||||
|
||||
if (style == "normal") {
|
||||
_splash_window->set_font_style(P3DSplashWindow::FS_normal);
|
||||
} else if (style == "oblique") {
|
||||
_splash_window->set_font_style(P3DSplashWindow::FS_oblique);
|
||||
} else if (style == "italic") {
|
||||
_splash_window->set_font_style(P3DSplashWindow::FS_italic);
|
||||
} else {
|
||||
nout << "parse_failure on font_style " << style << "\n";
|
||||
}
|
||||
}
|
||||
if (_fparams.has_token("font_weight")) {
|
||||
string weight = _fparams.lookup_token("font_weight");
|
||||
|
||||
if (weight == "normal") {
|
||||
_splash_window->set_font_weight(400);
|
||||
} else if (weight == "bold") {
|
||||
_splash_window->set_font_weight(700);
|
||||
} else if (weight == "bolder") {
|
||||
_splash_window->set_font_weight(700);
|
||||
} else if (weight == "lighter") {
|
||||
_splash_window->set_font_weight(100);
|
||||
} else if (weight.size() == 3 &&
|
||||
weight[0] >= '1' && weight[0] <= '9' &&
|
||||
weight[1] == '0' && weight[2] == '0') {
|
||||
_splash_window->set_font_weight(((int)weight[0] - 48) * 100);
|
||||
} else {
|
||||
nout << "parse_failure on font_weight " << weight << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_splash_window->set_wparams(_wparams);
|
||||
_splash_window->set_install_label(_install_label);
|
||||
|
||||
|
||||
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
|
||||
// Go get the required images.
|
||||
|
|
|
|||
|
|
@ -111,6 +111,18 @@ get_root_dir() const {
|
|||
return _root_dir;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::get_start_dir
|
||||
// Access: Public
|
||||
// Description: Returns the directory that the .p3d file should be
|
||||
// mounted to and run from. This is usually the
|
||||
// "start" subdirectory of the root_dir.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline const string &P3DInstanceManager::
|
||||
get_start_dir() const {
|
||||
return _start_dir;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::get_platform
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -201,7 +201,8 @@ initialize(int api_version, const string &contents_filename,
|
|||
const string &platform, const string &log_directory,
|
||||
const string &log_basename, bool trusted_environment,
|
||||
bool console_environment,
|
||||
const string &root_dir, const string &host_dir) {
|
||||
const string &root_dir, const string &host_dir,
|
||||
const string &start_dir) {
|
||||
_api_version = api_version;
|
||||
_host_url = host_url;
|
||||
_verify_contents = verify_contents;
|
||||
|
|
@ -258,14 +259,22 @@ initialize(int api_version, const string &contents_filename,
|
|||
|
||||
// TODO: Linux multiplatform support. Just add the
|
||||
// appropriate platform strings to _supported_platforms.
|
||||
} else {
|
||||
nout << "Platform string was set by plugin to " << _platform << "\n";
|
||||
}
|
||||
|
||||
if (_supported_platforms.empty()) {
|
||||
// Hack for older plug-ins, which should still remain compatible with
|
||||
// newer versions of the runtime distribution.
|
||||
if (_platform == "win32") {
|
||||
_supported_platforms.push_back("win_i386");
|
||||
}
|
||||
|
||||
// We always support at least the specific platform on which we're
|
||||
// running.
|
||||
_supported_platforms.push_back(_platform);
|
||||
}
|
||||
|
||||
|
||||
#ifdef P3D_PLUGIN_LOG_DIRECTORY
|
||||
if (_log_directory.empty()) {
|
||||
_log_directory = P3D_PLUGIN_LOG_DIRECTORY;
|
||||
|
|
@ -290,12 +299,18 @@ initialize(int api_version, const string &contents_filename,
|
|||
} else {
|
||||
_root_dir = root_dir;
|
||||
}
|
||||
|
||||
|
||||
_host_dir = host_dir;
|
||||
|
||||
if (start_dir.empty()) {
|
||||
_start_dir = _root_dir + "/start";
|
||||
} else {
|
||||
_start_dir = start_dir;
|
||||
}
|
||||
|
||||
// Allow the caller (e.g. panda3d.exe) to specify a log directory.
|
||||
// Or, allow the developer to compile one in.
|
||||
|
||||
//
|
||||
// Failing that, we write logfiles to Panda3D/log.
|
||||
if (_log_directory.empty()) {
|
||||
_log_directory = _root_dir + "/log";
|
||||
|
|
@ -1507,8 +1522,10 @@ create_runtime_environment() {
|
|||
|
||||
// Make the certificate directory.
|
||||
_certs_dir = _root_dir + "/certs";
|
||||
if (!mkdir_complete(_certs_dir, nout)) {
|
||||
nout << "Couldn't mkdir " << _certs_dir << "\n";
|
||||
if (!get_trusted_environment()) {
|
||||
if (!mkdir_complete(_certs_dir, nout)) {
|
||||
nout << "Couldn't mkdir " << _certs_dir << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_created_runtime_environment = true;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ public:
|
|||
bool trusted_environment,
|
||||
bool console_environment,
|
||||
const string &root_dir = "",
|
||||
const string &host_dir = "");
|
||||
const string &host_dir = "",
|
||||
const string &start_dir = "");
|
||||
|
||||
inline bool is_initialized() const;
|
||||
inline void reconsider_runtime_environment();
|
||||
|
|
@ -69,6 +70,7 @@ public:
|
|||
inline int get_api_version() const;
|
||||
inline const string &get_host_url() const;
|
||||
inline const string &get_root_dir() const;
|
||||
inline const string &get_start_dir() const;
|
||||
inline const string &get_platform() const;
|
||||
inline const string &get_temp_directory() const;
|
||||
inline const string &get_log_directory() const;
|
||||
|
|
@ -173,6 +175,7 @@ private:
|
|||
string _host_url;
|
||||
string _root_dir;
|
||||
string _host_dir;
|
||||
string _start_dir;
|
||||
string _certs_dir;
|
||||
P3D_verify_contents _verify_contents;
|
||||
string _platform;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ P3DOsxSplashWindow::
|
|||
P3DOsxSplashWindow(P3DInstance *inst, bool make_visible) :
|
||||
P3DSplashWindow(inst, make_visible)
|
||||
{
|
||||
_font_attribs = NULL;
|
||||
_install_progress = 0;
|
||||
_progress_known = true;
|
||||
_received_data = 0;
|
||||
|
|
@ -59,6 +60,9 @@ P3DOsxSplashWindow::
|
|||
DisposeWindow(_toplevel_window);
|
||||
_toplevel_window = NULL;
|
||||
}
|
||||
if (_font_attribs != NULL) {
|
||||
CFRelease(_font_attribs);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -123,6 +127,41 @@ set_wparams(const P3DWindowParams &wparams) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the attributes of the font we're going to use.
|
||||
int symbolic = 0;
|
||||
if (_font_style != FS_normal) {
|
||||
symbolic |= kCTFontItalicTrait;
|
||||
}
|
||||
if (_font_weight > 500) {
|
||||
symbolic |= kCTFontBoldTrait;
|
||||
}
|
||||
CFNumberRef symbolic_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &symbolic);
|
||||
|
||||
CFStringRef traits_keys[1] = { kCTFontSymbolicTrait };
|
||||
CFTypeRef traits_values[1] = { symbolic_ref };
|
||||
CFDictionaryRef traits = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&traits_keys, (const void **)&traits_values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
CFStringRef family = CFStringCreateWithCString(NULL, _font_family.c_str(), kCFStringEncodingUTF8);
|
||||
|
||||
CFStringRef attribs_keys[2] = { kCTFontFamilyNameAttribute, kCTFontTraitsAttribute };
|
||||
CFTypeRef attribs_values[2] = { family, traits };
|
||||
CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&attribs_keys, (const void **)&attribs_values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
// Create the font object.
|
||||
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes(attribs);
|
||||
CTFontRef font = CTFontCreateWithFontDescriptor(font_desc, _font_size, NULL);
|
||||
|
||||
CFStringRef keys[1] = { kCTFontAttributeName };
|
||||
CFTypeRef values[1] = { font };
|
||||
_font_attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
CFRelease(font);
|
||||
CFRelease(font_desc);
|
||||
CFRelease(attribs);
|
||||
CFRelease(traits);
|
||||
CFRelease(family);
|
||||
CFRelease(symbolic_ref);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -171,6 +210,9 @@ set_image_filename(const string &image_filename, ImagePlacement image_placement)
|
|||
case IP_button_click:
|
||||
load_image(_button_click_image, image_filename);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
refresh();
|
||||
|
|
@ -333,10 +375,8 @@ paint_window_osx_cgcontext(CGContextRef context) {
|
|||
CGColorRef bg = CGColorCreate(rgb_space, bg_components);
|
||||
|
||||
CGRect region = { { 0, 0 }, { _win_width, _win_height } };
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetFillColorWithColor(context, bg);
|
||||
CGContextAddRect(context, region);
|
||||
CGContextFillPath(context);
|
||||
CGContextFillRect(context, region);
|
||||
|
||||
CGColorRelease(bg);
|
||||
CGColorSpaceRelease(rgb_space);
|
||||
|
|
@ -445,8 +485,6 @@ handle_event_osx_event_record(const P3D_event_data &event) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DOsxSplashWindow::
|
||||
handle_event_osx_cocoa(const P3D_event_data &event) {
|
||||
bool retval = false;
|
||||
|
||||
assert(event._event_type == P3D_ET_osx_cocoa);
|
||||
const P3DCocoaEvent &ce = event._event._osx_cocoa._event;
|
||||
|
||||
|
|
@ -455,33 +493,31 @@ handle_event_osx_cocoa(const P3D_event_data &event) {
|
|||
if (_visible) {
|
||||
CGContextRef context = ce.data.draw.context;
|
||||
paint_window_osx_cgcontext(context);
|
||||
retval = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case P3DCocoaEventMouseDown:
|
||||
set_mouse_data((int)ce.data.mouse.pluginX, (int)ce.data.mouse.pluginY, true);
|
||||
retval = true;
|
||||
break;
|
||||
return true;
|
||||
|
||||
case P3DCocoaEventMouseUp:
|
||||
set_mouse_data((int)ce.data.mouse.pluginX, (int)ce.data.mouse.pluginY, false);
|
||||
retval = true;
|
||||
break;
|
||||
return true;
|
||||
|
||||
case P3DCocoaEventMouseMoved:
|
||||
case P3DCocoaEventMouseDragged:
|
||||
set_mouse_data((int)ce.data.mouse.pluginX, (int)ce.data.mouse.pluginY, _mouse_down);
|
||||
retval = true;
|
||||
break;
|
||||
return true;
|
||||
|
||||
case P3DCocoaEventFocusChanged:
|
||||
_mouse_active = (ce.data.focus.hasFocus != 0);
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
return retval;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -612,42 +648,33 @@ paint_image(CGContextRef context, const OsxImageData &image) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void P3DOsxSplashWindow::
|
||||
paint_progress_bar(CGContextRef context) {
|
||||
// Get some colors we'll need. We can't just use
|
||||
// CGColorGetConstantColor(), since that requires 10.5.
|
||||
CGFloat fg_components[] = { _fgcolor_r / 255.0f, _fgcolor_g / 255.0f, _fgcolor_b / 255.0f, 1 };
|
||||
CGFloat bg_components[] = { _bgcolor_r / 255.0f, _bgcolor_g / 255.0f, _bgcolor_b / 255.0f, 1 };
|
||||
CGFloat bar_components[] = { _barcolor_r / 255.0f, _barcolor_g / 255.0f, _barcolor_b / 255.0f, 1 };
|
||||
CGFloat bar_bg_components[] = { _bar_bgcolor_r / 255.0f, _bar_bgcolor_g / 255.0f, _bar_bgcolor_b / 255.0f, 1 };
|
||||
CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
|
||||
CGColorRef fg = CGColorCreate(rgb_space, fg_components);
|
||||
CGColorRef bg = CGColorCreate(rgb_space, bg_components);
|
||||
CGColorRef bar = CGColorCreate(rgb_space, bar_components);
|
||||
CGColorRef bar_bg = CGColorCreate(rgb_space, bar_bg_components);
|
||||
|
||||
// Get the proper placement for the progress bar.
|
||||
int bar_x, bar_y, bar_width, bar_height;
|
||||
get_bar_placement(bar_x, bar_y, bar_width, bar_height);
|
||||
|
||||
// We offset the bar by half a pixel, so we'll be drawing the
|
||||
// one-pixel line through the middle of a pixel, and it won't try to
|
||||
// antialias itself into a half-black two-pixel line.
|
||||
float bar_xf = bar_x + 0.5;
|
||||
float bar_yf = bar_y - 0.5;
|
||||
|
||||
CGRect bar_rect = { { bar_xf, bar_yf }, { bar_width, bar_height } };
|
||||
CGRect bar_rect = { { bar_x, bar_y }, { bar_width, bar_height } };
|
||||
|
||||
// Clear the entire progress bar to white (or the background color).
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetFillColorWithColor(context, bg);
|
||||
CGContextAddRect(context, bar_rect);
|
||||
CGContextFillPath(context);
|
||||
CGContextSetFillColorWithColor(context, bar_bg);
|
||||
CGContextFillRect(context, bar_rect);
|
||||
|
||||
// Draw the interior of the progress bar in blue (or the bar color).
|
||||
if (_progress_known) {
|
||||
int progress_width = (int)(bar_width * _install_progress + 0.5);
|
||||
if (progress_width != 0) {
|
||||
CGRect prog = { { bar_xf, bar_yf }, { progress_width, bar_height } };
|
||||
CGContextBeginPath(context);
|
||||
CGRect prog = { { bar_x, bar_y }, { progress_width, bar_height } };
|
||||
CGContextSetFillColorWithColor(context, bar);
|
||||
CGContextAddRect(context, prog);
|
||||
CGContextFillPath(context);
|
||||
CGContextFillRect(context, prog);
|
||||
}
|
||||
} else {
|
||||
// Progress is unknown. Draw a moving block, not a progress bar
|
||||
|
|
@ -660,57 +687,58 @@ paint_progress_bar(CGContextRef context) {
|
|||
progress = block_travel * 2 - progress;
|
||||
}
|
||||
|
||||
CGRect prog = { { bar_xf + progress, bar_yf }, { block_width, bar_height } };
|
||||
CGContextBeginPath(context);
|
||||
CGRect prog = { { bar_x + progress, bar_y }, { block_width, bar_height } };
|
||||
CGContextSetFillColorWithColor(context, bar);
|
||||
CGContextAddRect(context, prog);
|
||||
CGContextFillPath(context);
|
||||
CGContextFillRect(context, prog);
|
||||
}
|
||||
|
||||
|
||||
// Draw the black stroke around the progress bar.
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetLineWidth(context, 1);
|
||||
CGContextSetStrokeColorWithColor(context, fg);
|
||||
CGContextAddRect(context, bar_rect);
|
||||
CGContextStrokePath(context);
|
||||
if (_bar_border > 0) {
|
||||
// We offset the border by half a pixel, so we'll be drawing the
|
||||
// one-pixel line through the middle of a pixel, and it won't try to
|
||||
// antialias itself into a half-black two-pixel line.
|
||||
CGRect border_rect = { { bar_x - 0.5, bar_y - 0.5 },
|
||||
{ bar_width + 1, bar_height + 1 } };
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetLineWidth(context, 1);
|
||||
CGContextSetStrokeColorWithColor(context, fg);
|
||||
|
||||
for (int i = 0; i < _bar_border; ++i) {
|
||||
CGContextAddRect(context, border_rect);
|
||||
border_rect.origin.x -= 1;
|
||||
border_rect.origin.y -= 1;
|
||||
border_rect.size.width += 2;
|
||||
border_rect.size.height += 2;
|
||||
}
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
if (!_install_label.empty()) {
|
||||
// Now draw the install_label right above it.
|
||||
|
||||
// Need to invert the text so it won't be upside-down.
|
||||
CGAffineTransform text_xform = CGAffineTransformMakeScale(1, -1);
|
||||
CGContextSetTextMatrix(context, text_xform);
|
||||
|
||||
// Choose a suitable font.
|
||||
float text_height = 15.0;
|
||||
CGContextSelectFont(context, "Helvetica", text_height, kCGEncodingMacRoman);
|
||||
// Now draw the install_label right above it.
|
||||
CFStringRef string = CFStringCreateWithCString(NULL, _install_label.c_str(), kCFStringEncodingUTF8);
|
||||
CFAttributedStringRef attr_string = CFAttributedStringCreate(NULL, string, _font_attribs);
|
||||
CTLineRef line = CTLineCreateWithAttributedString(attr_string);
|
||||
|
||||
// Measure the text, for centering.
|
||||
CGContextSetTextPosition(context, 0, 0);
|
||||
CGContextSetTextDrawingMode(context, kCGTextInvisible);
|
||||
CGContextShowText(context, _install_label.data(), _install_label.length());
|
||||
CGPoint end_point = CGContextGetTextPosition(context);
|
||||
float text_width = end_point.x;
|
||||
|
||||
int text_x = (int)(_win_width - text_width) / 2;
|
||||
int text_y = (int)(bar_y - text_height * 1.5);
|
||||
|
||||
// Clear the rectangle behind the text to bg.
|
||||
CGRect text_rect = { { text_x - 2, text_y - 2 }, { text_width + 4, text_height + 4 } };
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextAddRect(context, text_rect);
|
||||
CGContextSetFillColorWithColor(context, bg);
|
||||
CGContextFillPath(context);
|
||||
// Determine the placement based on the size of the text.
|
||||
CGRect bounds = CTLineGetImageBounds(line, context);
|
||||
float text_x = (_win_width - bounds.size.width) / 2.0f - bounds.origin.x;
|
||||
float text_y = bar_y + bounds.origin.y - 4 - _bar_border;
|
||||
|
||||
// And finally, draw the text.
|
||||
CGContextSetTextDrawingMode(context, kCGTextFill);
|
||||
CGContextSetFillColorWithColor(context, fg);
|
||||
CGContextSetTextPosition(context, text_x, text_y);
|
||||
CTLineDraw(line, context);
|
||||
|
||||
CGContextShowTextAtPoint(context, text_x, text_y + text_height,
|
||||
_install_label.data(), _install_label.length());
|
||||
CFRelease(line);
|
||||
CFRelease(attr_string);
|
||||
CFRelease(string);
|
||||
}
|
||||
|
||||
CGColorRelease(bar_bg);
|
||||
CGColorRelease(bar);
|
||||
CGColorRelease(bg);
|
||||
CGColorRelease(fg);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ private:
|
|||
OsxImageData _button_rollover_image;
|
||||
OsxImageData _button_click_image;
|
||||
|
||||
CFDictionaryRef _font_attribs;
|
||||
|
||||
string _install_label;
|
||||
double _install_progress;
|
||||
bool _progress_known;
|
||||
|
|
|
|||
|
|
@ -150,10 +150,10 @@ main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!run_p3dpython(program_name, archive_file, input_handle, output_handle,
|
||||
NULL, interactive_console)) {
|
||||
int status = run_p3dpython(program_name, archive_file, input_handle,
|
||||
output_handle, NULL, interactive_console);
|
||||
if (status != 0) {
|
||||
cerr << "Failure on startup.\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
#include "py_panda.h"
|
||||
|
||||
extern "C" {
|
||||
// This has been compiled-in by the build system, if all is well.
|
||||
extern struct _frozen _PyImport_FrozenModules[];
|
||||
};
|
||||
|
||||
// There is only one P3DPythonRun object in any given process space.
|
||||
// Makes the statics easier to deal with, and we don't need multiple
|
||||
// instances of this thing.
|
||||
|
|
@ -54,16 +59,26 @@ P3DPythonRun(const char *program_name, const char *archive_file,
|
|||
_interactive_console = interactive_console;
|
||||
|
||||
if (program_name != NULL) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
// Python 3 case: we have to convert it to a wstring.
|
||||
TextEncoder enc;
|
||||
enc.set_text(program_name);
|
||||
_program_name = enc.get_wtext();
|
||||
#else
|
||||
// Python 2 is happy with a regular string.
|
||||
_program_name = program_name;
|
||||
#endif
|
||||
}
|
||||
if (archive_file != NULL) {
|
||||
_archive_file = Filename::from_os_specific(archive_file);
|
||||
}
|
||||
|
||||
_py_argc = 1;
|
||||
_py_argv = (char **)malloc(2 * sizeof(char *));
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
_py_argv[0] = (wchar_t *)_program_name.c_str();
|
||||
#else
|
||||
_py_argv[0] = (char *)_program_name.c_str();
|
||||
#endif
|
||||
_py_argv[1] = NULL;
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
|
@ -75,13 +90,30 @@ P3DPythonRun(const char *program_name, const char *archive_file,
|
|||
// Turn off the automatic load of site.py at startup.
|
||||
extern int Py_NoSiteFlag;
|
||||
Py_NoSiteFlag = 1;
|
||||
Py_NoUserSiteDirectory = 1;
|
||||
|
||||
// Tell Python not to write bytecode files for loaded modules.
|
||||
Py_DontWriteBytecodeFlag = 1;
|
||||
|
||||
// Prevent Python from complaining about finding the standard modules.
|
||||
Py_FrozenFlag = 1;
|
||||
|
||||
// This contains the modules we need in order to call Py_Initialize,
|
||||
// as well as the VFSImporter.
|
||||
PyImport_FrozenModules = _PyImport_FrozenModules;
|
||||
|
||||
// Initialize Python. It appears to be important to do this before
|
||||
// we open the pipe streams and spawn the thread, below.
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_SetProgramName((wchar_t *)_program_name.c_str());
|
||||
Py_SetPythonHome((wchar_t *)L"");
|
||||
#else
|
||||
Py_SetProgramName((char *)_program_name.c_str());
|
||||
Py_SetPythonHome((char *)"");
|
||||
#endif
|
||||
Py_Initialize();
|
||||
PyEval_InitThreads();
|
||||
PySys_SetArgv(_py_argc, _py_argv);
|
||||
PySys_SetArgvEx(_py_argc, _py_argv, 0);
|
||||
|
||||
// Open the error output before we do too much more.
|
||||
if (log_pathname != NULL && *log_pathname != '\0') {
|
||||
|
|
@ -137,8 +169,10 @@ P3DPythonRun::
|
|||
// Access: Public
|
||||
// Description: Runs the embedded Python process. This method does
|
||||
// not return until the plugin is ready to exit.
|
||||
//
|
||||
// Returns the exit status, which will be 0 on success.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DPythonRun::
|
||||
int P3DPythonRun::
|
||||
run_python() {
|
||||
#if defined(_WIN32) && defined(USE_DEBUG_PYTHON)
|
||||
// On Windows, in a debug build, we have to preload sys.dll_suffix =
|
||||
|
|
@ -154,36 +188,42 @@ run_python() {
|
|||
// setting __path__ of frozen modules properly.
|
||||
PyObject *panda3d_module = PyImport_AddModule("panda3d");
|
||||
if (panda3d_module == NULL) {
|
||||
nout << "Failed to create panda3d module:\n";
|
||||
nout << "Failed to add panda3d module:\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set the __path__ such that it can find panda3d/core.pyd, etc.
|
||||
// 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);
|
||||
PyModule_AddObject(panda3d_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length()));
|
||||
PyModule_AddStringConstant(panda3d_module, "__package__", "panda3d");
|
||||
|
||||
// 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";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
Py_DECREF(vfsimporter);
|
||||
|
||||
// And now we can import the VFSImporter module that was so defined.
|
||||
PyObject *vfsimporter_module = PyImport_ImportModule("VFSImporter");
|
||||
// Import the VFSImporter module that was frozen in.
|
||||
PyObject *vfsimporter_module = PyImport_ImportModule("direct.showbase.VFSImporter");
|
||||
if (vfsimporter_module == NULL) {
|
||||
nout << "Failed to import VFSImporter:\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now repair the "direct" and "direct.showbase" trees, which were
|
||||
// presumably frozen along with the VFSImporter, by setting their
|
||||
// __path__ such that we can still find the other direct modules.
|
||||
Filename direct_dir(dir, "direct");
|
||||
PyObject *direct_module = PyImport_AddModule("direct");
|
||||
if (direct_module != NULL) {
|
||||
dir_str = direct_dir.to_os_specific();
|
||||
PyModule_AddObject(direct_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length()));
|
||||
PyModule_AddStringConstant(direct_module, "__package__", "direct");
|
||||
}
|
||||
|
||||
PyObject *showbase_module = PyImport_AddModule("direct.showbase");
|
||||
if (showbase_module != NULL) {
|
||||
Filename showbase_dir(direct_dir, "showbase");
|
||||
dir_str = showbase_dir.to_os_specific();
|
||||
PyModule_AddObject(showbase_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length()));
|
||||
PyModule_AddStringConstant(showbase_module, "__package__", "direct.showbase");
|
||||
}
|
||||
|
||||
// And register the VFSImporter.
|
||||
|
|
@ -191,7 +231,7 @@ run_python() {
|
|||
if (result == NULL) {
|
||||
nout << "Failed to call VFSImporter.register():\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
Py_DECREF(result);
|
||||
Py_DECREF(vfsimporter_module);
|
||||
|
|
@ -203,12 +243,12 @@ run_python() {
|
|||
PT(Multifile) mf = new Multifile;
|
||||
if (!mf->open_read(_archive_file)) {
|
||||
nout << "Could not read " << _archive_file << "\n";
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
if (!vfs->mount(mf, dir, VirtualFileSystem::MF_read_only)) {
|
||||
nout << "Could not mount " << _archive_file << "\n";
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// And finally, we can import the startup module.
|
||||
|
|
@ -216,7 +256,7 @@ run_python() {
|
|||
if (app_runner_module == NULL) {
|
||||
nout << "Failed to import direct.p3d.AppRunner\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the pointers to the objects needed within the module.
|
||||
|
|
@ -224,7 +264,7 @@ run_python() {
|
|||
if (app_runner_class == NULL) {
|
||||
nout << "Failed to get AppRunner class\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Construct an instance of AppRunner.
|
||||
|
|
@ -232,47 +272,55 @@ run_python() {
|
|||
if (_runner == NULL) {
|
||||
nout << "Failed to construct AppRunner instance\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
Py_DECREF(app_runner_class);
|
||||
|
||||
// Get the UndefinedObject class.
|
||||
_undefined_object_class = PyObject_GetAttrString(app_runner_module, "UndefinedObject");
|
||||
if (_undefined_object_class == NULL) {
|
||||
// Import the JavaScript module.
|
||||
PyObject *javascript_module = PyImport_ImportModule("direct.p3d.JavaScript");
|
||||
if (javascript_module == NULL) {
|
||||
nout << "Failed to import direct.p3d.JavaScript\n";
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the UndefinedObject class.
|
||||
_undefined_object_class = PyObject_GetAttrString(javascript_module, "UndefinedObject");
|
||||
if (_undefined_object_class == NULL) {
|
||||
PyErr_Print();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// And the "Undefined" instance.
|
||||
_undefined = PyObject_GetAttrString(app_runner_module, "Undefined");
|
||||
_undefined = PyObject_GetAttrString(javascript_module, "Undefined");
|
||||
if (_undefined == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the ConcreteStruct class.
|
||||
_concrete_struct_class = PyObject_GetAttrString(app_runner_module, "ConcreteStruct");
|
||||
_concrete_struct_class = PyObject_GetAttrString(javascript_module, "ConcreteStruct");
|
||||
if (_concrete_struct_class == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the BrowserObject class.
|
||||
_browser_object_class = PyObject_GetAttrString(app_runner_module, "BrowserObject");
|
||||
_browser_object_class = PyObject_GetAttrString(javascript_module, "BrowserObject");
|
||||
if (_browser_object_class == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the global TaskManager.
|
||||
_taskMgr = PyObject_GetAttrString(app_runner_module, "taskMgr");
|
||||
if (_taskMgr == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Py_DECREF(app_runner_module);
|
||||
|
||||
Py_DECREF(javascript_module);
|
||||
|
||||
// Construct a Python wrapper around our methods we need to expose to Python.
|
||||
static PyMethodDef p3dpython_methods[] = {
|
||||
|
|
@ -282,15 +330,28 @@ run_python() {
|
|||
"Send an asynchronous request to the plugin host" },
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static PyModuleDef p3dpython_module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"p3dpython",
|
||||
NULL,
|
||||
-1,
|
||||
p3dpython_methods,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
PyObject *p3dpython = PyModule_Create(&p3dpython_module);
|
||||
#else
|
||||
PyObject *p3dpython = Py_InitModule("p3dpython", p3dpython_methods);
|
||||
#endif
|
||||
if (p3dpython == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
PyObject *request_func = PyObject_GetAttrString(p3dpython, "request_func");
|
||||
if (request_func == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now pass that func pointer back to our AppRunner instance, so it
|
||||
|
|
@ -298,7 +359,7 @@ run_python() {
|
|||
result = PyObject_CallMethod(_runner, (char *)"setRequestFunc", (char *)"N", request_func);
|
||||
if (result == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
Py_DECREF(result);
|
||||
|
||||
|
|
@ -318,7 +379,7 @@ run_python() {
|
|||
PyObject *check_comm = PyObject_GetAttrString(p3dpython, "check_comm");
|
||||
if (check_comm == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add it to the task manager. We do this instead of constructing a
|
||||
|
|
@ -326,7 +387,7 @@ run_python() {
|
|||
result = PyObject_CallMethod(_taskMgr, (char *)"add", (char *)"Ns", check_comm, "check_comm");
|
||||
if (result == NULL) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
Py_DECREF(result);
|
||||
|
||||
|
|
@ -334,18 +395,48 @@ run_python() {
|
|||
// taskMgr.run()).
|
||||
PyObject *done = PyObject_CallMethod(_runner, (char *)"run", (char *)"");
|
||||
if (done == NULL) {
|
||||
int status = 1;
|
||||
|
||||
// An uncaught application exception, and not handled by
|
||||
// appRunner.exceptionHandler.
|
||||
PyErr_Print();
|
||||
// appRunner.exceptionHandler. If it is a SystemExit, extract
|
||||
// the exit status that we should return.
|
||||
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
|
||||
PyObject *ptype, *ptraceback;
|
||||
PyObject *value = NULL;
|
||||
PyErr_Fetch(&ptype, &value, &ptraceback);
|
||||
|
||||
if (value != NULL && PyExceptionInstance_Check(value)) {
|
||||
PyObject *code = PyObject_GetAttrString(value, "code");
|
||||
if (code) {
|
||||
Py_DECREF(value);
|
||||
value = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (value == NULL || value == Py_None) {
|
||||
status = 0;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
} else if (PyLong_Check(value)) {
|
||||
status = (int)PyLong_AsLong(value);
|
||||
#else
|
||||
} else if (PyInt_Check(value)) {
|
||||
status = (int)PyInt_AsLong(value);
|
||||
#endif
|
||||
} else {
|
||||
status = 1;
|
||||
}
|
||||
} else {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
if (_interactive_console) {
|
||||
// Give an interactive user a chance to explore the exception.
|
||||
run_interactive_console();
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We're done.
|
||||
return false;
|
||||
return status;
|
||||
}
|
||||
|
||||
// A normal exit from the taskManager. We're presumably done.
|
||||
|
|
@ -355,7 +446,7 @@ run_python() {
|
|||
run_interactive_console();
|
||||
}
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -636,8 +727,11 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||
result = PyBool_FromLong(PyObject_IsTrue(obj));
|
||||
|
||||
} else if (strcmp(method_name, "__int__") == 0) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyNumber_Long(obj);
|
||||
#else
|
||||
result = PyNumber_Int(obj);
|
||||
|
||||
#endif
|
||||
} else if (strcmp(method_name, "__float__") == 0) {
|
||||
result = PyNumber_Float(obj);
|
||||
|
||||
|
|
@ -1502,10 +1596,12 @@ pyobj_to_xml(PyObject *value) {
|
|||
xvalue->SetAttribute("type", "bool");
|
||||
xvalue->SetAttribute("value", PyObject_IsTrue(value));
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
} else if (PyInt_Check(value)) {
|
||||
// A plain integer value.
|
||||
xvalue->SetAttribute("type", "int");
|
||||
xvalue->SetAttribute("value", PyInt_AsLong(value));
|
||||
#endif
|
||||
|
||||
} else if (PyLong_Check(value)) {
|
||||
// A long integer value. This gets converted either as an integer
|
||||
|
|
@ -1527,9 +1623,21 @@ pyobj_to_xml(PyObject *value) {
|
|||
xvalue->SetAttribute("type", "float");
|
||||
xvalue->SetDoubleAttribute("value", PyFloat_AsDouble(value));
|
||||
|
||||
|
||||
} else if (PyUnicode_Check(value)) {
|
||||
// A unicode value. Convert to utf-8 for the XML encoding.
|
||||
xvalue->SetAttribute("type", "string");
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
// In Python 3, there are only unicode strings, and there is a
|
||||
// handy function for getting the UTF-8 encoded version.
|
||||
Py_ssize_t length = 0;
|
||||
char *buffer = PyUnicode_AsUTF8AndSize(value, &length);
|
||||
if (buffer != NULL) {
|
||||
string str(buffer, length);
|
||||
xvalue->SetAttribute("value", str);
|
||||
}
|
||||
#else
|
||||
PyObject *as_str = PyUnicode_AsUTF8String(value);
|
||||
if (as_str != NULL) {
|
||||
char *buffer;
|
||||
|
|
@ -1563,6 +1671,7 @@ pyobj_to_xml(PyObject *value) {
|
|||
}
|
||||
Py_DECREF(ustr);
|
||||
}
|
||||
#endif // PY_MAJOR_VERSION
|
||||
|
||||
} else if (PyTuple_Check(value)) {
|
||||
// An immutable sequence. Pass it as a concrete.
|
||||
|
|
@ -1601,7 +1710,11 @@ pyobj_to_xml(PyObject *value) {
|
|||
PyObject *as_str;
|
||||
if (PyUnicode_Check(a)) {
|
||||
// The key is a unicode value.
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
as_str = a;
|
||||
#else
|
||||
as_str = PyUnicode_AsUTF8String(a);
|
||||
#endif
|
||||
} else {
|
||||
// The key is a string value or something else. Make it
|
||||
// a string.
|
||||
|
|
@ -1609,7 +1722,12 @@ pyobj_to_xml(PyObject *value) {
|
|||
}
|
||||
char *buffer;
|
||||
Py_ssize_t length;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
buffer = PyUnicode_AsUTF8AndSize(as_str, &length);
|
||||
if (buffer != NULL) {
|
||||
#else
|
||||
if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) {
|
||||
#endif
|
||||
string str(buffer, length);
|
||||
xitem->SetAttribute("key", str);
|
||||
}
|
||||
|
|
@ -1694,7 +1812,11 @@ xml_to_pyobj(TiXmlElement *xvalue) {
|
|||
} else if (strcmp(type, "int") == 0) {
|
||||
int value;
|
||||
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyLong_FromLong(value);
|
||||
#else
|
||||
return PyInt_FromLong(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
} else if (strcmp(type, "float") == 0) {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public:
|
|||
const char *log_pathname, bool interactive_console);
|
||||
~P3DPythonRun();
|
||||
|
||||
bool run_python();
|
||||
int run_python();
|
||||
|
||||
void set_window_open(P3DCInstance *inst, bool is_open);
|
||||
void request_keyboard_focus(P3DCInstance *inst);
|
||||
|
|
@ -159,10 +159,15 @@ private:
|
|||
|
||||
int _session_id;
|
||||
|
||||
string _program_name;
|
||||
Filename _archive_file;
|
||||
int _py_argc;
|
||||
char **_py_argv;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
wchar_t *_py_argv[2];
|
||||
wstring _program_name;
|
||||
#else
|
||||
char *_py_argv[2];
|
||||
string _program_name;
|
||||
#endif
|
||||
bool _interactive_console;
|
||||
|
||||
PyObject *_runner;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ void P3DSession::
|
|||
shutdown() {
|
||||
set_failed();
|
||||
|
||||
int exit_code = 0;
|
||||
|
||||
if (_p3dpython_started) {
|
||||
// Tell the process we're going away.
|
||||
TiXmlDocument doc;
|
||||
|
|
@ -139,7 +141,14 @@ shutdown() {
|
|||
nout << "Force-killing python process.\n";
|
||||
TerminateProcess(_p3dpython_handle, 2);
|
||||
}
|
||||
|
||||
|
||||
DWORD dw_exit_code = 0;
|
||||
if (!GetExitCodeProcess(_p3dpython_handle, &dw_exit_code)) {
|
||||
nout << "GetExitCodeProcess failed, error: " << GetLastError() << "\n";
|
||||
} else {
|
||||
exit_code = (int)dw_exit_code;
|
||||
}
|
||||
|
||||
CloseHandle(_p3dpython_handle);
|
||||
_p3dpython_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
|
|
@ -179,18 +188,23 @@ shutdown() {
|
|||
result = waitpid(_p3dpython_pid, &status, WNOHANG);
|
||||
}
|
||||
_p3dpython_pid = -1;
|
||||
|
||||
|
||||
nout << "Python process has successfully stopped.\n";
|
||||
if (WIFEXITED(status)) {
|
||||
nout << " exited normally, status = "
|
||||
<< WEXITSTATUS(status) << "\n";
|
||||
exit_code = WEXITSTATUS(status);
|
||||
nout << " exited normally, status = " << exit_code << "\n";
|
||||
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
<< WCOREDUMP(status) << "\n";
|
||||
|
||||
// This seems to be a popular shell convention.
|
||||
exit_code = 128 + WTERMSIG(status);
|
||||
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
nout << " stopped by " << WSTOPSIG(status) << "\n";
|
||||
}
|
||||
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
|
|
@ -211,6 +225,11 @@ shutdown() {
|
|||
|
||||
// Close the pipe now.
|
||||
_pipe_read.close();
|
||||
|
||||
// If we had an exit status, pass it on to the runtime process.
|
||||
if (exit_code != 0) {
|
||||
_exit(exit_code);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -717,7 +736,7 @@ start_p3dpython(P3DInstance *inst) {
|
|||
_keep_user_env = true;
|
||||
}
|
||||
if (!_keep_user_env) {
|
||||
_start_dir = inst_mgr->get_root_dir() + "/start" + inst->get_start_dir_suffix();
|
||||
_start_dir = inst_mgr->get_start_dir() + inst->get_start_dir_suffix();
|
||||
mkdir_complete(_start_dir, nout);
|
||||
}
|
||||
replace_slashes(_start_dir);
|
||||
|
|
@ -872,11 +891,13 @@ start_p3dpython(P3DInstance *inst) {
|
|||
// These are the enviroment variables we forward from the current
|
||||
// environment, if they are set.
|
||||
const char *keep[] = {
|
||||
"HOME", "USER",
|
||||
"HOME", "USER",
|
||||
#ifdef _WIN32
|
||||
"SYSTEMROOT", "USERPROFILE", "COMSPEC",
|
||||
"SYSTEMDRIVE", "ALLUSERSPROFILE", "APPDATA", "COMMONPROGRAMFILES",
|
||||
"PROGRAMFILES", "WINDIR", "PROGRAMDATA", "USERDOMAIN",
|
||||
#else
|
||||
"LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG",
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
"DISPLAY", "XAUTHORITY",
|
||||
|
|
@ -928,7 +949,11 @@ start_p3dpython(P3DInstance *inst) {
|
|||
const char *varc = var.c_str();
|
||||
bool found = false;
|
||||
for (int i = 0; dont_keep[i] != NULL && !found; ++i) {
|
||||
#ifdef _WIN32
|
||||
found = (_stricmp(dont_keep[i], varc) == 0);
|
||||
#else
|
||||
found = (strcmp(dont_keep[i], varc) == 0);
|
||||
#endif
|
||||
}
|
||||
if (!found) {
|
||||
// This variable is OK, keep it.
|
||||
|
|
@ -1704,15 +1729,24 @@ posix_create_process() {
|
|||
// its process. Report an error condition.
|
||||
nout << "Python process stopped immediately.\n";
|
||||
if (WIFEXITED(status)) {
|
||||
nout << " exited normally, status = "
|
||||
<< WEXITSTATUS(status) << "\n";
|
||||
int code = WEXITSTATUS(status);
|
||||
|
||||
nout << " exited normally, status = " << code << "\n";
|
||||
if (code != 0) {
|
||||
_exit(code);
|
||||
}
|
||||
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
<< WCOREDUMP(status) << "\n";
|
||||
|
||||
// This seems to be a popular shell convention.
|
||||
_exit(128 + WTERMSIG(status));
|
||||
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
nout << " stopped by " << WSTOPSIG(status) << "\n";
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
|
@ -1794,10 +1828,12 @@ p3dpython_thread_run() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!run_p3dpython(libp3dpython.c_str(), _mf_filename.c_str(),
|
||||
_input_handle, _output_handle, _log_pathname.c_str(),
|
||||
_interactive_console)) {
|
||||
int status = run_p3dpython(libp3dpython.c_str(), _mf_filename.c_str(),
|
||||
_input_handle, _output_handle, _log_pathname.c_str(),
|
||||
_interactive_console);
|
||||
if (status != 0) {
|
||||
nout << "Failure on startup.\n";
|
||||
_exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,19 @@ P3DSplashWindow(P3DInstance *inst, bool make_visible) :
|
|||
_barcolor_r = 0x6c;
|
||||
_barcolor_g = 0xa5;
|
||||
_barcolor_b = 0xe0;
|
||||
_bar_bgcolor_r = _bgcolor_r;
|
||||
_bar_bgcolor_g = _bgcolor_g;
|
||||
_bar_bgcolor_b = _bgcolor_b;
|
||||
_bar_border = 1;
|
||||
_bar_bottom = 24;
|
||||
_bar_width = 398;
|
||||
_bar_height = 22;
|
||||
_bar_width_ratio = 0.6;
|
||||
_bar_height_ratio = 0.1;
|
||||
_font_family = "Helvetica";
|
||||
_font_size = 12;
|
||||
_font_style = FS_normal;
|
||||
_font_weight = FW_normal;
|
||||
_button_width = 0;
|
||||
_button_height = 0;
|
||||
_button_x = 0;
|
||||
|
|
@ -113,7 +126,7 @@ set_image_filename(const string &image_filename, ImagePlacement image_placement)
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_fgcolor
|
||||
// Access: Public, Virtual
|
||||
// Access: Public
|
||||
// Description: Specifies the color that is used to display the text
|
||||
// above the loading bar.
|
||||
//
|
||||
|
|
@ -129,7 +142,7 @@ set_fgcolor(int r, int g, int b) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_bgcolor
|
||||
// Access: Public, Virtual
|
||||
// Access: Public
|
||||
// Description: Specifies the solid color that is displayed behind
|
||||
// the splash image, if any, or before the splash image
|
||||
// is loaded.
|
||||
|
|
@ -146,7 +159,7 @@ set_bgcolor(int r, int g, int b) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_barcolor
|
||||
// Access: Public, Virtual
|
||||
// Access: Public
|
||||
// Description: Specifies the color that is used to fill the
|
||||
// loading bar.
|
||||
//
|
||||
|
|
@ -160,6 +173,162 @@ set_barcolor(int r, int g, int b) {
|
|||
_barcolor_b = b;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_bar_bgcolor
|
||||
// Access: Public
|
||||
// Description: Specifies the solid color that is displayed behind
|
||||
// the loading bar.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_bar_bgcolor(int r, int g, int b) {
|
||||
nout << "bar_bgcolor " << r << ", " << g << ", " << b << "\n";
|
||||
_bar_bgcolor_r = r;
|
||||
_bar_bgcolor_g = g;
|
||||
_bar_bgcolor_b = b;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_bar_border
|
||||
// Access: Public
|
||||
// Description: Sets the width in pixels of the border around the
|
||||
// loading bar, or 0 not to draw a bar at all.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_bar_border(int border) {
|
||||
nout << "bar_border " << border << "\n";
|
||||
_bar_border = border;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_bar_bottom
|
||||
// Access: Public
|
||||
// Description: Sets the amount of background pixels between the
|
||||
// bottom edge of the window and the bottom edge of
|
||||
// the loading bar border.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_bar_bottom(int bottom) {
|
||||
nout << "bar_bottom " << bottom << "\n";
|
||||
_bar_bottom = bottom;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_bar_width
|
||||
// Access: Public
|
||||
// Description: Sets the width of the loading bar. If percent is
|
||||
// true, it is interpreted as a percentage of the
|
||||
// window width. If false, it is interpreted as an
|
||||
// absolute width in pixels.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_bar_width(int width, bool percent) {
|
||||
nout << "bar_width " << width;
|
||||
if (percent) {
|
||||
nout << '%';
|
||||
}
|
||||
nout << '\n';
|
||||
|
||||
if (percent) {
|
||||
_bar_width = -1;
|
||||
_bar_width_ratio = abs(width) / 100.0;
|
||||
} else {
|
||||
_bar_width = abs(width);
|
||||
_bar_width_ratio = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_bar_height
|
||||
// Access: Public
|
||||
// Description: Sets the height of the loading bar. If percent is
|
||||
// true, it is interpreted as a percentage of the
|
||||
// window height. If false, it is interpreted as an
|
||||
// absolute height in pixels.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_bar_height(int height, bool percent) {
|
||||
nout << "bar_height " << height;
|
||||
if (percent) {
|
||||
nout << '%';
|
||||
}
|
||||
nout << '\n';
|
||||
|
||||
if (percent) {
|
||||
_bar_height = -1;
|
||||
_bar_height_ratio = abs(height) / 100.0;
|
||||
} else {
|
||||
_bar_height = abs(height);
|
||||
_bar_height_ratio = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_font_family
|
||||
// Access: Public
|
||||
// Description: Sets the font family of the text above the loading
|
||||
// bar.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_font_family(const string &family) {
|
||||
nout << "font_family " << family << "\n";
|
||||
_font_family = family;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_font_size
|
||||
// Access: Public
|
||||
// Description: Sets the font size in pixels of the text above the
|
||||
// loading bar. The default value is 12.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_font_size(int size) {
|
||||
nout << "font_size " << size << "\n";
|
||||
_font_size = size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_font_style
|
||||
// Access: Public
|
||||
// Description: Sets the font style of the text above the loading
|
||||
// bar.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_font_style(FontStyle style) {
|
||||
nout << "font_style " << style << "\n";
|
||||
_font_style = style;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_font_weight
|
||||
// Access: Public
|
||||
// Description: Sets the font weight of the text above the loading
|
||||
// bar. The default is FW_normal. It should be
|
||||
// a multiple of 100 in the range 100-900.
|
||||
//
|
||||
// This may only be set before wparams is set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_font_weight(int weight) {
|
||||
nout << "font_weight " << weight << "\n";
|
||||
_font_weight = weight;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_install_label
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -271,10 +440,21 @@ read_image_data(ImageData &image, string &data,
|
|||
void P3DSplashWindow::
|
||||
get_bar_placement(int &bar_x, int &bar_y,
|
||||
int &bar_width, int &bar_height) {
|
||||
bar_width = min((int)(_win_width * 0.6), 400);
|
||||
bar_height = min((int)(_win_height * 0.1), 24);
|
||||
|
||||
bar_width = (int)(_win_width * _bar_width_ratio);
|
||||
bar_height = (int)(_win_height * _bar_height_ratio);
|
||||
|
||||
if (_bar_width >= 0) {
|
||||
bar_width = min(bar_width, _bar_width);
|
||||
}
|
||||
if (_bar_height >= 0) {
|
||||
bar_height = min(bar_height, _bar_height);
|
||||
}
|
||||
|
||||
// Horizontally center the bar, and set it at a fixed distance
|
||||
// from the bottom edge of the splash window.
|
||||
bar_x = (_win_width - bar_width) / 2;
|
||||
bar_y = (_win_height - bar_height * 2);
|
||||
bar_y = _win_height - _bar_bottom - _bar_border - bar_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -51,12 +51,32 @@ public:
|
|||
IP_button_click,
|
||||
IP_none
|
||||
};
|
||||
enum FontStyle {
|
||||
FS_normal,
|
||||
FS_italic,
|
||||
FS_oblique
|
||||
};
|
||||
enum FontWeight {
|
||||
FW_normal = 400,
|
||||
FW_medium = 500,
|
||||
FW_bold = 700,
|
||||
FW_black = 900
|
||||
};
|
||||
|
||||
virtual void set_image_filename(const string &image_filename,
|
||||
ImagePlacement image_placement);
|
||||
virtual void set_fgcolor(int r, int g, int b);
|
||||
virtual void set_bgcolor(int r, int g, int b);
|
||||
virtual void set_barcolor(int r, int g, int b);
|
||||
void set_fgcolor(int r, int g, int b);
|
||||
void set_bgcolor(int r, int g, int b);
|
||||
void set_barcolor(int r, int g, int b);
|
||||
void set_bar_bgcolor(int r, int g, int b);
|
||||
void set_bar_border(int border);
|
||||
void set_bar_bottom(int bottom);
|
||||
void set_bar_width(int width, bool percent=false);
|
||||
void set_bar_height(int height, bool percent=false);
|
||||
void set_font_family(const string &family);
|
||||
void set_font_size(int size);
|
||||
void set_font_style(FontStyle style);
|
||||
void set_font_weight(int weight);
|
||||
virtual void set_install_label(const string &install_label);
|
||||
virtual void set_install_progress(double install_progress,
|
||||
bool is_progress_known, size_t received_data);
|
||||
|
|
@ -105,6 +125,19 @@ protected:
|
|||
int _fgcolor_r, _fgcolor_g, _fgcolor_b;
|
||||
int _bgcolor_r, _bgcolor_g, _bgcolor_b;
|
||||
int _barcolor_r, _barcolor_g, _barcolor_b;
|
||||
int _bar_bgcolor_r, _bar_bgcolor_g, _bar_bgcolor_b;
|
||||
int _bar_border;
|
||||
|
||||
private:
|
||||
int _bar_bottom;
|
||||
int _bar_width, _bar_height;
|
||||
double _bar_width_ratio, _bar_height_ratio;
|
||||
|
||||
protected:
|
||||
string _font_family;
|
||||
int _font_size;
|
||||
FontStyle _font_style;
|
||||
int _font_weight;
|
||||
|
||||
// The region of the window for accepting button clicks.
|
||||
int _button_width, _button_height;
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@ P3DWinSplashWindow(P3DInstance *inst, bool make_visible) :
|
|||
_thread = NULL;
|
||||
_thread_id = 0;
|
||||
_hwnd = NULL;
|
||||
_font = NULL;
|
||||
_fg_brush = NULL;
|
||||
_bg_brush = NULL;
|
||||
_bar_brush = NULL;
|
||||
_bar_bg_brush = NULL;
|
||||
_thread_running = false;
|
||||
_install_progress = 0.0;
|
||||
_progress_known = true;
|
||||
|
|
@ -497,9 +499,21 @@ make_window() {
|
|||
ShowWindow(_hwnd, SW_HIDE);
|
||||
}
|
||||
|
||||
// Load the requested font.
|
||||
_font = CreateFontA(-_font_size, 0, 0, 0, _font_weight,
|
||||
(_font_style != FS_normal), FALSE, FALSE,
|
||||
ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
CLEARTYPE_QUALITY, VARIABLE_PITCH, _font_family.c_str());
|
||||
|
||||
if (_font == NULL) {
|
||||
nout << "CreateFont failed: " << GetLastError() << "\n";
|
||||
_font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
||||
}
|
||||
|
||||
_fg_brush = CreateSolidBrush(RGB(_fgcolor_r, _fgcolor_g, _fgcolor_b));
|
||||
_bg_brush = CreateSolidBrush(RGB(_bgcolor_r, _bgcolor_g, _bgcolor_b));
|
||||
_bar_brush = CreateSolidBrush(RGB(_barcolor_r, _barcolor_g, _barcolor_b));
|
||||
_bar_bg_brush = CreateSolidBrush(RGB(_bar_bgcolor_r, _bar_bgcolor_g, _bar_bgcolor_b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -635,6 +649,10 @@ close_window() {
|
|||
DeleteObject(_bar_brush);
|
||||
_bar_brush = NULL;
|
||||
}
|
||||
if (_bar_bg_brush != NULL) {
|
||||
DeleteObject(_bar_bg_brush);
|
||||
_bar_bg_brush = NULL;
|
||||
}
|
||||
|
||||
_background_image.dump_image();
|
||||
_button_ready_image.dump_image();
|
||||
|
|
@ -794,7 +812,7 @@ paint_progress_bar(HDC dc) {
|
|||
RECT bar_rect = { bar_x, bar_y, bar_x + bar_width, bar_y + bar_height };
|
||||
|
||||
// Clear the entire progress bar to white (or the background color).
|
||||
FillRect(dc, &bar_rect, _bg_brush);
|
||||
FillRect(dc, &bar_rect, _bar_bg_brush);
|
||||
|
||||
// Draw the interior of the progress bar in blue (or the bar color).
|
||||
if (_drawn_progress_known) {
|
||||
|
|
@ -820,23 +838,31 @@ paint_progress_bar(HDC dc) {
|
|||
}
|
||||
|
||||
// Now draw a black (or foreground) border around the progress bar.
|
||||
FrameRect(dc, &bar_rect, _fg_brush);
|
||||
if (_bar_border >= 0) {
|
||||
RECT border_rect = bar_rect;
|
||||
|
||||
for (int i = 0; i < _bar_border; ++i) {
|
||||
--border_rect.left;
|
||||
--border_rect.top;
|
||||
++border_rect.right;
|
||||
++border_rect.bottom;
|
||||
FrameRect(dc, &border_rect, _fg_brush);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_drawn_label.empty()) {
|
||||
// Now draw the install_label right above it.
|
||||
|
||||
const char *text = _drawn_label.c_str();
|
||||
HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
||||
|
||||
// Measure the text, for centering.
|
||||
SelectObject(dc, font);
|
||||
SelectObject(dc, _font);
|
||||
SIZE text_size;
|
||||
GetTextExtentPoint32(dc, text, strlen(text), &text_size);
|
||||
|
||||
int text_width = text_size.cx;
|
||||
int text_height = text_size.cy;
|
||||
int text_x = (_win_width - text_width) / 2;
|
||||
int text_y = bar_y - (int)(text_height * 1.5);
|
||||
int text_y = bar_y - (int)(text_height * 1.5) - _bar_border;
|
||||
|
||||
// Clear the rectangle behind the text to white.
|
||||
RECT text_rect = { text_x - 2, text_y - 2, text_x + text_width + 4, text_y + text_height + 4 };
|
||||
|
|
@ -856,7 +882,7 @@ paint_progress_bar(HDC dc) {
|
|||
// Access: Private
|
||||
// Description: The windows event-processing handler.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LONG P3DWinSplashWindow::
|
||||
LRESULT P3DWinSplashWindow::
|
||||
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
switch (msg) {
|
||||
case WM_DESTROY:
|
||||
|
|
@ -937,7 +963,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||
// Access: Private, Static
|
||||
// Description: The windows event-processing handler, static version.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LONG P3DWinSplashWindow::
|
||||
LRESULT P3DWinSplashWindow::
|
||||
st_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
LONG_PTR self = GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (self == NULL) {
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ private:
|
|||
void paint_window(HDC dc);
|
||||
bool paint_image(HDC dc, const WinImageData &image, bool use_alpha);
|
||||
void paint_progress_bar(HDC dc);
|
||||
LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
static LONG WINAPI st_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
LRESULT window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
static LRESULT WINAPI st_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
private:
|
||||
class WinImageData : public ImageData {
|
||||
|
|
@ -109,9 +109,11 @@ private:
|
|||
HANDLE _thread;
|
||||
DWORD _thread_id;
|
||||
HWND _hwnd;
|
||||
HFONT _font;
|
||||
HBRUSH _fg_brush;
|
||||
HBRUSH _bg_brush;
|
||||
HBRUSH _bar_brush;
|
||||
HBRUSH _bar_bg_brush;
|
||||
|
||||
static bool _registered_window_class;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,11 +47,14 @@ P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
|
|||
_display = None;
|
||||
_window = None;
|
||||
_screen = 0;
|
||||
_font = NULL;
|
||||
_graphics_context = None;
|
||||
_bar_context = None;
|
||||
_bar_bg_context = None;
|
||||
_fg_pixel = -1;
|
||||
_bg_pixel = -1;
|
||||
_bar_pixel = -1;
|
||||
_bar_bg_pixel = -1;
|
||||
_own_display = false;
|
||||
_install_progress = 0.0;
|
||||
_progress_known = true;
|
||||
|
|
@ -609,10 +612,15 @@ subprocess_run() {
|
|||
get_bar_placement(bar_x, bar_y, bar_width, bar_height);
|
||||
|
||||
if (needs_draw_label) {
|
||||
int text_width = _install_label.size() * 6;
|
||||
int text_height = 10;
|
||||
int direction, ascent, descent;
|
||||
XCharStruct extents;
|
||||
XTextExtents(_font, _install_label.c_str(), _install_label.size(),
|
||||
&direction, &ascent, &descent, &extents);
|
||||
|
||||
int text_width = extents.width;
|
||||
int text_height = extents.ascent + extents.descent;
|
||||
int text_x = (_win_width - text_width) / 2;
|
||||
int text_y = bar_y - 4;
|
||||
int text_y = bar_y - descent - _bar_border - 4;
|
||||
|
||||
XClearArea(_display, _window,
|
||||
text_x - 2, text_y - text_height - 2,
|
||||
|
|
@ -624,25 +632,44 @@ subprocess_run() {
|
|||
}
|
||||
|
||||
if (needs_redraw_progress) {
|
||||
XClearArea(_display, _window,
|
||||
bar_x, bar_y, bar_width, bar_height, false);
|
||||
XDrawRectangle(_display, _window, _graphics_context,
|
||||
bar_x, bar_y, bar_width, bar_height);
|
||||
// Draw the bar background.
|
||||
if (_bar_bg_context != None) {
|
||||
XFillRectangle(_display, _window, _bar_bg_context,
|
||||
bar_x, bar_y, bar_width, bar_height);
|
||||
} else {
|
||||
XClearArea(_display, _window,
|
||||
bar_x, bar_y, bar_width, bar_height, false);
|
||||
}
|
||||
|
||||
// Draw the border around the bar.
|
||||
int border_x = bar_x - 1;
|
||||
int border_y = bar_y - 1;
|
||||
int border_width = bar_width + 1;
|
||||
int border_height = bar_height + 1;
|
||||
|
||||
for (int i = 0; i < _bar_border; ++i) {
|
||||
XDrawRectangle(_display, _window, _graphics_context,
|
||||
border_x, border_y, border_width, border_height);
|
||||
border_x -= 1;
|
||||
border_y -= 1;
|
||||
border_width += 2;
|
||||
border_height += 2;
|
||||
}
|
||||
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);
|
||||
int progress_width = (int)((bar_width - 1) * _install_progress + 0.5);
|
||||
XFillRectangle(_display, _window, _bar_context,
|
||||
bar_x + 1, bar_y + 1,
|
||||
progress_width + 1, bar_height - 1);
|
||||
bar_x, bar_y,
|
||||
progress_width + 1, bar_height);
|
||||
} else {
|
||||
// Progress is unknown. Draw a moving block, not a progress bar
|
||||
// filling up.
|
||||
int block_width = (int)(bar_width * 0.1 + 0.5);
|
||||
int block_travel = (bar_width - 2) - block_width;
|
||||
int block_travel = (bar_width - 1) - block_width;
|
||||
int progress = (int)(_received_data * _unknown_progress_rate);
|
||||
progress = progress % (block_travel * 2);
|
||||
if (progress > block_travel) {
|
||||
|
|
@ -650,8 +677,8 @@ subprocess_run() {
|
|||
}
|
||||
|
||||
XFillRectangle(_display, _window, _bar_context,
|
||||
bar_x + 1 + progress, bar_y + 1,
|
||||
block_width + 1, bar_height - 1);
|
||||
bar_x + progress, bar_y,
|
||||
block_width + 1, bar_height);
|
||||
}
|
||||
needs_update_progress = false;
|
||||
}
|
||||
|
|
@ -681,10 +708,13 @@ subprocess_run() {
|
|||
}
|
||||
}
|
||||
|
||||
if (input_ready) {
|
||||
while (input_ready) {
|
||||
// Empty the pipe of whatever is in it.
|
||||
receive_command();
|
||||
input_ready = _pipe_read.has_gdata();
|
||||
}
|
||||
|
||||
// Sleep a good amount in order not to lock up the system.
|
||||
struct timespec req;
|
||||
req.tv_sec = 0;
|
||||
req.tv_nsec = 50000000; // 50 ms
|
||||
|
|
@ -955,10 +985,82 @@ setup_gc() {
|
|||
return;
|
||||
}
|
||||
|
||||
XFontStruct* fs = XLoadQueryFont(_display, "6x13");
|
||||
char style = 'r';
|
||||
if (_font_style == FS_oblique) {
|
||||
style = 'o';
|
||||
} else if (_font_style == FS_italic) {
|
||||
style = 'i';
|
||||
}
|
||||
|
||||
// Determine the order at which to try the various weights. From:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight
|
||||
const char *const *try_weights;
|
||||
const int num_weights = 7;
|
||||
|
||||
if (_font_weight > 700) {
|
||||
static const char *const weights[] = {"black", "bold", "demibold", "semibold", "medium", "regular", "extralight"};
|
||||
try_weights = weights;
|
||||
|
||||
} else if (_font_weight > 600) {
|
||||
static const char *const weights[] = {"bold", "black", "demibold", "semibold", "medium", "regular", "extralight"};
|
||||
try_weights = weights;
|
||||
|
||||
} else if (_font_weight > 500) {
|
||||
static const char *const weights[] = {"demibold", "semibold", "bold", "black", "medium", "regular", "extralight"};
|
||||
try_weights = weights;
|
||||
|
||||
} else if (_font_weight == 500) {
|
||||
static const char *const weights[] = {"medium", "regular", "extralight", "demibold", "semibold", "bold", "black"};
|
||||
try_weights = weights;
|
||||
|
||||
} else if (_font_weight >= 400) {
|
||||
static const char *const weights[] = {"regular", "medium", "extralight", "demibold", "semibold", "bold", "black"};
|
||||
try_weights = weights;
|
||||
|
||||
} else {
|
||||
static const char *const weights[] = {"extralight", "regular", "medium", "demibold", "semibold", "bold", "black"};
|
||||
try_weights = weights;
|
||||
}
|
||||
|
||||
char font_name[1024];
|
||||
|
||||
// Go through the weights array to find the best matching font.
|
||||
for (int i = 0; i < num_weights; ++i) {
|
||||
const char *weight_name = try_weights[i];
|
||||
|
||||
// Compose the proper pattern for finding the desired font face.
|
||||
snprintf(font_name, 1024, "-*-%s-%s-%c-normal--%d-*-*-*-*-*-iso8859-1",
|
||||
_font_family.c_str(), weight_name, style, _font_size);
|
||||
|
||||
_font = XLoadQueryFont(_display, font_name);
|
||||
if (_font != NULL) {
|
||||
break;
|
||||
}
|
||||
nout << "Font " << font_name << " unavailable.\n";
|
||||
|
||||
if (style == 'i' || style == 'o') {
|
||||
// If oblique is not found, try italic, and vice versa.
|
||||
char style2 = 216 - style;
|
||||
snprintf(font_name, 1024, "-*-%s-%s-%c-normal--%d-*-*-*-*-*-iso8859-1",
|
||||
_font_family.c_str(), weight_name, style2, _font_size);
|
||||
|
||||
_font = XLoadQueryFont(_display, font_name);
|
||||
if (_font != NULL) {
|
||||
break;
|
||||
}
|
||||
nout << "Font " << font_name << " unavailable.\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (_font != NULL) {
|
||||
nout << "Loaded font " << font_name << "\n";
|
||||
} else {
|
||||
nout << "Using fallback font 6x13.\n";
|
||||
_font = XLoadQueryFont(_display, "6x13");
|
||||
}
|
||||
|
||||
XGCValues gcval;
|
||||
gcval.font = fs->fid;
|
||||
gcval.font = _font->fid;
|
||||
gcval.function = GXcopy;
|
||||
gcval.plane_mask = AllPlanes;
|
||||
gcval.foreground = BlackPixel(_display, _screen);
|
||||
|
|
@ -988,6 +1090,24 @@ setup_gc() {
|
|||
|
||||
_bar_context = XCreateGC(_display, _window,
|
||||
GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
|
||||
|
||||
// And another for the background color of the bar.
|
||||
if (_bar_bgcolor_r != _bgcolor_r || _bar_bgcolor_g != _bgcolor_g ||
|
||||
_bar_bgcolor_b != _bgcolor_b) {
|
||||
XColor bar_bg;
|
||||
bar_bg.red = _bar_bgcolor_r * 0x101;
|
||||
bar_bg.green = _bar_bgcolor_g * 0x101;
|
||||
bar_bg.blue = _bar_bgcolor_b * 0x101;
|
||||
bar_bg.flags = DoRed | DoGreen | DoBlue;
|
||||
|
||||
if (XAllocColor(_display, colormap, &bar_bg)) {
|
||||
_bar_bg_pixel = bar_bg.pixel;
|
||||
gcval.foreground = bar_bg.pixel;
|
||||
}
|
||||
|
||||
_bar_bg_context = XCreateGC(_display, _window,
|
||||
GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1013,6 +1133,17 @@ close_window() {
|
|||
XFreeColors(_display, colormap, &_bar_pixel, 1, 0);
|
||||
}
|
||||
|
||||
if (_bar_bg_context != None) {
|
||||
if (_bar_bg_context != _graphics_context) {
|
||||
XFreeGC(_display, _bar_bg_context);
|
||||
}
|
||||
_bar_bg_context = None;
|
||||
|
||||
// Also free the color we allocated.
|
||||
Colormap colormap = DefaultColormap(_display, _screen);
|
||||
XFreeColors(_display, colormap, &_bar_bg_pixel, 1, 0);
|
||||
}
|
||||
|
||||
if (_fg_pixel != -1) {
|
||||
Colormap colormap = DefaultColormap(_display, _screen);
|
||||
XFreeColors(_display, colormap, &_fg_pixel, 1, 0);
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ private:
|
|||
void setup_gc();
|
||||
void close_window();
|
||||
|
||||
void update_image(X11ImageData &image);
|
||||
void update_image(X11ImageData &image);
|
||||
void compose_image();
|
||||
bool scale_image(vector<unsigned char> &image0, int &image0_width, int &image0_height,
|
||||
X11ImageData &image);
|
||||
|
|
@ -123,17 +123,20 @@ private:
|
|||
double _install_progress;
|
||||
bool _progress_known;
|
||||
size_t _received_data;
|
||||
|
||||
|
||||
string _label_text;
|
||||
|
||||
X11_Display *_display;
|
||||
int _screen;
|
||||
XFontStruct *_font;
|
||||
GC _graphics_context;
|
||||
GC _bar_context;
|
||||
GC _bar_bg_context;
|
||||
unsigned long _fg_pixel;
|
||||
unsigned long _bg_pixel;
|
||||
unsigned long _bar_pixel;
|
||||
|
||||
unsigned long _bar_bg_pixel;
|
||||
|
||||
X11_Window _window;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ P3D_initialize(int api_version, const char *contents_filename,
|
|||
const char *platform, const char *log_directory,
|
||||
const char *log_basename, bool trusted_environment,
|
||||
bool console_environment,
|
||||
const char *root_dir, const char *host_dir) {
|
||||
const char *root_dir, const char *host_dir,
|
||||
const char *start_dir) {
|
||||
if (api_version < 10 || api_version > P3D_API_VERSION) {
|
||||
// Can't accept an incompatible version.
|
||||
return false;
|
||||
|
|
@ -89,12 +90,16 @@ P3D_initialize(int api_version, const char *contents_filename,
|
|||
host_dir = "";
|
||||
}
|
||||
|
||||
if (api_version < 17 || start_dir == NULL) {
|
||||
start_dir = "";
|
||||
}
|
||||
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
bool result = inst_mgr->initialize(api_version, contents_filename, host_url,
|
||||
verify_contents, platform,
|
||||
log_directory, log_basename,
|
||||
trusted_environment, console_environment,
|
||||
root_dir, host_dir);
|
||||
root_dir, host_dir, start_dir);
|
||||
RELEASE_LOCK(_api_lock);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,11 @@
|
|||
#endif
|
||||
|
||||
#else /* _WIN32 */
|
||||
#if defined(BUILDING_P3D_PLUGIN) && defined(__GNUC__)
|
||||
#define EXPCL_P3D_PLUGIN __attribute__((visibility("default")))
|
||||
#else
|
||||
#define EXPCL_P3D_PLUGIN
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
|
@ -79,7 +83,7 @@ extern "C" {
|
|||
(below). This number will be incremented whenever there are changes
|
||||
to any of the interface specifications defined in this header
|
||||
file. */
|
||||
#define P3D_API_VERSION 16
|
||||
#define P3D_API_VERSION 17
|
||||
|
||||
/************************ GLOBAL FUNCTIONS **************************/
|
||||
|
||||
|
|
@ -161,7 +165,8 @@ P3D_initialize_func(int api_version, const char *contents_filename,
|
|||
const char *platform,
|
||||
const char *log_directory, const char *log_basename,
|
||||
bool trusted_environment, bool console_environment,
|
||||
const char *root_dir, const char *host_dir);
|
||||
const char *root_dir, const char *host_dir,
|
||||
const char *start_dir);
|
||||
|
||||
/* This function should be called to unload the core API. It will
|
||||
release all internally-allocated memory and return the core API to
|
||||
|
|
|
|||
|
|
@ -19,16 +19,17 @@
|
|||
// Function: run_p3dpython
|
||||
// Description: This externally-visible function is the main entry
|
||||
// point to this DLL, and it starts the whole thing
|
||||
// running. Returns true on success, false on failure.
|
||||
// running. Returns the exit status, which will be
|
||||
// 0 on success, 1 or otherwise on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
int
|
||||
run_p3dpython(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) {
|
||||
P3DPythonRun::_global_ptr =
|
||||
new P3DPythonRun(program_name, archive_file, input_handle, output_handle,
|
||||
P3DPythonRun::_global_ptr =
|
||||
new P3DPythonRun(program_name, archive_file, input_handle, output_handle,
|
||||
log_pathname, interactive_console);
|
||||
bool result = P3DPythonRun::_global_ptr->run_python();
|
||||
int result = P3DPythonRun::_global_ptr->run_python();
|
||||
delete P3DPythonRun::_global_ptr;
|
||||
P3DPythonRun::_global_ptr = NULL;
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@
|
|||
#define EXPCL_P3DPYTHON
|
||||
#endif
|
||||
|
||||
typedef bool
|
||||
typedef int
|
||||
run_p3dpython_func(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);
|
||||
|
||||
extern "C" EXPCL_P3DPYTHON bool
|
||||
extern "C" EXPCL_P3DPYTHON int
|
||||
run_p3dpython(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);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -581,12 +581,12 @@ int PPInstance::LoadPlugin( const std::string& dllFilename )
|
|||
pathname = override_filename;
|
||||
}
|
||||
#endif // P3D_PLUGIN_P3D_PLUGIN
|
||||
|
||||
|
||||
nout << "Attempting to load core API from " << pathname << "\n";
|
||||
string contents_filename = m_rootDir + "/contents.xml";
|
||||
if (!load_plugin(pathname, contents_filename, PANDA_PACKAGE_HOST_URL,
|
||||
P3D_VC_normal, "", "", "", false, false,
|
||||
m_rootDir, "", nout)) {
|
||||
P3D_VC_normal, "", "", "", false, false,
|
||||
m_rootDir, "", "", nout)) {
|
||||
nout << "Unable to launch core API in " << pathname << "\n";
|
||||
error = 1;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1738,8 +1738,8 @@ do_load_plugin() {
|
|||
nout << "Attempting to load core API from " << pathname << "\n";
|
||||
string contents_filename = _root_dir + "/contents.xml";
|
||||
if (!load_plugin(pathname, contents_filename, PANDA_PACKAGE_HOST_URL,
|
||||
P3D_VC_normal, "", "", "", false, false,
|
||||
_root_dir, "", nout)) {
|
||||
P3D_VC_normal, "", "", "", false, false,
|
||||
_root_dir, "", "", nout)) {
|
||||
nout << "Unable to launch core API in " << pathname << "\n";
|
||||
set_failed();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ run_embedded(streampos read_offset, int argc, char *argv[]) {
|
|||
// the + 1 from the test.
|
||||
_read_offset_check = read_offset + (streampos)1;
|
||||
if (_read_offset_check == (streampos)0xFF3D3D01) {
|
||||
cerr << "This program is not intended to be run directly.\nIt is used by pdeploy to construct an embedded Panda3D application.\n";
|
||||
cerr << "This program is not intended to be run directly.\nIt is used "
|
||||
"by pdeploy to construct an embedded Panda3D application.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -86,22 +87,30 @@ run_embedded(streampos read_offset, int argc, char *argv[]) {
|
|||
string value;
|
||||
string root_dir;
|
||||
string host_dir;
|
||||
string start_dir;
|
||||
|
||||
while (true) {
|
||||
if (curchr == EOF) {
|
||||
cerr << "Truncated stream\n";
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
} else if (curchr == 0) {
|
||||
// Two null bytes in a row means we've reached the end of the data.
|
||||
if (havenull) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// This means we haven't seen an '=' character yet.
|
||||
if (keyword == "") {
|
||||
if (curstr != "") {
|
||||
cerr << "Ignoring token '" << curstr << "' without value\n";
|
||||
}
|
||||
|
||||
} else if (keyword == "start_dir") {
|
||||
// Don't pass this on as a token, since it has slightly different
|
||||
// semantics when used as an HTML token.
|
||||
start_dir = curstr;
|
||||
|
||||
} else {
|
||||
value.assign(curstr);
|
||||
P3D_token token;
|
||||
|
|
@ -118,6 +127,8 @@ run_embedded(streampos read_offset, int argc, char *argv[]) {
|
|||
_got_win_size = true;
|
||||
} else if (keyword == "log_basename") {
|
||||
_log_basename = value;
|
||||
} else if (keyword == "log_directory") {
|
||||
_log_dirname = value;
|
||||
} else if (keyword == "root_dir") {
|
||||
root_dir = value;
|
||||
} else if (keyword == "host_dir") {
|
||||
|
|
@ -168,6 +179,13 @@ run_embedded(streampos read_offset, int argc, char *argv[]) {
|
|||
_host_dir = host_dir_f.to_os_specific();
|
||||
}
|
||||
|
||||
// Make the start directory absolute
|
||||
if (!start_dir.empty()) {
|
||||
Filename start_dir_f(start_dir);
|
||||
start_dir_f.make_absolute(f.get_dirname());
|
||||
_start_dir = start_dir_f.to_os_specific();
|
||||
}
|
||||
|
||||
// Initialize the core API by directly assigning all of the function
|
||||
// pointers.
|
||||
P3D_initialize_ptr = &P3D_initialize;
|
||||
|
|
@ -229,18 +247,17 @@ run_embedded(streampos read_offset, int argc, char *argv[]) {
|
|||
// function pointers. This will also call P3D_initialize().
|
||||
if (!init_plugin("", _host_url, _verify_contents, _this_platform,
|
||||
_log_dirname, _log_basename, true, _console_environment,
|
||||
_root_dir, _host_dir, cerr)) {
|
||||
_root_dir, _host_dir, _start_dir, cerr)) {
|
||||
cerr << "Unable to launch core API\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Create a plugin instance and run the program
|
||||
P3D_instance *inst = create_instance(f, true, argv, argc, read_offset);
|
||||
_instances.insert(inst);
|
||||
|
||||
run_main_loop();
|
||||
|
||||
|
||||
unload_plugin(cerr);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,6 +356,7 @@ bool Panda3D::
|
|||
get_plugin() {
|
||||
// First, look for the existing contents.xml file.
|
||||
bool success = false;
|
||||
bool is_fresh = false;
|
||||
|
||||
Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
|
||||
if (_verify_contents != P3D_VC_force) {
|
||||
|
|
@ -370,75 +371,100 @@ get_plugin() {
|
|||
if (!success) {
|
||||
// Couldn't read it (or it wasn't current enough), so go get a new
|
||||
// one.
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
|
||||
// Try the super_mirror first.
|
||||
if (!_super_mirror_url_prefix.empty()) {
|
||||
// We don't bother putting a uniquifying query string when we're
|
||||
// downloading this file from the super_mirror. The super_mirror
|
||||
// is by definition a cache, so it doesn't make sense to bust
|
||||
// caches here.
|
||||
string url = _super_mirror_url_prefix + "contents.xml";
|
||||
PT(HTTPChannel) channel = http->make_channel(false);
|
||||
channel->get_document(url);
|
||||
|
||||
Filename tempfile = Filename::temporary("", "p3d_");
|
||||
if (!channel->download_to_file(tempfile)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
tempfile.unlink();
|
||||
} else {
|
||||
// Successfully downloaded from the super_mirror; try to read it.
|
||||
success = read_contents_file(tempfile, true);
|
||||
tempfile.unlink();
|
||||
}
|
||||
if (!download_contents_file(contents_filename)) {
|
||||
// We don't have a usable contents.xml file.
|
||||
return false;
|
||||
}
|
||||
is_fresh = true;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Go download contents.xml from the actual host.
|
||||
ostringstream strm;
|
||||
strm << _host_url_prefix << "contents.xml";
|
||||
// Append a uniquifying query string to the URL to force the
|
||||
// download to go all the way through any caches. We use the time
|
||||
// in seconds; that's unique enough.
|
||||
strm << "?" << time(NULL);
|
||||
string url = strm.str();
|
||||
|
||||
// We might as well explicitly request the cache to be disabled too,
|
||||
// since we have an interface for that via HTTPChannel.
|
||||
DocumentSpec request(url);
|
||||
request.set_cache_control(DocumentSpec::CC_no_cache);
|
||||
|
||||
PT(HTTPChannel) channel = http->make_channel(false);
|
||||
channel->get_document(request);
|
||||
|
||||
// Since we have to download some of it, might as well ask the core
|
||||
// API to check all of it.
|
||||
if (_verify_contents == P3D_VC_none) {
|
||||
_verify_contents = P3D_VC_normal;
|
||||
}
|
||||
|
||||
// First, download it to a temporary file.
|
||||
Filename tempfile = Filename::temporary("", "p3d_");
|
||||
if (!channel->download_to_file(tempfile)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
|
||||
// Couldn't download, but try to read the existing contents.xml
|
||||
// file anyway. Maybe it's good enough.
|
||||
success = read_contents_file(contents_filename, false);
|
||||
|
||||
} else {
|
||||
// Successfully downloaded; read it and move it into place.
|
||||
success = read_contents_file(tempfile, true);
|
||||
}
|
||||
// Now that we've downloaded the contents file successfully, start
|
||||
// the Core API.
|
||||
if (!get_core_api()) {
|
||||
// We failed. Make sure contents.xml is up-to-date and try again.
|
||||
if (!is_fresh && download_contents_file(contents_filename) && get_core_api()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::download_contents_file
|
||||
// Access: Protected
|
||||
// Description: Redownloads the contents.xml file from the named
|
||||
// URL without first checking if it is up to date.
|
||||
// Returns true if we have a contents.xml file that
|
||||
// might be usable, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
download_contents_file(const Filename &contents_filename) {
|
||||
bool success = false;
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
|
||||
// Try the super_mirror first.
|
||||
if (!_super_mirror_url_prefix.empty()) {
|
||||
// We don't bother putting a uniquifying query string when we're
|
||||
// downloading this file from the super_mirror. The super_mirror
|
||||
// is by definition a cache, so it doesn't make sense to bust
|
||||
// caches here.
|
||||
string url = _super_mirror_url_prefix + "contents.xml";
|
||||
PT(HTTPChannel) channel = http->make_channel(false);
|
||||
channel->get_document(url);
|
||||
|
||||
Filename tempfile = Filename::temporary("", "p3d_");
|
||||
if (!channel->download_to_file(tempfile)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
tempfile.unlink();
|
||||
} else {
|
||||
// Successfully downloaded from the super_mirror; try to read it.
|
||||
success = read_contents_file(tempfile, true);
|
||||
tempfile.unlink();
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
// Now that we've downloaded the contents file successfully, start
|
||||
// the Core API.
|
||||
success = get_core_api();
|
||||
if (!success) {
|
||||
// Go download contents.xml from the actual host.
|
||||
ostringstream strm;
|
||||
strm << _host_url_prefix << "contents.xml";
|
||||
// Append a uniquifying query string to the URL to force the
|
||||
// download to go all the way through any caches. We use the time
|
||||
// in seconds; that's unique enough.
|
||||
strm << "?" << time(NULL);
|
||||
string url = strm.str();
|
||||
|
||||
// We might as well explicitly request the cache to be disabled too,
|
||||
// since we have an interface for that via HTTPChannel.
|
||||
DocumentSpec request(url);
|
||||
request.set_cache_control(DocumentSpec::CC_no_cache);
|
||||
|
||||
PT(HTTPChannel) channel = http->make_channel(false);
|
||||
channel->get_document(request);
|
||||
|
||||
// Since we have to download some of it, might as well ask the core
|
||||
// API to check all of it.
|
||||
if (_verify_contents == P3D_VC_none) {
|
||||
_verify_contents = P3D_VC_normal;
|
||||
}
|
||||
|
||||
// First, download it to a temporary file.
|
||||
Filename tempfile = Filename::temporary("", "p3d_");
|
||||
if (!channel->download_to_file(tempfile)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
|
||||
// Couldn't download, but try to read the existing contents.xml
|
||||
// file anyway. Maybe it's good enough.
|
||||
success = read_contents_file(contents_filename, false);
|
||||
|
||||
} else {
|
||||
// Successfully downloaded; read it and move it into place.
|
||||
success = read_contents_file(tempfile, true);
|
||||
}
|
||||
|
||||
tempfile.unlink();
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
@ -690,7 +716,6 @@ choose_random_mirrors(vector_string &result, int num_mirrors) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::get_core_api
|
||||
// Access: Protected
|
||||
|
|
@ -700,78 +725,12 @@ choose_random_mirrors(vector_string &result, int num_mirrors) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
get_core_api() {
|
||||
bool is_fresh = false;
|
||||
if (!_coreapi_dll.quick_verify(_root_dir)) {
|
||||
// The DLL file needs to be downloaded. Build up our list of
|
||||
// URL's to attempt to download it from, in reverse order.
|
||||
string url;
|
||||
vector_string core_urls;
|
||||
|
||||
// Our last act of desperation: hit the original host, with a
|
||||
// query uniquifier, to break through any caches.
|
||||
ostringstream strm;
|
||||
strm << _download_url_prefix << _coreapi_dll.get_filename()
|
||||
<< "?" << time(NULL);
|
||||
url = strm.str();
|
||||
core_urls.push_back(url);
|
||||
|
||||
// Before we try that, we'll hit the original host, without a
|
||||
// uniquifier.
|
||||
url = _download_url_prefix;
|
||||
url += _coreapi_dll.get_filename();
|
||||
core_urls.push_back(url);
|
||||
|
||||
// And before we try that, we'll try two mirrors, at random.
|
||||
vector_string mirrors;
|
||||
choose_random_mirrors(mirrors, 2);
|
||||
for (vector_string::iterator si = mirrors.begin();
|
||||
si != mirrors.end();
|
||||
++si) {
|
||||
url = (*si) + _coreapi_dll.get_filename();
|
||||
core_urls.push_back(url);
|
||||
}
|
||||
|
||||
// The very first thing we'll try is the super_mirror, if we have
|
||||
// one.
|
||||
if (!_super_mirror_url_prefix.empty()) {
|
||||
url = _super_mirror_url_prefix + _coreapi_dll.get_filename();
|
||||
core_urls.push_back(url);
|
||||
}
|
||||
|
||||
// Now pick URL's off the list, and try them, until we have
|
||||
// success.
|
||||
Filename pathname = Filename::from_os_specific(_coreapi_dll.get_pathname(_root_dir));
|
||||
pathname.make_dir();
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
|
||||
bool success = false;
|
||||
while (!core_urls.empty()) {
|
||||
url = core_urls.back();
|
||||
core_urls.pop_back();
|
||||
|
||||
PT(HTTPChannel) channel = http->get_document(url);
|
||||
if (!channel->download_to_file(pathname)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
|
||||
} else if (!_coreapi_dll.full_verify(_root_dir)) {
|
||||
cerr << "Mismatched download for " << url << "\n";
|
||||
|
||||
} else {
|
||||
// successfully downloaded!
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
cerr << "Couldn't download core API.\n";
|
||||
if (!download_core_api()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we had to download some of it, might as well ask the core
|
||||
// API to check all of it.
|
||||
if (_verify_contents == P3D_VC_none) {
|
||||
_verify_contents = P3D_VC_normal;
|
||||
}
|
||||
is_fresh = true;
|
||||
}
|
||||
|
||||
// Now we've got the DLL. Load it.
|
||||
|
|
@ -795,9 +754,19 @@ get_core_api() {
|
|||
if (!load_plugin(pathname, contents_filename.to_os_specific(),
|
||||
_host_url, _verify_contents, _this_platform, _log_dirname,
|
||||
_log_basename, trusted_environment, _console_environment,
|
||||
_root_dir, "", cerr)) {
|
||||
cerr << "Unable to launch core API in " << pathname << "\n";
|
||||
return false;
|
||||
_root_dir, _host_dir, _start_dir, cerr)) {
|
||||
|
||||
// If we're not sure this is the latest version, make sure it is
|
||||
// up-to-date, and then try again.
|
||||
if (is_fresh || !download_core_api() ||
|
||||
!load_plugin(pathname, contents_filename.to_os_specific(),
|
||||
_host_url, _verify_contents, _this_platform, _log_dirname,
|
||||
_log_basename, trusted_environment, _console_environment,
|
||||
_root_dir, _host_dir, _start_dir, cerr)) {
|
||||
|
||||
cerr << "Unable to launch core API in " << pathname << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Successfully loaded.
|
||||
|
|
@ -822,6 +791,87 @@ get_core_api() {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::download_core_api
|
||||
// Access: Protected
|
||||
// Description: Downloads the latest version of the core API from
|
||||
// the plug-in server.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
download_core_api() {
|
||||
// The DLL file needs to be downloaded. Build up our list of
|
||||
// URL's to attempt to download it from, in reverse order.
|
||||
string url;
|
||||
vector_string core_urls;
|
||||
|
||||
// Our last act of desperation: hit the original host, with a
|
||||
// query uniquifier, to break through any caches.
|
||||
ostringstream strm;
|
||||
strm << _download_url_prefix << _coreapi_dll.get_filename()
|
||||
<< "?" << time(NULL);
|
||||
url = strm.str();
|
||||
core_urls.push_back(url);
|
||||
|
||||
// Before we try that, we'll hit the original host, without a
|
||||
// uniquifier.
|
||||
url = _download_url_prefix;
|
||||
url += _coreapi_dll.get_filename();
|
||||
core_urls.push_back(url);
|
||||
|
||||
// And before we try that, we'll try two mirrors, at random.
|
||||
vector_string mirrors;
|
||||
choose_random_mirrors(mirrors, 2);
|
||||
for (vector_string::iterator si = mirrors.begin();
|
||||
si != mirrors.end();
|
||||
++si) {
|
||||
url = (*si) + _coreapi_dll.get_filename();
|
||||
core_urls.push_back(url);
|
||||
}
|
||||
|
||||
// The very first thing we'll try is the super_mirror, if we have
|
||||
// one.
|
||||
if (!_super_mirror_url_prefix.empty()) {
|
||||
url = _super_mirror_url_prefix + _coreapi_dll.get_filename();
|
||||
core_urls.push_back(url);
|
||||
}
|
||||
|
||||
// Now pick URL's off the list, and try them, until we have
|
||||
// success.
|
||||
Filename pathname = Filename::from_os_specific(_coreapi_dll.get_pathname(_root_dir));
|
||||
pathname.make_dir();
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
|
||||
bool success = false;
|
||||
while (!core_urls.empty()) {
|
||||
url = core_urls.back();
|
||||
core_urls.pop_back();
|
||||
|
||||
PT(HTTPChannel) channel = http->get_document(url);
|
||||
if (!channel->download_to_file(pathname)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
|
||||
} else if (!_coreapi_dll.full_verify(_root_dir)) {
|
||||
cerr << "Mismatched download for " << url << "\n";
|
||||
|
||||
} else {
|
||||
// successfully downloaded!
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we had to download some of it, might as well ask the core
|
||||
// API to check all of it.
|
||||
if (_verify_contents == P3D_VC_none) {
|
||||
_verify_contents = P3D_VC_normal;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::usage
|
||||
// Access: Protected
|
||||
|
|
|
|||
|
|
@ -42,12 +42,14 @@ public:
|
|||
protected:
|
||||
bool post_arg_processing();
|
||||
bool get_plugin();
|
||||
bool download_contents_file(const Filename &contents_filename);
|
||||
bool read_contents_file(const Filename &contents_filename, bool fresh_download);
|
||||
void find_host(TiXmlElement *xcontents);
|
||||
void read_xhost(TiXmlElement *xhost);
|
||||
void add_mirror(string mirror_url);
|
||||
void choose_random_mirrors(vector_string &result, int num_mirrors);
|
||||
bool get_core_api();
|
||||
bool download_core_api();
|
||||
|
||||
void usage();
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ make_parent_window() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
P3D_instance *Panda3DBase::
|
||||
create_instance(const string &p3d, bool start_instance,
|
||||
char **args, int num_args, const int &p3d_offset) {
|
||||
char **args, int num_args, int p3d_offset) {
|
||||
// Check to see if the p3d filename we were given is a URL, or a
|
||||
// local file.
|
||||
Filename p3d_filename = Filename::from_os_specific(p3d);
|
||||
|
|
@ -356,9 +356,9 @@ create_instance(const string &p3d, bool start_instance,
|
|||
|
||||
p3d_filename.make_absolute();
|
||||
os_p3d_filename = p3d_filename.to_os_specific();
|
||||
}
|
||||
}
|
||||
if (is_local) {
|
||||
read_p3d_info(p3d_filename);
|
||||
read_p3d_info(p3d_filename, p3d_offset);
|
||||
}
|
||||
|
||||
// Build up the token list.
|
||||
|
|
@ -454,9 +454,9 @@ delete_instance(P3D_instance *inst) {
|
|||
// parameters (like width and height).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3DBase::
|
||||
read_p3d_info(const Filename &p3d_filename) {
|
||||
read_p3d_info(const Filename &p3d_filename, int p3d_offset) {
|
||||
PT(Multifile) mf = new Multifile;
|
||||
if (!mf->open_read(p3d_filename)) {
|
||||
if (!mf->open_read(p3d_filename, p3d_offset)) {
|
||||
return false;
|
||||
}
|
||||
int si = mf->find_subfile("p3d_info.xml");
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ protected:
|
|||
|
||||
P3D_instance *
|
||||
create_instance(const string &p3d, bool start_instance,
|
||||
char **args, int num_args, const int &p3d_offset = 0);
|
||||
char **args, int num_args, int p3d_offset = 0);
|
||||
void delete_instance(P3D_instance *instance);
|
||||
|
||||
bool read_p3d_info(const Filename &p3d_filename);
|
||||
bool read_p3d_info(const Filename &p3d_filename, int p3d_offset = 0);
|
||||
bool parse_token(const char *arg);
|
||||
bool parse_int_pair(const char *arg, int &x, int &y);
|
||||
string lookup_token(const string &keyword) const;
|
||||
|
|
@ -74,6 +74,7 @@ protected:
|
|||
string _host_url;
|
||||
string _root_dir;
|
||||
string _host_dir;
|
||||
string _start_dir;
|
||||
string _log_dirname;
|
||||
string _log_basename;
|
||||
string _this_platform;
|
||||
|
|
|
|||
|
|
@ -855,7 +855,7 @@ class Loader(DirectObject):
|
|||
def loadShader (self, shaderPath, okMissing = False):
|
||||
shader = ShaderPool.loadShader (shaderPath)
|
||||
if not shader and not okMissing:
|
||||
message = 'Could not shader file: %s' % (shaderPath)
|
||||
message = 'Could not load shader file: %s' % (shaderPath)
|
||||
raise IOError, message
|
||||
return shader
|
||||
|
||||
|
|
|
|||
|
|
@ -1993,7 +1993,7 @@ def pstatcollect(scope, level = None):
|
|||
|
||||
try:
|
||||
|
||||
if not (__dev__ or config.GetBool('force-pstatcollect', 0)) or \
|
||||
if not (__dev__ or ConfigVariableBool('force-pstatcollect', False)) or \
|
||||
not scope:
|
||||
return decorator
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ __all__ = ['ShowBase', 'WindowControls']
|
|||
|
||||
from panda3d.core import *
|
||||
from panda3d.direct import get_config_showbase, throw_new_frame, init_app_for_gui
|
||||
from panda3d.direct import storeAccessibilityShortcutKeys, allowAccessibilityShortcutKeys
|
||||
|
||||
|
||||
# This needs to be available early for DirectGUI imports
|
||||
import __builtin__ as builtins
|
||||
|
|
@ -70,6 +72,8 @@ class ShowBase(DirectObject.DirectObject):
|
|||
if logStackDump or uploadStackDump:
|
||||
ExceptionVarDump.install(logStackDump, uploadStackDump)
|
||||
|
||||
self.__autoGarbageLogging = self.__dev__ and self.config.GetBool('auto-garbage-logging', False)
|
||||
|
||||
## The directory containing the main Python file of this application.
|
||||
self.mainDir = ExecutionEnvironment.getEnvironmentVariable("MAIN_DIR")
|
||||
|
||||
|
|
@ -289,7 +293,6 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.physicsMgrEnabled = 0
|
||||
self.physicsMgrAngular = 0
|
||||
|
||||
self.createBaseAudioManagers()
|
||||
self.createStats()
|
||||
|
||||
self.AppHasAudioFocus = 1
|
||||
|
|
@ -377,6 +380,8 @@ class ShowBase(DirectObject.DirectObject):
|
|||
else:
|
||||
ShowBase.notify.info('__dev__ == %s' % __dev__)
|
||||
|
||||
self.createBaseAudioManagers()
|
||||
|
||||
# set up recording of Functor creation stacks in __dev__
|
||||
PythonUtil.recordFunctorCreationStacks()
|
||||
|
||||
|
|
@ -526,9 +531,6 @@ class ShowBase(DirectObject.DirectObject):
|
|||
del self.winList
|
||||
del self.pipe
|
||||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
vfs.unmountAll()
|
||||
|
||||
def makeDefaultPipe(self, printPipeTypes = True):
|
||||
"""
|
||||
Creates the default GraphicsPipe, which will be used to make
|
||||
|
|
@ -2660,7 +2662,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
if not properties.getOpen():
|
||||
# If the user closes the main window, we should exit.
|
||||
self.notify.info("User closed main window.")
|
||||
if __dev__ and config.GetBool('auto-garbage-logging', 0):
|
||||
if self.__autoGarbageLogging:
|
||||
GarbageReport.b_checkForGarbageLeaks()
|
||||
self.userExit()
|
||||
|
||||
|
|
@ -2668,7 +2670,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.mainWinForeground = 1
|
||||
elif not properties.getForeground() and self.mainWinForeground:
|
||||
self.mainWinForeground = 0
|
||||
if __dev__ and config.GetBool('auto-garbage-logging', 0):
|
||||
if self.__autoGarbageLogging:
|
||||
GarbageReport.b_checkForGarbageLeaks()
|
||||
|
||||
if properties.getMinimized() and not self.mainWinMinimized:
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ class Transitions:
|
|||
self.loadFade()
|
||||
self.fade.reparentTo(aspect2d, FADE_SORT_INDEX)
|
||||
self.fade.setColor(self.alphaOn)
|
||||
elif base.config.GetBool('no-loading-screen',0):
|
||||
elif ConfigVariableBool('no-loading-screen', False):
|
||||
if finishIval:
|
||||
self.transitionIval = finishIval
|
||||
self.transitionIval.start()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
__all__ = ['register', 'sharedPackages',
|
||||
'reloadSharedPackage', 'reloadSharedPackages']
|
||||
|
||||
from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
|
||||
from panda3d._core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
|
||||
import sys
|
||||
import marshal
|
||||
import imp
|
||||
|
|
@ -25,12 +25,6 @@ sharedPackages = {}
|
|||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
|
||||
# Possible file types.
|
||||
FTPythonSource = 0
|
||||
FTPythonCompiled = 1
|
||||
FTExtensionModule = 2
|
||||
FTFrozenModule = 3
|
||||
|
||||
compiledExtensions = [ 'pyc', 'pyo' ]
|
||||
if not __debug__:
|
||||
# In optimized mode, we prefer loading .pyo files over .pyc files.
|
||||
|
|
@ -44,7 +38,10 @@ class VFSImporter:
|
|||
(among other places). """
|
||||
|
||||
def __init__(self, path):
|
||||
self.dir_path = Filename.fromOsSpecific(path)
|
||||
if isinstance(path, Filename):
|
||||
self.dir_path = Filename(path)
|
||||
else:
|
||||
self.dir_path = Filename.fromOsSpecific(path)
|
||||
|
||||
def find_module(self, fullname, path = None):
|
||||
if path is None:
|
||||
|
|
@ -60,7 +57,8 @@ class VFSImporter:
|
|||
filename.setExtension('py')
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(dir_path, vfile, filename, FTPythonSource)
|
||||
return VFSLoader(dir_path, vfile, filename,
|
||||
desc=('.py', 'U', imp.PY_SOURCE))
|
||||
|
||||
# If there's no .py file, but there's a .pyc file, load that
|
||||
# anyway.
|
||||
|
|
@ -69,33 +67,32 @@ class VFSImporter:
|
|||
filename.setExtension(ext)
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(dir_path, vfile, filename, FTPythonCompiled)
|
||||
return VFSLoader(dir_path, vfile, filename,
|
||||
desc=('.'+ext, 'rb', imp.PY_COMPILED))
|
||||
|
||||
# Look for a C/C++ extension module.
|
||||
for desc in imp.get_suffixes():
|
||||
if desc[2] != imp.C_EXTENSION:
|
||||
continue
|
||||
|
||||
filename = Filename(path)
|
||||
filename.setExtension(desc[0][1:])
|
||||
filename = Filename(path + desc[0])
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(dir_path, vfile, filename, FTExtensionModule,
|
||||
desc = desc)
|
||||
return VFSLoader(dir_path, vfile, filename, desc=desc)
|
||||
|
||||
# Finally, consider a package, i.e. a directory containing
|
||||
# __init__.py.
|
||||
filename = Filename(path, '__init__.py')
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(dir_path, vfile, filename, FTPythonSource,
|
||||
packagePath = path)
|
||||
return VFSLoader(dir_path, vfile, filename, packagePath=path,
|
||||
desc=('.py', 'U', imp.PY_SOURCE))
|
||||
for ext in compiledExtensions:
|
||||
filename = Filename(path, '__init__.' + ext)
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(dir_path, vfile, filename, FTPythonCompiled,
|
||||
packagePath = path)
|
||||
return VFSLoader(dir_path, vfile, filename, packagePath=path,
|
||||
desc=('.'+ext, 'rb', imp.PY_COMPILED))
|
||||
|
||||
#print >>sys.stderr, "not found."
|
||||
return None
|
||||
|
|
@ -104,22 +101,20 @@ 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):
|
||||
def __init__(self, dir_path, vfile, filename, desc, packagePath=None):
|
||||
self.dir_path = dir_path
|
||||
self.timestamp = None
|
||||
if vfile:
|
||||
self.timestamp = vfile.getTimestamp()
|
||||
self.filename = filename
|
||||
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:
|
||||
if self.desc[2] == imp.PY_FROZEN:
|
||||
return self._import_frozen_module(fullname)
|
||||
if self.fileType == FTExtensionModule:
|
||||
if self.desc[2] == imp.C_EXTENSION:
|
||||
return self._import_extension_module(fullname)
|
||||
|
||||
# Check if this is a child of a shared package.
|
||||
|
|
@ -137,7 +132,7 @@ class VFSLoader:
|
|||
|
||||
code = self._read_code()
|
||||
if not code:
|
||||
raise ImportError, 'No Python code in %s' % (fullname)
|
||||
raise ImportError('No Python code in %s' % (fullname))
|
||||
|
||||
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
|
||||
mod.__file__ = self.filename.toOsSpecific()
|
||||
|
|
@ -153,7 +148,7 @@ class VFSLoader:
|
|||
path = Filename(self.dir_path, Filename.fromOsSpecific(path))
|
||||
vfile = vfs.getFile(path)
|
||||
if not vfile:
|
||||
raise IOError
|
||||
raise IOError("Could not find '%s'" % (path))
|
||||
return vfile.readFile(True)
|
||||
|
||||
def is_package(self, fullname):
|
||||
|
|
@ -172,8 +167,8 @@ class VFSLoader:
|
|||
""" 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:
|
||||
if self.desc[2] == imp.PY_COMPILED or \
|
||||
self.desc[2] == imp.C_EXTENSION:
|
||||
return None
|
||||
|
||||
filename = Filename(self.filename)
|
||||
|
|
@ -181,7 +176,7 @@ class VFSLoader:
|
|||
filename.setText()
|
||||
vfile = vfs.getFile(filename)
|
||||
if not vfile:
|
||||
raise IOError
|
||||
raise IOError("Could not find '%s'" % (filename))
|
||||
return vfile.readFile(True)
|
||||
|
||||
def _import_extension_module(self, fullname):
|
||||
|
|
@ -231,6 +226,10 @@ class VFSLoader:
|
|||
#print >>sys.stderr, "importing frozen %s" % (fullname)
|
||||
module = imp.load_module(fullname, None, fullname,
|
||||
('', '', imp.PY_FROZEN))
|
||||
|
||||
# Workaround for bug in Python 2.
|
||||
if getattr(module, '__path__', None) == fullname:
|
||||
module.__path__ = []
|
||||
return module
|
||||
|
||||
def _read_code(self):
|
||||
|
|
@ -239,14 +238,14 @@ class VFSLoader:
|
|||
ValueError, SyntaxError, or a number of other errors generated
|
||||
by the low-level system. """
|
||||
|
||||
if self.fileType == FTPythonCompiled:
|
||||
if self.desc[2] == imp.PY_COMPILED:
|
||||
# It's a pyc file; just read it directly.
|
||||
pycVfile = vfs.getFile(self.filename, False)
|
||||
if pycVfile:
|
||||
return self._loadPyc(pycVfile, None)
|
||||
raise IOError, 'Could not read %s' % (self.filename)
|
||||
raise IOError('Could not read %s' % (self.filename))
|
||||
|
||||
elif self.fileType == FTExtensionModule:
|
||||
elif self.desc[2] == imp.C_EXTENSION:
|
||||
return None
|
||||
|
||||
# It's a .py file (or an __init__.py file; same thing). Read
|
||||
|
|
@ -282,16 +281,21 @@ class VFSLoader:
|
|||
|
||||
code = None
|
||||
data = vfile.readFile(True)
|
||||
if data[:4] == imp.get_magic():
|
||||
if data[:4] != imp.get_magic():
|
||||
raise ValueError("Bad magic number in %s" % (vfile))
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
t = int.from_bytes(data[4:8], 'little')
|
||||
data = data[12:]
|
||||
else:
|
||||
t = ord(data[4]) + (ord(data[5]) << 8) + \
|
||||
(ord(data[6]) << 16) + (ord(data[7]) << 24)
|
||||
if not timestamp or t == timestamp:
|
||||
code = marshal.loads(data[8:])
|
||||
else:
|
||||
raise ValueError, 'Timestamp wrong on %s' % (vfile)
|
||||
data = data[8:]
|
||||
|
||||
if not timestamp or t == timestamp:
|
||||
return marshal.loads(data)
|
||||
else:
|
||||
raise ValueError, 'Bad magic number in %s' % (vfile)
|
||||
return code
|
||||
raise ValueError("Timestamp wrong on %s" % (vfile))
|
||||
|
||||
|
||||
def _compile(self, filename, source):
|
||||
|
|
@ -311,15 +315,16 @@ class VFSLoader:
|
|||
except IOError:
|
||||
pass
|
||||
else:
|
||||
f.write('\0\0\0\0')
|
||||
f.write(chr(self.timestamp & 0xff) +
|
||||
chr((self.timestamp >> 8) & 0xff) +
|
||||
chr((self.timestamp >> 16) & 0xff) +
|
||||
chr((self.timestamp >> 24) & 0xff))
|
||||
f.write(marshal.dumps(code))
|
||||
f.flush()
|
||||
f.seek(0, 0)
|
||||
f.write(imp.get_magic())
|
||||
if sys.version_info >= (3, 0):
|
||||
f.write((self.timestamp & 0xffffffff).to_bytes(4, 'little'))
|
||||
f.write(b'\0\0\0\0')
|
||||
else:
|
||||
f.write(chr(self.timestamp & 0xff) +
|
||||
chr((self.timestamp >> 8) & 0xff) +
|
||||
chr((self.timestamp >> 16) & 0xff) +
|
||||
chr((self.timestamp >> 24) & 0xff))
|
||||
f.write(marshal.dumps(code))
|
||||
f.close()
|
||||
|
||||
return code
|
||||
|
|
@ -389,7 +394,7 @@ 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:
|
||||
if not getattr(mod, '__file__', None):
|
||||
return None
|
||||
|
||||
fullname = mod.__name__
|
||||
|
|
@ -434,6 +439,9 @@ class VFSSharedLoader:
|
|||
if self.reload:
|
||||
mod = sys.modules[fullname]
|
||||
path = mod.__path__ or []
|
||||
if path == fullname:
|
||||
# Work around Python bug setting __path__ of frozen modules.
|
||||
path = []
|
||||
vfs_shared_path = getattr(mod, '_vfs_shared_path', [])
|
||||
|
||||
for loader in self.loaders:
|
||||
|
|
@ -451,11 +459,12 @@ class VFSSharedLoader:
|
|||
|
||||
if mod is None:
|
||||
# If all of them failed to load, raise ImportError.
|
||||
raise ImportError, message
|
||||
raise ImportError(message)
|
||||
|
||||
# If at least one of them loaded successfully, return the
|
||||
# union of loaded modules.
|
||||
mod.__path__ = path
|
||||
mod.__package__ = fullname
|
||||
|
||||
# Also set this special symbol, which records that this is a
|
||||
# shared package, and also lists the paths we have already
|
||||
|
|
@ -516,7 +525,9 @@ def reloadSharedPackages():
|
|||
|
||||
#print >> sys.stderr, "reloadSharedPackages, path = %s, sharedPackages = %s" % (sys.path, sharedPackages.keys())
|
||||
|
||||
for fullname in sharedPackages.keys():
|
||||
# Sort the list, just to make sure parent packages are reloaded
|
||||
# before child packages are.
|
||||
for fullname in sorted(sharedPackages.keys()):
|
||||
mod = sys.modules.get(fullname, None)
|
||||
if not mod:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import marshal
|
|||
import imp
|
||||
import platform
|
||||
import types
|
||||
from distutils.sysconfig import PREFIX, get_python_inc, get_python_version
|
||||
from StringIO import StringIO
|
||||
from distutils.sysconfig import PREFIX, get_python_inc, get_python_version, get_config_var
|
||||
|
||||
# Temporary (?) try..except to protect against unbuilt p3extend_frozen.
|
||||
try:
|
||||
|
|
@ -17,7 +18,6 @@ except ImportError:
|
|||
p3extend_frozen = None
|
||||
|
||||
from panda3d.core import *
|
||||
from pandac.extension_native_helpers import dll_suffix, dll_ext
|
||||
|
||||
# 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.
|
||||
|
|
@ -31,14 +31,12 @@ isDebugBuild = (python.lower().endswith('_d'))
|
|||
# must be frozen in any main.exe.
|
||||
startupModules = [
|
||||
'site', 'sitecustomize', 'os', 'encodings.cp1252',
|
||||
'org',
|
||||
'encodings.latin_1', 'encodings.utf_8', 'io', 'org',
|
||||
]
|
||||
|
||||
# These are missing modules that we've reported already this session.
|
||||
reportedMissing = {}
|
||||
|
||||
# Our own Python source trees to watch out for.
|
||||
sourceTrees = ['direct']
|
||||
|
||||
class CompilationEnvironment:
|
||||
""" Create an instance of this class to record the commands to
|
||||
|
|
@ -64,7 +62,7 @@ class CompilationEnvironment:
|
|||
# Paths to Python stuff.
|
||||
self.Python = None
|
||||
self.PythonIPath = get_python_inc()
|
||||
self.PythonVersion = get_python_version()
|
||||
self.PythonVersion = get_config_var("LDVERSION") or get_python_version()
|
||||
|
||||
# The VC directory of Microsoft Visual Studio (if relevant)
|
||||
self.MSVC = None
|
||||
|
|
@ -445,7 +443,7 @@ extend_frozen_modules(const struct _frozen *new_modules, int new_count) {
|
|||
}
|
||||
|
||||
%(dllexport)svoid init%(moduleName)s() {
|
||||
extend_frozen_modules(_PyImport_FrozenModules, %(newcount)s);
|
||||
extend_frozen_modules(_PyImport_FrozenModules, sizeof(_PyImport_FrozenModules) / sizeof(struct _frozen));
|
||||
Py_InitModule("%(moduleName)s", nullMethods);
|
||||
}
|
||||
"""
|
||||
|
|
@ -458,7 +456,7 @@ programFile = """
|
|||
|
||||
%(moduleDefs)s
|
||||
|
||||
static struct _frozen _PyImport_FrozenModules[] = {
|
||||
struct _frozen _PyImport_FrozenModules[] = {
|
||||
%(moduleList)s
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
|
@ -485,7 +483,7 @@ okMissing = [
|
|||
'Carbon.Folder', 'Carbon.Folders', 'HouseGlobals', 'Carbon.File',
|
||||
'MacOS', '_emx_link', 'ce', 'mac', 'org.python.core', 'os.path',
|
||||
'os2', 'posix', 'pwd', 'readline', 'riscos', 'riscosenviron',
|
||||
'riscospath', 'dbm', 'fcntl', 'win32api',
|
||||
'riscospath', 'dbm', 'fcntl', 'win32api', 'usercustomize',
|
||||
'_winreg', 'ctypes', 'ctypes.wintypes', 'nt','msvcrt',
|
||||
'EasyDialogs', 'SOCKS', 'ic', 'rourl2path', 'termios',
|
||||
'OverrideFrom23._Res', 'email', 'email.Utils', 'email.Generator',
|
||||
|
|
@ -498,7 +496,8 @@ class Freezer:
|
|||
def __init__(self, moduleName, filename = None,
|
||||
implicit = False, guess = False,
|
||||
exclude = False, forbid = False,
|
||||
allowChildren = False, fromSource = None):
|
||||
allowChildren = False, fromSource = None,
|
||||
text = None):
|
||||
# The Python module name.
|
||||
self.moduleName = moduleName
|
||||
|
||||
|
|
@ -533,6 +532,9 @@ class Freezer:
|
|||
# record came from, supplied by the caller.
|
||||
self.fromSource = fromSource
|
||||
|
||||
# If this is set, it contains Python code of the module.
|
||||
self.text = text
|
||||
|
||||
# Some sanity checks.
|
||||
if not self.exclude:
|
||||
self.allowChildren = True
|
||||
|
|
@ -609,20 +611,14 @@ class Freezer:
|
|||
|
||||
self.mf = None
|
||||
|
||||
# Make sure we know how to find "direct".
|
||||
for sourceTree in sourceTrees:
|
||||
try:
|
||||
module = __import__(sourceTree)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Actually, make sure we know how to find all of the
|
||||
# already-imported modules. (Some of them might do their own
|
||||
# special path mangling.)
|
||||
for moduleName, module in sys.modules.items():
|
||||
if module and hasattr(module, '__path__'):
|
||||
path = getattr(module, '__path__')
|
||||
modulefinder.AddPackagePath(moduleName, path[0])
|
||||
if path:
|
||||
modulefinder.AddPackagePath(moduleName, path[0])
|
||||
|
||||
def excludeFrom(self, freezer):
|
||||
""" Excludes all modules that have already been processed by
|
||||
|
|
@ -749,7 +745,8 @@ class Freezer:
|
|||
return modules
|
||||
|
||||
def addModule(self, moduleName, implicit = False, newName = None,
|
||||
filename = None, guess = False, fromSource = None):
|
||||
filename = None, guess = False, fromSource = None,
|
||||
text = None):
|
||||
""" Adds a module to the list of modules to be exported by
|
||||
this tool. If implicit is true, it is OK if the module does
|
||||
not actually exist.
|
||||
|
|
@ -805,7 +802,7 @@ class Freezer:
|
|||
# It's actually a regular module.
|
||||
self.modules[newParentName] = self.ModuleDef(
|
||||
parentName, implicit = implicit, guess = guess,
|
||||
fromSource = fromSource)
|
||||
fromSource = fromSource, text = text)
|
||||
|
||||
else:
|
||||
# Now get all the py files in the parent directory.
|
||||
|
|
@ -820,9 +817,9 @@ class Freezer:
|
|||
# A normal, explicit module name.
|
||||
self.modules[newName] = self.ModuleDef(
|
||||
moduleName, filename = filename, implicit = implicit,
|
||||
guess = guess, fromSource = fromSource)
|
||||
guess = guess, fromSource = fromSource, text = text)
|
||||
|
||||
def done(self, compileToExe = False):
|
||||
def done(self, addStartupModules = False):
|
||||
""" Call this method after you have added all modules with
|
||||
addModule(). You may then call generateCode() or
|
||||
writeMultifile() to dump the resulting output. After a call
|
||||
|
|
@ -833,7 +830,9 @@ class Freezer:
|
|||
|
||||
# If we are building an exe, we also need to implicitly
|
||||
# bring in Python's startup modules.
|
||||
if compileToExe:
|
||||
if addStartupModules:
|
||||
self.modules['_frozen_importlib'] = self.ModuleDef('importlib._bootstrap', implicit = True)
|
||||
|
||||
for moduleName in startupModules:
|
||||
if moduleName not in self.modules:
|
||||
self.modules[moduleName] = self.ModuleDef(moduleName, implicit = True)
|
||||
|
|
@ -971,7 +970,10 @@ class Freezer:
|
|||
stuff = ("", "rb", imp.PY_COMPILED)
|
||||
self.mf.load_module(mdef.moduleName, fp, pathname, stuff)
|
||||
else:
|
||||
fp = open(pathname, modulefinder.READ_MODE)
|
||||
if mdef.text:
|
||||
fp = StringIO(mdef.text)
|
||||
else:
|
||||
fp = open(pathname, 'U')
|
||||
stuff = ("", "r", imp.PY_SOURCE)
|
||||
self.mf.load_module(mdef.moduleName, fp, pathname, stuff)
|
||||
|
||||
|
|
@ -1063,8 +1065,12 @@ class Freezer:
|
|||
|
||||
def __addPyc(self, multifile, filename, code, compressionLevel):
|
||||
if code:
|
||||
data = imp.get_magic() + '\0\0\0\0' + \
|
||||
marshal.dumps(code)
|
||||
data = imp.get_magic() + b'\0\0\0\0'
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
data += b'\0\0\0\0'
|
||||
|
||||
data += marshal.dumps(code)
|
||||
|
||||
stream = StringStream(data)
|
||||
multifile.addSubfile(filename, stream, compressionLevel)
|
||||
|
|
@ -1206,22 +1212,9 @@ class Freezer:
|
|||
multifile.flush()
|
||||
multifile.repack()
|
||||
|
||||
def generateCode(self, basename, compileToExe = False):
|
||||
""" After a call to done(), this freezes all of the
|
||||
accumulated python code into either an executable program (if
|
||||
compileToExe is true) or a dynamic library (if compileToExe is
|
||||
false). The basename is the name of the file to write,
|
||||
without the extension.
|
||||
|
||||
The return value is the newly-generated filename, including
|
||||
the filename extension. Additional extension modules are
|
||||
listed in self.extras. """
|
||||
|
||||
if compileToExe:
|
||||
# We must have a __main__ module to make an exe file.
|
||||
if not self.__writingModule('__main__'):
|
||||
message = "Can't generate an executable without a __main__ module."
|
||||
raise StandardError, message
|
||||
def writeCode(self, filename, initCode = ""):
|
||||
""" After a call to done(), this freezes all of the accumulated
|
||||
Python code into a C source file. """
|
||||
|
||||
self.__replacePaths()
|
||||
|
||||
|
|
@ -1239,38 +1232,57 @@ class Freezer:
|
|||
# Allow importing this module.
|
||||
module = self.mf.modules.get(origName, None)
|
||||
code = getattr(module, "__code__", None)
|
||||
if not code and moduleName in startupModules:
|
||||
if code:
|
||||
code = marshal.dumps(code)
|
||||
|
||||
mangledName = self.mangleName(moduleName)
|
||||
moduleDefs.append(self.makeModuleDef(mangledName, code))
|
||||
moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module))
|
||||
|
||||
elif moduleName in startupModules:
|
||||
# Forbid the loading of this startup module.
|
||||
moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
|
||||
|
||||
else:
|
||||
if origName in sourceTrees:
|
||||
# This is one of Panda3D's own Python source
|
||||
# trees. These are a special case: we don't
|
||||
# compile the __init__.py files within them,
|
||||
# since their only purpose is to munge the
|
||||
# __path__ variable anyway. Instead, we
|
||||
# pretend the __init__.py files are empty.
|
||||
code = compile('', moduleName, 'exec')
|
||||
|
||||
if code:
|
||||
code = marshal.dumps(code)
|
||||
|
||||
mangledName = self.mangleName(moduleName)
|
||||
moduleDefs.append(self.makeModuleDef(mangledName, code))
|
||||
moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module))
|
||||
# This is a module with no associated Python
|
||||
# code. It must be an extension module. Get the
|
||||
# filename.
|
||||
extensionFilename = getattr(module, '__file__', None)
|
||||
if extensionFilename:
|
||||
self.extras.append((moduleName, extensionFilename))
|
||||
else:
|
||||
# It doesn't even have a filename; it must
|
||||
# be a built-in module. No worries about
|
||||
# this one, then.
|
||||
pass
|
||||
|
||||
# This is a module with no associated Python
|
||||
# code. It must be an extension module. Get the
|
||||
# filename.
|
||||
extensionFilename = getattr(module, '__file__', None)
|
||||
if extensionFilename:
|
||||
self.extras.append((moduleName, extensionFilename))
|
||||
else:
|
||||
# It doesn't even have a filename; it must
|
||||
# be a built-in module. No worries about
|
||||
# this one, then.
|
||||
pass
|
||||
text = programFile % {
|
||||
'moduleDefs': '\n'.join(moduleDefs),
|
||||
'moduleList': '\n'.join(moduleList),
|
||||
'initCode': initCode
|
||||
}
|
||||
|
||||
if filename is not None:
|
||||
file = open(filename, 'w')
|
||||
file.write(text)
|
||||
file.close()
|
||||
|
||||
def generateCode(self, basename, compileToExe = False):
|
||||
""" After a call to done(), this freezes all of the
|
||||
accumulated python code into either an executable program (if
|
||||
compileToExe is true) or a dynamic library (if compileToExe is
|
||||
false). The basename is the name of the file to write,
|
||||
without the extension.
|
||||
|
||||
The return value is the newly-generated filename, including
|
||||
the filename extension. Additional extension modules are
|
||||
listed in self.extras. """
|
||||
|
||||
if compileToExe:
|
||||
# We must have a __main__ module to make an exe file.
|
||||
if not self.__writingModule('__main__'):
|
||||
message = "Can't generate an executable without a __main__ module."
|
||||
raise StandardError, message
|
||||
|
||||
filename = basename + self.sourceExtension
|
||||
|
||||
|
|
@ -1309,21 +1321,12 @@ class Freezer:
|
|||
|
||||
initCode = dllInitCode % {
|
||||
'moduleName' : os.path.basename(basename),
|
||||
'newcount' : len(moduleList),
|
||||
'dllexport' : dllexport,
|
||||
'dllimport' : dllimport,
|
||||
}
|
||||
compileFunc = self.cenv.compileDll
|
||||
|
||||
text = programFile % {
|
||||
'moduleDefs' : '\n'.join(moduleDefs),
|
||||
'moduleList' : '\n'.join(moduleList),
|
||||
'initCode' : initCode,
|
||||
}
|
||||
|
||||
file = open(filename, 'w')
|
||||
file.write(text)
|
||||
file.close()
|
||||
self.writeCode(filename, initCode=initCode)
|
||||
|
||||
try:
|
||||
compileFunc(filename, basename)
|
||||
|
|
@ -1342,7 +1345,10 @@ class Freezer:
|
|||
for i in range(0, len(code), 16):
|
||||
result += '\n '
|
||||
for c in code[i:i+16]:
|
||||
result += ('%d,' % ord(c))
|
||||
if isinstance(c, int): # Python 3
|
||||
result += ('%d,' % c)
|
||||
else: # Python 2
|
||||
result += ('%d,' % ord(c))
|
||||
result += '\n};\n'
|
||||
return result
|
||||
|
||||
|
|
@ -1379,9 +1385,13 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
def __init__(self, *args, **kw):
|
||||
modulefinder.ModuleFinder.__init__(self, *args, **kw)
|
||||
|
||||
def find_module(self, name, path, parent=None):
|
||||
def find_module(self, name, path, *args, **kwargs):
|
||||
if imp.is_frozen(name):
|
||||
# Don't pick up modules that are frozen into p3dpython.
|
||||
raise ImportError("'%s' is a frozen module" % (name))
|
||||
|
||||
try:
|
||||
return modulefinder.ModuleFinder.find_module(self, name, path, parent = parent)
|
||||
return modulefinder.ModuleFinder.find_module(self, name, path, *args, **kwargs)
|
||||
except ImportError:
|
||||
# It wasn't found through the normal channels. Maybe it's
|
||||
# one of ours, or maybe it's frozen?
|
||||
|
|
@ -1394,15 +1404,6 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
# It's a frozen module.
|
||||
return (None, name, ('', '', imp.PY_FROZEN))
|
||||
|
||||
# Look for a dtool extension. This loop is roughly lifted
|
||||
# from extension_native_helpers.Dtool_PreloadDLL().
|
||||
filename = name + dll_suffix + dll_ext
|
||||
for dir in sys.path + [sys.prefix]:
|
||||
lib = os.path.join(dir, filename)
|
||||
if os.path.exists(lib):
|
||||
file = open(lib, 'rb')
|
||||
return (file, lib, (dll_ext, 'rb', imp.C_EXTENSION))
|
||||
|
||||
message = "DLL loader cannot find %s." % (name)
|
||||
raise ImportError, message
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ class Rope(NodePath):
|
|||
thick lines built from triangle strips.
|
||||
"""
|
||||
|
||||
showRope = base.config.GetBool('show-rope', 1)
|
||||
showRope = ConfigVariableBool('show-rope', True, \
|
||||
"Set this to false to deactivate the display of ropes.")
|
||||
|
||||
def __init__(self, name = 'Rope'):
|
||||
self.ropeNode = RopeNode(name)
|
||||
|
|
@ -18,6 +19,9 @@ class Rope(NodePath):
|
|||
self.ropeNode.setCurve(self.curve)
|
||||
NodePath.__init__(self, self.ropeNode)
|
||||
self.name = name
|
||||
self.order = 0
|
||||
self.verts = []
|
||||
self.knots = None
|
||||
|
||||
def setup(self, order, verts, knots = None):
|
||||
"""This must be called to define the shape of the curve
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ Options:
|
|||
of the __path__ variable, and thus must be actually imported to
|
||||
determine the true value of __path__.
|
||||
|
||||
-s
|
||||
Adds the standard set of modules that are necessary for embedding
|
||||
the Python interpreter. Implicitly set if an executable is
|
||||
generated.
|
||||
|
||||
"""
|
||||
|
||||
import getopt
|
||||
|
|
@ -58,9 +63,10 @@ def usage(code, msg = ''):
|
|||
freezer = FreezeTool.Freezer()
|
||||
|
||||
basename = None
|
||||
addStartupModules = False
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:h')
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:sh')
|
||||
except getopt.error, msg:
|
||||
usage(1, msg)
|
||||
|
||||
|
|
@ -76,48 +82,57 @@ for opt, arg in opts:
|
|||
elif opt == '-p':
|
||||
for module in arg.split(','):
|
||||
freezer.handleCustomPath(module)
|
||||
elif opt == '-s':
|
||||
addStartupModules = True
|
||||
elif opt == '-h':
|
||||
usage(0)
|
||||
else:
|
||||
print 'illegal option: ' + flag
|
||||
sys.exit(1)
|
||||
|
||||
if not args:
|
||||
usage(0)
|
||||
|
||||
if not basename:
|
||||
usage(1, 'You did not specify an output file.')
|
||||
|
||||
if len(args) != 1:
|
||||
if len(args) > 1:
|
||||
usage(1, 'Only one main file may be specified.')
|
||||
|
||||
outputType = 'exe'
|
||||
bl = basename.lower()
|
||||
if bl.endswith('.mf'):
|
||||
outputType = 'mf'
|
||||
elif bl.endswith('.c'):
|
||||
outputType = 'c'
|
||||
elif bl.endswith('.dll') or bl.endswith('.pyd') or bl.endswith('.so'):
|
||||
basename = os.path.splitext(basename)[0]
|
||||
outputType = 'dll'
|
||||
elif bl.endswith('.exe'):
|
||||
basename = os.path.splitext(basename)[0]
|
||||
|
||||
startfile = args[0]
|
||||
startmod = startfile
|
||||
if startfile.endswith('.py') or startfile.endswith('.pyw') or \
|
||||
startfile.endswith('.pyc') or startfile.endswith('.pyo'):
|
||||
startmod = os.path.splitext(startfile)[0]
|
||||
|
||||
compileToExe = False
|
||||
if outputType == 'dll':
|
||||
freezer.addModule(startmod, filename = startfile)
|
||||
else:
|
||||
freezer.addModule('__main__', filename = startfile)
|
||||
compileToExe = True
|
||||
if args:
|
||||
startfile = args[0]
|
||||
startmod = startfile
|
||||
if startfile.endswith('.py') or startfile.endswith('.pyw') or \
|
||||
startfile.endswith('.pyc') or startfile.endswith('.pyo'):
|
||||
startmod = os.path.splitext(startfile)[0]
|
||||
|
||||
freezer.done(compileToExe = compileToExe)
|
||||
if outputType == 'dll' or outputType == 'c':
|
||||
freezer.addModule(startmod, filename = startfile)
|
||||
else:
|
||||
freezer.addModule('__main__', filename = startfile)
|
||||
compileToExe = True
|
||||
addStartupModules = True
|
||||
|
||||
elif outputType == 'exe':
|
||||
# We must have a main module when making an executable.
|
||||
usage(0)
|
||||
|
||||
freezer.done(addStartupModules = addStartupModules)
|
||||
|
||||
if outputType == 'mf':
|
||||
freezer.writeMultifile(basename)
|
||||
elif outputType == 'c':
|
||||
freezer.writeCode(basename)
|
||||
else:
|
||||
freezer.generateCode(basename, compileToExe = compileToExe)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,150 +5,208 @@ SIMPLE_THREADS model, by avoiding blocking all threads while waiting
|
|||
for I/O to complete. """
|
||||
|
||||
__all__ = [
|
||||
'file', 'open', 'listdir', 'walk', 'join',
|
||||
'open', 'listdir', 'walk', 'join',
|
||||
'isfile', 'isdir', 'exists', 'lexists', 'getmtime', 'getsize',
|
||||
'execfile',
|
||||
]
|
||||
|
||||
from panda3d import core
|
||||
import types
|
||||
import panda3d._core as core
|
||||
import sys
|
||||
import os
|
||||
import io
|
||||
import encodings
|
||||
from posixpath import join
|
||||
|
||||
_vfs = core.VirtualFileSystem.getGlobalPtr()
|
||||
|
||||
class file:
|
||||
def __init__(self, filename, mode = 'r', bufsize = None,
|
||||
autoUnwrap = False):
|
||||
self.__stream = None
|
||||
self.__needsVfsClose = False
|
||||
self.__reader = None
|
||||
self.__writer = None
|
||||
self.closed = True
|
||||
self.encoding = None
|
||||
self.errors = None
|
||||
self.__lastWrite = False
|
||||
if sys.version_info < (3, 0):
|
||||
# Python 3 defines these subtypes of IOError, but Python 2 doesn't.
|
||||
FileNotFoundError = IOError
|
||||
IsADirectoryError = IOError
|
||||
FileExistsError = IOError
|
||||
PermissionError = IOError
|
||||
|
||||
self.mode = mode
|
||||
self.name = None
|
||||
self.filename = None
|
||||
self.newlines = None
|
||||
self.softspace = False
|
||||
|
||||
readMode = False
|
||||
writeMode = False
|
||||
def open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True):
|
||||
if sys.version_info >= (3, 0):
|
||||
# Python 3 is much stricter than Python 2, which lets
|
||||
# unknown flags fall through.
|
||||
for ch in mode:
|
||||
if ch not in 'rwxabt+U':
|
||||
raise ValueError("invalid mode: '%s'" % (mode))
|
||||
|
||||
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, core.Istream)
|
||||
writeMode = isinstance(filename, core.Ostream)
|
||||
creating = 'x' in mode
|
||||
writing = 'w' in mode
|
||||
appending = 'a' in mode
|
||||
updating = '+' in mode
|
||||
binary = 'b' in mode
|
||||
universal = 'U' in mode
|
||||
reading = universal or 'r' in mode
|
||||
|
||||
elif isinstance(filename, core.VirtualFile):
|
||||
if binary and 't' in mode:
|
||||
raise ValueError("can't have text and binary mode at once")
|
||||
|
||||
if creating + reading + writing + appending > 1:
|
||||
raise ValueError("must have exactly one of create/read/write/append mode")
|
||||
|
||||
if binary:
|
||||
if encoding:
|
||||
raise ValueError("binary mode doesn't take an encoding argument")
|
||||
if errors:
|
||||
raise ValueError("binary mode doesn't take an errors argument")
|
||||
if newline:
|
||||
raise ValueError("binary mode doesn't take a newline argument")
|
||||
|
||||
if isinstance(file, core.Istream) or isinstance(file, core.Ostream):
|
||||
# If we were given a stream instead of a filename, assign
|
||||
# it directly.
|
||||
raw = StreamIOWrapper(file)
|
||||
raw.mode = mode
|
||||
|
||||
else:
|
||||
vfile = None
|
||||
|
||||
if isinstance(file, core.VirtualFile):
|
||||
# We can also "open" a VirtualFile object for reading.
|
||||
self.__stream = filename.openReadFile(autoUnwrap)
|
||||
if not self.__stream:
|
||||
message = 'Could not read virtual file %s' % (repr(filename))
|
||||
raise IOError, message
|
||||
self.__needsVfsClose = True
|
||||
readMode = True
|
||||
vfile = file
|
||||
filename = vfile.getFilename()
|
||||
elif isinstance(file, unicode):
|
||||
# If a raw string is given, assume it's an os-specific
|
||||
# filename.
|
||||
filename = core.Filename.fromOsSpecificW(file)
|
||||
elif isinstance(file, str):
|
||||
filename = core.Filename.fromOsSpecific(file)
|
||||
else:
|
||||
# If a Filename is given, make a writable copy anyway.
|
||||
filename = core.Filename(file)
|
||||
|
||||
if binary or sys.version_info >= (3, 0):
|
||||
filename.setBinary()
|
||||
else:
|
||||
filename.setText()
|
||||
|
||||
if not vfile:
|
||||
vfile = _vfs.getFile(filename)
|
||||
|
||||
if not vfile:
|
||||
if reading:
|
||||
raise FileNotFoundError("No such file or directory: '%s'" % (filename))
|
||||
|
||||
vfile = _vfs.createFile(filename)
|
||||
if not vfile:
|
||||
raise IOError("Failed to create file: '%s'" % (filename))
|
||||
|
||||
elif creating:
|
||||
# In 'creating' mode, we have to raise FileExistsError
|
||||
# if the file already exists. Otherwise, it's the same
|
||||
# as 'writing' mode.
|
||||
raise FileExistsError("File exists: '%s'" % (filename))
|
||||
|
||||
elif vfile.isDirectory():
|
||||
raise IsADirectoryError("Is a directory: '%s'" % (filename))
|
||||
|
||||
# Actually open the streams.
|
||||
if reading:
|
||||
if updating:
|
||||
stream = vfile.openReadWriteFile(False)
|
||||
else:
|
||||
stream = vfile.openReadFile(False)
|
||||
|
||||
if not stream:
|
||||
raise IOError("Could not open %s for reading" % (filename))
|
||||
|
||||
elif writing or creating:
|
||||
if updating:
|
||||
stream = vfile.openReadWriteFile(True)
|
||||
else:
|
||||
stream = vfile.openWriteFile(False, True)
|
||||
|
||||
if not stream:
|
||||
raise IOError("Could not open %s for writing" % (filename))
|
||||
|
||||
elif appending:
|
||||
if updating:
|
||||
stream = vfile.openReadAppendFile()
|
||||
else:
|
||||
stream = vfile.openAppendFile()
|
||||
|
||||
if not stream:
|
||||
raise IOError("Could not open %s for appending" % (filename))
|
||||
|
||||
else:
|
||||
# Otherwise, we must have been given a filename. Open it.
|
||||
if isinstance(filename, types.StringTypes):
|
||||
# If a raw string is given, assume it's an os-specific
|
||||
# filename.
|
||||
filename = core.Filename.fromOsSpecific(filename)
|
||||
else:
|
||||
# If a Filename is given, make a writable copy anyway.
|
||||
filename = core.Filename(filename)
|
||||
raise ValueError("Must have exactly one of create/read/write/append mode and at most one plus")
|
||||
|
||||
self.filename = filename
|
||||
self.name = filename.toOsSpecific()
|
||||
raw = StreamIOWrapper(stream, needsVfsClose=True)
|
||||
raw.mode = mode
|
||||
raw.name = vfile.getFilename().toOsSpecific()
|
||||
|
||||
binary = False
|
||||
if 'b' in mode:
|
||||
# Strip 'b'. This means a binary file.
|
||||
i = mode.index('b')
|
||||
mode = mode[:i] + mode[i + 1:]
|
||||
binary = True
|
||||
# If a binary stream was requested, return the stream we've created.
|
||||
if binary:
|
||||
return raw
|
||||
|
||||
if 'U' in mode:
|
||||
# Strip 'U'. We don't use it; universal-newline support
|
||||
# is built into Panda, and can't be changed at runtime.
|
||||
i = mode.index('U')
|
||||
mode = mode[:i] + mode[i + 1:]
|
||||
binary = False
|
||||
# If we're in Python 2, we don't decode unicode strings by default.
|
||||
if not encoding and sys.version_info < (3, 0):
|
||||
return raw
|
||||
|
||||
if mode == '':
|
||||
mode = 'r'
|
||||
line_buffering = False
|
||||
if buffering == 1:
|
||||
line_buffering = True
|
||||
elif buffering == 0:
|
||||
raise ValueError("can't have unbuffered text I/O")
|
||||
|
||||
# Per Python docs, we insist this is true.
|
||||
assert mode[0] in 'rwa'
|
||||
# Otherwise, create a TextIOWrapper object to wrap it.
|
||||
wrapper = io.TextIOWrapper(raw, encoding, errors, newline, line_buffering)
|
||||
wrapper.mode = mode
|
||||
return wrapper
|
||||
|
||||
if binary:
|
||||
filename.setBinary()
|
||||
else:
|
||||
filename.setText()
|
||||
|
||||
# Actually open the streams.
|
||||
if mode == 'w':
|
||||
self.__stream = _vfs.openWriteFile(filename, autoUnwrap, True)
|
||||
if not self.__stream:
|
||||
message = 'Could not open %s for writing' % (filename)
|
||||
raise IOError, message
|
||||
writeMode = True
|
||||
if sys.version_info < (3, 0):
|
||||
# Python 2 had an alias for open() called file().
|
||||
__all__.append('file')
|
||||
file = open
|
||||
|
||||
elif mode == 'a':
|
||||
self.__stream = _vfs.openAppendFile(filename)
|
||||
if not self.__stream:
|
||||
message = 'Could not open %s for writing' % (filename)
|
||||
raise IOError, message
|
||||
writeMode = True
|
||||
|
||||
elif mode == 'w+':
|
||||
self.__stream = _vfs.openReadWriteFile(filename, True)
|
||||
if not self.__stream:
|
||||
message = 'Could not open %s for writing' % (filename)
|
||||
raise IOError, message
|
||||
readMode = True
|
||||
writeMode = True
|
||||
class StreamIOWrapper(io.IOBase):
|
||||
""" This is a file-like object that wraps around a C++ istream and/or
|
||||
ostream object. It only deals with binary data; to work with text I/O,
|
||||
create an io.TextIOWrapper object around this, or use the open()
|
||||
function that is also provided with this module. """
|
||||
|
||||
elif mode == 'a+':
|
||||
self.__stream = _vfs.openReadAppendFile(filename)
|
||||
if not self.__stream:
|
||||
message = 'Could not open %s for writing' % (filename)
|
||||
raise IOError, message
|
||||
readMode = True
|
||||
writeMode = True
|
||||
def __init__(self, stream, needsVfsClose=False):
|
||||
self.__stream = stream
|
||||
self.__needsVfsClose = needsVfsClose
|
||||
self.__reader = None
|
||||
self.__writer = None
|
||||
self.__lastWrite = False
|
||||
|
||||
elif mode == 'r+':
|
||||
self.__stream = _vfs.openReadWriteFile(filename, False)
|
||||
if not self.__stream:
|
||||
message = 'Could not open %s for writing' % (filename)
|
||||
raise IOError, message
|
||||
readMode = True
|
||||
writeMode = True
|
||||
if isinstance(stream, core.Istream):
|
||||
self.__reader = core.StreamReader(stream, False)
|
||||
|
||||
elif mode == 'r':
|
||||
self.__stream = _vfs.openReadFile(filename, autoUnwrap)
|
||||
if not self.__stream:
|
||||
if not _vfs.exists(filename):
|
||||
message = 'No such file: %s' % (filename)
|
||||
else:
|
||||
message = 'Could not open %s for reading' % (filename)
|
||||
raise IOError, message
|
||||
readMode = True
|
||||
|
||||
self.__needsVfsClose = True
|
||||
|
||||
if readMode:
|
||||
self.__reader = core.StreamReader(self.__stream, False)
|
||||
if writeMode:
|
||||
self.__writer = core.StreamWriter(self.__stream, False)
|
||||
if isinstance(stream, core.Ostream):
|
||||
self.__writer = core.StreamWriter(stream, False)
|
||||
self.__lastWrite = True
|
||||
if sys.version_info >= (3, 0):
|
||||
# In Python 3, we use appendData, which only accepts bytes.
|
||||
self.__write = self.__writer.appendData
|
||||
else:
|
||||
# In Python 2.7, we also accept unicode objects, which are
|
||||
# implicitly converted to C++ strings.
|
||||
self.__write = self.__writer.write
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
def __repr__(self):
|
||||
s = "<direct.stdpy.file.StreamIOWrapper"
|
||||
if hasattr(self, 'name'):
|
||||
s += " name='%s'" % (self.name)
|
||||
if hasattr(self, 'mode'):
|
||||
s += " mode='%s'" % (self.mode)
|
||||
s += ">"
|
||||
return s
|
||||
|
||||
def readable(self):
|
||||
return self.__reader is not None
|
||||
|
||||
def writable(self):
|
||||
return self.__writer is not None
|
||||
|
||||
def close(self):
|
||||
if self.__needsVfsClose:
|
||||
|
|
@ -160,70 +218,51 @@ class file:
|
|||
_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:
|
||||
if self.__writer:
|
||||
self.__stream.clear() # clear eof flag
|
||||
self.__stream.flush()
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
line = self.readline()
|
||||
if line:
|
||||
return line
|
||||
raise StopIteration
|
||||
|
||||
def read(self, size = -1):
|
||||
def read(self, size=-1):
|
||||
if not self.__reader:
|
||||
if not self.__writer:
|
||||
# The stream is not even open at all.
|
||||
message = 'I/O operation on closed file'
|
||||
raise ValueError, message
|
||||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
# The stream is open only in write mode.
|
||||
message = 'Attempt to read from write-only stream'
|
||||
raise IOError, message
|
||||
raise IOError("Attempt to read from write-only stream")
|
||||
|
||||
self.__stream.clear() # clear eof flag
|
||||
self.__lastWrite = False
|
||||
if size >= 0:
|
||||
if size is not None and size >= 0:
|
||||
result = self.__reader.extractBytes(size)
|
||||
else:
|
||||
# Read to end-of-file.
|
||||
result = ''
|
||||
result = b''
|
||||
while not self.__stream.eof():
|
||||
result += self.__reader.extractBytes(1024)
|
||||
result += self.__reader.extractBytes(512)
|
||||
return result
|
||||
|
||||
def readline(self, size = -1):
|
||||
read1 = read
|
||||
|
||||
def readline(self, size=-1):
|
||||
if not self.__reader:
|
||||
if not self.__writer:
|
||||
# The stream is not even open at all.
|
||||
message = 'I/O operation on closed file'
|
||||
raise ValueError, message
|
||||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
# The stream is open only in write mode.
|
||||
message = 'Attempt to read from write-only stream'
|
||||
raise IOError, message
|
||||
raise IOError("Attempt to read from write-only stream")
|
||||
|
||||
self.__stream.clear() # clear eof flag
|
||||
self.__lastWrite = False
|
||||
return self.__reader.readline()
|
||||
|
||||
def readlines(self, sizehint = -1):
|
||||
lines = []
|
||||
line = self.readline()
|
||||
while line:
|
||||
lines.append(line)
|
||||
line = self.readline()
|
||||
return lines
|
||||
|
||||
xreadlines = readlines
|
||||
|
||||
def seek(self, offset, whence = 0):
|
||||
if self.__stream:
|
||||
self.__stream.clear() # clear eof flag
|
||||
|
|
@ -239,58 +278,43 @@ class file:
|
|||
else:
|
||||
if self.__reader:
|
||||
return self.__stream.tellg()
|
||||
message = 'I/O operation on closed file'
|
||||
raise ValueError, message
|
||||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
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. """
|
||||
raise NotImplementedError
|
||||
|
||||
def write(self, str):
|
||||
def write(self, b):
|
||||
if not self.__writer:
|
||||
if not self.__reader:
|
||||
# The stream is not even open at all.
|
||||
message = 'I/O operation on closed file'
|
||||
raise ValueError, message
|
||||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
# The stream is open only in read mode.
|
||||
message = 'Attempt to write to read-only stream'
|
||||
raise IOError, message
|
||||
raise IOError("Attempt to write to read-only stream")
|
||||
|
||||
self.__stream.clear() # clear eof flag
|
||||
self.__writer.appendData(str)
|
||||
self.__write(b)
|
||||
self.__lastWrite = True
|
||||
|
||||
def writelines(self, lines):
|
||||
if not self.__writer:
|
||||
if not self.__reader:
|
||||
# The stream is not even open at all.
|
||||
message = 'I/O operation on closed file'
|
||||
raise ValueError, message
|
||||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
# The stream is open only in read mode.
|
||||
message = 'Attempt to write to read-only stream'
|
||||
raise IOError, message
|
||||
raise IOError("Attempt to write to read-only stream")
|
||||
|
||||
self.__stream.clear() # clear eof flag
|
||||
for line in lines:
|
||||
self.__writer.appendData(line)
|
||||
self.__write(line)
|
||||
self.__lastWrite = True
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
self.close()
|
||||
|
||||
open = file
|
||||
|
||||
def listdir(path):
|
||||
""" Implements os.listdir over vfs. """
|
||||
files = []
|
||||
dirlist = _vfs.scanDirectory(core.Filename.fromOsSpecific(path))
|
||||
if dirlist is None:
|
||||
message = 'No such file or directory: %s' % (path)
|
||||
raise OSError, message
|
||||
raise OSError("No such file or directory: '%s'" % (path))
|
||||
|
||||
for file in dirlist:
|
||||
files.append(file.getFilename().getBasename())
|
||||
return files
|
||||
|
|
@ -323,20 +347,6 @@ def walk(top, topdown = True, onerror = None, followlinks = True):
|
|||
if not topdown:
|
||||
yield (top, dirnames, filenames)
|
||||
|
||||
def join(path, *args):
|
||||
for part in args:
|
||||
if part == '':
|
||||
continue
|
||||
|
||||
if part.startswith('/'):
|
||||
path = part
|
||||
elif path.endswith('/'):
|
||||
path = path + part
|
||||
else:
|
||||
path = '/'.join((path, part))
|
||||
|
||||
return path
|
||||
|
||||
def isfile(path):
|
||||
return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import Pmw, os,Placer
|
|||
|
||||
from panda3d.core import *
|
||||
from panda3d.physics import *
|
||||
from panda3d.direct import getParticlePath
|
||||
|
||||
|
||||
class ParticlePanel(AppShell):
|
||||
# Override class variables
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -49,214 +49,234 @@ extern int cppyydebug;
|
|||
REAL = 258,
|
||||
INTEGER = 259,
|
||||
CHAR_TOK = 260,
|
||||
STRING = 261,
|
||||
SIMPLE_STRING = 261,
|
||||
SIMPLE_IDENTIFIER = 262,
|
||||
IDENTIFIER = 263,
|
||||
TYPENAME_IDENTIFIER = 264,
|
||||
SCOPING = 265,
|
||||
TYPEDEFNAME = 266,
|
||||
ELLIPSIS = 267,
|
||||
OROR = 268,
|
||||
ANDAND = 269,
|
||||
EQCOMPARE = 270,
|
||||
NECOMPARE = 271,
|
||||
LECOMPARE = 272,
|
||||
GECOMPARE = 273,
|
||||
LSHIFT = 274,
|
||||
RSHIFT = 275,
|
||||
POINTSAT_STAR = 276,
|
||||
DOT_STAR = 277,
|
||||
UNARY = 278,
|
||||
UNARY_NOT = 279,
|
||||
UNARY_NEGATE = 280,
|
||||
UNARY_MINUS = 281,
|
||||
UNARY_STAR = 282,
|
||||
UNARY_REF = 283,
|
||||
POINTSAT = 284,
|
||||
SCOPE = 285,
|
||||
PLUSPLUS = 286,
|
||||
MINUSMINUS = 287,
|
||||
TIMESEQUAL = 288,
|
||||
DIVIDEEQUAL = 289,
|
||||
MODEQUAL = 290,
|
||||
PLUSEQUAL = 291,
|
||||
MINUSEQUAL = 292,
|
||||
OREQUAL = 293,
|
||||
ANDEQUAL = 294,
|
||||
XOREQUAL = 295,
|
||||
LSHIFTEQUAL = 296,
|
||||
RSHIFTEQUAL = 297,
|
||||
KW_BEGIN_PUBLISH = 298,
|
||||
KW_BLOCKING = 299,
|
||||
KW_BOOL = 300,
|
||||
KW_CATCH = 301,
|
||||
KW_CHAR = 302,
|
||||
KW_CHAR16_T = 303,
|
||||
KW_CHAR32_T = 304,
|
||||
KW_CLASS = 305,
|
||||
KW_CONST = 306,
|
||||
KW_DELETE = 307,
|
||||
KW_DOUBLE = 308,
|
||||
KW_DYNAMIC_CAST = 309,
|
||||
KW_ELSE = 310,
|
||||
KW_END_PUBLISH = 311,
|
||||
KW_ENUM = 312,
|
||||
KW_EXTENSION = 313,
|
||||
KW_EXTERN = 314,
|
||||
KW_EXPLICIT = 315,
|
||||
KW_PUBLISHED = 316,
|
||||
KW_FALSE = 317,
|
||||
KW_FLOAT = 318,
|
||||
KW_FRIEND = 319,
|
||||
KW_FOR = 320,
|
||||
KW_GOTO = 321,
|
||||
KW_IF = 322,
|
||||
KW_INLINE = 323,
|
||||
KW_INT = 324,
|
||||
KW_LONG = 325,
|
||||
KW_LONGLONG = 326,
|
||||
KW_MAKE_PROPERTY = 327,
|
||||
KW_MAKE_SEQ = 328,
|
||||
KW_MUTABLE = 329,
|
||||
KW_NAMESPACE = 330,
|
||||
KW_NEW = 331,
|
||||
KW_NOEXCEPT = 332,
|
||||
KW_OPERATOR = 333,
|
||||
KW_PRIVATE = 334,
|
||||
KW_PROTECTED = 335,
|
||||
KW_PUBLIC = 336,
|
||||
KW_REGISTER = 337,
|
||||
KW_RETURN = 338,
|
||||
KW_SHORT = 339,
|
||||
KW_SIGNED = 340,
|
||||
KW_SIZEOF = 341,
|
||||
KW_STATIC = 342,
|
||||
KW_STATIC_CAST = 343,
|
||||
KW_STRUCT = 344,
|
||||
KW_TEMPLATE = 345,
|
||||
KW_THROW = 346,
|
||||
KW_TRUE = 347,
|
||||
KW_TRY = 348,
|
||||
KW_TYPEDEF = 349,
|
||||
KW_TYPENAME = 350,
|
||||
KW_UNION = 351,
|
||||
KW_UNSIGNED = 352,
|
||||
KW_USING = 353,
|
||||
KW_VIRTUAL = 354,
|
||||
KW_VOID = 355,
|
||||
KW_VOLATILE = 356,
|
||||
KW_WCHAR_T = 357,
|
||||
KW_WHILE = 358,
|
||||
START_CPP = 359,
|
||||
START_CONST_EXPR = 360,
|
||||
START_TYPE = 361
|
||||
STRING_LITERAL = 263,
|
||||
CUSTOM_LITERAL = 264,
|
||||
IDENTIFIER = 265,
|
||||
TYPENAME_IDENTIFIER = 266,
|
||||
SCOPING = 267,
|
||||
TYPEDEFNAME = 268,
|
||||
ELLIPSIS = 269,
|
||||
OROR = 270,
|
||||
ANDAND = 271,
|
||||
EQCOMPARE = 272,
|
||||
NECOMPARE = 273,
|
||||
LECOMPARE = 274,
|
||||
GECOMPARE = 275,
|
||||
LSHIFT = 276,
|
||||
RSHIFT = 277,
|
||||
POINTSAT_STAR = 278,
|
||||
DOT_STAR = 279,
|
||||
UNARY = 280,
|
||||
UNARY_NOT = 281,
|
||||
UNARY_NEGATE = 282,
|
||||
UNARY_MINUS = 283,
|
||||
UNARY_STAR = 284,
|
||||
UNARY_REF = 285,
|
||||
POINTSAT = 286,
|
||||
SCOPE = 287,
|
||||
PLUSPLUS = 288,
|
||||
MINUSMINUS = 289,
|
||||
TIMESEQUAL = 290,
|
||||
DIVIDEEQUAL = 291,
|
||||
MODEQUAL = 292,
|
||||
PLUSEQUAL = 293,
|
||||
MINUSEQUAL = 294,
|
||||
OREQUAL = 295,
|
||||
ANDEQUAL = 296,
|
||||
XOREQUAL = 297,
|
||||
LSHIFTEQUAL = 298,
|
||||
RSHIFTEQUAL = 299,
|
||||
KW_ALIGNAS = 300,
|
||||
KW_ALIGNOF = 301,
|
||||
KW_AUTO = 302,
|
||||
KW_BEGIN_PUBLISH = 303,
|
||||
KW_BLOCKING = 304,
|
||||
KW_BOOL = 305,
|
||||
KW_CATCH = 306,
|
||||
KW_CHAR = 307,
|
||||
KW_CHAR16_T = 308,
|
||||
KW_CHAR32_T = 309,
|
||||
KW_CLASS = 310,
|
||||
KW_CONST = 311,
|
||||
KW_CONSTEXPR = 312,
|
||||
KW_DECLTYPE = 313,
|
||||
KW_DEFAULT = 314,
|
||||
KW_DELETE = 315,
|
||||
KW_DOUBLE = 316,
|
||||
KW_DYNAMIC_CAST = 317,
|
||||
KW_ELSE = 318,
|
||||
KW_END_PUBLISH = 319,
|
||||
KW_ENUM = 320,
|
||||
KW_EXTENSION = 321,
|
||||
KW_EXTERN = 322,
|
||||
KW_EXPLICIT = 323,
|
||||
KW_PUBLISHED = 324,
|
||||
KW_FALSE = 325,
|
||||
KW_FLOAT = 326,
|
||||
KW_FRIEND = 327,
|
||||
KW_FOR = 328,
|
||||
KW_GOTO = 329,
|
||||
KW_IF = 330,
|
||||
KW_INLINE = 331,
|
||||
KW_INT = 332,
|
||||
KW_LONG = 333,
|
||||
KW_LONGLONG = 334,
|
||||
KW_MAKE_PROPERTY = 335,
|
||||
KW_MAKE_SEQ = 336,
|
||||
KW_MUTABLE = 337,
|
||||
KW_NAMESPACE = 338,
|
||||
KW_NEW = 339,
|
||||
KW_NOEXCEPT = 340,
|
||||
KW_NULLPTR = 341,
|
||||
KW_OPERATOR = 342,
|
||||
KW_PRIVATE = 343,
|
||||
KW_PROTECTED = 344,
|
||||
KW_PUBLIC = 345,
|
||||
KW_REGISTER = 346,
|
||||
KW_RETURN = 347,
|
||||
KW_SHORT = 348,
|
||||
KW_SIGNED = 349,
|
||||
KW_SIZEOF = 350,
|
||||
KW_STATIC = 351,
|
||||
KW_STATIC_ASSERT = 352,
|
||||
KW_STATIC_CAST = 353,
|
||||
KW_STRUCT = 354,
|
||||
KW_TEMPLATE = 355,
|
||||
KW_THROW = 356,
|
||||
KW_TRUE = 357,
|
||||
KW_TRY = 358,
|
||||
KW_TYPEDEF = 359,
|
||||
KW_TYPENAME = 360,
|
||||
KW_UNION = 361,
|
||||
KW_UNSIGNED = 362,
|
||||
KW_USING = 363,
|
||||
KW_VIRTUAL = 364,
|
||||
KW_VOID = 365,
|
||||
KW_VOLATILE = 366,
|
||||
KW_WCHAR_T = 367,
|
||||
KW_WHILE = 368,
|
||||
START_CPP = 369,
|
||||
START_CONST_EXPR = 370,
|
||||
START_TYPE = 371
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define REAL 258
|
||||
#define INTEGER 259
|
||||
#define CHAR_TOK 260
|
||||
#define STRING 261
|
||||
#define SIMPLE_STRING 261
|
||||
#define SIMPLE_IDENTIFIER 262
|
||||
#define IDENTIFIER 263
|
||||
#define TYPENAME_IDENTIFIER 264
|
||||
#define SCOPING 265
|
||||
#define TYPEDEFNAME 266
|
||||
#define ELLIPSIS 267
|
||||
#define OROR 268
|
||||
#define ANDAND 269
|
||||
#define EQCOMPARE 270
|
||||
#define NECOMPARE 271
|
||||
#define LECOMPARE 272
|
||||
#define GECOMPARE 273
|
||||
#define LSHIFT 274
|
||||
#define RSHIFT 275
|
||||
#define POINTSAT_STAR 276
|
||||
#define DOT_STAR 277
|
||||
#define UNARY 278
|
||||
#define UNARY_NOT 279
|
||||
#define UNARY_NEGATE 280
|
||||
#define UNARY_MINUS 281
|
||||
#define UNARY_STAR 282
|
||||
#define UNARY_REF 283
|
||||
#define POINTSAT 284
|
||||
#define SCOPE 285
|
||||
#define PLUSPLUS 286
|
||||
#define MINUSMINUS 287
|
||||
#define TIMESEQUAL 288
|
||||
#define DIVIDEEQUAL 289
|
||||
#define MODEQUAL 290
|
||||
#define PLUSEQUAL 291
|
||||
#define MINUSEQUAL 292
|
||||
#define OREQUAL 293
|
||||
#define ANDEQUAL 294
|
||||
#define XOREQUAL 295
|
||||
#define LSHIFTEQUAL 296
|
||||
#define RSHIFTEQUAL 297
|
||||
#define KW_BEGIN_PUBLISH 298
|
||||
#define KW_BLOCKING 299
|
||||
#define KW_BOOL 300
|
||||
#define KW_CATCH 301
|
||||
#define KW_CHAR 302
|
||||
#define KW_CHAR16_T 303
|
||||
#define KW_CHAR32_T 304
|
||||
#define KW_CLASS 305
|
||||
#define KW_CONST 306
|
||||
#define KW_DELETE 307
|
||||
#define KW_DOUBLE 308
|
||||
#define KW_DYNAMIC_CAST 309
|
||||
#define KW_ELSE 310
|
||||
#define KW_END_PUBLISH 311
|
||||
#define KW_ENUM 312
|
||||
#define KW_EXTENSION 313
|
||||
#define KW_EXTERN 314
|
||||
#define KW_EXPLICIT 315
|
||||
#define KW_PUBLISHED 316
|
||||
#define KW_FALSE 317
|
||||
#define KW_FLOAT 318
|
||||
#define KW_FRIEND 319
|
||||
#define KW_FOR 320
|
||||
#define KW_GOTO 321
|
||||
#define KW_IF 322
|
||||
#define KW_INLINE 323
|
||||
#define KW_INT 324
|
||||
#define KW_LONG 325
|
||||
#define KW_LONGLONG 326
|
||||
#define KW_MAKE_PROPERTY 327
|
||||
#define KW_MAKE_SEQ 328
|
||||
#define KW_MUTABLE 329
|
||||
#define KW_NAMESPACE 330
|
||||
#define KW_NEW 331
|
||||
#define KW_NOEXCEPT 332
|
||||
#define KW_OPERATOR 333
|
||||
#define KW_PRIVATE 334
|
||||
#define KW_PROTECTED 335
|
||||
#define KW_PUBLIC 336
|
||||
#define KW_REGISTER 337
|
||||
#define KW_RETURN 338
|
||||
#define KW_SHORT 339
|
||||
#define KW_SIGNED 340
|
||||
#define KW_SIZEOF 341
|
||||
#define KW_STATIC 342
|
||||
#define KW_STATIC_CAST 343
|
||||
#define KW_STRUCT 344
|
||||
#define KW_TEMPLATE 345
|
||||
#define KW_THROW 346
|
||||
#define KW_TRUE 347
|
||||
#define KW_TRY 348
|
||||
#define KW_TYPEDEF 349
|
||||
#define KW_TYPENAME 350
|
||||
#define KW_UNION 351
|
||||
#define KW_UNSIGNED 352
|
||||
#define KW_USING 353
|
||||
#define KW_VIRTUAL 354
|
||||
#define KW_VOID 355
|
||||
#define KW_VOLATILE 356
|
||||
#define KW_WCHAR_T 357
|
||||
#define KW_WHILE 358
|
||||
#define START_CPP 359
|
||||
#define START_CONST_EXPR 360
|
||||
#define START_TYPE 361
|
||||
#define STRING_LITERAL 263
|
||||
#define CUSTOM_LITERAL 264
|
||||
#define IDENTIFIER 265
|
||||
#define TYPENAME_IDENTIFIER 266
|
||||
#define SCOPING 267
|
||||
#define TYPEDEFNAME 268
|
||||
#define ELLIPSIS 269
|
||||
#define OROR 270
|
||||
#define ANDAND 271
|
||||
#define EQCOMPARE 272
|
||||
#define NECOMPARE 273
|
||||
#define LECOMPARE 274
|
||||
#define GECOMPARE 275
|
||||
#define LSHIFT 276
|
||||
#define RSHIFT 277
|
||||
#define POINTSAT_STAR 278
|
||||
#define DOT_STAR 279
|
||||
#define UNARY 280
|
||||
#define UNARY_NOT 281
|
||||
#define UNARY_NEGATE 282
|
||||
#define UNARY_MINUS 283
|
||||
#define UNARY_STAR 284
|
||||
#define UNARY_REF 285
|
||||
#define POINTSAT 286
|
||||
#define SCOPE 287
|
||||
#define PLUSPLUS 288
|
||||
#define MINUSMINUS 289
|
||||
#define TIMESEQUAL 290
|
||||
#define DIVIDEEQUAL 291
|
||||
#define MODEQUAL 292
|
||||
#define PLUSEQUAL 293
|
||||
#define MINUSEQUAL 294
|
||||
#define OREQUAL 295
|
||||
#define ANDEQUAL 296
|
||||
#define XOREQUAL 297
|
||||
#define LSHIFTEQUAL 298
|
||||
#define RSHIFTEQUAL 299
|
||||
#define KW_ALIGNAS 300
|
||||
#define KW_ALIGNOF 301
|
||||
#define KW_AUTO 302
|
||||
#define KW_BEGIN_PUBLISH 303
|
||||
#define KW_BLOCKING 304
|
||||
#define KW_BOOL 305
|
||||
#define KW_CATCH 306
|
||||
#define KW_CHAR 307
|
||||
#define KW_CHAR16_T 308
|
||||
#define KW_CHAR32_T 309
|
||||
#define KW_CLASS 310
|
||||
#define KW_CONST 311
|
||||
#define KW_CONSTEXPR 312
|
||||
#define KW_DECLTYPE 313
|
||||
#define KW_DEFAULT 314
|
||||
#define KW_DELETE 315
|
||||
#define KW_DOUBLE 316
|
||||
#define KW_DYNAMIC_CAST 317
|
||||
#define KW_ELSE 318
|
||||
#define KW_END_PUBLISH 319
|
||||
#define KW_ENUM 320
|
||||
#define KW_EXTENSION 321
|
||||
#define KW_EXTERN 322
|
||||
#define KW_EXPLICIT 323
|
||||
#define KW_PUBLISHED 324
|
||||
#define KW_FALSE 325
|
||||
#define KW_FLOAT 326
|
||||
#define KW_FRIEND 327
|
||||
#define KW_FOR 328
|
||||
#define KW_GOTO 329
|
||||
#define KW_IF 330
|
||||
#define KW_INLINE 331
|
||||
#define KW_INT 332
|
||||
#define KW_LONG 333
|
||||
#define KW_LONGLONG 334
|
||||
#define KW_MAKE_PROPERTY 335
|
||||
#define KW_MAKE_SEQ 336
|
||||
#define KW_MUTABLE 337
|
||||
#define KW_NAMESPACE 338
|
||||
#define KW_NEW 339
|
||||
#define KW_NOEXCEPT 340
|
||||
#define KW_NULLPTR 341
|
||||
#define KW_OPERATOR 342
|
||||
#define KW_PRIVATE 343
|
||||
#define KW_PROTECTED 344
|
||||
#define KW_PUBLIC 345
|
||||
#define KW_REGISTER 346
|
||||
#define KW_RETURN 347
|
||||
#define KW_SHORT 348
|
||||
#define KW_SIGNED 349
|
||||
#define KW_SIZEOF 350
|
||||
#define KW_STATIC 351
|
||||
#define KW_STATIC_ASSERT 352
|
||||
#define KW_STATIC_CAST 353
|
||||
#define KW_STRUCT 354
|
||||
#define KW_TEMPLATE 355
|
||||
#define KW_THROW 356
|
||||
#define KW_TRUE 357
|
||||
#define KW_TRY 358
|
||||
#define KW_TYPEDEF 359
|
||||
#define KW_TYPENAME 360
|
||||
#define KW_UNION 361
|
||||
#define KW_UNSIGNED 362
|
||||
#define KW_USING 363
|
||||
#define KW_VIRTUAL 364
|
||||
#define KW_VOID 365
|
||||
#define KW_VOLATILE 366
|
||||
#define KW_WCHAR_T 367
|
||||
#define KW_WHILE 368
|
||||
#define START_CPP 369
|
||||
#define START_CONST_EXPR 370
|
||||
#define START_TYPE 371
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -57,17 +57,22 @@ int yyparse();
|
|||
|
||||
static void
|
||||
yyerror(const string &msg) {
|
||||
current_lexer->error(msg);
|
||||
current_lexer->error(msg, current_lexer->_last_token_loc);
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror(YYLTYPE *loc, const string &msg) {
|
||||
current_lexer->error(msg, *loc);
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror(const string &msg, YYLTYPE &loc) {
|
||||
current_lexer->error(msg, loc.first_line, loc.first_column);
|
||||
current_lexer->error(msg, loc);
|
||||
}
|
||||
|
||||
static void
|
||||
yywarning(const string &msg, YYLTYPE &loc) {
|
||||
current_lexer->warning(msg, loc.first_line, loc.first_column);
|
||||
current_lexer->warning(msg, loc);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -194,13 +199,18 @@ pop_struct() {
|
|||
|
||||
/* This is a bison-specific declaration to enable recursive calls to
|
||||
yyparse(). It changes the calling sequence to yylex(), passing
|
||||
pointers to the current yylval and yylloc. */
|
||||
%pure_parser
|
||||
pointers to the current yylval and yylloc. Bison 2.7 introduces a
|
||||
different syntax that will also pass the current yylloc to yyerror,
|
||||
but we have to support Bison versions as old as 2.5 for now. */
|
||||
/*%define api.pure full*/
|
||||
%pure-parser
|
||||
%locations
|
||||
|
||||
%token <u.real> REAL
|
||||
%token <u.integer> INTEGER
|
||||
%token <u.integer> CHAR_TOK
|
||||
%token <str> STRING SIMPLE_IDENTIFIER
|
||||
%token <str> SIMPLE_STRING SIMPLE_IDENTIFIER
|
||||
%token <u.expr> STRING_LITERAL CUSTOM_LITERAL
|
||||
%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER SCOPING
|
||||
%token <u.type> TYPEDEFNAME
|
||||
|
||||
|
|
@ -236,6 +246,9 @@ pop_struct() {
|
|||
%token LSHIFTEQUAL
|
||||
%token RSHIFTEQUAL
|
||||
|
||||
%token KW_ALIGNAS
|
||||
%token KW_ALIGNOF
|
||||
%token KW_AUTO
|
||||
%token KW_BEGIN_PUBLISH
|
||||
%token KW_BLOCKING
|
||||
%token KW_BOOL
|
||||
|
|
@ -245,6 +258,9 @@ pop_struct() {
|
|||
%token KW_CHAR32_T
|
||||
%token KW_CLASS
|
||||
%token KW_CONST
|
||||
%token KW_CONSTEXPR
|
||||
%token KW_DECLTYPE
|
||||
%token KW_DEFAULT
|
||||
%token KW_DELETE
|
||||
%token KW_DOUBLE
|
||||
%token KW_DYNAMIC_CAST
|
||||
|
|
@ -271,6 +287,7 @@ pop_struct() {
|
|||
%token KW_NAMESPACE
|
||||
%token KW_NEW
|
||||
%token KW_NOEXCEPT
|
||||
%token KW_NULLPTR
|
||||
%token KW_OPERATOR
|
||||
%token KW_PRIVATE
|
||||
%token KW_PROTECTED
|
||||
|
|
@ -281,6 +298,7 @@ pop_struct() {
|
|||
%token KW_SIGNED
|
||||
%token KW_SIZEOF
|
||||
%token KW_STATIC
|
||||
%token KW_STATIC_ASSERT
|
||||
%token KW_STATIC_CAST
|
||||
%token KW_STRUCT
|
||||
%token KW_TEMPLATE
|
||||
|
|
@ -338,7 +356,7 @@ pop_struct() {
|
|||
%type <u.type> enum_element_type
|
||||
/*%type <u.type> typedefname*/
|
||||
%type <u.identifier> name
|
||||
%type <str> string
|
||||
%type <u.expr> string_literal
|
||||
|
||||
/* We need to treat KW_OPERATOR as a scopable keyword. */
|
||||
%type <u.identifier> KW_OPERATOR
|
||||
|
|
@ -511,10 +529,31 @@ declaration:
|
|||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||
}
|
||||
}
|
||||
| KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
|
||||
| KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
|
||||
{
|
||||
CPPMakeSeq *make_seq = new CPPMakeSeq($3->get_simple_name(), $5->get_simple_name(), $7->get_simple_name(), @1.file);
|
||||
current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
|
||||
}
|
||||
| KW_STATIC_ASSERT '(' const_expr ',' string_literal ')'
|
||||
{
|
||||
CPPExpression::Result result = $3->evaluate();
|
||||
if (result._type == CPPExpression::RT_error) {
|
||||
yywarning("static_assert requires a constant expression", @3);
|
||||
} else if (!result.as_boolean()) {
|
||||
stringstream str;
|
||||
str << *$5;
|
||||
yywarning("static_assert failed: " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_STATIC_ASSERT '(' const_expr ')'
|
||||
{
|
||||
// This alternative version of static_assert was introduced in C++17.
|
||||
CPPExpression::Result result = $3->evaluate();
|
||||
if (result._type == CPPExpression::RT_error) {
|
||||
yywarning("static_assert requires a constant expression", @3);
|
||||
} else if (!result.as_boolean()) {
|
||||
yywarning("static_assert failed", @3);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -538,56 +577,60 @@ storage_class:
|
|||
{
|
||||
$$ = 0;
|
||||
}
|
||||
| storage_class KW_EXTERN
|
||||
| KW_EXTERN storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_extern;
|
||||
$$ = $2 | (int)CPPInstance::SC_extern;
|
||||
}
|
||||
| storage_class KW_EXTERN string
|
||||
| KW_EXTERN SIMPLE_STRING storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_extern;
|
||||
if ($3 == "C") {
|
||||
$$ = $3 | (int)CPPInstance::SC_extern;
|
||||
if ($2 == "C") {
|
||||
$$ |= (int)CPPInstance::SC_c_binding;
|
||||
} else if ($3 == "C++") {
|
||||
} else if ($2 == "C++") {
|
||||
$$ &= ~(int)CPPInstance::SC_c_binding;
|
||||
} else {
|
||||
yywarning("Ignoring unknown linkage type \"" + $3 + "\"", @3);
|
||||
yywarning("Ignoring unknown linkage type \"" + $2 + "\"", @2);
|
||||
}
|
||||
}
|
||||
| storage_class KW_STATIC
|
||||
| KW_STATIC storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_static;
|
||||
$$ = $2 | (int)CPPInstance::SC_static;
|
||||
}
|
||||
| storage_class KW_INLINE
|
||||
| KW_INLINE storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_inline;
|
||||
$$ = $2 | (int)CPPInstance::SC_inline;
|
||||
}
|
||||
| storage_class KW_VIRTUAL
|
||||
| KW_VIRTUAL storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_virtual;
|
||||
$$ = $2 | (int)CPPInstance::SC_virtual;
|
||||
}
|
||||
| storage_class KW_EXPLICIT
|
||||
| KW_EXPLICIT storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_explicit;
|
||||
$$ = $2 | (int)CPPInstance::SC_explicit;
|
||||
}
|
||||
| storage_class KW_VOLATILE
|
||||
| KW_REGISTER storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_volatile;
|
||||
$$ = $2 | (int)CPPInstance::SC_register;
|
||||
}
|
||||
| storage_class KW_MUTABLE
|
||||
| KW_VOLATILE storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_mutable;
|
||||
$$ = $2 | (int)CPPInstance::SC_volatile;
|
||||
}
|
||||
| storage_class KW_REGISTER
|
||||
| KW_MUTABLE storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_register;
|
||||
$$ = $2 | (int)CPPInstance::SC_mutable;
|
||||
}
|
||||
| storage_class KW_BLOCKING
|
||||
| KW_CONSTEXPR storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_blocking;
|
||||
$$ = $2 | (int)CPPInstance::SC_constexpr;
|
||||
}
|
||||
| storage_class KW_EXTENSION
|
||||
| KW_BLOCKING storage_class
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_extension;
|
||||
$$ = $2 | (int)CPPInstance::SC_blocking;
|
||||
}
|
||||
| KW_EXTENSION storage_class
|
||||
{
|
||||
$$ = $2 | (int)CPPInstance::SC_extension;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -771,16 +814,18 @@ function_prototype:
|
|||
}
|
||||
formal_parameter_list ')' function_post
|
||||
{
|
||||
pop_scope();
|
||||
CPPType *type;
|
||||
if ($1->get_simple_name() == current_scope->get_simple_name()) {
|
||||
if ($1->get_simple_name() == current_scope->get_simple_name() ||
|
||||
$1->get_simple_name() == string("~") + current_scope->get_simple_name()) {
|
||||
// This is a constructor, and has no return.
|
||||
type = new CPPSimpleType(CPPSimpleType::T_void);
|
||||
} else {
|
||||
// This isn't a constructor, so it has an implicit return type of
|
||||
// int.
|
||||
yywarning("function has no return type, assuming int", @1);
|
||||
type = new CPPSimpleType(CPPSimpleType::T_int);
|
||||
}
|
||||
pop_scope();
|
||||
|
||||
CPPInstanceIdentifier *ii = new CPPInstanceIdentifier($1);
|
||||
ii->add_func_modifier($4, $6);
|
||||
|
|
@ -822,7 +867,7 @@ function_prototype:
|
|||
yyerror("Invalid destructor name: ~" + $2->get_fully_scoped_name(), @2);
|
||||
} else {
|
||||
CPPIdentifier *ident =
|
||||
new CPPIdentifier("~" + $2->get_simple_name(), @2.file);
|
||||
new CPPIdentifier("~" + $2->get_simple_name(), @2);
|
||||
delete $2;
|
||||
|
||||
CPPType *type;
|
||||
|
|
@ -849,6 +894,9 @@ function_prototype:
|
|||
{
|
||||
pop_scope();
|
||||
CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if (type == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert(type != NULL);
|
||||
|
||||
CPPInstanceIdentifier *ii = $4;
|
||||
|
|
@ -864,6 +912,9 @@ function_prototype:
|
|||
{
|
||||
pop_scope();
|
||||
CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if (type == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert(type != NULL);
|
||||
|
||||
CPPInstanceIdentifier *ii = $5;
|
||||
|
|
@ -897,7 +948,7 @@ function_prototype:
|
|||
string name = "operator typecast " + $2->get_simple_name();
|
||||
CPPIdentifier *ident = $1;
|
||||
if (ident == NULL) {
|
||||
ident = new CPPIdentifier(name, @1.file);
|
||||
ident = new CPPIdentifier(name, @2);
|
||||
} else {
|
||||
ident->add_name(name);
|
||||
}
|
||||
|
|
@ -918,7 +969,7 @@ function_prototype:
|
|||
|
||||
CPPIdentifier *ident = $1;
|
||||
if (ident == NULL) {
|
||||
ident = new CPPIdentifier("operator typecast", @1.file);
|
||||
ident = new CPPIdentifier("operator typecast", @4);
|
||||
} else {
|
||||
ident->add_name("operator typecast");
|
||||
}
|
||||
|
|
@ -1138,6 +1189,7 @@ template_declaration:
|
|||
{
|
||||
pop_scope();
|
||||
}
|
||||
| KW_TEMPLATE type_like_declaration
|
||||
;
|
||||
|
||||
template_formal_parameters:
|
||||
|
|
@ -1205,6 +1257,9 @@ template_formal_parameter_type:
|
|||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if ($$ == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
;
|
||||
|
|
@ -1222,17 +1277,37 @@ instance_identifier:
|
|||
// like a regular function.
|
||||
CPPIdentifier *ident = $1;
|
||||
if (ident == NULL) {
|
||||
ident = new CPPIdentifier("operator "+$2, @2.file);
|
||||
ident = new CPPIdentifier("operator "+$2, @2);
|
||||
} else {
|
||||
ident->_names.push_back("operator "+$2);
|
||||
}
|
||||
|
||||
$$ = new CPPInstanceIdentifier(ident);
|
||||
}
|
||||
| KW_OPERATOR SIMPLE_STRING IDENTIFIER
|
||||
{
|
||||
// A C++11 literal operator.
|
||||
if (!$2.empty()) {
|
||||
yyerror("expected empty string", @2);
|
||||
}
|
||||
CPPIdentifier *ident = $1;
|
||||
if (ident == NULL) {
|
||||
ident = new CPPIdentifier("operator \"\" "+$3->get_simple_name(), @3);
|
||||
} else {
|
||||
ident->_names.push_back("operator \"\" "+$3->get_simple_name());
|
||||
}
|
||||
|
||||
$$ = new CPPInstanceIdentifier(ident);
|
||||
}
|
||||
| KW_CONST instance_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_const);
|
||||
}
|
||||
| KW_VOLATILE instance_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_volatile);
|
||||
}
|
||||
| '*' instance_identifier %prec UNARY
|
||||
{
|
||||
|
|
@ -1394,20 +1469,22 @@ formal_parameter:
|
|||
{
|
||||
$$ = new CPPInstance($1, $2, 0, @2.file);
|
||||
$$->set_initializer($3);
|
||||
}
|
||||
| IDENTIFIER formal_parameter_identifier maybe_initialize
|
||||
{
|
||||
yywarning("Not a type: " + $1->get_fully_scoped_name(), @1);
|
||||
CPPType *type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
|
||||
$$ = new CPPInstance(type, $2, 0, @2.file);
|
||||
$$->set_initializer($3);
|
||||
}
|
||||
| KW_CONST type formal_parameter_identifier maybe_initialize
|
||||
{
|
||||
$3->add_modifier(IIT_const);
|
||||
$$ = new CPPInstance($2, $3, 0, @3.file);
|
||||
$$->set_initializer($4);
|
||||
}
|
||||
| KW_CONST KW_REGISTER type formal_parameter_identifier maybe_initialize
|
||||
{
|
||||
$4->add_modifier(IIT_const);
|
||||
$$ = new CPPInstance($3, $4, 0, @3.file);
|
||||
$$->set_initializer($5);
|
||||
}
|
||||
| KW_REGISTER formal_parameter
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| formal_const_expr
|
||||
{
|
||||
|
|
@ -1435,6 +1512,11 @@ not_paren_formal_parameter_identifier:
|
|||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_const);
|
||||
}
|
||||
| KW_VOLATILE not_paren_formal_parameter_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_volatile);
|
||||
}
|
||||
| '*' not_paren_formal_parameter_identifier %prec UNARY
|
||||
{
|
||||
|
|
@ -1480,6 +1562,11 @@ formal_parameter_identifier:
|
|||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_const);
|
||||
}
|
||||
| KW_VOLATILE formal_parameter_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_volatile);
|
||||
}
|
||||
| '*' formal_parameter_identifier %prec UNARY
|
||||
{
|
||||
|
|
@ -1528,6 +1615,11 @@ empty_instance_identifier:
|
|||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_const);
|
||||
}
|
||||
| KW_VOLATILE empty_instance_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_volatile);
|
||||
}
|
||||
| '*' empty_instance_identifier %prec UNARY
|
||||
{
|
||||
|
|
@ -1570,6 +1662,9 @@ type:
|
|||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if ($$ == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
| KW_TYPENAME name
|
||||
|
|
@ -1619,6 +1714,19 @@ type:
|
|||
}
|
||||
$$ = et;
|
||||
}
|
||||
}
|
||||
| KW_DECLTYPE '(' const_expr ')'
|
||||
{
|
||||
$$ = $3->determine_type();
|
||||
if ($$ == (CPPType *)NULL) {
|
||||
stringstream str;
|
||||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_AUTO
|
||||
{
|
||||
$$ = new CPPSimpleType(CPPSimpleType::T_auto);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1630,6 +1738,9 @@ type_decl:
|
|||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if ($$ == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
| KW_TYPENAME name
|
||||
|
|
@ -1697,6 +1808,19 @@ type_decl:
|
|||
}
|
||||
$$ = et;
|
||||
}
|
||||
}
|
||||
| KW_DECLTYPE '(' const_expr ')'
|
||||
{
|
||||
$$ = $3->determine_type();
|
||||
if ($$ == (CPPType *)NULL) {
|
||||
stringstream str;
|
||||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_AUTO
|
||||
{
|
||||
$$ = new CPPSimpleType(CPPSimpleType::T_auto);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1708,6 +1832,9 @@ predefined_type:
|
|||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if ($$ == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
| KW_TYPENAME name
|
||||
|
|
@ -1980,8 +2107,32 @@ namespace_declaration:
|
|||
cpp '}'
|
||||
{
|
||||
pop_scope();
|
||||
}
|
||||
| KW_INLINE KW_NAMESPACE name '{'
|
||||
{
|
||||
CPPScope *scope = $3->find_scope(current_scope, global_scope, current_lexer);
|
||||
if (scope == NULL) {
|
||||
// This must be a new namespace declaration.
|
||||
CPPScope *parent_scope =
|
||||
$3->get_scope(current_scope, global_scope, current_lexer);
|
||||
if (parent_scope == NULL) {
|
||||
parent_scope = current_scope;
|
||||
}
|
||||
scope = new CPPScope(parent_scope, $3->_names.back(), V_public);
|
||||
}
|
||||
|
||||
CPPNamespace *nspace = new CPPNamespace($3, scope, @2.file);
|
||||
nspace->_is_inline = true;
|
||||
current_scope->add_declaration(nspace, global_scope, current_lexer, @2);
|
||||
current_scope->define_namespace(nspace);
|
||||
push_scope(scope);
|
||||
}
|
||||
cpp '}'
|
||||
{
|
||||
pop_scope();
|
||||
}
|
||||
| KW_NAMESPACE '{' cpp '}'
|
||||
| KW_INLINE KW_NAMESPACE '{' cpp '}'
|
||||
;
|
||||
|
||||
using_declaration:
|
||||
|
|
@ -2134,48 +2285,34 @@ code_block:
|
|||
|
||||
element:
|
||||
REAL
|
||||
{
|
||||
}
|
||||
| INTEGER
|
||||
{
|
||||
}
|
||||
| STRING
|
||||
{
|
||||
}
|
||||
| SIMPLE_STRING
|
||||
| STRING_LITERAL
|
||||
| CUSTOM_LITERAL
|
||||
| CHAR_TOK
|
||||
{
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
}
|
||||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
}
|
||||
| SCOPING
|
||||
{
|
||||
}
|
||||
| SIMPLE_IDENTIFIER
|
||||
{
|
||||
}
|
||||
| ELLIPSIS | OROR | ANDAND
|
||||
| EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE
|
||||
| LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT
|
||||
| SCOPE | PLUSPLUS | MINUSMINUS
|
||||
| TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
|
||||
| OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
|
||||
| KW_BOOL | KW_CATCH | KW_CHAR | KW_CHAR16_T | KW_CHAR32_T
|
||||
| KW_WCHAR_T | KW_CLASS | KW_CONST
|
||||
| KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH
|
||||
| KW_CHAR | KW_CHAR16_T | KW_CHAR32_T
|
||||
| KW_CLASS | KW_CONST | KW_CONSTEXPR | KW_DECLTYPE | KW_DEFAULT
|
||||
| KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM
|
||||
| KW_EXTERN | KW_EXPLICIT | KW_FALSE
|
||||
| KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO
|
||||
| KW_IF | KW_INLINE | KW_INT
|
||||
| KW_LONG | KW_MUTABLE | KW_NEW | KW_PRIVATE | KW_PROTECTED
|
||||
| KW_IF | KW_INLINE | KW_INT | KW_LONG | KW_MUTABLE
|
||||
| KW_NEW | KW_NULLPTR | KW_OPERATOR | KW_PRIVATE | KW_PROTECTED
|
||||
| KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_RETURN
|
||||
| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_CAST
|
||||
| KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF | KW_TYPENAME
|
||||
| KW_UNION | KW_UNSIGNED | KW_VIRTUAL | KW_VOID | KW_VOLATILE
|
||||
| KW_WHILE
|
||||
| KW_OPERATOR
|
||||
| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_ASSERT
|
||||
| KW_STATIC_CAST | KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY
|
||||
| KW_TYPEDEF | KW_TYPENAME | KW_UNION | KW_UNSIGNED | KW_VIRTUAL
|
||||
| KW_VOID | KW_VOLATILE | KW_WCHAR_T | KW_WHILE
|
||||
{
|
||||
}
|
||||
| '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%'
|
||||
|
|
@ -2236,6 +2373,10 @@ no_angle_bracket_const_expr:
|
|||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::alignof_func($3));
|
||||
}
|
||||
| '!' no_angle_bracket_const_expr %prec UNARY
|
||||
{
|
||||
|
|
@ -2247,15 +2388,7 @@ no_angle_bracket_const_expr:
|
|||
}
|
||||
| '-' no_angle_bracket_const_expr %prec UNARY
|
||||
{
|
||||
if ($2->_type == CPPExpression::T_integer) {
|
||||
$$ = $2;
|
||||
$$->_u._integer = -$$->_u._integer;
|
||||
} else if ($2->_type == CPPExpression::T_real) {
|
||||
$$ = $2;
|
||||
$$->_u._real = -$$->_u._real;
|
||||
} else {
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
| '*' no_angle_bracket_const_expr %prec UNARY
|
||||
{
|
||||
|
|
@ -2381,6 +2514,9 @@ const_expr:
|
|||
{
|
||||
// A constructor call.
|
||||
CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if (type == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert(type != NULL);
|
||||
$$ = new CPPExpression(CPPExpression::construct_op(type, $3));
|
||||
}
|
||||
|
|
@ -2463,6 +2599,10 @@ const_expr:
|
|||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::alignof_func($3));
|
||||
}
|
||||
| KW_NEW predefined_type %prec UNARY
|
||||
{
|
||||
|
|
@ -2482,15 +2622,7 @@ const_expr:
|
|||
}
|
||||
| '-' const_expr %prec UNARY
|
||||
{
|
||||
if ($2->_type == CPPExpression::T_integer) {
|
||||
$$ = $2;
|
||||
$$->_u._integer = -$$->_u._integer;
|
||||
} else if ($2->_type == CPPExpression::T_real) {
|
||||
$$ = $2;
|
||||
$$->_u._real = -$$->_u._real;
|
||||
} else {
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
| '*' const_expr %prec UNARY
|
||||
{
|
||||
|
|
@ -2623,13 +2755,21 @@ const_operand:
|
|||
{
|
||||
$$ = new CPPExpression($1);
|
||||
}
|
||||
| string
|
||||
| string_literal
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
$$ = $1;
|
||||
}
|
||||
| CUSTOM_LITERAL
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new CPPExpression($1, current_scope, global_scope, current_lexer);
|
||||
}
|
||||
| KW_NULLPTR
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::get_nullptr());
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -2660,6 +2800,10 @@ formal_const_expr:
|
|||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::alignof_func($3));
|
||||
}
|
||||
| KW_NEW predefined_type %prec UNARY
|
||||
{
|
||||
|
|
@ -2679,15 +2823,7 @@ formal_const_expr:
|
|||
}
|
||||
| '-' const_expr %prec UNARY
|
||||
{
|
||||
if ($2->_type == CPPExpression::T_integer) {
|
||||
$$ = $2;
|
||||
$$->_u._integer = -$$->_u._integer;
|
||||
} else if ($2->_type == CPPExpression::T_real) {
|
||||
$$ = $2;
|
||||
$$->_u._real = -$$->_u._real;
|
||||
} else {
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
| '&' const_expr %prec UNARY
|
||||
{
|
||||
|
|
@ -2816,9 +2952,21 @@ formal_const_operand:
|
|||
{
|
||||
$$ = new CPPExpression($1);
|
||||
}
|
||||
| string
|
||||
| string_literal
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
$$ = $1;
|
||||
}
|
||||
| CUSTOM_LITERAL
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new CPPExpression($1, current_scope, global_scope, current_lexer);
|
||||
}
|
||||
| KW_NULLPTR
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::get_nullptr());
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -2850,6 +2998,9 @@ typedefname:
|
|||
TYPENAME_IDENTIFIER
|
||||
{
|
||||
CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if (type == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert(type != NULL);
|
||||
$$ = type;
|
||||
}
|
||||
|
|
@ -2872,14 +3023,29 @@ name:
|
|||
}
|
||||
;
|
||||
|
||||
string:
|
||||
STRING
|
||||
string_literal:
|
||||
SIMPLE_STRING
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
}
|
||||
| STRING_LITERAL
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| string STRING
|
||||
| string_literal SIMPLE_STRING
|
||||
{
|
||||
$$ = $1 + $2;
|
||||
// The right string takes on the literal type of the left.
|
||||
$$ = $1;
|
||||
$$->_str += $2;
|
||||
}
|
||||
| string_literal STRING_LITERAL
|
||||
{
|
||||
// We have to check that the two literal types match up.
|
||||
$$ = $1;
|
||||
if ($2->_type != CPPExpression::T_string && $2->_type != $1->_type) {
|
||||
yywarning("cannot concatenate two string literals of different types", @$);
|
||||
}
|
||||
$$->_str += $2->_str;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ class cppyystype {
|
|||
public:
|
||||
string str;
|
||||
union {
|
||||
int integer;
|
||||
double real;
|
||||
unsigned long long integer;
|
||||
long double real;
|
||||
CPPScope *scope;
|
||||
CPPDeclaration *decl;
|
||||
CPPInstance *instance;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "cppConstType.h"
|
||||
#include "cppScope.h"
|
||||
#include "cppParser.h"
|
||||
#include "cppIdentifier.h"
|
||||
#include "indent.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -82,6 +83,7 @@ add_element(const string &name, CPPExpression *value) {
|
|||
inst = new CPPInstance(CPPType::new_type(new CPPConstType(_element_type)), ident);
|
||||
}
|
||||
|
||||
inst->_storage_class |= CPPInstance::SC_constexpr;
|
||||
_elements.push_back(inst);
|
||||
|
||||
if (value == (CPPExpression *)NULL) {
|
||||
|
|
@ -176,7 +178,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
|||
|
||||
bool any_changed = false;
|
||||
|
||||
for (int i = 0; i < _elements.size(); ++i) {
|
||||
for (size_t i = 0; i < _elements.size(); ++i) {
|
||||
CPPInstance *elem_rep =
|
||||
_elements[i]->substitute_decl(subst, current_scope, global_scope)
|
||||
->as_instance();
|
||||
|
|
|
|||
|
|
@ -201,6 +201,19 @@ output(ostream &out) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression::
|
||||
CPPExpression(unsigned long long value) :
|
||||
CPPDeclaration(CPPFile())
|
||||
{
|
||||
_type = T_integer;
|
||||
_u._integer = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -220,7 +233,7 @@ CPPExpression(int value) :
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression::
|
||||
CPPExpression(double value) :
|
||||
CPPExpression(long double value) :
|
||||
CPPDeclaration(CPPFile())
|
||||
{
|
||||
_type = T_real;
|
||||
|
|
@ -397,6 +410,89 @@ sizeof_func(CPPType *type) {
|
|||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named alignof_func constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
alignof_func(CPPType *type) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_alignof;
|
||||
expr._u._typecast._to = type;
|
||||
expr._u._typecast._op1 = NULL;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
literal(unsigned long long value, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_literal;
|
||||
expr._u._literal._value = new CPPExpression(value);
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
literal(long double value, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_literal;
|
||||
expr._u._literal._value = new CPPExpression(value);
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
literal(CPPExpression *value, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_literal;
|
||||
expr._u._literal._value = value;
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named raw_literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
raw_literal(const string &raw, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_raw_literal;
|
||||
expr._str = raw;
|
||||
expr._u._literal._value = (CPPExpression *)NULL;
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::get_nullptr
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const CPPExpression &CPPExpression::
|
||||
get_nullptr() {
|
||||
static CPPExpression expr(0);
|
||||
expr._type = T_nullptr;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Destructor
|
||||
// Access: Public
|
||||
|
|
@ -416,18 +512,29 @@ evaluate() const {
|
|||
Result r1, r2;
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return Result((void *)0);
|
||||
|
||||
case T_integer:
|
||||
return Result(_u._integer);
|
||||
return Result((int)_u._integer);
|
||||
|
||||
case T_real:
|
||||
return Result(_u._real);
|
||||
return Result((double)_u._real);
|
||||
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return Result();
|
||||
|
||||
case T_variable:
|
||||
if (_u._variable->_type != NULL &&
|
||||
_u._variable->_initializer != NULL) {
|
||||
// A constexpr variable, which is treated as const.
|
||||
if (_u._variable->_storage_class & CPPInstance::SC_constexpr) {
|
||||
return _u._variable->_initializer->evaluate();
|
||||
}
|
||||
// A const variable. Fetch its assigned value.
|
||||
CPPConstType *const_type = _u._variable->_type->as_const_type();
|
||||
if (const_type != NULL) {
|
||||
|
|
@ -468,6 +575,17 @@ evaluate() const {
|
|||
case T_sizeof:
|
||||
return Result();
|
||||
|
||||
case T_alignof:
|
||||
if (_u._typecast._to != NULL) {
|
||||
// Check if the type is defined with an alignas. TODO: this should
|
||||
// probably be moved to a virtual getter on CPPType.
|
||||
CPPExtensionType *etype = _u._typecast._to->as_extension_type();
|
||||
if (etype != NULL && etype->_alignment != NULL) {
|
||||
return etype->_alignment->evaluate();
|
||||
}
|
||||
}
|
||||
return Result();
|
||||
|
||||
case T_binary_operation:
|
||||
assert(_u._op._op2 != NULL);
|
||||
r2 = _u._op._op2->evaluate();
|
||||
|
|
@ -503,23 +621,39 @@ evaluate() const {
|
|||
// long as we can evaluate the second one *and* that comes out
|
||||
// to be true.
|
||||
if (_u._op._operator == OROR && r2._type == RT_integer &&
|
||||
r2.as_integer() != 0) {
|
||||
r2.as_boolean()) {
|
||||
return r2;
|
||||
}
|
||||
|
||||
// Ditto for the operator being && and the second one coming out
|
||||
// false.
|
||||
if (_u._op._operator == ANDAND && r2._type == RT_integer &&
|
||||
r2.as_integer() == 0) {
|
||||
!r2.as_boolean()) {
|
||||
return r2;
|
||||
}
|
||||
|
||||
// Also for the operator being [] and the operand being a string.
|
||||
if (_u._op._operator == '[' && r2._type == RT_integer &&
|
||||
(_u._op._op1->_type == T_string ||
|
||||
_u._op._op1->_type == T_u8string)) {
|
||||
|
||||
int index = (int)r2.as_integer();
|
||||
if ((size_t)index == _u._op._op1->_str.size()) {
|
||||
return Result(0);
|
||||
} else if (index >= 0 && (size_t)index < _u._op._op1->_str.size()) {
|
||||
return Result(_u._op._op1->_str[(size_t)index]);
|
||||
} else {
|
||||
cerr << "array index " << index << " out of bounds of string literal "
|
||||
<< *_u._op._op1 << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return r1;
|
||||
}
|
||||
|
||||
switch (_u._op._operator) {
|
||||
case UNARY_NOT:
|
||||
return Result(!r1.as_integer());
|
||||
return Result(!r1.as_boolean());
|
||||
|
||||
case UNARY_NEGATE:
|
||||
return Result(~r1.as_integer());
|
||||
|
|
@ -569,14 +703,14 @@ evaluate() const {
|
|||
return Result(r1.as_integer() & r2.as_integer());
|
||||
|
||||
case OROR:
|
||||
if (r1.as_integer()) {
|
||||
if (r1.as_boolean()) {
|
||||
return r1;
|
||||
} else {
|
||||
return r2;
|
||||
}
|
||||
|
||||
case ANDAND:
|
||||
if (r1.as_integer()) {
|
||||
if (r1.as_boolean()) {
|
||||
return r2;
|
||||
} else {
|
||||
return r1;
|
||||
|
|
@ -652,6 +786,10 @@ evaluate() const {
|
|||
abort();
|
||||
}
|
||||
|
||||
case T_literal:
|
||||
case T_raw_literal:
|
||||
return Result();
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
|
|
@ -671,25 +809,51 @@ determine_type() const {
|
|||
CPPType *t1 = (CPPType *)NULL;
|
||||
CPPType *t2 = (CPPType *)NULL;
|
||||
|
||||
CPPType *int_type =
|
||||
static CPPType *nullptr_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_nullptr));
|
||||
|
||||
static CPPType *int_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int));
|
||||
|
||||
CPPType *bool_type =
|
||||
static CPPType *unsigned_long_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
|
||||
CPPSimpleType::F_unsigned |
|
||||
CPPSimpleType::F_long));
|
||||
|
||||
static CPPType *bool_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool));
|
||||
|
||||
CPPType *float_type =
|
||||
static CPPType *float_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double));
|
||||
|
||||
CPPType *char_type =
|
||||
static CPPType *char_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char));
|
||||
|
||||
CPPType *const_char_type =
|
||||
CPPType::new_type(new CPPConstType(char_type));
|
||||
static CPPType *wchar_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t));
|
||||
|
||||
CPPType *char_star_type =
|
||||
CPPType::new_type(new CPPPointerType(const_char_type));
|
||||
static CPPType *char16_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t));
|
||||
|
||||
static CPPType *char32_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t));
|
||||
|
||||
static CPPType *char_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(char_type))));
|
||||
|
||||
static CPPType *wchar_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(wchar_type))));
|
||||
|
||||
static CPPType *char16_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(char16_type))));
|
||||
|
||||
static CPPType *char32_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(char32_type))));
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return nullptr_type;
|
||||
|
||||
case T_integer:
|
||||
return int_type;
|
||||
|
||||
|
|
@ -697,7 +861,19 @@ determine_type() const {
|
|||
return float_type;
|
||||
|
||||
case T_string:
|
||||
return char_star_type;
|
||||
return char_str_type;
|
||||
|
||||
case T_wstring:
|
||||
return wchar_str_type;
|
||||
|
||||
case T_u8string:
|
||||
return char_str_type;
|
||||
|
||||
case T_u16string:
|
||||
return char16_str_type;
|
||||
|
||||
case T_u32string:
|
||||
return char32_str_type;
|
||||
|
||||
case T_variable:
|
||||
return _u._variable->_type;
|
||||
|
|
@ -725,7 +901,11 @@ determine_type() const {
|
|||
return CPPType::new_type(new CPPPointerType(_u._typecast._to));
|
||||
|
||||
case T_sizeof:
|
||||
return int_type;
|
||||
case T_alignof:
|
||||
// Note: this should actually be size_t, but that is defined as a
|
||||
// typedef in parser-inc. We could try to resolve it, but that's
|
||||
// hacky. Eh, it's probably not worth the effort to get this right.
|
||||
return unsigned_long_type;
|
||||
|
||||
case T_binary_operation:
|
||||
case T_trinary_operation:
|
||||
|
|
@ -819,6 +999,18 @@ determine_type() const {
|
|||
abort();
|
||||
}
|
||||
|
||||
case T_literal:
|
||||
case T_raw_literal:
|
||||
if (_u._literal._operator != NULL) {
|
||||
CPPType *type = _u._literal._operator->_type;
|
||||
|
||||
CPPFunctionType *ftype = type->as_function_type();
|
||||
if (ftype != (CPPFunctionType *)NULL) {
|
||||
return ftype->_return_type;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
|
|
@ -842,9 +1034,14 @@ is_fully_specified() const {
|
|||
}
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
case T_integer:
|
||||
case T_real:
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return false;
|
||||
|
||||
case T_variable:
|
||||
|
|
@ -865,6 +1062,7 @@ is_fully_specified() const {
|
|||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to->is_fully_specified();
|
||||
|
||||
case T_trinary_operation:
|
||||
|
|
@ -882,6 +1080,13 @@ is_fully_specified() const {
|
|||
case T_unary_operation:
|
||||
return _u._op._op1->is_fully_specified();
|
||||
|
||||
case T_literal:
|
||||
return _u._literal._value->is_fully_specified() &&
|
||||
_u._literal._operator->is_fully_specified();
|
||||
|
||||
case T_raw_literal:
|
||||
return _u._literal._value->is_fully_specified();
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
@ -972,6 +1177,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
|||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
rep->_u._typecast._to =
|
||||
_u._typecast._to->substitute_decl(subst, current_scope, global_scope)
|
||||
->as_type();
|
||||
|
|
@ -1025,6 +1231,9 @@ is_tbd() const {
|
|||
case T_variable:
|
||||
if (_u._variable->_type != NULL &&
|
||||
_u._variable->_initializer != NULL) {
|
||||
if (_u._variable->_storage_class & CPPInstance::SC_constexpr) {
|
||||
return false;
|
||||
}
|
||||
CPPConstType *const_type = _u._variable->_type->as_const_type();
|
||||
if (const_type != NULL) {
|
||||
return false;
|
||||
|
|
@ -1042,6 +1251,7 @@ is_tbd() const {
|
|||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to->is_tbd();
|
||||
|
||||
case T_trinary_operation:
|
||||
|
|
@ -1075,6 +1285,10 @@ is_tbd() const {
|
|||
void CPPExpression::
|
||||
output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
out << "nullptr";
|
||||
break;
|
||||
|
||||
case T_integer:
|
||||
out << _u._integer;
|
||||
break;
|
||||
|
|
@ -1090,8 +1304,29 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
break;
|
||||
|
||||
case T_string:
|
||||
out << '"';
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
{
|
||||
switch (_type) {
|
||||
case T_wstring:
|
||||
out << 'L';
|
||||
break;
|
||||
case T_u8string:
|
||||
out << "u8";
|
||||
break;
|
||||
case T_u16string:
|
||||
out << "u";
|
||||
break;
|
||||
case T_u32string:
|
||||
out << "U";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// We don't really care about preserving the encoding for now.
|
||||
out << '"';
|
||||
string::const_iterator si;
|
||||
for (si = _str.begin(); si != _str.end(); ++si) {
|
||||
switch (*si) {
|
||||
|
|
@ -1135,9 +1370,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
if (_u._variable->_type != NULL &&
|
||||
_u._variable->_initializer != NULL &&
|
||||
_u._variable->_vis > V_public) {
|
||||
// A const variable. Fetch its assigned value.
|
||||
// A constexpr or const variable. Fetch its assigned value.
|
||||
CPPConstType *const_type = _u._variable->_type->as_const_type();
|
||||
if (const_type != NULL) {
|
||||
if ((_u._variable->_storage_class & CPPInstance::SC_constexpr) != 0 ||
|
||||
const_type != NULL) {
|
||||
_u._variable->_initializer->output(out, indent_level, scope, false);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1193,6 +1429,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
out << ")";
|
||||
break;
|
||||
|
||||
case T_alignof:
|
||||
out << "alignof(";
|
||||
_u._typecast._to->output(out, indent_level, scope, false);
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case T_unary_operation:
|
||||
switch (_u._op._operator) {
|
||||
case UNARY_NOT:
|
||||
|
|
@ -1208,9 +1450,8 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
break;
|
||||
|
||||
case UNARY_MINUS:
|
||||
out << "(- ";
|
||||
out << '-';
|
||||
_u._op._op1->output(out, indent_level, scope, false);
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case UNARY_STAR:
|
||||
|
|
@ -1362,6 +1603,24 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
out << ")";
|
||||
break;
|
||||
|
||||
case T_literal:
|
||||
_u._literal._value->output(out, indent_level, scope, false);
|
||||
if (_u._literal._operator != NULL) {
|
||||
string name = _u._literal._operator->get_simple_name();
|
||||
assert(name.substr(0, 12) == "operator \"\" ");
|
||||
out << name.substr(12);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_raw_literal:
|
||||
out << _str;
|
||||
if (_u._literal._operator != NULL) {
|
||||
string name = _u._literal._operator->get_simple_name();
|
||||
assert(name.substr(0, 12) == "operator \"\" ");
|
||||
out << name.substr(12);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
out << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
|
@ -1456,6 +1715,9 @@ is_equal(const CPPDeclaration *other) const {
|
|||
}
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return true;
|
||||
|
||||
case T_integer:
|
||||
return _u._integer == ot->_u._integer;
|
||||
|
||||
|
|
@ -1463,6 +1725,10 @@ is_equal(const CPPDeclaration *other) const {
|
|||
return _u._real == ot->_u._real;
|
||||
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return _str == ot->_str;
|
||||
|
||||
case T_variable:
|
||||
|
|
@ -1483,6 +1749,7 @@ is_equal(const CPPDeclaration *other) const {
|
|||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to == ot->_u._typecast._to;
|
||||
|
||||
case T_unary_operation:
|
||||
|
|
@ -1496,6 +1763,14 @@ is_equal(const CPPDeclaration *other) const {
|
|||
return *_u._op._op1 == *ot->_u._op._op1 &&
|
||||
*_u._op._op2 == *ot->_u._op._op2;
|
||||
|
||||
case T_literal:
|
||||
return *_u._literal._value == *ot->_u._literal._value &&
|
||||
_u._literal._operator == ot->_u._literal._operator;
|
||||
|
||||
case T_raw_literal:
|
||||
return _str == ot->_str &&
|
||||
_u._literal._operator == ot->_u._literal._operator;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
|
@ -1520,6 +1795,9 @@ is_less(const CPPDeclaration *other) const {
|
|||
}
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return false;
|
||||
|
||||
case T_integer:
|
||||
return _u._integer < ot->_u._integer;
|
||||
|
||||
|
|
@ -1527,6 +1805,10 @@ is_less(const CPPDeclaration *other) const {
|
|||
return _u._real < ot->_u._real;
|
||||
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return _str < ot->_str;
|
||||
|
||||
case T_variable:
|
||||
|
|
@ -1549,6 +1831,7 @@ is_less(const CPPDeclaration *other) const {
|
|||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to < ot->_u._typecast._to;
|
||||
|
||||
case T_trinary_operation:
|
||||
|
|
@ -1566,6 +1849,18 @@ is_less(const CPPDeclaration *other) const {
|
|||
case T_unary_operation:
|
||||
return *_u._op._op1 < *ot->_u._op._op1;
|
||||
|
||||
case T_literal:
|
||||
if (_u._literal._operator != ot->_u._literal._operator) {
|
||||
return _u._literal._operator < ot->_u._literal._operator;
|
||||
}
|
||||
return *_u._literal._value < *ot->_u._literal._value;
|
||||
|
||||
case T_raw_literal:
|
||||
if (_u._literal._operator != ot->_u._literal._operator) {
|
||||
return _u._literal._operator < ot->_u._literal._operator;
|
||||
}
|
||||
return _str < ot->_str;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ class CPPFunctionGroup;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class CPPExpression : public CPPDeclaration {
|
||||
public:
|
||||
CPPExpression(unsigned long long value);
|
||||
CPPExpression(int value);
|
||||
CPPExpression(const string &value);
|
||||
CPPExpression(double value);
|
||||
CPPExpression(long double value);
|
||||
CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
|
||||
CPPScope *global_scope, CPPPreprocessor *error_sink = NULL);
|
||||
CPPExpression(int unary_operator, CPPExpression *op1);
|
||||
|
|
@ -43,6 +44,14 @@ public:
|
|||
static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
|
||||
static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
|
||||
static CPPExpression sizeof_func(CPPType *type);
|
||||
static CPPExpression alignof_func(CPPType *type);
|
||||
|
||||
static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
|
||||
static CPPExpression literal(long double value, CPPInstance *lit_op);
|
||||
static CPPExpression literal(CPPExpression *value, CPPInstance *lit_op);
|
||||
static CPPExpression raw_literal(const string &raw, CPPInstance *lit_op);
|
||||
|
||||
static const CPPExpression &get_nullptr();
|
||||
|
||||
~CPPExpression();
|
||||
|
||||
|
|
@ -92,9 +101,14 @@ public:
|
|||
|
||||
|
||||
enum Type {
|
||||
T_nullptr,
|
||||
T_integer,
|
||||
T_real,
|
||||
T_string,
|
||||
T_wstring,
|
||||
T_u8string,
|
||||
T_u16string,
|
||||
T_u32string,
|
||||
T_variable,
|
||||
T_function,
|
||||
T_unknown_ident,
|
||||
|
|
@ -104,16 +118,19 @@ public:
|
|||
T_new,
|
||||
T_default_new,
|
||||
T_sizeof,
|
||||
T_alignof,
|
||||
T_unary_operation,
|
||||
T_binary_operation,
|
||||
T_trinary_operation,
|
||||
T_literal,
|
||||
T_raw_literal,
|
||||
};
|
||||
|
||||
Type _type;
|
||||
string _str;
|
||||
union {
|
||||
int _integer;
|
||||
double _real;
|
||||
unsigned long long _integer;
|
||||
long double _real;
|
||||
CPPInstance *_variable;
|
||||
CPPFunctionGroup *_fgroup;
|
||||
CPPIdentifier *_ident;
|
||||
|
|
@ -131,6 +148,11 @@ public:
|
|||
CPPExpression *_op2;
|
||||
CPPExpression *_op3;
|
||||
} _op;
|
||||
class {
|
||||
public:
|
||||
CPPInstance *_operator;
|
||||
CPPExpression *_value;
|
||||
} _literal;
|
||||
} _u;
|
||||
|
||||
protected:
|
||||
|
|
@ -146,5 +168,3 @@ operator << (ostream &out, const CPPExpression::Result &result) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ CPPExtensionType(CPPExtensionType::Type type,
|
|||
CPPIdentifier *ident, CPPScope *current_scope,
|
||||
const CPPFile &file) :
|
||||
CPPType(file),
|
||||
_type(type), _ident(ident)
|
||||
_type(type), _ident(ident),
|
||||
_alignment(NULL)
|
||||
{
|
||||
if (_ident != NULL) {
|
||||
_ident->_native_scope = current_scope;
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ public:
|
|||
|
||||
virtual CPPExtensionType *as_extension_type();
|
||||
|
||||
|
||||
Type _type;
|
||||
CPPIdentifier *_ident;
|
||||
CPPExpression *_alignment;
|
||||
};
|
||||
|
||||
ostream &operator << (ostream &out, CPPExtensionType::Type type);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,39 @@
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPIdentifier::
|
||||
CPPIdentifier(const string &name, const CPPFile &file) : _file(file) {
|
||||
CPPIdentifier(const string &name, const CPPFile &file) {
|
||||
_names.push_back(CPPNameComponent(name));
|
||||
_native_scope = (CPPScope *)NULL;
|
||||
_loc.first_line = 0;
|
||||
_loc.first_column = 0;
|
||||
_loc.last_line = 0;
|
||||
_loc.last_column = 0;
|
||||
_loc.file = file;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPIdentifier::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPIdentifier::
|
||||
CPPIdentifier(const CPPNameComponent &name, const CPPFile &file) {
|
||||
_names.push_back(name);
|
||||
_native_scope = (CPPScope *)NULL;
|
||||
_loc.first_line = 0;
|
||||
_loc.first_column = 0;
|
||||
_loc.last_line = 0;
|
||||
_loc.last_column = 0;
|
||||
_loc.file = file;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPIdentifier::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPIdentifier::
|
||||
CPPIdentifier(const string &name, const cppyyltype &loc) : _loc(loc) {
|
||||
_names.push_back(CPPNameComponent(name));
|
||||
_native_scope = (CPPScope *)NULL;
|
||||
}
|
||||
|
|
@ -39,7 +71,7 @@ CPPIdentifier(const string &name, const CPPFile &file) : _file(file) {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPIdentifier::
|
||||
CPPIdentifier(const CPPNameComponent &name, const CPPFile &file) : _file(file) {
|
||||
CPPIdentifier(const CPPNameComponent &name, const cppyyltype &loc) : _loc(loc) {
|
||||
_names.push_back(name);
|
||||
_native_scope = (CPPScope *)NULL;
|
||||
}
|
||||
|
|
@ -155,6 +187,12 @@ get_local_name(CPPScope *scope) const {
|
|||
// last name.
|
||||
CPPScope *my_scope = get_scope(scope, NULL);
|
||||
|
||||
// Strip off template scopes, since they don't add anything
|
||||
// particularly meaningful to the local name.
|
||||
while (my_scope != NULL && my_scope->as_template_scope() != NULL) {
|
||||
my_scope = my_scope->get_parent_scope();
|
||||
}
|
||||
|
||||
if (my_scope == NULL) {
|
||||
result = get_fully_scoped_name();
|
||||
} else if (my_scope == scope) {
|
||||
|
|
@ -256,7 +294,8 @@ get_scope(CPPScope *current_scope, CPPScope *global_scope,
|
|||
if (error_sink != NULL) {
|
||||
error_sink->error("Symbol " + _names[i].get_name() +
|
||||
" is not a known scope in " +
|
||||
scope->get_fully_scoped_name());
|
||||
scope->get_fully_scoped_name(),
|
||||
_loc);
|
||||
}
|
||||
return (CPPScope *)NULL;
|
||||
}
|
||||
|
|
@ -302,7 +341,8 @@ get_scope(CPPScope *current_scope, CPPScope *global_scope,
|
|||
if (error_sink != NULL) {
|
||||
error_sink->error("Symbol " + _names[i].get_name() +
|
||||
" is not a known scope in " +
|
||||
scope->get_fully_scoped_name());
|
||||
scope->get_fully_scoped_name(),
|
||||
_loc);
|
||||
}
|
||||
return (CPPScope *)NULL;
|
||||
}
|
||||
|
|
@ -429,7 +469,12 @@ find_symbol(CPPScope *current_scope, CPPScope *global_scope,
|
|||
|
||||
CPPDeclaration *sym;
|
||||
if (!_names.back().has_templ()) {
|
||||
sym = scope->find_symbol(get_simple_name());
|
||||
if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) {
|
||||
// An identifier like Class::Class always refers to the class constructor.
|
||||
sym = scope->get_struct_type()->get_constructor();
|
||||
} else {
|
||||
sym = scope->find_symbol(get_simple_name());
|
||||
}
|
||||
|
||||
} else {
|
||||
sym = scope->find_template(get_simple_name());
|
||||
|
|
@ -465,7 +510,12 @@ find_symbol(CPPScope *current_scope, CPPScope *global_scope,
|
|||
|
||||
CPPDeclaration *sym;
|
||||
if (!_names.back().has_templ()) {
|
||||
sym = scope->find_symbol(get_simple_name());
|
||||
if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) {
|
||||
// An identifier like Class::Class always refers to the class constructor.
|
||||
sym = scope->get_struct_type()->get_constructor();
|
||||
} else {
|
||||
sym = scope->find_symbol(get_simple_name());
|
||||
}
|
||||
|
||||
} else {
|
||||
sym = scope->find_template(get_simple_name());
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "cppDeclaration.h"
|
||||
#include "cppNameComponent.h"
|
||||
#include "cppFile.h"
|
||||
#include "cppBisonDefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
@ -37,6 +38,8 @@ class CPPIdentifier {
|
|||
public:
|
||||
CPPIdentifier(const string &name, const CPPFile &file = CPPFile());
|
||||
CPPIdentifier(const CPPNameComponent &name, const CPPFile &file = CPPFile());
|
||||
CPPIdentifier(const string &name, const cppyyltype &loc);
|
||||
CPPIdentifier(const CPPNameComponent &name, const cppyyltype &loc);
|
||||
void add_name(const string &name);
|
||||
void add_name(const CPPNameComponent &name);
|
||||
|
||||
|
|
@ -91,7 +94,7 @@ public:
|
|||
typedef vector<CPPNameComponent> Names;
|
||||
Names _names;
|
||||
CPPScope *_native_scope;
|
||||
CPPFile _file;
|
||||
cppyyltype _loc;
|
||||
};
|
||||
|
||||
inline ostream &operator << (ostream &out, const CPPIdentifier &identifier) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ CPPInstance(CPPType *type, const string &name, int storage_class) :
|
|||
CPPDeclaration(CPPFile()),
|
||||
_type(type),
|
||||
_ident(new CPPIdentifier(name)),
|
||||
_storage_class(storage_class)
|
||||
_storage_class(storage_class),
|
||||
_alignment(NULL)
|
||||
{
|
||||
_initializer = NULL;
|
||||
}
|
||||
|
|
@ -53,7 +54,8 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
|
|||
CPPDeclaration(CPPFile()),
|
||||
_type(type),
|
||||
_ident(ident),
|
||||
_storage_class(storage_class)
|
||||
_storage_class(storage_class),
|
||||
_alignment(NULL)
|
||||
{
|
||||
_initializer = NULL;
|
||||
}
|
||||
|
|
@ -69,7 +71,8 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
|
|||
CPPInstance::
|
||||
CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
|
||||
const CPPFile &file) :
|
||||
CPPDeclaration(file)
|
||||
CPPDeclaration(file),
|
||||
_alignment(NULL)
|
||||
{
|
||||
_type = ii->unroll_type(type);
|
||||
_ident = ii->_ident;
|
||||
|
|
@ -102,7 +105,8 @@ CPPInstance(const CPPInstance ©) :
|
|||
_type(copy._type),
|
||||
_ident(copy._ident),
|
||||
_initializer(copy._initializer),
|
||||
_storage_class(copy._storage_class)
|
||||
_storage_class(copy._storage_class),
|
||||
_alignment(copy._alignment)
|
||||
{
|
||||
assert(_type != NULL);
|
||||
}
|
||||
|
|
@ -153,6 +157,9 @@ operator == (const CPPInstance &other) const {
|
|||
if (_storage_class != other._storage_class) {
|
||||
return false;
|
||||
}
|
||||
if (_alignment != other._alignment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We *do* care about the identifier. We need to differentiate
|
||||
// types of function variables, among possibly other things, based
|
||||
|
|
@ -199,6 +206,9 @@ operator < (const CPPInstance &other) const {
|
|||
if (_storage_class != other._storage_class) {
|
||||
return _storage_class < other._storage_class;
|
||||
}
|
||||
if (_alignment != other._alignment) {
|
||||
return _alignment < other._alignment;
|
||||
}
|
||||
|
||||
// We *do* care about the identifier. We need to differentiate
|
||||
// types of function variables, among possibly other things, based
|
||||
|
|
@ -252,6 +262,29 @@ set_initializer(CPPExpression *initializer) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPInstance::set_alignment
|
||||
// Access: Public
|
||||
// Description: Sets the number of bytes to align this instance to.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPInstance::
|
||||
set_alignment(int align) {
|
||||
_alignment = new CPPExpression(align);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPInstance::set_alignment
|
||||
// Access: Public
|
||||
// Description: Sets the expression that is used to determine the
|
||||
// required alignment for the variable. This should
|
||||
// be a constant expression, but we don't presently
|
||||
// verify that it is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPInstance::
|
||||
set_alignment(CPPExpression *const_expr) {
|
||||
_alignment = const_expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPInstance::is_scoped
|
||||
// Access: Public
|
||||
|
|
@ -536,6 +569,11 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
|
|||
get_template_scope()->_parameters.write_formal(out, scope);
|
||||
indent(out, indent_level);
|
||||
}
|
||||
|
||||
if (_alignment != NULL) {
|
||||
out << "alignas(" << *_alignment << ") ";
|
||||
}
|
||||
|
||||
if (_storage_class & SC_static) {
|
||||
out << "static ";
|
||||
}
|
||||
|
|
@ -563,6 +601,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
|
|||
if (_storage_class & SC_mutable) {
|
||||
out << "mutable ";
|
||||
}
|
||||
if (_storage_class & SC_constexpr) {
|
||||
out << "constexpr ";
|
||||
}
|
||||
|
||||
string name;
|
||||
if (_ident != NULL) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "cppDeclaration.h"
|
||||
#include "cppType.h"
|
||||
#include "cppIdentifier.h"
|
||||
#include "cppTemplateParameterList.h"
|
||||
|
||||
class CPPInstanceIdentifier;
|
||||
|
|
@ -47,19 +46,20 @@ public:
|
|||
SC_pure_virtual = 0x0080,
|
||||
SC_volatile = 0x0100,
|
||||
SC_mutable = 0x0200,
|
||||
SC_constexpr = 0x0400,
|
||||
|
||||
// This bit is only set by CPPStructType::check_virtual().
|
||||
SC_inherited_virtual = 0x0400,
|
||||
SC_inherited_virtual = 0x0800,
|
||||
|
||||
// This is a special "storage class" for methods tagged with the
|
||||
// BLOCKING macro (i.e. the special __blocking keyword). These
|
||||
// are methods that might block and therefore need to release
|
||||
// Python threads for their duration.
|
||||
SC_blocking = 0x0800,
|
||||
SC_blocking = 0x1000,
|
||||
|
||||
// And this is for methods tagged with __extension, which declares
|
||||
// extension methods defined separately from the source code.
|
||||
SC_extension = 0x1000,
|
||||
SC_extension = 0x2000,
|
||||
};
|
||||
|
||||
CPPInstance(CPPType *type, const string &name, int storage_class = 0);
|
||||
|
|
@ -78,6 +78,8 @@ public:
|
|||
bool operator < (const CPPInstance &other) const;
|
||||
|
||||
void set_initializer(CPPExpression *initializer);
|
||||
void set_alignment(int align);
|
||||
void set_alignment(CPPExpression *const_expr);
|
||||
|
||||
bool is_scoped() const;
|
||||
CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
|
||||
|
|
@ -112,6 +114,7 @@ public:
|
|||
CPPExpression *_initializer;
|
||||
|
||||
int _storage_class;
|
||||
CPPExpression *_alignment;
|
||||
|
||||
private:
|
||||
typedef map<const CPPTemplateParameterList *, CPPInstance *, CPPTPLCompare> Instantiations;
|
||||
|
|
|
|||
|
|
@ -286,6 +286,11 @@ r_unroll_type(CPPType *start_type,
|
|||
result = new CPPConstType(r_unroll_type(start_type, mi));
|
||||
break;
|
||||
|
||||
case IIT_volatile:
|
||||
// Just pass it through for now.
|
||||
result = r_unroll_type(start_type, mi);
|
||||
break;
|
||||
|
||||
case IIT_paren:
|
||||
result = r_unroll_type(start_type, mi);
|
||||
break;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue