help for a small script

“”"
i need some help to do the following for all objects
at least all meshes in scene
may be with an option for only selected objects!

reset origin to center of object
reset the location scale and rotation

and equivalent to when we go in edit mode

set smooth
and re calculate all normals
then in data preference set the auto smooth to about 37 degrees

is it possible to do that with the new Bmesh data may be?

“”"
I got some codes working but need to add all the other parts
and not certain how to make it as simple as possible and fast
in case there is a lot of objects in scene




import bpy

scene = bpy.context.scene


for obj in bpy.context.scene.objects:
    if obj.type=="MESH":
        print ('ob name=',obj.name)
        bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
    
        apply_modifiers = True
#        modifiedmesh = object.to_mesh(scene,apply_modifiers,'PREVIEW')
    
scene.update()


#  mode Make it smooth
bpy.ops.object.shade_smooth()

# Edit mode re Calculate all normals

# show Face's Normals 
bpy.data.meshes[ "name" ].show_normal_face

# Re center origin

bpy.ops.object.origin_clear()                                    # Clear the object’s origin.
bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN')                # Set the object’s origin, by either moving the data, or set to center of data, or use 3d cursor


scene.update()





thanks for any feedback
happy bl

When you use operators like:

bpy.ops.object.transform_apply

they are acting on the selected objects so you need to select each object before calling it.

Apply all transforms to scene mesh objects

import bpy


scene = bpy.context.scene
objects = scene.objects


for obj in objects:
    if obj.type=="MESH":
        obj.select = True
    else:
        obj.select = False


# As this operator works on all selected objects not just the active one we 
# only need to call it once here instead of within the for loop, this will also be faster.
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)

and you can replace:

for obj in objects:
    if obj.type=="MESH":
        obj.select = True
    else:
        obj.select = False

with:

for obj in objects:
    obj.select = True if obj.type == "MESH" else False

Although that won’t make your code any faster. Here is a basic example of an operator that I think will do everything you’ve asked:


#TO RUN:
# Object Mode->[space_bar]->Test Example Operator

import bpy
from bpy.props import *
import math


class ExampleOperator(bpy.types.Operator):
    bl_idname = "object.example_operator"
    bl_label = "Test Example Operator"
    bl_options = {'REGISTER', 'UNDO'}


    ob_types = [('ALL_TYPES', "All Types", "", 1),
             ('MESH', "Meshes Only", "", 2),
             ('CURVE', "Curves Only", "", 3)]


    # Filter
    object_type = EnumProperty(items=ob_types, name="Object Types", default='ALL_TYPES')
    selected_only = BoolProperty(name="Selected Only", 
                                 description="Apply only to the selected object(s) otherwise apply to \
                                              all scene objects of the specified object type.",
                                 default=True)


    origin_types = [('GEOMETRY_ORIGIN', "GEOMETRY_ORIGIN", "", 1),
                    ('ORIGIN_GEOMETRY', "ORIGIN_GEOMETRY", "", 2),
                    ('ORIGIN_CURSOR', "ORIGIN_CURSOR", "", 3),
                    ('ORIGIN_CENTER_OF_MASS', "ORIGIN_CENTER_OF_MASS", "", 4)]


    origin_type = EnumProperty(items=origin_types, 
                               name="Origin Set To", 
                               default="ORIGIN_GEOMETRY")


    location = BoolProperty(name="Location", default=False)
    rotation = BoolProperty(name="Rotation", default=True)
    scale = BoolProperty(name="Scale", default=True)


    autosmooth_angle = FloatProperty(name="Auto Smooth Angle", subtype='ANGLE', default=math.radians(37.0))


    @classmethod
    def poll(cls, context):
        return True if context.mode == 'OBJECT' else False


    def execute(self, context):


        scene = bpy.context.scene
        objects = context.selected_objects if self.selected_only else scene.objects


        if self.object_type == 'ALL_TYPES':
            if not self.selected_only: # No point reselecting as we used context.selected_objects
                for obj in objects:
                    obj.select = True
        else:
            for obj in objects:
                obj.select = True if obj.type == self.object_type else False


        #bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.origin_set(type=self.origin_type)
        bpy.ops.object.transform_apply(location=self.location, rotation=self.rotation, scale=self.scale)
        bpy.ops.object.shade_smooth()


        mesh_objects = [ob for ob in objects if ob.type == 'MESH']


        for ob in mesh_objects:
            mesh = ob.data
            mesh.use_auto_smooth = True
            mesh.auto_smooth_angle = self.autosmooth_angle
            mesh.show_normal_face = True


            scene.objects.active = ob # Make this object the active one
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.normals_make_consistent()
            bpy.ops.object.mode_set(mode='OBJECT')




        return {'FINISHED'}


