1
$\begingroup$

Is it possible to give every scene the user creates an unique number? I thought about using the UUID lib for that so here is what I got so far:

def register():
    pow2_31 = 2**31
    mask32b = 0xFFFFFFFF
    p_uuid = uuid.uuid4().int
    p_uuid1 = p_uuid >> 96
    p_uuid1 -= pow2_31 if p_uuid1 >= pow2_31 else 0
    p_uuid2 = (p_uuid >> 64) & mask32b
    p_uuid2 -= pow2_31 if p_uuid2 >= pow2_31 else 0
    p_uuid3 = (p_uuid >> 32) & mask32b
    p_uuid3 -= pow2_31 if p_uuid3 >= pow2_31 else 0
    p_uuid4 = p_uuid & mask32b
    p_uuid4 -= pow2_31 if p_uuid4 >= pow2_31 else 0
    bpy.types.Scene.mhfc_uuid1 = IntProperty(
                                name="projectUUID",
                                description="An unique ID. DON'T TOUCH THIS UNLESS YOU ARE SURE WHAT YOU DO.",
                                subtype="UNSIGNED",
                                default= p_uuid1, # most uniqueness possible??
                                options=set()
                                )
    bpy.types.Scene.mhfc_uuid2 = IntProperty(
                                name="projectUUID",
                                description="An unique ID. DON'T TOUCH THIS UNLESS YOU ARE SURE WHAT YOU DO.",
                                subtype="UNSIGNED",
                                default= p_uuid2, # most uniqueness possible??
                                options=set()
                                )
    bpy.types.Scene.mhfc_uuid3 = IntProperty(
                                name="projectUUID",
                                description="An unique ID. DON'T TOUCH THIS UNLESS YOU ARE SURE WHAT YOU DO.",
                                subtype="UNSIGNED",
                                default= p_uuid3, # most uniqueness possible??
                                options=set()
                                )
    bpy.types.Scene.mhfc_uuid4 = IntProperty(
                                name="projectUUID",
                                description="An unique ID. DON'T TOUCH THIS UNLESS YOU ARE SURE WHAT YOU DO.",
                                subtype="UNSIGNED",
                                default= p_uuid4, # most uniqueness possible??
                                options=set()
                                )

The problem is that all scenes have the same uuid while Blender is not restarted. How can I generate a new random number for each scene the user creates?

$\endgroup$
0
$\begingroup$

You have added a property called mhfc_uuid1 to the Scene class and set the default value to the pre-calculated value of p_uuid1. Every scene will then get this same value when it is created.

You may want to set the default to zero and then before using it check if it is zero and then set it to a generated value.

class MyOperator(bpy.types.Operator):

    def execute(self, context):
        if context.scene.mhfc_uuid1 == 0:
            context.scene.mhfc_uuid1 = generateuuid()
        do_interesting_stuff()
        return {'FINISHED'}

You could setup existing scenes as your addon is enabled by adding something like this after you add the properties.

for sc in bpy.data.scenes:
    sc.mhfc_uuid1 = generateuuid()
$\endgroup$
  • $\begingroup$ thanks for the explanation why it doesn't work. The problem is that I want to set it once and for all when a new scene is creared. Is there a possiblity to register a callback when a new scene is CREATED? $\endgroup$ – WorldSEnder Aug 1 '14 at 11:03
  • $\begingroup$ I don't think there is a way to do that without patching blender. The closest would be a scene update handler where you could add the same if mhfc_uuid1 == 0 test every time a scene is updated. $\endgroup$ – sambler Aug 2 '14 at 9:52
0
$\begingroup$

This solves the problem per scene. If someone knows some kind of data that only exists per file, please post an answer.

You can register a handler that does exactly this and only checks once for every file. All you have to do is call bpy.app.handlers.load_post like this:

# Test addon
import bpy
import random
from bpy.types import Scene
from bpy.props import IntVectorProperty, BoolProperty
from bpy.app.handlers import persistent

@persistent
def load_handler(_):
    # reset if loaded file is the default file
    if bpy.data.filepath == '':
        for scene in bpy.data.scenes:
            scene.mhfc_isuuidset = False

def get_prop(name, valuegenerator, init_name=None):
    """
    This generates a new value if necessary before returning it.
    name: the properties own name
    valuegenerator: a function that takes two parameters:
            the object it is called on (e.g. the scene)
            the identifier of the value
            returns - the new value
    init_name: the name of a value that tells if this value
            initialized. If not init_name: returns a function
            that checks against the actual value
    """
    def get(self):
        if not getattr(self, init_name):
            self[name] = valuegenerator(self, name)
            setattr(self, init_name, True)
        return self[name]
    return get

pow2o31 = 2**31
def generator(obj, name):
    var = lambda: random.randint(-pow2o31, pow2o31-1)
    return (var(), var(), var(), var())

def register():
    bpy.app.handlers.load_post.append(load_handler)
    Scene.mhfc_isuuidset = BoolProperty(
                            name="isUUIDset",
                            description="Set to true if scene data is initialized. DON'T TOUCH THIS UNLESS YOU ARE SURE WHAT YOU DO.",
                            default=False,
                            options=set())
    Scene.mhfc_uuid = IntVectorProperty(
                        name="UUID",
                        description="An unique ID for this file. Read-only",
                        options=set(),
                        default=(0, 0, 0, 0),
                        size=4,
                        get=get_prop('mhfc_uuid', generator,'mhfc_isuuidset'))
if __name__ == "__main__":
    register()

A bit of explaination: We set the properties per scene, not per file (if someone has a fileunique type we can register types on, I would be very happy if you let me know). We set 5 properties: The UUID, split into 4 integers, making it a total of 128 bits and a boolean value that is defaulted to false (this gets in handy when opening files that haven't had this property registered).

All the uuid-values get assigned a getter-function that checks if the property in question is already initialized (in this case it checks for mhfc_isuuidsetn). If not it uses the generator function to get a new value and sets and returns it. This ensures that all following calls will return the same value. Also notice that no set-function is given so the value is automatically read-only.

The bpy.app.handlers.___ get called on certain points in time. We chose load_post here so that the data is already read and applied, if any exists. The function than goes through all the scenes if the default scene is being loaded (so a user can't possibly save a state in the default scene in his premature clicking ^_^) and reset the mhfc_isuuidset-value to False. We can easily check whether or not the a New File (StrgN) is opened because in the case the property bpy.data.filepath will be ''.

Then only one problem that is still there: All handlers get cleared on fileloading so we have to make sure that our handler is persistent by decorating it with the bpy.app.handlers.persistent tag.

$\endgroup$
  • $\begingroup$ Yes you now get unique uuid's set per scene but that is only applied to the scenes in a file when you open it or create a new file. It doesn't apply to a file that is already open when the addon is enabled (add a call to load_handler within register()) or when a new scene is created. A user would need to create a scene, save the file and re-open it to get a uuid for the new scene. That's why I suggested testing in an operator that uses the uuid. $\endgroup$ – sambler Aug 7 '14 at 7:02
  • $\begingroup$ Oh, you're totally right... I think I fixed that though by giving each property a get-function that checks whether or not she is already generated. $\endgroup$ – WorldSEnder Aug 7 '14 at 12:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.