How to create an operator for the mapping node (scale)

Scale
I made an addon (well, just two buttons for now) that adds and set nodes for tri-planar mapping textures. This, since Quixel Bridge drops only a bunch of textures and connect them to the principled BSDF. Got that, and works. So there is a button: add box mapping. Yay! But now I want the users to be able to adjust the scale (mapping node) in the UI.
The data path is: node_tree.nodes["Mapping"].inputs[3].default_value

So I guess I have to use, in the Operator Class, something with:
bpy.context.object.active_material.node_tree.nodes["Mapping"].inputs[3].default_value

And probably I need to set up a FloatVector property in the operator class so I get the scale x,y,z together in the UI?.

So far I got only this:

class QXH_OT_scaletex(bpy.types.Operator): 
    bl_idname ="qhx.scaletex"
    bl_label  = "Scale Texture"
    bl_description = "Scale the texture"
    
    @classmethod
    def poll(cls, context):
        return context.active_object is not None
    
    def execute(self, context):
        # Make some references to material and it's nodes
        activemat = context.object.active_material
        treenode = activemat.node_tree.nodes
        
        #scale the texture
        # treenode["Mapping"].inputs[3].default_value
        # ............
        
        return {FINISHED}

Try this:

bpy.context.object.active_material.node_tree.nodes["Mapping"].inputs["Scale"].default_value = (0.5,0.5,0.5)
1 Like

It works, but gives a button and sets the scaling to 0.5:
image
I’ll do some tests, and see if I can sliders

Update: not sure where I am heading to, so far I got:


class QXH_OT_scaletex(bpy.types.Operator): 
    bl_idname ="qxh.scaletex"
    bl_label  = "Scale Texture"
    bl_description = "Scale the texture"
    
    #create properties
    scale_prop : bpy.props.FloatVectorProperty(
        subtype="XYZ", 
        min=0.0, 
        max=1.0,
        size=4)     # size? 
    
    @classmethod
    def poll(cls, context):
        return context.active_object is not None  # todo: and if material has a mapping node
    
    def execute(self, context):
        # Make some references to material and it's nodes
        activemat = context.object.active_material
        treenode = activemat.node_tree.nodes
        
        #scale the texture
        # treenode["Mapping"].inputs["Scale"].default_value = (0.5,0.5,0.5) ...
        # ... that gave a button in the UI panel, and set the mapping to 0.5 
        # ....checking on how to get sliders instead
    
    def draw(self, context):
        row.prop(self, "scale_prop", text="Scale Texture")
        
        return {FINISHED}

Sliders are cool, but you should use a textbox instead, it’s much more practical.

Textbox looks to cumbersome to me; you think 0.2 is nice, press ok. No, 0.3 maybe. No, 0.23… Ahw yes, 0.236. So that is typing 4 times, and 4 times confirming? Why you favour texbox for scaling a texture?

def invoke(self,context,event):
        return context.window_manager.invoke_props_dialog(self)

You need this. Draw function is used to customize how this popup/dialog_box would look like. It is not necessary.

What if you want 0.24 but the slider jumps from 0.23 to 0.25? Or if you want a scale of 100 but the slider only allows [-5, +5]? Besides numeric textboxes can also slide if you click and drag the number.

1 Like

Also if you want slider you can use slider = True for property. But i suggest to define min and max if you are going to use sliders.

row.(context.object, "prop", slider=True)
1 Like

I got it to work with a function as described here: How to create panel for setting operator properties? - #2 by Shawn_Irwin by @Shawn_Irwin
And then you need to register the function.
The function is like this:

def do_update( self, context ):
    if context.active_object:
        context.active_object.location.x = self.someValue
    print( 'update', self.someValue )

And registration like this:

def register():
    bpy.types.Scene.someValue = bpy.props.FloatProperty(name = "Float", 
        description = "Enter a float", min = -100, max = 100, update=do_update )
    bpy.utils.register_class(SomePanel)

def unregister():
    bpy.utils.unregister_class(SomePanel)
    del bpy.types.Scene.someValue

And in the panel like this:

    def draw(self, context):
        layout = self.layout
        scn = context.scene
        layout.prop( scn, 'someValue' )

The only thing , the values show up in my panel like this:
vectorScale

The only thing is I need to have those vertical so the user can adjust the 3 values in one go.

Use bpy.props.FloatVectorProperty

1 Like

Ah, I didn’t know you can slide numbers in texboxes. I know a lot already, but there is way more to learn still for me. :upside_down_face:

1 Like