2
$\begingroup$

In Blender when I select an object and I change any setting, the other objects are not affected, but when I create a panel with properties from bpy.props, changing an intProperty on one changes it on the others

Look at this example: I made a custom panel with 2 properties

enter image description here

I create 2 object A and B with property "Resolution" = 12, then on object A I change resolution to 20

enter image description here

when clicking on object B I see that resolution is 20 as well, but I want it to be still 12.

I understand that this is because I have only registered one set of properties, that are all the same, so is there a way to register different properties for each object, and create a panel that shows only the properties of the active one?

(custom ID props could be a workaround, but I would prefer to use a custom panel because it's cleaner and drivers are way worse to trigger update functions)


here there is the part of the code related to properties:

class MyProperties(bpy.types.PropertyGroup):

    sphere_resolution: IntProperty(
        name="Resolution",
        description="resolution of the sphere",
        default=8,
        min=3,
        update=updateResolution #function that changes the subdivisions of the sphere
    )

    sphere_transform: FloatProperty(
        name="Transformation",
        description="curvature of the Radial Sphere: = 0 is a plane, 1 is a sphere",
        default=1.0,
        min=0.0,
        max=1.0
    )


# operator to create the objects. Each object should have its own properties
class MESH_OT_CreateRadialSphere(bpy.types.Operator):
    bl_idname = "mesh.create_radial_sphere"
    bl_label = "Radial Sphere"

    def execute(self, context):
        # stuff
        return {'FINISHED'}

# create panel. Here there should be the properties of the active object, if the active object was created by the create operator, and changing a value should only affect the active object
class MESH_PT_sphere_topologies(bpy.types.Panel):
    bl_idname = "MESH_PT_sphere_topologies"
    bl_label = "Sphere Topologies"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "data"

    @classmethod
    def poll(self, context):
        # stuff

    def draw(self, context):
        layout = self.layout
        mytool = context.scene.SphereTopology

        layout.prop(mytool, "sphere_resolution")
        layout.prop(mytool, "sphere_transform")


classes = (
    MESH_OT_CreateRadialSphere,
    MESH_PT_sphere_topologies,
    MyProperties
)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.SphereTopology = PointerProperty(type=MyProperties)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
    del bpy.types.Scene.SphereTopology
$\endgroup$
4
  • $\begingroup$ Hello, could you post your code ? What is "Resolution" related to ? $\endgroup$
    – Gorgious
    Commented Nov 23, 2020 at 15:05
  • $\begingroup$ @Gorgious I added a schematic version of the code (the entire code is too long). "Resolution" is just a intProperty I created. Each sphere is created with an operator and has a certain resolution: when I select a sphere I want to see the current Resolution value for that sphere and edit it (which through the update function modifies the mesh as needed). In the update function I can tell it to only modify the mesh of the active object, so it's not a problem, the problem is just that the "Resolution" in the panel doesn't reflects the true resolution of the selected sphere $\endgroup$
    – Tareyes
    Commented Nov 23, 2020 at 16:09
  • 1
    $\begingroup$ Thanks ! I think you need to add your SphereTopology class to bpy.types.Objectrather than to bpy.types.Scene else you only have one instance of your MyProperty group (per Scene), and only one shared value $\endgroup$
    – Gorgious
    Commented Nov 23, 2020 at 16:16
  • $\begingroup$ Thanks, you were right $\endgroup$
    – Tareyes
    Commented Nov 23, 2020 at 16:31

1 Answer 1

3
$\begingroup$

Easy. You would have to assign the PointerProperty to bpy.types.Object. Use context.object to get a reference. Demo based on the template from How to create a custom UI?

import bpy

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Menu,
                       Operator,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    Object Properties
# ------------------------------------------------------------------------

class MyProperties(PropertyGroup):

    my_bool: BoolProperty(
        name="Enable or Disable",
        description="A bool property",
        default = False
        )

    my_int: IntProperty(
        name = "Int Value",
        description="A integer property",
        default = 23,
        min = 10,
        max = 100
        )

    my_float: FloatProperty(
        name = "Float Value",
        description = "A float property",
        default = 23.7,
        min = 0.01,
        max = 30.0
        )

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"   


    @classmethod
    def poll(self,context):
        return context.object is not None

    def draw(self, context):
        layout = self.layout
        #scene = context.scene
        mytool = context.object.my_tool

        layout.prop(mytool, "my_bool")
        layout.prop(mytool, "my_int")
        layout.prop(mytool, "my_float")
        layout.separator()

# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------

classes = (
    MyProperties,
    OBJECT_PT_CustomPanel
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

    bpy.types.Object.my_tool = PointerProperty(type=MyProperties)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)
    del bpy.types.Object.my_tool


if __name__ == "__main__":
    register()
$\endgroup$
1
  • $\begingroup$ wow, I feel like a massive idiot now, but I was stuck on this stupid thing for days ahah $\endgroup$
    – Tareyes
    Commented Nov 23, 2020 at 16:32

You must log in to answer this question.

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