Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2019-12-30 01:50:54 +01:00
commit b78b7be326
21 changed files with 241 additions and 59 deletions

View File

@ -185,16 +185,19 @@ from the Play Store. Many of the dependencies can be installed by running the
following command in the Termux shell:
```bash
pkg install python-dev termux-tools ndk-stl ndk-sysroot clang libvorbis-dev libopus-dev opusfile-dev openal-soft-dev freetype-dev harfbuzz-dev libpng-dev ecj4.6 dx patchelf aapt apksigner libcrypt-dev
pkg install python ndk-sysroot clang bison freetype harfbuzz libpng eigen openal-soft opusfile libvorbis assimp libopus ecj dx patchelf aapt apksigner libcrypt openssl pkg-config
```
Then, you can build and install the .apk right away using these commands:
Then, you can build the .apk using this command:
```bash
python makepanda/makepanda.py --everything --target android-21 --no-tiff --installer
xdg-open panda3d.apk
```
You can install the generated panda3d.apk by browsing to the panda3d folder
using a file manager. You may need to copy it to `/sdcard` to be able to
access it from other apps.
To launch a Python program from Termux, you can use the `run_python.sh` script
inside the `panda/src/android` directory. It will launch Python in a separate
activity, load it with the Python script you passed as argument, and use a

View File

@ -5,6 +5,7 @@ __all__ = ['Actor']
from panda3d.core import *
from panda3d.core import Loader as PandaLoader
from direct.showbase.DirectObject import DirectObject
from direct.showbase.Loader import Loader
from direct.directnotify import DirectNotifyGlobal
@ -1886,6 +1887,9 @@ class Actor(DirectObject, NodePath):
else:
loaderOptions.setFlags(loaderOptions.getFlags() | LoaderOptions.LFReportErrors)
# Ensure that custom Python loader hooks are initialized.
Loader._loadPythonFileTypes()
# Pass loaderOptions to specify that we want to
# get the skeleton model. This only matters to model
# files (like .mb) for which we can choose to extract

View File

@ -253,8 +253,9 @@ do_unpack_int64(const char *buffer) {
((uint64_t)(unsigned char)buffer[4] << 32) |
((uint64_t)(unsigned char)buffer[5] << 40) |
((uint64_t)(unsigned char)buffer[6] << 48) |
((int64_t)(signed char)buffer[7] << 54));
((int64_t)(signed char)buffer[7] << 56));
}
/**
*
*/
@ -295,10 +296,9 @@ do_unpack_uint64(const char *buffer) {
((uint64_t)(unsigned char)buffer[4] << 32) |
((uint64_t)(unsigned char)buffer[5] << 40) |
((uint64_t)(unsigned char)buffer[6] << 48) |
((int64_t)(signed char)buffer[7] << 54));
((uint64_t)(unsigned char)buffer[7] << 56));
}
/**
*
*/

View File

@ -16,7 +16,6 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
#include "vector_uchar.h"
class DCFile;
class DCField;

View File

@ -16,7 +16,6 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
#include "vector_uchar.h"
class DCFile;
class DCClass;

View File

@ -32,6 +32,7 @@
#include "pvector.h"
#include "pmap.h"
#include "pset.h"
#include "vector_uchar.h"
#else // WITHIN_PANDA
@ -81,6 +82,7 @@
#define nassertr_always(condition, return_value) assert(condition)
#define nassertv(condition) assert(condition)
#define nassertv_always(condition) assert(condition)
#define nassert_raise(message) {std::cerr << message << std::endl; abort();}
// Panda defines a special Filename class. We'll use an ordinary string
// instead.
@ -97,8 +99,10 @@ typedef std::string Filename;
#define pvector std::vector
#define pmap std::map
#define pset std::set
#define vector_uchar std::vector<unsigned char>
#include <stdint.h>
#include <string.h>
typedef std::ifstream pifstream;
typedef std::ofstream pofstream;

View File

