2
$\begingroup$

I have a question about blender's python script. I would like to share variables among more than two operations, however I don't know how to.

If I use global variable, it's easy to solve this problem.

selected_faces = []
class SelectFace(bpy.types.Operator):
    bl_label = "Select Face"
    def execute(self, context):
        global selected_faces
        selected_faces = ...   # get selected faces.
        .....
class OperationAboutSelectedFaces(bpy.types.Operator):
    bl_label = "Operation About selected Face"
    def execute(self, context):
        global selected_faces
        # some operation to "selected_faces"

However, I want to avoid using global variable. So, I would like to rewrite this code as follows...

class SelectFace(bpy.types.Operator):
    bl_label = "Select Face"
    def execute(self, context):
        selected_faces = ... # get selected faces.
        .....
class OperationAboutSelectedFaces(bpy.types.Operator):
    bl_label = "Operation About selected Face"
    def execute(self, context):
        # some operation to "selected_faces"

Assuming operation sequence are as follows.

  1. "Select Face"
  2. "Operation About selected faces"

Thanks!

$\endgroup$
7
  • $\begingroup$ see this question, this answer and this $\endgroup$
    – Chebhou
    Commented Mar 22, 2015 at 13:30
  • $\begingroup$ I tried this one. However this solution makes error AttributeError: 'NoneType' object has no attribute 'operator' because class is derived from bpy.types.Operator. Is there any solutions passed variables between bpy.types.Operator? $\endgroup$
    – nutti
    Commented Mar 24, 2015 at 5:19
  • $\begingroup$ Both of your classes are global, you can store arbitrary data on them if you really have to: SelectFace.your_global = 123 $\endgroup$
    – CodeManX
    Commented Mar 24, 2015 at 22:36
  • $\begingroup$ Can't you pass your selected faces into the constructor of your derived class? Create a constructor (__init__) and pass your selected_faces into it. It would be something like this (check syntax): def __init__(self, selectedFaces): $\endgroup$ Commented Mar 25, 2015 at 20:59
  • $\begingroup$ @nutti is this your answer it is just a comment ? $\endgroup$
    – Chebhou
    Commented Mar 27, 2015 at 15:50

3 Answers 3

3
$\begingroup$

Finally, I solved this problem using static variable.

class SelectFace(bpy.types.Operator):
    bl_label = "Select Face"
    selected_faces = None
    def __init__(self):
        SelectFace.selected_faces = None
    def execute(self, context):
        SelectFace.selected_faces = ... # get selected faces.
        .....
class OperationAboutSelectedFaces(bpy.types.Operator):
    bl_label = "Operation About selected Face"
    def __init__(self):
        selected_faces = SelectFace.selected_faces
    def execute(self, context):
        # some operation to "selected_faces"

Thanks for your advice.

$\endgroup$
3
$\begingroup$

I could solve this problem.

Solution is shown below.

  • Create user defined class which has properties you want.
  • Register class to bpy.types.Scene.XXXXX when add-on is started
  • Get data from bpy.context.scene.XXXXX
  • Unregister class to bpy.types.Scene.XXXXX when add-on is stopped
class SelectFaceProp():
    selected_faces = None

class SelectFace(bpy.types.Operator):
    bl_label = "Select Face"
    def execute(self, context):
        props = bpy.context.scene.sf_props
        props.selected_faces = ... # get selected faces.
        .....
class OperationAboutSelectedFaces(bpy.types.Operator):
    bl_label = "Operation About selected Face"
    def execute(self, context):
        props = bpy.context.scene.sf_props
        # some operation to "props.selected_faces"

def register():
    bpy.types.Scene.sf_props = SelectFaceProp()

def unregister():
    del bpy.types.Scene.sf_props

Thank you!!!

$\endgroup$
1
$\begingroup$

You should not use global or static variables, the proper concept to use is Blender's context. Note that this is not a Python mechanism, but something provided by Blender.

The context keeps track of the state of Blender in things such as 'what is the selected scene? what is the active object? what is the current selection?'. This information can then be used by all of Blender's operators, not just your own. Operators, in turn, also affect the context, by for example, modifying the current selection. If you bypass the context, there will be some inconsistencies, such as operators working on your previous selection, because you never changed it in the context.

How to set that a given face is selected:

face.selected = True

Hot to get all selected faces in a mesh:

selected_faces = [face for face in mesh.faces if face.select]

The mesh can be obtained from the context that is passed as an argument to the operator's execute.

$\endgroup$
3
  • $\begingroup$ Yeah, I don't want to use global and static variable too. However, there is no way to pass variable between bpy.types.Operators. However I tried to store bpy.types.Scene.XXX, It doesn't work... $\endgroup$
    – nutti
    Commented Apr 24, 2015 at 16:39
  • $\begingroup$ You can store new properties in anything that is an ID. Scene should indeed work, as would an operator, but it really needs to be a new Blender property, not just a python variable. See bpy.props $\endgroup$
    – brita_
    Commented Apr 24, 2015 at 17:59
  • $\begingroup$ OK. By the way, is there any way to share PointerProperty? I can share IntProperty/FloatProperty, but I can't share PointerProperty. $\endgroup$
    – nutti
    Commented Apr 25, 2015 at 0:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .