Commit: 459365443f62d2f8e8718c1d1b0fbaafd6d765de
Author: Campbell Barton
Date:   Sun Aug 6 19:47:25 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB459365443f62d2f8e8718c1d1b0fbaafd6d765de

Manipulator: experimental lamp positioning tool

- New manipulator tracks lamps to position under cursor.
- Works with multiple lamps, keeping relative offsets.
- Holding Ctrl moves the lamp.
- Access via manipulator or Shift-T.

Code could be improved, but like to get feedback from users.

===================================================================

M       release/scripts/startup/bl_ui/space_view3d.py
M       source/blender/editors/object/object_intern.h
M       source/blender/editors/object/object_ops.c
M       source/blender/editors/object/object_transform.c
M       source/blender/editors/space_view3d/space_view3d.c
M       source/blender/editors/space_view3d/view3d_intern.h
M       source/blender/editors/space_view3d/view3d_manipulator_lamp.c
M       source/blender/editors/transform/transform_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py 
b/release/scripts/startup/bl_ui/space_view3d.py
index 28b9180bfa9..761e6294ffa 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -300,6 +300,12 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
         layout.operator("object.randomize_transform")
         layout.operator("object.align")
 
+        # TODO: there is a strange context bug here.
+        """
+        layout.operator_context = 'INVOKE_REGION_WIN'
+        layout.operator("object.transform_axis_target")
+        """
+
 
 # Armature EditMode extensions to Transform menu
 class VIEW3D_MT_transform_armature(VIEW3D_MT_transform_base):
diff --git a/source/blender/editors/object/object_intern.h 
b/source/blender/editors/object/object_intern.h
index f6fb3cc75b8..3e655fa04a4 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -55,6 +55,7 @@ void OBJECT_OT_scale_clear(struct wmOperatorType *ot);
 void OBJECT_OT_origin_clear(struct wmOperatorType *ot);
 void OBJECT_OT_visual_transform_apply(struct wmOperatorType *ot);
 void OBJECT_OT_transform_apply(struct wmOperatorType *ot);
+void OBJECT_OT_transform_axis_target(struct wmOperatorType *ot);
 void OBJECT_OT_origin_set(struct wmOperatorType *ot);
 
 /* object_relations.c */
diff --git a/source/blender/editors/object/object_ops.c 
b/source/blender/editors/object/object_ops.c
index ca02457ba39..07922f2d3b2 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -61,6 +61,7 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_origin_clear);
        WM_operatortype_append(OBJECT_OT_visual_transform_apply);
        WM_operatortype_append(OBJECT_OT_transform_apply);
+       WM_operatortype_append(OBJECT_OT_transform_axis_target);
        WM_operatortype_append(OBJECT_OT_origin_set);
        
        WM_operatortype_append(OBJECT_OT_mode_set);
diff --git a/source/blender/editors/object/object_transform.c 
b/source/blender/editors/object/object_transform.c
index 19f9c779132..cf68bd3e419 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -39,10 +39,12 @@
 #include "DNA_scene_types.h"
 #include "DNA_group_types.h"
 #include "DNA_lattice_types.h"
+#include "DNA_lamp_types.h"
 
 #include "BLI_math.h"
 #include "BLI_listbase.h"
 #include "BLI_utildefines.h"
+#include "BLI_array.h"
 
 #include "BKE_context.h"
 #include "BKE_curve.h"
@@ -72,6 +74,8 @@
 #include "ED_screen.h"
 #include "ED_view3d.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "object_intern.h"
 
 /*************************** Clear Transformation ****************************/
@@ -1124,3 +1128,385 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
        ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, 
"Type", "");
        RNA_def_enum(ot->srna, "center", prop_set_bounds_types, 
V3D_AROUND_CENTER_MEAN, "Center", "");
 }
