Object Creation API
These are the available ways to create an object in BPython:
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
- Works well, easy to understand.
- No risk of creating unlinked obdata.
- 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).
obdata = Mesh.New('mymesh') # using Mesh as an example ob = Object.New('Mesh') ob.link(obdata) scene.link(ob)
- Works well, easy to understand, too.
- 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).
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.
- 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)
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
- 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.
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.
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'))
- 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
- 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.
- 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)
- Clear and simple.
- Already takes care of obdata and also links to a scene.
- 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.
- 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).
<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)