Skip to content

Archive

Tag: Script

This article is useful you want to get productive quickly with blender scripting. There are much better ways to integrate scripts. I feel *almost* embarrassed to post this. Initially, however, script integration may feel intimidating. 

You’ve been toying around with the python console and/or adding quick scripts as text nodes in blender files, you wish to reuse your scripts, but add-on creation feels intricate? Read on.

However, if you’ve created a great script that you’d like to share with the community, you need to create an add-on instead (checking existing add-ons in the blender scripts folder is the way to go).

Move your script to py files

The idea here is to bypass time consuming integration steps, while retaining basic flexibility:

  • Don’t create an add-on.
  • Don’t create a button oriented UI
  • Keep scripts in *.py files (not in a *.blend file)

So, let’s say we have a script under /Users/Dick/foo.py, how can we call this from blender? The (quick and dirty) solution is to create a text node in the blender file, and add the following code:

# import sys and foo modules; append our script dir to the python path
import sys, imp
sys.path.append(“/Users/Dick”)

# import our py file as a module; reload to make sure recent changes
# to the script are considered
import foo
imp.reload(foo)

# call a function in the script file
foo.myFunction()

Then, we can invoke our script by hitting ‘run script’ in the text window.

We don’t want to type these lines over and over again. So we can add them as part of the default startup file. Just do File > Save User Settings.

Keep in mind that this will overwrite the startup file with whatever’s in your workspace (so, adding the quick and dirty ‘script runner’ right after opening blender is a good idea).

Exporting cloth animations required only a few changes to the ox3ich exporter.

=> Ox3ich exports blender meshes and animations (source, LGPL).

Since both qwagga (scene export) and ox3ich (mesh/animations export) are now available for download, I guess I’ll want to consolidate this soon with an online project manager. In the meantime… you can have a look at the notes below, outlining how ox3ich handles cloth animations.

Finding Cloth objects

myObject=bpy.data.objects["Dress"] // get the object to be exported

myObject.type == Modifier.Types.CLOTH // confirm this object has ‘cloth’ enabled

We could have an isCloth method, looking like this:

def isCloth(object):

for x in object.modifiers:

if x.type==Modifier.Types.ARMATURE:

return 1

return 0

Using Cloth Objects as equipment

A simple way to generate animations for equipment (see this article) consists in reusing the parent object’s Armature (with extra bones for equipment) and export the actual keyframes (the shape of the mesh as deformed by the armature). Mesh data is memory intensive. One advantage, however, is we don’t need to rewrite / adapt modifiers code.

Now, for equipment, we grab all actions and apply them to the actor’s armature. We’ll do the same for cloth objects. However, there is a difference

In the case of equipment the actor’s armature is on the object’s modifier stack and is really used to animate the object, not the actor.
In the case of cloth, we may not want to animate the cloth with the armature directly. Instead, we apply the armature (and the action) to the actor, which indirectly influences cloth dynamics.

So we need to retrieve the actor used to influence cloth dynamics. I’ll use the same naming convention I used for other equipment items, e.g. dress@player. Then we have:

def getArmatureForCloth(cloth):

influencingActor=bpy.data.objects[cloth.name.split('@')[-1]]

return getArmature(influencingActor)

This uses the naming convention to retrieve the actor. For basic animation export, ox3ich doesn’t need anything else (in code sample ‘object’ is the object using cloth modifier):

exportItemFile(object,path)                      # export basic mesh and material data

actions=getActions(object)                      # return actions for owner (uses naming convention)

armature=getArmatureForCloth(object)            # return the owner’s armature

exportActionFiles(actions,armature,object,path) # export all actions in the usual way.

Restricting key frames for export

By default, the exporter will export mesh data for all action frames, so I’ll extend the actor naming convention to allow us to define a frame range; for example

“player.walk@30-50″ # walk cycle includes only frames 30 to 50 for export

The following function parses the frame range according to this convention

def getFrameRange(action)

range=[1,30000]

parts=action.name.split(‘@’)

if len(parts)==2:

rngString=parts.split(‘-’)

range[0]=int(rngString[0])

range[1]=int(rngString[1])

return range

Notes

This is enough to get started with exporting cloth animations. There are several shortcomings:

  • The exporter does not bake cloth animations, this is done manually (so probably the cloth animation part only works if each file contains only one animation).
  • The exporter doesn’t explicitly handle cyclic animations. With my sample walk cycle, it doesn’t look all that bad, but there has to be a discontinuity between the first and last frame. Minimally the last frame should be replaced by the first frame. For smoother results, two consecutive cycles should be blended together, and I’d like the exporter to do this as well.

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 Blender, Actions contain information about ‘reusable animations’ that can be combined to generate complex animated scenes. Actions can also be used to create catalogues of animations associated with game assets.

I might have suggested before that a 3D artist may prefer to keep several avatar models in the same blender file. Keeping models in separate files makes it (not impossible yet) more difficult to share geometry and materials between models. For the designer, ‘sharing’ may not be a very high level concept, more something like ‘copy, paste and modify’. Nice, fast and simple.

Blender actions are created while posing armatures. Unfortunately, there is not a clear way to retain the connection between an action and the armature first used to generate this action. Here’s a little experiment that illustrates this:

1. Create an armature A with a bone named ‘Bone’. Create an action X for this armature.
2. Create an armature B with a bone named ‘Bone’ (same name). Make action X current in B.
2. Observe the result.

Essentially, Blender Actions are lists of keyframes ‘per channel’; a channel is just a name; the name binds bone names. Any armature can use any action, and this will be ‘effective’ as long as the names match.
That may be powerful. Not great when we want to export per character keyframes for each action.

At this point, we may consider loading a config file listing actions for each actor, or design a little script letting us retain the original armature <> action binding when creating new actions (I think that can be done and integrated nicely with Blender). But I won’t illustrate any of the above this time. I just fallback to a naming convention for my actions, something like:

myActor.jump
myActor.nod

Since all actions are dumped in the same list, this also allows quickly locating per character actions in the Blender interface.

Let’s not learn all about Python Strings

Instead, try this:

z='funbot.jump'
p=z.split('.')
p[0] # prints 'funbot'
p[1] # prints 'jump'

Now we can match each action to a character ‘owning’ this action. You can learn more about actions and *stuff* in previous articles on this blog.

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.

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).