1
$\begingroup$

Since my last question is getting a bit polluted, I'm going to ask this specific question here.

Update Reformatting this question entirely, starting by posting everything I currently have in the scripts. This is the script that's actually making the interface:


import bpy
import sys
sys.path.insert(0,"/path/to/test/folder/addon test") #I can't tell if this is doing anything.
#import import_py

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


# ------------------------------------------------------------------------
#    Scene Properties
# ------------------------------------------------------------------------

class MyProperties(PropertyGroup):

    my_bool: BoolProperty(
        name="DarkSkin",
        description="Tick for Dark Skin",
        default = False
        )
# this bool needs to control two node connections, and a property in a color mix node. Presently I have a tick box that does nothing.

    my_int: IntProperty(
        name = "Resolution",
        description="Mask Image Resolution (Pixels, Square)",
        default = 512,
        min = 256,
        max = 4096
        )

    my_float_vector: FloatVectorProperty(
        name = "Skin Base",
        subtype = "COLOR",
        size = 4,
        description="See the Included Color Pallet",
        default=(0.0, 0.0, 0.0, 1.0), 
        min= 0.0, # float
        max = 1.0
        )
        
    my_float_vector_1: FloatVectorProperty(
        name = "Skin SubSurface Tone",
        subtype = "COLOR",
        size = 4,
        description="See the Included Color Pallet",
        default=(0.0, 0.0, 0.0, 1.0), 
        min= 0.0, # float
        max = 1.0
        ) 
        
    my_float_vector_2: FloatVectorProperty(
        name = "Red Tone",
        subtype = "COLOR",
        size = 4,
        description="Redness",
        default=(0.0, 0.0, 0.0, 1.0), 
        min= 0.0, # float
        max = 1.0
        ) 
        
    my_float_vector_3: FloatVectorProperty(
        name = "Tan Tone",
        subtype = "COLOR",
        size = 4,
        description="Tan or Lightness",
        default=(0.0, 0.0, 0.0, 1.0), 
        min= 0.0, # float
        max = 1.0
        ) 


# ------------------------------------------------------------------------
#    Operators
# ------------------------------------------------------------------------

class WM_OT_Mask(Operator):
    bl_label = "Populate Masks"
    bl_idname = "wm.make_masks"

# This doesn't work, I don't know why. The button is there, but it either throws an error, or does nothing at all. Currently, it does nothing.

    def execute(self, context):
#        scene = context.scene
#        mytool = scene.my_tool
        imggen = "/path/to/test/folder/addon test/imggen.py"
        exec("imggen")


        return {'FINISHED'}

# ------------------------------------------------------------------------
#    Menus
# ------------------------------------------------------------------------

class OBJECT_MT_ObjectMenu(bpy.types.Menu):
    bl_label = "Character Object"
    bl_idname = "OBJECT_MT_custom_menu"

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

        # Built-in operators
        layout.prop(bpy.data.materials["Skin"].node_tree.nodes["Texture Coordinate"], "object")


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

class OBJECT_PT_CustomPanel(Panel):
    bl_label = "DIPSS Initial Setup"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "DIPPS"
    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 = scene.my_tool


        layout.menu(OBJECT_MT_ObjectMenu.bl_idname, text="Character Object", icon="HAND")
        layout.separator()
        layout.prop(mytool, "my_int")
        layout.operator("wm.make_masks")
        layout.separator()
        layout.prop(mytool, "my_bool")
        layout.prop(mytool, "my_float_vector", text="Skin Base Tone")
        layout.prop(mytool, "my_float_vector_1", text="SubSurface Tone")
        layout.prop(mytool, "my_float_vector_2", text="Redness")
        layout.prop(mytool, "my_float_vector_3", text="Tan Tone")
        layout.separator()

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

classes = (
    MyProperties,
    WM_OT_Mask,
    OBJECT_MT_ObjectMenu,
    OBJECT_PT_CustomPanel
)

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

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

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


if __name__ == "__main__":
    register()

This is one of the sections of the Image Generator script that I would like wm.makemasks to trigger:

# blank image
image = bpy.data.images.new("RedMask", width=size[0], height=size[1])

## For white image
# pixels = [1.0] * (4 * size[0] * size[1])

