Add Instance Offset operators to Collections property panel

Add three operators to the Collections properties panel:

- `object.instance_offset_to_cursor`, which is already available from
  the Object properties panel. The operator works on the active
  collection, though, so it's weird to not have it in the Collections
  panel.
- `object.instance_offset_from_object` is a new operator, which performs
  the same operation as above, but then based on the active object's
  evaluated world position.
- `object.instance_offset_to_cursor` is also new, and performs the
  opposite of the first operator: it moves the 3D cursor to the
  collection's instance offset.

The first two operators make it easier to set the instance offset. The
last operator makes it possible to actually see the offset in the 3D
viewport; drawing it using some overlay could also work, but that would
be more effort to get right, and then snapping the 3D cursor would still
be useful.

The operators are placed in a popup menu, as to not clutter the
interface too much with various buttons.

Reviewed By: dfelinto, eyecandy

Differential Revision: https://developer.blender.org/D14966
This commit is contained in:
Sybren A. Stüvel 2022-06-07 13:08:11 +02:00
parent 3a8a44b3f9
commit 2935b6a2ac
2 changed files with 47 additions and 2 deletions

View File

@ -855,6 +855,37 @@ class DupliOffsetFromCursor(Operator):
return {'FINISHED'}
class DupliOffsetToCursor(Operator):
"""Set cursor position to the offset used for collection instances"""
bl_idname = "object.instance_offset_to_cursor"
bl_label = "Set Cursor to Offset"
bl_options = {'INTERNAL', 'UNDO'}
def execute(self, context):
scene = context.scene
collection = context.collection
scene.cursor.location = collection.instance_offset
return {'FINISHED'}
class DupliOffsetFromObject(Operator):
"""Set offset used for collection instances based on the active object position"""
bl_idname = "object.instance_offset_from_object"
bl_label = "Set Offset from Object"
bl_options = {'INTERNAL', 'UNDO'}
@classmethod
def poll(cls, context):
return (context.active_object is not None)
def execute(self, context):
ob_eval = context.active_object.evaluated_get(context.view_layer.depsgraph)
world_loc = ob_eval.matrix_world.to_translation()
collection = context.collection
collection.instance_offset = world_loc
return {'FINISHED'}
class LoadImageAsEmpty:
bl_options = {'REGISTER', 'UNDO'}
@ -976,6 +1007,8 @@ class OBJECT_OT_assign_property_defaults(Operator):
classes = (
ClearAllRestrictRender,
DupliOffsetFromCursor,
DupliOffsetToCursor,
DupliOffsetFromObject,
IsolateTypeRender,
JoinUVs,
LoadBackgroundImage,

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from bpy.types import Panel
from bpy.types import Panel, Menu
class CollectionButtonsPanel:
@ -42,6 +42,16 @@ class COLLECTION_PT_collection_flags(CollectionButtonsPanel, Panel):
col.prop(vlc, "indirect_only", toggle=False)
class COLLECTION_MT_context_menu_instance_offset(Menu):
bl_label = "Instance Offset"
def draw(self, _context):
layout = self.layout
layout.operator("object.instance_offset_from_cursor")
layout.operator("object.instance_offset_from_object")
layout.operator("object.instance_offset_to_cursor")
class COLLECTION_PT_instancing(CollectionButtonsPanel, Panel):
bl_label = "Instancing"
@ -51,8 +61,9 @@ class COLLECTION_PT_instancing(CollectionButtonsPanel, Panel):
layout.use_property_decorate = False
collection = context.collection
row = layout.row()
row = layout.row(align=True)
row.prop(collection, "instance_offset")
row.menu("COLLECTION_MT_context_menu_instance_offset", icon='DOWNARROW_HLT', text="")
class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
@ -80,6 +91,7 @@ class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
classes = (
COLLECTION_MT_context_menu_instance_offset,
COLLECTION_PT_collection_flags,
COLLECTION_PT_instancing,
COLLECTION_PT_lineart_collection,