.blend append and link script

This is a script for importing and linking so the linked stuff is editable. To quote Zaz’s post that inspired this script (and helped clarify the original procedure):

My procedure for doing this is as follows. I SHIFT-F1 and select the file I want to get the model from. I then go into the Object “directory” of the .blend file I’m importing from and select the armature(s) and mesh Objects I want to import. I then import these via APPEND. Now this actually copies all of the items in their entirety into my current .blend file, but we’re not done yet.

I then rename the Datablocks for those imported objects by adding an X to the names. This is the left most name pull down menu under F9. Check the tooltip, it says Datablock in it. This might not be necessary, but I seem to have fewer crashes when I include this step.

Then I SHIFT-F1 and pick the elvis.blend file again, but this time I click on the LINK button. Rather than importing from the Object “directory” in the elvis.blend file, I now import from the Mesh and Armature “directories”. This only brings in the Datablocks/primitives, i.e. the actual meshes and/or armatures and not the Objects they are associated with. When you do this, you won’t see anything added to your 3D windows as the data you just imported isn’t associated with any Objects yet.

Once those datablocks/primitives are LINKed into my memphis.blend, I then select my armature and in the Editing (F9) panel, in the datablock pull down I switch the armature associated with the object to the one I just imported via a LINK. I then do this to the remaining armature and mesh objects. When I’m done with this, I have new Objects in my file that are copies of those objects from the elvis.blend file, however, the actual meshes and armatures are linked and changes I make to those in the elvis.blend file will be propogated to memphis.blend the next time I open it.

Why such a convoluted way of doing things ? Well, it has to do with how blender manages the data and how it works when you import via LINK vs. APPEND. Importing by APPENDing objects allows you to make any changes to those object you want. This makes sense as afterall, they were simply copied from the elvis.blend file into memphis.blend file and there is no longer any relationship between the two.

Importing objects by LINKing them causes all changes to propogate, however you can’t even move the object or change the actions on the armatures. Pretty useless in most situations.

see [OLD LINKS REMOVED] for more info, This script just automates that append > rename > import > link prcedure.

Currently this script doesn’t discriminate the files to import, if you want to import only specific items (lights, a leg etc…) you need to do the importing part yourself.

Some of this code is nabbed directly from the python API docs.
On a final note, this script is still beta. Any bugs or anything, post them here. I’ll endevour to fix them.


#!BPY
""" Registration info for Blender menus: 
Name: 'Bulk import and link'
Blender: 234
Group: 'Misc'
Tip: 'Import and replace mesh data'
"""

__author__ = "zenoscope"
__url__ = ("blender", "elysiun")
__version__ = "0.01 alpha"

__bpydoc__ = """\
"""

# ------------------------------------------
# Bulk import script 0.01 alpha
name="Bulk import"
Tip= 'Bulk import'
#----------------------------------------------
#----------------------------------------------

import Blender
from Blender import Library, Window, Draw, BGL, Camera, Object

object_list=[]
already_imported = 0

#1 SELECT file to append from.
def filename(name):
 open_library(name)

#2 import selected _OBJECT_ data.
def open_library(name):
 global object_list, already_imported
 object_list=[]
 already_imported = 1

 Library.Open(name) # opens the library file
 groups = Library.LinkableGroups()

 data_Type = 'Object'

#3 _append_ OBJECTS to new file.
 # if the objects are 'Object' (can change to Mesh, Arm, light etc...)
 if data_Type in groups:
   for obname in Library.Datablocks(data_Type):
     Library.Load(obname, data_Type, 0) # note the 0...
     # add the objec to a list so imported objects
     # _only_ are renamed.........
     object_list.append(obname)
   Library.Update()

 Library.Close()
 Window.RedrawAll()

#three buttons:
#1 import - opens import file and imports it as appended data

#2 rename - renames the imported data
def rename_imported():
 global object_list, already_imported

 if already_imported != 1: # if we haven't gone through the import process
    object_list=[]
    # usefule if stuff has already been imported, or as a bulk relink button
    # ob list is a text list, do a GetSelected and push the names into the list instead    
    object_list = Object.GetSelected()
 
 for ob in object_list: # loop through objects
  
  print ob
  rename_this = Blender.Object.Get(ob.name)
  
  if rename_this.getType() != 'Empty': # 'empty'  has no name
   data = rename_this.getData()  
  
   rename=len(str(data.name)) # if it doesn't end in an X already, add one.
   if data.name[rename-1] != "X":
    data.name = data.name + "X"
    if rename_this.getType() == 'Mesh':
     # Need to update NMesh data.
     data.update()
    
  
#3 link - reminder that the user has to do this themselves
#4 relink - relinks imported data so _you_ don't have to!

