3
$\begingroup$

I have an add-on split into multiple files.

Here is my file structure:

blueprint
    │   main_operator.py
    │   main_panel.py
    │   main_properties.py
    │   __init__.py
    │
    ├───buildings
    │       Apartment.py
    │       grid_build.py
    │       Office.py
    │       Skyscrappers.py
    │       small_shops.py
    │
    └───tools
            blender_tools.py

In my main_operator.py file I have this option in the class enabled: bl_options = {'REGISTER', 'UNDO'} Although when I run the add-on, all works but I get no 'Undo Panel' on the bottom left hand side once the add-on is run.

Typically in a simple file I would have the props variables defined inside the operator class.

bpy.props.BoolProperty()
bpy.props.FloatProperty()
bpy.props.IntProperty()
bpy.props.PointerProperty()
bpy.props.StringProperty()

All inside the Operator Class.

But in my complex file system I have successfully split them into a main_properties.py and main_operator.py

Here is my __init__.py:

bl_info = {
    "name": "Blueprint",
    "author": "Davi Silveira <vidasilveira85@gmail.com>",
    "version": (1, 0, 8),
    "blender": (2, 90, 1),
    "category": "Add Mesh",
    "location": "VIEW3D > BLueprint > UI",
    "description": "We Built This City",
    "warning": "Still under development",
    "doc_url": "",
    "tracker_url": "",
}

import bpy

from . main_operator import VIEW3D_OT_Blueprint
from . main_panel import OBJECT_PT_Blueprint
from . main_properties import Blueprint_Properties

classes = (
    OBJECT_PT_Blueprint,
    VIEW3D_OT_Blueprint,
    Blueprint_Properties,
    )

#### -----------------------------------------
#### Register Classes
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.tools = bpy.props.PointerProperty(type=Blueprint_Properties)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
    del bpy.types.Scene.tools
#### -----------------------------------------

I link in my main_panel.py to my Properties in my main_properties.py file by using: scene = context.scene.tools It all works as it should I guess. But in my main_operator.py file this scene = context.scene.tools does not work. All variables are frozen... They only change when I change the main add-on panel, the UNDO panel in the bottom will not change, only mirrors the main one. enter image description here

