Skip to content

Archive

Tag: Scripting

This A-Z list is a work in progress; just started :)

Add a new material

scene.objects.active = myObject
bpy.ops.object.material_slot_add() # add a material slot to active object
material = bpy.data.materials.new(“gold”)
# assuming the object previously had no material slots, otherwise search for empty slot
myObject.materials[0] = silver

Create an object

foo = bpy.data.objects.new(name=”foo”, object_data = data)
scene.objects.link( foo)

Create a mesh

mesh = bpy.data.meshes.new(“mesh”)

Populate using from_pydata(vertices,edges,faces). For example:

verts = [ ( 0,0,0), (1,0,0), (1,1,0), (0,1,0) ] # a square
edges = [] # usually not needed, but, e.g. [ (0,1), (1,2), (2,3), (3,0) ]
faces = [ (0,1,2,3) ] # connecting the square corners; can use 3, 4 points or more!
mesh.from_pydata(verts, edges, faces)

Duplicate an object

Method 1: bpy.ops.object.duplicate()

  • bpy.ops.object.duplicate() – duplicate currently selected objects (deep copy)
  • bpy.ops.object.duplicate( linked = True ) – duplicate currently selected objects (shallow copy – mesh and other properties should be shared).

@see make an object the only active, selected object

Method 2: create a new object and duplicate properties

The disadvantage of this is that duplicating all properties can be hard.

@see create an object

Get the current scene

bpy.context.scene

Get the scale (‘unit’) of the current scene

scene.unit_settings.scale_length

Make an object the active, selected object

Assume an object named X

for k in bpy.data.objects:
    k.select = False
X.select = True
scene.objects.active =  X

Set an object’s location

object.location = (x ,y ,z )

This post won’t give you all the information you need if you’re simply new to Blender Scripting. Many of us, however, continued scripting Blender 2.49 because 2.5 scripting wasn’t stable at the beginning. I’m quite sure this post can help you to migrate your scripts from 2.49 although it’s very hands on and I haven’t really tried to organize these useful bits.

  • Export script template (source code). This shows how to arrange metadata, invoke the file selector and write simple output to a file (to make sure something’s actually happening). Includes summary instructions to install the script.

I updated my exporter, Ox3ich, although not with all the features of the current 2.49 version. After trying it out a little I will make it available. In the meantime I list just a few of the many differences between the 2.49 / 2.59 APIs.

Writing I/O scripts for Blender 2.5 isn’t exactly what I’d like to do at the moment. I just have to. Scripting integration looks interesting, with a little more flexibility than in 2.4. Useful links…

As usual, looking at existing scripts will help. The documentation isn’t awesome.

Script Registration

  • The registration process has changed. The easy part is updating your metadata (just look at any of the scripts bundled with 2.5).
  • Scripts now require register/unregister methods. This allows tighter integration as far as I can see, notably it makes it easy/possible for a script to call another script.

Your script/add-on won’t automatically show in the designated menu, but it should appear under [file > user preferences > add-ons] where you can enable it. Then save user prefs (save as default option in the bottom left) to keep the script enabled next time. This page gives a little information about registering add-ons.

2.49 => 2.59 scripting : Miscellaneous changes

  • access current scene - bpy.context.scene
  • get object data (e.g mesh) – object.data
  • Blender.sys.join => os.path.join
  • Writing strings to output stream, see stack overflow answer (python 3.0)
  • mesh.verts => mesh.vertices
  • faces.verts => face.vertices - additionally, face.vertices is now an array of ints representing vertex indexing.
  • face.mat => face.material_index
  • mesh.getFromObject => object.to_mesh(bpy.context.scene,True,”PREVIEW”)
  • vertex.no => vertex.normal (but still uses vertex.co for ‘coord/coordinate’)
  • to change the current frame, use scene.frame_set(). Do not directly assign the frame number. Note that frame numbers start at 0, not 1.

There are changes from Python 2.x to Python 3.x in the way global variables are handled; this combines with a change in the way scripts are invoked, adding up to annoyances when trying a quick and dirty way to output debug info to a file…

Vertex colors

Vertex color data is now separate from face data, stored in Mesh.vertex_colors; additionally this now supports multiple layers, and colors are now in rgb float format (think it used to be rgba, byte format)

  • Iterate layers with something like for layer in mesh.vertex_colors
  • layer.active to find if a layer is active.
  • get layer data: layer.data
  • get vertex color for a face: layer.data[i], will contain corner colors for face at index i.
  • example 1: mesh.vertex_colors[0].data[1].color4[0]
    Red component for corner 4 in face 1, vcol layer 0 of mesh
  • example 2: mesh.vertex_colors[0].data[0].color1.r
  • Red component for corner 1, face 0, vcol layer 0 of mesh

