forked from bartvdbraak/blender
6acadfe982
Stupid typo in script, you couldn't go into a subgroup if it was the first property in the list. Also, name collision code needed a little work. This could result in overwriting properties with the New button, which should instead work as the rest of blender and add .XXX to the name.
498 lines
11 KiB
Python
Executable File
498 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 *
|
|
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
|
|
self.idindex = IDTypeModules[self.IDList][1]
|
|
|
|
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 >= 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
|