From 78c3db379c7108b9d231baf3c52d4869eb6428be Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 3 Nov 2019 11:48:51 +0100 Subject: [PATCH 1/5] gobj: fix tests crash due to ShaderBuffer context not cleared at GSG death --- panda/src/gobj/preparedGraphicsObjects.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/panda/src/gobj/preparedGraphicsObjects.cxx b/panda/src/gobj/preparedGraphicsObjects.cxx index e3ab0e8d83..099b40c899 100644 --- a/panda/src/gobj/preparedGraphicsObjects.cxx +++ b/panda/src/gobj/preparedGraphicsObjects.cxx @@ -1371,6 +1371,8 @@ release_all_shader_buffers() { ++bci) { BufferContext *bc = (BufferContext *)(*bci); + ((ShaderBuffer *)bc->_object)->clear_prepared(this); + bc->_object = nullptr; _released_shader_buffers.insert(bc); } From eb3b45ebb15d996ed0e155c087628fea9ea1c700 Mon Sep 17 00:00:00 2001 From: fireclawthefox Date: Fri, 1 Nov 2019 14:58:38 +0100 Subject: [PATCH 2/5] dgui: Fix reset text scale on DirectOptionMenu item unhighlight Set text scale to previous unhighlighted scale on unhighlight to keep custom scales --- direct/src/gui/DirectOptionMenu.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/direct/src/gui/DirectOptionMenu.py b/direct/src/gui/DirectOptionMenu.py index 818cc3f896..390f0a4198 100644 --- a/direct/src/gui/DirectOptionMenu.py +++ b/direct/src/gui/DirectOptionMenu.py @@ -72,6 +72,10 @@ class DirectOptionMenu(DirectButton): self.popupMenu = None self.selectedIndex = None self.highlightedIndex = None + if 'item_text_scale' in kw: + self._prevItemTextScale = kw['item_text_scale'] + else: + self._prevItemTextScale = (1,1) # A big screen encompassing frame to catch the cancel clicks self.cancelFrame = self.createcomponent( 'cancelframe', (), None, @@ -247,6 +251,7 @@ class DirectOptionMenu(DirectButton): def _highlightItem(self, item, index): """ Set frame color of highlighted item, record index """ + self._prevItemTextScale = item['text_scale'] item['frameColor'] = self['highlightColor'] item['frameSize'] = (self['highlightScale'][0]*self.minX, self['highlightScale'][0]*self.maxX, self['highlightScale'][1]*self.minZ, self['highlightScale'][1]*self.maxZ) item['text_scale'] = self['highlightScale'] @@ -256,7 +261,7 @@ class DirectOptionMenu(DirectButton): """ Clear frame color, clear highlightedIndex """ item['frameColor'] = frameColor item['frameSize'] = (self.minX, self.maxX, self.minZ, self.maxZ) - item['text_scale'] = (1,1) + item['text_scale'] = self._prevItemTextScale self.highlightedIndex = None def selectHighlightedIndex(self, event = None): From 69e8b4ed3c2156e2e9015bd8c048a80bb4269a18 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 3 Nov 2019 12:09:36 +0100 Subject: [PATCH 3/5] showbase: make render2d available to GUI items without ShowBase --- direct/src/showbase/ShowBase.py | 9 +++++++-- direct/src/showbase/ShowBaseGlobal.py | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index e79cc31751..98abb1780b 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -544,6 +544,8 @@ class ShowBase(DirectObject.DirectObject): del ShowBaseGlobal.base self.aspect2d.node().removeAllChildren() + self.render2d.node().removeAllChildren() + self.aspect2d.reparent_to(self.render2d) # [gjeon] restore sticky key settings if self.config.GetBool('disable-sticky-keys', 0): @@ -1108,8 +1110,12 @@ class ShowBase(DirectObject.DirectObject): 2-d objects and gui elements that are superimposed over the 3-d geometry in the window. """ + # We've already created aspect2d in ShowBaseGlobal, for the + # benefit of creating DirectGui elements before ShowBase. + from . import ShowBaseGlobal + ## This is the root of the 2-D scene graph. - self.render2d = NodePath('render2d') + self.render2d = ShowBaseGlobal.render2d # Set up some overrides to turn off certain properties which # we probably won't need for 2-d objects. @@ -1140,7 +1146,6 @@ class ShowBase(DirectObject.DirectObject): ## aspect2d, which scales things back to the right aspect ## ratio along the X axis (Z is still from -1 to 1) self.aspect2d = ShowBaseGlobal.aspect2d - self.aspect2d.reparentTo(self.render2d) aspectRatio = self.getAspectRatio() self.aspect2d.setScale(1.0 / aspectRatio, 1.0, 1.0) diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 8acd70d18d..7aaaed3f45 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -26,7 +26,8 @@ cvMgr = ConfigVariableManager.getGlobalPtr() pandaSystem = PandaSystem.getGlobalPtr() # This is defined here so GUI elements can be instantiated before ShowBase. -aspect2d = NodePath(PGTop("aspect2d")) +render2d = NodePath("render2d") +aspect2d = render2d.attachNewNode(PGTop("aspect2d")) hidden = NodePath("hidden") # Set direct notify categories now that we have config From 2e3b350510cb91aa0e88400434d371621cb6bb44 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 3 Nov 2019 12:12:42 +0100 Subject: [PATCH 4/5] dgui: allow creating DirectOptionMenu without ShowBase --- direct/src/gui/DirectOptionMenu.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/direct/src/gui/DirectOptionMenu.py b/direct/src/gui/DirectOptionMenu.py index 390f0a4198..fe417cfd9f 100644 --- a/direct/src/gui/DirectOptionMenu.py +++ b/direct/src/gui/DirectOptionMenu.py @@ -7,11 +7,13 @@ in-depth explanation and an example of how to use this class. __all__ = ['DirectOptionMenu'] from panda3d.core import * +from direct.showbase import ShowBaseGlobal from . import DirectGuiGlobals as DGG from .DirectButton import * from .DirectLabel import * from .DirectFrame import * + class DirectOptionMenu(DirectButton): """ DirectOptionMenu(parent) - Create a DirectButton which pops up a @@ -222,27 +224,27 @@ class DirectOptionMenu(DirectButton): self.popupMenu.setZ( self, self.minZ + (self.selectedIndex + 1)*self.maxHeight) # Make sure the whole popup menu is visible - pos = self.popupMenu.getPos(render2d) - scale = self.popupMenu.getScale(render2d) + pos = self.popupMenu.getPos(ShowBaseGlobal.render2d) + scale = self.popupMenu.getScale(ShowBaseGlobal.render2d) # How are we doing relative to the right side of the screen maxX = pos[0] + fb[1] * scale[0] if maxX > 1.0: # Need to move menu to the left - self.popupMenu.setX(render2d, pos[0] + (1.0 - maxX)) + self.popupMenu.setX(ShowBaseGlobal.render2d, pos[0] + (1.0 - maxX)) # How about up and down? minZ = pos[2] + fb[2] * scale[2] maxZ = pos[2] + fb[3] * scale[2] if minZ < -1.0: # Menu too low, move it up - self.popupMenu.setZ(render2d, pos[2] + (-1.0 - minZ)) + self.popupMenu.setZ(ShowBaseGlobal.render2d, pos[2] + (-1.0 - minZ)) elif maxZ > 1.0: # Menu too high, move it down - self.popupMenu.setZ(render2d, pos[2] + (1.0 - maxZ)) + self.popupMenu.setZ(ShowBaseGlobal.render2d, pos[2] + (1.0 - maxZ)) # Also display cancel frame to catch clicks outside of the popup self.cancelFrame.show() # Position and scale cancel frame to fill entire window - self.cancelFrame.setPos(render2d, 0, 0, 0) - self.cancelFrame.setScale(render2d, 1, 1, 1) + self.cancelFrame.setPos(ShowBaseGlobal.render2d, 0, 0, 0) + self.cancelFrame.setScale(ShowBaseGlobal.render2d, 1, 1, 1) def hidePopupMenu(self, event = None): """ Put away popup and cancel frame """ From e6fc6c695dbb9c61dc316c8fc3b17e2d41983245 Mon Sep 17 00:00:00 2001 From: fireclawthefox Date: Sun, 3 Nov 2019 12:14:37 +0100 Subject: [PATCH 5/5] tests: add unit tests for DirectOptionMenu --- tests/gui/test_DirectOptionMenu.py | 73 ++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/gui/test_DirectOptionMenu.py diff --git a/tests/gui/test_DirectOptionMenu.py b/tests/gui/test_DirectOptionMenu.py new file mode 100644 index 0000000000..f83ada1352 --- /dev/null +++ b/tests/gui/test_DirectOptionMenu.py @@ -0,0 +1,73 @@ +from direct.gui.DirectOptionMenu import DirectOptionMenu +import pytest + + +def test_menu_destroy(): + menu = DirectOptionMenu(items=["item1", "item2"]) + menu.destroy() + + +def test_showPopupMenu(): + menu = DirectOptionMenu() + + # Showing an option menu without items will raise an exception + with pytest.raises(Exception): + menu.showPopupMenu() + + menu["items"] = ["item1", "item2"] + menu.showPopupMenu() + assert not menu.popupMenu.isHidden() + assert not menu.cancelFrame.isHidden() + + menu.hidePopupMenu() + assert menu.popupMenu.isHidden() + assert menu.cancelFrame.isHidden() + + +def test_index(): + menu = DirectOptionMenu(items=["item1", "item2"]) + assert menu.index("item1") == 0 + assert menu.index("item2") == 1 + + +def test_set_get(): + menu = DirectOptionMenu(items=["item1", "item2"]) + menu.set(1, False) + assert menu.selectedIndex == 1 + assert menu.get() == "item2" + assert menu["text"] == "item2" + + +def test_initialitem(): + # initialitem by string + menuByStr = DirectOptionMenu(items=["item1", "item2"], initialitem="item2") + assert menuByStr.get() == "item2" + assert menuByStr["text"] == "item2" + + # initialitem by Index + menuByIdx = DirectOptionMenu(items=["item1", "item2"], initialitem=1) + assert menuByIdx.get() == "item2" + assert menuByIdx["text"] == "item2" + + +def test_item_text_scale(): + highlightScale = (2, 2) + unhighlightScale = (0.5, 0.5) + menu = DirectOptionMenu( + items=["item1", "item2"], + item_text_scale=unhighlightScale, + highlightScale=highlightScale) + + # initial scale + item = menu.component("item0") + + item_text_scale = 0.8 + assert item["text_scale"] == unhighlightScale + + # highlight scale + menu._highlightItem(item, 0) + assert item["text_scale"] == highlightScale + + # back to initial scale + menu._unhighlightItem(item, item["frameColor"]) + assert item["text_scale"] == unhighlightScale