Random links

So what makes me feel like scripting XCode?

  • Not being able to sort group items alphabetically (or maybe I just don’t know)
  • Adding assets manually. Although to be fair, the problem is more likely that my asset exporter generates many junk files I do not want to add (don’t ask)
  • Objective C Properties. Having said that, is a macro worse than a script, and more importantly, does it even matter?
  • Turning project groups into folders (or maybe I just don’t know how)
  • Typing signatures whenever I need to implement a protocol…
  • Project files are hard to understand, even harder to modify.
  • … (1)

We can script XCode using either applescript or python

I can’t kick myself to read any of this today.

(1) Didn’t think of anything else, but feels right.

In my previous article, I drafted/debugged basic combat behavior in a game prototype. A simple combat system probably needs to account for the following – if only to get animations to sync correctly if character actions are independent.

  • Impact Frame – unless you have fine grained collision detection, the impact frame determines when the opponent actually gets hit.
    I am adding per action impact frames – each action can define it’s own frame/time offset. I’ll probably use a time offset instead later, but that will be part of a general effort on my part to move from frame based to time based modelling.
  • Passive reaction – When an actor gets hit, they cannot enforce their decisions.
  • Impact condition. A simple model can take into account the orientation relative to, and distance from, the target. My model already has this but that seems a little buggy.

Writing a class to hold impact frames is nothing, although you might legitimately want to store your impact frame information anywhere else:

#import “ImpactFrames.h”

#import “Definitions.h” // used for the ‘act’ typedef which is just a NSString*

@implementation ImpactFrames

static NSMutableDictionary* map;

+(void)putFrameOffset:(int)frameOffset forAction:(act)action{

if (map==nil)map=[[NSMutableDictionary alloc]init];

[map setObject:[NSNumber numberWithInt:frameOffset] forKey:action];

}

+(int)getFrameOffset:(act)forAction{

return [((NSNumber*)[map objectForKey:forAction]) intValue];

}

+(void)clear{

[map release];

map=nil;

}

@end

Passive reactions can be implemented using three tags: action, affect and activity

  • Activity represents the current action.
  • Affect represents a passive reaction to an external action
  • Action represents the actor’s decision.

Then each evaluation can be structured as follows:

  1. If an affect is defined, override action with affect
  2. If the current activity matches the current action, continue.
    1. If we have not reached the last frame for this action, continue to the next frame.
    2. If we have reached the last frame, clear the affect and action labels.
  3. If the current activity is the ‘rip state’ return immediately.
  4. If the current action is different from the current activity, initialize this action.

I had to patch my actions a little because I manage motion and activity independently, so I need to replicate some of the logic.

I have this little character that goes on to hit an NPC for a test, and the NPC dies on the spot. Actually, now that I remember, I have an animation for the death of my NPC. What I want to make happen:

  • The PC getting hit
    • A NPC needs to aim their action at the PC.
    • User interaction needs to be disabled while the PC register the hit.
    • An animation needs to be played.
    • Other effects may be seen, e.g. lose life points
  • The NPC not chasing after the PC while dying (that’s a bug)

I’d rather use my behavior (pseudo)scripting API instead of just hacking away. Conceptually, integrating player decisions with standard NPC scripting fits fairly well, so I should put my code where my brains are.

Design bites back, the dog doesn’t.

My ‘biting dog’ script doesn’t seem to work as well as it used to be. This relates in part to design issues with my framework:

  • In my script, the dog would walk to the player and start to bite. If the player moves away, the dog starts chasing the player. This is correct since the player has moved within ‘chase range’ and is now out of biting range. However, at that point the biting action is not reset and that has reached frame zero. I need to reset an action whenever it completes, so I have introduced a ‘reset’ method.
    >> actions are instantiated too early. The action descriptor should be used to regenerate the action whenever the condition is filled. This will avoid relying on a ‘reset’ call. In other words, the condition should be armed and attached to the agent; the action descriptor should be attached to the condition. When the condition is fulfilled, a new instance of the matching action should be created.
  • I used to rely on the agent having non zero speed to determine the agent state is ‘walking’. This is more than wrong. There are various factors that can affect an agent speed. I have corrected this but forgot to update the action tag in Approach, Avoid, MoveTo, etc…

Let the player be hurt

I add a couple of lignes to my script (in fact i add a player script since I have none) for the player to be ‘hurt’. Hurt is just a label here, but that could bind an animation.

Roughly speaking, things work out pretty good, but not good enough. If the player targets the dog, the PC and NPC end up rushing each other. I can’t clearly see which one hits the other first. The player seems to have the upper hand.

