Merge branch 'master' into cmake

This commit is contained in:
Sam Edwards 2019-09-06 04:05:12 -06:00
commit dbe7a2f94b
32 changed files with 718 additions and 1205 deletions

View File

@ -66,6 +66,8 @@ def _parse_dict(input):
def egg2bam(_build_cmd, srcpath, dstpath):
if dstpath.endswith('.gz') or dstpath.endswith('.pz'):
dstpath = dstpath[:-3]
dstpath = dstpath + '.bam'
try:
subprocess.check_call([
@ -895,6 +897,9 @@ class build_apps(setuptools.Command):
os.makedirs(dst_dir)
ext = os.path.splitext(src)[1]
# If the file ends with .gz/.pz, we strip this off.
if ext in ('.gz', '.pz'):
ext = os.path.splitext(src[:-3])[1]
if not ext:
ext = os.path.basename(src)

View File

@ -344,6 +344,7 @@ class Icon:
if required_size * 2 in sizes:
from_size = required_size * 2
else:
from_size = 0
for from_size in sizes:
if from_size > required_size:
break
@ -367,7 +368,7 @@ class Icon:
# XOR mask
if bpp == 24:
# Align rows to 4-byte boundary
rowalign = '\0' * (-(size * 3) & 3)
rowalign = b'\0' * (-(size * 3) & 3)
for y in xrange(size):
for x in xrange(size):
r, g, b = image.getXel(x, size - y - 1)
@ -383,35 +384,14 @@ class Icon:
elif bpp == 8:
# We'll have to generate a palette of 256 colors.
hist = PNMImage.Histogram()
if image.hasAlpha():
# Make a copy without alpha channel.
image2 = PNMImage(image)
image2 = PNMImage(image)
if image2.hasAlpha():
image2.premultiplyAlpha()
image2.removeAlpha()
else:
image2 = image
image2.quantize(256)
image2.make_histogram(hist)
colors = list(hist.get_pixels())
if len(colors) > 256:
# Palette too large; remove infrequent colors.
colors.sort(key=hist.get_count, reverse=True)
# Find the closest color on the palette matching each color
# that didn't fit. This is certainly not the best palette
# generation code, but it'll do for now.
closest_indices = []
for color in colors[256:]:
closest_index = 0
closest_diff = 1025
for i, closest_color in enumerate(colors[:256]):
diff = abs(color.get_red() - closest_color.get_red()) \
+ abs(color.get_green() - closest_color.get_green()) \
+ abs(color.get_blue() - closest_color.get_blue())
if diff < closest_diff:
closest_index = i
closest_diff = diff
assert closest_diff < 100
closest_indices.append(closest_index)
assert len(colors) <= 256
# Write the palette.
i = 0
@ -503,7 +483,7 @@ class Icon:
if size > 256:
continue
elif size == 256:
ico.write('\0\0')
ico.write(b'\0\0')
else:
ico.write(struct.pack('<BB', size, size))

View File

@ -83,6 +83,7 @@ def open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None,
elif isinstance(file, strType):
filename = core.Filename.fromOsSpecific(file)
else:
# It's either a Filename object or an os.PathLike.
# If a Filename is given, make a writable copy anyway.
filename = core.Filename(file)

View File

@ -50,19 +50,7 @@ load_dso(const DSearchPath &path, const Filename &filename) {
return nullptr;
}
std::wstring os_specific_w = abspath.to_os_specific_w();
// Try using LoadLibraryEx, if possible.
typedef HMODULE (WINAPI *tLoadLibraryEx)(LPCWSTR, HANDLE, DWORD);
tLoadLibraryEx pLoadLibraryEx;
HINSTANCE hLib = LoadLibrary("kernel32.dll");
if (hLib) {
pLoadLibraryEx = (tLoadLibraryEx)GetProcAddress(hLib, "LoadLibraryExW");
if (pLoadLibraryEx) {
return pLoadLibraryEx(os_specific_w.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
}
}
return LoadLibraryW(os_specific_w.c_str());
return LoadLibraryExW(os_specific_w.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
}
bool

View File

@ -2038,33 +2038,11 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
iproperty._length_function = length_function;
}
if (make_property->_type == CPPMakeProperty::T_normal) {
if (getter != nullptr) {
iproperty._flags |= InterrogateElement::F_has_getter;
iproperty._getter = get_function(getter, "", struct_type,
struct_type->get_scope(), 0);
nassertr(iproperty._getter, 0);
}
} else {
// We could have a mixed sequence/mapping property, so synthesize a
// getitem function. We don't really care what's in here; we just use
// this to store the remaps.
if (!iproperty.has_getter()) {
iproperty._flags |= InterrogateElement::F_has_getter;
iproperty._getter = InterrogateDatabase::get_ptr()->get_next_index();
InterrogateFunction *ifunction = new InterrogateFunction;
ifunction->_instances = new InterrogateFunction::Instances;
InterrogateDatabase::get_ptr()->add_function(iproperty._getter, ifunction);
}
// Add our getter to the generated getitem function.
string signature = TypeManager::get_function_signature(getter);
InterrogateFunction &ifunction =
InterrogateDatabase::get_ptr()->update_function(iproperty._getter);
if (ifunction._instances == nullptr) {
ifunction._instances = new InterrogateFunction::Instances;
}
ifunction._instances->insert(InterrogateFunction::Instances::value_type(signature, getter));
if (getter != nullptr) {
iproperty._flags |= InterrogateElement::F_has_getter;
iproperty._getter = get_function(getter, "", struct_type,
struct_type->get_scope(), 0);
nassertr(iproperty._getter, 0);
}
if (hasser != nullptr) {

View File

@ -4603,33 +4603,7 @@ if PkgSkip("OPENAL") == 0 and not RUNTIME:
#
if (PkgSkip("OPENSSL")==0 and not RTDIST and not RUNTIME and PkgSkip("DEPLOYTOOLS")==0):
OPTS=['DIR:panda/src/downloadertools', 'OPENSSL', 'ZLIB', 'ADVAPI', 'WINSOCK2', 'WINSHELL', 'WINGDI', 'WINUSER']
TargetAdd('apply_patch_apply_patch.obj', opts=OPTS, input='apply_patch.cxx')
TargetAdd('apply_patch.exe', input=['apply_patch_apply_patch.obj'])
TargetAdd('apply_patch.exe', input=COMMON_PANDA_LIBS)
TargetAdd('apply_patch.exe', opts=OPTS)
TargetAdd('build_patch_build_patch.obj', opts=OPTS, input='build_patch.cxx')
TargetAdd('build_patch.exe', input=['build_patch_build_patch.obj'])
TargetAdd('build_patch.exe', input=COMMON_PANDA_LIBS)
TargetAdd('build_patch.exe', opts=OPTS)
if not PkgSkip("ZLIB"):
TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx')
TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj'])
TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS)
TargetAdd('check_adler.exe', opts=OPTS)
TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx')
TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj'])
TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS)
TargetAdd('check_crc.exe', opts=OPTS)
TargetAdd('check_md5_check_md5.obj', opts=OPTS, input='check_md5.cxx')
TargetAdd('check_md5.exe', input=['check_md5_check_md5.obj'])
TargetAdd('check_md5.exe', input=COMMON_PANDA_LIBS)
TargetAdd('check_md5.exe', opts=OPTS)
OPTS=['DIR:panda/src/downloadertools', 'OPENSSL', 'ADVAPI', 'WINSOCK2', 'WINSHELL', 'WINGDI', 'WINUSER']
TargetAdd('pdecrypt_pdecrypt.obj', opts=OPTS, input='pdecrypt.cxx')
TargetAdd('pdecrypt.exe', input=['pdecrypt_pdecrypt.obj'])
@ -4641,11 +4615,6 @@ if (PkgSkip("OPENSSL")==0 and not RTDIST and not RUNTIME and PkgSkip("DEPLOYTOOL
TargetAdd('pencrypt.exe', input=COMMON_PANDA_LIBS)
TargetAdd('pencrypt.exe', opts=OPTS)
TargetAdd('show_ddb_show_ddb.obj', opts=OPTS, input='show_ddb.cxx')
TargetAdd('show_ddb.exe', input=['show_ddb_show_ddb.obj'])
TargetAdd('show_ddb.exe', input=COMMON_PANDA_LIBS)
TargetAdd('show_ddb.exe', opts=OPTS)
#
# DIRECTORY: panda/src/downloadertools/
#

View File

@ -2079,16 +2079,10 @@
<File RelativePath="..\panda\src\pnmimagetypes\colrops.c"></File>
</Filter>
<Filter Name="downloadertools">
<File RelativePath="..\panda\src\downloadertools\show_ddb.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\pencrypt.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\check_adler.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\pdecrypt.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\pzip.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\multify.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\check_md5.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\check_crc.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\apply_patch.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\build_patch.cxx"></File>
<File RelativePath="..\panda\src\downloadertools\punzip.cxx"></File>
</Filter>
<Filter Name="gles2gsg">

View File

@ -1,333 +0,0 @@
# This script imports Panda3D modules just to make sure that there are no
# missing imports. It is useful for a quick and dirty test to make sure
# that there are no obvious build issues.
import os, importlib
# This will print out imports on the command line.
import direct.showbase.VerboseImport
import imp
import panda3d
dir = os.path.dirname(panda3d.__file__)
extensions = set()
for suffix in imp.get_suffixes():
extensions.add(suffix[0])
for basename in os.listdir(dir):
module = basename.split('.', 1)[0]
ext = basename[len(module):]
if ext in extensions:
importlib.import_module('panda3d.%s' % (module))
import direct.actor.Actor
import direct.actor.DistributedActor
import direct.cluster.ClusterClient
import direct.cluster.ClusterConfig
import direct.cluster.ClusterMsgs
import direct.cluster.ClusterServer
import direct.controls.BattleWalker
import direct.controls.ControlManager
import direct.controls.DevWalker
import direct.controls.GhostWalker
import direct.controls.GravityWalker
import direct.controls.InputState
import direct.controls.NonPhysicsWalker
import direct.controls.ObserverWalker
import direct.controls.PhysicsRoller
import direct.controls.PhysicsWalker
import direct.controls.SwimWalker
import direct.controls.TwoDWalker
import direct.directnotify.DirectNotify
import direct.directnotify.DirectNotifyGlobal
import direct.directnotify.Logger
import direct.directnotify.LoggerGlobal
import direct.directnotify.Notifier
import direct.directnotify.RotatingLog
import direct.directtools.DirectCameraControl
import direct.directtools.DirectGeometry
import direct.directtools.DirectGlobals
import direct.directtools.DirectGrid
import direct.directtools.DirectLights
import direct.directtools.DirectManipulation
import direct.directtools.DirectSelection
import direct.directtools.DirectUtil
import direct.directutil.DeltaProfiler
import direct.directutil.DistributedLargeBlobSender
import direct.directutil.DistributedLargeBlobSenderAI
import direct.directutil.LargeBlobSenderConsts
import direct.directutil.Mopath
import direct.directutil.Verify
import direct.directutil.WeightedChoice
import direct.dist.FreezeTool
import direct.distributed.AsyncRequest
import direct.distributed.CRCache
import direct.distributed.CRDataCache
import direct.distributed.CachedDOData
import direct.distributed.CartesianGridBase
import direct.distributed.ClientRepository
import direct.distributed.ClientRepositoryBase
import direct.distributed.ClockDelta
import direct.distributed.ConnectionRepository
import direct.distributed.DistributedCamera
import direct.distributed.DistributedCameraAI
import direct.distributed.DistributedCameraOV
import direct.distributed.DistributedCartesianGrid
import direct.distributed.DistributedCartesianGridAI
import direct.distributed.DistributedNode
import direct.distributed.DistributedNodeAI
import direct.distributed.DistributedNodeUD
import direct.distributed.DistributedObject
import direct.distributed.DistributedObjectAI
import direct.distributed.DistributedObjectBase
import direct.distributed.DistributedObjectGlobal
import direct.distributed.DistributedObjectGlobalAI
import direct.distributed.DistributedObjectGlobalUD
import direct.distributed.DistributedObjectOV
import direct.distributed.DistributedObjectUD
import direct.distributed.DistributedSmoothNodeAI
import direct.distributed.DistributedSmoothNodeBase
import direct.distributed.DoCollectionManager
import direct.distributed.DoHierarchy
import direct.distributed.DoInterestManager
import direct.distributed.GridChild
import direct.distributed.GridParent
import direct.distributed.InterestWatcher
import direct.distributed.MsgTypes
import direct.distributed.MsgTypesCMU
import direct.distributed.NetMessenger
import direct.distributed.ParentMgr
import direct.distributed.PyDatagram
import direct.distributed.PyDatagramIterator
import direct.distributed.RelatedObjectMgr
import direct.distributed.SampleObject
import direct.distributed.ServerRepository
import direct.distributed.StagedObject
import direct.distributed.TimeManager
import direct.distributed.TimeManagerAI
import direct.extensions_native.extension_native_helpers
import direct.filter.CommonFilters
import direct.filter.FilterManager
import direct.fsm.ClassicFSM
import direct.fsm.FSM
import direct.fsm.FourState
import direct.fsm.FourStateAI
import direct.fsm.SampleFSM
import direct.fsm.State
import direct.fsm.StateData
import direct.fsm.StatePush
import direct.gui.DirectButton
import direct.gui.DirectCheckBox
import direct.gui.DirectCheckButton
import direct.gui.DirectDialog
import direct.gui.DirectEntry
import direct.gui.DirectEntryScroll
import direct.gui.DirectFrame
import direct.gui.DirectGui
import direct.gui.DirectGuiBase
import direct.gui.DirectGuiGlobals
import direct.gui.DirectGuiTest
import direct.gui.DirectLabel
import direct.gui.DirectOptionMenu
import direct.gui.DirectRadioButton
import direct.gui.DirectScrollBar
import direct.gui.DirectScrolledFrame
import direct.gui.DirectScrolledList
import direct.gui.DirectSlider
import direct.gui.DirectWaitBar
import direct.gui.OnscreenGeom
import direct.gui.OnscreenImage
import direct.gui.OnscreenText
import direct.interval.ActorInterval
import direct.interval.AnimControlInterval
import direct.interval.FunctionInterval
import direct.interval.IndirectInterval
import direct.interval.Interval
import direct.interval.IntervalGlobal
import direct.interval.IntervalManager
import direct.interval.IntervalTest
import direct.interval.LerpBlendHelpers
import direct.interval.LerpInterval
import direct.interval.MetaInterval
import direct.interval.MopathInterval
import direct.interval.ParticleInterval
import direct.interval.ProjectileInterval
import direct.interval.ProjectileIntervalTest
import direct.interval.SoundInterval
import direct.interval.TestInterval
import direct.motiontrail.MotionTrail
import direct.p3d.AppRunner
import direct.p3d.DWBPackageInstaller
import direct.p3d.DeploymentTools
import direct.p3d.FileSpec
import direct.p3d.HostInfo
import direct.p3d.InstalledHostData
import direct.p3d.InstalledPackageData
import direct.p3d.JavaScript
import direct.p3d.PackageInfo
import direct.p3d.PackageInstaller
import direct.p3d.PackageMerger
import direct.p3d.Packager
import direct.p3d.PatchMaker
import direct.p3d.ScanDirectoryNode
import direct.p3d.SeqValue
import direct.particles.ForceGroup
import direct.particles.GlobalForceGroup
import direct.particles.ParticleEffect
import direct.particles.ParticleFloorTest
import direct.particles.ParticleManagerGlobal
import direct.particles.ParticleTest
import direct.particles.Particles
import direct.particles.SpriteParticleRendererExt
import direct.physics.FallTest
import direct.physics.RotationTest
import direct.showbase.AppRunnerGlobal
import direct.showbase.Audio3DManager
import direct.showbase.BufferViewer
import direct.showbase.BulletinBoard
import direct.showbase.BulletinBoardGlobal
import direct.showbase.BulletinBoardWatcher
import direct.showbase.ContainerLeakDetector
import direct.showbase.ContainerReport
import direct.showbase.CountedResource
import direct.showbase.DirectObject
import direct.showbase.DistancePhasedNode
import direct.showbase.EventGroup
import direct.showbase.EventManager
import direct.showbase.EventManagerGlobal
import direct.showbase.ExceptionVarDump
import direct.showbase.Factory
import direct.showbase.Finder
import direct.showbase.GarbageReport
import direct.showbase.GarbageReportScheduler
import direct.showbase.InputStateGlobal
import direct.showbase.Job
import direct.showbase.JobManager
import direct.showbase.JobManagerGlobal
import direct.showbase.LeakDetectors
import direct.showbase.Loader
import direct.showbase.Messenger
import direct.showbase.MessengerGlobal
import direct.showbase.MessengerLeakDetector
import direct.showbase.MirrorDemo
import direct.showbase.ObjectPool
import direct.showbase.ObjectReport
import direct.showbase.OnScreenDebug
import direct.showbase.PhasedObject
import direct.showbase.PhysicsManagerGlobal
import direct.showbase.Pool
import direct.showbase.ProfileSession
import direct.showbase.PythonUtil
import direct.showbase.RandomNumGen
import direct.showbase.ReferrerSearch
import direct.showbase.SfxPlayer
import direct.showbase.ShadowDemo
import direct.showbase.ShadowPlacer
import direct.showbase.ShowBase
import direct.showbase.TaskThreaded
import direct.showbase.ThreeUpShow
import direct.showbase.Transitions
import direct.showbase.VFSImporter
import direct.showbase.WxGlobal
import direct.showutil.BuildGeometry
import direct.showutil.Effects
import direct.showutil.Rope
import direct.showutil.TexMemWatcher
import direct.showutil.TexViewer
import direct.stdpy.file
import direct.stdpy.glob
#import direct.stdpy.pickle
import direct.stdpy.thread
import direct.stdpy.threading
import direct.stdpy.threading2
import direct.task.FrameProfiler
import direct.task.MiniTask
import direct.task.Task
import direct.task.TaskManagerGlobal
import direct.task.TaskProfiler
import direct.task.TaskTester
import direct.task.Timer
try:
import Pmw
except ImportError:
Pmw = None
print("Skipping Tk modules due to missing Pmw.")
if Pmw:
import direct.showbase.TkGlobal
import direct.tkpanels.AnimPanel
import direct.tkpanels.DirectSessionPanel
import direct.tkpanels.FSMInspector
import direct.tkpanels.Inspector
import direct.tkpanels.MopathRecorder
import direct.tkpanels.NotifyPanel
import direct.tkpanels.ParticlePanel
import direct.tkpanels.Placer
import direct.tkpanels.TaskManagerPanel
import direct.tkwidgets.AppShell
import direct.tkwidgets.Dial
import direct.tkwidgets.EntryScale
import direct.tkwidgets.Floater
import direct.tkwidgets.MemoryExplorer
import direct.tkwidgets.ProgressBar
import direct.tkwidgets.SceneGraphExplorer
import direct.tkwidgets.Slider
import direct.tkwidgets.Tree
import direct.tkwidgets.Valuator
import direct.tkwidgets.VectorWidgets
import direct.tkwidgets.WidgetPropertiesDialog
try:
import wx
except ImportError:
wx = None
print("Skipping wxPython and leveleditor modules due to missing wx.")
if wx:
import direct.wxwidgets.ViewPort
import direct.wxwidgets.WxAppShell
import direct.wxwidgets.WxPandaShell
import direct.wxwidgets.WxPandaWindow
import direct.wxwidgets.WxSlider
import direct.leveleditor.ActionMgr
import direct.leveleditor.AnimControlUI
import direct.leveleditor.AnimGlobals
import direct.leveleditor.AnimMgr
import direct.leveleditor.AnimMgrBase
import direct.leveleditor.CurveAnimUI
import direct.leveleditor.CurveEditor
import direct.leveleditor.FileMgr
import direct.leveleditor.GraphEditorUI
import direct.leveleditor.HotKeyUI
import direct.leveleditor.LayerEditorUI
import direct.leveleditor.LevelEditor
import direct.leveleditor.LevelEditorBase
import direct.leveleditor.LevelEditorStart
import direct.leveleditor.LevelEditorUI
import direct.leveleditor.LevelEditorUIBase
import direct.leveleditor.LevelLoader
import direct.leveleditor.LevelLoaderBase
import direct.leveleditor.MayaConverter
import direct.leveleditor.ObjectGlobals
import direct.leveleditor.ObjectHandler
import direct.leveleditor.ObjectMgr
import direct.leveleditor.ObjectMgrBase
import direct.leveleditor.ObjectPalette
import direct.leveleditor.ObjectPaletteBase
import direct.leveleditor.ObjectPaletteUI
import direct.leveleditor.ObjectPropertyUI
import direct.leveleditor.PaletteTreeCtrl
import direct.leveleditor.ProtoObjs
import direct.leveleditor.ProtoObjsUI
import direct.leveleditor.ProtoPalette
import direct.leveleditor.ProtoPaletteBase
import direct.leveleditor.ProtoPaletteUI
import direct.leveleditor.SceneGraphUI
import direct.leveleditor.SceneGraphUIBase
print("Finished.")

View File

@ -36,14 +36,6 @@ def test_wheel(wheel, verbose=False):
shutil.rmtree(envdir)
sys.exit(1)
# Temp hack to patch issue pypa/pip#6885 in pip 19.2.2 and Python 3.8.
if sys.platform == "win32" and "-cp38-cp38-" in wheel and os.path.isdir(os.path.join(envdir, "Lib", "site-packages", "pip-19.2.2.dist-info")):
pep425tags = os.path.join(envdir, "Lib", "site-packages", "pip", "_internal", "pep425tags.py")
if os.path.isfile(pep425tags):
data = open(pep425tags, "r").read()
data = data.replace(" m = 'm'\n", " m = ''\n")
open(pep425tags, "w").write(data)
# Install pytest into the environment, as well as our wheel.
if subprocess.call([python, "-m", "pip", "install", "pytest", wheel]) != 0:
shutil.rmtree(envdir)

View File

@ -58,7 +58,7 @@ PUBLISHED:
void set_gravity(PN_stdfloat gx, PN_stdfloat gy, PN_stdfloat gz);
const LVector3 get_gravity() const;
int do_physics(PN_stdfloat dt, int max_substeps=1, PN_stdfloat stepsize=1.0f/60.0f);
BLOCKING int do_physics(PN_stdfloat dt, int max_substeps=1, PN_stdfloat stepsize=1.0f/60.0f);
BulletSoftBodyWorldInfo get_world_info();

View File

@ -1,46 +0,0 @@
/**
* 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."
*
* @file apply_patch.cxx
*/
#include "pandabase.h"
#include "panda_getopt.h"
#include "preprocess_argv.h"
#include "patchfile.h"
#include "filename.h"
using std::cerr;
using std::endl;
int
main(int argc, char **argv) {
preprocess_argv(argc, argv);
if (argc < 3) {
cerr << "Usage: apply_patch <patch_file> <old_file>" << endl;
cerr << "Will overwrite old_file" << endl;
return 1;
}
Filename patch = argv[1];
patch.set_binary();
Filename file = argv[2];
file.set_binary();
Patchfile pfile;
cerr << "Applying patch file " << patch << " to " << file << endl;
if (pfile.apply(patch, file) == false) {
cerr << "apply patch failed" << endl;
return 1;
}
return 0;
}

View File

@ -1,125 +0,0 @@
/**
* 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."
*
* @file build_patch.cxx
*/
#include "pandabase.h"
#include "panda_getopt.h"
#include "preprocess_argv.h"
#include "patchfile.h"
#include "filename.h"
using std::cerr;
using std::endl;
void
usage() {
cerr << "Usage: build_patch [opts] <old_file> <new_file>" << endl;
}
void
help() {
usage();
cerr << "\n"
"This program generates a patch file that describes the differences\n"
"between any two source files. The patch file can later be used to\n"
"construct <new_file>, given <old_file>. Arbitrary file types, including\n"
"binary files, are supported.\n\n"
"The patching algorithm can get very slow for very large files. As an\n"
"optimization, if the input files are both Panda Multifiles, the patcher\n"
"will by default patch them on a per-subfile basis, which has the potential\n"
"to be much faster. The -c option will forbid this and force the patcher\n"
"to work on the full file.\n\n"
"Options:\n\n"
" -o output_name\n"
" Specify the filename of the patch file to generate.\n\n"
" -c\n"
" Always generate patches against the complete file, even if the\n"
" input files appear to be multifiles.\n\n"
" -f footprint_length\n"
" Specify the footprint length for the patching algorithm.\n\n";
}
int
main(int argc, char **argv) {
Filename patch_file;
bool complete_file = false;
int footprint_length = 0;
// extern char *optarg;
extern int optind;
static const char *optflags = "o:cf:h";
preprocess_argv(argc, argv);
int flag = getopt(argc, argv, optflags);
Filename rel_path;
while (flag != EOF) {
switch (flag) {
case 'o':
patch_file = optarg;
break;
case 'c':
complete_file = true;
break;
case 'f':
footprint_length = atoi(optarg);
break;
case 'h':
help();
return 1;
case '?':
usage();
return 1;
default:
cerr << "Unhandled switch: " << flag << endl;
break;
}
flag = getopt(argc, argv, optflags);
}
argc -= (optind - 1);
argv += (optind - 1);
if (argc < 3) {
usage();
return 1;
}
Filename src_file = Filename::from_os_specific(argv[1]);
src_file.set_binary();
Filename dest_file = Filename::from_os_specific(argv[2]);
dest_file.set_binary();
if (patch_file.empty()) {
patch_file = dest_file.get_fullpath() + ".pch";
}
Patchfile pfile;
pfile.set_allow_multifile(!complete_file);
if (footprint_length != 0) {
cerr << "Footprint length is " << footprint_length << "\n";
pfile.set_footprint_length(footprint_length);
}
cerr << "Building patch file to convert " << src_file << " to "
<< dest_file << endl;
if (pfile.build(src_file, dest_file, patch_file) == false) {
cerr << "build patch failed" << endl;
return 1;
}
return 0;
}

View File

@ -1,26 +0,0 @@
/**
* 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."
*
* @file check_adler.cxx
*/
#include "download_utils.h"
int
main(int argc, char *argv[]) {
if (argc < 2) {
std::cerr << "Usage: check_adler <file>" << std::endl;
return 1;
}
Filename source_file = argv[1];
std::cout << check_adler(source_file);
return 0;
}

View File

@ -1,26 +0,0 @@
/**
* 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."
*
* @file check_crc.cxx
*/
#include "download_utils.h"
int
main(int argc, char *argv[]) {
if (argc < 2) {
std::cerr << "Usage: check_crc <file>" << std::endl;
return 1;
}
Filename source_file = argv[1];
std::cout << check_crc(source_file);
return 0;
}

View File

@ -1,155 +0,0 @@
/**
* 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."
*
* @file check_md5.cxx
*/
#include "pandabase.h"
#include "hashVal.h"
#include "filename.h"
#include "panda_getopt.h"
#include "preprocess_argv.h"
using std::cerr;
using std::cout;
bool output_decimal = false;
bool suppress_filename = false;
pofstream binary_output;
void
usage() {
cerr <<
"\n"
"Usage:\n\n"
"check_md5 [-q] [-d] [-b filename] [-i \"input string\"] [file1 file2 ...]\n"
"check_md5 -h\n\n";
}
void
help() {
usage();
cerr <<
"This program outputs the MD5 hash of one or more files (or of a string\n"
"passed on the command line with -i).\n\n"
"An MD5 hash is a 128-bit value. The output is presented as a 32-digit\n"
"hexadecimal string by default, but with -d, it is presented as four\n"
"big-endian unsigned 32-bit decimal integers. Normally the filename\n"
"of each file is printed along with the hash; -q suppresses this.\n\n"
"To write the 16 bytes (per input file) of the output directly to a\n"
"binary file, use -b with the name of the file to receive the output.\n";
}
void
output_hash(const std::string &filename, const HashVal &hash) {
if (!suppress_filename && !filename.empty()) {
cout << filename << " ";
}
if (output_decimal) {
hash.output_dec(cout);
} else {
hash.output_hex(cout);
}
cout << "\n";
// Also output to the binary_output file if it is open. No sweat if it's
// not.
hash.output_binary(binary_output);
}
int
main(int argc, char **argv) {
extern char *optarg;
extern int optind;
const char *optstr = "i:db:qh";
bool got_input_string = false;
std::string input_string;
Filename binary_output_filename;
preprocess_argv(argc, argv);
int flag = getopt(argc, argv, optstr);
while (flag != EOF) {
switch (flag) {
case 'i':
got_input_string = true;
input_string = optarg;
break;
case 'd':
output_decimal = true;
break;
case 'b':
binary_output_filename = Filename::binary_filename(std::string(optarg));
break;
case 'q':
suppress_filename = true;
break;
case 'h':
help();
exit(1);
default:
exit(1);
}
flag = getopt(argc, argv, optstr);
}
argc -= (optind-1);
argv += (optind-1);
if (argc < 2 && !got_input_string) {
usage();
exit(1);
}
if (!binary_output_filename.empty()) {
if (!binary_output_filename.open_write(binary_output)) {
cerr << "Unable to open " << binary_output_filename << ".\n";
exit(1);
}
}
if (got_input_string) {
HashVal hash;
hash.hash_string(input_string);
output_hash("", hash);
}
bool okflag = true;
for (int i = 1; i < argc; i++) {
Filename source_file = Filename::from_os_specific(argv[i]);
if (!source_file.exists()) {
cerr << source_file << " not found!\n";
okflag = false;
} else {
HashVal hash;
if (!hash.hash_file(source_file)) {
cerr << "Unable to read " << source_file << "\n";
okflag = false;
} else {
output_hash(source_file.get_basename(), hash);
}
}
}
if (!okflag) {
exit(1);
}
return 0;
}

View File

@ -1,32 +0,0 @@
/**
* 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."
*
* @file show_ddb.cxx
* @author drose
* @date 2002-11-02
*/
#include "pandabase.h"
#include "downloadDb.h"
#include "filename.h"
int
main(int argc, char *argv[]) {
if (argc != 3) {
std::cerr << "Usage: show_ddb server.ddb client.ddb\n";
return 1;
}
Filename server_ddb = Filename::from_os_specific(argv[1]);
Filename client_ddb = Filename::from_os_specific(argv[2]);
DownloadDb db(server_ddb, client_ddb);
db.write(std::cout);
return 0;
}

View File

@ -46,11 +46,13 @@ queue_event(CPT_Event event) {
LightMutexHolder holder(_lock);
_queue.push_back(event);
if (event_cat.is_spam() || event_cat.is_debug()) {
if (event_cat.is_debug()) {
if (event->get_name() == "NewFrame") {
// Don't bother us with this particularly spammy event.
event_cat.spam()
<< "Throwing event " << *event << "\n";
if (event_cat.is_spam()) {
event_cat.spam()
<< "Throwing event " << *event << "\n";
}
} else {
event_cat.debug()
<< "Throwing event " << *event << "\n";

View File

@ -26,15 +26,6 @@
#include <string.h> // for strstr
#ifdef HAVE_TAR
#include <libtar.h>
#include <fcntl.h> // for O_RDONLY
#endif // HAVE_TAR
#ifdef HAVE_TAR
std::istream *Patchfile::_tar_istream = nullptr;
#endif // HAVE_TAR
using std::endl;
using std::ios;
using std::istream;
@ -1160,202 +1151,6 @@ compute_mf_patches(ostream &write_stream,
return true;
}
#ifdef HAVE_TAR
/**
* Uses libtar to extract the location within the tar file of each of the
* subfiles. Returns true if the tar file is read successfully, false if
* there is an error (e.g. it is not a tar file).
*/
bool Patchfile::
read_tar(TarDef &tar, istream &stream) {
TAR *tfile;
tartype_t tt;
tt.openfunc = tar_openfunc;
tt.closefunc = tar_closefunc;
tt.readfunc = tar_readfunc;
tt.writefunc = tar_writefunc;
stream.seekg(0, ios::beg);
nassertr(_tar_istream == nullptr, false);
_tar_istream = &stream;
if (tar_open(&tfile, (char *)"dummy", &tt, O_RDONLY, 0, 0) != 0) {
_tar_istream = nullptr;
return false;
}
// Walk through the tar file, noting the current file position as we reach
// each subfile. Use this information to infer the start and end of each
// subfile within the stream.
streampos last_pos = 0;
int flag = th_read(tfile);
while (flag == 0) {
TarSubfile subfile;
subfile._name = th_get_pathname(tfile);
subfile._header_start = last_pos;
subfile._data_start = stream.tellg();
subfile._data_end = subfile._data_start + (streampos)th_get_size(tfile);
tar_skip_regfile(tfile);
subfile._end = stream.tellg();
tar.push_back(subfile);
last_pos = subfile._end;
flag = th_read(tfile);
}
// Create one more "subfile" for the bytes at the tail of the file. This
// subfile has no name.
TarSubfile subfile;
subfile._header_start = last_pos;
stream.clear();
stream.seekg(0, ios::end);
subfile._data_start = stream.tellg();
subfile._data_end = subfile._data_start;
subfile._end = subfile._data_start;
tar.push_back(subfile);
tar_close(tfile);
_tar_istream = nullptr;
return (flag == 1);
}
#endif // HAVE_TAR
#ifdef HAVE_TAR
/**
* Computes patches for the files, knowing that they are both tar files. This
* is similar to compute_mf_patches().
*
* The tar indexes should have been built up by a previous call to read_tar().
*/
bool Patchfile::
compute_tar_patches(ostream &write_stream,
uint32_t offset_orig, uint32_t offset_new,
istream &stream_orig, istream &stream_new,
TarDef &tar_orig, TarDef &tar_new) {
// Sort the orig list by filename, so we can quickly look up files from the
// new list.
tar_orig.sort();
// However, it is important to keep the new list in its original, on-disk
// order.
// Walk through each subfile in the new tar file. If a particular subfile
// exists in both source files, we compute the patches for the subfile; for
// a new subfile, we trivially add it. If a subfile has been removed, we
// simply don't add it (we'll never even notice this case).
IStreamWrapper stream_origw(stream_orig);
IStreamWrapper stream_neww(stream_new);
TarDef::const_iterator ni;
streampos last_pos = 0;
for (ni = tar_new.begin(); ni != tar_new.end(); ++ni) {
const TarSubfile &sf_new =(*ni);
nassertr(sf_new._header_start == last_pos, false);
TarDef::const_iterator oi = tar_orig.find(sf_new);
if (oi == tar_orig.end()) {
// This is a newly-added subfile. Add it the hard way.
express_cat.info()
<< "Adding subfile " << sf_new._name << "\n";
streampos new_start = sf_new._header_start;
size_t new_size = sf_new._end - sf_new._header_start;
char *buffer_new = (char *)PANDA_MALLOC_ARRAY(new_size);
stream_new.seekg(new_start, ios::beg);
stream_new.read(buffer_new, new_size);
cache_add_and_copy(write_stream, new_size, buffer_new, 0, 0);
PANDA_FREE_ARRAY(buffer_new);
} else {
// This subfile exists in both the original and the new files. Patch
// it.
const TarSubfile &sf_orig =(*oi);
// We patch the header and data of the file separately, so we can
// accurately detect nested multifiles. The extra data at the end of
// the file (possibly introduced by a tar file's blocking) is the
// footer, which is also patched separately.
if (!patch_subfile(write_stream, offset_orig, offset_new, "",
stream_origw, sf_orig._header_start, sf_orig._data_start,
stream_neww, sf_new._header_start, sf_new._data_start)) {
return false;
}
if (!patch_subfile(write_stream, offset_orig, offset_new, sf_new._name,
stream_origw, sf_orig._data_start, sf_orig._data_end,
stream_neww, sf_new._data_start, sf_new._data_end)) {
return false;
}
if (!patch_subfile(write_stream, offset_orig, offset_new, "",
stream_origw, sf_orig._data_end, sf_orig._end,
stream_neww, sf_new._data_end, sf_new._end)) {
return false;
}
}
last_pos = sf_new._end;
}
return true;
}
#endif // HAVE_TAR
#ifdef HAVE_TAR
/**
* A callback function to redirect libtar to read from our istream instead of
* using low-level Unix I/O.
*/
int Patchfile::
tar_openfunc(const char *, int, ...) {
// Since we don't actually open a file--the stream is already open--we do
// nothing here.
return 0;
}
#endif // HAVE_TAR
#ifdef HAVE_TAR
/**
* A callback function to redirect libtar to read from our istream instead of
* using low-level Unix I/O.
*/
int Patchfile::
tar_closefunc(int) {
// Since we don't actually open a file, no need to close it either.
return 0;
}
#endif // HAVE_TAR
#ifdef HAVE_TAR
/**
* A callback function to redirect libtar to read from our istream instead of
* using low-level Unix I/O.
*/
ssize_t Patchfile::
tar_readfunc(int, void *buffer, size_t nbytes) {
nassertr(_tar_istream != nullptr, 0);
_tar_istream->read((char *)buffer, nbytes);
return (ssize_t)_tar_istream->gcount();
}
#endif // HAVE_TAR
#ifdef HAVE_TAR
/**
* A callback function to redirect libtar to read from our istream instead of
* using low-level Unix I/O.
*/
ssize_t Patchfile::
tar_writefunc(int, const void *, size_t) {
// Since we use libtar only for reading, it is an error if this method gets
// called.
nassertr(false, -1);
return -1;
}
#endif // HAVE_TAR
/**
*
* This implementation uses the "greedy differencing algorithm" described in
@ -1440,10 +1235,6 @@ do_compute_patches(const Filename &file_orig, const Filename &file_new,
// Check whether our input files are Panda multifiles or tar files.
bool is_multifile = false;
#ifdef HAVE_TAR
bool is_tarfile = false;
TarDef tar_orig, tar_new;
#endif // HAVE_TAR
if (_allow_multifile) {
if (strstr(file_orig.get_basename().c_str(), ".mf") != nullptr ||
@ -1465,15 +1256,6 @@ do_compute_patches(const Filename &file_orig, const Filename &file_new,
}
PANDA_FREE_ARRAY(buffer);
}
#ifdef HAVE_TAR
if (strstr(file_orig.get_basename().c_str(), ".tar") != nullptr ||
strstr(file_new.get_basename().c_str(), ".tar") != nullptr) {
if (read_tar(tar_orig, stream_orig) &&
read_tar(tar_new, stream_new)) {
is_tarfile = true;
}
}
#endif // HAVE_TAR
}
if (is_multifile) {
@ -1485,17 +1267,6 @@ do_compute_patches(const Filename &file_orig, const Filename &file_new,
stream_orig, stream_new)) {
return false;
}
#ifdef HAVE_TAR
} else if (is_tarfile) {
if (express_cat.is_debug()) {
express_cat.debug()
<< file_orig.get_basename() << " appears to be a tar file.\n";
}
if (!compute_tar_patches(write_stream, offset_orig, offset_new,
stream_orig, stream_new, tar_orig, tar_new)) {
return false;
}
#endif // HAVE_TAR
} else {
if (express_cat.is_debug()) {
express_cat.debug()

View File

@ -108,35 +108,6 @@ private:
bool compute_mf_patches(std::ostream &write_stream,
uint32_t offset_orig, uint32_t offset_new,
std::istream &stream_orig, std::istream &stream_new);
#ifdef HAVE_TAR
class TarSubfile {
public:
inline bool operator < (const TarSubfile &other) const {
return _name < other._name;
}
std::string _name;
std::streampos _header_start;
std::streampos _data_start;
std::streampos _data_end;
std::streampos _end;
};
typedef ov_set<TarSubfile> TarDef;
bool read_tar(TarDef &tar, std::istream &stream);
bool compute_tar_patches(std::ostream &write_stream,
uint32_t offset_orig, uint32_t offset_new,
std::istream &stream_orig, std::istream &stream_new,
TarDef &tar_orig, TarDef &tar_new);
// Because this is static, we can only call read_tar() one at a time--no
// threads, please.
static std::istream *_tar_istream;
static int tar_openfunc(const char *filename, int oflags, ...);
static int tar_closefunc(int fd);
static ssize_t tar_readfunc(int fd, void *buffer, size_t nbytes);
static ssize_t tar_writefunc(int fd, const void *buffer, size_t nbytes);
#endif // HAVE_TAR
bool do_compute_patches(const Filename &file_orig, const Filename &file_new,
std::ostream &write_stream,

View File

@ -41,6 +41,8 @@
#include "pta_LVecBase2.h"
#include "stl_compares.h"
#include "shaderInput.h"
#include "internalNameCollection.h"
#include "materialCollection.h"
#include "textureCollection.h"
#include "textureStageCollection.h"
@ -49,13 +51,9 @@ class FindApproxPath;
class FindApproxLevelEntry;
class Light;
class PolylightNode;
class InternalNameCollection;
class Texture;
class TextureStage;
class TextureCollection;
class TextureStageCollection;
class Material;
class MaterialCollection;
class Fog;
class GlobPattern;
class PreparedGraphicsObjects;
@ -1054,6 +1052,8 @@ private:
INLINE std::ostream &operator << (std::ostream &out, const NodePath &node_path);
#include "nodePathCollection.h"
#include "nodePath.I"
#endif

View File

@ -86,8 +86,8 @@ Pipeline::
void Pipeline::
cycle() {
#ifdef THREADED_PIPELINE
if (pipeline_cat.is_debug()) {
pipeline_cat.debug()
if (pipeline_cat.is_spam()) {
pipeline_cat.spam()
<< "Beginning the pipeline cycle\n";
}

View File

@ -71,6 +71,57 @@ clamp_val(int input_value) const {
return (xelval)std::min(std::max(0, input_value), (int)get_maxval());
}
/**
* A handy function to scale non-alpha values from [0..1] to
* [0..get_maxval()]. Do not use this for alpha values, see to_alpha_val.
*/
INLINE xel PNMImage::
to_val(const LRGBColorf &value) const {
xel col;
switch (_xel_encoding) {
case XE_generic:
case XE_generic_alpha:
{
LRGBColorf scaled = value * get_maxval() + 0.5f;
col.r = clamp_val((int)scaled[0]);
col.g = clamp_val((int)scaled[1]);
col.b = clamp_val((int)scaled[2]);
}
break;
case XE_generic_sRGB:
case XE_generic_sRGB_alpha:
col.r = clamp_val((int)
(encode_sRGB_float(value[0]) * get_maxval() + 0.5f));
col.g = clamp_val((int)
(encode_sRGB_float(value[1]) * get_maxval() + 0.5f));
col.b = clamp_val((int)
(encode_sRGB_float(value[2]) * get_maxval() + 0.5f));
break;
case XE_uchar_sRGB:
case XE_uchar_sRGB_alpha:
encode_sRGB_uchar(LColorf(value, 0.0f), col);
break;
case XE_uchar_sRGB_sse2:
case XE_uchar_sRGB_alpha_sse2:
encode_sRGB_uchar_sse2(LColorf(value, 0.0f), col);
break;
case XE_scRGB:
case XE_scRGB_alpha:
{
LRGBColorf scaled = value * 8192.f + 4096.5f;
col.r = std::min(std::max(0, (int)scaled[0]), 65535);
col.g = std::min(std::max(0, (int)scaled[1]), 65535);
col.b = std::min(std::max(0, (int)scaled[2]), 65535);
}
break;
}
return col;
}
/**
* A handy function to scale non-alpha values from [0..1] to
* [0..get_maxval()]. Do not use this for alpha values, see to_alpha_val.
@ -112,6 +163,44 @@ to_alpha_val(float input_value) const {
return clamp_val((int)(input_value * get_maxval() + 0.5));
}
/**
* A handy function to scale non-alpha values from [0..get_maxval()] to
* [0..1]. Do not use this for alpha values, see from_alpha_val.
*/
INLINE LRGBColorf PNMImage::
from_val(const xel &col) const {
switch (_xel_encoding) {
case XE_generic:
case XE_generic_alpha:
return LRGBColorf(col.r, col.g, col.b) * _inv_maxval;
case XE_generic_sRGB:
case XE_generic_sRGB_alpha:
return LRGBColorf(
decode_sRGB_float(col.r * _inv_maxval),
decode_sRGB_float(col.g * _inv_maxval),
decode_sRGB_float(col.b * _inv_maxval));
case XE_uchar_sRGB:
case XE_uchar_sRGB_alpha:
case XE_uchar_sRGB_sse2:
case XE_uchar_sRGB_alpha_sse2:
return LRGBColorf(
decode_sRGB_float((unsigned char)col.r),
decode_sRGB_float((unsigned char)col.g),
decode_sRGB_float((unsigned char)col.b));
case XE_scRGB:
case XE_scRGB_alpha:
return LRGBColorf((int)col.r - 4096,
(int)col.g - 4096,
(int)col.b - 4096) * (1.f / 8192.f);
default:
return LRGBColorf(0);
}
}
/**
* A handy function to scale non-alpha values from [0..get_maxval()] to
* [0..1]. Do not use this for alpha values, see from_alpha_val.
@ -479,39 +568,7 @@ set_alpha_val(int x, int y, xelval a) {
INLINE LRGBColorf PNMImage::
get_xel(int x, int y) const {
nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, LRGBColorf::zero());
const xel &col = row(y)[x];
switch (_xel_encoding) {
case XE_generic:
case XE_generic_alpha:
return LRGBColorf(col.r, col.g, col.b) * _inv_maxval;
case XE_generic_sRGB:
case XE_generic_sRGB_alpha:
return LRGBColorf(
decode_sRGB_float(col.r * _inv_maxval),
decode_sRGB_float(col.g * _inv_maxval),
decode_sRGB_float(col.b * _inv_maxval));
case XE_uchar_sRGB:
case XE_uchar_sRGB_alpha:
case XE_uchar_sRGB_sse2:
case XE_uchar_sRGB_alpha_sse2:
return LRGBColorf(
decode_sRGB_float((unsigned char)col.r),
decode_sRGB_float((unsigned char)col.g),
decode_sRGB_float((unsigned char)col.b));
case XE_scRGB:
case XE_scRGB_alpha:
return LRGBColorf((int)col.r - 4096,
(int)col.g - 4096,
(int)col.b - 4096) * (1.f / 8192.f);
default:
return LRGBColorf(0);
}
return from_val(row(y)[x]);
}
/**
@ -521,50 +578,7 @@ get_xel(int x, int y) const {
INLINE void PNMImage::
set_xel(int x, int y, const LRGBColorf &value) {
nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
xel &col = row(y)[x];
switch (_xel_encoding) {
case XE_generic:
case XE_generic_alpha:
{
LRGBColorf scaled = value * get_maxval() + 0.5f;
col.r = clamp_val((int)scaled[0]);
col.g = clamp_val((int)scaled[1]);
col.b = clamp_val((int)scaled[2]);
}
break;
case XE_generic_sRGB:
case XE_generic_sRGB_alpha:
col.r = clamp_val((int)
(encode_sRGB_float(value[0]) * get_maxval() + 0.5f));
col.g = clamp_val((int)
(encode_sRGB_float(value[1]) * get_maxval() + 0.5f));
col.b = clamp_val((int)
(encode_sRGB_float(value[2]) * get_maxval() + 0.5f));
break;
case XE_uchar_sRGB:
case XE_uchar_sRGB_alpha:
encode_sRGB_uchar(LColorf(value, 0.0f), col);
break;
case XE_uchar_sRGB_sse2:
case XE_uchar_sRGB_alpha_sse2:
encode_sRGB_uchar_sse2(LColorf(value, 0.0f), col);
break;
case XE_scRGB:
case XE_scRGB_alpha:
{
LRGBColorf scaled = value * 8192.f + 4096.5f;
col.r = std::min(std::max(0, (int)scaled[0]), 65535);
col.g = std::min(std::max(0, (int)scaled[1]), 65535);
col.b = std::min(std::max(0, (int)scaled[2]), 65535);
}
break;
}
row(y)[x] = to_val(value);
}
/**

View File

@ -1928,6 +1928,51 @@ make_histogram(PNMImage::Histogram &histogram) {
histogram.swap(pixels, hist_map);
}
/**
* Reduces the number of unique colors in the image to (at most) the given
* count. Fewer colors than requested may be left in the image after this
* operation, but never more.
*
* At present, this is only supported on images without an alpha channel.
*
* @since 1.10.5
*/
void PNMImage::
quantize(size_t max_colors) {
nassertv(_array != nullptr);
nassertv(!has_alpha());
size_t array_size = _x_size * _y_size;
// Get all the unique colors in this image.
pmap<xel, xel> color_map;
for (size_t i = 0; i < array_size; ++i) {
color_map[_array[i]];
}
size_t num_colors = color_map.size();
if (num_colors <= max_colors) {
// We are already down to the requested number of colors.
return;
}
// Collect all the colors into a contiguous array.
xel *colors = (xel *)alloca(num_colors * sizeof(xel));
size_t i = 0;
for (pmap<xel, xel>::const_iterator it = color_map.begin();
it != color_map.end(); ++it) {
colors[i++] = it->first;
}
nassertv(i == num_colors);
// Apply the median cut algorithm, which will give us a color map.
r_quantize(color_map, max_colors, colors, num_colors);
// Replace all the existing colors with the corresponding bucket average.
for (size_t i = 0; i < array_size; ++i) {
_array[i] = color_map[_array[i]];
}
}
/**
* Fills the image with a grayscale perlin noise pattern based on the
* indicated parameters. Uses set_xel to set the grayscale values. The sx
@ -2161,6 +2206,92 @@ setup_encoding() {
}
}
/**
* Recursive implementation of quantize() using the median cut algorithm.
*/
void PNMImage::
r_quantize(pmap<xel, xel> &color_map, size_t max_colors,
xel *colors, size_t num_colors) {
if (num_colors <= max_colors) {
// All points in this bucket can be preserved 1:1.
for (size_t i = 0; i < num_colors; ++i) {
const xel &col = colors[i];
color_map[col] = col;
}
return;
}
else if (max_colors == 1) {
// We've reached the target. Calculate the average, in linear space.
LRGBColorf avg(0);
for (size_t i = 0; i < num_colors; ++i) {
avg += from_val(colors[i]);
}
avg *= 1.0f / num_colors;
xel avg_val = to_val(avg);
// Map all colors in this bucket to the avg.
for (size_t i = 0; i < num_colors; ++i) {
color_map[colors[i]] = avg_val;
}
return;
}
else if (max_colors == 0) {
// Not sure how this happens, but we can't preserve any color here.
return;
}
// Find the minimum/maximum RGB values. We should probably do this in
// linear space, but eh.
xelval min_r = _maxval;
xelval min_g = _maxval;
xelval min_b = _maxval;
xelval max_r = 0, max_g = 0, max_b = 0;
for (size_t i = 0; i < num_colors; ++i) {
const xel &col = colors[i];
min_r = std::min(min_r, col.r);
max_r = std::max(max_r, col.r);
min_g = std::min(min_g, col.g);
max_g = std::max(max_g, col.g);
min_b = std::min(min_b, col.b);
max_b = std::max(max_b, col.b);
}
int diff_r = max_r - min_r;
int diff_g = max_g - min_g;
int diff_b = max_b - min_b;
auto sort_by_red = [](const xel &c1, const xel &c2) {
return c1.r < c2.r;
};
auto sort_by_green = [](const xel &c1, const xel &c2) {
return c1.g < c2.g;
};
auto sort_by_blue = [](const xel &c1, const xel &c2) {
return c1.b < c2.b;
};
// Sort by the component with the most variation.
if (diff_g >= diff_r) {
if (diff_g >= diff_b) {
std::sort(colors, colors + num_colors, sort_by_green);
} else {
std::sort(colors, colors + num_colors, sort_by_blue);
}
} else if (diff_r >= diff_b) {
std::sort(colors, colors + num_colors, sort_by_red);
} else {
std::sort(colors, colors + num_colors, sort_by_blue);
}
// Subdivide the sorted colors into two buckets, and recurse.
size_t max_colors_1 = max_colors / 2;
size_t max_colors_2 = max_colors - max_colors_1;
size_t num_colors_1 = num_colors / 2;
size_t num_colors_2 = num_colors - num_colors_1;
r_quantize(color_map, max_colors_1, colors, num_colors_1);
r_quantize(color_map, max_colors_2, colors + num_colors_1, num_colors_2);
}
/**
* Recursively fills in the minimum distance measured from a certain set of
* points into the gray channel.

View File

@ -68,8 +68,10 @@ PUBLISHED:
INLINE ~PNMImage();
INLINE xelval clamp_val(int input_value) const;
INLINE xel to_val(const LRGBColorf &input_value) const;
INLINE xelval to_val(float input_value) const;
INLINE xelval to_alpha_val(float input_value) const;
INLINE LRGBColorf from_val(const xel &input_value) const;
INLINE float from_val(xelval input_value) const;
INLINE float from_alpha_val(xelval input_value) const;
@ -254,6 +256,7 @@ PUBLISHED:
int xborder = 0, int yborder = 0);
void make_histogram(Histogram &hist);
void quantize(size_t max_colors);
BLOCKING void perlin_noise_fill(float sx, float sy, int table_size = 256,
unsigned long seed = 0);
void perlin_noise_fill(StackedPerlinNoise2 &perlin);
@ -346,6 +349,9 @@ private:
void setup_rc();
void setup_encoding();
void r_quantize(pmap<xel, xel> &color_map, size_t max_colors,
xel *colors, size_t num_colors);
PUBLISHED:
PNMImage operator ~() const;

View File

@ -59,6 +59,22 @@ PUBLISHED:
void operator *= (const double mult)
{ r *= mult; g *= mult; b *= mult; }
bool operator == (const pixel &other) {
return r == other.r && g == other.g && r == other.r;
}
bool operator != (const pixel &other) {
return r != other.r || g != other.g || r != other.r;
}
bool operator < (const pixel &other) const {
if (r != other.r) {
return r < other.r;
}
if (g != other.g) {
return g < other.g;
}
return b < other.b;
}
#ifdef HAVE_PYTHON
static int size() { return 3; }
void output(std::ostream &out) {

View File

@ -15,6 +15,7 @@
#define CONFIG_ASSIMP_H
#include "pandatoolbase.h"
#include "notifyCategoryProxy.h"
#include "configVariableBool.h"
#include "configVariableDouble.h"
#include "dconfig.h"

View File

@ -99,8 +99,7 @@ run() {
out << std::hex << std::setfill('0');
int count = 0;
int col = 0;
unsigned int ch;
ch = in.get();
int ch = in.get();
while (!in.fail() && ch != EOF) {
if (col == 0) {
out << "\n ";
@ -110,7 +109,7 @@ run() {
} else {
out << ", ";
}
out << "0x" << std::setw(2) << ch;
out << "0x" << std::setw(2) << (unsigned int)ch;
col++;
count++;
ch = in.get();

View File

@ -15,7 +15,7 @@
#define CONFIG_PTLOADER_H
#include "pandatoolbase.h"
#include "notifyCategoryProxy.h"
#include "dconfig.h"
#include "distanceUnit.h"
#include "configVariableEnum.h"

View File

@ -0,0 +1,24 @@
from panda3d.core import Filename
import sys, os
import pytest
@pytest.mark.skipif(sys.version_info < (3, 6), reason="Requires Python 3.6")
def test_filename_fspath():
fn = Filename.from_os_specific(__file__)
assert os.fspath(fn) == fn.to_os_specific_w()
@pytest.mark.skipif(sys.version_info < (3, 6), reason="Requires Python 3.6")
def test_filename_open():
fn = Filename.from_os_specific(__file__)
open(fn, 'rb')
@pytest.mark.skipif(sys.version_info < (3, 4), reason="Requires Python 3.4")
def test_filename_ctor_pathlib():
pathlib = pytest.importorskip('pathlib')
path = pathlib.Path(__file__)
fn = Filename(path)
assert fn.to_os_specific_w() == str(path)

View File

@ -1,4 +1,5 @@
from panda3d.core import PNMImage, PNMImageHeader
from random import randint
def test_pixelspec_ctor():
@ -19,3 +20,53 @@ def test_pixelspec_coerce():
img = PNMImage(1, 1, 4)
img.set_pixel(0, 0, (1, 2, 3, 4))
assert img.get_pixel(0, 0) == (1, 2, 3, 4)
def test_pnmimage_to_val():
img = PNMImage(1, 1)
assert img.to_val(-0.5) == 0
assert img.to_val(0.0) == 0
assert img.to_val(0.5) == 128
assert img.to_val(1.0) == 255
assert img.to_val(2.0) == 255
def test_pnmimage_from_val():
img = PNMImage(1, 1)
assert img.from_val(0) == 0.0
assert img.to_val(img.from_val(128)) == 128
assert img.from_val(255) == 1.0
def test_pnmimage_quantize():
img = PNMImage(32, 32, 3)
for x in range(32):
for y in range(32):
img.set_xel_val(x, y, randint(0, 100), randint(50, 100), randint(0, 1))
hist = PNMImage.Histogram()
img.make_histogram(hist)
num_colors = hist.get_num_pixels()
assert num_colors > 100
img2 = PNMImage(img)
img2.quantize(100)
hist = PNMImage.Histogram()
img2.make_histogram(hist)
assert hist.get_num_pixels() <= 100
# Make sure that this is reasonably close
max_dist = 0
for x in range(32):
for y in range(32):
diff = img.get_xel(x, y) - img2.get_xel(x, y)
max_dist = max(max_dist, diff.length_squared())
# Also make sure that they are not out of range of the original
col = img2.get_xel_val(x, y)
assert col.r <= 100
assert col.g >= 50 and col.g <= 100
assert col.b in (0, 1)
assert max_dist < 0.1 ** 2

View File

@ -0,0 +1,35 @@
from panda3d.core import ModifierButtons
def test_modifierbuttons_empty():
# Tests the initial state of a ModifierButtons object.
btns = ModifierButtons()
assert btns == ModifierButtons(btns)
assert btns != ModifierButtons()
assert btns.matches(ModifierButtons())
assert not btns.is_down("alt")
assert not btns.is_any_down()
assert not btns.has_button("alt")
assert btns.get_prefix() == ""
assert btns.get_num_buttons() == 0
assert len(btns.buttons) == 0
def test_modifierbuttons_cow():
# Tests the copy-on-write mechanism of the button list.
btns1 = ModifierButtons()
btns1.add_button("space")
# Modifying original should not affect copy
btns2 = ModifierButtons(btns1)
assert tuple(btns2.buttons) == tuple(btns1.buttons)
btns1.add_button("enter")
assert tuple(btns1.buttons) == ("space", "enter")
assert tuple(btns2.buttons) == ("space",)
# Modifying copy should not affect original
btns3 = ModifierButtons(btns2)
assert tuple(btns3.buttons) == tuple(btns2.buttons)
btns3.add_button("escape")
assert tuple(btns2.buttons) == ("space",)
assert tuple(btns3.buttons) == ("space", "escape")

328
tests/test_imports.py Normal file
View File

@ -0,0 +1,328 @@
# These tests import Panda3D modules just to make sure that there are no
# missing imports. It is useful for a quick and dirty test to make sure
# that there are no obvious build issues.
import pytest
# This will print out imports on the command line.
#import direct.showbase.VerboseImport
def test_imports_panda3d():
import imp, importlib, os
import panda3d
dir = os.path.dirname(panda3d.__file__)
extensions = set()
for suffix in imp.get_suffixes():
extensions.add(suffix[0])
for basename in os.listdir(dir):
module = basename.split('.', 1)[0]
ext = basename[len(module):]
if ext in extensions:
importlib.import_module('panda3d.%s' % (module))
def test_imports_direct():
import direct.actor.Actor
import direct.actor.DistributedActor
import direct.cluster.ClusterClient
import direct.cluster.ClusterConfig
import direct.cluster.ClusterMsgs
import direct.cluster.ClusterServer
import direct.controls.BattleWalker
import direct.controls.ControlManager
import direct.controls.DevWalker
import direct.controls.GhostWalker
import direct.controls.GravityWalker
import direct.controls.InputState
import direct.controls.NonPhysicsWalker
import direct.controls.ObserverWalker
import direct.controls.PhysicsRoller
import direct.controls.PhysicsWalker
import direct.controls.SwimWalker
import direct.controls.TwoDWalker
import direct.directnotify.DirectNotify
import direct.directnotify.DirectNotifyGlobal
import direct.directnotify.Logger
import direct.directnotify.LoggerGlobal
import direct.directnotify.Notifier
import direct.directnotify.RotatingLog
import direct.directtools.DirectCameraControl
import direct.directtools.DirectGeometry
import direct.directtools.DirectGlobals
import direct.directtools.DirectGrid
import direct.directtools.DirectLights
import direct.directtools.DirectManipulation
import direct.directtools.DirectSelection
import direct.directtools.DirectUtil
import direct.directutil.DeltaProfiler
import direct.directutil.DistributedLargeBlobSender
import direct.directutil.DistributedLargeBlobSenderAI
import direct.directutil.LargeBlobSenderConsts
import direct.directutil.Mopath
import direct.directutil.Verify
import direct.directutil.WeightedChoice
import direct.dist.FreezeTool
import direct.distributed.AsyncRequest
import direct.distributed.CRCache
import direct.distributed.CRDataCache
import direct.distributed.CachedDOData
import direct.distributed.CartesianGridBase
import direct.distributed.ClientRepository
import direct.distributed.ClientRepositoryBase
import direct.distributed.ClockDelta
import direct.distributed.ConnectionRepository
import direct.distributed.DistributedCamera
import direct.distributed.DistributedCameraAI
import direct.distributed.DistributedCameraOV
import direct.distributed.DistributedCartesianGrid
import direct.distributed.DistributedCartesianGridAI
import direct.distributed.DistributedNode
import direct.distributed.DistributedNodeAI
import direct.distributed.DistributedNodeUD
import direct.distributed.DistributedObject
import direct.distributed.DistributedObjectAI
import direct.distributed.DistributedObjectBase
import direct.distributed.DistributedObjectGlobal
import direct.distributed.DistributedObjectGlobalAI
import direct.distributed.DistributedObjectGlobalUD
import direct.distributed.DistributedObjectOV
import direct.distributed.DistributedObjectUD
import direct.distributed.DistributedSmoothNodeAI
import direct.distributed.DistributedSmoothNodeBase
import direct.distributed.DoCollectionManager
import direct.distributed.DoHierarchy
import direct.distributed.DoInterestManager
import direct.distributed.GridChild
import direct.distributed.GridParent
import direct.distributed.InterestWatcher
import direct.distributed.MsgTypes
import direct.distributed.MsgTypesCMU
import direct.distributed.NetMessenger
import direct.distributed.ParentMgr
import direct.distributed.PyDatagram
import direct.distributed.PyDatagramIterator
import direct.distributed.RelatedObjectMgr
import direct.distributed.SampleObject
import direct.distributed.ServerRepository
import direct.distributed.StagedObject
import direct.distributed.TimeManager
import direct.distributed.TimeManagerAI
import direct.extensions_native.extension_native_helpers
import direct.filter.CommonFilters
import direct.filter.FilterManager
import direct.fsm.ClassicFSM
import direct.fsm.FSM
import direct.fsm.FourState
import direct.fsm.FourStateAI
import direct.fsm.SampleFSM
import direct.fsm.State
import direct.fsm.StateData
import direct.fsm.StatePush
import direct.gui.DirectButton
import direct.gui.DirectCheckBox
import direct.gui.DirectCheckButton
import direct.gui.DirectDialog
import direct.gui.DirectEntry
import direct.gui.DirectEntryScroll
import direct.gui.DirectFrame
import direct.gui.DirectGui
import direct.gui.DirectGuiBase
import direct.gui.DirectGuiGlobals
import direct.gui.DirectGuiTest
import direct.gui.DirectLabel
import direct.gui.DirectOptionMenu
import direct.gui.DirectRadioButton
import direct.gui.DirectScrollBar
import direct.gui.DirectScrolledFrame
import direct.gui.DirectScrolledList
import direct.gui.DirectSlider
import direct.gui.DirectWaitBar
import direct.gui.OnscreenGeom
import direct.gui.OnscreenImage
import direct.gui.OnscreenText
import direct.interval.ActorInterval
import direct.interval.AnimControlInterval
import direct.interval.FunctionInterval
import direct.interval.IndirectInterval
import direct.interval.Interval
import direct.interval.IntervalGlobal
import direct.interval.IntervalManager
import direct.interval.IntervalTest
import direct.interval.LerpBlendHelpers
import direct.interval.LerpInterval
import direct.interval.MetaInterval
import direct.interval.MopathInterval
import direct.interval.ParticleInterval
import direct.interval.ProjectileInterval
import direct.interval.ProjectileIntervalTest
import direct.interval.SoundInterval
import direct.interval.TestInterval
import direct.motiontrail.MotionTrail
import direct.p3d.AppRunner
import direct.p3d.DWBPackageInstaller
import direct.p3d.DeploymentTools
import direct.p3d.FileSpec
import direct.p3d.HostInfo
import direct.p3d.InstalledHostData
import direct.p3d.InstalledPackageData
import direct.p3d.JavaScript
import direct.p3d.PackageInfo
import direct.p3d.PackageInstaller
import direct.p3d.PackageMerger
import direct.p3d.Packager
import direct.p3d.PatchMaker
import direct.p3d.ScanDirectoryNode
import direct.p3d.SeqValue
import direct.particles.ForceGroup
import direct.particles.GlobalForceGroup
import direct.particles.ParticleEffect
import direct.particles.ParticleFloorTest
import direct.particles.ParticleManagerGlobal
import direct.particles.ParticleTest
import direct.particles.Particles
import direct.particles.SpriteParticleRendererExt
import direct.physics.FallTest
import direct.physics.RotationTest
import direct.showbase.AppRunnerGlobal
import direct.showbase.Audio3DManager
import direct.showbase.BufferViewer
import direct.showbase.BulletinBoard
import direct.showbase.BulletinBoardGlobal
import direct.showbase.BulletinBoardWatcher
import direct.showbase.ContainerLeakDetector
import direct.showbase.ContainerReport
import direct.showbase.CountedResource
import direct.showbase.DirectObject
import direct.showbase.DistancePhasedNode
import direct.showbase.EventGroup
import direct.showbase.EventManager
import direct.showbase.EventManagerGlobal
import direct.showbase.ExceptionVarDump
import direct.showbase.Factory
import direct.showbase.Finder
import direct.showbase.GarbageReport
import direct.showbase.GarbageReportScheduler
import direct.showbase.InputStateGlobal
import direct.showbase.Job
import direct.showbase.JobManager
import direct.showbase.JobManagerGlobal
import direct.showbase.LeakDetectors
import direct.showbase.Loader
import direct.showbase.Messenger
import direct.showbase.MessengerGlobal
import direct.showbase.MessengerLeakDetector
import direct.showbase.MirrorDemo
import direct.showbase.ObjectPool
import direct.showbase.ObjectReport
import direct.showbase.OnScreenDebug
import direct.showbase.PhasedObject
import direct.showbase.PhysicsManagerGlobal
import direct.showbase.Pool
import direct.showbase.ProfileSession
import direct.showbase.PythonUtil
import direct.showbase.RandomNumGen
import direct.showbase.ReferrerSearch
import direct.showbase.SfxPlayer
import direct.showbase.ShadowDemo
import direct.showbase.ShadowPlacer
import direct.showbase.ShowBase
import direct.showbase.TaskThreaded
import direct.showbase.ThreeUpShow
import direct.showbase.Transitions
import direct.showbase.VFSImporter
import direct.showbase.WxGlobal
import direct.showutil.BuildGeometry
import direct.showutil.Effects
import direct.showutil.Rope
import direct.showutil.TexMemWatcher
import direct.showutil.TexViewer
import direct.stdpy.file
import direct.stdpy.glob
import direct.stdpy.pickle
import direct.stdpy.thread
import direct.stdpy.threading
import direct.stdpy.threading2
import direct.task.FrameProfiler
import direct.task.MiniTask
import direct.task.Task
import direct.task.TaskManagerGlobal
import direct.task.TaskProfiler
import direct.task.TaskTester
import direct.task.Timer
def test_imports_tk():
Pmw = pytest.importorskip('Pmw')
import direct.showbase.TkGlobal
import direct.tkpanels.AnimPanel
import direct.tkpanels.DirectSessionPanel
import direct.tkpanels.FSMInspector
import direct.tkpanels.Inspector
import direct.tkpanels.MopathRecorder
import direct.tkpanels.NotifyPanel
import direct.tkpanels.ParticlePanel
import direct.tkpanels.Placer
import direct.tkpanels.TaskManagerPanel
import direct.tkwidgets.AppShell
import direct.tkwidgets.Dial
import direct.tkwidgets.EntryScale
import direct.tkwidgets.Floater
import direct.tkwidgets.MemoryExplorer
import direct.tkwidgets.ProgressBar
import direct.tkwidgets.SceneGraphExplorer
import direct.tkwidgets.Slider
import direct.tkwidgets.Tree
import direct.tkwidgets.Valuator
import direct.tkwidgets.VectorWidgets
import direct.tkwidgets.WidgetPropertiesDialog
def test_imports_wx():
wx = pytest.importorskip('wx')
import direct.wxwidgets.ViewPort
import direct.wxwidgets.WxAppShell
import direct.wxwidgets.WxPandaShell
import direct.wxwidgets.WxPandaWindow
import direct.wxwidgets.WxSlider
import direct.leveleditor.ActionMgr
import direct.leveleditor.AnimControlUI
import direct.leveleditor.AnimGlobals
import direct.leveleditor.AnimMgr
import direct.leveleditor.AnimMgrBase
import direct.leveleditor.CurveAnimUI
import direct.leveleditor.CurveEditor
import direct.leveleditor.FileMgr
import direct.leveleditor.GraphEditorUI
import direct.leveleditor.HotKeyUI
import direct.leveleditor.LayerEditorUI
import direct.leveleditor.LevelEditor
import direct.leveleditor.LevelEditorBase
import direct.leveleditor.LevelEditorStart
import direct.leveleditor.LevelEditorUI
import direct.leveleditor.LevelEditorUIBase
import direct.leveleditor.LevelLoader
import direct.leveleditor.LevelLoaderBase
import direct.leveleditor.MayaConverter
import direct.leveleditor.ObjectGlobals
import direct.leveleditor.ObjectHandler
import direct.leveleditor.ObjectMgr
import direct.leveleditor.ObjectMgrBase
import direct.leveleditor.ObjectPalette
import direct.leveleditor.ObjectPaletteBase
import direct.leveleditor.ObjectPaletteUI
import direct.leveleditor.ObjectPropertyUI
import direct.leveleditor.PaletteTreeCtrl
import direct.leveleditor.ProtoObjs
import direct.leveleditor.ProtoObjsUI
import direct.leveleditor.ProtoPalette
import direct.leveleditor.ProtoPaletteBase
import direct.leveleditor.ProtoPaletteUI
import direct.leveleditor.SceneGraphUI
import direct.leveleditor.SceneGraphUIBase