Dev:2.4/Source/Python/API/ObjectCreation
目次
Object Creation API
Current
These are the available ways to create an object in BPython:
Recommended
ob = Object.New(type) # type is a string: 'Mesh', 'Lamp', 'Camera', etc.
obdata = ob.data # access the new object's data
scene.link(ob) # link ob to a scene
- Pros:
- Works well, easy to understand.
- No risk of creating unlinked obdata.
- Cons:
- A little too verbose for such a common operation.
- If the script coder doesn't link to a scene we may end up with an unlinked object that also doesn't have obdata (it is only created when ob.data is first accessed or when linking to a scene).
Also possible
obdata = Mesh.New('mymesh') # using Mesh as an example
ob = Object.New('Mesh')
ob.link(obdata)
scene.link(ob)
- Pros:
- Works well, easy to understand, too.
- Cons:
- Even more verbose.
- If an error happens or the script writer forgets to link obdata to ob or ob to scene we end up with unlinked data in Blender.
- If the object is linked to a scene, first, object data is unnecessarily (in this example) created for it and later substituted by obdata at ob.link(obdata).
Summing up
The situation can and should be improved. These are our goals:
- Avoid pitfalls like the issues mentioned above.
- Present a less verbose way to create and link ob+obdata to a scene.
- Not break compatibility, if possible.
There are uses where the current API might be necessary and, more important, many scripts out there depend on it. Since we are not creating a new API right now, the best way to solve this is to have a simple and safe alternative that we can recommend users to adopt.
Planned updates
- Object.New() can be changed to accept a 'data' keyword argument:
ob = Object.New(type, name, data = None) # data can be an obdata of the right 'type'.
- NEW: Object.New() can be changed to accept a 'scene' keyword argument:
ob = Object.New(type, name, data = None, scene = None)
# The current scene is used, unless the user provides a different one.
So, with these two updates, this:
import Blender
ob = Blender.Object.New('Lamp')
data = Blender.Lamp.New()
ob.link(data)
scene = Blender.Scene.GetCurrent()
scene.link(ob)
or this:
import Blender
ob = Blender.Object.New('Lamp')
scene = Blender.Scene.GetCurrent()
scene.link(ob) # automatically adds the obdata
can safely be written as:
import Blender
ob = Blender.Object.New('Lamp')
The above changes should be added early next week, unless someone has a good point against it.
- To help create duplicates we can use a .copy() method:
ob = Object.Get(name)
ob2 = ob.copy() # normal copy
ob3 = ob.copy(linked = True) # linked copy
ten_objects = ob.copy(linked = True, count = 10) # returns list or tuple
- Notes:
- These changes don't break the current API.
Ideas for an alternative
Start with the scene
A point we all seem to agree on is that this alternative should at once create an object+obdata and link it to a scene. An elegant way to do this is to have it as a scene method.
Iterator: scene.objects
This is in Blender's CVS as an experimental feature, designed to eventually replace the current method of adding objects and dealing with the objects in the scene.
Example usage:
from Blender import Scene, Object
scn= Scene.GetCurrent()
print len(scn.objects) # Print the number of objects in the scene
scn.objects.remove(Object.Get('Cube')) # instead of scene.unlink()
scn.objects.add(someObject) # instead of scn.link()
# Adding an object from obdata in 1 step
ob= scn.objects.new(Mesh.New('Cube'))
- Pros:
- Thin wrapper, more efficient than scn.getChidren() in many cases.
- New objects are ALWAYS added to a scene and have obdata
- New objects can be made with 1 command
- Acts like a set with generic set operations.
- Gives object operations their own namespace
scn.link(ob) and scn.unlink() don't obviously refer to objects. - Scene operations that currently deal with objects can be moved into this iterator. scn.getActiveObject() can be made scn.objects.active
- Cons:
- Not compatible with current method (would have to coexist initially)
- Changes functionality unnecessarily - add() and remove() are just scn.link() and scn.unlink() renamed and in a more obscure place.
- Notes:
- Campbell already committed this to cvs, so it can be tested.
- --Ideasman42 04:36, 29 August 2006 (CEST) Writes...
Stivs was critical of the way objects uses scn.objects add()|remove()|new()
suggesting these functions should be accessible directly from the scene.
There are arguments for and against I can think of for this...
Moving object manipulation functions to the scene, ob= scn.newObject(obdata) could replace my proposed ob= scn.objects.new(obdata). However doing this opens up a namespace problem. - Scenes don't just deal with objects - if they did we could scrap scn.objects and just add iterator functions to scn.
eg. for ob in scn: print ob.name.
Separate object type creation
Instead of a general object creation function or method, we could have specific ones:
# these create objects of the indicated kind:
mesh_ob = scene.addMesh(name = 'Mesh', data = None)
lamp_ob = scene.addLamp(name = 'Lamp', type = <Spot>, data = None)
cam_ob = scene.addCamera(name = 'Camera', type = <Persp>, data = None)
#and so on
#Say we want a new mesh object linked to existing obdata:
obdata = Mesh.Get('mymeshdata') # our mesh data
ob = scene.addMesh(name = 'NewMesh', data = obdata)
- Pros:
- Clear and simple.
- Already takes care of obdata and also links to a scene.
- Cons:
- Creates a bunch of functions instead of one single scene.addObject.
- Data spesific functions are not an advantage when adding from obdata since the obdata already defines its own type.
- Functions dont obviously deal with objects only. Other functions that add elements to a scene may then be confused with obdata. - ob.addScriptLink() for eg.
- Notes:
- In the code we used placeholders <Spot> and <Persp> instead of strings because we've discussed using constants for these things everywhere (where to put these constants for easier access?).
- We can further simplify access via scenes by pre-importing Blender.Scene functions and variables in our main dictionary (but this is another discussion).
Other ideas?
<Feel free to add them>
Comments and Suggestions
- We need to be aware of the problem with curves- a curve object can't exist without at least 1 curve, this will be a problem when adding an object directly to a scene from new obdata. Maybe always have a 1 point curve at 0,0,0 --Ideasman42 05:09, 29 August 2006 (CEST)