Bite me, Stab me

I still need to ensure two things:

  • I seem to have a targeting problem.
    • There is a limit angle for a hit to register – an actor needs to be facing the target. This shouldn’t, but seems to be a problem.
  • Both the player and the dog should be able to hit each other in turn.
    • As far as I know there is no lag time between hits.
    • Also, I have no ‘impact frame’ defined. In other words, while an actor is acting, the actor is being hit – these are ‘linked states’ rather than an action and reaction.

Whenever I bind a script using my Interpreter, the following occurs:

  1. For each type definition in the script (a type definition is associated with an actor’s label, bindType is invoked.
  2. bindType, creates both a reflex map and an affect map.
  3. Actions are added to the reflex map ; interactions are added to the affect map.

This means that action/interaction couples are grouped per actor in the main transition. Although not ideal, this seems to work fine:

(Aim) player aims action:stab

(AffectAction) player targetted by:hurt

(BasicActorUpdates) resolve Actor player {…} to hurt

(BasicActorUpdates) resolve Actor dog {…} to bite

What the log indicates is that even though the player aims the stab action, it is being hurt, which overrides the player’s intent.

If I look at AffectBinding (which causes both the dog to bite the dust and the player to be hurt when attacked), I see that states are linked at every frame. In retrospect, this is an obviously poor design. It would be way more efficient and probably more useful to just trigger the affect once. But what happens in my case is that the affect triggers over and over until the activity stops.

So in this case, for as long as the dog is in ‘bite state’, the player state is ‘hurt’. Since the dog bites in a loop, the player can never counter-attack, because affects (passive actions) override decisions.

In ActorAffectCondition (a condition that triggers an affect, such as being hurt, when another actor is performing an action on the target), i have a checkAgainst: method. There, I add a condition specifying an ‘impact frame’ for the source action.

The result is immediate (and visually obvious) – instead of  sticking to the ‘hurt state’ the PC now blips between hurt and normal. This also means that the PC can counter-attack.

R.I.P

I still have this problem with the ‘zombie dog’. The death state shouldn’t allow wagging dog tail and biting a victorious player.

In theory I could add a capacity switch to the dog’s stab response. But there’s nothing to check for capacities just yet. Since being dead is a peculiar state, I will hack this once.

Activity change is ultimately driven by an actor’s step: method. This iterates activities and cycles them. For now, this allows all activities to be interrupted.

I could force all activities to complete before another starts. Trying this is interesting but for now, not very effective, causing more inconsistent behavior.

Instead I only force the ‘rip state’ to be sticky.

Oh my. This dog is still running around though. Motion is controlled independently from action… so I wire another hack into my
[BasicActorUpdates updateActorLocation:]
method.

Conclusion

This is my first debugging session on the behavior engine since I wrote the original draft and validated the test suite. Since the test suite was so simple – testing really basic cases – surprises tend to occur.

The design of behavior implementation isn’t good. I’ll make another implementation later I guess, including only current activities in the loop and adopting an event driven approach for higher level behaviors. This will be cleaner, more intuitive, and reduce processing load.

Meanwhile, there are also shortages in action descriptions:

  • An action should at least have a flag (maybe with a default) indicating whether this action can be interrupted. Passive responses shouldn’t be interruptible. Many actions (e.g., walk cycle) work out better if they can be interrupted.
  • An action should specify an impact frame, and whether the effect is punctual or continuous.
  • An action should ideally have a lag time. This could somehow be made integral to impact frames.

At higher level, a working combat model should take into account the following:

  1. The speed of an attack depends on the length of the attack animation. If the attack has an ‘impact frame’ then a longer attack means attacking less often.
  2. If the attack can be interrupted, then the later the impact frame, the easier it is for the player to anticipate the attack.
  3. The speed of recovery determines the ability to counter-attack. If recovery is slow, then the opponent may be able to attack another time.

Tomorrow, I need to:

  • Allow specifying impact frames.
  • Test with actual animations
  • Allow specifying which actions can be interrupted, and which cannot.

Wow. Kind of blended into the new year without noticing. But then 2009 hasn’t been a bad year. Let’s keep it up :)

In my series of articles about Blender Export scripts, I explored how we can use Blender scenes as game asset libraries. In this article, I cover basic facilities needed to export a scene to several files representing
game assets.

Interactive Session

Try this:

Blender.sys.makename(ext='.foo')

Then this:

Blender.sys.makename()

Using the above, you can avoid accidentally overriding the .blend file, making sure, the default export file name uses the correct extension.

Now let's try this:

