Merge branch 'release/1.9.x'

Conflicts:
	direct/src/p3d/Packager.py
	direct/src/p3d/ppackage.py
	makepanda/makepandacore.py
This commit is contained in:
rdb 2015-11-21 03:17:33 +01:00
commit 0a9f9887f9
17 changed files with 229 additions and 127 deletions

View File

@ -1532,8 +1532,10 @@ class Actor(DirectObject, NodePath):
# actions
def animPanel(self):
from direct.showbase import TkGlobal
from direct.tkpanels import AnimPanel
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
AnimPanel = importlib.import_module('direct.tkpanels.AnimPanel')
return AnimPanel.AnimPanel(self)
def stop(self, animName=None, partName=None):

View File

@ -111,10 +111,13 @@ class DirectNotify:
category.setWarning(1)
category.setInfo(1)
category.setDebug(1)
def popupControls(self, tl = None):
from direct.tkpanels import NotifyPanel
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
NotifyPanel = importlib.import_module('direct.tkpanels.NotifyPanel')
NotifyPanel.NotifyPanel(self, tl)
def giveNotify(self,cls):
cls.notify = self.newCategory(cls.__name__)

View File

@ -60,13 +60,17 @@ 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
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
Tkinter = importlib.import_module('Tkinter')
if tl == None:
tl = Toplevel()
tl = Tkinter.Toplevel()
tl.title('Interval Controls')
outerFrame = Frame(tl)
outerFrame = Tkinter.Frame(tl)
def entryScaleCommand(t, s=self):
s.setT(t)
s.pause()
@ -75,8 +79,8 @@ def popupControls(self, tl = None):
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)
es.pack(expand = 1, fill = Tkinter.X)
bf = Tkinter.Frame(outerFrame)
# Jump to start and end
def toStart(s=self, es=es):
s.setT(0.0)
@ -84,23 +88,23 @@ def popupControls(self, tl = None):
def toEnd(s=self):
s.setT(s.getDuration())
s.pause()
jumpToStart = Button(bf, text = '<<', command = toStart)
jumpToStart = Tkinter.Button(bf, text = '<<', command = toStart)
# Stop/play buttons
def doPlay(s=self, es=es):
s.resume(es.get())
stop = Button(bf, text = 'Stop',
stop = Tkinter.Button(bf, text = 'Stop',
command = lambda s=self: s.pause())
play = Button(
play = Tkinter.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)
jumpToEnd = Tkinter.Button(bf, text = '>>', command = toEnd)
jumpToStart.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
play.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
stop.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
jumpToEnd.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
bf.pack(expand = 1, fill = Tkinter.X)
outerFrame.pack(expand = 1, fill = Tkinter.X)
# Add function to update slider during setT calls
def update(t, es=es):
es.set(t, fCommand = 0)

View File

@ -407,7 +407,10 @@ del iPosHprScale
#####################################################################
def place(self):
base.startDirect(fWantTk = 1)
from direct.tkpanels import Placer
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
Placer = importlib.import_module('direct.tkpanels.Placer')
return Placer.place(self)
Dtool_funcToMethod(place, NodePath)
@ -415,7 +418,10 @@ del place
#####################################################################
def explore(self):
base.startDirect(fWantTk = 1)
from direct.tkwidgets import SceneGraphExplorer
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
SceneGraphExplorer = importlib.import_module('direct.tkwidgets.SceneGraphExplorer')
return SceneGraphExplorer.explore(self)
Dtool_funcToMethod(explore, NodePath)
@ -423,7 +429,10 @@ del explore
#####################################################################
def rgbPanel(self, cb = None):
base.startTk()
from direct.tkwidgets import Slider
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
Slider = importlib.import_module('direct.tkwidgets.Slider')
return Slider.rgbPanel(self, cb)
Dtool_funcToMethod(rgbPanel, NodePath)

View File

@ -369,7 +369,10 @@ class ClassicFSM(DirectObject):
return 0
def view(self):
from direct.tkpanels import FSMInspector
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
FSMInspector = importlib.import_module('direct.tkpanels.FSMInspector')
FSMInspector.FSMInspector(self)
def isInternalStateInFlux(self):

View File

@ -444,16 +444,16 @@ class Interval(DirectObject):
"""
Popup control panel for interval.
"""
from direct.showbase import TkGlobal
import math
# I moved this here because Toontown does not ship Tk
from Tkinter import Toplevel, Frame, Button, LEFT, X
import Pmw
from direct.tkwidgets import EntryScale
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
Tkinter = importlib.import_module('Tkinter')
if tl == None:
tl = Toplevel()
tl = Tkinter.Toplevel()
tl.title('Interval Controls')
outerFrame = Frame(tl)
outerFrame = Tkinter.Frame(tl)
def entryScaleCommand(t, s=self):
s.setT(t)
s.pause()
@ -462,8 +462,8 @@ class Interval(DirectObject):
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)
es.pack(expand = 1, fill = Tkinter.X)
bf = Tkinter.Frame(outerFrame)
# Jump to start and end
def toStart(s=self, es=es):
s.clearToInitial()
@ -473,23 +473,23 @@ class Interval(DirectObject):
s.setT(s.getDuration())
es.set(s.getDuration(), fCommand = 0)
s.pause()
jumpToStart = Button(bf, text = '<<', command = toStart)
jumpToStart = Tkinter.Button(bf, text = '<<', command = toStart)
# Stop/play buttons
def doPlay(s=self, es=es):
s.resume(es.get())
stop = Button(bf, text = 'Stop',
stop = Tkinter.Button(bf, text = 'Stop',
command = lambda s=self: s.pause())
play = Button(
play = Tkinter.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)
jumpToEnd = Tkinter.Button(bf, text = '>>', command = toEnd)
jumpToStart.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
play.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
stop.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
jumpToEnd.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
bf.pack(expand = 1, fill = Tkinter.X)
outerFrame.pack(expand = 1, fill = Tkinter.X)
# Add function to update slider during setT calls
def update(t, es=es):
es.set(t, fCommand = 0)

View File

@ -424,47 +424,8 @@ class AppRunner(DirectObject):
it downloads a new version on-the-spot. Returns true on
success, false on failure. """
if fileSpec.quickVerify(pathname = localPathname):
# It's good, keep it.
return True
assert self.http
# It's stale, get a new one.
doc = None
if self.superMirrorUrl:
# Use the "super mirror" first.
url = core.URLSpec(self.superMirrorUrl + fileSpec.filename)
self.notify.info("Freshening %s" % (url))
doc = self.http.getDocument(url)
if not doc or not doc.isValid():
# Failing the super mirror, contact the actual host.
url = core.URLSpec(host.hostUrlPrefix + fileSpec.filename)
self.notify.info("Freshening %s" % (url))
doc = self.http.getDocument(url)
if not doc.isValid():
return False
file = Filename.temporary('', 'p3d_')
if not doc.downloadToFile(file):
# Failed to download.
file.unlink()
return False
# Successfully downloaded!
localPathname.makeDir()
if not file.renameTo(localPathname):
# Couldn't move it into place.
file.unlink()
return False
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
return True
return host.freshenFile(self.http, fileSpec, localPathname)
def scanInstalledPackages(self):
""" Scans the hosts and packages already installed locally on

View File

@ -40,8 +40,6 @@ class HostInfo:
Note that perPlatform is also restricted by the individual
package's specification. """
assert appRunner or rootDir or hostDir
self.__setHostUrl(hostUrl)
self.appRunner = appRunner
self.rootDir = rootDir
@ -112,6 +110,52 @@ class HostInfo:
# https-protected hostUrl, it will be the cleartext channel.
self.downloadUrlPrefix = self.hostUrlPrefix
def freshenFile(self, http, fileSpec, localPathname):
""" Ensures that the localPathname is the most current version
of the file defined by fileSpec, as offered by host. If not,
it downloads a new version on-the-spot. Returns true on
success, false on failure. """
if fileSpec.quickVerify(pathname = localPathname):
# It's good, keep it.
return True
# It's stale, get a new one.
doc = None
if self.appRunner and self.appRunner.superMirrorUrl:
# Use the "super mirror" first.
url = core.URLSpec(self.appRunner.superMirrorUrl + fileSpec.filename)
self.notify.info("Freshening %s" % (url))
doc = http.getDocument(url)
if not doc or not doc.isValid():
# Failing the super mirror, contact the actual host.
url = core.URLSpec(self.hostUrlPrefix + fileSpec.filename)
self.notify.info("Freshening %s" % (url))
doc = http.getDocument(url)
if not doc.isValid():
return False
file = Filename.temporary('', 'p3d_')
if not doc.downloadToFile(file):
# Failed to download.
file.unlink()
return False
# Successfully downloaded!
localPathname.makeDir()
if not file.renameTo(localPathname):
# Couldn't move it into place.
file.unlink()
return False
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
return True
def downloadContentsFile(self, http, redownload = False,
hashVal = None):
""" Downloads the contents.xml file for this particular host,

View File

@ -13,12 +13,12 @@ import os
import glob
import string
import types
import getpass
import struct
import subprocess
import copy
from direct.p3d.FileSpec import FileSpec
from direct.p3d.SeqValue import SeqValue
from direct.p3d.HostInfo import HostInfo
from direct.showbase import Loader
from direct.showbase import AppRunnerGlobal
from direct.showutil import FreezeTool
@ -378,7 +378,8 @@ class Packager:
# This records the current list of modules we have added so
# far.
self.freezer = FreezeTool.Freezer(platform = self.packager.platform)
self.freezer.storePythonSource = self.packager.storePythonSource
# Map of extensions to files to number (ignored by dir)
self.ignoredDirFiles = {}
@ -1075,7 +1076,7 @@ class Packager:
fpath.append(Filename("/Library/Frameworks"))
fpath.append(Filename("/System/Library/Frameworks"))
fpath.append(Filename("/Developer/Library/Frameworks"))
fpath.append(Filename("/Users/%s" % getpass.getuser(), "Library/Frameworks"))
fpath.append(Filename(os.path.expanduser("~"), "Library/Frameworks"))
if "HOME" in os.environ:
fpath.append(Filename(os.environ["HOME"], "Library/Frameworks"))
ffilename = Filename(library.split('.framework/', 1)[0].split('/')[-1] + '.framework')
@ -2233,6 +2234,11 @@ class Packager:
self.host = PandaSystem.getPackageHostUrl()
self.addHost(self.host)
# This will be used when we're not compiling in the packaged
# environment.
self.__hostInfos = {}
self.http = HTTPClient.getGlobalPtr()
# The maximum amount of time a client should cache the
# contents.xml before re-querying the server, in seconds.
self.maxAge = 0
@ -2318,6 +2324,10 @@ class Packager:
# any applications.
self.allowPythonDev = False
# Set this flag to store the original Python source files,
# without compiling them to .pyc or .pyo.
self.storePythonSource = False
# Fill this with a list of (certificate, chain, pkey,
# password) tuples to automatically sign each p3d file
# generated.
@ -3028,17 +3038,10 @@ class Packager:
def __findPackageOnHost(self, packageName, platform, version, hostUrl, requires = None):
appRunner = AppRunnerGlobal.appRunner
if not appRunner:
# We don't download import files from a host unless we're
# running in a packaged environment ourselves. It would
# be possible to do this, but a fair bit of work for not
# much gain--this is meant to be run in a packaged
# environment.
return None
# Make sure we have a fresh version of the contents file.
host = appRunner.getHost(hostUrl)
if not host.downloadContentsFile(appRunner.http):
host = self.__getHostInfo(hostUrl)
if not host.downloadContentsFile(self.http):
return None
packageInfos = []
@ -3063,23 +3066,48 @@ class Packager:
# Now we've retrieved a PackageInfo. Get the import desc file
# from it.
filename = Filename(host.hostDir, 'imports/' + packageInfo.importDescFile.basename)
if not appRunner.freshenFile(host, packageInfo.importDescFile, filename):
if host.hostDir:
filename = Filename(host.hostDir, 'imports/' + packageInfo.importDescFile.basename)
else:
# We're not running in the packaged environment, so download
# to a temporary file instead of the host directory.
filename = Filename.temporary('', 'import_' + packageInfo.importDescFile.basename, '.xml')
if not host.freshenFile(self.http, packageInfo.importDescFile, filename):
self.notify.error("Couldn't download import file.")
continue
# Now that we have the import desc file, use it to load one of
# our Package objects.
package = self.Package('', self)
if not package.readImportDescFile(filename):
continue
success = package.readImportDescFile(filename)
if self.__packageIsValid(package, requires, platform):
if not host.hostDir:
# Don't forget to delete the temporary file we created.
filename.unlink()
if success and self.__packageIsValid(package, requires, platform):
return package
# Couldn't find a suitable package.
return None
def __getHostInfo(self, hostUrl = None):
""" This shadows appRunner.getHost(), for the purpose of running
outside the packaged environment. """
if not hostUrl:
hostUrl = PandaSystem.getPackageHostUrl()
if AppRunnerGlobal.appRunner:
return AppRunnerGlobal.appRunner.getHost(hostUrl)
host = self.__hostInfos.get(hostUrl, None)
if not host:
host = HostInfo(hostUrl)
self.__hostInfos[hostUrl] = host
return host
def __sortImportPackages(self, packages):
""" Given a list of Packages read from *.import.xml filenames,
sorts them in reverse order by version, so that the

View File

@ -83,6 +83,10 @@ Options:
initially, but should not be set on an application intended for
deployment.
-N
If this option is set, Packager will not try to compile any Python
files to .pyc or .pyo, instead storing the original source files.
-u
On the Mac OSX platform, this means that Panda was built with
universal binaries, and the package should be built that way as
@ -152,6 +156,7 @@ buildPatches = False
installSearch = []
signParams = []
allowPythonDev = False
storePythonSource = False
universalBinaries = False
systemRoot = None
ignoreSetHost = False
@ -160,7 +165,7 @@ p3dSuffix = ''
platforms = []
try:
opts, args = getopt.getopt(sys.argv[1:], 'i:ps:S:DuP:R:Ha:hv')
opts, args = getopt.getopt(sys.argv[1:], 'i:ps:S:DNuP:R:Ha:hv')
except getopt.error as msg:
usage(1, msg)
@ -182,6 +187,8 @@ for opt, arg in opts:
Filename.fromOsSpecific(password)))
elif opt == '-D':
allowPythonDev = True
elif opt == '-N':
storePythonSource = True
elif opt == '-u':
universalBinaries = True
elif opt == '-P':
@ -236,6 +243,7 @@ for platform in platforms:
packager.installSearch = [installDir] + packager.installSearch
packager.signParams = signParams
packager.allowPythonDev = allowPythonDev
packager.storePythonSource = storePythonSource
packager.systemRoot = systemRoot
packager.ignoreSetHost = ignoreSetHost
packager.verbosePrint = verbosePrint

