Unique Libload

Ever wanted to LibLoad multiple of the same object? No? I’m not really surprised.

Use:

  • However many identical meshes you like with different UV layouts, without having to duplicate them inside a blend
  • Same thing for Vertex Colors, materials, or any mesh-based property. (ie you can change the material on one mesh without affecting the others)

Requirements:

  • Object you want to add is on a hidden layer in the blend to LibLoad

import bge


byte_strings = {}


def add_unique(obj_name, identifier, ref_obj, file_name):
    '''Loads a unique instance of an object.
    INPUTS:
        - obj_name, the name of the object to add
        - identifier, the library-name to store the object under (will have a number added after it)
        - ref_obj, where to add the object
        - file_name, where the object resides (string)

    OUTPUTS:
        - added_object, the object that was added
    '''
    if obj_name not in byte_strings:
        path = bge.logic.expandPath(file_name)
        byte_strings['obj_name'] = open(path, 'rb').read()
    identifier = identifier + str(0)
    while identifier in bge.logic.LibList():
        identifier = identifier+str(int(identifier[-1])+1)
    bge.logic.LibLoad(identifier, 'Scene', byte_strings['obj_name'])
    scene = bge.logic.getCurrentScene()
    new_obj = [o for o in scene.objectsInactive if o.name == obj_name and 'old' not in o][0]
    new_obj['old'] = 0


    added_obj = scene.addObject(new_obj, ref_obj)
    return added_obj

In my case, loaded objects need to be added right away, but if you want want to get a reference to the added object on the inactive layer, then just remove the line starting with ‘added_obj’ and replace the ‘return added_obj’ with ‘return new_obj’

Have fun with it (for those of you who ever use this sort of code)

Cool code. LibLoad is really useful, and posts that educate on what you can do with it are great. What did you mean by this, by the way"

?

If you’re texturing object using GLSL code (asgiven here), then you can set the material for one object separately from another object.
Normally if you apply a shader like that to one object, all of it’s duplicates will inherit the same shader (because they share the mesh). If you’re libloaded like this, then it’s an independant mesh, so it can be object-specific.

I have not actually tried that yet though, just theorized about it. I also haven’t seen a point for changing material like that, for me, the reason for this code was vertex colors.

I revised this snippet today to work with multiple objects and to do so in a simpler way:


def unique_libload(file_path):
    '''Loads a unique instance of a blend.
    INPUTS:
        - file_path - path to the blend file


    OUTPUTS:
        - added_objects, the object that were added
    '''
    scene = bge.logic.getCurrentScene()
    old_objects = scene.objects + scene.objectsInactive
    
    f = open(file_path, 'rb').read()
    identifier = file_path + str(0)
    while identifier in bge.logic.LibList():
        identifier = identifier+str(int(identifier[-1])+1)
    bge.logic.LibLoad(identifier, 'Scene', f)
    
    all_obj = scene.objects + scene.objectsInactive
    
    added_objects = []
    
    for o in all_obj:
        if o not in old_objects:
            added_objects.append(o)


    return added_objects

It will load the blend and return a list of added objects. If you have lots of objects in your scene it may cause lag, but then libload will cause lag anyway…

If I do this (libLoad unique mesh with unique materials) and delete a object,
Can I simply spawn a copy of the hidden layer object, and replace mesh with the libLoad mesh?

EndObject() of a libNew does not libFree the mesh correct?

I am going to do

If “uniqueMeshName” does not exist:
(libload trick to make mesh, name it uniquemeshname)
Else:
Add object(blank pecs card) set mesh to uniqueMeshName

In 90% of cases you should use LIbNew instead of LibLoadUnique. LibLoadUnique is painfully slow. Like, really, glacially slow. Only do it at load-time. It also frequently loses relative paths. IN other words: it’s probably not want you want. Just use LibNew (unless you need to duplicate materials or textures).

What are you actually trying to do here? (ie what is the desired outcome, not what code are you planning to write).

Yes, you need to make sure you free things properly. endObject is not sufficient. In the years since writing this snippet, I have vastly improved how I manage libloads, and have several nice constructs around them to simplify this process. I’ll have to polish them and upload at some point.

Remember that now you have non-unique mesh names. You’ll have to make sure you use the correct mesh. I don’t think you can rename meshes.

for each pecs card -> load a unique card material->set texture to whatEver.png

each card = 1 string and 1 image.

I don’t want the end user to have to use blender to add new cards, just add a word to a text file and a image to a directory
using the app*

each card will be a 256x256 image I think*

imagine if you could not deal with words , but did fine with pictures.

this software is to build sentences using images an a ui to speak.