def relink_imported():
  global object_list,already_imported

  Window.WaitCursor(1)

  if already_imported != 1: # if we haven't gone through the import process
    object_list=[]
    # usefule if stuff has already been imported, or as a bulk relink button
    # ob list is a text list, do a GetSelected and push the names into the list instead
    
    new_list = Object.GetSelected()
    for ob in new_list:
      # get the dataname and hack it.
      data = ob.getName() #Object.Get(ob)
      renamed_Object= data
      object_list.append(renamed_Object)
  #else
  # already_imported = 0

  print "ob list" + str(object_list)

  for ob in object_list:
    
    relink_this = Blender.Object.Get(ob) # object to get new data

    #print "relink" + str(relink_this)
    #-diff syntax for each type! grrrr
    #relink_type = str(relink_this.getType())

    #print "type" + str(relink_type)
    #relink_data = eval("Blender."+ relink_type + ".Get(ob[ :-4])")
    
    #print "data" + str(relink_data)
    #-relink_data = Blender.Mesh.Get(ob)
    #relink_this.link(relink_data )

    if relink_this.getType() != 'Empty':
     ch=Object.Get(ob)
     data_name = ch.getData(1,0)
     data_name = data_name[ :-1]
     print str(data_name)
     print "reconnecting "+ ch.getData(1,0) +" to " + data_name 

    if relink_this.getType() == 'Mesh': 
      try:
       relink_data = Blender.Mesh.Get(data_name)
       relink_this.link(relink_data)
      except:
       pass
    elif relink_this.getType() == 'Lamp': 
      try:
       relink_data = Blender.Lamp.Get(data_name)
       relink_this.link(relink_data)
      except:
       pass
    elif relink_this.getType() == 'Armature':
      try:
       relink_data = Blender.Armature.Get(data_name) # Blender.Armature.Get(ob)       
       relink_this.link(relink_data)
      except:
       pass
    elif relink_this.getType() == 'Camera': 
      try:
       #relink_data = Blender.Camera.Get(data_name)
       print "for some reason CAMERAS don't work"
      except:
       pass
    elif relink_this.getType() == 'Empty': 
       pass
  Window.Redraw(-1)
  Window.WaitCursor(0)


def import_file():
 Window.FileSelector(filename, "Choose Library", "*.blend")

##########################

def event(evt, val):    # the function to handle input events
  Draw.Redraw(1)

def button_event(evt):  # the function to handle Draw Button events
  global message, truncate
  if evt == 1:	
	import_file()
  elif evt == 2:
	rename_imported()	
  elif evt == 3:
	link_import()
  elif evt == 4:
	relink_imported()
  elif evt == 5:
	Draw.Exit()
  elif evt == 6:
    truncate = 0

  Draw.Redraw(1)

def gui():              # the function to draw the screen
  pos = 200
  BGL.glClearColor(0,0,1,1)
  BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
  BGL.glColor3f(0,1,1)
  BGL.glRasterPos2i(150, pos)
  Draw.Text("Directions for use:")
  BGL.glRasterPos2i(150, pos-20)
  Draw.Text(" 1) import your objects, either using the APPEND button on this script, or")
  BGL.glRasterPos2i(150, pos-40)
  Draw.Text("the usual Blender way: SHIFT+F1 -> APPEND, selecting objects in the object directory")
  BGL.glRasterPos2i(150, pos-60)
  Draw.Text("Using the script will import all of the objects in the file.") 
  BGL.glRasterPos2i(150, pos-80)
  Draw.Text("2) Select the objects and then press the RENAME button. This will add an X ")
  BGL.glRasterPos2i(150, pos-100)
  Draw.Text("to the end of the data name. Emptys cant be renamed, they have no dataname.")
  # and doesn't have bounds checking either, sigh. Maxchars for dataname is 19 chars.
  BGL.glRasterPos2i(150, pos-120)
  Draw.Text("3) Go SHIFT+F1 - > APPEND -> LINK and select things in the mesh/armature/whatever directory.")
  BGL.glRasterPos2i(150, pos-140)
  Draw.Text("Be sure to use relative links if its cross-platform.")
  BGL.glRasterPos2i(150, pos-160)
  Draw.Text("4) Press the RELINK button - again with everything highlighted - to link the")
  BGL.glRasterPos2i(150, pos-180)
  Draw.Text("appended objects and the linked data together.")

  Draw.Button("Append", 1, 10, 150, 80, 20,"append")
  # add toggles for mesh, lights, cameras actions, etc...
  Draw.Button("rename", 2, 10, 120, 80, 20,"append")
  #Draw.Button("Link", 3, 10, 90, 80, 20,"append")
  Draw.Button("ReLink Data", 4, 10, 60, 80, 20,"append")
  Draw.Button("Quit", 5, 10, 10, 55, 20,"append")
  
Draw.Register(gui, event, button_event)  # registering the 3 callbacks