2
$\begingroup$

Is it possible to set some rotation values to Blender GUI corresponding object fields (or any other like location or scale) without actually applying them to the object itself, like some sort of "offset"?

I mean I have script that set some objects to scene, rotate them right but writes its values as (0,0,0) instead of their real rotation values (but I know those real values myself so I could set them BUT without changing object actual rotation)...like let's say object rotation value is 0 but I want to be represented and set visually in Blender rotation fields as 90 - is something like this possible, please?

P.S.: I NEED SCRIPT BASED ANSWERS ONLY

$\endgroup$
6
  • 1
    $\begingroup$ You could try something like setting the rotation to -180 (and actually rotating the object), applying it (setting rotation to zero without affecting the object), then rotating by 90. $\endgroup$
    – gandalf3
    Commented Jun 1, 2014 at 20:00
  • $\begingroup$ actually that was exactly what I was intended to do right from the first time but the problem is that the code is really quite complicated dealing with mathutils Matrix so it cannot be done easily like that simply because it is really problem to understand the code in its complexity...so I really need to know if what I am asking is possible at all $\endgroup$
    – bublible
    Commented Jun 1, 2014 at 21:41
  • $\begingroup$ @gandalf3 actually as I play more with the code now I see what you meant by APPLY and it could work, that was part I was missing in my concept ;) gonna play more with ot and then let you know... $\endgroup$
    – bublible
    Commented Jun 1, 2014 at 22:42
  • $\begingroup$ @gandalf3 yea, your solution with APPLYING CHANGES making values offset-like finaly works after some time of tweaking and changing things around, thanx a lot for the suggestion my friend! ;) $\endgroup$
    – bublible
    Commented Jun 2, 2014 at 10:17
  • $\begingroup$ Could you post your answer in the Answers box so this question can be marked as "answered"? $\endgroup$
    – rioforce
    Commented Jun 2, 2014 at 14:32

4 Answers 4

3
$\begingroup$

Here's a script which does this, comments inline.

import bpy
import math

#target rotation:
target_rotation = [90, 90, 90]
#object to operate on (active object):
ob = bpy.context.active_object



#this assumes you are starting at 0 rotaton, so you pobably want to apply rotation before doing anything:
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False) #apply rotation
#get inverse of rotation we want:
t_rot = (math.radians(target_rotation[0]*-1),
         math.radians(target_rotation[1]*-1), 
         math.radians(target_rotation[2]*-1))
#we need to apply the rotations in reverse order, so unsure that we are in zyx:
ob.rotation_mode = 'ZYX'
ob.rotation_euler = (t_rot) #set rotation to inverse
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False) #apply rotation

t_rot = (math.radians(target_rotation[0]),
         math.radians(target_rotation[1]), 
         math.radians(target_rotation[2]))
ob.rotation_mode = 'XYZ' #set rotation mode back (was zyx, so we want xyz)
ob.rotation_euler = (t_rot) #set rotation

Pardon my probably poor python ;)

$\endgroup$
2
  • 1
    $\begingroup$ I was searching for this whole evening... thanks :) $\endgroup$ Commented Sep 1, 2022 at 22:35
  • $\begingroup$ The script gandalf3 provided works great for me. Is there a way to apply this to all selected objects in a hierarchy? When I select a hierarchy and run this script, only the object at the top of the hierarchy gets updated. $\endgroup$
    – skuwid
    Commented Jul 24 at 20:20
1
$\begingroup$

Just for completeness sake

So gandalf3 provided a beautiful answer applying the difference. If however, you want to actually change the values, and only fake differing values in the user interface, you can overwrite the interface instead. The idea is to display custom properties instead of the ones usually found. The custom properties can then in turn set, get and modify the true values according to your likings.

This here is a much simplified example overwriting the render-panel.

class Render_panel_override(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Render"
    bl_idname = "RENDER_PT_render" # <== we assume the same bl-id that the original panel has
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "render"

    def draw(self, context):
        layout = self.layout
        obj = context.scene.objects.active

        layout.row().label(text="Hello world!", icon='WORLD_DATA')
        layout.row().label(text="Active object is: " + obj.name)
        layout.row().prop(obj, "name")
        layout.row().operator("mesh.primitive_cube_add")

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

def unregister():
    bpy.utils.unregister_class(Render_panel_override)
$\endgroup$
0
$\begingroup$

You could try something like setting the rotation to -180 (and actually rotating the object), applying it (setting rotation to zero without affecting the object), then rotating by 90. – correct answer provided by gandalf3

$\endgroup$
0
$\begingroup$

Note: This anwser is based on gandalf3 correct solution and is related to @skuwid comment in the gandalf3 anwser comments

Here is what I created based on gandalf3 answer to iterate through all selected objects:

import bpy
import math

# Target rotation:
target_rotation = [90, 90, 90]

# Objects to operate on (all selected objects):
selected_objects = bpy.context.selected_objects

# Loop through all selected objects
for ob in selected_objects:
    # Deselect all objects first to avoid any overlap
    bpy.ops.object.select_all(action='DESELECT')

    # Select the current object and make it active
    ob.select_set(True)
    bpy.context.view_layer.objects.active = ob

    # Apply current rotation to zero out before applying new rotation
    # Using isolate_users here is optional - in my case I had to use it because children of my objects have been using Multi User Data which dissallowed applying transform
    bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, isolate_users = True)

    # Get inverse of the rotation we want
    t_rot = (math.radians(target_rotation[0] * -1),
         math.radians(target_rotation[1] * -1),
         math.radians(target_rotation[2] * -1))

    # Set rotation mode and apply the inverse rotation in ZYX order
    ob.rotation_mode = 'ZYX'
    ob.rotation_euler = t_rot  # Set rotation to inverse
    bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)

    # Now apply the actual target rotation
    t_rot = (math.radians(target_rotation[0]),
         math.radians(target_rotation[1]),
         math.radians(target_rotation[2]))

    ob.rotation_mode = 'XYZ'  # Set rotation mode back to XYZ
    ob.rotation_euler = t_rot  # Set rotation

    # Deselect the current object before moving to the next one
    ob.select_set(False)

I'm also not using blender and python very often so beware of any mistakes I may have accidentally put there ;)

$\endgroup$
2
  • $\begingroup$ How does this help the OP? $\endgroup$
    – Joachim
    Commented Sep 17 at 16:02
  • $\begingroup$ @Joachim user skuwid in the replies to gandalf3 anwser has asked for a version of the script that works for all selected objects. Since I did that I figured i might post my solution in case someone would need it. At first I wanted to put it in a comment below skuwid question but i was not allowed to do that so I posted it as an anwser. $\endgroup$ Commented Sep 18 at 7:48

You must log in to answer this question.

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