[Alpha] TreeGUI

Second try at making the picture names theme independant.

The theme folder is passed down to doImage, where it is stripped from the filename (if present) before being used as dictionary key.
This version needs that all picture path doesn’t include the theme folder, including the one used in init of the theme.

    def doFolders(self,folder):
        """ 
            walk the sub folders and files in this foler 
            and insert them into the atlas 
        """
        for f in sorted(walkdir(folder)):
            
#            if "ttf" in f:        
#                self.doFont(f)
#                self.files.append(f)
                
            if ".png" in f or ".rgb" in f:
                self.doImage(f, folder)
                self.files.append(f)
    def doImage(self, f, themeFolder):
        """ process an image and put it into the atlas """ 
        print "Doing image:",f
        i = PNMImage(f)
        i.addAlpha()
        short = f
        if short.startswith(themeFolder):
          short = f.replace(themeFolder,"",1)
          while short[0] in ["/", "\\"]:
            short = short[1:]
        self.it.add(short,i)
    def getRect(self,name):
        """ 
            return 4 values that correspond to the named rectangle 
        """ 
        try:       
            image = self.images[name]
            return image.x,image.y,image.w,image.h
        except KeyError:
            print "can't find picture",name
            return (0,0,0,0)

I noticed that sha is deprecated, I made the following changes to eggatlas.py:

import hashlib in place of import sha

and

def doHash(self,folder):
        """ 
            walk the sub folders and files in this folder 
            and get hash of their names 
        """
        files = []
        for f in walkdir(folder):
            if ".font.egg" in f or ".png" in f or ".rgb" in f:        
                files.append("%s:%f"%(f,os.stat(f).st_mtime))
        text = "\n".join(sorted(files))
        return hashlib.sha224(text).hexdigest()

instead of returning sha.new(text)

There’s another issue I ran into on Mac OS X (Snow Leopard), that I don’t see on windows. It complains on the following line in drawer.py:

drawer.setPlateSize(32)

and says that setPlateSize does not exist. Its in the api, and it works on windows. I’m not sure if this is an issue with the latest build of 1.7, or just an issue with Panda on Mac.

I commented out the line and everything seemed to still be working properly.

Yes in 1.7.0 TreeGUI will use the new MeshDrawer2d. I all ready ported it. I should test and commit it soon.

I merged the two suggestions you guys submitted. I also made fonts theme folder independent.

@Treeform,

I’m having issues with my interface being glitchy. I have the following issue:

Clicking a button does not always have the expected behavior of clicking button, but sometimes “drags” the interior of the screen. For example, I try to click the button … it doesn’t click but instead moves all the elements within the open form to the left or up.

Is there a setting I need to set to keep the interior of the form from being draggable? Also, the buttons do not click on every button of the button, I have to move my cursor over a certain part of it and then I am able to click.

can you post your code? Or a small sample that demonstrates the problem?

Here is a class I wrote for the gameplay settings of the game, I removed the code for retrieving and setting the scroll speed and just left the parts pertaining to treegui.

I can reproduce easiest when using the ‘close’ button. I noticed also that when I go to use the button and I hit the left or top side of the button - the button always highlights and is useable. If the mouse cursor enters from the right or bottom side, the button does not highlight … is not clickable, and this is where I have the issue with being able to shift the elements of the form.

class gameplayFrame(MicroForm):
    style = "default"
    
    def __init__(self):
        MicroForm.__init__(self, "Gameplay")

        currentScrollSpeed = 0.3

        self.add(Label("Scroll Speed",pos=Vec2(10,20)))
        self.scrollSpeedSlider =  ScrollBarX(pos=(10,40),size=(100,15))
        self.scrollSpeedSlider.scroller.x = float(currentScrollSpeed) * 100
        self.scrollSpeedSlider.value = float(currentScrollSpeed) * 100
        self.add(self.scrollSpeedSlider)
        
        
        self.add(Button('Apply', pos=Vec2(10,230), size=Vec2(70,16), onClick=self.apply))
        self.add(Button('Close', pos=Vec2(100,230), size=Vec2(70,16), onClick=self.close))
        
        self.x = "center" #"center"
        self.y = "center" #"center"
        self.width = 350
        self.height = 250
        
        gui.add(self)
    
    def apply(self):
        dialog("Information", "Settings applied.")
        """write settings to config"""
            	        
        
    def close(self):
        optionsFrame()
        gui.remove(self)

I am sorry i cant run it now, i will when i get home. But from first look MicroForm adds its own controls and hides their drawing. This is done as not to clutter up the user interface. Think mini windows. Try using the normal Form - it does not hide any thing. Or if you don’t want any thing from related try Pane.

What I want this code to do is that when you press one of the buttons(inventoryknapp01-04) it leads to a new function. It is going to be used in the inventory and work like a simplified version of the oblivion inventory, here is the sketch: bildr.no/view/575511’>http://bildr.no/view/575511

Talked with you in the chat and you suggested I post it here so you could take a look at it and see if you could translate it, if you had time :slight_smile:

from direct.gui.DirectGui import *
import direct.directbase.DirectStart
from pandac.PandaModules import *