@ -16,7 +16,6 @@
#include "dcbase.h"
#include "primeNumberGenerator.h"
#include "vector_uchar.h"
/**
* This class generates an arbitrary hash number from a sequence of ints.

View File

@ -22,6 +22,8 @@ class Loader(DirectObject):
notify = directNotify.newCategory("Loader")
loaderIndex = 0
_loadedPythonFileTypes = False
class Callback:
"""Returned by loadModel when used asynchronously. This class is
modelled after Future, and can be awaited."""
@ -149,8 +151,7 @@ class Loader(DirectObject):
Loader.loaderIndex += 1
self.accept(self.hook, self.__gotAsyncObject)
if ConfigVariableBool('loader-support-entry-points', True):
self._loadPythonFileTypes()
self._loadPythonFileTypes()
def destroy(self):
self.ignore(self.hook)
@ -158,7 +159,14 @@ class Loader(DirectObject):
del self.base
del self.loader
def _loadPythonFileTypes(self):
@classmethod
def _loadPythonFileTypes(cls):
if cls._loadedPythonFileTypes:
return
if not ConfigVariableBool('loader-support-entry-points', True):
return
import importlib
try:
pkg_resources = importlib.import_module('pkg_resources')
@ -171,6 +179,8 @@ class Loader(DirectObject):
for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'):
registry.register_deferred_type(entry_point)
cls._loadedPythonFileTypes = True
# model loading funcs
def loadModel(self, modelPath, loaderOptions = None, noCache = None,
allowInstance = False, okMissing = None,

View File

@ -87,7 +87,7 @@ class Thread(ThreadBase):
object. The wrapper is designed to emulate Python's own
threading.Thread object. """
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, daemon=None):
ThreadBase.__init__(self)
assert group is None
@ -99,7 +99,10 @@ class Thread(ThreadBase):
name = _newname()
current = current_thread()
self.__dict__['daemon'] = current.daemon
if daemon is not None:
self.__dict__['daemon'] = daemon
else:
self.__dict__['daemon'] = current.daemon
self.__dict__['name'] = name
def call_run():

View File

@ -14,6 +14,7 @@ module, and so it is therefore layered on top of Panda's thread
implementation. """
import sys as _sys
import atexit as _atexit
from direct.stdpy import thread as _thread
from direct.stdpy.thread import stack_size, _newname, _local as local
@ -395,8 +396,12 @@ class Thread(_Verbose):
# operation on/with a NoneType
__exc_info = _sys.exc_info
# Set to True when the _shutdown handler is registered as atexit function.
# Protected by _active_limbo_lock.
__registered_atexit = False
def __init__(self, group=None, target=None, name=None,
args=(), kwargs=None, verbose=None):
args=(), kwargs=None, verbose=None, daemon=None):
assert group is None, "group argument must be None for now"
_Verbose.__init__(self, verbose)
if kwargs is None:
@ -405,7 +410,10 @@ class Thread(_Verbose):
self.__name = str(name or _newname())
self.__args = args
self.__kwargs = kwargs
self.__daemonic = self._set_daemon()
if daemon is not None:
self.__daemonic = daemon
else:
self.__daemonic = self._set_daemon()
self.__started = False
self.__stopped = False
self.__block = Condition(Lock())
@ -436,6 +444,14 @@ class Thread(_Verbose):
self._note("%s.start(): starting thread", self)
_active_limbo_lock.acquire()
_limbo[self] = self
# If we are starting a non-daemon thread, we need to call join() on it
# when the interpreter exits. Python will call _shutdown() on the
# built-in threading module automatically, but not on our module.
if not self.__daemonic and not Thread.__registered_atexit:
_atexit.register(_shutdown)
Thread.__registered_atexit = True
_active_limbo_lock.release()
_start_new_thread(self.__bootstrap, ())
self.__started = True
@ -599,6 +615,9 @@ class Thread(_Verbose):
assert not self.__started, "cannot set daemon status of active thread"
self.__daemonic = daemonic
name = property(getName, setName)
daemon = property(isDaemon, setDaemon)
# The timer class was contributed by Itamar Shtull-Trauring
def Timer(*args, **kwargs):
@ -670,7 +689,7 @@ class _MainThread(Thread):
class _DummyThread(Thread):
def __init__(self):
Thread.__init__(self, name=_newname("Dummy-%d"))
Thread.__init__(self, name=_newname("Dummy-%d"), daemon=True)
# Thread.__block consumes an OS-level locking primitive, which
# can never be used by a _DummyThread. Since a _DummyThread

View File

@ -141,16 +141,13 @@ typedef long Py_hash_t;
#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg)
INLINE PyObject *_PyObject_CallNoArg(PyObject *func) {
static PyTupleObject empty_tuple = {PyVarObject_HEAD_INIT(nullptr, 0)};
#ifdef Py_TRACE_REFS
_Py_AddToAllObjects((PyObject *)&empty_tuple, 0);
#endif
return PyObject_Call(func, (PyObject *)&empty_tuple, nullptr);
static PyObject *empty_tuple = PyTuple_New(0);
return PyObject_Call(func, empty_tuple, nullptr);
}
# define _PyObject_CallNoArg _PyObject_CallNoArg
#endif
#ifndef _PyObject_FastCall
#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_FastCall)
INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs) {
PyObject *tuple = PyTuple_New(nargs);
for (Py_ssize_t i = 0; i < nargs; ++i) {

View File

@ -944,11 +944,12 @@ if (COMPILER=="GCC"):
for pkg in MAYAVERSIONS:
if (PkgSkip(pkg)==0 and (pkg in SDK)):
if GetTarget() == 'darwin':
LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/Maya.app/Contents/MacOS")
LibName(pkg, "-Wl,-rpath,/Applications/Autodesk/" + pkg.lower() + "/Maya.app/Contents/MacOS")
else:
LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/lib")
LibName(pkg, "-lOpenMaya")
LibName(pkg, "-lOpenMayaAnim")
LibName(pkg, "-lOpenMayaUI")
LibName(pkg, "-lAnimSlice")
LibName(pkg, "-lDeformSlice")
LibName(pkg, "-lModifiers")
@ -967,7 +968,8 @@ if (COMPILER=="GCC"):
LibName(pkg, "-lDependEngine")
LibName(pkg, "-lCommandEngine")
LibName(pkg, "-lFoundation")
LibName(pkg, "-lIMFbase")
if pkg != "MAYA2020":
LibName(pkg, "-lIMFbase")
if GetTarget() != 'darwin':
LibName(pkg, "-lOpenMayalib")
else:
@ -2612,7 +2614,13 @@ if not PkgSkip("PYTHON"):
ConditionalWriteFile(GetOutputDir() + '/panda3d/__init__.py', p3d_init)
# Also add this file, for backward compatibility.
ConditionalWriteFile(GetOutputDir() + '/panda3d/dtoolconfig.py', """
ConditionalWriteFile(GetOutputDir() + '/panda3d/dtoolconfig.py', """\
'''Alias of :mod:`panda3d.interrogatedb`.
.. deprecated:: 1.10.0
This module has been renamed to :mod:`panda3d.interrogatedb`.
'''
if __debug__:
print("Warning: panda3d.dtoolconfig is deprecated, use panda3d.interrogatedb instead.")
from .interrogatedb import *

View File

@ -106,6 +106,7 @@ MAYAVERSIONINFO = [("MAYA6", "6.0"),
("MAYA2017","2017"),
("MAYA2018","2018"),
("MAYA2019","2019"),
("MAYA2020","2020"),
]
MAXVERSIONINFO = [("MAX6", "SOFTWARE\\Autodesk\\3DSMAX\\6.0", "installdir", "maxsdk\\cssdk\\include"),
@ -2803,7 +2804,7 @@ def SetupVisualStudioEnviron():
elif not win_kit.endswith('\\'):
win_kit += '\\'
for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763:
for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763, 18362:
version = "10.0.{0}.0".format(vnum)
if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"):
print("Using Universal CRT %s" % (version))

View File

@ -701,10 +701,15 @@ if __debug__:
# Put the .exe files inside the panda3d-tools directory.
whl.write_file('panda3d_tools/' + file, source_path)
if basename.endswith('_bin'):
# These tools won't be invoked by the user directly.
continue
# Tell pip to create a wrapper script.
funcname = basename.replace('-', '_')
entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
entry_points += '[distutils.commands]\n'
entry_points += 'build_apps = direct.dist.commands:build_apps\n'
entry_points += 'bdist_apps = direct.dist.commands:bdist_apps\n'

View File

@ -45,6 +45,10 @@
TypeHandle CocoaGraphicsWindow::_type_handle;
#ifndef MAC_OS_X_VERSION_10_15
#define NSAppKitVersionNumber10_14 1671
#endif
/**
*
*/
@ -1095,7 +1099,28 @@ set_properties_now(WindowProperties &properties) {
*/
CGDisplayModeRef CocoaGraphicsWindow::
find_display_mode(int width, int height) {
CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL);
CFDictionaryRef options = NULL;
// On macOS 10.15+ (Catalina), we want to select the display mode with the
// samescaling factor as the current view to avoid cropping or scaling issues.
// This is a workaround until HiDPI display or scaling factor is properly
// handled. CGDisplayCopyAllDisplayModes() does not return upscaled display
// mode unless explicitly asked with kCGDisplayShowDuplicateLowResolutionModes
// (which is undocumented...).
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14) {
const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
const CFBooleanRef dictvalues[] = {kCFBooleanTrue};
options = CFDictionaryCreate(NULL,
(const void **)dictkeys,
(const void **)dictvalues,
1,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
#endif
CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, options);
CFRelease(options);
size_t num_modes = CFArrayGetCount(modes);
CGDisplayModeRef mode;
@ -1104,14 +1129,22 @@ find_display_mode(int width, int height) {
int refresh_rate;
mode = CGDisplayCopyDisplayMode(_display);
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080
// First check if the current mode is adequate.
if (CGDisplayModeGetWidth(mode) == width &&
CGDisplayModeGetHeight(mode) == height) {
return mode;
}
#endif
current_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode);
refresh_rate = CGDisplayModeGetRefreshRate(mode);
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
// Calculate the pixel width and height of the fullscreen mode we want using
// the currentdisplay mode dimensions and pixel dimensions.
size_t expected_pixel_width = (size_t(width) * CGDisplayModeGetPixelWidth(mode)) / CGDisplayModeGetWidth(mode);
size_t expected_pixel_height = (size_t(height) * CGDisplayModeGetPixelHeight(mode)) / CGDisplayModeGetHeight(mode);
#endif
CGDisplayModeRelease(mode);
for (size_t i = 0; i < num_modes; ++i) {
@ -1119,9 +1152,17 @@ find_display_mode(int width, int height) {
CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(mode);
// As explained above, we want to select the fullscreen display mode using
// the same scaling factor, but only for MacOS 10.15+ To do this we check
// the mode width and heightbut also actual pixel widh and height.
if (CGDisplayModeGetWidth(mode) == width &&
CGDisplayModeGetHeight(mode) == height &&
CGDisplayModeGetRefreshRate(mode) == refresh_rate &&
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
(floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14 ||
(CGDisplayModeGetPixelWidth(mode) == expected_pixel_width &&
CGDisplayModeGetPixelHeight(mode) == expected_pixel_height)) &&
#endif
CFStringCompare(pixel_encoding, current_pixel_encoding, 0) == kCFCompareEqualTo) {
CFRetain(mode);

View File

@ -496,6 +496,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
}
#endif
dvbc->update_data_size_bytes(num_bytes);
return dvbc;
} else {
dxgsg9_cat.error()
@ -533,14 +534,42 @@ apply_vertex_buffer(VertexBufferContext *vbc,
return false;
}
PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread());
#if 0
if (dvbc->changed_size(reader)) {
// We have to destroy the old vertex buffer and create a new one.
dvbc->create_vbuffer(*_screen, reader);
// Destroy and recreate the buffer.
if (dvbc->_vbuffer != nullptr) {
dvbc->_vbuffer->Release();
dvbc->_vbuffer = nullptr;
}
DWORD usage;
D3DPOOL pool;
if (_screen->_managed_vertex_buffers) {
pool = D3DPOOL_MANAGED;
usage = D3DUSAGE_WRITEONLY;
} else {
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
}
PStatTimer timer(_create_vertex_buffer_pcollector, Thread::get_current_thread());
HRESULT hr;
int attempts = 0;
do {
hr = _screen->_d3d_device->CreateVertexBuffer(num_bytes, usage, dvbc->_fvf, pool, &dvbc->_vbuffer, nullptr);
attempts++;
} while (check_dx_allocation(hr, num_bytes, attempts));
if (FAILED(hr)) {
dvbc->_vbuffer = nullptr;
dxgsg9_cat.error()
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
return false;
}
}
#endif
PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread());
HRESULT hr;
BYTE *local_pointer;
@ -5240,6 +5269,7 @@ calc_fb_properties(DWORD cformat, DWORD dformat,
#define GAMMA_1 (255.0 * 256.0)
static bool _gamma_table_initialized = false;
static bool _gamma_changed = false;
static unsigned short _original_gamma_table [256 * 3];
void _create_gamma_table_dx9 (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
@ -5337,6 +5367,7 @@ static_set_gamma(bool restore, PN_stdfloat gamma) {
if (SetDeviceGammaRamp (hdc, ramp)) {
set = true;
_gamma_changed = !restore;
}
ReleaseDC (nullptr, hdc);
@ -5374,7 +5405,9 @@ restore_gamma() {
void DXGraphicsStateGuardian9::
atexit_function(void) {
set_cg_device(nullptr);
static_set_gamma(true, 1.0f);
if (_gamma_changed) {
static_set_gamma(true, 1.0f);
}
}
/**

View File

@ -2523,6 +2523,20 @@ reset() {
}
#endif
#if defined(OPENGLES) && !defined(OPENGLES_1)
if (is_at_least_gles_version(3, 0)) {
_glReadBuffer = (PFNGLREADBUFFERPROC)
get_extension_func("glReadBuffer");
} else if (has_extension("GL_NV_read_buffer")) {
_glReadBuffer = (PFNGLREADBUFFERPROC)
get_extension_func("glReadBufferNV");
} else {
_glReadBuffer = nullptr;
}
#endif
#ifndef OPENGLES_1
_max_color_targets = 1;
if (_glDrawBuffers != nullptr) {
@ -9060,7 +9074,7 @@ set_draw_buffer(int rbtype) {
*/
void CLP(GraphicsStateGuardian)::
set_read_buffer(int rbtype) {
#ifndef OPENGLES // Draw buffers not supported by OpenGL ES. (TODO!)
#ifndef OPENGLES_1 // Draw buffers not supported by OpenGL ES 1.
if (rbtype & (RenderBuffer::T_depth | RenderBuffer::T_stencil)) {
// Special case: don't have to call ReadBuffer for these.
return;
@ -9093,10 +9107,14 @@ set_read_buffer(int rbtype) {
}
++index;
}
#ifdef OPENGLES
_glReadBuffer(buffer);
#else
glReadBuffer(buffer);
#endif
} else {
#ifndef OPENGLES
switch (rbtype & RenderBuffer::T_color) {
case RenderBuffer::T_front:
glReadBuffer(GL_FRONT);
@ -9133,10 +9151,11 @@ set_read_buffer(int rbtype) {
default:
break;
}
#endif // OPENGLES
}
report_my_gl_errors();
#endif // OPENGLES
#endif // OPENGLES_1
}
/**

View File

@ -92,6 +92,7 @@ typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
typedef void (APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
@ -939,6 +940,10 @@ public:
PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer;
PFNGLDRAWBUFFERSPROC _glDrawBuffers;
#if defined(OPENGLES) && !defined(OPENGLES_1)
PFNGLREADBUFFERPROC _glReadBuffer;
#endif
#ifndef OPENGLES_1
PFNGLCLEARBUFFERFVPROC _glClearBufferfv;
PFNGLCLEARBUFFERIVPROC _glClearBufferiv;

View File

@ -371,13 +371,13 @@ find_fullscreen_crtc(const LPoint2i &point,
for (int i = 0; i < res->ncrtc; ++i) {
RRCrtc crtc = res->crtcs[i];
if (auto info = get_crtc_info(res.get(), crtc)) {
if (point[0] >= info->x && point[0] < info->x + info->width &&
point[1] >= info->y && point[1] < info->y + info->height) {
if (point[0] >= info->x && point[0] < info->x + (int)info->width &&
point[1] >= info->y && point[1] < info->y + (int)info->height) {
x = info->x;
y = info->y;
width = info->width;
height = info->height;
width = (int)info->width;
height = (int)info->height;
return crtc;
}
}

View File

@ -107,6 +107,7 @@ struct MayaVerInfo maya_versions[] = {
{ "MAYA2017", "2017"},
{ "MAYA2018", "2018"},
{ "MAYA2019", "2019"},
{ "MAYA2020", "2020"},
{ 0, 0 },
};
@ -194,26 +195,22 @@ int
main(int argc, char *argv[]) {
// First, get the command line and append _bin, so we will actually run
// maya2egg_bin.exe, egg2maya_bin.exe, etc.
Filename command = Filename::from_os_specific(argv[0]);
if (!command.is_fully_qualified()) {
DSearchPath path;
path.append_path(ExecutionEnvironment::get_environment_variable("PATH"));
#ifdef _WIN32
command.set_extension("exe");
#endif
command.resolve_filename(path);
Filename command = ExecutionEnvironment::get_binary_name();
if (command.empty() || command == "unknown" || !command.exists()) {
command = Filename::from_os_specific(argv[0]);
if (!command.is_fully_qualified()) {
DSearchPath path;
path.append_path(ExecutionEnvironment::get_environment_variable("PATH"));
#ifdef _WIN32
command.set_extension("exe");
#endif
command.resolve_filename(path);
}
}
#ifdef _WIN32
if (command.get_extension() == "exe") {
command.set_extension("");
}
#endif
command = command.get_fullpath() + string("_bin");
#ifdef _WIN32
command.set_extension("exe");
#endif
command.set_basename_wo_extension(command.get_basename_wo_extension() + "_bin");
string os_command = command.to_os_specific();
// First start with $PANDA_MAYA_LOCATION. If it is set, it overrides

View File

@ -0,0 +1,36 @@
import pytest
direct = pytest.importorskip("panda3d.direct")
def test_pack_int8():
for num in range(-128, 128):
packer = direct.DCPacker()
packer.raw_pack_int8(num)
packer.set_unpack_data(packer.get_bytes())
assert packer.raw_unpack_int8() == num
def test_pack_uint8():
for num in range(256):
packer = direct.DCPacker()
packer.raw_pack_uint8(num)
packer.set_unpack_data(packer.get_bytes())
assert packer.raw_unpack_uint8() == num
def test_pack_int64():
for num in (0, -1, 0x7fffffff, -0x80000000, 0x7fffffffffffffff, 0x7ffffffffffffffe, -0x8000000000000000, -0x7fffffffffffffff):
packer = direct.DCPacker()
packer.raw_pack_int64(num)
packer.set_unpack_data(packer.get_bytes())
assert packer.raw_unpack_int64() == num
def test_pack_uint64():
for num in (0, 1, 0x7fffffff, 0xffffffff, 0x7fffffffffffffff, 0xfffffffffffffffe, 0xffffffffffffffff):
packer = direct.DCPacker()
packer.raw_pack_uint64(num)
packer.set_unpack_data(packer.get_bytes())
assert packer.raw_unpack_uint64() == num