forked from bartvdbraak/blender
6b65e39a44
- switching the define on in buildsystems (NaN, auto and msvc are done) - again import _Blender, which is the C module, from the Python modules
392 lines
11 KiB
Python
392 lines
11 KiB
Python
##
|
|
## Blender API mid level layer 01/2002 // strubi@blender.nl
|
|
##
|
|
## $Id$
|
|
##
|
|
|
|
"""The Blender Object module
|
|
|
|
This module provides **Object** manipulation routines.
|
|
|
|
Example::
|
|
|
|
from Blender import Object
|
|
ob = Object.get('Plane')
|
|
actobj = Object.getSelected()[0] # get active Object
|
|
print actobj.loc # print position
|
|
ob.makeParent([actobj]) # make ob the parent of actobj
|
|
"""
|
|
|
|
import _Blender.Object as _Object
|
|
|
|
import shadow
|
|
reload(shadow) # XXX
|
|
|
|
class _C:
|
|
pass
|
|
|
|
InstanceType = type(_C())
|
|
del _C # don't export this
|
|
|
|
|
|
def _Empty_nodata(obj):
|
|
return None
|
|
|
|
class Object(shadow.hasIPO):
|
|
"""Blender Object
|
|
|
|
A Blender Object (note the capital O) is the instance of a 3D structure,
|
|
or rather, the Object that is (normally) visible in your Blender Scene.
|
|
|
|
An instance of a Blender Object object is created by::
|
|
|
|
from Blender import Object
|
|
ob = Object.New(type) # type must be a valid type string,
|
|
# see Object.Types
|
|
|
|
...
|
|
|
|
Attributes
|
|
|
|
Note that it is in general not recommended to access the Object's
|
|
attributes directly. Please rather use the get-/set- functions instead.
|
|
|
|
loc -- position vector (LocX, LocY, LocZ)
|
|
|
|
dloc -- delta position vector (dLocX, dLocY, dLocZ)
|
|
|
|
rot -- euler rotation vector (RotX, RotY, RotZ).
|
|
Warning: this may change in future.
|
|
|
|
drot -- delta rotation euler vector (dRotX, dRotY, dRotZ)
|
|
Warning: this may change in future.
|
|
|
|
size -- scale vector (SizeX, SizeY, SizeZ)
|
|
|
|
dsize -- delta scale vector (dSizeX, dSizeY, dSizeZ)
|
|
|
|
layer -- layer bitvector (20 bit), defining what layers the object is
|
|
visible in
|
|
|
|
|
|
The following items are listed here only for compatibility to older
|
|
scripts and are READ-ONLY! **USE the get- functions instead!**
|
|
|
|
data -- reference to the data object (e.g. Mesh, Camera, Lamp, etc.)
|
|
|
|
parent -- reference to the parent object, if existing, 'None' otherwise.
|
|
|
|
track -- reference to the tracked object, if existing, 'None' otherwise.
|
|
|
|
This bit mask can be read and written:
|
|
|
|
colbits -- the Material usage mask. A set bit #n means:
|
|
The Material #n in the *Object's* material list is used.
|
|
Otherwise, the Material #n of the Objects *Data* material list
|
|
is displayed.
|
|
"""
|
|
|
|
def __init__(self, object = None):
|
|
"""Returns an empty shadow Object"""
|
|
self._object = object
|
|
|
|
def __repr__(self):
|
|
return "[Object \"%s\"]" % self.name
|
|
|
|
def link(self, data):
|
|
"""Links Object 'self' with data 'data'. The data type must match
|
|
the Object's type, so you cannot link a Lamp to a mesh type Object.
|
|
'data' can also be an Ipo object (IpoBlock)
|
|
"""
|
|
from _Blender import Types
|
|
# special case for NMesh:
|
|
if type(data) == Types.NMeshType:
|
|
return self._object.link(data)
|
|
elif type(data) == InstanceType:
|
|
if data.__class__.__name__ == "rawMesh":
|
|
data.update() # update mesh
|
|
elif data.__class__.__name__ == "IpoBlock":
|
|
self.setIpo(data)
|
|
|
|
return shadow._link(self, data)
|
|
|
|
def copy(self):
|
|
"""Returns a copy of 'self'.
|
|
This is a true, linked copy, i.e. the copy shares the same data as the
|
|
original. The returned object is *free*, meaning, not linked to any scene."""
|
|
return Object(self._object.copy())
|
|
|
|
#def clone(self):
|
|
#"""Makes a clone of the specified object in the current scene and
|
|
##returns its reference"""
|
|
#return Object(self._object.clone())
|
|
|
|
def shareFrom(self, object):
|
|
"""Link data of 'self' with data of 'object'. This works only if
|
|
'object' has the same type as 'self'."""
|
|
return Object(self._object.shareFrom(object._object))
|
|
|
|
def getMatrix(self):
|
|
"""Returns the object matrix"""
|
|
return self._object.getMatrix()
|
|
|
|
def getInverseMatrix(self):
|
|
"""Returns the object's inverse matrix"""
|
|
return self._object.getInverseMatrix()
|
|
|
|
def getData(self):
|
|
"Returns the Datablock object containing the object's data, e.g. Mesh"
|
|
t = self._object.getType()
|
|
data = self._object.data
|
|
try:
|
|
return self._dataWrappers[t][1](data)
|
|
except:
|
|
raise TypeError, "getData() not yet supported for this object type"
|
|
|
|
def getDeformData(self):
|
|
"""Returns the Datablock object containing the object's deformed data.
|
|
Currently, this is only supported for a Mesh"""
|
|
import _Blender.NMesh as _NMesh
|
|
t = self._object.getType()
|
|
if t == self.Types['Mesh']:
|
|
data = _NMesh.GetRawFromObject(self.name)
|
|
return self._dataWrappers[t][1](data)
|
|
else:
|
|
raise TypeError, "getDeformData() not yet supported for this object type"
|
|
|
|
def getType(self):
|
|
"Returns type string of Object, which is one of Object.Types.keys()"
|
|
t = self._object.getType()
|
|
try:
|
|
return self._dataWrappers[t][0]
|
|
except:
|
|
return "<unsupported>"
|
|
|
|
def getParent(self):
|
|
"Returns object's parent object"
|
|
if self._object.parent:
|
|
return Object(self._object.parent)
|
|
return None
|
|
|
|
def getTracked(self):
|
|
"Returns object's tracked object"
|
|
if self._object.track:
|
|
return Object(self._object.track)
|
|
return None
|
|
|
|
# FUTURE FEATURE :-) :
|
|
# def getLocation():
|
|
# """Returns the object's location (x, y, z).
|
|
#By default, the location vector is always relative to the object's parent.
|
|
#If the location of another coordinate system is wanted, specify 'origin' by
|
|
#the object whose coordinate system the location should be calculated in.
|
|
|
|
#If world coordinates are wanted, set 'relative' = "World"."""
|
|
|
|
def getLocation(self, relative = None):
|
|
"""Returns the object's location (x, y, z). For the moment,
|
|
'relative' has no effect."""
|
|
l = self._object.loc
|
|
return (l[0], l[1], l[2])
|
|
|
|
def setLocation(self, location, relative = None):
|
|
"""Sets the object's location. 'location' must be a vector triple.
|
|
See 'getLocation()' about relative coordinate systems."""
|
|
l = self._object.loc # make sure this is copied
|
|
l[0], l[1], l[2] = location
|
|
|
|
def getDeltaLocation(self):
|
|
"""Returns the object's delta location (x, y, z)"""
|
|
l = self._object.dloc
|
|
return (l[0], l[1], l[2])
|
|
|
|
def setDeltaLocation(self, delta_location):
|
|
"""Sets the object's delta location which must be a vector triple"""
|
|
l = self._object.dloc # make sure this is copied
|
|
l[0], l[1], l[2] = delta_location
|
|
|
|
def getEuler(self):
|
|
"""Returns the object's rotation as Euler rotation vector
|
|
(rotX, rotY, rotZ)"""
|
|
e = self._object.rot
|
|
return (e[0], e[1], e[2])
|
|
|
|
def setEuler(self, euler = (0.0, 0.0, 0.0)):
|
|
"""Sets the object's rotation according to the specified Euler angles.
|
|
'euler' must be a vector triple"""
|
|
e = self._object.rot
|
|
e[0], e[1], e[2] = euler
|
|
|
|
def makeParent(self, objlist, mode = 0, fast = 0):
|
|
"""Makes 'self' the parent of the objects in 'objlist' which must be
|
|
a list of valid Objects.
|
|
If specified:
|
|
|
|
mode -- 0: make parent with inverse
|
|
|
|
1: without inverse
|
|
|
|
fast -- 0: update scene hierarchy automatically
|
|
|
|
1: don't update scene hierarchy (faster). In this case, you
|
|
must explicitely update the Scene hierarchy, see:
|
|
'Blender.Scene.getCurrent().update()'"""
|
|
list = map(lambda x: x._object, objlist)
|
|
return Object(self._object.makeParent(list, mode, fast))
|
|
|
|
def clrParent(self, mode = 0, fast = 0):
|
|
"""Clears parent object.
|
|
If specified:
|
|
|
|
mode -- 2: keep object transform
|
|
|
|
fast > 0 -- don't update scene hierarchy (faster)"""
|
|
return Object(self._object.clrParent(mode, fast))
|
|
|
|
def getMaterials(self):
|
|
"""Returns list of materials assigned to the object"""
|
|
from Blender import Material
|
|
return shadow._List(self._object.getMaterials(), Material.Material)
|
|
|
|
def setMaterials(self, materials = []):
|
|
"""Sets materials. 'materials' must be a list of valid material objects"""
|
|
o = self._object
|
|
old_mask = o.colbits
|
|
o.colbits = -1 # set material->object linking
|
|
o.setMaterials(map(lambda x: x._object, materials))
|
|
o.colbits = old_mask
|
|
|
|
def materialUsage(self, flag):
|
|
"""Determines the way the material is used and returns status.
|
|
|
|
'flag' = 'Data' : Materials assigned to the object's data are shown. (default)
|
|
|
|
'flag' = 'Object' : Materials assigned to the object are shown.
|
|
|
|
The second case is desired when the object's data wants to be shared among
|
|
objects, but not the Materials assigned to their data. See also 'colbits'
|
|
attribute for more (and no future compatible) control."""
|
|
if flag == "Object":
|
|
self._object.colbits = -1
|
|
elif flag == "Data":
|
|
self._object.colbits = 0
|
|
return self._object.colbits
|
|
else:
|
|
raise TypeError, "unknown mode %s" % flag
|
|
|
|
_getters = {}
|
|
|
|
from Blender import Mesh, Camera, Lamp
|
|
|
|
t = _Object.Types
|
|
Types = {"Camera" : t.CAMERA,
|
|
"Empty" : t.EMPTY,
|
|
"Lamp" : t.LAMP,
|
|
"Mesh" : t.MESH,
|
|
}
|
|
|
|
# create lookup table for data wrappers
|
|
_dataWrappers = range(max(Types.values()) + 1)
|
|
_dataWrappers[t.MESH] = ("Mesh", Mesh.rawMesh)
|
|
_dataWrappers[t.CAMERA] = ("Camera", Camera.Camera)
|
|
_dataWrappers[t.LAMP] = ("Lamp", Lamp.Lamp)
|
|
_dataWrappers[t.EMPTY] = ("Empty", _Empty_nodata)
|
|
|
|
t = _Object.DrawTypes
|
|
DrawTypes = {"Bounds" : t.BOUNDBOX,
|
|
"Wire" : t.WIRE,
|
|
"Solid" : t.SOLID,
|
|
"Shaded" : t.SHADED,
|
|
}
|
|
|
|
t = _Object.DrawModes
|
|
DrawModes = {"axis" : t.AXIS,
|
|
"boundbox" : t.BOUNDBOX,
|
|
"texspace" : t.TEXSPACE,
|
|
"name" : t.NAME,
|
|
}
|
|
|
|
|
|
del t
|
|
del Mesh, Camera, Lamp
|
|
|
|
def getDrawMode(self):
|
|
"""Returns the Object draw modes as a list of strings"""
|
|
return shadow._getModeBits(self.DrawModes, self._object.drawMode)
|
|
|
|
def setDrawMode(self, *args):
|
|
"""Sets the Object's drawing modes as a list of strings"""
|
|
self._object.drawMode = shadow._setModeBits(self.DrawModes, args)
|
|
|
|
def getDrawType(self):
|
|
"""Returns the Object draw type"""
|
|
for k in self.DrawTypes.keys():
|
|
if self.DrawTypes[k] == self.drawType:
|
|
return k
|
|
|
|
def setDrawType(self, name):
|
|
"""Sets the Object draw type. 'name' must be one of:
|
|
|
|
* 'Bounds' : Draw bounding box only
|
|
|
|
* 'Wire' : Draw in wireframe mode
|
|
|
|
* 'Solid' : Draw solid
|
|
|
|
* 'Shaded' : Draw solid, shaded and textures
|
|
"""
|
|
try:
|
|
self._object.drawType = self.DrawTypes[name]
|
|
except:
|
|
raise TypeError, "type must be one of %s" % self.DrawTypes.keys()
|
|
|
|
|
|
##################
|
|
# MODULE FUNCTIONS
|
|
|
|
def New(objtype, name = None):
|
|
"""Creates a new, empty object and returns it.
|
|
'objtype' is a string and must be one of::
|
|
|
|
Camera
|
|
Empty
|
|
Mesh
|
|
Lamp
|
|
|
|
More object types will be supported in future.
|
|
|
|
Example::
|
|
|
|
ob = Object.New('Camera')
|
|
"""
|
|
|
|
if type(objtype) == type(0):
|
|
obj = Object(_Object.New(objtype)) # emulate old syntax
|
|
else:
|
|
t = Object.Types[objtype]
|
|
obj = Object(_Object.New(t))
|
|
return obj
|
|
|
|
def get(name = None):
|
|
"""If 'name' given, the Object 'name' is returned if existing, 'None' otherwise.
|
|
If no name is given, a list of all Objects is returned"""
|
|
if name:
|
|
ob = _Object.get(name)
|
|
if ob:
|
|
return Object(ob)
|
|
else:
|
|
return None
|
|
else:
|
|
return shadow._List(_Object.get(), Object)
|
|
|
|
Get = get # emulation
|
|
|
|
def getSelected():
|
|
"""Returns a list of selected Objects in the active layer(s).
|
|
The active object is the first in the list, if visible"""
|
|
return shadow._List(_Object.getSelected(), Object)
|
|
|
|
GetSelected = getSelected # emulation
|
|
|
|
Types = _Object.Types # for compatibility
|