Display Region Affected on parenting gui object to canvas

Hi,

I’ve encountered into a strange problem while dealing with display regions, outside of a certain vertical frame, the content within the display region is not rendered. I made two gifs to show what I mean:

dpErrorOne

And another one, at the bottom:

dpErrorTwo

Here is some code that shows what I’m doing:

from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.gui.DirectGui import *
from panda3d.core import *
import math
#done.

class run_me(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.startRoutine()
        self.animationTypeFrameData = DirectScrolledFrame(frameColor=(0.5, 0.5, 0.5, 1),canvasSize = (-0.9,0.4,-0.1,2), frameSize=(0.15, 1, -0.8, 0.7),pos=(-1.16, 0, 0.0100004), scale=(0.724712, 0.724712, 0.724712), relief=DGG.RIDGE, borderWidth=(0.02,0.02))
        parentCanvas = self.animationTypeFrameData.getCanvas()
        OnscreenText(text = "W-A-S-D, move the display region around", pos = (-0.030999999999999944, 0.8000000000000005), scale = 0.05)
        butt1=DirectButton(text = "Button", pos=(-0.75,0,1.8),scale=.05)
        #butt1.reparentTo(parentCanvas)
            
    def spawnLinkDisplayRegion(self,drNumber,positionList):
       #->drNumber: number of display regions to spawn.
       #->positionList: positions of display region: [[0.1, 0.27, 0.45, 0.65] [] [] ...]
       #->returnDataStructure: [[DR,camera,render] [] [] []]
       returnDataStructure=[]
       for numm in xrange(drNumber):
           displayRegion = base.win.makeDisplayRegion(positionList[numm][0], positionList[numm][1], positionList[numm][2], positionList[numm][3])
           displayRegion.setSort(20)
           #set the dp color:
           displayRegion.setClearColor(Vec4(0, 0,0, 0.3))
           displayRegion.setClearColorActive(True)
           #camera:
           camNode = Camera('cam')
           camNP = NodePath(camNode)
           displayRegion.setCamera(camNP)
           #set the aspect ratio:
           camNP.node().getLens().setAspectRatio(float(displayRegion.getPixelWidth()) / float(displayRegion.getPixelHeight()))
           #render:
           render21 = NodePath('render21')
           camNP.reparentTo(render21)
           #append:
           returnDataStructure.append([displayRegion,camNP,render21])
       return returnDataStructure

    def generalLowerDpReparentRoutine(self,*args):
       #args:[np,destinationRender,destinationCamera]
       np=args[0]
       destinationRender=args[1]
       destinationCamera=args[2]
       np.reparentTo(destinationRender)
       np.clearTransform()
       self.setCameraViewPort(np,destinationCamera,1)


    def setCameraViewPort(self,sentModel,sentCamera,viewDistance):
       #set the view distance
       lensBounds=base.cam.node().getLens().makeBounds()
       bounds = sentModel.getBounds()
       tb1=sentModel.getTightBounds()
       tb=sentModel.getTightBounds(render)
       sentCamera.setPos(bounds.getCenter())
       fov=sentCamera.node().getLens().getFov()
       distance=bounds.getRadius()/math.tan(deg2Rad(min(fov[0],fov[1])*0.5))
       sentCamera.setY(sentCamera,-distance*viewDistance)
       #done!

    def setSentWidgetSize(self,*args):
        sentWidget=args[0]
        self.widgetTranslateMotion=True
        self.setKeyValuePairDict={"front":0,"back":0,"left":0,"right":0}
        
        self.accept('w',self.setKeyValuePair,['front',1])
        self.accept('w-up',self.setKeyValuePair,['front',0])

        self.accept('s',self.setKeyValuePair,['back',1])
        self.accept('s-up',self.setKeyValuePair,['back',0])    

        self.accept('a',self.setKeyValuePair,['left',1])
        self.accept('a-up',self.setKeyValuePair,['left',0])

        self.accept('d',self.setKeyValuePair,['right',1])
        self.accept('d-up',self.setKeyValuePair,['right',0])
        
        self.accept('e',self.toggleWidgetTranslateMotion)
        taskMgr.add(self.monitorSetWidgetDPSize,"monitorSetWidgetDPSizeNom",extraArgs=[sentWidget],appendTask=True)

    def toggleWidgetTranslateMotion(self,*args):
       if not self.widgetTranslateMotion: self.widgetTranslateMotion=True
       elif self.widgetTranslateMotion: self.widgetTranslateMotion=False

    def setKeyValuePair(self,key,value):
        self.setKeyValuePairDict[key]=value

    def monitorSetWidgetDPSize(self,widget,task):
       leftX=widget.getDimensions()[0]
       rightX=widget.getDimensions()[1]
       lowY=widget.getDimensions()[2]
       highY=widget.getDimensions()[3]
       if(self.setKeyValuePairDict["front"]):
           if(not self.widgetTranslateMotion):
               highY+=0.001
               lowY-=0.001
           else:    
               highY+=0.001
               lowY+=0.001
       if(self.setKeyValuePairDict["back"]):
           if(not self.widgetTranslateMotion):
               highY-=0.001
               lowY+=0.001
           else:
               highY-=0.001
               lowY-=0.001
       if(self.setKeyValuePairDict["left"]):
           if(not self.widgetTranslateMotion):
               leftX+=0.001
               rightX-=0.001
           else:
               leftX-=0.001
               rightX-=0.001
       if(self.setKeyValuePairDict["right"]):
           if(not self.widgetTranslateMotion):
               leftX-=0.001
               rightX+=0.001
           else:
               leftX+=0.001
               rightX+=0.001
       widget.setDimensions(leftX,rightX,lowY,highY)
       camNP=widget.getCamera()
       camNP.node().getLens().setAspectRatio(float(widget.getPixelWidth()) / float(widget.getPixelHeight()))
       return task.cont

    def startRoutine(self):
       self.mapHoldingDisplayRegion=self.spawnLinkDisplayRegion(1,[[0.725996, 0.989994, 0.782993, 0.968994]])
       trkr1=base.loader.loadModel("smiley.egg")
       #trkr1.reparentTo(self.mapHoldingDisplayRegion[0][2])
       self.generalLowerDpReparentRoutine(trkr1,self.mapHoldingDisplayRegion[0][2],self.mapHoldingDisplayRegion[0][1])
       self.setSentWidgetSize(self.mapHoldingDisplayRegion[0][0],3)
       
w = run_me()
w.run()

Just copy-paste and run the code. To see the bug, uncomment this:

        #butt1.reparentTo(parentCanvas)

This behaviour however happens only on one of my computers and also, it only happens whenever I parent a DirectGui object such as a button to canvas from the DirectScrolledFrame class. It is truly strange, I really don’t know what could be causing it. I should also mention that I am currently using a slightly older version of 1.10.0 (I will upgrade later), so maybe this is a known problem that has already been solved in more recent versions. If not, how would I solve this? Should one just avoid using DirectScrolledFrame - canvas to avoid this (and other) issues?

Specs on the pc where this error happens:

Processor: intel core i5-4590@3.30GHZ
Ram: 4GB
64 Bit Os
Intel Hd Graphics
Intel Hd Graphics 4600
Graphics Memory 2121Mb
Monitor: hp f1904
Os: Windows 10 pro 2015

Nothing special or fancy, extremely basic setup as you can see, but it is on this pc that this problem exists. I therefore don’t know if this bug will pop up in other pcs or in newer versions of panda; as I said if it is already resolved in newer panda versions, then I will just have to see if it vanishes after I upgrade.
Again, this is the first time this is happening and it only happens after I parent something like a button to the canvas of a scrolledFrame! How weird is that?!

Thanks in advance.

It looks like it may be an issue with the ScissorEffects that DirectScrolledFrame uses to clip its contents to its frame.

A fix for a clipping issue was included in 1.10.4, I believe–but as that was a different issue, I don’t know whether the fix in question will affect the behaviour that you’re experiencing. Still, it may be worth upgrading to find out!

Well perhaps it could be that, but in the meantime, could I trouble you to run my code on your machine and see if you get any errors? After uncommenting the line that parents the button to the canvas, is the content of the display region rendered?

Thanks.

Sure!

To check that I’m doing this correctly, here’s how I tested it:

  • I uncommented line 16, which reads “butt1.reparentTo(parentCanvas)”
  • I then ran the program and used the WASD keys to control the black rectangle which contained a smiley-face, moving it around to various parts of the screen.
  • As I did so, I observed the appearance of the black rectangle and its smiley-face.
  • And for good measure, I looked briefly at the scrolled-frame containing the button, too, and moved its scroll-bars a little.

In doing so, I noticed nothing odd: the smiley continued to take up the full height of the black rectangle, and the scrolled-frame and its button appeared as expected.

I toyed briefly with the mode activated by pressing “e”; not knowing quite what it was expected to do, I’m not sure of whether the results were as intended, but they looked fine. (Well, until I caused the height to be zero, and thus crashed the program with a division-by-zero exception. :P)

Note that I’m using (what I think is) the most-recent stable build, 1.10.5.

The error does only pop up in the current computer I’m using, it doesn’t exist for the others I have access to, which is weird. This is what it looks like on this pc:

dpErrorThree

As I said, the content of the display region is only rendered within a restricted vertical frame inside the main window, whenever anything is parented to the canvas of a DirectScrolledFrame object. Of course, I could just avoid using canvases and use display regions to simulate them altogether.
The “e” trigger was just to shift between increasing the width/length of the display region and translating its position on the screen.
Anyways, I appreciate your help, if upon upgrading to the most recent, stable build, I am still facing this strange issue, then I’ll just have to disregard using the DirectScrolledFrame class. :confused:

1 Like

I’d suggest reporting it as a bug on GitHub–others may face similar problems, after all, and either way it seems a pity to discard an otherwise-useful GUI widget!