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 Nov 23 '20 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 Nov 23 '20 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 Nov 23 '20 at 16:16
  • $\begingroup$ Thanks, you were right $\endgroup$ – Tareyes Nov 23 '20 at 16:31
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 Nov 23 '20 at 16:32

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.