Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2019-03-04 16:57:52 +01:00
commit cbb3c182a5
16 changed files with 248 additions and 120 deletions

View File

@ -22,7 +22,7 @@ Installing Panda3D
==================
The latest Panda3D SDK can be downloaded from
[this page](https://www.panda3d.org/download/sdk-1-10-0/).
[this page](https://www.panda3d.org/download/sdk-1-10-1/).
If you are familiar with installing Python packages, you can use
the following comand:

View File

@ -100,8 +100,10 @@ class DirectScrolledFrame(DirectFrame):
simpleChildGui = self.guiDict.get(parts[-1])
if simpleChildGui:
simpleChildGui.destroy()
self.verticalScroll.destroy()
self.horizontalScroll.destroy()
del self.verticalScroll
del self.horizontalScroll
if self.verticalScroll:
self.verticalScroll.destroy()
if self.horizontalScroll:
self.horizontalScroll.destroy()
self.verticalScroll = None
self.horizontalScroll = None
DirectFrame.destroy(self)

View File

@ -96,22 +96,21 @@ class ParticlePanel(AppShell):
## MENUBAR ENTRIES ##
# FILE MENU
# Get a handle on the file menu so commands can be inserted
# before quit item
fileMenu = self.menuBar.component('File-menu')
# MRM: Need to add load and save effects methods
fileMenu.insert_command(
fileMenu.index('Quit'),
label = 'Load Params',
command = self.loadParticleEffectFromFile)
fileMenu.insert_command(
fileMenu.index('Quit'),
label = 'Save Params',
command = self.saveParticleEffectToFile)
fileMenu.insert_command(
fileMenu.index('Quit'),
label = 'Print Params',
command = lambda s = self: s.particles.printParams())
# Get a handle on the file menu, and delete the Quit item that AppShell
# created so we can add it back after adding the other items.
self.menuBar.deletemenuitems('File', 0, 0)
self.menuBar.addmenuitem('File', 'command',
label='Load Params',
command=self.loadParticleEffectFromFile)
self.menuBar.addmenuitem('File', 'command',
label='Save Params',
command=self.saveParticleEffectToFile)
self.menuBar.addmenuitem('File', 'command',
label='Print Params',
command=lambda s=self:s.particles.printParams())
self.menuBar.addmenuitem('File', 'command', 'Quit this application',
label='Quit',
command=self.quit)
# PARTICLE MANAGER MENU
self.menuBar.addmenu('ParticleMgr', 'ParticleMgr Operations')

View File

@ -397,17 +397,25 @@ get_call_str(const string &container, const vector_string &pexprs) const {
}
// It's not possible to assign arrays in C++, we have to copy them.
CPPArrayType *array_type = _parameters[_first_true_parameter]._remap->get_orig_type()->as_array_type();
bool paren_close = false;
CPPType *param_type = _parameters[_first_true_parameter]._remap->get_orig_type();
CPPArrayType *array_type = param_type->as_array_type();
if (array_type != nullptr) {
call << "std::copy(" << expr << ", " << expr << " + " << *array_type->_bounds << ", ";
} else {
paren_close = true;
}
else if (TypeManager::is_pointer_to_PyObject(param_type)) {
call << "Dtool_Assign_PyObject(" << expr << ", ";
paren_close = true;
}
else {
call << expr << " = ";
}
_parameters[_first_true_parameter]._remap->pass_parameter(call,
get_parameter_expr(_first_true_parameter, pexprs));
if (array_type != nullptr) {
if (paren_close) {
call << ')';
}
@ -772,6 +780,11 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
_return_value_destructor = builder.get_destructor_for(return_meat_type);
}
if (_type == T_getter && TypeManager::is_pointer_to_PyObject(return_type)) {
_manage_reference_count = true;
_return_value_needs_management = true;
}
// Check for a special meaning by name and signature.
size_t first_param = 0;
if (_has_this) {

View File

@ -1690,7 +1690,6 @@ write_module_class(ostream &out, Object *obj) {
SlottedFunctionDef def;
def._answer_location = true_key;
def._wrapper_type = slotted_def._wrapper_type;
def._min_version = 0x03000000;
def._wrapper_name = func->_name + "_" + true_key;
slots[true_key] = def;
}
@ -5993,7 +5992,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
indent(out, indent_level) << "}\n";
}
return_expr = manage_return_value(out, indent_level, remap, "return_value");
if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) {
indent(out, indent_level) << "Py_XINCREF(return_value);\n";
} else {
return_expr = manage_return_value(out, indent_level, remap, "return_value");
}
return_expr = remap->_return_type->temporary_to_return(return_expr);
}

