forked from bartvdbraak/blender
7a19fe19f6
Turned out somehow I managed to miss adding the proper type refs in Blender.Types for IDGroupType and IDArrayType, which made the script not work. So, I've got it all fixed now. Or at least hopefully :)
497 lines
11 KiB
Python
Executable File
497 lines
11 KiB
Python
Executable File
#!BPY
|
|
|
|
"""
|
|
Name: 'ID Property Browser'
|
|
Blender: 242
|
|
Group: 'Help'
|
|
Tooltip: 'Browse ID properties'
|
|
"""
|
|
|
|
__author__ = "Joe Eagar"
|
|
__version__ = "0.3.108"
|
|
__email__ = "joeedh@gmail.com"
|
|
__bpydoc__ = """\
|
|
|
|
Allows browsing, creating and editing of ID Properties
|
|
for various ID block types such as mesh, scene, object,
|
|
etc.
|
|
"""
|
|
|
|
|
|
from Blender import *
|
|
from Blender.BGL import *
|
|
from Blender.Types import IDGroupType, IDArrayType
|
|
import Blender
|
|
|
|
def IsInRectWH(mx, my, x, y, wid, hgt):
|
|
if mx >= x and mx <= x + wid:
|
|
if my >= y and my <= y + hgt:
|
|
return 1
|
|
return 0
|
|
|
|
Button_Back = 1
|
|
Button_New = 2
|
|
Button_MatMenu = 3
|
|
Button_TypeMenu = 4
|
|
|
|
ButStart = 55
|
|
|
|
IDP_String = 0
|
|
IDP_Int = 1
|
|
IDP_Float = 2
|
|
IDP_Array = 5
|
|
IDP_Group = 6
|
|
|
|
ButDelStart = 255
|
|
#max limit for string input button
|
|
strmax = 100
|
|
|
|
State_Normal = 0
|
|
State_InArray = 1
|
|
|
|
#IDTypeModules entries are of form [module, active_object_index, module_name]
|
|
IDTypeModules = [[Scene, 0, "Scenes"], [Object, 0, "Objects"], [Mesh, 0, "Meshes"]]
|
|
IDTypeModules += [[Material, 0, "Materials"], [Texture, 0, "Textures"]]
|
|
IDTypeModules += [[Image, 0, "Images"]]
|
|
|
|
class IDArrayBrowser:
|
|
array = 0
|
|
parentbrowser = 0
|
|
buts = 0
|
|
|
|
def __init__(self):
|
|
self.buts = []
|
|
|
|
def Draw(self):
|
|
pb = self.parentbrowser
|
|
x = pb.x
|
|
y = pb.y
|
|
width = pb.width
|
|
height = pb.height
|
|
pad = pb.pad
|
|
itemhgt = pb.itemhgt
|
|
cellwid = 65
|
|
y = y + height - itemhgt - pad
|
|
|
|
Draw.PushButton("Back", Button_Back, x, y, 40, 20)
|
|
y -= itemhgt + pad
|
|
|
|
self.buts = []
|
|
|
|
for i in xrange(len(self.array)):
|
|
st = ""
|
|
if type(self.array[0]) == type(0.0):
|
|
st = "%.5f" % self.array[i]
|
|
else: st = str(self.array[i])
|
|
|
|
b = Draw.String("", ButStart+i, x, y, cellwid, itemhgt, st, 30)
|
|
self.buts.append(b)
|
|
x += cellwid + pad
|
|
if x + cellwid + pad > width:
|
|
x = 0
|
|
y -= itemhgt + pad
|
|
|
|
def Button(self, bval):
|
|
if bval == Button_Back:
|
|
self.parentbrowser.state = State_Normal
|
|
self.parentbrowser.array = 0
|
|
self.buts = []
|
|
Draw.Draw()
|
|
self.array = 0
|
|
elif bval >= ButStart:
|
|
i = bval - ButStart
|
|
st = self.buts[i].val
|
|
n = 0
|
|
if type(self.array[0]) == type(0.0):
|
|
try:
|
|
n = int(st)
|
|
except:
|
|
return
|
|
elif type(self.array[0]) == type(0):
|
|
try:
|
|
n = float(st)
|
|
except:
|
|
return
|
|
|
|
self.array[i] = n
|
|
Draw.Draw()
|
|
|
|
def Evt(self, evt, val):
|
|
if evt == Draw.ESCKEY:
|
|
Draw.Exit()
|
|
|
|
class IDPropertyBrowser:
|
|
width = 0
|
|
height = 0
|
|
x = 0
|
|
y = 0
|
|
scrollx = 0
|
|
scrolly = 0
|
|
itemhgt = 22
|
|
pad = 2
|
|
|
|
group = 0
|
|
parents = 0 #list stack of parent groups
|
|
active_item = -1
|
|
mousecursor = 0
|
|
_i = 0
|
|
buts = []
|
|
|
|
state = 0
|
|
array = 0
|
|
prop = 0
|
|
|
|
IDList = 0
|
|
idindex = 0
|
|
idblock = 0
|
|
|
|
type = 0 # attach buildin type() method to class
|
|
# since oddly it's not available to button
|
|
# callbacks! EEK! :(
|
|
|
|
def __init__(self, idgroup, mat, x, y, wid, hgt):
|
|
self.group = idgroup
|
|
self.prop = idgroup
|
|
self.x = x
|
|
self.y = y
|
|
self.width = wid
|
|
self.height = hgt
|
|
self.mousecursor = [0, 0]
|
|
self.parents = []
|
|
self.idblock = mat
|
|
self.type = type
|
|
|
|
def DrawBox(self, glmode, x, y, width, height):
|
|
glBegin(glmode)
|
|
glVertex2f(x, y)
|
|
glVertex2f(x+width, y)
|
|
glVertex2f(x+width, y+height)
|
|
glVertex2f(x, y+height)
|
|
glEnd()
|
|
|
|
def Draw(self):
|
|
global IDTypeModules
|
|
|
|
#first draw outlining box :)
|
|
glColor3f(0, 0, 0)
|
|
self.DrawBox(GL_LINE_LOOP, self.x, self.y, self.width, self.height)
|
|
|
|
itemhgt = self.itemhgt
|
|
pad = self.pad
|
|
x = self.x
|
|
y = self.y + self.height - itemhgt - pad
|
|
|
|
if self.state == State_InArray:
|
|
self.array.Draw()
|
|
return
|
|
|
|
plist = []
|
|
self.buts = []
|
|
for p in self.group.iteritems():
|
|
plist.append(p)
|
|
|
|
#-------do top buttons----------#
|
|
Draw.PushButton("New", Button_New, x, y, 40, 20)
|
|
x += 40 + pad
|
|
#do the menu button for all materials
|
|
st = ""
|
|
|
|
blocks = IDTypeModules[self.IDList][0].Get()
|
|
i = 1
|
|
mi = 0
|
|
for m in blocks:
|
|
if m.name == self.idblock.name:
|
|
mi = i
|
|
st += m.name + " %x" + str(i) + "|"
|
|
i += 1
|
|
|
|
self.menubut = Draw.Menu(st, Button_MatMenu, x, y, 100, 20, mi)
|
|
|
|
x += 100 + pad
|
|
|
|
st = ""
|
|
i = 0
|
|
for e in IDTypeModules:
|
|
st += e[2] + " %x" + str(i+1) + "|"
|
|
i += 1
|
|
|
|
cur = self.IDList + 1
|
|
self.idmenu = Draw.Menu(st, Button_TypeMenu, x, y, 100, 20, cur)
|
|
x = self.x
|
|
y -= self.itemhgt + self.pad
|
|
|
|
#-----------do property items---------#
|
|
i = 0
|
|
while y > self.y - 20 - pad and i < len(plist):
|
|
k = plist[i][0]
|
|
p = plist[i][1]
|
|
if i == self.active_item:
|
|
glColor3f(0.5, 0.4, 0.3)
|
|
self.DrawBox(GL_POLYGON, x+pad, y, self.width-pad*2, itemhgt)
|
|
|
|
glColor3f(0, 0, 0)
|
|
self.DrawBox(GL_LINE_LOOP, x+pad, y, self.width-pad*2, itemhgt)
|
|
|
|
glRasterPos2f(x+pad*2, y+3)
|
|
Draw.Text(str(k)) #str(self.mousecursor) + " " + str(self.active_item)) #p.name)
|
|
tlen = Draw.GetStringWidth(str(k))
|
|
|
|
if type(p) == type(""):
|
|
b = Draw.String("", ButStart+i, x+pad*5+tlen, y, 200, itemhgt, p, strmax)
|
|
self.buts.append(b)
|
|
elif type(p) in [type(0), type(0.0)]:
|
|
#only do precision to 5 points on floats
|
|
st = ""
|
|
if type(p) == type(0.0):
|
|
st = "%.5f" % p
|
|
else: st = str(p)
|
|
b = Draw.String("", ButStart+i, x+pad*5+tlen, y, 75, itemhgt, st, strmax)
|
|
self.buts.append(b)
|
|
else:
|
|
self.buts.append(None)
|
|
|
|
Draw.PushButton("Del", ButDelStart+i, x+self.width-35, y, 30, 20)
|
|
|
|
i += 1
|
|
y -= self.itemhgt + self.pad
|
|
|
|
if len(self.parents) != 0:
|
|
Draw.PushButton("Back", Button_Back, x, y, 40, 20)
|
|
x = x + 40 + pad
|
|
|
|
def SetActive(self):
|
|
m = self.mousecursor
|
|
itemhgt = self.itemhgt
|
|
pad = self.pad
|
|
|
|
x = self.x + pad
|
|
y = self.y + self.height - itemhgt - pad - itemhgt
|
|
|
|
plist = []
|
|
for p in self.group.iteritems():
|
|
plist.append(p)
|
|
|
|
self.active_item = -1
|
|
i = 0
|
|
while y > self.y and i < len(plist):
|
|
p = plist[i]
|
|
if IsInRectWH(m[0], m[1], x, y, self.width-pad, itemhgt):
|
|
self.active_item = i
|
|
|
|
i += 1
|
|
y -= self.itemhgt + self.pad
|
|
|
|
def EventIn(self, evt, val):
|
|
if self.state == State_InArray:
|
|
self.array.Evt(evt, val)
|
|
|
|
if evt == Draw.ESCKEY:
|
|
Draw.Exit()
|
|
if evt == Draw.MOUSEX or evt == Draw.MOUSEY:
|
|
size = Buffer(GL_FLOAT, 4)
|
|
glGetFloatv(GL_SCISSOR_BOX, size)
|
|
if evt == Draw.MOUSEX:
|
|
self.mousecursor[0] = val - size[0]
|
|
else:
|
|
self.mousecursor[1] = val - size[1]
|
|
del size
|
|
|
|
self.SetActive()
|
|
self._i += 1
|
|
if self._i == 5:
|
|
Draw.Draw()
|
|
self._i = 0
|
|
|
|
plist = []
|
|
for p in self.group.iteritems():
|
|
plist.append(p)
|
|
|
|
if evt == Draw.LEFTMOUSE and val == 1:
|
|
a = self.active_item
|
|
if a >= 0 and a < len(plist):
|
|
p = plist[a]
|
|
|
|
basictypes = [IDGroupType, type(0.0), type(""), type(0)]
|
|
if type(p[1]) == IDGroupType:
|
|
self.parents.append(self.group)
|
|
self.group = p[1]
|
|
self.active_item = -1
|
|
Draw.Draw()
|
|
elif type(p[1]) == IDArrayType:
|
|
self.array = IDArrayBrowser()
|
|
self.array.array = p[1]
|
|
self.array.parentbrowser = self
|
|
self.state = State_InArray
|
|
Draw.Draw()
|
|
|
|
if evt == Draw.TKEY and val == 1:
|
|
try:
|
|
self.prop['float'] = 0.0
|
|
self.prop['int'] = 1
|
|
self.prop['string'] = "hi!"
|
|
self.prop['float array'] = [0, 0, 1.0, 0]
|
|
self.prop['int array'] = [0, 0, 0, 0]
|
|
self.prop.data['a subgroup'] = {"int": 0, "float": 0.0, "anothergroup": {"a": 0.0, "intarr": [0, 0, 0, 0]}}
|
|
Draw.Draw()
|
|
except:
|
|
Draw.PupMenu("Can only do T once per block, the test names are already taken!")
|
|
|
|
|
|
def Button(self, bval):
|
|
global IDTypeModules
|
|
if self.state == State_InArray:
|
|
self.array.Button(bval)
|
|
return
|
|
|
|
if bval == Button_MatMenu:
|
|
global IDTypeModules
|
|
|
|
val = self.idindex = self.menubut.val - 1
|
|
i = self.IDList
|
|
block = IDTypeModules[i][0].Get()[val]
|
|
self.idblock = block
|
|
self.prop = block.properties
|
|
self.group = self.prop
|
|
self.active_item = -1
|
|
self.parents = []
|
|
Draw.Draw()
|
|
|
|
if bval == Button_TypeMenu:
|
|
i = IDTypeModules[self.idmenu.val-1]
|
|
if len(i[0].Get()) == 0:
|
|
Draw.PupMenu("Error%t|There are no " + i[2] + "!")
|
|
return
|
|
|
|
IDTypeModules[self.IDList][1] = self.idindex
|
|
self.IDList = self.idmenu.val-1
|
|
val = self.idindex = IDTypeModules[self.IDList][1]
|
|
i = self.IDList
|
|
block = IDTypeModules[i][0].Get()[val]
|
|
self.idblock = block
|
|
self.prop = block.properties
|
|
self.group = self.prop
|
|
self.active_item = -1
|
|
self.parents = []
|
|
Draw.Draw()
|
|
|
|
if bval >= ButDelStart:
|
|
plist = []
|
|
for p in self.group:
|
|
plist.append(p)
|
|
prop = plist[bval - ButDelStart]
|
|
del self.group[prop]
|
|
Draw.Draw()
|
|
|
|
elif bval >= ButStart:
|
|
plist = []
|
|
for p in self.group.iteritems():
|
|
plist.append(p)
|
|
|
|
prop = plist[bval - ButStart]
|
|
print prop
|
|
|
|
if self.type(prop[1]) == self.type(""):
|
|
self.group[prop[0]] = self.buts[bval - ButStart].val
|
|
elif self.type(prop[1]) == self.type(0):
|
|
i = self.buts[bval - ButStart].val
|
|
try:
|
|
i = int(i)
|
|
self.group[prop[0]] = i
|
|
except:
|
|
Draw.Draw()
|
|
return
|
|
Draw.Draw()
|
|
elif self.type(prop[1]) == self.type(0.0):
|
|
f = self.buts[bval - ButStart].val
|
|
try:
|
|
f = float(f)
|
|
self.group[prop[0]] = f
|
|
except:
|
|
Draw.Draw()
|
|
return
|
|
Draw.Draw()
|
|
|
|
elif bval == Button_Back:
|
|
self.group = self.parents[len(self.parents)-1]
|
|
self.parents.pop(len(self.parents)-1)
|
|
Draw.Draw()
|
|
|
|
elif bval == Button_New:
|
|
name = Draw.Create("untitled")
|
|
stype = Draw.Create(0)
|
|
gtype = Draw.Create(0)
|
|
ftype = Draw.Create(0)
|
|
itype = Draw.Create(0)
|
|
atype = Draw.Create(0)
|
|
|
|
block = []
|
|
block.append(("Name: ", name, 0, 30, "Click to type in the name of the new ID property"))
|
|
block.append("Type")
|
|
block.append(("String", stype))
|
|
block.append(("Subgroup", gtype))
|
|
block.append(("Float", ftype))
|
|
block.append(("Int", itype))
|
|
block.append(("Array", atype))
|
|
|
|
retval = Blender.Draw.PupBlock("New IDProperty", block)
|
|
if retval == 0: return
|
|
|
|
name = name.val
|
|
i = 1
|
|
stop = 0
|
|
while stop == 0:
|
|
stop = 1
|
|
for p in self.group:
|
|
if p == name:
|
|
d = name.rfind(".")
|
|
if d != -1:
|
|
name = name[:d]
|
|
name = name + "." + str(i).zfill(3)
|
|
i += 1
|
|
stop = 0
|
|
|
|
type = "String"
|
|
if stype.val:
|
|
self.group[name] = ""
|
|
elif gtype.val:
|
|
self.group[name] = {}
|
|
elif ftype.val:
|
|
self.group[name] = 0.0
|
|
elif itype.val:
|
|
self.group[name] = 0 #newProperty("Int", name, 0)
|
|
elif atype.val:
|
|
arrfloat = Draw.Create(0)
|
|
arrint = Draw.Create(0)
|
|
arrlen = Draw.Create(3)
|
|
block = []
|
|
block.append("Type")
|
|
block.append(("Float", arrfloat, "Make a float array"))
|
|
block.append(("Int", arrint, "Make an integer array"))
|
|
block.append(("Len", arrlen, 2, 200))
|
|
retval = Blender.Draw.PupBlock("Array Properties", block)
|
|
|
|
if retval:
|
|
tmpl = "Float"
|
|
if arrfloat.val:
|
|
tmpl = 0.0
|
|
elif arrint.val:
|
|
tmpl = 0
|
|
arr = [tmpl for x in xrange(arrlen.val)]
|
|
self.group[name] = arr
|
|
|
|
|
|
def Go(self):
|
|
Draw.Register(self.Draw, self.EventIn, self.Button)
|
|
|
|
scenes = Scene.Get()
|
|
|
|
size = Window.GetAreaSize()
|
|
browser = IDPropertyBrowser(scenes[0].properties, scenes[0], 2, 2, size[0], size[1])
|
|
browser.Go()
|
|
|
|
#a = prop.newProperty("String", "hwello!", "bleh")
|
|
#b = prop.newProperty("Group", "subgroup")
|
|
|
|
#for p in prop:
|
|
#print p.name
|