Here is my '''main_operator```:

import bpy

from .tools.blender_tools import move_it, re_size, hide, de_select, dimension
from .buildings.grid_build import grid
from . main_properties import Blueprint_Properties

class VIEW3D_OT_Blueprint(bpy.types.Operator):
    """Blueprint we built this city"""
    bl_label    = "Building Options".upper()
    bl_idname   = "mesh.blueprint"
    bl_category = "View"
    bl_context  = "objectmode"
    bl_options  = {'REGISTER', 'UNDO'}

    ####--Execute
    ####------------------------------------------------------
    def execute(self, context):
        ####--Pre Start
        de_select(True, 'OBJECT') # Select All Objs
        hide(True)
        # deactivate others
        for obj in bpy.data.objects:
            if obj.select_get() is True:
                obj.select_set(False)

        current_coll = bpy.context.collection # list of all collections
        new_coll = bpy.data.collections.new('Buildings') # new collection
        bpy.context.scene.collection.children.link(new_coll) # show in OUTLINER
        ####-----------------------------------------------------

        ####--Call Functions to Run Script
        scene = bpy.context.scene
        tool  = scene.tools
        
        # bpy.context.scene.tool_settings.use_snap = True
        grid(tool.x_location, tool.y_location, current_coll, new_coll)
        ####-----------------------------------------------------
        
        return {'FINISHED'}
    
    #def draw(self, context):
        #layout = self.layout
        #scene = context.scene.tools

        #row = layout.row()
        #box = row.box()

        #box.label(text='The Grid Blueprint', icon='LIGHTPROBE_GRID')
        
        #layout.separator()

        #col = layout.column(align=True)
        #box = col.box()
        #box.prop(scene, "density", icon='GROUP_VERTEX')
        
        #box.label(text='Location Options')
        #box.prop(scene, "random_placement", icon='SNAP_GRID')
        #box.prop(scene, "rotation_variation", icon='DRIVER_ROTATIONAL_DIFFERENCE')
        
        #col = layout.column(align=True)  
        #col.label(text='Grid Properties', icon='SNAP_GRID')
        #col.prop(scene, "x_location", icon='AXIS_SIDE')
        #col.prop(scene, "y_location", icon='AXIS_FRONT')

        #col = layout.column()
        #box = col.box()
        #box.prop(scene, "random_memory", icon='MEMORY')

Here is my main_properties.py:

import bpy

from bpy.props import IntProperty, StringProperty, BoolProperty, FloatProperty

class Blueprint_Properties(bpy.types.PropertyGroup):
    density: IntProperty(
        name = "City Density",
        description = "How far apart building are to each other",
        default = 45,
        min = 1,
        max = 100
    )

####---------------------------------------------------
####---Buildings
    apartment_building: BoolProperty(
        name = "Apartment Buildings",
        description = "Variety of Apartment Complexes",
        default = True
    )

    office_building: BoolProperty(
        name = "Office Buildings",
        description = "Variety of Office Buildings",
        default = False
    )
    
    skyscraper_building: BoolProperty(
        name = "Skyscraper Buildings",
        description = "Variety of Skyscrapers",
        default = False
    ) 
####---------------------------------------------------

####---------------------------------------------------
####---Buildings Floors
    apartment_floors: IntProperty(
        name = "Maximum Floors",
        description = "How many floors per Apartment",
        default = 14,
        min = 3,
        max = 100
    )

    office_floors: IntProperty(
        name = "Maximum Floors",
        description = "How many floors per Office Building",
        default = 25,
        min = 5,
        max = 100
    )

    skyscraper_floors: IntProperty(
        name = "Maximum Floors",
        description = "How many floors per Skyscraper",
        default = 53,
        min = 30,
        max = 100
    )
####---------------------------------------------------

    random_placement: BoolProperty(
        name = "Random Placement",
        description = "Randomize whether a building will be placed",
        default = False
    )

    rotation_variation: BoolProperty(
        name = "Rotation Variation",
        description = "Allow variation in the rotation of objects",
        default = True
    )

    x_location: IntProperty(
        name= "X Location",
        description="Number of buildings to build in X axis",
        default=4, min=1, soft_max=10, max=20
    )

    y_location: IntProperty(
        name= "Y Location",
        description="Number of buildings to build in X axis",
        default=4, min=1, soft_max=10, max=20
    )

    random_memory: IntProperty(
        name = "Random Memory",
        description = "Random Versions",
        default = 1,
        min = 1,
        max = 100
    )

THINGS I'VE TRIED

  1. Got rid of the def draw function in the operator which gives me nothing... Why is that? Typically with the bl_options = {'REGISTER', 'UNDO'} I should get the properties in a small side panel.

  2. When I add def draw with tool = context.scene.tools I can see everything in the UNDO but nothing works. All variables are frozen... anytime I try changing anything in the console it runs the script but nothing changes. ** What I do to the main panel shows up in the 'UNDO' Panel in the bottom of the screen like a mirror.

$\endgroup$
7
  • $\begingroup$ going to be far less confusing if you use tools = context.scene.tools Could you please add the code to define and register scene tools propertygroup. $\endgroup$
    – batFINGER
    Feb 3 '21 at 19:39
  • $\begingroup$ Sure, thing. Thanks Adding it now $\endgroup$ Feb 3 '21 at 20:58
  • $\begingroup$ I just found out that when I add a draw function to my operator class. Referencing the props by tool = context.scene.tools the UNDO options shows everything correctly, but I just figured out it's not exactly frozen but a copy of the main_panel class I can change the variables in the main side panel and it changes the 'UNDO' panel on the bottom left... $\endgroup$ Feb 3 '21 at 21:14
  • $\begingroup$ You need to register your property group and then refer to it by the name(space) you've registered it under. This line looks wrong to me: box.prop(Blueprint_Properties, "density", icon='GROUP_VERTEX'). Blender should already give you a hint at the source of the issue. Check the console/terminal for error messages (Linux, macOS - start Blender from a terminal; Window - Use Window > Toggle System Console). $\endgroup$
    – Robert Gützkow
    Feb 3 '21 at 22:00
  • $\begingroup$ Robert G. Thanks, that line was totally wrong... it should of been scene but you know when I fix that I get a duplicate of the main_panel on the 'UNDO' panel in the bottom left. It's frozen and only changes when I change the main Panel add-on. Like it's linked to it... I've been using the terminal this whole time, the "toggle_system_console" from Blender. I'll try starting Blender from the Terminal but I really don't know what it will tell me. Thanks again $\endgroup$ Feb 4 '21 at 0:58
1
$\begingroup$

I figured it out,

I needed to add all of the Properties I used in my main_properties.py file into my Operator. Then reference those as self instead of using the scene = bpy.context.scene; tool = scene.tools. I was referencing tool which was routing back to my side panel addon Properties Attributes. It should look like this.

class VIEW3D_OT_Blueprint(bpy.types.Operator):
    """Blueprint we built this city"""
    bl_label    = "Building Options".upper()
    bl_idname   = "mesh.blueprint"
    bl_category = "View"
    bl_context  = "objectmode"
    bl_options  = {'REGISTER', 'UNDO'}
    
    ####---------------------------------------------------
    ####---
    Buildings
    apartment_building: BoolProperty(
        name = "Apartment Buildings",
        description = "Variety of Apartment Complexes",
        default = True
    )

    office_building: BoolProperty(
        name = "Office Buildings",
        description = "Variety of Office Buildings",
        default = False
    )
    
    skyscraper_building: BoolProperty(
        name = "Skyscraper Buildings",
        description = "Variety of Skyscrapers",
        default = False
    ) 
    ####---------------------------------------------------
    ####--Execute
    ####------------------------------------------------------
    def execute(self, context):
        ####code###

    def draw(self, context):
        layout = self.layout

        col = layout.column()
        col.prop(self, "apartment_building")
```
$\endgroup$

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.