pixels = [None] * size[0] * size[1]
for x in range(size[0]):
    for y in range(size[1]):
        # assign RGBA to something useful
        r = 0
        g = 0
        b = 0
        a = 1.0

        pixels[(y * size[0]) + x] = [r, g, b, a]

# flatten list
pixels = [chan for px in pixels for chan in px]

# assign pixels
image.pixels = pixels

# write image
image.filepath_raw = "//RedMask.png"
image.file_format = 'PNG'
image.save()

# find node and assign the texture to it
img = bpy.data.images.load("//RedMask.png", check_existing=True)
bpy.data.materials["Skin"].node_tree.nodes["RedMask"].image = img
bpy.data.images["RedMask"].colorspace_settings.name = 'sRGB'

The sections are all the same except for file names, and the script works perfectly when I run it.

And this is the script that bridges the Node Tree with the UI script:

import bpy

# ------------------------------------------------------------------------
#    Color Pickers
# ------------------------------------------------------------------------


mat = bpy.data.materials['Skin']
nodes = mat.node_tree.nodes
node = nodes.get("SkinBase")
# change the color
node.outputs[0].default_value = (bpy.data.scenes["Scene"].my_tool.my_float_vector)

mat = bpy.data.materials['Skin']
nodes = mat.node_tree.nodes
node = nodes.get("SubSurface")
# change the color
node.outputs[0].default_value = (bpy.data.scenes["Scene"].my_tool.my_float_vector_1)

mat = bpy.data.materials['Skin']
nodes = mat.node_tree.nodes
node = nodes.get("RedTone")
# change the color
node.outputs[0].default_value = (bpy.data.scenes["Scene"].my_tool.my_float_vector_2)

mat = bpy.data.materials['Skin']
nodes = mat.node_tree.nodes
node = nodes.get("TanTone")
# change the color
node.outputs[0].default_value = (bpy.data.scenes["Scene"].my_tool.my_float_vector_3)

I have decided to move this section to its' own script for two reasons. One, for my own sanity it's easier to group functions like this together so I can check them all. Two, Even if I can't get it to dynamically update, if I can make a button run a script, I can make an Update Button just for this script. Bit less elegant, but that's ok, as long as it works.

I'm really banging my head against a wall on this code here, I'm a 3D and texturing guy, code is gibberish to me. I'd like to learn enough to not struggle on something this relatively simple. Trouble is, I can't actually tell why any of these things work or don't work.

Update I found a solution to make a button that runs a script.

class WM_OT_Mask(Operator):
    bl_label = "Populate Masks"
    bl_idname = "wm.make_masks"

    def execute(self, context):
        text_main= bpy.data.texts['imggen']
        context_c = context.copy()
        context_c['edit_text'] = text_main
        bpy.ops.text.run_script(context_c)
        return {'FINISHED'}

This question held the answer. Now I must see if there's an answer to my other problem hidden in this technique.

$\endgroup$
3
  • $\begingroup$ You should post the entire script, or at least everything connected to this issue, it's hard to tell what the aim is or what the issue might be coming from from just this little bit of code. $\endgroup$
    – Jakemoyo
    Jun 21, 2022 at 22:00
  • $\begingroup$ You can register an update function in the FloatVectorProperty and update the RGB Node in that update function. Without seeing a complete error traceback and more of the surrounding code it's impossible to guess what's wrong with the second fragment. $\endgroup$ Jun 21, 2022 at 22:03
  • $\begingroup$ The whole code is kind of a mess... I've been cludging things together until things work. I'll see about trimming it down and updating. $\endgroup$ Jun 21, 2022 at 22:07

1 Answer 1

1
$\begingroup$

I figured out a way to do this that doesn't involve the second script at all.

skinbase = bpy.data.materials["Skin"].node_tree.nodes["SkinBase"].outputs[0]
layout.template_color_picker(skinbase, "default_value", value_slider=True)

It took me almost all day to get it, turns out the trick is to define the output in the def line, and define "default_value" in the layout line. The only thing wrong with this approach is that it displays as the full wheel interface. If anyone can find me a way to collapse it to a single bar, I'd appreciate it.

Update I figured that out just now:

layout.prop(skinbase, "default_value", text="Skin Base Tone")

This way it displays as a simple color bar, and expands to the full wheel interface when you click on it.

$\endgroup$

You must log in to answer this question.

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