diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 948891d19d..e5d9ac4f72 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -13,6 +13,7 @@ import stat import struct import imp import string +import time import setuptools import distutils.log @@ -30,6 +31,15 @@ if sys.version_info < (3, 0): # Python 3 defines these subtypes of IOError, but Python 2 doesn't. FileNotFoundError = IOError + # Warn the user. They might be using Python 2 by accident. + print("=================================================================") + print("WARNING: You are using Python 2, which will soon be discontinued.") + print("WARNING: Please use Python 3 for best results and continued") + print("WARNING: support after the EOL date of December 31st, 2019.") + print("=================================================================") + sys.stdout.flush() + time.sleep(4.0) + def _parse_list(input): if isinstance(input, basestring): @@ -229,7 +239,9 @@ class build_apps(setuptools.Command): self.requirements_path = os.path.join(os.getcwd(), 'requirements.txt') self.use_optimized_wheels = True self.optimized_wheel_index = '' - self.pypi_extra_indexes = [] + self.pypi_extra_indexes = [ + 'https://archive.panda3d.org/thirdparty', + ] self.file_handlers = {} self.exclude_dependencies = [ # Windows diff --git a/direct/src/filter/FilterManager.py b/direct/src/filter/FilterManager.py index 4150cba568..5696ac9460 100644 --- a/direct/src/filter/FilterManager.py +++ b/direct/src/filter/FilterManager.py @@ -124,7 +124,7 @@ class FilterManager(DirectObject): return winx,winy - def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None): + def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None, fbprops=None): """ Causes the scene to be rendered into the supplied textures instead of into the original window. Puts a fullscreen quad @@ -185,7 +185,10 @@ class FilterManager(DirectObject): # Choose the size of the offscreen buffer. (winx, winy) = self.getScaledSize(1,1,1) - buffer = self.createBuffer("filter-base", winx, winy, texgroup) + if fbprops is not None: + buffer = self.createBuffer("filter-base", winx, winy, texgroup, fbprops=fbprops) + else: + buffer = self.createBuffer("filter-base", winx, winy, texgroup) if (buffer == None): return None @@ -287,7 +290,7 @@ class FilterManager(DirectObject): return quad - def createBuffer(self, name, xsize, ysize, texgroup, depthbits=1): + def createBuffer(self, name, xsize, ysize, texgroup, depthbits=1, fbprops=None): """ Low-level buffer creation. Not intended for public use. """ winprops = WindowProperties() @@ -297,6 +300,9 @@ class FilterManager(DirectObject): props.setRgbColor(1) props.setDepthBits(depthbits) props.setStereo(self.win.isStereo()) + if fbprops is not None: + props.addProperties(fbprops) + depthtex, colortex, auxtex0, auxtex1 = texgroup if (auxtex0 != None): props.setAuxRgba(1) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 2d32d2b338..041c2fc40a 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -1677,13 +1677,17 @@ class ShowBase(DirectObject.DirectObject): return self.mouseWatcherNode.getModifierButtons().isDown( KeyboardButton.meta()) - def attachInputDevice(self, device, prefix=None): + def attachInputDevice(self, device, prefix=None, gui=False): """ This function attaches an input device to the data graph, which will cause the device to be polled and generate events. If a prefix is given and not None, it is used to prefix events generated by this device, separated by a hyphen. + The gui argument can be set to True (as of Panda3D 1.10.3) to set up + the default MouseWatcher to receive inputs from this device, allowing + it to control user interfaces. + If you call this, you should consider calling detachInputDevice when you are done with the device or when it is disconnected. """ @@ -1694,13 +1698,17 @@ class ShowBase(DirectObject.DirectObject): idn = self.dataRoot.attachNewNode(InputDeviceNode(device, device.name)) # Setup the button thrower to generate events for the device. - bt = idn.attachNewNode(ButtonThrower(device.name)) - if prefix is not None: - bt.node().setPrefix(prefix + '-') + if prefix is not None or not gui: + bt = idn.attachNewNode(ButtonThrower(device.name)) + if prefix is not None: + bt.node().setPrefix(prefix + '-') + self.deviceButtonThrowers.append(bt) assert self.notify.debug("Attached input device {0} with prefix {1}".format(device, prefix)) self.__inputDeviceNodes[device] = idn - self.deviceButtonThrowers.append(bt) + + if gui: + idn.node().addChild(self.mouseWatcherNode) def detachInputDevice(self, device): """ diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 6151a2c00d..3ad8e01428 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -597,8 +597,31 @@ reset() { query_glsl_version(); #ifndef OPENGLES - bool core_profile = is_at_least_gl_version(3, 2) && - !has_extension("GL_ARB_compatibility"); + // Determine whether this OpenGL context has compatibility features. + bool core_profile = false; + + if (_gl_version_major >= 3) { + if (_gl_version_major > 3 || _gl_version_minor >= 2) { + // OpenGL 3.2 has a built-in way to check this. + GLint profile_mask = 0; + glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile_mask); + + if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT) { + core_profile = true; + } else if (profile_mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) { + core_profile = false; + } else { + core_profile = !has_extension("GL_ARB_compatibility"); + } + } else { + // OpenGL 3.0/3.1. + GLint flags = 0; + glGetIntegerv(GL_CONTEXT_FLAGS, &flags); + if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) { + core_profile = true; + } + } + } if (GLCAT.is_debug()) { if (core_profile) { diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 8789f26650..14264e142a 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -3206,6 +3206,10 @@ glsl_compile_and_link() { valid &= glsl_compile_shader(Shader::ST_compute); } + if (!valid) { + return false; + } + // There might be warnings, so report those. GLSLShaders::const_iterator // it; for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) { // glsl_report_shader_errors(*it); } diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 08e200a4a0..49eaf78a69 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -17,6 +17,11 @@ ConfigVariableInt gl_version ("gl-version", "", PRC_DESC("Set this to get an OpenGL context with a specific version.")); +ConfigVariableBool gl_forward_compatible + ("gl-forward-compatible", false, + PRC_DESC("Setting this to true will request a forward-compatible OpenGL " + "context, which will not support the fixed-function pipeline.")); + ConfigVariableBool gl_support_fbo ("gl-support-fbo", true, PRC_DESC("Configure this false if your GL's implementation of " diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index 3c6dd81e7b..415286c674 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -41,6 +41,7 @@ // #define GSG_VERBOSE 1 extern EXPCL_GL ConfigVariableInt gl_version; +extern EXPCL_GL ConfigVariableBool gl_forward_compatible; extern EXPCL_GL ConfigVariableBool gl_support_fbo; extern ConfigVariableBool gl_cheap_textures; extern ConfigVariableBool gl_ignore_clamp; diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx index d620427afa..83ea5f2b2f 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx @@ -352,9 +352,20 @@ choose_pixel_format(const FrameBufferProperties &properties, attrib_list[n++] = gl_version[1]; } } + int flags = 0; if (gl_debug) { + flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + } + if (gl_forward_compatible) { + flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + if (gl_version.get_num_words() == 0 || gl_version[0] < 2) { + glxdisplay_cat.error() + << "gl-forward-compatible requires gl-version >= 3 0\n"; + } + } + if (flags != 0) { attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB; - attrib_list[n++] = GLX_CONTEXT_DEBUG_BIT_ARB; + attrib_list[n++] = flags; } attrib_list[n] = None; _context = _glXCreateContextAttribs(_display, _fbconfig, _share_context, diff --git a/panda/src/pgui/pgButton.cxx b/panda/src/pgui/pgButton.cxx index d1eba186c0..09a91120d4 100644 --- a/panda/src/pgui/pgButton.cxx +++ b/panda/src/pgui/pgButton.cxx @@ -115,7 +115,11 @@ release(const MouseWatcherParameter ¶m, bool background) { if (has_click_button(param.get_button())) { _button_down = false; if (get_active()) { - if (param.is_outside()) { + // Note that a "click" may come from a keyboard button press. In that + // case, instead of checking that the mouse cursor is still over the + // button, we check whether the item has keyboard focus. + if (param.is_outside() && + (MouseButton::is_mouse_button(param.get_button()) || !get_focus())) { set_state(S_ready); } else { set_state(S_rollover); diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index c98f12cf48..ed9b0e0b2c 100644 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -609,9 +609,20 @@ make_context(HDC hdc) { attrib_list[n++] = gl_version[1]; } } + int flags = 0; if (gl_debug) { + flags |= WGL_CONTEXT_DEBUG_BIT_ARB; + } + if (gl_forward_compatible) { + flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + if (gl_version.get_num_words() == 0 || gl_version[0] < 2) { + wgldisplay_cat.error() + << "gl-forward-compatible requires gl-version >= 3 0\n"; + } + } + if (flags != 0) { attrib_list[n++] = WGL_CONTEXT_FLAGS_ARB; - attrib_list[n++] = WGL_CONTEXT_DEBUG_BIT_ARB; + attrib_list[n++] = flags; } #ifndef SUPPORT_FIXED_FUNCTION attrib_list[n++] = WGL_CONTEXT_PROFILE_MASK_ARB; diff --git a/panda/src/windisplay/config_windisplay.cxx b/panda/src/windisplay/config_windisplay.cxx index 6e0ea2406d..62040c553a 100644 --- a/panda/src/windisplay/config_windisplay.cxx +++ b/panda/src/windisplay/config_windisplay.cxx @@ -86,6 +86,11 @@ ConfigVariableBool swapbuffer_framelock ("swapbuffer-framelock", false, PRC_DESC("Set this true to enable HW swapbuffer frame-lock on 3dlabs cards")); +ConfigVariableBool paste_emit_keystrokes +("paste-emit-keystrokes", true, + PRC_DESC("Handle paste events (Ctrl-V) as separate keystroke events for each " + "pasted character.")); + /** * Initializes the library. This must be called at least once before any of * the functions or classes in this library can be used. Normally it will be diff --git a/panda/src/windisplay/config_windisplay.h b/panda/src/windisplay/config_windisplay.h index 3256287f5b..7199b8603d 100644 --- a/panda/src/windisplay/config_windisplay.h +++ b/panda/src/windisplay/config_windisplay.h @@ -31,6 +31,7 @@ extern ConfigVariableBool ime_hide; extern ConfigVariableBool request_dxdisplay_information; extern ConfigVariableBool dpi_aware; extern ConfigVariableBool dpi_window_resize; +extern ConfigVariableBool paste_emit_keystrokes; extern EXPCL_PANDAWIN ConfigVariableBool swapbuffer_framelock; diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index d3e444cac9..c2e98beb0e 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -1927,7 +1927,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // Handle Cntrl-V paste from clipboard. Is there a better way to detect // this hotkey? if ((wparam=='V') && (GetKeyState(VK_CONTROL) < 0) && - !_input_devices.empty()) { + !_input_devices.empty() && paste_emit_keystrokes) { HGLOBAL hglb; char *lptstr;