View File

@ -90,6 +90,19 @@ INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, i
Py_RETURN_RICHCOMPARE(cmpval, 0, op);
}
/**
* Utility function for assigning a PyObject pointer while managing refcounts.
*/
ALWAYS_INLINE void
Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value) {
PyObject *prev_value = ptr;
if (prev_value != value) {
Py_XINCREF(value);
ptr = value;
Py_XDECREF(prev_value);
}
}
/**
* Converts the enum value to a C long.
*/

View File

@ -238,6 +238,8 @@ EXPCL_PYPANDA PyObject *_Dtool_Return(PyObject *value);
#define Dtool_Return(value) _Dtool_Return(value)
#endif
ALWAYS_INLINE void Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value);
/**
* Wrapper around Python 3.4's enum library, which does not have a C API.
*/

View File

@ -157,7 +157,7 @@ def usage(problem):
print(" --everything (enable every third-party lib)")
print(" --directx-sdk=X (specify version of DirectX SDK to use: jun2010, aug2009, mar2009, aug2006)")
print(" --windows-sdk=X (specify Windows SDK version, eg. 7.0, 7.1 or 10. Default is 7.1)")
print(" --msvc-version=X (specify Visual C++ version, eg. 10, 11, 12, 14. Default is 14)")
print(" --msvc-version=X (specify Visual C++ version, eg. 10, 11, 12, 14, 14.1, 14.2. Default is 14)")
print(" --use-icl (experimental setting to use an intel compiler instead of MSVC on Windows)")
print("")
print("The simplest way to compile panda is to just type:")

View File

@ -78,6 +78,7 @@ MSVCVERSIONINFO = {
(12,0): {"vsversion":(12,0), "vsname":"Visual Studio 2013"},
(14,0): {"vsversion":(14,0), "vsname":"Visual Studio 2015"},
(14,1): {"vsversion":(15,0), "vsname":"Visual Studio 2017"},
(14,2): {"vsversion":(16,0), "vsname":"Visual Studio 2019"},
}
########################################################################

View File