+
+/* -------------------------------------------------------------------- */
+
+/** \name Transform Axis Target
+ *
+ * Note this is an experemental operator to point lamps/cameras at objects.
+ * We may re-work how this behaves based on user feedback.
+ * - campbell.
+ * \{ */
+
+/* When using multiple objects, apply their relative rotational offset to the 
active object. */
+#define USE_RELATIVE_ROTATION
+
+struct XFormAxisItem {
+       Object *ob;
+       float rot_mat[3][3];
+       void *obtfm;
+       float xform_dist;
+
+#ifdef USE_RELATIVE_ROTATION
+       /* use when translating multiple */
+       float xform_rot_offset[3][3];
+#endif
+};
+
+struct XFormAxisData {
+       ViewContext vc;
+       struct {
+               float depth;
+               float normal[3];
+               bool is_depth_valid;
+               bool is_normal_valid;
+       } prev;
+
+       struct XFormAxisItem *object_data;
+       uint object_data_len;
+       bool is_translate;
+
+       int init_event;
+};
+
+static bool object_is_target_compat(const Object *ob)
+{
+       if (ob->type == OB_LAMP) {
+               const Lamp *la = ob->data;
+               if (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA)) {
+                       return true;
+               }
+       }
+       /* We might want to enable this later, for now just lamps */
+#if 0
+       else if (ob->type == OB_CAMERA) {
+               return true;
+       }
+#endif
+       return false;
+}
+
+static void object_transform_axis_target_free_data(wmOperator *op)
+{
+       struct XFormAxisData *xfd = op->customdata;
+       struct XFormAxisItem *item = xfd->object_data;
+       for (int i = 0; i < xfd->object_data_len; i++, item++) {
+               MEM_freeN(item->obtfm);
+       }
+       MEM_freeN(xfd->object_data);
+       MEM_freeN(xfd);
+       op->customdata = NULL;
+}
+
+/* We may want to expose as alternative to: BKE_object_apply_rotation */
+static void object_apply_rotation(Object *ob, const float rmat[3][3])
+{
+       float size[3];
+       float loc[3];
+       float rmat4[4][4];
+       copy_m4_m3(rmat4, rmat);
+
+       copy_v3_v3(size, ob->size);
+       copy_v3_v3(loc, ob->loc);
+       BKE_object_apply_mat4(ob, rmat4, true, true);
+       copy_v3_v3(ob->size, size);
+       copy_v3_v3(ob->loc, loc);
+}
+/* We may want to extract this to: BKE_object_apply_location */
+static void object_apply_location(Object *ob, const float loc[3])
+{
+       /* quick but weak */
+       Object ob_prev = *ob;
+       float mat[4][4];
+       copy_m4_m4(mat, ob->obmat);
+       copy_v3_v3(mat[3], loc);
+       BKE_object_apply_mat4(ob, mat, true, true);
+       copy_v3_v3(mat[3], ob->loc);
+       *ob = ob_prev;
+       copy_v3_v3(ob->loc, mat[3]);
+}
+
+static void object_orient_to_location(
+        Object *ob, float rot_orig[3][3], const float axis[3], const float 
location[3])
+{
+       float delta[3];
+       sub_v3_v3v3(delta, ob->obmat[3], location);
+       if (normalize_v3(delta) != 0.0f) {
+               if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
+                       float delta_rot[3][3];
+                       float final_rot[3][3];
+                       rotation_between_vecs_to_mat3(delta_rot, axis, delta);
+
+                       mul_m3_m3m3(final_rot, delta_rot, rot_orig);
+
+                       object_apply_rotation(ob, final_rot);
+
+                       DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+               }
+       }
+}
+
+static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
+{
+       struct XFormAxisData *xfd = op->customdata;
+       struct XFormAxisItem *item = xfd->object_data;
+       for (int i = 0; i < xfd->object_data_len; i++, item++) {
+               BKE_object_tfm_restore(item->ob, item->obtfm);
+               DEG_id_tag_update(&item->ob->id, OB_RECALC_OB);
+               WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+       }
+
+       object_transform_axis_target_free_data(op);
+}
+
+static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, 
const wmEvent *event)
+{
+       ViewContext vc;
+       view3d_set_viewcontext(C, &vc);
+
+       if (!object_is_target_compat(vc.obact)) {
+               /* Falls back to texture space transform. */
+               return OPERATOR_PASS_THROUGH;
+       }
+
+       ED_view3d_autodist_init(C, vc.depsgraph, vc.ar, vc.v3d, 0);
+
+       if (vc.rv3d->depths != NULL) {
+               vc.rv3d->depths->damaged = true;
+       }
+       ED_view3d_depth_update(vc.ar);
+
+       if (vc.rv3d->depths == NULL) {
+               BKE_report(op->reports, RPT_WARNING, "Unable to access depth 
buffer, using view plane");
+               return OPERATOR_CANCELLED;
+       }
+
+       ED_region_tag_redraw(vc.ar);
+
+       struct XFormAxisData *xfd;
+       xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), 
__func__);
+
+       /* Don't change this at runtime. */
+       xfd->vc = vc;
+       xfd->vc.mval[0] = event->mval[0];
+       xfd->vc.mval[1] = event->mval[1];
+
+       xfd->prev.depth = 1.0f;
+       xfd->prev.is_depth_valid = false;
+       xfd->prev.is_normal_valid = false;
+       xfd->is_translate = false;
+
+       xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
+
+       {
+               struct XFormAxisItem *object_data = NULL;
+               BLI_array_declare(object_data);
+
+               struct XFormAxisItem *item = BLI_array_append_ret(object_data);
+               item->ob = xfd->vc.obact;
+
+               CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+               {
+                       if ((ob != xfd->vc.obact) && 
object_is_target_compat(ob)) {
+                               item = BLI_array_append_ret(object_data);
+                               item->ob = ob;
+                       }
+               }
+               CTX_DATA_END;
+
+               xfd->object_data = object_data;
+               xfd->object_data_len = BLI_array_count(object_data);
+
+               if (xfd->object_data_len != BLI_array_count(object_data)) {
+                       xfd->object_data = MEM_reallocN(xfd->object_data, 
xfd->object_data_len * sizeof(*xfd->object_data));
+               }
+       }
+
+       {
+               struct XFormAxisItem *item = xfd->object_data;
+               for (int i = 0; i < xfd->object_data_len; i++, item++) {
+                       item->obtfm = BKE_object_tfm_backup(item->ob);
+                       BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
+               }
+       }
+
+       WM_event_add_modal_handler(C, op);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static int object_transform_axis_target_modal(bContext *C, wmOperator *op, 
const wmEvent *event)
+{
+       struct XFormAxisData *xfd = op->customdata;
+       ARegion *ar = xfd->vc.ar;
+
+       view3d_operator_needs_opengl(C);
+
+       const bool is_translate = (event->ctrl != 0);
+       const bool is_translate_init = is_translate && (xfd->is_translate != 
is_translate);
+
+       if (event->type == MOUSEMOVE || is_translate_init) {
+               const ViewDepths *depths = xfd->vc.rv3d->depths;
+               if (depths &&
+                   ((unsigned int)event->mval[0] < depths->w) &&
+                   ((unsigned int)event->mval[1] < depths->h))
+               {
+                       double depth = 
(double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
+                       float location_world[3];
+                       if (depth == 1.0f) {
+                               if (xfd->prev.is_depth_valid) {
+                                       depth = (double)xfd->prev.depth;
+                               }
+                       }
+                       if ((depth > depths->depth_range[0]) && (depth < 
depths->depth_range[1])) {
+                               xfd->prev.depth = depth;
+                               xfd->prev.is_depth_valid = true;
+                               if (ED_view3d_depth_unproject(ar, event->mval, 
depth, location_world)) {
+                                       if (is_translate) {
+
+                                               float normal[3];
+                                               bool normal_found = false;
+                                               if 
(ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
+                                                       normal_found = true;
+
+                                                       /* cheap attempt to 
smooth normals out a bit! */
+                                                       const uint ofs = 2;
+                                                       for (uint x = -ofs; x 
<= ofs; x += ofs / 2) {
+                                                               for (uint y = 
-ofs; y <= ofs; y += ofs / 2) {
+                                                                       if (x 
!= 0 && y != 0) {
+                                                                               
int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
+                                                                               
float n[3];
+                                                                               
if (ED_view3d_depth_read_cached_normal(
+                                                                               
        &xfd->vc, mval_ofs, n))
+                                                                               
{
+                                                                               
        add_v3_v3(normal, n);
+                                                                               
}
+                                                                       }
+                                                               }
+                                                       }
+                                                       n

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to