View File

@ -325,7 +325,10 @@ def adjust(command = None, dim = 1, parent = None, **kw):
10.0
"""
# Make sure we enable Tk
from direct.tkwidgets import Valuator
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
Valuator = importlib.import_module('direct.tkwidgets.Valuator')
# Set command if specified
if command:
kw['command'] = lambda x: apply(command, x)

View File

@ -14,7 +14,10 @@ assert base
directNotify.setDconfigLevels()
def inspect(anObject):
from direct.tkpanels import Inspector
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
Inspector = importlib.import_module('direct.tkpanels.Inspector')
return Inspector.inspect(anObject)
import __builtin__

View File

@ -1143,6 +1143,7 @@ class Freezer:
elif getattr(module, '__file__', None):
sourceFilename = Filename.fromOsSpecific(module.__file__)
sourceFilename.setExtension("py")
sourceFilename.setText()
if self.storePythonSource:
if sourceFilename and sourceFilename.exists():

View File

@ -582,7 +582,10 @@ class TaskManager:
return numFound
def popupControls(self):
from direct.tkpanels import TaskManagerPanel
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
TaskManagerPanel = importlib.import_module('direct.tkpanels.TaskManagerPanel')
return TaskManagerPanel.TaskManagerPanel(self)
def getProfileSession(self, name=None):

View File

@ -4179,6 +4179,11 @@ bool RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) {
assert(in1 != NULL);
assert(in2 != NULL);
if (in1->_const_method != in2->_const_method) {
// Non-const methods should come first.
return in2->_const_method;
}
if (in1->_parameters.size() != in2->_parameters.size()) {
return (in1->_parameters.size() > in2->_parameters.size());
}

View File

@ -1856,6 +1856,11 @@ def Package(target, inputs, opts):
command += "direct/src/p3d/ppackage.py"
if not RTDIST:
# Don't compile Python sources, because we might not running in the same
# Python version as the selected host.
command += " -N"
if GetTarget() == "darwin":
if SDK.get("MACOSX"):
command += " -R \"%s\"" % SDK["MACOSX"]
@ -1868,8 +1873,31 @@ def Package(target, inputs, opts):
command += " -i \"" + GetOutputDir() + "/stage\""
if (P3DSUFFIX):
command += ' -a "' + P3DSUFFIX + '"'
command += " " + inputs[0]
oscmd(command)
if GetOrigExt(target) == '.p3d':
# Build a specific .p3d file.
basename = os.path.basename(os.path.splitext(target)[0])
command += " " + basename
oscmd(command)
if GetTarget() == 'windows':
# Make an .exe that calls this .p3d.
objfile = FindLocation('p3dWrapper_' + basename + '.obj', [])
CompileCxx(objfile, 'direct/src/p3d/p3dWrapper.c', [])
exefile = FindLocation(basename + '.exe', [])
CompileLink(exefile, [objfile], ['ADVAPI'])
# Move it to the bin directory.
os.rename(GetOutputDir() + '/stage/' + basename + P3DSUFFIX + '.p3d', target)
if sys.platform != 'win32':
oscmd('chmod +x ' + BracketNameWithQuotes(target))
else:
# This is presumably a package or set of packages.
oscmd(command)
##########################################################################################
#
@ -1970,7 +1998,10 @@ def CompileAnything(target, inputs, opts, progress = None):
ProgressOutput(progress, "Compiling MIDL file", infile)
return CompileMIDL(target, infile, opts)
elif (infile.endswith(".pdef")):
ProgressOutput(progress, "Building package from pdef file", infile)
if origsuffix == '.p3d':
ProgressOutput(progress, "Building package", target)
else:
ProgressOutput(progress, "Building package from pdef file", infile)
return Package(target, inputs, opts)
elif origsuffix in SUFFIX_LIB:
ProgressOutput(progress, "Linking static library", target)
@ -6234,26 +6265,17 @@ if (RTDIST):
TargetAdd('_thirdparty', opts=OPTS, input='thirdparty.pdef')
#
# Distribute prebuilt .p3d files as executable.
# If we have a host URL and distributor, we can make .p3d deployment tools.
#
if (PkgSkip("DIRECT")==0 and not RUNTIME and not RTDIST):
if GetTarget() == 'windows':
if not PkgSkip("DIRECT") and not PkgSkip("DEPLOYTOOLS") and not RUNTIME and not RTDIST and HOST_URL and DISTRIBUTOR:
OPTS=['DIR:direct/src/p3d']
TargetAdd('p3dWrapper.obj', opts=OPTS, input='p3dWrapper.c')
TargetAdd('p3dWrapper.exe', input='p3dWrapper.obj')
TargetAdd('p3dWrapper.exe', opts=["ADVAPI"])
for g in glob.glob("direct/src/p3d/*.p3d"):
base = os.path.basename(g)
base = base.split(".", 1)[0]
if GetTarget() == 'windows':
TargetAdd(base+".exe", input='p3dWrapper.exe')
CopyFile(GetOutputDir()+"/bin/"+base+".p3d", g)
else:
CopyFile(GetOutputDir()+"/bin/"+base, g)
oscmd("chmod +x "+GetOutputDir()+"/bin/"+base)
TargetAdd('packp3d.p3d', opts=OPTS, input='panda3d.pdef')
TargetAdd('pdeploy.p3d', opts=OPTS, input='panda3d.pdef')
TargetAdd('pmerge.p3d', opts=OPTS, input='panda3d.pdef')
TargetAdd('ppackage.p3d', opts=OPTS, input='panda3d.pdef')
TargetAdd('ppatcher.p3d', opts=OPTS, input='panda3d.pdef')
##########################################################################################
#

View File

@ -1881,7 +1881,7 @@ def SdkLocatePython(prefer_thirdparty_python=False):
sdkdir += "-x64"
SDK["PYTHON"] = sdkdir
SDK["PYTHONEXEC"] = SDK["PYTHON"].replace('/', '\\') + "\\python"
SDK["PYTHONEXEC"] = SDK["PYTHON"].replace('\\', '/') + "/python"
if (GetOptimize() <= 2):
SDK["PYTHONEXEC"] += "_d.exe"
else:
@ -2824,6 +2824,7 @@ def CalcLocation(fn, ipath):
if (fn.endswith(".dle")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".dle"
if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".dll"
if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn
if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn
if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+dllext+".lib"
if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+dllext+".lib"
elif (target == 'darwin'):
@ -2835,6 +2836,7 @@ def CalcLocation(fn, ipath):
if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".so"
if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn
if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4]
if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn[:-4]
if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+".a"
if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a"
if (fn.endswith(".rsrc")): return OUTPUTDIR+"/tmp/"+fn
@ -2857,6 +2859,7 @@ def CalcLocation(fn, ipath):
if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn
if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".so"
if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4]
if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn[:-4]
if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+".a"
if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a"
if (fn.endswith(".dat")): return OUTPUTDIR+"/tmp/"+fn