class Inventory():
  def __init__(self):
      # Screen size:
      dr = base.win.makeDisplayRegion()
      dr.setSort(20)

      myCamera2d = NodePath(Camera('myCam2d'))
      lens = OrthographicLens()
      lens.setFilmSize(base.win.getXSize(), base.win.getYSize())
      lens.setNearFar(-1000, 1000)
      myCamera2d.node().setLens(lens)

      myRender2d = NodePath('myRender2d')
      myRender2d.setDepthTest(False)
      myRender2d.setDepthWrite(False)
      myCamera2d.reparentTo(myRender2d)
      dr.setCamera(myCamera2d)
      
      self.i2d = myRender2d
      X = base.win.getXSize()
      Y = base.win.getYSize()
      self.X0 = -X/2
      self.Y0 = -Y/2
      self.X100 = X/2
      self.Y100 = Y/2
      
      print self.X0, self.Y0, self.X100, self.Y100
      
      self.toggled = False
  
  def c(self, size, XorY='X', margin=0):
      X = base.win.getXSize()
      Y = base.win.getYSize()
      if XorY == 'X':
         axis = X
      elif XorY == 'Y':
         axis = -Y
         margin = -margin # Fix negative integer issue
      else:
         axis = X

      
      if str(size)[-2:] == 'px':
         final = int(-(axis/2)-int(size[:-2]))
      if str(size)[-1:] == '%':
         size = int(size[:-1])
         final = int(-(axis/2)+(size/100.0*axis))
      
      return final+margin
  
  def toggle(self):
      def testf(self):
            print "entotre"
      if self.toggled == False:
         # Inventory frame:
         self.inventory = DirectFrame(pos=(self.c('0px', 'X', margin=25), 1, self.c('0px', 'Y', margin=25)), frameSize=(800,-0,0,-600), frameColor=(1,1,1,0.8))
         self.inventory.reparentTo(self.i2d)
         self.inventory.setBin("fixed", 0)
         self.inventoryknapp01 = DirectButton(pos=(self.c('0px', 'X', margin=0), 1, self.c('0px', 'Y', margin=0)), frameSize=(800,640,-940,-975), frameColor=(0,0,1,1))
         self.inventoryknapp01.reparentTo(self.inventory)
         self.inventoryknapp01.setBin("fixed", 1)
         self.inventoryknapp02 = DirectButton(pos=(self.c('0px', 'x', margin=0), 1, self.c('0px', 'Y', margin=0)), frameSize=(960,800,-940,-975), frameColor=(1,0,0,1))
         self.inventoryknapp02.reparentTo(self.inventory)
         self.inventoryknapp02.setBin("fixed", 1)
         self.inventoryknapp03 = DirectButton(pos=(self.c('0px', 'x', margin=0), 1, self.c('0px', 'Y', margin=0)), frameSize=(1120,960,-940,-975), frameColor=(0,1,0,1))
         self.inventoryknapp03.reparentTo(self.inventory)
         self.inventoryknapp03.setBin("fixed", 1)
         self.inventoryknapp04 = DirectButton(pos=(self.c('0px', 'x', margin=0), 1, self.c('0px', 'Y', margin=0)), frameSize=(1280,1120,-940,-975), frameColor=(1,1,0,1), commandButtons= DGG.LMB, command=testf)
         self.inventoryknapp04.reparentTo(self.inventory)
         self.inventoryknapp04.setBin("fixed", 1)
         
         # Other stuff inside of inventory frame:

         # Toggle inventory on/off:
         self.toggled = True
      else:
         self.inventory.destroy()
         
         # Toggle inventory on/off:
         self.toggled = False
      

@treeform,

Ok, I derived a new class from Pane, called PlainForm(didn’t want the scrollbars), and the button clicking issues have gone away. Looks like that is an issue specifically with the MicroForm.

Yes it is, microform has really specific use. Could you post the src for the plain form?

Here’s the code for the PlainForm as well as for a dialog.

class PlainForm(Pane):
     def __init__(self,title,pos=Vec2(200,200),size=Vec2(200,300)):
          Pane.__init__(self)
          self.bar = Pane.add(self,Button(title,
          pos=Vec2(20,0),
          size=Vec2(min(200,size[0]-40),20),
          onClick=self.onClick));
          self.bar.skinType = "FRAMEBAR"
        
     def onClick(self):
          """ frames consume mouse clicks """
          return False

        
class Dialog(PlainForm):
     style = "default"
     
     def __init__(self, title, text):
          PlainForm.__init__(self, "%s" % title)
     
          self.add(Label("%s" % text,pos=Vec2(10,30)))
          self.add(Button('OK', pos=Vec2(10,180), size=Vec2(70,16), onClick=self.close))
         
          self.x = "center" #"center"
          self.y = "center" #"center"
          self.width = 200
          self.height = 200
 
          gui.add(self)
     
     def close(self):
          gui.remove(self)

Should dialog have an icon?

Yes, yes it should. I didn’t even think of that.

Do you have any code updates on getting treegui to work with p3d? (since we’ll need to read the bam file instead of egg) If not then I might take a crack at it.

I already have the p3d solved. I will try to write stuff up on it soon and commit.

Is there a way to make the text in the text inputs to stay within the bounds of the input control?

I just tried to run the tut_form example but ran into an issue:

The first path seems to be broken (
cacheRTheme instead of cache/RTheme). Futhermore it looks like windows vista denie the write access. Any idea how to solve this problem?

Is anyone still working on this? I had a question about the RealIcon class.

I created a PNG file with GIMP that’s 50x50 pixels, so I thought the ‘iconRec’ I pass in should be [0,0,50,50] I guess I don’t fully understand the uv coords because this causes it to tile itself, I dug around and found that if I use the values from self.iconFile.getXSize() and self.iconFile.getYSize() (32,32) then it works as I was expecting. My question is (since I know this is being handled with the current system using 1 file for the whole thing), how do you convert from image pixel coordinates to the uv coords used in the system?

Nevermind, someone filled me on the whole power of two situation with the textures and p3d.