2
$\begingroup$

I have created a simple addon that creates a series of metaballs. Sometimes when the addon executes, the metaballs are rendered invisible (as only outlines, no surface). Usually the metaballs seem to be created correctly (ie, visible) -- sometimes it can be a little bit hard to reproduce the problem.

When I encounter the problem, I can re-execute the script with the same parameters (click to edit a field and then hit enter) and the metaballs/surface will often then suddenly appear. The inconsistency here makes me wonder if this is really a bug in my script or if it might be a bug in Blender itself.

Any ideas what could be causing the issue?

Edit: bpy.context.scene.update() has been no help.

enter image description here

bl_info = {
    "name": "Metaball Thing",
    "category": "Object",
}

import logging
import random
import math
import mathutils
from mathutils import Vector
import string
import abc
import bpy

log = logging.getLogger(__name__)

class ObjectMetaballThing(bpy.types.Operator):
    """Object Metaball Thing"""
    bl_idname = "object.metaball_thing"
    bl_label = "Metaball Thing"
    bl_options = {'REGISTER', 'UNDO'}

    # ========= Properties =========
    primaryRadius = bpy.props.FloatProperty(name="Primary Radius", default=9, min=0, max=10000)
    seriesRatio = bpy.props.FloatProperty(name="Series Ratio", default=0.333, min=0, max=1)
    scale = bpy.props.FloatProperty(name="Scale", default=1.0, min=0, max=100)
    numBubbles = bpy.props.IntProperty(name="Num Bubbles", default=3, min=1, max=10)
    resFactor = bpy.props.FloatProperty(name="Res Factor", default=0.01, min=0, max=100)


    def execute(self, context):
        # add metaball object
        disambiguator = '-' + ''.join(random.choice(string.ascii_uppercase + string.digits) for c in range(8))
        mball = bpy.data.metaballs.new("SurfaceBall" + disambiguator)
        obj = bpy.data.objects.new("SurfaceBallObject" + disambiguator, mball)
        context.scene.objects.link(obj)

        # resolution is based on radius
        mball.resolution = self.primaryRadius * self.resFactor
        mball.render_resolution = mball.resolution * 0.25

        # create the initial ball
        centerball = mball.elements.new()
        centerball.co = (0, 0, 0)
        centerball.radius = self.primaryRadius

        # build a series of smaller metaelements
        dist = 0
        radius = self.primaryRadius
        postElements = []
        for p in range(self.numBubbles):
            dist += radius * 0.5
            radius *= self.seriesRatio;
            dist += radius * 0.5

            center = Vector([0, 0, 1])
            center *= dist * self.scale

            element = mball.elements.new()
            element.co = center
            element.radius = radius

            log.warning("element at " + str(center.z) + ", radius " + str(radius))
            postElements.append(element)


        obj.select = True
        context.scene.objects.active = obj

        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(ObjectMetaballThing.bl_idname)

# store keymaps here to access after registration
addon_keymaps = []


def register():
    bpy.utils.register_class(ObjectMetaballThing)
    bpy.types.VIEW3D_MT_object.append(menu_func)

    # handle the keymap
    wm = bpy.context.window_manager
    # Note that in background mode (no GUI available), keyconfigs are not available either, so we have to check this
    # to avoid nasty errors in background case.
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
        kmi = km.keymap_items.new(ObjectMetaballThing.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)

        addon_keymaps.append((km, kmi))


def unregister():
    # Note: when unregistering, it's usually good practice to do it in reverse order you registered.
    # Can avoid strange issues like keymap still referring to operators already unregistered...
    # handle the keymap
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

    bpy.utils.unregister_class(ObjectMetaballThing)
    bpy.types.VIEW3D_MT_object.remove(menu_func)


if __name__ == "__main__":
    register()
$\endgroup$
1
$\begingroup$

Try to bpy.context.scene.update()

Update data tagged to be updated from previous access to data or operators

$\endgroup$
  • $\begingroup$ That's a good idea, but I tried it -- adding the update() call right before execute() returns -- and I was still able to reproduce the problem after that. $\endgroup$ – slerfsterdn May 17 at 16:41

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.