def register():
    bpy.utils.register_class(ExampleOperator)


def unregister():
    bpy.utils.unregister_class(ExampleOperator)


if __name__ == '__main__':
    register()


Hope it helps!

When you use operators like:

bpy.ops.object.transform_apply

they are acting on the selected objects so you need to select each object before calling it.


# Apply all transforms to scene mesh objects
import bpy

scene = bpy.context.scene
objects = scene.objects

for obj in objects:
    if obj.type=="MESH":
        obj.select = True
    else:
        obj.select = False

# As this operator works on all selected objects not just the active one we 
# only need to call it once here instead of within the for loop, this will also be faster.
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)

and you can replace:

for obj in objects:
    if obj.type=="MESH":
        obj.select = True
    else:
        obj.select = False

with:

for obj in objects:
    obj.select = True if obj.type == "MESH" else False

Although that won’t make your code any faster. Here is a basic example of an operator that I think will do everything you’ve asked:

Example_Operator.zip (1.23 KB)

Hope it helps!

I almost forgot about this thread!

nice example here thanks
will study that

now what is the difference between center of mass and origin geometry
I thought this was the same thing !

when you start this it will stay active and each time you select anything will do the clean up automatically if I understand it right

but I would prefer to run it when needed from let say a run button in the tool panel
cause I don’t need to redo it each time I select things

it is more to use it ounce and a while and do some clean up on some objects faster then doing it manually.

many times I add a few objects change scale and rot and instead of manually doing these few things for each object
just do it faster with small script that can help save time and frustration of repeating commands

but this script should do the job

only thing missing is the Re calculate all face’s normal on selected objects

but even that is not really good enough in Bl
some times you still need to change some normals manually
is there a way to make the manual changes done for good
cause if you re calculate it will screw some normals again !

thanks
happy bl

Well ‘origin to center of mass’ is pretty self explanatory as you can kind of see in the image below there is an equal amount of mass on either side of the pivot point i.e. the pivot is not in the center. However ‘origin to geometry’ I think is just averaging the positions of all the verts and because there are more verts at the bottom of the object the pivot is placed further down.

Yup exactly! if you register an operator with the line:

bl_options = {‘REGISTER’, ‘UNDO’}

Blender will undo the operators changes and re-execute the operator every time you change a setting. However, operators do remember changes to their setting, so the next time you execute the operator it will use the modified settings and not the hard coded default ones. So you can for example select one object execute the operator and perform the required changes then select all the other objects and execute the operator again to apply those modified setting again.

First off, just in case you are unaware of it, all buttons in the Blender UI are just operators so you can create a panel and simply add this example operator to it.

So you would prefer to be able to set all the options first then run the operator, OK that’s easy enough to change…hold on…

OK done. :stuck_out_tongue:
my_tools.zip (1.54 KB)

Although I think the only reason to really change to this way of operating would be if the script was actually taking a noticeable amount of time to execute, which I guess may happen if you run it on a crazy amount of objects and/or objects with very high poly counts.

Have you tried the ‘Copy Attributes Menu’ addon that ships with Blender? With it you can easily copy various attributes like scale, rotation etc from the active object to all the other selected objects.

Actually it does do that, but I didn’t add an option to disable it.

There’s no pleasing some people :rolleyes:

Well I assume you are marking the edges sharp in edit mode so I guess Blender is just not able to maintain the data. Personally I haven’t had any problems but I don’t do much low poly modeling. If you want to post an example blend showing this problem I’d be happy to take a look at it for you.

You’re welcome.