data='foo'
fname=Blender.sys.makename(ext='.exnfo')
fname # prints 'PATH_TO_BLEND_FILE/BLEND_FILE_NAME.exnfo'
file=open(fname,'w')
file.write(data)
file.close()
Blender.sys.exists(fname) # prints '1' for true
input=open(fname,'r')
target=input.read()
target # prints foo!
input.close()

Use something like this to retain the path to export to across Blender sessions, saving
frustrating moments browsing to the same path over and over.

The Blender file chooser isn't terribly helpful to export to folders as it doesn't allow selecting a directory so easily. Worse, I haven't really found a way that a new directory can be created using a Blender script (being Noob-y?). Having said that, with a little assistance, we can still get a user to enter a directory path, and with the above, we make it easy to just reuse the same path.

To generate file names under a given path, use something like:

x=Blender.sys.makename()
parent=Blender.sys.dirname(x)
child=Blender.sys.basename(x)
dirname=Blender.sys.join(parent,child)
fname=Blender.sys.join(parent,'dummy.txt')
fname # just print the result to be sure...

Note that x and dirname are... exactly the same thing. This is just to illustrate defining a default export folder (if we want to export a scene to several files) and creating a path to export to.

Finally, code to pop a file chooser and bind it to a callback will look like:

# the callback
def exportTo(fname)
# do something useful...

#pop the file chooser
Blender.Window.FileSelector(exportTo, 'Meshes in Exile','dummy.myExtension')