@ -120,7 +120,7 @@ do_set_mass(PN_stdfloat mass) {
btScalar bt_mass = mass;
btVector3 bt_inertia(0.0, 0.0, 0.0);
if (bt_mass > 0.0) {
if (bt_mass > 0.0 && !_shapes.empty()) {
_rigid->getCollisionShape()->calculateLocalInertia(bt_mass, bt_inertia);
}

View File

@ -43,7 +43,7 @@ class BulletPersistentManifold;
class BulletShape;
class BulletSoftBodyWorldInfo;
extern PT(CallbackObject) bullet_contact_added_callback;
extern EXPCL_PANDABULLET PT(CallbackObject) bullet_contact_added_callback;
/**
*

View File

@ -711,8 +711,11 @@ close_window() {
}
if (_window != nil) {
[_window setReleasedWhenClosed: YES];
[_window close];
// Process events once more so any pending NSEvents are cleared. Not doing
// this causes the window to stick around after calling [_window close].
process_events();
_window = nil;
}

View File

@ -34,7 +34,6 @@ class CocoaGraphicsWindow;
- (void)windowDidBecomeKey:(NSNotification *)notification;
- (void)windowDidResignKey:(NSNotification *)notification;
- (BOOL)windowShouldClose:(id)sender;
- (void)windowWillClose:(NSNotification *)notification;
// TODO: handle fullscreen on Lion.

View File

@ -50,11 +50,11 @@
}
- (BOOL) windowShouldClose:(id)sender {
return _graphicsWindow->handle_close_request();
}
- (void) windowWillClose:(NSNotification *)notification {
_graphicsWindow->handle_close_event();
bool should_close = _graphicsWindow->handle_close_request();
if (should_close) {
_graphicsWindow->handle_close_event();
}
return should_close;
}
@end

View File

@ -17,6 +17,22 @@
#if defined(_WIN32) && !defined(CPPPARSER)
#ifdef HAVE_THREADS
/**
*
*/
class InputThread : public Thread {
public:
InputThread(WinInputDeviceManager *manager) :
Thread("input", "input"), _manager(manager) {}
private:
virtual void thread_main();
WinInputDeviceManager *_manager;
};
#endif
/**
* Initializes the input device manager by scanning which devices are currently
* connected and setting up any platform-dependent structures necessary for
@ -37,7 +53,7 @@ WinInputDeviceManager() :
_xinput_device2.local_object();
_xinput_device3.local_object();
// This function is only available in Vista and later, so we use a wrapper.
// This function is only available in Vista and later, so we use a wrapper.
HMODULE module = LoadLibraryA("cfgmgr32.dll");
if (module) {
_CM_Get_DevNode_PropertyW = (pCM_Get_DevNode_Property)GetProcAddress(module, "CM_Get_DevNode_PropertyW");
@ -45,83 +61,16 @@ WinInputDeviceManager() :
_CM_Get_DevNode_PropertyW = nullptr;
}
// Now create a message-only window for the raw input.
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = window_proc;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "InputDeviceManager";
if (!RegisterClassEx(&wc)) {
device_cat.warning()
<< "Failed to register message-only window class.\n";
return;
}
_message_hwnd = CreateWindowEx(0, wc.lpszClassName, "InputDeviceManager", 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
if (!_message_hwnd) {
device_cat.warning()
<< "Failed to create message-only window.\n";
return;
}
// Now listen for raw input devices using the created message loop.
RAWINPUTDEVICE rid[3];
rid[0].usUsagePage = 1;
rid[0].usUsage = 4; // Joysticks
rid[0].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
rid[0].hwndTarget = _message_hwnd;
rid[1].usUsagePage = 1;
rid[1].usUsage = 5; // Gamepads
rid[1].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
rid[1].hwndTarget = _message_hwnd;
rid[2].usUsagePage = 1;
rid[2].usUsage = 8; // Multi-axis controllers (including 3D mice)
rid[2].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
rid[2].hwndTarget = _message_hwnd;
if (!RegisterRawInputDevices(rid, 3, sizeof(RAWINPUTDEVICE))) {
device_cat.warning()
<< "Failed to register raw input devices.\n";
}
// Do we have any XInput devices plugged in now?
int num_xinput = 0;
HANDLE xinput_handle;
RAWINPUTDEVICELIST devices[64];
UINT num_devices = 64;
num_devices = GetRawInputDeviceList(devices, &num_devices, sizeof(RAWINPUTDEVICELIST));
if (num_devices == (UINT)-1) {
return;
}
for (UINT i = 0; i < num_devices; ++i) {
if (devices[i].dwType != RIM_TYPEHID) {
continue;
}
HANDLE handle = devices[i].hDevice;
UINT size;
if (GetRawInputDeviceInfoA(handle, RIDI_DEVICENAME, nullptr, &size) != 0) {
continue;
}
char *path = (char *)alloca(size);
if (path == nullptr ||
GetRawInputDeviceInfoA(handle, RIDI_DEVICENAME, (void *)path, &size) < 0) {
continue;
}
if (strstr(path, "&IG_") != nullptr) {
xinput_handle = handle;
++num_xinput;
}
}
if (num_xinput == 1) {
// There's only one XInput device, so we know which one it is.
on_input_device_arrival(xinput_handle);
} else if (num_xinput > 0) {
// Just poll all the XInput devices.
_xinput_device0.detect(this);
_xinput_device1.detect(this);
_xinput_device2.detect(this);
_xinput_device3.detect(this);
// If we have threading enabled, start a thread with a message-only window
// loop to listen for input events.
#ifdef HAVE_THREADS
if (Thread::is_threading_supported()) {
PT(Thread) thread = new InputThread(this);
thread->start(TP_normal, false);
} else
#endif
{
setup_message_loop();
}
}
@ -131,8 +80,17 @@ WinInputDeviceManager() :
WinInputDeviceManager::
~WinInputDeviceManager() {
if (_message_hwnd != nullptr) {
DestroyWindow(_message_hwnd);
_message_hwnd = nullptr;
#ifdef HAVE_THREADS
if (Thread::is_threading_supported()) {
HWND hwnd = _message_hwnd;
if (hwnd) {
SendMessage(hwnd, WM_QUIT, 0, 0);
}
} else
#endif
{
destroy_message_loop();
}
}
}
@ -397,10 +355,110 @@ on_input_device_removal(HANDLE handle) {
*/
void WinInputDeviceManager::
update() {
MSG msg;
while (PeekMessage(&msg, _message_hwnd, WM_INPUT_DEVICE_CHANGE, WM_INPUT, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/**
* Sets up a Windows message loop. Should be called from the thread that will
* be handling the messages.
*/
HWND WinInputDeviceManager::
setup_message_loop() {
_message_hwnd = 0;
// Now create a message-only window for the raw input.
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = window_proc;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "InputDeviceManager";
if (!RegisterClassEx(&wc)) {
device_cat.warning()
<< "Failed to register message-only window class for input device detection.\n";
} else {
_message_hwnd = CreateWindowEx(0, wc.lpszClassName, "InputDeviceManager", 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
if (!_message_hwnd) {
device_cat.warning()
<< "Failed to create message-only window for input device detection.\n";
}
}
// Now listen for raw input devices using the created message loop.
RAWINPUTDEVICE rid[3];
rid[0].usUsagePage = 1;
rid[0].usUsage = 4; // Joysticks
rid[0].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
rid[0].hwndTarget = _message_hwnd;
rid[1].usUsagePage = 1;
rid[1].usUsage = 5; // Gamepads
rid[1].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
rid[1].hwndTarget = _message_hwnd;
rid[2].usUsagePage = 1;
rid[2].usUsage = 8; // Multi-axis controllers (including 3D mice)
rid[2].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
rid[2].hwndTarget = _message_hwnd;
if (!RegisterRawInputDevices(rid, 3, sizeof(RAWINPUTDEVICE))) {
device_cat.warning()
<< "Failed to register raw input devices.\n";
}
// Do we have any XInput devices plugged in now?
int num_xinput = 0;
HANDLE xinput_handle;
RAWINPUTDEVICELIST devices[64];
UINT num_devices = 64;
num_devices = GetRawInputDeviceList(devices, &num_devices, sizeof(RAWINPUTDEVICELIST));
if (num_devices == (UINT)-1) {
num_devices = 0;
}
for (UINT i = 0; i < num_devices; ++i) {
if (devices[i].dwType != RIM_TYPEHID) {
continue;
}
HANDLE handle = devices[i].hDevice;
UINT size;
if (GetRawInputDeviceInfoA(handle, RIDI_DEVICENAME, nullptr, &size) != 0) {
continue;
}
char *path = (char *)alloca(size);
if (path == nullptr ||
GetRawInputDeviceInfoA(handle, RIDI_DEVICENAME, (void *)path, &size) < 0) {
continue;
}
if (strstr(path, "&IG_") != nullptr) {
xinput_handle = handle;
++num_xinput;
}
}
if (num_xinput == 1) {
// There's only one XInput device, so we know which one it is.
on_input_device_arrival(xinput_handle);
} else if (num_xinput > 0) {
// Just poll all the XInput devices.
_xinput_device0.detect(this);
_xinput_device1.detect(this);
_xinput_device2.detect(this);
_xinput_device3.detect(this);
}
return _message_hwnd;
}
/**
* Tears down the message loop. Should be called from the thread that called
* setup_message_loop().
*/
void WinInputDeviceManager::
destroy_message_loop() {
HWND hwnd = nullptr;
{
LightMutexHolder holder(_lock);
std::swap(_message_hwnd, hwnd);
}
if (hwnd) {
DestroyWindow(hwnd);
}
}
@ -442,4 +500,36 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
return DefWindowProcW(hwnd, msg, wparam, lparam);
}
#ifdef HAVE_THREADS
/**
* Thread entry point for the input listener thread.
*/
void InputThread::
thread_main() {
WinInputDeviceManager *manager = _manager;
HWND hwnd = manager->setup_message_loop();
if (!hwnd) {
return;
}
if (device_cat.is_debug()) {
device_cat.debug()
<< "Started input device listener thread.\n";
}
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (device_cat.is_debug()) {
device_cat.debug()
<< "Stopping input device listener thread.\n";
}
manager->destroy_message_loop();
}
#endif // HAVE_THREADS
#endif

View File

@ -41,6 +41,9 @@ public:
void on_input_device_arrival(HANDLE handle);
void on_input_device_removal(HANDLE handle);
HWND setup_message_loop();
void destroy_message_loop();
private:
// There are always exactly four of these in existence.
XInputDevice _xinput_device0;