adding vertex memory explorer

This commit is contained in:
YoungWook Yang 2008-07-22 22:25:59 +00:00
parent 13ac116d63
commit 227ed2dc45
2 changed files with 376 additions and 19 deletions

View File

@ -14,6 +14,7 @@ from direct.tkwidgets import Slider
from direct.tkwidgets import VectorWidgets from direct.tkwidgets import VectorWidgets
from direct.tkwidgets import SceneGraphExplorer from direct.tkwidgets import SceneGraphExplorer
from TaskManagerPanel import TaskManagerWidget from TaskManagerPanel import TaskManagerWidget
from direct.tkwidgets import MemoryExplorer
""" """
Possible to add: Possible to add:
@ -183,17 +184,22 @@ class DirectSessionPanel(AppShell):
# Create the notebook pages # Create the notebook pages
notebook = Pmw.NoteBook(notebookFrame) notebook = Pmw.NoteBook(notebookFrame)
notebook.pack(fill = BOTH, expand = 1) notebook.pack(fill = BOTH, expand = 1)
envPage = notebook.add('Environment') self.createEnvPage(notebook.add('Environment'))
lightsPage = notebook.add('Lights') self.createLightsPage(notebook.add('Lights'))
gridPage = notebook.add('Grid') self.createGridPage(notebook.add('Grid'))
devicePage = notebook.add('Devices') self.createDevicePage(notebook.add('Devices'))
tasksPage = notebook.add('Tasks') self.createTasksPage(notebook.add('Tasks'))
scenePage = notebook.add('Scene') self.createMemPage(notebook.add('Memory'))
notebook.setnaturalsize()
framePane.pack(expand = 1, fill = BOTH)
mainFrame.pack(fill = 'both', expand = 1)
# Put this here so it isn't called right away # Put this here so it isn't called right away
notebook['raisecommand'] = self.updateInfo notebook['raisecommand'] = self.updateInfo
## Environment page ## def createEnvPage(self, envPage):
# Backgroud color
bkgrdFrame = Frame(envPage, borderwidth = 2, relief = 'sunken') bkgrdFrame = Frame(envPage, borderwidth = 2, relief = 'sunken')
Label(bkgrdFrame, text = 'Background', Label(bkgrdFrame, text = 'Background',
@ -273,7 +279,6 @@ class DirectSessionPanel(AppShell):
frame.pack(side = LEFT, fill = X, expand = 0) frame.pack(side = LEFT, fill = X, expand = 0)
fovFrame.pack(fill = X, expand = 1) fovFrame.pack(fill = X, expand = 1)
drFrame.pack(fill = BOTH, expand = 0) drFrame.pack(fill = BOTH, expand = 0)
## Render Style ## ## Render Style ##
@ -305,7 +310,7 @@ class DirectSessionPanel(AppShell):
self.toggleWireframeButton.pack(fill = X, expand = 1) self.toggleWireframeButton.pack(fill = X, expand = 1)
toggleFrame.pack(side = LEFT, fill = X, expand = 1) toggleFrame.pack(side = LEFT, fill = X, expand = 1)
## Lights page ## def createLightsPage(self, lightsPage):
# Lights # # Lights #
lightFrame = Frame(lightsPage, borderwidth = 2, relief = 'sunken') lightFrame = Frame(lightsPage, borderwidth = 2, relief = 'sunken')
self.lightsButton = Menubutton(lightFrame, text = 'Lights', self.lightsButton = Menubutton(lightFrame, text = 'Lights',
@ -470,7 +475,8 @@ class DirectSessionPanel(AppShell):
lightFrame.pack(expand = 1, fill = BOTH) lightFrame.pack(expand = 1, fill = BOTH)
## GRID PAGE ##
def createGridPage(self, gridPage):
Label(gridPage, text = 'Grid', Label(gridPage, text = 'Grid',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0) font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.enableGrid = BooleanVar() self.enableGrid = BooleanVar()
@ -524,7 +530,7 @@ class DirectSessionPanel(AppShell):
self.gridSnapAngle['command'] = base.direct.grid.setSnapAngle self.gridSnapAngle['command'] = base.direct.grid.setSnapAngle
self.gridSnapAngle.pack(fill = X, expand = 0) self.gridSnapAngle.pack(fill = X, expand = 0)
## DEVICE PAGE ## def createDevicePage(self, devicePage):
Label(devicePage, text = 'DEVICES', Label(devicePage, text = 'DEVICES',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0) font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
@ -590,16 +596,18 @@ class DirectSessionPanel(AppShell):
self.jbHprSF.pack(fill = X, expand = 0) self.jbHprSF.pack(fill = X, expand = 0)
self.bind(self.jbHprSF, 'Set joybox HPR speed multiplier') self.bind(self.jbHprSF, 'Set joybox HPR speed multiplier')
## TASKS PAGE ## def createTasksPage(self, tasksPage):
Label(tasksPage, text = 'TASKS', Label(tasksPage, text = 'TASKS',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0) font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.taskMgrPanel = TaskManagerWidget(tasksPage, taskMgr) self.taskMgrPanel = TaskManagerWidget(tasksPage, taskMgr)
self.taskMgrPanel.taskListBox['listbox_height'] = 10 self.taskMgrPanel.taskListBox['listbox_height'] = 10
notebook.setnaturalsize() def createMemPage(self, memPage):
self.MemExp = MemoryExplorer.MemoryExplorer(
framePane.pack(expand = 1, fill = BOTH) memPage, nodePath = render,
mainFrame.pack(fill = 'both', expand = 1) scrolledCanvas_hull_width = 250,
scrolledCanvas_hull_height = 250)
self.MemExp.pack(fill = BOTH, expand = 1)
def toggleDirect(self): def toggleDirect(self):
if self.directEnabled.get(): if self.directEnabled.get():

View File

@ -0,0 +1,349 @@
from direct.showbase.DirectObject import DirectObject
from direct.showbase.TkGlobal import *
from Tkinter import *
from Tree import *
import Pmw
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
DEFAULT_BT_WIDTH = 50.0
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
class MemoryExplorer(Pmw.MegaWidget, DirectObject):
#--------------------------------------------------------------------------
# Init
#--------------------------------------------------------------------------
def __init__(self, parent = None, nodePath = render, **kw):
optiondefs = (('menuItems', [], Pmw.INITOPT),)
self.defineoptions(kw, optiondefs)
Pmw.MegaWidget.__init__(self, parent)
self.nodePath = nodePath
self.renderItem = None
self.render2dItem = None
self.buttons = []
self.labels = []
self.rootItem = None
self.btWidth = DEFAULT_BT_WIDTH
self.createScrolledFrame()
self.createScale()
self.createRefreshBT()
self.balloon = Pmw.Balloon(self.interior())
def createScrolledFrame(self):
self.frame = Pmw.ScrolledFrame(self.interior(),
labelpos = 'n',
label_text = 'ScrolledFrame',
usehullsize = 1,
hull_width = 200,
hull_height = 220,)
self.frame.pack(padx = 3, pady = 3, fill = BOTH, expand = 1)
def createScale(self):
self.scaleCtrl = Scale(self.interior(),
label = "Graph Scale",
from_= 0.0,
to = 20.0,
resolution = 0.1,
orient = HORIZONTAL,
command = self.onScaleUpdate)
self.scaleCtrl.pack(side = LEFT, fill = BOTH, expand = 1)
self.scaleCtrl.set(0.0)
def createRefreshBT(self):
self.refreshBT = Button(self.interior(), text = 'Refresh', command = self.refresh)
self.refreshBT.pack(side = LEFT, fill = BOTH, expand = 1)
#--------------------------------------------------------------------------
# Item Ctrls
#--------------------------------------------------------------------------
def createDefaultCtrls(self):
if self.renderItem == None or self.render2dItem == None:
return
totalBytes = self.renderItem.getVertexBytes()+self.render2dItem.getVertexBytes()
self.addChildCtrl(self.renderItem, totalBytes)
self.addChildCtrl(self.render2dItem, totalBytes)
self.setTitle("ALL", totalBytes)
def setTitle(self, parent, bytes):
self.frame["label_text"] = "[%s] - %s bytes" % (parent, bytes)
def resetCtrls(self):
for button in self.buttons:
self.balloon.unbind(button)
button.destroy()
self.buttons = []
for label in self.labels:
label.destroy()
self.labels = []
def getNewButton(self, width, ratio):
newBT = Button(self.frame.interior(),
anchor = W,
width = width)
if ratio == 0.0:
newBT['bg'] = "grey"
newBT['text'] = "."
else:
newBT['bg'] = Pmw.Color.hue2name(0.0, 1.0-ratio)
newBT['text'] = "%0.2f%%" % (ratio*100.0)
return newBT
def addSelfCtrl(self, item, totalBytes):
self.addLabel("[self] : %s bytes" % item.getSelfVertexBytes())
bt = self.addButton(item.getSelfVertexBytes(),
totalBytes,
self.onSelfButtonLClick,
self.onSelfButtonRClick,
item)
def addChildCtrl(self, item, totalBytes):
self.addLabel("%s [+%s] : %s bytes" % (item.getName(),
item.getNumChildren(),
item.getVertexBytes()))
bt = self.addButton(item.getVertexBytes(),
totalBytes,
self.onChildButtonLClick,
self.onChildButtonRClick,
item)
def addButton(self, vertexBytes, totalBytes, funcLClick, funcRClick, item):
width = self.getBTWidth(vertexBytes, totalBytes)
if totalBytes == 0:
ratio = 0.0
else:
ratio = vertexBytes/float(totalBytes)
bt = self.getNewButton(width, ratio)
def callbackL(event):
funcLClick(item)
def callbackR(event):
funcRClick(item)
bt.bind("<Button-1>", callbackL)
bt.bind("<Button-3>", callbackR)
bt.pack(side = TOP, anchor = NW)
self.buttons.append(bt)
self.balloon.bind(bt, item.getPathName())
return bt
def addLabel(self, label):
label = Label(self.frame.interior(), text = label)
label.pack(side = TOP, anchor = NW, expand = 0)
self.labels.append(label)
def getBTWidth(self, vertexBytes, totalBytes):
if totalBytes == 0:
return 1
width = int(self.btWidth * vertexBytes / totalBytes)
if width == 0:
width = 1
return width
#--------------------------------------------------------------------------
# Callback
#--------------------------------------------------------------------------
def onScaleUpdate(self, arg):
self.btWidth = DEFAULT_BT_WIDTH + DEFAULT_BT_WIDTH * float(arg)
if self.rootItem:
self.updateBTWidth()
else:
self.updateDefaultBTWidth()
def updateBTWidth(self):
self.buttons[0]['width'] = self.getBTWidth(self.rootItem.getSelfVertexBytes(),
self.rootItem.getVertexBytes())
btIndex = 1
for item in self.rootItem.getChildrenAsList():
self.buttons[btIndex]['width'] = self.getBTWidth(item.getVertexBytes(),
self.rootItem.getVertexBytes())
btIndex += 1
def updateDefaultBTWidth(self):
if self.renderItem == None or self.render2dItem == None:
return
totalBytes = self.renderItem.getVertexBytes() + self.render2dItem.getVertexBytes()
self.buttons[0]['width'] = self.getBTWidth(self.renderItem.getVertexBytes(), totalBytes)
self.buttons[1]['width'] = self.getBTWidth(self.render2dItem.getVertexBytes(), totalBytes)
def onSelfButtonLClick(self, item):
pass
def onSelfButtonRClick(self, item):
parentItem = item.getParent()
self.resetCtrls()
self.addItemCtrls(parentItem)
def onChildButtonLClick(self, item):
if item.getNumChildren() == 0:
return
self.resetCtrls()
self.addItemCtrls(item)
def onChildButtonRClick(self, item):
parentItem = item.getParent()
if parentItem:
self.resetCtrls()
self.addItemCtrls(parentItem.getParent())
def addItemCtrls(self, item):
self.rootItem = item
if item == None:
self.createDefaultCtrls()
else:
self.addSelfCtrl(item, item.getVertexBytes())
for child in item.getChildrenAsList():
self.addChildCtrl(child, item.getVertexBytes())
self.setTitle(item.getPathName(), item.getVertexBytes())
#--------------------------------------------------------------------------
# List & Analyze
#--------------------------------------------------------------------------
def makeList(self):
self.renderItem = MemoryExplorerItem(None, render)
self.buildList(self.renderItem)
self.render2dItem = MemoryExplorerItem(None, render2d)
self.buildList(self.render2dItem)
def buildList(self, parentItem):
for nodePath in parentItem.nodePath.getChildrenAsList():
item = MemoryExplorerItem(parentItem, nodePath)
parentItem.addChild(item)
self.buildList(item)
def analyze(self):
self.renderItem.analyze()
self.render2dItem.analyze()
def refresh(self):
self.makeList()
self.analyze()
self.resetCtrls()
self.createDefaultCtrls()
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
class MemoryExplorerItem:
def __init__(self, parent, nodePath):
self.parent = parent
self.nodePath = nodePath
self.children = []
self.selfVertexBytes = 0
self.childrenVertexBytes = 0
self.numFaces = 0
self.textureBytes = 0
if parent:
self.pathName = parent.pathName + "/" + nodePath.getName()
else:
self.pathName = nodePath.getName()
def getParent(self):
return self.parent
def addChild(self, child):
self.children.append(child)
def getNumChildren(self):
return len(self.children)
def getChildrenAsList(self):
return self.children
def getName(self):
return self.nodePath.getName()
def getPathName(self):
return self.pathName
def getVertexBytes(self):
return self.selfVertexBytes + self.childrenVertexBytes
def getSelfVertexBytes(self):
return self.selfVertexBytes
def analyze(self):
self.selfVertexBytes = 0
self.childrenVertexBytes = 0
self.numFaces = 0
self.textureBytes = 0
self.calcTextureBytes()
if self.nodePath.node().isGeomNode():
geomNode = self.nodePath.node()
for i in range(geomNode.getNumGeoms()):
geom = geomNode.getGeom(i)
self.calcVertexBytes(geom)
self.calcNumFaces(geom)
self.analyzeChildren()
def calcVertexBytes(self, geom):
vData = geom.getVertexData()
for j in range(vData.getNumArrays()):
array = vData.getArray(j)
self.selfVertexBytes += array.getDataSizeBytes()
def calcTextureBytes(self):
texCol = self.nodePath.findAllTextures()
for i in range(texCol.getNumTextures()):
tex = texCol.getTexture(i)
self.textureBytes += tex.estimateTextureMemory()
# what about shared textures by multiple nodes ?
def calcNumFaces(self, geom):
for k in range(geom.getNumPrimitives()):
primitive = geom.getPrimitive(k)
self.numFaces += primitive.getNumFaces()
def analyzeChildren(self):
for child in self.children:
child.analyze()
self.childrenVertexBytes += child.getVertexBytes()
self.numFaces += child.numFaces
def ls(self, indent = ""):
print(indent + self.nodePath.getName() + " " + str(self.vertexBytes) + " " + str(self.numFaces) + " " + str(self.textureBytes))
indent = indent + " "
for child in self.children:
child.ls(indent)