4
$\begingroup$

My problem is as following:

I want to create custom rendering settings for Blender, that will set up the camera and the screen resolution - initialize an isometric projection, basing on the target tile width given in pixels.

I can do almost everything: I've created a Panel in the "RENDER" tab in the Properties view, and I've created an operator which will render everything and export the sprites in a designed format.

The only thing that is left is that I can't create controls for the settings that need to be there: the slider for the tile width, or perhaps other settings - I need to be able to read this values when the addon renders stuff.

The UILayout "layout" object that I can get from "self.layout" in the panels draw method has a method called "prop", but it requires an instance of an ID class object or OperatorProperties instance (the docs say it needs AnyType but in order . The first would work if I've kept the data per Object or per Scene basis. But I don't really know if this is a good idea.

This is a stub of what I got:

import bpy

bl_info = { 
    "name":     "Render ISO", 
    "category": "Render"  # perhaps wrong
}



class RenderIsoOperator(bpy.types.Operator):
    ''' An example operator for addon '''
    bl_idname = "render.render_iso"
    bl_label  = "Render ISO"
    bl_options = {'REGISTER'}

    tile_width = bpy.props.IntProperty(
        name="Tile width",
        min=0,
        max=1000
    )

    def execute(self, context):
        obj = context.scene.objects.active
        # Do the rendering here
        return {"FINISHED"}

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

class RenderIsoPanel(bpy.types.Panel):
    bl_idname = "RENDER_PT_render_iso"
    bl_label = "Render ISO"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "render"
    bl_options = {'DEFAULT_CLOSED'}


    def draw(self, context):
        layout = self.layout
        layout.operator(RenderIsoOperator.bl_idname)
        # Get the controls here.

def register():
    bpy.utils.register_class(RenderIsoOperator)
    bpy.utils.register_class(RenderIsoPanel)

def unregister():
    bpy.utils.unregister_class(RenderIsoOperator)
    bpy.utils.register_class(RenderIsoPanel)



if __name__ == "__main__":
    register()
$\endgroup$
2
  • $\begingroup$ I'd recommend use a PropertyGroup, possibly with a callback: blender.stackexchange.com/a/10919/3710 $\endgroup$
    – p2or
    Dec 22, 2015 at 13:47
  • $\begingroup$ A quick note from me: the "render" bl_context doesn't work if you don't support the COMPAT_ENGINES = ["CYCLES", "EEVEE"] in newer Blender versions. $\endgroup$
    – luke1985
    Jan 19, 2021 at 11:47

1 Answer 1

5
$\begingroup$

Using both a pointer, property group setup. The tile width, scene.iso_render.tile_width, is passed to the operator. You could bypass defining and using the operator property entirely and just use context.scene.iso_render.tile_width (and other settings) directly in the operator.

import bpy
from bpy.props import IntProperty, PointerProperty
from bpy.types import PropertyGroup, Operator, Panel
from bpy.utils import register_class, unregister_class

bl_info = { 
    "name":     "Render ISO", 
    "category": "Render"  # perhaps wrong
}

class RenderIsoOperator(Operator):
    ''' An example operator for addon '''
    bl_idname = "render.render_iso"
    bl_label  = "Render ISO"
    bl_options = {'REGISTER'}

    tile_width = IntProperty(
        name="Tile width",
        min=0,
        max=1000
    )

    def execute(self, context):
        obj = context.scene.objects.active
        # Do the rendering here
        return {"FINISHED"}


class RenderIsoPanel(Panel):
    bl_idname = "RENDER_PT_render_iso"
    bl_label = "Render ISO"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "render"
    bl_options = {'DEFAULT_CLOSED'}

    def draw(self, context):
        scene = context.scene
        layout = self.layout
        op = layout.operator(RenderIsoOperator.bl_idname)
        op.tile_width = scene.iso_render.tile_width
        layout.prop(scene.iso_render, "tile_width")

class IsoRenderSettings(PropertyGroup):
    tile_width = IntProperty(
        name="Tile width",
        min=0,
        max=1000
    )
def register():
    register_class(IsoRenderSettings)

    bpy.types.Scene.iso_render = PointerProperty(type=IsoRenderSettings)
    register_class(RenderIsoOperator)
    register_class(RenderIsoPanel)

def unregister():
    unregister_class(IsoRenderSettings)
    unregister_class(RenderIsoOperator)
    unregister_class(RenderIsoPanel)
    del(bpy.types.Scene.iso_render)

if __name__ == "__main__":
    register()
$\endgroup$
1
  • $\begingroup$ Yes, that's what I actually did, I wanted to avoid writing to the Scene(ID) datablock, but I've found no workaround. Thanks nevertheless, this will certainly stand for some knowledge of the not-so-easy Blender Python API. $\endgroup$
    – luke1985
    Dec 22, 2015 at 14:55

You must log in to answer this question.

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