(not sure if this works in interactive mode, but that's what we need)

Putting it all together, we can create a script that:
- Retrieves a path to export to, from a well known location (as in, the same folder as the blender file). The export path is (sensibly) specific to each Blender scene.
- Suggests such previous export path, if available.
- Otherwise suggests a reasonable path for an export folder
- Generates filenames to export within such export folder.

Checkout previous articles for 'actually how to export the real data'.

My current export script for character animation requires a naming convention for binding a character to it’s armature.  Also, the script only exports the currently selected mesh.

In this article, I illustrate how to examine a Blender scene to discover assets; I also show how to find the armature modifier associated with an animated character.

In outline, this is how to structure a script to export an asset library:

  • Iterate all objects in the scene
  • Retain only Mesh objects.
  • For each mesh object, check whether this object uses an armature; if so, assume the object is a kind of actor or character.
  • Export mesh objects as appropriate (You can learn how to do this from previous articles on this blog)

Interactive session

Let’s try the following:

s=Blender.Scene.GetCurrent()
s.objects
for x in s.objects:
	x.type

(After typing ‘x.type’ in the interactive console, press enter twice to effect the loop)

This will print the type of each object in the order they are stored in the scene. We only want to export Mesh objects. Pick any Mesh object using an armature. (in my case, index 1 in the object list).

object=s.objects[1]
for x in object.modifiers:
	if(x.type==Modifier.Types.ARMATURE):
		x

This will print something like:

[Modifier "Armature", Type "Armature"]

That’s all we need to identify actors and props in a Blender Scene.

Material assignments allow defining per face or per object materials. In this interactive scripting session I show how materials, material properties and material assignments can be accessed. Next time I will expose a simple solution for exporting character animations.

Per face material assignments

For the record, material assignments are accessible from [buttons window > editing tab > Link and Materials panel. There's the usual up/down arrow to select an existing material or creating a new one. Although the actual material editor is elsewhere, you can still choose a color and a name for a material created here without exiting the editing tab. Upon creating / selecting a material, the current selection is assigned this material. Or you can select vertices later and use the 'Assign' button.

Interactive Scripting Session

This may not require additional comments:

bot=Blender.Object.Get("FunBot")
mesh=bot.getData(mesh=1)
faces=mesh.faces

# this will print the material index
faces[0].mat

# to find the name of a material
# get materials as an array
materials=mesh.materials
# this prints the name of the material assigned to face zero.
materials[faces[0].mat]

# this illustrates material properties
# (in interactive mode, prints material property values)
mat=materials[0]
mat.rgbCol
mat.amb
mat.alpha
math.hard/512
mat.specCol
mat.emit

Material.Get() can be used to get all materials in a scene - for an export script, however, it may be more efficient to map materials as we export geometry to avoid exporting unused materials.

Finally, there's an *awful* lot more about Blender materials in the Material API (link to Blender docs).

In Blender, an Action is a sequence of key frames representing a character gesture (walking, jumping, slashing, falling, etc…). Actions are used as building blocks in Blender’s non linear animation (NLA) editor. We can use actions to create ‘animation catalogues’. An export script using actions might be used to batch export all animations for one or several characters, so we can update our game assets whenever we need, which simplifies and enhances flow.

Interactive Scripting Session

For this session, I have created a little robot – ‘funbot’ and an armature for it.
I then create two actions and detach them from the funbot. To take advantage of actions, we need to make each action current, i.e. for every action we attach the action to the armature and export all frames or key frames (either the armature frames/keyframes or the deformed mesh) before moving to the next action. Time for scripting:

#retrieve the action dictionary
actions=Blender.Armature.NLA.GetActions()

#get an action named 'nod' (as defined by your animator)
action=actions.get("nod")

#the following prints '[Action "nod"]'
armature=Object.Get("FunBotArmature")

#this makes the action current for the armature,
#so we can playback the action and record it.
action.setActive(armature)

#even if you call this, the window won't update, but the underlying
#model does, which is what we need for export.
scene=Blender.Scene.GetCurrent()
scene.update(1)

The above script does nearly everything we need related to actions – giving access to all defined actions within a blender file, it retrieves an action by name, applies it to the correct armature and updates the scene; at this point we’re nearly ready to iterate action frames and export the model and/or armature to a file (see my interactive session on exporting meshes deformed using an armature)

Just one more thing we need is knowing the number of frames in the animation. We can actually get better than just the number of frames – instead, we can get the list of keyframes, in ascending order:

#get the list of keyframes
keys=action.getFrameNumbers()
#print all keyframe indices, like ' [1,11,24,36,] '
list(keys)
#print the length of the animation
keys[len(keys)-1]

Using this, we can choose to either export only keyframes (use less memory), or all frames in the animation (OK for really simple animations and models).

Before I forget… for some reason the Blender APIDoc doesn’t just turn up whenever I google it. Here it is.

Just a while back I published a weeny export script and matching C/Objective C code that can be used to export mesh data from blender to OpenGL vertex arrays.

To export animated characters, we need to do either of two things:

  1. Export Armature key frames or frames, along with their attachment to target objects; then apply the deformation either in real time, or maybe just before we need to animate the model. The upside is that this is memory savvy. The downside is that if your game engine can’t handle your exported armatures (I don’t know how likely to happen this might be) or you don’t use a game engine, you’ll have to work out deformations yourself, starting from a fairly complex high level model.
  2. Export ready mesh key-frames or frames, with the armature effect already applied. The downside is that this requires a lot more memory.

My hunch is that how much ‘a lot more’ matters really depends how large your models are and what kind of platform you’re running on. I plan running on the iPhone/iTouch with isometric views. This means that my 3D sprites will be small – hence require less polygons. For some animations, a little compression (e.g. retaining unchanged coordinates from a previous frame) can be considered if needed, never mind sharing geometry across models.

In this article I show how to force modifiers to be applied before exporting mesh data – one way to attach an armature in blender is via modifiers. This is a good opportunity to try interactive scripting with Blender, making learning scripting easy and fun :)

Effecting the modifier stack also means that you can export complex operations applied to your object, not just armature modifiers.

Give back to Caesar what belongs to  Chicken – I borrowed this technique from the Blender to Panda3D export script – Chicken exports to Panda3D’s *.egg format,

***Believe it or not, *.egg came first, then Chicken somehow assisted the birth of this tutorial.

An Interactive Scripting Session

First I make a triangle pointing up in the z x plane, ensuring x==0 for the middle vertex. I add an armature – just one bone – aligned on the z axis and pose it to drag the top vertex to the right, about 1 unit. Finally I add the armature as modifier. I think this is important, afaik this wouldn’t work if the armature parented
the mesh. Then I type the following in the scripting console:

scene=Blender.Scene.getCurrent()
obj =scene.objects[1]
mesh=obj.getData(mesh=1)

# next line prints coord without deformation
mesh.verts[2].co.x

# this is where the magic happens
# getFromObject implicitly applies all modifiers.
tmesh.getFromObject(obj,0,1)

#next line prints coord with deformation
tmesh.verts[2].co.x

OK, this shows that we can export the deformed mesh. Now we need to get each
frame. So I insert a keyframe for the rotation of the bone (pose mode),
go 10 frames further and pose with the tip of the bone pointing right.

First, let’s repeat the first experiment,
browsing to frame 11 (left/right arrow keys)

tmesh.getFromObject(obj,0,1)
tmesh.verts[2].co.x

This shows that the script is, by default,
querying the current frame.
I found a command to change the frame:

context = scene.getRenderingContext()
# set the current frame
context.currentFrame(3)
scene.update(1)
tmesh.getFromObject(obj,0,1)
tmesh.verts[2].co.x

If you repeat this operation using the frame value, you will see that the vertex coordinate moves at every frame.

Next time I’ll look into exporting several actions for a given character.