Dev talk:Source/BPython/API/ObjectCreation
Discussion: Ideas for an alternative
The main problem (well pointed by Stephen) with Campbell's scene.objects iterators was having new/add methods. It looked wrong to be able to change the number of objects, specially in a loop. But doing some more research on it, it's clear that Python itself accepts addition methods in containers with iter functionality (after all, dicts, lists, etc. can be iterators) and prevents messing with their size with a runtime error:
dict = {'one':1, 'two':2, 'three': 3} for k in dict: if k == 'two': dict['four'] = 4 print k
This triggers:
Traceback (most recent call last): File "<pyshell#7>", line 1, in -toplevel- for k in dict: RuntimeError: dictionary changed size during iteration
So, if we can code this error checking, too, scene.objects.new or .add looks nice enough.
Willian 20:33, 9 December 2006 (CET)
If we are to have scn.add() rather then scn.objects.add() have about we make it that operations on scene are always related to objects.
for ob in scn: print ob.name
len(scn)
scn.add(ob) scn.add(data= obdata) scn.remove(ob)
We can seperate other functuionality that might need adding/removing into sub iterators so there is no confusion with scn.add() and adding other data.
so we could still have scn.scriptlinks.add(script, event=...)
--Ideasman42 18:14, 10 September 2006 (CEST)
Iterators show promise, but I'd like to expand on them and have more features, otherwise they are just a fancy way to repeat what we already have:
- Still having to use Object.New() like this:
ob = scene.objects.new(Mesh.New('Cube'))
is not the best we can do. Example: for the very basic task of creating and naming an object it would translate to:
import Blender from Blender import Scene, Mesh # or import * scene = Scene.GetCurrent() ob = scene.objects.new(Mesh.New('Cube')) ob.name = 'somename'
A little too much code, just like our current situation. Been thinking about something like this:
import Blender scene = Blender.scenes.active scene.objects.add(<mesh>, dataname = 'Cube')
#so, using: scene.objects.add(type = <mesh>, name = 'Mesh',dataname = 'Mesh', data = None) #or even: scene.meshes.add(name = 'Mesh', dataname = 'Mesh', data = None) #also, to link existing objects: me = Object.Get("meshob") scene.meshes.link(me)
In other words, having a Blender.scenes iterator and iterator(s) for objects in the Scene module. Note: used "<mesh>" for type because it might be string or constant, let's see.
Anyway, still discussing / thinking.Willian18:59, 30 August 2006 (CEST)
Early stages
We're only thinking and discussing, for now. Nothing is defined yet and opinions / new ideas are welcome.
|
Update
Still thinking... also using feedback to the list or via irc from Matt Ebb, Campbell Barton, Martin Poirier, Toni Alatalo and Ken Hughes. Thanks all.
Right now I'm considering these ideas:
- Remove the need to import Blender and some / most / all its submodules and data.
- In other words, init the Python interpreter with the C equivalent of this setup:
import Blender from Blender import Scene, Mesh, Camera # ... or simply *
- Add a few things:
- Special iterators: Blender.scenes and scene.objects, too, maybe more.
- + dict like access: scene.objects['name'], which is equiv. to Object.Get('name').
- Add Blender.Data (or some other name) module to access id lists (objects, mesh data objects, etc. etc.).
- Constants in the modules themselves for easier access:
- Lamp.SUN, Lamp.SPOT, Camera.ORTHO, etc.
- ob types (also) directly in the Blender module: MESH, EMPTY, LAMP, etc
- ob primitive types, too, as: SPHERE, CUBE, etc. (or Mesh.SPHERE, Mesh.CUBE, then later Curve.BEZIER_CIRCLE, Curve.NURBS_CIRCLE, etc.) Note: we need UVSPHERE and ICOSPHERE, SPHERE (if we add it) would be an alias for the most popular of these two.
- Add scene.add():
- Campbell suggested scene.objects.new() instead, but scene.add() is looking better to me, it's less verbose, more readable. Compare these two lines:
scene.add(Mesh.New()) scene.objects.new(Mesh.New())
First, I dislike the repetition of "new" in the later, specially with one being lower and the other upper case (one of those little things that force users to learn and remember quirks). And "add" also sounds better than "new" in this case to me. But between scene.objects.add() and scene.add() I still prefer the shorter version for its simplicity and good description of what is going on: scene is a container, you're adding an object to it.
The method could accept varied input to create objects from:
scene.add(MESH) # a constant scene.add(Object.New('Mesh')) # a new object scene.add(ob) # an existing object scene.add(Mesh.New()) # ob data, object is created and linked to it scene.add(mesh) # existing ob data scene.add(SPHERE) # a constant for a primitive #or scene.add(Mesh.SPHERE) # But here's the issue with upper/lower again: MESH, Mesh scene.add(SPHERE, rings = 16, segments = 16) # keyword params # we can also extend it to accept script links: scene.add(SCRIPTLINK)
With these, here are some simple examples of complete scripts:
scn = scenes.active scn.add(CUBE) scn.add(SPHERE, rings = 10, segments = 10)
cam = Camera.New('mycam', 'ortho') light = Object.New('Lamp') scenes.active.add(cam) scenes.active.add(light)
Still considering:
- It's obvious that "scenes.active" will be needed very often, so probably we should have a Blender.scene object always pointing to it (remember that I'd like to import these names from the Blender module on startup, so Blender.something can be accessed directly, no need to import / reference the Blender module). Maybe also scene.object (for active object, if any), too. That's a tiny but important step towards a "state machine" API, something Stephen told me he's been thinking about, too. Ex:
scene.add(CUBE) print scene.object.name scenes.active = <another scene> # scenes['myscene'], for example
BUT we can have problems with Blender.scene, because of existing scripts that have vars called "scene". Because "scene = <something>" would either cause an error, if <something> is not a scene or make the passed scene the active one, something the script writer might not have intended. Well, this may not be a huge problem, let's see.
Willian 22:58, 6 September 2006 (CEST)
Question on Scene API
Hi Folks,
Objects refactor opens up a wider issue with scene, Should we make it more modular? At the moment you can do:
scn.addScriptLink() scn.remopeScriptLink()
With more data being added to the scenes (tool options), and for general API niceness, I think we should divide Scene into parts: this has already been started with renderdata and radiosity.
# At the moment we have scn.addScriptLinks() scn.getScriptLinks() scn.clearScriptLinks() # scriptlinks could be an iterator with add/remove functons scn.scriptlinks.add() scn.scriptlinks.remove() scn.scriptlinks.clear() # or = [] # We could allow access to tool settings (they are stored in the scene too) scn.tools.color= someColor scn.tools.threshold= 1.0
The question- do we want to move functionality into their own namespace.
scn.addMesh(...) is very convenient for new users but kinda pollutes the namespace IMHO.
NMesh was an example of how this was messy-
me= ob.data
you could do
me.faces.append(...)
or
me.addFace(...)
Currently we have
ob= scn.getActiveObject()
it could be
ob= scn.obejcts.active
Why support both modes?
maybe we need a wiki for this discussion also.
--Ideasman42 19:01, 30 August 2006 (CEST)